diff options
Diffstat (limited to 'source/blender/editors/space_image')
-rw-r--r-- | source/blender/editors/space_image/image_buttons.c | 71 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_ops.c | 175 |
2 files changed, 155 insertions, 91 deletions
diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index a2db6827b0e..38a54ade367 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -345,6 +345,13 @@ struct ImageUI_Data { int rpass_index; }; +static struct ImageUI_Data *ui_imageuser_data_copy(const struct ImageUI_Data *rnd_pt_src) +{ + struct ImageUI_Data *rnd_pt_dst = MEM_mallocN(sizeof(*rnd_pt_src), __func__); + memcpy(rnd_pt_dst, rnd_pt_src, sizeof(*rnd_pt_src)); + return rnd_pt_dst; +} + static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt) { struct ImageUI_Data *rnd_data = rnd_pt; @@ -532,9 +539,10 @@ static void ui_imageuser_view_menu_multiview(bContext *UNUSED(C), uiLayout *layo } /* 5 layer button callbacks... */ -static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) +static void image_multi_cb(bContext *C, void *rnd_pt, void *rr_v) { - ImageUser *iuser = iuser_v; + struct ImageUI_Data *rnd_data = rnd_pt; + ImageUser *iuser = rnd_data->iuser; BKE_image_multilayer_index(rr_v, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); @@ -575,6 +583,8 @@ static bool ui_imageuser_layer_menu_step(bContext *C, int direction, void *rnd_p BLI_assert(0); } + BKE_image_release_renderresult(scene, image); + if (changed) { BKE_image_multilayer_index(rr, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); @@ -662,10 +672,11 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt } /* 5 view button callbacks... */ -static void image_multiview_cb(bContext *C, void *ima_v, void *iuser_v) +static void image_multiview_cb(bContext *C, void *rnd_pt, void *UNUSED(arg_v)) { - Image *ima = ima_v; - ImageUser *iuser = iuser_v; + struct ImageUI_Data *rnd_data = rnd_pt; + Image *ima = rnd_data->image; + ImageUser *iuser = rnd_data->iuser; BKE_image_multiview_index(ima, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); @@ -692,7 +703,7 @@ static void uiblock_layer_pass_buttons( uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w, short *render_slot) { - static struct ImageUI_Data rnd_pt; /* XXX, workaround */ + struct ImageUI_Data rnd_pt_local, *rnd_pt = NULL; uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; RenderLayer *rl = NULL; @@ -708,10 +719,10 @@ static void uiblock_layer_pass_buttons( wmenu2 = (3 * w) / 5; wmenu3 = (3 * w) / 6; wmenu4 = (3 * w) / 6; - - rnd_pt.image = image; - rnd_pt.iuser = iuser; - rnd_pt.rpass_index = 0; + + rnd_pt_local.image = image; + rnd_pt_local.iuser = iuser; + rnd_pt_local.rpass_index = 0; /* menu buts */ if (render_slot) { @@ -723,10 +734,12 @@ static void uiblock_layer_pass_buttons( BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1); } + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); but = uiDefMenuBut(block, ui_imageuser_slot_menu, image, str, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select Slot")); UI_but_func_menu_step_set(but, ui_imageuser_slot_menu_step); - UI_but_func_set(but, image_multi_cb, rr, iuser); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; } if (rr) { @@ -738,15 +751,18 @@ static void uiblock_layer_pass_buttons( fake_name = ui_imageuser_layer_fake_name(rr); rpass_index = iuser->layer - (fake_name ? 1 : 0); rl = BLI_findlink(&rr->layers, rpass_index); - rnd_pt.rpass_index = rpass_index; + rnd_pt_local.rpass_index = rpass_index; if (RE_layers_have_name(rr)) { display_name = rl ? rl->name : (fake_name ? fake_name : ""); - but = uiDefMenuBut(block, ui_imageuser_layer_menu, &rnd_pt, display_name, - 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer")); + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_layer_menu, rnd_pt, display_name, + 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer")); UI_but_func_menu_step_set(but, ui_imageuser_layer_menu_step); - UI_but_func_set(but, image_multi_cb, rr, iuser); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; } /* pass */ @@ -754,11 +770,14 @@ static void uiblock_layer_pass_buttons( rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL); display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : ""); - but = uiDefMenuBut(block, ui_imageuser_pass_menu, &rnd_pt, IFACE_(display_name), - 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass")); + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name), + 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass")); UI_but_func_menu_step_set(but, ui_imageuser_pass_menu_step); - UI_but_func_set(but, image_multi_cb, rr, iuser); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; /* view */ if (BLI_listbase_count_ex(&rr->views, 2) > 1 && @@ -767,9 +786,13 @@ static void uiblock_layer_pass_buttons( rview = BLI_findlink(&rr->views, iuser->view); display_name = rview ? rview->name : ""; - but = uiDefMenuBut(block, ui_imageuser_view_menu_rr, &rnd_pt, display_name, 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View")); - UI_but_func_set(but, image_multi_cb, rr, iuser); + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_view_menu_rr, rnd_pt, display_name, + 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View")); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; } } @@ -787,9 +810,13 @@ static void uiblock_layer_pass_buttons( } } - but = uiDefMenuBut(block, ui_imageuser_view_menu_multiview, &rnd_pt, display_name, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View")); - UI_but_func_set(but, image_multiview_cb, image, iuser); + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_view_menu_multiview, rnd_pt, display_name, + 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View")); + UI_but_funcN_set(but, image_multiview_cb, rnd_pt, NULL); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; } } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 06caf930988..1158e692182 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1061,6 +1061,12 @@ typedef struct ImageOpenData { ImageFormatData im_format; } ImageOpenData; +typedef struct ImageFrameRange { + struct ImageFrameRange *next, *prev; + ListBase frames; + char filepath[FILE_MAX]; +} ImageFrameRange; + typedef struct ImageFrame { struct ImageFrame *next, *prev; int framenr; @@ -1086,10 +1092,10 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op) * \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) +static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all) { char dir[FILE_MAXDIR]; - bool is_first_entry = true; + ImageFrameRange *frame_range = NULL; RNA_string_get(ptr, "directory", dir); RNA_BEGIN (ptr, itemptr, "files") @@ -1101,29 +1107,26 @@ static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *p 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; + frame->framenr = BLI_stringdec(filename, head, tail, &digits); + + /* still in the same sequence */ + if ((frame_range != NULL) && + (STREQLEN(base_head, head, FILE_MAX)) && + (STREQLEN(base_tail, tail, FILE_MAX))) + { + /* pass */ } else { - frame->framenr = BLI_stringdec(filename, head, tail, &digits); + /* 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); - /* 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(filename); - MEM_freeN(frame); - break; - } + 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 @@ -1164,6 +1167,52 @@ static int image_sequence_get_len(ListBase *frames, int *ofs) return 0; } +static Image *image_open_single( + wmOperator *op, const char *filepath, const char *relbase, + bool is_relative_path, bool use_multiview, int frame_seq_len) +{ + bool exists = false; + Image *ima = NULL; + + errno = 0; + ima = BKE_image_load_exists_ex(filepath, &exists); + + if (!ima) { + if (op->customdata) MEM_freeN(op->customdata); + BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", + filepath, errno ? strerror(errno) : TIP_("unsupported image format")); + return NULL; + } + + if (!exists) { + /* only image path after save, never ibuf */ + if (is_relative_path) { + BLI_path_rel(ima->name, relbase); + } + + /* handle multiview images */ + if (use_multiview) { + ImageOpenData *iod = op->customdata; + ImageFormatData *imf = &iod->im_format; + + ima->flag |= IMA_USE_VIEWS; + ima->views_format = imf->views_format; + *ima->stereo3d_format = imf->stereo3d_format; + } + else { + ima->flag &= ~IMA_USE_VIEWS; + BKE_image_free_views(ima); + } + + if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) { + ima->source = IMA_SRC_SEQUENCE; + } + } + + return ima; +} + + static int image_open_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1174,70 +1223,60 @@ static int image_open_exec(bContext *C, wmOperator *op) ImageOpenData *iod = op->customdata; PointerRNA idptr; Image *ima = NULL; - char path[FILE_MAX]; + char filepath[FILE_MAX]; int frame_seq_len = 0; int frame_ofs = 1; - bool exists = false; const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); + const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview"); - RNA_string_get(op->ptr, "filepath", path); + if (!op->customdata) + image_open_init(C, op); + + RNA_string_get(op->ptr, "filepath", filepath); if (RNA_struct_property_is_set(op->ptr, "directory") && RNA_struct_property_is_set(op->ptr, "files")) { - /* only to pass to imbuf */ - char path_full[FILE_MAX]; - BLI_strncpy(path_full, path, sizeof(path_full)); - BLI_path_abs(path_full, G.main->name); + bool was_relative = BLI_path_is_rel(filepath); + ListBase frame_ranges_all; - if (!IMB_isanim(path_full)) { - bool was_relative = BLI_path_is_rel(path); - ListBase frames; + 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; + int frame_range_seq_len = image_sequence_get_len(&frame_range->frames, &frame_range_ofs); + BLI_freelistN(&frame_range->frames); - BLI_listbase_clear(&frames); - image_sequence_get_frames(op->ptr, &frames, path, sizeof(path)); - frame_seq_len = image_sequence_get_len(&frames, &frame_ofs); - BLI_freelistN(&frames); + char filepath_range[FILE_MAX]; + BLI_strncpy(filepath_range, frame_range->filepath, sizeof(filepath_range)); if (was_relative) { - BLI_path_rel(path, G.main->name); + BLI_path_rel(filepath_range, bmain->name); } - } - } - - errno = 0; - ima = BKE_image_load_exists_ex(path, &exists); + Image *ima_range = image_open_single( + op, filepath_range, bmain->name, + is_relative_path, use_multiview, frame_range_seq_len); - if (!ima) { - if (op->customdata) MEM_freeN(op->customdata); - BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", - path, errno ? strerror(errno) : TIP_("unsupported image format")); - return OPERATOR_CANCELLED; - } - - if (!op->customdata) - image_open_init(C, op); - - /* handle multiview images */ - if (RNA_boolean_get(op->ptr, "use_multiview")) { - ImageFormatData *imf = &iod->im_format; - - ima->flag |= IMA_USE_VIEWS; - ima->views_format = imf->views_format; - *ima->stereo3d_format = imf->stereo3d_format; + /* 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_freelistN(&frame_ranges_all); } else { - ima->flag &= ~IMA_USE_VIEWS; - BKE_image_free_views(ima); + /* for drag & drop etc. */ + ima = image_open_single( + op, filepath, bmain->name, + is_relative_path, use_multiview, 1); } - /* only image path after save, never ibuf */ - if (is_relative_path) { - if (!exists) { - BLI_path_rel(ima->name, bmain->name); - } + if (ima == NULL) { + return OPERATOR_CANCELLED; } /* hook into UI */ @@ -1245,11 +1284,9 @@ static int image_open_exec(bContext *C, wmOperator *op) if (iod->pprop.prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&ima->id); - 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(&iod->pprop.ptr, iod->pprop.prop, idptr); RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop); @@ -2359,7 +2396,7 @@ static int image_new_exec(bContext *C, wmOperator *op) if (prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&ima->id); RNA_id_pointer_create(&ima->id, &idptr); |