New "use placeholders" feature of the sequencer did not detect correct
filenames. Added BLI_path utility functions to decompose a path name and extract the frame number. It should be useful in autocollapse feature as well
This commit is contained in:
@@ -132,6 +132,8 @@ bool BLI_parent_dir(char *path) ATTR_NONNULL();
|
|||||||
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL();
|
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL();
|
||||||
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL();
|
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL();
|
||||||
bool BLI_path_frame_range(char *path, int sta, int end, int digits) ATTR_NONNULL();
|
bool BLI_path_frame_range(char *path, int sta, int end, int digits) ATTR_NONNULL();
|
||||||
|
bool BLI_path_frame_get(char *path, int *r_frame, int *numdigits) ATTR_NONNULL();
|
||||||
|
void BLI_path_frame_strip(char *path, bool setsharp, char *ext) ATTR_NONNULL();
|
||||||
bool BLI_path_frame_check_chars(const char *path) ATTR_NONNULL();
|
bool BLI_path_frame_check_chars(const char *path) ATTR_NONNULL();
|
||||||
bool BLI_path_cwd(char *path) ATTR_NONNULL();
|
bool BLI_path_cwd(char *path) ATTR_NONNULL();
|
||||||
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL();
|
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL();
|
||||||
|
@@ -858,6 +858,111 @@ bool BLI_path_frame_range(char *path, int sta, int end, int digits)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the frame from a filename formatted by blender's frame scheme
|
||||||
|
*/
|
||||||
|
bool BLI_path_frame_get(char *path, int *r_frame, int *r_numdigits)
|
||||||
|
{
|
||||||
|
if (path && *path) {
|
||||||
|
char *file = (char *)BLI_last_slash(path);
|
||||||
|
char *c;
|
||||||
|
int len, numdigits;
|
||||||
|
|
||||||
|
numdigits = *r_numdigits = 0;
|
||||||
|
|
||||||
|
if (file == NULL)
|
||||||
|
file = path;
|
||||||
|
|
||||||
|
/* first get the extension part */
|
||||||
|
len = strlen(file);
|
||||||
|
|
||||||
|
c = file + len;
|
||||||
|
|
||||||
|
/* isolate extension */
|
||||||
|
while (--c != file) {
|
||||||
|
if (*c == '.') {
|
||||||
|
c--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find start of number */
|
||||||
|
while (c != (file - 1) && isdigit(*c)) {
|
||||||
|
c--;
|
||||||
|
numdigits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numdigits) {
|
||||||
|
char prevchar;
|
||||||
|
|
||||||
|
c++;
|
||||||
|
prevchar = c[numdigits];
|
||||||
|
c[numdigits] = 0;
|
||||||
|
|
||||||
|
/* was the number really an extension? */
|
||||||
|
*r_frame = atoi(c);
|
||||||
|
c[numdigits] = prevchar;
|
||||||
|
|
||||||
|
*r_numdigits = numdigits;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BLI_path_frame_strip(char *path, bool setsharp, char *ext)
|
||||||
|
{
|
||||||
|
if (path && *path) {
|
||||||
|
char *file = (char *)BLI_last_slash(path);
|
||||||
|
char *c, *suffix;
|
||||||
|
int len;
|
||||||
|
int numdigits = 0;
|
||||||
|
|
||||||
|
if (file == NULL)
|
||||||
|
file = path;
|
||||||
|
|
||||||
|
/* first get the extension part */
|
||||||
|
len = strlen(file);
|
||||||
|
|
||||||
|
c = file + len;
|
||||||
|
|
||||||
|
/* isolate extension */
|
||||||
|
while (--c != file) {
|
||||||
|
if (*c == '.') {
|
||||||
|
c--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suffix = c + 1;
|
||||||
|
|
||||||
|
/* find start of number */
|
||||||
|
while (c != (file - 1) && isdigit(*c)) {
|
||||||
|
c--;
|
||||||
|
numdigits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
c++;
|
||||||
|
|
||||||
|
if(numdigits) {
|
||||||
|
/* replace the number with the suffix and terminate the string */
|
||||||
|
while (numdigits--) {
|
||||||
|
if (ext) *ext++ = *suffix;
|
||||||
|
|
||||||
|
if (setsharp) *c++ = '#';
|
||||||
|
else *c++ = *suffix;
|
||||||
|
|
||||||
|
suffix++;
|
||||||
|
}
|
||||||
|
*c = 0;
|
||||||
|
if (ext) *ext = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range
|
* Check if we have '#' chars, usable for #BLI_path_frame, #BLI_path_frame_range
|
||||||
*/
|
*/
|
||||||
|
@@ -752,33 +752,20 @@ void SEQUENCER_OT_sound_strip_add(struct wmOperatorType *ot)
|
|||||||
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
|
RNA_def_boolean(ot->srna, "cache", false, "Cache", "Cache the sound in memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe)
|
int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minframe, int *r_numdigits)
|
||||||
{
|
{
|
||||||
int minframe = INT32_MAX, maxframe = INT32_MIN;
|
int minframe = INT32_MAX, maxframe = INT32_MIN;
|
||||||
|
int numdigits = 0;
|
||||||
|
|
||||||
RNA_BEGIN (op->ptr, itemptr, "files")
|
RNA_BEGIN (op->ptr, itemptr, "files")
|
||||||
{
|
{
|
||||||
char *filename = NULL, *filename_stripped;
|
char *filename;
|
||||||
int frame;
|
int frame;
|
||||||
/* just get the first filename */
|
/* just get the first filename */
|
||||||
filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
|
filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
|
||||||
|
|
||||||
if (filename) {
|
if (filename) {
|
||||||
bool is_numeric;
|
if (BLI_path_frame_get(filename, &frame, &numdigits)) {
|
||||||
|
|
||||||
filename_stripped = filename;
|
|
||||||
|
|
||||||
/* strip numeric extensions */
|
|
||||||
while (*filename_stripped && isdigit(*filename_stripped)) {
|
|
||||||
filename_stripped++;
|
|
||||||
}
|
|
||||||
|
|
||||||
is_numeric = (filename_stripped != filename && *filename_stripped == '.');
|
|
||||||
|
|
||||||
if (is_numeric) {
|
|
||||||
/* was the number really an extension? */
|
|
||||||
*filename_stripped = 0;
|
|
||||||
frame = atoi(filename);
|
|
||||||
minframe = min_ii(minframe, frame);
|
minframe = min_ii(minframe, frame);
|
||||||
maxframe = max_ii(maxframe, frame);
|
maxframe = max_ii(maxframe, frame);
|
||||||
}
|
}
|
||||||
@@ -794,14 +781,15 @@ int sequencer_image_seq_get_minmax_frame(wmOperator *op, int sfra, int *r_minfra
|
|||||||
}
|
}
|
||||||
|
|
||||||
*r_minframe = minframe;
|
*r_minframe = minframe;
|
||||||
|
*r_numdigits = numdigits;
|
||||||
|
|
||||||
return maxframe - minframe + 1;
|
return maxframe - minframe + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe)
|
void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len, int minframe, int numdigits)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char *filename = NULL, *filename_stripped;
|
char *filename = NULL;
|
||||||
RNA_BEGIN (op->ptr, itemptr, "files")
|
RNA_BEGIN (op->ptr, itemptr, "files")
|
||||||
{
|
{
|
||||||
/* just get the first filename */
|
/* just get the first filename */
|
||||||
@@ -810,26 +798,16 @@ void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len,
|
|||||||
}
|
}
|
||||||
RNA_END;
|
RNA_END;
|
||||||
|
|
||||||
filename_stripped = filename;
|
if (filename) {
|
||||||
|
char ext[PATH_MAX];
|
||||||
if (filename_stripped) {
|
char filename_stripped[PATH_MAX];
|
||||||
int numlen = 0;
|
/* strip the frame from filename and substitute with # */
|
||||||
|
BLI_path_frame_strip(filename, true, ext);
|
||||||
/* strip numeric extensions */
|
|
||||||
while (*filename_stripped && isdigit(*filename_stripped)) {
|
|
||||||
filename_stripped++;
|
|
||||||
numlen++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* was the number really an extension? */
|
|
||||||
if (*filename_stripped == '.')
|
|
||||||
filename_stripped++;
|
|
||||||
else {
|
|
||||||
filename_stripped = filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++, se++) {
|
for (i = 0; i < len; i++, se++) {
|
||||||
BLI_snprintf(se->name, sizeof(se->name), "%0*d.%s", numlen, minframe + i, filename_stripped);
|
BLI_strncpy(filename_stripped, filename, sizeof(filename_stripped));
|
||||||
|
BLI_path_frame(filename_stripped, minframe + i, numdigits);
|
||||||
|
BLI_snprintf(se->name, sizeof(se->name), "%s%s", filename_stripped, ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_freeN(filename);
|
MEM_freeN(filename);
|
||||||
@@ -840,7 +818,7 @@ void sequencer_image_seq_reserve_frames(wmOperator *op, StripElem *se, int len,
|
|||||||
/* add image operator */
|
/* add image operator */
|
||||||
static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
|
static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
int minframe;
|
int minframe, numdigits;
|
||||||
/* cant use the generic function for this */
|
/* cant use the generic function for this */
|
||||||
Scene *scene = CTX_data_scene(C); /* only for sound */
|
Scene *scene = CTX_data_scene(C); /* only for sound */
|
||||||
Editing *ed = BKE_sequencer_editing_get(scene, true);
|
Editing *ed = BKE_sequencer_editing_get(scene, true);
|
||||||
@@ -855,7 +833,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
/* images are unique in how they handle this - 1 per strip elem */
|
/* images are unique in how they handle this - 1 per strip elem */
|
||||||
if (use_placeholders) {
|
if (use_placeholders) {
|
||||||
seq_load.len = sequencer_image_seq_get_minmax_frame(op, seq_load.start_frame, &minframe);
|
seq_load.len = sequencer_image_seq_get_minmax_frame(op, seq_load.start_frame, &minframe, &numdigits);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
|
seq_load.len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
|
||||||
@@ -873,7 +851,7 @@ static int sequencer_add_image_strip_exec(bContext *C, wmOperator *op)
|
|||||||
se = strip->stripdata;
|
se = strip->stripdata;
|
||||||
|
|
||||||
if (use_placeholders) {
|
if (use_placeholders) {
|
||||||
sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe);
|
sequencer_image_seq_reserve_frames(op, se, seq_load.len, minframe, numdigits);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RNA_BEGIN (op->ptr, itemptr, "files")
|
RNA_BEGIN (op->ptr, itemptr, "files")
|
||||||
|
@@ -3695,7 +3695,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
|
|||||||
Sequence *seq = BKE_sequencer_active_get(scene);
|
Sequence *seq = BKE_sequencer_active_get(scene);
|
||||||
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
|
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
|
||||||
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
|
const bool use_placeholders = RNA_boolean_get(op->ptr, "use_placeholders");
|
||||||
int minframe;
|
int minframe, numdigits;
|
||||||
|
|
||||||
if (seq->type == SEQ_TYPE_IMAGE) {
|
if (seq->type == SEQ_TYPE_IMAGE) {
|
||||||
char directory[FILE_MAX];
|
char directory[FILE_MAX];
|
||||||
@@ -3704,7 +3704,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
/* need to find min/max frame for placeholders */
|
/* need to find min/max frame for placeholders */
|
||||||
if (use_placeholders) {
|
if (use_placeholders) {
|
||||||
len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe);
|
len = sequencer_image_seq_get_minmax_frame(op, seq->sfra, &minframe, &numdigits);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
|
len = RNA_property_collection_length(op->ptr, RNA_struct_find_property(op->ptr, "files"));
|
||||||
@@ -3727,7 +3727,7 @@ static int sequencer_change_path_exec(bContext *C, wmOperator *op)
|
|||||||
seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem");
|
seq->strip->stripdata = se = MEM_callocN(len * sizeof(StripElem), "stripelem");
|
||||||
|
|
||||||
if (use_placeholders) {
|
if (use_placeholders) {
|
||||||
sequencer_image_seq_reserve_frames(op, se, len, minframe);
|
sequencer_image_seq_reserve_frames(op, se, len, minframe, numdigits);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
RNA_BEGIN (op->ptr, itemptr, "files")
|
RNA_BEGIN (op->ptr, itemptr, "files")
|
||||||
|
@@ -205,8 +205,8 @@ void SEQUENCER_OT_sample(struct wmOperatorType *ot);
|
|||||||
void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
|
void sequencer_preview_add_sound(const struct bContext *C, struct Sequence *seq);
|
||||||
|
|
||||||
/* sequencer_add */
|
/* sequencer_add */
|
||||||
int sequencer_image_seq_get_minmax_frame(struct wmOperator *op, int sfra, int *r_minframe);
|
int sequencer_image_seq_get_minmax_frame(struct wmOperator *op, int sfra, int *r_minframe, int *r_numdigits);
|
||||||
void sequencer_image_seq_reserve_frames(struct wmOperator *op, struct StripElem *se, int len, int minframe);
|
void sequencer_image_seq_reserve_frames(struct wmOperator *op, struct StripElem *se, int len, int minframe, int numdigits);
|
||||||
|
|
||||||
#endif /* __SEQUENCER_INTERN_H__ */
|
#endif /* __SEQUENCER_INTERN_H__ */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user