diff options
author | Julian Eisel <julian@blender.org> | 2020-03-26 23:03:42 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2020-03-26 23:18:45 +0300 |
commit | c94b6209861ca7cc3985b53474feed7d94c0221a (patch) | |
tree | 752054f0dca1338cda5cf8ad4f6d18573fcca3b9 /source/blender/editors/space_image | |
parent | 357ed79cb93f9d655501a828c6cddd68282de62d (diff) | |
parent | afb1a64ccb81b7ed792f64151986f40f53af8da5 (diff) |
Merge branch 'master' into wm-drag-drop-rewrite
Diffstat (limited to 'source/blender/editors/space_image')
-rw-r--r-- | source/blender/editors/space_image/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_buttons.c | 16 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_draw.c | 152 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_edit.c | 126 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_intern.h | 4 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_ops.c | 687 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_sequence.c | 248 | ||||
-rw-r--r-- | source/blender/editors/space_image/image_undo.c | 63 | ||||
-rw-r--r-- | source/blender/editors/space_image/space_image.c | 254 |
9 files changed, 849 insertions, 702 deletions
diff --git a/source/blender/editors/space_image/CMakeLists.txt b/source/blender/editors/space_image/CMakeLists.txt index 5abcff436f1..12de74c6ae7 100644 --- a/source/blender/editors/space_image/CMakeLists.txt +++ b/source/blender/editors/space_image/CMakeLists.txt @@ -43,6 +43,7 @@ set(SRC image_draw.c image_edit.c image_ops.c + image_sequence.c image_undo.c space_image.c diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index 270fe0c59dc..873091bd68d 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -21,8 +21,8 @@ * \ingroup spimage */ -#include <string.h> #include <stdio.h> +#include <string.h> #include "DNA_node_types.h" #include "DNA_scene_types.h" @@ -37,8 +37,8 @@ #include "BKE_context.h" #include "BKE_image.h" #include "BKE_node.h" -#include "BKE_screen.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "RE_pipeline.h" @@ -47,8 +47,8 @@ #include "IMB_imbuf_types.h" #include "ED_gpencil.h" -#include "ED_screen.h" #include "ED_image.h" +#include "ED_screen.h" #include "RNA_access.h" @@ -980,6 +980,16 @@ void uiTemplateImage(uiLayout *layout, bool is_data = IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name); uiLayoutSetActive(sub, !is_data); } + + if (ima && iuser) { + void *lock; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, iuser, &lock); + + if (ibuf && ibuf->rect_float && (ibuf->flags & IB_halffloat) == 0) { + uiItemR(col, &imaptr, "use_half_precision", 0, NULL, ICON_NONE); + } + BKE_image_release_ibuf(ima, ibuf, lock); + } } uiItemR(col, &imaptr, "use_view_as_render", 0, NULL, ICON_NONE); diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index 3f563fe9033..85f7f744abc 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -27,26 +27,26 @@ #include "MEM_guardedalloc.h" +#include "DNA_brush_types.h" #include "DNA_camera_types.h" +#include "DNA_mask_types.h" #include "DNA_object_types.h" -#include "DNA_space_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" -#include "DNA_brush_types.h" -#include "DNA_mask_types.h" +#include "DNA_space_types.h" #include "PIL_time.h" #include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_rect.h" -#include "BLI_threads.h" #include "BLI_string.h" +#include "BLI_threads.h" #include "BLI_utildefines.h" +#include "IMB_colormanagement.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" -#include "IMB_colormanagement.h" #include "IMB_moviecache.h" #include "BKE_context.h" @@ -72,13 +72,13 @@ #include "UI_resources.h" #include "UI_view2d.h" -#include "RE_pipeline.h" #include "RE_engine.h" +#include "RE_pipeline.h" #include "image_intern.h" static void draw_render_info( - const bContext *C, Scene *scene, Image *ima, ARegion *ar, float zoomx, float zoomy) + const bContext *C, Scene *scene, Image *ima, ARegion *region, float zoomx, float zoomy) { Render *re = RE_GetSceneRender(scene); RenderData *rd = RE_engine_get_render_data(re); @@ -91,7 +91,7 @@ static void draw_render_info( if (rr && rr->text) { float fill_color[4] = {0.0f, 0.0f, 0.0f, 0.25f}; - ED_region_info_draw(ar, rr->text, fill_color, true); + ED_region_info_draw(region, rr->text, fill_color, true); } BKE_image_release_renderresult(stats_scene, ima); @@ -104,7 +104,7 @@ static void draw_render_info( if (total_tiles) { /* find window pixel coordinates of origin */ int x, y; - UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y); + UI_view2d_view_to_region(®ion->v2d, 0.0f, 0.0f, &x, &y); GPU_matrix_push(); GPU_matrix_translate_2f(x, y); @@ -141,13 +141,13 @@ static void draw_render_info( /* used by node view too */ void ED_image_draw_info(Scene *scene, - ARegion *ar, + ARegion *region, bool color_manage, bool use_default_view, int channels, int x, int y, - const unsigned char cp[4], + const uchar cp[4], const float fp[4], const float linearcol[4], int *zp, @@ -157,20 +157,20 @@ void ED_image_draw_info(Scene *scene, char str[256]; int dx = 6; /* local coordinate visible rect inside region, to accommodate overlapping ui */ - const rcti *rect = ED_region_visible_rect(ar); + const rcti *rect = ED_region_visible_rect(region); const int ymin = rect->ymin; const int dy = ymin + 0.3f * UI_UNIT_Y; /* text colors */ /* XXX colored text not allowed in Blender UI */ #if 0 - unsigned char red[3] = {255, 50, 50}; - unsigned char green[3] = {0, 255, 0}; - unsigned char blue[3] = {100, 100, 255}; + uchar red[3] = {255, 50, 50}; + uchar green[3] = {0, 255, 0}; + uchar blue[3] = {100, 100, 255}; #else - unsigned char red[3] = {255, 255, 255}; - unsigned char green[3] = {255, 255, 255}; - unsigned char blue[3] = {255, 255, 255}; + uchar red[3] = {255, 255, 255}; + uchar green[3] = {255, 255, 255}; + uchar blue[3] = {255, 255, 255}; #endif float hue = 0, sat = 0, val = 0, lum = 0, u = 0, v = 0; float col[4], finalcol[4]; @@ -185,7 +185,7 @@ void ED_image_draw_info(Scene *scene, /* noisy, high contrast make impossible to read if lower alpha is used. */ immUniformColor4ub(0, 0, 0, 190); - immRecti(pos, 0, ymin, BLI_rcti_size_x(&ar->winrct) + 1, ymin + UI_UNIT_Y); + immRecti(pos, 0, ymin, BLI_rcti_size_x(®ion->winrct) + 1, ymin + UI_UNIT_Y); immUnbindProgram(); @@ -532,7 +532,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene, MEM_freeN(rectf); } -static void draw_udim_label(ARegion *ar, float fx, float fy, const char *label) +static void draw_udim_label(ARegion *region, float fx, float fy, const char *label) { if (label == NULL || !label[0]) { return; @@ -540,14 +540,14 @@ static void draw_udim_label(ARegion *ar, float fx, float fy, const char *label) /* find window pixel coordinates of origin */ int x, y; - UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y); + UI_view2d_view_to_region(®ion->v2d, fx, fy, &x, &y); GPU_blend_set_func_separate( GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); GPU_blend(true); int textwidth = BLF_width(blf_mono_font, label, strlen(label)) + 10; - float stepx = BLI_rcti_size_x(&ar->v2d.mask) / BLI_rctf_size_x(&ar->v2d.cur); + float stepx = BLI_rcti_size_x(®ion->v2d.mask) / BLI_rctf_size_x(®ion->v2d.cur); float opacity; if (textwidth < 0.5f * (stepx - 10)) { opacity = 1.0f; @@ -567,7 +567,7 @@ static void draw_udim_label(ARegion *ar, float fx, float fy, const char *label) static void draw_image_buffer(const bContext *C, SpaceImage *sima, - ARegion *ar, + ARegion *region, Scene *scene, ImBuf *ibuf, float fx, @@ -576,12 +576,13 @@ static void draw_image_buffer(const bContext *C, float zoomy) { int x, y; + int sima_flag = sima->flag & ED_space_image_get_display_channel_mask(ibuf); /* find window pixel coordinates of origin */ - UI_view2d_view_to_region(&ar->v2d, fx, fy, &x, &y); + UI_view2d_view_to_region(®ion->v2d, fx, fy, &x, &y); /* this part is generic image display */ - if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { + if (sima_flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { if (ibuf->zbuf) { sima_draw_zbuf_pixels(x, y, ibuf->x, ibuf->y, ibuf->zbuf, zoomx, zoomy); } @@ -595,9 +596,9 @@ static void draw_image_buffer(const bContext *C, else { int clip_max_x, clip_max_y; UI_view2d_view_to_region( - &ar->v2d, ar->v2d.cur.xmax, ar->v2d.cur.ymax, &clip_max_x, &clip_max_y); + ®ion->v2d, region->v2d.cur.xmax, region->v2d.cur.ymax, &clip_max_x, &clip_max_y); - if (sima->flag & SI_USE_ALPHA) { + if (sima_flag & SI_USE_ALPHA) { imm_draw_box_checker_2d(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy); GPU_blend(true); @@ -606,28 +607,28 @@ static void draw_image_buffer(const bContext *C, } /* If RGBA display with color management */ - if ((sima->flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) { + if ((sima_flag & (SI_SHOW_R | SI_SHOW_G | SI_SHOW_B | SI_SHOW_ALPHA)) == 0) { ED_draw_imbuf_ctx_clipping( C, ibuf, x, y, GL_NEAREST, 0, 0, clip_max_x, clip_max_y, zoomx, zoomy); } else { float shuffle[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - unsigned char *display_buffer; + uchar *display_buffer; void *cache_handle; ColorManagedViewSettings *view_settings; ColorManagedDisplaySettings *display_settings; - if (sima->flag & SI_SHOW_R) { + if (sima_flag & SI_SHOW_R) { shuffle[0] = 1.0f; } - else if (sima->flag & SI_SHOW_G) { + else if (sima_flag & SI_SHOW_G) { shuffle[1] = 1.0f; } - else if (sima->flag & SI_SHOW_B) { + else if (sima_flag & SI_SHOW_B) { shuffle[2] = 1.0f; } - else if (sima->flag & SI_SHOW_ALPHA) { + else if (sima_flag & SI_SHOW_ALPHA) { shuffle[3] = 1.0f; } @@ -661,7 +662,7 @@ static void draw_image_buffer(const bContext *C, IMB_display_buffer_release(cache_handle); } - if (sima->flag & SI_USE_ALPHA) { + if (sima_flag & SI_USE_ALPHA) { GPU_blend(false); } } @@ -669,7 +670,7 @@ static void draw_image_buffer(const bContext *C, static void draw_image_buffer_repeated(const bContext *C, SpaceImage *sima, - ARegion *ar, + ARegion *region, Scene *scene, ImBuf *ibuf, float zoomx, @@ -677,14 +678,14 @@ static void draw_image_buffer_repeated(const bContext *C, { const double time_current = PIL_check_seconds_timer(); - const int xmax = ceil(ar->v2d.cur.xmax); - const int ymax = ceil(ar->v2d.cur.ymax); - const int xmin = floor(ar->v2d.cur.xmin); - const int ymin = floor(ar->v2d.cur.ymin); + const int xmax = ceil(region->v2d.cur.xmax); + const int ymax = ceil(region->v2d.cur.ymax); + const int xmin = floor(region->v2d.cur.xmin); + const int ymin = floor(region->v2d.cur.ymin); for (int x = xmin; x < xmax; x++) { for (int y = ymin; y < ymax; y++) { - draw_image_buffer(C, sima, ar, scene, ibuf, x, y, zoomx, zoomy); + draw_image_buffer(C, sima, region, scene, ibuf, x, y, zoomx, zoomy); /* only draw until running out of time */ if ((PIL_check_seconds_timer() - time_current) > 0.25) { @@ -744,7 +745,7 @@ void draw_image_sample_line(SpaceImage *sima) } static void draw_image_paint_helpers( - const bContext *C, ARegion *ar, Scene *scene, float zoomx, float zoomy) + const bContext *C, ARegion *region, Scene *scene, float zoomx, float zoomy) { Brush *brush; int x, y; @@ -758,9 +759,10 @@ static void draw_image_paint_helpers( if (ibuf) { void *cache_handle = NULL; float col[4] = {1.0f, 1.0f, 1.0f, brush->clone.alpha}; - UI_view2d_view_to_region(&ar->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y); + UI_view2d_view_to_region( + ®ion->v2d, brush->clone.offset[0], brush->clone.offset[1], &x, &y); - unsigned char *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + uchar *display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); if (!display_buffer) { BKE_image_release_ibuf(brush->clone.image, ibuf, NULL); @@ -794,9 +796,9 @@ static void draw_image_paint_helpers( } } -static void draw_udim_tile_grid(unsigned int pos_attr, - unsigned int color_attr, - ARegion *ar, +static void draw_udim_tile_grid(uint pos_attr, + uint color_attr, + ARegion *region, int x, int y, float stepx, @@ -804,7 +806,7 @@ static void draw_udim_tile_grid(unsigned int pos_attr, const float color[3]) { float x1, y1; - UI_view2d_view_to_region_fl(&ar->v2d, x, y, &x1, &y1); + UI_view2d_view_to_region_fl(®ion->v2d, x, y, &x1, &y1); int gridpos[5][2] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}, {0, 0}}; for (int i = 0; i < 4; i++) { immAttr3fv(color_attr, color); @@ -814,7 +816,7 @@ static void draw_udim_tile_grid(unsigned int pos_attr, } } -static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima) +static void draw_udim_tile_grids(ARegion *region, SpaceImage *sima, Image *ima) { int num_tiles; if (ima != NULL) { @@ -828,12 +830,12 @@ static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima) num_tiles = sima->tile_grid_shape[0] * sima->tile_grid_shape[1]; } - float stepx = BLI_rcti_size_x(&ar->v2d.mask) / BLI_rctf_size_x(&ar->v2d.cur); - float stepy = BLI_rcti_size_y(&ar->v2d.mask) / BLI_rctf_size_y(&ar->v2d.cur); + float stepx = BLI_rcti_size_x(®ion->v2d.mask) / BLI_rctf_size_x(®ion->v2d.cur); + float stepy = BLI_rcti_size_y(®ion->v2d.mask) / BLI_rctf_size_y(®ion->v2d.cur); GPUVertFormat *format = immVertexFormat(); - unsigned int pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); - unsigned color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); + uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + uint color = GPU_vertformat_attr_add(format, "color", GPU_COMP_F32, 3, GPU_FETCH_FLOAT); immBindBuiltinProgram(GPU_SHADER_2D_FLAT_COLOR); immBegin(GPU_PRIM_LINES, 8 * num_tiles); @@ -849,20 +851,20 @@ static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima) if (tile != cur_tile) { int x = (tile->tile_number - 1001) % 10; int y = (tile->tile_number - 1001) / 10; - draw_udim_tile_grid(pos, color, ar, x, y, stepx, stepy, theme_color); + draw_udim_tile_grid(pos, color, region, x, y, stepx, stepy, theme_color); } } if (cur_tile != NULL) { int cur_x = (cur_tile->tile_number - 1001) % 10; int cur_y = (cur_tile->tile_number - 1001) / 10; - draw_udim_tile_grid(pos, color, ar, cur_x, cur_y, stepx, stepy, selected_color); + draw_udim_tile_grid(pos, color, region, cur_x, cur_y, stepx, stepy, selected_color); } } else { for (int y = 0; y < sima->tile_grid_shape[1]; y++) { for (int x = 0; x < sima->tile_grid_shape[0]; x++) { - draw_udim_tile_grid(pos, color, ar, x, y, stepx, stepy, theme_color); + draw_udim_tile_grid(pos, color, region, x, y, stepx, stepy, theme_color); } } } @@ -873,7 +875,7 @@ static void draw_udim_tile_grids(ARegion *ar, SpaceImage *sima, Image *ima) /* draw main image region */ -void draw_image_main(const bContext *C, ARegion *ar) +void draw_image_main(const bContext *C, ARegion *region) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); @@ -905,7 +907,7 @@ void draw_image_main(const bContext *C, ARegion *ar) /* retrieve the image and information about it */ ima = ED_space_image(sima); - ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy); + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); /* Tag image as in active use for garbage collector. */ if (ima) { @@ -949,31 +951,31 @@ void draw_image_main(const bContext *C, ARegion *ar) LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) { int x = (tile->tile_number - 1001) % 10; int y = (tile->tile_number - 1001) / 10; - ED_region_grid_draw(ar, zoomx, zoomy, x, y); + ED_region_grid_draw(region, zoomx, zoomy, x, y); } } else { for (int y = 0; y < sima->tile_grid_shape[1]; y++) { for (int x = 0; x < sima->tile_grid_shape[0]; x++) { - ED_region_grid_draw(ar, zoomx, zoomy, x, y); + ED_region_grid_draw(region, zoomx, zoomy, x, y); } } } } else { if (sima->flag & SI_DRAW_TILE) { - draw_image_buffer_repeated(C, sima, ar, scene, ibuf, zoomx, zoomy); + draw_image_buffer_repeated(C, sima, region, scene, ibuf, zoomx, zoomy); } else { main_w = ibuf->x; main_h = ibuf->y; - draw_image_buffer(C, sima, ar, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); + draw_image_buffer(C, sima, region, scene, ibuf, 0.0f, 0.0f, zoomx, zoomy); if (ima->source == IMA_SRC_TILED) { ImageTile *tile = BKE_image_get_tile(ima, 0); char label[sizeof(tile->label)]; BKE_image_get_tile_label(ima, tile, label, sizeof(label)); - draw_udim_label(ar, 0.0f, 0.0f, label); + draw_udim_label(region, 0.0f, 0.0f, label); } } @@ -982,7 +984,7 @@ void draw_image_main(const bContext *C, ARegion *ar) rctf frame; BLI_rctf_init(&frame, 0.0f, ibuf->x, 0.0f, ibuf->y); - UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &x, &y); + UI_view2d_view_to_region(®ion->v2d, 0.0f, 0.0f, &x, &y); ED_region_image_metadata_draw(x, y, ibuf, &frame, zoomx, zoomy); } @@ -1005,18 +1007,18 @@ void draw_image_main(const bContext *C, ARegion *ar) float tile_zoomx = (zoomx * main_w) / ibuf->x; float tile_zoomy = (zoomy * main_h) / ibuf->y; - draw_image_buffer(C, sima, ar, scene, ibuf, x_pos, y_pos, tile_zoomx, tile_zoomy); - draw_udim_label(ar, x_pos, y_pos, label); + draw_image_buffer(C, sima, region, scene, ibuf, x_pos, y_pos, tile_zoomx, tile_zoomy); + draw_udim_label(region, x_pos, y_pos, label); } ED_space_image_release_buffer(sima, ibuf, lock); } } - draw_udim_tile_grids(ar, sima, ima); + draw_udim_tile_grids(region, sima, ima); /* paint helpers */ if (show_paint) { - draw_image_paint_helpers(C, ar, scene, zoomx, zoomy); + draw_image_paint_helpers(C, region, scene, zoomx, zoomy); } if (show_viewer) { @@ -1025,7 +1027,7 @@ void draw_image_main(const bContext *C, ARegion *ar) /* render info */ if (ima && show_render) { - draw_render_info(C, sima->iuser.scene, ima, ar, zoomx, zoomy); + draw_render_info(C, sima->iuser.scene, ima, region, zoomx, zoomy); } } @@ -1045,12 +1047,12 @@ bool ED_space_image_show_cache(SpaceImage *sima) return true; } -void draw_image_cache(const bContext *C, ARegion *ar) +void draw_image_cache(const bContext *C, ARegion *region) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); Image *image = ED_space_image(sima); - float x, cfra = CFRA, sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1); + float x, cfra = CFRA, sfra = SFRA, efra = EFRA, framelen = region->winx / (efra - sfra + 1); Mask *mask = NULL; if (!ED_space_image_show_cache(sima)) { @@ -1062,7 +1064,7 @@ void draw_image_cache(const bContext *C, ARegion *ar) } /* Local coordinate visible rect inside region, to accommodate overlapping ui. */ - const rcti *rect_visible = ED_region_visible_rect(ar); + const rcti *rect_visible = ED_region_visible_rect(region); const int region_bottom = rect_visible->ymin; GPU_blend(true); @@ -1070,7 +1072,7 @@ void draw_image_cache(const bContext *C, ARegion *ar) GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_ONE, GPU_ONE_MINUS_SRC_ALPHA); /* Draw cache background. */ - ED_region_cache_draw_background(ar); + ED_region_cache_draw_background(region); /* Draw cached segments. */ if (image != NULL && image->cache != NULL && @@ -1080,13 +1082,13 @@ void draw_image_cache(const bContext *C, ARegion *ar) IMB_moviecache_get_cache_segments(image->cache, IMB_PROXY_NONE, 0, &num_segments, &points); ED_region_cache_draw_cached_segments( - ar, num_segments, points, sfra + sima->iuser.offset, efra + sima->iuser.offset); + region, num_segments, points, sfra + sima->iuser.offset, efra + sima->iuser.offset); } GPU_blend(false); /* Draw current frame. */ - x = (cfra - sfra) / (efra - sfra + 1) * ar->winx; + x = (cfra - sfra) / (efra - sfra + 1) * region->winx; uint pos = GPU_vertformat_attr_add( immVertexFormat(), "pos", GPU_COMP_I32, 2, GPU_FETCH_INT_TO_FLOAT); @@ -1098,6 +1100,6 @@ void draw_image_cache(const bContext *C, ARegion *ar) ED_region_cache_draw_curfra_label(cfra, x, region_bottom + 8.0f * UI_DPI_FAC); if (mask != NULL) { - ED_mask_draw_frames(mask, ar, cfra, sfra, efra); + ED_mask_draw_frames(mask, region, cfra, sfra, efra); } } diff --git a/source/blender/editors/space_image/image_edit.c b/source/blender/editors/space_image/image_edit.c index c1ed049130e..7f911113b7c 100644 --- a/source/blender/editors/space_image/image_edit.c +++ b/source/blender/editors/space_image/image_edit.c @@ -26,15 +26,15 @@ #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "BLI_rect.h" #include "BLI_listbase.h" +#include "BLI_rect.h" #include "BKE_colortools.h" #include "BKE_context.h" #include "BKE_editmesh.h" #include "BKE_global.h" #include "BKE_image.h" -#include "BKE_library.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "IMB_imbuf_types.h" @@ -175,6 +175,30 @@ void ED_space_image_release_buffer(SpaceImage *sima, ImBuf *ibuf, void *lock) } } +/* Get the SpaceImage flag that is valid for the given ibuf. */ +int ED_space_image_get_display_channel_mask(ImBuf *ibuf) +{ + int result = (SI_USE_ALPHA | SI_SHOW_ALPHA | SI_SHOW_ZBUF | SI_SHOW_R | SI_SHOW_G | SI_SHOW_B); + if (!ibuf) { + return result; + } + + const bool color = ibuf->channels >= 3; + const bool alpha = ibuf->channels == 4; + const bool zbuf = ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1); + + if (!alpha) { + result &= ~(SI_USE_ALPHA | SI_SHOW_ALPHA); + } + if (!zbuf) { + result &= ~(SI_SHOW_ZBUF); + } + if (!color) { + result &= ~(SI_SHOW_R | SI_SHOW_G | SI_SHOW_B); + } + return result; +} + bool ED_space_image_has_buffer(SpaceImage *sima) { ImBuf *ibuf; @@ -188,7 +212,7 @@ bool ED_space_image_has_buffer(SpaceImage *sima) return has_buffer; } -void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) +void ED_space_image_get_size(SpaceImage *sima, int *r_width, int *r_height) { Scene *scene = sima->iuser.scene; ImBuf *ibuf; @@ -198,107 +222,107 @@ void ED_space_image_get_size(SpaceImage *sima, int *width, int *height) ibuf = ED_space_image_acquire_buffer(sima, &lock, 0); if (ibuf && ibuf->x > 0 && ibuf->y > 0) { - *width = ibuf->x; - *height = ibuf->y; + *r_width = ibuf->x; + *r_height = ibuf->y; } else if (sima->image && sima->image->type == IMA_TYPE_R_RESULT && scene) { /* not very important, just nice */ - *width = (scene->r.xsch * scene->r.size) / 100; - *height = (scene->r.ysch * scene->r.size) / 100; + *r_width = (scene->r.xsch * scene->r.size) / 100; + *r_height = (scene->r.ysch * scene->r.size) / 100; if ((scene->r.mode & R_BORDER) && (scene->r.mode & R_CROP)) { - *width *= BLI_rctf_size_x(&scene->r.border); - *height *= BLI_rctf_size_y(&scene->r.border); + *r_width *= BLI_rctf_size_x(&scene->r.border); + *r_height *= BLI_rctf_size_y(&scene->r.border); } } /* I know a bit weak... but preview uses not actual image size */ - // XXX else if (image_preview_active(sima, width, height)); + // XXX else if (image_preview_active(sima, r_width, r_height)); else { - *width = IMG_SIZE_FALLBACK; - *height = IMG_SIZE_FALLBACK; + *r_width = IMG_SIZE_FALLBACK; + *r_height = IMG_SIZE_FALLBACK; } ED_space_image_release_buffer(sima, ibuf, lock); } -void ED_space_image_get_size_fl(SpaceImage *sima, float size[2]) +void ED_space_image_get_size_fl(SpaceImage *sima, float r_size[2]) { int size_i[2]; ED_space_image_get_size(sima, &size_i[0], &size_i[1]); - size[0] = size_i[0]; - size[1] = size_i[1]; + r_size[0] = size_i[0]; + r_size[1] = size_i[1]; } -void ED_space_image_get_aspect(SpaceImage *sima, float *aspx, float *aspy) +void ED_space_image_get_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy) { Image *ima = sima->image; if ((ima == NULL) || (ima->aspx == 0.0f || ima->aspy == 0.0f)) { - *aspx = *aspy = 1.0; + *r_aspx = *r_aspy = 1.0; } else { - BKE_image_get_aspect(ima, aspx, aspy); + BKE_image_get_aspect(ima, r_aspx, r_aspy); } } -void ED_space_image_get_zoom(SpaceImage *sima, ARegion *ar, float *zoomx, float *zoomy) +void ED_space_image_get_zoom(SpaceImage *sima, ARegion *region, float *r_zoomx, float *r_zoomy) { int width, height; ED_space_image_get_size(sima, &width, &height); - *zoomx = (float)(BLI_rcti_size_x(&ar->winrct) + 1) / - (float)(BLI_rctf_size_x(&ar->v2d.cur) * width); - *zoomy = (float)(BLI_rcti_size_y(&ar->winrct) + 1) / - (float)(BLI_rctf_size_y(&ar->v2d.cur) * height); + *r_zoomx = (float)(BLI_rcti_size_x(®ion->winrct) + 1) / + (float)(BLI_rctf_size_x(®ion->v2d.cur) * width); + *r_zoomy = (float)(BLI_rcti_size_y(®ion->winrct) + 1) / + (float)(BLI_rctf_size_y(®ion->v2d.cur) * height); } -void ED_space_image_get_uv_aspect(SpaceImage *sima, float *aspx, float *aspy) +void ED_space_image_get_uv_aspect(SpaceImage *sima, float *r_aspx, float *r_aspy) { int w, h; - ED_space_image_get_aspect(sima, aspx, aspy); + ED_space_image_get_aspect(sima, r_aspx, r_aspy); ED_space_image_get_size(sima, &w, &h); - *aspx *= (float)w; - *aspy *= (float)h; + *r_aspx *= (float)w; + *r_aspy *= (float)h; - if (*aspx < *aspy) { - *aspy = *aspy / *aspx; - *aspx = 1.0f; + if (*r_aspx < *r_aspy) { + *r_aspy = *r_aspy / *r_aspx; + *r_aspx = 1.0f; } else { - *aspx = *aspx / *aspy; - *aspy = 1.0f; + *r_aspx = *r_aspx / *r_aspy; + *r_aspy = 1.0f; } } -void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *aspx, float *aspy) +void ED_image_get_uv_aspect(Image *ima, ImageUser *iuser, float *r_aspx, float *r_aspy) { if (ima) { int w, h; - BKE_image_get_aspect(ima, aspx, aspy); + BKE_image_get_aspect(ima, r_aspx, r_aspy); BKE_image_get_size(ima, iuser, &w, &h); - *aspx *= (float)w; - *aspy *= (float)h; + *r_aspx *= (float)w; + *r_aspy *= (float)h; } else { - *aspx = 1.0f; - *aspy = 1.0f; + *r_aspx = 1.0f; + *r_aspy = 1.0f; } } /* takes event->mval */ -void ED_image_mouse_pos(SpaceImage *sima, ARegion *ar, const int mval[2], float co[2]) +void ED_image_mouse_pos(SpaceImage *sima, ARegion *region, const int mval[2], float co[2]) { int sx, sy, width, height; float zoomx, zoomy; - ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy); + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); ED_space_image_get_size(sima, &width, &height); - UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy); + UI_view2d_view_to_region(®ion->v2d, 0.0f, 0.0f, &sx, &sy); co[0] = ((mval[0] - sx) / zoomx) / width; co[1] = ((mval[1] - sy) / zoomy) / height; @@ -316,29 +340,33 @@ void ED_image_view_center_to_point(SpaceImage *sima, float x, float y) sima->yof = (y - 0.5f) * height * aspy; } -void ED_image_point_pos(SpaceImage *sima, ARegion *ar, float x, float y, float *xr, float *yr) +void ED_image_point_pos( + SpaceImage *sima, ARegion *region, float x, float y, float *r_x, float *r_y) { int sx, sy, width, height; float zoomx, zoomy; - ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy); + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); ED_space_image_get_size(sima, &width, &height); - UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy); + UI_view2d_view_to_region(®ion->v2d, 0.0f, 0.0f, &sx, &sy); - *xr = ((x - sx) / zoomx) / width; - *yr = ((y - sy) / zoomy) / height; + *r_x = ((x - sx) / zoomx) / width; + *r_y = ((y - sy) / zoomy) / height; } -void ED_image_point_pos__reverse(SpaceImage *sima, ARegion *ar, const float co[2], float r_co[2]) +void ED_image_point_pos__reverse(SpaceImage *sima, + ARegion *region, + const float co[2], + float r_co[2]) { float zoomx, zoomy; int width, height; int sx, sy; - UI_view2d_view_to_region(&ar->v2d, 0.0f, 0.0f, &sx, &sy); + UI_view2d_view_to_region(®ion->v2d, 0.0f, 0.0f, &sx, &sy); ED_space_image_get_size(sima, &width, &height); - ED_space_image_get_zoom(sima, ar, &zoomx, &zoomy); + ED_space_image_get_zoom(sima, region, &zoomx, &zoomy); r_co[0] = (co[0] * width * zoomx) + (float)sx; r_co[1] = (co[1] * height * zoomy) + (float)sy; diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index f3ec68db562..ae26363ad79 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -37,8 +37,8 @@ struct wmOperatorType; extern const char *image_context_dir[]; /* doc access */ /* image_draw.c */ -void draw_image_main(const struct bContext *C, struct ARegion *ar); -void draw_image_cache(const struct bContext *C, struct ARegion *ar); +void draw_image_main(const struct bContext *C, struct ARegion *region); +void draw_image_cache(const struct bContext *C, struct ARegion *region); void draw_image_grease_pencil(struct bContext *C, bool onlyv2d); void draw_image_sample_line(struct SpaceImage *sima); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 17c6f76a1d9..7bd1b8e8291 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -21,11 +21,11 @@ * \ingroup spimage */ -#include <stddef.h> -#include <string.h> +#include <errno.h> #include <fcntl.h> +#include <stddef.h> #include <stdlib.h> -#include <errno.h> +#include <string.h> #ifndef WIN32 # include <unistd.h> #else @@ -46,31 +46,31 @@ #include "BLT_translation.h" #include "DNA_camera_types.h" -#include "DNA_object_types.h" #include "DNA_node_types.h" +#include "DNA_object_types.h" #include "DNA_packedFile_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "BKE_colortools.h" #include "BKE_context.h" +#include "BKE_global.h" #include "BKE_icons.h" #include "BKE_image.h" #include "BKE_image_save.h" -#include "BKE_global.h" -#include "BKE_library.h" +#include "BKE_lib_id.h" #include "BKE_main.h" #include "BKE_packedFile.h" #include "BKE_paint.h" #include "BKE_report.h" -#include "BKE_screen.h" #include "BKE_scene.h" +#include "BKE_screen.h" #include "DEG_depsgraph.h" #include "GPU_draw.h" -#include "GPU_state.h" #include "GPU_immediate.h" +#include "GPU_state.h" #include "IMB_colormanagement.h" #include "IMB_imbuf.h" @@ -90,8 +90,8 @@ #include "ED_render.h" #include "ED_screen.h" #include "ED_space_api.h" -#include "ED_uvedit.h" #include "ED_util.h" +#include "ED_uvedit.h" #include "UI_interface.h" #include "UI_resources.h" @@ -111,7 +111,7 @@ * \{ */ static void sima_zoom_set( - SpaceImage *sima, ARegion *ar, float zoom, const float location[2], const bool zoom_to_pos) + SpaceImage *sima, ARegion *region, float zoom, const float location[2], const bool zoom_to_pos) { float oldzoom = sima->zoom; int width, height; @@ -128,10 +128,10 @@ static void sima_zoom_set( if ((width < 4) && (height < 4) && sima->zoom < oldzoom) { sima->zoom = oldzoom; } - else if (BLI_rcti_size_x(&ar->winrct) <= sima->zoom) { + else if (BLI_rcti_size_x(®ion->winrct) <= sima->zoom) { sima->zoom = oldzoom; } - else if (BLI_rcti_size_y(&ar->winrct) <= sima->zoom) { + else if (BLI_rcti_size_y(®ion->winrct) <= sima->zoom) { sima->zoom = oldzoom; } } @@ -150,16 +150,19 @@ static void sima_zoom_set( } } -static void sima_zoom_set_factor( - SpaceImage *sima, ARegion *ar, float zoomfac, const float location[2], const bool zoom_to_pos) +static void sima_zoom_set_factor(SpaceImage *sima, + ARegion *region, + float zoomfac, + const float location[2], + const bool zoom_to_pos) { - sima_zoom_set(sima, ar, sima->zoom * zoomfac, location, zoom_to_pos); + sima_zoom_set(sima, region, sima->zoom * zoomfac, location, zoom_to_pos); } /** * Fits the view to the bounds exactly, caller should add margin if needed. */ -static void sima_zoom_set_from_bounds(SpaceImage *sima, ARegion *ar, const rctf *bounds) +static void sima_zoom_set_from_bounds(SpaceImage *sima, ARegion *region, const rctf *bounds) { int image_size[2]; float aspx, aspy; @@ -175,13 +178,13 @@ static void sima_zoom_set_from_bounds(SpaceImage *sima, ARegion *ar, const rctf sima->yof = roundf((BLI_rctf_cent_y(bounds) - 0.5f) * image_size[1]); float size_xy[2], size; - size_xy[0] = BLI_rcti_size_x(&ar->winrct) / (BLI_rctf_size_x(bounds) * image_size[0]); - size_xy[1] = BLI_rcti_size_y(&ar->winrct) / (BLI_rctf_size_y(bounds) * image_size[1]); + size_xy[0] = BLI_rcti_size_x(®ion->winrct) / (BLI_rctf_size_x(bounds) * image_size[0]); + size_xy[1] = BLI_rcti_size_y(®ion->winrct) / (BLI_rctf_size_y(bounds) * image_size[1]); size = min_ff(size_xy[0], size_xy[1]); CLAMP_MAX(size, 100.0f); - sima_zoom_set(sima, ar, size, NULL, false); + sima_zoom_set(sima, region, size, NULL, false); } static Image *image_from_context(const bContext *C) @@ -235,7 +238,7 @@ static bool image_from_context_has_data_poll(bContext *C) /** * Use this when the image buffer is accessed without the image user. */ -static bool image_from_contect_has_data_poll_no_image_user(bContext *C) +static bool image_from_context_has_data_poll_no_image_user(bContext *C) { Image *ima = image_from_context(C); @@ -252,10 +255,10 @@ static bool image_not_packed_poll(bContext *C) bool space_image_main_region_poll(bContext *C) { SpaceImage *sima = CTX_wm_space_image(C); - /* XXX ARegion *ar = CTX_wm_region(C); */ + /* XXX ARegion *region = CTX_wm_region(C); */ if (sima) { - return true; /* XXX (ar && ar->type->regionid == RGN_TYPE_WINDOW); */ + return true; /* XXX (region && region->type->regionid == RGN_TYPE_WINDOW); */ } return false; } @@ -462,14 +465,14 @@ typedef struct ViewZoomData { /* */ SpaceImage *sima; - ARegion *ar; + ARegion *region; } ViewZoomData; static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *event) { wmWindow *win = CTX_wm_window(C); SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); ViewZoomData *vpd; op->customdata = vpd = MEM_callocN(sizeof(ViewZoomData), "ImageViewZoomData"); @@ -486,7 +489,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve vpd->launch_event = WM_userdef_event_type_from_keymap_type(event->type); UI_view2d_region_to_view( - &ar->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]); + ®ion->v2d, event->mval[0], event->mval[1], &vpd->location[0], &vpd->location[1]); if (U.viewzoom == USER_ZOOM_CONT) { /* needs a timer to continue redrawing */ @@ -495,7 +498,7 @@ static void image_view_zoom_init(bContext *C, wmOperator *op, const wmEvent *eve } vpd->sima = sima; - vpd->ar = ar; + vpd->region = region; WM_event_add_modal_handler(C, op); } @@ -523,11 +526,11 @@ static void image_view_zoom_exit(bContext *C, wmOperator *op, bool cancel) static int image_view_zoom_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); - sima_zoom_set_factor(sima, ar, RNA_float_get(op->ptr, "factor"), NULL, false); + sima_zoom_set_factor(sima, region, RNA_float_get(op->ptr, "factor"), NULL, false); - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } @@ -542,10 +545,11 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev { if (event->type == MOUSEZOOM || event->type == MOUSEPAN) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); float delta, factor, location[2]; - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); + UI_view2d_region_to_view( + ®ion->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); delta = event->prevx - event->x + event->prevy - event->y; @@ -557,11 +561,11 @@ static int image_view_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev RNA_float_set(op->ptr, "factor", factor); const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init"); sima_zoom_set(sima, - ar, + region, sima->zoom * factor, location, (use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS))); - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } @@ -616,8 +620,8 @@ static void image_zoom_apply(ViewZoomData *vpd, } RNA_float_set(op->ptr, "factor", factor); - sima_zoom_set(vpd->sima, vpd->ar, vpd->zoom * factor, vpd->location, zoom_to_pos); - ED_region_tag_redraw(vpd->ar); + sima_zoom_set(vpd->sima, vpd->region, vpd->zoom * factor, vpd->location, zoom_to_pos); + ED_region_tag_redraw(vpd->region); } static int image_view_zoom_modal(bContext *C, wmOperator *op, const wmEvent *event) @@ -715,7 +719,7 @@ static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmE } else { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); float pan_vec[3]; const wmNDOFMotionData *ndof = event->customdata; @@ -726,11 +730,11 @@ static int image_view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), const wmE mul_v2_fl(pan_vec, (speed * ndof->dt) / sima->zoom); pan_vec[2] *= -ndof->dt; - sima_zoom_set_factor(sima, ar, 1.0f + pan_vec[2], NULL, false); + sima_zoom_set_factor(sima, region, 1.0f + pan_vec[2], NULL, false); sima->xof += pan_vec[0]; sima->yof += pan_vec[1]; - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } @@ -766,14 +770,14 @@ void IMAGE_OT_view_ndof(wmOperatorType *ot) static int image_view_all_exec(bContext *C, wmOperator *op) { SpaceImage *sima; - ARegion *ar; + ARegion *region; float aspx, aspy, zoomx, zoomy, w, h; int width, height; const bool fit_view = RNA_boolean_get(op->ptr, "fit_view"); /* retrieve state */ sima = CTX_wm_space_image(C); - ar = CTX_wm_region(C); + region = CTX_wm_region(C); ED_space_image_get_size(sima, &width, &height); ED_space_image_get_aspect(sima, &aspx, &aspy); @@ -781,9 +785,32 @@ static int image_view_all_exec(bContext *C, wmOperator *op) w = width * aspx; h = height * aspy; + float xof = 0.0f, yof = 0.0f; + if ((sima->image == NULL) || (sima->image->source == IMA_SRC_TILED)) { + /* Extend the shown area to cover all UDIM tiles. */ + int x_tiles, y_tiles; + if (sima->image == NULL) { + x_tiles = sima->tile_grid_shape[0]; + y_tiles = sima->tile_grid_shape[1]; + } + else { + x_tiles = y_tiles = 1; + LISTBASE_FOREACH (ImageTile *, tile, &sima->image->tiles) { + int tile_x = (tile->tile_number - 1001) % 10; + int tile_y = (tile->tile_number - 1001) / 10; + x_tiles = max_ii(x_tiles, tile_x + 1); + y_tiles = max_ii(y_tiles, tile_y + 1); + } + } + xof = 0.5f * (x_tiles - 1.0f) * w; + yof = 0.5f * (y_tiles - 1.0f) * h; + w *= x_tiles; + h *= y_tiles; + } + /* check if the image will fit in the image with (zoom == 1) */ - width = BLI_rcti_size_x(&ar->winrct) + 1; - height = BLI_rcti_size_y(&ar->winrct) + 1; + width = BLI_rcti_size_x(®ion->winrct) + 1; + height = BLI_rcti_size_y(®ion->winrct) + 1; if (fit_view) { const int margin = 5; /* margin from border */ @@ -791,7 +818,7 @@ static int image_view_all_exec(bContext *C, wmOperator *op) zoomx = (float)width / (w + 2 * margin); zoomy = (float)height / (h + 2 * margin); - sima_zoom_set(sima, ar, min_ff(zoomx, zoomy), NULL, false); + sima_zoom_set(sima, region, min_ff(zoomx, zoomy), NULL, false); } else { if ((w >= width || h >= height) && (width > 0 && height > 0)) { @@ -799,16 +826,17 @@ static int image_view_all_exec(bContext *C, wmOperator *op) zoomy = (float)height / h; /* find the zoom value that will fit the image in the image space */ - sima_zoom_set(sima, ar, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL, false); + sima_zoom_set(sima, region, 1.0f / power_of_2(1.0f / min_ff(zoomx, zoomy)), NULL, false); } else { - sima_zoom_set(sima, ar, 1.0f, NULL, false); + sima_zoom_set(sima, region, 1.0f, NULL, false); } } - sima->xof = sima->yof = 0.0f; + sima->xof = xof; + sima->yof = yof; - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } @@ -843,11 +871,11 @@ void IMAGE_OT_view_all(wmOperatorType *ot) static int view_center_cursor_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); ED_image_view_center_to_point(sima, sima->cursor[0], sima->cursor[1]); - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } @@ -867,13 +895,13 @@ void IMAGE_OT_view_center_cursor(wmOperatorType *ot) /** \} */ /* -------------------------------------------------------------------- */ -/** \name View Selected Operator +/** \name Frame Selected Operator * \{ */ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceImage *sima; - ARegion *ar; + ARegion *region; Scene *scene; ViewLayer *view_layer; Object *obedit; @@ -881,7 +909,7 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) /* retrieve state */ sima = CTX_wm_space_image(C); - ar = CTX_wm_region(C); + region = CTX_wm_region(C); scene = CTX_data_scene(C); view_layer = CTX_data_view_layer(C); obedit = CTX_data_edit_object(C); @@ -910,9 +938,9 @@ static int image_view_selected_exec(bContext *C, wmOperator *UNUSED(op)) /* add some margin */ BLI_rctf_scale(&bounds, 1.4f); - sima_zoom_set_from_bounds(sima, ar, &bounds); + sima_zoom_set_from_bounds(sima, region, &bounds); - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } @@ -943,25 +971,26 @@ void IMAGE_OT_view_selected(wmOperatorType *ot) static int image_view_zoom_in_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); float location[2]; RNA_float_get_array(op->ptr, "location", location); sima_zoom_set_factor( - sima, ar, powf(2.0f, 1.0f / 3.0f), location, U.uiflag & USER_ZOOM_TO_MOUSEPOS); + sima, region, powf(2.0f, 1.0f / 3.0f), location, U.uiflag & USER_ZOOM_TO_MOUSEPOS); - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } static int image_view_zoom_in_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); float location[2]; - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); + UI_view2d_region_to_view( + ®ion->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); RNA_float_set_array(op->ptr, "location", location); return image_view_zoom_in_exec(C, op); @@ -1001,25 +1030,26 @@ void IMAGE_OT_view_zoom_in(wmOperatorType *ot) static int image_view_zoom_out_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); float location[2]; RNA_float_get_array(op->ptr, "location", location); sima_zoom_set_factor( - sima, ar, powf(0.5f, 1.0f / 3.0f), location, U.uiflag & USER_ZOOM_TO_MOUSEPOS); + sima, region, powf(0.5f, 1.0f / 3.0f), location, U.uiflag & USER_ZOOM_TO_MOUSEPOS); - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } static int image_view_zoom_out_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); float location[2]; - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); + UI_view2d_region_to_view( + ®ion->v2d, event->mval[0], event->mval[1], &location[0], &location[1]); RNA_float_set_array(op->ptr, "location", location); return image_view_zoom_out_exec(C, op); @@ -1065,15 +1095,15 @@ void IMAGE_OT_view_zoom_out(wmOperatorType *ot) static int image_view_zoom_ratio_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); - sima_zoom_set(sima, ar, RNA_float_get(op->ptr, "ratio"), NULL, false); + sima_zoom_set(sima, region, RNA_float_get(op->ptr, "ratio"), NULL, false); /* ensure pixel exact locations for draw */ sima->xof = (int)sima->xof; sima->yof = (int)sima->yof; - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } @@ -1113,13 +1143,13 @@ void IMAGE_OT_view_zoom_ratio(wmOperatorType *ot) static int image_view_zoom_border_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); rctf bounds; const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out"); WM_operator_properties_border_to_rctf(op, &bounds); - UI_view2d_region_to_view_rctf(&ar->v2d, &bounds, &bounds); + UI_view2d_region_to_view_rctf(®ion->v2d, &bounds, &bounds); const struct { float xof; @@ -1131,7 +1161,7 @@ static int image_view_zoom_border_exec(bContext *C, wmOperator *op) .zoom = sima->zoom, }; - sima_zoom_set_from_bounds(sima, ar, &bounds); + sima_zoom_set_from_bounds(sima, region, &bounds); /* zoom out */ if (!zoom_in) { @@ -1140,7 +1170,7 @@ static int image_view_zoom_border_exec(bContext *C, wmOperator *op) sima->zoom = sima_view_prev.zoom * (sima_view_prev.zoom / sima->zoom); } - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); return OPERATOR_FINISHED; } @@ -1183,18 +1213,6 @@ typedef struct ImageOpenData { ImageFormatData im_format; } ImageOpenData; -typedef struct ImageFrameRange { - struct ImageFrameRange *next, *prev; - ListBase frames; - /** The full path of the first file in the list of image files */ - char filepath[FILE_MAX]; -} ImageFrameRange; - -typedef struct ImageFrame { - struct ImageFrame *next, *prev; - int framenr; -} ImageFrame; - static void image_open_init(bContext *C, wmOperator *op) { ImageOpenData *iod; @@ -1209,179 +1227,18 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op) op->customdata = NULL; } -/** - * 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_all[out]: the list of frame numbers found in the files matching - * the first one by name. - */ -static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all) -{ - char dir[FILE_MAXDIR]; - const bool do_frame_range = RNA_boolean_get(ptr, "use_sequence_detection"); - ImageFrameRange *frame_range = NULL; - - 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 */ - frame->framenr = BLI_stringdec(filename, head, tail, &digits); - - /* still in the same sequence */ - if (do_frame_range && (frame_range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) && - (STREQLEN(base_tail, tail, FILE_MAX))) { - /* pass */ - } - else { - /* 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); - - 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; -} - -static int image_cmp_frame(const void *a, const void *b) -{ - const ImageFrame *frame_a = a; - const ImageFrame *frame_b = b; - - if (frame_a->framenr < frame_b->framenr) { - return -1; - } - if (frame_a->framenr > frame_b->framenr) { - return 1; - } - return 0; -} - -/* Checks whether the given filepath refers to a UDIM texture. - * If yes, the range from 1001 to the highest tile is returned, otherwise 0. - * - * If the result is positive, the filepath will be overwritten with that of - * the 1001 tile. - * udim_tiles may get filled even if the result ultimately is false! */ -static int image_get_udim(char *filepath, LinkNodePair *udim_tiles) -{ - char filename[FILE_MAX], dirname[FILE_MAXDIR]; - BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename)); - - 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 || id >= IMA_UDIM_MAX) { - return 0; - } - - bool is_udim = true; - bool has_primary = false; - int max_udim = 0; - - 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 >= IMA_UDIM_MAX) { - is_udim = false; - break; - } - if (id == 1001) { - has_primary = true; - } - - BLI_linklist_append(udim_tiles, POINTER_FROM_INT(id)); - max_udim = max_ii(max_udim, id); - } - BLI_filelist_free(dir, totfile); - - if (is_udim && has_primary) { - char primary_filename[FILE_MAX]; - BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001); - BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename); - return max_udim - 1000; - } - return 0; -} - -/** - * 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] offset the first frame number in the sequence. - * \return the number of contiguous frames in the sequence - */ -static int image_sequence_get_len(ImageFrameRange *frame_range, - int *ofs, - char *filepath_range, - LinkNodePair *udim_tiles) -{ - ImageFrame *frame; - - BLI_listbase_sort(&frame_range->frames, image_cmp_frame); - BLI_strncpy(filepath_range, frame_range->filepath, FILE_MAX); - - frame = frame_range->frames.first; - if (frame != NULL) { - int frame_curr = frame->framenr; - (*ofs) = frame_curr; - - if (udim_tiles != NULL) { - int len_udim = image_get_udim(filepath_range, udim_tiles); - if (len_udim > 0) { - *ofs = 1001; - return len_udim; - } - } - - while (frame != NULL && (frame->framenr == frame_curr)) { - frame_curr++; - frame = frame->next; - } - return frame_curr - (*ofs); - } - *ofs = 0; - return 0; -} - static Image *image_open_single(Main *bmain, wmOperator *op, - const char *filepath, + ImageFrameRange *range, const char *relbase, bool is_relative_path, - bool use_multiview, - int frame_seq_len, - int frame_seq_ofs, - LinkNodePair *udim_tiles) + bool use_multiview) { bool exists = false; Image *ima = NULL; errno = 0; - ima = BKE_image_load_exists_ex(bmain, filepath, &exists); + ima = BKE_image_load_exists_ex(bmain, range->filepath, &exists); if (!ima) { if (op->customdata) { @@ -1390,7 +1247,7 @@ static Image *image_open_single(Main *bmain, BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", - filepath, + range->filepath, errno ? strerror(errno) : TIP_("unsupported image format")); return NULL; } @@ -1415,11 +1272,11 @@ static Image *image_open_single(Main *bmain, BKE_image_free_views(ima); } - if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) { - if (udim_tiles && frame_seq_ofs == 1001) { + if ((range->length > 1) && (ima->source == IMA_SRC_FILE)) { + if (range->udim_tiles.first && range->offset == 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); + for (LinkData *node = range->udim_tiles.first; node; node = node->next) { + BKE_image_add_tile(ima, POINTER_AS_INT(node->data), NULL); } } else { @@ -1440,7 +1297,6 @@ static int image_open_exec(bContext *C, wmOperator *op) ImageUser *iuser = NULL; ImageOpenData *iod = op->customdata; Image *ima = NULL; - char filepath[FILE_MAX]; int frame_seq_len = 0; int frame_ofs = 1; @@ -1452,83 +1308,21 @@ static int image_open_exec(bContext *C, wmOperator *op) 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")) { - bool was_relative = BLI_path_is_rel(filepath); - ListBase frame_ranges_all; - - 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; + ListBase ranges = ED_image_filesel_detect_sequences(bmain, op, use_udim); + for (ImageFrameRange *range = ranges.first; range; range = range->next) { + Image *ima_range = image_open_single( + bmain, op, range, BKE_main_blendfile_path(bmain), is_relative_path, use_multiview); - LinkNodePair udim_tiles = {NULL}; - LinkNodePair *udim_tiles_ptr = use_udim ? (&udim_tiles) : NULL; - - char filepath_range[FILE_MAX]; - int frame_range_seq_len = image_sequence_get_len( - frame_range, &frame_range_ofs, filepath_range, udim_tiles_ptr); - BLI_freelistN(&frame_range->frames); - - if (was_relative) { - BLI_path_rel(filepath_range, BKE_main_blendfile_path(bmain)); - } - - Image *ima_range = image_open_single(bmain, - op, - filepath_range, - BKE_main_blendfile_path(bmain), - is_relative_path, - use_multiview, - frame_range_seq_len, - frame_range_ofs, - udim_tiles_ptr); - - /* 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_linklist_free(udim_tiles.list, NULL); + /* take the first image */ + if ((ima == NULL) && ima_range) { + ima = ima_range; + frame_seq_len = range->length; + frame_ofs = range->offset; } - BLI_freelistN(&frame_ranges_all); - } - else { - /* for drag & drop etc. */ - - LinkNodePair udim_tiles = {NULL}; - frame_seq_len = 1; - char filepath_range[FILE_MAX]; - BLI_strncpy(filepath_range, filepath, FILE_MAX); - - if (use_udim > 0) { - /* Try to find UDIM tiles corresponding to the image */ - int udim_len = image_get_udim(filepath_range, &udim_tiles); - - /* If we found something, mark the image as tiled. */ - if (udim_len) { - frame_seq_len = udim_len; - frame_ofs = 1001; - } - } - - ima = image_open_single(bmain, - op, - filepath_range, - BKE_main_blendfile_path(bmain), - is_relative_path, - use_multiview, - frame_seq_len, - frame_ofs, - &udim_tiles); - BLI_linklist_free(udim_tiles.list, NULL); + BLI_freelistN(&range->udim_tiles); } + BLI_freelistN(&ranges); if (ima == NULL) { return OPERATOR_CANCELLED; @@ -1877,6 +1671,12 @@ void IMAGE_OT_replace(wmOperatorType *ot) /** \name Save Image As Operator * \{ */ +typedef struct ImageSaveData { + ImageUser *iuser; + Image *image; + ImageFormatData im_format; +} ImageSaveData; + static char imtype_best_depth(ImBuf *ibuf, const char imtype) { const char depth_ok = BKE_imtype_valid_depths(imtype); @@ -1956,9 +1756,6 @@ static int image_save_options_init(Main *bmain, opts->im_format.views_format = ima->views_format; } - ///* XXX - this is lame, we need to make these available too! */ - // opts->subimtype = scene->r.subimtype; - BLI_strncpy(opts->filepath, ibuf->name, sizeof(opts->filepath)); /* sanitize all settings */ @@ -2006,6 +1803,8 @@ static int image_save_options_init(Main *bmain, /* color management */ BKE_color_managed_display_settings_copy(&opts->im_format.display_settings, &scene->display_settings); + + BKE_color_managed_view_settings_free(&opts->im_format.view_settings); BKE_color_managed_view_settings_copy(&opts->im_format.view_settings, &scene->view_settings); } @@ -2014,12 +1813,14 @@ static int image_save_options_init(Main *bmain, return (ibuf != NULL); } -static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOperator *op) +static void image_save_options_from_op(Main *bmain, + ImageSaveOptions *opts, + wmOperator *op, + ImageFormatData *imf) { - if (op->customdata) { + if (imf) { BKE_color_managed_view_settings_free(&opts->im_format.view_settings); - - opts->im_format = *(ImageFormatData *)op->customdata; + opts->im_format = *imf; } if (RNA_struct_property_is_set(op->ptr, "filepath")) { @@ -2031,20 +1832,17 @@ static void image_save_options_from_op(Main *bmain, ImageSaveOptions *opts, wmOp static void image_save_options_to_op(ImageSaveOptions *opts, wmOperator *op) { if (op->customdata) { - BKE_color_managed_view_settings_free(&((ImageFormatData *)op->customdata)->view_settings); - - *(ImageFormatData *)op->customdata = opts->im_format; + ImageSaveData *isd = op->customdata; + BKE_color_managed_view_settings_free(&isd->im_format.view_settings); + isd->im_format = opts->im_format; } RNA_string_set(op->ptr, "filepath", opts->filepath); } -static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *opts) +static bool save_image_op( + Main *bmain, Image *ima, ImageUser *iuser, wmOperator *op, ImageSaveOptions *opts) { - Main *bmain = CTX_data_main(C); - Image *ima = image_from_context(C); - ImageUser *iuser = image_user_from_context(C); - opts->relative = (RNA_struct_find_property(op->ptr, "relative_path") && RNA_boolean_get(op->ptr, "relative_path")); opts->save_copy = (RNA_struct_find_property(op->ptr, "copy") && @@ -2061,7 +1859,7 @@ static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *o /* Remember file path for next save. */ BLI_strncpy(G.ima, opts->filepath, sizeof(G.ima)); - WM_event_add_notifier(C, NC_IMAGE | NA_EDITED, ima); + WM_main_add_notifier(NC_IMAGE | NA_EDITED, ima); return ok; } @@ -2069,8 +1867,8 @@ static bool save_image_op(const bContext *C, wmOperator *op, ImageSaveOptions *o static void image_save_as_free(wmOperator *op) { if (op->customdata) { - ImageFormatData *im_format = (ImageFormatData *)op->customdata; - BKE_color_managed_view_settings_free(&im_format->view_settings); + ImageSaveData *isd = op->customdata; + BKE_color_managed_view_settings_free(&isd->im_format.view_settings); MEM_freeN(op->customdata); op->customdata = NULL; @@ -2081,20 +1879,32 @@ static int image_save_as_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - Image *image = image_from_context(C); - ImageUser *iuser = image_user_from_context(C); ImageSaveOptions opts; + Image *image = NULL; + ImageUser *iuser = NULL; + ImageFormatData *imf = NULL; + if (op->customdata) { + ImageSaveData *isd = op->customdata; + image = isd->image; + iuser = isd->iuser; + imf = &isd->im_format; + } + else { + image = image_from_context(C); + iuser = image_user_from_context(C); + } + BKE_image_save_options_init(&opts, bmain, scene); /* just in case to initialize values, * these should be set on invoke or by the caller. */ image_save_options_init(bmain, &opts, image, iuser, false, false); - image_save_options_from_op(bmain, &opts, op); + image_save_options_from_op(bmain, &opts, op, imf); opts.do_newpath = true; - save_image_op(C, op, &opts); + save_image_op(bmain, image, iuser, op, &opts); if (opts.save_copy == false) { BKE_image_free_packedfiles(image); @@ -2107,8 +1917,8 @@ static int image_save_as_exec(bContext *C, wmOperator *op) static bool image_save_as_check(bContext *UNUSED(C), wmOperator *op) { - ImageFormatData *imf = op->customdata; - return WM_operator_filesel_ensure_ext_imtype(op, imf); + ImageSaveData *isd = op->customdata; + return WM_operator_filesel_ensure_ext_imtype(op, &isd->im_format); } static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) @@ -2140,8 +1950,12 @@ static int image_save_as_invoke(bContext *C, wmOperator *op, const wmEvent *UNUS RNA_boolean_set(op->ptr, "save_as_render", save_as_render); - op->customdata = MEM_mallocN(sizeof(opts.im_format), __func__); - memcpy(op->customdata, &opts.im_format, sizeof(opts.im_format)); + ImageSaveData *isd = MEM_callocN(sizeof(*isd), __func__); + isd->image = ima; + isd->iuser = iuser; + + memcpy(&isd->im_format, &opts.im_format, sizeof(opts.im_format)); + op->customdata = isd; /* show multiview save options only if image has multiviews */ prop = RNA_struct_find_property(op->ptr, "show_multiview"); @@ -2174,12 +1988,12 @@ static bool image_save_as_draw_check_prop(PointerRNA *ptr, static void image_save_as_draw(bContext *UNUSED(C), wmOperator *op) { uiLayout *layout = op->layout; - ImageFormatData *imf = op->customdata; + ImageSaveData *isd = op->customdata; PointerRNA imf_ptr, ptr; const bool is_multiview = RNA_boolean_get(op->ptr, "show_multiview"); /* image template */ - RNA_pointer_create(NULL, &RNA_ImageFormatSettings, imf, &imf_ptr); + RNA_pointer_create(NULL, &RNA_ImageFormatSettings, &isd->im_format, &imf_ptr); uiTemplateImageSettings(layout, &imf_ptr, false); /* main draw call */ @@ -2319,6 +2133,7 @@ static int image_save_exec(bContext *C, wmOperator *op) ImageUser *iuser = image_user_from_context(C); Scene *scene = CTX_data_scene(C); ImageSaveOptions opts; + bool ok = false; if (BKE_image_has_packedfile(image)) { /* Save packed files to memory. */ @@ -2330,21 +2145,28 @@ static int image_save_exec(bContext *C, wmOperator *op) if (image_save_options_init(bmain, &opts, image, iuser, false, false) == 0) { return OPERATOR_CANCELLED; } - image_save_options_from_op(bmain, &opts, op); + image_save_options_from_op(bmain, &opts, op, NULL); if (BLI_exists(opts.filepath) && BLI_file_is_writable(opts.filepath)) { - if (save_image_op(C, op, &opts)) { + if (save_image_op(bmain, image, iuser, op, &opts)) { /* report since this can be called from key-shortcuts */ BKE_reportf(op->reports, RPT_INFO, "Saved Image '%s'", opts.filepath); + ok = true; } } else { BKE_reportf( op->reports, RPT_ERROR, "Cannot save image, path '%s' is not writable", opts.filepath); - return OPERATOR_CANCELLED; } - return OPERATOR_FINISHED; + BKE_color_managed_view_settings_free(&opts.im_format.view_settings); + + if (ok) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_CANCELLED; + } } static int image_save_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) @@ -2486,7 +2308,7 @@ static bool image_should_be_saved_when_modified(Image *ima) static bool image_should_be_saved(Image *ima, bool *is_format_writable) { if (BKE_image_is_dirty_writable(ima, is_format_writable) && - (ima->source == IMA_SRC_FILE || ima->source == IMA_SRC_GENERATED)) { + ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_GENERATED, IMA_SRC_TILED)) { return image_should_be_saved_when_modified(ima); } else { @@ -2499,12 +2321,12 @@ static bool image_has_valid_path(Image *ima) return strchr(ima->name, '\\') || strchr(ima->name, '/'); } -bool ED_image_should_save_modified(const bContext *C) +bool ED_image_should_save_modified(const Main *bmain) { ReportList reports; BKE_reports_init(&reports, RPT_STORE); - uint modified_images_count = ED_image_save_all_modified_info(C, &reports); + uint modified_images_count = ED_image_save_all_modified_info(bmain, &reports); bool should_save = modified_images_count || !BLI_listbase_is_empty(&reports.list); BKE_reports_clear(&reports); @@ -2512,9 +2334,8 @@ bool ED_image_should_save_modified(const bContext *C) return should_save; } -int ED_image_save_all_modified_info(const bContext *C, ReportList *reports) +int ED_image_save_all_modified_info(const Main *bmain, ReportList *reports) { - Main *bmain = CTX_data_main(C); GSet *unique_paths = BLI_gset_str_new(__func__); int num_saveable_images = 0; @@ -2530,7 +2351,7 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports) else { BKE_reportf(reports, RPT_WARNING, - "Packed library image: %s from library %s can't be saved", + "Packed library image can't be saved: \"%s\" from \"%s\"", ima->id.name + 2, ima->id.lib->name); } @@ -2538,7 +2359,7 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports) else if (!is_format_writable) { BKE_reportf(reports, RPT_WARNING, - "Image %s can't be saved automatically, must use a different file format", + "Image can't be saved, use a different file format: \"%s\"", ima->id.name + 2); } else { @@ -2547,7 +2368,7 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports) if (BLI_gset_haskey(unique_paths, ima->name)) { BKE_reportf(reports, RPT_WARNING, - "File path used by more than one saved image: %s", + "Multiple images can't be saved to an identical path: \"%s\"", ima->name); } else { @@ -2555,11 +2376,8 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports) } } else { - BKE_reportf(reports, - RPT_WARNING, - "Image %s can't be saved, no valid file path: %s", - ima->id.name + 2, - ima->name); + BKE_reportf( + reports, RPT_WARNING, "Image can't be saved, no valid file path: \"%s\"", ima->name); } } } @@ -2571,9 +2389,10 @@ int ED_image_save_all_modified_info(const bContext *C, ReportList *reports) bool ED_image_save_all_modified(const bContext *C, ReportList *reports) { - ED_image_save_all_modified_info(C, reports); - Main *bmain = CTX_data_main(C); + + ED_image_save_all_modified_info(bmain, reports); + bool ok = true; for (Image *ima = bmain->images.first; ima; ima = ima->id.next) { @@ -2601,7 +2420,7 @@ bool ED_image_save_all_modified(const bContext *C, ReportList *reports) static bool image_save_all_modified_poll(bContext *C) { - int num_files = ED_image_save_all_modified_info(C, NULL); + int num_files = ED_image_save_all_modified_info(CTX_data_main(C), NULL); return num_files > 0; } @@ -2797,7 +2616,7 @@ static int image_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e /* Better for user feedback. */ RNA_string_set(op->ptr, "name", DATA_(IMA_DEF_NAME)); - return WM_operator_props_dialog_popup(C, op, 300, 100); + return WM_operator_props_dialog_popup(C, op, 300); } static void image_new_draw(bContext *UNUSED(C), wmOperator *op) @@ -2929,7 +2748,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, 0); + ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser); if (is_paint) { ED_imapaint_clear_partial_redraw(); @@ -3011,7 +2830,7 @@ void IMAGE_OT_invert(wmOperatorType *ot) /* api callbacks */ ot->exec = image_invert_exec; - ot->poll = image_from_contect_has_data_poll_no_image_user; + ot->poll = image_from_context_has_data_poll_no_image_user; /* properties */ prop = RNA_def_boolean(ot->srna, "invert_r", 0, "Red", "Invert Red Channel"); @@ -3043,7 +2862,7 @@ static int image_scale_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED RNA_property_int_set_array(op->ptr, prop, size); BKE_image_release_ibuf(ima, ibuf, NULL); } - return WM_operator_props_dialog_popup(C, op, 200, 200); + return WM_operator_props_dialog_popup(C, op, 200); } static int image_scale_exec(bContext *C, wmOperator *op) @@ -3073,7 +2892,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, 0); + ED_image_undo_push_begin_with_image(op->type->name, ima, ibuf, &sima->iuser); ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; IMB_scaleImBuf(ibuf, size[0], size[1]); @@ -3100,7 +2919,7 @@ void IMAGE_OT_resize(wmOperatorType *ot) /* api callbacks */ ot->invoke = image_scale_invoke; ot->exec = image_scale_exec; - ot->poll = image_from_contect_has_data_poll_no_image_user; + ot->poll = image_from_context_has_data_poll_no_image_user; /* properties */ RNA_def_int_vector(ot->srna, "size", 2, NULL, 1, INT_MAX, "Size", "", 1, SHRT_MAX); @@ -3124,7 +2943,8 @@ static bool image_pack_test(bContext *C, wmOperator *op) } 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"); + BKE_report( + op->reports, RPT_ERROR, "Packing movies, image sequences or tiled images not supported"); return 0; } @@ -3174,14 +2994,15 @@ void IMAGE_OT_pack(wmOperatorType *ot) static int image_unpack_exec(bContext *C, wmOperator *op) { + Main *bmain = CTX_data_main(C); Image *ima = image_from_context(C); int method = RNA_enum_get(op->ptr, "method"); - /* find the suppplied image by name */ + /* find the supplied image by name */ if (RNA_struct_property_is_set(op->ptr, "id")) { char imaname[MAX_ID_NAME - 2]; RNA_string_get(op->ptr, "id", imaname); - ima = BLI_findstring(&CTX_data_main(C)->images, imaname, offsetof(ID, name) + 2); + ima = BLI_findstring(&bmain->images, imaname, offsetof(ID, name) + 2); if (!ima) { ima = image_from_context(C); } @@ -3192,7 +3013,8 @@ static int image_unpack_exec(bContext *C, wmOperator *op) } 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"); + BKE_report( + op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported"); return OPERATOR_CANCELLED; } @@ -3225,7 +3047,8 @@ static int image_unpack_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE } 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"); + BKE_report( + op->reports, RPT_ERROR, "Unpacking movies, image sequences or tiled images not supported"); return OPERATOR_CANCELLED; } @@ -3300,7 +3123,7 @@ typedef struct ImageSampleInfo { int use_default_view; } ImageSampleInfo; -static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) +static void image_sample_draw(const bContext *C, ARegion *region, void *arg_info) { ImageSampleInfo *info = arg_info; if (!info->draw) { @@ -3309,7 +3132,7 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) Scene *scene = CTX_data_scene(C); ED_image_draw_info(scene, - ar, + region, info->color_manage, info->use_default_view, info->channels, @@ -3335,9 +3158,10 @@ static void image_sample_draw(const bContext *C, ARegion *ar, void *arg_info) /* TODO(campbell): lock to pixels. */ rctf sample_rect_fl; - BLI_rctf_init_pt_radius(&sample_rect_fl, - (float[2]){event->x - ar->winrct.xmin, event->y - ar->winrct.ymin}, - (float)(info->sample_size / 2.0f) * sima->zoom); + BLI_rctf_init_pt_radius( + &sample_rect_fl, + (float[2]){event->x - region->winrct.xmin, event->y - region->winrct.ymin}, + (float)(info->sample_size / 2.0f) * sima->zoom); glEnable(GL_COLOR_LOGIC_OP); glLogicOp(GL_XOR); @@ -3354,13 +3178,13 @@ 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]) +bool ED_space_image_color_sample(SpaceImage *sima, ARegion *region, int mval[2], float r_col[3]) { if (sima->image == NULL) { return false; } float uv[2]; - UI_view2d_region_to_view(&ar->v2d, mval[0], mval[1], &uv[0], &uv[1]); + UI_view2d_region_to_view(®ion->v2d, mval[0], mval[1], &uv[0], &uv[1]); int tile = BKE_image_get_tile_from_pos(sima->image, uv, uv, NULL); void *lock; @@ -3475,11 +3299,11 @@ static void image_sample_rect_color_float(ImBuf *ibuf, const rcti *rect, float r 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); + ARegion *region = 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]); + UI_view2d_region_to_view(®ion->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; @@ -3619,10 +3443,10 @@ static void image_sample_exit(bContext *C, wmOperator *op) static int image_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); ImageSampleInfo *info; - if (ar->regiontype == RGN_TYPE_WINDOW) { + if (region->regiontype == RGN_TYPE_WINDOW) { if (event->mval[1] <= 16 && ED_space_image_show_cache(sima)) { return OPERATOR_PASS_THROUGH; } @@ -3634,9 +3458,9 @@ static int image_sample_invoke(bContext *C, wmOperator *op, const wmEvent *event info = MEM_callocN(sizeof(ImageSampleInfo), "ImageSampleInfo"); - info->art = ar->type; + info->art = region->type; info->draw_handle = ED_region_draw_cb_activate( - ar->type, image_sample_draw, info, REGION_DRAW_POST_PIXEL); + region->type, image_sample_draw, info, REGION_DRAW_POST_PIXEL); info->sample_size = RNA_int_get(op->ptr, "size"); op->customdata = info; @@ -3701,7 +3525,7 @@ void IMAGE_OT_sample(wmOperatorType *ot) static int image_sample_line_exec(bContext *C, wmOperator *op) { SpaceImage *sima = CTX_wm_space_image(C); - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); Image *ima = ED_space_image(sima); @@ -3711,8 +3535,8 @@ static int image_sample_line_exec(bContext *C, wmOperator *op) 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]); + UI_view2d_region_to_view(®ion->v2d, x_start, y_start, &uv1[0], &uv1[1]); + UI_view2d_region_to_view(®ion->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); @@ -4014,19 +3838,19 @@ static int change_frame_exec(bContext *C, wmOperator *op) static int frame_from_event(bContext *C, const wmEvent *event) { - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); int framenr = 0; - if (ar->regiontype == RGN_TYPE_WINDOW) { - float sfra = SFRA, efra = EFRA, framelen = ar->winx / (efra - sfra + 1); + if (region->regiontype == RGN_TYPE_WINDOW) { + float sfra = SFRA, efra = EFRA, framelen = region->winx / (efra - sfra + 1); framenr = sfra + event->mval[0] / framelen; } else { float viewx, viewy; - UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &viewx, &viewy); + UI_view2d_region_to_view(®ion->v2d, event->mval[0], event->mval[1], &viewx, &viewy); framenr = round_fl_to_int(viewx); } @@ -4036,13 +3860,13 @@ static int frame_from_event(bContext *C, const wmEvent *event) static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event) { - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); - if (ar->regiontype == RGN_TYPE_WINDOW) { + if (region->regiontype == RGN_TYPE_WINDOW) { SpaceImage *sima = CTX_wm_space_image(C); /* Local coordinate visible rect inside region, to accommodate overlapping ui. */ - const rcti *rect_visible = ED_region_visible_rect(ar); + const rcti *rect_visible = ED_region_visible_rect(region); const int region_bottom = rect_visible->ymin; if (event->mval[1] > (region_bottom + 16 * UI_DPI_FAC) || !ED_space_image_show_cache(sima)) { @@ -4063,7 +3887,7 @@ static int change_frame_invoke(bContext *C, wmOperator *op, const wmEvent *event static int change_frame_modal(bContext *C, wmOperator *op, const wmEvent *event) { switch (event->type) { - case ESCKEY: + case EVT_ESCKEY: return OPERATOR_FINISHED; case MOUSEMOVE: @@ -4111,7 +3935,7 @@ static int image_read_viewlayers_exec(bContext *C, wmOperator *UNUSED(op)) SpaceImage *sima = CTX_wm_space_image(C); Image *ima; - ima = BKE_image_verify_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); + ima = BKE_image_ensure_viewer(bmain, IMA_TYPE_R_RESULT, "Render Result"); if (sima->image == NULL) { ED_space_image_set(bmain, sima, NULL, ima, false); } @@ -4143,7 +3967,7 @@ void IMAGE_OT_read_viewlayers(wmOperatorType *ot) static int render_border_exec(bContext *C, wmOperator *op) { - ARegion *ar = CTX_wm_region(C); + ARegion *region = CTX_wm_region(C); Scene *scene = CTX_data_scene(C); Render *re = RE_GetSceneRender(scene); RenderData *rd; @@ -4162,7 +3986,7 @@ static int render_border_exec(bContext *C, wmOperator *op) /* get rectangle from operator */ WM_operator_properties_border_to_rctf(op, &border); - UI_view2d_region_to_view_rctf(&ar->v2d, &border, &border); + UI_view2d_region_to_view_rctf(®ion->v2d, &border, &border); /* actually set border */ CLAMP(border.xmin, 0.0f, 1.0f); @@ -4240,7 +4064,9 @@ void IMAGE_OT_clear_render_border(wmOperatorType *ot) /** \} */ -/* ********************* Add tile operator ****************** */ +/* -------------------------------------------------------------------- */ +/** \name Add Tile Operator + * \{ */ static bool do_fill_tile(PointerRNA *ptr, Image *ima, ImageTile *tile) { @@ -4346,7 +4172,13 @@ static int tile_add_exec(bContext *C, wmOperator *op) Image *ima = CTX_data_edit_image(C); int start_tile = RNA_int_get(op->ptr, "number"); - int end_tile = min_ii(start_tile + RNA_int_get(op->ptr, "count"), IMA_UDIM_MAX); + int end_tile = start_tile + RNA_int_get(op->ptr, "count"); + + if (start_tile < 1001 || end_tile > IMA_UDIM_MAX) { + BKE_report(op->reports, RPT_ERROR, "Invalid UDIM index range was specified"); + return OPERATOR_CANCELLED; + } + bool fill_tile = RNA_boolean_get(op->ptr, "fill"); char *label = RNA_string_get_alloc(op->ptr, "label", NULL, 0); @@ -4395,7 +4227,7 @@ static int tile_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(ev RNA_int_set(op->ptr, "count", 1); RNA_string_set(op->ptr, "label", ""); - return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X, 5 * UI_UNIT_Y); + return WM_operator_props_dialog_popup(C, op, 10 * UI_UNIT_X); } static void tile_add_draw(bContext *UNUSED(C), wmOperator *op) @@ -4442,15 +4274,26 @@ void IMAGE_OT_tile_add(wmOperatorType *ot) /* 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_int(ot->srna, + "number", + 1002, + 1001, + IMA_UDIM_MAX, + "Number", + "UDIM number of the tile", + 1001, + 1099); RNA_def_int(ot->srna, "count", 1, 1, INT_MAX, "Count", "How many tiles to add", 1, 1000); RNA_def_string(ot->srna, "label", NULL, 0, "Label", "Optional tile label"); RNA_def_boolean(ot->srna, "fill", true, "Fill", "Fill new tile with a generated image"); def_fill_tile(ot->srna); } -/* ********************* Remove tile operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Remove Tile Operator + * \{ */ static bool tile_remove_poll(bContext *C) { @@ -4491,7 +4334,11 @@ void IMAGE_OT_tile_remove(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } -/* ********************* Fill tile operator ****************** */ +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Fill Tile Operator + * \{ */ static bool tile_fill_poll(bContext *C) { @@ -4522,7 +4369,7 @@ static int tile_fill_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(e { initialize_fill_tile(op->ptr, CTX_data_edit_image(C), NULL); - return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, 5 * UI_UNIT_Y); + return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X); } static void tile_fill_draw(bContext *UNUSED(C), wmOperator *op) diff --git a/source/blender/editors/space_image/image_sequence.c b/source/blender/editors/space_image/image_sequence.c new file mode 100644 index 00000000000..cc6fe38866d --- /dev/null +++ b/source/blender/editors/space_image/image_sequence.c @@ -0,0 +1,248 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +/** \file + * \ingroup spimage + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_fileops.h" +#include "BLI_fileops_types.h" +#include "BLI_linklist.h" +#include "BLI_listbase.h" +#include "BLI_math_base.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "DNA_image_types.h" +#include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" + +#include "RNA_access.h" + +#include "BKE_image.h" +#include "BKE_main.h" + +#include "ED_image.h" + +#include "WM_types.h" + +typedef struct ImageFrame { + struct ImageFrame *next, *prev; + int framenr; +} ImageFrame; + +/** + * Get a list of frames from the list of image files matching the first file + * name sequence pattern. The files and directory are read from standard + * fileselect operator properties. + * + * The output is a list of frame ranges, each containing a list of frames with matching names. + */ +static void image_sequence_get_frame_ranges(wmOperator *op, ListBase *ranges) +{ + char dir[FILE_MAXDIR]; + const bool do_frame_range = RNA_boolean_get(op->ptr, "use_sequence_detection"); + ImageFrameRange *range = NULL; + + RNA_string_get(op->ptr, "directory", dir); + RNA_BEGIN (op->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 */ + frame->framenr = BLI_stringdec(filename, head, tail, &digits); + + /* still in the same sequence */ + if (do_frame_range && (range != NULL) && (STREQLEN(base_head, head, FILE_MAX)) && + (STREQLEN(base_tail, tail, FILE_MAX))) { + /* pass */ + } + else { + /* start a new frame range */ + range = MEM_callocN(sizeof(*range), __func__); + BLI_join_dirfile(range->filepath, sizeof(range->filepath), dir, filename); + BLI_addtail(ranges, range); + + BLI_strncpy(base_head, head, sizeof(base_head)); + BLI_strncpy(base_tail, tail, sizeof(base_tail)); + } + + BLI_addtail(&range->frames, frame); + MEM_freeN(filename); + } + RNA_END; +} + +static int image_cmp_frame(const void *a, const void *b) +{ + const ImageFrame *frame_a = a; + const ImageFrame *frame_b = b; + + if (frame_a->framenr < frame_b->framenr) { + return -1; + } + if (frame_a->framenr > frame_b->framenr) { + return 1; + } + return 0; +} + +/* + * Checks whether the given filepath refers to a UDIM texture. + * If yes, the range from 1001 to the highest tile is returned, otherwise 0. + * + * If the result is positive, the filepath will be overwritten with that of + * the 1001 tile. + * + * udim_tiles may get filled even if the result ultimately is false! + */ +static int image_get_udim(char *filepath, ListBase *udim_tiles) +{ + char filename[FILE_MAX], dirname[FILE_MAXDIR]; + BLI_split_dirfile(filepath, dirname, filename, sizeof(dirname), sizeof(filename)); + + 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 || id >= IMA_UDIM_MAX) { + return 0; + } + + bool is_udim = true; + bool has_primary = false; + int max_udim = 0; + + 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 >= IMA_UDIM_MAX) { + is_udim = false; + break; + } + if (id == 1001) { + has_primary = true; + } + + BLI_addtail(udim_tiles, BLI_genericNodeN(POINTER_FROM_INT(id))); + max_udim = max_ii(max_udim, id); + } + BLI_filelist_free(dir, totfile); + + if (is_udim && has_primary) { + char primary_filename[FILE_MAX]; + BLI_stringenc(primary_filename, base_head, base_tail, digits, 1001); + BLI_join_dirfile(filepath, FILE_MAX, dirname, primary_filename); + return max_udim - 1000; + } + return 0; +} + +/** + * From a list of frames, compute the start (offset) and length of the sequence + * of contiguous frames. If UDIM is detect, it will return UDIM tiles as well. + */ +static void image_detect_frame_range(ImageFrameRange *range, const bool detect_udim) +{ + /* UDIM */ + if (detect_udim) { + int len_udim = image_get_udim(range->filepath, &range->udim_tiles); + + if (len_udim > 0) { + range->offset = 1001; + range->length = len_udim; + return; + } + } + + /* Image Sequence */ + BLI_listbase_sort(&range->frames, image_cmp_frame); + + ImageFrame *frame = range->frames.first; + if (frame != NULL) { + int frame_curr = frame->framenr; + range->offset = frame_curr; + + while (frame != NULL && (frame->framenr == frame_curr)) { + frame_curr++; + frame = frame->next; + } + + range->length = frame_curr - range->offset; + } + else { + range->length = 1; + range->offset = 0; + } +} + +/* Used for both images and volume file loading. */ +ListBase ED_image_filesel_detect_sequences(Main *bmain, wmOperator *op, const bool detect_udim) +{ + ListBase ranges; + BLI_listbase_clear(&ranges); + + char filepath[FILE_MAX]; + RNA_string_get(op->ptr, "filepath", filepath); + + /* File browser. */ + if (RNA_struct_property_is_set(op->ptr, "directory") && + RNA_struct_property_is_set(op->ptr, "files")) { + const bool was_relative = BLI_path_is_rel(filepath); + + image_sequence_get_frame_ranges(op, &ranges); + for (ImageFrameRange *range = ranges.first; range; range = range->next) { + image_detect_frame_range(range, detect_udim); + BLI_freelistN(&range->frames); + + if (was_relative) { + BLI_path_rel(range->filepath, BKE_main_blendfile_path(bmain)); + } + } + } + /* Filepath property for drag & drop etc. */ + else { + ImageFrameRange *range = MEM_callocN(sizeof(*range), __func__); + BLI_addtail(&ranges, range); + + BLI_strncpy(range->filepath, filepath, FILE_MAX); + image_detect_frame_range(range, detect_udim); + } + + return ranges; +} diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c index 79aa4d2ed7f..1394c05d7bc 100644 --- a/source/blender/editors/space_image/image_undo.c +++ b/source/blender/editors/space_image/image_undo.c @@ -34,16 +34,16 @@ #include "MEM_guardedalloc.h" -#include "BLI_math.h" #include "BLI_blenlib.h" -#include "BLI_utildefines.h" +#include "BLI_math.h" #include "BLI_threads.h" +#include "BLI_utildefines.h" #include "DNA_image_types.h" -#include "DNA_windowmanager_types.h" #include "DNA_object_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" +#include "DNA_windowmanager_types.h" #include "IMB_imbuf.h" #include "IMB_imbuf_types.h" @@ -55,10 +55,10 @@ #include "DEG_depsgraph.h" +#include "ED_object.h" #include "ED_paint.h" #include "ED_undo.h" #include "ED_util.h" -#include "ED_object.h" #include "GPU_draw.h" @@ -107,7 +107,11 @@ typedef struct PaintTile { struct PaintTile *next, *prev; Image *image; ImBuf *ibuf; - int tile_number; + /* For 2D image painting the ImageUser uses most of the values. + * Even though views and passes are stored they are currently not supported for painting. + * For 3D projection painting this only uses a tile & frame number. + * The scene pointer must be cleared (or temporarily set it as needed, but leave cleared). */ + ImageUser iuser; union { float *fp; uint *uint; @@ -149,7 +153,7 @@ static void ptile_invalidate_list(ListBase *paint_tiles) void *ED_image_paint_tile_find(ListBase *paint_tiles, Image *image, ImBuf *ibuf, - int tile_number, + ImageUser *iuser, int x_tile, int y_tile, ushort **r_mask, @@ -157,11 +161,11 @@ void *ED_image_paint_tile_find(ListBase *paint_tiles, { for (PaintTile *ptile = paint_tiles->first; ptile; ptile = ptile->next) { if (ptile->x_tile == x_tile && ptile->y_tile == y_tile) { - if (ptile->image == image && ptile->ibuf == ibuf && ptile->tile_number == tile_number) { + if (ptile->image == image && ptile->ibuf == ibuf && ptile->iuser.tile == iuser->tile) { if (r_mask) { /* allocate mask if requested. */ if (!ptile->mask) { - ptile->mask = MEM_callocN(sizeof(ushort) * SQUARE(ED_IMAGE_UNDO_TILE_SIZE), + ptile->mask = MEM_callocN(sizeof(ushort) * square_i(ED_IMAGE_UNDO_TILE_SIZE), "UndoImageTile.mask"); } *r_mask = ptile->mask; @@ -180,7 +184,7 @@ void *ED_image_paint_tile_push(ListBase *paint_tiles, Image *image, ImBuf *ibuf, ImBuf **tmpibuf, - int tile_number, + ImageUser *iuser, int x_tile, int y_tile, ushort **r_mask, @@ -195,7 +199,7 @@ void *ED_image_paint_tile_push(ListBase *paint_tiles, /* in projective painting we keep accounting of tiles, so if we need one pushed, just push! */ if (find_prev) { void *data = ED_image_paint_tile_find( - paint_tiles, image, ibuf, tile_number, x_tile, y_tile, r_mask, true); + paint_tiles, image, ibuf, iuser, x_tile, y_tile, r_mask, true); if (data) { return data; } @@ -209,19 +213,20 @@ void *ED_image_paint_tile_push(ListBase *paint_tiles, ptile->image = image; ptile->ibuf = ibuf; - ptile->tile_number = tile_number; + ptile->iuser = *iuser; + ptile->iuser.scene = NULL; ptile->x_tile = x_tile; ptile->y_tile = y_tile; /* add mask explicitly here */ if (r_mask) { - *r_mask = ptile->mask = MEM_callocN(sizeof(ushort) * SQUARE(ED_IMAGE_UNDO_TILE_SIZE), + *r_mask = ptile->mask = MEM_callocN(sizeof(ushort) * square_i(ED_IMAGE_UNDO_TILE_SIZE), "PaintTile.mask"); } ptile->rect.pt = MEM_mapallocN((ibuf->rect_float ? sizeof(float[4]) : sizeof(char[4])) * - SQUARE(ED_IMAGE_UNDO_TILE_SIZE), + square_i(ED_IMAGE_UNDO_TILE_SIZE), "PaintTile.rect"); ptile->use_float = has_float; @@ -264,10 +269,7 @@ static void ptile_restore_runtime_list(ListBase *paint_tiles) for (PaintTile *ptile = paint_tiles->first; ptile; ptile = ptile->next) { Image *image = ptile->image; - ImageUser iuser; - BKE_imageuser_default(&iuser); - iuser.tile = ptile->tile_number; - ImBuf *ibuf = BKE_image_acquire_ibuf(image, &iuser, NULL); + ImBuf *ibuf = BKE_image_acquire_ibuf(image, &ptile->iuser, NULL); const bool has_float = (ibuf->rect_float != NULL); if (has_float) { @@ -333,10 +335,10 @@ static UndoImageTile *utile_alloc(bool has_float) { UndoImageTile *utile = MEM_callocN(sizeof(*utile), "ImageUndoTile"); if (has_float) { - utile->rect.fp = MEM_mallocN(sizeof(float[4]) * SQUARE(ED_IMAGE_UNDO_TILE_SIZE), __func__); + utile->rect.fp = MEM_mallocN(sizeof(float[4]) * square_i(ED_IMAGE_UNDO_TILE_SIZE), __func__); } else { - utile->rect.uint = MEM_mallocN(sizeof(uint) * SQUARE(ED_IMAGE_UNDO_TILE_SIZE), __func__); + utile->rect.uint = MEM_mallocN(sizeof(uint) * square_i(ED_IMAGE_UNDO_TILE_SIZE), __func__); } return utile; } @@ -659,22 +661,23 @@ static UndoImageHandle *uhandle_lookup(ListBase *undo_handles, const Image *imag return NULL; } -static UndoImageHandle *uhandle_add(ListBase *undo_handles, Image *image, int tile_number) +static UndoImageHandle *uhandle_add(ListBase *undo_handles, Image *image, ImageUser *iuser) { - BLI_assert(uhandle_lookup(undo_handles, image, tile_number) == NULL); + BLI_assert(uhandle_lookup(undo_handles, image, iuser->tile) == NULL); UndoImageHandle *uh = MEM_callocN(sizeof(*uh), __func__); uh->image_ref.ptr = image; + uh->iuser = *iuser; + BLI_assert(uh->iuser.scene == NULL); uh->iuser.ok = 1; - uh->iuser.tile = tile_number; BLI_addtail(undo_handles, uh); return uh; } -static UndoImageHandle *uhandle_ensure(ListBase *undo_handles, Image *image, int tile_number) +static UndoImageHandle *uhandle_ensure(ListBase *undo_handles, Image *image, ImageUser *iuser) { - UndoImageHandle *uh = uhandle_lookup(undo_handles, image, tile_number); + UndoImageHandle *uh = uhandle_lookup(undo_handles, image, iuser->tile); if (uh == NULL) { - uh = uhandle_add(undo_handles, image, tile_number); + uh = uhandle_add(undo_handles, image, iuser); } return uh; } @@ -779,7 +782,7 @@ static bool image_undosys_step_encode(struct bContext *C, /* Initialize undo tiles from ptiles (if they exist). */ for (PaintTile *ptile = us->paint_tiles.first, *ptile_next; ptile; ptile = ptile_next) { if (ptile->valid) { - UndoImageHandle *uh = uhandle_ensure(&us->handles, ptile->image, ptile->tile_number); + UndoImageHandle *uh = uhandle_ensure(&us->handles, ptile->image, &ptile->iuser); UndoImageBuf *ubuf_pre = uhandle_ensure_ubuf(uh, ptile->image, ptile->ibuf); UndoImageTile *utile = MEM_callocN(sizeof(*utile), "UndoImageTile"); @@ -1047,12 +1050,12 @@ void ED_image_undo_push_begin(const char *name, int paint_mode) void ED_image_undo_push_begin_with_image(const char *name, Image *image, ImBuf *ibuf, - int tile_number) + ImageUser *iuser) { ImageUndoStep *us = image_undo_push_begin(name, PAINT_MODE_TEXTURE_2D); - BLI_assert(BKE_image_get_tile(image, tile_number)); - UndoImageHandle *uh = uhandle_ensure(&us->handles, image, tile_number); + BLI_assert(BKE_image_get_tile(image, iuser->tile)); + UndoImageHandle *uh = uhandle_ensure(&us->handles, image, iuser); UndoImageBuf *ubuf_pre = uhandle_ensure_ubuf(uh, image, ibuf); BLI_assert(ubuf_pre->post == NULL); @@ -1061,7 +1064,7 @@ void ED_image_undo_push_begin_with_image(const char *name, us_reference = (ImageUndoStep *)us_reference->step.prev; } UndoImageBuf *ubuf_reference = (us_reference ? ubuf_lookup_from_reference( - us_reference, image, tile_number, ubuf_pre) : + us_reference, image, iuser->tile, ubuf_pre) : NULL); if (ubuf_reference) { diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 833bcb6537a..14cc6a9e151 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -22,12 +22,12 @@ */ #include "DNA_gpencil_types.h" -#include "DNA_mesh_types.h" +#include "DNA_image_types.h" #include "DNA_mask_types.h" +#include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" -#include "DNA_image_types.h" #include "MEM_guardedalloc.h" @@ -40,7 +40,7 @@ #include "BKE_editmesh.h" #include "BKE_image.h" #include "BKE_layer.h" -#include "BKE_library.h" +#include "BKE_lib_id.h" #include "BKE_material.h" #include "BKE_scene.h" #include "BKE_screen.h" @@ -59,23 +59,23 @@ #include "ED_mesh.h" #include "ED_node.h" #include "ED_render.h" -#include "ED_space_api.h" #include "ED_screen.h" -#include "ED_uvedit.h" +#include "ED_space_api.h" #include "ED_transform.h" +#include "ED_uvedit.h" #include "WM_api.h" -#include "WM_types.h" #include "WM_message.h" +#include "WM_types.h" -#include "UI_resources.h" #include "UI_interface.h" +#include "UI_resources.h" #include "UI_view2d.h" -#include "image_intern.h" -#include "GPU_framebuffer.h" #include "GPU_batch_presets.h" +#include "GPU_framebuffer.h" #include "GPU_viewport.h" +#include "image_intern.h" /* TODO(fclem) remove bad level calls */ #include "../draw/DRW_engine.h" @@ -86,11 +86,11 @@ static void image_scopes_tag_refresh(ScrArea *sa) { SpaceImage *sima = (SpaceImage *)sa->spacedata.first; - ARegion *ar; + ARegion *region; /* only while histogram is visible */ - for (ar = sa->regionbase.first; ar; ar = ar->next) { - if (ar->regiontype == RGN_TYPE_TOOL_PROPS && ar->flag & RGN_FLAG_HIDDEN) { + for (region = sa->regionbase.first; region; region = region->next) { + if (region->regiontype == RGN_TYPE_TOOL_PROPS && region->flag & RGN_FLAG_HIDDEN) { return; } } @@ -119,7 +119,7 @@ static void image_user_refresh_scene(const bContext *C, SpaceImage *sima) static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(scene)) { - ARegion *ar; + ARegion *region; SpaceImage *simage; simage = MEM_callocN(sizeof(SpaceImage), "initimage"); @@ -138,41 +138,41 @@ static SpaceLink *image_new(const ScrArea *UNUSED(area), const Scene *UNUSED(sce simage->tile_grid_shape[1] = 1; /* tool header */ - ar = MEM_callocN(sizeof(ARegion), "tool header for image"); + region = MEM_callocN(sizeof(ARegion), "tool header for image"); - BLI_addtail(&simage->regionbase, ar); - ar->regiontype = RGN_TYPE_TOOL_HEADER; - ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; - ar->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER; + BLI_addtail(&simage->regionbase, region); + region->regiontype = RGN_TYPE_TOOL_HEADER; + region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + region->flag = RGN_FLAG_HIDDEN | RGN_FLAG_HIDDEN_BY_USER; /* header */ - ar = MEM_callocN(sizeof(ARegion), "header for image"); + region = MEM_callocN(sizeof(ARegion), "header for image"); - BLI_addtail(&simage->regionbase, ar); - ar->regiontype = RGN_TYPE_HEADER; - ar->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; + BLI_addtail(&simage->regionbase, region); + region->regiontype = RGN_TYPE_HEADER; + region->alignment = (U.uiflag & USER_HEADER_BOTTOM) ? RGN_ALIGN_BOTTOM : RGN_ALIGN_TOP; /* buttons/list view */ - ar = MEM_callocN(sizeof(ARegion), "buttons for image"); + region = MEM_callocN(sizeof(ARegion), "buttons for image"); - BLI_addtail(&simage->regionbase, ar); - ar->regiontype = RGN_TYPE_UI; - ar->alignment = RGN_ALIGN_RIGHT; - ar->flag = RGN_FLAG_HIDDEN; + BLI_addtail(&simage->regionbase, region); + region->regiontype = RGN_TYPE_UI; + region->alignment = RGN_ALIGN_RIGHT; + region->flag = RGN_FLAG_HIDDEN; /* scopes/uv sculpt/paint */ - ar = MEM_callocN(sizeof(ARegion), "buttons for image"); + region = MEM_callocN(sizeof(ARegion), "buttons for image"); - BLI_addtail(&simage->regionbase, ar); - ar->regiontype = RGN_TYPE_TOOLS; - ar->alignment = RGN_ALIGN_LEFT; - ar->flag = RGN_FLAG_HIDDEN; + BLI_addtail(&simage->regionbase, region); + region->regiontype = RGN_TYPE_TOOLS; + region->alignment = RGN_ALIGN_LEFT; + region->flag = RGN_FLAG_HIDDEN; /* main area */ - ar = MEM_callocN(sizeof(ARegion), "main area for image"); + region = MEM_callocN(sizeof(ARegion), "main area for image"); - BLI_addtail(&simage->regionbase, ar); - ar->regiontype = RGN_TYPE_WINDOW; + BLI_addtail(&simage->regionbase, region); + region->regiontype = RGN_TYPE_WINDOW; return (SpaceLink *)simage; } @@ -498,7 +498,7 @@ static void image_widgets(void) /************************** main region ***************************/ /* sets up the fields of the View2D from zoom and offset */ -static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar) +static void image_main_region_set_view2d(SpaceImage *sima, ARegion *region) { Image *ima = ED_space_image(sima); @@ -512,79 +512,79 @@ static void image_main_region_set_view2d(SpaceImage *sima, ARegion *ar) h *= ima->aspy / ima->aspx; } - int winx = BLI_rcti_size_x(&ar->winrct) + 1; - int winy = BLI_rcti_size_y(&ar->winrct) + 1; + int winx = BLI_rcti_size_x(®ion->winrct) + 1; + int winy = BLI_rcti_size_y(®ion->winrct) + 1; /* For region overlap, move center so image doesn't overlap header. */ - const rcti *visible_rect = ED_region_visible_rect(ar); + const rcti *visible_rect = ED_region_visible_rect(region); const int visible_winy = BLI_rcti_size_y(visible_rect) + 1; int visible_centerx = 0; int visible_centery = visible_rect->ymin + (visible_winy - winy) / 2; - ar->v2d.tot.xmin = 0; - ar->v2d.tot.ymin = 0; - ar->v2d.tot.xmax = w; - ar->v2d.tot.ymax = h; + region->v2d.tot.xmin = 0; + region->v2d.tot.ymin = 0; + region->v2d.tot.xmax = w; + region->v2d.tot.ymax = h; - ar->v2d.mask.xmin = ar->v2d.mask.ymin = 0; - ar->v2d.mask.xmax = winx; - ar->v2d.mask.ymax = winy; + region->v2d.mask.xmin = region->v2d.mask.ymin = 0; + region->v2d.mask.xmax = winx; + region->v2d.mask.ymax = winy; /* which part of the image space do we see? */ - float x1 = ar->winrct.xmin + visible_centerx + (winx - sima->zoom * w) / 2.0f; - float y1 = ar->winrct.ymin + visible_centery + (winy - sima->zoom * h) / 2.0f; + float x1 = region->winrct.xmin + visible_centerx + (winx - sima->zoom * w) / 2.0f; + float y1 = region->winrct.ymin + visible_centery + (winy - sima->zoom * h) / 2.0f; x1 -= sima->zoom * sima->xof; y1 -= sima->zoom * sima->yof; /* relative display right */ - ar->v2d.cur.xmin = ((ar->winrct.xmin - (float)x1) / sima->zoom); - ar->v2d.cur.xmax = ar->v2d.cur.xmin + ((float)winx / sima->zoom); + region->v2d.cur.xmin = ((region->winrct.xmin - (float)x1) / sima->zoom); + region->v2d.cur.xmax = region->v2d.cur.xmin + ((float)winx / sima->zoom); /* relative display left */ - ar->v2d.cur.ymin = ((ar->winrct.ymin - (float)y1) / sima->zoom); - ar->v2d.cur.ymax = ar->v2d.cur.ymin + ((float)winy / sima->zoom); + region->v2d.cur.ymin = ((region->winrct.ymin - (float)y1) / sima->zoom); + region->v2d.cur.ymax = region->v2d.cur.ymin + ((float)winy / sima->zoom); /* normalize 0.0..1.0 */ - ar->v2d.cur.xmin /= w; - ar->v2d.cur.xmax /= w; - ar->v2d.cur.ymin /= h; - ar->v2d.cur.ymax /= h; + region->v2d.cur.xmin /= w; + region->v2d.cur.xmax /= w; + region->v2d.cur.ymin /= h; + region->v2d.cur.ymax /= h; } /* add handlers, stuff you only do once or on area/region changes */ -static void image_main_region_init(wmWindowManager *wm, ARegion *ar) +static void image_main_region_init(wmWindowManager *wm, ARegion *region) { wmKeyMap *keymap; // image space manages own v2d - // UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_STANDARD, ar->winx, ar->winy); + // UI_view2d_region_reinit(®ion->v2d, V2D_COMMONVIEW_STANDARD, region->winx, region->winy); /* mask polls mode */ keymap = WM_keymap_ensure(wm->defaultconf, "Mask Editing", 0, 0); - WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); + WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); /* image paint polls for mode */ keymap = WM_keymap_ensure(wm->defaultconf, "Curve", 0, 0); - WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); + WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); keymap = WM_keymap_ensure(wm->defaultconf, "Paint Curve", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + WM_event_add_keymap_handler(®ion->handlers, keymap); keymap = WM_keymap_ensure(wm->defaultconf, "Image Paint", 0, 0); - WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); + WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); keymap = WM_keymap_ensure(wm->defaultconf, "UV Editor", 0, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + WM_event_add_keymap_handler(®ion->handlers, keymap); /* own keymaps */ keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + WM_event_add_keymap_handler(®ion->handlers, keymap); keymap = WM_keymap_ensure(wm->defaultconf, "Image", SPACE_IMAGE, 0); - WM_event_add_keymap_handler_v2d_mask(&ar->handlers, keymap); + WM_event_add_keymap_handler_v2d_mask(®ion->handlers, keymap); } -static void image_main_region_draw(const bContext *C, ARegion *ar) +static void image_main_region_draw(const bContext *C, ARegion *region) { /* draw entirely, view changes should be handled here */ SpaceImage *sima = CTX_wm_space_image(C); @@ -596,7 +596,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) bool show_curve = false; Scene *scene = CTX_data_scene(C); ViewLayer *view_layer = CTX_data_view_layer(C); - View2D *v2d = &ar->v2d; + View2D *v2d = ®ion->v2d; // View2DScrollers *scrollers; float col[3]; @@ -604,32 +604,36 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) * old context since we now use it for drawing the entire area. */ gpu_batch_presets_reset(); - GPUViewport *viewport = - ar->draw_buffer->viewport[ar->draw_buffer->stereo ? sima->iuser.multiview_eye : 0]; + GPUViewport *viewport = region->draw_buffer->viewport; DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); GPU_framebuffer_bind(fbl->default_fb); + GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f); + GPU_clear(GPU_COLOR_BIT); + + GPU_framebuffer_bind(fbl->overlay_fb); + glDisable(GL_FRAMEBUFFER_SRGB); /* XXX not supported yet, disabling for now */ scene->r.scemode &= ~R_COMP_CROP; /* clear and setup matrix */ UI_GetThemeColor3fv(TH_BACK, col); - GPU_clear_color(col[0], col[1], col[2], 0.0f); + GPU_clear_color(col[0], col[1], col[2], 1.0f); GPU_clear(GPU_COLOR_BIT); GPU_depth_test(false); image_user_refresh_scene(C, sima); /* we set view2d from own zoom and offset each time */ - image_main_region_set_view2d(sima, ar); + image_main_region_set_view2d(sima, region); /* we draw image in pixelspace */ - draw_image_main(C, ar); + draw_image_main(C, region); /* and uvs in 0.0-1.0 space */ UI_view2d_view_ortho(v2d); - ED_region_draw_cb_draw(C, ar, REGION_DRAW_PRE_VIEW); + ED_region_draw_cb_draw(C, region, REGION_DRAW_PRE_VIEW); ED_uvedit_draw_main(sima, scene, view_layer, obedit, obact, depsgraph); @@ -644,7 +648,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) show_curve = true; } - ED_region_draw_cb_draw(C, ar, REGION_DRAW_POST_VIEW); + ED_region_draw_cb_draw(C, region, REGION_DRAW_POST_VIEW); if (sima->flag & SI_SHOW_GPENCIL) { /* Grease Pencil too (in addition to UV's) */ @@ -684,7 +688,7 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) ED_mask_draw_region(depsgraph, mask, - ar, + region, sima->mask_info.draw_flag, sima->mask_info.draw_type, sima->mask_info.overlay_mode, @@ -700,51 +704,54 @@ static void image_main_region_draw(const bContext *C, ARegion *ar) if (show_uvedit || mask || show_curve) { UI_view2d_view_ortho(v2d); - ED_image_draw_cursor(ar, sima->cursor); + ED_image_draw_cursor(region, sima->cursor); UI_view2d_view_restore(C); } - WM_gizmomap_draw(ar->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D); + WM_gizmomap_draw(region->gizmo_map, C, WM_GIZMOMAP_DRAWSTEP_2D); - draw_image_cache(C, ar); + draw_image_cache(C, region); } -static void image_main_region_listener( - wmWindow *UNUSED(win), ScrArea *sa, ARegion *ar, wmNotifier *wmn, const Scene *UNUSED(scene)) +static void image_main_region_listener(wmWindow *UNUSED(win), + ScrArea *sa, + ARegion *region, + wmNotifier *wmn, + const Scene *UNUSED(scene)) { /* context changes */ switch (wmn->category) { case NC_GEOM: if (ELEM(wmn->data, ND_DATA, ND_SELECT)) { - WM_gizmomap_tag_refresh(ar->gizmo_map); + WM_gizmomap_tag_refresh(region->gizmo_map); } break; case NC_GPENCIL: if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } else if (wmn->data & ND_GPENCIL_EDITMODE) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; case NC_IMAGE: if (wmn->action == NA_PAINTING) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } - WM_gizmomap_tag_refresh(ar->gizmo_map); + WM_gizmomap_tag_refresh(region->gizmo_map); break; case NC_MATERIAL: if (wmn->data == ND_SHADING_LINKS) { SpaceImage *sima = sa->spacedata.first; if (sima->iuser.scene && (sima->iuser.scene->toolsettings->uv_flag & UV_SHOW_SAME_IMAGE)) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } } break; case NC_SCREEN: if (ELEM(wmn->data, ND_LAYER)) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; } @@ -753,18 +760,18 @@ static void image_main_region_listener( /* *********************** buttons region ************************ */ /* add handlers, stuff you only do once or on area/region changes */ -static void image_buttons_region_init(wmWindowManager *wm, ARegion *ar) +static void image_buttons_region_init(wmWindowManager *wm, ARegion *region) { wmKeyMap *keymap; - ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE; - ED_region_panels_init(wm, ar); + region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE; + ED_region_panels_init(wm, region); keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + WM_event_add_keymap_handler(®ion->handlers, keymap); } -static void image_buttons_region_layout(const bContext *C, ARegion *ar) +static void image_buttons_region_layout(const bContext *C, ARegion *region) { const enum eContextObjectMode mode = CTX_data_mode_enum(C); const char *contexts_base[3] = {NULL}; @@ -788,10 +795,11 @@ static void image_buttons_region_layout(const bContext *C, ARegion *ar) } const bool vertical = true; - ED_region_panels_layout_ex(C, ar, &ar->type->paneltypes, contexts_base, -1, vertical, NULL); + ED_region_panels_layout_ex( + C, region, ®ion->type->paneltypes, contexts_base, -1, vertical, NULL); } -static void image_buttons_region_draw(const bContext *C, ARegion *ar) +static void image_buttons_region_draw(const bContext *C, ARegion *region) { SpaceImage *sima = CTX_wm_space_image(C); Scene *scene = CTX_data_scene(C); @@ -799,7 +807,7 @@ static void image_buttons_region_draw(const bContext *C, ARegion *ar) /* TODO(lukas): Support tiles in scopes? */ ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock, 0); /* XXX performance regression if name of scopes category changes! */ - PanelCategoryStack *category = UI_panel_category_active_find(ar, "Scopes"); + PanelCategoryStack *category = UI_panel_category_active_find(region, "Scopes"); /* only update scopes if scope category is active */ if (category) { @@ -819,12 +827,12 @@ static void image_buttons_region_draw(const bContext *C, ARegion *ar) ED_space_image_release_buffer(sima, ibuf, lock); /* Layout handles details. */ - ED_region_panels_draw(C, ar); + ED_region_panels_draw(C, region); } static void image_buttons_region_listener(wmWindow *UNUSED(win), ScrArea *UNUSED(sa), - ARegion *ar, + ARegion *region, wmNotifier *wmn, const Scene *UNUSED(scene)) { @@ -834,33 +842,33 @@ static void image_buttons_region_listener(wmWindow *UNUSED(win), case NC_MATERIAL: /* sending by texture render job and needed to properly update displaying * brush texture icon */ - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); break; case NC_SCENE: switch (wmn->data) { case ND_MODE: case ND_RENDER_RESULT: case ND_COMPO_RESULT: - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); break; } break; case NC_IMAGE: if (wmn->action != NA_PAINTING) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; case NC_NODE: - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); break; case NC_GPENCIL: if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; case NC_BRUSH: if (wmn->action == NA_EDITED) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; } @@ -869,25 +877,25 @@ static void image_buttons_region_listener(wmWindow *UNUSED(win), /* *********************** scopes region ************************ */ /* add handlers, stuff you only do once or on area/region changes */ -static void image_tools_region_init(wmWindowManager *wm, ARegion *ar) +static void image_tools_region_init(wmWindowManager *wm, ARegion *region) { wmKeyMap *keymap; - ar->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE; - ED_region_panels_init(wm, ar); + region->v2d.scroll = V2D_SCROLL_RIGHT | V2D_SCROLL_VERTICAL_HIDE; + ED_region_panels_init(wm, region); keymap = WM_keymap_ensure(wm->defaultconf, "Image Generic", SPACE_IMAGE, 0); - WM_event_add_keymap_handler(&ar->handlers, keymap); + WM_event_add_keymap_handler(®ion->handlers, keymap); } -static void image_tools_region_draw(const bContext *C, ARegion *ar) +static void image_tools_region_draw(const bContext *C, ARegion *region) { - ED_region_panels(C, ar); + ED_region_panels(C, region); } static void image_tools_region_listener(wmWindow *UNUSED(win), ScrArea *UNUSED(sa), - ARegion *ar, + ARegion *region, wmNotifier *wmn, const Scene *UNUSED(scene)) { @@ -895,13 +903,13 @@ static void image_tools_region_listener(wmWindow *UNUSED(win), switch (wmn->category) { case NC_GPENCIL: if (wmn->data == ND_DATA || ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; case NC_BRUSH: /* NA_SELECTED is used on brush changes */ if (ELEM(wmn->action, NA_EDITED, NA_SELECTED)) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; case NC_SCENE: @@ -909,17 +917,17 @@ static void image_tools_region_listener(wmWindow *UNUSED(win), case ND_MODE: case ND_RENDER_RESULT: case ND_COMPO_RESULT: - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); break; } break; case NC_IMAGE: if (wmn->action != NA_PAINTING) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; case NC_NODE: - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); break; } } @@ -927,24 +935,24 @@ static void image_tools_region_listener(wmWindow *UNUSED(win), /************************* header region **************************/ /* add handlers, stuff you only do once or on area/region changes */ -static void image_header_region_init(wmWindowManager *UNUSED(wm), ARegion *ar) +static void image_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region) { - ED_region_header_init(ar); + ED_region_header_init(region); } -static void image_header_region_draw(const bContext *C, ARegion *ar) +static void image_header_region_draw(const bContext *C, ARegion *region) { ScrArea *sa = CTX_wm_area(C); SpaceImage *sima = sa->spacedata.first; image_user_refresh_scene(C, sima); - ED_region_header(C, ar); + ED_region_header(C, region); } static void image_header_region_listener(wmWindow *UNUSED(win), ScrArea *UNUSED(sa), - ARegion *ar, + ARegion *region, wmNotifier *wmn, const Scene *UNUSED(scene)) { @@ -954,7 +962,7 @@ static void image_header_region_listener(wmWindow *UNUSED(win), switch (wmn->data) { case ND_MODE: case ND_TOOLSETTINGS: - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); break; } break; @@ -962,13 +970,13 @@ static void image_header_region_listener(wmWindow *UNUSED(win), switch (wmn->data) { case ND_DATA: case ND_SELECT: - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); break; } break; case NC_BRUSH: if (wmn->action == NA_EDITED) { - ED_region_tag_redraw(ar); + ED_region_tag_redraw(region); } break; } |