Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2012-08-19 19:41:56 +0400
committerSergey Sharybin <sergey.vfx@gmail.com>2012-08-19 19:41:56 +0400
commit995a19a983b2c44ec9afec049395d7c1b4320137 (patch)
tree8333563ae983641434179839755aab67ecdc2aad /source
parent994d75b6ae78fee99afd949292e48c4f32292995 (diff)
Sequencer: per-sequence modifier stack for color grading
This implements basic color grading modifiers in sequencer, supporting color balance, RGB curves and HUE corrections. Implementation is close to object modifiers, some details are there: http://wiki.blender.org/index.php/User:Nazg-gul/SequencerModifiers Modifiers supports multi-threaded calculation, masks and instant parameter changes. Also added cache for pre-processed image buffers for current frame, so changing sequence properties does not require rendering of original sequence (like rendering scene, loading file from disk and so)
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_colortools.h4
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h50
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/colortools.c75
-rw-r--r--source/blender/blenkernel/intern/seqcache.c120
-rw-r--r--source/blender/blenkernel/intern/seqmodifier.c522
-rw-r--r--source/blender/blenkernel/intern/sequencer.c434
-rw-r--r--source/blender/blenloader/intern/readfile.c37
-rw-r--r--source/blender/blenloader/intern/writefile.c42
-rw-r--r--source/blender/editors/space_sequencer/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_modifier.c164
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c4
-rw-r--r--source/blender/makesdna/DNA_sequence_types.h61
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c333
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c1
16 files changed, 1645 insertions, 208 deletions
diff --git a/source/blender/blenkernel/BKE_colortools.h b/source/blender/blenkernel/BKE_colortools.h
index f58af8f39a0..dcb40c960b1 100644
--- a/source/blender/blenkernel/BKE_colortools.h
+++ b/source/blender/blenkernel/BKE_colortools.h
@@ -47,8 +47,11 @@ struct rctf;
# define DO_INLINE static inline
#endif
+void curvemapping_set_defaults(struct CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy);
struct CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy);
+void curvemapping_free_data(struct CurveMapping *cumap);
void curvemapping_free(struct CurveMapping *cumap);
+void curvemapping_copy_data(struct CurveMapping *target, struct CurveMapping *cumap);
struct CurveMapping *curvemapping_copy(struct CurveMapping *cumap);
void curvemapping_set_black_white(struct CurveMapping *cumap, const float black[3], const float white[3]);
@@ -69,6 +72,7 @@ float curvemap_evaluateF(struct CurveMap *cuma, float value);
float curvemapping_evaluateF(struct CurveMapping *cumap, int cur, float value);
void curvemapping_evaluate3F(struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
void curvemapping_evaluateRGBF(struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
+void curvemapping_evaluate_premulRGB(struct CurveMapping *cumap, unsigned char vecout_byte[3], const unsigned char vecin_byte[3]);
void curvemapping_evaluate_premulRGBF(struct CurveMapping *cumap, float vecout[3], const float vecin[3]);
void curvemapping_do_ibuf(struct CurveMapping *cumap, struct ImBuf *ibuf);
void curvemapping_premultiply(struct CurveMapping *cumap, int restore);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 823b1dd14da..d05e065ac15 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -31,11 +31,14 @@
*/
struct bContext;
+struct StripColorBalance;
struct Editing;
struct ImBuf;
struct Main;
+struct Mask;
struct Scene;
struct Sequence;
+struct SequenceModifierData;
struct Strip;
struct StripElem;
struct bSound;
@@ -241,6 +244,10 @@ void BKE_sequencer_cache_put(SeqRenderData context, struct Sequence *seq, float
void BKE_sequencer_cache_cleanup_sequence(struct Sequence *seq);
+struct ImBuf *BKE_sequencer_preprocessed_cache_get(SeqRenderData context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type);
+void BKE_sequencer_preprocessed_cache_put(SeqRenderData context, struct Sequence *seq, float cfra, seq_stripelem_ibuf_t type, struct ImBuf *ibuf);
+void BKE_sequencer_preprocessed_cache_cleanup_sequence(struct Sequence *seq);
+
/* **********************************************************************
* seqeffects.c
*
@@ -289,6 +296,7 @@ int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char
int BKE_sequence_check_depend(struct Sequence *seq, struct Sequence *cur);
void BKE_sequence_invalidate_cache(struct Scene *scene, struct Sequence *seq);
+void BKE_sequence_invalidate_cache_for_modifier(struct Scene *scene, struct Sequence *seq);
void BKE_sequencer_update_sound_bounds_all(struct Scene *scene);
void BKE_sequencer_update_sound_bounds(struct Scene *scene, struct Sequence *seq);
@@ -347,4 +355,46 @@ extern SequencerDrawView sequencer_view3d_cb;
extern ListBase seqbase_clipboard;
extern int seqbase_clipboard_frame;
+/* modifiers */
+typedef struct SequenceModifierTypeInfo {
+ /* default name for the modifier */
+ char name[64]; /* MAX_NAME */
+
+ /* DNA structure name used on load/save filed */
+ char struct_name[64]; /* MAX_NAME */
+
+ /* size of modifier data structure, used by allocation */
+ int struct_size;
+
+ /* data initialization */
+ void (*init_data) (struct SequenceModifierData *smd);
+
+ /* free data used by modifier,
+ * only modifier-specific data should be freed, modifier descriptor would
+ * be freed outside of this callback
+ */
+ void (*free_data) (struct SequenceModifierData *smd);
+
+ /* copy data from one modifier to another */
+ void (*copy_data) (struct SequenceModifierData *smd, struct SequenceModifierData *target);
+
+ /* apply modifier on a given image buffer */
+ struct ImBuf* (*apply) (struct SequenceModifierData *smd, struct ImBuf *ibuf, struct ImBuf *mask);
+} SequenceModifierTypeInfo;
+
+struct SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type);
+
+void BKE_sequence_modifier_new(struct Sequence *seq, int type);
+void BKE_sequence_modifier_free(struct SequenceModifierData *smd);
+void BKE_sequence_modifier_unique_name(struct Sequence *seq, struct SequenceModifierData *smd);
+struct SequenceModifierData *BKE_sequence_modifier_find_by_name(struct Sequence *seq, char *name);
+struct ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, struct Sequence *seq, struct ImBuf *ibuf, int cfra);
+void BKE_sequence_modifier_list_copy(struct Sequence *seqn, struct Sequence *seq);
+
+int BKE_sequence_supports_modifiers(struct Sequence *seq);
+
+/* internal filters */
+struct ImBuf *BKE_sequencer_render_mask_input(SeqRenderData context, int mask_input_type, struct Sequence *mask_sequence, struct Mask *mask_id, int cfra, int make_float);
+void BKE_sequencer_color_balance_apply(struct StripColorBalance *cb, struct ImBuf *ibuf, float mul, short make_float, struct ImBuf *mask_input);
+
#endif /* __BKE_SEQUENCER_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 38a39ad492d..0a0635126f5 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -128,6 +128,7 @@ set(SRC
intern/script.c
intern/seqcache.c
intern/seqeffects.c
+ intern/seqmodifier.c
intern/sequencer.c
intern/shrinkwrap.c
intern/sketch.c
diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c
index 20fae973756..118169e8f7d 100644
--- a/source/blender/blenkernel/intern/colortools.c
+++ b/source/blender/blenkernel/intern/colortools.c
@@ -56,13 +56,11 @@
/* ***************** operations on full struct ************* */
-CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
+void curvemapping_set_defaults(CurveMapping *cumap, int tot, float minx, float miny, float maxx, float maxy)
{
- CurveMapping *cumap;
int a;
float clipminx, clipminy, clipmaxx, clipmaxy;
- cumap = MEM_callocN(sizeof(CurveMapping), "new curvemap");
cumap->flag = CUMA_DO_CLIP;
if (tot == 4) cumap->cur = 3; /* rhms, hack for 'col' curve? */
@@ -89,38 +87,59 @@ CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, floa
}
cumap->changed_timestamp = 0;
+}
+
+CurveMapping *curvemapping_add(int tot, float minx, float miny, float maxx, float maxy)
+{
+ CurveMapping *cumap;
+
+ cumap = MEM_callocN(sizeof(CurveMapping), "new curvemap");
+
+ curvemapping_set_defaults(cumap, tot, minx, miny, maxx, maxy);
return cumap;
}
-void curvemapping_free(CurveMapping *cumap)
+void curvemapping_free_data(CurveMapping *cumap)
{
int a;
-
+
+ for (a = 0; a < CM_TOT; a++) {
+ if (cumap->cm[a].curve) MEM_freeN(cumap->cm[a].curve);
+ if (cumap->cm[a].table) MEM_freeN(cumap->cm[a].table);
+ if (cumap->cm[a].premultable) MEM_freeN(cumap->cm[a].premultable);
+ }
+}
+
+void curvemapping_free(CurveMapping *cumap)
+{
if (cumap) {
- for (a = 0; a < CM_TOT; a++) {
- if (cumap->cm[a].curve) MEM_freeN(cumap->cm[a].curve);
- if (cumap->cm[a].table) MEM_freeN(cumap->cm[a].table);
- if (cumap->cm[a].premultable) MEM_freeN(cumap->cm[a].premultable);
- }
+ curvemapping_free_data(cumap);
MEM_freeN(cumap);
}
}
-CurveMapping *curvemapping_copy(CurveMapping *cumap)
+void curvemapping_copy_data(CurveMapping *target, CurveMapping *cumap)
{
int a;
-
+
+ *target = *cumap;
+
+ for (a = 0; a < CM_TOT; a++) {
+ if (cumap->cm[a].curve)
+ target->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve);
+ if (cumap->cm[a].table)
+ target->cm[a].table = MEM_dupallocN(cumap->cm[a].table);
+ if (cumap->cm[a].premultable)
+ target->cm[a].premultable = MEM_dupallocN(cumap->cm[a].premultable);
+ }
+}
+
+CurveMapping *curvemapping_copy(CurveMapping *cumap)
+{
if (cumap) {
CurveMapping *cumapn = MEM_dupallocN(cumap);
- for (a = 0; a < CM_TOT; a++) {
- if (cumap->cm[a].curve)
- cumapn->cm[a].curve = MEM_dupallocN(cumap->cm[a].curve);
- if (cumap->cm[a].table)
- cumapn->cm[a].table = MEM_dupallocN(cumap->cm[a].table);
- if (cumap->cm[a].premultable)
- cumapn->cm[a].premultable = MEM_dupallocN(cumap->cm[a].premultable);
- }
+ curvemapping_copy_data(cumapn, cumap);
return cumapn;
}
return NULL;
@@ -782,6 +801,22 @@ void curvemapping_evaluate_premulRGBF(CurveMapping *cumap, float vecout[3], cons
vecout[2] = curvemap_evaluateF(cumap->cm + 2, fac);
}
+/* same as above, byte version */
+void curvemapping_evaluate_premulRGB(CurveMapping *cumap, unsigned char vecout_byte[3], const unsigned char vecin_byte[3])
+{
+ float vecin[3], vecout[3];
+
+ vecin[0] = (float) vecin_byte[0] / 255.0f;
+ vecin[1] = (float) vecin_byte[1] / 255.0f;
+ vecin[2] = (float) vecin_byte[2] / 255.0f;
+
+ curvemapping_evaluate_premulRGBF(cumap, vecout, vecin);
+
+ vecout_byte[0] = FTOCHAR(vecout[0]);
+ vecout_byte[1] = FTOCHAR(vecout[1]);
+ vecout_byte[2] = FTOCHAR(vecout[2]);
+}
+
/* only used for image editor curves */
void curvemapping_do_ibuf(CurveMapping *cumap, ImBuf *ibuf)
diff --git a/source/blender/blenkernel/intern/seqcache.c b/source/blender/blenkernel/intern/seqcache.c
index 387ec67eb1c..d79f23e8979 100644
--- a/source/blender/blenkernel/intern/seqcache.c
+++ b/source/blender/blenkernel/intern/seqcache.c
@@ -37,8 +37,11 @@
#include "BKE_sequencer.h"
#include "IMB_moviecache.h"
+#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
+#include "BLI_listbase.h"
+
typedef struct SeqCacheKey {
struct Sequence *seq;
SeqRenderData context;
@@ -46,7 +49,25 @@ typedef struct SeqCacheKey {
seq_stripelem_ibuf_t type;
} SeqCacheKey;
+typedef struct SeqPreprocessCacheElem {
+ struct SeqPreprocessCacheElem *next, *prev;
+
+ struct Sequence *seq;
+ SeqRenderData context;
+ seq_stripelem_ibuf_t type;
+
+ ImBuf *ibuf;
+} SeqPreprocessCacheElem;
+
+typedef struct SeqPreprocessCache {
+ int cfra;
+ ListBase elems;
+} SeqPreprocessCache;
+
static struct MovieCache *moviecache = NULL;
+static struct SeqPreprocessCache *preprocess_cache = NULL;
+
+static void preprocessed_cache_destruct(void);
static int seq_cmp_render_data(const SeqRenderData *a, const SeqRenderData *b)
{
@@ -160,6 +181,8 @@ void BKE_sequencer_cache_destruct(void)
{
if (moviecache)
IMB_moviecache_free(moviecache);
+
+ preprocessed_cache_destruct();
}
void BKE_sequencer_cache_cleanup(void)
@@ -219,3 +242,100 @@ void BKE_sequencer_cache_put(SeqRenderData context, Sequence *seq, float cfra, s
IMB_moviecache_put(moviecache, &key, i);
}
+
+static void preprocessed_cache_clean(void)
+{
+ SeqPreprocessCacheElem *elem;
+
+ if (!preprocess_cache)
+ return;
+
+ for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
+ IMB_freeImBuf(elem->ibuf);
+ }
+ BLI_freelistN(&preprocess_cache->elems);
+
+ preprocess_cache->elems.first = preprocess_cache->elems.last = NULL;
+}
+
+static void preprocessed_cache_destruct(void)
+{
+ if (!preprocess_cache)
+ return;
+
+ preprocessed_cache_clean();
+
+ MEM_freeN(preprocess_cache);
+ preprocess_cache = NULL;
+}
+
+ImBuf *BKE_sequencer_preprocessed_cache_get(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type)
+{
+ SeqPreprocessCacheElem *elem;
+
+ if (!preprocess_cache)
+ return NULL;
+
+ if (preprocess_cache->cfra != cfra)
+ return NULL;
+
+ for (elem = preprocess_cache->elems.first; elem; elem = elem->next) {
+ if (elem->seq != seq)
+ continue;
+
+ if (elem->type != type)
+ continue;
+
+ if (seq_cmp_render_data(&elem->context, &context) != 0)
+ continue;
+
+ IMB_refImBuf(elem->ibuf);
+ return elem->ibuf;
+ }
+
+ return NULL;
+}
+
+void BKE_sequencer_preprocessed_cache_put(SeqRenderData context, Sequence *seq, float cfra, seq_stripelem_ibuf_t type, ImBuf *ibuf)
+{
+ SeqPreprocessCacheElem *elem;
+
+ if (!preprocess_cache) {
+ preprocess_cache = MEM_callocN(sizeof(SeqPreprocessCache), "sequencer preprocessed cache");
+ }
+ else {
+ if (preprocess_cache->cfra != cfra)
+ preprocessed_cache_clean();
+ }
+
+ elem = MEM_callocN(sizeof(SeqPreprocessCacheElem), "sequencer preprocessed cache element");
+
+ elem->seq = seq;
+ elem->type = type;
+ elem->context = context;
+ elem->ibuf = ibuf;
+
+ preprocess_cache->cfra = cfra;
+
+ IMB_refImBuf(ibuf);
+
+ BLI_addtail(&preprocess_cache->elems, elem);
+}
+
+void BKE_sequencer_preprocessed_cache_cleanup_sequence(Sequence *seq)
+{
+ SeqPreprocessCacheElem *elem, *elem_next;
+
+ if (!preprocess_cache)
+ return;
+
+ for (elem = preprocess_cache->elems.first; elem; elem = elem_next) {
+ elem_next = elem->next;
+
+ if (elem->seq == seq) {
+ IMB_freeImBuf(elem->ibuf);
+
+ BLI_freelinkN(&preprocess_cache->elems, elem);
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c
new file mode 100644
index 00000000000..4157a3a1562
--- /dev/null
+++ b/source/blender/blenkernel/intern/seqmodifier.c
@@ -0,0 +1,522 @@
+/*
+ * ***** 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) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/seqmodifier.c
+ * \ingroup bke
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_listbase.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+
+#include "DNA_sequence_types.h"
+
+#include "BKE_colortools.h"
+#include "BKE_sequencer.h"
+#include "BKE_utildefines.h"
+
+#include "IMB_imbuf.h"
+#include "IMB_imbuf_types.h"
+
+static SequenceModifierTypeInfo *modifiersTypes[NUM_SEQUENCE_MODIFIER_TYPES];
+static int modifierTypesInit = FALSE;
+
+/*********************** Modifiers *************************/
+
+typedef void (*modifier_apply_threaded_cb) (int width, int height, unsigned char *rect, float *rect_float,
+ unsigned char *mask_rect, float *mask_rect_float, void *data_v);
+
+typedef struct ModifierInitData {
+ ImBuf *ibuf;
+ ImBuf *mask;
+ void *user_data;
+
+ modifier_apply_threaded_cb apply_callback;
+} ModifierInitData;
+
+typedef struct ModifierThread {
+ int width, height;
+
+ unsigned char *rect, *mask_rect;
+ float *rect_float, *mask_rect_float;
+
+ void *user_data;
+
+ modifier_apply_threaded_cb apply_callback;
+} ModifierThread;
+
+
+static ImBuf *modifier_mask_get(SequenceModifierData *smd, SeqRenderData context, int cfra, int make_float)
+{
+ return BKE_sequencer_render_mask_input(context, smd->mask_input_type, smd->mask_sequence, smd->mask_id, cfra, make_float);
+}
+
+static void modifier_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
+{
+ ModifierThread *handle = (ModifierThread *) handle_v;
+ ModifierInitData *init_data = (ModifierInitData *) init_data_v;
+ ImBuf *ibuf = init_data->ibuf;
+ ImBuf *mask = init_data->mask;
+
+ int offset = 4 * start_line * ibuf->x;
+
+ memset(handle, 0, sizeof(ModifierThread));
+
+ handle->width = ibuf->x;
+ handle->height = tot_line;
+ handle->apply_callback = init_data->apply_callback;
+ handle->user_data = init_data->user_data;
+
+ if (ibuf->rect)
+ handle->rect = (unsigned char *) ibuf->rect + offset;
+
+ if (ibuf->rect_float)
+ handle->rect_float = ibuf->rect_float + offset;
+
+ if (mask) {
+ if (mask->rect)
+ handle->mask_rect = (unsigned char *) mask->rect + offset;
+
+ if (mask->rect_float)
+ handle->mask_rect_float = mask->rect_float + offset;
+ }
+ else {
+ handle->mask_rect = NULL;
+ handle->mask_rect_float = NULL;
+ }
+}
+
+static void *modifier_do_thread(void *thread_data_v)
+{
+ ModifierThread *td = (ModifierThread *) thread_data_v;
+
+ td->apply_callback(td->width, td->height, td->rect, td->rect_float, td->mask_rect, td->mask_rect_float, td->user_data);
+
+ return NULL;
+}
+
+static void modifier_apply_threaded(ImBuf *ibuf, ImBuf *mask, modifier_apply_threaded_cb apply_callback, void *user_data)
+{
+ ModifierInitData init_data;
+
+ init_data.ibuf = ibuf;
+ init_data.mask = mask;
+ init_data.user_data = user_data;
+
+ init_data.apply_callback = apply_callback;
+
+ IMB_processor_apply_threaded(ibuf->y, sizeof(ModifierThread), &init_data,
+ modifier_init_handle, modifier_do_thread);
+}
+
+/* **** Color Balance Modifier **** */
+
+void colorBalance_init_data(SequenceModifierData *smd)
+{
+ ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd;
+ int c;
+
+ cbmd->color_multiply = 1.0f;
+
+ for (c = 0; c < 3; c++) {
+ cbmd->color_balance.lift[c] = 1.0f;
+ cbmd->color_balance.gamma[c] = 1.0f;
+ cbmd->color_balance.gain[c] = 1.0f;
+ }
+}
+
+ImBuf *colorBalance_apply(SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
+{
+ ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd;
+ ImBuf *ibuf_new = IMB_dupImBuf(ibuf);
+
+ BKE_sequencer_color_balance_apply(&cbmd->color_balance, ibuf_new, cbmd->color_multiply, FALSE, mask);
+
+ return ibuf_new;
+}
+
+static SequenceModifierTypeInfo seqModifier_ColorBalance = {
+ "Color Balance", /* name */
+ "ColorBalanceModifierData", /* struct_name */
+ sizeof(ColorBalanceModifierData), /* struct_size */
+ colorBalance_init_data, /* init_data */
+ NULL, /* free_data */
+ NULL, /* copy_data */
+ colorBalance_apply /* apply */
+};
+
+/* **** Curves Modifier **** */
+
+void curves_init_data(SequenceModifierData *smd)
+{
+ CurvesModifierData *cmd = (CurvesModifierData *) smd;
+
+ curvemapping_set_defaults(&cmd->curve_mapping, 4, 0.0f, 0.0f, 1.0f, 1.0f);
+}
+
+void curves_free_data(SequenceModifierData *smd)
+{
+ CurvesModifierData *cmd = (CurvesModifierData *) smd;
+
+ curvemapping_free_data(&cmd->curve_mapping);
+}
+
+void curves_copy_data(SequenceModifierData *target, SequenceModifierData *smd)
+{
+ CurvesModifierData *cmd = (CurvesModifierData *) smd;
+ CurvesModifierData *cmd_target = (CurvesModifierData *) target;
+
+ curvemapping_copy_data(&cmd_target->curve_mapping, &cmd->curve_mapping);
+}
+
+void curves_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
+ unsigned char *mask_rect, float *mask_rect_float, void *data_v)
+{
+ CurveMapping *curve_mapping = (CurveMapping *) data_v;
+ int x, y;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ int pixel_index = (y * width + x) * 4;
+
+ if (rect_float) {
+ float *pixel = rect_float + pixel_index;
+ float result[3];
+
+ curvemapping_evaluate_premulRGBF(curve_mapping, result, pixel);
+
+ if (mask_rect_float) {
+ float *m = mask_rect_float + pixel_index;
+
+ pixel[0] = pixel[0] * (1.0f - m[0]) + result[0] * m[0];
+ pixel[1] = pixel[1] * (1.0f - m[1]) + result[1] * m[1];
+ pixel[2] = pixel[2] * (1.0f - m[2]) + result[2] * m[2];
+ }
+ else {
+ pixel[0] = result[0];
+ pixel[1] = result[1];
+ pixel[2] = result[2];
+ }
+ }
+ if (rect) {
+ unsigned char *pixel = rect + pixel_index;
+ unsigned char result[3];
+
+ curvemapping_evaluate_premulRGB(curve_mapping, result, pixel);
+
+ if (mask_rect) {
+ float t[3];
+
+ rgb_uchar_to_float(t, mask_rect + pixel_index);
+
+ pixel[0] = pixel[0] * (1.0f - t[0]) + result[0] * t[0];
+ pixel[1] = pixel[1] * (1.0f - t[1]) + result[1] * t[1];
+ pixel[2] = pixel[2] * (1.0f - t[2]) + result[2] * t[2];
+ }
+ else {
+ pixel[0] = result[0];
+ pixel[1] = result[1];
+ pixel[2] = result[2];
+ }
+ }
+ }
+ }
+}
+
+ImBuf *curves_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
+{
+ CurvesModifierData *cmd = (CurvesModifierData *) smd;
+ ImBuf *ibuf_new = IMB_dupImBuf(ibuf);
+
+ float black[3] = {0.0f, 0.0f, 0.0f};
+ float white[3] = {1.0f, 1.0f, 1.0f};
+
+ curvemapping_initialize(&cmd->curve_mapping);
+
+ curvemapping_premultiply(&cmd->curve_mapping, 0);
+ curvemapping_set_black_white(&cmd->curve_mapping, black, white);
+
+ modifier_apply_threaded(ibuf_new, mask, curves_apply_threaded, &cmd->curve_mapping);
+
+ curvemapping_premultiply(&cmd->curve_mapping, 1);
+
+ return ibuf_new;
+}
+
+static SequenceModifierTypeInfo seqModifier_Curves = {
+ "Curves", /* name */
+ "CurvesModifierData", /* struct_name */
+ sizeof(CurvesModifierData), /* struct_size */
+ curves_init_data, /* init_data */
+ curves_free_data, /* free_data */
+ curves_copy_data, /* copy_data */
+ curves_apply /* apply */
+};
+
+/* **** Hue Correct Modifier **** */
+
+void hue_correct_init_data(SequenceModifierData *smd)
+{
+ HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
+ int c;
+
+ curvemapping_set_defaults(&hcmd->curve_mapping, 1, 0.0f, 0.0f, 1.0f, 1.0f);
+ hcmd->curve_mapping.preset = CURVE_PRESET_MID9;
+
+ for (c = 0; c < 3; c++) {
+ CurveMap *cuma = &hcmd->curve_mapping.cm[c];
+
+ curvemap_reset(cuma, &hcmd->curve_mapping.clipr, hcmd->curve_mapping.preset, CURVEMAP_SLOPE_POSITIVE);
+ }
+
+ /* default to showing Saturation */
+ hcmd->curve_mapping.cur = 1;
+}
+
+void hue_correct_free_data(SequenceModifierData *smd)
+{
+ HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
+
+ curvemapping_free_data(&hcmd->curve_mapping);
+}
+
+void hue_correct_copy_data(SequenceModifierData *target, SequenceModifierData *smd)
+{
+ HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
+ HueCorrectModifierData *hcmd_target = (HueCorrectModifierData *) target;
+
+ curvemapping_copy_data(&hcmd_target->curve_mapping, &hcmd->curve_mapping);
+}
+
+void hue_correct_apply_threaded(int width, int height, unsigned char *rect, float *rect_float,
+ unsigned char *mask_rect, float *mask_rect_float, void *data_v)
+{
+ CurveMapping *curve_mapping = (CurveMapping *) data_v;
+ int x, y;
+
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width; x++) {
+ int pixel_index = (y * width + x) * 4;
+ float pixel[3], result[3], mask[3] = {1.0f, 1.0f, 1.0f};
+ float hsv[3], f;
+
+ if (rect_float)
+ copy_v3_v3(pixel, rect_float + pixel_index);
+ else
+ rgb_uchar_to_float(pixel, rect + pixel_index);
+
+ rgb_to_hsv(pixel[0], pixel[1], pixel[2], hsv, hsv + 1, hsv + 2);
+
+ /* adjust hue, scaling returned default 0.5 up to 1 */
+ f = curvemapping_evaluateF(curve_mapping, 0, hsv[0]);
+ hsv[0] += f - 0.5f;
+
+ /* adjust saturation, scaling returned default 0.5 up to 1 */
+ f = curvemapping_evaluateF(curve_mapping, 1, hsv[0]);
+ hsv[1] *= (f * 2.0f);
+
+ /* adjust value, scaling returned default 0.5 up to 1 */
+ f = curvemapping_evaluateF(curve_mapping, 2, hsv[0]);
+ hsv[2] *= (f * 2.f);
+
+ hsv[0] = hsv[0] - floorf(hsv[0]); /* mod 1.0 */
+ CLAMP(hsv[1], 0.0f, 1.0f);
+
+ /* convert back to rgb */
+ hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2);
+
+ if (mask_rect_float)
+ copy_v3_v3(mask, mask_rect_float + pixel_index);
+ else if (mask_rect)
+ rgb_uchar_to_float(mask, mask_rect + pixel_index);
+
+ result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0];
+ result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1];
+ result[2] = pixel[2] * (1.0f - mask[2]) + result[2] * mask[2];
+
+ if (rect_float)
+ copy_v3_v3(rect_float + pixel_index, result);
+ else
+ rgb_float_to_uchar(rect + pixel_index, result);
+ }
+ }
+}
+
+ImBuf *hue_correct_apply(struct SequenceModifierData *smd, ImBuf *ibuf, ImBuf *mask)
+{
+ HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
+ ImBuf *ibuf_new = IMB_dupImBuf(ibuf);
+
+ curvemapping_initialize(&hcmd->curve_mapping);
+
+ modifier_apply_threaded(ibuf_new, mask, hue_correct_apply_threaded, &hcmd->curve_mapping);
+
+ return ibuf_new;
+}
+
+static SequenceModifierTypeInfo seqModifier_HueCorrect = {
+ "Hue Correct", /* name */
+ "HueCorrectModifierData", /* struct_name */
+ sizeof(HueCorrectModifierData), /* struct_size */
+ hue_correct_init_data, /* init_data */
+ hue_correct_free_data, /* free_data */
+ hue_correct_copy_data, /* copy_data */
+ hue_correct_apply /* apply */
+};
+
+/*********************** Modifier functions *************************/
+
+static void sequence_modifier_type_info_init(void)
+{
+#define INIT_TYPE(typeName) (modifiersTypes[seqModifierType_##typeName] = &seqModifier_##typeName)
+
+ INIT_TYPE(ColorBalance);
+ INIT_TYPE(Curves);
+ INIT_TYPE(HueCorrect);
+
+#undef INIT_TYPE
+}
+
+SequenceModifierTypeInfo *BKE_sequence_modifier_type_info_get(int type)
+{
+ if (!modifierTypesInit) {
+ sequence_modifier_type_info_init();
+ modifierTypesInit = TRUE;
+ }
+
+ return modifiersTypes[type];
+}
+
+void BKE_sequence_modifier_new(Sequence *seq, int type)
+{
+ SequenceModifierData *smd;
+ SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(type);
+
+ smd = MEM_callocN(smti->struct_size, "sequence modifier");
+
+ smd->type = type;
+ smd->flag |= SEQUENCE_MODIFIER_EXPANDED;
+
+ BLI_strncpy(smd->name, smti->name, sizeof(smd->name));
+
+ BLI_addtail(&seq->modifiers, smd);
+
+ BKE_sequence_modifier_unique_name(seq, smd);
+
+ if (smti->init_data)
+ smti->init_data(smd);
+}
+
+void BKE_sequence_modifier_free(SequenceModifierData *smd)
+{
+ SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+
+ if (smti && smti->free_data) {
+ smti->free_data(smd);
+ }
+
+ MEM_freeN(smd);
+}
+
+void BKE_sequence_modifier_unique_name(Sequence *seq, SequenceModifierData *smd)
+{
+ SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+
+ BLI_uniquename(&seq->modifiers, smd, smti->name, '.', offsetof(SequenceModifierData, name), sizeof(smd->name));
+}
+
+SequenceModifierData *BKE_sequence_modifier_find_by_name(Sequence *seq, char *name)
+{
+ return BLI_findstring(&(seq->modifiers), name, offsetof(SequenceModifierData, name));
+}
+
+ImBuf *BKE_sequence_modifier_apply_stack(SeqRenderData context, Sequence *seq, ImBuf *ibuf, int cfra)
+{
+ SequenceModifierData *smd;
+ ImBuf *processed_ibuf = ibuf;
+
+ for (smd = seq->modifiers.first; smd; smd = smd->next) {
+ SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+ ImBuf *ibuf_new;
+
+ /* could happen if modifier is being removed or not exists in current version of blender */
+ if (!smti)
+ continue;
+
+ /* modifier is muted, do nothing */
+ if (smd->flag & SEQUENCE_MODIFIER_MUTE)
+ continue;
+
+ if (smti->apply) {
+ ImBuf *mask = modifier_mask_get(smd, context, cfra, ibuf->rect_float != NULL);
+
+ if (processed_ibuf == ibuf)
+ processed_ibuf = IMB_dupImBuf(ibuf);
+
+ ibuf_new = smti->apply(smd, processed_ibuf, mask);
+
+ if (ibuf_new != processed_ibuf) {
+ IMB_freeImBuf(processed_ibuf);
+ processed_ibuf = ibuf_new;
+ }
+
+ if (mask)
+ IMB_freeImBuf(mask);
+ }
+ }
+
+ return processed_ibuf;
+}
+
+void BKE_sequence_modifier_list_copy(Sequence *seqn, Sequence *seq)
+{
+ SequenceModifierData *smd;
+
+ for (smd = seq->modifiers.first; smd; smd = smd->next) {
+ SequenceModifierData *smdn;
+ SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+
+ smdn = MEM_dupallocN(smd);
+
+ if (smti && smti->copy_data)
+ smti->copy_data(smdn, smd);
+
+ smdn->next = smdn->prev = NULL;
+ BLI_addtail(&seqn->modifiers, smdn);
+ }
+}
+
+int BKE_sequence_supports_modifiers(Sequence *seq)
+{
+ return !ELEM(seq->type, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD);
+}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 9625fad69a6..b156d622202 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -83,6 +83,7 @@
static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep, float cfra, int chanshown);
static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra);
static void seq_free_animdata(Scene *scene, Sequence *seq);
+static ImBuf *seq_render_mask(SeqRenderData context, Mask *mask, float nr, short make_float);
/* **** XXX ******** */
#define SELECT 1
@@ -203,7 +204,18 @@ void BKE_sequence_free(Scene *scene, Sequence *seq)
seq_free_animdata(scene, seq);
}
+ /* free modifiers */
+ if (seq->modifiers.first) {
+ SequenceModifierData *smd, *smd_next;
+
+ for (smd = seq->modifiers.first; smd; smd = smd_next) {
+ smd_next = smd->next;
+ BKE_sequence_modifier_free(smd);
+ }
+ }
+
BKE_sequencer_cache_cleanup_sequence(seq);
+ BKE_sequencer_preprocessed_cache_cleanup_sequence(seq);
MEM_freeN(seq);
}
@@ -1432,7 +1444,7 @@ static void make_cb_table_float(float lift, float gain, float gamma,
}
}
-static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul)
+static void color_balance_byte_byte(StripColorBalance *cb_, unsigned char *rect, unsigned char *mask_rect, int width, int height, float mul)
{
unsigned char cb_tab[3][256];
int c;
@@ -1440,7 +1452,7 @@ static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned
unsigned char *e = p + width * 4 * height;
unsigned char *m = mask_rect;
- StripColorBalance cb = calc_cb(seq->strip->color_balance);
+ StripColorBalance cb = calc_cb(cb_);
for (c = 0; c < 3; c++) {
make_cb_table_byte(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
@@ -1466,7 +1478,7 @@ static void color_balance_byte_byte(Sequence *seq, unsigned char *rect, unsigned
}
}
-static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *rect_float, unsigned char *mask_rect, int width, int height, float mul)
+static void color_balance_byte_float(StripColorBalance *cb_, unsigned char *rect, float *rect_float, unsigned char *mask_rect, int width, int height, float mul)
{
float cb_tab[4][256];
int c, i;
@@ -1478,7 +1490,7 @@ static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *
o = rect_float;
- cb = calc_cb(seq->strip->color_balance);
+ cb = calc_cb(cb_);
for (c = 0; c < 3; c++) {
make_cb_table_float(cb.lift[c], cb.gain[c], cb.gamma[c], cb_tab[c], mul);
@@ -1510,12 +1522,12 @@ static void color_balance_byte_float(Sequence *seq, unsigned char *rect, float *
}
}
-static void color_balance_float_float(Sequence *seq, float *rect_float, float *mask_rect_float, int width, int height, float mul)
+static void color_balance_float_float(StripColorBalance *cb_, float *rect_float, float *mask_rect_float, int width, int height, float mul)
{
float *p = rect_float;
float *e = rect_float + width * 4 * height;
float *m = mask_rect_float;
- StripColorBalance cb = calc_cb(seq->strip->color_balance);
+ StripColorBalance cb = calc_cb(cb_);
while (p < e) {
int c;
@@ -1535,20 +1547,23 @@ static void color_balance_float_float(Sequence *seq, float *rect_float, float *m
}
typedef struct ColorBalanceInitData {
- Sequence *seq;
+ StripColorBalance *cb;
ImBuf *ibuf;
float mul;
ImBuf *mask;
+ short make_float;
} ColorBalanceInitData;
typedef struct ColorBalanceThread {
- Sequence *seq;
+ StripColorBalance *cb;
float mul;
int width, height;
unsigned char *rect, *mask_rect;
float *rect_float, *mask_rect_float;
+
+ short make_float;
} ColorBalanceThread;
static void color_balance_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
@@ -1562,10 +1577,11 @@ static void color_balance_init_handle(void *handle_v, int start_line, int tot_li
memset(handle, 0, sizeof(ColorBalanceThread));
- handle->seq = init_data->seq;
+ handle->cb = init_data->cb;
handle->mul = init_data->mul;
handle->width = ibuf->x;
handle->height = tot_line;
+ handle->make_float = init_data->make_float;
if (ibuf->rect)
handle->rect = (unsigned char *) ibuf->rect + offset;
@@ -1589,7 +1605,7 @@ static void color_balance_init_handle(void *handle_v, int start_line, int tot_li
static void *color_balance_do_thread(void *thread_data_v)
{
ColorBalanceThread *thread_data = (ColorBalanceThread *) thread_data_v;
- Sequence *seq = thread_data->seq;
+ StripColorBalance *cb = thread_data->cb;
int width = thread_data->width, height = thread_data->height;
unsigned char *rect = thread_data->rect;
unsigned char *mask_rect = thread_data->mask_rect;
@@ -1598,48 +1614,56 @@ static void *color_balance_do_thread(void *thread_data_v)
float mul = thread_data->mul;
if (rect_float) {
- color_balance_float_float(seq, rect_float, mask_rect_float, width, height, mul);
+ color_balance_float_float(cb, rect_float, mask_rect_float, width, height, mul);
}
- else if (seq->flag & SEQ_MAKE_FLOAT) {
- color_balance_byte_float(seq, rect, rect_float, mask_rect, width, height, mul);
+ else if (thread_data->make_float) {
+ color_balance_byte_float(cb, rect, rect_float, mask_rect, width, height, mul);
}
else {
- color_balance_byte_byte(seq, rect, mask_rect, width, height, mul);
+ color_balance_byte_byte(cb, rect, mask_rect, width, height, mul);
}
return NULL;
}
-static void color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra)
+ImBuf *BKE_sequencer_render_mask_input(SeqRenderData context, int mask_input_type, Sequence *mask_sequence, Mask *mask_id, int cfra, int make_float)
+{
+ ImBuf *mask_input = NULL;
+
+ if (mask_input_type == SEQUENCE_MASK_INPUT_STRIP) {
+ if (mask_sequence) {
+ mask_input = seq_render_strip(context, mask_sequence, cfra);
+
+ if (make_float) {
+ if (!mask_input->rect_float)
+ IMB_float_from_rect(mask_input);
+ }
+ else {
+ if (!mask_input->rect)
+ IMB_rect_from_float(mask_input);
+ }
+ }
+ }
+ else if (mask_input_type == SEQUENCE_MASK_INPUT_ID) {
+ mask_input = seq_render_mask(context, mask_id, cfra, make_float);
+ }
+
+ return mask_input;
+}
+
+void BKE_sequencer_color_balance_apply(StripColorBalance *cb, ImBuf *ibuf, float mul, short make_float, ImBuf *mask_input)
{
ColorBalanceInitData init_data;
- if (!ibuf->rect_float && seq->flag & SEQ_MAKE_FLOAT)
+ if (!ibuf->rect_float && make_float)
imb_addrectfloatImBuf(ibuf);
- init_data.seq = seq;
+ init_data.cb = cb;
init_data.ibuf = ibuf;
init_data.mul = mul;
init_data.mask = NULL;
-
- if (seq->mask_sequence) {
- if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) {
- ImBuf *mask = seq_render_strip(context, seq->mask_sequence, cfra);
-
- if (mask) {
- if (ibuf->rect_float) {
- if (!mask->rect_float)
- IMB_float_from_rect(mask);
- }
- else {
- if (!mask->rect)
- IMB_rect_from_float(mask);
- }
-
- init_data.mask = mask;
- }
- }
- }
+ init_data.make_float = make_float;
+ init_data.mask = mask_input;
IMB_processor_apply_threaded(ibuf->y, sizeof(ColorBalanceThread), &init_data,
color_balance_init_handle, color_balance_do_thread);
@@ -1650,9 +1674,26 @@ static void color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, flo
*/
if (ibuf->rect_float && ibuf->rect)
imb_freerectImBuf(ibuf);
+}
- if (init_data.mask)
- IMB_freeImBuf(init_data.mask);
+static void sequence_color_balance(SeqRenderData context, Sequence *seq, ImBuf *ibuf, float mul, int cfra)
+{
+ StripColorBalance *cb = seq->strip->color_balance;
+ ImBuf *mask_input = NULL;
+ short make_float = seq->flag & SEQ_MAKE_FLOAT;
+
+ if (seq->mask_sequence) {
+ if (seq->mask_sequence != seq && !BKE_sequence_check_depend(seq, seq->mask_sequence)) {
+ int make_float = ibuf->rect_float != NULL;
+
+ mask_input = BKE_sequencer_render_mask_input(context, SEQUENCE_MASK_INPUT_STRIP, seq->mask_sequence, NULL, cfra, make_float);
+ }
+ }
+
+ BKE_sequencer_color_balance_apply(cb, ibuf, mul, make_float, mask_input);
+
+ if (mask_input)
+ IMB_freeImBuf(mask_input);
}
/*
@@ -1696,6 +1737,10 @@ int BKE_sequencer_input_have_to_preprocess(SeqRenderData UNUSED(context), Sequen
if (seq->sat != 1.0f) {
return TRUE;
}
+
+ if (seq->modifiers.first) {
+ return TRUE;
+ }
return FALSE;
}
@@ -1795,7 +1840,7 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
}
if (seq->flag & SEQ_USE_COLOR_BALANCE && seq->strip->color_balance) {
- color_balance(context, seq, ibuf, mul, cfra);
+ sequence_color_balance(context, seq, ibuf, mul, cfra);
mul = 1.0;
}
@@ -1818,7 +1863,6 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
}
}
-
if (ibuf->x != context.rectx || ibuf->y != context.recty) {
if (context.scene->r.mode & R_OSA) {
IMB_scaleImBuf(ibuf, (short)context.rectx, (short)context.recty);
@@ -1827,6 +1871,16 @@ static ImBuf *input_preprocess(SeqRenderData context, Sequence *seq, float cfra,
IMB_scalefastImBuf(ibuf, (short)context.rectx, (short)context.recty);
}
}
+
+ if (seq->modifiers.first) {
+ ImBuf *ibuf_new = BKE_sequence_modifier_apply_stack(context, seq, ibuf, cfra);
+
+ if (ibuf_new != ibuf) {
+ IMB_freeImBuf(ibuf);
+ ibuf = ibuf_new;
+ }
+ }
+
return ibuf;
}
@@ -2098,23 +2152,23 @@ static ImBuf *seq_render_movieclip_strip(SeqRenderData context, Sequence *seq, f
}
-static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float nr)
+static ImBuf *seq_render_mask(SeqRenderData context, Mask *mask, float nr, short make_float)
{
/* TODO - add option to rasterize to alpha imbuf? */
ImBuf *ibuf = NULL;
float *maskbuf;
int i;
- if (!seq->mask) {
+ if (!mask) {
return NULL;
}
else {
Mask *mask_temp;
MaskRasterHandle *mr_handle;
- mask_temp = BKE_mask_copy_nolib(seq->mask);
+ mask_temp = BKE_mask_copy_nolib(mask);
- BKE_mask_evaluate(mask_temp, seq->mask->sfra + nr, TRUE);
+ BKE_mask_evaluate(mask_temp, mask->sfra + nr, TRUE);
maskbuf = MEM_mallocN(sizeof(float) * context.rectx * context.recty, __func__);
@@ -2131,7 +2185,7 @@ static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float
}
- if (seq->flag & SEQ_MAKE_FLOAT) {
+ if (make_float) {
/* pixels */
float *fp_src;
float *fp_dst;
@@ -2173,6 +2227,13 @@ static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float
return ibuf;
}
+static ImBuf *seq_render_mask_strip(SeqRenderData context, Sequence *seq, float nr)
+{
+ short make_float = seq->flag & SEQ_MAKE_FLOAT;
+
+ return seq_render_mask(context, seq->mask, nr, make_float);
+}
+
static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float nr)
{
ImBuf *ibuf = NULL;
@@ -2328,160 +2389,146 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float
return ibuf;
}
-static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
+static ImBuf *do_render_strip_uncached(SeqRenderData context, Sequence *seq, float cfra)
{
ImBuf *ibuf = NULL;
- char name[FILE_MAX];
- int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
- int is_proxy_image = FALSE;
float nr = give_stripelem_index(seq, cfra);
- /* all effects are handled similarly with the exception of speed effect */
int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
- int is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
-
- ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
-
- /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
- * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */
- if (ibuf)
- use_preprocess = FALSE;
-
- if (ibuf == NULL)
- ibuf = copy_from_ibuf_still(context, seq, nr);
-
- /* MOVIECLIPs have their own proxy management */
- if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
- ibuf = seq_proxy_fetch(context, seq, cfra);
- is_proxy_image = (ibuf != NULL);
- }
+ int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
+ char name[FILE_MAX];
- if (ibuf == NULL) switch (type) {
- case SEQ_TYPE_META:
- {
- ImBuf *meta_ibuf = NULL;
+ switch (type) {
+ case SEQ_TYPE_META:
+ {
+ ImBuf *meta_ibuf = NULL;
- if (seq->seqbase.first)
- meta_ibuf = seq_render_strip_stack(
- context, &seq->seqbase,
- seq->start + nr, 0);
+ if (seq->seqbase.first)
+ meta_ibuf = seq_render_strip_stack(context, &seq->seqbase, seq->start + nr, 0);
- if (meta_ibuf) {
- ibuf = meta_ibuf;
- if (ibuf && use_preprocess) {
- ImBuf *i = IMB_dupImBuf(ibuf);
+ if (meta_ibuf) {
+ ibuf = meta_ibuf;
+ if (ibuf && use_preprocess) {
+ ImBuf *i = IMB_dupImBuf(ibuf);
- IMB_freeImBuf(ibuf);
+ IMB_freeImBuf(ibuf);
- ibuf = i;
- }
+ ibuf = i;
}
-
- break;
}
- case SEQ_TYPE_SPEED:
- {
- ImBuf *child_ibuf = NULL;
- float f_cfra;
- SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
+ break;
+ }
- BKE_sequence_effect_speed_rebuild_map(context.scene, seq, 0);
+ case SEQ_TYPE_SPEED:
+ {
+ ImBuf *child_ibuf = NULL;
- /* weeek! */
- f_cfra = seq->start + s->frameMap[(int)nr];
+ float f_cfra;
+ SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
- child_ibuf = seq_render_strip(context, seq->seq1, f_cfra);
+ BKE_sequence_effect_speed_rebuild_map(context.scene, seq, 0);
- if (child_ibuf) {
- ibuf = child_ibuf;
- if (ibuf && use_preprocess) {
- ImBuf *i = IMB_dupImBuf(ibuf);
+ /* weeek! */
+ f_cfra = seq->start + s->frameMap[(int)nr];
- IMB_freeImBuf(ibuf);
+ child_ibuf = seq_render_strip(context, seq->seq1, f_cfra);
- ibuf = i;
- }
+ if (child_ibuf) {
+ ibuf = child_ibuf;
+ if (ibuf && use_preprocess) {
+ ImBuf *i = IMB_dupImBuf(ibuf);
+
+ IMB_freeImBuf(ibuf);
+
+ ibuf = i;
}
- break;
}
- case SEQ_TYPE_EFFECT:
- {
- ibuf = seq_render_effect_strip_impl(context, seq, seq->start + nr);
- break;
- }
- case SEQ_TYPE_IMAGE:
- {
- StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra);
+ break;
+ }
- if (s_elem) {
- BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
- BLI_path_abs(name, G.main->name);
- }
+ case SEQ_TYPE_EFFECT:
+ {
+ ibuf = seq_render_effect_strip_impl(context, seq, seq->start + nr);
+ break;
+ }
- if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) {
- /* we don't need both (speed reasons)! */
- if (ibuf->rect_float && ibuf->rect)
- imb_freerectImBuf(ibuf);
+ case SEQ_TYPE_IMAGE:
+ {
+ StripElem *s_elem = BKE_sequencer_give_stripelem(seq, cfra);
- /* all sequencer color is done in SRGB space, linear gives odd crossfades */
- if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
- IMB_convert_profile(ibuf, IB_PROFILE_NONE);
+ if (s_elem) {
+ BLI_join_dirfile(name, sizeof(name), seq->strip->dir, s_elem->name);
+ BLI_path_abs(name, G.main->name);
+ }
- copy_to_ibuf_still(context, seq, nr, ibuf);
+ if (s_elem && (ibuf = IMB_loadiffname(name, IB_rect))) {
+ /* we don't need both (speed reasons)! */
+ if (ibuf->rect_float && ibuf->rect)
+ imb_freerectImBuf(ibuf);
- s_elem->orig_width = ibuf->x;
- s_elem->orig_height = ibuf->y;
- }
- break;
+ /* all sequencer color is done in SRGB space, linear gives odd crossfades */
+ if (ibuf->profile == IB_PROFILE_LINEAR_RGB)
+ IMB_convert_profile(ibuf, IB_PROFILE_NONE);
+
+ copy_to_ibuf_still(context, seq, nr, ibuf);
+
+ s_elem->orig_width = ibuf->x;
+ s_elem->orig_height = ibuf->y;
}
- case SEQ_TYPE_MOVIE:
- {
- seq_open_anim_file(seq);
+ break;
+ }
+
+ case SEQ_TYPE_MOVIE:
+ {
+ seq_open_anim_file(seq);
- if (seq->anim) {
- IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
+ if (seq->anim) {
+ IMB_anim_set_preseek(seq->anim, seq->anim_preseek);
- ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs,
- seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
- seq_rendersize_to_proxysize(context.preview_render_size));
+ ibuf = IMB_anim_absolute(seq->anim, nr + seq->anim_startofs,
+ seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN,
+ seq_rendersize_to_proxysize(context.preview_render_size));
- /* we don't need both (speed reasons)! */
- if (ibuf && ibuf->rect_float && ibuf->rect)
- imb_freerectImBuf(ibuf);
- if (ibuf) {
- seq->strip->stripdata->orig_width = ibuf->x;
- seq->strip->stripdata->orig_height = ibuf->y;
- }
+ /* we don't need both (speed reasons)! */
+ if (ibuf && ibuf->rect_float && ibuf->rect)
+ imb_freerectImBuf(ibuf);
+ if (ibuf) {
+ seq->strip->stripdata->orig_width = ibuf->x;
+ seq->strip->stripdata->orig_height = ibuf->y;
}
- copy_to_ibuf_still(context, seq, nr, ibuf);
- break;
}
- case SEQ_TYPE_SCENE:
- {
- /* scene can be NULL after deletions */
- ibuf = seq_render_scene_strip(context, seq, nr);
+ copy_to_ibuf_still(context, seq, nr, ibuf);
+ break;
+ }
- /* Scene strips update all animation, so we need to restore original state.*/
- BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra);
+ case SEQ_TYPE_SCENE:
+ {
+ /* scene can be NULL after deletions */
+ ibuf = seq_render_scene_strip(context, seq, nr);
- copy_to_ibuf_still(context, seq, nr, ibuf);
- break;
- }
- case SEQ_TYPE_MOVIECLIP:
- {
- ibuf = seq_render_movieclip_strip(context, seq, nr);
+ /* Scene strips update all animation, so we need to restore original state.*/
+ BKE_animsys_evaluate_all_animation(context.bmain, context.scene, cfra);
- if (ibuf && use_preprocess) {
- ImBuf *i = IMB_dupImBuf(ibuf);
+ copy_to_ibuf_still(context, seq, nr, ibuf);
+ break;
+ }
- IMB_freeImBuf(ibuf);
+ case SEQ_TYPE_MOVIECLIP:
+ {
+ ibuf = seq_render_movieclip_strip(context, seq, nr);
- ibuf = i;
- }
+ if (ibuf && use_preprocess) {
+ ImBuf *i = IMB_dupImBuf(ibuf);
- copy_to_ibuf_still(context, seq, nr, ibuf);
- break;
+ IMB_freeImBuf(ibuf);
+
+ ibuf = i;
}
+
+ copy_to_ibuf_still(context, seq, nr, ibuf);
+ break;
+ }
+
case SEQ_TYPE_MASK:
{
/* ibuf is alwats new */
@@ -2492,6 +2539,45 @@ static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
}
}
+ return ibuf;
+}
+
+static ImBuf *seq_render_strip(SeqRenderData context, Sequence *seq, float cfra)
+{
+ ImBuf *ibuf = NULL;
+ int use_preprocess = BKE_sequencer_input_have_to_preprocess(context, seq, cfra);
+ int is_proxy_image = FALSE;
+ float nr = give_stripelem_index(seq, cfra);
+ /* all effects are handled similarly with the exception of speed effect */
+ int type = (seq->type & SEQ_TYPE_EFFECT && seq->type != SEQ_TYPE_SPEED) ? SEQ_TYPE_EFFECT : seq->type;
+ int is_preprocessed = !ELEM3(type, SEQ_TYPE_IMAGE, SEQ_TYPE_MOVIE, SEQ_TYPE_SCENE);
+
+ ibuf = BKE_sequencer_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
+
+ /* currently, we cache preprocessed images in SEQ_STRIPELEM_IBUF,
+ * but not(!) on SEQ_STRIPELEM_IBUF_ENDSTILL and ..._STARTSTILL */
+ if (ibuf)
+ use_preprocess = FALSE;
+
+ if (ibuf == NULL)
+ ibuf = copy_from_ibuf_still(context, seq, nr);
+
+ if (ibuf == NULL) {
+ ibuf = BKE_sequencer_preprocessed_cache_get(context, seq, cfra, SEQ_STRIPELEM_IBUF);
+
+ if (ibuf == NULL) {
+ /* MOVIECLIPs have their own proxy management */
+ if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) {
+ ibuf = seq_proxy_fetch(context, seq, cfra);
+ is_proxy_image = (ibuf != NULL);
+ }
+
+ ibuf = do_render_strip_uncached(context, seq, cfra);
+
+ BKE_sequencer_preprocessed_cache_put(context, seq, cfra, SEQ_STRIPELEM_IBUF, ibuf);
+ }
+ }
+
if (ibuf == NULL)
ibuf = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect);
@@ -2876,7 +2962,7 @@ int BKE_sequence_check_depend(Sequence *seq, Sequence *cur)
return TRUE;
}
-void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
+static void sequence_invalidate_cache(Scene *scene, Sequence *seq, int invalidate_preprocess)
{
Editing *ed = scene->ed;
Sequence *cur;
@@ -2884,18 +2970,33 @@ void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
/* invalidate cache for current sequence */
BKE_sequencer_cache_cleanup_sequence(seq);
+ if (invalidate_preprocess)
+ BKE_sequencer_preprocessed_cache_cleanup_sequence(seq);
+
/* invalidate cache for all dependent sequences */
SEQ_BEGIN (ed, cur)
{
if (cur == seq)
continue;
- if (BKE_sequence_check_depend(seq, cur))
+ if (BKE_sequence_check_depend(seq, cur)) {
BKE_sequencer_cache_cleanup_sequence(cur);
+ BKE_sequencer_preprocessed_cache_cleanup_sequence(cur);
+ }
}
SEQ_END
}
+void BKE_sequence_invalidate_cache(Scene *scene, Sequence *seq)
+{
+ sequence_invalidate_cache(scene, seq, TRUE);
+}
+
+void BKE_sequence_invalidate_cache_for_modifier(Scene *scene, Sequence *seq)
+{
+ sequence_invalidate_cache(scene, seq, FALSE);
+}
+
void BKE_sequencer_free_imbuf(Scene *scene, ListBase *seqbase, int check_mem_usage, int keep_file_handles)
{
Sequence *seq;
@@ -3941,6 +4042,12 @@ static Sequence *seq_dupli(Scene *scene, Scene *scene_to, Sequence *seq, int dup
seqn->strip->color_balance = MEM_dupallocN(seq->strip->color_balance);
}
+ if (seqn->modifiers.first) {
+ seqn->modifiers.first = seqn->modifiers.last = NULL;
+
+ BKE_sequence_modifier_list_copy(seqn, seq);
+ }
+
if (seq->type == SEQ_TYPE_META) {
seqn->strip->stripdata = NULL;
@@ -4060,3 +4167,4 @@ int BKE_seqence_is_valid_check(Sequence *seq)
return TRUE;
}
+
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index e7722e07442..eb22b9a2e2e 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -4785,6 +4785,16 @@ static void link_paint(FileData *fd, Scene *sce, Paint *p)
}
}
+static void lib_link_sequence_modifiers(FileData *fd, Scene *scene, ListBase *lb)
+{
+ SequenceModifierData *smd;
+
+ for (smd = lb->first; smd; smd = smd->next) {
+ if (smd->mask_id)
+ smd->mask_id = newlibadr_us(fd, scene->id.lib, smd->mask_id);
+ }
+}
+
static void lib_link_scene(FileData *fd, Main *main)
{
Scene *sce;
@@ -4869,6 +4879,8 @@ static void lib_link_scene(FileData *fd, Main *main)
}
}
seq->anim = NULL;
+
+ lib_link_sequence_modifiers(fd, sce, &seq->modifiers);
}
SEQ_END
@@ -4925,6 +4937,29 @@ static void direct_link_paint(FileData *fd, Paint **paint)
(*paint)->num_input_samples = 1;
}
+static void direct_link_sequence_modifiers(FileData *fd, ListBase *lb)
+{
+ SequenceModifierData *smd;
+
+ link_list(fd, lb);
+
+ for (smd = lb->first; smd; smd = smd->next) {
+ if (smd->mask_sequence)
+ smd->mask_sequence = newdataadr(fd, smd->mask_sequence);
+
+ if (smd->type == seqModifierType_Curves) {
+ CurvesModifierData *cmd = (CurvesModifierData *) smd;
+
+ direct_link_curvemapping(fd, &cmd->curve_mapping);
+ }
+ else if (smd->type == seqModifierType_HueCorrect) {
+ HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
+
+ direct_link_curvemapping(fd, &hcmd->curve_mapping);
+ }
+ }
+}
+
static void direct_link_scene(FileData *fd, Scene *sce)
{
Editing *ed;
@@ -5037,6 +5072,8 @@ static void direct_link_scene(FileData *fd, Scene *sce)
// seq->strip->color_balance->gui = 0; // XXX - peter, is this relevant in 2.5?
}
}
+
+ direct_link_sequence_modifiers(fd, &seq->modifiers);
}
SEQ_END
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 2a68af688ed..4ada0c54a93 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -646,15 +646,21 @@ static void write_animdata(WriteData *wd, AnimData *adt)
write_nladata(wd, &adt->nla_tracks);
}
-static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
+static void write_curvemapping_curves(WriteData *wd, CurveMapping *cumap)
{
int a;
-
- writestruct(wd, DATA, "CurveMapping", 1, cumap);
- for (a=0; a<CM_TOT; a++)
+
+ for (a = 0; a < CM_TOT; a++)
writestruct(wd, DATA, "CurveMapPoint", cumap->cm[a].totpoint, cumap->cm[a].curve);
}
+static void write_curvemapping(WriteData *wd, CurveMapping *cumap)
+{
+ writestruct(wd, DATA, "CurveMapping", 1, cumap);
+
+ write_curvemapping_curves(wd, cumap);
+}
+
static void write_node_socket(WriteData *wd, bNodeSocket *sock)
{
bNodeSocketType *stype= ntreeGetSocketType(sock->type);
@@ -2086,6 +2092,32 @@ static void write_lamps(WriteData *wd, ListBase *idbase)
}
}
+static void write_sequence_modifiers(WriteData *wd, ListBase *modbase)
+{
+ SequenceModifierData *smd;
+
+ for (smd = modbase->first; smd; smd = smd->next) {
+ SequenceModifierTypeInfo *smti = BKE_sequence_modifier_type_info_get(smd->type);
+
+ if (smti) {
+ writestruct(wd, DATA, smti->struct_name, 1, smd);
+
+ if (smd->type == seqModifierType_Curves) {
+ CurvesModifierData *cmd = (CurvesModifierData *) smd;
+
+ write_curvemapping(wd, &cmd->curve_mapping);
+ }
+ else if (smd->type == seqModifierType_HueCorrect) {
+ HueCorrectModifierData *hcmd = (HueCorrectModifierData *) smd;
+
+ write_curvemapping(wd, &hcmd->curve_mapping);
+ }
+ }
+ else {
+ writestruct(wd, DATA, "SequenceModifierData", 1, smd);
+ }
+ }
+}
static void write_scenes(WriteData *wd, ListBase *scebase)
{
@@ -2192,6 +2224,8 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
strip->done = TRUE;
}
+
+ write_sequence_modifiers(wd, &seq->modifiers);
}
SEQ_END
diff --git a/source/blender/editors/space_sequencer/CMakeLists.txt b/source/blender/editors/space_sequencer/CMakeLists.txt
index 7bee8c2bebf..dd5fbb92171 100644
--- a/source/blender/editors/space_sequencer/CMakeLists.txt
+++ b/source/blender/editors/space_sequencer/CMakeLists.txt
@@ -40,6 +40,7 @@ set(SRC
sequencer_buttons.c
sequencer_draw.c
sequencer_edit.c
+ sequencer_modifier.c
sequencer_ops.c
sequencer_scopes.c
sequencer_select.c
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 16cf929a832..bad4fcf9135 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -177,5 +177,9 @@ struct ImBuf *make_histogram_view_from_ibuf(struct ImBuf * ibuf);
void sequencer_buttons_register(struct ARegionType *art);
void SEQUENCER_OT_properties(struct wmOperatorType *ot);
+/* sequencer_modifiers.c */
+void SEQUENCER_OT_strip_modifier_add(struct wmOperatorType *ot);
+void SEQUENCER_OT_strip_modifier_remove(struct wmOperatorType *ot);
+
#endif /* __SEQUENCER_INTERN_H__ */
diff --git a/source/blender/editors/space_sequencer/sequencer_modifier.c b/source/blender/editors/space_sequencer/sequencer_modifier.c
new file mode 100644
index 00000000000..4ae4b995c11
--- /dev/null
+++ b/source/blender/editors/space_sequencer/sequencer_modifier.c
@@ -0,0 +1,164 @@
+/*
+ * ***** 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) 2012 Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation,
+ * Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+/** \file blender/editors/space_sequencer/sequencer_modifier.c
+ * \ingroup spseq
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "DNA_scene_types.h"
+#include "DNA_mask_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_sequencer.h"
+#include "BKE_movieclip.h"
+#include "BKE_sequencer.h"
+#include "BKE_mask.h"
+#include "BKE_report.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "UI_interface.h"
+#include "UI_resources.h"
+
+/* own include */
+#include "sequencer_intern.h"
+
+/*********************** Add modifier operator *************************/
+
+static int strip_modifier_active_poll(bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
+
+ if (ed) {
+ Sequence *seq = BKE_sequencer_active_get(scene);
+
+ if (seq)
+ return BKE_sequence_supports_modifiers(seq);
+ }
+
+ return FALSE;
+}
+
+static int strip_modifier_add_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ int type = RNA_enum_get(op->ptr, "type");
+
+ BKE_sequence_modifier_new(seq, type);
+
+ BKE_sequence_invalidate_cache(scene, seq);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_strip_modifier_add(wmOperatorType *ot)
+{
+ PropertyRNA *prop;
+
+ /* TODO: de-duplicate from RNA */
+ static EnumPropertyItem sequence_modifier_type_items[] = {
+ {seqModifierType_ColorBalance, "COLOR_BALANCE", ICON_NONE, "Color Balance", ""},
+ {seqModifierType_Curves, "CURVES", ICON_NONE, "Curves", ""},
+ {seqModifierType_HueCorrect,"HUE_CORRECT", ICON_NONE, "Hue Correct", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name = "Add Strip Modifier";
+ ot->idname = "SEQUENCER_OT_strip_modifier_add";
+ ot->description = "Add a modifier to strip";
+
+ /* api callbacks */
+ ot->exec = strip_modifier_add_exec;
+ ot->poll = strip_modifier_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ prop = RNA_def_enum(ot->srna, "type", sequence_modifier_type_items, seqModifierType_ColorBalance, "Type", "");
+ ot->prop = prop;
+}
+
+/*********************** Remove modifier operator *************************/
+
+static int strip_modifier_remove_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ Sequence *seq = BKE_sequencer_active_get(scene);
+ char name[MAX_NAME];
+ SequenceModifierData *smd;
+
+ RNA_string_get(op->ptr, "name", name);
+
+ smd = BKE_sequence_modifier_find_by_name(seq, name);
+ if (!smd)
+ return OPERATOR_CANCELLED;
+
+ BLI_remlink(&seq->modifiers, smd);
+ BKE_sequence_modifier_free(smd);
+
+ BKE_sequence_invalidate_cache(scene, seq);
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_strip_modifier_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Strip Modifier";
+ ot->idname = "SEQUENCER_OT_strip_modifier_remove";
+ ot->description = "Add a modifier to strip";
+
+ /* api callbacks */
+ ot->exec = strip_modifier_remove_exec;
+ ot->poll = strip_modifier_active_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_string(ot->srna, "name", "Name", MAX_NAME, "Name", "Name of modifier to remove");
+}
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index 4a1c8f0c006..45ffc997172 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -114,6 +114,10 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_copy);
WM_operatortype_append(SEQUENCER_OT_paste);
+
+ /* sequencer_modifiers.c */
+ WM_operatortype_append(SEQUENCER_OT_strip_modifier_add);
+ WM_operatortype_append(SEQUENCER_OT_strip_modifier_remove);
}
diff --git a/source/blender/makesdna/DNA_sequence_types.h b/source/blender/makesdna/DNA_sequence_types.h
index 16e8b8904fa..d6c59456bd0 100644
--- a/source/blender/makesdna/DNA_sequence_types.h
+++ b/source/blender/makesdna/DNA_sequence_types.h
@@ -34,6 +34,7 @@
#define __DNA_SEQUENCE_TYPES_H__
#include "DNA_defs.h"
+#include "DNA_color_types.h"
#include "DNA_listBase.h"
#include "DNA_vec_types.h"
@@ -167,6 +168,9 @@ typedef struct Sequence {
/* is sfra needed anymore? - it looks like its only used in one place */
int sfra, pad; /* starting frame according to the timeline of the scene. */
+
+ /* modifiers */
+ ListBase modifiers;
} Sequence;
typedef struct MetaStack {
@@ -229,6 +233,40 @@ typedef struct SpeedControlVars {
int lastValidFrame;
} SpeedControlVars;
+/* ***************** Sequence modifiers ****************** */
+
+typedef struct SequenceModifierData {
+ struct SequenceModifierData *next, *prev;
+ int type, flag;
+ char name[64]; /* MAX_NAME */
+
+ /* mask input, either sequence or maks ID */
+ int mask_input_type, pad;
+
+ struct Sequence *mask_sequence;
+ struct Mask *mask_id;
+} SequenceModifierData;
+
+typedef struct ColorBalanceModifierData {
+ SequenceModifierData modifier;
+
+ StripColorBalance color_balance;
+ float color_multiply;
+ int pad;
+} ColorBalanceModifierData;
+
+typedef struct CurvesModifierData {
+ SequenceModifierData modifier;
+
+ struct CurveMapping curve_mapping;
+} CurvesModifierData;
+
+typedef struct HueCorrectModifierData {
+ SequenceModifierData modifier;
+
+ struct CurveMapping curve_mapping;
+} HueCorrectModifierData;
+
#define MAXSEQ 32
#define SELECT 1
@@ -352,5 +390,26 @@ enum {
#define SEQ_HAS_PATH(_seq) (ELEM4((_seq)->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_SOUND_RAM, SEQ_TYPE_SOUND_HD))
-#endif
+/* modifiers */
+
+/* SequenceModifierData->type */
+enum {
+ seqModifierType_ColorBalance = 1,
+ seqModifierType_Curves = 2,
+ seqModifierType_HueCorrect = 3,
+
+ NUM_SEQUENCE_MODIFIER_TYPES
+};
+
+/* SequenceModifierData->flag */
+enum {
+ SEQUENCE_MODIFIER_MUTE = (1 << 0),
+ SEQUENCE_MODIFIER_EXPANDED = (1 << 1),
+};
+
+enum {
+ SEQUENCE_MASK_INPUT_STRIP = 0,
+ SEQUENCE_MASK_INPUT_ID = 1
+};
+#endif
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 6fc304e6bbb..fd8195005aa 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -332,8 +332,9 @@ static char *rna_SequenceTransform_path(PointerRNA *ptr)
return BLI_strdup("");
}
-static void rna_SequenceTransform_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_SequenceTransform_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
Sequence *seq = sequence_get_by_transform(ed, ptr->data);
@@ -376,8 +377,9 @@ static char *rna_SequenceCrop_path(PointerRNA *ptr)
return BLI_strdup("");
}
-static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_SequenceCrop_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
Sequence *seq = sequence_get_by_crop(ed, ptr->data);
@@ -613,8 +615,9 @@ static void rna_SequenceElement_filename_set(PointerRNA *ptr, const char *value)
}
#endif
-static void rna_Sequence_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_Sequence_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
if (ed) {
@@ -638,8 +641,9 @@ static int rna_Sequence_otherSequence_poll(PointerRNA *ptr, PointerRNA value)
return TRUE;
}
-static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
BKE_sequencer_free_imbuf(scene, &ed->seqbase, FALSE, FALSE);
@@ -648,16 +652,18 @@ static void rna_Sequence_update_reopen_files(Main *UNUSED(bmain), Scene *scene,
BKE_sequencer_update_sound_bounds(scene, ptr->data);
}
-static void rna_Sequence_mute_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Sequence_mute_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
BKE_sequencer_update_muting(ed);
rna_Sequence_update(bmain, scene, ptr);
}
-static void rna_Sequence_filepath_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Sequence_filepath_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Sequence *seq = (Sequence *)(ptr->data);
BKE_sequence_reload_new_file(scene, seq, TRUE);
BKE_sequence_calc(scene, seq);
@@ -686,8 +692,9 @@ static Sequence *sequence_get_by_proxy(Editing *ed, StripProxy *proxy)
return data.seq;
}
-static void rna_Sequence_tcindex_update(Main *bmain, Scene *scene, PointerRNA *ptr)
+static void rna_Sequence_tcindex_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
Sequence *seq = sequence_get_by_proxy(ed, ptr->data);
@@ -695,8 +702,9 @@ static void rna_Sequence_tcindex_update(Main *bmain, Scene *scene, PointerRNA *p
rna_Sequence_frame_change_update(scene, seq);
}
-static void rna_SequenceProxy_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_SequenceProxy_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
Sequence *seq = sequence_get_by_proxy(ed, ptr->data);
@@ -724,6 +732,22 @@ static int colbalance_seq_cmp_cb(Sequence *seq, void *arg_pt)
data->seq = seq;
return -1; /* done so bail out */
}
+
+ if (seq->modifiers.first) {
+ SequenceModifierData *smd = seq->modifiers.first;
+
+ for (smd = seq->modifiers.first; smd; smd = smd->next) {
+ if (smd->type == seqModifierType_ColorBalance) {
+ ColorBalanceModifierData *cbmd = (ColorBalanceModifierData *) smd;
+
+ if (&cbmd->color_balance == data->data) {
+ data->seq = seq;
+ return -1; /* done so bail out */
+ }
+ }
+ }
+ }
+
return 1;
}
@@ -752,12 +776,16 @@ static char *rna_SequenceColorBalance_path(PointerRNA *ptr)
return BLI_strdup("");
}
-static void rna_SequenceColorBalance_update(Main *UNUSED(bmain), Scene *scene, PointerRNA *ptr)
+static void rna_SequenceColorBalance_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
+ Scene *scene = (Scene *) ptr->id.data;
Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
Sequence *seq = sequence_get_by_colorbalance(ed, ptr->data);
- BKE_sequence_invalidate_cache(scene, seq);
+ if (seq->strip->color_balance == ptr->data)
+ BKE_sequence_invalidate_cache(scene, seq);
+ else
+ BKE_sequence_invalidate_cache_for_modifier(scene, seq);
}
static void rna_SequenceEditor_overlay_lock_set(PointerRNA *ptr, int value)
@@ -825,6 +853,113 @@ static float rna_WipeSequence_angle_get(PointerRNA *ptr)
return DEG2RADF(((WipeVars *)seq->effectdata)->angle);
}
+static int modifier_seq_cmp_cb(Sequence *seq, void *arg_pt)
+{
+ SequenceSearchData *data = arg_pt;
+
+ if (BLI_findindex(&seq->modifiers, data->data) != -1) {
+ data->seq = seq;
+ return -1; /* done so bail out */
+ }
+
+ return 1;
+}
+
+static Sequence *sequence_get_by_modifier(Editing *ed, SequenceModifierData *smd)
+{
+ SequenceSearchData data;
+
+ data.seq = NULL;
+ data.data = smd;
+
+ /* irritating we need to search for our sequence! */
+ BKE_sequencer_base_recursive_apply(&ed->seqbase, modifier_seq_cmp_cb, &data);
+
+ return data.seq;
+}
+
+static StructRNA *rna_SequenceModifier_refine(struct PointerRNA *ptr)
+{
+ SequenceModifierData *smd = (SequenceModifierData *) ptr->data;
+
+ switch (smd->type) {
+ case seqModifierType_ColorBalance:
+ return &RNA_ColorBalanceModifier;
+ case seqModifierType_Curves:
+ return &RNA_CurvesModifier;
+ case seqModifierType_HueCorrect:
+ return &RNA_HueCorrectModifier;
+ default:
+ return &RNA_SequenceModifier;
+ }
+}
+
+static char *rna_SequenceModifier_path(PointerRNA *ptr)
+{
+ Scene *scene = ptr->id.data;
+ Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
+ SequenceModifierData *smd = ptr->data;
+ Sequence *seq = sequence_get_by_modifier(ed, smd);
+
+ if (seq && seq->name + 2)
+ return BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].modifiers[\"%s\"]", seq->name + 2, smd->name);
+ else
+ return BLI_strdup("");
+}
+
+static void rna_SequenceModifier_name_set(PointerRNA *ptr, const char *value)
+{
+ SequenceModifierData *smd = ptr->data;
+ Scene *scene = (Scene *) ptr->id.data;
+ Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
+ Sequence *seq = sequence_get_by_modifier(ed, smd);
+ AnimData *adt;
+ char oldname[sizeof(smd->name)];
+
+ /* make a copy of the old name first */
+ BLI_strncpy(oldname, smd->name, sizeof(smd->name));
+
+ /* copy the new name into the name slot */
+ BLI_strncpy_utf8(smd->name, value, sizeof(smd->name));
+
+ /* make sure the name is truly unique */
+ BKE_sequence_modifier_unique_name(seq, smd);
+
+ /* fix all the animation data which may link to this */
+ adt = BKE_animdata_from_id(&scene->id);
+ if (adt) {
+ char path[1024];
+
+ BLI_snprintf(path, sizeof(path), "sequence_editor.sequences_all[\"%s\"].modifiers", seq->name);
+ BKE_animdata_fix_paths_rename(&scene->id, adt, NULL, path, oldname, smd->name + 2, 0, 0, 1);
+ }
+}
+
+static void rna_SequenceModifier_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
+{
+ /* strip from other scenes could be modified, so using active scene is not reliable */
+ Scene *scene = (Scene *) ptr->id.data;
+ Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
+ Sequence *seq = sequence_get_by_modifier(ed, ptr->data);
+
+ BKE_sequence_invalidate_cache_for_modifier(scene, seq);
+}
+
+static int rna_SequenceModifier_otherSequence_poll(PointerRNA *ptr, PointerRNA value)
+{
+ Scene *scene = (Scene *) ptr->id.data;
+ Editing *ed = BKE_sequencer_editing_get(scene, FALSE);
+ Sequence *seq = sequence_get_by_modifier(ed, ptr->data);
+ Sequence *cur = (Sequence *) value.data;
+
+ if (seq == cur)
+ return FALSE;
+
+ if (BKE_sequence_check_depend(seq, cur))
+ return FALSE;
+
+ return TRUE;
+}
#else
@@ -991,13 +1126,13 @@ static void rna_def_strip_proxy(BlenderRNA *brna)
}
-static void rna_def_strip_color_balance(BlenderRNA *brna)
+static void rna_def_color_balance(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
- srna = RNA_def_struct(brna, "SequenceColorBalance", NULL);
- RNA_def_struct_ui_text(srna, "Sequence Color Balance", "Color balance parameters for a sequence strip");
+ srna = RNA_def_struct(brna, "SequenceColorBalanceData", NULL);
+ RNA_def_struct_ui_text(srna, "Sequence Color Balance Data", "Color balance parameters for a sequence strip and it's modifiers");
RNA_def_struct_sdna(srna, "StripColorBalance");
prop = RNA_def_property(srna, "lift", PROP_FLOAT, PROP_COLOR);
@@ -1005,19 +1140,19 @@ static void rna_def_strip_color_balance(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0, 2, 0.1, 3);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
-
+
prop = RNA_def_property(srna, "gamma", PROP_FLOAT, PROP_COLOR);
RNA_def_property_ui_text(prop, "Gamma", "Color balance gamma (midtones)");
RNA_def_property_ui_range(prop, 0, 2, 0.1, 3);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
-
+
prop = RNA_def_property(srna, "gain", PROP_FLOAT, PROP_COLOR);
RNA_def_property_ui_text(prop, "Gain", "Color balance gain (highlights)");
RNA_def_property_ui_range(prop, 0, 2, 0.1, 3);
RNA_def_property_float_default(prop, 1.0f);
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
-
+
prop = RNA_def_property(srna, "invert_gain", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQ_COLOR_BALANCE_INVERSE_GAIN);
RNA_def_property_ui_text(prop, "Inverse Gain", "");
@@ -1033,15 +1168,13 @@ static void rna_def_strip_color_balance(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Inverse Lift", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceColorBalance_update");
- RNA_def_struct_path_func(srna, "rna_SequenceColorBalance_path");
-
/* not yet used */
#if 0
prop = RNA_def_property(srna, "exposure", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Exposure", "");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_ColorBabalnce_update");
-
+
prop = RNA_def_property(srna, "saturation", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Saturation", "");
@@ -1049,6 +1182,17 @@ static void rna_def_strip_color_balance(BlenderRNA *brna)
#endif
}
+static void rna_def_strip_color_balance(BlenderRNA *brna)
+{
+ StructRNA *srna;
+
+ srna = RNA_def_struct(brna, "SequenceColorBalance", "SequenceColorBalanceData");
+ RNA_def_struct_ui_text(srna, "Sequence Color Balance", "Color balance parameters for a sequence strip");
+ RNA_def_struct_sdna(srna, "StripColorBalance");
+
+ RNA_def_struct_path_func(srna, "rna_SequenceColorBalance_path");
+}
+
EnumPropertyItem blend_mode_items[] = {
{SEQ_BLEND_REPLACE, "REPLACE", 0, "Replace", ""},
{SEQ_TYPE_CROSS, "CROSS", 0, "Cross", ""},
@@ -1062,6 +1206,18 @@ EnumPropertyItem blend_mode_items[] = {
{0, NULL, 0, NULL, NULL}
};
+static void rna_def_sequence_modifiers(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ RNA_def_property_srna(cprop, "SequenceModifiers");
+ srna = RNA_def_struct(brna, "SequenceModifiers", NULL);
+ RNA_def_struct_sdna(srna, "Sequence");
+ RNA_def_struct_ui_text(srna, "Strip Modifiers", "Collection of strip modifiers");
+
+ /* TODO: implement new/remove/clear methods for modifier stack */
+}
+
static void rna_def_sequence(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1253,6 +1409,12 @@ static void rna_def_sequence(BlenderRNA *brna)
"to this frame");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
+ /* modifiers */
+ prop = RNA_def_property(srna, "modifiers", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_struct_type(prop, "SequenceModifier");
+ RNA_def_property_ui_text(prop, "Modifiers", "Modifiers affecting this strip");
+ rna_def_sequence_modifiers(brna, prop);
+
RNA_api_sequence_strip(srna);
}
@@ -1475,7 +1637,7 @@ static void rna_def_effect_inputs(StructRNA *srna, int count, int supports_mask)
*/
if (supports_mask) {
- prop = RNA_def_property(srna, "input_mask", PROP_POINTER, PROP_NONE);
+ prop = RNA_def_property(srna, "input_mask_strip", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "mask_sequence");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Sequence_otherSequence_poll");
RNA_def_property_flag(prop, PROP_EDITABLE);
@@ -1963,8 +2125,138 @@ static void rna_def_effects(BlenderRNA *brna)
}
}
+static void rna_def_modifier(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static EnumPropertyItem sequence_modifier_type_items[] = {
+ {seqModifierType_ColorBalance, "COLOR_BALANCE", ICON_NONE, "Color Balance", ""},
+ {seqModifierType_Curves, "CURVES", ICON_NONE, "Curves", ""},
+ {seqModifierType_HueCorrect,"HUE_CORRECT", ICON_NONE, "Hue Correct", ""},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ static const EnumPropertyItem mask_input_type_items[] = {
+ {SEQUENCE_MASK_INPUT_STRIP, "STRIP", 0, "Strip", "Use sequencer strip as mask input"},
+ {SEQUENCE_MASK_INPUT_ID, "ID", 0, "Mask", "Use mask ID as mask input"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ srna = RNA_def_struct(brna, "SequenceModifier", NULL);
+ RNA_def_struct_sdna(srna, "SequenceModifierData");
+ RNA_def_struct_ui_text(srna, "SequenceModifier", "Modifier for sequence strip");
+ RNA_def_struct_refine_func(srna, "rna_SequenceModifier_refine");
+ RNA_def_struct_path_func(srna, "rna_SequenceModifier_path");
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_SequenceModifier_name_set");
+ RNA_def_property_ui_text(prop, "Name", "");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_enum_items(prop, sequence_modifier_type_items);
+ RNA_def_property_ui_text(prop, "Type", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQUENCE_MODIFIER_MUTE);
+ RNA_def_property_ui_text(prop, "Mute", "Mute this modifier");
+ RNA_def_property_ui_icon(prop, ICON_RESTRICT_VIEW_OFF, 1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
+
+ prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", SEQUENCE_MODIFIER_EXPANDED);
+ RNA_def_property_ui_text(prop, "Expanded", "Mute expanded settings for the modifier");
+ RNA_def_property_ui_icon(prop, ICON_TRIA_RIGHT, 1);
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
+
+ prop = RNA_def_property(srna, "input_mask_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "mask_input_type");
+ RNA_def_property_enum_items(prop, mask_input_type_items);
+ RNA_def_property_ui_text(prop, "Mask Input Type", "Type of input data used for mask");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
+
+ prop = RNA_def_property(srna, "input_mask_strip", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "mask_sequence");
+ RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_SequenceModifier_otherSequence_poll");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Mask Strip", "Strip used as mask input for the modifier");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
+
+ prop = RNA_def_property(srna, "input_mask_id", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "mask_id");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Mask", "Mask ID used as mask input for the modifier");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
+}
+
+static void rna_def_colorbalance_modifier(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "ColorBalanceModifier", "SequenceModifier");
+ RNA_def_struct_sdna(srna, "ColorBalanceModifierData");
+ RNA_def_struct_ui_text(srna, "ColorBalanceModifier", "Color balance modifier for sequence strip");
+
+ prop = RNA_def_property(srna, "color_balance", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "SequenceColorBalanceData");
+
+ prop = RNA_def_property(srna, "color_multiply", PROP_FLOAT, PROP_UNSIGNED);
+ RNA_def_property_float_sdna(prop, NULL, "color_multiply");
+ RNA_def_property_range(prop, 0.0f, 20.0f);
+ RNA_def_property_float_default(prop, 1.0f);
+ RNA_def_property_ui_text(prop, "Multiply Colors", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
+}
+
+static void rna_def_curves_modifier(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "CurvesModifier", "SequenceModifier");
+ RNA_def_struct_sdna(srna, "CurvesModifierData");
+ RNA_def_struct_ui_text(srna, "CurvesModifier", "RGB curves modifier for sequence strip");
+
+ prop = RNA_def_property(srna, "curve_mapping", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve_mapping");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Curve Mapping", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
+}
+
+static void rna_def_hue_modifier(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "HueCorrectModifier", "SequenceModifier");
+ RNA_def_struct_sdna(srna, "HueCorrectModifierData");
+ RNA_def_struct_ui_text(srna, "HueCorrectModifier", "Hue correction modifier for sequence strip");
+
+ prop = RNA_def_property(srna, "curve_mapping", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "curve_mapping");
+ RNA_def_property_struct_type(prop, "CurveMapping");
+ RNA_def_property_ui_text(prop, "Curve Mapping", "");
+ RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_SequenceModifier_update");
+}
+
+static void rna_def_modifiers(BlenderRNA *brna)
+{
+ rna_def_modifier(brna);
+ rna_def_colorbalance_modifier(brna);
+ rna_def_curves_modifier(brna);
+ rna_def_hue_modifier(brna);
+}
+
void RNA_def_sequencer(BlenderRNA *brna)
{
+ rna_def_color_balance(brna);
+
rna_def_strip_element(brna);
rna_def_strip_proxy(brna);
rna_def_strip_color_balance(brna);
@@ -1983,6 +2275,7 @@ void RNA_def_sequencer(BlenderRNA *brna)
rna_def_sound(brna);
rna_def_effect(brna);
rna_def_effects(brna);
+ rna_def_modifiers(brna);
}
#endif
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 96ddcce6004..cf43bd74d72 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -125,6 +125,7 @@ void RNA_api_ui_layout(StructRNA *srna)
{0, "NONE", 0, "None", ""},
{'v', "VECTOR", 0, "Vector", ""},
{'c', "COLOR", 0, "Color", ""},
+ {'h', "HUE", 0, "Hue", ""},
{0, NULL, 0, NULL, NULL}
};