diff options
49 files changed, 674 insertions, 286 deletions
diff --git a/extern/audaspace/include/devices/DeviceManager.h b/extern/audaspace/include/devices/DeviceManager.h index 27a546630e8..fa84025478f 100644 --- a/extern/audaspace/include/devices/DeviceManager.h +++ b/extern/audaspace/include/devices/DeviceManager.h @@ -27,6 +27,7 @@ #include <memory> #include <vector> #include <unordered_map> +#include <string> AUD_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/integrator/init_from_bake.h b/intern/cycles/kernel/integrator/init_from_bake.h index 667ba949760..cc3fbe3fe39 100644 --- a/intern/cycles/kernel/integrator/init_from_bake.h +++ b/intern/cycles/kernel/integrator/init_from_bake.h @@ -156,6 +156,13 @@ ccl_device bool integrator_init_from_bake(KernelGlobals kg, u = v; v = 1.0f - tmp - v; + const float tmpdx = dudx; + const float tmpdy = dudy; + dudx = dvdx; + dudy = dvdy; + dvdx = -tmpdx - dvdx; + dvdy = -tmpdy - dvdy; + /* Position and normal on triangle. */ const int object = kernel_data.bake.object_index; float3 P, Ng; diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset.h index 81b520a1db0..bcbe19c0f3e 100644 --- a/source/blender/blenkernel/BKE_asset.h +++ b/source/blender/blenkernel/BKE_asset.h @@ -23,6 +23,9 @@ struct ID; struct IDProperty; struct PreviewImage; +/** C handle for #bke::AssetRepresentation. */ +typedef struct AssetRepresentation AssetRepresentation; + typedef void (*PreSaveFn)(void *asset_ptr, struct AssetMetaData *asset_data); typedef struct AssetTypeInfo { @@ -68,6 +71,22 @@ struct PreviewImage *BKE_asset_metadata_preview_get_from_id(const struct AssetMe void BKE_asset_metadata_write(struct BlendWriter *writer, struct AssetMetaData *asset_data); void BKE_asset_metadata_read(struct BlendDataReader *reader, struct AssetMetaData *asset_data); +const char *BKE_asset_representation_name_get(const AssetRepresentation *asset) + ATTR_WARN_UNUSED_RESULT; +AssetMetaData *BKE_asset_representation_metadata_get(const AssetRepresentation *asset) + ATTR_WARN_UNUSED_RESULT; +bool BKE_asset_representation_is_local_id(const AssetRepresentation *asset) + ATTR_WARN_UNUSED_RESULT; + #ifdef __cplusplus } #endif + +#ifdef __cplusplus + +# include <memory> + +[[nodiscard]] std::unique_ptr<AssetMetaData> BKE_asset_metadata_move_to_unique_ptr( + AssetMetaData *asset_data); + +#endif diff --git a/source/blender/blenkernel/BKE_asset_library.h b/source/blender/blenkernel/BKE_asset_library.h index 824bc24203d..fc648ff6976 100644 --- a/source/blender/blenkernel/BKE_asset_library.h +++ b/source/blender/blenkernel/BKE_asset_library.h @@ -6,6 +6,7 @@ #pragma once +struct IDRemapper; struct Main; #ifdef __cplusplus @@ -24,41 +25,6 @@ typedef struct AssetLibrary AssetLibrary; */ struct AssetLibrary *BKE_asset_library_load(const char *library_path); -/** - * Try to find an appropriate location for an asset library root from a file or directory path. - * Does not check if \a input_path exists. - * - * The design is made to find an appropriate asset library path from a .blend file path, but - * technically works with any file or directory as \a input_path. - * Design is: - * * If \a input_path lies within a known asset library path (i.e. an asset library registered in - * the Preferences), return the asset library path. - * * Otherwise, if \a input_path has a parent path, return the parent path (e.g. to use the - * directory a .blend file is in as asset library root). - * * If \a input_path is empty or doesn't have a parent path (e.g. because a .blend wasn't saved - * yet), there is no suitable path. The caller has to decide how to handle this case. - * - * \param r_library_path: The returned asset library path with a trailing slash, or an empty string - * if no suitable path is found. Assumed to be a buffer of at least - * #FILE_MAXDIR bytes. - * - * \return True if the function could find a valid, that is, a non-empty path to return in \a - * r_library_path. - */ -bool BKE_asset_library_find_suitable_root_path_from_path( - const char *input_path, char r_library_path[768 /* FILE_MAXDIR */]); -/** - * Uses the current location on disk of the file represented by \a bmain as input to - * #BKE_asset_library_find_suitable_root_path_from_path(). Refer to it for a design - * description. - * - * \return True if the function could find a valid, that is, a non-empty path to return in \a - * r_library_path. If \a bmain wasn't saved into a file yet, the return value will be - * false. - */ -bool BKE_asset_library_find_suitable_root_path_from_main( - const struct Main *bmain, char r_library_path[768 /* FILE_MAXDIR */]); - /** Look up the asset's catalog and copy its simple name into #asset_data. */ void BKE_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_library, struct AssetMetaData *asset_data); @@ -66,6 +32,10 @@ void BKE_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_lib /** Return whether any loaded AssetLibrary has unsaved changes to its catalogs. */ bool BKE_asset_library_has_any_unsaved_catalogs(void); +/** An asset library can include local IDs (IDs in the current file). Their pointers need to be + * remapped on change (or assets removed as IDs gets removed). */ +void BKE_asset_library_remap_ids(struct IDRemapper *mappings); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_asset_library.hh b/source/blender/blenkernel/BKE_asset_library.hh index 2058df71f6a..f69847bd1ed 100644 --- a/source/blender/blenkernel/BKE_asset_library.hh +++ b/source/blender/blenkernel/BKE_asset_library.hh @@ -12,6 +12,9 @@ #include "DNA_asset_types.h" +#include "BLI_string_ref.hh" +#include "BLI_vector.hh" + #include "BKE_asset_library.h" #include "BKE_asset_catalog.hh" @@ -19,11 +22,18 @@ #include <memory> +struct AssetLibraryReference; +struct Main; + namespace blender::bke { +class AssetRepresentation; + /** * AssetLibrary provides access to an asset library's data. - * For now this is only for catalogs, later this can be expanded to indexes/caches/more. + * + * The asset library contains catalogs and storage for asset representations. It could be extended + * to also include asset indexes and more. */ struct AssetLibrary { /* Controlled by #ED_asset_catalogs_set_save_catalogs_when_file_is_saved, @@ -35,12 +45,25 @@ struct AssetLibrary { AssetLibrary(); ~AssetLibrary(); - void load(StringRefNull library_root_directory); + void load_catalogs(StringRefNull library_root_directory); /** Load catalogs that have changed on disk. */ void refresh(); /** + * Create a representation of an asset to be considered part of this library. Once the + * representation is not needed anymore, it must be freed using #remove_asset(), or there will be + * leaking that's only cleared when the library storage is destructed (typically on exit or + * loading a different file). + */ + AssetRepresentation &add_external_asset(StringRef name, std::unique_ptr<AssetMetaData> metadata); + AssetRepresentation &add_local_id_asset(ID &id); + /** Remove an asset from the library that was added using #add_external_asset() or + * #add_local_id_asset(). + * \return True on success, false if the asset couldn't be found inside the library. */ + bool remove_asset(AssetRepresentation &asset); + + /** * Update `catalog_simple_name` by looking up the asset's catalog by its ID. * * No-op if the catalog cannot be found. This could be the kind of "the @@ -53,8 +76,27 @@ struct AssetLibrary { void on_blend_save_post(Main *bmain, PointerRNA **pointers, int num_pointers); + void remap_ids(struct IDRemapper &mappings); + private: bCallbackFuncStore on_save_callback_store_{}; + + /** Storage for assets (better said their representations) that are considered to be part of this + * library. Assets are not automatically loaded into this when loading an asset library. Assets + * have to be loaded externally and added to this storage via #add_external_asset() or + * #add_local_id_asset(). So this really is arbitrary storage as far as #AssetLibrary is + * concerned (allowing the API user to manage partial library storage and partial loading, so + * only relevant parts of a library are kept in memory). + * + * For now, multiple parts of Blender just keep adding their own assets to this storage. E.g. + * multiple asset browsers might load multiple representations for the same asset into this. + * Currently there is just no way to properly identify assets, or keep track of which assets are + * already in memory and which not. Neither do we keep track of how many parts of Blender are + * using an asset or an asset library, which is needed to know when assets can be freed. + */ + Vector<std::unique_ptr<AssetRepresentation>> asset_storage_; + + std::optional<int> find_asset_index(const AssetRepresentation &asset); }; Vector<AssetLibraryReference> all_valid_asset_library_refs(); @@ -64,6 +106,40 @@ Vector<AssetLibraryReference> all_valid_asset_library_refs(); blender::bke::AssetLibrary *BKE_asset_library_load(const Main *bmain, const AssetLibraryReference &library_reference); +/** + * Try to find an appropriate location for an asset library root from a file or directory path. + * Does not check if \a input_path exists. + * + * The design is made to find an appropriate asset library path from a .blend file path, but + * technically works with any file or directory as \a input_path. + * Design is: + * * If \a input_path lies within a known asset library path (i.e. an asset library registered in + * the Preferences), return the asset library path. + * * Otherwise, if \a input_path has a parent path, return the parent path (e.g. to use the + * directory a .blend file is in as asset library root). + * * If \a input_path is empty or doesn't have a parent path (e.g. because a .blend wasn't saved + * yet), there is no suitable path. The caller has to decide how to handle this case. + * + * \param r_library_path: The returned asset library path with a trailing slash, or an empty string + * if no suitable path is found. Assumed to be a buffer of at least + * #FILE_MAXDIR bytes. + * + * \return True if the function could find a valid, that is, a non-empty path to return in \a + * r_library_path. + */ +std::string BKE_asset_library_find_suitable_root_path_from_path(blender::StringRefNull input_path); + +/** + * Uses the current location on disk of the file represented by \a bmain as input to + * #BKE_asset_library_find_suitable_root_path_from_path(). Refer to it for a design + * description. + * + * \return True if the function could find a valid, that is, a non-empty path to return in \a + * r_library_path. If \a bmain wasn't saved into a file yet, the return value will be + * false. + */ +std::string BKE_asset_library_find_suitable_root_path_from_main(const struct Main *bmain); + blender::bke::AssetCatalogService *BKE_asset_library_get_catalog_service( const ::AssetLibrary *library); blender::bke::AssetCatalogTree *BKE_asset_library_get_catalog_tree(const ::AssetLibrary *library); diff --git a/source/blender/blenkernel/BKE_asset_representation.hh b/source/blender/blenkernel/BKE_asset_representation.hh new file mode 100644 index 00000000000..edaa5a203ba --- /dev/null +++ b/source/blender/blenkernel/BKE_asset_representation.hh @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bke + */ + +#pragma once + +#include <memory> +#include <string> + +#include "BLI_string_ref.hh" + +struct AssetMetaData; +struct ID; + +namespace blender::bke { + +/** + * \brief Abstraction to reference an asset, with necessary data for display & interaction. + * + * https://wiki.blender.org/wiki/Source/Architecture/Asset_System/Back_End#Asset_Representation + */ +class AssetRepresentation { + friend struct AssetLibrary; + + struct ExternalAsset { + std::string name; + std::unique_ptr<AssetMetaData> metadata_ = nullptr; + }; + + /** Indicate if this is a local or external asset, and as such, which of the union members below + * should be used. */ + const bool is_local_id_ = false; + + union { + ExternalAsset external_asset_; + ID *local_asset_id_ = nullptr; /* Non-owning. */ + }; + + public: + /** Constructs an asset representation for an external ID. The asset will not be editable. */ + explicit AssetRepresentation(StringRef name, std::unique_ptr<AssetMetaData> metadata); + /** Constructs an asset representation for an ID stored in the current file. This makes the asset + * local and fully editable. */ + explicit AssetRepresentation(ID &id); + AssetRepresentation(AssetRepresentation &&other); + /* Non-copyable type. */ + AssetRepresentation(const AssetRepresentation &other) = delete; + ~AssetRepresentation(); + + /* Non-move-assignable type. Move construction is fine, but treat the "identity" (e.g. local vs + * external asset) of an asset representation as immutable. */ + AssetRepresentation &operator=(AssetRepresentation &&other) = delete; + /* Non-copyable type. */ + AssetRepresentation &operator=(const AssetRepresentation &other) = delete; + + StringRefNull get_name() const; + AssetMetaData &get_metadata() const; + /** Returns if this asset is stored inside this current file, and as such fully editable. */ + bool is_local_id() const; +}; + +} // namespace blender::bke diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index a797aef73f6..05b9aca7544 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -291,7 +291,11 @@ void psys_set_current_num(struct Object *ob, int index); /* UNUSED */ // struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); -struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim); +/** + * Initialize/free data for particle simulation evaluation. + */ +void psys_sim_data_init(struct ParticleSimulationData *sim); +void psys_sim_data_free(struct ParticleSimulationData *sim); /** * For a given evaluated particle system get its original. @@ -416,7 +420,7 @@ void psys_get_particle_on_path(struct ParticleSimulationData *sim, struct ParticleKey *state, bool vel); /** - * Gets particle's state at a time. + * Gets particle's state at a time. Must call psys_sim_data_init before this. * \return true if particle exists and can be seen and false if not. */ bool psys_get_particle_state(struct ParticleSimulationData *sim, diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 7d43fa7e6af..462ccc19601 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -75,6 +75,7 @@ set(SRC intern/asset_catalog_path.cc intern/asset_library.cc intern/asset_library_service.cc + intern/asset_representation.cc intern/attribute.cc intern/attribute_access.cc intern/attribute_math.cc @@ -324,6 +325,7 @@ set(SRC BKE_asset_catalog_path.hh BKE_asset_library.h BKE_asset_library.hh + BKE_asset_representation.hh BKE_attribute.h BKE_attribute.hh BKE_attribute_math.hh diff --git a/source/blender/blenkernel/intern/asset.cc b/source/blender/blenkernel/intern/asset.cc index 67802b1d6b4..7103e017847 100644 --- a/source/blender/blenkernel/intern/asset.cc +++ b/source/blender/blenkernel/intern/asset.cc @@ -27,21 +27,31 @@ using namespace blender; AssetMetaData *BKE_asset_metadata_create() { - AssetMetaData *asset_data = (AssetMetaData *)MEM_callocN(sizeof(*asset_data), __func__); - memcpy(asset_data, DNA_struct_default_get(AssetMetaData), sizeof(*asset_data)); - return asset_data; + const AssetMetaData *default_metadata = DNA_struct_default_get(AssetMetaData); + return MEM_new<AssetMetaData>(__func__, *default_metadata); } void BKE_asset_metadata_free(AssetMetaData **asset_data) { - if ((*asset_data)->properties) { - IDP_FreeProperty((*asset_data)->properties); + (*asset_data)->~AssetMetaData(); + MEM_SAFE_FREE(*asset_data); +} + +AssetMetaData::~AssetMetaData() +{ + if (properties) { + IDP_FreeProperty(properties); } - MEM_SAFE_FREE((*asset_data)->author); - MEM_SAFE_FREE((*asset_data)->description); - BLI_freelistN(&(*asset_data)->tags); + MEM_SAFE_FREE(author); + MEM_SAFE_FREE(description); + BLI_freelistN(&tags); +} - MEM_SAFE_FREE(*asset_data); +std::unique_ptr<AssetMetaData> BKE_asset_metadata_move_to_unique_ptr(AssetMetaData *asset_data) +{ + std::unique_ptr unique_asset_data = std::make_unique<AssetMetaData>(*asset_data); + *asset_data = *DNA_struct_default_get(AssetMetaData); + return unique_asset_data; } static AssetTag *asset_metadata_tag_add(AssetMetaData *asset_data, const char *const name) diff --git a/source/blender/blenkernel/intern/asset_catalog.cc b/source/blender/blenkernel/intern/asset_catalog.cc index 62d03b2d79b..a9fe59eba64 100644 --- a/source/blender/blenkernel/intern/asset_catalog.cc +++ b/source/blender/blenkernel/intern/asset_catalog.cc @@ -508,14 +508,13 @@ CatalogFilePath AssetCatalogService::find_suitable_cdf_path_for_writing( "catalog definition file should be put"); /* Ask the asset library API for an appropriate location. */ - char suitable_root_path[PATH_MAX]; - const bool asset_lib_root_found = BKE_asset_library_find_suitable_root_path_from_path( - blend_file_path.c_str(), suitable_root_path); - if (asset_lib_root_found) { + const std::string suitable_root_path = BKE_asset_library_find_suitable_root_path_from_path( + blend_file_path); + if (!suitable_root_path.empty()) { char asset_lib_cdf_path[PATH_MAX]; BLI_path_join(asset_lib_cdf_path, sizeof(asset_lib_cdf_path), - suitable_root_path, + suitable_root_path.c_str(), DEFAULT_CATALOG_FILENAME.c_str()); return asset_lib_cdf_path; } diff --git a/source/blender/blenkernel/intern/asset_library.cc b/source/blender/blenkernel/intern/asset_library.cc index b8420af1168..4dccee425c6 100644 --- a/source/blender/blenkernel/intern/asset_library.cc +++ b/source/blender/blenkernel/intern/asset_library.cc @@ -7,11 +7,14 @@ #include <memory> #include "BKE_asset_library.hh" +#include "BKE_asset_representation.hh" +#include "BKE_lib_remap.h" #include "BKE_main.h" #include "BKE_preferences.h" #include "BLI_fileops.h" #include "BLI_path_util.h" +#include "BLI_set.hh" #include "DNA_asset_types.h" #include "DNA_userdef_types.h" @@ -50,22 +53,22 @@ bool BKE_asset_library_has_any_unsaved_catalogs() return service->has_any_unsaved_catalogs(); } -bool BKE_asset_library_find_suitable_root_path_from_path(const char *input_path, - char *r_library_path) +std::string BKE_asset_library_find_suitable_root_path_from_path( + const blender::StringRefNull input_path) { if (bUserAssetLibrary *preferences_lib = BKE_preferences_asset_library_containing_path( - &U, input_path)) { - BLI_strncpy(r_library_path, preferences_lib->path, FILE_MAXDIR); - return true; + &U, input_path.c_str())) { + return preferences_lib->path; } - BLI_split_dir_part(input_path, r_library_path, FILE_MAXDIR); - return r_library_path[0] != '\0'; + char buffer[FILE_MAXDIR]; + BLI_split_dir_part(input_path.c_str(), buffer, FILE_MAXDIR); + return buffer; } -bool BKE_asset_library_find_suitable_root_path_from_main(const Main *bmain, char *r_library_path) +std::string BKE_asset_library_find_suitable_root_path_from_main(const Main *bmain) { - return BKE_asset_library_find_suitable_root_path_from_path(bmain->filepath, r_library_path); + return BKE_asset_library_find_suitable_root_path_from_path(bmain->filepath); } blender::bke::AssetCatalogService *BKE_asset_library_get_catalog_service( @@ -98,6 +101,13 @@ void BKE_asset_library_refresh_catalog_simplename(struct AssetLibrary *asset_lib lib->refresh_catalog_simplename(asset_data); } +void BKE_asset_library_remap_ids(IDRemapper *mappings) +{ + blender::bke::AssetLibraryService *service = blender::bke::AssetLibraryService::get(); + service->foreach_loaded_asset_library( + [mappings](blender::bke::AssetLibrary &library) { library.remap_ids(*mappings); }); +} + namespace blender::bke { AssetLibrary::AssetLibrary() : catalog_service(std::make_unique<AssetCatalogService>()) @@ -111,7 +121,7 @@ AssetLibrary::~AssetLibrary() } } -void AssetLibrary::load(StringRefNull library_root_directory) +void AssetLibrary::load_catalogs(StringRefNull library_root_directory) { auto catalog_service = std::make_unique<AssetCatalogService>(library_root_directory); catalog_service->load_from_disk(); @@ -123,6 +133,44 @@ void AssetLibrary::refresh() this->catalog_service->reload_catalogs(); } +AssetRepresentation &AssetLibrary::add_external_asset(StringRef name, + std::unique_ptr<AssetMetaData> metadata) +{ + asset_storage_.append(std::make_unique<AssetRepresentation>(name, std::move(metadata))); + return *asset_storage_.last(); +} + +AssetRepresentation &AssetLibrary::add_local_id_asset(ID &id) +{ + asset_storage_.append(std::make_unique<AssetRepresentation>(id)); + return *asset_storage_.last(); +} + +std::optional<int> AssetLibrary::find_asset_index(const AssetRepresentation &asset) +{ + int index = 0; + /* Find index of asset. */ + for (auto &asset_uptr : asset_storage_) { + if (&asset == asset_uptr.get()) { + return index; + } + index++; + } + + return {}; +} + +bool AssetLibrary::remove_asset(AssetRepresentation &asset) +{ + std::optional<int> asset_index = find_asset_index(asset); + if (!asset_index) { + return false; + } + + asset_storage_.remove_and_reorder(*asset_index); + return true; +} + namespace { void asset_library_on_save_post(struct Main *main, struct PointerRNA **pointers, @@ -166,6 +214,28 @@ void AssetLibrary::on_blend_save_post(struct Main *main, } } +void AssetLibrary::remap_ids(IDRemapper &mappings) +{ + Set<AssetRepresentation *> removed_id_assets; + + for (auto &asset_uptr : asset_storage_) { + if (!asset_uptr->is_local_id()) { + continue; + } + + IDRemapperApplyResult result = BKE_id_remapper_apply( + &mappings, &asset_uptr->local_asset_id_, ID_REMAP_APPLY_DEFAULT); + if (result == ID_REMAP_RESULT_SOURCE_UNASSIGNED) { + removed_id_assets.add(asset_uptr.get()); + } + } + + /* Remove the assets from storage. */ + for (AssetRepresentation *asset : removed_id_assets) { + remove_asset(*asset); + } +} + void AssetLibrary::refresh_catalog_simplename(struct AssetMetaData *asset_data) { if (BLI_uuid_is_nil(asset_data->catalog_id)) { diff --git a/source/blender/blenkernel/intern/asset_library_service.cc b/source/blender/blenkernel/intern/asset_library_service.cc index cd8de7908bf..35441b9b795 100644 --- a/source/blender/blenkernel/intern/asset_library_service.cc +++ b/source/blender/blenkernel/intern/asset_library_service.cc @@ -6,6 +6,7 @@ #include "asset_library_service.hh" +#include "BKE_asset_library.hh" #include "BKE_blender.h" #include "BKE_preferences.h" @@ -47,15 +48,10 @@ AssetLibrary *AssetLibraryService::get_asset_library( { if (library_reference.type == ASSET_LIBRARY_LOCAL) { /* For the "Current File" library we get the asset library root path based on main. */ - char root_path[FILE_MAX]; - if (bmain) { - BKE_asset_library_find_suitable_root_path_from_main(bmain, root_path); - } - else { - root_path[0] = '\0'; - } + std::string root_path = bmain ? BKE_asset_library_find_suitable_root_path_from_main(bmain) : + ""; - if (root_path[0] == '\0') { + if (root_path.empty()) { /* File wasn't saved yet. */ return get_asset_library_current_file(); } @@ -104,7 +100,7 @@ AssetLibrary *AssetLibraryService::get_asset_library_on_disk(StringRefNull top_l AssetLibrary *lib = lib_uptr.get(); lib->on_blend_save_handler_register(); - lib->load(top_dir_trailing_slash); + lib->load_catalogs(top_dir_trailing_slash); on_disk_libraries_.add_new(top_dir_trailing_slash, std::move(lib_uptr)); CLOG_INFO(&LOG, 2, "get \"%s\" (loaded)", top_dir_trailing_slash.c_str()); @@ -180,4 +176,15 @@ bool AssetLibraryService::has_any_unsaved_catalogs() const return false; } +void AssetLibraryService::foreach_loaded_asset_library(FunctionRef<void(AssetLibrary &)> fn) const +{ + if (current_file_library_) { + fn(*current_file_library_); + } + + for (const auto &asset_lib_uptr : on_disk_libraries_.values()) { + fn(*asset_lib_uptr); + } +} + } // namespace blender::bke diff --git a/source/blender/blenkernel/intern/asset_library_service.hh b/source/blender/blenkernel/intern/asset_library_service.hh index c22c6b182ce..6caaea72875 100644 --- a/source/blender/blenkernel/intern/asset_library_service.hh +++ b/source/blender/blenkernel/intern/asset_library_service.hh @@ -12,10 +12,13 @@ #include "BKE_asset_library.hh" +#include "BLI_function_ref.hh" #include "BLI_map.hh" #include <memory> +struct AssetLibraryReference; + namespace blender::bke { /** @@ -58,11 +61,16 @@ class AssetLibraryService { /** Returns whether there are any known asset libraries with unsaved catalog edits. */ bool has_any_unsaved_catalogs() const; + void foreach_loaded_asset_library(FunctionRef<void(AssetLibrary &)> fn) const; + protected: static std::unique_ptr<AssetLibraryService> instance_; /* Mapping absolute path of the library's top-level directory to the AssetLibrary instance. */ Map<std::string, AssetLibraryPtr> on_disk_libraries_; + /** Library without a known path, i.e. the "Current File" library if the file isn't saved yet. If + * the file was saved, a valid path for the library can be determined and #on_disk_libraries_ + * above should be used. */ AssetLibraryPtr current_file_library_; /* Handlers for managing the life cycle of the AssetLibraryService instance. */ diff --git a/source/blender/blenkernel/intern/asset_library_service_test.cc b/source/blender/blenkernel/intern/asset_library_service_test.cc index 7952e7ea3b0..18fdcb80155 100644 --- a/source/blender/blenkernel/intern/asset_library_service_test.cc +++ b/source/blender/blenkernel/intern/asset_library_service_test.cc @@ -8,6 +8,9 @@ #include "BKE_appdir.h" #include "BKE_callbacks.h" +#include "BKE_main.h" + +#include "DNA_asset_types.h" #include "CLG_log.h" @@ -102,6 +105,26 @@ TEST_F(AssetLibraryServiceTest, library_pointers) * cannot be reliably tested by just pointer comparison, though. */ } +TEST_F(AssetLibraryServiceTest, library_from_reference) +{ + AssetLibraryService *service = AssetLibraryService::get(); + AssetLibrary *const lib = service->get_asset_library_on_disk(asset_library_root_); + AssetLibrary *const curfile_lib = service->get_asset_library_current_file(); + + AssetLibraryReference ref{}; + ref.type = ASSET_LIBRARY_LOCAL; + EXPECT_EQ(curfile_lib, service->get_asset_library(nullptr, ref)) + << "Getting the local (current file) reference without a main saved on disk should return " + "the current file library"; + + Main dummy_main{}; + std::string dummy_filepath = asset_library_root_ + SEP + "dummy.blend"; + BLI_strncpy(dummy_main.filepath, dummy_filepath.c_str(), sizeof(dummy_main.filepath)); + EXPECT_EQ(lib, service->get_asset_library(&dummy_main, ref)) + << "Getting the local (current file) reference with a main saved on disk should return " + "the an asset library for this directory"; +} + TEST_F(AssetLibraryServiceTest, library_path_trailing_slashes) { AssetLibraryService *service = AssetLibraryService::get(); diff --git a/source/blender/blenkernel/intern/asset_representation.cc b/source/blender/blenkernel/intern/asset_representation.cc new file mode 100644 index 00000000000..bbaa634d5ad --- /dev/null +++ b/source/blender/blenkernel/intern/asset_representation.cc @@ -0,0 +1,98 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bke + */ + +#include <stdexcept> + +#include "DNA_ID.h" +#include "DNA_asset_types.h" + +#include "BKE_asset.h" +#include "BKE_asset_representation.hh" + +namespace blender::bke { + +AssetRepresentation::AssetRepresentation(StringRef name, std::unique_ptr<AssetMetaData> metadata) + : is_local_id_(false), external_asset_() +{ + external_asset_.name = name; + external_asset_.metadata_ = std::move(metadata); +} + +AssetRepresentation::AssetRepresentation(ID &id) : is_local_id_(true), local_asset_id_(&id) +{ + if (!id.asset_data) { + throw std::invalid_argument("Passed ID is not an asset"); + } +} + +AssetRepresentation::AssetRepresentation(AssetRepresentation &&other) + : is_local_id_(other.is_local_id_) +{ + if (is_local_id_) { + local_asset_id_ = other.local_asset_id_; + other.local_asset_id_ = nullptr; + } + else { + external_asset_ = std::move(other.external_asset_); + } +} + +AssetRepresentation::~AssetRepresentation() +{ + if (!is_local_id_) { + external_asset_.~ExternalAsset(); + } +} + +StringRefNull AssetRepresentation::get_name() const +{ + if (is_local_id_) { + return local_asset_id_->name + 2; + } + + return external_asset_.name; +} + +AssetMetaData &AssetRepresentation::get_metadata() const +{ + return is_local_id_ ? *local_asset_id_->asset_data : *external_asset_.metadata_; +} + +bool AssetRepresentation::is_local_id() const +{ + return is_local_id_; +} + +} // namespace blender::bke + +/* ---------------------------------------------------------------------- */ +/** \name C-API + * \{ */ + +using namespace blender; + +const char *BKE_asset_representation_name_get(const AssetRepresentation *asset_handle) +{ + const bke::AssetRepresentation *asset = reinterpret_cast<const bke::AssetRepresentation *>( + asset_handle); + return asset->get_name().c_str(); +} + +AssetMetaData *BKE_asset_representation_metadata_get(const AssetRepresentation *asset_handle) +{ + const bke::AssetRepresentation *asset = reinterpret_cast<const bke::AssetRepresentation *>( + asset_handle); + return &asset->get_metadata(); +} + +bool BKE_asset_representation_is_local_id(const AssetRepresentation *asset_handle) +{ + const bke::AssetRepresentation *asset = reinterpret_cast<const bke::AssetRepresentation *>( + asset_handle); + return asset->is_local_id(); +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/asset_test.cc b/source/blender/blenkernel/intern/asset_test.cc index fa8769862a8..5ff65054926 100644 --- a/source/blender/blenkernel/intern/asset_test.cc +++ b/source/blender/blenkernel/intern/asset_test.cc @@ -13,7 +13,7 @@ namespace blender::bke::tests { TEST(AssetMetadataTest, set_catalog_id) { - AssetMetaData meta; + AssetMetaData meta{}; const bUUID uuid = BLI_uuid_generate_random(); /* Test trivial values. */ diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 1d6092849cc..0ddd53ccb99 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -1495,7 +1495,7 @@ AssetHandle CTX_wm_asset_handle(const bContext *C, bool *r_is_valid) * require returning a non-owning pointer, which we don't have in the Asset Browser (yet). */ FileDirEntry *file = (FileDirEntry *)CTX_data_pointer_get_type(C, "active_file", &RNA_FileSelectEntry).data; - if (file && file->asset_data) { + if (file && file->asset) { *r_is_valid = true; return (AssetHandle){.file_data = file}; } diff --git a/source/blender/blenkernel/intern/fluid.c b/source/blender/blenkernel/intern/fluid.c index a3d2d73678c..c72f498cd5a 100644 --- a/source/blender/blenkernel/intern/fluid.c +++ b/source/blender/blenkernel/intern/fluid.c @@ -1532,18 +1532,8 @@ static void emit_from_particles(Object *flow_ob, sim.scene = scene; sim.ob = flow_ob; sim.psys = psys; - sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); - /* prepare curvemapping tables */ - if ((psys->part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && psys->part->clumpcurve) { - BKE_curvemapping_changed_all(psys->part->clumpcurve); - } - if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve) { - BKE_curvemapping_changed_all(psys->part->roughcurve); - } - if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve) { - BKE_curvemapping_changed_all(psys->part->twistcurve); - } + psys_sim_data_init(&sim); /* initialize particle cache */ if (psys->part->type == PART_HAIR) { @@ -1684,6 +1674,8 @@ static void emit_from_particles(Object *flow_ob, if (particle_vel) { MEM_freeN(particle_vel); } + + psys_sim_data_free(&sim); } } diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index c7643c56212..92b34b9e1af 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -21,6 +21,7 @@ #include "BKE_anim_data.h" #include "BKE_asset.h" +#include "BKE_asset_library.h" #include "BKE_idprop.h" #include "BKE_idtype.h" #include "BKE_key.h" @@ -137,16 +138,16 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i BKE_main_lock(bmain); } + struct IDRemapper *remapper = BKE_id_remapper_create(); + BKE_id_remapper_add(remapper, id, NULL); + if ((flag & LIB_ID_FREE_NO_UI_USER) == 0) { if (free_notifier_reference_cb) { free_notifier_reference_cb(id); } if (remap_editor_id_reference_cb) { - struct IDRemapper *remapper = BKE_id_remapper_create(); - BKE_id_remapper_add(remapper, id, NULL); remap_editor_id_reference_cb(remapper); - BKE_id_remapper_free(remapper); } } @@ -158,6 +159,9 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i } } + BKE_asset_library_remap_ids(remapper); + BKE_id_remapper_free(remapper); + BKE_libblock_free_data(id, (flag & LIB_ID_FREE_NO_USER_REFCOUNT) == 0); if ((flag & LIB_ID_FREE_NO_MAIN) == 0) { diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 59530a6d6a6..796ed4f8316 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -653,38 +653,29 @@ Material **BKE_object_material_get_p(Object *ob, short act) /* if object cannot have material, (totcolp == NULL) */ totcolp = BKE_object_material_len_p(ob); - if (totcolp == NULL || ob->totcol == 0) { + if (totcolp == NULL || *totcolp == 0) { return NULL; } - /* return NULL for invalid 'act', can happen for mesh face indices */ - if (act > ob->totcol) { - return NULL; - } - if (act <= 0) { - if (act < 0) { - CLOG_ERROR(&LOG, "Negative material index!"); - } - return NULL; - } + /* Clamp to number of slots if index is out of range, same convention as used for rendering. */ + const int slot_index = clamp_i(act - 1, 0, *totcolp - 1); - if (ob->matbits && ob->matbits[act - 1]) { /* in object */ - ma_p = &ob->mat[act - 1]; + /* Fix inconsistency which may happen when library linked data reduces the number of + * slots but object was not updated. Ideally should be fixed elsewhere. */ + if (*totcolp < ob->totcol) { + ob->totcol = *totcolp; } - else { /* in data */ - - /* check for inconsistency */ - if (*totcolp < ob->totcol) { - ob->totcol = *totcolp; - } - if (act > ob->totcol) { - act = ob->totcol; - } + if (slot_index < ob->totcol && ob->matbits && ob->matbits[slot_index]) { + /* Use object material slot. */ + ma_p = &ob->mat[slot_index]; + } + else { + /* Use data material slot. */ matarar = BKE_object_material_array_p(ob); if (matarar && *matarar) { - ma_p = &(*matarar)[act - 1]; + ma_p = &(*matarar)[slot_index]; } else { ma_p = NULL; @@ -717,17 +708,17 @@ static ID *get_evaluated_object_data_with_materials(Object *ob) Material *BKE_object_material_get_eval(Object *ob, short act) { BLI_assert(DEG_is_evaluated_object(ob)); - const int slot_index = act - 1; - if (slot_index < 0) { - return NULL; - } ID *data = get_evaluated_object_data_with_materials(ob); const short *tot_slots_data_ptr = BKE_id_material_len_p(data); const int tot_slots_data = tot_slots_data_ptr ? *tot_slots_data_ptr : 0; - if (slot_index >= tot_slots_data) { + + if (tot_slots_data == 0) { return NULL; } + + /* Clamp to number of slots if index is out of range, same convention as used for rendering. */ + const int slot_index = clamp_i(act - 1, 0, tot_slots_data - 1); const int tot_slots_object = ob->totcol; Material ***materials_data_ptr = BKE_id_material_array_p(data); diff --git a/source/blender/blenkernel/intern/object_dupli.cc b/source/blender/blenkernel/intern/object_dupli.cc index a41f7c8bce4..5efd44c620b 100644 --- a/source/blender/blenkernel/intern/object_dupli.cc +++ b/source/blender/blenkernel/intern/object_dupli.cc @@ -1390,7 +1390,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem RNG *rng = BLI_rng_new_srandom(31415926u + uint(psys->seed)); - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); /* Gather list of objects or single object. */ int totcollection = 0; @@ -1612,17 +1612,13 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } BLI_rng_free(rng); + psys_sim_data_free(&sim); } /* Clean up. */ if (oblist) { MEM_freeN(oblist); } - - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = nullptr; - } } static void make_duplis_particles(const DupliContext *ctx) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 4a0a09bcf56..6a277295efd 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -684,10 +684,13 @@ void psys_set_current_num(Object *ob, int index) } } -struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData *sim) +void psys_sim_data_init(ParticleSimulationData *sim) { - struct LatticeDeformData *lattice_deform_data = NULL; + ParticleSystem *psys = sim->psys; + ParticleSettings *part = psys->part; + /* Prepare lattice deform. */ + psys->lattice_deform_data = NULL; if (psys_in_edit_mode(sim->depsgraph, sim->psys) == 0) { Object *lattice = NULL; ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys); @@ -699,19 +702,39 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData if (md->mode & mode) { LatticeModifierData *lmd = (LatticeModifierData *)md; lattice = lmd->object; - sim->psys->lattice_strength = lmd->strength; + psys->lattice_strength = lmd->strength; } break; } } if (lattice) { - lattice_deform_data = BKE_lattice_deform_data_create(lattice, NULL); + psys->lattice_deform_data = BKE_lattice_deform_data_create(lattice, NULL); } } - return lattice_deform_data; + /* Prepare curvemapping tables. */ + if ((part->child_flag & PART_CHILD_USE_CLUMP_CURVE) && part->clumpcurve) { + BKE_curvemapping_init(part->clumpcurve); + } + if ((part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && part->roughcurve) { + BKE_curvemapping_init(part->roughcurve); + } + if ((part->child_flag & PART_CHILD_USE_TWIST_CURVE) && part->twistcurve) { + BKE_curvemapping_init(part->twistcurve); + } } + +void psys_sim_data_free(ParticleSimulationData *sim) +{ + ParticleSystem *psys = sim->psys; + + if (psys->lattice_deform_data) { + BKE_lattice_deform_data_destroy(psys->lattice_deform_data); + psys->lattice_deform_data = NULL; + } +} + void psys_disable_all(Object *ob) { ParticleSystem *psys = ob->particlesystem.first; @@ -2784,7 +2807,7 @@ static bool psys_thread_context_init_path(ParticleThreadContext *ctx, ctx->cfra = cfra; ctx->editupdate = editupdate; - psys->lattice_deform_data = psys_create_lattice_deform_data(&ctx->sim); + psys_sim_data_init(&ctx->sim); /* cache all relevant vertex groups if they exist */ ctx->vg_length = psys_cache_vgroup(ctx->mesh, psys, PSYS_VG_LENGTH); @@ -3340,7 +3363,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re cache = psys->pathcache = psys_alloc_path_cache_buffers( &psys->pathcachebufs, totpart, segments + 1); - psys->lattice_deform_data = psys_create_lattice_deform_data(sim); + psys_sim_data_init(sim); ma = BKE_object_material_get(sim->ob, psys->part->omat); if (ma && (psys->part->draw_col == PART_DRAW_COL_MAT)) { copy_v3_v3(col, &ma->r); @@ -3507,10 +3530,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re psys->totcached = totpart; - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(sim); if (vg_effector) { MEM_freeN(vg_effector); @@ -4867,6 +4887,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, } } } + bool psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *state, @@ -5225,7 +5246,7 @@ void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, Par sim.psys = psys; sim.psmd = psys_get_modifier(ob, psys); - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); if (psys->lattice_deform_data) { ParticleData *pa = psys->particles; @@ -5246,12 +5267,11 @@ void psys_apply_hair_lattice(Depsgraph *depsgraph, Scene *scene, Object *ob, Par } } - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - /* protect the applied shape */ psys->flag |= PSYS_EDITED; } + + psys_sim_data_free(&sim); } /* Draw Engine */ diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 72094f8cf04..d97a217a734 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -516,10 +516,7 @@ void psys_thread_context_free(ParticleThreadContext *ctx) MEM_freeN(ctx->vg_twist); } - if (ctx->sim.psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(ctx->sim.psys->lattice_deform_data); - ctx->sim.psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&ctx->sim); /* distribution */ if (ctx->jit) { @@ -3557,12 +3554,12 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) invert_m4_m4(ob->world_to_object, ob->object_to_world); - psys->lattice_deform_data = psys_create_lattice_deform_data(sim); - if (psys->totpart == 0) { return; } + psys_sim_data_init(sim); + /* save new keys for elements if needed */ LOOP_PARTICLES { @@ -3596,6 +3593,8 @@ static void save_hair(ParticleSimulationData *sim, float UNUSED(cfra)) zero_v3(root->co); } } + + psys_sim_data_free(sim); } /* Code for an adaptive time step based on the Courant-Friedrichs-Lewy @@ -4099,6 +4098,8 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_ disp = psys_get_current_display_percentage(psys, use_render_params); + psys_sim_data_init(sim); + LOOP_PARTICLES { psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); @@ -4107,8 +4108,6 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_ pa->size *= 1.0f - part->randsize * psys_frand(psys, p + 1); } - psys->lattice_deform_data = psys_create_lattice_deform_data(sim); - dietime = pa->dietime; /* update alive status and push events */ @@ -4125,11 +4124,6 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_ pa->alive = PARS_ALIVE; } - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } - if (psys_frand(psys, p) > disp) { pa->flag |= PARS_NO_DISP; } @@ -4137,6 +4131,8 @@ static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_ pa->flag &= ~PARS_NO_DISP; } } + + psys_sim_data_free(sim); } static bool particles_has_flip(short parttype) @@ -4609,10 +4605,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ update_children(sim, use_render_params); /* cleanup */ - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(sim); } void psys_changed_type(Object *ob, ParticleSystem *psys) diff --git a/source/blender/draw/intern/draw_cache_impl_particles.c b/source/blender/draw/intern/draw_cache_impl_particles.c index 8facea4333f..cddab74c46f 100644 --- a/source/blender/draw/intern/draw_cache_impl_particles.c +++ b/source/blender/draw/intern/draw_cache_impl_particles.c @@ -1346,7 +1346,7 @@ static void particle_batch_cache_ensure_pos(Object *object, sim.ob = object; sim.psys = psys; sim.psmd = psys_get_modifier(object, psys); - sim.psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); GPU_VERTBUF_DISCARD_SAFE(point_cache->pos); @@ -1392,6 +1392,8 @@ static void particle_batch_cache_ensure_pos(Object *object, if (curr_point != psys->totpart) { GPU_vertbuf_data_resize(point_cache->pos, curr_point); } + + psys_sim_data_free(&sim); } static void drw_particle_update_ptcache_edit(Object *object_eval, diff --git a/source/blender/editors/asset/intern/asset_handle.cc b/source/blender/editors/asset/intern/asset_handle.cc index 00fffd595c0..0b2cd352d77 100644 --- a/source/blender/editors/asset/intern/asset_handle.cc +++ b/source/blender/editors/asset/intern/asset_handle.cc @@ -8,6 +8,9 @@ #include "DNA_space_types.h" +#include "BKE_asset.h" +#include "BKE_asset_representation.hh" + #include "BLO_readfile.h" #include "ED_asset_handle.h" @@ -17,12 +20,12 @@ const char *ED_asset_handle_get_name(const AssetHandle *asset) { - return asset->file_data->name; + return BKE_asset_representation_name_get(asset->file_data->asset); } -AssetMetaData *ED_asset_handle_get_metadata(const AssetHandle *asset) +AssetMetaData *ED_asset_handle_get_metadata(const AssetHandle *asset_handle) { - return asset->file_data->asset_data; + return BKE_asset_representation_metadata_get(asset_handle->file_data->asset); } ID *ED_asset_handle_get_local_id(const AssetHandle *asset) diff --git a/source/blender/editors/asset/intern/asset_temp_id_consumer.cc b/source/blender/editors/asset/intern/asset_temp_id_consumer.cc index 376454d62b6..d1fd48d966c 100644 --- a/source/blender/editors/asset/intern/asset_temp_id_consumer.cc +++ b/source/blender/editors/asset/intern/asset_temp_id_consumer.cc @@ -72,7 +72,7 @@ AssetTempIDConsumer *ED_asset_temp_id_consumer_create(const AssetHandle *handle) if (!handle) { return nullptr; } - BLI_assert(handle->file_data->asset_data != nullptr); + BLI_assert(handle->file_data->asset != nullptr); return reinterpret_cast<AssetTempIDConsumer *>( MEM_new<AssetTemporaryIDConsumer>(__func__, *handle)); } diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 66b3d9fba6b..415356d1d71 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -1789,7 +1789,6 @@ void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, float scale); void UI_but_drag_set_asset(uiBut *but, const struct AssetHandle *asset, const char *path, - struct AssetMetaData *metadata, int import_type, /* eFileAssetImportType */ int icon, struct ImBuf *imb, diff --git a/source/blender/editors/interface/interface_drag.cc b/source/blender/editors/interface/interface_drag.cc index 4bf2dac4151..e959986d19e 100644 --- a/source/blender/editors/interface/interface_drag.cc +++ b/source/blender/editors/interface/interface_drag.cc @@ -27,15 +27,14 @@ void UI_but_drag_attach_image(uiBut *but, struct ImBuf *imb, const float scale) } void UI_but_drag_set_asset(uiBut *but, - const AssetHandle *asset, + const AssetHandle *asset_handle, const char *path, - struct AssetMetaData *metadata, int import_type, int icon, struct ImBuf *imb, float scale) { - wmDragAsset *asset_drag = WM_drag_create_asset_data(asset, metadata, path, import_type); + wmDragAsset *asset_drag = WM_drag_create_asset_data(asset_handle, path, import_type); /* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the * #wmDropBox. diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc index 11fe653724c..9a3f7800c64 100644 --- a/source/blender/editors/interface/interface_template_asset_view.cc +++ b/source/blender/editors/interface/interface_template_asset_view.cc @@ -57,7 +57,6 @@ static void asset_view_item_but_drag_set(uiBut *but, UI_but_drag_set_asset(but, asset_handle, BLI_strdup(blend_path), - ED_asset_handle_get_metadata(asset_handle), FILE_ASSET_IMPORT_APPEND, ED_asset_handle_get_preview_icon_id(asset_handle), imbuf, diff --git a/source/blender/editors/space_file/CMakeLists.txt b/source/blender/editors/space_file/CMakeLists.txt index 688aa846c30..76564f38da8 100644 --- a/source/blender/editors/space_file/CMakeLists.txt +++ b/source/blender/editors/space_file/CMakeLists.txt @@ -46,6 +46,10 @@ set(LIB bf_blenkernel ) +if(WIN32) + add_definitions(-DNOMINMAX) +endif() + if(WITH_HEADLESS) add_definitions(-DWITH_HEADLESS) else() diff --git a/source/blender/editors/space_file/asset_catalog_tree_view.cc b/source/blender/editors/space_file/asset_catalog_tree_view.cc index 4eb2958f5a2..fe2e46fc056 100644 --- a/source/blender/editors/space_file/asset_catalog_tree_view.cc +++ b/source/blender/editors/space_file/asset_catalog_tree_view.cc @@ -708,12 +708,11 @@ bool file_set_asset_catalog_filter_settings( void file_ensure_updated_catalog_filter_data( FileAssetCatalogFilterSettingsHandle *filter_settings_handle, - const ::AssetLibrary *asset_library) + const bke::AssetLibrary *asset_library) { AssetCatalogFilterSettings *filter_settings = reinterpret_cast<AssetCatalogFilterSettings *>( filter_settings_handle); - const AssetCatalogService *catalog_service = BKE_asset_library_get_catalog_service( - asset_library); + const AssetCatalogService *catalog_service = asset_library->catalog_service.get(); if (filter_settings->asset_catalog_visibility != FILE_SHOW_ASSETS_ALL_CATALOGS) { filter_settings->catalog_filter = std::make_unique<AssetCatalogFilter>( diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 240901318b5..ed0132c6990 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -171,7 +171,6 @@ static void file_draw_icon(const SpaceFile *sfile, UI_but_drag_set_asset(but, &(AssetHandle){.file_data = file}, BLI_strdup(blend_path), - file->asset_data, asset_params->import_type, icon, preview_image, @@ -565,7 +564,6 @@ static void file_draw_preview(const SpaceFile *sfile, UI_but_drag_set_asset(but, &(AssetHandle){.file_data = file}, BLI_strdup(blend_path), - file->asset_data, asset_params->import_type, icon, imb, diff --git a/source/blender/editors/space_file/file_indexer.cc b/source/blender/editors/space_file/file_indexer.cc index ec631eb48b3..8520ac34122 100644 --- a/source/blender/editors/space_file/file_indexer.cc +++ b/source/blender/editors/space_file/file_indexer.cc @@ -67,8 +67,9 @@ void ED_file_indexer_entries_extend_from_datablock_infos( } } -static void ED_file_indexer_entry_free(void *indexer_entry) +static void ED_file_indexer_entry_free(void *indexer_entry_ptr) { + FileIndexerEntry *indexer_entry = static_cast<FileIndexerEntry *>(indexer_entry_ptr); MEM_freeN(indexer_entry); } diff --git a/source/blender/editors/space_file/file_intern.h b/source/blender/editors/space_file/file_intern.h index eac72af00ab..0ca09487507 100644 --- a/source/blender/editors/space_file/file_intern.h +++ b/source/blender/editors/space_file/file_intern.h @@ -218,6 +218,17 @@ void file_path_to_ui_path(const char *path, char *r_pathi, int max_size); /* C-handle for #ed::asset_browser::AssetCatalogFilterSettings. */ typedef struct FileAssetCatalogFilterSettingsHandle FileAssetCatalogFilterSettingsHandle; +void file_create_asset_catalog_tree_view_in_layout(struct AssetLibrary *asset_library, + struct uiLayout *layout, + SpaceFile *space_file, + FileAssetSelectParams *params); + +#ifdef __cplusplus + +namespace blender::bke { +struct AssetLibrary; +} + FileAssetCatalogFilterSettingsHandle *file_create_asset_catalog_filter_settings(void); void file_delete_asset_catalog_filter_settings( FileAssetCatalogFilterSettingsHandle **filter_settings_handle); @@ -231,15 +242,12 @@ bool file_set_asset_catalog_filter_settings( bUUID catalog_id); void file_ensure_updated_catalog_filter_data( FileAssetCatalogFilterSettingsHandle *filter_settings_handle, - const struct AssetLibrary *asset_library); + const blender::bke::AssetLibrary *asset_library); bool file_is_asset_visible_in_catalog_filter_settings( const FileAssetCatalogFilterSettingsHandle *filter_settings_handle, const AssetMetaData *asset_data); -void file_create_asset_catalog_tree_view_in_layout(struct AssetLibrary *asset_library, - struct uiLayout *layout, - struct SpaceFile *space_file, - struct FileAssetSelectParams *params); +#endif #ifdef __cplusplus } diff --git a/source/blender/editors/space_file/filelist.cc b/source/blender/editors/space_file/filelist.cc index 9ca5b1da7da..c4d99d41a60 100644 --- a/source/blender/editors/space_file/filelist.cc +++ b/source/blender/editors/space_file/filelist.cc @@ -43,6 +43,8 @@ #include "BKE_asset.h" #include "BKE_asset_library.h" +#include "BKE_asset_library.hh" +#include "BKE_asset_representation.hh" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_icons.h" @@ -78,6 +80,8 @@ #include "file_intern.h" #include "filelist.h" +using namespace blender; + #define FILEDIR_NBR_ENTRIES_UNSET -1 /* ------------------FILELIST------------------------ */ @@ -95,7 +99,7 @@ struct FileListInternEntry { /** Optional argument for shortcuts, aliases etc. */ char *redirection_path; /** not strictly needed, but used during sorting, avoids to have to recompute it there... */ - char *name; + const char *name; bool free_name; /** @@ -112,9 +116,8 @@ struct FileListInternEntry { PreviewImage *preview_image; } local_data; - /** When the file represents an asset read from another file, it is stored here. - * Owning pointer. */ - AssetMetaData *imported_asset_data; + /* References an asset in the asset library storage. */ + bke::AssetRepresentation *asset; /* Non-owning. */ /* See #FILE_ENTRY_BLENDERLIB_NO_PREVIEW. */ bool blenderlib_has_no_preview; @@ -210,7 +213,7 @@ struct FileList { eFileSelectType type; /* The library this list was created for. Stored here so we know when to re-read. */ AssetLibraryReference *asset_library_ref; - AssetLibrary *asset_library; /* Non-owning pointer. */ + bke::AssetLibrary *asset_library; /* Non-owning. */ short flags; @@ -776,8 +779,10 @@ static bool is_filtered_id_file_type(const FileListInternEntry *file, */ static AssetMetaData *filelist_file_internal_get_asset_data(const FileListInternEntry *file) { - const ID *local_id = file->local_data.id; - return local_id ? local_id->asset_data : file->imported_asset_data; + if (!file->asset) { + return nullptr; + } + return &file->asset->get_metadata(); } static void prepare_filter_asset_library(const FileList *filelist, FileListFilter *filter) @@ -1016,7 +1021,7 @@ void filelist_setindexer(FileList *filelist, const FileIndexerType *indexer) void filelist_set_asset_catalog_filter_options( FileList *filelist, eFileSel_Params_AssetCatalogVisibility catalog_visibility, - const bUUID *catalog_id) + const ::bUUID *catalog_id) { if (!filelist->filter_data.asset_catalog_filter) { /* There's no filter data yet. */ @@ -1362,7 +1367,7 @@ static bool filelist_checkdir_main_assets(struct FileList * /*filelist*/, static void filelist_entry_clear(FileDirEntry *entry) { if (entry->name && ((entry->flags & FILE_ENTRY_NAME_FREE) != 0)) { - MEM_freeN(entry->name); + MEM_freeN((char *)entry->name); } if (entry->relpath) { MEM_freeN(entry->relpath); @@ -1399,8 +1404,13 @@ static void filelist_direntryarr_free(FileDirEntryArr *array) array->entries_filtered_num = FILEDIR_NBR_ENTRIES_UNSET; } -static void filelist_intern_entry_free(FileListInternEntry *entry) +static void filelist_intern_entry_free(FileList *filelist, FileListInternEntry *entry) { + if (entry->asset) { + BLI_assert(filelist->asset_library); + filelist->asset_library->remove_asset(*entry->asset); + } + if (entry->relpath) { MEM_freeN(entry->relpath); } @@ -1408,19 +1418,16 @@ static void filelist_intern_entry_free(FileListInternEntry *entry) MEM_freeN(entry->redirection_path); } if (entry->name && entry->free_name) { - MEM_freeN(entry->name); - } - /* If we own the asset-data (it was generated from external file data), free it. */ - if (entry->imported_asset_data) { - BKE_asset_metadata_free(&entry->imported_asset_data); + MEM_freeN((char *)entry->name); } MEM_freeN(entry); } -static void filelist_intern_free(FileListIntern *filelist_intern) +static void filelist_intern_free(FileList *filelist) { + FileListIntern *filelist_intern = &filelist->filelist_intern; LISTBASE_FOREACH_MUTABLE (FileListInternEntry *, entry, &filelist_intern->entries) { - filelist_intern_entry_free(entry); + filelist_intern_entry_free(filelist, entry); } BLI_listbase_clear(&filelist_intern->entries); @@ -1430,8 +1437,9 @@ static void filelist_intern_free(FileListIntern *filelist_intern) /** * \return the number of main files removed. */ -static int filelist_intern_free_main_files(FileListIntern *filelist_intern) +static int filelist_intern_free_main_files(FileList *filelist) { + FileListIntern *filelist_intern = &filelist->filelist_intern; int removed_counter = 0; LISTBASE_FOREACH_MUTABLE (FileListInternEntry *, entry, &filelist_intern->entries) { if (!filelist_intern_entry_is_main_file(entry)) { @@ -1439,7 +1447,7 @@ static int filelist_intern_free_main_files(FileListIntern *filelist_intern) } BLI_remlink(&filelist_intern->entries, entry); - filelist_intern_entry_free(entry); + filelist_intern_entry_free(filelist, entry); removed_counter++; } @@ -1794,7 +1802,7 @@ void filelist_clear_ex(struct FileList *filelist, filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size); } - filelist_intern_free(&filelist->filelist_intern); + filelist_intern_free(filelist); filelist_direntryarr_free(&filelist->filelist); @@ -1822,7 +1830,7 @@ static void filelist_clear_main_files(FileList *filelist, filelist_cache_clear(&filelist->filelist_cache, filelist->filelist_cache.size); } - const int removed_files = filelist_intern_free_main_files(&filelist->filelist_intern); + const int removed_files = filelist_intern_free_main_files(filelist); filelist->filelist.entries_num -= removed_files; filelist->filelist.entries_filtered_num = FILEDIR_NBR_ENTRIES_UNSET; @@ -1881,7 +1889,7 @@ void filelist_free(struct FileList *filelist) AssetLibrary *filelist_asset_library(FileList *filelist) { - return filelist->asset_library; + return reinterpret_cast<::AssetLibrary *>(filelist->asset_library); } void filelist_freelib(struct FileList *filelist) @@ -1897,11 +1905,15 @@ BlendHandle *filelist_lib(struct FileList *filelist) return filelist->libfiledata; } -static char *fileentry_uiname(const char *root, - const char *relpath, - const eFileSel_File_Types typeflag, - char *buff) +static const char *fileentry_uiname(const char *root, FileListInternEntry *entry, char *buff) { + if (entry->asset) { + const StringRefNull asset_name = entry->asset->get_name(); + return BLI_strdupn(asset_name.c_str(), asset_name.size()); + } + + const char *relpath = entry->relpath; + const eFileSel_File_Types typeflag = entry->typeflag; char *name = nullptr; if (typeflag & FILE_TYPE_FTFONT && !(typeflag & FILE_TYPE_BLENDERLIB)) { @@ -2042,10 +2054,7 @@ static FileDirEntry *filelist_file_create_entry(FileList *filelist, const int in ret->redirection_path = BLI_strdup(entry->redirection_path); } ret->id = entry->local_data.id; - ret->asset_data = entry->imported_asset_data ? entry->imported_asset_data : nullptr; - if (ret->id && (ret->asset_data == nullptr)) { - ret->asset_data = ret->id->asset_data; - } + ret->asset = reinterpret_cast<::AssetRepresentation *>(entry->asset); /* For some file types the preview is already available. */ if (entry->local_data.preview_image && BKE_previewimg_is_finished(entry->local_data.preview_image, ICON_SIZE_PREVIEW)) { @@ -2996,8 +3005,13 @@ static FileListInternEntry *filelist_readjob_list_lib_group_create(const int idc return entry; } -static void filelist_readjob_list_lib_add_datablock(ListBase *entries, - const BLODataBlockInfo *datablock_info, +/** + * \warning: This "steals" the asset metadata from \a datablock_info. Not great design but fixing + * this requires redesigning things on the caller side for proper ownership management. + */ +static void filelist_readjob_list_lib_add_datablock(FileList *filelist, + ListBase *entries, + BLODataBlockInfo *datablock_info, const bool prefix_relpath_with_group_name, const int idcode, const char *group_name) @@ -3010,21 +3024,29 @@ static void filelist_readjob_list_lib_add_datablock(ListBase *entries, entry->relpath = BLI_strdup(datablock_info->name); } entry->typeflag |= FILE_TYPE_BLENDERLIB; - if (datablock_info) { entry->blenderlib_has_no_preview = datablock_info->no_preview_found; if (datablock_info->asset_data) { entry->typeflag |= FILE_TYPE_ASSET; - /* Moves ownership! */ - entry->imported_asset_data = datablock_info->asset_data; + + if (filelist->asset_library) { + /** XXX Moving out the asset metadata like this isn't great. */ + std::unique_ptr metadata = BKE_asset_metadata_move_to_unique_ptr( + datablock_info->asset_data); + BKE_asset_metadata_free(&datablock_info->asset_data); + + entry->asset = &filelist->asset_library->add_external_asset(datablock_info->name, + std::move(metadata)); + } } } entry->blentype = idcode; BLI_addtail(entries, entry); } -static void filelist_readjob_list_lib_add_datablocks(ListBase *entries, +static void filelist_readjob_list_lib_add_datablocks(FileList *filelist, + ListBase *entries, LinkNode *datablock_infos, const bool prefix_relpath_with_group_name, const int idcode, @@ -3033,19 +3055,21 @@ static void filelist_readjob_list_lib_add_datablocks(ListBase *entries, for (LinkNode *ln = datablock_infos; ln; ln = ln->next) { struct BLODataBlockInfo *datablock_info = static_cast<BLODataBlockInfo *>(ln->link); filelist_readjob_list_lib_add_datablock( - entries, datablock_info, prefix_relpath_with_group_name, idcode, group_name); + filelist, entries, datablock_info, prefix_relpath_with_group_name, idcode, group_name); } } static void filelist_readjob_list_lib_add_from_indexer_entries( + FileList *filelist, ListBase *entries, const FileIndexerEntries *indexer_entries, const bool prefix_relpath_with_group_name) { for (const LinkNode *ln = indexer_entries->entries; ln; ln = ln->next) { - const FileIndexerEntry *indexer_entry = (const FileIndexerEntry *)ln->link; + FileIndexerEntry *indexer_entry = static_cast<FileIndexerEntry *>(ln->link); const char *group_name = BKE_idtype_idcode_to_name(indexer_entry->idcode); - filelist_readjob_list_lib_add_datablock(entries, + filelist_readjob_list_lib_add_datablock(filelist, + entries, &indexer_entry->datablock_info, prefix_relpath_with_group_name, indexer_entry->idcode, @@ -3073,7 +3097,8 @@ typedef struct FileIndexer { void *user_data; } FileIndexer; -static int filelist_readjob_list_lib_populate_from_index(ListBase *entries, +static int filelist_readjob_list_lib_populate_from_index(FileList *filelist, + ListBase *entries, const ListLibOptions options, const int read_from_index, const FileIndexerEntries *indexer_entries) @@ -3085,11 +3110,12 @@ static int filelist_readjob_list_lib_populate_from_index(ListBase *entries, navigate_to_parent_len = 1; } - filelist_readjob_list_lib_add_from_indexer_entries(entries, indexer_entries, true); + filelist_readjob_list_lib_add_from_indexer_entries(filelist, entries, indexer_entries, true); return read_from_index + navigate_to_parent_len; } -static int filelist_readjob_list_lib(const char *root, +static int filelist_readjob_list_lib(FileList *filelist, + const char *root, ListBase *entries, const ListLibOptions options, FileIndexer *indexer_runtime) @@ -3128,7 +3154,7 @@ static int filelist_readjob_list_lib(const char *root, dir, &indexer_entries, &read_from_index, indexer_runtime->user_data); if (indexer_result == FILE_INDEXER_ENTRIES_LOADED) { int entries_read = filelist_readjob_list_lib_populate_from_index( - entries, options, read_from_index, &indexer_entries); + filelist, entries, options, read_from_index, &indexer_entries); ED_file_indexer_entries_clear(&indexer_entries); return entries_read; } @@ -3158,7 +3184,8 @@ static int filelist_readjob_list_lib(const char *root, const int idcode = groupname_to_code(group); LinkNode *datablock_infos = BLO_blendhandle_get_datablock_info( libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &datablock_len); - filelist_readjob_list_lib_add_datablocks(entries, datablock_infos, false, idcode, group); + filelist_readjob_list_lib_add_datablocks( + filelist, entries, datablock_infos, false, idcode, group); BLI_linklist_freeN(datablock_infos); } else { @@ -3177,7 +3204,7 @@ static int filelist_readjob_list_lib(const char *root, LinkNode *group_datablock_infos = BLO_blendhandle_get_datablock_info( libfiledata, idcode, options & LIST_LIB_ASSETS_ONLY, &group_datablock_len); filelist_readjob_list_lib_add_datablocks( - entries, group_datablock_infos, true, idcode, group_name); + filelist, entries, group_datablock_infos, true, idcode, group_name); if (use_indexer) { ED_file_indexer_entries_extend_from_datablock_infos( &indexer_entries, group_datablock_infos, idcode); @@ -3529,7 +3556,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, list_lib_options |= LIST_LIB_ASSETS_ONLY; } entries_num = filelist_readjob_list_lib( - subdir, &entries, list_lib_options, &indexer_runtime); + filelist, subdir, &entries, list_lib_options, &indexer_runtime); if (entries_num > 0) { is_lib = true; } @@ -3550,7 +3577,7 @@ static void filelist_readjob_recursive_dir_add_items(const bool do_lib, MEM_freeN(entry->relpath); entry->relpath = BLI_strdup(dir + 2); /* + 2 to remove '//' * added by BLI_path_rel to rel_subdir. */ - entry->name = fileentry_uiname(root, entry->relpath, entry->typeflag, dir); + entry->name = fileentry_uiname(root, entry, dir); entry->free_name = true; if (filelist_readjob_should_recurse_into_entry( @@ -3626,20 +3653,6 @@ static void filelist_readjob_lib(FileListReadJob *job_params, filelist_readjob_do(true, job_params, stop, do_update, progress); } -static void filelist_asset_library_path(const FileListReadJob *job_params, - char r_library_root_path[FILE_MAX]) -{ - if (job_params->filelist->type == FILE_MAIN_ASSET) { - /* For the "Current File" library (#FILE_MAIN_ASSET) we get the asset library root path based - * on main. */ - BKE_asset_library_find_suitable_root_path_from_main(job_params->current_main, - r_library_root_path); - } - else { - BLI_strncpy(r_library_root_path, job_params->tmp_filelist->filelist.root, FILE_MAX); - } -} - /** * Load asset library data, which currently means loading the asset catalogs for the library. */ @@ -3657,12 +3670,10 @@ static void filelist_readjob_load_asset_library_data(FileListReadJob *job_params return; } - char library_root_path[FILE_MAX]; - filelist_asset_library_path(job_params, library_root_path); - /* Load asset catalogs, into the temp filelist for thread-safety. * #filelist_readjob_endjob() will move it into the real filelist. */ - tmp_filelist->asset_library = BKE_asset_library_load(library_root_path); + tmp_filelist->asset_library = BKE_asset_library_load(job_params->current_main, + *job_params->filelist->asset_library_ref); *do_update = true; } @@ -3699,6 +3710,9 @@ static void filelist_readjob_main_assets_add_items(FileListReadJob *job_params, entry->local_data.preview_image = BKE_asset_metadata_preview_get_from_id(id_iter->asset_data, id_iter); entry->local_data.id = id_iter; + if (filelist->asset_library) { + entry->asset = &filelist->asset_library->add_local_id_asset(*id_iter); + } entries_num++; BLI_addtail(&tmp_entries, entry); } diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 74f1b8e838a..95b87f06d96 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -950,7 +950,7 @@ static int /*eContextResult*/ file_context(const bContext *C, for (int file_index = 0; file_index < num_files_filtered; file_index++) { if (filelist_entry_is_selected(sfile->files, file_index)) { FileDirEntry *entry = filelist_file(sfile->files, file_index); - if (entry->asset_data) { + if (entry->asset) { CTX_data_list_add(result, &screen->id, &RNA_FileSelectEntry, entry); } } diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 637c795d4d7..8eeba8727dc 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -1678,6 +1678,7 @@ static int node_join_exec(bContext *C, wmOperator * /*op*/) const Set<bNode *> selected_nodes = get_selected_nodes(ntree); bNode *frame_node = nodeAddStaticNode(C, &ntree, NODE_FRAME); + nodeSetActive(&ntree, frame_node); /* reset tags */ LISTBASE_FOREACH (bNode *, node, &ntree.nodes) { diff --git a/source/blender/geometry/intern/set_curve_type.cc b/source/blender/geometry/intern/set_curve_type.cc index 4233c62c7b3..e069732ca9b 100644 --- a/source/blender/geometry/intern/set_curve_type.cc +++ b/source/blender/geometry/intern/set_curve_type.cc @@ -257,7 +257,7 @@ static int to_bezier_size(const CurveType src_type, switch (src_type) { case CURVE_TYPE_NURBS: { if (is_nurbs_to_bezier_one_to_one(knots_mode)) { - return cyclic ? src_size : src_size - 2; + return cyclic ? src_size : std::max(1, src_size - 2); } return (src_size + 1) / 3; } @@ -392,6 +392,13 @@ static bke::CurvesGeometry convert_curves_to_bezier(const bke::CurvesGeometry &s const IndexRange src_points = src_curves.points_for_curve(i); const IndexRange dst_points = dst_curves.points_for_curve(i); const Span<float3> src_curve_positions = src_positions.slice(src_points); + if (dst_points.size() == 1) { + const float3 &position = src_positions[src_points.first()]; + dst_positions[dst_points.first()] = position; + dst_handles_l[dst_points.first()] = position; + dst_handles_r[dst_points.first()] = position; + continue; + } KnotsMode knots_mode = KnotsMode(src_knot_modes[i]); Span<float3> nurbs_positions = src_curve_positions; diff --git a/source/blender/io/alembic/exporter/abc_writer_points.cc b/source/blender/io/alembic/exporter/abc_writer_points.cc index 6ec6f736818..9372bffc3ca 100644 --- a/source/blender/io/alembic/exporter/abc_writer_points.cc +++ b/source/blender/io/alembic/exporter/abc_writer_points.cc @@ -85,7 +85,7 @@ void ABCPointsWriter::do_write(HierarchyContext &context) sim.ob = context.object; sim.psys = psys; - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); uint64_t index = 0; for (int p = 0; p < psys->totpart; p++) { @@ -113,10 +113,7 @@ void ABCPointsWriter::do_write(HierarchyContext &context) ids.push_back(index++); } - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = nullptr; - } + psys_sim_data_free(&sim); Alembic::Abc::P3fArraySample psample(points); Alembic::Abc::UInt64ArraySample idsample(ids); diff --git a/source/blender/makesdna/DNA_asset_types.h b/source/blender/makesdna/DNA_asset_types.h index 29795519719..d7e3bcfc919 100644 --- a/source/blender/makesdna/DNA_asset_types.h +++ b/source/blender/makesdna/DNA_asset_types.h @@ -42,6 +42,10 @@ typedef struct AssetFilterSettings { * more than that from the file. So pointers to other IDs or ID data are strictly forbidden. */ typedef struct AssetMetaData { +#ifdef __cplusplus + ~AssetMetaData(); +#endif + /** Runtime type, to reference event callbacks. Only valid for local assets. */ struct AssetTypeInfo *local_type_info; @@ -114,6 +118,8 @@ typedef struct AssetLibraryReference { } AssetLibraryReference; /** + * To be replaced by #AssetRepresentation! + * * Not part of the core design, we should try to get rid of it. Only needed to wrap FileDirEntry * into a type with PropertyGroup as base, so we can have an RNA collection of #AssetHandle's to * pass to the UI. diff --git a/source/blender/makesdna/DNA_space_types.h b/source/blender/makesdna/DNA_space_types.h index 4bb92e6fcc5..d6d5f64a6a6 100644 --- a/source/blender/makesdna/DNA_space_types.h +++ b/source/blender/makesdna/DNA_space_types.h @@ -1107,7 +1107,7 @@ typedef struct FileDirEntry { uint32_t uid; /* FileUID */ /* Name needs freeing if FILE_ENTRY_NAME_FREE is set. Otherwise this is a direct pointer to a * name buffer. */ - char *name; + const char *name; uint64_t size; int64_t time; @@ -1134,7 +1134,7 @@ typedef struct FileDirEntry { /** If this file represents an asset, its asset data is here. Note that we may show assets of * external files in which case this is set but not the id above. * Note comment for FileListInternEntry.local_data, the same applies here! */ - struct AssetMetaData *asset_data; + struct AssetRepresentation *asset; /* The icon_id for the preview image. */ int preview_icon_id; diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index b2663b89333..b0311d63d44 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -540,6 +540,7 @@ static const EnumPropertyItem rna_enum_curve_display_handle_items[] = { # include "BLI_string.h" # include "BKE_anim_data.h" +# include "BKE_asset.h" # include "BKE_brush.h" # include "BKE_colortools.h" # include "BKE_context.h" @@ -2761,18 +2762,24 @@ static PointerRNA rna_FileBrowser_FileSelectEntry_asset_data_get(PointerRNA *ptr { const FileDirEntry *entry = ptr->data; + if (!entry->asset) { + return PointerRNA_NULL; + } + + AssetMetaData *asset_data = BKE_asset_representation_metadata_get(entry->asset); + /* Note that the owning ID of the RNA pointer (`ptr->owner_id`) has to be set carefully: * Local IDs (`entry->id`) own their asset metadata themselves. Asset metadata from other blend * files are owned by the file browser (`entry`). Only if this is set correctly, we can tell from * the metadata RNA pointer if the metadata is stored locally and can thus be edited or not. */ - if (entry->id) { + if (BKE_asset_representation_is_local_id(entry->asset)) { PointerRNA id_ptr; RNA_id_pointer_create(entry->id, &id_ptr); - return rna_pointer_inherit_refine(&id_ptr, &RNA_AssetMetaData, entry->asset_data); + return rna_pointer_inherit_refine(&id_ptr, &RNA_AssetMetaData, asset_data); } - return rna_pointer_inherit_refine(ptr, &RNA_AssetMetaData, entry->asset_data); + return rna_pointer_inherit_refine(ptr, &RNA_AssetMetaData, asset_data); } static int rna_FileBrowser_FileSelectEntry_name_editable(PointerRNA *ptr, const char **r_info) @@ -2782,7 +2789,7 @@ static int rna_FileBrowser_FileSelectEntry_name_editable(PointerRNA *ptr, const /* This actually always returns 0 (the name is never editable) but we want to get a disabled * message returned to `r_info` in some cases. */ - if (entry->asset_data) { + if (entry->asset) { PointerRNA asset_data_ptr = rna_FileBrowser_FileSelectEntry_asset_data_get(ptr); /* Get disabled hint from asset metadata polling. */ rna_AssetMetaData_editable(&asset_data_ptr, r_info); diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 96bf836fa4a..b0806fed91c 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -987,7 +987,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, /* getting back to object space */ invert_m4_m4(imat, ctx->object->object_to_world); - psmd->psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); const MVert *mesh_verts = BKE_mesh_verts(mesh); MVert *explode_verts = BKE_mesh_verts_for_write(explode); @@ -1112,10 +1112,7 @@ static Mesh *explodeMesh(ExplodeModifierData *emd, BKE_mesh_calc_edges_tessface(explode); BKE_mesh_convert_mfaces_to_mpolys(explode); - if (psmd->psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psmd->psys->lattice_deform_data); - psmd->psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&sim); return explode; } diff --git a/source/blender/modifiers/intern/MOD_particleinstance.c b/source/blender/modifiers/intern/MOD_particleinstance.c index f65f8bc4fb3..46e14dd6bfb 100644 --- a/source/blender/modifiers/intern/MOD_particleinstance.c +++ b/source/blender/modifiers/intern/MOD_particleinstance.c @@ -303,7 +303,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * maxedge += totedge; } - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); if (psys->flag & (PSYS_HAIR_DONE | PSYS_KEYED) || psys->pointcache->flag & PTCACHE_BAKED) { float min[3], max[3]; @@ -514,10 +514,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *ctx, Mesh * p_skip++; } - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&sim); if (size) { MEM_freeN(size); diff --git a/source/blender/render/intern/bake.c b/source/blender/render/intern/bake.c index 9b56e18bb26..d9f7f9fa0af 100644 --- a/source/blender/render/intern/bake.c +++ b/source/blender/render/intern/bake.c @@ -747,6 +747,7 @@ void RE_bake_pixels_populate(Mesh *me, BKE_mesh_recalc_looptri(loops, polys, verts, me->totloop, me->totpoly, looptri); const int *material_indices = BKE_mesh_material_indices(me); + const int materials_num = targets->materials_num; for (int i = 0; i < tottri; i++) { const MLoopTri *lt = &looptri[i]; @@ -754,7 +755,10 @@ void RE_bake_pixels_populate(Mesh *me, bd.primitive_id = i; /* Find images matching this material. */ - Image *image = targets->material_to_image[material_indices ? material_indices[lt->poly] : 0]; + const int material_index = (material_indices && materials_num) ? + clamp_i(material_indices[lt->poly], 0, materials_num - 1) : + 0; + Image *image = targets->material_to_image[material_index]; for (int image_id = 0; image_id < targets->images_num; image_id++) { BakeImage *bk_image = &targets->images[image_id]; if (bk_image->image != image) { diff --git a/source/blender/render/intern/texture_pointdensity.c b/source/blender/render/intern/texture_pointdensity.c index 5c31192f62a..09173aaa0e3 100644 --- a/source/blender/render/intern/texture_pointdensity.c +++ b/source/blender/render/intern/texture_pointdensity.c @@ -178,7 +178,7 @@ static void pointdensity_cache_psys( invert_m4_m4(ob->world_to_object, ob->object_to_world); total_particles = psys->totpart + psys->totchild; - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); pd->point_tree = BLI_bvhtree_new(total_particles, 0.0, 4, 6); pd->totpoints = total_particles; @@ -258,10 +258,7 @@ static void pointdensity_cache_psys( BLI_bvhtree_balance(pd->point_tree); - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&sim); } static void pointdensity_cache_vertex_color(PointDensity *pd, @@ -780,7 +777,7 @@ static void particle_system_minmax(Depsgraph *depsgraph, invert_m4_m4(imat, object->object_to_world); total_particles = psys->totpart + psys->totchild; - psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); + psys_sim_data_init(&sim); for (i = 0, pa = psys->particles; i < total_particles; i++, pa++) { float co_object[3], co_min[3], co_max[3]; @@ -796,10 +793,7 @@ static void particle_system_minmax(Depsgraph *depsgraph, minmax_v3v3_v3(min, max, co_max); } - if (psys->lattice_deform_data) { - BKE_lattice_deform_data_destroy(psys->lattice_deform_data); - psys->lattice_deform_data = NULL; - } + psys_sim_data_free(&sim); } void RE_point_density_cache(struct Depsgraph *depsgraph, PointDensity *pd) diff --git a/source/blender/sequencer/intern/effects.c b/source/blender/sequencer/intern/effects.c index 8469876ba25..6dd75031f3b 100644 --- a/source/blender/sequencer/intern/effects.c +++ b/source/blender/sequencer/intern/effects.c @@ -704,10 +704,13 @@ static void do_gammacross_effect_float( for (int i = 0; i < y; i++) { for (int j = 0; j < x; j++) { - *rt = gammaCorrect(mfac * invGammaCorrect(*rt1) + fac * invGammaCorrect(*rt2)); - rt1++; - rt2++; - rt++; + rt[0] = gammaCorrect(mfac * invGammaCorrect(rt1[0]) + fac * invGammaCorrect(rt2[0])); + rt[1] = gammaCorrect(mfac * invGammaCorrect(rt1[1]) + fac * invGammaCorrect(rt2[1])); + rt[2] = gammaCorrect(mfac * invGammaCorrect(rt1[2]) + fac * invGammaCorrect(rt2[2])); + rt[3] = gammaCorrect(mfac * invGammaCorrect(rt1[3]) + fac * invGammaCorrect(rt2[3])); + rt1 += 4; + rt2+=4; + rt+=4; } } } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 329e22c156a..3526a4349b5 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -1302,7 +1302,6 @@ bool WM_drag_is_ID_type(const struct wmDrag *drag, int idcode); * \note Does not store \a asset in any way, so it's fine to pass a temporary. */ wmDragAsset *WM_drag_create_asset_data(const struct AssetHandle *asset, - struct AssetMetaData *metadata, const char *path, int import_type); struct wmDragAsset *WM_drag_get_asset_data(const struct wmDrag *drag, int idcode); diff --git a/source/blender/windowmanager/intern/wm_dragdrop.cc b/source/blender/windowmanager/intern/wm_dragdrop.cc index fb63abed9e9..393149f20f5 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.cc +++ b/source/blender/windowmanager/intern/wm_dragdrop.cc @@ -556,15 +556,12 @@ bool WM_drag_is_ID_type(const wmDrag *drag, int idcode) return WM_drag_get_local_ID(drag, idcode) || WM_drag_get_asset_data(drag, idcode); } -wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset, - AssetMetaData *metadata, - const char *path, - int import_type) +wmDragAsset *WM_drag_create_asset_data(const AssetHandle *asset, const char *path, int import_type) { wmDragAsset *asset_drag = MEM_new<wmDragAsset>(__func__); BLI_strncpy(asset_drag->name, ED_asset_handle_get_name(asset), sizeof(asset_drag->name)); - asset_drag->metadata = metadata; + asset_drag->metadata = ED_asset_handle_get_metadata(asset); asset_drag->path = path; asset_drag->id_type = ED_asset_handle_get_id_type(asset); asset_drag->import_type = import_type; @@ -733,12 +730,11 @@ void WM_drag_add_asset_list_item( drag_asset->asset_data.local_id = local_id; } else { - AssetMetaData *metadata = ED_asset_handle_get_metadata(asset); char asset_blend_path[FILE_MAX_LIBEXTRA]; ED_asset_handle_get_full_library_path(C, asset_library_ref, asset, asset_blend_path); drag_asset->is_external = true; drag_asset->asset_data.external_info = WM_drag_create_asset_data( - asset, metadata, BLI_strdup(asset_blend_path), FILE_ASSET_IMPORT_APPEND); + asset, BLI_strdup(asset_blend_path), FILE_ASSET_IMPORT_APPEND); } BLI_addtail(&drag->asset_items, drag_asset); } |