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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py28
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenkernel/intern/scene.c12
-rw-r--r--source/blender/blenloader/intern/versioning_290.c182
-rw-r--r--source/blender/editors/space_sequencer/sequencer_add.c29
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c145
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h2
-rw-r--r--source/blender/editors/space_sequencer/sequencer_ops.c2
-rw-r--r--source/blender/imbuf/IMB_imbuf.h2
-rw-r--r--source/blender/imbuf/intern/anim_movie.c10
-rw-r--r--source/blender/makesdna/DNA_scene_types.h15
-rw-r--r--source/blender/makesrna/intern/rna_scene.c38
-rw-r--r--source/blender/sequencer/SEQ_sequencer.h27
-rw-r--r--source/blender/sequencer/intern/render.c18
-rw-r--r--source/blender/sequencer/intern/sequencer.c33
-rw-r--r--source/blender/sequencer/intern/strip_add.c14
-rw-r--r--source/blender/sequencer/intern/utils.c34
17 files changed, 541 insertions, 52 deletions
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 84602057e18..e79b5d3e2c8 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -129,6 +129,8 @@ class SEQUENCER_HT_header(Header):
layout = self.layout
st = context.space_data
+ scene = context.scene
+ sequencer_tool_settings = context.tool_settings.sequencer_tool_settings
show_region_tool_header = st.show_region_tool_header
@@ -139,9 +141,15 @@ class SEQUENCER_HT_header(Header):
SEQUENCER_MT_editor_menus.draw_collapsible(context, layout)
- layout.separator_spacer()
+ if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
+ layout.separator_spacer()
+ row = layout.row(align=True)
+ row.prop(sequencer_tool_settings, "fit_method", text="")
+ layout.separator_spacer()
if st.view_type in {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ if st.view_type == 'PREVIEW':
+ layout.separator_spacer()
layout.prop(st, "display_mode", text="", icon_only=True)
layout.prop(st, "preview_channels", text="", icon_only=True)
@@ -700,6 +708,22 @@ class SEQUENCER_MT_add_effect(Menu):
col.enabled = selected_sequences_len(context) != 0
+class SEQUENCER_MT_strip_image_transform(Menu):
+ bl_label = "Image Transform"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("sequencer.strip_transform_fit", text="Scale To Fit").fit_method = 'FIT'
+ layout.operator("sequencer.strip_transform_fit", text="Scale to Fill").fit_method = 'FILL'
+ layout.operator("sequencer.strip_transform_fit", text="Stretch To Fill").fit_method = 'STRETCH'
+ layout.separator()
+
+ layout.operator("sequencer.strip_transform_clear", text="Clear Position").property = 'POSITION'
+ layout.operator("sequencer.strip_transform_clear", text="Clear Scale").property = 'SCALE'
+ layout.operator("sequencer.strip_transform_clear", text="Clear Rotation").property = 'ROTATION'
+ layout.operator("sequencer.strip_transform_clear", text="Clear All").property = 'ALL'
+
class SEQUENCER_MT_strip_transform(Menu):
bl_label = "Transform"
@@ -794,6 +818,7 @@ class SEQUENCER_MT_strip(Menu):
layout.separator()
layout.menu("SEQUENCER_MT_strip_transform")
+ layout.menu("SEQUENCER_MT_strip_image_transform")
layout.separator()
layout.operator("sequencer.split", text="Split").type = 'SOFT'
@@ -2285,6 +2310,7 @@ classes = (
SEQUENCER_MT_strip_effect,
SEQUENCER_MT_strip_movie,
SEQUENCER_MT_strip,
+ SEQUENCER_MT_strip_image_transform,
SEQUENCER_MT_strip_transform,
SEQUENCER_MT_strip_input,
SEQUENCER_MT_strip_lock_mute,
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index ca95ca8bda0..1ed4d1183a1 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -39,7 +39,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 7
+#define BLENDER_FILE_SUBVERSION 8
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index f63d443d29f..cc192c1c3c0 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -222,6 +222,7 @@ static void scene_init_data(ID *id)
/* Curve Profile */
scene->toolsettings->custom_bevel_profile_preset = BKE_curveprofile_add(PROF_PRESET_LINE);
+ scene->toolsettings->sequencer_tool_settings = SEQ_tool_settings_init();
for (size_t i = 0; i < ARRAY_SIZE(scene->orientation_slots); i++) {
scene->orientation_slots[i].index_custom = -1;
@@ -862,6 +863,9 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
if (tos->custom_bevel_profile_preset) {
BKE_curveprofile_blend_write(writer, tos->custom_bevel_profile_preset);
}
+ if (tos->sequencer_tool_settings) {
+ BLO_write_struct(writer, SequencerToolSettings, tos->sequencer_tool_settings);
+ }
BKE_paint_blend_write(writer, &tos->imapaint.paint);
@@ -1121,6 +1125,8 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
if (sce->toolsettings->custom_bevel_profile_preset) {
BKE_curveprofile_blend_read(reader, sce->toolsettings->custom_bevel_profile_preset);
}
+
+ BLO_read_data_address(reader, &sce->toolsettings->sequencer_tool_settings);
}
if (sce->ed) {
@@ -1792,6 +1798,8 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
ts->gp_sculpt.cur_primitive = BKE_curvemapping_copy(ts->gp_sculpt.cur_primitive);
ts->custom_bevel_profile_preset = BKE_curveprofile_copy(ts->custom_bevel_profile_preset);
+
+ ts->sequencer_tool_settings = SEQ_tool_settings_copy(ts->sequencer_tool_settings);
return ts;
}
@@ -1850,6 +1858,10 @@ void BKE_toolsettings_free(ToolSettings *toolsettings)
BKE_curveprofile_free(toolsettings->custom_bevel_profile_preset);
}
+ if (toolsettings->sequencer_tool_settings) {
+ SEQ_tool_settings_free(toolsettings->sequencer_tool_settings);
+ }
+
MEM_freeN(toolsettings);
}
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 49e1b057b39..753cc861982 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -74,6 +74,29 @@
/* Make preferences read-only, use versioning_userdef.c. */
#define U (*((const UserDef *)&U))
+static eSpaceSeq_Proxy_RenderSize get_sequencer_render_size(Main *bmain)
+{
+ eSpaceSeq_Proxy_RenderSize render_size = 100;
+
+ for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
+ switch (sl->spacetype) {
+ case SPACE_SEQ: {
+ SpaceSeq *sseq = (SpaceSeq *)sl;
+ if (sseq->mainb == SEQ_DRAW_IMG_IMBUF) {
+ render_size = sseq->render_size;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return render_size;
+}
+
/* image_size is width or height depending what RNA property is converted - X or Y. */
static void seq_convert_transform_animation(const Scene *scene,
const char *path,
@@ -212,6 +235,90 @@ static void seq_convert_transform_crop_lb(const Scene *scene,
}
}
+static void seq_convert_transform_animation_2(const Scene *scene,
+ const char *path,
+ const float scale_to_fit_factor)
+{
+ if (scene->adt == NULL || scene->adt->action == NULL) {
+ return;
+ }
+
+ FCurve *fcu = BKE_fcurve_find(&scene->adt->action->curves, path, 0);
+ if (fcu != NULL && !BKE_fcurve_is_empty(fcu)) {
+ BezTriple *bezt = fcu->bezt;
+ for (int i = 0; i < fcu->totvert; i++, bezt++) {
+ /* Same math as with old_image_center_*, but simplified. */
+ bezt->vec[1][1] *= scale_to_fit_factor;
+ }
+ }
+}
+
+static void seq_convert_transform_crop_2(const Scene *scene,
+ Sequence *seq,
+ const eSpaceSeq_Proxy_RenderSize render_size)
+{
+ const StripElem *s_elem = SEQ_render_give_stripelem(seq, seq->start);
+ if (s_elem == NULL) {
+ return;
+ }
+
+ StripCrop *c = seq->strip->crop;
+ StripTransform *t = seq->strip->transform;
+ int image_size_x = s_elem->orig_width;
+ int image_size_y = s_elem->orig_height;
+
+ if (SEQ_can_use_proxy(seq, SEQ_rendersize_to_proxysize(render_size))) {
+ image_size_x /= SEQ_rendersize_to_scale_factor(render_size);
+ image_size_y /= SEQ_rendersize_to_scale_factor(render_size);
+ }
+
+ /* Calculate scale factor, so image fits in preview area with original aspect ratio. */
+ const float scale_to_fit_factor = MIN2((float)scene->r.xsch / (float)image_size_x,
+ (float)scene->r.ysch / (float)image_size_y);
+ t->scale_x *= scale_to_fit_factor;
+ t->scale_y *= scale_to_fit_factor;
+ c->top /= scale_to_fit_factor;
+ c->bottom /= scale_to_fit_factor;
+ c->left /= scale_to_fit_factor;
+ c->right /= scale_to_fit_factor;
+
+ char name_esc[(sizeof(seq->name) - 2) * 2], *path;
+ BLI_str_escape(name_esc, seq->name + 2, sizeof(name_esc));
+ path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform.offset_x", name_esc);
+ seq_convert_transform_animation_2(scene, path, scale_to_fit_factor);
+ MEM_freeN(path);
+ path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].transform.offset_y", name_esc);
+ seq_convert_transform_animation_2(scene, path, scale_to_fit_factor);
+ MEM_freeN(path);
+ path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.min_x", name_esc);
+ seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor);
+ MEM_freeN(path);
+ path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.max_x", name_esc);
+ seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor);
+ MEM_freeN(path);
+ path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.min_y", name_esc);
+ seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor);
+ MEM_freeN(path);
+ path = BLI_sprintfN("sequence_editor.sequences_all[\"%s\"].crop.max_x", name_esc);
+ seq_convert_transform_animation_2(scene, path, 1 / scale_to_fit_factor);
+ MEM_freeN(path);
+}
+
+static void seq_convert_transform_crop_lb_2(const Scene *scene,
+ const ListBase *lb,
+ const eSpaceSeq_Proxy_RenderSize render_size)
+{
+
+ LISTBASE_FOREACH (Sequence *, seq, lb) {
+ if (seq->type != SEQ_TYPE_SOUND_RAM) {
+ seq_convert_transform_crop_2(scene, seq, render_size);
+ }
+ if (seq->type == SEQ_TYPE_META) {
+ seq_convert_transform_crop_lb_2(scene, &seq->seqbase, render_size);
+ }
+ }
+}
+
void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
{
if (!MAIN_VERSION_ATLEAST(bmain, 290, 1)) {
@@ -441,25 +548,35 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
if (!MAIN_VERSION_ATLEAST(bmain, 292, 2)) {
- eSpaceSeq_Proxy_RenderSize render_size = 100;
+ eSpaceSeq_Proxy_RenderSize render_size = get_sequencer_render_size(bmain);
- for (bScreen *screen = bmain->screens.first; screen; screen = screen->id.next) {
- LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
- LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
- switch (sl->spacetype) {
- case SPACE_SEQ: {
- SpaceSeq *sseq = (SpaceSeq *)sl;
- render_size = sseq->render_size;
- break;
- }
- }
- }
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (scene->ed != NULL) {
+ seq_convert_transform_crop_lb(scene, &scene->ed->seqbase, render_size);
}
}
+ }
+ if (!MAIN_VERSION_ATLEAST(bmain, 292, 8)) {
+ /* Systematically rebuild posebones to ensure consistent ordering matching the one of bones in
+ * Armature obdata. */
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ if (ob->type == OB_ARMATURE) {
+ BKE_pose_rebuild(bmain, ob, ob->data, true);
+ }
+ }
+
+ /* Wet Paint Radius Factor */
+ for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
+ if (br->ob_mode & OB_MODE_SCULPT && br->wet_paint_radius_factor == 0.0f) {
+ br->wet_paint_radius_factor = 1.0f;
+ }
+ }
+
+ eSpaceSeq_Proxy_RenderSize render_size = get_sequencer_render_size(bmain);
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
if (scene->ed != NULL) {
- seq_convert_transform_crop_lb(scene, &scene->ed->seqbase, render_size);
+ seq_convert_transform_crop_lb_2(scene, &scene->ed->seqbase, render_size);
}
}
}
@@ -476,21 +593,6 @@ void do_versions_after_linking_290(Main *bmain, ReportList *UNUSED(reports))
*/
{
/* Keep this block, even when empty. */
-
- /* Systematically rebuild posebones to ensure consistent ordering matching the one of bones in
- * Armature obdata. */
- LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
- if (ob->type == OB_ARMATURE) {
- BKE_pose_rebuild(bmain, ob, ob->data, true);
- }
- }
- }
-
- /* Wet Paint Radius Factor */
- for (Brush *br = bmain->brushes.first; br; br = br->id.next) {
- if (br->ob_mode & OB_MODE_SCULPT && br->wet_paint_radius_factor == 0.0f) {
- br->wet_paint_radius_factor = 1.0f;
- }
}
}
@@ -1305,6 +1407,22 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
+ if (!MAIN_VERSION_ATLEAST(bmain, 292, 8)) {
+ LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
+ LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
+ if (STREQ(node->idname, "GeometryNodeRandomAttribute")) {
+ STRNCPY(node->idname, "GeometryNodeAttributeRandomize");
+ }
+ }
+ }
+
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (scene->ed != NULL) {
+ scene->toolsettings->sequencer_tool_settings = SEQ_tool_settings_init();
+ }
+ }
+ }
+
/**
* Versioning code until next subversion bump goes here.
*
@@ -1316,13 +1434,5 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
*/
{
/* Keep this block, even when empty. */
-
- LISTBASE_FOREACH (bNodeTree *, ntree, &bmain->nodetrees) {
- LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- if (STREQ(node->idname, "GeometryNodeRandomAttribute")) {
- STRNCPY(node->idname, "GeometryNodeAttributeRandomize");
- }
- }
- }
}
}
diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c
index 37dfcdbc765..71433a6978a 100644
--- a/source/blender/editors/space_sequencer/sequencer_add.c
+++ b/source/blender/editors/space_sequencer/sequencer_add.c
@@ -81,9 +81,18 @@ typedef struct SequencerAddData {
#define SEQPROP_ENDFRAME (1 << 1)
#define SEQPROP_NOPATHS (1 << 2)
#define SEQPROP_NOCHAN (1 << 3)
+#define SEQPROP_FIT_METHOD (1 << 4)
#define SELECT 1
+static const EnumPropertyItem scale_fit_methods[] = {
+ {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"},
+ {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"},
+ {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image to fill the canvas"},
+ {SEQ_USE_ORIGINAL_SIZE, "ORIGINAL", 0, "Use Original Size", "Keep image at its original size"},
+ {0, NULL, 0, NULL, NULL},
+};
+
static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
{
PropertyRNA *prop;
@@ -123,6 +132,15 @@ static void sequencer_generic_props__internal(wmOperatorType *ot, int flag)
prop = RNA_def_boolean(
ot->srna, "overlap", 0, "Allow Overlap", "Don't correct overlap on new sequence strips");
RNA_def_property_flag(prop, PROP_HIDDEN);
+
+ if (flag & SEQPROP_FIT_METHOD) {
+ ot->prop = RNA_def_enum(ot->srna,
+ "fit_method",
+ scale_fit_methods,
+ SEQ_SCALE_TO_FIT,
+ "Fit Method",
+ "Scale fit method");
+ }
}
static void sequencer_generic_invoke_path__internal(bContext *C,
@@ -206,6 +224,8 @@ static void seq_load_operator_info(SeqLoadInfo *seq_load, bContext *C, wmOperato
seq_load->end_frame = seq_load->start_frame;
seq_load->channel = RNA_int_get(op->ptr, "channel");
seq_load->len = 1;
+ seq_load->fit_method = RNA_enum_get(op->ptr, "fit_method");
+ SEQ_tool_settings_fit_method_set(CTX_data_scene(C), seq_load->fit_method);
if ((prop = RNA_struct_find_property(op->ptr, "filepath"))) {
/* Full path, file is set by the caller. */
@@ -659,6 +679,7 @@ static int sequencer_add_movie_strip_invoke(bContext *C,
if (ed && ed->seqbasep && ed->seqbasep->first) {
RNA_boolean_set(op->ptr, "use_framerate", false);
}
+ RNA_enum_set(op->ptr, "fit_method", SEQ_tool_settings_fit_method_get(scene));
/* This is for drag and drop. */
if ((RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) ||
@@ -725,7 +746,7 @@ void SEQUENCER_OT_movie_strip_add(struct wmOperatorType *ot)
WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME);
+ sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_FIT_METHOD);
RNA_def_boolean(ot->srna, "sound", true, "Sound", "Load sound with the movie");
RNA_def_boolean(ot->srna,
"use_framerate",
@@ -928,6 +949,9 @@ static int sequencer_add_image_strip_invoke(bContext *C,
PropertyRNA *prop;
Scene *scene = CTX_data_scene(C);
+ const SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings;
+ RNA_enum_set(op->ptr, "fit_method", tool_settings->fit_method);
+
/* Name set already by drag and drop. */
if (RNA_struct_property_is_set(op->ptr, "files") && RNA_collection_length(op->ptr, "files")) {
sequencer_generic_invoke_xy__internal(
@@ -972,7 +996,8 @@ void SEQUENCER_OT_image_strip_add(struct wmOperatorType *ot)
WM_FILESEL_SHOW_PROPS | WM_FILESEL_DIRECTORY,
FILE_DEFAULTDISPLAY,
FILE_SORT_DEFAULT);
- sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME);
+ sequencer_generic_props__internal(ot,
+ SEQPROP_STARTFRAME | SEQPROP_ENDFRAME | SEQPROP_FIT_METHOD);
RNA_def_boolean(ot->srna,
"use_placeholders",
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 1e3529a9607..ddc9ba2e0f6 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -3414,3 +3414,148 @@ Sequence *find_nearest_seq(Scene *scene, View2D *v2d, int *hand, const int mval[
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Strip Transform Operator
+ * \{ */
+
+enum {
+ STRIP_TRANSFORM_POSITION,
+ STRIP_TRANSFORM_SCALE,
+ STRIP_TRANSFORM_ROTATION,
+ STRIP_TRANSFORM_ALL,
+};
+
+static const EnumPropertyItem transform_reset_properties[] = {
+ {STRIP_TRANSFORM_POSITION, "POSITION", 0, "Position", "Reset strip transform location"},
+ {STRIP_TRANSFORM_SCALE, "SCALE", 0, "Scale", "Reset strip transform scale"},
+ {STRIP_TRANSFORM_ROTATION, "ROTATION", 0, "Rotation", "Reset strip transform rotation"},
+ {STRIP_TRANSFORM_ALL, "ALL", 0, "All", "Reset strip transform location, scale and rotation"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int sequencer_strip_transform_clear_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ const Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ const int property = RNA_enum_get(op->ptr, "property");
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) {
+ StripTransform *transform = seq->strip->transform;
+ switch (property) {
+ case STRIP_TRANSFORM_POSITION:
+ transform->xofs = 0;
+ transform->yofs = 0;
+ break;
+ case STRIP_TRANSFORM_SCALE:
+ transform->scale_x = 1.0f;
+ transform->scale_y = 1.0f;
+ break;
+ case STRIP_TRANSFORM_ROTATION:
+ transform->rotation = 0.0f;
+ break;
+ case STRIP_TRANSFORM_ALL:
+ transform->xofs = 0;
+ transform->yofs = 0;
+ transform->scale_x = 1.0f;
+ transform->scale_y = 1.0f;
+ transform->rotation = 0.0f;
+ break;
+ }
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_strip_transform_clear(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Clear Strip Transform";
+ ot->idname = "SEQUENCER_OT_strip_transform_clear";
+ ot->description = "Reset image transformation to default value";
+
+ /* Api callbacks. */
+ ot->exec = sequencer_strip_transform_clear_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* Flags. */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "property",
+ transform_reset_properties,
+ STRIP_TRANSFORM_ALL,
+ "Property",
+ "Strip transform property to be reset");
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Transform Set Fit Operator
+ * \{ */
+
+static const EnumPropertyItem scale_fit_methods[] = {
+ {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image so fits in preview"},
+ {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image so it fills preview completely"},
+ {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image so it fills preview"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static int sequencer_strip_transform_fit_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ const Editing *ed = BKE_sequencer_editing_get(scene, false);
+ Sequence *seq;
+ const eSeqImageFitMethod fit_method = RNA_enum_get(op->ptr, "fit_method");
+
+ for (seq = ed->seqbasep->first; seq; seq = seq->next) {
+ if (seq->flag & SELECT && seq->type != SEQ_TYPE_SOUND_RAM) {
+ const int timeline_frame = CFRA;
+ StripElem *strip_elem = SEQ_render_give_stripelem(seq, timeline_frame);
+
+ if (strip_elem == NULL) {
+ continue;
+ }
+
+ SEQ_set_scale_to_fit(seq,
+ strip_elem->orig_width,
+ strip_elem->orig_height,
+ scene->r.xsch,
+ scene->r.ysch,
+ fit_method);
+ BKE_sequence_invalidate_cache_preprocessed(scene, seq);
+ }
+ }
+
+ WM_event_add_notifier(C, NC_SCENE | ND_SEQUENCER, scene);
+ return OPERATOR_FINISHED;
+}
+
+void SEQUENCER_OT_strip_transform_fit(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Strip Transform Set Fit";
+ ot->idname = "SEQUENCER_OT_strip_transform_fit";
+
+ /* Api callbacks. */
+ ot->exec = sequencer_strip_transform_fit_exec;
+ ot->poll = sequencer_edit_poll;
+
+ /* Flags. */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ ot->prop = RNA_def_enum(ot->srna,
+ "fit_method",
+ scale_fit_methods,
+ SEQ_SCALE_TO_FIT,
+ "Fit Method",
+ "Scale fit fit_method");
+}
+
+/** \} */
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 6ccfd3a9045..4c942a83f2b 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -144,6 +144,8 @@ void SEQUENCER_OT_enable_proxies(struct wmOperatorType *ot);
void SEQUENCER_OT_export_subtitles(struct wmOperatorType *ot);
void SEQUENCER_OT_set_range_to_strips(struct wmOperatorType *ot);
+void SEQUENCER_OT_strip_transform_clear(struct wmOperatorType *ot);
+void SEQUENCER_OT_strip_transform_fit(struct wmOperatorType *ot);
/* sequencer_select.c */
void SEQUENCER_OT_select_all(struct wmOperatorType *ot);
diff --git a/source/blender/editors/space_sequencer/sequencer_ops.c b/source/blender/editors/space_sequencer/sequencer_ops.c
index bdf6e4ece7f..7bfc8600544 100644
--- a/source/blender/editors/space_sequencer/sequencer_ops.c
+++ b/source/blender/editors/space_sequencer/sequencer_ops.c
@@ -81,6 +81,8 @@ void sequencer_operatortypes(void)
WM_operatortype_append(SEQUENCER_OT_change_path);
WM_operatortype_append(SEQUENCER_OT_set_range_to_strips);
+ WM_operatortype_append(SEQUENCER_OT_strip_transform_clear);
+ WM_operatortype_append(SEQUENCER_OT_strip_transform_fit);
/* sequencer_select.c */
WM_operatortype_append(SEQUENCER_OT_select_all);
diff --git a/source/blender/imbuf/IMB_imbuf.h b/source/blender/imbuf/IMB_imbuf.h
index 957352595ed..58ddc918f61 100644
--- a/source/blender/imbuf/IMB_imbuf.h
+++ b/source/blender/imbuf/IMB_imbuf.h
@@ -382,6 +382,8 @@ bool IMB_anim_can_produce_frames(const struct anim *anim);
int ismovie(const char *filepath);
void IMB_anim_set_preseek(struct anim *anim, int preseek);
int IMB_anim_get_preseek(struct anim *anim);
+int IMB_anim_get_image_width(struct anim *anim);
+int IMB_anim_get_image_height(struct anim *anim);
/**
*
diff --git a/source/blender/imbuf/intern/anim_movie.c b/source/blender/imbuf/intern/anim_movie.c
index d825b20f5f2..9b01ea0840f 100644
--- a/source/blender/imbuf/intern/anim_movie.c
+++ b/source/blender/imbuf/intern/anim_movie.c
@@ -1506,3 +1506,13 @@ int IMB_anim_get_preseek(struct anim *anim)
{
return anim->preseek;
}
+
+int IMB_anim_get_image_width(struct anim *anim)
+{
+ return anim->x;
+}
+
+int IMB_anim_get_image_height(struct anim *anim)
+{
+ return anim->y;
+}
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 8d43483dfe4..f73f99eb4e7 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -1339,6 +1339,18 @@ typedef struct MeshStatVis {
float sharp_min, sharp_max;
} MeshStatVis;
+typedef struct SequencerToolSettings {
+ /* eSeqImageFitMethod */
+ int fit_method;
+} SequencerToolSettings;
+
+typedef enum eSeqImageFitMethod {
+ SEQ_SCALE_TO_FIT,
+ SEQ_SCALE_TO_FILL,
+ SEQ_STRETCH_TO_FILL,
+ SEQ_USE_ORIGINAL_SIZE,
+} eSeqImageFitMethod;
+
/* *************************************************************** */
/* Tool Settings */
@@ -1513,6 +1525,9 @@ typedef struct ToolSettings {
* Temporary until there is a proper preset system that stores the profiles or maybe stores
* entire bevel configurations. */
struct CurveProfile *custom_bevel_profile_preset;
+
+ struct SequencerToolSettings *sequencer_tool_settings;
+
} ToolSettings;
/* *************************************************************** */
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index e149bb4ecad..7cae88d292b 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2200,6 +2200,11 @@ static char *rna_CurvePaintSettings_path(PointerRNA *UNUSED(ptr))
return BLI_strdup("tool_settings.curve_paint_settings");
}
+static char *rna_SequencerToolSettings_path(PointerRNA *UNUSED(ptr))
+{
+ return BLI_strdup("tool_settings.sequencer_tool_settings");
+}
+
/* generic function to recalc geometry */
static void rna_EditMesh_update(bContext *C, PointerRNA *UNUSED(ptr))
{
@@ -3584,6 +3589,38 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_pointer_sdna(prop, NULL, "custom_bevel_profile_preset");
RNA_def_property_struct_type(prop, "CurveProfile");
RNA_def_property_ui_text(prop, "Curve Profile Widget", "Used for defining a profile's path");
+
+ /* Sequencer tool settings */
+ prop = RNA_def_property(srna, "sequencer_tool_settings", PROP_POINTER, PROP_NONE);
+ RNA_def_property_flag(prop, PROP_NEVER_NULL);
+ RNA_def_property_struct_type(prop, "SequencerToolSettings");
+ RNA_def_property_ui_text(prop, "Sequencer Tool Settings", NULL);
+}
+
+static void rna_def_sequencer_tool_settings(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ static const EnumPropertyItem scale_fit_methods[] = {
+ {SEQ_SCALE_TO_FIT, "FIT", 0, "Scale to Fit", "Scale image to fit within the canvas"},
+ {SEQ_SCALE_TO_FILL, "FILL", 0, "Scale to Fill", "Scale image to completely fill the canvas"},
+ {SEQ_STRETCH_TO_FILL, "STRETCH", 0, "Stretch to Fill", "Stretch image to fill the canvas"},
+ {SEQ_USE_ORIGINAL_SIZE,
+ "ORIGINAL",
+ 0,
+ "Use Original Size",
+ "Keep image at its original size"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
+ srna = RNA_def_struct(brna, "SequencerToolSettings", NULL);
+ RNA_def_struct_path_func(srna, "rna_SequencerToolSettings_path");
+ RNA_def_struct_ui_text(srna, "Sequencer Tool Settings", "");
+
+ prop = RNA_def_property(srna, "fit_method", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, scale_fit_methods);
+ RNA_def_property_ui_text(prop, "Fit Method", "Scale fit method");
}
static void rna_def_unified_paint_settings(BlenderRNA *brna)
@@ -7968,6 +8005,7 @@ void RNA_def_scene(BlenderRNA *brna)
rna_def_gpencil_interpolate(brna);
rna_def_unified_paint_settings(brna);
rna_def_curve_paint_settings(brna);
+ rna_def_sequencer_tool_settings(brna);
rna_def_statvis(brna);
rna_def_unit_settings(brna);
rna_def_scene_image_format_data(brna);
diff --git a/source/blender/sequencer/SEQ_sequencer.h b/source/blender/sequencer/SEQ_sequencer.h
index 8c4863d98ed..9b4c88520b4 100644
--- a/source/blender/sequencer/SEQ_sequencer.h
+++ b/source/blender/sequencer/SEQ_sequencer.h
@@ -23,6 +23,8 @@
* \ingroup sequencer
*/
+#include "DNA_scene_types.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -47,6 +49,10 @@ struct StripElem;
struct TextVars;
struct bContext;
struct bSound;
+struct BlendWriter;
+struct BlendDataReader;
+struct BlendLibReader;
+struct SequencerToolSettings;
/* Wipe effect */
enum {
@@ -179,6 +185,12 @@ void SEQ_render_pixel_from_sequencer_space_v4(struct Scene *scene, float pixel[4
* Sequencer scene functions
* ********************************************************************** */
+struct SequencerToolSettings *SEQ_tool_settings_init(void);
+void SEQ_tool_settings_free(struct SequencerToolSettings *tool_settings);
+eSeqImageFitMethod SEQ_tool_settings_fit_method_get(struct Scene *scene);
+void SEQ_tool_settings_fit_method_set(struct Scene *scene, eSeqImageFitMethod fit_method);
+
+struct SequencerToolSettings *SEQ_tool_settings_copy(struct SequencerToolSettings *tool_settings);
struct Editing *BKE_sequencer_editing_get(struct Scene *scene, bool alloc);
struct Editing *BKE_sequencer_editing_ensure(struct Scene *scene);
void BKE_sequencer_editing_free(struct Scene *scene, const bool do_id_user);
@@ -361,6 +373,20 @@ void BKE_sequence_invalidate_cache_in_range(struct Scene *scene,
void BKE_sequencer_all_free_anim_ibufs(struct Scene *scene, int timeline_frame);
/* **********************************************************************
+ * util.c
+ *
+ * Add strips
+ * **********************************************************************
+ */
+
+void SEQ_set_scale_to_fit(const struct Sequence *seq,
+ const int image_width,
+ const int image_height,
+ const int preview_width,
+ const int preview_height,
+ const eSeqImageFitMethod fit_method);
+
+/* **********************************************************************
* sequencer.c
*
* Add strips
@@ -376,6 +402,7 @@ typedef struct SeqLoadInfo {
int type;
int len; /* only for image strips */
char path[1024]; /* 1024 = FILE_MAX */
+ eSeqImageFitMethod fit_method;
/* multiview */
char views_format;
diff --git a/source/blender/sequencer/intern/render.c b/source/blender/sequencer/intern/render.c
index 155258dc2c3..2e757a06751 100644
--- a/source/blender/sequencer/intern/render.c
+++ b/source/blender/sequencer/intern/render.c
@@ -528,7 +528,6 @@ static void sequencer_image_transform_init(void *handle_v,
handle->ibuf_source = init_data->ibuf_source;
handle->ibuf_out = init_data->ibuf_out;
handle->transform = init_data->transform;
- handle->scale_to_fit = init_data->scale_to_fit;
handle->image_scale_factor = init_data->image_scale_factor;
handle->for_render = init_data->for_render;
@@ -540,8 +539,8 @@ static void *sequencer_image_transform_do_thread(void *data_v)
{
const ImageTransformThreadData *data = (ImageTransformThreadData *)data_v;
const StripTransform *transform = data->transform;
- const float scale_x = transform->scale_x * data->scale_to_fit;
- const float scale_y = transform->scale_y * data->scale_to_fit;
+ const float scale_x = transform->scale_x * data->image_scale_factor;
+ const float scale_y = transform->scale_y * data->image_scale_factor;
const float scale_to_fit_offs_x = (data->ibuf_out->x - data->ibuf_source->x) / 2;
const float scale_to_fit_offs_y = (data->ibuf_out->y - data->ibuf_source->y) / 2;
const float translate_x = transform->xofs * data->image_scale_factor + scale_to_fit_offs_x;
@@ -626,10 +625,6 @@ static ImBuf *input_preprocess(const SeqRenderData *context,
IMB_filtery(preprocessed_ibuf);
}
- /* Calculate scale factor, so image fits in preview area with original aspect ratio. */
- const float scale_to_fit_factor = MIN2((float)context->rectx / (float)ibuf->x,
- (float)context->recty / (float)ibuf->y);
-
/* Get scale factor if preview resolution doesn't match project resolution. */
float preview_scale_factor;
if (context->preview_render_size == SEQ_RENDER_SIZE_SCENE) {
@@ -648,10 +643,10 @@ static ImBuf *input_preprocess(const SeqRenderData *context,
const int height = ibuf->y;
const StripCrop *c = seq->strip->crop;
- const int left = c->left / scale_to_fit_factor * preview_scale_factor;
- const int right = c->right / scale_to_fit_factor * preview_scale_factor;
- const int top = c->top / scale_to_fit_factor * preview_scale_factor;
- const int bottom = c->bottom / scale_to_fit_factor * preview_scale_factor;
+ const int left = c->left;
+ const int right = c->right;
+ const int top = c->top;
+ const int bottom = c->bottom;
const float col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
/* Left. */
@@ -673,7 +668,6 @@ static ImBuf *input_preprocess(const SeqRenderData *context,
init_data.ibuf_source = ibuf;
init_data.ibuf_out = preprocessed_ibuf;
init_data.transform = seq->strip->transform;
- init_data.scale_to_fit = scale_to_fit_factor;
init_data.image_scale_factor = preview_scale_factor;
init_data.for_render = context->for_render;
IMB_processor_apply_threaded(context->recty,
diff --git a/source/blender/sequencer/intern/sequencer.c b/source/blender/sequencer/intern/sequencer.c
index c998886626c..82971a30c31 100644
--- a/source/blender/sequencer/intern/sequencer.c
+++ b/source/blender/sequencer/intern/sequencer.c
@@ -301,6 +301,32 @@ static void seq_new_fix_links_recursive(Sequence *seq)
}
}
}
+
+SequencerToolSettings *SEQ_tool_settings_init(void)
+{
+ SequencerToolSettings *tool_settings = MEM_callocN(sizeof(SequencerToolSettings),
+ "Sequencer tool settings");
+ tool_settings->fit_method = SEQ_SCALE_TO_FIT;
+ return tool_settings;
+}
+
+void SEQ_tool_settings_free(SequencerToolSettings *tool_settings)
+{
+ MEM_freeN(tool_settings);
+}
+
+eSeqImageFitMethod SEQ_tool_settings_fit_method_get(Scene *scene)
+{
+ const SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings;
+ return tool_settings->fit_method;
+}
+
+void SEQ_tool_settings_fit_method_set(Scene *scene, eSeqImageFitMethod fit_method)
+{
+ SequencerToolSettings *tool_settings = scene->toolsettings->sequencer_tool_settings;
+ tool_settings->fit_method = fit_method;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -609,4 +635,11 @@ static void seq_free_animdata(Scene *scene, Sequence *seq)
}
#undef SEQ_RNAPATH_MAXSTR
+
+SequencerToolSettings *SEQ_tool_settings_copy(SequencerToolSettings *tool_settings)
+{
+ SequencerToolSettings *tool_settings_copy = MEM_dupallocN(tool_settings);
+ return tool_settings_copy;
+}
+
/** \} */
diff --git a/source/blender/sequencer/intern/strip_add.c b/source/blender/sequencer/intern/strip_add.c
index d2e4025bdfc..9c9d51e9286 100644
--- a/source/blender/sequencer/intern/strip_add.c
+++ b/source/blender/sequencer/intern/strip_add.c
@@ -118,6 +118,15 @@ Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoad
seq->flag |= seq_load->flag & SEQ_USE_VIEWS;
seq_load_apply(CTX_data_main(C), scene, seq, seq_load);
+
+ char file_path[FILE_MAX];
+ BLI_join_dirfile(file_path, sizeof(file_path), seq_load->path, seq_load->name);
+ ImBuf *ibuf = IMB_loadiffname(file_path, IB_rect, seq->strip->colorspace_settings.name);
+ if (ibuf != NULL) {
+ SEQ_set_scale_to_fit(seq, ibuf->x, ibuf->y, scene->r.xsch, scene->r.ysch, seq_load->fit_method);
+ IMB_freeImBuf(ibuf);
+ }
+
BKE_sequence_invalidate_cache_composite(scene, seq);
return seq;
@@ -275,6 +284,11 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
IMB_anim_load_metadata(anim_arr[0]);
seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
+
+ const float width = IMB_anim_get_image_width(anim_arr[0]);
+ const float height = IMB_anim_get_image_height(anim_arr[0]);
+ SEQ_set_scale_to_fit(seq, width, height, scene->r.xsch, scene->r.ysch, seq_load->fit_method);
+
BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2);
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
diff --git a/source/blender/sequencer/intern/utils.c b/source/blender/sequencer/intern/utils.c
index 2b1d36a7709..ab0b65dba7f 100644
--- a/source/blender/sequencer/intern/utils.c
+++ b/source/blender/sequencer/intern/utils.c
@@ -36,6 +36,7 @@
#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
+#include "BLI_utildefines.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -547,3 +548,36 @@ bool sequencer_seq_generates_image(Sequence *seq)
}
return false;
}
+
+void SEQ_set_scale_to_fit(const Sequence *seq,
+ const int image_width,
+ const int image_height,
+ const int preview_width,
+ const int preview_height,
+ const eSeqImageFitMethod fit_method)
+{
+ StripTransform *transform = seq->strip->transform;
+
+ switch (fit_method) {
+ case SEQ_SCALE_TO_FIT:
+ transform->scale_x = transform->scale_y = MIN2((float)preview_width / (float)image_width,
+ (float)preview_height / (float)image_height);
+
+ break;
+ case SEQ_SCALE_TO_FILL:
+
+ transform->scale_x = transform->scale_y = MAX2((float)preview_width / (float)image_width,
+ (float)preview_height / (float)image_height);
+ break;
+ case SEQ_STRETCH_TO_FILL:
+ transform->scale_x = (float)preview_width / (float)image_width;
+ transform->scale_y = (float)preview_height / (float)image_height;
+ break;
+ case SEQ_USE_ORIGINAL_SIZE:
+ transform->scale_x = 1.0f;
+ transform->scale_y = 1.0f;
+ break;
+ }
+
+ return;
+}