Fix T99388: Obey relative path option when saving UDIMs

Ensure that the Image maintains the proper file path after saving all
the individual tiles.

The image_save_post function is unaware that the filepath it receives
is only for a single tile, not the entire Image, and happily keeps
setting ima->filepath to the concrete filepath for each tile.

There were 2 problems with the code that attempted to correct the
Image filepath back to the UDIM virtual form:
- It would trample the "relative" directory that might have been set
- It would do the wrong thing if no tiles could be saved at all

The design is now as follows: Example of trying to save to a new PathB
|                                  | all tiles ok     | any tile not ok|
| -------------------------------- | ---------------- | ---------------|
| ima->filepath is currently empty | set to new PathB | keep empty     |
| ima->filepath is currently PathA | set to new PathB | keep PathA     |

Differential Revision: https://developer.blender.org/D15384
This commit is contained in:
Jesse Yurkovich 2022-07-07 02:08:32 -07:00
parent 50f9c1c09c
commit f256201876
Notes: blender-bot 2023-02-14 09:38:57 +01:00
Referenced by issue #99388, Saving external image to udim makes path absolute
1 changed files with 27 additions and 13 deletions

View File

@ -253,6 +253,21 @@ void BKE_image_save_options_free(ImageSaveOptions *opts)
BKE_image_format_free(&opts->im_format);
}
static void image_save_update_filepath(Image *ima,
const char *filepath,
const ImageSaveOptions *opts)
{
if (opts->do_newpath) {
BLI_strncpy(ima->filepath, filepath, sizeof(ima->filepath));
/* only image path, never ibuf */
if (opts->relative) {
const char *relbase = ID_BLEND_PATH(opts->bmain, &ima->id);
BLI_path_rel(ima->filepath, relbase); /* only after saving */
}
}
}
static void image_save_post(ReportList *reports,
Image *ima,
ImBuf *ibuf,
@ -273,13 +288,11 @@ static void image_save_post(ReportList *reports,
if (opts->do_newpath) {
BLI_strncpy(ibuf->name, filepath, sizeof(ibuf->name));
BLI_strncpy(ima->filepath, filepath, sizeof(ima->filepath));
}
/* only image path, never ibuf */
if (opts->relative) {
const char *relbase = ID_BLEND_PATH(opts->bmain, &ima->id);
BLI_path_rel(ima->filepath, relbase); /* only after saving */
}
/* The tiled image codepath must call this on its own. */
if (ima->source != IMA_SRC_TILED) {
image_save_update_filepath(ima, filepath, opts);
}
ibuf->userflags &= ~IB_BITMAPDIRTY;
@ -640,22 +653,23 @@ bool BKE_image_save(
ok = image_save_single(reports, ima, iuser, opts, &colorspace_changed);
}
else {
char filepath[FILE_MAX];
BLI_strncpy(filepath, opts->filepath, sizeof(filepath));
/* Save all the tiles. */
LISTBASE_FOREACH (ImageTile *, tile, &ima->tiles) {
ImageSaveOptions tile_opts = *opts;
BKE_image_set_filepath_from_tile_number(
opts->filepath, udim_pattern, tile_format, tile->tile_number);
tile_opts.filepath, udim_pattern, tile_format, tile->tile_number);
iuser->tile = tile->tile_number;
ok = image_save_single(reports, ima, iuser, opts, &colorspace_changed);
ok = image_save_single(reports, ima, iuser, &tile_opts, &colorspace_changed);
if (!ok) {
break;
}
}
BLI_strncpy(ima->filepath, filepath, sizeof(ima->filepath));
BLI_strncpy(opts->filepath, filepath, sizeof(opts->filepath));
/* Set the image path only if all tiles were ok. */
if (ok) {
image_save_update_filepath(ima, opts->filepath, opts);
}
MEM_freeN(udim_pattern);
}