diff options
18 files changed, 1712 insertions, 230 deletions
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 5302ad9b471..0b4d4cd19e4 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -774,7 +774,7 @@ class IMAGE_PT_paint_curve(BrushButtonsPanel, Panel): toolsettings = context.tool_settings.image_paint brush = toolsettings.brush - layout.template_curve_mapping(brush, "curve") + layout.template_curve_mapping(brush, "curve", type='COLOR') row = layout.row(align=True) row.operator("brush.curve_preset", icon='SMOOTHCURVE', text="").shape = 'SMOOTH' diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 50c8603a7c2..cd10bce8ef6 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -28,6 +28,29 @@ def act_strip(context): return None +def draw_color_balance(layout, color_balance): + col = layout.column() + col.label(text="Lift:") + col.template_color_wheel(color_balance, "lift", value_slider=True, cubic=True) + row = col.row() + row.prop(color_balance, "lift", text="") + row.prop(color_balance, "invert_lift", text="Inverse") + + col = layout.column() + col.label(text="Gamma:") + col.template_color_wheel(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) + row = col.row() + row.prop(color_balance, "gamma", text="") + row.prop(color_balance, "invert_gamma", text="Inverse") + + col = layout.column() + col.label(text="Gain:") + col.template_color_wheel(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) + row = col.row() + row.prop(color_balance, "gain", text="") + row.prop(color_balance, "invert_gain", text="Inverse") + + class SEQUENCER_HT_header(Header): bl_space_type = 'SEQUENCE_EDITOR' @@ -442,7 +465,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): if strip.is_supports_mask: col = layout.column() - col.prop_search(strip, "input_mask", sequencer, "sequences") + col.prop_search(strip, "input_mask_strip", sequencer, "sequences", text="Mask") if strip.type == 'COLOR': layout.prop(strip, "color") @@ -772,26 +795,7 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): layout.prop(strip, "use_color_balance") if strip.use_color_balance and strip.color_balance: # TODO - need to add this somehow - col = layout.column() - col.label(text="Lift:") - col.template_color_wheel(strip.color_balance, "lift", value_slider=True, cubic=True) - row = col.row() - row.prop(strip.color_balance, "lift", text="") - row.prop(strip.color_balance, "invert_lift", text="Inverse") - - col = layout.column() - col.label(text="Gamma:") - col.template_color_wheel(strip.color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) - row = col.row() - row.prop(strip.color_balance, "gamma", text="") - row.prop(strip.color_balance, "invert_gamma", text="Inverse") - - col = layout.column() - col.label(text="Gain:") - col.template_color_wheel(strip.color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) - row = col.row() - row.prop(strip.color_balance, "gain", text="") - row.prop(strip.color_balance, "invert_gain", text="Inverse") + draw_color_balance(layout, strip.color_balance) class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): @@ -878,5 +882,46 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel): col.prop(st, "show_separate_color") col.prop(st, "proxy_render_size") + +class SEQUENCER_PT_modifiers(SequencerButtonsPanel, Panel): + bl_label = "Modifiers" + + def draw(self, context): + layout = self.layout + + strip = act_strip(context) + sequencer = context.scene.sequence_editor + + layout.operator_menu_enum("sequencer.strip_modifier_add", "type") + + for mod in strip.modifiers: + box = layout.box() + + row = box.row() + row.prop(mod, "show_expanded", text="", emboss=False) + row.prop(mod, "name") + + row.prop(mod, "mute", text="") + props = row.operator("sequencer.strip_modifier_remove", text="", icon='X') + props.name = mod.name + + if mod.show_expanded: + row = box.row() + row.prop(mod, "input_mask_type", expand=True) + + if mod.input_mask_type == 'STRIP': + box.prop_search(mod, "input_mask_strip", sequencer, "sequences", text="Mask") + else: + box.prop(mod, "input_mask_id") + + if mod.type == 'COLOR_BALANCE': + box.prop(mod, "color_multiply") + draw_color_balance(box, mod.color_balance) + elif mod.type == 'CURVES': + box.template_curve_mapping(mod, "curve_mapping", type='COLOR') + elif mod.type == 'HUE_CORRECT': + box.template_curve_mapping(mod, "curve_mapping", type='HUE') + + if __name__ == "__main__": # only for live edit. bpy.utils.register_module(__name__) 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} }; |