UI: Video Sequencer sidebar overhaul
authorWilliam Reynish <billrey@me.com>
Thu, 16 May 2019 11:58:04 +0000 (13:58 +0200)
committerWilliam Reynish <billrey@me.com>
Thu, 16 May 2019 11:58:04 +0000 (13:58 +0200)
  - 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

release/scripts/startup/bl_ui/space_sequencer.py
source/blender/makesrna/intern/rna_sequencer.c

index d820676..73a2528 100644 (file)
@@ -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="")
+        row = layout.row(align=True)
+        row.prop(strip, "name", text=""+strip.type.title()+"")
+        row.prop(strip, "lock", toggle=True, icon_only=True)
 
-        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="")
+class SEQUENCER_PT_adjust_offset(SequencerButtonsPanel, Panel):
+    bl_label = "Offset"
+    bl_parent_id = "SEQUENCER_PT_adjust"
+    bl_options = {'DEFAULT_CLOSED'}
 
-            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)
+    @classmethod
+    def poll(cls, context):
+        strip = act_strip(context)
+        return strip.type != 'SOUND'
 
-        else:
-            row = layout.row()
-            row.prop(strip, "mute", toggle=True, icon_only=True, icon='MUTE_IPO_OFF')
+    def draw_header(self, context):
+        strip = act_strip(context)
+        self.layout.prop(strip, "use_translation", text="")
 
-        col = layout.column(align=True)
-        row = col.row(align=True)
+    def draw(self, context):
+        layout = self.layout
+        layout.use_property_split = True
+        layout.use_property_decorate = False
 
-        row_sub = row.row(align=True)
-        row_sub.enabled = not strip.lock
-        row_sub.prop(strip, "channel")
-        row.prop(strip, "lock", toggle=True, icon_only=True)
+        strip = act_strip(context)
 
-        sub = col.column(align=True)
-        sub.enabled = not strip.lock
-        sub.prop(strip, "frame_start")
-        sub.prop(strip, "frame_final_duration")
+        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
-        scene = context.scene
+        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
-
-            split = layout.split(factor=0.4)
-            split.label(text="Color Space:")
-            split.prop(strip.colorspace_settings, "name", text="")
+                layout.prop(elem, "filename", text="")  # strip.elements[0] could be a fallback
 
-            split = layout.split(factor=0.4)
-            split.label(text="Alpha:")
-            split.prop(strip, "alpha_mode", text="")
+            layout.prop(strip.colorspace_settings, "name", text="Color Space")
 
-            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.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:
+                    split.label(text="Unpack")
+                    split.operator("sound.unpack", icon='PACKAGE', text="")
+                else:
+                    split.label(text="Pack")
+                    split.operator("sound.pack", icon='UGLYPACKAGE', 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.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")
-
-        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")
-
-            row.prop(sound, "use_memory_cache")
+                split.label(text="Pack")
+                split.operator("sound.pack", icon='UGLYPACKAGE', text="")
 
-            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,73 @@ 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"
+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):
-        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")
+        if not cls.has_sequencer(context):
+            return False
 
+        strip = act_strip(context)
+        if not strip:
+            return False
 
-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)
+        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
 
-        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")
+        strip = act_strip(context)
 
         col = layout.column()
-        col.operator("sequencer.enable_proxies")
-        col.operator("sequencer.rebuild_proxy")
+        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_strip_proxy(SequencerButtonsPanel, Panel):
-    bl_label = "Strip Proxy & Timecode"
-    bl_category = "Proxy & Cache"
+class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel):
+    bl_label = "Proxy/Timecode"
+    bl_category = "Strip"
+    bl_options = {'DEFAULT_CLOSED'}
 
     @classmethod
     def poll(cls, context):
@@ -1284,7 +1452,7 @@ 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', '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")
+            row.prop(strip.proxy, "build_75")
             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_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")
-
 
-class SEQUENCER_PT_strip_cache(SequencerButtonsPanel, Panel):
-    bl_label = "Strip Cache"
-    bl_category = "Proxy & Cache"
+                col.prop(proxy, "timecode", text="Timecode Index")
 
-    @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,
 )
index 0b1e35e..2af06fc 100644 (file)
@@ -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");