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.c459
1 files changed, 414 insertions, 45 deletions
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c
index 8d17b703449..4404f904891 100644
--- a/source/blender/editors/space_image/image_ops.c
+++ b/source/blender/editors/space_image/image_ops.c
@@ -35,7 +35,10 @@
#include "MEM_guardedalloc.h"
#include "BLI_blenlib.h"
+#include "BLI_fileops.h"
+#include "BLI_fileops_types.h"
#include "BLI_ghash.h"
+#include "BLI_linklist.h"
#include "BLI_math.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -1264,6 +1267,51 @@ static int image_cmp_frame(const void *a, const void *b)
return 0;
}
+static int image_get_udim(const char *filepath, LinkNodePair *udim_tiles)
+{
+ char filename[FILE_MAX], dirname[FILE_MAXDIR];
+ BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename));
+
+ if (strstr(filename, "1001") == NULL) {
+ return 0;
+ }
+
+ bool is_udim = true;
+ int max_udim = 0;
+
+ 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) {
+ 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 >= 2000) {
+ is_udim = false;
+ break;
+ }
+
+ BLI_linklist_append(udim_tiles, POINTER_FROM_INT(id));
+ max_udim = max_ii(max_udim, id);
+ }
+
+ BLI_filelist_free(dir, totfile);
+ }
+
+ return is_udim ? (max_udim - 1001) : 0;
+}
+
/**
* Return the start (offset) and the length of the sequence of
* continuous frames in the list of frames.
@@ -1272,21 +1320,27 @@ static int image_cmp_frame(const void *a, const void *b)
* \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(ListBase *frames, int *ofs)
+static int image_sequence_get_len(ImageFrameRange *frame_range, int *ofs, LinkNodePair *udim_tiles)
{
ImageFrame *frame;
- BLI_listbase_sort(frames, image_cmp_frame);
+ BLI_listbase_sort(&frame_range->frames, image_cmp_frame);
- frame = frames->first;
- if (frame) {
+ frame = frame_range->frames.first;
+ if (frame != NULL) {
int frame_curr = frame->framenr;
(*ofs) = frame_curr;
- while (frame && (frame->framenr == frame_curr)) {
- frame_curr++;
- frame = frame->next;
+
+ if (udim_tiles != NULL && (frame_curr == 1001)) {
+ return 1 + image_get_udim(frame_range->filepath, udim_tiles);
+ }
+ else {
+ while (frame != NULL && (frame->framenr == frame_curr)) {
+ frame_curr++;
+ frame = frame->next;
+ }
+ return frame_curr - (*ofs);
}
- return frame_curr - (*ofs);
}
*ofs = 0;
return 0;
@@ -1298,7 +1352,9 @@ static Image *image_open_single(Main *bmain,
const char *relbase,
bool is_relative_path,
bool use_multiview,
- int frame_seq_len)
+ int frame_seq_len,
+ int frame_seq_ofs,
+ LinkNodePair *udim_tiles)
{
bool exists = false;
Image *ima = NULL;
@@ -1339,7 +1395,15 @@ static Image *image_open_single(Main *bmain,
}
if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) {
- ima->source = IMA_SRC_SEQUENCE;
+ if (udim_tiles && frame_seq_ofs == 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);
+ }
+ }
+ else {
+ ima->source = IMA_SRC_SEQUENCE;
+ }
}
}
@@ -1358,9 +1422,11 @@ static int image_open_exec(bContext *C, wmOperator *op)
char filepath[FILE_MAX];
int frame_seq_len = 0;
int frame_ofs = 1;
+ LinkNodePair udim_tiles = {NULL};
const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path");
const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview");
+ const bool use_udim = RNA_boolean_get(op->ptr, "use_udim_detecting");
if (!op->customdata) {
image_open_init(C, op);
@@ -1378,7 +1444,10 @@ static int image_open_exec(bContext *C, wmOperator *op)
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);
+
+ LinkNodePair *udim_tiles_ptr = use_udim ? (&udim_tiles) : NULL;
+ int frame_range_seq_len = image_sequence_get_len(
+ frame_range, &frame_range_ofs, udim_tiles_ptr);
BLI_freelistN(&frame_range->frames);
char filepath_range[FILE_MAX];
@@ -1394,7 +1463,9 @@ static int image_open_exec(bContext *C, wmOperator *op)
BKE_main_blendfile_path(bmain),
is_relative_path,
use_multiview,
- frame_range_seq_len);
+ frame_range_seq_len,
+ frame_range_ofs,
+ udim_tiles_ptr);
/* take the first image */
if ((ima == NULL) && ima_range) {
@@ -1407,10 +1478,31 @@ static int image_open_exec(bContext *C, wmOperator *op)
}
else {
/* for drag & drop etc. */
- ima = image_open_single(
- bmain, op, filepath, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview, 1);
+ frame_seq_len = 1;
+
+ if (use_udim) {
+ /* Try to find UDIM tiles corresponding to the image */
+ frame_seq_len = 1 + image_get_udim(filepath, &udim_tiles);
+
+ /* If we found something, mark the image as tiled. */
+ if (frame_seq_len > 1) {
+ frame_ofs = 1001;
+ }
+ }
+
+ ima = image_open_single(bmain,
+ op,
+ filepath,
+ BKE_main_blendfile_path(bmain),
+ is_relative_path,
+ use_multiview,
+ frame_seq_len,
+ frame_ofs,
+ &udim_tiles);
}
+ BLI_linklist_free(udim_tiles.list, NULL);
+
if (ima == NULL) {
return OPERATOR_CANCELLED;
}
@@ -1458,7 +1550,8 @@ static int image_open_exec(bContext *C, wmOperator *op)
/* initialize because of new image */
if (iuser) {
- iuser->frames = frame_seq_len;
+ /* If the sequence was a tiled image, we only have one frame. */
+ iuser->frames = (ima->source == IMA_SRC_SEQUENCE) ? frame_seq_len : 1;
iuser->sfra = 1;
iuser->framenr = 1;
if (ima->source == IMA_SRC_MOVIE) {
@@ -1604,6 +1697,11 @@ void IMAGE_OT_open(wmOperatorType *ot)
true,
"Detect Sequences",
"Automatically detect animated sequences in selected images (based on file names)");
+ RNA_def_boolean(ot->srna,
+ "use_udim_detecting",
+ true,
+ "Detect UDIMs",
+ "Detect selected UDIM files and load all matching tiles");
}
/** \} */
@@ -1870,6 +1968,12 @@ static int image_save_options_init(Main *bmain,
BLI_path_make_safe(opts->filepath);
BLI_path_abs(opts->filepath, is_prev_save ? G.ima : BKE_main_blendfile_path(bmain));
}
+
+ /* append UDIM numbering if not present */
+ if (ima->source == IMA_SRC_TILED && (BLI_stringdec(ima->name, NULL, NULL, NULL) != 1001)) {
+ int len = strlen(opts->filepath);
+ STR_CONCAT(opts->filepath, len, ".1001");
+ }
}
/* color management */
@@ -2608,13 +2712,23 @@ static int image_new_exec(bContext *C, wmOperator *op)
RNA_float_get_array(op->ptr, "color", color);
alpha = RNA_boolean_get(op->ptr, "alpha");
stereo3d = RNA_boolean_get(op->ptr, "use_stereo_3d");
+ bool tiled = RNA_boolean_get(op->ptr, "tiled");
if (!alpha) {
color[3] = 1.0f;
}
- ima = BKE_image_add_generated(
- bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d, false);
+ ima = BKE_image_add_generated(bmain,
+ width,
+ height,
+ name,
+ alpha ? 32 : 24,
+ floatbuf,
+ gen_type,
+ color,
+ stereo3d,
+ false,
+ tiled);
if (!ima) {
image_new_free(op);
@@ -2698,6 +2812,9 @@ static void image_new_draw(bContext *UNUSED(C), wmOperator *op)
uiItemL(col[0], "", ICON_NONE);
uiItemR(col[1], &ptr, "float", 0, NULL, ICON_NONE);
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "tiled", 0, NULL, ICON_NONE);
+
#if 0
if (is_multiview) {
uiItemL(col[0], "", ICON_NONE);
@@ -2753,6 +2870,8 @@ void IMAGE_OT_new(wmOperatorType *ot)
prop = RNA_def_boolean(
ot->srna, "use_stereo_3d", 0, "Stereo 3D", "Create an image with left and right views");
RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
+ prop = RNA_def_boolean(ot->srna, "tiled", 0, "Tiled", "Create a tiled image");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
#undef IMA_DEF_NAME
@@ -2783,7 +2902,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);
+ ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, 0);
if (is_paint) {
ED_imapaint_clear_partial_redraw();
@@ -2927,7 +3046,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);
+ ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, 0);
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
IMB_scaleImBuf(ibuf, size[0], size[1]);
@@ -2977,7 +3096,7 @@ static bool image_pack_test(bContext *C, wmOperator *op)
return 0;
}
- if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
BKE_report(op->reports, RPT_ERROR, "Packing movies or image sequences not supported");
return 0;
}
@@ -3045,7 +3164,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
return OPERATOR_CANCELLED;
}
@@ -3078,7 +3197,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
return OPERATOR_CANCELLED;
}
- if (ima->source == IMA_SRC_SEQUENCE || ima->source == IMA_SRC_MOVIE) {
+ if (ELEM(ima->source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE, IMA_SRC_TILED)) {
BKE_report(op->reports, RPT_ERROR, "Unpacking movies or image sequences not supported");
return OPERATOR_CANCELLED;
}
@@ -3210,9 +3329,12 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info)
/* Returns color in linear space, matching ED_space_node_color_sample(). */
bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], float r_col[3])
{
+ float uv[2];
+ UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &uv[0], &uv[1]);
+ int tile = BKE_image_get_tile_from_pos(sima->image, uv, uv, NULL);
+
void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
- float fx, fy;
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
bool ret = false;
if (ibuf == NULL) {
@@ -3220,12 +3342,10 @@ bool ED_space_image_color_sample(SpaceImage *sima, ARegion *ar, int mval[2], flo
return false;
}
- UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &fx, &fy);
-
- if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
+ if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 1.0f && uv[1] < 1.0f) {
const float *fp;
unsigned char *cp;
- int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
+ int x = (int)(uv[0] * ibuf->x), y = (int)(uv[1] * ibuf->y);
CLAMP(x, 0, ibuf->x - 1);
CLAMP(y, 0, ibuf->y - 1);
@@ -3326,10 +3446,15 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event
{
SpaceImage *sima = CTX_wm_space_image(C);
ARegion *ar = CTX_wm_region(C);
+ Image *image = ED_space_image(sima);
+
+ float uv[2];
+ UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &uv[0], &uv[1]);
+ int tile = BKE_image_get_tile_from_pos(sima->image, uv, uv, NULL);
+
void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
ImageSampleInfo *info = op->customdata;
- float fx, fy;
Scene *scene = CTX_data_scene(C);
CurveMapping *curve_mapping = scene->view_settings.curve_mapping;
@@ -3339,11 +3464,8 @@ static void image_sample_apply(bContext *C, wmOperator *op, const wmEvent *event
return;
}
- UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fx, &fy);
-
- if (fx >= 0.0f && fy >= 0.0f && fx < 1.0f && fy < 1.0f) {
- int x = (int)(fx * ibuf->x), y = (int)(fy * ibuf->y);
- Image *image = ED_space_image(sima);
+ if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 1.0f && uv[1] < 1.0f) {
+ int x = (int)(uv[0] * ibuf->x), y = (int)(uv[1] * ibuf->y);
CLAMP(x, 0, ibuf->x - 1);
CLAMP(y, 0, ibuf->y - 1);
@@ -3551,18 +3673,25 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
SpaceImage *sima = CTX_wm_space_image(C);
ARegion *ar = CTX_wm_region(C);
Scene *scene = CTX_data_scene(C);
+ Image *ima = ED_space_image(sima);
int x_start = RNA_int_get(op->ptr, "xstart");
int y_start = RNA_int_get(op->ptr, "ystart");
int x_end = RNA_int_get(op->ptr, "xend");
int y_end = RNA_int_get(op->ptr, "yend");
+ float uv1[2], uv2[2], ofs[2];
+ UI_view2d_region_to_view(&ar->v2d, x_start, y_start, &uv1[0], &uv1[1]);
+ UI_view2d_region_to_view(&ar->v2d, x_end, y_end, &uv2[0], &uv2[1]);
+
+ /* If the image has tiles, shift the positions accordingly. */
+ int tile = BKE_image_get_tile_from_pos(ima, uv1, uv1, ofs);
+ sub_v2_v2(uv2, ofs);
+
void *lock;
- ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock);
+ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile);
Histogram *hist = &sima->sample_line_hist;
- float x1f, y1f, x2f, y2f;
-
if (ibuf == NULL) {
ED_space_image_release_buffer(sima, ibuf, lock);
return OPERATOR_CANCELLED;
@@ -3573,13 +3702,8 @@ static int image_sample_line_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
- UI_view2d_region_to_view(&ar->v2d, x_start, y_start, &x1f, &y1f);
- UI_view2d_region_to_view(&ar->v2d, x_end, y_end, &x2f, &y2f);
-
- hist->co[0][0] = x1f;
- hist->co[0][1] = y1f;
- hist->co[1][0] = x2f;
- hist->co[1][1] = y2f;
+ copy_v2_v2(hist->co[0], uv1);
+ copy_v2_v2(hist->co[1], uv2);
/* enable line drawing */
hist->flag |= HISTO_FLAG_SAMPLELINE;
@@ -4085,3 +4209,248 @@ void IMAGE_OT_clear_render_border(wmOperatorType *ot)
}
/** \} */
+
+/* ********************* Add tile operator ****************** */
+
+static bool tile_poll(bContext *C)
+{
+ Image *ima = CTX_data_edit_image(C);
+
+ return (ima != NULL && ima->source == IMA_SRC_TILED);
+}
+
+static int tile_add_exec(bContext *C, wmOperator *op)
+{
+ Image *ima = CTX_data_edit_image(C);
+
+ int tile_number = RNA_int_get(op->ptr, "number");
+
+ char *label = RNA_string_get_alloc(op->ptr, "label", NULL, 0);
+
+ ImageTile *tile = BKE_image_add_tile(ima, tile_number, label);
+ MEM_freeN(label);
+
+ if (tile == NULL) {
+ return OPERATOR_CANCELLED;
+ }
+
+ ima->active_tile_index = BLI_findindex(&ima->tiles, tile);
+
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int tile_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Image *ima = CTX_data_edit_image(C);
+
+ /* Find the first gap in tile numbers or the number after the last if
+ * no gap exists. */
+ int next_number = 0;
+ LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
+ next_number = tile->tile_number + 1;
+ if (tile->next == NULL || tile->next->tile_number > next_number) {
+ break;
+ }
+ }
+
+ RNA_int_set(op->ptr, "number", next_number);
+ RNA_string_set(op->ptr, "label", "");
+
+ return WM_operator_props_dialog_popup(C, op, 5 * UI_UNIT_X, 5 * UI_UNIT_Y);
+}
+
+static void tile_add_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *split, *col[2];
+ uiLayout *layout = op->layout;
+ PointerRNA ptr;
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+
+ split = uiLayoutSplit(layout, 0.5f, false);
+ col[0] = uiLayoutColumn(split, false);
+ col[1] = uiLayoutColumn(split, false);
+
+ uiItemL(col[0], IFACE_("Number"), ICON_NONE);
+ uiItemR(col[1], &ptr, "number", 0, "", ICON_NONE);
+
+ uiItemL(col[0], IFACE_("Label"), ICON_NONE);
+ uiItemR(col[1], &ptr, "label", 0, "", ICON_NONE);
+}
+
+void IMAGE_OT_tile_add(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add tile";
+ ot->description = "Adds a tile to the image";
+ ot->idname = "IMAGE_OT_tile_add";
+
+ /* api callbacks */
+ ot->poll = tile_poll;
+ ot->exec = tile_add_exec;
+ ot->invoke = tile_add_invoke;
+ ot->ui = tile_add_draw;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ RNA_def_int(
+ ot->srna, "number", 1002, 1001, INT_MAX, "Number", "UDIM number of the tile", 1001, 1099);
+ RNA_def_string(ot->srna, "label", NULL, 0, "Label", "Optional tile label");
+}
+
+/* ********************* Remove tile operator ****************** */
+
+static bool tile_remove_poll(bContext *C)
+{
+ Image *ima = CTX_data_edit_image(C);
+
+ return (ima != NULL && ima->source == IMA_SRC_TILED && ima->active_tile_index != 0);
+}
+
+static int tile_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Image *ima = CTX_data_edit_image(C);
+
+ ImageTile *tile = BLI_findlink(&ima->tiles, ima->active_tile_index);
+ if (!BKE_image_remove_tile(ima, tile)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ /* Ensure that the active index is valid. */
+ ima->active_tile_index = min_ii(ima->active_tile_index, BLI_listbase_count(&ima->tiles) - 1);
+
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void IMAGE_OT_tile_remove(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove tile";
+ ot->description = "Removes a tile from the image";
+ ot->idname = "IMAGE_OT_tile_remove";
+
+ /* api callbacks */
+ ot->poll = tile_remove_poll;
+ ot->exec = tile_remove_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/* ********************* Fill tile operator ****************** */
+
+static int tile_fill_exec(bContext *C, wmOperator *op)
+{
+ Image *ima = CTX_data_edit_image(C);
+
+ float color[4];
+ RNA_float_get_array(op->ptr, "color", color);
+ int gen_type = RNA_enum_get(op->ptr, "generated_type");
+ int width = RNA_int_get(op->ptr, "width");
+ int height = RNA_int_get(op->ptr, "height");
+ bool is_float = RNA_boolean_get(op->ptr, "float");
+ int planes = RNA_boolean_get(op->ptr, "alpha") ? 32 : 24;
+
+ ImageTile *tile = BLI_findlink(&ima->tiles, ima->active_tile_index);
+ if (!BKE_image_fill_tile(ima, tile, width, height, color, gen_type, planes, is_float)) {
+ return OPERATOR_CANCELLED;
+ }
+
+ WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+static int tile_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ Image *ima = CTX_data_edit_image(C);
+
+ /* Acquire first tile to get the defaults. */
+ ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL);
+ if (ibuf != NULL) {
+ RNA_int_set(op->ptr, "width", ibuf->x);
+ RNA_int_set(op->ptr, "height", ibuf->y);
+ RNA_boolean_set(op->ptr, "float", ibuf->rect_float != NULL);
+ RNA_boolean_set(op->ptr, "alpha", ibuf->planes > 24);
+ BKE_image_release_ibuf(ima, ibuf, NULL);
+ }
+
+ return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y);
+}
+
+static void tile_fill_draw(bContext *UNUSED(C), wmOperator *op)
+{
+ uiLayout *split, *col[2];
+ uiLayout *layout = op->layout;
+ PointerRNA ptr;
+
+ RNA_pointer_create(NULL, op->type->srna, op->properties, &ptr);
+
+ /* copy of WM_operator_props_dialog_popup() layout */
+
+ split = uiLayoutSplit(layout, 0.5f, false);
+ col[0] = uiLayoutColumn(split, false);
+ col[1] = uiLayoutColumn(split, false);
+
+ uiItemL(col[0], IFACE_("Color"), ICON_NONE);
+ uiItemR(col[1], &ptr, "color", 0, "", ICON_NONE);
+
+ uiItemL(col[0], IFACE_("Width"), ICON_NONE);
+ uiItemR(col[1], &ptr, "width", 0, "", ICON_NONE);
+
+ uiItemL(col[0], IFACE_("Height"), ICON_NONE);
+ uiItemR(col[1], &ptr, "height", 0, "", ICON_NONE);
+
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "alpha", 0, NULL, ICON_NONE);
+
+ uiItemL(col[0], IFACE_("Generated Type"), ICON_NONE);
+ uiItemR(col[1], &ptr, "generated_type", 0, "", ICON_NONE);
+
+ uiItemL(col[0], "", ICON_NONE);
+ uiItemR(col[1], &ptr, "float", 0, NULL, ICON_NONE);
+}
+
+void IMAGE_OT_tile_fill(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Fill tile";
+ ot->description = "Fill the current tile with a generated image";
+ ot->idname = "IMAGE_OT_tile_fill";
+
+ /* api callbacks */
+ ot->poll = tile_poll;
+ ot->exec = tile_fill_exec;
+ ot->invoke = tile_fill_invoke;
+ ot->ui = tile_fill_draw;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ PropertyRNA *prop;
+ static float default_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ prop = RNA_def_float_color(
+ ot->srna, "color", 4, NULL, 0.0f, FLT_MAX, "Color", "Default fill color", 0.0f, 1.0f);
+ RNA_def_property_subtype(prop, PROP_COLOR_GAMMA);
+ RNA_def_property_float_array_default(prop, default_color);
+ RNA_def_enum(ot->srna,
+ "generated_type",
+ rna_enum_image_generated_type_items,
+ IMA_GENTYPE_BLANK,
+ "Generated Type",
+ "Fill the image with a grid for UV map testing");
+ prop = RNA_def_int(ot->srna, "width", 1024, 1, INT_MAX, "Width", "Image width", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+ prop = RNA_def_int(ot->srna, "height", 1024, 1, INT_MAX, "Height", "Image height", 1, 16384);
+ RNA_def_property_subtype(prop, PROP_PIXEL);
+
+ /* Only needed when filling the first tile. */
+ RNA_def_boolean(
+ ot->srna, "float", 0, "32 bit Float", "Create image with 32 bit floating point bit depth");
+ RNA_def_boolean(ot->srna, "alpha", 1, "Alpha", "Create an image with an alpha channel");
+}