diff options
Diffstat (limited to 'source/blender/editors/space_image/image_ops.c')
-rw-r--r-- | source/blender/editors/space_image/image_ops.c | 458 |
1 files changed, 413 insertions, 45 deletions
diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index be91f7abf99..bcbfa1342d5 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -45,6 +45,9 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_string_utf8.h" +#include "BLI_fileops.h" +#include "BLI_fileops_types.h" +#include "BLI_linklist.h" #include "BLT_translation.h" @@ -223,7 +226,7 @@ static bool space_image_file_exists_poll(bContext *C) bool ret = false; char name[FILE_MAX]; - ibuf = ED_space_image_acquire_buffer(sima, &lock); + ibuf = ED_space_image_acquire_buffer(sima, &lock, 0); if (ibuf) { BLI_strncpy(name, ibuf->name, FILE_MAX); BLI_path_abs(name, BKE_main_blendfile_path(bmain)); @@ -1150,6 +1153,52 @@ static int image_cmp_frame(const void *a, const void *b) return 0; } +static int image_get_udim(const char *filepath, LinkNodePair *udim_tiles) +{ + if (strstr(filepath, "1001") == NULL) { + return 0; + } + + char filename[FILE_MAX], dirname[FILE_MAXDIR]; + BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename)); + + 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, SET_INT_IN_POINTER(id - 1001)); + 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 * @@ -1157,21 +1206,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; + frame = frame_range->frames.first; if (frame) { int frame_curr = frame->framenr; (*ofs) = frame_curr; - while (frame && (frame->framenr == frame_curr)) { - frame_curr++; - frame = frame->next; + + if (udim_tiles && (frame_curr == 1001)) { + return 1 + image_get_udim(frame_range->filepath, udim_tiles); + } + else { + while (frame && (frame->framenr == frame_curr)) { + frame_curr++; + frame = frame->next; + } + return frame_curr - (*ofs); } - return frame_curr - (*ofs); } *ofs = 0; return 0; @@ -1179,7 +1234,8 @@ static int image_sequence_get_len(ListBase *frames, int *ofs) static Image *image_open_single( Main *bmain, wmOperator *op, const char *filepath, const char *relbase, - bool is_relative_path, bool use_multiview, int frame_seq_len) + bool is_relative_path, bool use_multiview, int frame_seq_len, + int frame_seq_ofs, LinkNodePair *udim_tiles) { bool exists = false; Image *ima = NULL; @@ -1215,7 +1271,15 @@ static Image *image_open_single( } 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, GET_INT_FROM_POINTER(node->link), NULL); + } + } + else { + ima->source = IMA_SRC_SEQUENCE; + } } } @@ -1238,6 +1302,7 @@ static int image_open_exec(bContext *C, wmOperator *op) 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"); if (!op->customdata) image_open_init(C, op); @@ -1254,7 +1319,9 @@ static int image_open_exec(bContext *C, wmOperator *op) 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); + LinkNodePair udim_tiles = {NULL}; + int frame_range_seq_len = image_sequence_get_len(frame_range, &frame_range_ofs, + use_udim? &udim_tiles : NULL); BLI_freelistN(&frame_range->frames); char filepath_range[FILE_MAX]; @@ -1266,7 +1333,10 @@ static int image_open_exec(bContext *C, wmOperator *op) Image *ima_range = image_open_single( bmain, op, filepath_range, BKE_main_blendfile_path(bmain), - is_relative_path, use_multiview, frame_range_seq_len); + is_relative_path, use_multiview, frame_range_seq_len, frame_range_ofs, + use_udim? &udim_tiles : NULL); + + BLI_linklist_free(udim_tiles.list, NULL); /* take the first image */ if ((ima == NULL) && ima_range) { @@ -1278,10 +1348,17 @@ static int image_open_exec(bContext *C, wmOperator *op) BLI_freelistN(&frame_ranges_all); } else { + int sequence_len = 1; + LinkNodePair udim_tiles = {NULL}; + if (use_udim) { + sequence_len = image_get_udim(filepath, &udim_tiles); + } /* for drag & drop etc. */ ima = image_open_single( bmain, op, filepath, BKE_main_blendfile_path(bmain), - is_relative_path, use_multiview, 1); + is_relative_path, use_multiview, 1, sequence_len, &udim_tiles); + + BLI_linklist_free(udim_tiles.list, NULL); } if (ima == NULL) { @@ -1331,7 +1408,7 @@ static int image_open_exec(bContext *C, wmOperator *op) /* initialize because of new image */ if (iuser) { - iuser->frames = frame_seq_len; + iuser->frames = (ima->source == IMA_SRC_SEQUENCE)? frame_seq_len : 1; iuser->sfra = 1; iuser->framenr = 1; if (ima->source == IMA_SRC_MOVIE) { @@ -1464,6 +1541,7 @@ void IMAGE_OT_open(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_sequence_detection", true, "Detect Sequences", "Automatically detect animated sequences in selected images (based on file names)"); + RNA_def_boolean(ot->srna, "use_udim", true, "Detect UDIMs", "Detect selected UDIM files and load all matching tiles"); } /******************** Match movie length operator ********************/ @@ -1630,7 +1708,7 @@ static int save_image_options_init(Main *bmain, SaveImageOptions *simopts, Space const bool guess_path, const bool save_as_render) { void *lock; - ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); + ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, 0); if (ibuf) { Image *ima = sima->image; @@ -1698,6 +1776,11 @@ static int save_image_options_init(Main *bmain, SaveImageOptions *simopts, Space BLI_snprintf(simopts->filepath, sizeof(simopts->filepath), "//%s", ima->id.name + 2); BLI_path_abs(simopts->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)) { + strncat(simopts->filepath, ".1001", sizeof(simopts->filepath) - 6); + } } /* color management */ @@ -1811,18 +1894,16 @@ static void save_imbuf_post(ImBuf *ibuf, ImBuf *colormanaged_ibuf) * \note ``ima->name`` and ``ibuf->name`` should end up the same. * \note for multiview the first ``ibuf`` is important to get the settings. */ -static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath) +static bool save_image_single(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath, int tile) { Main *bmain = CTX_data_main(C); Image *ima = ED_space_image(sima); void *lock; - ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); + ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, tile); Scene *scene; RenderResult *rr = NULL; bool ok = false; - WM_cursor_wait(1); - if (ibuf) { ImBuf *colormanaged_ibuf = NULL; const char *relbase = ID_BLEND_PATH(CTX_data_main(C), &ima->id); @@ -2036,11 +2117,49 @@ cleanup: BKE_image_release_renderresult(scene, ima); } - WM_cursor_wait(0); - return ok; } +static bool save_image_doit(bContext *C, SpaceImage *sima, wmOperator *op, SaveImageOptions *simopts, bool do_newpath) +{ + Image *ima = ED_space_image(sima); + + if (ima->source == IMA_SRC_TILED) { + if (BLI_stringdec(simopts->filepath, NULL, NULL, NULL) != 1001) { + BKE_reportf(op->reports, RPT_ERROR, + "When saving a tiled image, the path '%s' must contain the UDIM tag 1001", simopts->filepath); + return false; + } + } + + WM_cursor_wait(1); + + if (!save_image_single(C, sima, op, simopts, do_newpath, 0)) { + WM_cursor_wait(0); + return false; + } + + if (ima->source == IMA_SRC_TILED) { + char filepath[FILE_MAX]; + BLI_strncpy(filepath, simopts->filepath, sizeof(filepath)); + LISTBASE_FOREACH(ImageTile*, tile, &ima->tiles) { + if (tile->tile_number == 0) + continue; + + char head[FILE_MAX], tail[FILE_MAX]; + unsigned short numlen; + BLI_stringdec(filepath, head, tail, &numlen); + BLI_stringenc(simopts->filepath, head, tail, numlen, 1001 + tile->tile_number); + + save_image_single(C, sima, op, simopts, do_newpath, tile->tile_number); + } + BLI_strncpy(simopts->filepath, filepath, sizeof(simopts->filepath)); + } + + WM_cursor_wait(0); + return true; +} + static void image_save_as_free(wmOperator *op) { if (op->customdata) { @@ -2258,7 +2377,7 @@ static int image_save_sequence_exec(bContext *C, wmOperator *op) if (sima->image == NULL) return OPERATOR_CANCELLED; - if (sima->image->source != IMA_SRC_SEQUENCE) { + if (ELEM(sima->image->source, IMA_SRC_SEQUENCE, IMA_SRC_TILED)) { BKE_report(op->reports, RPT_ERROR, "Can only save sequence on image sequences"); return OPERATOR_CANCELLED; } @@ -2441,11 +2560,12 @@ 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); + ima = BKE_image_add_generated(bmain, width, height, name, alpha ? 32 : 24, floatbuf, gen_type, color, stereo3d, tiled); if (!ima) { image_new_free(op); @@ -2529,6 +2649,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); @@ -2577,6 +2700,8 @@ void IMAGE_OT_new(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); 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 @@ -2704,7 +2829,7 @@ static bool image_pack_test(bContext *C, wmOperator *op) if (!as_png && BKE_image_has_packedfile(ima)) 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; } @@ -2805,7 +2930,7 @@ static int image_unpack_exec(bContext *C, wmOperator *op) if (!ima || !BKE_image_has_packedfile(ima)) 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; } @@ -2833,7 +2958,7 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE if (!ima || !BKE_image_has_packedfile(ima)) 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; } @@ -2903,9 +3028,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) { @@ -2913,12 +3041,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); @@ -2944,10 +3070,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; @@ -2957,13 +3088,10 @@ 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) { + 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); - Image *image = ED_space_image(sima); + 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); @@ -3171,12 +3299,29 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) int x_end = RNA_int_get(op->ptr, "xend"); int y_end = RNA_int_get(op->ptr, "yend"); + float x1f, y1f, x2f, y2f; + 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); + + /* If the image has tiles, shift the positions accordingly. */ + Image *image = ED_space_image(sima); + int tile = 0, ix = 0, iy = 0; + if (image && image->source == IMA_SRC_TILED) { + ix = (int) x1f; + iy = (int) y1f; + CLAMP(ix, 0, 9); + + x1f -= ix; + x2f -= ix; + y1f -= iy; + y2f -= iy; + tile = 10*iy + ix; + } + 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; @@ -3187,13 +3332,12 @@ 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; + hist->draw_offset[0] = ix; + hist->draw_offset[1] = iy; /* enable line drawing */ hist->flag |= HISTO_FLAG_SAMPLELINE; @@ -3807,3 +3951,227 @@ void IMAGE_OT_clear_render_border(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } + +/* ********************* Add tile operator ****************** */ + +static bool add_tile_poll(bContext *C) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + + return (ima && ima->source == IMA_SRC_TILED && (BKE_image_get_tile(ima, sima->curtile) == NULL)); +} + +static int add_tile_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = ED_space_image(sima); + + if (BKE_image_add_tile(ima, sima->curtile, NULL) == NULL) + return OPERATOR_CANCELLED; + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_add_tile(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Add tile"; + ot->description = "Adds a tile to the image"; + ot->idname = "IMAGE_OT_add_tile"; + + /* api callbacks */ + ot->poll = add_tile_poll; + ot->exec = add_tile_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ********************* Remove tile operator ****************** */ + +static bool remove_tile_poll(bContext *C) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + + return (ima && ima->source == IMA_SRC_TILED && BKE_image_get_tile(ima, sima->curtile)); +} + +static int remove_tile_exec(bContext *C, wmOperator *UNUSED(op)) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = ED_space_image(sima); + + ImageTile *tile = BKE_image_get_tile(ima, sima->curtile); + if (!BKE_image_remove_tile(ima, tile)) + return OPERATOR_CANCELLED; + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_remove_tile(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Remove tile"; + ot->description = "Removes a tile from the image"; + ot->idname = "IMAGE_OT_remove_tile"; + + /* api callbacks */ + ot->poll = remove_tile_poll; + ot->exec = remove_tile_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* ********************* Fill tile operator ****************** */ + +static bool fill_tile_poll(bContext *C) +{ + Image *ima = CTX_data_edit_image(C); + SpaceImage *sima = CTX_wm_space_image(C); + + return (ima && ima->source == IMA_SRC_TILED && BKE_image_get_tile(ima, sima->curtile)); +} + +static int fill_tile_exec(bContext *C, wmOperator *op) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = ED_space_image(sima); + + 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"); + + ImageTile *tile = BKE_image_get_tile(ima, sima->curtile); + if (!BKE_image_fill_tile(ima, tile, width, height, color, gen_type)) + return OPERATOR_CANCELLED; + + WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); + + return OPERATOR_FINISHED; +} + +static int fill_tile_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = ED_space_image(sima); + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, NULL); + if (ibuf) { + RNA_int_set(op->ptr, "width", ibuf->x); + RNA_int_set(op->ptr, "height", ibuf->y); + 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 fill_tile_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], IFACE_("Generated Type"), ICON_NONE); + uiItemR(col[1], &ptr, "generated_type", 0, "", ICON_NONE); +} + +void IMAGE_OT_fill_tile(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Fill tile"; + ot->description = "Fill the current tile with a generated image"; + ot->idname = "IMAGE_OT_fill_tile"; + + /* api callbacks */ + ot->poll = fill_tile_poll; + ot->exec = fill_tile_exec; + ot->invoke = fill_tile_invoke; + ot->ui = fill_tile_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); +} + +/* ********************* Select tile operator ****************** */ + +static bool image_select_tile_poll(bContext *C) +{ + SpaceImage *sima = CTX_wm_space_image(C); + Image *ima = CTX_data_edit_image(C); + + if (ima) { + return (ima->source == IMA_SRC_TILED); + } + else { + return (sima->tile_grid_shape[0] > 1) || (sima->tile_grid_shape[1] > 1); + } +} + +static int image_select_tile_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + SpaceImage *sima = CTX_wm_space_image(C); + ARegion *ar = CTX_wm_region(C); + + float uv[2]; + UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &uv[0], &uv[1]); + + if (uv[0] >= 0.0f && uv[1] >= 0.0f && uv[0] < 10.0f) { + int tx = (int) uv[0]; + int ty = (int) uv[1]; + + sima->curtile = 10*ty + tx; + + WM_event_add_notifier(C, NC_WINDOW, NULL); + return OPERATOR_FINISHED; + } + + return OPERATOR_CANCELLED; +} + +void IMAGE_OT_select_tile(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Select tile"; + ot->idname = "IMAGE_OT_select_tile"; + ot->description = "Use mouse to select a tile of the image"; + + /* api callbacks */ + ot->invoke = image_select_tile_invoke; + ot->poll = image_select_tile_poll; +}
\ No newline at end of file |