Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntonio Vazquez <blendergit@gmail.com>2022-11-10 12:02:48 +0300
committerAntonio Vazquez <blendergit@gmail.com>2022-11-10 12:02:48 +0300
commit7c576792c93192d652805e6f5352bff53f161e74 (patch)
tree7c76bfe3703ca6fd50bc043a072d173da91b71fa
parent11b9723d1dd58b5f6c364d4d8686ed21b82d2e64 (diff)
parentbaabac5909204000664e675095e0340b4833f67d (diff)
Merge branch 'master' into asset-lite-greasepencil
-rw-r--r--extern/audaspace/include/devices/DeviceManager.h1
-rw-r--r--intern/cycles/blender/addon/engine.py1
-rw-r--r--intern/cycles/blender/addon/operators.py2
-rw-r--r--intern/cycles/blender/addon/ui.py5
-rw-r--r--intern/cycles/kernel/integrator/init_from_bake.h7
-rw-r--r--intern/cycles/kernel/osl/services.cpp7
-rw-r--r--intern/cycles/session/merge.h2
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp38
-rw-r--r--release/datafiles/fonts/Noto Sans CJK Regular.woff2bin11672912 -> 11425316 bytes
-rw-r--r--source/blender/blenfont/intern/blf_thumbs.c2
-rw-r--r--source/blender/blenkernel/BKE_asset.h19
-rw-r--r--source/blender/blenkernel/BKE_asset_library.h40
-rw-r--r--source/blender/blenkernel/BKE_asset_library.hh80
-rw-r--r--source/blender/blenkernel/BKE_asset_representation.hh64
-rw-r--r--source/blender/blenkernel/BKE_curves_utils.hh327
-rw-r--r--source/blender/blenkernel/BKE_particle.h8
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/asset.cc28
-rw-r--r--source/blender/blenkernel/intern/asset_catalog.cc9
-rw-r--r--source/blender/blenkernel/intern/asset_library.cc90
-rw-r--r--source/blender/blenkernel/intern/asset_library_service.cc25
-rw-r--r--source/blender/blenkernel/intern/asset_library_service.hh8
-rw-r--r--source/blender/blenkernel/intern/asset_library_service_test.cc23
-rw-r--r--source/blender/blenkernel/intern/asset_representation.cc98
-rw-r--r--source/blender/blenkernel/intern/asset_test.cc2
-rw-r--r--source/blender/blenkernel/intern/context.c2
-rw-r--r--source/blender/blenkernel/intern/fluid.c14
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c10
-rw-r--r--source/blender/blenkernel/intern/material.c47
-rw-r--r--source/blender/blenkernel/intern/object_dupli.cc8
-rw-r--r--source/blender/blenkernel/intern/particle.c50
-rw-r--r--source/blender/blenkernel/intern/particle_system.c27
-rw-r--r--source/blender/blenloader/intern/versioning_260.c12
-rw-r--r--source/blender/compositor/nodes/COM_OutputFileNode.cc2
-rw-r--r--source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h2
-rw-r--r--source/blender/compositor/operations/COM_OutputFileOperation.h2
-rw-r--r--source/blender/draw/intern/draw_cache_impl_particles.c4
-rw-r--r--source/blender/editors/asset/intern/asset_handle.cc9
-rw-r--r--source/blender/editors/asset/intern/asset_temp_id_consumer.cc2
-rw-r--r--source/blender/editors/include/UI_interface.h1
-rw-r--r--source/blender/editors/interface/interface_drag.cc5
-rw-r--r--source/blender/editors/interface/interface_template_asset_view.cc1
-rw-r--r--source/blender/editors/space_file/CMakeLists.txt4
-rw-r--r--source/blender/editors/space_file/asset_catalog_tree_view.cc5
-rw-r--r--source/blender/editors/space_file/file_draw.c2
-rw-r--r--source/blender/editors/space_file/file_indexer.cc3
-rw-r--r--source/blender/editors/space_file/file_intern.h18
-rw-r--r--source/blender/editors/space_file/filelist.cc144
-rw-r--r--source/blender/editors/space_file/space_file.c2
-rw-r--r--source/blender/editors/space_node/node_relationships.cc1
-rw-r--r--source/blender/editors/space_text/text_ops.c6
-rw-r--r--source/blender/geometry/GEO_trim_curves.hh20
-rw-r--r--source/blender/geometry/intern/set_curve_type.cc9
-rw-r--r--source/blender/geometry/intern/trim_curves.cc978
-rw-r--r--source/blender/imbuf/intern/jp2.c2
-rw-r--r--source/blender/imbuf/intern/openexr/openexr_api.cpp2
-rw-r--r--source/blender/io/alembic/exporter/abc_writer_points.cc7
-rw-r--r--source/blender/makesdna/DNA_asset_types.h6
-rw-r--r--source/blender/makesdna/DNA_space_types.h4
-rw-r--r--source/blender/makesrna/intern/rna_space.c15
-rw-r--r--source/blender/modifiers/intern/MOD_explode.c7
-rw-r--r--source/blender/modifiers/intern/MOD_particleinstance.c7
-rw-r--r--source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc47
-rw-r--r--source/blender/render/intern/bake.c6
-rw-r--r--source/blender/render/intern/texture_pointdensity.c14
-rw-r--r--source/blender/sequencer/intern/effects.c11
-rw-r--r--source/blender/windowmanager/WM_api.h1
-rw-r--r--source/blender/windowmanager/intern/wm_dragdrop.cc10
68 files changed, 1353 insertions, 1064 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/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py
index 83dc6332f47..4ac078ed8a5 100644
--- a/intern/cycles/blender/addon/engine.py
+++ b/intern/cycles/blender/addon/engine.py
@@ -155,6 +155,7 @@ def with_osl():
import _cycles
return _cycles.with_osl
+
def osl_version():
import _cycles
return _cycles.osl_version
diff --git a/intern/cycles/blender/addon/operators.py b/intern/cycles/blender/addon/operators.py
index ab474cda0ab..3680d11359e 100644
--- a/intern/cycles/blender/addon/operators.py
+++ b/intern/cycles/blender/addon/operators.py
@@ -114,7 +114,7 @@ class CYCLES_OT_denoise_animation(Operator):
class CYCLES_OT_merge_images(Operator):
- "Combine OpenEXR multilayer images rendered with different sample " \
+ "Combine OpenEXR multi-layer images rendered with different sample " \
"ranges into one image with reduced noise"
bl_idname = "cycles.merge_images"
bl_label = "Merge Images"
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 11fa2bc62fb..10a37688f45 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -2305,7 +2305,10 @@ def draw_device(self, context):
col.prop(cscene, "device")
from . import engine
- if engine.with_osl() and (use_cpu(context) or (use_optix(context) and (engine.osl_version()[1] >= 13 or engine.osl_version()[0] > 1))):
+ if engine.with_osl() and (
+ use_cpu(context) or
+ (use_optix(context) and (engine.osl_version()[1] >= 13 or engine.osl_version()[0] > 1))
+ ):
col.prop(cscene, "shading_system")
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/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp
index 454b75ea4d9..3fd098de4bb 100644
--- a/intern/cycles/kernel/osl/services.cpp
+++ b/intern/cycles/kernel/osl/services.cpp
@@ -1176,9 +1176,10 @@ TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring file
return (TextureSystem::TextureHandle *)it->second.get();
}
else {
- if (it != textures.end() && it->second->type == OSLTextureHandle::SVM && it->second->svm_slots[0].w == -1) {
- return reinterpret_cast<TextureSystem::TextureHandle *>(
- static_cast<uintptr_t>(it->second->svm_slots[0].y + 1));
+ if (it != textures.end() && it->second->type == OSLTextureHandle::SVM &&
+ it->second->svm_slots[0].w == -1) {
+ return reinterpret_cast<TextureSystem::TextureHandle *>(
+ static_cast<uintptr_t>(it->second->svm_slots[0].y + 1));
}
return NULL;
diff --git a/intern/cycles/session/merge.h b/intern/cycles/session/merge.h
index 702ca5c3eb8..d8a4f04a27b 100644
--- a/intern/cycles/session/merge.h
+++ b/intern/cycles/session/merge.h
@@ -9,7 +9,7 @@
CCL_NAMESPACE_BEGIN
-/* Merge OpenEXR multilayer renders. */
+/* Merge OpenEXR multi-layer renders. */
class ImageMerger {
public:
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index a2028de6f53..42da4a3ebbf 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -4985,6 +4985,42 @@ static const struct wl_registry_listener registry_listener = {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Listener (Display), #wl_display_listener
+ * \{ */
+
+static CLG_LogRef LOG_WL_DISPLAY = {"ghost.wl.handle.display"};
+#define LOG (&LOG_WL_DISPLAY)
+
+static void display_handle_error(
+ void *data, struct wl_display *wl_display, void *object_id, uint32_t code, const char *message)
+{
+ GWL_Display *display = static_cast<GWL_Display *>(data);
+ GHOST_ASSERT(display->wl_display == wl_display, "Invalid internal state");
+ (void)display;
+
+ /* NOTE: code is #wl_display_error, there isn't a convenient way to convert to an ID. */
+ CLOG_INFO(LOG, 2, "error (code=%u, object_id=%p, message=%s)", code, object_id, message);
+}
+
+static void display_handle_delete_id(void *data, struct wl_display *wl_display, uint32_t id)
+{
+ GWL_Display *display = static_cast<GWL_Display *>(data);
+ GHOST_ASSERT(display->wl_display == wl_display, "Invalid internal state");
+ (void)display;
+
+ CLOG_INFO(LOG, 2, "delete_id (id=%u)", id);
+}
+
+static const struct wl_display_listener display_listener = {
+ display_handle_error,
+ display_handle_delete_id,
+};
+
+#undef LOG
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name GHOST Implementation
*
* WAYLAND specific implementation of the #GHOST_System interface.
@@ -5006,6 +5042,8 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
/* This may be removed later if decorations are required, needed as part of registration. */
display_->xdg_decor = new GWL_XDG_Decor_System;
+ wl_display_add_listener(display_->wl_display, &display_listener, display_);
+
/* Register interfaces. */
{
display_->registry_skip_update_all = true;
diff --git a/release/datafiles/fonts/Noto Sans CJK Regular.woff2 b/release/datafiles/fonts/Noto Sans CJK Regular.woff2
index 5d3854b6bf7..4180a5914fa 100644
--- a/release/datafiles/fonts/Noto Sans CJK Regular.woff2
+++ b/release/datafiles/fonts/Noto Sans CJK Regular.woff2
Binary files differ
diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c
index ac2f2f35ca3..8a640ac86a7 100644
--- a/source/blender/blenfont/intern/blf_thumbs.c
+++ b/source/blender/blenfont/intern/blf_thumbs.c
@@ -46,7 +46,7 @@ typedef struct UnicodeSample {
* those need to be checked last. */
static const UnicodeSample unicode_samples[] = {
/* Chinese, Japanese, Korean, ordered specific to general. */
- {U"\uc870\uc120\uae00", 2, TT_UCR_HANGUL}, /* 조선글 */
+ {U"\ud55c\uad6d\uc5b4", 2, TT_UCR_HANGUL}, /* 한국어 */
{U"\u3042\u30a2\u4e9c", 2, TT_UCR_HIRAGANA}, /* あア亜 */
{U"\u30a2\u30a4\u4e9c", 2, TT_UCR_KATAKANA}, /* アイ亜 */
{U"\u1956\u195b\u1966", 3, TT_UCR_TAI_LE}, /* ᥖᥛᥦ */
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_curves_utils.hh b/source/blender/blenkernel/BKE_curves_utils.hh
index f9155023db7..1e06cb2d4c7 100644
--- a/source/blender/blenkernel/BKE_curves_utils.hh
+++ b/source/blender/blenkernel/BKE_curves_utils.hh
@@ -67,86 +67,228 @@ struct CurvePoint : public CurveSegment {
};
/**
- * Cyclical index range. Iterates the interval [start, end).
+ * Cyclical index range. Allows iteration over a plain 'IndexRange' interval on form [start, end)
+ * while also supporting treating the underlying array as a cyclic array where the last index is
+ * followed by the first index in the 'cyclical' range. The cyclical index range can then be
+ * considered a combination of the intervals separated by the last index of the underlying array,
+ * namely [start, range_size) and [0, end) where start/end is the indices iterated between and
+ * range_size is the size of the underlying array. To cycle the underlying array the interval
+ * [0, range_size) can be iterated over an arbitrary amount of times in between.
*/
class IndexRangeCyclic {
/* Index to the start and end of the iterated range.
*/
- int64_t start_ = 0;
- int64_t end_ = 0;
- /* Index for the start and end of the entire iterable range which contains the iterated range
- * (e.g. the point range for an individual spline/curve within the entire Curves point domain).
+ int start_ = 0;
+ int end_ = 0;
+ /* Size of the underlying iterable range.
*/
- int64_t range_start_ = 0;
- int64_t range_end_ = 0;
+ int range_size_ = 0;
/* Number of times the range end is passed when the range is iterated.
*/
- int64_t cycles_ = 0;
-
- constexpr IndexRangeCyclic(int64_t begin,
- int64_t end,
- int64_t iterable_range_start,
- int64_t iterable_range_end,
- int64_t cycles)
- : start_(begin),
- end_(end),
- range_start_(iterable_range_start),
- range_end_(iterable_range_end),
- cycles_(cycles)
- {
- }
+ int cycles_ = 0;
public:
constexpr IndexRangeCyclic() = default;
~IndexRangeCyclic() = default;
- constexpr IndexRangeCyclic(int64_t start, int64_t end, IndexRange iterable_range, int64_t cycles)
- : start_(start),
- end_(end),
- range_start_(iterable_range.first()),
- range_end_(iterable_range.one_after_last()),
- cycles_(cycles)
+ constexpr IndexRangeCyclic(const int start,
+ const int end,
+ const int iterable_range_size,
+ const int cycles)
+ : start_(start), end_(end), range_size_(iterable_range_size), cycles_(cycles)
{
}
/**
* Create an iterator over the cyclical interval [start_index, end_index).
*/
- constexpr IndexRangeCyclic(int64_t start, int64_t end, IndexRange iterable_range)
+ constexpr IndexRangeCyclic(const int start, const int end, const int iterable_range_size)
: start_(start),
- end_(end == iterable_range.one_after_last() ? iterable_range.first() : end),
- range_start_(iterable_range.first()),
- range_end_(iterable_range.one_after_last()),
+ end_(end == iterable_range_size ? 0 : end),
+ range_size_(iterable_range_size),
cycles_(end < start)
{
}
/**
- * Increment the range by adding the given number of indices to the beginning of the range.
+ * Create a cyclical iterator of the specified size.
+ *
+ * \param start_point: Point on the curve that define the starting point of the interval.
+ * \param iterator_size: Number of elements to iterate (size of the iterated cyclical range).
+ * \param iterable_range_size: Size of the underlying range (superset to the cyclical range).
+ */
+ static IndexRangeCyclic get_range_from_size(const int start_index,
+ const int iterator_size,
+ const int iterable_range_size)
+ {
+ BLI_assert(start_index >= 0);
+ BLI_assert(iterator_size >= 0);
+ BLI_assert(iterable_range_size > 0);
+ const int num_until_loop = iterable_range_size - start_index;
+ if (iterator_size < num_until_loop) {
+ return IndexRangeCyclic(start_index, start_index + iterator_size, iterable_range_size, 0);
+ }
+
+ const int num_remaining = iterator_size - num_until_loop;
+ const int num_full_cycles = num_remaining /
+ iterable_range_size; /* Integer division (rounded down). */
+ const int end_index = num_remaining - num_full_cycles * iterable_range_size;
+ return IndexRangeCyclic(start_index, end_index, iterable_range_size, num_full_cycles + 1);
+ }
+
+ /**
+ * Create a cyclical iterator for all control points within the interval [start_point, end_point]
+ * including any control point at the start or end point.
+ *
+ * \param start_point: Point on the curve that define the starting point of the interval.
+ * \param end_point: Point on the curve that define the end point of the interval (included).
+ * \param iterable_range_size: Size of the underlying range (superset to the cyclical range).
+ */
+ static IndexRangeCyclic get_range_between_endpoints(const CurvePoint start_point,
+ const CurvePoint end_point,
+ const int iterable_range_size)
+ {
+ BLI_assert(iterable_range_size > 0);
+ const int start_index = start_point.parameter == 0.0 ? start_point.index :
+ start_point.next_index;
+ int end_index = end_point.parameter == 0.0 ? end_point.index : end_point.next_index;
+ int cycles;
+
+ if (end_point.is_controlpoint()) {
+ BLI_assert(end_index < iterable_range_size);
+ ++end_index;
+ if (end_index == iterable_range_size) {
+ end_index = 0;
+ }
+ /* end_point < start_point but parameter is irrelevant (end_point is controlpoint), and loop
+ * when equal due to increment. */
+ cycles = end_index <= start_index;
+ }
+ else {
+ cycles = end_point < start_point || end_index < start_index;
+ }
+ return IndexRangeCyclic(start_index, end_index, iterable_range_size, cycles);
+ }
+
+ /**
+ * Next index within the iterable range.
+ */
+ template<typename IndexT> constexpr IndexT next_index(const IndexT index, const bool cyclic)
+ {
+ static_assert((is_same_any_v<IndexT, int, int>), "Expected signed integer type.");
+ const IndexT next_index = index + 1;
+ if (next_index == this->size_range()) {
+ return cyclic ? 0 : index;
+ }
+ return next_index;
+ }
+
+ /**
+ * Previous index within the iterable range.
+ */
+ template<typename IndexT> constexpr IndexT previous_index(const IndexT index, const bool cyclic)
+ {
+ static_assert((is_same_any_v<IndexT, int, int64_t>), "Expected signed integer type.");
+ const IndexT prev_index = index - 1;
+ if (prev_index < 0) {
+ return cyclic ? this->size_range() - 1 : 0;
+ }
+ return prev_index;
+ }
+
+ /**
+ * Increment the range by adding `n` loops to the range. This invokes undefined behavior when n
+ * is negative.
+ */
+ constexpr IndexRangeCyclic push_loop(const int n = 1) const
+ {
+ return {this->start_, this->end_, this->range_size_, this->cycles_ + n};
+ }
+
+ /**
+ * Increment the range by adding the given number of indices to the beginning of the iterated
+ * range. This invokes undefined behavior when n is negative.
*/
- constexpr IndexRangeCyclic push_forward(int n)
+ constexpr IndexRangeCyclic push_front(const int n = 1) const
{
BLI_assert(n >= 0);
- int64_t nstart = start_ - n;
- int64_t cycles = cycles_;
- if (nstart < range_start_) {
+ int new_start = this->start_ - n;
+ int num_cycles = this->cycles_;
+ if (new_start < 0) {
+ const int new_cycles = n / this->size_range(); /* Integer division (floor) */
+ const int remainder = new_start + this->size_range() * new_cycles;
+ const bool underflow = remainder < 0;
+ new_start = remainder + (underflow ? this->size_range() : 0);
+ num_cycles += new_cycles + int(underflow);
+ }
+ BLI_assert(num_cycles >= 0);
+ BLI_assert(num_cycles > 0 ||
+ (new_start <= this->end_ || (this->end_ == 0 && new_start < this->size_range())));
+ return {new_start, this->end_, this->range_size_, num_cycles};
+ }
- cycles += (int64_t)(n / (range_end_ - range_start_)) + (end_ < nstart) - (end_ < start_);
+ /**
+ * Increment the range by adding the given number of indices to the end of the iterated range.
+ * This invokes undefined behavior when n is negative.
+ */
+ constexpr IndexRangeCyclic push_back(const int n = 1) const
+ {
+ BLI_assert(n >= 0);
+ int new_end = this->end_ + n;
+ int num_cycles = this->cycles_;
+ if (this->size_range() <= new_end) {
+ const int new_cycles = n / this->size_range(); /* Integer division (floor) */
+ const int remainder = new_end - this->size_range() * new_cycles;
+ const bool overflow = remainder >= this->size_range();
+ new_end = remainder - (overflow ? this->size_range() : 0);
+ num_cycles += new_cycles + int(overflow);
}
- return {nstart, end_, range_start_, range_end_, cycles};
+ BLI_assert(num_cycles >= 0);
+ BLI_assert(num_cycles > 0 || (this->start_ <= new_end || new_end == 0));
+ return {this->start_, new_end, this->range_size_, num_cycles};
}
+
/**
- * Increment the range by adding the given number of indices to the end of the range.
+ * Returns a new range with n indices removed from the beginning of the range.
+ * This invokes undefined behavior.
*/
- constexpr IndexRangeCyclic push_backward(int n)
+ constexpr IndexRangeCyclic drop_front(const int n = 1) const
{
BLI_assert(n >= 0);
- int64_t new_end = end_ + n;
- int64_t cycles = cycles_;
- if (range_end_ <= new_end) {
- cycles += (int64_t)(n / (range_end_ - range_start_)) + (new_end < start_) - (end_ < start_);
+ int new_start = this->start_ + n;
+ int num_cycles = this->cycles_;
+ if (this->size_range() <= new_start) {
+ const int dropped_cycles = n / this->size_range(); /* Integer division (floor) */
+ const int remainder = new_start - this->size_range() * dropped_cycles;
+ const bool overflow = remainder >= this->size_range();
+ new_start = remainder - (overflow ? this->size_range() : 0);
+ num_cycles -= dropped_cycles + int(overflow);
}
- return {start_, new_end, range_start_, range_end_, cycles};
+ BLI_assert(num_cycles >= 0);
+ BLI_assert(num_cycles > 0 ||
+ (new_start <= this->end_ || (this->end_ == 0 && new_start < this->size_range())));
+ return {new_start, this->end_, this->range_size_, num_cycles};
+ }
+
+ /**
+ * Returns a new range with n indices removed from the end of the range.
+ * This invokes undefined behavior when n is negative or n is larger then the underlying range.
+ */
+ constexpr IndexRangeCyclic drop_back(const int n = 1) const
+ {
+ BLI_assert(n >= 0);
+ int new_end = this->end_ - n;
+ int num_cycles = this->cycles_;
+ if (0 >= new_end) {
+ const int dropped_cycles = n / this->size_range(); /* Integer division (floor) */
+ const int remainder = new_end + this->size_range() * dropped_cycles;
+ const bool underflow = remainder < 0;
+ new_end = remainder + (underflow ? this->size_range() : 0);
+ num_cycles -= dropped_cycles + int(underflow);
+ }
+ BLI_assert(num_cycles >= 0);
+ BLI_assert(num_cycles > 0 || (this->start_ <= new_end || new_end == 0));
+ return {this->start_, new_end, this->range_size_, num_cycles};
}
/**
@@ -154,7 +296,7 @@ class IndexRangeCyclic {
*/
constexpr IndexRange curve_range() const
{
- return IndexRange(range_start_, total_size());
+ return IndexRange(0, this->size_range());
}
/**
@@ -162,7 +304,7 @@ class IndexRangeCyclic {
*/
constexpr IndexRange range_before_loop() const
{
- return IndexRange(start_, size_before_loop());
+ return IndexRange(this->start_, this->size_before_loop());
}
/**
@@ -170,88 +312,104 @@ class IndexRangeCyclic {
*/
constexpr IndexRange range_after_loop() const
{
- return IndexRange(range_start_, size_after_loop());
+ return IndexRange(0, this->size_after_loop());
}
/**
- * Size of the entire iterable range.
+ * Number of elements in the underlying iterable range.
*/
- constexpr int64_t total_size() const
+ constexpr int size_range() const
{
- return range_end_ - range_start_;
+ return this->range_size_;
}
/**
* Number of elements between the first element in the range up to the last element in the curve.
*/
- constexpr int64_t size_before_loop() const
+ constexpr int size_before_loop() const
{
- return range_end_ - start_;
+ return this->range_size_ - this->start_;
}
/**
* Number of elements between the first element in the iterable range up to the last element in
* the range.
*/
- constexpr int64_t size_after_loop() const
+ constexpr int size_after_loop() const
{
- return end_ - range_start_;
+ return this->end_;
}
/**
- * Get number of elements iterated by the cyclical index range.
+ * Number of elements iterated by the cyclical index range.
*/
- constexpr int64_t size() const
+ constexpr int size() const
{
- if (cycles_ > 0) {
- return size_before_loop() + end_ + (cycles_ - 1) * (range_end_ - range_start_);
+ if (this->cycles_ > 0) {
+ return this->size_before_loop() + this->end_ + (this->cycles_ - 1) * this->range_size_;
}
else {
- return end_ - start_;
+ return int(this->end_ - this->start_);
}
}
/**
* Return the number of times the iterator will cycle before ending.
*/
- constexpr int64_t cycles() const
+ constexpr int cycles() const
+ {
+ return this->cycles_;
+ }
+
+ constexpr int first() const
{
- return cycles_;
+ return this->start_;
}
- constexpr int64_t first() const
+ constexpr int last() const
{
- return start_;
+ BLI_assert(this->size() > 0);
+ return int(this->end_ - 1);
}
- constexpr int64_t one_after_last() const
+ constexpr int one_after_last() const
+ {
+ return this->end_;
+ }
+
+ constexpr bool operator==(const IndexRangeCyclic &other) const
+ {
+ return this->start_ == other.start_ && this->end_ == other.end_ &&
+ this->cycles_ == other.cycles_ && this->range_size_ == other.range_size_;
+ }
+ constexpr bool operator!=(const IndexRangeCyclic &other) const
{
- return end_;
+ return !this->operator==(other);
}
struct CyclicIterator; /* Forward declaration */
constexpr CyclicIterator begin() const
{
- return CyclicIterator(range_start_, range_end_, start_, 0);
+ return CyclicIterator(this->range_size_, this->start_, 0);
}
constexpr CyclicIterator end() const
{
- return CyclicIterator(range_start_, range_end_, end_, cycles_);
+ return CyclicIterator(this->range_size_, this->end_, this->cycles_);
}
struct CyclicIterator {
- int64_t index_, begin_, end_, cycles_;
+ int index_, range_end_, cycles_;
- constexpr CyclicIterator(int64_t range_begin, int64_t range_end, int64_t index, int64_t cycles)
- : index_(index), begin_(range_begin), end_(range_end), cycles_(cycles)
+ constexpr CyclicIterator(const int range_end, const int index, const int cycles)
+ : index_(index), range_end_(range_end), cycles_(cycles)
{
- BLI_assert(range_begin <= index && index <= range_end);
+ BLI_assert(0 <= index && index <= range_end);
}
constexpr CyclicIterator(const CyclicIterator &copy)
- : index_(copy.index_), begin_(copy.begin_), end_(copy.end_), cycles_(copy.cycles_)
+ : index_(copy.index_), range_end_(copy.range_end_), cycles_(copy.cycles_)
{
}
~CyclicIterator() = default;
@@ -261,37 +419,36 @@ class IndexRangeCyclic {
if (this == &copy) {
return *this;
}
- index_ = copy.index_;
- begin_ = copy.begin_;
- end_ = copy.end_;
- cycles_ = copy.cycles_;
+ this->index_ = copy.index_;
+ this->range_end_ = copy.range_end_;
+ this->cycles_ = copy.cycles_;
return *this;
}
constexpr CyclicIterator &operator++()
{
- index_++;
- if (index_ == end_) {
- index_ = begin_;
- cycles_++;
+ this->index_++;
+ if (this->index_ == this->range_end_) {
+ this->index_ = 0;
+ this->cycles_++;
}
return *this;
}
- void increment(int64_t n)
+ void increment(const int n)
{
for (int i = 0; i < n; i++) {
++*this;
}
}
- constexpr const int64_t &operator*() const
+ constexpr const int &operator*() const
{
- return index_;
+ return this->index_;
}
constexpr bool operator==(const CyclicIterator &other) const
{
- return index_ == other.index_ && cycles_ == other.cycles_;
+ return this->index_ == other.index_ && this->cycles_ == other.cycles_;
}
constexpr bool operator!=(const CyclicIterator &other) const
{
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/blenloader/intern/versioning_260.c b/source/blender/blenloader/intern/versioning_260.c
index cdb63bd8075..47a1f7f7241 100644
--- a/source/blender/blenloader/intern/versioning_260.c
+++ b/source/blender/blenloader/intern/versioning_260.c
@@ -280,10 +280,9 @@ static void do_versions_nodetree_multi_file_output_format_2_62_1(Scene *sce, bNo
BLI_strncpy(filename, old_image->name, sizeof(filename));
}
- /* if z buffer is saved, change the image type to multilayer exr.
- * XXX this is slightly messy, Z buffer was ignored before for anything but EXR and IRIS ...
- * I'm just assuming here that IRIZ means IRIS with z buffer ...
- */
+ /* If Z buffer is saved, change the image type to multi-layer EXR.
+ * XXX: this is slightly messy, Z buffer was ignored before for anything but EXR and IRIS ...
+ * I'm just assuming here that IRIZ means IRIS with z buffer. */
if (old_data && ELEM(old_data->im_format.imtype, R_IMF_IMTYPE_IRIZ, R_IMF_IMTYPE_OPENEXR)) {
char sockpath[FILE_MAX];
@@ -393,9 +392,8 @@ static void do_versions_nodetree_file_output_layers_2_64_5(bNodeTree *ntree)
for (sock = node->inputs.first; sock; sock = sock->next) {
NodeImageMultiFileSocket *input = sock->storage;
- /* multilayer names are stored as separate strings now,
- * used the path string before, so copy it over.
- */
+ /* Multi-layer names are stored as separate strings now,
+ * used the path string before, so copy it over. */
BLI_strncpy(input->layer, input->path, sizeof(input->layer));
/* paths/layer names also have to be unique now, initial check */
diff --git a/source/blender/compositor/nodes/COM_OutputFileNode.cc b/source/blender/compositor/nodes/COM_OutputFileNode.cc
index fc4270cc222..50989f73986 100644
--- a/source/blender/compositor/nodes/COM_OutputFileNode.cc
+++ b/source/blender/compositor/nodes/COM_OutputFileNode.cc
@@ -65,7 +65,7 @@ void OutputFileNode::convert_to_operations(NodeConverter &converter,
if (storage->format.imtype == R_IMF_IMTYPE_MULTILAYER) {
const bool use_half_float = (storage->format.depth == R_IMF_CHAN_DEPTH_16);
- /* single output operation for the multilayer file */
+ /* Single output operation for the multi-layer file. */
OutputOpenExrMultiLayerOperation *output_operation;
if (is_multiview && storage->format.views_format == R_IMF_VIEWS_MULTIVIEW) {
diff --git a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
index e36999e5cf1..70773c1a559 100644
--- a/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileMultiViewOperation.h
@@ -31,7 +31,7 @@ class OutputOpenExrSingleLayerMultiViewOperation : public OutputSingleLayerOpera
void deinit_execution() override;
};
-/* Writes inputs into OpenEXR multilayer channels. */
+/** Writes inputs into OpenEXR multi-layer channels. */
class OutputOpenExrMultiLayerMultiViewOperation : public OutputOpenExrMultiLayerOperation {
private:
public:
diff --git a/source/blender/compositor/operations/COM_OutputFileOperation.h b/source/blender/compositor/operations/COM_OutputFileOperation.h
index df1d68838d9..716bede8035 100644
--- a/source/blender/compositor/operations/COM_OutputFileOperation.h
+++ b/source/blender/compositor/operations/COM_OutputFileOperation.h
@@ -71,7 +71,7 @@ struct OutputOpenExrLayer {
SocketReader *image_input;
};
-/* Writes inputs into OpenEXR multilayer channels. */
+/* Writes inputs into OpenEXR multi-layer channels. */
class OutputOpenExrMultiLayerOperation : public MultiThreadedOperation {
protected:
const Scene *scene_;
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/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c
index f0196bf8e00..0ddd06ead62 100644
--- a/source/blender/editors/space_text/text_ops.c
+++ b/source/blender/editors/space_text/text_ops.c
@@ -3487,10 +3487,10 @@ static int text_insert_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* NOTE: the "text" property is always set from key-map,
* so we can't use #RNA_struct_property_is_set, check the length instead. */
if (!RNA_string_length(op->ptr, "text")) {
- /* if alt/ctrl/super are pressed pass through except for utf8 character event
+ /* If Alt/Control/Super are pressed pass through except for utf8 character event
* (when input method are used for utf8 inputs, the user may assign key event
- * including alt/ctrl/super like ctrl+m to commit utf8 string. in such case,
- * the modifiers in the utf8 character event make no sense.) */
+ * including Alt/Control/Super like Control-M to commit utf8 string.
+ * In such case, the modifiers in the utf8 character event make no sense). */
if ((event->modifier & (KM_CTRL | KM_OSKEY)) && !event->utf8_buf[0]) {
return OPERATOR_PASS_THROUGH;
}
diff --git a/source/blender/geometry/GEO_trim_curves.hh b/source/blender/geometry/GEO_trim_curves.hh
index d2ff770f225..197ef79c25b 100644
--- a/source/blender/geometry/GEO_trim_curves.hh
+++ b/source/blender/geometry/GEO_trim_curves.hh
@@ -3,6 +3,7 @@
#pragma once
#include "BLI_span.hh"
+#include "DNA_node_types.h"
#include "BKE_curves.hh"
#include "BKE_curves_utils.hh"
@@ -16,21 +17,8 @@ namespace blender::geometry {
*/
bke::CurvesGeometry trim_curves(const bke::CurvesGeometry &src_curves,
IndexMask selection,
- Span<bke::curves::CurvePoint> start_points,
- Span<bke::curves::CurvePoint> end_points);
-
-/**
- * Find the point(s) and piecewise segment corresponding to the given distance along the length of
- * the curve. Returns points on the evaluated curve for Catmull-Rom and NURBS splines.
- *
- * \param curves: Curve geometry to sample.
- * \param lengths: Distance along the curve on form [0.0, length] to determine the point for.
- * \param curve_indices: Curve index to lookup for each 'length', negative index are set to 0.
- * \param normalized_factors: If true, 'lengths' are normalized to the interval [0.0, 1.0].
- */
-Array<bke::curves::CurvePoint, 12> lookup_curve_points(const bke::CurvesGeometry &curves,
- Span<float> lengths,
- Span<int64_t> curve_indices,
- bool normalized_factors);
+ const VArray<float> &starts,
+ const VArray<float> &ends,
+ GeometryNodeCurveSampleMode mode);
} // namespace blender::geometry
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/geometry/intern/trim_curves.cc b/source/blender/geometry/intern/trim_curves.cc
index f2adc3b58d3..82e9ee78592 100644
--- a/source/blender/geometry/intern/trim_curves.cc
+++ b/source/blender/geometry/intern/trim_curves.cc
@@ -18,61 +18,6 @@
namespace blender::geometry {
/* -------------------------------------------------------------------- */
-/** \name Curve Enums
- * \{ */
-
-#define CURVE_TYPE_AS_MASK(curve_type) ((CurveTypeMask)(1 << int(curve_type)))
-
-enum CurveTypeMask {
- CURVE_TYPE_MASK_CATMULL_ROM = (1 << 0),
- CURVE_TYPE_MASK_POLY = (1 << 1),
- CURVE_TYPE_MASK_BEZIER = (1 << 2),
- CURVE_TYPE_MASK_NURBS = (1 << 3),
- CURVE_TYPE_MASK_ALL = (1 << 4) - 1
-};
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name #IndexRangeCyclic Utilities
- * \{ */
-
-/**
- * Create a cyclical iterator for all control points within the interval [start_point, end_point]
- * including any control point at the start or end point.
- *
- * \param start_point: Point on the curve that define the starting point of the interval.
- * \param end_point: Point on the curve that define the end point of the interval (included).
- * \param points: #IndexRange for the curve points.
- */
-static bke::curves::IndexRangeCyclic get_range_between_endpoints(
- const bke::curves::CurvePoint start_point,
- const bke::curves::CurvePoint end_point,
- const IndexRange points)
-{
- const int64_t start_index = start_point.parameter == 0.0 ? start_point.index :
- start_point.next_index;
- int64_t end_index = end_point.parameter == 0.0 ? end_point.index : end_point.next_index;
- int64_t cycles;
-
- if (end_point.is_controlpoint()) {
- ++end_index;
- if (end_index > points.last()) {
- end_index = points.one_after_last();
- }
- /* end_point < start_point but parameter is irrelevant (end_point is controlpoint), and loop
- * when equal due to increment. */
- cycles = end_index <= start_index;
- }
- else {
- cycles = end_point < start_point || end_index < start_index;
- }
- return bke::curves::IndexRangeCyclic(start_index, end_index, points, cycles);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Lookup Curve Points
* \{ */
@@ -88,11 +33,11 @@ static bke::curves::IndexRangeCyclic get_range_between_endpoints(
* \param num_curve_points: Total number of control points in the curve.
* \return: Point on the piecewise segment matching the given distance.
*/
-static bke::curves::CurvePoint lookup_curve_point(const Span<float> lengths,
- const float sample_length,
- const bool cyclic,
- const int resolution,
- const int num_curve_points)
+static bke::curves::CurvePoint lookup_point_uniform_spacing(const Span<float> lengths,
+ const float sample_length,
+ const bool cyclic,
+ const int resolution,
+ const int num_curve_points)
{
BLI_assert(!cyclic || lengths.size() / resolution >= 2);
const int last_index = num_curve_points - 1;
@@ -117,7 +62,7 @@ static bke::curves::CurvePoint lookup_curve_point(const Span<float> lengths,
/**
* Find the point on the 'evaluated' polygonal curve.
*/
-static bke::curves::CurvePoint lookup_evaluated_point(const Span<float> lengths,
+static bke::curves::CurvePoint lookup_point_polygonal(const Span<float> lengths,
const float sample_length,
const bool cyclic,
const int evaluated_size)
@@ -142,7 +87,7 @@ static bke::curves::CurvePoint lookup_evaluated_point(const Span<float> lengths,
/**
* Find the point on a Bezier curve using the 'bezier_offsets' cache.
*/
-static bke::curves::CurvePoint lookup_bezier_point(const Span<int> bezier_offsets,
+static bke::curves::CurvePoint lookup_point_bezier(const Span<int> bezier_offsets,
const Span<float> lengths,
const float sample_length,
const bool cyclic,
@@ -166,197 +111,73 @@ static bke::curves::CurvePoint lookup_bezier_point(const Span<int> bezier_offset
const int right = left == last_index ? 0 : left + 1;
const int prev_offset = left == 0 ? 0 : bezier_offsets[int64_t(left) - 1];
- const float offset_in_segment = eval_factor + eval_index - prev_offset;
+ const float offset_in_segment = eval_factor + (eval_index - prev_offset);
const int segment_resolution = bezier_offsets[left] - prev_offset;
const float parameter = std::clamp(offset_in_segment / segment_resolution, 0.0f, 1.0f);
return {{left, right}, parameter};
}
-Array<bke::curves::CurvePoint, 12> lookup_curve_points(const bke::CurvesGeometry &curves,
- const Span<float> lengths,
- const Span<int64_t> curve_indices,
- const bool normalized_factors)
-{
- BLI_assert(lengths.size() == curve_indices.size());
- BLI_assert(*std::max_element(curve_indices.begin(), curve_indices.end()) < curves.curves_num());
-
- const VArray<bool> cyclic = curves.cyclic();
- const VArray<int> resolution = curves.resolution();
- const VArray<int8_t> curve_types = curves.curve_types();
-
- /* Compute curve lengths! */
- curves.ensure_evaluated_lengths();
- curves.ensure_evaluated_offsets();
-
- /* Find the curve points referenced by the input! */
- Array<bke::curves::CurvePoint, 12> lookups(curve_indices.size());
- threading::parallel_for(curve_indices.index_range(), 128, [&](const IndexRange range) {
- for (const int64_t lookup_index : range) {
- const int64_t curve_i = curve_indices[lookup_index];
-
- const int point_count = curves.points_num_for_curve(curve_i);
- if (curve_i < 0 || point_count == 1) {
- lookups[lookup_index] = {{0, 0}, 0.0f};
- continue;
- }
-
- const Span<float> accumulated_lengths = curves.evaluated_lengths_for_curve(curve_i,
- cyclic[curve_i]);
- BLI_assert(accumulated_lengths.size() > 0);
-
- const float sample_length = normalized_factors ?
- lengths[lookup_index] * accumulated_lengths.last() :
- lengths[lookup_index];
-
- const CurveType curve_type = (CurveType)curve_types[curve_i];
-
- switch (curve_type) {
- case CURVE_TYPE_BEZIER: {
- if (bke::curves::bezier::has_vector_handles(
- point_count,
- curves.evaluated_points_for_curve(curve_i).size(),
- cyclic[curve_i],
- resolution[curve_i])) {
- const Span<int> bezier_offsets = curves.bezier_evaluated_offsets_for_curve(curve_i);
- lookups[lookup_index] = lookup_bezier_point(
- bezier_offsets, accumulated_lengths, sample_length, cyclic[curve_i], point_count);
- }
- else {
- lookups[lookup_index] = lookup_curve_point(accumulated_lengths,
- sample_length,
- cyclic[curve_i],
- resolution[curve_i],
- point_count);
- }
- break;
- }
- case CURVE_TYPE_CATMULL_ROM: {
- lookups[lookup_index] = lookup_curve_point(accumulated_lengths,
- sample_length,
- cyclic[curve_i],
- resolution[curve_i],
- point_count);
- break;
- }
- case CURVE_TYPE_NURBS:
- case CURVE_TYPE_POLY:
- default: {
- /* Handle general case as an "evaluated" or polygonal curve. */
- BLI_assert(resolution[curve_i] > 0);
- lookups[lookup_index] = lookup_evaluated_point(
- accumulated_lengths,
- sample_length,
- cyclic[curve_i],
- curves.evaluated_points_for_curve(curve_i).size());
- break;
- }
- }
- }
- });
- return lookups;
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Transfer Curve Domain
- * \{ */
-
-/**
- * Determine curve type(s) for the copied curves given the supported set of types and knot modes.
- * If a curve type is not supported the default type is set.
- */
-static void determine_copyable_curve_types(
- const bke::CurvesGeometry &src_curves,
- bke::CurvesGeometry &dst_curves,
- const IndexMask selection,
- const IndexMask selection_inverse,
- const CurveTypeMask supported_curve_type_mask,
- const int8_t default_curve_type = int8_t(CURVE_TYPE_POLY))
-{
- const VArray<int8_t> src_curve_types = src_curves.curve_types();
- const VArray<int8_t> src_knot_modes = src_curves.nurbs_knots_modes();
- MutableSpan<int8_t> dst_curve_types = dst_curves.curve_types_for_write();
-
- threading::parallel_for(selection.index_range(), 4096, [&](const IndexRange selection_range) {
- for (const int64_t curve_i : selection.slice(selection_range)) {
- if (supported_curve_type_mask & CURVE_TYPE_AS_MASK(src_curve_types[curve_i])) {
- dst_curve_types[curve_i] = src_curve_types[curve_i];
- }
- else {
- dst_curve_types[curve_i] = default_curve_type;
- }
- }
- });
-
- array_utils::copy(src_curve_types, selection_inverse, dst_curve_types);
-}
-
-/**
- * Determine if a curve is treated as an evaluated curve. Curves which inherently do not support
- * trimming are discretized (e.g. NURBS).
- */
-static bool copy_as_evaluated_curve(const int8_t src_type, const int8_t dst_type)
+static bke::curves::CurvePoint lookup_point_bezier(const bke::CurvesGeometry &src_curves,
+ const int64_t curve_index,
+ const Span<float> accumulated_lengths,
+ const float sample_length,
+ const bool cyclic,
+ const int resolution,
+ const int num_curve_points)
{
- return src_type != CURVE_TYPE_POLY && dst_type == CURVE_TYPE_POLY;
+ if (bke::curves::bezier::has_vector_handles(
+ num_curve_points,
+ src_curves.evaluated_points_for_curve(curve_index).size(),
+ cyclic,
+ resolution)) {
+ const Span<int> bezier_offsets = src_curves.bezier_evaluated_offsets_for_curve(curve_index);
+ return lookup_point_bezier(
+ bezier_offsets, accumulated_lengths, sample_length, cyclic, num_curve_points);
+ }
+ else {
+ return lookup_point_uniform_spacing(
+ accumulated_lengths, sample_length, cyclic, resolution, num_curve_points);
+ }
}
-/** \} */
-
-/* -------------------------------------------------------------------- */
-/** \name Specialized Curve Constructors
- * \{ */
-
-static void compute_trim_result_offsets(const bke::CurvesGeometry &src_curves,
- const IndexMask selection,
- const IndexMask inverse_selection,
- const Span<bke::curves::CurvePoint> start_points,
- const Span<bke::curves::CurvePoint> end_points,
- const VArray<int8_t> dst_curve_types,
- MutableSpan<int> dst_curve_offsets,
- Vector<int64_t> &r_curve_indices,
- Vector<int64_t> &r_point_curve_indices)
+static bke::curves::CurvePoint lookup_curve_point(const bke::CurvesGeometry &src_curves,
+ const CurveType curve_type,
+ const int64_t curve_index,
+ const Span<float> accumulated_lengths,
+ const float sample_length,
+ const bool cyclic,
+ const int resolution,
+ const int num_curve_points)
{
- BLI_assert(r_curve_indices.size() == 0);
- BLI_assert(r_point_curve_indices.size() == 0);
- const VArray<bool> cyclic = src_curves.cyclic();
- const VArray<int8_t> curve_types = src_curves.curve_types();
- r_curve_indices.reserve(selection.size());
-
- for (const int64_t curve_i : selection) {
-
- int64_t src_point_count;
-
- if (copy_as_evaluated_curve(curve_types[curve_i], dst_curve_types[curve_i])) {
- src_point_count = src_curves.evaluated_points_for_curve(curve_i).size();
- }
- else {
- src_point_count = int64_t(src_curves.points_num_for_curve(curve_i));
- }
- BLI_assert(src_point_count > 0);
+ if (num_curve_points == 1) {
+ return {{0, 0}, 0.0f};
+ }
- if (start_points[curve_i] == end_points[curve_i]) {
- dst_curve_offsets[curve_i] = 1;
- r_point_curve_indices.append(curve_i);
- }
- else {
- const bke::curves::IndexRangeCyclic point_range = get_range_between_endpoints(
- start_points[curve_i], end_points[curve_i], {0, src_point_count});
- const int count = point_range.size() + !start_points[curve_i].is_controlpoint() +
- !end_points[curve_i].is_controlpoint();
- dst_curve_offsets[curve_i] = count;
- r_curve_indices.append(curve_i);
- }
- BLI_assert(dst_curve_offsets[curve_i] > 0);
+ if (curve_type == CURVE_TYPE_CATMULL_ROM) {
+ return lookup_point_uniform_spacing(
+ accumulated_lengths, sample_length, cyclic, resolution, num_curve_points);
+ }
+ else if (curve_type == CURVE_TYPE_BEZIER) {
+ return lookup_point_bezier(src_curves,
+ curve_index,
+ accumulated_lengths,
+ sample_length,
+ cyclic,
+ resolution,
+ num_curve_points);
+ }
+ else if (curve_type == CURVE_TYPE_POLY) {
+ return lookup_point_polygonal(accumulated_lengths, sample_length, cyclic, num_curve_points);
+ }
+ else {
+ /* Handle evaluated curve. */
+ BLI_assert(resolution > 0);
+ return lookup_point_polygonal(accumulated_lengths,
+ sample_length,
+ cyclic,
+ src_curves.evaluated_points_for_curve(curve_index).size());
}
- threading::parallel_for(
- inverse_selection.index_range(), 4096, [&](const IndexRange selection_range) {
- for (const int64_t curve_i : inverse_selection.slice(selection_range)) {
- dst_curve_offsets[curve_i] = src_curves.points_num_for_curve(curve_i);
- }
- });
- bke::curves::accumulate_counts_to_offsets(dst_curve_offsets);
}
/** \} */
@@ -367,41 +188,42 @@ static void compute_trim_result_offsets(const bke::CurvesGeometry &src_curves,
static void fill_bezier_data(bke::CurvesGeometry &dst_curves, const IndexMask selection)
{
- if (dst_curves.has_curve_with_type(CURVE_TYPE_BEZIER)) {
- MutableSpan<float3> handle_positions_left = dst_curves.handle_positions_left_for_write();
- MutableSpan<float3> handle_positions_right = dst_curves.handle_positions_right_for_write();
- MutableSpan<int8_t> handle_types_left = dst_curves.handle_types_left_for_write();
- MutableSpan<int8_t> handle_types_right = dst_curves.handle_types_right_for_write();
-
- threading::parallel_for(selection.index_range(), 4096, [&](const IndexRange range) {
- for (const int64_t curve_i : selection.slice(range)) {
- const IndexRange points = dst_curves.points_for_curve(curve_i);
- handle_types_right.slice(points).fill(int8_t(BEZIER_HANDLE_FREE));
- handle_types_left.slice(points).fill(int8_t(BEZIER_HANDLE_FREE));
- handle_positions_left.slice(points).fill({0.0f, 0.0f, 0.0f});
- handle_positions_right.slice(points).fill({0.0f, 0.0f, 0.0f});
- }
- });
+ if (!dst_curves.has_curve_with_type(CURVE_TYPE_BEZIER)) {
+ return;
}
+ MutableSpan<float3> handle_positions_left = dst_curves.handle_positions_left_for_write();
+ MutableSpan<float3> handle_positions_right = dst_curves.handle_positions_right_for_write();
+ MutableSpan<int8_t> handle_types_left = dst_curves.handle_types_left_for_write();
+ MutableSpan<int8_t> handle_types_right = dst_curves.handle_types_right_for_write();
+
+ threading::parallel_for(selection.index_range(), 4096, [&](const IndexRange range) {
+ for (const int64_t curve_i : selection.slice(range)) {
+ const IndexRange points = dst_curves.points_for_curve(curve_i);
+ handle_types_right.slice(points).fill(int8_t(BEZIER_HANDLE_FREE));
+ handle_types_left.slice(points).fill(int8_t(BEZIER_HANDLE_FREE));
+ handle_positions_left.slice(points).fill({0.0f, 0.0f, 0.0f});
+ handle_positions_right.slice(points).fill({0.0f, 0.0f, 0.0f});
+ }
+ });
}
static void fill_nurbs_data(bke::CurvesGeometry &dst_curves, const IndexMask selection)
{
- if (dst_curves.has_curve_with_type(CURVE_TYPE_NURBS)) {
- bke::curves::fill_points(dst_curves, selection, 0.0f, dst_curves.nurbs_weights_for_write());
+ if (!dst_curves.has_curve_with_type(CURVE_TYPE_NURBS)) {
+ return;
}
+ bke::curves::fill_points(dst_curves, selection, 0.0f, dst_curves.nurbs_weights_for_write());
}
template<typename T>
static int64_t copy_point_data_between_endpoints(const Span<T> src_data,
MutableSpan<T> dst_data,
const bke::curves::IndexRangeCyclic src_range,
- const int64_t src_index,
int64_t dst_index)
{
int64_t increment;
if (src_range.cycles()) {
increment = src_range.size_before_loop();
- dst_data.slice(dst_index, increment).copy_from(src_data.slice(src_index, increment));
+ dst_data.slice(dst_index, increment).copy_from(src_data.slice(src_range.first(), increment));
dst_index += increment;
increment = src_range.size_after_loop();
@@ -411,7 +233,7 @@ static int64_t copy_point_data_between_endpoints(const Span<T> src_data,
}
else {
increment = src_range.one_after_last() - src_range.first();
- dst_data.slice(dst_index, increment).copy_from(src_data.slice(src_index, increment));
+ dst_data.slice(dst_index, increment).copy_from(src_data.slice(src_range.first(), increment));
dst_index += increment;
}
return dst_index;
@@ -466,82 +288,6 @@ static bke::curves::bezier::Insertion knot_insert_bezier(
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Sample Single Point
- * \{ */
-
-template<typename T>
-static void sample_linear(const Span<T> src_data,
- MutableSpan<T> dst_data,
- const IndexRange dst_range,
- const bke::curves::CurvePoint sample_point)
-{
- BLI_assert(dst_range.size() == 1);
- if (sample_point.is_controlpoint()) {
- /* Resolves cases where the source curve consist of a single control point. */
- const int index = sample_point.parameter == 1.0 ? sample_point.next_index : sample_point.index;
- dst_data[dst_range.first()] = src_data[index];
- }
- else {
- dst_data[dst_range.first()] = attribute_math::mix2(
- sample_point.parameter, src_data[sample_point.index], src_data[sample_point.next_index]);
- }
-}
-
-template<typename T>
-static void sample_catmull_rom(const Span<T> src_data,
- MutableSpan<T> dst_data,
- const IndexRange dst_range,
- const bke::curves::CurvePoint sample_point,
- const bool src_cyclic)
-{
- BLI_assert(dst_range.size() == 1);
- if (sample_point.is_controlpoint()) {
- /* Resolves cases where the source curve consist of a single control point. */
- const int index = sample_point.parameter == 1.0 ? sample_point.next_index : sample_point.index;
- dst_data[dst_range.first()] = src_data[index];
- }
- else {
- dst_data[dst_range.first()] = interpolate_catmull_rom(src_data, sample_point, src_cyclic);
- }
-}
-
-static void sample_bezier(const Span<float3> src_positions,
- const Span<float3> src_handles_l,
- const Span<float3> src_handles_r,
- const Span<int8_t> src_types_l,
- const Span<int8_t> src_types_r,
- MutableSpan<float3> dst_positions,
- MutableSpan<float3> dst_handles_l,
- MutableSpan<float3> dst_handles_r,
- MutableSpan<int8_t> dst_types_l,
- MutableSpan<int8_t> dst_types_r,
- const IndexRange dst_range,
- const bke::curves::CurvePoint sample_point)
-{
- BLI_assert(dst_range.size() == 1);
- if (sample_point.is_controlpoint()) {
- /* Resolves cases where the source curve consist of a single control point. */
- const int index = sample_point.parameter == 1.0 ? sample_point.next_index : sample_point.index;
- dst_positions[dst_range.first()] = src_positions[index];
- dst_handles_l[dst_range.first()] = src_handles_l[index];
- dst_handles_r[dst_range.first()] = src_handles_r[index];
- dst_types_l[dst_range.first()] = src_types_l[index];
- dst_types_r[dst_range.first()] = src_types_r[index];
- }
- else {
- bke::curves::bezier::Insertion insertion_point = knot_insert_bezier(
- src_positions, src_handles_l, src_handles_r, sample_point);
- dst_positions[dst_range.first()] = insertion_point.position;
- dst_handles_l[dst_range.first()] = insertion_point.left_handle;
- dst_handles_r[dst_range.first()] = insertion_point.right_handle;
- dst_types_l[dst_range.first()] = BEZIER_HANDLE_FREE;
- dst_types_r[dst_range.first()] = BEZIER_HANDLE_FREE;
- }
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Sample Curve Interval (Trim)
* \{ */
@@ -561,19 +307,18 @@ static void sample_bezier(const Span<float3> src_positions,
template<typename T, bool include_start_point = true>
static void sample_interval_linear(const Span<T> src_data,
MutableSpan<T> dst_data,
- const bke::curves::IndexRangeCyclic src_range,
+ bke::curves::IndexRangeCyclic src_range,
const IndexRange dst_range,
const bke::curves::CurvePoint start_point,
const bke::curves::CurvePoint end_point)
{
- int64_t src_index = src_range.first();
int64_t dst_index = dst_range.first();
if (start_point.is_controlpoint()) {
/* 'start_point' is included in the copy iteration. */
if constexpr (!include_start_point) {
/* Skip first. */
- ++src_index;
+ src_range = src_range.drop_front();
}
}
else if constexpr (!include_start_point) {
@@ -586,8 +331,11 @@ static void sample_interval_linear(const Span<T> src_data,
++dst_index;
}
- dst_index = copy_point_data_between_endpoints(
- src_data, dst_data, src_range, src_index, dst_index);
+ dst_index = copy_point_data_between_endpoints(src_data, dst_data, src_range, dst_index);
+ if (dst_range.size() == 1) {
+ BLI_assert(dst_index == dst_range.one_after_last());
+ return;
+ }
/* Handle last case */
if (end_point.is_controlpoint()) {
@@ -603,27 +351,18 @@ static void sample_interval_linear(const Span<T> src_data,
BLI_assert(dst_index == dst_range.one_after_last());
}
-template<typename T, bool include_start_point = true>
+template<typename T>
static void sample_interval_catmull_rom(const Span<T> src_data,
MutableSpan<T> dst_data,
- const bke::curves::IndexRangeCyclic src_range,
+ bke::curves::IndexRangeCyclic src_range,
const IndexRange dst_range,
const bke::curves::CurvePoint start_point,
const bke::curves::CurvePoint end_point,
const bool src_cyclic)
{
- int64_t src_index = src_range.first();
int64_t dst_index = dst_range.first();
if (start_point.is_controlpoint()) {
- /* 'start_point' is included in the copy iteration. */
- if constexpr (!include_start_point) {
- /* Skip first. */
- ++src_index;
- }
- }
- else if constexpr (!include_start_point) {
- /* Do nothing (excluded). */
}
else {
/* General case, sample 'start_point' */
@@ -631,8 +370,11 @@ static void sample_interval_catmull_rom(const Span<T> src_data,
++dst_index;
}
- dst_index = copy_point_data_between_endpoints(
- src_data, dst_data, src_range, src_index, dst_index);
+ dst_index = copy_point_data_between_endpoints(src_data, dst_data, src_range, dst_index);
+ if (dst_range.size() == 1) {
+ BLI_assert(dst_index == dst_range.one_after_last());
+ return;
+ }
/* Handle last case */
if (end_point.is_controlpoint()) {
@@ -658,20 +400,19 @@ static void sample_interval_bezier(const Span<float3> src_positions,
MutableSpan<float3> dst_handles_r,
MutableSpan<int8_t> dst_types_l,
MutableSpan<int8_t> dst_types_r,
- const bke::curves::IndexRangeCyclic src_range,
+ bke::curves::IndexRangeCyclic src_range,
const IndexRange dst_range,
const bke::curves::CurvePoint start_point,
const bke::curves::CurvePoint end_point)
{
bke::curves::bezier::Insertion start_point_insert;
- int64_t src_index = src_range.first();
int64_t dst_index = dst_range.first();
bool start_point_trimmed = false;
if (start_point.is_controlpoint()) {
/* The 'start_point' control point is included in the copy iteration. */
if constexpr (!include_start_point) {
- ++src_index; /* Skip first! */
+ src_range = src_range.drop_front();
}
}
else if constexpr (!include_start_point) {
@@ -696,7 +437,7 @@ static void sample_interval_bezier(const Span<float3> src_positions,
src_range.one_after_last() - src_range.first();
const IndexRange dst_range_to_end(dst_index, increment);
- const IndexRange src_range_to_end(src_index, increment);
+ const IndexRange src_range_to_end(src_range.first(), increment);
dst_positions.slice(dst_range_to_end).copy_from(src_positions.slice(src_range_to_end));
dst_handles_l.slice(dst_range_to_end).copy_from(src_handles_l.slice(src_range_to_end));
dst_handles_r.slice(dst_range_to_end).copy_from(src_handles_r.slice(src_range_to_end));
@@ -704,6 +445,11 @@ static void sample_interval_bezier(const Span<float3> src_positions,
dst_types_r.slice(dst_range_to_end).copy_from(src_types_r.slice(src_range_to_end));
dst_index += increment;
+ if (dst_range.size() == 1) {
+ BLI_assert(dst_index == dst_range.one_after_last());
+ return;
+ }
+
increment = src_range.size_after_loop();
if (src_range.cycles() && increment > 0) {
const IndexRange dst_range_looped(dst_index, increment);
@@ -769,174 +515,6 @@ static void sample_interval_bezier(const Span<float3> src_positions,
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Convert to Point Curves
- * \{ */
-
-static void convert_point_polygonal_curves(
- const bke::CurvesGeometry &src_curves,
- bke::CurvesGeometry &dst_curves,
- const IndexMask selection,
- const Span<bke::curves::CurvePoint> sample_points,
- MutableSpan<bke::AttributeTransferData> transfer_attributes)
-{
- const Span<float3> src_positions = src_curves.positions();
- MutableSpan<float3> dst_positions = dst_curves.positions_for_write();
-
- threading::parallel_for(selection.index_range(), 4096, [&](const IndexRange range) {
- for (const int64_t curve_i : selection.slice(range)) {
- const IndexRange src_points = src_curves.points_for_curve(curve_i);
- const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
-
- sample_linear<float3>(
- src_positions.slice(src_points), dst_positions, dst_points, sample_points[curve_i]);
-
- for (bke::AttributeTransferData &attribute : transfer_attributes) {
- attribute_math::convert_to_static_type(attribute.meta_data.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- sample_linear<T>(attribute.src.template typed<T>().slice(src_points),
- attribute.dst.span.typed<T>(),
- dst_curves.points_for_curve(curve_i),
- sample_points[curve_i]);
- });
- }
- }
- });
-
- fill_bezier_data(dst_curves, selection);
- fill_nurbs_data(dst_curves, selection);
-}
-
-static void convert_point_catmull_curves(
- const bke::CurvesGeometry &src_curves,
- bke::CurvesGeometry &dst_curves,
- const IndexMask selection,
- const Span<bke::curves::CurvePoint> sample_points,
- MutableSpan<bke::AttributeTransferData> transfer_attributes)
-{
- const Span<float3> src_positions = src_curves.positions();
- const VArray<bool> src_cyclic = src_curves.cyclic();
-
- MutableSpan<float3> dst_positions = dst_curves.positions_for_write();
-
- threading::parallel_for(selection.index_range(), 4096, [&](const IndexRange range) {
- for (const int64_t curve_i : selection.slice(range)) {
- const IndexRange src_points = src_curves.points_for_curve(curve_i);
- const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
-
- sample_catmull_rom<float3>(src_positions.slice(src_points),
- dst_positions,
- dst_points,
- sample_points[curve_i],
- src_cyclic[curve_i]);
- for (bke::AttributeTransferData &attribute : transfer_attributes) {
- attribute_math::convert_to_static_type(attribute.meta_data.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- sample_catmull_rom<T>(attribute.src.template typed<T>().slice(src_points),
- attribute.dst.span.typed<T>(),
- dst_points,
- sample_points[curve_i],
- src_cyclic[curve_i]);
- });
- }
- }
- });
- fill_bezier_data(dst_curves, selection);
- fill_nurbs_data(dst_curves, selection);
-}
-
-static void convert_point_bezier_curves(
- const bke::CurvesGeometry &src_curves,
- bke::CurvesGeometry &dst_curves,
- const IndexMask selection,
- const Span<bke::curves::CurvePoint> sample_points,
- MutableSpan<bke::AttributeTransferData> transfer_attributes)
-{
- const Span<float3> src_positions = src_curves.positions();
- const VArraySpan<int8_t> src_types_l{src_curves.handle_types_left()};
- const VArraySpan<int8_t> src_types_r{src_curves.handle_types_right()};
- const Span<float3> src_handles_l = src_curves.handle_positions_left();
- const Span<float3> src_handles_r = src_curves.handle_positions_right();
-
- MutableSpan<float3> dst_positions = dst_curves.positions_for_write();
- MutableSpan<int8_t> dst_types_l = dst_curves.handle_types_left_for_write();
- MutableSpan<int8_t> dst_types_r = dst_curves.handle_types_right_for_write();
- MutableSpan<float3> dst_handles_l = dst_curves.handle_positions_left_for_write();
- MutableSpan<float3> dst_handles_r = dst_curves.handle_positions_right_for_write();
-
- threading::parallel_for(selection.index_range(), 4096, [&](const IndexRange range) {
- for (const int64_t curve_i : selection.slice(range)) {
- const IndexRange src_points = src_curves.points_for_curve(curve_i);
- const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
-
- sample_bezier(src_positions.slice(src_points),
- src_handles_l.slice(src_points),
- src_handles_r.slice(src_points),
- src_types_l.slice(src_points),
- src_types_r.slice(src_points),
- dst_positions,
- dst_handles_l,
- dst_handles_r,
- dst_types_l,
- dst_types_r,
- dst_points,
- sample_points[curve_i]);
-
- for (bke::AttributeTransferData &attribute : transfer_attributes) {
- attribute_math::convert_to_static_type(attribute.meta_data.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- sample_linear<T>(attribute.src.template typed<T>().slice(src_points),
- attribute.dst.span.typed<T>(),
- dst_points,
- sample_points[curve_i]);
- });
- }
- }
- });
- fill_nurbs_data(dst_curves, selection);
-}
-
-static void convert_point_evaluated_curves(
- const bke::CurvesGeometry &src_curves,
- bke::CurvesGeometry &dst_curves,
- const IndexMask selection,
- const Span<bke::curves::CurvePoint> evaluated_sample_points,
- MutableSpan<bke::AttributeTransferData> transfer_attributes)
-{
- const Span<float3> src_eval_positions = src_curves.evaluated_positions();
- MutableSpan<float3> dst_positions = dst_curves.positions_for_write();
-
- threading::parallel_for(selection.index_range(), 4096, [&](const IndexRange range) {
- for (const int64_t curve_i : selection.slice(range)) {
- const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
- const IndexRange src_evaluated_points = src_curves.evaluated_points_for_curve(curve_i);
-
- sample_linear<float3>(src_eval_positions.slice(src_evaluated_points),
- dst_positions,
- dst_points,
- evaluated_sample_points[curve_i]);
-
- for (bke::AttributeTransferData &attribute : transfer_attributes) {
- attribute_math::convert_to_static_type(attribute.meta_data.data_type, [&](auto dummy) {
- using T = decltype(dummy);
- GArray evaluated_data(CPPType::get<T>(), src_evaluated_points.size());
- GMutableSpan evaluated_span = evaluated_data.as_mutable_span();
- src_curves.interpolate_to_evaluated(
- curve_i, attribute.src.slice(src_curves.points_for_curve(curve_i)), evaluated_span);
- sample_linear<T>(evaluated_span.typed<T>(),
- attribute.dst.span.typed<T>(),
- dst_points,
- evaluated_sample_points[curve_i]);
- });
- }
- }
- });
- fill_bezier_data(dst_curves, selection);
- fill_nurbs_data(dst_curves, selection);
-}
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Trim Curves
* \{ */
@@ -945,6 +523,7 @@ static void trim_attribute_linear(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const Span<bke::curves::CurvePoint> start_points,
const Span<bke::curves::CurvePoint> end_points,
+ const Span<bke::curves::IndexRangeCyclic> src_ranges,
MutableSpan<bke::AttributeTransferData> transfer_attributes)
{
for (bke::AttributeTransferData &attribute : transfer_attributes) {
@@ -955,11 +534,9 @@ static void trim_attribute_linear(const bke::CurvesGeometry &src_curves,
for (const int64_t curve_i : selection.slice(range)) {
const IndexRange src_points = src_curves.points_for_curve(curve_i);
- bke::curves::IndexRangeCyclic src_sample_range = get_range_between_endpoints(
- start_points[curve_i], end_points[curve_i], {0, src_points.size()});
sample_interval_linear<T>(attribute.src.template typed<T>().slice(src_points),
attribute.dst.span.typed<T>(),
- src_sample_range,
+ src_ranges[curve_i],
dst_curves.points_for_curve(curve_i),
start_points[curve_i],
end_points[curve_i]);
@@ -974,6 +551,7 @@ static void trim_polygonal_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const Span<bke::curves::CurvePoint> start_points,
const Span<bke::curves::CurvePoint> end_points,
+ const Span<bke::curves::IndexRangeCyclic> src_ranges,
MutableSpan<bke::AttributeTransferData> transfer_attributes)
{
const Span<float3> src_positions = src_curves.positions();
@@ -984,11 +562,9 @@ static void trim_polygonal_curves(const bke::CurvesGeometry &src_curves,
const IndexRange src_points = src_curves.points_for_curve(curve_i);
const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
- bke::curves::IndexRangeCyclic src_sample_range = get_range_between_endpoints(
- start_points[curve_i], end_points[curve_i], {0, src_points.size()});
sample_interval_linear<float3>(src_positions.slice(src_points),
dst_positions,
- src_sample_range,
+ src_ranges[curve_i],
dst_points,
start_points[curve_i],
end_points[curve_i]);
@@ -996,8 +572,13 @@ static void trim_polygonal_curves(const bke::CurvesGeometry &src_curves,
});
fill_bezier_data(dst_curves, selection);
fill_nurbs_data(dst_curves, selection);
- trim_attribute_linear(
- src_curves, dst_curves, selection, start_points, end_points, transfer_attributes);
+ trim_attribute_linear(src_curves,
+ dst_curves,
+ selection,
+ start_points,
+ end_points,
+ src_ranges,
+ transfer_attributes);
}
static void trim_catmull_rom_curves(const bke::CurvesGeometry &src_curves,
@@ -1005,6 +586,7 @@ static void trim_catmull_rom_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const Span<bke::curves::CurvePoint> start_points,
const Span<bke::curves::CurvePoint> end_points,
+ const Span<bke::curves::IndexRangeCyclic> src_ranges,
MutableSpan<bke::AttributeTransferData> transfer_attributes)
{
const Span<float3> src_positions = src_curves.positions();
@@ -1016,11 +598,9 @@ static void trim_catmull_rom_curves(const bke::CurvesGeometry &src_curves,
const IndexRange src_points = src_curves.points_for_curve(curve_i);
const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
- bke::curves::IndexRangeCyclic src_sample_range = get_range_between_endpoints(
- start_points[curve_i], end_points[curve_i], {0, src_points.size()});
sample_interval_catmull_rom<float3>(src_positions.slice(src_points),
dst_positions,
- src_sample_range,
+ src_ranges[curve_i],
dst_points,
start_points[curve_i],
end_points[curve_i],
@@ -1039,11 +619,9 @@ static void trim_catmull_rom_curves(const bke::CurvesGeometry &src_curves,
const IndexRange src_points = src_curves.points_for_curve(curve_i);
const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
- bke::curves::IndexRangeCyclic src_sample_range = get_range_between_endpoints(
- start_points[curve_i], end_points[curve_i], {0, src_points.size()});
sample_interval_catmull_rom<T>(attribute.src.template typed<T>().slice(src_points),
attribute.dst.span.typed<T>(),
- src_sample_range,
+ src_ranges[curve_i],
dst_points,
start_points[curve_i],
end_points[curve_i],
@@ -1059,6 +637,7 @@ static void trim_bezier_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const Span<bke::curves::CurvePoint> start_points,
const Span<bke::curves::CurvePoint> end_points,
+ const Span<bke::curves::IndexRangeCyclic> src_ranges,
MutableSpan<bke::AttributeTransferData> transfer_attributes)
{
const Span<float3> src_positions = src_curves.positions();
@@ -1078,8 +657,6 @@ static void trim_bezier_curves(const bke::CurvesGeometry &src_curves,
const IndexRange src_points = src_curves.points_for_curve(curve_i);
const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
- bke::curves::IndexRangeCyclic src_sample_range = get_range_between_endpoints(
- start_points[curve_i], end_points[curve_i], {0, src_points.size()});
sample_interval_bezier(src_positions.slice(src_points),
src_handles_l.slice(src_points),
src_handles_r.slice(src_points),
@@ -1090,15 +667,20 @@ static void trim_bezier_curves(const bke::CurvesGeometry &src_curves,
dst_handles_r,
dst_types_l,
dst_types_r,
- src_sample_range,
+ src_ranges[curve_i],
dst_points,
start_points[curve_i],
end_points[curve_i]);
}
});
fill_nurbs_data(dst_curves, selection);
- trim_attribute_linear(
- src_curves, dst_curves, selection, start_points, end_points, transfer_attributes);
+ trim_attribute_linear(src_curves,
+ dst_curves,
+ selection,
+ start_points,
+ end_points,
+ src_ranges,
+ transfer_attributes);
}
static void trim_evaluated_curves(const bke::CurvesGeometry &src_curves,
@@ -1106,6 +688,7 @@ static void trim_evaluated_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
const Span<bke::curves::CurvePoint> start_points,
const Span<bke::curves::CurvePoint> end_points,
+ const Span<bke::curves::IndexRangeCyclic> src_ranges,
MutableSpan<bke::AttributeTransferData> transfer_attributes)
{
const Span<float3> src_eval_positions = src_curves.evaluated_positions();
@@ -1116,11 +699,9 @@ static void trim_evaluated_curves(const bke::CurvesGeometry &src_curves,
const IndexRange dst_points = dst_curves.points_for_curve(curve_i);
const IndexRange src_evaluated_points = src_curves.evaluated_points_for_curve(curve_i);
- bke::curves::IndexRangeCyclic src_sample_range = get_range_between_endpoints(
- start_points[curve_i], end_points[curve_i], {0, src_evaluated_points.size()});
sample_interval_linear<float3>(src_eval_positions.slice(src_evaluated_points),
dst_positions,
- src_sample_range,
+ src_ranges[curve_i],
dst_points,
start_points[curve_i],
end_points[curve_i]);
@@ -1141,11 +722,9 @@ static void trim_evaluated_curves(const bke::CurvesGeometry &src_curves,
GMutableSpan evaluated_span = evaluated_data.as_mutable_span();
src_curves.interpolate_to_evaluated(
curve_i, attribute.src.slice(src_curves.points_for_curve(curve_i)), evaluated_span);
- bke::curves::IndexRangeCyclic src_sample_range = get_range_between_endpoints(
- start_points[curve_i], end_points[curve_i], {0, src_evaluated_points.size()});
sample_interval_linear<T>(evaluated_span.typed<T>(),
attribute.dst.span.typed<T>(),
- src_sample_range,
+ src_ranges[curve_i],
dst_curves.points_for_curve(curve_i),
start_points[curve_i],
end_points[curve_i]);
@@ -1155,52 +734,204 @@ static void trim_evaluated_curves(const bke::CurvesGeometry &src_curves,
}
}
+/* -------------------------------------------------------------------- */
+/** \name Compute trim parameters
+ * \{ */
+
+static float trim_sample_length(const Span<float> accumulated_lengths,
+ const float sample_length,
+ const GeometryNodeCurveSampleMode mode)
+{
+ float length = mode == GEO_NODE_CURVE_SAMPLE_FACTOR ?
+ sample_length * accumulated_lengths.last() :
+ sample_length;
+ return std::clamp(length, 0.0f, accumulated_lengths.last());
+}
+
+/**
+ * Compute the selection for the given curve type. Tracks indices for splitting the selection if
+ * there are curves reduced to a single point.
+ */
+static void compute_curve_trim_parameters(const bke::CurvesGeometry &curves,
+ const IndexMask selection,
+ const VArray<float> &starts,
+ const VArray<float> &ends,
+ const GeometryNodeCurveSampleMode mode,
+ MutableSpan<int> dst_curve_size,
+ MutableSpan<int8_t> dst_curve_types,
+ MutableSpan<bke::curves::CurvePoint> start_points,
+ MutableSpan<bke::curves::CurvePoint> end_points,
+ MutableSpan<bke::curves::IndexRangeCyclic> src_ranges)
+{
+ const VArray<bool> src_cyclic = curves.cyclic();
+ const VArray<int> resolution = curves.resolution();
+ const VArray<int8_t> curve_types = curves.curve_types();
+
+ /* Compute. */
+ threading::parallel_for(selection.index_range(), 128, [&](const IndexRange selection_range) {
+ for (const int64_t curve_i : selection.slice(selection_range)) {
+ CurveType curve_type = CurveType(curve_types[curve_i]);
+
+ int point_count;
+ if (curve_type == CURVE_TYPE_NURBS) {
+ dst_curve_types[curve_i] = CURVE_TYPE_POLY;
+ point_count = curves.evaluated_points_for_curve(curve_i).size();
+ }
+ else {
+ dst_curve_types[curve_i] = curve_type;
+ point_count = curves.points_num_for_curve(curve_i);
+ }
+ if (point_count == 1) {
+ /* Single point. */
+ dst_curve_size[curve_i] = 1;
+ src_ranges[curve_i] = bke::curves::IndexRangeCyclic(0, 0, 1, 1);
+ start_points[curve_i] = {0, 0, 0.0f};
+ end_points[curve_i] = {0, 0, 0.0f};
+ continue;
+ }
+
+ const bool cyclic = src_cyclic[curve_i];
+ const Span<float> lengths = curves.evaluated_lengths_for_curve(curve_i, cyclic);
+ BLI_assert(lengths.size() > 0);
+
+ const float start_length = trim_sample_length(lengths, starts[curve_i], mode);
+ float end_length;
+
+ bool equal_sample_point;
+ if (cyclic) {
+ end_length = trim_sample_length(lengths, ends[curve_i], mode);
+ const float cyclic_start = start_length == lengths.last() ? 0.0f : start_length;
+ const float cyclic_end = end_length == lengths.last() ? 0.0f : end_length;
+ equal_sample_point = cyclic_start == cyclic_end;
+ }
+ else {
+ end_length = ends[curve_i] <= starts[curve_i] ?
+ start_length :
+ trim_sample_length(lengths, ends[curve_i], mode);
+ equal_sample_point = start_length == end_length;
+ }
+
+ start_points[curve_i] = lookup_curve_point(curves,
+ curve_type,
+ curve_i,
+ lengths,
+ start_length,
+ cyclic,
+ resolution[curve_i],
+ point_count);
+ if (equal_sample_point) {
+ end_points[curve_i] = start_points[curve_i];
+ if (end_length <= start_length) {
+ /* Single point. */
+ dst_curve_size[curve_i] = 1;
+ src_ranges[curve_i] = bke::curves::IndexRangeCyclic::get_range_from_size(
+ start_points[curve_i].index,
+ start_points[curve_i].is_controlpoint(), /* Only iterate if control point. */
+ point_count);
+ }
+ else {
+ /* Split. */
+ src_ranges[curve_i] = bke::curves::IndexRangeCyclic::get_range_between_endpoints(
+ start_points[curve_i], end_points[curve_i], point_count)
+ .push_loop();
+ const int count = 1 + !start_points[curve_i].is_controlpoint() + point_count;
+ BLI_assert(count > 1);
+ dst_curve_size[curve_i] = count;
+ }
+ }
+ else {
+ /* General case. */
+ end_points[curve_i] = lookup_curve_point(curves,
+ curve_type,
+ curve_i,
+ lengths,
+ end_length,
+ cyclic,
+ resolution[curve_i],
+ point_count);
+
+ src_ranges[curve_i] = bke::curves::IndexRangeCyclic::get_range_between_endpoints(
+ start_points[curve_i], end_points[curve_i], point_count);
+ const int count = src_ranges[curve_i].size() + !start_points[curve_i].is_controlpoint() +
+ !end_points[curve_i].is_controlpoint();
+ BLI_assert(count > 1);
+ dst_curve_size[curve_i] = count;
+ }
+ BLI_assert(dst_curve_size[curve_i] > 0);
+ }
+ });
+}
+
+/** \} */
+
bke::CurvesGeometry trim_curves(const bke::CurvesGeometry &src_curves,
const IndexMask selection,
- const Span<bke::curves::CurvePoint> start_points,
- const Span<bke::curves::CurvePoint> end_points)
+ const VArray<float> &starts,
+ const VArray<float> &ends,
+ const GeometryNodeCurveSampleMode mode)
{
BLI_assert(selection.size() > 0);
- BLI_assert(selection.last() <= start_points.size());
- BLI_assert(start_points.size() == end_points.size());
+ BLI_assert(selection.last() <= src_curves.curves_num());
+ BLI_assert(starts.size() == src_curves.curves_num());
+ BLI_assert(starts.size() == ends.size());
+ src_curves.ensure_evaluated_lengths();
- src_curves.ensure_evaluated_offsets();
Vector<int64_t> inverse_selection_indices;
const IndexMask inverse_selection = selection.invert(src_curves.curves_range(),
inverse_selection_indices);
- /* Create trim curves. */
+ /* Create destination curves. */
bke::CurvesGeometry dst_curves(0, src_curves.curves_num());
- determine_copyable_curve_types(src_curves,
- dst_curves,
- selection,
- inverse_selection,
- (CurveTypeMask)(CURVE_TYPE_MASK_CATMULL_ROM |
- CURVE_TYPE_MASK_POLY | CURVE_TYPE_MASK_BEZIER));
-
- Vector<int64_t> curve_indices;
- Vector<int64_t> point_curve_indices;
- compute_trim_result_offsets(src_curves,
- selection,
- inverse_selection,
- start_points,
- end_points,
- dst_curves.curve_types(),
- dst_curves.offsets_for_write(),
- curve_indices,
- point_curve_indices);
- /* Finalize by updating the geometry container. */
+ MutableSpan<int> dst_curve_offsets = dst_curves.offsets_for_write();
+ MutableSpan<int8_t> dst_curve_types = dst_curves.curve_types_for_write();
+ Array<bke::curves::CurvePoint, 12> start_points(src_curves.curves_num());
+ Array<bke::curves::CurvePoint, 12> end_points(src_curves.curves_num());
+ Array<bke::curves::IndexRangeCyclic, 12> src_ranges(src_curves.curves_num());
+
+ if (src_curves.has_curve_with_type({CURVE_TYPE_BEZIER, CURVE_TYPE_NURBS})) {
+ src_curves.ensure_evaluated_offsets();
+ if (src_curves.has_curve_with_type(CURVE_TYPE_NURBS)) {
+ src_curves.evaluated_positions();
+ }
+ }
+
+ /* Compute destination curves. */
+ compute_curve_trim_parameters(src_curves,
+ selection,
+ starts,
+ ends,
+ mode,
+ dst_curve_offsets,
+ dst_curve_types,
+ start_points,
+ end_points,
+ src_ranges);
+
+ /* Transfer copied curves parameters. */
+ const VArray<int8_t> src_curve_types = src_curves.curve_types();
+ threading::parallel_for(
+ inverse_selection.index_range(), 4096, [&](const IndexRange selection_range) {
+ for (const int64_t curve_i : inverse_selection.slice(selection_range)) {
+ dst_curve_offsets[curve_i] = src_curves.points_num_for_curve(curve_i);
+ dst_curve_types[curve_i] = src_curve_types[curve_i];
+ }
+ });
+ /* Finalize and update the geometry container. */
+ bke::curves::accumulate_counts_to_offsets(dst_curve_offsets);
dst_curves.resize(dst_curves.offsets().last(), dst_curves.curves_num());
dst_curves.update_curve_types();
/* Populate curve domain. */
const bke::AttributeAccessor src_attributes = src_curves.attributes();
bke::MutableAttributeAccessor dst_attributes = dst_curves.attributes_for_write();
- bke::copy_attribute_domain(src_attributes,
- dst_attributes,
- selection,
- ATTR_DOMAIN_CURVE,
- {"cyclic", "curve_type", "nurbs_order", "knots_mode"});
+ Set<std::string> transfer_curve_skip = {"cyclic", "curve_type", "nurbs_order", "knots_mode"};
+ if (dst_curves.has_curve_with_type(CURVE_TYPE_NURBS)) {
+ /* If a NURBS curve is copied keep */
+ transfer_curve_skip.remove("nurbs_order");
+ transfer_curve_skip.remove("knots_mode");
+ }
+ bke::copy_attribute_domain(
+ src_attributes, dst_attributes, selection, ATTR_DOMAIN_CURVE, transfer_curve_skip);
/* Fetch custom point domain attributes for transfer (copy). */
Vector<bke::AttributeTransferData> transfer_attributes = bke::retrieve_attributes_for_transfer(
@@ -1214,61 +945,55 @@ bke::CurvesGeometry trim_curves(const bke::CurvesGeometry &src_curves,
"handle_type_right",
"nurbs_weight"});
- auto trim_catmull = [&](IndexMask selection) {
- trim_catmull_rom_curves(
- src_curves, dst_curves, selection, start_points, end_points, transfer_attributes);
+ auto trim_catmull = [&](const IndexMask selection) {
+ trim_catmull_rom_curves(src_curves,
+ dst_curves,
+ selection,
+ start_points,
+ end_points,
+ src_ranges,
+ transfer_attributes);
};
- auto trim_poly = [&](IndexMask selection) {
- trim_polygonal_curves(
- src_curves, dst_curves, selection, start_points, end_points, transfer_attributes);
+ auto trim_poly = [&](const IndexMask selection) {
+ trim_polygonal_curves(src_curves,
+ dst_curves,
+ selection,
+ start_points,
+ end_points,
+ src_ranges,
+ transfer_attributes);
};
- auto trim_bezier = [&](IndexMask selection) {
- trim_bezier_curves(
- src_curves, dst_curves, selection, start_points, end_points, transfer_attributes);
+ auto trim_bezier = [&](const IndexMask selection) {
+ trim_bezier_curves(src_curves,
+ dst_curves,
+ selection,
+ start_points,
+ end_points,
+ src_ranges,
+ transfer_attributes);
};
- auto trim_evaluated = [&](IndexMask selection) {
+ auto trim_evaluated = [&](const IndexMask selection) {
/* Ensure evaluated positions are available. */
src_curves.ensure_evaluated_offsets();
src_curves.evaluated_positions();
- trim_evaluated_curves(
- src_curves, dst_curves, selection, start_points, end_points, transfer_attributes);
- };
-
- auto single_point_catmull = [&](IndexMask selection) {
- convert_point_catmull_curves(
- src_curves, dst_curves, selection, start_points, transfer_attributes);
- };
- auto single_point_poly = [&](IndexMask selection) {
- convert_point_polygonal_curves(
- src_curves, dst_curves, selection, start_points, transfer_attributes);
- };
- auto single_point_bezier = [&](IndexMask selection) {
- convert_point_bezier_curves(
- src_curves, dst_curves, selection, start_points, transfer_attributes);
- };
- auto single_point_evaluated = [&](IndexMask selection) {
- convert_point_evaluated_curves(
- src_curves, dst_curves, selection, start_points, transfer_attributes);
+ trim_evaluated_curves(src_curves,
+ dst_curves,
+ selection,
+ start_points,
+ end_points,
+ src_ranges,
+ transfer_attributes);
};
/* Populate point domain. */
bke::curves::foreach_curve_by_type(src_curves.curve_types(),
src_curves.curve_type_counts(),
- curve_indices.as_span(),
+ selection,
trim_catmull,
trim_poly,
trim_bezier,
trim_evaluated);
- if (point_curve_indices.size()) {
- bke::curves::foreach_curve_by_type(src_curves.curve_types(),
- src_curves.curve_type_counts(),
- point_curve_indices.as_span(),
- single_point_catmull,
- single_point_poly,
- single_point_bezier,
- single_point_evaluated);
- }
/* Cleanup/close context */
for (bke::AttributeTransferData &attribute : transfer_attributes) {
attribute.dst.finish();
@@ -1276,14 +1001,21 @@ bke::CurvesGeometry trim_curves(const bke::CurvesGeometry &src_curves,
/* Copy unselected */
if (!inverse_selection.is_empty()) {
+ transfer_curve_skip.remove("cyclic");
bke::copy_attribute_domain(
- src_attributes, dst_attributes, inverse_selection, ATTR_DOMAIN_CURVE);
+ src_attributes, dst_attributes, inverse_selection, ATTR_DOMAIN_CURVE, transfer_curve_skip);
/* Trim curves are no longer cyclic. If all curves are trimmed, this will be set implicitly. */
dst_curves.cyclic_for_write().fill_indices(selection, false);
+ Set<std::string> copy_point_skip;
+ if (!dst_curves.has_curve_with_type(CURVE_TYPE_NURBS) &&
+ src_curves.has_curve_with_type(CURVE_TYPE_NURBS)) {
+ copy_point_skip.add("nurbs_weight");
+ }
+
/* Copy point domain. */
for (auto &attribute : bke::retrieve_attributes_for_transfer(
- src_attributes, dst_attributes, ATTR_DOMAIN_MASK_POINT)) {
+ src_attributes, dst_attributes, ATTR_DOMAIN_MASK_POINT, copy_point_skip)) {
bke::curves::copy_point_data(
src_curves, dst_curves, inverse_selection, attribute.src, attribute.dst.span);
attribute.dst.finish();
diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c
index f3d6d19cb8d..4320f870d64 100644
--- a/source/blender/imbuf/intern/jp2.c
+++ b/source/blender/imbuf/intern/jp2.c
@@ -125,7 +125,7 @@ struct BufInfo {
static void opj_read_from_buffer_free(void *UNUSED(p_user_data))
{
- /* nop */
+ /* NOP. */
}
static OPJ_SIZE_T opj_read_from_buffer(void *p_buffer, OPJ_SIZE_T p_nb_bytes, void *p_user_data)
diff --git a/source/blender/imbuf/intern/openexr/openexr_api.cpp b/source/blender/imbuf/intern/openexr/openexr_api.cpp
index d4a89c9e1c9..d2bdb5041c5 100644
--- a/source/blender/imbuf/intern/openexr/openexr_api.cpp
+++ b/source/blender/imbuf/intern/openexr/openexr_api.cpp
@@ -811,7 +811,7 @@ static void imb_exr_get_views(MultiPartInputFile &file, StringVector &views)
}
}
-/* Multilayer Blender files have the view name in all the passes (even the default view one) */
+/* Multi-layer Blender files have the view name in all the passes (even the default view one). */
static void imb_exr_insert_view_name(char *name_full, const char *passname, const char *viewname)
{
BLI_assert(!ELEM(name_full, passname, viewname));
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/nodes/geometry/nodes/node_geo_curve_trim.cc b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
index 3ec71877b7c..b0c2f3117fa 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_curve_trim.cc
@@ -19,6 +19,7 @@ NODE_STORAGE_FUNCS(NodeGeometryCurveTrim)
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Geometry>(N_("Curve")).supported_type(GEO_COMPONENT_TYPE_CURVE);
+ b.add_input<decl::Bool>(N_("Selection")).default_value(true).hide_value().supports_field();
b.add_input<decl::Float>(N_("Start"))
.min(0.0f)
.max(1.0f)
@@ -64,7 +65,7 @@ static void node_update(bNodeTree *ntree, bNode *node)
const NodeGeometryCurveTrim &storage = node_storage(*node);
const GeometryNodeCurveSampleMode mode = (GeometryNodeCurveSampleMode)storage.mode;
- bNodeSocket *start_fac = static_cast<bNodeSocket *>(node->inputs.first)->next;
+ bNodeSocket *start_fac = static_cast<bNodeSocket *>(node->inputs.first)->next->next;
bNodeSocket *end_fac = start_fac->next;
bNodeSocket *start_len = end_fac->next;
bNodeSocket *end_len = start_len->next;
@@ -109,6 +110,7 @@ static void node_gather_link_searches(GatherLinkSearchOpParams &params)
static void geometry_set_curve_trim(GeometrySet &geometry_set,
const GeometryNodeCurveSampleMode mode,
+ Field<bool> &selection_field,
Field<float> &start_field,
Field<float> &end_field)
{
@@ -123,41 +125,21 @@ static void geometry_set_curve_trim(GeometrySet &geometry_set,
bke::CurvesFieldContext field_context{src_curves, ATTR_DOMAIN_CURVE};
fn::FieldEvaluator evaluator{field_context, src_curves.curves_num()};
+ evaluator.add(selection_field);
evaluator.add(start_field);
evaluator.add(end_field);
evaluator.evaluate();
- const VArray<float> starts = evaluator.get_evaluated<float>(0);
- const VArray<float> ends = evaluator.get_evaluated<float>(1);
-
- const VArray<bool> cyclic = src_curves.cyclic();
-
- /* If node length input is on form [0, 1] instead of [0, length]*/
- const bool normalized_length_lookup = mode == GEO_NODE_CURVE_SAMPLE_FACTOR;
-
- /* Stack start + end field. */
- Vector<float> length_factors(src_curves.curves_num() * 2);
- Vector<int64_t> lookup_indices(src_curves.curves_num() * 2);
- threading::parallel_for(src_curves.curves_range(), 512, [&](IndexRange curve_range) {
- for (const int64_t curve_i : curve_range) {
- const bool negative_trim = !cyclic[curve_i] && starts[curve_i] > ends[curve_i];
- length_factors[curve_i] = starts[curve_i];
- length_factors[curve_i + src_curves.curves_num()] = negative_trim ? starts[curve_i] :
- ends[curve_i];
- lookup_indices[curve_i] = curve_i;
- lookup_indices[curve_i + src_curves.curves_num()] = curve_i;
- }
- });
- /* Create curve trim lookup table. */
- Array<bke::curves::CurvePoint, 12> point_lookups = geometry::lookup_curve_points(
- src_curves, length_factors, lookup_indices, normalized_length_lookup);
+ const IndexMask selection = evaluator.get_evaluated_as_mask(0);
+ const VArray<float> starts = evaluator.get_evaluated<float>(1);
+ const VArray<float> ends = evaluator.get_evaluated<float>(2);
- bke::CurvesGeometry dst_curves = geometry::trim_curves(
- src_curves,
- src_curves.curves_range().as_span(),
- point_lookups.as_span().slice(0, src_curves.curves_num()),
- point_lookups.as_span().slice(src_curves.curves_num(), src_curves.curves_num()));
+ if (selection.is_empty()) {
+ return;
+ }
+ bke::CurvesGeometry dst_curves = geometry::trim_curves(
+ src_curves, selection, starts, ends, mode);
Curves *dst_curves_id = bke::curves_new_nomain(std::move(dst_curves));
bke::curves_copy_parameters(src_curves_id, *dst_curves_id);
geometry_set.replace_curves(dst_curves_id);
@@ -171,18 +153,19 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Curve");
GeometryComponentEditData::remember_deformed_curve_positions_if_necessary(geometry_set);
+ Field<bool> selection_field = params.extract_input<Field<bool>>("Selection");
if (mode == GEO_NODE_CURVE_SAMPLE_FACTOR) {
Field<float> start_field = params.extract_input<Field<float>>("Start");
Field<float> end_field = params.extract_input<Field<float>>("End");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
- geometry_set_curve_trim(geometry_set, mode, start_field, end_field);
+ geometry_set_curve_trim(geometry_set, mode, selection_field, start_field, end_field);
});
}
else if (mode == GEO_NODE_CURVE_SAMPLE_LENGTH) {
Field<float> start_field = params.extract_input<Field<float>>("Start_001");
Field<float> end_field = params.extract_input<Field<float>>("End_001");
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
- geometry_set_curve_trim(geometry_set, mode, start_field, end_field);
+ geometry_set_curve_trim(geometry_set, mode, selection_field, start_field, end_field);
});
}
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..3e3fe85ed39 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);
}