Refactor BKE_bpath module.
The main goal of this refactor is to make BPath module use `IDTypeInfo`, and move each ID-specific part of the `foreach_path` looper into their own IDTypeInfo struct, using a new `foreach_path` callback. Additionally, following improvements/cleanups are included: * Attempt to get better, more consistent namings. ** In particular, move from `path_visitor` to more standard `foreach_path`. * Update and extend documentation. ** API doc was moved to header, according to recent discussions on this topic. * Remove `BKE_bpath_relocate_visitor` from API, this is specific callback that belongs in `lib_id.c` user code. NOTE: This commit is expected to be 100% non-behavioral-change. This implies that several potential further changes were only noted as comments (like using a more generic solution for `lib_id_library_local_paths`, addressing inconsistencies like path of packed libraries always being skipped, regardless of the `BKE_BPATH_FOREACH_PATH_SKIP_PACKED` `eBPathForeachFlag` flag value, etc.). NOTE: basic unittests were added to master already in rBdcc500e5a265093bc9cc. Reviewed By: brecht Differential Revision: https://developer.blender.org/D13381
This commit is contained in:
parent
6ae34bb071
commit
e5e8db73df
|
@ -16,10 +16,14 @@
|
|||
|
||||
/** \file
|
||||
* \ingroup bke
|
||||
* \attention Based on ghash, difference is ghash is not a fixed size,
|
||||
* so for BPath we don't need to malloc
|
||||
*
|
||||
* \warning All paths manipulated by this API are assumed to be either constant char buffers of
|
||||
* `FILE_MAX` size, or allocated char buffers not bigger than `FILE_MAX`.
|
||||
*/
|
||||
|
||||
/* TODO: Make this module handle a bit more safely string length, instead of assuming buffers are
|
||||
* FILE_MAX len etc. */
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -31,66 +35,175 @@ struct ListBase;
|
|||
struct Main;
|
||||
struct ReportList;
|
||||
|
||||
/* Function that does something with an ID's file path. Should return 1 if the
|
||||
* path has changed, and in that case, should write the result to pathOut. */
|
||||
typedef bool (*BPathVisitor)(void *userdata, char *path_dst, const char *path_src);
|
||||
/* Executes 'visit' for each path associated with 'id'. */
|
||||
void BKE_bpath_traverse_id(struct Main *bmain,
|
||||
struct ID *id,
|
||||
BPathVisitor visit_cb,
|
||||
const int flag,
|
||||
void *bpath_user_data);
|
||||
void BKE_bpath_traverse_id_list(struct Main *bmain,
|
||||
struct ListBase *lb,
|
||||
BPathVisitor visit_cb,
|
||||
const int flag,
|
||||
void *bpath_user_data);
|
||||
void BKE_bpath_traverse_main(struct Main *bmain,
|
||||
BPathVisitor visit_cb,
|
||||
const int flag,
|
||||
void *bpath_user_data);
|
||||
bool BKE_bpath_relocate_visitor(void *oldbasepath, char *path_dst, const char *path_src);
|
||||
/** \name Core `foreach_path` API.
|
||||
* \{ */
|
||||
|
||||
/* Functions for temp backup/restore of paths, path count must NOT change */
|
||||
void *BKE_bpath_list_backup(struct Main *bmain, const int flag);
|
||||
void BKE_bpath_list_restore(struct Main *bmain, const int flag, void *ls_handle);
|
||||
void BKE_bpath_list_free(void *ls_handle);
|
||||
typedef enum eBPathForeachFlag {
|
||||
/** Flags controlling the behavior of the generic BPath API. */
|
||||
|
||||
enum {
|
||||
/* convert paths to absolute */
|
||||
BKE_BPATH_TRAVERSE_ABS = (1 << 0),
|
||||
/* skip library paths */
|
||||
BKE_BPATH_TRAVERSE_SKIP_LIBRARY = (1 << 1),
|
||||
/* skip packed data */
|
||||
BKE_BPATH_TRAVERSE_SKIP_PACKED = (1 << 2),
|
||||
/* skip paths where a single dir is used with an array of files, eg.
|
||||
* sequence strip images and pointcache. in this case only use the first
|
||||
* file, this is needed for directory manipulation functions which might
|
||||
* otherwise modify the same directory multiple times */
|
||||
BKE_BPATH_TRAVERSE_SKIP_MULTIFILE = (1 << 3),
|
||||
/* reload data (when the path is edited) */
|
||||
BKE_BPATH_TRAVERSE_RELOAD_EDITED = (1 << 4),
|
||||
};
|
||||
/** Ensures the `absolute_base_path` member of #BPathForeachPathData is initialized properly with
|
||||
* the path of the current .blend file. This can be used by the callbacks to convert relative
|
||||
* paths to absolute ones. */
|
||||
BKE_BPATH_FOREACH_PATH_ABSOLUTE = (1 << 0),
|
||||
/** Skip paths of linked IDs. */
|
||||
BKE_BPATH_FOREACH_PATH_SKIP_LINKED = (1 << 1),
|
||||
/** Skip paths when their matching data is packed. */
|
||||
BKE_BPATH_FOREACH_PATH_SKIP_PACKED = (1 << 2),
|
||||
|
||||
/* high level funcs */
|
||||
/** Flags not affecting the generic BPath API. Those may be used by specific IDTypeInfo
|
||||
* `foreach_path` implementations and/or callbacks to implement specific behaviors. */
|
||||
|
||||
/* creates a text file with missing files if there are any */
|
||||
/** Skip paths where a single dir is used with an array of files, eg. sequence strip images or
|
||||
* pointcaches. In this case only use the first file path is processed.
|
||||
*
|
||||
* This is needed for directory manipulation callbacks which might otherwise modify the same
|
||||
* directory multiple times. */
|
||||
BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE = (1 << 8),
|
||||
/** Reload data (when the path is edited).
|
||||
* \note Ony used by Image IDType currently. */
|
||||
BKE_BPATH_FOREACH_PATH_RELOAD_EDITED = (1 << 9),
|
||||
} eBPathForeachFlag;
|
||||
|
||||
struct BPathForeachPathData;
|
||||
|
||||
/** Callback used to iterate over an ID's file paths.
|
||||
*
|
||||
* \note `path`s parameters should be considered as having a maximal `FILE_MAX` string length.
|
||||
*
|
||||
* \return `true` if the path has been changed, and in that case, result should be written into
|
||||
* `r_path_dst`. */
|
||||
typedef bool (*BPathForeachPathFunctionCallback)(struct BPathForeachPathData *bpath_data,
|
||||
char *r_path_dst,
|
||||
const char *path_src);
|
||||
|
||||
/** Storage for common data needed accross the BPath 'foreach_path' code. */
|
||||
typedef struct BPathForeachPathData {
|
||||
struct Main *bmain;
|
||||
|
||||
BPathForeachPathFunctionCallback callback_function;
|
||||
eBPathForeachFlag flag;
|
||||
|
||||
void *user_data;
|
||||
|
||||
/* 'Private' data, caller don't need to set those. */
|
||||
|
||||
/** The root to use as base for relative paths. Only set if `BKE_BPATH_FOREACH_PATH_ABSOLUTE`
|
||||
* flag is set, NULL otherwise. */
|
||||
const char *absolute_base_path;
|
||||
} BPathForeachPathData;
|
||||
|
||||
/** Run `bpath_data.callback_function` on all paths contained in `id`. */
|
||||
void BKE_bpath_foreach_path_id(BPathForeachPathData *bpath_data, struct ID *id);
|
||||
|
||||
/** Run `bpath_data.callback_function` on all paths of all IDs in `bmain`. */
|
||||
void BKE_bpath_foreach_path_main(BPathForeachPathData *bpath_data);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name Helpers to handle common cases from `IDTypeInfo`'s `foreach_path` functions.
|
||||
* \{ */
|
||||
|
||||
/* TODO: Investigate using macros around those calls to check a bit better about actual
|
||||
* strings/buffers length (e,g, with static asserts). */
|
||||
|
||||
/**
|
||||
* Run the callback on a path, replacing the content of the string as needed.
|
||||
*
|
||||
* \param path: A fixed, FILE_MAX-sized char buffer.
|
||||
*
|
||||
* \return true is \a path was modified, false otherwise.
|
||||
*/
|
||||
bool BKE_bpath_foreach_path_fixed_process(struct BPathForeachPathData *bpath_data, char *path);
|
||||
|
||||
/**
|
||||
* Run the callback on a (directory + file) path, replacing the content of the two strings as
|
||||
* needed.
|
||||
*
|
||||
* \param path_dir: A fixed, FILE_MAXDIR-sized char buffer.
|
||||
* \param path_file: A fixed, FILE_MAXFILE-sized char buffer.
|
||||
*
|
||||
* \return true is \a path_dir and/or \a path_file were modified, false otherwise.
|
||||
*/
|
||||
bool BKE_bpath_foreach_path_dirfile_fixed_process(struct BPathForeachPathData *bpath_data,
|
||||
char *path_dir,
|
||||
char *path_file);
|
||||
|
||||
/**
|
||||
* Run the callback on a path, replacing the content of the string as needed.
|
||||
*
|
||||
* \param path: A pointer to a MEM-allocated string. If modified, it will be freed and replaced by
|
||||
* a new allocated string.
|
||||
* \note path is expected to be FILE_MAX size or smaller.
|
||||
*
|
||||
* \return true is \a path was modified and re-allocated, false otherwise.
|
||||
*/
|
||||
bool BKE_bpath_foreach_path_allocated_process(struct BPathForeachPathData *bpath_data,
|
||||
char **path);
|
||||
|
||||
/** \} */
|
||||
|
||||
/** \name High level features.
|
||||
* \{ */
|
||||
|
||||
/** Check for missing files. */
|
||||
void BKE_bpath_missing_files_check(struct Main *bmain, struct ReportList *reports);
|
||||
|
||||
/** Recursively search into given search directory, for all file paths of all IDs in given \a
|
||||
* bmain, and replace existing paths as needed.
|
||||
*
|
||||
* \note The search will happen into the whole search directory tree recursively (with a limit of
|
||||
* MAX_DIR_RECURSE), if several files are found matching a searched filename, the biggest one will
|
||||
* be used. This is so that things like thumbnails don't get selected instead of the actual image
|
||||
* e.g.
|
||||
*
|
||||
* \param searchpath: The root directory in which the new filepaths should be searched for.
|
||||
* \param find_all: If `true`, also search for files which current path is still valid, if `false`
|
||||
* skip those still valid paths.
|
||||
* */
|
||||
void BKE_bpath_missing_files_find(struct Main *bmain,
|
||||
const char *searchpath,
|
||||
struct ReportList *reports,
|
||||
const bool find_all);
|
||||
|
||||
/** Rebase all relative file paths in given \a bmain from \a basedir_src to \a basedir_dst. */
|
||||
void BKE_bpath_relative_rebase(struct Main *bmain,
|
||||
const char *basedir_src,
|
||||
const char *basedir_dst,
|
||||
struct ReportList *reports);
|
||||
|
||||
/** Make all absolute file paths in given \a bmain relative to given \a basedir. */
|
||||
void BKE_bpath_relative_convert(struct Main *bmain,
|
||||
const char *basedir,
|
||||
struct ReportList *reports);
|
||||
|
||||
/** Make all relative file paths in given \a bmain absolute, using given \a basedir as root. */
|
||||
void BKE_bpath_absolute_convert(struct Main *bmain,
|
||||
const char *basedir,
|
||||
struct ReportList *reports);
|
||||
|
||||
/** Temp backup of paths from all IDs in given \a bmain.
|
||||
*
|
||||
* \return An opaque handle to pass to #BKE_bpath_list_restore and #BKE_bpath_list_free.
|
||||
*/
|
||||
void *BKE_bpath_list_backup(struct Main *bmain, const eBPathForeachFlag flag);
|
||||
|
||||
/** Restore the temp backup of paths from \a path_list_handle into all IDs in given \a bmain.
|
||||
*
|
||||
* \note This function assumes that the data in given Main did not change (no
|
||||
* addition/deletion/re-ordering of IDs, or their file paths) since the call to
|
||||
* #BKE_bpath_list_backup that generated the given \a path_list_handle. */
|
||||
void BKE_bpath_list_restore(struct Main *bmain,
|
||||
const eBPathForeachFlag flag,
|
||||
void *path_list_handle);
|
||||
|
||||
/** Free the temp backup of paths in \a path_list_handle.
|
||||
*
|
||||
* \note This function assumes that the path list has already been restored with a call to
|
||||
* #BKE_bpath_list_restore, and is therefore empty. */
|
||||
void BKE_bpath_list_free(void *path_list_handle);
|
||||
|
||||
/** \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,7 @@ struct BlendDataReader;
|
|||
struct BlendExpander;
|
||||
struct BlendLibReader;
|
||||
struct BlendWriter;
|
||||
struct BPathForeachPathData;
|
||||
struct ID;
|
||||
struct LibraryForeachIDData;
|
||||
struct Main;
|
||||
|
@ -100,6 +101,8 @@ typedef void (*IDTypeForeachCacheFunction)(struct ID *id,
|
|||
IDTypeForeachCacheFunctionCallback function_callback,
|
||||
void *user_data);
|
||||
|
||||
typedef void (*IDTypeForeachPathFunction)(struct ID *id, struct BPathForeachPathData *bpath_data);
|
||||
|
||||
typedef struct ID *(*IDTypeEmbeddedOwnerGetFunction)(struct Main *bmain, struct ID *id);
|
||||
|
||||
typedef void (*IDTypeBlendWriteFunction)(struct BlendWriter *writer,
|
||||
|
@ -189,6 +192,11 @@ typedef struct IDTypeInfo {
|
|||
*/
|
||||
IDTypeForeachCacheFunction foreach_cache;
|
||||
|
||||
/**
|
||||
* Iterator over all file paths of given ID.
|
||||
*/
|
||||
IDTypeForeachPathFunction foreach_path;
|
||||
|
||||
/**
|
||||
* For embedded IDs, return their owner ID.
|
||||
*/
|
||||
|
|
|
@ -328,6 +328,7 @@ IDTypeInfo IDType_ID_AC = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = action_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = action_blend_write,
|
||||
|
|
|
@ -330,6 +330,7 @@ IDTypeInfo IDType_ID_AR = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = armature_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = armature_blend_write,
|
||||
|
|
|
@ -78,7 +78,9 @@
|
|||
/** \name High Level `.blend` file read/write.
|
||||
* \{ */
|
||||
|
||||
static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const char *path_src)
|
||||
static bool foreach_path_clean_cb(BPathForeachPathData *UNUSED(bpath_data),
|
||||
char *path_dst,
|
||||
const char *path_src)
|
||||
{
|
||||
strcpy(path_dst, path_src);
|
||||
BLI_path_slash_native(path_dst);
|
||||
|
@ -86,13 +88,14 @@ static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const c
|
|||
}
|
||||
|
||||
/* make sure path names are correct for OS */
|
||||
static void clean_paths(Main *main)
|
||||
static void clean_paths(Main *bmain)
|
||||
{
|
||||
Scene *scene;
|
||||
BKE_bpath_foreach_path_main(&(BPathForeachPathData){.bmain = bmain,
|
||||
.callback_function = foreach_path_clean_cb,
|
||||
.flag = BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE,
|
||||
.user_data = NULL});
|
||||
|
||||
BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
|
||||
|
||||
for (scene = main->scenes.first; scene; scene = scene->id.next) {
|
||||
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
|
||||
BLI_path_slash_native(scene->r.pic);
|
||||
}
|
||||
}
|
||||
|
@ -887,7 +890,8 @@ bool BKE_blendfile_write_partial(Main *bmain_src,
|
|||
int a, retval;
|
||||
|
||||
void *path_list_backup = NULL;
|
||||
const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
|
||||
const eBPathForeachFlag path_list_flag = (BKE_BPATH_FOREACH_PATH_SKIP_LINKED |
|
||||
BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE);
|
||||
|
||||
/* This is needed to be able to load that file as a real one later
|
||||
* (otherwise main->name will not be set at read time). */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -160,7 +160,7 @@ TEST_F(BPathTest, list_backup_restore)
|
|||
MovieClip *movie_clip = reinterpret_cast<MovieClip *>(bmain->movieclips.first);
|
||||
BLI_strncpy(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE, sizeof(movie_clip->filepath));
|
||||
|
||||
void *path_list_handle = BKE_bpath_list_backup(bmain, 0);
|
||||
void *path_list_handle = BKE_bpath_list_backup(bmain, static_cast<eBPathForeachFlag>(0));
|
||||
|
||||
ListBase *path_list = reinterpret_cast<ListBase *>(path_list_handle);
|
||||
EXPECT_EQ(BLI_listbase_count(path_list), 2);
|
||||
|
@ -169,7 +169,7 @@ TEST_F(BPathTest, list_backup_restore)
|
|||
text->filepath = BLI_strdup(TEXT_PATH_ABSOLUTE);
|
||||
BLI_strncpy(movie_clip->filepath, MOVIECLIP_PATH_RELATIVE, sizeof(movie_clip->filepath));
|
||||
|
||||
BKE_bpath_list_restore(bmain, 0, path_list_handle);
|
||||
BKE_bpath_list_restore(bmain, static_cast<eBPathForeachFlag>(0), path_list_handle);
|
||||
|
||||
EXPECT_STREQ(text->filepath, TEXT_PATH_RELATIVE);
|
||||
EXPECT_STREQ(movie_clip->filepath, MOVIECLIP_PATH_ABSOLUTE);
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_brush.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_context.h"
|
||||
|
@ -218,6 +219,14 @@ static void brush_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
BKE_texture_mtex_foreach_id(data, &brush->mask_mtex));
|
||||
}
|
||||
|
||||
static void brush_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
Brush *brush = (Brush *)id;
|
||||
if (brush->icon_filepath[0] != '\0') {
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, brush->icon_filepath);
|
||||
}
|
||||
}
|
||||
|
||||
static void brush_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Brush *brush = (Brush *)id;
|
||||
|
@ -422,6 +431,7 @@ IDTypeInfo IDType_ID_BR = {
|
|||
.make_local = brush_make_local,
|
||||
.foreach_id = brush_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = brush_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = brush_blend_write,
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_cachefile.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
|
@ -94,6 +95,12 @@ static void cache_file_free_data(ID *id)
|
|||
BLI_freelistN(&cache_file->object_paths);
|
||||
}
|
||||
|
||||
static void cache_file_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
CacheFile *cache_file = (CacheFile *)id;
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, cache_file->filepath);
|
||||
}
|
||||
|
||||
static void cache_file_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
CacheFile *cache_file = (CacheFile *)id;
|
||||
|
@ -142,6 +149,7 @@ IDTypeInfo IDType_ID_CF = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = cache_file_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = cache_file_blend_write,
|
||||
|
|
|
@ -190,6 +190,7 @@ IDTypeInfo IDType_ID_CA = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = camera_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = camera_blend_write,
|
||||
|
|
|
@ -383,6 +383,7 @@ IDTypeInfo IDType_ID_GR = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = collection_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = collection_owner_get,
|
||||
|
||||
.blend_write = collection_blend_write,
|
||||
|
|
|
@ -320,6 +320,7 @@ IDTypeInfo IDType_ID_CU = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = curve_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = curve_blend_write,
|
||||
|
|
|
@ -328,6 +328,7 @@ IDTypeInfo IDType_ID_GD = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = greasepencil_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = greasepencil_blend_write,
|
||||
|
|
|
@ -190,6 +190,7 @@ IDTypeInfo IDType_ID_HA = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = hair_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = hair_blend_write,
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_icons.h"
|
||||
|
@ -252,6 +253,34 @@ static void image_foreach_cache(ID *id,
|
|||
}
|
||||
}
|
||||
|
||||
static void image_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
Image *ima = (Image *)id;
|
||||
const eBPathForeachFlag flag = bpath_data->flag;
|
||||
|
||||
if (BKE_image_has_packedfile(ima) && (flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
|
||||
return;
|
||||
}
|
||||
/* Skip empty file paths, these are typically from generated images and
|
||||
* don't make sense to add directories to until the image has been saved
|
||||
* once to give it a meaningful value. */
|
||||
/* TODO re-assess whether this behavior is disired in the new generic code context. */
|
||||
if (!ELEM(ima->source, IMA_SRC_FILE, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE, IMA_SRC_TILED) ||
|
||||
ima->filepath[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (BKE_bpath_foreach_path_fixed_process(bpath_data, ima->filepath)) {
|
||||
if (flag & BKE_BPATH_FOREACH_PATH_RELOAD_EDITED) {
|
||||
if (!BKE_image_has_packedfile(ima) &&
|
||||
/* Image may have been painted onto (and not saved, T44543). */
|
||||
!BKE_image_is_dirty(ima)) {
|
||||
BKE_image_signal(bpath_data->bmain, ima, NULL, IMA_SIGNAL_RELOAD);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void image_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Image *ima = (Image *)id;
|
||||
|
@ -377,6 +406,7 @@ IDTypeInfo IDType_ID_IM = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = image_foreach_cache,
|
||||
.foreach_path = image_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = image_blend_write,
|
||||
|
|
|
@ -193,6 +193,7 @@ IDTypeInfo IDType_ID_IP = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = NULL,
|
||||
|
|
|
@ -221,6 +221,7 @@ IDTypeInfo IDType_ID_KE = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = shapekey_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
/* A bit weird, due to shapekeys not being strictly speaking embedded data... But they also
|
||||
* share a lot with those (non linkable, only ever used by one owner ID, etc.). */
|
||||
.owner_get = shapekey_owner_get,
|
||||
|
|
|
@ -205,6 +205,7 @@ IDTypeInfo IDType_ID_LT = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = lattice_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = lattice_blend_write,
|
||||
|
|
|
@ -107,6 +107,8 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = NULL,
|
||||
.blend_read_data = NULL,
|
||||
|
@ -124,19 +126,57 @@ IDTypeInfo IDType_ID_LINK_PLACEHOLDER = {
|
|||
|
||||
/* ************* general ************************ */
|
||||
|
||||
/**
|
||||
* Rewrites a relative path to be relative to the main file - unless the path is
|
||||
* absolute, in which case it is not altered.
|
||||
*/
|
||||
static bool lib_id_library_local_paths_callback(BPathForeachPathData *bpath_data,
|
||||
char *r_path_dst,
|
||||
const char *path_src)
|
||||
{
|
||||
const char **data = bpath_data->user_data;
|
||||
/* be sure there is low chance of the path being too short */
|
||||
char filepath[(FILE_MAXDIR * 2) + FILE_MAXFILE];
|
||||
const char *base_new = data[0];
|
||||
const char *base_old = data[1];
|
||||
|
||||
if (BLI_path_is_rel(base_old)) {
|
||||
CLOG_ERROR(&LOG, "old base path '%s' is not absolute.", base_old);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Make referenced file absolute. This would be a side-effect of
|
||||
* BLI_path_normalize, but we do it explicitly so we know if it changed. */
|
||||
BLI_strncpy(filepath, path_src, FILE_MAX);
|
||||
if (BLI_path_abs(filepath, base_old)) {
|
||||
/* Path was relative and is now absolute. Remap.
|
||||
* Important BLI_path_normalize runs before the path is made relative
|
||||
* because it won't work for paths that start with "//../" */
|
||||
BLI_path_normalize(base_new, filepath);
|
||||
BLI_path_rel(filepath, base_new);
|
||||
BLI_strncpy(r_path_dst, filepath, FILE_MAX);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Path was not relative to begin with. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This has to be called from each make_local_* func, we could call from BKE_lib_id_make_local()
|
||||
* but then the make local functions would not be self contained.
|
||||
* Also note that the id _must_ have a library - campbell */
|
||||
/* TODO: This can probably be replaced by an ID-level version of #BKE_bpath_relative_rebase. */
|
||||
static void lib_id_library_local_paths(Main *bmain, Library *lib, ID *id)
|
||||
{
|
||||
const char *bpath_user_data[2] = {BKE_main_blendfile_path(bmain), lib->filepath_abs};
|
||||
|
||||
BKE_bpath_traverse_id(bmain,
|
||||
id,
|
||||
BKE_bpath_relocate_visitor,
|
||||
BKE_BPATH_TRAVERSE_SKIP_MULTIFILE,
|
||||
(void *)bpath_user_data);
|
||||
BKE_bpath_foreach_path_id(
|
||||
&(BPathForeachPathData){.bmain = bmain,
|
||||
.callback_function = lib_id_library_local_paths_callback,
|
||||
.flag = BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE,
|
||||
.user_data = (void *)bpath_user_data},
|
||||
id);
|
||||
}
|
||||
|
||||
static int lib_id_clear_library_data_users_update_cb(LibraryIDLinkCallbackData *cb_data)
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_lib_query.h"
|
||||
|
@ -60,6 +61,22 @@ static void library_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, lib->parent, IDWALK_CB_NEVER_SELF);
|
||||
}
|
||||
|
||||
static void library_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
Library *lib = (Library *)id;
|
||||
|
||||
/* FIXME: Find if we should respect #BKE_BPATH_FOREACH_PATH_SKIP_PACKED here, and if not, explain
|
||||
* why. */
|
||||
if (lib->packedfile !=
|
||||
NULL /*&& (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0 */) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (BKE_bpath_foreach_path_fixed_process(bpath_data, lib->filepath)) {
|
||||
BKE_library_filepath_set(bpath_data->bmain, lib, lib->filepath);
|
||||
}
|
||||
}
|
||||
|
||||
IDTypeInfo IDType_ID_LI = {
|
||||
.id_code = ID_LI,
|
||||
.id_filter = 0,
|
||||
|
@ -77,6 +94,7 @@ IDTypeInfo IDType_ID_LI = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = library_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = library_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = NULL,
|
||||
|
|
|
@ -203,6 +203,7 @@ IDTypeInfo IDType_ID_LA = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = light_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = light_blend_write,
|
||||
|
|
|
@ -100,6 +100,7 @@ IDTypeInfo IDType_ID_LP = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = lightprobe_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = lightprobe_blend_write,
|
||||
|
|
|
@ -762,6 +762,7 @@ IDTypeInfo IDType_ID_LS = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = linestyle_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = linestyle_blend_write,
|
||||
|
|
|
@ -263,6 +263,7 @@ IDTypeInfo IDType_ID_MSK = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = mask_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = mask_blend_write,
|
||||
|
|
|
@ -269,6 +269,7 @@ IDTypeInfo IDType_ID_MA = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = material_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = material_blend_write,
|
||||
|
|
|
@ -197,6 +197,7 @@ IDTypeInfo IDType_ID_MB = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = metaball_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = metaball_blend_write,
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_deform.h"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_global.h"
|
||||
|
@ -183,6 +184,14 @@ static void mesh_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
}
|
||||
}
|
||||
|
||||
static void mesh_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
Mesh *me = (Mesh *)id;
|
||||
if (me->ldata.external) {
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, me->ldata.external->filename);
|
||||
}
|
||||
}
|
||||
|
||||
static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Mesh *mesh = (Mesh *)id;
|
||||
|
@ -371,6 +380,7 @@ IDTypeInfo IDType_ID_ME = {
|
|||
/* make_local */ nullptr,
|
||||
/* foreach_id */ mesh_foreach_id,
|
||||
/* foreach_cache */ nullptr,
|
||||
/* foreach_path */ mesh_foreach_path,
|
||||
/* owner_get */ nullptr,
|
||||
|
||||
/* blend_write */ mesh_blend_write,
|
||||
|
|
|
@ -60,6 +60,7 @@
|
|||
#include "BLT_translation.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idtype.h"
|
||||
|
@ -165,6 +166,12 @@ static void movie_clip_foreach_cache(ID *id,
|
|||
function_callback(id, &key, (void **)&movie_clip->tracking.camera.intrinsics, 0, user_data);
|
||||
}
|
||||
|
||||
static void movie_clip_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
MovieClip *movie_clip = (MovieClip *)id;
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, movie_clip->filepath);
|
||||
}
|
||||
|
||||
static void write_movieTracks(BlendWriter *writer, ListBase *tracks)
|
||||
{
|
||||
MovieTrackingTrack *track;
|
||||
|
@ -355,6 +362,7 @@ IDTypeInfo IDType_ID_MC = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = movie_clip_foreach_id,
|
||||
.foreach_cache = movie_clip_foreach_cache,
|
||||
.foreach_path = movie_clip_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = movieclip_blend_write,
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_colortools.h"
|
||||
#include "BKE_cryptomatte.h"
|
||||
#include "BKE_global.h"
|
||||
|
@ -416,6 +417,29 @@ static void node_foreach_cache(ID *id,
|
|||
}
|
||||
}
|
||||
|
||||
static void node_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id);
|
||||
|
||||
switch (ntree->type) {
|
||||
case NTREE_SHADER: {
|
||||
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
|
||||
if (node->type == SH_NODE_SCRIPT) {
|
||||
NodeShaderScript *nss = reinterpret_cast<NodeShaderScript *>(node->storage);
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, nss->filepath);
|
||||
}
|
||||
else if (node->type == SH_NODE_TEX_IES) {
|
||||
NodeShaderTexIES *ies = reinterpret_cast<NodeShaderTexIES *>(node->storage);
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, ies->filepath);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static ID *node_owner_get(Main *bmain, ID *id)
|
||||
{
|
||||
if ((id->flag & LIB_EMBEDDED_DATA) == 0) {
|
||||
|
@ -1055,6 +1079,7 @@ IDTypeInfo IDType_ID_NT = {
|
|||
/* make_local */ nullptr,
|
||||
/* foreach_id */ node_foreach_id,
|
||||
/* foreach_cache */ node_foreach_cache,
|
||||
/* foreach_path */ node_foreach_path,
|
||||
/* owner_get */ node_owner_get,
|
||||
|
||||
/* blend_write */ ntree_blend_write,
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
#include "BKE_animsys.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_constraint.h"
|
||||
|
@ -548,6 +549,66 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
|
|||
}
|
||||
}
|
||||
|
||||
static void object_foreach_path_pointcache(ListBase *ptcache_list, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
for (PointCache *cache = (PointCache *)ptcache_list->first; cache != nullptr;
|
||||
cache = cache->next) {
|
||||
if (cache->flag & PTCACHE_DISK_CACHE) {
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, cache->path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void object_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
Object *ob = reinterpret_cast<Object *>(id);
|
||||
|
||||
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
|
||||
/* TODO: Move that to #ModifierTypeInfo. */
|
||||
switch (md->type) {
|
||||
case eModifierType_Fluidsim: {
|
||||
FluidsimModifierData *fluidmd = reinterpret_cast<FluidsimModifierData *>(md);
|
||||
if (fluidmd->fss) {
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, fluidmd->fss->surfdataPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eModifierType_Fluid: {
|
||||
FluidModifierData *fmd = reinterpret_cast<FluidModifierData *>(md);
|
||||
if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, fmd->domain->cache_directory);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case eModifierType_Cloth: {
|
||||
ClothModifierData *clmd = reinterpret_cast<ClothModifierData *>(md);
|
||||
object_foreach_path_pointcache(&clmd->ptcaches, bpath_data);
|
||||
break;
|
||||
}
|
||||
case eModifierType_Ocean: {
|
||||
OceanModifierData *omd = reinterpret_cast<OceanModifierData *>(md);
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, omd->cachepath);
|
||||
break;
|
||||
}
|
||||
case eModifierType_MeshCache: {
|
||||
MeshCacheModifierData *mcmd = reinterpret_cast<MeshCacheModifierData *>(md);
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, mcmd->filepath);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ob->soft != nullptr) {
|
||||
object_foreach_path_pointcache(&ob->soft->shared->ptcaches, bpath_data);
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH (ParticleSystem *, psys, &ob->particlesystem) {
|
||||
object_foreach_path_pointcache(&psys->ptcaches, bpath_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void write_fmaps(BlendWriter *writer, ListBase *fbase)
|
||||
{
|
||||
LISTBASE_FOREACH (bFaceMap *, fmap, fbase) {
|
||||
|
@ -1266,6 +1327,7 @@ IDTypeInfo IDType_ID_OB = {
|
|||
/* make_local */ object_make_local,
|
||||
/* foreach_id */ object_foreach_id,
|
||||
/* foreach_cache */ nullptr,
|
||||
/* foreach_path */ object_foreach_path,
|
||||
/* owner_get */ nullptr,
|
||||
|
||||
/* blend_write */ object_blend_write,
|
||||
|
|
|
@ -151,6 +151,7 @@ IDTypeInfo IDType_ID_PAL = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = palette_blend_write,
|
||||
|
@ -217,6 +218,7 @@ IDTypeInfo IDType_ID_PC = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = paint_curve_blend_write,
|
||||
|
|
|
@ -508,6 +508,7 @@ IDTypeInfo IDType_ID_PA = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = particle_settings_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = particle_settings_blend_write,
|
||||
|
|
|
@ -183,6 +183,7 @@ IDTypeInfo IDType_ID_PT = {
|
|||
/* make_local */ nullptr,
|
||||
/* foreach_id */ pointcloud_foreach_id,
|
||||
/* foreach_cache */ nullptr,
|
||||
/* foreach_path */ nullptr,
|
||||
/* owner_get */ nullptr,
|
||||
|
||||
/* blend_write */ pointcloud_blend_write,
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
#include "BKE_anim_data.h"
|
||||
#include "BKE_animsys.h"
|
||||
#include "BKE_armature.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_cachefile.h"
|
||||
#include "BKE_collection.h"
|
||||
#include "BKE_colortools.h"
|
||||
|
@ -891,6 +892,45 @@ static void scene_foreach_cache(ID *id,
|
|||
user_data);
|
||||
}
|
||||
|
||||
static bool seq_foreach_path_callback(Sequence *seq, void *user_data)
|
||||
{
|
||||
if (SEQ_HAS_PATH(seq)) {
|
||||
StripElem *se = seq->strip->stripdata;
|
||||
BPathForeachPathData *bpath_data = (BPathForeachPathData *)user_data;
|
||||
|
||||
if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_SOUND_RAM) && se) {
|
||||
BKE_bpath_foreach_path_dirfile_fixed_process(bpath_data, seq->strip->dir, se->name);
|
||||
}
|
||||
else if ((seq->type == SEQ_TYPE_IMAGE) && se) {
|
||||
/* NOTE: An option not to loop over all strips could be usefull? */
|
||||
unsigned int len = (unsigned int)MEM_allocN_len(se) / (unsigned int)sizeof(*se);
|
||||
unsigned int i;
|
||||
|
||||
if (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE) {
|
||||
/* only operate on one path */
|
||||
len = MIN2(1u, len);
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++, se++) {
|
||||
BKE_bpath_foreach_path_dirfile_fixed_process(bpath_data, seq->strip->dir, se->name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* simple case */
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, seq->strip->dir);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void scene_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
Scene *scene = (Scene *)id;
|
||||
if (scene->ed != NULL) {
|
||||
SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_path_callback, bpath_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Scene *sce = (Scene *)id;
|
||||
|
@ -1610,6 +1650,7 @@ IDTypeInfo IDType_ID_SCE = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = scene_foreach_id,
|
||||
.foreach_cache = scene_foreach_cache,
|
||||
.foreach_path = scene_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = scene_blend_write,
|
||||
|
|
|
@ -312,6 +312,7 @@ IDTypeInfo IDType_ID_SCR = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = screen_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = screen_blend_write,
|
||||
|
|
|
@ -162,6 +162,7 @@ IDTypeInfo IDType_ID_SIM = {
|
|||
/* make_local */ nullptr,
|
||||
/* foreach_id */ simulation_foreach_id,
|
||||
/* foreach_cache */ nullptr,
|
||||
/* foreach_path */ nullptr,
|
||||
/* owner_get */ nullptr,
|
||||
|
||||
/* blend_write */ simulation_blend_write,
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
# include <AUD_Special.h>
|
||||
#endif
|
||||
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
|
@ -133,6 +134,17 @@ static void sound_foreach_cache(ID *id,
|
|||
function_callback(id, &key, &sound->waveform, 0, user_data);
|
||||
}
|
||||
|
||||
static void sound_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
bSound *sound = (bSound *)id;
|
||||
if (sound->packedfile != NULL && (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* FIXME: This does not check for empty path... */
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, sound->filepath);
|
||||
}
|
||||
|
||||
static void sound_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
bSound *sound = (bSound *)id;
|
||||
|
@ -214,6 +226,7 @@ IDTypeInfo IDType_ID_SO = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = sound_foreach_cache,
|
||||
.foreach_path = sound_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = sound_blend_write,
|
||||
|
|
|
@ -107,6 +107,7 @@ IDTypeInfo IDType_ID_SPK = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = speaker_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = speaker_blend_write,
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "DNA_text_types.h"
|
||||
#include "DNA_userdef_types.h"
|
||||
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_idtype.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_main.h"
|
||||
|
@ -169,6 +170,15 @@ static void text_free_data(ID *id)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void text_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
Text *text = (Text *)id;
|
||||
|
||||
if (text->filepath != NULL) {
|
||||
BKE_bpath_foreach_path_allocated_process(bpath_data, &text->filepath);
|
||||
}
|
||||
}
|
||||
|
||||
static void text_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Text *text = (Text *)id;
|
||||
|
@ -250,6 +260,7 @@ IDTypeInfo IDType_ID_TXT = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = text_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = text_blend_write,
|
||||
|
|
|
@ -219,6 +219,7 @@ IDTypeInfo IDType_ID_TE = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = texture_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = texture_blend_write,
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "DNA_vfont_types.h"
|
||||
|
||||
#include "BKE_anim_path.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_curve.h"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idtype.h"
|
||||
|
@ -123,6 +124,21 @@ static void vfont_free_data(ID *id)
|
|||
}
|
||||
}
|
||||
|
||||
static void vfont_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
VFont *vfont = (VFont *)id;
|
||||
|
||||
if (vfont->packedfile != NULL && (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (BKE_vfont_is_builtin(vfont)) {
|
||||
return;
|
||||
}
|
||||
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, vfont->filepath);
|
||||
}
|
||||
|
||||
static void vfont_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
VFont *vf = (VFont *)id;
|
||||
|
@ -170,6 +186,7 @@ IDTypeInfo IDType_ID_VF = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = NULL,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = vfont_foreach_path,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = vfont_blend_write,
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BKE_anim_data.h"
|
||||
#include "BKE_bpath.h"
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idtype.h"
|
||||
|
@ -576,6 +577,17 @@ static void volume_foreach_cache(ID *id,
|
|||
function_callback(id, &key, (void **)&volume->runtime.grids, 0, user_data);
|
||||
}
|
||||
|
||||
static void volume_foreach_path(ID *id, BPathForeachPathData *bpath_data)
|
||||
{
|
||||
Volume *volume = reinterpret_cast<Volume *>(id);
|
||||
|
||||
if (volume->packedfile != nullptr && (bpath_data->flag & BKE_BPATH_FOREACH_PATH_SKIP_PACKED) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
BKE_bpath_foreach_path_fixed_process(bpath_data, volume->filepath);
|
||||
}
|
||||
|
||||
static void volume_blend_write(BlendWriter *writer, ID *id, const void *id_address)
|
||||
{
|
||||
Volume *volume = (Volume *)id;
|
||||
|
@ -653,6 +665,7 @@ IDTypeInfo IDType_ID_VO = {
|
|||
/* make_local */ nullptr,
|
||||
/* foreach_id */ volume_foreach_id,
|
||||
/* foreach_cache */ volume_foreach_cache,
|
||||
/* foreach_path */ volume_foreach_path,
|
||||
/* owner_get */ nullptr,
|
||||
|
||||
/* blend_write */ volume_blend_write,
|
||||
|
|
|
@ -195,6 +195,7 @@ IDTypeInfo IDType_ID_WS = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = workspace_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = workspace_blend_write,
|
||||
|
|
|
@ -200,6 +200,7 @@ IDTypeInfo IDType_ID_WO = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = world_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = world_blend_write,
|
||||
|
|
|
@ -1332,7 +1332,8 @@ bool BLO_write_file(Main *mainvar,
|
|||
|
||||
/* path backup/restore */
|
||||
void *path_list_backup = NULL;
|
||||
const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
|
||||
const eBPathForeachFlag path_list_flag = (BKE_BPATH_FOREACH_PATH_SKIP_LINKED |
|
||||
BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE);
|
||||
|
||||
if (G.debug & G_DEBUG_IO && mainvar->lock != NULL) {
|
||||
BKE_report(reports, RPT_INFO, "Checking sanity of current .blend file *BEFORE* save to disk");
|
||||
|
|
|
@ -880,11 +880,12 @@ struct FileCheckCallbackInfo {
|
|||
bool external_file_found;
|
||||
};
|
||||
|
||||
static bool external_file_check_callback(void *callback_info_ptr,
|
||||
static bool external_file_check_callback(BPathForeachPathData *bpath_data,
|
||||
char * /*path_dst*/,
|
||||
const char *path_src)
|
||||
{
|
||||
FileCheckCallbackInfo *callback_info = static_cast<FileCheckCallbackInfo *>(callback_info_ptr);
|
||||
FileCheckCallbackInfo *callback_info = static_cast<FileCheckCallbackInfo *>(
|
||||
bpath_data->user_data);
|
||||
BKE_reportf(callback_info->reports,
|
||||
RPT_ERROR,
|
||||
"Unable to install asset bundle, has external dependency \"%s\"",
|
||||
|
@ -904,12 +905,19 @@ static bool has_external_files(Main *bmain, struct ReportList *reports)
|
|||
{
|
||||
struct FileCheckCallbackInfo callback_info = {reports, false};
|
||||
|
||||
BKE_bpath_traverse_main(
|
||||
bmain,
|
||||
&external_file_check_callback,
|
||||
BKE_BPATH_TRAVERSE_SKIP_PACKED /* Packed files are fine. */
|
||||
| BKE_BPATH_TRAVERSE_SKIP_MULTIFILE /* Only report multifiles once, it's enough. */,
|
||||
&callback_info);
|
||||
eBPathForeachFlag flag = static_cast<eBPathForeachFlag>(
|
||||
BKE_BPATH_FOREACH_PATH_SKIP_PACKED /* Packed files are fine. */
|
||||
| BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE); /* Only report multifiles once, it's enough. */
|
||||
|
||||
BPathForeachPathData bpath_data = {
|
||||
/* bmain */ bmain,
|
||||
/* callback_function */ &external_file_check_callback,
|
||||
/* flag */ flag,
|
||||
/* user_data */ &callback_info,
|
||||
/* absolute_base_path */ nullptr,
|
||||
};
|
||||
|
||||
BKE_bpath_foreach_path_main(&bpath_data);
|
||||
return callback_info.external_file_found;
|
||||
}
|
||||
|
||||
|
|
|
@ -720,6 +720,7 @@ typedef struct RenderData {
|
|||
|
||||
/* path to render output */
|
||||
/** 1024 = FILE_MAX. */
|
||||
/* NOTE: Excluded from `BKE_bpath_foreach_path_` / `scene_foreach_path` code. */
|
||||
char pic[1024];
|
||||
|
||||
/* stamps flags. */
|
||||
|
|
|
@ -94,10 +94,13 @@ static PyObject *bpy_script_paths(PyObject *UNUSED(self))
|
|||
return ret;
|
||||
}
|
||||
|
||||
static bool bpy_blend_paths_visit_cb(void *userdata, char *UNUSED(path_dst), const char *path_src)
|
||||
static bool bpy_blend_foreach_path_cb(BPathForeachPathData *bpath_data,
|
||||
char *UNUSED(path_dst),
|
||||
const char *path_src)
|
||||
{
|
||||
PyList_APPEND((PyObject *)userdata, PyC_UnicodeFromByte(path_src));
|
||||
return false; /* never edits the path */
|
||||
PyObject *py_list = bpath_data->user_data;
|
||||
PyList_APPEND(py_list, PyC_UnicodeFromByte(path_src));
|
||||
return false; /* Never edits the path. */
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(bpy_blend_paths_doc,
|
||||
|
@ -115,7 +118,7 @@ PyDoc_STRVAR(bpy_blend_paths_doc,
|
|||
" :rtype: list of strings\n");
|
||||
static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObject *kw)
|
||||
{
|
||||
int flag = 0;
|
||||
eBPathForeachFlag flag = 0;
|
||||
PyObject *list;
|
||||
|
||||
bool absolute = false;
|
||||
|
@ -137,18 +140,21 @@ static PyObject *bpy_blend_paths(PyObject *UNUSED(self), PyObject *args, PyObjec
|
|||
}
|
||||
|
||||
if (absolute) {
|
||||
flag |= BKE_BPATH_TRAVERSE_ABS;
|
||||
flag |= BKE_BPATH_FOREACH_PATH_ABSOLUTE;
|
||||
}
|
||||
if (!packed) {
|
||||
flag |= BKE_BPATH_TRAVERSE_SKIP_PACKED;
|
||||
flag |= BKE_BPATH_FOREACH_PATH_SKIP_PACKED;
|
||||
}
|
||||
if (local) {
|
||||
flag |= BKE_BPATH_TRAVERSE_SKIP_LIBRARY;
|
||||
flag |= BKE_BPATH_FOREACH_PATH_SKIP_LINKED;
|
||||
}
|
||||
|
||||
list = PyList_New(0);
|
||||
|
||||
BKE_bpath_traverse_main(G_MAIN, bpy_blend_paths_visit_cb, flag, (void *)list);
|
||||
BKE_bpath_foreach_path_main(&(BPathForeachPathData){.bmain = G_MAIN,
|
||||
.callback_function = bpy_blend_foreach_path_cb,
|
||||
.flag = flag,
|
||||
.user_data = list});
|
||||
|
||||
return list;
|
||||
}
|
||||
|
|
|
@ -280,6 +280,7 @@ IDTypeInfo IDType_ID_WM = {
|
|||
.make_local = NULL,
|
||||
.foreach_id = window_manager_foreach_id,
|
||||
.foreach_cache = NULL,
|
||||
.foreach_path = NULL,
|
||||
.owner_get = NULL,
|
||||
|
||||
.blend_write = window_manager_blend_write,
|
||||
|
|
Loading…
Reference in New Issue