From 86eefefdc1aae2a3ab4160770032671abf55aa30 Mon Sep 17 00:00:00 2001 From: William Reynish Date: Thu, 16 May 2019 13:58:04 +0200 Subject: [PATCH] UI: Video Sequencer sidebar overhaul - Use single column layout - Move the rather obscure Backdrop toggle into the View menu - Use correct units for Crop and Offset (pixels) - Re-organize the sidebar in 2 main groups: Adjust & Info Adjust includes Compositing, Offset, Crop, Video, Color, Sound Info includes strip name, path, start/end and other data Original changes by tintwotin, with changes and adjustments on top by me --- .../scripts/startup/bl_ui/space_sequencer.py | 753 +++++++++++------- .../blender/makesrna/intern/rna_sequencer.c | 12 +- 2 files changed, 460 insertions(+), 305 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index d820676c86c..73a252885a8 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -44,7 +44,14 @@ def selected_sequences_len(context): def draw_color_balance(layout, color_balance): - box = layout.box() + + layout.use_property_split = False + + flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) + col = flow.column() + + + box = col.box() split = box.split(factor=0.35) col = split.column(align=True) col.label(text="Lift:") @@ -54,7 +61,9 @@ def draw_color_balance(layout, color_balance): col.prop(color_balance, "invert_lift", text="Invert", icon='ARROW_LEFTRIGHT') split.template_color_picker(color_balance, "lift", value_slider=True, cubic=True) - box = layout.box() + col = flow.column() + + box = col.box() split = box.split(factor=0.35) col = split.column(align=True) col.label(text="Gamma:") @@ -64,7 +73,9 @@ def draw_color_balance(layout, color_balance): col.prop(color_balance, "invert_gamma", text="Invert", icon='ARROW_LEFTRIGHT') split.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) - box = layout.box() + col = flow.column() + + box = col.box() split = box.split(factor=0.35) col = split.column(align=True) col.label(text="Gain:") @@ -90,9 +101,6 @@ class SEQUENCER_HT_header(Header): SEQUENCER_MT_editor_menus.draw_collapsible(context, layout) - if st.view_type == 'SEQUENCER': - layout.prop(st, "show_backdrop", text="Backdrop") - layout.separator_spacer() layout.template_running_jobs() @@ -196,6 +204,9 @@ class SEQUENCER_MT_view(Menu): layout.operator_context = 'INVOKE_REGION_PREVIEW' layout.prop(st, "show_region_ui") layout.operator_context = 'INVOKE_DEFAULT' + + if st.view_type == 'SEQUENCER': + layout.prop(st, "show_backdrop", text="Backdrop") layout.separator() @@ -689,76 +700,81 @@ class SequencerButtonsPanel_Output: return cls.has_preview(context) -class SEQUENCER_PT_edit(SequencerButtonsPanel, Panel): - bl_label = "Edit Strip" +class SEQUENCER_PT_info(SequencerButtonsPanel, Panel): + bl_label = "Info" + bl_options = {'DEFAULT_CLOSED'} bl_category = "Strip" def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False scene = context.scene - frame_current = scene.frame_current strip = act_strip(context) - split = layout.split(factor=0.25) - split.label(text="Name:") - split.prop(strip, "name", text="") - - split = layout.split(factor=0.25) - split.label(text="Type:") - split.prop(strip, "type", text="") - - if strip.type != 'SOUND': - split = layout.split(factor=0.25) - split.label(text="Blend:") - split.prop(strip, "blend_type", text="") - - row = layout.row(align=True) - sub = row.row(align=True) - sub.active = (not strip.mute) - sub.prop(strip, "blend_alpha", text="Opacity", slider=True) - row.prop(strip, "mute", toggle=True, icon_only=True) - - else: - row = layout.row() - row.prop(strip, "mute", toggle=True, icon_only=True, icon='MUTE_IPO_OFF') - - col = layout.column(align=True) - row = col.row(align=True) - - row_sub = row.row(align=True) - row_sub.enabled = not strip.lock - row_sub.prop(strip, "channel") + row = layout.row(align=True) + row.prop(strip, "name", text=""+strip.type.title()+"") row.prop(strip, "lock", toggle=True, icon_only=True) - sub = col.column(align=True) - sub.enabled = not strip.lock - sub.prop(strip, "frame_start") - sub.prop(strip, "frame_final_duration") + +class SEQUENCER_PT_adjust_offset(SequencerButtonsPanel, Panel): + bl_label = "Offset" + bl_parent_id = "SEQUENCER_PT_adjust" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + strip = act_strip(context) + return strip.type != 'SOUND' + + def draw_header(self, context): + strip = act_strip(context) + self.layout.prop(strip, "use_translation", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + strip = act_strip(context) + + layout.active = strip.use_translation col = layout.column(align=True) - row = col.row(align=True) - row.label(text=iface_("Final Length: %s") % bpy.utils.smpte_from_frame(strip.frame_final_duration), - translate=False) - row = col.row(align=True) - row.active = strip.frame_start <= frame_current <= strip.frame_start + strip.frame_duration - row.label(text=iface_("Playhead: %d") % (frame_current - strip.frame_start), translate=False) - col.label(text=iface_("Frame Offset %d:%d") % (strip.frame_offset_start, strip.frame_offset_end), - translate=False) - col.label(text=iface_("Frame Still %d:%d") % (strip.frame_still_start, strip.frame_still_end), translate=False) + col.prop(strip.transform, "offset_x", text="Position X") + col.prop(strip.transform, "offset_y", text="Y") - elem = False - if strip.type == 'IMAGE': - elem = strip.strip_elem_from_frame(frame_current) - elif strip.type == 'MOVIE': - elem = strip.elements[0] +class SEQUENCER_PT_adjust_crop(SequencerButtonsPanel, Panel): + bl_label = "Crop" + bl_parent_id = "SEQUENCER_PT_adjust" + bl_options = {'DEFAULT_CLOSED'} - if elem and elem.orig_width > 0 and elem.orig_height > 0: - col.label(text=iface_("Original Dimension: %dx%d") % (elem.orig_width, elem.orig_height), translate=False) - else: - col.label(text="Original Dimension: None") + @classmethod + def poll(cls, context): + strip = act_strip(context) + return strip.type != 'SOUND' + + def draw_header(self, context): + strip = act_strip(context) + self.layout.prop(strip, "use_crop", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + strip = act_strip(context) + + layout.active = strip.use_crop + + col = layout.column(align=True) + col.prop(strip.crop, "min_x") + col.prop(strip.crop, "max_x") + col.prop(strip.crop, "max_y") + col.prop(strip.crop, "min_y") class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): @@ -783,6 +799,8 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False strip = act_strip(context) @@ -799,7 +817,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): elif strip.type == 'WIPE': col = layout.column() col.prop(strip, "transition_type") - col.label(text="Direction:") + col.alignment = "RIGHT" col.row().prop(strip, "direction", expand=True) col = layout.column() @@ -826,7 +844,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): layout.prop(strip, "speed_factor") else: layout.prop(strip, "speed_factor", text="Frame Number") - layout.prop(strip, "use_scale_to_length") + layout.prop(strip, "scale_to_length") elif strip.type == 'TRANSFORM': layout = self.layout @@ -834,11 +852,9 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): col.prop(strip, "interpolation") col.prop(strip, "translation_unit") - col = layout.column(align=True) - col.label(text="Position:") - row = col.row(align=True) - row.prop(strip, "translate_start_x", text="X") - row.prop(strip, "translate_start_y", text="Y") + layout=layout.column(align=True) + layout.prop(strip, "translate_start_x", text="Position X") + layout.prop(strip, "translate_start_y", text="Y") layout.separator() @@ -848,17 +864,12 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): col = layout.column(align=True) col.prop(strip, "scale_start_x", text="Scale") else: - col = layout.column(align=True) - col.label(text="Scale:") - row = col.row(align=True) - row.prop(strip, "scale_start_x", text="X") - row.prop(strip, "scale_start_y", text="Y") + layout.prop(strip, "scale_start_x", text="Scale X") + layout.prop(strip, "scale_start_y", text="Y") layout.separator() - col = layout.column(align=True) - col.label(text="Rotation:") - col.prop(strip, "rotation_start", text="Rotation") + layout.prop(strip, "rotation_start", text="Rotation") elif strip.type == 'MULTICAM': col = layout.column(align=True) @@ -869,8 +880,8 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): # The multicam strip needs at least 2 strips to be useful if strip_channel > 2: BT_ROW = 4 - - col.label(text="Cut To:") + #col.alignment = "RIGHT" + col.label(text=" Cut to") row = col.row() for i in range(1, strip_channel): @@ -909,12 +920,12 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): rowsub.prop(strip, "shadow_color", text="") col.prop(strip, "align_x") - col.prop(strip, "align_y") - col.label(text="Location") + col.prop(strip, "align_y", text = "Y") row = col.row(align=True) - row.prop(strip, "location", text="") + row.prop(strip, "location", text="Location") col.prop(strip, "wrap_width") - layout.operator("sequencer.export_subtitles", icon='EXPORT') + + layout.operator("sequencer.export_subtitles", text="Export Subtitles", icon='EXPORT') col = layout.column(align=True) if strip.type == 'SPEED': @@ -924,19 +935,19 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): if not strip.use_default_fade: col.prop(strip, "effect_fader", text="Effect Fader") elif strip.type == 'GAUSSIAN_BLUR': - row = col.row(align=True) - row.prop(strip, "size_x") - row.prop(strip, "size_y") + layout = layout.column(align=True) + layout.prop(strip, "size_x", text = "Size X") + layout.prop(strip, "size_y", text = "Y") elif strip.type == 'COLORMIX': - split = layout.split(factor=0.35) - split.label(text="Blend Mode:") - split.prop(strip, "blend_effect", text="") + layout.prop(strip, "blend_effect", text="Blend Mode") row = layout.row(align=True) row.prop(strip, "factor", slider=True) -class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): - bl_label = "Strip Input" +class SEQUENCER_PT_info_input(SequencerButtonsPanel, Panel): + bl_label = "Input" + bl_parent_id = "SEQUENCER_PT_info" + bl_options = {'DEFAULT_CLOSED'} bl_category = "Strip" @classmethod @@ -948,83 +959,69 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): if not strip: return False - return strip.type in { - 'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'META', - 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER', - 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', - 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', - 'MULTICAM', 'SPEED', 'ADJUSTMENT', 'COLORMIX' - } + return strip.type in {'MOVIE', 'IMAGE', 'SOUND'} + + ''', 'SCENE', 'MOVIECLIP', 'META', + 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER', + 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', + 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', + 'MULTICAM', 'SPEED', 'ADJUSTMENT', 'COLORMIX' }''' def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + st = context.space_data scene = context.scene - strip = act_strip(context) - seq_type = strip.type # draw a filename if we have one if seq_type == 'IMAGE': - split = layout.split(factor=0.2) - split.label(text="Path:") - split.prop(strip, "directory", text="") + layout.prop(strip, "directory", text="") # Current element for the filename elem = strip.strip_elem_from_frame(scene.frame_current) if elem: - split = layout.split(factor=0.2) - split.label(text="File:") - split.prop(elem, "filename", text="") # strip.elements[0] could be a fallback + layout.prop(elem, "filename", text="") # strip.elements[0] could be a fallback - split = layout.split(factor=0.4) - split.label(text="Color Space:") - split.prop(strip.colorspace_settings, "name", text="") + layout.prop(strip.colorspace_settings, "name", text="Color Space") - split = layout.split(factor=0.4) - split.label(text="Alpha:") - split.prop(strip, "alpha_mode", text="") - - layout.operator("sequencer.change_path", icon='FILEBROWSER').filter_image = True + layout.prop(strip, "alpha_mode", text="Alpha") + sub = layout.column(align=True) + sub.operator("sequencer.change_path", text="Change Data/Files", icon='FILEBROWSER').filter_image = True elif seq_type == 'MOVIE': - split = layout.split(factor=0.2) - split.label(text="Path:") - split.prop(strip, "filepath", text="") + layout.prop(strip, "filepath", text="") - split = layout.split(factor=0.4) - split.label(text="Color Space:") - split.prop(strip.colorspace_settings, "name", text="") + layout.prop(strip.colorspace_settings, "name", text="Color Space") layout.prop(strip, "mpeg_preseek") layout.prop(strip, "stream_index") + + elif seq_type == 'SOUND': + sound = strip.sound + layout.template_ID(strip, "sound", open="sound.open") + if sound is not None: + layout.prop(sound, "filepath", text="") - layout.prop(strip, "use_translation", text="Image Offset") - if strip.use_translation: - row = layout.row(align=True) - row.prop(strip.transform, "offset_x", text="X") - row.prop(strip.transform, "offset_y", text="Y") + layout.use_property_split = True + layout.use_property_decorate = False - layout.prop(strip, "use_crop", text="Image Crop") - if strip.use_crop: - col = layout.column(align=True) - col.prop(strip.crop, "max_y") - row = col.row(align=True) - row.prop(strip.crop, "min_x") - row.prop(strip.crop, "max_x") - col.prop(strip.crop, "min_y") + layout.alignment = 'RIGHT' + sub = layout.column(align=True) + split = sub.split(factor=0.5, align=True) + split.alignment = 'RIGHT' + if sound.packed_file: + split.label(text="Unpack") + split.operator("sound.unpack", icon='PACKAGE', text="") + else: + split.label(text="Pack") + split.operator("sound.pack", icon='UGLYPACKAGE', text="") - if not isinstance(strip, bpy.types.EffectSequence): - layout.label(text="Trim Duration (hard):") - row = layout.row(align=True) - row.prop(strip, "animation_offset_start", text="Start") - row.prop(strip, "animation_offset_end", text="End") - - layout.label(text="Trim Duration (soft):") - row = layout.row(align=True) - row.prop(strip, "frame_offset_start", text="Start") - row.prop(strip, "frame_offset_end", text="End") + layout.prop(sound, "use_memory_cache") if scene.render.use_multiview and seq_type in {'IMAGE', 'MOVIE'}: layout.prop(strip, "use_multiview") @@ -1032,7 +1029,6 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): col = layout.column() col.active = strip.use_multiview - col.label(text="Views Format:") col.row().prop(strip, "views_format", expand=True) box = col.box() @@ -1042,6 +1038,7 @@ class SEQUENCER_PT_input(SequencerButtonsPanel, Panel): class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel): bl_label = "Sound" + bl_parent_id = "" bl_category = "Strip" @classmethod @@ -1057,6 +1054,8 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False st = context.space_data strip = act_strip(context) @@ -1066,35 +1065,21 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel): if sound is not None: layout.prop(sound, "filepath", text="") - row = layout.row() + layout.use_property_split = True + layout.use_property_decorate = False + + layout.alignment = 'RIGHT' + sub = layout.column(align=True) + split = sub.split(factor=0.5, align=True) + split.alignment = 'RIGHT' if sound.packed_file: - row.operator("sound.unpack", icon='PACKAGE', text="Unpack") + split.label(text="Unpack") + split.operator("sound.unpack", icon='PACKAGE', text="") else: - row.operator("sound.pack", icon='UGLYPACKAGE', text="Pack") + split.label(text="Pack") + split.operator("sound.pack", icon='UGLYPACKAGE', text="") - row.prop(sound, "use_memory_cache") - - layout.prop(sound, "use_mono") - - if st.waveform_display_type == 'DEFAULT_WAVEFORMS': - layout.prop(strip, "show_waveform") - - col = layout.column(align=True) - col.prop(strip, "volume") - col.prop(strip, "pitch") - col.prop(strip, "pan") - - col = layout.column(align=True) - col.label(text="Trim Duration (hard):") - row = layout.row(align=True) - row.prop(strip, "animation_offset_start", text="Start") - row.prop(strip, "animation_offset_end", text="End") - - col = layout.column(align=True) - col.label(text="Trim Duration (soft):") - row = layout.row(align=True) - row.prop(strip, "frame_offset_start", text="Start") - row.prop(strip, "frame_offset_end", text="End") + layout.prop(sound, "use_memory_cache") class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): @@ -1114,6 +1099,8 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False strip = act_strip(context) @@ -1121,28 +1108,26 @@ class SEQUENCER_PT_scene(SequencerButtonsPanel, Panel): scene = strip.scene layout.prop(strip, "use_sequence") + + layout.prop(scene, "audio_volume", text="Volume") if not strip.use_sequence: - layout.label(text="Camera Override") - layout.template_ID(strip, "scene_camera") + layout.alignment = 'RIGHT' + sub = layout.column(align=True) + split = sub.split(factor=0.5, align=True) + split.alignment = 'RIGHT' + split.label(text="Camera Override") + split.template_ID(strip, "scene_camera") layout.prop(strip, "use_grease_pencil", text="Show Grease Pencil") - if scene: - layout.prop(scene, "audio_volume", text="Audio Volume") - if not strip.use_sequence: if scene: # Warning, this is not a good convention to follow. # Expose here because setting the alpha from the 'Render' menu is very inconvenient. - layout.label(text="Preview") + #layout.label(text="Preview") layout.prop(scene.render, "alpha_mode") - if scene: - sta = scene.frame_start - end = scene.frame_end - layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False) - class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): bl_label = "Mask" @@ -1161,6 +1146,8 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False strip = act_strip(context) @@ -1174,8 +1161,199 @@ class SEQUENCER_PT_mask(SequencerButtonsPanel, Panel): layout.label(text=iface_("Original frame range: %d-%d (%d)") % (sta, end, end - sta + 1), translate=False) -class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): - bl_label = "Filter" +class SEQUENCER_PT_info_data(SequencerButtonsPanel, Panel): + bl_label = "Data" + bl_category = "Strip" + bl_parent_id = "SEQUENCER_PT_info" + + @classmethod + def poll(cls, context): + if not cls.has_sequencer(context): + return False + + strip = act_strip(context) + if not strip: + return False + + return strip.type + + def draw(self, context): + layout = self.layout + layout.use_property_split = False + layout.use_property_decorate = False + + scene = context.scene + frame_current = scene.frame_current + strip = act_strip(context) + + length_list = [str(strip.frame_start), str(strip.frame_final_end), str(strip.frame_final_duration), str(strip.frame_offset_start), str(strip.frame_offset_end), str(strip.animation_offset_start), str(strip.animation_offset_end)] + max_length = max(len(x) for x in length_list) + max_factor = (1.9-max_length)/30 + + sub = layout.row(align=True) + sub.enabled = not strip.lock + split = sub.split(factor=0.5+max_factor) + split.alignment = 'RIGHT' + split.label(text='Channel') + split.prop(strip, "channel", text="") + + sub = layout.column(align=True) + sub.enabled = not strip.lock + split = sub.split(factor=0.5+max_factor) + split.alignment = 'RIGHT' + split.label(text="Start") + split.prop(strip, "frame_start", text=str(bpy.utils.smpte_from_frame(strip.frame_start)).replace(':', ' ')) + split = sub.split(factor=0.5+max_factor) + split.alignment = 'RIGHT' + split.label(text="End") + split.prop(strip, "frame_final_end", text=str(bpy.utils.smpte_from_frame(strip.frame_final_end)).replace(':', ' ')) + split = sub.split(factor=0.5+max_factor) + split.alignment = 'RIGHT' + split.label(text="Duration") + split.prop(strip, "frame_final_duration", text=str(bpy.utils.smpte_from_frame(strip.frame_final_duration)).replace(':', ' ')) + + if not isinstance(strip, bpy.types.EffectSequence): + layout.alignment = 'RIGHT' + sub = layout.column(align=True) + split = sub.split(factor=0.5+max_factor, align=True) + split.alignment = 'RIGHT' + split.label(text="Soft Trim Start") + split.prop(strip, "frame_offset_start", text=str(bpy.utils.smpte_from_frame(strip.frame_offset_start)).replace(':', ' ')) + split = sub.split(factor=0.5+max_factor, align=True) + split.alignment = 'RIGHT' + split.label(text='End') + split.prop(strip, "frame_offset_end", text=str(bpy.utils.smpte_from_frame(strip.frame_offset_end)).replace(':', ' ')) + + layout.alignment = 'RIGHT' + sub = layout.column(align=True) + split = sub.split(factor=0.5+max_factor) + split.alignment = 'RIGHT' + split.label(text="Hard Trim Start") + split.prop(strip, "animation_offset_start", text=str(bpy.utils.smpte_from_frame(strip.animation_offset_start)).replace(':', ' ')) + split = sub.split(factor=0.5+max_factor, align=True) + split.alignment = 'RIGHT' + split.label(text='End') + split.prop(strip, "animation_offset_end", text=str(bpy.utils.smpte_from_frame(strip.animation_offset_end)).replace(':', ' ')) + + playhead = frame_current - strip.frame_start + col = layout.column(align=True) + col = col.box() + col.active = (frame_current >= strip.frame_start and frame_current <= strip.frame_start + strip.frame_final_duration) + split = col.split(factor=0.5+max_factor) + split.alignment = 'RIGHT' + split.label(text="Playhead") + split.label(text="%s: %s" % ((bpy.utils.smpte_from_frame(playhead).replace(':', ' ')), (str(playhead)))) + + ''' Old data - anyone missing this data? + col.label(text=iface_("Frame Offset %d:%d") % (strip.frame_offset_start, strip.frame_offset_end), + translate=False) + col.label(text=iface_("Frame Still %d:%d") % (strip.frame_still_start, strip.frame_still_end), translate=False)''' + + elem = False + + if strip.type == 'IMAGE': + elem = strip.strip_elem_from_frame(frame_current) + elif strip.type == 'MOVIE': + elem = strip.elements[0] + + if strip.type != "SOUND": + split = col.split(factor=0.5+max_factor) + split.alignment = 'RIGHT' + split.label(text="Resolution") + if elem and elem.orig_width > 0 and elem.orig_height > 0: + split.label(text="%dx%d" % (elem.orig_width, elem.orig_height), translate=False) + else: + split.label(text="None") + + if strip.type == "SCENE": + scene = strip.scene + + if scene: + sta = scene.frame_start + end = scene.frame_end + split = col.split(factor=0.5+max_factor) + split.alignment = 'RIGHT' + split.label(text="Original Frame Range") + split.alignment = 'LEFT' + split.label(text="%d-%d (%d)" % (sta, end, end - sta + 1), translate=False) + + +class SEQUENCER_PT_adjust(SequencerButtonsPanel, Panel): + bl_label = "Adjust" + bl_category = "Strip" + + def draw(self, context): + pass + + +class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel): + bl_label = "Sound" + bl_parent_id = "SEQUENCER_PT_adjust" + + @classmethod + def poll(cls, context): + strip = act_strip(context) + return strip.type == 'SOUND' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + st = context.space_data + strip = act_strip(context) + + sound = strip.sound + + col = layout.column() + + row = col.row(align=True) + sub = row.row(align=True) + sub.active = (not strip.mute) + + sub.prop(strip, "volume", text="Volume") + sub.prop(strip, "mute", toggle=True, icon_only=True, icon='MUTE_IPO_ON') + + col.prop(strip, "pitch") + col.prop(strip, "pan") + + if sound is not None: + + if st.waveform_display_type == 'DEFAULT_WAVEFORMS': + col.prop(strip, "show_waveform") + col.prop(sound, "use_mono") + + +class SEQUENCER_PT_adjust_comp(SequencerButtonsPanel, Panel): + bl_label = "Compositing" + bl_parent_id = "SEQUENCER_PT_adjust" + + @classmethod + def poll(cls, context): + strip = act_strip(context) + return strip.type != 'SOUND' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + strip = act_strip(context) + + layout.prop(strip, "blend_type", text="Blend") + + row = layout.row(align=True) + sub = row.row(align=True) + sub.active = (not strip.mute) + + sub.prop(strip, "blend_alpha", text="Opacity", slider=True) + sub.prop(strip, "mute", toggle=True, icon_only=True) + + +class SEQUENCER_PT_adjust_video(SequencerButtonsPanel, Panel): + bl_label = "Video" + bl_parent_id = "SEQUENCER_PT_adjust" + bl_options = {'DEFAULT_CLOSED'} bl_category = "Strip" @classmethod @@ -1197,83 +1375,38 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False strip = act_strip(context) col = layout.column() - col.label(text="Video:") col.prop(strip, "strobe") if strip.type == 'MOVIECLIP': col = layout.column() - col.label(text="Tracker:") + col.label(text="Tracker") col.prop(strip, "stabilize2d") col = layout.column() - col.label(text="Distortion:") + col.label(text="Distortion") col.prop(strip, "undistort") + col.separator() - split = layout.split(factor=0.6) - col = split.column() - col.prop(strip, "use_reverse_frames", text="Reverse") + col.prop(strip, "use_reverse_frames", text="Backwards") col.prop(strip, "use_deinterlace") + + col.separator() - col = split.column() - col.prop(strip, "use_flip_x", text="X Flip") - col.prop(strip, "use_flip_y", text="Y Flip") - - layout.label(text="Color:") - col = layout.column(align=True) - col.prop(strip, "color_saturation", text="Saturation") - col.prop(strip, "color_multiply", text="Multiply") - layout.prop(strip, "use_float", text="Convert to Float") + col.prop(strip, "use_flip_x", text="Flip X") + col.prop(strip, "use_flip_y", text="Flip Y") -class SEQUENCER_PT_cache_settings(SequencerButtonsPanel, Panel): - bl_label = "Cache Settings" - bl_category = "Proxy & Cache" - - @classmethod - def poll(cls, context): - return cls.has_sequencer(context) - - def draw(self, context): - layout = self.layout - ed = context.scene.sequence_editor - - layout.prop(ed, "use_cache_raw") - layout.prop(ed, "use_cache_preprocessed") - layout.prop(ed, "use_cache_composite") - layout.prop(ed, "use_cache_final") - layout.separator() - layout.prop(ed, "recycle_max_cost") - - -class SEQUENCER_PT_proxy_settings(SequencerButtonsPanel, Panel): - bl_label = "Proxy Settings" - bl_category = "Proxy & Cache" - @classmethod - def poll(cls, context): - return cls.has_sequencer(context) - - def draw(self, context): - layout = self.layout - - ed = context.scene.sequence_editor - - flow = layout.column_flow() - flow.prop(ed, "proxy_storage", text="Storage") - if ed.proxy_storage == 'PROJECT': - flow.prop(ed, "proxy_dir", text="Directory") - - col = layout.column() - col.operator("sequencer.enable_proxies") - col.operator("sequencer.rebuild_proxy") - - -class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): - bl_label = "Strip Proxy & Timecode" - bl_category = "Proxy & Cache" +class SEQUENCER_PT_adjust_color(SequencerButtonsPanel, Panel): + bl_label = "Color" + bl_parent_id = "SEQUENCER_PT_adjust" + bl_options = {'DEFAULT_CLOSED'} + bl_category = "Strip" @classmethod def poll(cls, context): @@ -1284,7 +1417,42 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): if not strip: return False - return strip.type in {'MOVIE', 'IMAGE', 'META'} + return strip.type in { + 'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'MASK', + 'META', 'ADD', 'SUBTRACT', 'ALPHA_OVER', + 'ALPHA_UNDER', 'CROSS', 'GAMMA_CROSS', 'MULTIPLY', + 'OVER_DROP', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', + 'MULTICAM', 'SPEED', 'ADJUSTMENT', 'COLORMIX' + } + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + strip = act_strip(context) + + col = layout.column() + col.prop(strip, "color_saturation", text="Saturation") + col.prop(strip, "color_multiply", text="Multiply") + col.prop(strip, "use_float", text="Convert to Float") + + +class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): + bl_label = "Proxy/Timecode" + bl_category = "Strip" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + if not cls.has_sequencer(context): + return False + + strip = act_strip(context) + if not strip: + return False + + return strip.type in {'MOVIE', 'IMAGE', 'SCENE', 'META', 'MULTICAM'} def draw_header(self, context): strip = act_strip(context) @@ -1293,6 +1461,8 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False ed = context.scene.sequence_editor @@ -1302,7 +1472,10 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): proxy = strip.proxy flow = layout.column_flow() - if ed.proxy_storage == 'PER_STRIP': + flow.prop(ed, "proxy_storage", text="Storage") + if ed.proxy_storage == 'PROJECT': + flow.prop(ed, "proxy_dir", text="Directory") + else: flow.prop(proxy, "use_proxy_custom_directory") flow.prop(proxy, "use_proxy_custom_file") @@ -1311,11 +1484,17 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): if proxy.use_proxy_custom_file: flow.prop(proxy, "filepath") + layout = layout.box() row = layout.row(align=True) - row.prop(strip.proxy, "build_25", toggle=True) - row.prop(strip.proxy, "build_50", toggle=True) - row.prop(strip.proxy, "build_75", toggle=True) - row.prop(strip.proxy, "build_100", toggle=True) + row.prop(strip.proxy, "build_25") + row.prop(strip.proxy, "build_75") + row = layout.row(align=True) + row.prop(strip.proxy, "build_50") + row.prop(strip.proxy, "build_100") + + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False layout.prop(proxy, "use_overwrite") @@ -1324,45 +1503,23 @@ class SEQUENCER_PT_strip_proxy(SequencerButtonsPanel, Panel): if strip.type == 'MOVIE': col = layout.column() - col.label(text="Use timecode index:") - col.prop(proxy, "timecode") + col.prop(proxy, "timecode", text="Timecode Index") - -class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel): - bl_label = "Strip Cache" - bl_category = "Proxy & Cache" - - @classmethod - def poll(cls, context): - if not cls.has_sequencer(context): - return False - if act_strip(context) is not None: - return True - - def draw_header(self, context): - strip = act_strip(context) - self.layout.prop(strip, "override_cache_settings", text="") - - def draw(self, context): - layout = self.layout - strip = act_strip(context) - layout.active = strip.override_cache_settings - - layout.prop(strip, "use_cache_raw") - layout.prop(strip, "use_cache_preprocessed") - layout.prop(strip, "use_cache_composite") + col = layout.column() + col.operator("sequencer.enable_proxies") + col.operator("sequencer.rebuild_proxy") class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel): - bl_label = "Scene Shading" + bl_label = "Scene Preview/Render" bl_space_type = 'SEQUENCE_EDITOR' bl_region_type = 'UI' - bl_category = "Strip" def draw(self, context): layout = self.layout - + layout.use_property_split = True + layout.use_property_decorate = False render = context.scene.render col = layout.column() @@ -1374,10 +1531,11 @@ class SEQUENCER_PT_preview(SequencerButtonsPanel_Output, Panel): class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel): bl_label = "View Settings" - bl_category = "Strip" def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False st = context.space_data @@ -1396,7 +1554,6 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel): class SEQUENCER_PT_view_safe_areas(SequencerButtonsPanel_Output, Panel): bl_label = "Safe Areas" - bl_category = "Strip" bl_options = {'DEFAULT_CLOSED'} @classmethod @@ -1414,6 +1571,7 @@ class SEQUENCER_PT_view_safe_areas(SequencerButtonsPanel_Output, Panel): from .properties_data_camera import draw_display_safe_settings layout = self.layout + st = context.space_data safe_data = context.scene.safe_areas @@ -1426,6 +1584,8 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False strip = act_strip(context) ed = context.scene.sequence_editor @@ -1499,17 +1659,6 @@ class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): class SEQUENCER_PT_grease_pencil(AnnotationDataPanel, SequencerButtonsPanel_Output, Panel): bl_space_type = 'SEQUENCE_EDITOR' bl_region_type = 'UI' - bl_category = "Strip" - - # NOTE: this is just a wrapper around the generic GP Panel - # But, it should only show up when there are images in the preview region - - -class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_Output, Panel): - bl_space_type = 'SEQUENCE_EDITOR' - bl_region_type = 'UI' - bl_category = "Strip" - bl_parent_id = 'SEQUENCER_PT_grease_pencil' # NOTE: this is just a wrapper around the generic GP Panel # But, it should only show up when there are images in the preview region @@ -1518,7 +1667,6 @@ class SEQUENCER_PT_annotation_onion(AnnotationOnionSkin, SequencerButtonsPanel_O class SEQUENCER_PT_grease_pencil_tools(GreasePencilToolsPanel, SequencerButtonsPanel_Output, Panel): bl_space_type = 'SEQUENCE_EDITOR' bl_region_type = 'UI' - bl_category = "Strip" # NOTE: this is just a wrapper around the generic GP tools panel # It contains access to some essential tools usually found only in @@ -1551,23 +1699,30 @@ classes = ( SEQUENCER_MT_strip_input, SEQUENCER_MT_strip_lock_mute, SEQUENCER_MT_context_menu, - SEQUENCER_PT_edit, + + SEQUENCER_PT_adjust, + SEQUENCER_PT_adjust_comp, + SEQUENCER_PT_adjust_offset, + SEQUENCER_PT_adjust_crop, + SEQUENCER_PT_adjust_video, + SEQUENCER_PT_adjust_color, + SEQUENCER_PT_adjust_sound, + SEQUENCER_PT_effect, - SEQUENCER_PT_input, - SEQUENCER_PT_sound, SEQUENCER_PT_scene, SEQUENCER_PT_mask, - SEQUENCER_PT_filter, - SEQUENCER_PT_cache_settings, - SEQUENCER_PT_proxy_settings, - SEQUENCER_PT_strip_proxy, - SEQUENCER_PT_strip_cache, + + SEQUENCER_PT_proxy, SEQUENCER_PT_preview, SEQUENCER_PT_view, SEQUENCER_PT_view_safe_areas, SEQUENCER_PT_modifiers, + + SEQUENCER_PT_info, + SEQUENCER_PT_info_input, + SEQUENCER_PT_info_data, + SEQUENCER_PT_grease_pencil, - SEQUENCER_PT_annotation_onion, SEQUENCER_PT_grease_pencil_tools, SEQUENCER_PT_custom_props, ) diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c index 0b1e35e3a74..2af06fc4684 100644 --- a/source/blender/makesrna/intern/rna_sequencer.c +++ b/source/blender/makesrna/intern/rna_sequencer.c @@ -1189,25 +1189,25 @@ static void rna_def_strip_crop(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Sequence Crop", "Cropping parameters for a sequence strip"); RNA_def_struct_sdna(srna, "StripCrop"); - prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_UNSIGNED); + prop = RNA_def_property(srna, "max_y", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "top"); RNA_def_property_ui_text(prop, "Top", "Number of pixels to crop from the top"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); - prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_UNSIGNED); + prop = RNA_def_property(srna, "min_y", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "bottom"); RNA_def_property_ui_text(prop, "Bottom", "Number of pixels to crop from the bottom"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); - prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_UNSIGNED); + prop = RNA_def_property(srna, "min_x", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "left"); RNA_def_property_ui_text(prop, "Left", "Number of pixels to crop from the left side"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceCrop_update"); - prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_UNSIGNED); + prop = RNA_def_property(srna, "max_x", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "right"); RNA_def_property_ui_text(prop, "Right", "Number of pixels to crop from the right side"); RNA_def_property_ui_range(prop, 0, 4096, 1, -1); @@ -1225,14 +1225,14 @@ static void rna_def_strip_transform(BlenderRNA *brna) RNA_def_struct_ui_text(srna, "Sequence Transform", "Transform parameters for a sequence strip"); RNA_def_struct_sdna(srna, "StripTransform"); - prop = RNA_def_property(srna, "offset_x", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "offset_x", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "xofs"); RNA_def_property_ui_text( prop, "Offset X", "Amount to move the input on the X axis within its boundaries"); RNA_def_property_ui_range(prop, -4096, 4096, 1, -1); RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceTransform_update"); - prop = RNA_def_property(srna, "offset_y", PROP_INT, PROP_NONE); + prop = RNA_def_property(srna, "offset_y", PROP_INT, PROP_PIXEL); RNA_def_property_int_sdna(prop, NULL, "yofs"); RNA_def_property_ui_text( prop, "Offset Y", "Amount to move the input on the Y axis within its boundaries");