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:
Diffstat (limited to 'source/blender/editors/space_image/image_ops.c')
-rw-r--r--source/blender/editors/space_image/image_ops.c239
1 files changed, 195 insertions, 44 deletions
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 336331e44e7..4036f859231 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -45,6 +45,7 @@
#include "BKE_main.h"
#include "BKE_packedFile.h"
#include "BKE_report.h"
+#include "BKE_scene.h"
#include "DEG_depsgraph.h"
@@ -197,6 +198,27 @@ static ImageUser *image_user_from_context(const bContext *C)
return (sima) ? &sima->iuser : NULL;
}
+static ImageUser image_user_from_context_and_active_tile(const bContext *C, Image *ima)
+{
+ /* Try to get image user from context if available, otherwise use default. */
+ ImageUser *iuser_context = image_user_from_context(C);
+ ImageUser iuser;
+ if (iuser_context) {
+ iuser = *iuser_context;
+ }
+ else {
+ BKE_imageuser_default(&iuser);
+ }
+
+ /* Use the file associated with the active tile. Otherwise use the first tile. */
+ if (ima && ima->source == IMA_SRC_TILED) {
+ const ImageTile *active = (ImageTile *)BLI_findlink(&ima->tiles, ima->active_tile_index);
+ iuser.tile = active ? active->tile_number : ((ImageTile *)ima->tiles.first)->tile_number;
+ }
+
+ return iuser;
+}
+
static bool image_from_context_has_data_poll(bContext *C)
{
Image *ima = image_from_context(C);
@@ -214,13 +236,14 @@ static bool image_from_context_has_data_poll(bContext *C)
}
/**
- * Use this when the image buffer is accessed without the image user.
+ * Use this when the image buffer is accessing the active tile without the image user.
*/
-static bool image_from_context_has_data_poll_no_image_user(bContext *C)
+static bool image_from_context_has_data_poll_active_tile(bContext *C)
{
Image *ima = image_from_context(C);
+ ImageUser iuser = image_user_from_context_and_active_tile(C, ima);
- return BKE_image_has_ibuf(ima, NULL);
+ return BKE_image_has_ibuf(ima, &iuser);
}
static bool image_not_packed_poll(bContext *C)
@@ -949,7 +972,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op))
static bool image_view_selected_poll(bContext *C)
{
- return (space_image_main_region_poll(C) && (ED_operator_uvedit(C) || ED_operator_mask(C)));
+ return (space_image_main_region_poll(C) && (ED_operator_uvedit(C) || ED_maskedit_poll(C)));
}
void IMAGE_OT_view_selected(wmOperatorType *ot)
@@ -1274,8 +1297,8 @@ static Image *image_open_single(Main *bmain,
BKE_image_free_views(ima);
}
- if ((range->length > 1) && (ima->source == IMA_SRC_FILE)) {
- if (range->udim_tiles.first) {
+ if (ima->source == IMA_SRC_FILE) {
+ if (range->udims_detected && range->udim_tiles.first) {
ima->source = IMA_SRC_TILED;
ImageTile *first_tile = ima->tiles.first;
first_tile->tile_number = range->offset;
@@ -1283,7 +1306,7 @@ static Image *image_open_single(Main *bmain,
BKE_image_add_tile(ima, POINTER_AS_INT(node->data), NULL);
}
}
- else {
+ else if (range->length > 1) {
ima->source = IMA_SRC_SEQUENCE;
}
}
@@ -1446,7 +1469,7 @@ static int image_open_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(
image_open_init(C, op);
- /* show multiview save options only if scene has multiviews */
+ /* Show multi-view save options only if scene has multi-views. */
PropertyRNA *prop;
prop = RNA_struct_find_property(op->ptr, "show_multiview");
RNA_property_boolean_set(op->ptr, prop, (scene->r.scemode & R_MULTIVIEW) != 0);
@@ -1535,6 +1558,115 @@ void IMAGE_OT_open(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Browse Image Operator
+ * \{ */
+
+static int image_file_browse_exec(bContext *C, wmOperator *op)
+{
+ Image *ima = op->customdata;
+ if (ima == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ char filepath[FILE_MAX];
+ RNA_string_get(op->ptr, "filepath", filepath);
+
+ /* If loading into a tiled texture, ensure that the filename is tokenized. */
+ if (ima->source == IMA_SRC_TILED) {
+ char *filename = (char *)BLI_path_basename(filepath);
+ BKE_image_ensure_tile_token(filename);
+ }
+
+ PointerRNA imaptr;
+ PropertyRNA *imaprop;
+ RNA_id_pointer_create(&ima->id, &imaptr);
+ imaprop = RNA_struct_find_property(&imaptr, "filepath");
+
+ RNA_property_string_set(&imaptr, imaprop, filepath);
+ RNA_property_update(C, &imaptr, imaprop);
+
+ return OPERATOR_FINISHED;
+}
+
+static int image_file_browse_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Image *ima = image_from_context(C);
+ if (!ima) {
+ return OPERATOR_CANCELLED;
+ }
+
+ char filepath[FILE_MAX];
+ BLI_strncpy(filepath, ima->filepath, sizeof(filepath));
+
+ /* Shift+Click to open the file, Alt+Click to browse a folder in the OS's browser. */
+ if (event->modifier & (KM_SHIFT | KM_ALT)) {
+ wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true);
+ PointerRNA props_ptr;
+
+ if (event->modifier & KM_ALT) {
+ char *lslash = (char *)BLI_path_slash_rfind(filepath);
+ if (lslash) {
+ *lslash = '\0';
+ }
+ }
+ else if (ima->source == IMA_SRC_TILED) {
+ ImageUser iuser = image_user_from_context_and_active_tile(C, ima);
+ BKE_image_user_file_path(&iuser, ima, filepath);
+ }
+
+ WM_operator_properties_create_ptr(&props_ptr, ot);
+ RNA_string_set(&props_ptr, "filepath", filepath);
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_DEFAULT, &props_ptr, NULL);
+ WM_operator_properties_free(&props_ptr);
+
+ return OPERATOR_CANCELLED;
+ }
+
+ /* The image is typically passed to the operator via layout/button context (e.g.
+ * #uiLayoutSetContextPointer()). The File Browser doesn't support restoring this context
+ * when calling `exec()` though, so we have to pass it the image via custom data. */
+ op->customdata = ima;
+
+ image_filesel(C, op, filepath);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static bool image_file_browse_poll(bContext *C)
+{
+ return image_from_context(C) != NULL;
+}
+
+void IMAGE_OT_file_browse(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Browse Image";
+ ot->description =
+ "Open an image file browser, hold Shift to open the file, Alt to browse containing "
+ "directory";
+ ot->idname = "IMAGE_OT_file_browse";
+
+ /* api callbacks */
+ ot->exec = image_file_browse_exec;
+ ot->invoke = image_file_browse_invoke;
+ ot->poll = image_file_browse_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_UNDO;
+
+ /* properties */
+ WM_operator_properties_filesel(ot,
+ FILE_TYPE_FOLDER | FILE_TYPE_IMAGE | FILE_TYPE_MOVIE,
+ FILE_SPECIAL,
+ FILE_OPENFILE,
+ WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH,
+ FILE_DEFAULTDISPLAY,
+ FILE_SORT_DEFAULT);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Match Movie Length Operator
* \{ */
@@ -1696,11 +1828,10 @@ static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOp
RNA_boolean_get(op->ptr, "copy"));
opts->save_as_render = (RNA_struct_find_property(op->ptr, "save_as_render") &&
RNA_boolean_get(op->ptr, "save_as_render"));
- opts->do_newpath = true;
}
static bool save_image_op(
- Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, ImageSaveOptions *opts)
+ Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, const ImageSaveOptions *opts)
{
WM_cursor_wait(true);
@@ -1727,12 +1858,14 @@ static ImageSaveData *image_save_as_init(bContext *C, wmOperator *op)
isd->image = image;
isd->iuser = iuser;
- if (!BKE_image_save_options_init(&isd->opts, bmain, scene, image, iuser, true)) {
+ if (!BKE_image_save_options_init(&isd->opts, bmain, scene, image, iuser, true, false)) {
BKE_image_save_options_free(&isd->opts);
MEM_freeN(isd);
return NULL;
}
+ isd->opts.do_newpath = true;
+
if (!RNA_struct_property_is_set(op->ptr, "filepath")) {
RNA_string_set(op->ptr, "filepath", isd->opts.filepath);
}
@@ -1994,7 +2127,7 @@ static int image_save_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
- if (!BKE_image_save_options_init(&opts, bmain, scene, image, iuser, false)) {
+ if (!BKE_image_save_options_init(&opts, bmain, scene, image, iuser, false, false)) {
BKE_image_save_options_free(&opts);
return OPERATOR_CANCELLED;
}
@@ -2266,7 +2399,7 @@ bool ED_image_save_all_modified(const bContext *C, ReportList *reports)
if (image_has_valid_path(ima)) {
ImageSaveOptions opts;
Scene *scene = CTX_data_scene(C);
- if (!BKE_image_save_options_init(&opts, bmain, scene, ima, NULL, false)) {
+ if (BKE_image_save_options_init(&opts, bmain, scene, ima, NULL, false, false)) {
bool saved_successfully = BKE_image_save(reports, bmain, ima, NULL, &opts);
ok = ok && saved_successfully;
}
@@ -2573,7 +2706,8 @@ void IMAGE_OT_new(wmOperatorType *ot)
static int image_flip_exec(bContext *C, wmOperator *op)
{
Image *ima = image_from_context(C);
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ImageUser iuser = image_user_from_context_and_active_tile(C, ima);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
SpaceImage *sima = CTX_wm_space_image(C);
const bool is_paint = ((sima != NULL) && (sima->mode == SI_MODE_PAINT));
@@ -2590,7 +2724,7 @@ static int image_flip_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
- ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser);
+ ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &iuser);
if (is_paint) {
ED_imapaint_clear_partial_redraw();
@@ -2670,7 +2804,7 @@ void IMAGE_OT_flip(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_flip_exec;
- ot->poll = image_from_context_has_data_poll_no_image_user;
+ ot->poll = image_from_context_has_data_poll_active_tile;
/* properties */
PropertyRNA *prop;
@@ -2693,7 +2827,8 @@ void IMAGE_OT_flip(wmOperatorType *ot)
static int image_invert_exec(bContext *C, wmOperator *op)
{
Image *ima = image_from_context(C);
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ImageUser iuser = image_user_from_context_and_active_tile(C, ima);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
SpaceImage *sima = CTX_wm_space_image(C);
const bool is_paint = ((sima != NULL) && (sima->mode == SI_MODE_PAINT));
@@ -2710,7 +2845,7 @@ static int image_invert_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser);
+ ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &iuser);
if (is_paint) {
ED_imapaint_clear_partial_redraw();
@@ -2791,7 +2926,7 @@ void IMAGE_OT_invert(wmOperatorType *ot)
/* api callbacks */
ot->exec = image_invert_exec;
- ot->poll = image_from_context_has_data_poll_no_image_user;
+ ot->poll = image_from_context_has_data_poll_active_tile;
/* properties */
prop = RNA_def_boolean(ot->srna, "invert_r", 0, "Red", "Invert red channel");
@@ -2816,9 +2951,10 @@ void IMAGE_OT_invert(wmOperatorType *ot)
static int image_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
Image *ima = image_from_context(C);
+ ImageUser iuser = image_user_from_context_and_active_tile(C, ima);
PropertyRNA *prop = RNA_struct_find_property(op->ptr, "size");
if (!RNA_property_is_set(op->ptr, prop)) {
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
const int size[2] = {ibuf->x, ibuf->y};
RNA_property_int_set_array(op->ptr, prop, size);
BKE_image_release_ibuf(ima, ibuf, NULL);
@@ -2829,7 +2965,8 @@ static int image_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED
static int image_scale_exec(bContext *C, wmOperator *op)
{
Image *ima = image_from_context(C);
- ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ ImageUser iuser = image_user_from_context_and_active_tile(C, ima);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &iuser, NULL);
SpaceImage *sima = CTX_wm_space_image(C);
const bool is_paint = ((sima != NULL) && (sima->mode == SI_MODE_PAINT));
@@ -2853,7 +2990,7 @@ static int image_scale_exec(bContext *C, wmOperator *op)
RNA_property_int_set_array(op->ptr, prop, size);
}
- ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser);
+ ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &iuser);
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
IMB_scaleImBuf(ibuf, size[0], size[1]);
@@ -2879,7 +3016,7 @@ void IMAGE_OT_resize(wmOperatorType *ot)
/* api callbacks */
ot->invoke = image_scale_invoke;
ot->exec = image_scale_exec;
- ot->poll = image_from_context_has_data_poll_no_image_user;
+ ot->poll = image_from_context_has_data_poll_active_tile;
/* properties */
RNA_def_int_vector(ot->srna, "size", 2, NULL, 1, INT_MAX, "Size", "", 1, SHRT_MAX);
@@ -3075,7 +3212,7 @@ bool ED_space_image_get_position(SpaceImage *sima,
}
bool ED_space_image_color_sample(
- SpaceImage *sima, ARegion *region, int mval[2], float r_col[3], bool *r_is_data)
+ SpaceImage *sima, ARegion *region, const int mval[2], float r_col[3], bool *r_is_data)
{
if (r_is_data) {
*r_is_data = false;
@@ -3335,10 +3472,10 @@ void IMAGE_OT_cycle_render_slot(wmOperatorType *ot)
static int image_clear_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
- if (!BKE_image_clear_renderslot(ima, &sima->iuser, ima->render_slot)) {
+ if (!BKE_image_clear_renderslot(ima, iuser, ima->render_slot)) {
return OPERATOR_CANCELLED;
}
@@ -3403,10 +3540,10 @@ void IMAGE_OT_add_render_slot(wmOperatorType *ot)
static int image_remove_render_slot_exec(bContext *C, wmOperator *UNUSED(op))
{
- SpaceImage *sima = CTX_wm_space_image(C);
Image *ima = image_from_context(C);
+ ImageUser *iuser = image_user_from_context(C);
- if (!BKE_image_remove_renderslot(ima, &sima->iuser, ima->render_slot)) {
+ if (!BKE_image_remove_renderslot(ima, iuser, ima->render_slot)) {
return OPERATOR_CANCELLED;
}
@@ -3451,9 +3588,9 @@ static void change_frame_apply(bContext *C, wmOperator *op)
Scene *scene = CTX_data_scene(C);
/* set the new frame number */
- CFRA = RNA_int_get(op->ptr, "frame");
- FRAMENUMBER_MIN_CLAMP(CFRA);
- SUBFRA = 0.0f;
+ scene->r.cfra = RNA_int_get(op->ptr, "frame");
+ FRAMENUMBER_MIN_CLAMP(scene->r.cfra);
+ scene->r.subframe = 0.0f;
/* do updates */
DEG_id_tag_update(&scene->id, ID_RECALC_FRAME_CHANGE);
@@ -3474,7 +3611,7 @@ static int frame_from_event(bContext *C, const wmEvent *event)
int framenr = 0;
if (region->regiontype == RGN_TYPE_WINDOW) {
- float sfra = SFRA, efra = EFRA, framelen = region->winx / (efra - sfra + 1);
+ float sfra = scene->r.sfra, efra = scene->r.efra, framelen = region->winx / (efra - sfra + 1);
framenr = sfra + event->mval[0] / framelen;
}
@@ -3596,38 +3733,52 @@ static int render_border_exec(bContext *C, wmOperator *op)
ARegion *region = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
Render *re = RE_GetSceneRender(scene);
- RenderData *rd;
- rctf border;
+ SpaceImage *sima = CTX_wm_space_image(C);
if (re == NULL) {
/* Shouldn't happen, but better be safe close to the release. */
return OPERATOR_CANCELLED;
}
- rd = RE_engine_get_render_data(re);
- if ((rd->mode & (R_BORDER | R_CROP)) == (R_BORDER | R_CROP)) {
- BKE_report(op->reports, RPT_INFO, "Can not set border from a cropped render");
- return OPERATOR_CANCELLED;
- }
+ /* Get information about the previous render, or current scene if no render yet. */
+ int width, height;
+ BKE_render_resolution(&scene->r, false, &width, &height);
+ const RenderData *rd = ED_space_image_has_buffer(sima) ? RE_engine_get_render_data(re) :
+ &scene->r;
- /* get rectangle from operator */
+ /* Get rectangle from the operator. */
+ rctf border;
WM_operator_properties_border_to_rctf(op, &border);
UI_view2d_region_to_view_rctf(&region->v2d, &border, &border);
- /* actually set border */
+ /* Adjust for cropping. */
+ if ((rd->mode & (R_BORDER | R_CROP)) == (R_BORDER | R_CROP)) {
+ border.xmin = rd->border.xmin + border.xmin * (rd->border.xmax - rd->border.xmin);
+ border.xmax = rd->border.xmin + border.xmax * (rd->border.xmax - rd->border.xmin);
+ border.ymin = rd->border.ymin + border.ymin * (rd->border.ymax - rd->border.ymin);
+ border.ymax = rd->border.ymin + border.ymax * (rd->border.ymax - rd->border.ymin);
+ }
+
CLAMP(border.xmin, 0.0f, 1.0f);
CLAMP(border.ymin, 0.0f, 1.0f);
CLAMP(border.xmax, 0.0f, 1.0f);
CLAMP(border.ymax, 0.0f, 1.0f);
- scene->r.border = border;
- /* drawing a border surrounding the entire camera view switches off border rendering
- * or the border covers no pixels */
+ /* Drawing a border surrounding the entire camera view switches off border rendering
+ * or the border covers no pixels. */
if ((border.xmin <= 0.0f && border.xmax >= 1.0f && border.ymin <= 0.0f && border.ymax >= 1.0f) ||
(border.xmin == border.xmax || border.ymin == border.ymax)) {
scene->r.mode &= ~R_BORDER;
}
else {
+ /* Snap border to pixel boundaries, so drawing a border within a pixel selects that pixel. */
+ border.xmin = floorf(border.xmin * width) / width;
+ border.xmax = ceilf(border.xmax * width) / width;
+ border.ymin = floorf(border.ymin * height) / height;
+ border.ymax = ceilf(border.ymax * height) / height;
+
+ /* Set border. */
+ scene->r.border = border;
scene->r.mode |= R_BORDER;
}