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--source/blender/editors/space_image/image_ops.c153
-rw-r--r--source/blender/editors/space_node/drawnode.c11
2 files changed, 141 insertions, 23 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 ********************/
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index c30c4fe9ada..e8547b7c164 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -659,6 +659,8 @@ static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
/* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
Scene *scene = CTX_data_scene(C);
ImageUser *iuser = iuserptr->data;
+ Image *ima = imaptr->data;
+
char numstr[32];
const int framenr = BKE_image_user_frame_get(iuser, CFRA, 0, NULL);
BLI_snprintf(numstr, sizeof(numstr), IFACE_("Frame: %d"), framenr);
@@ -773,6 +775,7 @@ static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA
PointerRNA imaptr = RNA_pointer_get(ptr, "image");
PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
@@ -798,6 +801,7 @@ static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, Poin
PointerRNA imaptr = RNA_pointer_get(ptr, "image");
PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
@@ -1103,13 +1107,13 @@ static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *
bNode *node = ptr->data;
PointerRNA imaptr, iuserptr;
+ RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
-
if (!node->id) return;
imaptr = RNA_pointer_get(ptr, "image");
- RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
-
+
node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr);
}
@@ -1119,6 +1123,7 @@ static void node_composit_buts_image_ex(uiLayout *layout, bContext *C, PointerRN
PointerRNA iuserptr;
RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
+ uiLayoutSetContextPointer(layout, "image_user", &iuserptr);
uiTemplateImage(layout, C, ptr, "image", &iuserptr, 0);
}