Cleanup: split image sequence detection into own file, and make it reusable
This commit is contained in:
parent
4c4e798f35
commit
da38cb622e
|
@ -24,15 +24,21 @@
|
|||
#ifndef __ED_IMAGE_H__
|
||||
#define __ED_IMAGE_H__
|
||||
|
||||
#include "DNA_listBase.h"
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
struct ARegion;
|
||||
struct ImBuf;
|
||||
struct Image;
|
||||
struct ImageUser;
|
||||
struct LinkNodePair;
|
||||
struct Main;
|
||||
struct ReportList;
|
||||
struct Scene;
|
||||
struct SpaceImage;
|
||||
struct ViewLayer;
|
||||
struct bContext;
|
||||
struct wmOperator;
|
||||
struct wmWindowManager;
|
||||
|
||||
/* image_edit.c, exported for transform */
|
||||
|
@ -116,4 +122,24 @@ bool ED_image_should_save_modified(const struct bContext *C);
|
|||
int ED_image_save_all_modified_info(const struct bContext *C, struct ReportList *reports);
|
||||
bool ED_image_save_all_modified(const struct bContext *C, struct ReportList *reports);
|
||||
|
||||
/* image_sequence.c */
|
||||
typedef struct ImageFrameRange {
|
||||
struct ImageFrameRange *next, *prev;
|
||||
|
||||
/** Absolute file path of the first file in the range. */
|
||||
char filepath[FILE_MAX];
|
||||
/* Sequence parameters. */
|
||||
int length;
|
||||
int offset;
|
||||
/* UDIM tiles. */
|
||||
ListBase udim_tiles;
|
||||
|
||||
/* Temporary data. */
|
||||
ListBase frames;
|
||||
} ImageFrameRange;
|
||||
|
||||
ListBase ED_image_filesel_detect_sequences(struct Main *bmain,
|
||||
struct wmOperator *op,
|
||||
const bool detect_udim);
|
||||
|
||||
#endif /* __ED_IMAGE_H__ */
|
||||
|
|
|
@ -43,6 +43,7 @@ set(SRC
|
|||
image_draw.c
|
||||
image_edit.c
|
||||
image_ops.c
|
||||
image_sequence.c
|
||||
image_undo.c
|
||||
space_image.c
|
||||
|
||||
|
|
|
@ -1207,18 +1207,6 @@ typedef struct ImageOpenData {
|
|||
ImageFormatData im_format;
|
||||
} ImageOpenData;
|
||||
|
||||
typedef struct ImageFrameRange {
|
||||
struct ImageFrameRange *next, *prev;
|
||||
ListBase frames;
|
||||
/** The full path of the first file in the list of image files */
|
||||
char filepath[FILE_MAX];
|
||||
} ImageFrameRange;
|
||||
|
||||
typedef struct ImageFrame {
|
||||
struct ImageFrame *next, *prev;
|
||||
int framenr;
|
||||
} ImageFrame;
|
||||
|
||||
static void image_open_init(bContext *C, wmOperator *op)
|
||||
{
|
||||
ImageOpenData *iod;
|
||||
|
@ -1233,179 +1221,18 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
|
|||
op->customdata = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of frames from the list of image files matching the first file name sequence pattern.
|
||||
* \param ptr[in]: The RNA pointer containing the "directory" entry and "files" collection.
|
||||
* \param frames_all[out]: the list of frame numbers found in the files matching
|
||||
* the first one by name.
|
||||
*/
|
||||
static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all)
|
||||
{
|
||||
char dir[FILE_MAXDIR];
|
||||
const bool do_frame_range = RNA_boolean_get(ptr, "use_sequence_detection");
|
||||
ImageFrameRange *frame_range = NULL;
|
||||
|
||||
RNA_string_get(ptr, "directory", dir);
|
||||
RNA_BEGIN (ptr, itemptr, "files") {
|
||||
char base_head[FILE_MAX], base_tail[FILE_MAX];
|
||||
char head[FILE_MAX], tail[FILE_MAX];
|
||||
unsigned short digits;
|
||||
char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
|
||||
ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
|
||||
|
||||
/* use the first file in the list as base filename */
|
||||
frame->framenr = BLI_stringdec(filename, head, tail, &digits);
|
||||
|
||||
/* still in the same sequence */
|
||||
if (do_frame_range && (frame_range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) &&
|
||||
(STREQLEN(base_tail, tail, FILE_MAX))) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
/* start a new frame range */
|
||||
frame_range = MEM_callocN(sizeof(*frame_range), __func__);
|
||||
BLI_join_dirfile(frame_range->filepath, sizeof(frame_range->filepath), dir, filename);
|
||||
BLI_addtail(frames_all, frame_range);
|
||||
|
||||
BLI_strncpy(base_head, head, sizeof(base_head));
|
||||
BLI_strncpy(base_tail, tail, sizeof(base_tail));
|
||||
}
|
||||
|
||||
BLI_addtail(&frame_range->frames, frame);
|
||||
MEM_freeN(filename);
|
||||
}
|
||||
RNA_END;
|
||||
}
|
||||
|
||||
static int image_cmp_frame(const void *a, const void *b)
|
||||
{
|
||||
const ImageFrame *frame_a = a;
|
||||
const ImageFrame *frame_b = b;
|
||||
|
||||
if (frame_a->framenr < frame_b->framenr) {
|
||||
return -1;
|
||||
}
|
||||
if (frame_a->framenr > frame_b->framenr) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Checks whether the given filepath refers to a UDIM texture.
|
||||
* If yes, the range from 1001 to the highest tile is returned, otherwise 0.
|
||||
*
|
||||
* If the result is positive, the filepath will be overwritten with that of
|
||||
* the 1001 tile.
|
||||
* udim_tiles may get filled even if the result ultimately is false! */
|
||||
static int image_get_udim(char *filepath, LinkNodePair *udim_tiles)
|
||||
{
|
||||
char filename[FILE_MAX], dirname[FILE_MAXDIR];
|
||||
BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
|
||||
|
||||
unsigned short digits;
|
||||
char base_head[FILE_MAX], base_tail[FILE_MAX];
|
||||
int id = BLI_stringdec(filename, base_head, base_tail, &digits);
|
||||
|
||||
if (id < 1001 || id >= IMA_UDIM_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_udim = true;
|
||||
bool has_primary = false;
|
||||
int max_udim = 0;
|
||||
|
||||
struct direntry *dir;
|
||||
uint totfile = BLI_filelist_dir_contents(dirname, &dir);
|
||||
for (int i = 0; i < totfile; i++) {
|
||||
if (!(dir[i].type & S_IFREG)) {
|
||||
continue;
|
||||
}
|
||||
char head[FILE_MAX], tail[FILE_MAX];
|
||||
id = BLI_stringdec(dir[i].relname, head, tail, &digits);
|
||||
|
||||
if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) ||
|
||||
!(STREQLEN(base_tail, tail, FILE_MAX))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id < 1001 || id >= IMA_UDIM_MAX) {
|
||||
is_udim = false;
|
||||
break;
|
||||
}
|
||||
if (id == 1001) {
|
||||
has_primary = true;
|
||||
}
|
||||
|
||||
BLI_linklist_append(udim_tiles, POINTER_FROM_INT(id));
|
||||
max_udim = max_ii(max_udim, id);
|
||||
}
|
||||
BLI_filelist_free(dir, totfile);
|
||||
|
||||
if (is_udim && has_primary) {
|
||||
char primary_filename[FILE_MAX];
|
||||
BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001);
|
||||
BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename);
|
||||
return max_udim - 1000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the start (offset) and the length of the sequence of
|
||||
* continuous frames in the list of frames.
|
||||
*
|
||||
* \param frames: [in] the list of frame numbers, as a side-effect the list is sorted.
|
||||
* \param ofs: [out] offset the first frame number in the sequence.
|
||||
* \return the number of contiguous frames in the sequence
|
||||
*/
|
||||
static int image_sequence_get_len(ImageFrameRange *frame_range,
|
||||
int *ofs,
|
||||
char *filepath_range,
|
||||
LinkNodePair *udim_tiles)
|
||||
{
|
||||
ImageFrame *frame;
|
||||
|
||||
BLI_listbase_sort(&frame_range->frames, image_cmp_frame);
|
||||
BLI_strncpy(filepath_range, frame_range->filepath, FILE_MAX);
|
||||
|
||||
frame = frame_range->frames.first;
|
||||
if (frame != NULL) {
|
||||
int frame_curr = frame->framenr;
|
||||
(*ofs) = frame_curr;
|
||||
|
||||
if (udim_tiles != NULL) {
|
||||
int len_udim = image_get_udim(filepath_range, udim_tiles);
|
||||
if (len_udim > 0) {
|
||||
*ofs = 1001;
|
||||
return len_udim;
|
||||
}
|
||||
}
|
||||
|
||||
while (frame != NULL && (frame->framenr == frame_curr)) {
|
||||
frame_curr++;
|
||||
frame = frame->next;
|
||||
}
|
||||
return frame_curr - (*ofs);
|
||||
}
|
||||
*ofs = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Image *image_open_single(Main *bmain,
|
||||
wmOperator *op,
|
||||
const char *filepath,
|
||||
ImageFrameRange *range,
|
||||
const char *relbase,
|
||||
bool is_relative_path,
|
||||
bool use_multiview,
|
||||
int frame_seq_len,
|
||||
int frame_seq_ofs,
|
||||
LinkNodePair *udim_tiles)
|
||||
bool use_multiview)
|
||||
{
|
||||
bool exists = false;
|
||||
Image *ima = NULL;
|
||||
|
||||
errno = 0;
|
||||
ima = BKE_image_load_exists_ex(bmain, filepath, &exists);
|
||||
ima = BKE_image_load_exists_ex(bmain, range->filepath, &exists);
|
||||
|
||||
if (!ima) {
|
||||
if (op->customdata) {
|
||||
|
@ -1414,7 +1241,7 @@ static Image *image_open_single(Main *bmain,
|
|||
BKE_reportf(op->reports,
|
||||
RPT_ERROR,
|
||||
"Cannot read '%s': %s",
|
||||
filepath,
|
||||
range->filepath,
|
||||
errno ? strerror(errno) : TIP_("unsupported image format"));
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1439,11 +1266,11 @@ static Image *image_open_single(Main *bmain,
|
|||
BKE_image_free_views(ima);
|
||||
}
|
||||
|
||||
if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
|
||||
if (udim_tiles && frame_seq_ofs == 1001) {
|
||||
if ((range->length > 1) && (ima->source == IMA_SRC_FILE)) {
|
||||
if (range->udim_tiles.first && range->offset == 1001) {
|
||||
ima->source = IMA_SRC_TILED;
|
||||
for (LinkNode *node = udim_tiles->list; node; node = node->next) {
|
||||
BKE_image_add_tile(ima, POINTER_AS_INT(node->link), NULL);
|
||||
for (LinkData *node = range->udim_tiles.first; node; node = node->next) {
|
||||
BKE_image_add_tile(ima, POINTER_AS_INT(node->data), NULL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1464,7 +1291,6 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
|||
ImageUser *iuser = NULL;
|
||||
ImageOpenData *iod = op->customdata;
|
||||
Image *ima = NULL;
|
||||
char filepath[FILE_MAX];
|
||||
int frame_seq_len = 0;
|
||||
int frame_ofs = 1;
|
||||
|
||||
|
@ -1476,83 +1302,21 @@ static int image_open_exec(bContext *C, wmOperator *op)
|
|||
image_open_init(C, op);
|
||||
}
|
||||
|
||||
RNA_string_get(op->ptr, "filepath", filepath);
|
||||
ListBase ranges = ED_image_filesel_detect_sequences(bmain, op, use_udim);
|
||||
for (ImageFrameRange *range = ranges.first; range; range = range->next) {
|
||||
Image *ima_range = image_open_single(
|
||||
bmain, op, range, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview);
|
||||
|
||||
if (RNA_struct_property_is_set(op->ptr, "directory") &&
|
||||
RNA_struct_property_is_set(op->ptr, "files")) {
|
||||
bool was_relative = BLI_path_is_rel(filepath);
|
||||
ListBase frame_ranges_all;
|
||||
|
||||
BLI_listbase_clear(&frame_ranges_all);
|
||||
image_sequence_get_frame_ranges(op->ptr, &frame_ranges_all);
|
||||
for (ImageFrameRange *frame_range = frame_ranges_all.first; frame_range;
|
||||
frame_range = frame_range->next) {
|
||||
int frame_range_ofs;
|
||||
|
||||
LinkNodePair udim_tiles = {NULL};
|
||||
LinkNodePair *udim_tiles_ptr = use_udim ? (&udim_tiles) : NULL;
|
||||
|
||||
char filepath_range[FILE_MAX];
|
||||
int frame_range_seq_len = image_sequence_get_len(
|
||||
frame_range, &frame_range_ofs, filepath_range, udim_tiles_ptr);
|
||||
BLI_freelistN(&frame_range->frames);
|
||||
|
||||
if (was_relative) {
|
||||
BLI_path_rel(filepath_range, BKE_main_blendfile_path(bmain));
|
||||
}
|
||||
|
||||
Image *ima_range = image_open_single(bmain,
|
||||
op,
|
||||
filepath_range,
|
||||
BKE_main_blendfile_path(bmain),
|
||||
is_relative_path,
|
||||
use_multiview,
|
||||
frame_range_seq_len,
|
||||
frame_range_ofs,
|
||||
udim_tiles_ptr);
|
||||
|
||||
/* take the first image */
|
||||
if ((ima == NULL) && ima_range) {
|
||||
ima = ima_range;
|
||||
frame_seq_len = frame_range_seq_len;
|
||||
frame_ofs = frame_range_ofs;
|
||||
}
|
||||
|
||||
BLI_linklist_free(udim_tiles.list, NULL);
|
||||
}
|
||||
BLI_freelistN(&frame_ranges_all);
|
||||
}
|
||||
else {
|
||||
/* for drag & drop etc. */
|
||||
|
||||
LinkNodePair udim_tiles = {NULL};
|
||||
frame_seq_len = 1;
|
||||
char filepath_range[FILE_MAX];
|
||||
BLI_strncpy(filepath_range, filepath, FILE_MAX);
|
||||
|
||||
if (use_udim > 0) {
|
||||
/* Try to find UDIM tiles corresponding to the image */
|
||||
int udim_len = image_get_udim(filepath_range, &udim_tiles);
|
||||
|
||||
/* If we found something, mark the image as tiled. */
|
||||
if (udim_len) {
|
||||
frame_seq_len = udim_len;
|
||||
frame_ofs = 1001;
|
||||
}
|
||||
/* take the first image */
|
||||
if ((ima == NULL) && ima_range) {
|
||||
ima = ima_range;
|
||||
frame_seq_len = range->length;
|
||||
frame_ofs = range->offset;
|
||||
}
|
||||
|
||||
ima = image_open_single(bmain,
|
||||
op,
|
||||
filepath_range,
|
||||
BKE_main_blendfile_path(bmain),
|
||||
is_relative_path,
|
||||
use_multiview,
|
||||
frame_seq_len,
|
||||
frame_ofs,
|
||||
&udim_tiles);
|
||||
|
||||
BLI_linklist_free(udim_tiles.list, NULL);
|
||||
BLI_freelistN(&range->udim_tiles);
|
||||
}
|
||||
BLI_freelistN(&ranges);
|
||||
|
||||
if (ima == NULL) {
|
||||
return OPERATOR_CANCELLED;
|
||||
|
|
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* 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) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup spimage
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_fileops_types.h"
|
||||
#include "BLI_linklist.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_path_util.h"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "DNA_image_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
#include "DNA_windowmanager_types.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
|
||||
#include "BKE_image.h"
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "ED_image.h"
|
||||
|
||||
#include "WM_types.h"
|
||||
|
||||
typedef struct ImageFrame {
|
||||
struct ImageFrame *next, *prev;
|
||||
int framenr;
|
||||
} ImageFrame;
|
||||
|
||||
/**
|
||||
* Get a list of frames from the list of image files matching the first file
|
||||
* name sequence pattern. The files and directory are read from standard
|
||||
* fileselect operator properties.
|
||||
*
|
||||
* The output is a list of frame ranges, each containg a list of frames with
|
||||
* matching names.
|
||||
*/
|
||||
static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges)
|
||||
{
|
||||
char dir[FILE_MAXDIR];
|
||||
const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection");
|
||||
ImageFrameRange *range = NULL;
|
||||
|
||||
RNA_string_get(op->ptr, "directory", dir);
|
||||
RNA_BEGIN (op->ptr, itemptr, "files") {
|
||||
char base_head[FILE_MAX], base_tail[FILE_MAX];
|
||||
char head[FILE_MAX], tail[FILE_MAX];
|
||||
unsigned short digits;
|
||||
char *filename = RNA_string_get_alloc(&itemptr, "name", NULL, 0);
|
||||
ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame");
|
||||
|
||||
/* use the first file in the list as base filename */
|
||||
frame->framenr = BLI_stringdec(filename, head, tail, &digits);
|
||||
|
||||
/* still in the same sequence */
|
||||
if (do_frame_range && (range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) &&
|
||||
(STREQLEN(base_tail, tail, FILE_MAX))) {
|
||||
/* pass */
|
||||
}
|
||||
else {
|
||||
/* start a new frame range */
|
||||
range = MEM_callocN(sizeof(*range), __func__);
|
||||
BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename);
|
||||
BLI_addtail(ranges, range);
|
||||
|
||||
BLI_strncpy(base_head, head, sizeof(base_head));
|
||||
BLI_strncpy(base_tail, tail, sizeof(base_tail));
|
||||
}
|
||||
|
||||
BLI_addtail(&range->frames, frame);
|
||||
MEM_freeN(filename);
|
||||
}
|
||||
RNA_END;
|
||||
}
|
||||
|
||||
static int image_cmp_frame(const void *a, const void *b)
|
||||
{
|
||||
const ImageFrame *frame_a = a;
|
||||
const ImageFrame *frame_b = b;
|
||||
|
||||
if (frame_a->framenr < frame_b->framenr) {
|
||||
return -1;
|
||||
}
|
||||
if (frame_a->framenr > frame_b->framenr) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether the given filepath refers to a UDIM texture.
|
||||
* If yes, the range from 1001 to the highest tile is returned, otherwise 0.
|
||||
*
|
||||
* If the result is positive, the filepath will be overwritten with that of
|
||||
* the 1001 tile.
|
||||
*
|
||||
* udim_tiles may get filled even if the result ultimately is false!
|
||||
*/
|
||||
static int image_get_udim(char *filepath, ListBase *udim_tiles)
|
||||
{
|
||||
char filename[FILE_MAX], dirname[FILE_MAXDIR];
|
||||
BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
|
||||
|
||||
unsigned short digits;
|
||||
char base_head[FILE_MAX], base_tail[FILE_MAX];
|
||||
int id = BLI_stringdec(filename, base_head, base_tail, &digits);
|
||||
|
||||
if (id < 1001 || id >= IMA_UDIM_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool is_udim = true;
|
||||
bool has_primary = false;
|
||||
int max_udim = 0;
|
||||
|
||||
struct direntry *dir;
|
||||
uint totfile = BLI_filelist_dir_contents(dirname, &dir);
|
||||
for (int i = 0; i < totfile; i++) {
|
||||
if (!(dir[i].type & S_IFREG)) {
|
||||
continue;
|
||||
}
|
||||
char head[FILE_MAX], tail[FILE_MAX];
|
||||
id = BLI_stringdec(dir[i].relname, head, tail, &digits);
|
||||
|
||||
if (digits > 4 || !(STREQLEN(base_head, head, FILE_MAX)) ||
|
||||
!(STREQLEN(base_tail, tail, FILE_MAX))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (id < 1001 || id >= IMA_UDIM_MAX) {
|
||||
is_udim = false;
|
||||
break;
|
||||
}
|
||||
if (id == 1001) {
|
||||
has_primary = true;
|
||||
}
|
||||
|
||||
BLI_addtail(udim_tiles, BLI_genericNodeN(POINTER_FROM_INT(id)));
|
||||
max_udim = max_ii(max_udim, id);
|
||||
}
|
||||
BLI_filelist_free(dir, totfile);
|
||||
|
||||
if (is_udim && has_primary) {
|
||||
char primary_filename[FILE_MAX];
|
||||
BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001);
|
||||
BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename);
|
||||
return max_udim - 1000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* From a list of frames, compute the start (offset) and length of the sequence
|
||||
* of contiguous frames. If UDIM is detect, it will return UDIM tiles as well.
|
||||
*/
|
||||
static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim)
|
||||
{
|
||||
/* UDIM */
|
||||
if (detect_udim) {
|
||||
int len_udim = image_get_udim(range->filepath, &range->udim_tiles);
|
||||
|
||||
if (len_udim > 0) {
|
||||
range->offset = 1001;
|
||||
range->length = len_udim;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Image Sequence */
|
||||
BLI_listbase_sort(&range->frames, image_cmp_frame);
|
||||
|
||||
ImageFrame *frame = range->frames.first;
|
||||
if (frame != NULL) {
|
||||
int frame_curr = frame->framenr;
|
||||
range->offset = frame_curr;
|
||||
|
||||
while (frame != NULL && (frame->framenr == frame_curr)) {
|
||||
frame_curr++;
|
||||
frame = frame->next;
|
||||
}
|
||||
|
||||
range->length = frame_curr - range->offset;
|
||||
}
|
||||
else {
|
||||
range->length = 1;
|
||||
range->offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Used for both images and volume file loading. */
|
||||
ListBase ED_image_filesel_detect_sequences(Main *bmain, wmOperator *op, const bool detect_udim)
|
||||
{
|
||||
ListBase ranges;
|
||||
BLI_listbase_clear(&ranges);
|
||||
|
||||
char filepath[FILE_MAX];
|
||||
RNA_string_get(op->ptr, "filepath", filepath);
|
||||
|
||||
/* File browser. */
|
||||
if (RNA_struct_property_is_set(op->ptr, "directory") &&
|
||||
RNA_struct_property_is_set(op->ptr, "files")) {
|
||||
const bool was_relative = BLI_path_is_rel(filepath);
|
||||
|
||||
image_sequence_get_frame_ranges(op, &ranges);
|
||||
for (ImageFrameRange *range = ranges.first; range; range = range->next) {
|
||||
image_detect_frame_range(range, detect_udim);
|
||||
BLI_freelistN(&range->frames);
|
||||
|
||||
if (was_relative) {
|
||||
BLI_path_rel(range->filepath, BKE_main_blendfile_path(bmain));
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Filepath property for drag & drop etc. */
|
||||
else {
|
||||
ImageFrameRange *range = MEM_callocN(sizeof(*range), __func__);
|
||||
BLI_addtail(&ranges, range);
|
||||
|
||||
BLI_strncpy(range->filepath, filepath, FILE_MAX);
|
||||
image_detect_frame_range(range, detect_udim);
|
||||
}
|
||||
|
||||
return ranges;
|
||||
}
|
Loading…
Reference in New Issue