Politically correct terrible consequencer changes
authorAntony Riakiotakis <kalast@gmail.com>
Mon, 24 Nov 2014 17:18:35 +0000 (18:18 +0100)
committerAntony Riakiotakis <kalast@gmail.com>
Mon, 24 Nov 2014 17:23:44 +0000 (18:23 +0100)
This patch includes the work done in the terrible consequencer branch
that hasn't been merged to master minus a few controversial and WIP
stuff, like strip parenting, new sequence data structs and cuddly
widgets.

What is included:

* Strip extensions only when slipping. It can very easily be made an
option but with a few strips with overlapping durations it makes view
too crowded and difficult to make out.
* Threaded waveform loading + code that restores waveforms on undo (not
used though, since sound_load recreates everything. There's a patch for
review D876)
* Toggle to enable backdrop in the strip sequence editor
* Toggle to easily turn on/off waveform display
* Snapping during transform on sequence boundaries. Snapping to start or
end of selection depends on position of mouse when invoking the operator
* Snapping of timeline indicator in sequencer to strip boundaries. To
use just press and hold ctrl while dragging.

Reviewers: campbellbarton

Differential Revision: https://developer.blender.org/D904

29 files changed:
intern/audaspace/intern/AUD_C-API.cpp
intern/audaspace/intern/AUD_C-API.h
release/scripts/startup/bl_ui/space_sequencer.py
source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/BKE_sound.h
source/blender/blenkernel/intern/sequencer.c
source/blender/blenkernel/intern/sound.c
source/blender/blenloader/intern/readblenentry.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/readfile.h
source/blender/blenloader/intern/writefile.c
source/blender/editors/animation/anim_ops.c
source/blender/editors/space_sequencer/CMakeLists.txt
source/blender/editors/space_sequencer/sequencer_draw.c
source/blender/editors/space_sequencer/sequencer_edit.c
source/blender/editors/space_sequencer/sequencer_intern.h
source/blender/editors/space_sequencer/sequencer_ops.c
source/blender/editors/space_sequencer/sequencer_preview.c [new file with mode: 0644]
source/blender/editors/space_sequencer/space_sequencer.c
source/blender/editors/transform/transform.c
source/blender/editors/transform/transform.h
source/blender/editors/transform/transform_conversions.c
source/blender/editors/transform/transform_snap.c
source/blender/makesdna/DNA_sequence_types.h
source/blender/makesdna/DNA_sound_types.h
source/blender/makesdna/DNA_space_types.h
source/blender/makesrna/intern/rna_sound.c
source/blender/makesrna/intern/rna_space.c
source/blender/windowmanager/WM_api.h

index d2a934740d6efdf0055282c28add64ad0096af66..45d72ccb50ebd9f0954b24844927ecf1fd97fc17 100644 (file)
@@ -46,6 +46,7 @@
 #include <cstring>
 #include <cmath>
 #include <sstream>
+#include <iostream>
 
 #include "AUD_NULLDevice.h"
 #include "AUD_I3DDevice.h"
@@ -317,8 +318,9 @@ AUD_SoundInfo AUD_getInfo(AUD_Sound *sound)
                        info.length = reader->getLength() / (float) info.specs.rate;
                }
        }
-       catch(AUD_Exception&)
+       catch(AUD_Exception &ae)
        {
+               std::cout << ae.str << std::endl;
        }
 
        return info;
@@ -1084,7 +1086,7 @@ int AUD_doesPlayback()
        return -1;
 }
 
-int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second)
+int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second, short *interrupt)
 {
        AUD_DeviceSpecs specs;
        sample_t *buf;
@@ -1107,6 +1109,9 @@ int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_pe
        for (int i = 0; i < length; i++) {
                len = floor(samplejump * (i+1)) - floor(samplejump * i);
 
+               if (*interrupt) {
+                       return 0;
+               }
                aBuffer.assureSize(len * AUD_SAMPLE_SIZE(specs));
                buf = aBuffer.getBuffer();
 
index 64a3d06bd5fe86d565da4c52ef42166aab15af54..657d4e6fd02f583938edd24edbd52e2a6b144cc1 100644 (file)
@@ -646,7 +646,7 @@ extern int AUD_doesPlayback(void);
  * \param samples_per_second How many samples to read per second of the sound.
  * \return How many samples really have been read. Always <= length.
  */
-extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second);
+extern int AUD_readSound(AUD_Sound *sound, sample_t *buffer, int length, int samples_per_second, short *interrupt);
 
 /**
  * Copies a sound.
index feb90da3d639b52043fd059fb3308d7d85432e21..650c63140d22920c9c172096c4be34e24f15fc50 100644 (file)
@@ -71,6 +71,7 @@ class SEQUENCER_HT_header(Header):
         row.prop(scene, "lock_frame_selection_to_range", text="", toggle=True)
 
         layout.prop(st, "view_type", expand=True, text="")
+        layout.prop(st, "waveform_draw_type", text="")
 
         if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
             layout.prop(st, "display_mode", expand=True, text="")
@@ -82,6 +83,7 @@ class SEQUENCER_HT_header(Header):
 
             layout.separator()
             layout.operator("sequencer.refresh_all")
+            layout.prop(st, "show_backdrop")
         else:
             if st.view_type == 'SEQUENCER_PREVIEW':
                 layout.separator()
@@ -716,6 +718,7 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
     def draw(self, context):
         layout = self.layout
 
+        st = context.space_data
         strip = act_strip(context)
         sound = strip.sound
 
@@ -734,7 +737,9 @@ class SEQUENCER_PT_sound(SequencerButtonsPanel, Panel):
 
             row.prop(sound, "use_memory_cache")
 
-        layout.prop(strip, "show_waveform")
+        if st.waveform_draw_type == 'DEFAULT_WAVEFORMS':
+            layout.prop(strip, "show_waveform")
+
         layout.prop(strip, "volume")
         layout.prop(strip, "pitch")
         layout.prop(strip, "pan")
index e460d0d8917023e73dfe74f22590d6d2282a53ac..97cd5bd1bcb36869d60989b11067cb42d0a60866 100644 (file)
@@ -377,6 +377,17 @@ struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine);
 void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq);
 void BKE_sequence_init_colorspace(struct Sequence *seq);
 
+/* RNA enums, just to be more readable */
+enum {
+       SEQ_SIDE_NONE = 0,
+       SEQ_SIDE_LEFT,
+       SEQ_SIDE_RIGHT,
+       SEQ_SIDE_BOTH
+};
+int BKE_sequencer_find_next_prev_edit(
+        struct Scene *scene, int cfra, const short side,
+        const bool do_skip_mute, const bool do_center, const bool do_unselected);
+
 struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
 struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
 struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load);
index 50ca5fcdf7b04922b128aa18fd941dbea36c9ff8..f318c74258b6c54f2e83acc4579696ee6a055b30 100644 (file)
@@ -71,8 +71,6 @@ void sound_delete(struct Main *bmain, struct bSound *sound);
 
 void sound_cache(struct bSound *sound);
 
-void sound_cache_notifying(struct Main *main, struct bSound *sound);
-
 void sound_delete_cache(struct bSound *sound);
 
 void sound_load(struct Main *main, struct bSound *sound);
@@ -132,7 +130,7 @@ int sound_scene_playing(struct Scene *scene);
 
 void sound_free_waveform(struct bSound *sound);
 
-void sound_read_waveform(struct bSound *sound);
+void sound_read_waveform(struct bSound *sound, bool locked, short *stop);
 
 void sound_update_scene(struct Main *bmain, struct Scene *scene);
 
index 9a144ec8e44d37a0588d2494fe53560066db5fc2..20698cc60e831ce9831138419cf7885100b349da 100644 (file)
@@ -892,7 +892,6 @@ void BKE_sequencer_sort(Scene *scene)
        Editing *ed = BKE_sequencer_editing_get(scene, false);
        Sequence *seq, *seqt;
 
-       
        if (ed == NULL)
                return;
 
@@ -4675,3 +4674,70 @@ bool BKE_sequence_is_valid_check(Sequence *seq)
        return true;
 }
 
+int BKE_sequencer_find_next_prev_edit(
+        Scene *scene, int cfra, const short side,
+        const bool do_skip_mute, const bool do_center, const bool do_unselected)
+{
+       Editing *ed = BKE_sequencer_editing_get(scene, false);
+       Sequence *seq;
+
+       int dist, best_dist, best_frame = cfra;
+       int seq_frames[2], seq_frames_tot;
+
+       /* in case where both is passed, frame just finds the nearest end while frame_left the nearest start */
+
+       best_dist = MAXFRAME * 2;
+
+       if (ed == NULL) return cfra;
+
+       for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+               int i;
+
+               if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
+                       continue;
+               }
+
+               if (do_unselected && (seq->flag & SELECT))
+                       continue;
+
+               if (do_center) {
+                       seq_frames[0] = (seq->startdisp + seq->enddisp) / 2;
+                       seq_frames_tot = 1;
+               }
+               else {
+                       seq_frames[0] = seq->startdisp;
+                       seq_frames[1] = seq->enddisp;
+
+                       seq_frames_tot = 2;
+               }
+
+               for (i = 0; i < seq_frames_tot; i++) {
+                       const int seq_frame = seq_frames[i];
+
+                       dist = MAXFRAME * 2;
+
+                       switch (side) {
+                               case SEQ_SIDE_LEFT:
+                                       if (seq_frame < cfra) {
+                                               dist = cfra - seq_frame;
+                                       }
+                                       break;
+                               case SEQ_SIDE_RIGHT:
+                                       if (seq_frame > cfra) {
+                                               dist = seq_frame - cfra;
+                                       }
+                                       break;
+                               case SEQ_SIDE_BOTH:
+                                       dist = abs(seq_frame - cfra);
+                                       break;
+                       }
+
+                       if (dist < best_dist) {
+                               best_frame = seq_frame;
+                               best_dist = dist;
+                       }
+               }
+       }
+
+       return best_frame;
+}
index da6ead06d984c8c12786e9b2d2fbcb4612d34f31..3c7b01f9052661bd46410d3146ae88b1f6f3ff12 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
+#include "BLI_threads.h"
 
 #include "DNA_anim_types.h"
 #include "DNA_object_types.h"
@@ -116,6 +117,12 @@ void BKE_sound_free(bSound *sound)
        }
 
        sound_free_waveform(sound);
+       
+       if (sound->mutex) {
+               BLI_mutex_free(sound->mutex);
+               sound->mutex = NULL;
+       }
+       
 #endif  /* WITH_AUDASPACE */
 }
 
@@ -296,12 +303,6 @@ void sound_cache(bSound *sound)
                sound->playback_handle = sound->handle;
 }
 
-void sound_cache_notifying(struct Main *main, bSound *sound)
-{
-       sound_cache(sound);
-       sound_update_sequencer(main, sound);
-}
-
 void sound_delete_cache(bSound *sound)
 {
        sound->flags &= ~SOUND_FLAGS_CACHING;
@@ -680,22 +681,40 @@ void sound_free_waveform(bSound *sound)
        sound->waveform = NULL;
 }
 
-void sound_read_waveform(bSound *sound)
+void sound_read_waveform(bSound *sound, bool locked, short *stop)
 {
        AUD_SoundInfo info;
-
+       SoundWaveform *waveform = NULL;
+       
        info = AUD_getInfo(sound->playback_handle);
-
+       
        if (info.length > 0) {
-               SoundWaveform *waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform");
                int length = info.length * SOUND_WAVE_SAMPLES_PER_SECOND;
-
+               
+               waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform");
                waveform->data = MEM_mallocN(length * sizeof(float) * 3, "SoundWaveform.samples");
-               waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND);
-
+               waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND, stop);
+               
+               if (*stop) {
+                       MEM_freeN(waveform->data);
+                       MEM_freeN(waveform);
+                       if (locked)
+                               BLI_mutex_lock(sound->mutex);
+                       sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+                       if (locked)
+                               BLI_mutex_unlock(sound->mutex);
+                       return;
+               }
+               
                sound_free_waveform(sound);
-               sound->waveform = waveform;
        }
+       
+       if (locked)
+               BLI_mutex_lock(sound->mutex);
+       sound->waveform = waveform;
+       sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+       if (locked)
+               BLI_mutex_unlock(sound->mutex);
 }
 
 void sound_update_scene(Main *bmain, struct Scene *scene)
@@ -830,7 +849,7 @@ void sound_stop_scene(struct Scene *UNUSED(scene)) {}
 void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {}
 float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; }
 int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; }
-void sound_read_waveform(struct bSound *UNUSED(sound)) {}
+void sound_read_waveform(struct bSound *sound, bool locked, short *stop) { UNUSED_VARS(sound, locked, stop); }
 void sound_init_main(struct Main *UNUSED(bmain)) {}
 void sound_set_cfra(int UNUSED(cfra)) {}
 void sound_update_sequencer(struct Main *UNUSED(main), struct bSound *UNUSED(sound)) {}
index d9bcfc2e8f958b31f99e3f10a10d9efb1bbfad4e..95440158277b4b757465463ec6da2180b1a876d8 100644 (file)
@@ -308,6 +308,9 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
                
                /* makes lookup of existing video clips in old main */
                blo_make_movieclip_pointer_map(fd, oldmain);
+
+               /* make lookups of existing sound data in old main */
+               blo_make_sound_pointer_map(fd, oldmain);
                
                /* removed packed data from this trick - it's internal data that needs saves */
                
@@ -318,7 +321,10 @@ BlendFileData *BLO_read_from_memfile(Main *oldmain, const char *filename, MemFil
                
                /* ensures relinked movie clips are not freed */
                blo_end_movieclip_pointer_map(fd, oldmain);
-                               
+               
+               /* ensures relinked sounds are not freed */
+               blo_end_sound_pointer_map(fd, oldmain);
+
                /* move libraries from old main to new main */
                if (bfd && mainlist.first != mainlist.last) {
                        
index dd947ae5f79e800543e545aed5865f1d53e4ea46..9b043c6dbda8c9ec92010ab4054240735cfe0d1a 100644 (file)
@@ -1128,6 +1128,8 @@ void blo_freefiledata(FileData *fd)
                        oldnewmap_free(fd->imamap);
                if (fd->movieclipmap)
                        oldnewmap_free(fd->movieclipmap);
+               if (fd->soundmap)
+                       oldnewmap_free(fd->soundmap);
                if (fd->packedmap)
                        oldnewmap_free(fd->packedmap);
                if (fd->libmap && !(fd->flags & FD_FLAGS_NOT_MY_LIBMAP))
@@ -1221,6 +1223,13 @@ static void *newmclipadr(FileData *fd, void *adr)      /* used to restore movie
        return NULL;
 }
 
+static void *newsoundadr(FileData *fd, void *adr)      /* used to restore sound data after undo */
+{
+       if (fd->soundmap && adr)
+               return oldnewmap_lookup_and_inc(fd->soundmap, adr, true);
+       return NULL;
+}
+
 static void *newpackedadr(FileData *fd, void *adr)      /* used to restore packed data after undo */
 {
        if (fd->packedmap && adr)
@@ -1437,6 +1446,37 @@ void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain)
        }
 }
 
+void blo_make_sound_pointer_map(FileData *fd, Main *oldmain)
+{
+       bSound *sound = oldmain->sound.first;
+       
+       fd->soundmap = oldnewmap_new();
+       
+       for (; sound; sound = sound->id.next) {
+               if (sound->waveform)
+                       oldnewmap_insert(fd->soundmap, sound->waveform, sound->waveform, 0);                    
+       }
+}
+
+/* set old main sound caches to zero if it has been restored */
+/* this works because freeing old main only happens after this call */
+void blo_end_sound_pointer_map(FileData *fd, Main *oldmain)
+{
+       OldNew *entry = fd->soundmap->entries;
+       bSound *sound = oldmain->sound.first;
+       int i;
+       
+       /* used entries were restored, so we put them to zero */
+       for (i = 0; i < fd->soundmap->nentries; i++, entry++) {
+               if (entry->nr > 0)
+                       entry->newp = NULL;
+       }
+       
+       for (; sound; sound = sound->id.next) {
+               sound->waveform = newsoundadr(fd, sound->waveform);
+       }
+}
+
 /* XXX disabled this feature - packed files also belong in temp saves and quit.blend, to make restore work */
 
 static void insert_packedmap(FileData *fd, PackedFile *pf)
@@ -5457,7 +5497,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
        }
 
        if (sce->ed) {
-               ListBase *old_seqbasep = &((Editing *)sce->ed)->seqbase;
+               ListBase *old_seqbasep = &sce->ed->seqbase;
                
                ed = sce->ed = newdataadr(fd, sce->ed);
                
@@ -5471,6 +5511,7 @@ static void direct_link_scene(FileData *fd, Scene *sce)
                        seq->seq1= newdataadr(fd, seq->seq1);
                        seq->seq2= newdataadr(fd, seq->seq2);
                        seq->seq3= newdataadr(fd, seq->seq3);
+                       
                        /* a patch: after introduction of effects with 3 input strips */
                        if (seq->seq3 == NULL) seq->seq3 = seq->seq2;
                        
@@ -6776,14 +6817,26 @@ static void direct_link_sound(FileData *fd, bSound *sound)
 {
        sound->handle = NULL;
        sound->playback_handle = NULL;
-       sound->waveform = NULL;
 
-       // versioning stuff, if there was a cache, then we enable caching:
+       /* versioning stuff, if there was a cache, then we enable caching: */
        if (sound->cache) {
                sound->flags |= SOUND_FLAGS_CACHING;
                sound->cache = NULL;
        }
 
+       if (fd->soundmap) {
+               sound->waveform = newsoundadr(fd, sound->waveform);
+       }       
+       else {
+               sound->waveform = NULL;
+       }
+               
+       if (sound->mutex)
+               sound->mutex = BLI_mutex_alloc();
+       
+       /* clear waveform loading flag */
+       sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+
        sound->packedfile = direct_link_packedfile(fd, sound->packedfile);
        sound->newpackedfile = direct_link_packedfile(fd, sound->newpackedfile);
 }
index d56f58d1b37ac32a89c4d4e7cd4ba759c5f7520e..2b40accbf212c584943df6e5c71f9f6f5f095cd1 100644 (file)
@@ -88,6 +88,7 @@ typedef struct FileData {
        struct OldNewMap *libmap;
        struct OldNewMap *imamap;
        struct OldNewMap *movieclipmap;
+       struct OldNewMap *soundmap;
        struct OldNewMap *packedmap;
        
        struct BHeadSort *bheadmap;
@@ -133,6 +134,8 @@ void blo_make_image_pointer_map(FileData *fd, Main *oldmain);
 void blo_end_image_pointer_map(FileData *fd, Main *oldmain);
 void blo_make_movieclip_pointer_map(FileData *fd, Main *oldmain);
 void blo_end_movieclip_pointer_map(FileData *fd, Main *oldmain);
+void blo_make_sound_pointer_map(FileData *fd, Main *oldmain);
+void blo_end_sound_pointer_map(FileData *fd, Main *oldmain);
 void blo_make_packed_pointer_map(FileData *fd, Main *oldmain);
 void blo_end_packed_pointer_map(FileData *fd, Main *oldmain);
 void blo_add_library_pointer_map(ListBase *mainlist, FileData *fd);
index 59f126577031eac3acd3efe6444fb501202bbc13..13cceb9fe45e9b6d5de20c21324dfbd1521daf44 100644 (file)
 #include "BKE_node.h"
 #include "BKE_report.h"
 #include "BKE_sequencer.h"
+#include "BKE_sound.h"
 #include "BKE_subsurf.h"
 #include "BKE_modifier.h"
 #include "BKE_fcurve.h"
index 0f202003dd8b63131a5996b1f582ea3480cb5d68..8a9e02a64ea69f6b4a1cb1326721a6b5bc6adb47 100644 (file)
@@ -41,6 +41,7 @@
 #include "DNA_scene_types.h"
 
 #include "BKE_context.h"
+#include "BKE_sequencer.h"
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_sound.h"
@@ -92,9 +93,15 @@ static void change_frame_apply(bContext *C, wmOperator *op)
 {
        Main *bmain = CTX_data_main(C);
        Scene *scene = CTX_data_scene(C);
-       
+       int frame = RNA_int_get(op->ptr, "frame");
+       bool do_snap = RNA_boolean_get(op->ptr, "snap");
+
+       if (do_snap && CTX_wm_space_seq(C)) {
+               frame = BKE_sequencer_find_next_prev_edit(scene, frame, SEQ_SIDE_BOTH, true, false, false);
+       }
+
        /* set the new frame number */
-       CFRA = RNA_int_get(op->ptr, "frame");
+       CFRA = frame;
        FRAMENUMBER_MIN_CLAMP(CFRA);
        SUBFRA = 0.0f;
        
@@ -144,7 +151,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event
         * click-dragging over a range (modal scrubbing).
         */
        RNA_int_set(op->ptr, "frame", frame_from_event(C, event));
-       
+
        change_frame_apply(C, op);
        
        /* add temp handler */
@@ -175,6 +182,16 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
                        if (event->val == KM_RELEASE)
                                return OPERATOR_FINISHED;
                        break;
+
+               case LEFTCTRLKEY:
+               case RIGHTCTRLKEY:
+                       if (event->val == KM_RELEASE) {
+                               RNA_boolean_set(op->ptr, "snap", false);
+                       }
+                       else if (event->val == KM_PRESS) {
+                               RNA_boolean_set(op->ptr, "snap", true);
+                       }
+                       break;
        }
 
        return OPERATOR_RUNNING_MODAL;
@@ -182,6 +199,8 @@ static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event)
 
 static void ANIM_OT_change_frame(wmOperatorType *ot)
 {
+       PropertyRNA *prop;
+
        /* identifiers */
        ot->name = "Change Frame";
        ot->idname = "ANIM_OT_change_frame";
@@ -198,6 +217,8 @@ static void ANIM_OT_change_frame(wmOperatorType *ot)
 
        /* rna */
        ot->prop = RNA_def_int(ot->srna, "frame", 0, MINAFRAME, MAXFRAME, "Frame", "", MINAFRAME, MAXFRAME);
+       prop = RNA_def_boolean(ot->srna, "snap", false, "Snap", "");
+       RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
 /* ****************** set preview range operator ****************************/
index 4cf9c0c95c240b7ccfd29874b6ddf9f315cf9f82..d9aff2781f0df0e91cde39c4ac6af409f5d55ae0 100644 (file)
@@ -43,6 +43,7 @@ set(SRC
        sequencer_edit.c
        sequencer_modifier.c
        sequencer_ops.c
+       sequencer_preview.c
        sequencer_scopes.c
        sequencer_select.c
        sequencer_view.c
index fa82704c36f26de9fece9c0c413d72d3d2714d33..1235ba8a421b116290019a35c399bbc17a2cc2cb 100644 (file)
@@ -34,6 +34,7 @@
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
 #include "BLI_utildefines.h"
+#include "BLI_threads.h"
 
 #include "IMB_imbuf_types.h"
 
@@ -62,6 +63,7 @@
 #include "ED_mask.h"
 #include "ED_sequencer.h"
 #include "ED_space_api.h"
+#include "ED_screen.h"
 
 #include "UI_interface.h"
 #include "UI_resources.h"
@@ -69,6 +71,8 @@
 
 #include "WM_api.h"
 
+#include "MEM_guardedalloc.h"
+
 /* own include */
 #include "sequencer_intern.h"
 
@@ -86,9 +90,7 @@
 #undef SEQP_BEGIN
 #undef SEQ_END
 
-static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
-
-static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[3])
+void color3ubv_from_seq(Scene *curscene, Sequence *seq, unsigned char col[3])
 {
        unsigned char blendcol[3];
        SolidColorVars *colvars = (SolidColorVars *)seq->effectdata;
@@ -179,14 +181,14 @@ static void get_seq_color3ubv(Scene *curscene, Sequence *seq, unsigned char col[
        }
 }
 
-static void drawseqwave(Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
+static void drawseqwave(const bContext *C, SpaceSeq *sseq, Scene *scene, Sequence *seq, float x1, float y1, float x2, float y2, float stepsize)
 {
        /*
         * x1 is the starting x value to draw the wave,
         * x2 the end x value, same for y1 and y2
         * stepsize is width of a pixel.
         */
-       if (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM) {
+       if ((sseq->flag & SEQ_ALL_WAVEFORMS) || (seq->flag & SEQ_AUDIO_DRAW_WAVEFORM)) {
                int i, j, pos;
                int length = floor((x2 - x1) / stepsize) + 1;
                float ymid = (y1 + y2) / 2;
@@ -194,20 +196,30 @@ static void drawseqwave(Scene *scene, Sequence *seq, float x1, float y1, float x
                float samplestep;
                float startsample, endsample;
                float value;
-
+               bSound *sound = seq->sound;
+               
                SoundWaveform *waveform;
-
-               if (!seq->sound->waveform)
-                       sound_read_waveform(seq->sound);
-
-               if (!seq->sound->waveform)
-                       return;  /* zero length sound */
-
+               
+               if (!sound->mutex)
+                       sound->mutex = BLI_mutex_alloc();
+               
+               BLI_mutex_lock(sound->mutex);
+               if (!seq->sound->waveform) {
+                       if(!(sound->flags & SOUND_FLAGS_WAVEFORM_LOADING)) {
+                               /* prevent sounds from reloading */
+                               seq->sound->flags |= SOUND_FLAGS_WAVEFORM_LOADING;
+                               BLI_mutex_unlock(sound->mutex);
+                               sequencer_preview_add_sound(C, seq);
+                       }
+                       else {
+                               BLI_mutex_unlock(sound->mutex);
+                       }
+                       return;  /* nothing to draw */
+               }
+               BLI_mutex_unlock(sound->mutex);
+               
                waveform = seq->sound->waveform;
-
-               if (!waveform)
-                       return;
-
+               
                startsample = floor((seq->startofs + seq->anim_startofs) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
                endsample = ceil((seq->startofs + seq->anim_startofs + seq->enddisp - seq->startdisp) / FPS * SOUND_WAVE_SAMPLES_PER_SECOND);
                samplestep = (endsample - startsample) * stepsize / (x2 - x1);
@@ -303,7 +315,7 @@ static void drawmeta_contents(Scene *scene, Sequence *seqm, float x1, float y1,
                        if ((seqm->flag & SEQ_MUTE) == 0 && (seq->flag & SEQ_MUTE))
                                drawmeta_stipple(1);
 
-                       get_seq_color3ubv(scene, seq, col);
+                       color3ubv_from_seq(scene, seq, col);
 
                        glColor4ubv(col);
                        
@@ -422,112 +434,6 @@ static void draw_seq_handle(View2D *v2d, Sequence *seq, const float handsize_cla
        }
 }
 
-static void draw_seq_extensions(Scene *scene, ARegion *ar, Sequence *seq)
-{
-       float x1, x2, y1, y2, pixely, a;
-       unsigned char col[3], blendcol[3];
-       View2D *v2d = &ar->v2d;
-       
-       if (seq->type >= SEQ_TYPE_EFFECT) return;
-
-       x1 = seq->startdisp;
-       x2 = seq->enddisp;
-       
-       y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
-       y2 = seq->machine + SEQ_STRIP_OFSTOP;
-
-       pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
-       
-       if (pixely <= 0) return;  /* can happen when the view is split/resized */
-       
-       blendcol[0] = blendcol[1] = blendcol[2] = 120;
-
-       if (seq->startofs) {
-               glEnable(GL_BLEND);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               
-               get_seq_color3ubv(scene, seq, col);
-               
-               if (seq->flag & SELECT) {
-                       UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
-                       glColor4ub(col[0], col[1], col[2], 170);
-               }
-               else {
-                       UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
-                       glColor4ub(col[0], col[1], col[2], 110);
-               }
-               
-               glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
-               
-               if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
-               else glColor4ub(col[0], col[1], col[2], 160);
-
-               fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);  //outline
-               
-               glDisable(GL_BLEND);
-       }
-       if (seq->endofs) {
-               glEnable(GL_BLEND);
-               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-               
-               get_seq_color3ubv(scene, seq, col);
-               
-               if (seq->flag & SELECT) {
-                       UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
-                       glColor4ub(col[0], col[1], col[2], 170);
-               }
-               else {
-                       UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
-                       glColor4ub(col[0], col[1], col[2], 110);
-               }
-               
-               glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
-               
-               if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
-               else glColor4ub(col[0], col[1], col[2], 160);
-
-               fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline
-               
-               glDisable(GL_BLEND);
-       }
-       if (seq->startstill) {
-               get_seq_color3ubv(scene, seq, col);
-               UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
-               glColor3ubv((GLubyte *)col);
-               
-               draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
-               
-               /* feint pinstripes, helps see exactly which is extended and which isn't,
-                * especially when the extension is very small */ 
-               if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
-               else UI_GetColorPtrShade3ubv(col, col, -16);
-               
-               glColor3ubv((GLubyte *)col);
-               
-               for (a = y1; a < y2; a += pixely * 2.0f) {
-                       fdrawline(x1,  a,  (float)(seq->start),  a);
-               }
-       }
-       if (seq->endstill) {
-               get_seq_color3ubv(scene, seq, col);
-               UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
-               glColor3ubv((GLubyte *)col);
-               
-               draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2);
-               
-               /* feint pinstripes, helps see exactly which is extended and which isn't,
-                * especially when the extension is very small */ 
-               if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24);
-               else UI_GetColorPtrShade3ubv(col, col, -16);
-               
-               glColor3ubv((GLubyte *)col);
-               
-               for (a = y1; a < y2; a += pixely * 2.0f) {
-                       fdrawline((float)(seq->start + seq->len),  a,  x2,  a);
-               }
-       }
-}
-
 /* draw info text on a sequence strip */
 static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float y1, float y2, const unsigned char background_col[3])
 {
@@ -634,7 +540,7 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
 }
 
 /* draws a shaded strip, made from gradient + flat color + gradient */
-static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
+void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2)
 {
        float ymid1, ymid2;
        
@@ -696,7 +602,7 @@ static void draw_shadedstrip(Sequence *seq, unsigned char col[3], float x1, floa
  * ARegion is currently only used to get the windows width in pixels
  * so wave file sample drawing precision is zoom adjusted
  */
-static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline_tint, float pixelx)
+static void draw_seq_strip(const bContext *C, SpaceSeq *sseq, Scene *scene, ARegion *ar, Sequence *seq, int outline_tint, float pixelx)
 {
        View2D *v2d = &ar->v2d;
        float x1, x2, y1, y2;
@@ -714,8 +620,8 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
 
 
        /* get the correct color per strip type*/
-       //get_seq_color3ubv(scene, seq, col);
-       get_seq_color3ubv(scene, seq, background_col);
+       //color3ubv_from_seq(scene, seq, col);
+       color3ubv_from_seq(scene, seq, background_col);
        
        /* draw the main strip body */
        if (is_single_image) {  /* single image */
@@ -727,10 +633,6 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
                draw_shadedstrip(seq, background_col, x1, y1, x2, y2);
        }
        
-       /* draw additional info and controls */
-       if (!is_single_image)
-               draw_seq_extensions(scene, ar, seq);
-       
        draw_seq_handle(v2d, seq, handsize_clamped, SEQ_LEFTHANDLE);
        draw_seq_handle(v2d, seq, handsize_clamped, SEQ_RIGHTHANDLE);
        
@@ -740,7 +642,9 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
        
        /* draw sound wave */
        if (seq->type == SEQ_TYPE_SOUND_RAM) {
-               drawseqwave(scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
+               if(!(sseq->flag & SEQ_NO_WAVEFORMS)) {
+                       drawseqwave(C, sseq, scene, seq, x1, y1, x2, y2, BLI_rctf_size_x(&ar->v2d.cur) / ar->winx);
+               }
        }
 
        /* draw lock */
@@ -773,7 +677,7 @@ static void draw_seq_strip(Scene *scene, ARegion *ar, Sequence *seq, int outline
                glDisable(GL_POLYGON_STIPPLE);
        }
 
-       get_seq_color3ubv(scene, seq, col);
+       color3ubv_from_seq(scene, seq, col);
        if ((G.moving & G_TRANSFORM_SEQ) && (seq->flag & SELECT)) {
                if (seq->flag & SEQ_OVERLAP) {
                        col[0] = 255; col[1] = col[2] = 40;
@@ -924,7 +828,7 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop
        return scope;
 }
 
-void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay)
+void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq, int cfra, int frame_ofs, bool draw_overlay, bool draw_backdrop)
 {
        struct Main *bmain = CTX_data_main(C);
        struct ImBuf *ibuf = NULL;
@@ -980,7 +884,7 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
                viewrecty /= proxy_size / 100.0f;
        }
 
-       if (!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) {
+       if ((!draw_overlay || sseq->overlay_type == SEQ_DRAW_OVERLAY_REFERENCE) && !draw_backdrop) {
                UI_GetThemeColor3fv(TH_SEQ_PREVIEW, col);
                glClearColor(col[0], col[1], col[2], 0.0);
                glClear(GL_COLOR_BUFFER_BIT);
@@ -1055,23 +959,25 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
        /* without this colors can flicker from previous opengl state */
        glColor4ub(255, 255, 255, 255);
 
-       UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
-       UI_view2d_curRect_validate(v2d);
-
-       /* setting up the view - actual drawing starts here */
-       UI_view2d_view_ortho(v2d);
-
-       /* only draw alpha for main buffer */
-       if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
-               if (sseq->flag & SEQ_USE_ALPHA) {
-                       glEnable(GL_BLEND);
-                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-                       fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
-                       glColor4f(1.0, 1.0, 1.0, 1.0);
+       if (!draw_backdrop) {
+               UI_view2d_totRect_set(v2d, viewrectx + 0.5f, viewrecty + 0.5f);
+               UI_view2d_curRect_validate(v2d);
+               
+               /* setting up the view - actual drawing starts here */
+               UI_view2d_view_ortho(v2d);
+               
+               /* only draw alpha for main buffer */
+               if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+                       if (sseq->flag & SEQ_USE_ALPHA) {
+                               glEnable(GL_BLEND);
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+                               
+                               fdrawcheckerboard(v2d->tot.xmin, v2d->tot.ymin, v2d->tot.xmax, v2d->tot.ymax);
+                               glColor4f(1.0, 1.0, 1.0, 1.0);
+                       }
                }
        }
-
+       
        if (scope) {
                IMB_freeImBuf(ibuf);
                ibuf = scope;
@@ -1161,6 +1067,14 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
        else
                glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ibuf->x, ibuf->y, 0, format, type, display_buffer);
 
+       if (draw_backdrop) {
+               glMatrixMode(GL_PROJECTION);
+               glPushMatrix();
+               glLoadIdentity();
+               glMatrixMode(GL_MODELVIEW);
+               glPushMatrix();
+               glLoadIdentity();
+       }
        glBegin(GL_QUADS);
 
        if (draw_overlay) {
@@ -1183,6 +1097,25 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
                        glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
                }
        }
+       else if (draw_backdrop) {
+               float aspect = BLI_rcti_size_x(&ar->winrct) / (float)BLI_rcti_size_y(&ar->winrct);      
+               float image_aspect = viewrectx/viewrecty;
+               float imagex, imagey;
+               
+               if (aspect >= image_aspect) {
+                       imagex = image_aspect/aspect;
+                       imagey = 1.0f;
+               }
+               else {
+                       imagex = 1.0f;  
+                       imagey = aspect/image_aspect;
+               }
+               
+               glTexCoord2f(0.0f, 0.0f); glVertex2f(-imagex, -imagey);
+               glTexCoord2f(0.0f, 1.0f); glVertex2f(-imagex, imagey);
+               glTexCoord2f(1.0f, 1.0f); glVertex2f(imagex, imagey);
+               glTexCoord2f(1.0f, 0.0f); glVertex2f(imagex, -imagey);          
+       }
        else {
                glTexCoord2f(0.0f, 0.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymin);
                glTexCoord2f(0.0f, 1.0f); glVertex2f(v2d->tot.xmin, v2d->tot.ymax);
@@ -1190,6 +1123,15 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
                glTexCoord2f(1.0f, 0.0f); glVertex2f(v2d->tot.xmax, v2d->tot.ymin);
        }
        glEnd();
+       
+       if (draw_backdrop) {
+               glPopMatrix();
+               glMatrixMode(GL_PROJECTION);
+               glPopMatrix();
+               glMatrixMode(GL_MODELVIEW);
+               
+       }
+       
        glBindTexture(GL_TEXTURE_2D, last_texid);
        glDisable(GL_TEXTURE_2D);
        if (sseq->mainb == SEQ_DRAW_IMG_IMBUF && sseq->flag & SEQ_USE_ALPHA)
@@ -1199,6 +1141,16 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
        if (glsl_used)
                IMB_colormanagement_finish_glsl_draw();
 
+       if (cache_handle)
+               IMB_display_buffer_release(cache_handle);
+
+       if (!scope)
+               IMB_freeImBuf(ibuf);
+       
+       if (draw_backdrop) {
+               return;
+       }
+       
        if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
 
                float x1 = v2d->tot.xmin;
@@ -1248,9 +1200,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
                        ED_gpencil_draw_2dimage(C);
                }
        }
-
-       if (!scope)
-               IMB_freeImBuf(ibuf);
        
        /* ortho at pixel level */
        UI_view2d_view_restore(C);
@@ -1287,9 +1236,6 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq
                                            NULL, C);
                }
        }
-
-       if (cache_handle)
-               IMB_display_buffer_release(cache_handle);
 }
 
 #if 0
@@ -1366,6 +1312,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
 {
        Scene *scene = CTX_data_scene(C);
        View2D *v2d = &ar->v2d;
+       SpaceSeq *sseq = CTX_wm_space_seq(C);
        Sequence *last_seq = BKE_sequencer_active_get(scene);
        int sel = 0, j;
        float pixelx = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask);
@@ -1386,7 +1333,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
                        else if (seq->machine > v2d->cur.ymax) continue;
                        
                        /* strip passed all tests unscathed... so draw it now */
-                       draw_seq_strip(scene, ar, seq, outline_tint, pixelx);
+                       draw_seq_strip(C, sseq, scene, ar, seq, outline_tint, pixelx);
                }
                
                /* draw selected next time round */
@@ -1395,7 +1342,7 @@ static void draw_seq_strips(const bContext *C, Editing *ed, ARegion *ar)
        
        /* draw the last selected last (i.e. 'active' in other parts of Blender), removes some overlapping error */
        if (last_seq)
-               draw_seq_strip(scene, ar, last_seq, 120, pixelx);
+               draw_seq_strip(C, sseq, scene, ar, last_seq, 120, pixelx);
 }
 
 static void seq_draw_sfra_efra(Scene *scene, View2D *v2d)
@@ -1473,6 +1420,12 @@ void draw_timeline_seq(const bContext *C, ARegion *ar)
        // NOTE: the gridlines are currently spaced every 25 frames, which is only fine for 25 fps, but maybe not for 30...
        UI_view2d_constant_grid_draw(v2d);
 
+       if (sseq->draw_flag & SEQ_DRAW_BACKDROP) {
+               draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, true);
+               UI_SetTheme(SPACE_SEQ, RGN_TYPE_WINDOW);
+               UI_view2d_view_ortho(v2d);
+       }
+               
        ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW);
        
        seq_draw_sfra_efra(scene, v2d);
index b9e1fb9c02acade36182231d16da10220f985c82..2525b5d13e229a15d988e8a61369924d37705004 100644 (file)
 #include "ED_screen.h"
 #include "ED_transform.h"
 #include "ED_sequencer.h"
+#include "ED_space_api.h"
 
 #include "UI_view2d.h"
+#include "UI_resources.h"
+
+#include "GL/glew.h"
+#include "BIF_glutil.h"
 
 /* own include */
 #include "sequencer_intern.h"
@@ -1231,7 +1236,6 @@ void SEQUENCER_OT_snap(struct wmOperatorType *ot)
        RNA_def_int(ot->srna, "frame", 0, INT_MIN, INT_MAX, "Frame", "Frame where selected strips will be snapped", INT_MIN, INT_MAX);
 }
 
-
 typedef struct SlipData {
        int init_mouse[2];
        float init_mouseloc[2];
@@ -1241,6 +1245,7 @@ typedef struct SlipData {
        int num_seq;
        bool slow;
        int slow_offset; /* offset at the point where offset was turned on */
+       void *draw_handle;
 } SlipData;
 
 static void transseq_backup(TransSeq *ts, Sequence *seq)
@@ -1274,15 +1279,129 @@ static void transseq_restore(TransSeq *ts, Sequence *seq)
        seq->len = ts->len;
 }
 
-static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool first_level)
+static void draw_slip_extensions(const bContext *C, ARegion *ar, void *data)
+{
+       Scene *scene = CTX_data_scene(C);
+       float x1, x2, y1, y2, pixely, a;
+       unsigned char col[3], blendcol[3];
+       View2D *v2d = &ar->v2d;
+       SlipData *td = data;
+       int i;
+
+       for (i = 0; i < td->num_seq; i++) {
+               Sequence *seq = td->seq_array[i];
+
+               if ((seq->type != SEQ_TYPE_META) && td->trim[i]) {
+
+                       x1 = seq->startdisp;
+                       x2 = seq->enddisp;
+
+                       y1 = seq->machine + SEQ_STRIP_OFSBOTTOM;
+                       y2 = seq->machine + SEQ_STRIP_OFSTOP;
+
+                       pixely = BLI_rctf_size_y(&v2d->cur) / BLI_rcti_size_y(&v2d->mask);
+
+                       if (pixely <= 0) return;  /* can happen when the view is split/resized */
+
+                       blendcol[0] = blendcol[1] = blendcol[2] = 120;
+
+                       if (seq->startofs) {
+                               glEnable(GL_BLEND);
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+                               color3ubv_from_seq(scene, seq, col);
+
+                               if (seq->flag & SELECT) {
+                                       UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+                                       glColor4ub(col[0], col[1], col[2], 170);
+                               }
+                               else {
+                                       UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+                                       glColor4ub(col[0], col[1], col[2], 110);
+                               }
+
+                               glRectf((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);
+
+                               if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+                               else glColor4ub(col[0], col[1], col[2], 160);
+
+                               fdrawbox((float)(seq->start), y1 - SEQ_STRIP_OFSBOTTOM, x1, y1);  //outline
+
+                               glDisable(GL_BLEND);
+                       }
+                       if (seq->endofs) {
+                               glEnable(GL_BLEND);
+                               glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+                               color3ubv_from_seq(scene, seq, col);
+
+                               if (seq->flag & SELECT) {
+                                       UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.3, -40);
+                                       glColor4ub(col[0], col[1], col[2], 170);
+                               }
+                               else {
+                                       UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.6, 0);
+                                       glColor4ub(col[0], col[1], col[2], 110);
+                               }
+
+                               glRectf(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM);
+
+                               if (seq->flag & SELECT) glColor4ub(col[0], col[1], col[2], 255);
+                               else glColor4ub(col[0], col[1], col[2], 160);
+
+                               fdrawbox(x2, y2, (float)(seq->start + seq->len), y2 + SEQ_STRIP_OFSBOTTOM); //outline
+
+                               glDisable(GL_BLEND);
+                       }
+                       if (seq->startstill) {
+                               color3ubv_from_seq(scene, seq, col);
+                               UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+                               glColor3ubv((GLubyte *)col);
+
+                               draw_shadedstrip(seq, col, x1, y1, (float)(seq->start), y2);
+
+                               /* feint pinstripes, helps see exactly which is extended and which isn't,
+                                * especially when the extension is very small */
+                               if (seq->flag & SELECT) UI_GetColorPtrBlendShade3ubv(col, col, col, 0.0, 24);
+                               else UI_GetColorPtrShade3ubv(col, col, -16);
+
+                               glColor3ubv((GLubyte *)col);
+
+                               for (a = y1; a < y2; a += pixely * 2.0f) {
+                                       fdrawline(x1,  a,  (float)(seq->start),  a);
+                               }
+                       }
+                       if (seq->endstill) {
+                               color3ubv_from_seq(scene, seq, col);
+                               UI_GetColorPtrBlendShade3ubv(col, blendcol, col, 0.75, 40);
+                               glColor3ubv((GLubyte *)col);
+
+                               draw_shadedstrip(seq, col, (float)(seq->start + seq->len), y1, x2, y2);
+
+                               /* feint pinstripes, helps see exactly which is extended and which isn't,
+                                * especially when the extension is very small */
+                               if (seq->flag & SELECT) UI_GetColorPtrShade3ubv(col, col, 24);
+                               else UI_GetColorPtrShade3ubv(col, col, -16);
+
+                               glColor3ubv((GLubyte *)col);
+
+                               for (a = y1; a < y2; a += pixely * 2.0f) {
+                                       fdrawline((float)(seq->start + seq->len),  a,  x2,  a);
+                               }
+                       }
+               }
+       }
+}
+
+static int slip_add_sequences_rec(ListBase *seqbasep, Sequence **seq_array, bool *trim, int offset, bool do_trim)
 {
        Sequence *seq;
        int num_items = 0;
 
        for (seq = seqbasep->first; seq; seq = seq->next) {
-               if (!first_level || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
+               if (!do_trim || (!(seq->type & SEQ_TYPE_EFFECT) && (seq->flag & SELECT))) {
                        seq_array[offset + num_items] = seq;
-                       trim[offset + num_items] = first_level;
+                       trim[offset + num_items] = do_trim;
                        num_items++;
 
                        if (seq->type == SEQ_TYPE_META) {
@@ -1322,6 +1441,7 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
        SlipData *data;
        Scene *scene = CTX_data_scene(C);
        Editing *ed = BKE_sequencer_editing_get(scene, false);
+       ARegion *ar = CTX_wm_region(C);
        float mouseloc[2];
        int num_seq, i;
        View2D *v2d = UI_view2d_fromcontext(C);
@@ -1344,6 +1464,8 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
                transseq_backup(data->ts + i, data->seq_array[i]);
        }
 
+       data->draw_handle = ED_region_draw_cb_activate(ar->type, draw_slip_extensions, data, REGION_DRAW_POST_VIEW);
+
        UI_view2d_region_to_view(v2d, event->mval[0], event->mval[1], &mouseloc[0], &mouseloc[1]);
 
        copy_v2_v2_int(data->init_mouse, event->mval);
@@ -1353,6 +1475,9 @@ static int sequencer_slip_invoke(bContext *C, wmOperator *op, const wmEvent *eve
 
        WM_event_add_modal_handler(C, op);
 
+       /* notify so we draw extensions immediately */
+       WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
        return OPERATOR_RUNNING_MODAL;
 }
 
@@ -1463,6 +1588,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
        Scene *scene = CTX_data_scene(C);
        SlipData *data = (SlipData *)op->customdata;
        ScrArea *sa = CTX_wm_area(C);
+       ARegion *ar = CTX_wm_region(C);
 
        switch (event->type) {
                case MOUSEMOVE:
@@ -1504,6 +1630,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
 
                case LEFTMOUSE:
                {
+                       ED_region_draw_cb_exit(ar->type, data->draw_handle);
                        MEM_freeN(data->seq_array);
                        MEM_freeN(data->trim);
                        MEM_freeN(data->ts);
@@ -1532,6 +1659,8 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
                                BKE_sequence_calc(scene, seq);
                        }
 
+                       ED_region_draw_cb_exit(ar->type, data->draw_handle);
+
                        MEM_freeN(data->seq_array);
                        MEM_freeN(data->ts);
                        MEM_freeN(data->trim);
@@ -1587,7 +1716,6 @@ void SEQUENCER_OT_slip(struct wmOperatorType *ot)
                    INT32_MIN, INT32_MAX);
 }
 
-
 /* mute operator */
 static int sequencer_mute_exec(bContext *C, wmOperator *op)
 {
@@ -2810,74 +2938,13 @@ void SEQUENCER_OT_view_selected(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER;
 }
 
-
-static int find_next_prev_edit(Scene *scene, int cfra,
-                               const short side,
-                               const bool do_skip_mute, const bool do_center)
-{
-       Editing *ed = BKE_sequencer_editing_get(scene, false);
-       Sequence *seq;
-       
-       int dist, best_dist, best_frame = cfra;
-       int seq_frames[2], seq_frames_tot;
-
-       best_dist = MAXFRAME * 2;
-
-       if (ed == NULL) return cfra;
-       
-       for (seq = ed->seqbasep->first; seq; seq = seq->next) {
-               int i;
-
-               if (do_skip_mute && (seq->flag & SEQ_MUTE)) {
-                       continue;
-               }
-
-               if (do_center) {
-                       seq_frames[0] = (seq->startdisp + seq->enddisp) / 2;
-                       seq_frames_tot = 1;
-               }
-               else {
-                       seq_frames[0] = seq->startdisp;
-                       seq_frames[1] = seq->enddisp;
-
-                       seq_frames_tot = 2;
-               }
-
-               for (i = 0; i < seq_frames_tot; i++) {
-                       const int seq_frame = seq_frames[i];
-
-                       dist = MAXFRAME * 2;
-
-                       switch (side) {
-                               case SEQ_SIDE_LEFT:
-                                       if (seq_frame < cfra) {
-                                               dist = cfra - seq_frame;
-                                       }
-                                       break;
-                               case SEQ_SIDE_RIGHT:
-                                       if (seq_frame > cfra) {
-                                               dist = seq_frame - cfra;
-                                       }
-                                       break;
-                       }
-
-                       if (dist < best_dist) {
-                               best_frame = seq_frame;
-                               best_dist = dist;
-                       }
-               }
-       }
-
-       return best_frame;
-}
-
 static bool strip_jump_internal(Scene *scene,
                                 const short side,
                                 const bool do_skip_mute, const bool do_center)
 {
        bool changed = false;
        int cfra = CFRA;
-       int nfra = find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center);
+       int nfra = BKE_sequencer_find_next_prev_edit(scene, cfra, side, do_skip_mute, do_center, false);
        
        if (nfra != cfra) {
                CFRA = nfra;
@@ -3623,4 +3690,3 @@ void SEQUENCER_OT_change_path(struct wmOperatorType *ot)
                                       WM_FILESEL_DIRECTORY | WM_FILESEL_RELPATH | WM_FILESEL_FILEPATH | WM_FILESEL_FILES,
                                       FILE_DEFAULTDISPLAY);
 }
-
index 438696d0327ddff2da9bc5dee06652d75747c415..f3723b73865cd62e22debfeb74c3933f3c762331 100644 (file)
@@ -45,6 +45,7 @@ struct ARegion;
 struct ARegionType;
 struct Scene;
 struct Main;
+struct SequencePreview;
 
 /* space_sequencer.c */
 struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
@@ -52,7 +53,9 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa);
 
 /* sequencer_draw.c */
 void draw_timeline_seq(const struct bContext *C, struct ARegion *ar);
-void draw_image_seq(const struct bContext *C, struct Scene *scene, struct  ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay);
+void draw_image_seq(const struct bContext *C, struct Scene *scene, struct  ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, bool draw_overlay, bool draw_backdrop);
+void color3ubv_from_seq(struct Scene *curscene, struct Sequence *seq, unsigned char col[3]);
+void draw_shadedstrip(struct Sequence *seq, unsigned char col[3], float x1, float y1, float x2, float y2);
 
 /* UNUSED */
 // void seq_reset_imageofs(struct SpaceSeq *sseq);
@@ -150,13 +153,6 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot);
 void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot);
 void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot);
 
-/* RNA enums, just to be more readable */
-enum {
-       SEQ_SIDE_NONE = 0,
-       SEQ_SIDE_LEFT,
-       SEQ_SIDE_RIGHT,
-       SEQ_SIDE_BOTH
-};
 enum {
        SEQ_CUT_SOFT,
        SEQ_CUT_HARD
@@ -199,5 +195,8 @@ void SEQUENCER_OT_strip_modifier_move(struct wmOperatorType *ot);
 /* sequencer_view.c */
 void SEQUENCER_OT_sample(struct wmOperatorType *ot);
 
+/* sequencer_preview.c */
+void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
+
 #endif /* __SEQUENCER_INTERN_H__ */
 
index 88646b55e23f5f9dfeea3eb22b779ce01f3d84a1..9b5ef18f7cd1cec559982ef223bb28712e64f462 100644 (file)
@@ -40,6 +40,8 @@
 #include "ED_markers.h"
 #include "ED_transform.h" /* transform keymap */
 
+#include "BKE_sequencer.h"
+
 #include "sequencer_intern.h"
 
 
diff --git a/source/blender/editors/space_sequencer/sequencer_preview.c b/source/blender/editors/space_sequencer/sequencer_preview.c
new file mode 100644 (file)
index 0000000..dd6349e
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation, 2003-2009, Antony Riakiotakis
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_sequencer/sequencer_preview.c
+ *  \ingroup spseq
+ */
+
+#include "DNA_sequence_types.h"
+#include "DNA_sound_types.h"
+
+#include "BLI_listbase.h"
+#include "BLI_threads.h"
+
+#include "BKE_sound.h"
+#include "BKE_context.h"
+#include "BKE_global.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "sequencer_intern.h"
+
+typedef struct PreviewJob {
+       ListBase previews;
+       ThreadMutex *mutex;
+       Scene *scene;
+       int total;
+       int processed;
+} PreviewJob;
+
+typedef struct PreviewJobAudio {
+       struct PreviewJobAudio *next, *prev;
+       bSound *sound;
+       int lr; /* sample left or right */
+       int startframe;
+       bool waveform; /* reload sound or waveform */
+} PreviewJobAudio;
+
+static void free_preview_job(void *data)
+{
+       PreviewJob *pj = (PreviewJob *)data;
+
+       BLI_mutex_free(pj->mutex);
+       BLI_freelistN(&pj->previews);
+       MEM_freeN(pj);
+}
+
+/* only this runs inside thread */
+static void preview_startjob(void *data, short *stop, short *do_update, float *progress)
+{
+       PreviewJob *pj = data;
+       PreviewJobAudio *previewjb;
+
+       BLI_mutex_lock(pj->mutex);
+       previewjb = pj->previews.first;
+       BLI_mutex_unlock(pj->mutex);
+       
+       while (previewjb) {
+               PreviewJobAudio *preview_next;
+               bSound *sound = previewjb->sound;
+               
+               sound_read_waveform(sound, true, stop);
+
+               if (*stop || G.is_break) {
+                       BLI_mutex_lock(pj->mutex);
+                       previewjb = previewjb->next;
+                       BLI_mutex_unlock(pj->mutex);
+                       while (previewjb) {
+                               sound = previewjb->sound;
+
+                               /* make sure we cleanup the loading flag! */
+                               BLI_mutex_lock(sound->mutex);
+                               sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING;
+                               BLI_mutex_unlock(sound->mutex);
+                               
+                               BLI_mutex_lock(pj->mutex);
+                               previewjb = previewjb->next;
+                               BLI_mutex_unlock(pj->mutex);
+                       }
+                       
+                       BLI_mutex_lock(pj->mutex);
+                       BLI_freelistN(&pj->previews);
+                       pj->total = 0;
+                       pj->processed = 0;
+                       BLI_mutex_unlock(pj->mutex);
+                       break;
+               }
+               
+               BLI_mutex_lock(pj->mutex);
+               preview_next = previewjb->next;
+               BLI_freelinkN(&pj->previews, previewjb);
+               previewjb = preview_next;
+               pj->processed++;                
+               *progress = (pj->total > 0) ? (float)pj->processed / (float)pj->total : 1.0;
+               *do_update = true;
+               BLI_mutex_unlock(pj->mutex);
+       }
+}
+
+static void preview_endjob(void *data)
+{
+       PreviewJob *pj = data;
+
+       WM_main_add_notifier(NC_SCENE | ND_SEQUENCER, pj->scene);
+}
+
+
+void sequencer_preview_add_sound(const bContext *C, Sequence *seq)
+{
+       /* first, get the preview job, if it exists */
+       wmJob *wm_job;
+       PreviewJob *pj;
+       ScrArea *sa = CTX_wm_area(C);
+       PreviewJobAudio *audiojob = MEM_callocN(sizeof(PreviewJobAudio), "preview_audio");
+       wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), sa, "Strip Previews",
+                            WM_JOB_PROGRESS, WM_JOB_TYPE_SEQ_BUILD_PREVIEW);
+
+       pj = WM_jobs_customdata_get(wm_job);
+
+       if (!pj) {
+               pj = MEM_callocN(sizeof(PreviewJob), "preview rebuild job");
+       
+               pj->mutex = BLI_mutex_alloc();
+               pj->scene = CTX_data_scene(C);
+               
+               WM_jobs_customdata_set(wm_job, pj, free_preview_job);
+               WM_jobs_timer(wm_job, 0.1, NC_SCENE | ND_SEQUENCER, NC_SCENE | ND_SEQUENCER);
+               WM_jobs_callbacks(wm_job, preview_startjob, NULL, NULL, preview_endjob);
+       }
+       
+       /* attempt to lock mutex of job here */
+               
+       audiojob->sound = seq->sound;
+       
+       BLI_mutex_lock(pj->mutex);
+       BLI_addtail(&pj->previews, audiojob);
+       pj->total++;
+       BLI_mutex_unlock(pj->mutex);
+
+       if (!WM_jobs_is_running(wm_job)) {
+               G.is_break = false;
+               WM_jobs_start(CTX_wm_manager(C), wm_job);
+       }
+
+       ED_area_tag_redraw(sa); 
+}
index 007d3c44a6471746ce51a9c405d3e76d3387d814..3f9e2f7257885326437162128e90f6fd6bbcb6e9 100644 (file)
@@ -559,7 +559,7 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
        if (sseq->mainb == SEQ_DRAW_SEQUENCE) sseq->mainb = SEQ_DRAW_IMG_IMBUF;
 
        if (!show_split || sseq->overlay_type != SEQ_DRAW_OVERLAY_REFERENCE)
-               draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false);
+               draw_image_seq(C, scene, ar, sseq, scene->r.cfra, 0, false, false);
 
        if (show_split && sseq->overlay_type != SEQ_DRAW_OVERLAY_CURRENT) {
                int over_cfra;
@@ -570,7 +570,7 @@ static void sequencer_preview_area_draw(const bContext *C, ARegion *ar)
                        over_cfra = scene->r.cfra + scene->ed->over_ofs;
 
                if (over_cfra != scene->r.cfra || sseq->overlay_type != SEQ_DRAW_OVERLAY_RECT)
-                       draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true);
+                       draw_image_seq(C, scene, ar, sseq, scene->r.cfra, over_cfra - scene->r.cfra, true, false);
        }
 
        if ((U.uiflag & USER_SHOW_FPS) && ED_screen_animation_playing(wm)) {
index ca9712814200bfbfe3431118f9ebd1258005f434..7e27c11ec8ad1d5375947f7be3d33bcbc5aab394 100644 (file)
@@ -7126,10 +7126,11 @@ static void headerSeqSlide(TransInfo *t, float val[2], char str[MAX_INFO_LEN])
                            WM_bool_as_string((t->flag & T_ALT_TRANSFORM) != 0));
 }
 
-static void applySeqSlideValue(TransInfo *t, const float val[2])
+static void applySeqSlideValue(TransInfo *t, const float val[2], int frame)
 {
        TransData *td = t->data;
        int i;
+       TransSeq *ts = t->customData;
 
        for (i = 0; i < t->total; i++, td++) {
                float tvec[2];
@@ -7144,15 +7145,21 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
 
                mul_v2_fl(tvec, td->factor);
 
-               td->loc[0] = td->iloc[0] + tvec[0];
+               if (t->modifiers & MOD_SNAP_INVERT) {
+                       td->loc[0] = frame + td->factor * (td->iloc[0] - ts->min);
+               }
+               else {
+                       td->loc[0] = td->iloc[0] + tvec[0];
+               }
+
                td->loc[1] = td->iloc[1] + tvec[1];
        }
 }
 
-static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
+static void applySeqSlide(TransInfo *t, const int mval[2])
 {
        char str[MAX_INFO_LEN];
-
+       int snap_frame = 0;
        if (t->con.mode & CON_APPLY) {
                float pvec[3] = {0.0f, 0.0f, 0.0f};
                float tvec[3];
@@ -7160,7 +7167,8 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
                copy_v3_v3(t->values, tvec);
        }
        else {
-               snapGridIncrement(t, t->values);
+               snap_frame = snapSequenceBounds(t, mval);
+               // snapGridIncrement(t, t->values);
                applyNumInput(&t->num, t->values);
        }
 
@@ -7168,7 +7176,7 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
        t->values[1] = floor(t->values[1] + 0.5f);
 
        headerSeqSlide(t, t->values, str);
-       applySeqSlideValue(t, t->values);
+       applySeqSlideValue(t, t->values, snap_frame);
 
        recalcData(t);
 
index 67d55639528bc1177e093a9a3ea067377e2c7e32..c2891b50321fc49d5f25383522d00ee7ecc029a4 100644 (file)
@@ -173,6 +173,13 @@ typedef struct TransDataSeq {
 
 } TransDataSeq;
 
+typedef struct TransSeq {
+       TransDataSeq *tdseq;
+       int min;
+       int max;
+       bool snap_left;
+} TransSeq;
+
 /* for NLA transform (stored in td->extra pointer) */
 typedef struct TransDataNla {
        ID *id;                                         /* ID-block NLA-data is attached to */
@@ -588,6 +595,8 @@ typedef enum {
 void snapGridIncrement(TransInfo *t, float *val);
 void snapGridIncrementAction(TransInfo *t, float *val, GearsType action);
 
+int snapSequenceBounds(TransInfo *t, const int mval[2]);
+
 bool activeSnap(TransInfo *t);
 bool validSnap(TransInfo *t);
 
index e16a7155fe6af6b3f77df9dff997dd47f9474713..4d70768cfaa9ee76a8f117ba494f985f4da496b7 100644 (file)
@@ -4528,10 +4528,47 @@ static int SeqToTransData_Recursive(TransInfo *t, ListBase *seqbase, TransData *
                        }
                }
        }
-
        return tot;
 }
 
+
+static void SeqTransDataBounds(TransInfo *t, ListBase *seqbase, TransSeq *ts)
+{
+       Sequence *seq;
+       int recursive, count, flag;
+       int max = INT32_MIN, min = INT32_MAX;
+
+       for (seq = seqbase->first; seq; seq = seq->next) {
+
+               /* just to get the flag since there are corner cases where this isn't totally obvious */
+               SeqTransInfo(t, seq, &recursive, &count, &flag);
+
+               /* use 'flag' which is derived from seq->flag but modified for special cases */
+               if (flag & SELECT) {
+                       if (flag & (SEQ_LEFTSEL | SEQ_RIGHTSEL)) {
+                               if (flag & SEQ_LEFTSEL) {
+                                       min = min_ii(seq->startdisp, min);
+                                       max = max_ii(seq->startdisp, max);
+                               }
+                               if (flag & SEQ_RIGHTSEL) {
+                                       min = min_ii(seq->enddisp, min);
+                                       max = max_ii(seq->enddisp, max);
+                               }
+                       }
+                       else {
+                               min = min_ii(seq->startdisp, min);
+                               max = max_ii(seq->enddisp, max);
+                       }
+               }
+       }
+
+       if (ts) {
+               ts->max = max;
+               ts->min = min;
+       }
+}
+
+
 static void freeSeqData(TransInfo *t)
 {
        Editing *ed = BKE_sequencer_editing_get(t->scene, false);
@@ -4694,6 +4731,8 @@ static void freeSeqData(TransInfo *t)
        }
 
        if ((t->customData != NULL) && (t->flag & T_FREE_CUSTOMDATA)) {
+               TransSeq *ts = t->customData;
+               MEM_freeN(ts->tdseq);
                MEM_freeN(t->customData);
                t->customData = NULL;
        }
@@ -4713,6 +4752,8 @@ static void createTransSeqData(bContext *C, TransInfo *t)
        TransData *td = NULL;
        TransData2D *td2d = NULL;
        TransDataSeq *tdsq = NULL;
+       TransSeq *ts = NULL;
+       float xmouse, ymouse;
 
        int count = 0;
 
@@ -4723,12 +4764,11 @@ static void createTransSeqData(bContext *C, TransInfo *t)
 
        t->customFree = freeSeqData;
 
+       UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
+
        /* which side of the current frame should be allowed */
        if (t->mode == TFM_TIME_EXTEND) {
                /* only side on which mouse is gets transformed */
-               float xmouse, ymouse;
-
-               UI_view2d_region_to_view(v2d, t->imval[0], t->imval[1], &xmouse, &ymouse);
                t->frame_side = (xmouse > CFRA) ? 'R' : 'L';
        }
        else {
@@ -4768,15 +4808,19 @@ static void createTransSeqData(bContext *C, TransInfo *t)
                return;
        }
 
+       t->customData = ts = MEM_mallocN(sizeof(TransSeq), "transseq");
        td = t->data = MEM_callocN(t->total * sizeof(TransData), "TransSeq TransData");
        td2d = t->data2d = MEM_callocN(t->total * sizeof(TransData2D), "TransSeq TransData2D");
-       tdsq = t->customData = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
+       ts->tdseq = tdsq = MEM_callocN(t->total * sizeof(TransDataSeq), "TransSeq TransDataSeq");
        t->flag |= T_FREE_CUSTOMDATA;
 
-
-
        /* loop 2: build transdata array */
        SeqToTransData_Recursive(t, ed->seqbasep, td, td2d, tdsq);
+       SeqTransDataBounds(t, ed->seqbasep, ts);
+       
+       /* set the snap mode based on how close the mouse is at the end/start points */
+       if (abs(xmouse - ts->max) > abs(xmouse - ts->min))
+               ts->snap_left = true;
 
 #undef XXX_DURIAN_ANIM_TX_HACK
 }
index 92c9c55ac64b64511f58990d66fc8b369f1b89a4..4a2927ace00d923e56c44e796a501537d415423a 100644 (file)
@@ -59,6 +59,7 @@
 #include "BKE_anim.h"  /* for duplis */
 #include "BKE_context.h"
 #include "BKE_editmesh.h"
+#include "BKE_sequencer.h"
 #include "BKE_main.h"
 #include "BKE_tracking.h"
 
@@ -2430,6 +2431,27 @@ void snapGridIncrement(TransInfo *t, float *val)
        snapGridIncrementAction(t, val, action);
 }
 
+int snapSequenceBounds(TransInfo *t, const int mval[2])
+{
+       float xmouse, ymouse;
+       int frame;
+       int mframe;
+       TransSeq *ts = t->customData;
+       /* reuse increment, strictly speaking could be another snap mode, but leave as is */
+       if (!(t->modifiers & MOD_SNAP_INVERT))
+               return 0;
+
+       /* convert to frame range */
+       UI_view2d_region_to_view(&t->ar->v2d, mval[0], mval[1], &xmouse, &ymouse);
+       mframe = iroundf(xmouse);
+       /* now find the closest sequence */
+       frame = BKE_sequencer_find_next_prev_edit(t->scene, mframe, SEQ_SIDE_BOTH, true, false, true);
+
+       if (!ts->snap_left)
+               frame = frame - (ts->max - ts->min);
+
+       return frame;
+}
 
 static void applyGridIncrement(TransInfo *t, float *val, int max_index, const float fac[3], GearsType action)
 {
index af33ae80ed9d6111dcc7586ea31549bdf6683483..a7288b95a7a14867d86cea8e8683f091ac5ec1cc 100644 (file)
@@ -131,10 +131,11 @@ typedef struct Sequence {
 
        int flag, type; /*flags bitmap (see below) and the type of sequence*/
        int len; /* the length of the contents of this strip - before handles are applied */
-       int start, startofs, endofs;
-       int startstill, endstill;
+       int start; /* start frame of contents of strip in absolute frame coordinates. For metastrips start of first strip startdisp */
+       int startofs, endofs; /* frames after the first frame where display starts, frames before the last frame where display ends */
+       int startstill, endstill; /* frames that use the first frame before data begins, frames that use the last frame after data ends */
        int machine, depth; /*machine - the strip channel, depth - the depth in the sequence when dealing with metastrips */
-       int startdisp, enddisp; /*starting and ending points in the sequence*/
+       int startdisp, enddisp; /* starting and ending points of the strip in the sequence*/
        float sat;
        float mul, handsize;
 
index d7a513597777a21f4de3c8651a06530ce8e97788..4ab22e4f7b73dce82b0c50fa60aeac398c8900c9 100644 (file)
@@ -95,6 +95,8 @@ typedef struct bSound {
         */
        void *playback_handle;
 
+       /* mutex for asynchronous loading of sounds */
+       void *mutex;
        /* XXX unused currently (SOUND_TYPE_LIMITER) */
        /* float start, end; */
 } bSound;
@@ -116,9 +118,10 @@ enum {
 };
 
 enum {
-       SOUND_FLAGS_3D          = (1 << 3),  /* deprecated! used for sound actuator loading */
-       SOUND_FLAGS_CACHING     = (1 << 4),
-       SOUND_FLAGS_MONO        = (1 << 5),
+       SOUND_FLAGS_3D                   = (1 << 3),  /* deprecated! used for sound actuator loading */
+       SOUND_FLAGS_CACHING              = (1 << 4),
+       SOUND_FLAGS_MONO                 = (1 << 5),
+       SOUND_FLAGS_WAVEFORM_LOADING     = (1 << 6),
 };
 
 #if (DNA_DEPRECATED_GCC_POISON == 1)
index a8fe8ceb6b0be0e89f6ba69efb334789fda27e11..dd661d00d546af059be5a3da02ce253c7670a978 100644 (file)
@@ -497,6 +497,8 @@ typedef struct SpaceSeq {
        float zoom DNA_DEPRECATED;  /* deprecated, handled by View2D now */
        int view; /* see SEQ_VIEW_* below */
        int overlay_type;
+       int draw_flag; /* overlay an image of the editing on below the strips */
+       int pad;
 
        struct bGPdata *gpd;        /* grease-pencil data */
 
@@ -513,6 +515,12 @@ typedef enum eSpaceSeq_RegionType {
        SEQ_DRAW_IMG_HISTOGRAM = 4,
 } eSpaceSeq_RegionType;
 
+/* sseq->draw_flag */
+typedef enum eSpaceSeq_DrawFlag {
+       SEQ_DRAW_BACKDROP              = (1 << 0),
+} eSpaceSeq_DrawFlag;
+
+
 /* sseq->flag */
 typedef enum eSpaceSeq_Flag {
        SEQ_DRAWFRAMES              = (1 << 0),
@@ -522,6 +530,8 @@ typedef enum eSpaceSeq_Flag {
        SEQ_SHOW_GPENCIL            = (1 << 4),
        SEQ_NO_DRAW_CFRANUM         = (1 << 5),
        SEQ_USE_ALPHA               = (1 << 6), /* use RGBA display mode for preview */
+       SEQ_ALL_WAVEFORMS           = (1 << 7), /* draw all waveforms */
+       SEQ_NO_WAVEFORMS            = (1 << 8), /* draw no waveforms */
 } eSpaceSeq_Flag;
 
 /* sseq->view */
index 206a72a01b0d3fb1b52368b6220307110e3d6ff7..aa39e81d39050774e2231f1c5264602b7ccab4ac 100644 (file)
@@ -38,6 +38,7 @@
 
 #include "BKE_sound.h"
 #include "BKE_context.h"
+#include "BKE_sequencer.h"
 
 static void rna_Sound_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
 {
@@ -59,9 +60,9 @@ static void rna_Sound_caching_set(PointerRNA *ptr, const int value)
                sound_delete_cache(sound);
 }
 
-static void rna_Sound_caching_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_Sound_caching_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
 {
-       sound_update_sequencer(bmain, (bSound *)(ptr->data));
+       BKE_sequencer_update_sound(scene, (bSound *)(ptr->data));
 }
 
 #else
index cb5da547c8082f2798245f2247abb74a7f0a3534..78e351d1231eec2e05f43e3116eee8868aa6218d 100644 (file)
@@ -2514,6 +2514,16 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
                {0, NULL, 0, NULL, NULL}
        };
 
+       static EnumPropertyItem waveform_type_draw_items[] = {
+               {SEQ_NO_WAVEFORMS, "NO_WAVEFORMS", 0, "Waveforms Off",
+                "No waveforms drawn for all sound strips"},
+               {SEQ_ALL_WAVEFORMS, "ALL_WAVEFORMS", 0, "Waveforms On",
+                "Waveforms drawn for all sound strips"},
+               {0, "DEFAULT_WAVEFORMS", 0, "Use Strip Option",
+                "Waveforms drawn according to strip setting"},
+               {0, NULL, 0, NULL, NULL}
+       };
+
        srna = RNA_def_struct(brna, "SpaceSequenceEditor", "Space");
        RNA_def_struct_sdna(srna, "SpaceSeq");
        RNA_def_struct_ui_text(srna, "Space Sequence Editor", "Sequence editor space data");
@@ -2583,6 +2593,12 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Draw Channels", "Channels of the preview to draw");
        RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
 
+       prop = RNA_def_property(srna, "waveform_draw_type", PROP_ENUM, PROP_NONE);
+       RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
+       RNA_def_property_enum_items(prop, waveform_type_draw_items);
+       RNA_def_property_ui_text(prop, "Waveform Drawing", "How Waveforms are drawn");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
        prop = RNA_def_property(srna, "draw_overexposed", PROP_INT, PROP_NONE);
        RNA_def_property_int_sdna(prop, NULL, "zebra");
        RNA_def_property_ui_text(prop, "Show Overexposed", "Show overexposed areas with zebra stripes");
@@ -2609,6 +2625,11 @@ static void rna_def_space_sequencer(BlenderRNA *brna)
        RNA_def_property_enum_items(prop, overlay_type_items);
        RNA_def_property_ui_text(prop, "Overlay Type", "Overlay draw type");
        RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
+
+       prop = RNA_def_property(srna, "show_backdrop", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "draw_flag", SEQ_DRAW_BACKDROP);
+       RNA_def_property_ui_text(prop, "Use Backdrop", "Display result under strips");
+       RNA_def_property_update(prop, NC_SPACE | ND_SPACE_SEQUENCER, NULL);
 }
 
 static void rna_def_space_text(BlenderRNA *brna)
index d626c9171f54cfe7b490a557cecfee1172d93f6f..ced7222b0461fbeca4a5047d86e8accac28b787b 100644 (file)
@@ -398,6 +398,7 @@ enum {
        WM_JOB_TYPE_CLIP_SOLVE_CAMERA,
        WM_JOB_TYPE_CLIP_PREFETCH,
        WM_JOB_TYPE_SEQ_BUILD_PROXY,
+       WM_JOB_TYPE_SEQ_BUILD_PREVIEW,
        /* add as needed, screencast, seq proxy build
         * if having hard coded values is a problem */
 };