UI Experiment: Image Sequence Collapse #119193
|
@ -101,6 +101,9 @@ struct FileListInternEntry {
|
||||||
const char *name;
|
const char *name;
|
||||||
bool free_name;
|
bool free_name;
|
||||||
|
|
||||||
|
int sequence_start;
|
||||||
|
int sequence_end;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is data from the current main, represented by this file. It's crucial that this is
|
* This is data from the current main, represented by this file. It's crucial that this is
|
||||||
* updated correctly on undo, redo and file reading (without UI). The space is responsible to
|
* updated correctly on undo, redo and file reading (without UI). The space is responsible to
|
||||||
|
@ -686,6 +689,11 @@ static bool is_filtered_hidden(const char *filename,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Let's just reuse this filter setting for image sequences for now. */
|
||||||
|
if ((filter->flags & FLF_HIDE_DOT) && file->sequence_start && !file->sequence_end) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2103,7 +2111,27 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in
|
||||||
|
|
||||||
ret->relpath = BLI_strdup(entry->relpath);
|
ret->relpath = BLI_strdup(entry->relpath);
|
||||||
if (entry->free_name) {
|
if (entry->free_name) {
|
||||||
ret->name = BLI_strdup(entry->name);
|
if ((filelist->filter_data.flags & FLF_HIDE_DOT) && entry->typeflag & FILE_TYPE_IMAGE &&
|
||||||
|
entry->sequence_start && entry->sequence_end &&
|
||||||
|
(entry->sequence_start != entry->sequence_end))
|
||||||
|
{
|
||||||
|
char head[FILE_MAX], tail[FILE_MAX];
|
||||||
|
ushort digits;
|
||||||
|
int num = BLI_path_sequence_decode(
|
||||||
|
entry->relpath, head, sizeof(head), tail, sizeof(tail), &digits);
|
||||||
|
ret->name = BLI_sprintfN("%s%.*s%s (%0*i-%0*i)",
|
||||||
|
head,
|
||||||
|
digits,
|
||||||
|
"####################",
|
||||||
|
tail,
|
||||||
|
digits,
|
||||||
|
entry->sequence_start,
|
||||||
|
digits,
|
||||||
|
entry->sequence_end);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret->name = BLI_strdup(entry->name);
|
||||||
|
}
|
||||||
ret->flags |= FILE_ENTRY_NAME_FREE;
|
ret->flags |= FILE_ENTRY_NAME_FREE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -3060,85 +3088,127 @@ static int filelist_readjob_list_dir(FileListReadJob *job_params,
|
||||||
/* Full path of the item. */
|
/* Full path of the item. */
|
||||||
char full_path[FILE_MAX];
|
char full_path[FILE_MAX];
|
||||||
|
|
||||||
|
FileListInternEntry *entry = nullptr;
|
||||||
|
|
||||||
|
/* Used to find image sequences. */
|
||||||
|
FileListInternEntry *image_sequence_start = nullptr;
|
||||||
|
char seq_head[FILE_MAX] = {0};
|
||||||
|
char seq_tail[FILE_MAX] = {0};
|
||||||
|
ushort seq_digits;
|
||||||
|
|
||||||
const int files_num = BLI_filelist_dir_contents(root, &files);
|
const int files_num = BLI_filelist_dir_contents(root, &files);
|
||||||
if (files) {
|
|
||||||
int i = files_num;
|
|
||||||
while (i--) {
|
|
||||||
FileListInternEntry *entry;
|
|
||||||
|
|
||||||
if (skip_currpar && FILENAME_IS_CURRPAR(files[i].relname)) {
|
for (int i = 0; i < files_num; i++) {
|
||||||
continue;
|
if (skip_currpar && FILENAME_IS_CURRPAR(files[i].relname)) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
entry = MEM_cnew<FileListInternEntry>(__func__);
|
if (skip_currpar && FILENAME_IS_CURRPAR(files[i].relname)) {
|
||||||
entry->relpath = current_relpath_append(job_params, files[i].relname);
|
continue;
|
||||||
entry->st = files[i].s;
|
}
|
||||||
|
|
||||||
BLI_path_join(full_path, FILE_MAX, root, files[i].relname);
|
entry = MEM_cnew<FileListInternEntry>(__func__);
|
||||||
char *target = full_path;
|
entry->relpath = current_relpath_append(job_params, files[i].relname);
|
||||||
|
entry->st = files[i].s;
|
||||||
|
|
||||||
/* Set initial file type and attributes. */
|
BLI_path_join(full_path, FILE_MAX, root, files[i].relname);
|
||||||
entry->attributes = BLI_file_attributes(full_path);
|
char *target = full_path;
|
||||||
if (S_ISDIR(files[i].s.st_mode)
|
|
||||||
|
/* Set initial file type and attributes. */
|
||||||
|
entry->attributes = BLI_file_attributes(full_path);
|
||||||
|
if (S_ISDIR(files[i].s.st_mode)
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
&& !(ED_path_extension_type(full_path) & FILE_TYPE_BUNDLE)
|
&& !(ED_path_extension_type(full_path) & FILE_TYPE_BUNDLE)
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
entry->typeflag = FILE_TYPE_DIR;
|
entry->typeflag = FILE_TYPE_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this a file that points to another file? */
|
/* Is this a file that points to another file? */
|
||||||
if (entry->attributes & FILE_ATTR_ALIAS) {
|
if (entry->attributes & FILE_ATTR_ALIAS) {
|
||||||
entry->redirection_path = MEM_cnew_array<char>(FILE_MAXDIR, __func__);
|
entry->redirection_path = MEM_cnew_array<char>(FILE_MAXDIR, __func__);
|
||||||
if (BLI_file_alias_target(full_path, entry->redirection_path)) {
|
if (BLI_file_alias_target(full_path, entry->redirection_path)) {
|
||||||
if (BLI_is_dir(entry->redirection_path)) {
|
if (BLI_is_dir(entry->redirection_path)) {
|
||||||
entry->typeflag = FILE_TYPE_DIR;
|
entry->typeflag = FILE_TYPE_DIR;
|
||||||
BLI_path_slash_ensure(entry->redirection_path, FILE_MAXDIR);
|
BLI_path_slash_ensure(entry->redirection_path, FILE_MAXDIR);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
entry->typeflag = (eFileSel_File_Types)ED_path_extension_type(entry->redirection_path);
|
entry->typeflag = (eFileSel_File_Types)ED_path_extension_type(entry->redirection_path);
|
||||||
}
|
}
|
||||||
target = entry->redirection_path;
|
target = entry->redirection_path;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
/* On Windows don't show `.lnk` extension for valid shortcuts. */
|
/* On Windows don't show `.lnk` extension for valid shortcuts. */
|
||||||
BLI_path_extension_strip(entry->relpath);
|
BLI_path_extension_strip(entry->relpath);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
else {
|
|
||||||
MEM_freeN(entry->redirection_path);
|
|
||||||
entry->redirection_path = nullptr;
|
|
||||||
entry->attributes |= FILE_ATTR_HIDDEN;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if (!(entry->typeflag & FILE_TYPE_DIR)) {
|
MEM_freeN(entry->redirection_path);
|
||||||
if (do_lib && BKE_blendfile_extension_check(target)) {
|
entry->redirection_path = nullptr;
|
||||||
/* If we are considering .blend files as libraries, promote them to directory status. */
|
|
||||||
entry->typeflag = FILE_TYPE_BLENDER;
|
|
||||||
/* prevent current file being used as acceptable dir */
|
|
||||||
if (BLI_path_cmp(main_filepath, target) != 0) {
|
|
||||||
entry->typeflag |= FILE_TYPE_DIR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
entry->typeflag = (eFileSel_File_Types)ED_path_extension_type(target);
|
|
||||||
if (filter_glob[0] && BLI_path_extension_check_glob(target, filter_glob)) {
|
|
||||||
entry->typeflag |= FILE_TYPE_OPERATOR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
/* Set linux-style dot files hidden too. */
|
|
||||||
if (is_hidden_dot_filename(entry->relpath, entry)) {
|
|
||||||
entry->attributes |= FILE_ATTR_HIDDEN;
|
entry->attributes |= FILE_ATTR_HIDDEN;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(entry->typeflag & FILE_TYPE_DIR)) {
|
||||||
|
if (do_lib && BKE_blendfile_extension_check(target)) {
|
||||||
|
/* If we are considering .blend files as libraries, promote them to directory status. */
|
||||||
|
entry->typeflag = FILE_TYPE_BLENDER;
|
||||||
|
/* prevent current file being used as acceptable dir */
|
||||||
|
if (BLI_path_cmp(main_filepath, target) != 0) {
|
||||||
|
entry->typeflag |= FILE_TYPE_DIR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
entry->typeflag = (eFileSel_File_Types)ED_path_extension_type(target);
|
||||||
|
if (filter_glob[0] && BLI_path_extension_check_glob(target, filter_glob)) {
|
||||||
|
entry->typeflag |= FILE_TYPE_OPERATOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (entry->typeflag & FILE_TYPE_IMAGE) {
|
||||||
|
char head[FILE_MAX], tail[FILE_MAX];
|
||||||
|
ushort digits;
|
||||||
|
int num = BLI_path_sequence_decode(
|
||||||
|
entry->relpath, head, sizeof(head), tail, sizeof(tail), &digits);
|
||||||
|
if (num) {
|
||||||
|
entry->sequence_start = num;
|
||||||
|
if (image_sequence_start && (num == image_sequence_start->sequence_end + 1) &&
|
||||||
|
(digits == seq_digits) && (STREQLEN(head, seq_head, sizeof(head))) &&
|
||||||
|
(STREQLEN(tail, seq_tail, sizeof(tail))))
|
||||||
|
{
|
||||||
|
/* This is a child member of an image sequence. */
|
||||||
|
entry->sequence_end = 0;
|
||||||
|
/* Mark the parent as valid. */
|
||||||
|
image_sequence_start->sequence_end++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* This one might be the start if valid children follow. */
|
||||||
|
image_sequence_start = entry;
|
||||||
|
image_sequence_start->sequence_end = num;
|
||||||
|
seq_digits = digits;
|
||||||
|
STRNCPY(seq_head, head);
|
||||||
|
STRNCPY(seq_tail, tail);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
image_sequence_start = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
/* Set linux-style dot files hidden too. */
|
||||||
|
if (is_hidden_dot_filename(entry->relpath, entry)) {
|
||||||
|
entry->attributes |= FILE_ATTR_HIDDEN;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BLI_addtail(entries, entry);
|
BLI_addtail(entries, entry);
|
||||||
entries_num++;
|
entries_num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (files) {
|
||||||
BLI_filelist_free(files, files_num);
|
BLI_filelist_free(files, files_num);
|
||||||
}
|
}
|
||||||
return entries_num;
|
return entries_num;
|
||||||
|
|
Loading…
Reference in New Issue