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:
authorAndrea Weikert <elubie@gmx.net>2014-01-20 21:54:03 +0400
committerAndrea Weikert <elubie@gmx.net>2014-01-20 22:13:21 +0400
commit04f81c8225f28ba9722cc06dc7f2d8a4d72a3fa3 (patch)
tree8be3afae34e9682dc5a7014454712ca93e89b56f /source/blender/editors/space_image
parent4c6a72a7d8102b93307c13eedd81ecf0c6051d8b (diff)
Fix T37481: Image Sequence can't be loaded
Allow loading of image sequences in addition to single images in the open image operator I solved it by adding the possibility to load an image sequence in the Load Image Operator. The image user is passed in the operator customdata now as well, best solution for now, but general handling of image user still a bit weak. The offset and length of the image sequence is now calculated in the image open operator by storing all found frames in a list and sorting this list. Reviewed By: campbellbarton, brecht, lukastoenne Differential Revision: https://developer.blender.org/D209
Diffstat (limited to 'source/blender/editors/space_image')
-rw-r--r--source/blender/editors/space_image/image_ops.c153
1 files changed, 133 insertions, 20 deletions
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index c2046e6b48e..b4d98b0d829 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -915,12 +915,23 @@ static void image_filesel(bContext *C, wmOperator *op, const char *path)
/******************** open image operator ********************/
+typedef struct ImageOpenData {
+ PropertyPointerRNA pprop;
+ ImageUser *iuser;
+} ImageOpenData;
+
+typedef struct ImageFrame {
+ struct ImageFrame *next, *prev;
+ int framenr;
+} ImageFrame;
+
static void image_open_init(bContext *C, wmOperator *op)
{
- PropertyPointerRNA *pprop;
+ ImageOpenData *iod;
- op->customdata = pprop = MEM_callocN(sizeof(PropertyPointerRNA), "OpenPropertyPointerRNA");
- uiIDContextProperty(C, &pprop->ptr, &pprop->prop);
+ op->customdata = iod = MEM_callocN(sizeof(ImageOpenData), __func__);
+ iod->iuser = CTX_data_pointer_get_type(C, "image_user", &RNA_ImageUser).data;
+ uiIDContextProperty(C, &iod->pprop.ptr, &iod->pprop.prop);
}
static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
@@ -929,45 +940,145 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op)
op->customdata = NULL;
}
+/**
+ * @brief 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 [out] the list of frame numbers found in the files matching the first one by name
+ * @param path [out] the full path of the first file in the list of image files
+ */
+static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *path, const size_t maxlen)
+{
+ char dir[FILE_MAXDIR];
+ bool is_first_entry = true;
+
+ 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 */
+ if (is_first_entry) {
+ BLI_join_dirfile(path, maxlen, dir, filename);
+ frame->framenr = BLI_stringdec(filename, base_head, base_tail, &digits);
+ BLI_addtail(frames, frame);
+ is_first_entry = false;
+ }
+ else {
+ frame->framenr = BLI_stringdec(filename, head, tail, &digits);
+
+ /* still in the same sequence */
+ if ((STREQLEN(base_head, head, FILE_MAX)) &&
+ (STREQLEN(base_tail, tail, FILE_MAX)))
+ {
+ BLI_addtail(frames, frame);
+ }
+ else {
+ /* different file base name found, is ignored */
+ MEM_freeN(frame);
+ break;
+ }
+ }
+
+ MEM_freeN(filename);
+ }
+ RNA_END
+}
+
+static int image_cmp_frame(void *a, void *b)
+{
+ ImageFrame *frame_a = (ImageFrame *)a;
+ ImageFrame *frame_b = (ImageFrame *)b;
+
+ if (frame_a->framenr < frame_b->framenr) return -1;
+ if (frame_a->framenr > frame_b->framenr) return 1;
+ return 0;
+}
+
+/**
+ * @brief 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] offest, the first frame number in the sequence
+ * @return the number of continuos frames in the sequence
+ */
+static int image_sequence_get_len(ListBase *frames, int *ofs)
+{
+ ImageFrame *frame;
+
+ BLI_sortlist(frames, image_cmp_frame);
+
+ frame = frames->first;
+ if (frame) {
+ int frame_curr = frame->framenr;
+ (*ofs) = frame_curr;
+ while (frame && (frame->framenr == frame_curr)) {
+ frame_curr++;
+ frame = frame->next;
+ }
+ return frame_curr - (*ofs);
+ }
+ return 0;
+}
+
static int image_open_exec(bContext *C, wmOperator *op)
{
SpaceImage *sima = CTX_wm_space_image(C); /* XXX other space types can call */
Scene *scene = CTX_data_scene(C);
Object *obedit = CTX_data_edit_object(C);
ImageUser *iuser = NULL;
- PropertyPointerRNA *pprop;
+ ImageOpenData *iod;
PointerRNA idptr;
Image *ima = NULL;
- char str[FILE_MAX];
+ char path[FILE_MAX];
+ int frame_seq_len = 0;
+ int frame_ofs = 1;
- RNA_string_get(op->ptr, "filepath", str);
- /* default to frame 1 if there's no scene in context */
+ if (RNA_struct_property_is_set(op->ptr, "files") && RNA_struct_property_is_set(op->ptr, "directory")) {
+ ListBase frames;
+
+ frames.first = frames.last = NULL;
+ image_sequence_get_frames(op->ptr, &frames, path, sizeof(path));
+ frame_seq_len = image_sequence_get_len(&frames, &frame_ofs);
+ BLI_freelistN(&frames);
+ }
+ else {
+ RNA_string_get(op->ptr, "filepath", path);
+ }
errno = 0;
- ima = BKE_image_load_exists(str);
+ ima = BKE_image_load_exists(path);
if (!ima) {
if (op->customdata) MEM_freeN(op->customdata);
BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s",
- str, errno ? strerror(errno) : TIP_("unsupported image format"));
+ path, errno ? strerror(errno) : TIP_("unsupported image format"));
return OPERATOR_CANCELLED;
}
-
+
if (!op->customdata)
image_open_init(C, op);
/* hook into UI */
- pprop = op->customdata;
+ iod = op->customdata;
- if (pprop->prop) {
+ if (iod->pprop.prop) {
/* when creating new ID blocks, use is already 1, but RNA
* pointer se also increases user, so this compensates it */
ima->id.us--;
-
+ if ((frame_seq_len > 1) && ima->source == IMA_SRC_FILE) {
+ ima->source = IMA_SRC_SEQUENCE;
+ }
RNA_id_pointer_create(&ima->id, &idptr);
- RNA_property_pointer_set(&pprop->ptr, pprop->prop, idptr);
- RNA_property_update(C, &pprop->ptr, pprop->prop);
+ RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, idptr);
+ RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop);
+ }
+
+ if (iod->iuser) {
+ iuser = iod->iuser;
}
else if (sima) {
ED_space_image_set(sima, scene, obedit, ima);
@@ -975,15 +1086,17 @@ static int image_open_exec(bContext *C, wmOperator *op)
}
else {
Tex *tex = CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
- if (tex && tex->type == TEX_IMAGE)
+ if (tex && tex->type == TEX_IMAGE) {
iuser = &tex->iuser;
-
+ }
}
-
+
/* initialize because of new image */
if (iuser) {
+ iuser->frames = frame_seq_len;
iuser->sfra = 1;
- iuser->offset = 0;
+ iuser->framenr = 1;
+ iuser->offset = frame_ofs - 1;
iuser->fie_ima = 2;
}
@@ -1065,7 +1178,7 @@ void IMAGE_OT_open(wmOperatorType *ot)
/* properties */
WM_operator_properties_filesel(ot, FOLDERFILE | IMAGEFILE | MOVIEFILE, FILE_SPECIAL, FILE_OPENFILE,
- WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
+ WM_FILESEL_FILEPATH | WM_FILESEL_DIRECTORY | WM_FILESEL_FILES | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY);
}
/******************** Match movie length operator ********************/