diff options
Diffstat (limited to 'source/blender/blenkernel')
45 files changed, 922 insertions, 692 deletions
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_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index a7150913290..4bffa5492b5 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -17,15 +17,15 @@ extern "C" { */ /* Blender major and minor version. */ -#define BLENDER_VERSION 304 +#define BLENDER_VERSION 305 /* Blender patch version for bugfix releases. */ #define BLENDER_VERSION_PATCH 0 /** Blender release cycle stage: alpha/beta/rc/release. */ -#define BLENDER_VERSION_CYCLE beta +#define BLENDER_VERSION_CYCLE alpha /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 6 +#define BLENDER_FILE_SUBVERSION 0 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and show a warning if the file diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh index 4c7ff8c1813..a479dcb574d 100644 --- a/source/blender/blenkernel/BKE_curves.hh +++ b/source/blender/blenkernel/BKE_curves.hh @@ -11,6 +11,7 @@ #include <mutex> +#include "BLI_cache_mutex.hh" #include "BLI_float3x3.hh" #include "BLI_float4x4.hh" #include "BLI_generic_virtual_array.hh" @@ -80,17 +81,14 @@ class CurvesGeometryRuntime { */ mutable Vector<int> evaluated_offsets_cache; mutable Vector<int> bezier_evaluated_offsets; - mutable std::mutex offsets_cache_mutex; - mutable bool offsets_cache_dirty = true; + mutable CacheMutex offsets_cache_mutex; mutable Vector<curves::nurbs::BasisCache> nurbs_basis_cache; - mutable std::mutex nurbs_basis_cache_mutex; - mutable bool nurbs_basis_cache_dirty = true; + mutable CacheMutex nurbs_basis_cache_mutex; /** Cache of evaluated positions. */ mutable Vector<float3> evaluated_position_cache; - mutable std::mutex position_cache_mutex; - mutable bool position_cache_dirty = true; + mutable CacheMutex position_cache_mutex; /** * The evaluated positions result, using a separate span in case all curves are poly curves, * in which case a separate array of evaluated positions is unnecessary. @@ -103,18 +101,15 @@ class CurvesGeometryRuntime { * make slicing this array for a curve fast, an extra float is stored for every curve. */ mutable Vector<float> evaluated_length_cache; - mutable std::mutex length_cache_mutex; - mutable bool length_cache_dirty = true; + mutable CacheMutex length_cache_mutex; /** Direction of the curve at each evaluated point. */ mutable Vector<float3> evaluated_tangent_cache; - mutable std::mutex tangent_cache_mutex; - mutable bool tangent_cache_dirty = true; + mutable CacheMutex tangent_cache_mutex; /** Normal direction vectors for each evaluated point. */ mutable Vector<float3> evaluated_normal_cache; - mutable std::mutex normal_cache_mutex; - mutable bool normal_cache_dirty = true; + mutable CacheMutex normal_cache_mutex; }; /** @@ -909,13 +904,13 @@ inline int CurvesGeometry::evaluated_points_num() const inline IndexRange CurvesGeometry::evaluated_points_for_curve(int index) const { - BLI_assert(!this->runtime->offsets_cache_dirty); + BLI_assert(this->runtime->offsets_cache_mutex.is_cached()); return offsets_to_range(this->runtime->evaluated_offsets_cache.as_span(), index); } inline IndexRange CurvesGeometry::evaluated_points_for_curves(const IndexRange curves) const { - BLI_assert(!this->runtime->offsets_cache_dirty); + BLI_assert(this->runtime->offsets_cache_mutex.is_cached()); BLI_assert(this->curve_num > 0); const int offset = this->runtime->evaluated_offsets_cache[curves.start()]; const int offset_next = this->runtime->evaluated_offsets_cache[curves.one_after_last()]; @@ -940,7 +935,7 @@ inline IndexRange CurvesGeometry::lengths_range_for_curve(const int curve_index, inline Span<float> CurvesGeometry::evaluated_lengths_for_curve(const int curve_index, const bool cyclic) const { - BLI_assert(!this->runtime->length_cache_dirty); + BLI_assert(this->runtime->length_cache_mutex.is_cached()); const IndexRange range = this->lengths_range_for_curve(curve_index, cyclic); return this->runtime->evaluated_length_cache.as_span().slice(range); } diff --git a/source/blender/blenkernel/BKE_curves_utils.hh b/source/blender/blenkernel/BKE_curves_utils.hh index a8e6772eca1..1e06cb2d4c7 100644 --- a/source/blender/blenkernel/BKE_curves_utils.hh +++ b/source/blender/blenkernel/BKE_curves_utils.hh @@ -543,12 +543,6 @@ IndexMask indices_for_type(const VArray<int8_t> &types, const IndexMask selection, Vector<int64_t> &r_indices); -void indices_for_each_type(const VArray<int8_t> &types, - const std::array<int, CURVE_TYPES_NUM> &counts, - const IndexMask selection, - std::array<IndexMask, CURVE_TYPES_NUM> &r_type_masks, - std::array<Vector<int64_t>, CURVE_TYPES_NUM> &r_type_indices); - void foreach_curve_by_type(const VArray<int8_t> &types, const std::array<int, CURVE_TYPES_NUM> &type_counts, IndexMask selection, @@ -557,15 +551,6 @@ void foreach_curve_by_type(const VArray<int8_t> &types, FunctionRef<void(IndexMask)> bezier_fn, FunctionRef<void(IndexMask)> nurbs_fn); -/** - * Same as 'by_type' but index mask for each curve type is pre-computed. - */ -void foreach_curve_by_type_mask(const std::array<IndexMask, CURVE_TYPES_NUM> &curve_type_mask, - FunctionRef<void(IndexMask)> catmull_rom_fn, - FunctionRef<void(IndexMask)> poly_fn, - FunctionRef<void(IndexMask)> bezier_fn, - FunctionRef<void(IndexMask)> nurbs_fn); - /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index f761e28cbb4..1cdd3c02d8d 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -552,7 +552,6 @@ bool CustomData_verify_versions(struct CustomData *data, int index); /* BMesh specific custom-data stuff. */ -void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *ldata); void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, char htype); /** diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index 109d3e6d977..431bc11b07f 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -119,7 +119,7 @@ struct DynamicPaintSurface *get_activeSurface(struct DynamicPaintCanvasSettings int dynamicPaint_createUVSurface(struct Scene *scene, struct DynamicPaintSurface *surface, float *progress, - short *do_update); + bool *do_update); /** * Calculate a single frame and included sub-frames for surface. */ diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index c11e6353bc0..cbdf37e14bd 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -431,6 +431,11 @@ bool BKE_fcurve_is_keyframable(struct FCurve *fcu); bool BKE_fcurve_is_protected(struct FCurve *fcu); /** + * Are any of the keyframe control points selected on the F-Curve? + */ +bool BKE_fcurve_has_selected_control_points(const struct FCurve *fcu); + +/** * Checks if the F-Curve has a Cycles modifier with simple settings * that warrant transition smoothing. */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 0ff7f50f71c..8f6786d4113 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -307,8 +307,6 @@ void BKE_mesh_translate(struct Mesh *me, const float offset[3], bool do_keys); void BKE_mesh_tessface_clear(struct Mesh *mesh); -void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh); - void BKE_mesh_mselect_clear(struct Mesh *me); void BKE_mesh_mselect_validate(struct Mesh *me); /** @@ -974,11 +972,6 @@ void BKE_mesh_strip_loose_faces(struct Mesh *me); void BKE_mesh_strip_loose_polysloops(struct Mesh *me); void BKE_mesh_strip_loose_edges(struct Mesh *me); -/** - * If the mesh is from a very old blender version, - * convert #MFace.edcode to edge #ME_EDGEDRAW. - */ -void BKE_mesh_calc_edges_legacy(struct Mesh *me, bool use_old); void BKE_mesh_calc_edges_loose(struct Mesh *mesh); /** * Calculate edges from polygons. diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h index 92182f8045b..5eae7bf3b22 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h @@ -95,8 +95,6 @@ void BKE_mesh_tessface_calc(struct Mesh *mesh); void BKE_mesh_tessface_ensure(struct Mesh *mesh); -void BKE_mesh_add_mface_layers(struct CustomData *fdata, struct CustomData *ldata, int total); - /** * Rotates the vertices of a face in case v[2] or v[3] (vertex index) is = 0. * this is necessary to make the if #MFace.v4 check for quads work. @@ -123,6 +121,13 @@ void BKE_mesh_convert_mfaces_to_mpolys(struct Mesh *mesh); */ void BKE_mesh_do_versions_convert_mfaces_to_mpolys(struct Mesh *mesh); +/** + * Convert legacy #MFace.edcode to edge #ME_EDGEDRAW. + */ +void BKE_mesh_calc_edges_legacy(struct Mesh *me, bool use_old); + +void BKE_mesh_do_versions_cd_flag_init(struct Mesh *mesh); + /* Inlines */ /* NOTE(@sybren): Instead of -1 that function uses ORIGINDEX_NONE as defined in BKE_customdata.h, diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index 9d9c2f57f89..705158bec0b 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -63,6 +63,10 @@ typedef struct UvElement { * If islands are calculated, it also stores UvElements * belonging to the same uv island in sequence and * the number of uvs per island. + * + * \note in C++, #head_table and #unique_index_table would + * be `mutable`, as they are created on demand, and never + * changed after creation. */ typedef struct UvElementMap { /** UvElement Storage. */ @@ -78,6 +82,9 @@ typedef struct UvElementMap { /** If Non-NULL, pointer to local head of each unique UV. */ struct UvElement **head_table; + /** If Non-NULL, pointer to index of each unique UV. */ + int *unique_index_table; + /** Number of islands, or zero if not calculated. */ int total_islands; /** Array of starting index in #storage where each island begins. */ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 6eb9650348a..4d883f9e31e 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -988,8 +988,6 @@ void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *outputs); void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth); void node_type_size_preset(struct bNodeType *ntype, eNodeSizePreset size); -void node_type_init(struct bNodeType *ntype, - void (*initfunc)(struct bNodeTree *ntree, struct bNode *node)); /** * \warning Nodes defining a storage type _must_ allocate this for new nodes. * Otherwise nodes will reload as undefined (T46619). @@ -1000,17 +998,6 @@ void node_type_storage(struct bNodeType *ntype, void (*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node)); -void node_type_update(struct bNodeType *ntype, - void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node)); -void node_type_group_update(struct bNodeType *ntype, - void (*group_update_func)(struct bNodeTree *ntree, - struct bNode *node)); - -void node_type_exec(struct bNodeType *ntype, - NodeInitExecFunction init_exec_fn, - NodeFreeExecFunction free_exec_fn, - NodeExecFunction exec_fn); -void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpu_fn); /** \} */ @@ -1018,7 +1005,7 @@ void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpu_fn); /** \name Node Generic Functions * \{ */ -bool BKE_node_is_connected_to_output(struct bNodeTree *ntree, struct bNode *node); +bool BKE_node_is_connected_to_output(const struct bNodeTree *ntree, const struct bNode *node); /* ************** COMMON NODES *************** */ @@ -1033,8 +1020,6 @@ bool BKE_node_is_connected_to_output(struct bNodeTree *ntree, struct bNode *node #define NODE_GROUP_OUTPUT 8 #define NODE_CUSTOM_GROUP 9 -void BKE_node_tree_unlink_id(ID *id, struct bNodeTree *ntree); - /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 11c37a74a54..f0bb530e32b 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -170,7 +170,7 @@ int BKE_sound_scene_playing(struct Scene *scene); void BKE_sound_free_waveform(struct bSound *sound); -void BKE_sound_read_waveform(struct Main *bmain, struct bSound *sound, short *stop); +void BKE_sound_read_waveform(struct Main *bmain, struct bSound *sound, bool *stop); void BKE_sound_update_scene(struct Depsgraph *depsgraph, struct Scene *scene); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 89f30ce8ef8..70c1049b5d7 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -657,8 +657,8 @@ void BKE_tracking_reconstruction_context_free(struct MovieReconstructContext *co * callback in libmv side and passing to an interface. */ void BKE_tracking_reconstruction_solve(struct MovieReconstructContext *context, - short *stop, - short *do_update, + bool *stop, + bool *do_update, float *progress, char *stats_message, int message_size); 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/curve_to_mesh_convert.cc b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc index ecf3be9bd81..3a86068d8e8 100644 --- a/source/blender/blenkernel/intern/curve_to_mesh_convert.cc +++ b/source/blender/blenkernel/intern/curve_to_mesh_convert.cc @@ -71,7 +71,7 @@ static void fill_mesh_topology(const int vert_offset, MEdge &edge = edges[profile_edge_offset + i_ring]; edge.v1 = ring_vert_offset + i_profile; edge.v2 = next_ring_vert_offset + i_profile; - edge.flag = ME_EDGEDRAW | ME_EDGERENDER; + edge.flag = ME_EDGEDRAW; } } @@ -87,7 +87,7 @@ static void fill_mesh_topology(const int vert_offset, MEdge &edge = edges[ring_edge_offset + i_profile]; edge.v1 = ring_vert_offset + i_profile; edge.v2 = ring_vert_offset + i_next_profile; - edge.flag = ME_EDGEDRAW | ME_EDGERENDER; + edge.flag = ME_EDGEDRAW; } } diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc index 7c338480c71..43bdb8e7b8c 100644 --- a/source/blender/blenkernel/intern/curves_geometry.cc +++ b/source/blender/blenkernel/intern/curves_geometry.cc @@ -511,17 +511,7 @@ static void calculate_evaluated_offsets(const CurvesGeometry &curves, void CurvesGeometry::ensure_evaluated_offsets() const { - if (!this->runtime->offsets_cache_dirty) { - return; - } - - /* A double checked lock. */ - std::scoped_lock lock{this->runtime->offsets_cache_mutex}; - if (!this->runtime->offsets_cache_dirty) { - return; - } - - threading::isolate_task([&]() { + this->runtime->offsets_cache_mutex.ensure([&]() { this->runtime->evaluated_offsets_cache.resize(this->curves_num() + 1); if (this->has_curve_with_type(CURVE_TYPE_BEZIER)) { @@ -534,8 +524,6 @@ void CurvesGeometry::ensure_evaluated_offsets() const calculate_evaluated_offsets( *this, this->runtime->evaluated_offsets_cache, this->runtime->bezier_evaluated_offsets); }); - - this->runtime->offsets_cache_dirty = false; } Span<int> CurvesGeometry::evaluated_offsets() const @@ -569,17 +557,7 @@ Array<int> CurvesGeometry::point_to_curve_map() const void CurvesGeometry::ensure_nurbs_basis_cache() const { - if (!this->runtime->nurbs_basis_cache_dirty) { - return; - } - - /* A double checked lock. */ - std::scoped_lock lock{this->runtime->nurbs_basis_cache_mutex}; - if (!this->runtime->nurbs_basis_cache_dirty) { - return; - } - - threading::isolate_task([&]() { + this->runtime->nurbs_basis_cache_mutex.ensure([&]() { Vector<int64_t> nurbs_indices; const IndexMask nurbs_mask = this->indices_for_curve_type(CURVE_TYPE_NURBS, nurbs_indices); if (nurbs_mask.is_empty()) { @@ -619,23 +597,11 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const } }); }); - - this->runtime->nurbs_basis_cache_dirty = false; } Span<float3> CurvesGeometry::evaluated_positions() const { - if (!this->runtime->position_cache_dirty) { - return this->runtime->evaluated_positions_span; - } - - /* A double checked lock. */ - std::scoped_lock lock{this->runtime->position_cache_mutex}; - if (!this->runtime->position_cache_dirty) { - return this->runtime->evaluated_positions_span; - } - - threading::isolate_task([&]() { + this->runtime->position_cache_mutex.ensure([&]() { if (this->is_single_type(CURVE_TYPE_POLY)) { this->runtime->evaluated_positions_span = this->positions(); this->runtime->evaluated_position_cache.clear_and_make_inline(); @@ -699,24 +665,12 @@ Span<float3> CurvesGeometry::evaluated_positions() const } }); }); - - this->runtime->position_cache_dirty = false; return this->runtime->evaluated_positions_span; } Span<float3> CurvesGeometry::evaluated_tangents() const { - if (!this->runtime->tangent_cache_dirty) { - return this->runtime->evaluated_tangent_cache; - } - - /* A double checked lock. */ - std::scoped_lock lock{this->runtime->tangent_cache_mutex}; - if (!this->runtime->tangent_cache_dirty) { - return this->runtime->evaluated_tangent_cache; - } - - threading::isolate_task([&]() { + this->runtime->tangent_cache_mutex.ensure([&]() { const Span<float3> evaluated_positions = this->evaluated_positions(); const VArray<bool> cyclic = this->cyclic(); @@ -732,9 +686,9 @@ Span<float3> CurvesGeometry::evaluated_tangents() const } }); - /* Correct the first and last tangents of non-cyclic Bezier curves so that they align with the - * inner handles. This is a separate loop to avoid the cost when Bezier type curves are not - * used. */ + /* Correct the first and last tangents of non-cyclic Bezier curves so that they align with + * the inner handles. This is a separate loop to avoid the cost when Bezier type curves are + * not used. */ Vector<int64_t> bezier_indices; const IndexMask bezier_mask = this->indices_for_curve_type(CURVE_TYPE_BEZIER, bezier_indices); if (!bezier_mask.is_empty()) { @@ -765,8 +719,6 @@ Span<float3> CurvesGeometry::evaluated_tangents() const }); } }); - - this->runtime->tangent_cache_dirty = false; return this->runtime->evaluated_tangent_cache; } @@ -781,17 +733,7 @@ static void rotate_directions_around_axes(MutableSpan<float3> directions, Span<float3> CurvesGeometry::evaluated_normals() const { - if (!this->runtime->normal_cache_dirty) { - return this->runtime->evaluated_normal_cache; - } - - /* A double checked lock. */ - std::scoped_lock lock{this->runtime->normal_cache_mutex}; - if (!this->runtime->normal_cache_dirty) { - return this->runtime->evaluated_normal_cache; - } - - threading::isolate_task([&]() { + this->runtime->normal_cache_mutex.ensure([&]() { const Span<float3> evaluated_tangents = this->evaluated_tangents(); const VArray<bool> cyclic = this->cyclic(); const VArray<int8_t> normal_mode = this->normal_mode(); @@ -842,8 +784,6 @@ Span<float3> CurvesGeometry::evaluated_normals() const } }); }); - - this->runtime->normal_cache_dirty = false; return this->runtime->evaluated_normal_cache; } @@ -851,8 +791,8 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index, const GSpan src, GMutableSpan dst) const { - BLI_assert(!this->runtime->offsets_cache_dirty); - BLI_assert(!this->runtime->nurbs_basis_cache_dirty); + BLI_assert(this->runtime->offsets_cache_mutex.is_cached()); + BLI_assert(this->runtime->nurbs_basis_cache_mutex.is_cached()); const IndexRange points = this->points_for_curve(curve_index); BLI_assert(src.size() == points.size()); BLI_assert(dst.size() == this->evaluated_points_for_curve(curve_index).size()); @@ -881,8 +821,8 @@ void CurvesGeometry::interpolate_to_evaluated(const int curve_index, void CurvesGeometry::interpolate_to_evaluated(const GSpan src, GMutableSpan dst) const { - BLI_assert(!this->runtime->offsets_cache_dirty); - BLI_assert(!this->runtime->nurbs_basis_cache_dirty); + BLI_assert(this->runtime->offsets_cache_mutex.is_cached()); + BLI_assert(this->runtime->nurbs_basis_cache_mutex.is_cached()); const VArray<int8_t> types = this->curve_types(); const VArray<int> resolution = this->resolution(); const VArray<bool> cyclic = this->cyclic(); @@ -923,17 +863,7 @@ void CurvesGeometry::interpolate_to_evaluated(const GSpan src, GMutableSpan dst) void CurvesGeometry::ensure_evaluated_lengths() const { - if (!this->runtime->length_cache_dirty) { - return; - } - - /* A double checked lock. */ - std::scoped_lock lock{this->runtime->length_cache_mutex}; - if (!this->runtime->length_cache_dirty) { - return; - } - - threading::isolate_task([&]() { + this->runtime->length_cache_mutex.ensure([&]() { /* Use an extra length value for the final cyclic segment for a consistent size * (see comment on #evaluated_length_cache). */ const int total_num = this->evaluated_points_num() + this->curves_num(); @@ -954,8 +884,6 @@ void CurvesGeometry::ensure_evaluated_lengths() const } }); }); - - this->runtime->length_cache_dirty = false; } void CurvesGeometry::ensure_can_interpolate_to_evaluated() const @@ -986,23 +914,23 @@ void CurvesGeometry::resize(const int points_num, const int curves_num) void CurvesGeometry::tag_positions_changed() { - this->runtime->position_cache_dirty = true; - this->runtime->tangent_cache_dirty = true; - this->runtime->normal_cache_dirty = true; - this->runtime->length_cache_dirty = true; + this->runtime->position_cache_mutex.tag_dirty(); + this->runtime->tangent_cache_mutex.tag_dirty(); + this->runtime->normal_cache_mutex.tag_dirty(); + this->runtime->length_cache_mutex.tag_dirty(); } void CurvesGeometry::tag_topology_changed() { - this->runtime->position_cache_dirty = true; - this->runtime->tangent_cache_dirty = true; - this->runtime->normal_cache_dirty = true; - this->runtime->offsets_cache_dirty = true; - this->runtime->nurbs_basis_cache_dirty = true; - this->runtime->length_cache_dirty = true; + this->runtime->position_cache_mutex.tag_dirty(); + this->runtime->tangent_cache_mutex.tag_dirty(); + this->runtime->normal_cache_mutex.tag_dirty(); + this->runtime->offsets_cache_mutex.tag_dirty(); + this->runtime->nurbs_basis_cache_mutex.tag_dirty(); + this->runtime->length_cache_mutex.tag_dirty(); } void CurvesGeometry::tag_normals_changed() { - this->runtime->normal_cache_dirty = true; + this->runtime->normal_cache_mutex.tag_dirty(); } static void translate_positions(MutableSpan<float3> positions, const float3 &translation) diff --git a/source/blender/blenkernel/intern/curves_utils.cc b/source/blender/blenkernel/intern/curves_utils.cc index 2b13a7d3c8a..f5a69a995a3 100644 --- a/source/blender/blenkernel/intern/curves_utils.cc +++ b/source/blender/blenkernel/intern/curves_utils.cc @@ -128,18 +128,6 @@ IndexMask indices_for_type(const VArray<int8_t> &types, selection, 4096, r_indices, [&](const int index) { return types_span[index] == type; }); } -void indices_for_each_type(const VArray<int8_t> &types, - const std::array<int, CURVE_TYPES_NUM> &counts, - const IndexMask selection, - std::array<IndexMask, CURVE_TYPES_NUM> &r_type_masks, - std::array<Vector<int64_t>, CURVE_TYPES_NUM> &r_type_indices) -{ - for (const int64_t curve_type : IndexRange(CURVE_TYPES_NUM)) { - r_type_masks[curve_type] = indices_for_type( - types, counts, CurveType(curve_type), selection, r_type_indices[curve_type]); - } -} - void foreach_curve_by_type(const VArray<int8_t> &types, const std::array<int, CURVE_TYPES_NUM> &counts, const IndexMask selection, @@ -162,21 +150,4 @@ void foreach_curve_by_type(const VArray<int8_t> &types, call_if_not_empty(CURVE_TYPE_NURBS, nurbs_fn); } -void foreach_curve_by_type_mask(const std::array<IndexMask, CURVE_TYPES_NUM> &curve_type_mask, - FunctionRef<void(IndexMask)> catmull_rom_fn, - FunctionRef<void(IndexMask)> poly_fn, - FunctionRef<void(IndexMask)> bezier_fn, - FunctionRef<void(IndexMask)> nurbs_fn) -{ - auto call_if_not_empty = [&](const IndexMask curve_type_mask, FunctionRef<void(IndexMask)> fn) { - if (!curve_type_mask.is_empty()) { - fn(curve_type_mask); - } - }; - call_if_not_empty(curve_type_mask[0], catmull_rom_fn); - call_if_not_empty(curve_type_mask[1], poly_fn); - call_if_not_empty(curve_type_mask[2], bezier_fn); - call_if_not_empty(curve_type_mask[3], nurbs_fn); -} - } // namespace blender::bke::curves diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index 01017466764..84aa2207400 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -3607,39 +3607,6 @@ const char *CustomData_get_layer_name(const CustomData *data, const int type, co /* BMesh functions */ -void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *ldata) -{ - int act; - - if (CustomData_has_layer(ldata, CD_MLOOPUV)) { - act = CustomData_get_active_layer(ldata, CD_MLOOPUV); - CustomData_set_layer_active(fdata, CD_MTFACE, act); - - act = CustomData_get_render_layer(ldata, CD_MLOOPUV); - CustomData_set_layer_render(fdata, CD_MTFACE, act); - - act = CustomData_get_clone_layer(ldata, CD_MLOOPUV); - CustomData_set_layer_clone(fdata, CD_MTFACE, act); - - act = CustomData_get_stencil_layer(ldata, CD_MLOOPUV); - CustomData_set_layer_stencil(fdata, CD_MTFACE, act); - } - - if (CustomData_has_layer(ldata, CD_PROP_BYTE_COLOR)) { - act = CustomData_get_active_layer(ldata, CD_PROP_BYTE_COLOR); - CustomData_set_layer_active(fdata, CD_MCOL, act); - - act = CustomData_get_render_layer(ldata, CD_PROP_BYTE_COLOR); - CustomData_set_layer_render(fdata, CD_MCOL, act); - - act = CustomData_get_clone_layer(ldata, CD_PROP_BYTE_COLOR); - CustomData_set_layer_clone(fdata, CD_MCOL, act); - - act = CustomData_get_stencil_layer(ldata, CD_PROP_BYTE_COLOR); - CustomData_set_layer_stencil(fdata, CD_MCOL, act); - } -} - void CustomData_bmesh_init_pool(CustomData *data, const int totelem, const char htype) { int chunksize; diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index b9cec17b6e0..e0ae3f42be6 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -2790,7 +2790,7 @@ static bool dynamicPaint_symmetrizeAdjData(PaintAdjData *ed, int active_points) int dynamicPaint_createUVSurface(Scene *scene, DynamicPaintSurface *surface, float *progress, - short *do_update) + bool *do_update) { /* Antialias jitter point relative coords */ const int aa_samples = (surface->flags & MOD_DPAINT_ANTIALIAS) ? 5 : 1; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index beea3217126..d248faaab00 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -965,6 +965,18 @@ bool BKE_fcurve_is_protected(FCurve *fcu) return ((fcu->flag & FCURVE_PROTECTED) || ((fcu->grp) && (fcu->grp->flag & AGRP_PROTECTED))); } +bool BKE_fcurve_has_selected_control_points(const FCurve *fcu) +{ + int i; + BezTriple *bezt; + for (bezt = fcu->bezt, i = 0; i < fcu->totvert; ++i, ++bezt) { + if ((bezt->f2 & SELECT) != 0) { + return true; + } + } + return false; +} + bool BKE_fcurve_is_keyframable(FCurve *fcu) { /* F-Curve's keyframes must be "usable" (i.e. visible + have an effect on final result) */ 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/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 0018c217964..2d613f24a0a 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -1608,38 +1608,6 @@ void BKE_mesh_tessface_clear(Mesh *mesh) mesh_tessface_clear_intern(mesh, true); } -void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh) -{ - if (UNLIKELY(mesh->cd_flag)) { - return; - } - - const Span<MVert> verts = mesh->verts(); - const Span<MEdge> edges = mesh->edges(); - - for (const MVert &vert : verts) { - if (vert.bweight_legacy != 0) { - mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; - break; - } - } - - for (const MEdge &edge : edges) { - if (edge.bweight_legacy != 0) { - mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; - if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) { - break; - } - } - if (edge.crease_legacy != 0) { - mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; - if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { - break; - } - } - } -} - /* -------------------------------------------------------------------- */ /* MSelect functions (currently used in weight paint mode) */ diff --git a/source/blender/blenkernel/intern/mesh_calc_edges.cc b/source/blender/blenkernel/intern/mesh_calc_edges.cc index 5e6babdf7b4..4a4c2ebcbb0 100644 --- a/source/blender/blenkernel/intern/mesh_calc_edges.cc +++ b/source/blender/blenkernel/intern/mesh_calc_edges.cc @@ -146,7 +146,7 @@ static void serialize_and_initialize_deduplicated_edges(MutableSpan<EdgeMap> edg /* Initialize new edge. */ new_edge.v1 = item.key.v_low; new_edge.v2 = item.key.v_high; - new_edge.flag = ME_EDGEDRAW | ME_EDGERENDER; + new_edge.flag = ME_EDGEDRAW; } item.value.index = new_edge_index; new_edge_index++; diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 784d35a8d65..2255038a991 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -119,7 +119,7 @@ static void make_edges_mdata_extend(Mesh &mesh) BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2); BLI_edgehashIterator_setValue(ehi, POINTER_FROM_UINT(e_index)); - medge->flag = ME_EDGEDRAW | ME_EDGERENDER; + medge->flag = ME_EDGEDRAW; } BLI_edgehashIterator_free(ehi); @@ -223,7 +223,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba for (b = 1; b < dl->nr; b++) { medge->v1 = startvert + ofs + b - 1; medge->v2 = startvert + ofs + b; - medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW; + medge->flag = ME_LOOSEEDGE | ME_EDGEDRAW; medge++; } @@ -251,7 +251,7 @@ static Mesh *mesh_nurbs_displist_to_mesh(const Curve *cu, const ListBase *dispba else { medge->v2 = startvert + ofs + b + 1; } - medge->flag = ME_LOOSEEDGE | ME_EDGERENDER | ME_EDGEDRAW; + medge->flag = ME_LOOSEEDGE | ME_EDGEDRAW; medge++; } } @@ -706,7 +706,7 @@ void BKE_mesh_edges_set_draw_render(Mesh *mesh) { MutableSpan<MEdge> edges = mesh->edges_for_write(); for (int i = 0; i < mesh->totedge; i++) { - edges[i].flag |= ME_EDGEDRAW | ME_EDGERENDER; + edges[i].flag |= ME_EDGEDRAW; } } diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index df3057d9592..23426f8c087 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -30,6 +30,258 @@ #include "BKE_multires.h" /* -------------------------------------------------------------------- */ +/** \name Legacy Edge Calculation + * \{ */ + +struct EdgeSort { + uint v1, v2; + char is_loose, is_draw; +}; + +/* edges have to be added with lowest index first for sorting */ +static void to_edgesort(struct EdgeSort *ed, uint v1, uint v2, char is_loose, short is_draw) +{ + if (v1 < v2) { + ed->v1 = v1; + ed->v2 = v2; + } + else { + ed->v1 = v2; + ed->v2 = v1; + } + ed->is_loose = is_loose; + ed->is_draw = is_draw; +} + +static int vergedgesort(const void *v1, const void *v2) +{ + const struct EdgeSort *x1 = static_cast<const struct EdgeSort *>(v1); + const struct EdgeSort *x2 = static_cast<const struct EdgeSort *>(v2); + + if (x1->v1 > x2->v1) { + return 1; + } + if (x1->v1 < x2->v1) { + return -1; + } + if (x1->v2 > x2->v2) { + return 1; + } + if (x1->v2 < x2->v2) { + return -1; + } + + return 0; +} + +/* Create edges based on known verts and faces, + * this function is only used when loading very old blend files */ +static void mesh_calc_edges_mdata(const MVert * /*allvert*/, + const MFace *allface, + MLoop *allloop, + const MPoly *allpoly, + int /*totvert*/, + int totface, + int /*totloop*/, + int totpoly, + const bool use_old, + MEdge **r_medge, + int *r_totedge) +{ + const MPoly *mpoly; + const MFace *mface; + MEdge *medge, *med; + EdgeHash *hash; + struct EdgeSort *edsort, *ed; + int a, totedge = 0; + uint totedge_final = 0; + uint edge_index; + + /* we put all edges in array, sort them, and detect doubles that way */ + + for (a = totface, mface = allface; a > 0; a--, mface++) { + if (mface->v4) { + totedge += 4; + } + else if (mface->v3) { + totedge += 3; + } + else { + totedge += 1; + } + } + + if (totedge == 0) { + /* flag that mesh has edges */ + (*r_medge) = (MEdge *)MEM_callocN(0, __func__); + (*r_totedge) = 0; + return; + } + + ed = edsort = (EdgeSort *)MEM_mallocN(totedge * sizeof(struct EdgeSort), "EdgeSort"); + + for (a = totface, mface = allface; a > 0; a--, mface++) { + to_edgesort(ed++, mface->v1, mface->v2, !mface->v3, mface->edcode & ME_V1V2); + if (mface->v4) { + to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3); + to_edgesort(ed++, mface->v3, mface->v4, 0, mface->edcode & ME_V3V4); + to_edgesort(ed++, mface->v4, mface->v1, 0, mface->edcode & ME_V4V1); + } + else if (mface->v3) { + to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3); + to_edgesort(ed++, mface->v3, mface->v1, 0, mface->edcode & ME_V3V1); + } + } + + qsort(edsort, totedge, sizeof(struct EdgeSort), vergedgesort); + + /* count final amount */ + for (a = totedge, ed = edsort; a > 1; a--, ed++) { + /* edge is unique when it differs from next edge, or is last */ + if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) { + totedge_final++; + } + } + totedge_final++; + + medge = (MEdge *)MEM_callocN(sizeof(MEdge) * totedge_final, __func__); + + for (a = totedge, med = medge, ed = edsort; a > 1; a--, ed++) { + /* edge is unique when it differs from next edge, or is last */ + if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) { + med->v1 = ed->v1; + med->v2 = ed->v2; + if (use_old == false || ed->is_draw) { + med->flag = ME_EDGEDRAW; + } + if (ed->is_loose) { + med->flag |= ME_LOOSEEDGE; + } + + /* order is swapped so extruding this edge as a surface won't flip face normals + * with cyclic curves */ + if (ed->v1 + 1 != ed->v2) { + SWAP(uint, med->v1, med->v2); + } + med++; + } + else { + /* Equal edge, merge the draw-flag. */ + (ed + 1)->is_draw |= ed->is_draw; + } + } + /* last edge */ + med->v1 = ed->v1; + med->v2 = ed->v2; + med->flag = ME_EDGEDRAW; + if (ed->is_loose) { + med->flag |= ME_LOOSEEDGE; + } + + MEM_freeN(edsort); + + /* set edge members of mloops */ + hash = BLI_edgehash_new_ex(__func__, totedge_final); + for (edge_index = 0, med = medge; edge_index < totedge_final; edge_index++, med++) { + BLI_edgehash_insert(hash, med->v1, med->v2, POINTER_FROM_UINT(edge_index)); + } + + mpoly = allpoly; + for (a = 0; a < totpoly; a++, mpoly++) { + MLoop *ml, *ml_next; + int i = mpoly->totloop; + + ml_next = allloop + mpoly->loopstart; /* first loop */ + ml = &ml_next[i - 1]; /* last loop */ + + while (i-- != 0) { + ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(hash, ml->v, ml_next->v)); + ml = ml_next; + ml_next++; + } + } + + BLI_edgehash_free(hash, nullptr); + + *r_medge = medge; + *r_totedge = totedge_final; +} + +void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old) +{ + using namespace blender; + MEdge *medge; + int totedge = 0; + const Span<MVert> verts = me->verts(); + const Span<MPoly> polys = me->polys(); + MutableSpan<MLoop> loops = me->loops_for_write(); + + mesh_calc_edges_mdata(verts.data(), + (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE), + loops.data(), + polys.data(), + verts.size(), + me->totface, + loops.size(), + polys.size(), + use_old, + &medge, + &totedge); + + if (totedge == 0) { + /* flag that mesh has edges */ + me->totedge = 0; + return; + } + + medge = (MEdge *)CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, totedge); + me->totedge = totedge; + + BKE_mesh_strip_loose_faces(me); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name CD Flag Initialization + * \{ */ + +void BKE_mesh_do_versions_cd_flag_init(Mesh *mesh) +{ + using namespace blender; + if (UNLIKELY(mesh->cd_flag)) { + return; + } + + const Span<MVert> verts = mesh->verts(); + const Span<MEdge> edges = mesh->edges(); + + for (const MVert &vert : verts) { + if (vert.bweight_legacy != 0) { + mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; + break; + } + } + + for (const MEdge &edge : edges) { + if (edge.bweight_legacy != 0) { + mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + if (mesh->cd_flag & ME_CDFLAG_EDGE_CREASE) { + break; + } + } + if (edge.crease_legacy != 0) { + mesh->cd_flag |= ME_CDFLAG_EDGE_CREASE; + if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { + break; + } + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ /** \name NGon Tessellation (NGon to MFace Conversion) * \{ */ @@ -278,6 +530,115 @@ static void convert_mfaces_to_mpolys(ID *id, #undef ME_FGON } +static void update_active_fdata_layers(CustomData *fdata, CustomData *ldata) +{ + int act; + + if (CustomData_has_layer(ldata, CD_MLOOPUV)) { + act = CustomData_get_active_layer(ldata, CD_MLOOPUV); + CustomData_set_layer_active(fdata, CD_MTFACE, act); + + act = CustomData_get_render_layer(ldata, CD_MLOOPUV); + CustomData_set_layer_render(fdata, CD_MTFACE, act); + + act = CustomData_get_clone_layer(ldata, CD_MLOOPUV); + CustomData_set_layer_clone(fdata, CD_MTFACE, act); + + act = CustomData_get_stencil_layer(ldata, CD_MLOOPUV); + CustomData_set_layer_stencil(fdata, CD_MTFACE, act); + } + + if (CustomData_has_layer(ldata, CD_PROP_BYTE_COLOR)) { + act = CustomData_get_active_layer(ldata, CD_PROP_BYTE_COLOR); + CustomData_set_layer_active(fdata, CD_MCOL, act); + + act = CustomData_get_render_layer(ldata, CD_PROP_BYTE_COLOR); + CustomData_set_layer_render(fdata, CD_MCOL, act); + + act = CustomData_get_clone_layer(ldata, CD_PROP_BYTE_COLOR); + CustomData_set_layer_clone(fdata, CD_MCOL, act); + + act = CustomData_get_stencil_layer(ldata, CD_PROP_BYTE_COLOR); + CustomData_set_layer_stencil(fdata, CD_MCOL, act); + } +} + +#ifndef NDEBUG +/** + * Debug check, used to assert when we expect layers to be in/out of sync. + * + * \param fallback: Use when there are no layers to handle, + * since callers may expect success or failure. + */ +static bool check_matching_legacy_layer_counts(CustomData *fdata, CustomData *ldata, bool fallback) +{ + int a_num = 0, b_num = 0; +# define LAYER_CMP(l_a, t_a, l_b, t_b) \ + ((a_num += CustomData_number_of_layers(l_a, t_a)) == \ + (b_num += CustomData_number_of_layers(l_b, t_b))) + + if (!LAYER_CMP(ldata, CD_MLOOPUV, fdata, CD_MTFACE)) { + return false; + } + if (!LAYER_CMP(ldata, CD_PROP_BYTE_COLOR, fdata, CD_MCOL)) { + return false; + } + if (!LAYER_CMP(ldata, CD_PREVIEW_MLOOPCOL, fdata, CD_PREVIEW_MCOL)) { + return false; + } + if (!LAYER_CMP(ldata, CD_ORIGSPACE_MLOOP, fdata, CD_ORIGSPACE)) { + return false; + } + if (!LAYER_CMP(ldata, CD_NORMAL, fdata, CD_TESSLOOPNORMAL)) { + return false; + } + if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT)) { + return false; + } + +# undef LAYER_CMP + + /* if no layers are on either CustomData's, + * then there was nothing to do... */ + return a_num ? true : fallback; +} +#endif + +static void add_mface_layers(CustomData *fdata, CustomData *ldata, int total) +{ + /* avoid accumulating extra layers */ + BLI_assert(!check_matching_legacy_layer_counts(fdata, ldata, false)); + + for (int i = 0; i < ldata->totlayer; i++) { + if (ldata->layers[i].type == CD_MLOOPUV) { + CustomData_add_layer_named( + fdata, CD_MTFACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); + } + if (ldata->layers[i].type == CD_PROP_BYTE_COLOR) { + CustomData_add_layer_named( + fdata, CD_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); + } + else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) { + CustomData_add_layer_named( + fdata, CD_PREVIEW_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); + } + else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) { + CustomData_add_layer_named( + fdata, CD_ORIGSPACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); + } + else if (ldata->layers[i].type == CD_NORMAL) { + CustomData_add_layer_named( + fdata, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); + } + else if (ldata->layers[i].type == CD_TANGENT) { + CustomData_add_layer_named( + fdata, CD_TANGENT, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); + } + } + + update_active_fdata_layers(fdata, ldata); +} + static void mesh_ensure_tessellation_customdata(Mesh *me) { if (UNLIKELY((me->totface != 0) && (me->totpoly == 0))) { @@ -296,7 +657,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) if (tottex_tessface != tottex_original || totcol_tessface != totcol_original) { BKE_mesh_tessface_clear(me); - BKE_mesh_add_mface_layers(&me->fdata, &me->ldata, me->totface); + add_mface_layers(&me->fdata, &me->ldata, me->totface); /* TODO: add some `--debug-mesh` option. */ if (G.debug & G_DEBUG) { @@ -784,7 +1145,7 @@ static int mesh_tessface_calc(CustomData *fdata, /* #CD_ORIGINDEX will contain an array of indices from tessellation-faces to the polygons * they are directly tessellated from. */ CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface); - BKE_mesh_add_mface_layers(fdata, ldata, totface); + add_mface_layers(fdata, ldata, totface); /* NOTE: quad detection issue - fourth vertidx vs fourth loopidx: * Polygons take care of their loops ordering, hence not of their vertices ordering. @@ -840,82 +1201,6 @@ void BKE_mesh_tessface_ensure(struct Mesh *mesh) } } -#ifndef NDEBUG -/** - * Debug check, used to assert when we expect layers to be in/out of sync. - * - * \param fallback: Use when there are no layers to handle, - * since callers may expect success or failure. - */ -static bool check_matching_legacy_layer_counts(CustomData *fdata, CustomData *ldata, bool fallback) -{ - int a_num = 0, b_num = 0; -# define LAYER_CMP(l_a, t_a, l_b, t_b) \ - ((a_num += CustomData_number_of_layers(l_a, t_a)) == \ - (b_num += CustomData_number_of_layers(l_b, t_b))) - - if (!LAYER_CMP(ldata, CD_MLOOPUV, fdata, CD_MTFACE)) { - return false; - } - if (!LAYER_CMP(ldata, CD_PROP_BYTE_COLOR, fdata, CD_MCOL)) { - return false; - } - if (!LAYER_CMP(ldata, CD_PREVIEW_MLOOPCOL, fdata, CD_PREVIEW_MCOL)) { - return false; - } - if (!LAYER_CMP(ldata, CD_ORIGSPACE_MLOOP, fdata, CD_ORIGSPACE)) { - return false; - } - if (!LAYER_CMP(ldata, CD_NORMAL, fdata, CD_TESSLOOPNORMAL)) { - return false; - } - if (!LAYER_CMP(ldata, CD_TANGENT, fdata, CD_TANGENT)) { - return false; - } - -# undef LAYER_CMP - - /* if no layers are on either CustomData's, - * then there was nothing to do... */ - return a_num ? true : fallback; -} -#endif - -void BKE_mesh_add_mface_layers(CustomData *fdata, CustomData *ldata, int total) -{ - /* avoid accumulating extra layers */ - BLI_assert(!check_matching_legacy_layer_counts(fdata, ldata, false)); - - for (int i = 0; i < ldata->totlayer; i++) { - if (ldata->layers[i].type == CD_MLOOPUV) { - CustomData_add_layer_named( - fdata, CD_MTFACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); - } - if (ldata->layers[i].type == CD_PROP_BYTE_COLOR) { - CustomData_add_layer_named( - fdata, CD_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); - } - else if (ldata->layers[i].type == CD_PREVIEW_MLOOPCOL) { - CustomData_add_layer_named( - fdata, CD_PREVIEW_MCOL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); - } - else if (ldata->layers[i].type == CD_ORIGSPACE_MLOOP) { - CustomData_add_layer_named( - fdata, CD_ORIGSPACE, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); - } - else if (ldata->layers[i].type == CD_NORMAL) { - CustomData_add_layer_named( - fdata, CD_TESSLOOPNORMAL, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); - } - else if (ldata->layers[i].type == CD_TANGENT) { - CustomData_add_layer_named( - fdata, CD_TANGENT, CD_SET_DEFAULT, nullptr, total, ldata->layers[i].name); - } - } - - CustomData_bmesh_update_active_layers(fdata, ldata); -} - /** \} */ /* -------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc index f38efd2cf65..0887e26148a 100644 --- a/source/blender/blenkernel/intern/mesh_remesh_voxel.cc +++ b/source/blender/blenkernel/intern/mesh_remesh_voxel.cc @@ -426,23 +426,18 @@ void BKE_remesh_reproject_vertex_paint(Mesh *target, const Mesh *source) else { /* Lazily init vertex -> loop maps. */ if (!source_lmap) { - const MPoly *source_polys = (MPoly *)CustomData_get_layer(&source->pdata, CD_MPOLY); - const MLoop *source_loops = (MLoop *)CustomData_get_layer(&source->ldata, CD_MLOOP); - const MPoly *target_polys = (MPoly *)CustomData_get_layer(&target->pdata, CD_MPOLY); - const MLoop *target_loops = (MLoop *)CustomData_get_layer(&target->ldata, CD_MLOOP); - BKE_mesh_vert_loop_map_create(&source_lmap, &source_lmap_mem, - source_polys, - source_loops, + source->polys().data(), + source->loops().data(), source->totvert, source->totpoly, source->totloop); BKE_mesh_vert_loop_map_create(&target_lmap, &target_lmap_mem, - target_polys, - target_loops, + target->polys().data(), + target->loops().data(), target->totvert, target->totpoly, target->totloop); diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc index 9b140171912..9cd3b6e9e9e 100644 --- a/source/blender/blenkernel/intern/mesh_validate.cc +++ b/source/blender/blenkernel/intern/mesh_validate.cc @@ -1315,216 +1315,6 @@ void BKE_mesh_strip_loose_edges(Mesh *me) /** \name Mesh Edge Calculation * \{ */ -/* make edges in a Mesh, for outside of editmode */ - -struct EdgeSort { - uint v1, v2; - char is_loose, is_draw; -}; - -/* edges have to be added with lowest index first for sorting */ -static void to_edgesort(struct EdgeSort *ed, uint v1, uint v2, char is_loose, short is_draw) -{ - if (v1 < v2) { - ed->v1 = v1; - ed->v2 = v2; - } - else { - ed->v1 = v2; - ed->v2 = v1; - } - ed->is_loose = is_loose; - ed->is_draw = is_draw; -} - -static int vergedgesort(const void *v1, const void *v2) -{ - const struct EdgeSort *x1 = static_cast<const struct EdgeSort *>(v1); - const struct EdgeSort *x2 = static_cast<const struct EdgeSort *>(v2); - - if (x1->v1 > x2->v1) { - return 1; - } - if (x1->v1 < x2->v1) { - return -1; - } - if (x1->v2 > x2->v2) { - return 1; - } - if (x1->v2 < x2->v2) { - return -1; - } - - return 0; -} - -/* Create edges based on known verts and faces, - * this function is only used when loading very old blend files */ - -static void mesh_calc_edges_mdata(const MVert * /*allvert*/, - const MFace *allface, - MLoop *allloop, - const MPoly *allpoly, - int /*totvert*/, - int totface, - int /*totloop*/, - int totpoly, - const bool use_old, - MEdge **r_medge, - int *r_totedge) -{ - const MPoly *mpoly; - const MFace *mface; - MEdge *medge, *med; - EdgeHash *hash; - struct EdgeSort *edsort, *ed; - int a, totedge = 0; - uint totedge_final = 0; - uint edge_index; - - /* we put all edges in array, sort them, and detect doubles that way */ - - for (a = totface, mface = allface; a > 0; a--, mface++) { - if (mface->v4) { - totedge += 4; - } - else if (mface->v3) { - totedge += 3; - } - else { - totedge += 1; - } - } - - if (totedge == 0) { - /* flag that mesh has edges */ - (*r_medge) = (MEdge *)MEM_callocN(0, __func__); - (*r_totedge) = 0; - return; - } - - ed = edsort = (EdgeSort *)MEM_mallocN(totedge * sizeof(struct EdgeSort), "EdgeSort"); - - for (a = totface, mface = allface; a > 0; a--, mface++) { - to_edgesort(ed++, mface->v1, mface->v2, !mface->v3, mface->edcode & ME_V1V2); - if (mface->v4) { - to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3); - to_edgesort(ed++, mface->v3, mface->v4, 0, mface->edcode & ME_V3V4); - to_edgesort(ed++, mface->v4, mface->v1, 0, mface->edcode & ME_V4V1); - } - else if (mface->v3) { - to_edgesort(ed++, mface->v2, mface->v3, 0, mface->edcode & ME_V2V3); - to_edgesort(ed++, mface->v3, mface->v1, 0, mface->edcode & ME_V3V1); - } - } - - qsort(edsort, totedge, sizeof(struct EdgeSort), vergedgesort); - - /* count final amount */ - for (a = totedge, ed = edsort; a > 1; a--, ed++) { - /* edge is unique when it differs from next edge, or is last */ - if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) { - totedge_final++; - } - } - totedge_final++; - - medge = (MEdge *)MEM_callocN(sizeof(MEdge) * totedge_final, __func__); - - for (a = totedge, med = medge, ed = edsort; a > 1; a--, ed++) { - /* edge is unique when it differs from next edge, or is last */ - if (ed->v1 != (ed + 1)->v1 || ed->v2 != (ed + 1)->v2) { - med->v1 = ed->v1; - med->v2 = ed->v2; - if (use_old == false || ed->is_draw) { - med->flag = ME_EDGEDRAW | ME_EDGERENDER; - } - if (ed->is_loose) { - med->flag |= ME_LOOSEEDGE; - } - - /* order is swapped so extruding this edge as a surface won't flip face normals - * with cyclic curves */ - if (ed->v1 + 1 != ed->v2) { - SWAP(uint, med->v1, med->v2); - } - med++; - } - else { - /* Equal edge, merge the draw-flag. */ - (ed + 1)->is_draw |= ed->is_draw; - } - } - /* last edge */ - med->v1 = ed->v1; - med->v2 = ed->v2; - med->flag = ME_EDGEDRAW; - if (ed->is_loose) { - med->flag |= ME_LOOSEEDGE; - } - med->flag |= ME_EDGERENDER; - - MEM_freeN(edsort); - - /* set edge members of mloops */ - hash = BLI_edgehash_new_ex(__func__, totedge_final); - for (edge_index = 0, med = medge; edge_index < totedge_final; edge_index++, med++) { - BLI_edgehash_insert(hash, med->v1, med->v2, POINTER_FROM_UINT(edge_index)); - } - - mpoly = allpoly; - for (a = 0; a < totpoly; a++, mpoly++) { - MLoop *ml, *ml_next; - int i = mpoly->totloop; - - ml_next = allloop + mpoly->loopstart; /* first loop */ - ml = &ml_next[i - 1]; /* last loop */ - - while (i-- != 0) { - ml->e = POINTER_AS_UINT(BLI_edgehash_lookup(hash, ml->v, ml_next->v)); - ml = ml_next; - ml_next++; - } - } - - BLI_edgehash_free(hash, nullptr); - - *r_medge = medge; - *r_totedge = totedge_final; -} - -void BKE_mesh_calc_edges_legacy(Mesh *me, const bool use_old) -{ - MEdge *medge; - int totedge = 0; - const Span<MVert> verts = me->verts(); - const Span<MPoly> polys = me->polys(); - MutableSpan<MLoop> loops = me->loops_for_write(); - - mesh_calc_edges_mdata(verts.data(), - (MFace *)CustomData_get_layer(&me->fdata, CD_MFACE), - loops.data(), - polys.data(), - verts.size(), - me->totface, - loops.size(), - polys.size(), - use_old, - &medge, - &totedge); - - if (totedge == 0) { - /* flag that mesh has edges */ - me->totedge = 0; - return; - } - - medge = (MEdge *)CustomData_add_layer(&me->edata, CD_MEDGE, CD_ASSIGN, medge, totedge); - me->totedge = totedge; - - BKE_mesh_strip_loose_faces(me); -} - void BKE_mesh_calc_edges_loose(Mesh *mesh) { const Span<MLoop> loops = mesh->loops(); @@ -1579,7 +1369,7 @@ void BKE_mesh_calc_edges_tessface(Mesh *mesh) BLI_edgesetIterator_step(ehi), i++, med++, index++) { BLI_edgesetIterator_getKey(ehi, &med->v1, &med->v2); - med->flag = ME_EDGEDRAW | ME_EDGERENDER; + med->flag = ME_EDGEDRAW; *index = ORIGINDEX_NONE; } BLI_edgesetIterator_free(ehi); diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index eb0c78e9361..31fc8afea84 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -4346,12 +4346,6 @@ void node_type_socket_templates(struct bNodeType *ntype, } } -void node_type_init(struct bNodeType *ntype, - void (*initfunc)(struct bNodeTree *ntree, struct bNode *node)) -{ - ntype->initfunc = initfunc; -} - void node_type_size(struct bNodeType *ntype, int width, int minwidth, int maxwidth) { ntype->width = width; @@ -4399,33 +4393,6 @@ void node_type_storage(bNodeType *ntype, ntype->freefunc = freefunc; } -void node_type_update(struct bNodeType *ntype, - void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node)) -{ - ntype->updatefunc = updatefunc; -} - -void node_type_group_update(struct bNodeType *ntype, - void (*group_update_func)(struct bNodeTree *ntree, struct bNode *node)) -{ - ntype->group_update_func = group_update_func; -} - -void node_type_exec(struct bNodeType *ntype, - NodeInitExecFunction init_exec_fn, - NodeFreeExecFunction free_exec_fn, - NodeExecFunction exec_fn) -{ - ntype->init_exec_fn = init_exec_fn; - ntype->free_exec_fn = free_exec_fn; - ntype->exec_fn = exec_fn; -} - -void node_type_gpu(struct bNodeType *ntype, NodeGPUExecFunction gpu_fn) -{ - ntype->gpu_fn = gpu_fn; -} - /* callbacks for undefined types */ static bool node_undefined_poll(bNodeType * /*ntype*/, diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 1aef42ef037..51a20cf1e35 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -1025,7 +1025,7 @@ void BKE_sound_free_waveform(bSound *sound) sound->tags &= ~SOUND_TAGS_WAVEFORM_NO_RELOAD; } -void BKE_sound_read_waveform(Main *bmain, bSound *sound, short *stop) +void BKE_sound_read_waveform(Main *bmain, bSound *sound, bool *stop) { bool need_close_audio_handles = false; if (sound->playback_handle == NULL) { @@ -1041,8 +1041,11 @@ void BKE_sound_read_waveform(Main *bmain, bSound *sound, short *stop) int length = info.length * SOUND_WAVE_SAMPLES_PER_SECOND; waveform->data = MEM_mallocN(sizeof(float[3]) * length, "SoundWaveform.samples"); + /* Ideally this would take a boolean argument. */ + short stop_i16 = *stop; waveform->length = AUD_readSound( - sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND, stop); + sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND, &stop_i16); + *stop = stop_i16 != 0; } else { /* Create an empty waveform here if the sound couldn't be @@ -1381,7 +1384,7 @@ int BKE_sound_scene_playing(Scene *UNUSED(scene)) void BKE_sound_read_waveform(Main *bmain, bSound *sound, /* NOLINTNEXTLINE: readability-non-const-parameter. */ - short *stop) + bool *stop) { UNUSED_VARS(sound, stop, bmain); } diff --git a/source/blender/blenkernel/intern/subdiv_mesh.cc b/source/blender/blenkernel/intern/subdiv_mesh.cc index 3b97c1f5e68..e1c434f2b2e 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_mesh.cc @@ -794,7 +794,7 @@ static void subdiv_copy_edge_data(SubdivMeshContext *ctx, /* TODO: Ensure crease layer isn't copied to result. */ subdiv_edge->flag = 0; if (!ctx->settings->use_optimal_display) { - subdiv_edge->flag |= ME_EDGERENDER; + subdiv_edge->flag |= ME_EDGEDRAW; } if (ctx->edge_origindex != nullptr) { ctx->edge_origindex[subdiv_edge_index] = ORIGINDEX_NONE; @@ -804,7 +804,7 @@ static void subdiv_copy_edge_data(SubdivMeshContext *ctx, const int coarse_edge_index = coarse_edge - ctx->coarse_edges; CustomData_copy_data( &ctx->coarse_mesh->edata, &ctx->subdiv_mesh->edata, coarse_edge_index, subdiv_edge_index, 1); - subdiv_edge->flag |= ME_EDGERENDER; + subdiv_edge->flag |= ME_EDGEDRAW; } static void subdiv_mesh_edge(const SubdivForeachContext *foreach_context, diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index c37f4b1ea2f..80fb637b76e 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -962,7 +962,7 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) int edgeSize = ccgSubSurf_getEdgeSize(ss); uint i = 0; short *edgeFlags = ccgdm->edgeFlags; - const short ed_interior_flag = ccgdm->drawInteriorEdges ? (ME_EDGEDRAW | ME_EDGERENDER) : 0; + const short ed_interior_flag = ccgdm->drawInteriorEdges ? ME_EDGEDRAW : 0; totface = ccgSubSurf_getNumFaces(ss); for (index = 0; index < totface; index++) { @@ -1005,11 +1005,11 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge) if (edgeFlags) { if (edgeIdx != -1) { - ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW | ME_EDGERENDER); + ed_flag |= ((edgeFlags[index] & (ME_SEAM | ME_SHARP)) | ME_EDGEDRAW); } } else { - ed_flag |= ME_EDGEDRAW | ME_EDGERENDER; + ed_flag |= ME_EDGEDRAW; } for (x = 0; x < edgeSize - 1; x++) { diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c index 11041b4c0fd..e784c39ba08 100644 --- a/source/blender/blenkernel/intern/tracking_solver.c +++ b/source/blender/blenkernel/intern/tracking_solver.c @@ -56,8 +56,8 @@ typedef struct MovieReconstructContext { } MovieReconstructContext; typedef struct ReconstructProgressData { - short *stop; - short *do_update; + bool *stop; + bool *do_update; float *progress; char *stats_message; int message_size; @@ -465,8 +465,8 @@ static void reconstructionOptionsFromContext(libmv_ReconstructionOptions *recons } void BKE_tracking_reconstruction_solve(MovieReconstructContext *context, - short *stop, - short *do_update, + bool *stop, + bool *do_update, float *progress, char *stats_message, int message_size) diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 1d4cbc48833..8d6dba440fd 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -141,19 +141,25 @@ static int write_audio_frame(FFMpegContext *context) frame->pts = context->audio_time / av_q2d(c->time_base); frame->nb_samples = context->audio_input_samples; frame->format = c->sample_fmt; +# ifdef FFMPEG_USE_OLD_CHANNEL_VARS frame->channels = c->channels; frame->channel_layout = c->channel_layout; + const int num_channels = c->channels; +# else + av_channel_layout_copy(&frame->ch_layout, &c->ch_layout); + const int num_channels = c->ch_layout.nb_channels; +# endif if (context->audio_deinterleave) { int channel, i; uint8_t *temp; - for (channel = 0; channel < c->channels; channel++) { + for (channel = 0; channel < num_channels; channel++) { for (i = 0; i < frame->nb_samples; i++) { memcpy(context->audio_deinterleave_buffer + (i + channel * frame->nb_samples) * context->audio_sample_size, context->audio_input_buffer + - (c->channels * i + channel) * context->audio_sample_size, + (num_channels * i + channel) * context->audio_sample_size, context->audio_sample_size); } } @@ -164,10 +170,11 @@ static int write_audio_frame(FFMpegContext *context) } avcodec_fill_audio_frame(frame, - c->channels, + num_channels, c->sample_fmt, context->audio_input_buffer, - context->audio_input_samples * c->channels * context->audio_sample_size, + context->audio_input_samples * num_channels * + context->audio_sample_size, 1); int success = 1; @@ -944,25 +951,34 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, c->sample_rate = rd->ffcodecdata.audio_mixrate; c->bit_rate = context->ffmpeg_audio_bitrate * 1000; c->sample_fmt = AV_SAMPLE_FMT_S16; - c->channels = rd->ffcodecdata.audio_channels; + const int num_channels = rd->ffcodecdata.audio_channels; + int channel_layout_mask = 0; switch (rd->ffcodecdata.audio_channels) { case FFM_CHANNELS_MONO: - c->channel_layout = AV_CH_LAYOUT_MONO; + channel_layout_mask = AV_CH_LAYOUT_MONO; break; case FFM_CHANNELS_STEREO: - c->channel_layout = AV_CH_LAYOUT_STEREO; + channel_layout_mask = AV_CH_LAYOUT_STEREO; break; case FFM_CHANNELS_SURROUND4: - c->channel_layout = AV_CH_LAYOUT_QUAD; + channel_layout_mask = AV_CH_LAYOUT_QUAD; break; case FFM_CHANNELS_SURROUND51: - c->channel_layout = AV_CH_LAYOUT_5POINT1_BACK; + channel_layout_mask = AV_CH_LAYOUT_5POINT1_BACK; break; case FFM_CHANNELS_SURROUND71: - c->channel_layout = AV_CH_LAYOUT_7POINT1; + channel_layout_mask = AV_CH_LAYOUT_7POINT1; break; } + BLI_assert(channel_layout_mask != 0); + +# ifdef FFMPEG_USE_OLD_CHANNEL_VARS + c->channels = num_channels; + c->channel_layout = channel_layout_mask; +# else + av_channel_layout_from_mask(&c->ch_layout, channel_layout_mask); +# endif if (request_float_audio_buffer(codec_id)) { /* mainly for AAC codec which is experimental */ @@ -1027,7 +1043,7 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, * not sure if that is needed anymore, so let's try out if there are any * complaints regarding some FFmpeg versions users might have. */ context->audio_input_samples = AV_INPUT_BUFFER_MIN_SIZE * 8 / c->bits_per_coded_sample / - c->channels; + num_channels; } else { context->audio_input_samples = c->frame_size; @@ -1037,11 +1053,11 @@ static AVStream *alloc_audio_stream(FFMpegContext *context, context->audio_sample_size = av_get_bytes_per_sample(c->sample_fmt); - context->audio_input_buffer = (uint8_t *)av_malloc(context->audio_input_samples * c->channels * + context->audio_input_buffer = (uint8_t *)av_malloc(context->audio_input_samples * num_channels * context->audio_sample_size); if (context->audio_deinterleave) { context->audio_deinterleave_buffer = (uint8_t *)av_malloc( - context->audio_input_samples * c->channels * context->audio_sample_size); + context->audio_input_samples * num_channels * context->audio_sample_size); } context->audio_time = 0.0f; @@ -1432,7 +1448,11 @@ int BKE_ffmpeg_start(void *context_v, AVCodecContext *c = context->audio_codec; AUD_DeviceSpecs specs; +# ifdef FFMPEG_USE_OLD_CHANNEL_VARS specs.channels = c->channels; +# else + specs.channels = c->ch_layout.nb_channels; +# endif switch (av_get_packed_sample_fmt(c->sample_fmt)) { case AV_SAMPLE_FMT_U8: |