Text effect strip for sequencer.
Is pretty much what it says :) Easy subtitles for everyone! Supports size, positioning, a cheap shadow effect (probably will need more work), and autocentering on x axis. Now you can go wild with long spanish names in your soap opera videos. Will probably be refined as days go by, but at least it's now ready for testing.
This commit is contained in:
@@ -333,6 +333,7 @@ class SEQUENCER_MT_add_effect(Menu):
|
||||
layout.operator("sequencer.effect_strip_add", text="Over Drop").type = 'OVER_DROP'
|
||||
layout.operator("sequencer.effect_strip_add", text="Wipe").type = 'WIPE'
|
||||
layout.operator("sequencer.effect_strip_add", text="Glow").type = 'GLOW'
|
||||
layout.operator("sequencer.effect_strip_add", text="Text").type = 'TEXT'
|
||||
layout.operator("sequencer.effect_strip_add", text="Transform").type = 'TRANSFORM'
|
||||
layout.operator("sequencer.effect_strip_add", text="Color").type = 'COLOR'
|
||||
layout.operator("sequencer.effect_strip_add", text="Speed Control").type = 'SPEED'
|
||||
@@ -537,7 +538,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
|
||||
return strip.type in {'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
|
||||
'CROSS', 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP',
|
||||
'WIPE', 'GLOW', 'TRANSFORM', 'COLOR', 'SPEED',
|
||||
'MULTICAM', 'GAUSSIAN_BLUR'}
|
||||
'MULTICAM', 'GAUSSIAN_BLUR', 'TEXT'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -628,6 +629,17 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
|
||||
for i in range(1, strip.channel):
|
||||
row.operator("sequencer.cut_multicam", text="%d" % i).camera = i
|
||||
|
||||
elif strip.type == 'TEXT':
|
||||
col = layout.column()
|
||||
col.prop(strip, "text")
|
||||
col.prop(strip, "text_size")
|
||||
col.prop(strip, "use_shadow")
|
||||
col.prop(strip, "use_autocenter")
|
||||
row = layout.row(align=True)
|
||||
if not strip.use_autocenter:
|
||||
row.prop(strip, "xpos")
|
||||
row.prop(strip, "ypos")
|
||||
|
||||
col = layout.column(align=True)
|
||||
if strip.type == 'SPEED':
|
||||
col.prop(strip, "multiply_speed")
|
||||
@@ -638,7 +650,7 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
|
||||
elif strip.type == 'GAUSSIAN_BLUR':
|
||||
col.prop(strip, "size_x")
|
||||
col.prop(strip, "size_y")
|
||||
|
||||
|
||||
|
||||
class SEQUENCER_PT_input(SequencerButtonsPanel, Panel):
|
||||
bl_label = "Strip Input"
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "BLI_math.h" /* windows needs for M_PI */
|
||||
#include "BLI_utildefines.h"
|
||||
#include "BLI_string.h"
|
||||
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_sequence_types.h"
|
||||
@@ -54,6 +55,8 @@
|
||||
|
||||
#include "RE_pipeline.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
||||
static void slice_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
|
||||
const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1,
|
||||
unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out)
|
||||
@@ -2876,6 +2879,82 @@ static void do_gaussian_blur_effect(const SeqRenderData *context,
|
||||
}
|
||||
}
|
||||
|
||||
/*********************** text *************************/
|
||||
static void init_text_effect(Sequence *seq)
|
||||
{
|
||||
TextVars *data;
|
||||
|
||||
if (seq->effectdata)
|
||||
MEM_freeN(seq->effectdata);
|
||||
|
||||
data = seq->effectdata = MEM_callocN(sizeof(TextVars), "textvars");
|
||||
data->text_size = U.pixelsize * 30;
|
||||
BLI_strncpy(data->text, "Text", sizeof(data->text));
|
||||
}
|
||||
|
||||
static int num_inputs_text(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int early_out_text(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
|
||||
{
|
||||
TextVars *data = seq->effectdata;
|
||||
if (data->text[0] == 0 || data->text_size < 1) {
|
||||
return EARLY_USE_INPUT_1;
|
||||
}
|
||||
return EARLY_NO_INPUT;
|
||||
}
|
||||
|
||||
static ImBuf *do_text_effect(const SeqRenderData *context, Sequence *seq, float UNUSED(cfra), float UNUSED(facf0), float UNUSED(facf1),
|
||||
ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
|
||||
{
|
||||
ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
|
||||
TextVars *data = seq->effectdata;
|
||||
int width = out->x;
|
||||
int height = out->y;
|
||||
struct ColorManagedDisplay *display;
|
||||
const char *display_device;
|
||||
const int mono = blf_mono_font_render; // XXX
|
||||
int y_ofs, x, y, w;
|
||||
|
||||
display_device = context->scene->display_settings.display_device;
|
||||
display = IMB_colormanagement_display_get_named(display_device);
|
||||
|
||||
/* set before return */
|
||||
BLF_size(mono, (context->scene->r.size / 100.0f) * data->text_size, 72);
|
||||
|
||||
BLF_buffer(mono, out->rect_float, (unsigned char *)out->rect, width, height, out->channels, display);
|
||||
|
||||
y_ofs = -BLF_descender(mono);
|
||||
|
||||
w = BLF_width(mono, data->text, sizeof(data->text));
|
||||
|
||||
if (data->flags & TEXT_SEQ_AUTO_CENTER)
|
||||
x = width / 2 - w / 2;
|
||||
else
|
||||
x = (context->scene->r.size / 100.0f) * data->xpos;
|
||||
|
||||
y = y_ofs + (context->scene->r.size / 100.0f) * data->ypos;
|
||||
|
||||
/* BLF_SHADOW won't work with buffers, instead use cheap shadow trick */
|
||||
if (data->flags & TEXT_SEQ_SHADOW) {
|
||||
int fontx, fonty;
|
||||
fontx = BLF_width_max(mono);
|
||||
fonty = BLF_height_max(mono);
|
||||
BLF_position(mono, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0);
|
||||
BLF_buffer_col(mono, 0.0f, 0.0f, 0.0f, 1.0);
|
||||
BLF_draw_buffer(mono, data->text);
|
||||
}
|
||||
BLF_position(mono, x, y, 0.0);
|
||||
BLF_buffer_col(mono, 1.0f, 1.0f, 1.0f, 1.0);
|
||||
BLF_draw_buffer(mono, data->text);
|
||||
|
||||
BLF_buffer(mono, NULL, NULL, 0, 0, 0, NULL);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/*********************** sequence effect factory *************************/
|
||||
|
||||
static void init_noop(Sequence *UNUSED(seq))
|
||||
@@ -2898,6 +2977,19 @@ static int num_inputs_default(void)
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void copy_effect_default(Sequence *dst, Sequence *src)
|
||||
{
|
||||
dst->effectdata = MEM_dupallocN(src->effectdata);
|
||||
}
|
||||
|
||||
static void free_effect_default(Sequence *seq)
|
||||
{
|
||||
if (seq->effectdata)
|
||||
MEM_freeN(seq->effectdata);
|
||||
|
||||
seq->effectdata = NULL;
|
||||
}
|
||||
|
||||
static int early_out_noop(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
|
||||
{
|
||||
return EARLY_DO_EFFECT;
|
||||
@@ -3073,6 +3165,14 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
|
||||
rval.early_out = early_out_gaussian_blur;
|
||||
rval.execute_slice = do_gaussian_blur_effect;
|
||||
break;
|
||||
case SEQ_TYPE_TEXT:
|
||||
rval.num_inputs = num_inputs_text;
|
||||
rval.init = init_text_effect;
|
||||
rval.free = free_effect_default;
|
||||
rval.copy = copy_effect_default;
|
||||
rval.early_out = early_out_text;
|
||||
rval.execute = do_text_effect;
|
||||
break;
|
||||
}
|
||||
|
||||
return rval;
|
||||
|
||||
@@ -1115,6 +1115,7 @@ static const char *give_seqname_by_type(int type)
|
||||
case SEQ_TYPE_ADJUSTMENT: return "Adjustment";
|
||||
case SEQ_TYPE_SPEED: return "Speed";
|
||||
case SEQ_TYPE_GAUSSIAN_BLUR: return "Gaussian Blur";
|
||||
case SEQ_TYPE_TEXT: return "Text";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -2468,6 +2468,9 @@ static void write_scenes(WriteData *wd, ListBase *scebase)
|
||||
case SEQ_TYPE_GAUSSIAN_BLUR:
|
||||
writestruct(wd, DATA, "GaussianBlurVars", 1, seq->effectdata);
|
||||
break;
|
||||
case SEQ_TYPE_TEXT:
|
||||
writestruct(wd, DATA, "TextVars", 1, seq->effectdata);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1010,6 +1010,9 @@ static int sequencer_add_effect_strip_exec(bContext *C, wmOperator *op)
|
||||
else if (seq->type == SEQ_TYPE_ADJUSTMENT) {
|
||||
seq->blend_mode = SEQ_TYPE_CROSS;
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_TEXT) {
|
||||
seq->blend_mode = SEQ_TYPE_ALPHAOVER;
|
||||
}
|
||||
|
||||
/* an unset channel is a special case where we automatically go above
|
||||
* the other strips. */
|
||||
|
||||
@@ -499,6 +499,11 @@ static void draw_seq_text(View2D *v2d, Sequence *seq, float x1, float x2, float
|
||||
str_len = BLI_snprintf(str, sizeof(str), "%s: %s%s | %d",
|
||||
name, seq->strip->dir, seq->strip->stripdata->name, seq->len);
|
||||
}
|
||||
else if (seq->type == SEQ_TYPE_TEXT) {
|
||||
TextVars *textdata = seq->effectdata;
|
||||
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
|
||||
textdata->text, seq->startdisp);
|
||||
}
|
||||
else if (seq->type & SEQ_TYPE_EFFECT) {
|
||||
str_len = BLI_snprintf(str, sizeof(str), "%s | %d",
|
||||
name, seq->len);
|
||||
|
||||
@@ -91,6 +91,7 @@ EnumPropertyItem sequencer_prop_effect_types[] = {
|
||||
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
|
||||
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
|
||||
{SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
|
||||
{SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -191,7 +191,7 @@ void gpu_debug_init(void)
|
||||
|
||||
#if !defined(WITH_GLEW_ES) && !defined(GLEW_ES_ONLY)
|
||||
if (GLEW_VERSION_4_3) {
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
//glEnable(GL_DEBUG_OUTPUT);
|
||||
glDebugMessageCallback(gpu_debug_proc, mxGetCurrentContext());
|
||||
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, GL_TRUE);
|
||||
GPU_STRING_MARKER(sizeof(success), success);
|
||||
|
||||
@@ -271,6 +271,17 @@ typedef struct GaussianBlurVars {
|
||||
float size_y;
|
||||
} GaussianBlurVars;
|
||||
|
||||
typedef struct TextVars {
|
||||
char text[512];
|
||||
int text_size;
|
||||
int xpos, ypos;
|
||||
int flags;
|
||||
} TextVars;
|
||||
|
||||
enum {
|
||||
TEXT_SEQ_SHADOW = (1 << 0),
|
||||
TEXT_SEQ_AUTO_CENTER = (1 << 1),
|
||||
};
|
||||
/* ***************** Sequence modifiers ****************** */
|
||||
|
||||
typedef struct SequenceModifierData {
|
||||
@@ -463,7 +474,9 @@ enum {
|
||||
SEQ_TYPE_MULTICAM = 30,
|
||||
SEQ_TYPE_ADJUSTMENT = 31,
|
||||
SEQ_TYPE_GAUSSIAN_BLUR = 40,
|
||||
SEQ_TYPE_MAX = 40
|
||||
SEQ_TYPE_TEXT = 41,
|
||||
|
||||
SEQ_TYPE_MAX = 41
|
||||
};
|
||||
|
||||
#define SEQ_MOVIECLIP_RENDER_UNDISTORTED (1 << 0)
|
||||
|
||||
@@ -625,6 +625,7 @@ extern StructRNA RNA_ThemeNodeEditor;
|
||||
extern StructRNA RNA_ThemeOutliner;
|
||||
extern StructRNA RNA_ThemeProperties;
|
||||
extern StructRNA RNA_ThemeSequenceEditor;
|
||||
extern StructRNA RNA_TextSequence;
|
||||
extern StructRNA RNA_ThemeSpaceGeneric;
|
||||
extern StructRNA RNA_ThemeSpaceGradient;
|
||||
extern StructRNA RNA_ThemeSpaceListGeneric;
|
||||
|
||||
@@ -546,6 +546,8 @@ static StructRNA *rna_Sequence_refine(struct PointerRNA *ptr)
|
||||
return &RNA_SpeedControlSequence;
|
||||
case SEQ_TYPE_GAUSSIAN_BLUR:
|
||||
return &RNA_GaussianBlurSequence;
|
||||
case SEQ_TYPE_TEXT:
|
||||
return &RNA_TextSequence;
|
||||
default:
|
||||
return &RNA_Sequence;
|
||||
}
|
||||
@@ -1407,6 +1409,7 @@ static void rna_def_sequence(BlenderRNA *brna)
|
||||
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
|
||||
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
|
||||
{SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
|
||||
{SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -2302,6 +2305,42 @@ static void rna_def_gaussian_blur(StructRNA *srna)
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
}
|
||||
|
||||
static void rna_def_text(StructRNA *srna)
|
||||
{
|
||||
PropertyRNA *prop;
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "TextVars", "effectdata");
|
||||
|
||||
prop = RNA_def_property(srna, "text_size", PROP_INT, PROP_UNSIGNED);
|
||||
RNA_def_property_ui_text(prop, "Size", "Size of the text");
|
||||
RNA_def_property_ui_range(prop, 0.0f, 1000, 1, -1);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop = RNA_def_property(srna, "xpos", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "X Position", "X position of the text");
|
||||
RNA_def_property_ui_range(prop, -1000, 1000, 1, -1);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop = RNA_def_property(srna, "ypos", PROP_INT, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Y Position", "Y position of the text");
|
||||
RNA_def_property_ui_range(prop, -1000, 1000, 1, -1);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop = RNA_def_property(srna, "text", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_ui_text(prop, "Text", "Text that will be displayed");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_shadow", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", TEXT_SEQ_SHADOW);
|
||||
RNA_def_property_ui_text(prop, "Shadow", "draw text with shadow");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_autocenter", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flags", TEXT_SEQ_AUTO_CENTER);
|
||||
RNA_def_property_ui_text(prop, "Auto-Center", "draw text centered in x axis");
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");
|
||||
}
|
||||
|
||||
static EffectInfo def_effects[] = {
|
||||
{"AddSequence", "Add Sequence", "Add Sequence", NULL, 2},
|
||||
{"AdjustmentSequence", "Adjustment Layer Sequence",
|
||||
@@ -2326,6 +2365,8 @@ static EffectInfo def_effects[] = {
|
||||
rna_def_wipe, 1},
|
||||
{"GaussianBlurSequence", "Gaussian Blur Sequence", "Sequence strip creating a gaussian blur",
|
||||
rna_def_gaussian_blur, 1},
|
||||
{"TextSequence", "Text Sequence", "Sequence strip creating text",
|
||||
rna_def_text, 0},
|
||||
{"", "", "", NULL, 0}
|
||||
};
|
||||
|
||||
|
||||
@@ -474,6 +474,7 @@ void RNA_api_sequences(BlenderRNA *brna, PropertyRNA *cprop)
|
||||
{SEQ_TYPE_MULTICAM, "MULTICAM", 0, "Multicam Selector", ""},
|
||||
{SEQ_TYPE_ADJUSTMENT, "ADJUSTMENT", 0, "Adjustment Layer", ""},
|
||||
{SEQ_TYPE_GAUSSIAN_BLUR, "GAUSSIAN_BLUR", 0, "Gaussian Blur", ""},
|
||||
{SEQ_TYPE_TEXT, "TEXT", 0, "Text", ""},
|
||||
{0, NULL, 0, NULL, NULL}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user