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:
authorJoseph Eagar <joeedh@gmail.com>2022-03-29 08:54:24 +0300
committerJoseph Eagar <joeedh@gmail.com>2022-03-29 08:54:24 +0300
commit176b331c43c5378b0a346b7c96b0934c9c5bf19f (patch)
tree546efd965d57bfa16945c2ef1ab664b2a3667471 /source/blender/blenkernel
parent2f3ace40240797100161a659a12d995e1480b91b (diff)
parent540bfbbb27966b4b8affeaa273a70beac9373b23 (diff)
Merge branch 'master' into temp-sculpt-colors
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_attribute_math.hh2
-rw-r--r--source/blender/blenkernel/BKE_curves.hh62
-rw-r--r--source/blender/blenkernel/BKE_customdata.h2
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h2
-rw-r--r--source/blender/blenkernel/BKE_gpencil_geom.h58
-rw-r--r--source/blender/blenkernel/BKE_image_partial_update.hh6
-rw-r--r--source/blender/blenkernel/BKE_image_save.h13
-rw-r--r--source/blender/blenkernel/BKE_layer.h32
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h2
-rw-r--r--source/blender/blenkernel/BKE_packedFile.h6
-rw-r--r--source/blender/blenkernel/BKE_scene.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt21
-rw-r--r--source/blender/blenkernel/intern/appdir.c12
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c2
-rw-r--r--source/blender/blenkernel/intern/collection.c6
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c50
-rw-r--r--source/blender/blenkernel/intern/curve.cc6
-rw-r--r--source/blender/blenkernel/intern/curve_bezier.cc50
-rw-r--r--source/blender/blenkernel/intern/curve_catmull_rom.cc6
-rw-r--r--source/blender/blenkernel/intern/curve_eval.cc4
-rw-r--r--source/blender/blenkernel/intern/curve_nurbs.cc41
-rw-r--r--source/blender/blenkernel/intern/curves.cc10
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc176
-rw-r--r--source/blender/blenkernel/intern/curves_geometry_test.cc99
-rw-r--r--source/blender/blenkernel/intern/customdata.cc184
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c4
-rw-r--r--source/blender/blenkernel/intern/geometry_component_curves.cc4
-rw-r--r--source/blender/blenkernel/intern/geometry_component_mesh.cc67
-rw-r--r--source/blender/blenkernel/intern/gpencil_geom.cc467
-rw-r--r--source/blender/blenkernel/intern/image.cc328
-rw-r--r--source/blender/blenkernel/intern/image_format.cc38
-rw-r--r--source/blender/blenkernel/intern/image_partial_update.cc2
-rw-r--r--source/blender/blenkernel/intern/image_save.cc16
-rw-r--r--source/blender/blenkernel/intern/image_test.cc186
-rw-r--r--source/blender/blenkernel/intern/mesh.cc2
-rw-r--r--source/blender/blenkernel/intern/mesh_convert.cc12
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.cc2
-rw-r--r--source/blender/blenkernel/intern/mesh_mapping.c8
-rw-r--r--source/blender/blenkernel/intern/mesh_normals.cc46
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.cc3
-rw-r--r--source/blender/blenkernel/intern/object.cc6
-rw-r--r--source/blender/blenkernel/intern/packedFile.c16
-rw-r--r--source/blender/blenkernel/intern/particle.c8
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c6
-rw-r--r--source/blender/blenkernel/intern/particle_system.c14
-rw-r--r--source/blender/blenkernel/intern/scene.cc (renamed from source/blender/blenkernel/intern/scene.c)515
-rw-r--r--source/blender/blenkernel/intern/studiolight.c14
-rw-r--r--source/blender/blenkernel/intern/subdiv.c2
49 files changed, 1635 insertions, 987 deletions
diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh
index 3075c0689e9..9efa64d1474 100644
--- a/source/blender/blenkernel/BKE_attribute_math.hh
+++ b/source/blender/blenkernel/BKE_attribute_math.hh
@@ -22,7 +22,7 @@ inline void convert_to_static_type(const CPPType &cpp_type, const Func &func)
[&](auto type_tag) {
using T = typename decltype(type_tag)::type;
if constexpr (std::is_same_v<T, void>) {
- /* It's expected that the given cpp type is one of the supported once. */
+ /* It's expected that the given cpp type is one of the supported ones. */
BLI_assert_unreachable();
}
else {
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index eb4f8f5d5c8..82f77d83bec 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -122,14 +122,14 @@ class CurvesGeometry : public ::CurvesGeometry {
* Accessors.
*/
- int points_size() const;
- int curves_size() const;
+ int points_num() const;
+ int curves_num() const;
IndexRange points_range() const;
IndexRange curves_range() const;
/**
* The index of the first point in every curve. The size of this span is one larger than the
- * number of curves. Consider using #range_for_curve rather than using the offsets directly.
+ * number of curves. Consider using #points_for_curve rather than using the offsets directly.
*/
Span<int> offsets() const;
MutableSpan<int> offsets();
@@ -137,8 +137,8 @@ class CurvesGeometry : public ::CurvesGeometry {
/**
* Access a range of indices of point data for a specific curve.
*/
- IndexRange range_for_curve(int index) const;
- IndexRange range_for_curves(IndexRange curves) const;
+ IndexRange points_for_curve(int index) const;
+ IndexRange points_for_curves(IndexRange curves) const;
/** The type (#CurveType) of each curve, or potentially a single if all are the same type. */
VArray<int8_t> curve_types() const;
@@ -146,6 +146,8 @@ class CurvesGeometry : public ::CurvesGeometry {
MutableSpan<int8_t> curve_types();
bool has_curve_with_type(const CurveType type) const;
+ /** Return the number of curves with each type. */
+ std::array<int, CURVE_TYPES_NUM> count_curve_types() const;
MutableSpan<float3> positions();
Span<float3> positions() const;
@@ -243,23 +245,36 @@ class CurvesGeometry : public ::CurvesGeometry {
* The total number of points in the evaluated poly curve.
* This can depend on the resolution attribute if it exists.
*/
- int evaluated_points_size() const;
+ int evaluated_points_num() const;
/**
* Access a range of indices of point data for a specific curve.
* Call #evaluated_offsets() first to ensure that the evaluated offsets cache is current.
*/
- IndexRange evaluated_range_for_curve(int index) const;
+ IndexRange evaluated_points_for_curve(int index) const;
+ IndexRange evaluated_points_for_curves(IndexRange curves) const;
/**
* The index of the first evaluated point for every curve. The size of this span is one larger
- * than the number of curves. Consider using #evaluated_range_for_curve rather than using the
+ * than the number of curves. Consider using #evaluated_points_for_curve rather than using the
* offsets directly.
*/
Span<int> evaluated_offsets() const;
+ /** Makes sure the data described by #evaluated_offsets if necessary. */
+ void ensure_evaluated_offsets() const;
+
Span<float3> evaluated_positions() const;
+ /**
+ * Evaluate a generic data to the standard evaluated points of a specific curve,
+ * defined by the resolution attribute or other factors, depending on the curve type.
+ *
+ * \warning This function expects offsets to the evaluated points for each curve to be
+ * calculated. That can be ensured with #ensure_evaluated_offsets.
+ */
+ void interpolate_to_evaluated(int curve_index, GSpan src, GMutableSpan dst) const;
+
private:
/**
* Make sure the basis weights for NURBS curve's evaluated points are calculated.
@@ -275,7 +290,7 @@ class CurvesGeometry : public ::CurvesGeometry {
* Change the number of elements. New values for existing attributes should be properly
* initialized afterwards.
*/
- void resize(int point_size, int curve_size);
+ void resize(int points_num, int curves_num);
/** Call after deforming the position attribute. */
void tag_positions_changed();
@@ -314,9 +329,9 @@ namespace curves {
* and the fact that curves with two points cannot be cyclic. The logic is simple, but this
* function should be used to make intentions clearer.
*/
-inline int curve_segment_size(const int size, const bool cyclic)
+inline int curve_segment_size(const int points_num, const bool cyclic)
{
- return (cyclic && size > 2) ? size : size - 1;
+ return (cyclic && points_num > 2) ? points_num : points_num - 1;
}
namespace bezier {
@@ -375,16 +390,23 @@ void calculate_evaluated_positions(Span<float3> positions,
Span<int> evaluated_offsets,
MutableSpan<float3> evaluated_positions);
+/**
+ * Evaluate generic data to the evaluated points, with counts for each segment described by
+ * #evaluated_offsets. Unlike other curve types, for Bezier curves generic data and positions
+ * are treated separately, since attribute values aren't stored for the handle control points.
+ */
+void interpolate_to_evaluated(GSpan src, Span<int> evaluated_offsets, GMutableSpan dst);
+
} // namespace bezier
namespace catmull_rom {
/**
* Calculate the number of evaluated points that #interpolate_to_evaluated is expected to produce.
- * \param size: The number of points in the curve.
+ * \param points_num: The number of points in the curve.
* \param resolution: The resolution for each segment.
*/
-int calculate_evaluated_size(int size, bool cyclic, int resolution);
+int calculate_evaluated_size(int points_num, bool cyclic, int resolution);
/**
* Evaluate the Catmull Rom curve. The length of the #dst span should be calculated with
@@ -399,7 +421,7 @@ namespace nurbs {
/**
* Checks the conditions that a NURBS curve needs to evaluate.
*/
-bool check_valid_size_and_order(int size, int8_t order, bool cyclic, KnotsMode knots_mode);
+bool check_valid_size_and_order(int points_num, int8_t order, bool cyclic, KnotsMode knots_mode);
/**
* Calculate the standard evaluated size for a NURBS curve, using the standard that
@@ -410,14 +432,14 @@ bool check_valid_size_and_order(int size, int8_t order, bool cyclic, KnotsMode k
* shared.
*/
int calculate_evaluated_size(
- int size, int8_t order, bool cyclic, int resolution, KnotsMode knots_mode);
+ int points_num, int8_t order, bool cyclic, int resolution, KnotsMode knots_mode);
/**
* Calculate the length of the knot vector for a NURBS curve with the given properties.
* The knots must be longer for a cyclic curve, for example, in order to provide weights for the
* last evaluated points that are also influenced by the first control points.
*/
-int knots_size(int size, int8_t order, bool cyclic);
+int knots_size(int points_num, int8_t order, bool cyclic);
/**
* Calculate the knots for a spline given its properties, based on built-in standards defined by
@@ -428,7 +450,7 @@ int knots_size(int size, int8_t order, bool cyclic);
* changes, and is generally more intuitive than defining the knot vector manually.
*/
void calculate_knots(
- int size, KnotsMode mode, int8_t order, bool cyclic, MutableSpan<float> knots);
+ int points_num, KnotsMode mode, int8_t order, bool cyclic, MutableSpan<float> knots);
/**
* Based on the knots, the order, and other properties of a NURBS curve, calculate a cache that can
@@ -436,7 +458,7 @@ void calculate_knots(
* two pieces of information for every evaluated point: the first control point that influences it,
* and a weight for each control point.
*/
-void calculate_basis_cache(int size,
+void calculate_basis_cache(int points_num,
int evaluated_size,
int8_t order,
bool cyclic,
@@ -461,11 +483,11 @@ void interpolate_to_evaluated(const BasisCache &basis_cache,
} // namespace curves
-Curves *curves_new_nomain(int point_size, int curves_size);
+Curves *curves_new_nomain(int points_num, int curves_num);
/**
* Create a new curves data-block containing a single curve with the given length and type.
*/
-Curves *curves_new_nomain_single(int point_size, CurveType type);
+Curves *curves_new_nomain_single(int points_num, CurveType type);
} // namespace blender::bke
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 911f4aab394..6b805a4c29d 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -589,7 +589,7 @@ void CustomData_layers__print(struct CustomData *data);
/* External file storage */
void CustomData_external_add(
- struct CustomData *data, struct ID *id, int type, int totelem, const char *filename);
+ struct CustomData *data, struct ID *id, int type, int totelem, const char *filepath);
void CustomData_external_remove(struct CustomData *data, struct ID *id, int type, int totelem);
bool CustomData_external_test(struct CustomData *data, int type);
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index 5a1c99774fd..109d3e6d977 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -129,7 +129,7 @@ int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface,
struct Object *cObject,
int frame);
void dynamicPaint_outputSurfaceImage(struct DynamicPaintSurface *surface,
- char *filename,
+ const char *filepath,
short output_layer);
/* PaintPoint state */
diff --git a/source/blender/blenkernel/BKE_gpencil_geom.h b/source/blender/blenkernel/BKE_gpencil_geom.h
index 4127030e96f..ad3b1971ca9 100644
--- a/source/blender/blenkernel/BKE_gpencil_geom.h
+++ b/source/blender/blenkernel/BKE_gpencil_geom.h
@@ -220,30 +220,78 @@ bool BKE_gpencil_stroke_sample(struct bGPdata *gpd,
* \param gps: Stroke to smooth
* \param i: Point index
* \param inf: Amount of smoothing to apply
+ * \param iterations: Radius of points to consider, equivalent to iterations
* \param smooth_caps: Apply smooth to stroke extremes
+ * \param keep_shape: Smooth out fine details first
+ * \param r_gps: Stroke to put the result into
*/
-bool BKE_gpencil_stroke_smooth_point(struct bGPDstroke *gps, int i, float inf, bool smooth_caps);
+bool BKE_gpencil_stroke_smooth_point(struct bGPDstroke *gps,
+ int point_index,
+ float influence,
+ int iterations,
+ bool smooth_caps,
+ bool keep_shape,
+ struct bGPDstroke *r_gps);
/**
* Apply smooth strength to stroke point.
* \param gps: Stroke to smooth
* \param point_index: Point index
* \param influence: Amount of smoothing to apply
+ * \param iterations: Radius of points to consider, equivalent to iterations
+ * \param r_gps: Stroke to put the result into
*/
-bool BKE_gpencil_stroke_smooth_strength(struct bGPDstroke *gps, int point_index, float influence);
+bool BKE_gpencil_stroke_smooth_strength(struct bGPDstroke *gps,
+ int point_index,
+ float influence,
+ int iterations,
+ struct bGPDstroke *r_gps);
/**
* Apply smooth for thickness to stroke point (use pressure).
* \param gps: Stroke to smooth
* \param point_index: Point index
* \param influence: Amount of smoothing to apply
+ * \param iterations: Radius of points to consider, equivalent to iterations
+ * \param r_gps: Stroke to put the result into
*/
-bool BKE_gpencil_stroke_smooth_thickness(struct bGPDstroke *gps, int point_index, float influence);
+bool BKE_gpencil_stroke_smooth_thickness(struct bGPDstroke *gps,
+ int point_index,
+ float influence,
+ int iterations,
+ struct bGPDstroke *r_gps);
/**
- * Apply smooth for UV rotation to stroke point (use pressure).
+ * Apply smooth for UV rotation/factor to stroke point.
* \param gps: Stroke to smooth
* \param point_index: Point index
* \param influence: Amount of smoothing to apply
+ * \param iterations: Radius of points to consider, equivalent to iterations
+ * \param r_gps: Stroke to put the result into
*/
-bool BKE_gpencil_stroke_smooth_uv(struct bGPDstroke *gps, int point_index, float influence);
+bool BKE_gpencil_stroke_smooth_uv(struct bGPDstroke *gps,
+ int point_index,
+ float influence,
+ int iterations,
+ struct bGPDstroke *r_gps);
+/**
+ * Apply smooth operation to the stroke.
+ * \param gps: Stroke to smooth
+ * \param influence: The interpolation factor for the smooth and the original stroke
+ * \param iterations: Radius of points to consider, equivalent to iterations
+ * \param smooth_position: Smooth point locations
+ * \param smooth_strength: Smooth point strength
+ * \param smooth_thickness: Smooth point thickness
+ * \param smooth_uv: Smooth uv rotation/factor
+ * \param keep_shape: Use different distribution for smooth locations to keep the shape
+ * \param weights: per point weights to multiply influence with (optional, can be null)
+ */
+void BKE_gpencil_stroke_smooth(struct bGPDstroke *gps,
+ const float influence,
+ const int iterations,
+ const bool smooth_position,
+ const bool smooth_strength,
+ const bool smooth_thickness,
+ const bool smooth_uv,
+ const bool keep_shape,
+ const float *weights);
/**
* Close grease pencil stroke.
* \param gps: Stroke to close
diff --git a/source/blender/blenkernel/BKE_image_partial_update.hh b/source/blender/blenkernel/BKE_image_partial_update.hh
index 8cbb8819551..393bf003caa 100644
--- a/source/blender/blenkernel/BKE_image_partial_update.hh
+++ b/source/blender/blenkernel/BKE_image_partial_update.hh
@@ -165,6 +165,7 @@ class ImageTileData : AbstractTileData {
* Can be nullptr when the file doesn't exist or when the tile hasn't been initialized.
*/
ImBuf *tile_buffer = nullptr;
+ void *tile_buffer_lock = nullptr;
ImageTileData(Image *image, ImageUser *image_user) : image(image)
{
@@ -177,14 +178,15 @@ class ImageTileData : AbstractTileData {
{
image_user.tile = new_tile_number;
tile = BKE_image_get_tile(image, new_tile_number);
- tile_buffer = BKE_image_acquire_ibuf(image, &image_user, NULL);
+ tile_buffer = BKE_image_acquire_ibuf(image, &image_user, &tile_buffer_lock);
}
void free_data() override
{
- BKE_image_release_ibuf(image, tile_buffer, nullptr);
+ BKE_image_release_ibuf(image, tile_buffer, tile_buffer_lock);
tile = nullptr;
tile_buffer = nullptr;
+ tile_buffer_lock = nullptr;
}
};
diff --git a/source/blender/blenkernel/BKE_image_save.h b/source/blender/blenkernel/BKE_image_save.h
index b022e677845..052fc937af9 100644
--- a/source/blender/blenkernel/BKE_image_save.h
+++ b/source/blender/blenkernel/BKE_image_save.h
@@ -49,21 +49,26 @@ bool BKE_image_save(struct ReportList *reports,
/* Render saving. */
-/* Save single or multilayer OpenEXR files from the render result.
- * Optionally saves only a specific view or layer. */
+/**
+ * Save single or multi-layer OpenEXR files from the render result.
+ * Optionally saves only a specific view or layer.
+ */
bool BKE_image_render_write_exr(struct ReportList *reports,
const struct RenderResult *rr,
- const char *filename,
+ const char *filepath,
const struct ImageFormatData *imf,
const bool save_as_render,
const char *view,
int layer);
+/**
+ * \param filepath_basis: May be used as-is, or used as a basis for multi-view images.
+ */
bool BKE_image_render_write(struct ReportList *reports,
struct RenderResult *rr,
const struct Scene *scene,
const bool stamp,
- const char *name);
+ const char *filepath_basis);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 7f099125706..77a3223c064 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -301,10 +301,9 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_SELECTED_OBJECT_BEGIN(_view_layer, _v3d, _instance) \
{ \
- struct ObjectsVisibleIteratorData data_ = { \
- .view_layer = _view_layer, \
- .v3d = _v3d, \
- }; \
+ struct ObjectsVisibleIteratorData data_ = {NULL}; \
+ data_.view_layer = _view_layer; \
+ data_.v3d = _v3d; \
ITER_BEGIN (BKE_view_layer_selected_objects_iterator_begin, \
BKE_view_layer_selected_objects_iterator_next, \
BKE_view_layer_selected_objects_iterator_end, \
@@ -319,7 +318,9 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_SELECTED_EDITABLE_OBJECT_BEGIN(_view_layer, _v3d, _instance) \
{ \
- struct ObjectsVisibleIteratorData data_ = {_view_layer, _v3d}; \
+ struct ObjectsVisibleIteratorData data_ = {NULL}; \
+ data_.view_layer = _view_layer; \
+ data_.v3d = _v3d; \
ITER_BEGIN (BKE_view_layer_selected_editable_objects_iterator_begin, \
BKE_view_layer_selected_editable_objects_iterator_next, \
BKE_view_layer_selected_editable_objects_iterator_end, \
@@ -334,10 +335,9 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_VISIBLE_OBJECT_BEGIN(_view_layer, _v3d, _instance) \
{ \
- struct ObjectsVisibleIteratorData data_ = { \
- .view_layer = _view_layer, \
- .v3d = _v3d, \
- }; \
+ struct ObjectsVisibleIteratorData data_ = {NULL}; \
+ data_.view_layer = _view_layer; \
+ data_.v3d = _v3d; \
ITER_BEGIN (BKE_view_layer_visible_objects_iterator_begin, \
BKE_view_layer_visible_objects_iterator_next, \
BKE_view_layer_visible_objects_iterator_end, \
@@ -404,10 +404,9 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_VISIBLE_BASE_BEGIN(_view_layer, _v3d, _instance) \
{ \
- struct ObjectsVisibleIteratorData data_ = { \
- .view_layer = _view_layer, \
- .v3d = _v3d, \
- }; \
+ struct ObjectsVisibleIteratorData data_ = {NULL}; \
+ data_.view_layer = _view_layer; \
+ data_.v3d = _v3d; \
ITER_BEGIN (BKE_view_layer_visible_bases_iterator_begin, \
BKE_view_layer_visible_bases_iterator_next, \
BKE_view_layer_visible_bases_iterator_end, \
@@ -437,10 +436,9 @@ void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter);
IteratorBeginCb func_begin; \
IteratorCb func_next, func_end; \
void *data_in; \
- struct ObjectsVisibleIteratorData data_ = { \
- .view_layer = _view_layer, \
- .v3d = _v3d, \
- }; \
+ struct ObjectsVisibleIteratorData data_ = {NULL}; \
+ data_.view_layer = _view_layer; \
+ data_.v3d = _v3d; \
\
if (flag == SELECT) { \
func_begin = &BKE_view_layer_selected_objects_iterator_begin; \
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index 040be8d1280..c3122758a72 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -515,7 +515,7 @@ void BKE_main_id_flag_listbase(struct ListBase *lb, int flag, bool value);
void BKE_main_id_flag_all(struct Main *bmain, int flag, bool value);
/**
- * Next to indirect usage in `readfile.c/writefile.c` also in `editobject.c`, `scene.c`.
+ * Next to indirect usage in `readfile.c/writefile.c` also in `editobject.c`, `scene.cc`.
*/
void BKE_main_id_newptr_and_tag_clear(struct Main *bmain);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index 0ba9713b96d..1ad20c52a4b 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -571,7 +571,7 @@ typedef struct MLoopNorSpaceArray {
struct LinkNode
*loops_pool; /* Allocated once, avoids to call BLI_linklist_prepend_arena() for each loop! */
char data_type; /* Whether we store loop indices, or pointers to BMLoop. */
- int num_spaces; /* Number of clnors spaces defined in this array. */
+ int spaces_num; /* Number of clnors spaces defined in this array. */
struct MemArena *mem;
} MLoopNorSpaceArray;
/**
diff --git a/source/blender/blenkernel/BKE_packedFile.h b/source/blender/blenkernel/BKE_packedFile.h
index 8433894b8c5..893aa2a5b1c 100644
--- a/source/blender/blenkernel/BKE_packedFile.h
+++ b/source/blender/blenkernel/BKE_packedFile.h
@@ -45,7 +45,7 @@ enum ePF_FileStatus {
struct PackedFile *BKE_packedfile_duplicate(const struct PackedFile *pf_src);
struct PackedFile *BKE_packedfile_new(struct ReportList *reports,
- const char *filename,
+ const char *filepath,
const char *basepath);
struct PackedFile *BKE_packedfile_new_from_memory(void *mem, int memlen);
@@ -102,7 +102,7 @@ int BKE_packedfile_unpack_all_libraries(struct Main *bmain, struct ReportList *r
int BKE_packedfile_write_to_file(struct ReportList *reports,
const char *ref_file_name,
- const char *filename,
+ const char *filepath,
struct PackedFile *pf,
bool guimode);
@@ -122,7 +122,7 @@ int BKE_packedfile_count_all(struct Main *bmain);
* - #PF_NOFILE: the original file doesn't exist.
*/
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
- const char *filename,
+ const char *filepath_rel,
struct PackedFile *pf);
/* Read. */
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 8c50a89ec90..a6402a1e8a1 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -225,7 +225,7 @@ bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *s
/* Render profile. */
int get_render_subsurf_level(const struct RenderData *r, int lvl, bool for_render);
-int get_render_child_particle_number(const struct RenderData *r, int num, bool for_render);
+int get_render_child_particle_number(const struct RenderData *r, int child_num, bool for_render);
bool BKE_scene_use_shading_nodes_custom(struct Scene *scene);
bool BKE_scene_use_spherical_stereo(struct Scene *scene);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index e4edd01481b..a39d981d74f 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -104,8 +104,6 @@ set(SRC
intern/crazyspace.c
intern/cryptomatte.cc
intern/curve.cc
- intern/curves.cc
- intern/curves_geometry.cc
intern/curve_bevel.c
intern/curve_bezier.cc
intern/curve_catmull_rom.cc
@@ -116,6 +114,8 @@ set(SRC
intern/curve_nurbs.cc
intern/curve_to_mesh_convert.cc
intern/curveprofile.cc
+ intern/curves.cc
+ intern/curves_geometry.cc
intern/customdata.cc
intern/customdata_file.c
intern/data_transfer.c
@@ -157,9 +157,9 @@ set(SRC
intern/idtype.c
intern/image.cc
intern/image_format.cc
- intern/image_partial_update.cc
intern/image_gen.c
intern/image_gpu.cc
+ intern/image_partial_update.cc
intern/image_save.cc
intern/ipo.c
intern/kelvinlet.c
@@ -248,7 +248,7 @@ set(SRC
intern/preferences.c
intern/report.c
intern/rigidbody.c
- intern/scene.c
+ intern/scene.cc
intern/screen.c
intern/shader_fx.c
intern/shrinkwrap.c
@@ -349,10 +349,10 @@ set(SRC
BKE_cryptomatte.h
BKE_cryptomatte.hh
BKE_curve.h
- BKE_curves.h
- BKE_curves.hh
BKE_curve_to_mesh.hh
BKE_curveprofile.h
+ BKE_curves.h
+ BKE_curves.hh
BKE_customdata.h
BKE_customdata_file.h
BKE_data_transfer.h
@@ -600,14 +600,14 @@ if(WITH_IMAGE_CINEON)
add_definitions(-DWITH_CINEON)
endif()
-if(WITH_IMAGE_FRAMESERVER)
- add_definitions(-DWITH_FRAMESERVER)
-endif()
-
if(WITH_IMAGE_HDR)
add_definitions(-DWITH_HDR)
endif()
+if(WITH_IMAGE_WEBP)
+ add_definitions(-DWITH_WEBP)
+endif()
+
if(WITH_CODEC_AVI)
list(APPEND INC
../io/avi
@@ -821,6 +821,7 @@ if(WITH_GTESTS)
intern/fcurve_test.cc
intern/idprop_serialize_test.cc
intern/image_partial_update_test.cc
+ intern/image_test.cc
intern/lattice_deform_test.cc
intern/layer_test.cc
intern/lib_id_remapper_test.cc
diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c
index b0393ed723d..8d3649fef08 100644
--- a/source/blender/blenkernel/intern/appdir.c
+++ b/source/blender/blenkernel/intern/appdir.c
@@ -1022,16 +1022,16 @@ void BKE_appdir_app_templates(ListBase *templates)
continue;
}
- struct direntry *dir;
- uint totfile = BLI_filelist_dir_contents(subdir, &dir);
- for (int f = 0; f < totfile; f++) {
- if (!FILENAME_IS_CURRPAR(dir[f].relname) && S_ISDIR(dir[f].type)) {
- char *template = BLI_strdup(dir[f].relname);
+ struct direntry *dirs;
+ const uint dir_num = BLI_filelist_dir_contents(subdir, &dirs);
+ for (int f = 0; f < dir_num; f++) {
+ if (!FILENAME_IS_CURRPAR(dirs[f].relname) && S_ISDIR(dirs[f].type)) {
+ char *template = BLI_strdup(dirs[f].relname);
BLI_addtail(templates, BLI_genericNodeN(template));
}
}
- BLI_filelist_free(dir, totfile);
+ BLI_filelist_free(dirs, dir_num);
}
}
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
index 294fe57c923..be2abdbfb69 100644
--- a/source/blender/blenkernel/intern/blendfile_link_append.c
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -999,7 +999,7 @@ static void blendfile_link_append_proxies_convert(Main *bmain, ReportList *repor
RPT_WARNING,
"Proxies have been removed from Blender (%d proxies were automatically converted "
"to library overrides, %d proxies could not be converted and were cleared). "
- "Please consider re-saving any library .blend file with the newest Blender version.",
+ "Please consider re-saving any library .blend file with the newest Blender version",
bf_reports.count.proxies_to_lib_overrides_success,
bf_reports.count.proxies_to_lib_overrides_failures);
}
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 891145b47c9..bdaea487cfb 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -432,7 +432,8 @@ void BKE_collection_add_from_object(Main *bmain,
bool is_instantiated = false;
FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
- if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, ob_src)) {
+ if (!ID_IS_LINKED(collection) && !ID_IS_OVERRIDABLE_LIBRARY(collection) &&
+ BKE_collection_has_object(collection, ob_src)) {
collection_child_add(collection, collection_dst, 0, true);
is_instantiated = true;
}
@@ -454,7 +455,8 @@ void BKE_collection_add_from_collection(Main *bmain,
bool is_instantiated = false;
FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
- if (!ID_IS_LINKED(collection) && collection_find_child(collection, collection_src)) {
+ if (!ID_IS_LINKED(collection) && !ID_IS_OVERRIDABLE_LIBRARY(collection) &&
+ collection_find_child(collection, collection_src)) {
collection_child_add(collection, collection_dst, 0, true);
is_instantiated = true;
}
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 9d13bf3ac11..96389c44839 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -236,7 +236,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
ModifierData *md;
Mesh *me_input = ob->data;
Mesh *me = NULL;
- int i, a, numleft = 0, numVerts = 0;
+ int i, a, modifiers_left_num = 0, verts_num = 0;
int cageIndex = BKE_modifiers_get_cage_index(scene, ob, NULL, 1);
float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
VirtualModifierData virtualModifierData;
@@ -266,14 +266,14 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
BLI_linklist_free((LinkNode *)datamasks, NULL);
me = BKE_mesh_wrapper_from_editmesh_with_coords(em, &cd_mask_extra, NULL, me_input);
- deformedVerts = editbmesh_vert_coords_alloc(em, &numVerts);
- defmats = MEM_mallocN(sizeof(*defmats) * numVerts, "defmats");
+ deformedVerts = editbmesh_vert_coords_alloc(em, &verts_num);
+ defmats = MEM_mallocN(sizeof(*defmats) * verts_num, "defmats");
- for (a = 0; a < numVerts; a++) {
+ for (a = 0; a < verts_num; a++) {
unit_m3(defmats[a]);
}
}
- mti->deformMatricesEM(md, &mectx, em, me, deformedVerts, defmats, numVerts);
+ mti->deformMatricesEM(md, &mectx, em, me, deformedVerts, defmats, verts_num);
}
else {
break;
@@ -283,7 +283,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
for (; md && i <= cageIndex; md = md->next, i++) {
if (editbmesh_modifier_is_enabled(scene, ob, md, me != NULL) &&
BKE_modifier_is_correctable_deformed(md)) {
- numleft++;
+ modifiers_left_num++;
}
}
@@ -294,7 +294,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgra
*deformmats = defmats;
*deformcos = deformedVerts;
- return numleft;
+ return modifiers_left_num;
}
/**
@@ -319,13 +319,13 @@ static void crazyspace_init_verts_and_matrices(const Mesh *mesh,
float (**deformmats)[3][3],
float (**deformcos)[3])
{
- int num_verts;
- *deformcos = BKE_mesh_vert_coords_alloc(mesh, &num_verts);
- *deformmats = MEM_callocN(sizeof(**deformmats) * num_verts, "defmats");
- for (int a = 0; a < num_verts; a++) {
+ int verts_num;
+ *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num);
+ *deformmats = MEM_callocN(sizeof(**deformmats) * verts_num, "defmats");
+ for (int a = 0; a < verts_num; a++) {
unit_m3((*deformmats)[a]);
}
- BLI_assert(num_verts == mesh->totvert);
+ BLI_assert(verts_num == mesh->totvert);
}
static bool crazyspace_modifier_supports_deform_matrices(ModifierData *md)
@@ -352,7 +352,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
ModifierData *md;
Mesh *me_eval = NULL;
float(*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL;
- int numleft = 0;
+ int modifiers_left_num = 0;
VirtualModifierData virtualModifierData;
Object object_eval;
crazyspace_init_object_for_eval(depsgraph, object, &object_eval);
@@ -364,7 +364,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
if (is_sculpt_mode && has_multires) {
*deformmats = NULL;
*deformcos = NULL;
- return numleft;
+ return modifiers_left_num;
}
md = BKE_modifiers_get_virtual_modifierlist(&object_eval, &virtualModifierData);
@@ -401,7 +401,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
}
if (crazyspace_modifier_supports_deform(md)) {
- numleft++;
+ modifiers_left_num++;
}
}
@@ -412,7 +412,7 @@ int BKE_sculpt_get_first_deform_matrices(struct Depsgraph *depsgraph,
*deformmats = defmats;
*deformcos = deformedVerts;
- return numleft;
+ return modifiers_left_num;
}
void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
@@ -489,13 +489,13 @@ void BKE_crazyspace_build_sculpt(struct Depsgraph *depsgraph,
}
if (*deformmats == NULL) {
- int a, numVerts;
+ int a, verts_num;
Mesh *mesh = (Mesh *)object->data;
- *deformcos = BKE_mesh_vert_coords_alloc(mesh, &numVerts);
- *deformmats = MEM_callocN(sizeof(*(*deformmats)) * numVerts, "defmats");
+ *deformcos = BKE_mesh_vert_coords_alloc(mesh, &verts_num);
+ *deformmats = MEM_callocN(sizeof(*(*deformmats)) * verts_num, "defmats");
- for (a = 0; a < numVerts; a++) {
+ for (a = 0; a < verts_num; a++) {
unit_m3((*deformmats)[a]);
}
}
@@ -523,7 +523,7 @@ void BKE_crazyspace_api_eval(Depsgraph *depsgraph,
}
const Mesh *mesh = (const Mesh *)object->data;
- object->runtime.crazyspace_num_verts = mesh->totvert;
+ object->runtime.crazyspace_verts_num = mesh->totvert;
BKE_crazyspace_build_sculpt(depsgraph,
scene,
object,
@@ -537,12 +537,12 @@ void BKE_crazyspace_api_displacement_to_deformed(struct Object *object,
float displacement[3],
float r_displacement_deformed[3])
{
- if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_num_verts) {
+ if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) {
BKE_reportf(reports,
RPT_ERROR,
"Invalid vertex index %d (expected to be within 0 to %d range)",
vertex_index,
- object->runtime.crazyspace_num_verts);
+ object->runtime.crazyspace_verts_num);
return;
}
@@ -557,12 +557,12 @@ void BKE_crazyspace_api_displacement_to_original(struct Object *object,
float displacement_deformed[3],
float r_displacement[3])
{
- if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_num_verts) {
+ if (vertex_index < 0 || vertex_index >= object->runtime.crazyspace_verts_num) {
BKE_reportf(reports,
RPT_ERROR,
"Invalid vertex index %d (expected to be within 0 to %d range))",
vertex_index,
- object->runtime.crazyspace_num_verts);
+ object->runtime.crazyspace_verts_num);
return;
}
diff --git a/source/blender/blenkernel/intern/curve.cc b/source/blender/blenkernel/intern/curve.cc
index 354ddd7d167..8b58ad848f2 100644
--- a/source/blender/blenkernel/intern/curve.cc
+++ b/source/blender/blenkernel/intern/curve.cc
@@ -4718,11 +4718,11 @@ static NURBSValidationStatus nurb_check_valid(const int pnts,
if (pnts <= 1) {
return NURBSValidationStatus::AtLeastTwoPointsRequired;
}
- else if (type == CU_NURBS) {
+ if (type == CU_NURBS) {
if (pnts < order) {
return NURBSValidationStatus::MorePointsThanOrderRequired;
}
- else if (flag & CU_NURB_BEZIER) {
+ if (flag & CU_NURB_BEZIER) {
int points_needed = 0;
if (flag & CU_NURB_CYCLIC) {
const int remainder = pnts % (order - 1);
@@ -4765,7 +4765,7 @@ bool BKE_nurb_valid_message(const int pnts,
message_dst[0] = 0;
return false;
}
- msg_template = TIP_("At least two points required.");
+ msg_template = TIP_("At least two points required");
break;
case NURBSValidationStatus::MorePointsThanOrderRequired:
msg_template = TIP_("Must have more control points than Order");
diff --git a/source/blender/blenkernel/intern/curve_bezier.cc b/source/blender/blenkernel/intern/curve_bezier.cc
index 52a2674ab3d..b11216983b2 100644
--- a/source/blender/blenkernel/intern/curve_bezier.cc
+++ b/source/blender/blenkernel/intern/curve_bezier.cc
@@ -121,8 +121,8 @@ void calculate_evaluated_positions(const Span<float3> positions,
});
/* Evaluate the final cyclic segment if necessary. */
- const IndexRange evaluated_range = offsets_to_range(evaluated_offsets, positions.size() - 2);
- if (evaluated_range.size() == 1) {
+ const IndexRange last_segment_points = offsets_to_range(evaluated_offsets, positions.size() - 2);
+ if (last_segment_points.size() == 1) {
evaluated_positions.last() = positions.last();
}
else {
@@ -130,10 +130,54 @@ void calculate_evaluated_positions(const Span<float3> positions,
handles_right.last(),
handles_left.first(),
positions.first(),
- evaluated_positions.slice(evaluated_range));
+ evaluated_positions.slice(last_segment_points));
}
}
+template<typename T>
+static inline void linear_interpolation(const T &a, const T &b, MutableSpan<T> dst)
+{
+ dst.first() = a;
+ const float step = 1.0f / dst.size();
+ for (const int i : dst.index_range().drop_front(1)) {
+ dst[i] = attribute_math::mix2(i * step, a, b);
+ }
+}
+
+template<typename T>
+static void interpolate_to_evaluated(const Span<T> src,
+ const Span<int> evaluated_offsets,
+ MutableSpan<T> dst)
+{
+ BLI_assert(!src.is_empty());
+ BLI_assert(dst.size() == src.size());
+ BLI_assert(evaluated_offsets.last() == dst.size());
+
+ linear_interpolation(src.first(), src[1], dst.take_front(evaluated_offsets.first()));
+
+ threading::parallel_for(
+ src.index_range().drop_back(1).drop_front(1), 512, [&](IndexRange range) {
+ for (const int i : range) {
+ const IndexRange segment_points = offsets_to_range(evaluated_offsets, i - 1);
+ linear_interpolation(src[i], src[i + 1], dst.slice(segment_points));
+ }
+ });
+
+ const IndexRange last_segment_points(evaluated_offsets.last(1),
+ evaluated_offsets.last() - evaluated_offsets.last(1));
+ linear_interpolation(src.last(), src.first(), dst.slice(last_segment_points));
+}
+
+void interpolate_to_evaluated(const GSpan src, const Span<int> evaluated_offsets, GMutableSpan dst)
+{
+ attribute_math::convert_to_static_type(src.type(), [&](auto dummy) {
+ using T = decltype(dummy);
+ if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
+ interpolate_to_evaluated(src.typed<T>(), evaluated_offsets, dst.typed<T>());
+ }
+ });
+}
+
/** \} */
} // namespace blender::bke::curves::bezier
diff --git a/source/blender/blenkernel/intern/curve_catmull_rom.cc b/source/blender/blenkernel/intern/curve_catmull_rom.cc
index 27687eb736f..ea3672dd56b 100644
--- a/source/blender/blenkernel/intern/curve_catmull_rom.cc
+++ b/source/blender/blenkernel/intern/curve_catmull_rom.cc
@@ -9,11 +9,11 @@
namespace blender::bke::curves::catmull_rom {
-int calculate_evaluated_size(const int size, const bool cyclic, const int resolution)
+int calculate_evaluated_size(const int points_num, const bool cyclic, const int resolution)
{
- const int eval_size = resolution * curve_segment_size(size, cyclic);
+ const int eval_size = resolution * curve_segment_size(points_num, cyclic);
/* If the curve isn't cyclic, one last point is added to the final point. */
- return (cyclic && size > 2) ? eval_size : eval_size + 1;
+ return (cyclic && points_num > 2) ? eval_size : eval_size + 1;
}
/* Adapted from Cycles #catmull_rom_basis_eval function. */
diff --git a/source/blender/blenkernel/intern/curve_eval.cc b/source/blender/blenkernel/intern/curve_eval.cc
index b2399f25638..2cf83b57881 100644
--- a/source/blender/blenkernel/intern/curve_eval.cc
+++ b/source/blender/blenkernel/intern/curve_eval.cc
@@ -398,7 +398,7 @@ std::unique_ptr<CurveEval> curves_to_curve_eval(const Curves &curves)
VArray<int8_t> curve_types = geometry.curve_types();
std::unique_ptr<CurveEval> curve_eval = std::make_unique<CurveEval>();
for (const int curve_index : curve_types.index_range()) {
- const IndexRange point_range = geometry.range_for_curve(curve_index);
+ const IndexRange point_range = geometry.points_for_curve(curve_index);
std::unique_ptr<Spline> spline;
switch (curve_types[curve_index]) {
@@ -489,7 +489,7 @@ Curves *curve_eval_to_curves(const CurveEval &curve_eval)
const Spline &spline = *curve_eval.splines()[curve_index];
curve_types[curve_index] = curve_eval.splines()[curve_index]->type();
- const IndexRange point_range = geometry.range_for_curve(curve_index);
+ const IndexRange point_range = geometry.points_for_curve(curve_index);
switch (spline.type()) {
case CURVE_TYPE_POLY:
diff --git a/source/blender/blenkernel/intern/curve_nurbs.cc b/source/blender/blenkernel/intern/curve_nurbs.cc
index a4cdbbca654..0114c0b45f4 100644
--- a/source/blender/blenkernel/intern/curve_nurbs.cc
+++ b/source/blender/blenkernel/intern/curve_nurbs.cc
@@ -10,53 +10,53 @@
namespace blender::bke::curves::nurbs {
-bool check_valid_size_and_order(const int size,
+bool check_valid_size_and_order(const int points_num,
const int8_t order,
const bool cyclic,
const KnotsMode knots_mode)
{
- if (size < order) {
+ if (points_num < order) {
return false;
}
if (ELEM(knots_mode, NURBS_KNOT_MODE_BEZIER, NURBS_KNOT_MODE_ENDPOINT_BEZIER)) {
- if (knots_mode == NURBS_KNOT_MODE_BEZIER && size <= order) {
+ if (knots_mode == NURBS_KNOT_MODE_BEZIER && points_num <= order) {
return false;
}
- return (!cyclic || size % (order - 1) == 0);
+ return (!cyclic || points_num % (order - 1) == 0);
}
return true;
}
-int calculate_evaluated_size(const int size,
+int calculate_evaluated_size(const int points_num,
const int8_t order,
const bool cyclic,
const int resolution,
const KnotsMode knots_mode)
{
- if (!check_valid_size_and_order(size, order, cyclic, knots_mode)) {
+ if (!check_valid_size_and_order(points_num, order, cyclic, knots_mode)) {
return 0;
}
- return resolution * curve_segment_size(size, cyclic);
+ return resolution * curve_segment_size(points_num, cyclic);
}
-int knots_size(const int size, const int8_t order, const bool cyclic)
+int knots_size(const int points_num, const int8_t order, const bool cyclic)
{
if (cyclic) {
- return size + order * 2 - 1;
+ return points_num + order * 2 - 1;
}
- return size + order;
+ return points_num + order;
}
-void calculate_knots(const int size,
+void calculate_knots(const int points_num,
const KnotsMode mode,
const int8_t order,
const bool cyclic,
MutableSpan<float> knots)
{
- BLI_assert(knots.size() == knots_size(size, order, cyclic));
- UNUSED_VARS_NDEBUG(size);
+ BLI_assert(knots.size() == knots_size(points_num, order, cyclic));
+ UNUSED_VARS_NDEBUG(points_num);
const bool is_bezier = ELEM(mode, NURBS_KNOT_MODE_BEZIER, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
const bool is_end_point = ELEM(mode, NURBS_KNOT_MODE_ENDPOINT, NURBS_KNOT_MODE_ENDPOINT_BEZIER);
@@ -94,7 +94,7 @@ void calculate_knots(const int size,
}
static void calculate_basis_for_point(const float parameter,
- const int size,
+ const int points_num,
const int degree,
const Span<float> knots,
MutableSpan<float> r_weights,
@@ -104,7 +104,7 @@ static void calculate_basis_for_point(const float parameter,
int start = 0;
int end = 0;
- for (const int i : IndexRange(size + degree)) {
+ for (const int i : IndexRange(points_num + degree)) {
const bool knots_equal = knots[i] == knots[i + 1];
if (knots_equal || parameter < knots[i] || parameter > knots[i + 1]) {
continue;
@@ -121,7 +121,7 @@ static void calculate_basis_for_point(const float parameter,
for (const int i_order : IndexRange(2, degree)) {
if (end + i_order >= knots.size()) {
- end = size + degree - i_order;
+ end = points_num + degree - i_order;
}
for (const int i : IndexRange(end - start + 1)) {
const int knot_index = start + i;
@@ -146,15 +146,14 @@ static void calculate_basis_for_point(const float parameter,
r_start_index = start;
}
-void calculate_basis_cache(const int size,
+void calculate_basis_cache(const int points_num,
const int evaluated_size,
const int8_t order,
const bool cyclic,
const Span<float> knots,
BasisCache &basis_cache)
{
- BLI_assert(size > 0);
- BLI_assert(evaluated_size > 0);
+ BLI_assert(points_num > 0);
const int8_t degree = order - 1;
@@ -168,7 +167,7 @@ void calculate_basis_cache(const int size,
MutableSpan<float> basis_weights(basis_cache.weights);
MutableSpan<int> basis_start_indices(basis_cache.start_indices);
- const int last_control_point_index = cyclic ? size + degree : size;
+ const int last_control_point_index = cyclic ? points_num + degree : points_num;
const int evaluated_segment_size = curve_segment_size(evaluated_size, cyclic);
const float start = knots[degree];
@@ -176,7 +175,7 @@ void calculate_basis_cache(const int size,
const float step = (end - start) / evaluated_segment_size;
for (const int i : IndexRange(evaluated_size)) {
/* Clamp parameter due to floating point inaccuracy. */
- const float parameter = std::clamp(start + step * i, knots[0], knots[size + degree]);
+ const float parameter = std::clamp(start + step * i, knots[0], knots[points_num + degree]);
MutableSpan<float> point_weights = basis_weights.slice(i * order, order);
diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc
index 838f7f28e93..82db1176759 100644
--- a/source/blender/blenkernel/intern/curves.cc
+++ b/source/blender/blenkernel/intern/curves.cc
@@ -366,19 +366,19 @@ void BKE_curves_batch_cache_free(Curves *curves)
namespace blender::bke {
-Curves *curves_new_nomain(const int point_size, const int curves_size)
+Curves *curves_new_nomain(const int points_num, const int curves_num)
{
Curves *curves = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
CurvesGeometry &geometry = CurvesGeometry::wrap(curves->geometry);
- geometry.resize(point_size, curves_size);
+ geometry.resize(points_num, curves_num);
return curves;
}
-Curves *curves_new_nomain_single(const int point_size, const CurveType type)
+Curves *curves_new_nomain_single(const int points_num, const CurveType type)
{
- Curves *curves = curves_new_nomain(point_size, 1);
+ Curves *curves = curves_new_nomain(points_num, 1);
CurvesGeometry &geometry = CurvesGeometry::wrap(curves->geometry);
- geometry.offsets().last() = point_size;
+ geometry.offsets().last() = points_num;
geometry.curve_types().first() = type;
return curves;
}
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index db69fbc4063..7ceaa8f0f37 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -149,24 +149,24 @@ CurvesGeometry::~CurvesGeometry()
/** \name Accessors
* \{ */
-int CurvesGeometry::points_size() const
+int CurvesGeometry::points_num() const
{
return this->point_size;
}
-int CurvesGeometry::curves_size() const
+int CurvesGeometry::curves_num() const
{
return this->curve_size;
}
IndexRange CurvesGeometry::points_range() const
{
- return IndexRange(this->points_size());
+ return IndexRange(this->points_num());
}
IndexRange CurvesGeometry::curves_range() const
{
- return IndexRange(this->curves_size());
+ return IndexRange(this->curves_num());
}
-IndexRange CurvesGeometry::range_for_curve(const int index) const
+IndexRange CurvesGeometry::points_for_curve(const int index) const
{
BLI_assert(this->curve_size > 0);
BLI_assert(this->curve_offsets != nullptr);
@@ -175,7 +175,7 @@ IndexRange CurvesGeometry::range_for_curve(const int index) const
return {offset, offset_next - offset};
}
-IndexRange CurvesGeometry::range_for_curves(const IndexRange curves) const
+IndexRange CurvesGeometry::points_for_curves(const IndexRange curves) const
{
BLI_assert(this->curve_size > 0);
BLI_assert(this->curve_offsets != nullptr);
@@ -186,7 +186,7 @@ IndexRange CurvesGeometry::range_for_curves(const IndexRange curves) const
static int domain_size(const CurvesGeometry &curves, const AttributeDomain domain)
{
- return domain == ATTR_DOMAIN_POINT ? curves.points_size() : curves.curves_size();
+ return domain == ATTR_DOMAIN_POINT ? curves.points_num() : curves.curves_num();
}
static CustomData &domain_custom_data(CurvesGeometry &curves, const AttributeDomain domain)
@@ -277,6 +277,40 @@ bool CurvesGeometry::has_curve_with_type(const CurveType type) const
return false;
}
+std::array<int, CURVE_TYPES_NUM> CurvesGeometry::count_curve_types() const
+{
+ using CountsType = std::array<int, CURVE_TYPES_NUM>;
+
+ CountsType identity;
+ identity.fill(0);
+
+ const VArray<int8_t> types = this->curve_types();
+ if (types.is_single()) {
+ identity[types.get_internal_single()] = this->curves_num();
+ return identity;
+ }
+
+ Span<int8_t> types_span = types.get_internal_span();
+ return threading::parallel_reduce(
+ this->curves_range(),
+ 2048,
+ identity,
+ [&](const IndexRange curves_range, const CountsType &init) {
+ CountsType result = init;
+ for (const int curve_index : curves_range) {
+ result[types_span[curve_index]]++;
+ }
+ return result;
+ },
+ [](const CountsType &a, const CountsType &b) {
+ CountsType result = a;
+ for (const int i : IndexRange(CURVE_TYPES_NUM)) {
+ result[i] += b[i];
+ }
+ return result;
+ });
+}
+
MutableSpan<float3> CurvesGeometry::positions()
{
this->position = (float(*)[3])CustomData_duplicate_referenced_layer_named(
@@ -431,7 +465,7 @@ static void calculate_evaluated_offsets(const CurvesGeometry &curves,
VArray<int8_t> nurbs_knots_modes = curves.nurbs_knots_modes();
build_offsets(offsets, [&](const int curve_index) -> int {
- const IndexRange points = curves.range_for_curve(curve_index);
+ const IndexRange points = curves.points_for_curve(curve_index);
switch (types[curve_index]) {
case CURVE_TYPE_CATMULL_ROM:
return curves::catmull_rom::calculate_evaluated_size(
@@ -457,35 +491,44 @@ static void calculate_evaluated_offsets(const CurvesGeometry &curves,
});
}
-int CurvesGeometry::evaluated_points_size() const
+int CurvesGeometry::evaluated_points_num() const
{
/* This could avoid calculating offsets in the future in simple circumstances. */
return this->evaluated_offsets().last();
}
-IndexRange CurvesGeometry::evaluated_range_for_curve(int index) const
+IndexRange CurvesGeometry::evaluated_points_for_curve(int index) const
{
BLI_assert(!this->runtime->offsets_cache_dirty);
return offsets_to_range(this->runtime->evaluated_offsets_cache.as_span(), index);
}
-Span<int> CurvesGeometry::evaluated_offsets() const
+IndexRange CurvesGeometry::evaluated_points_for_curves(const IndexRange curves) const
+{
+ BLI_assert(!this->runtime->offsets_cache_dirty);
+ BLI_assert(this->curve_size > 0);
+ const int offset = this->runtime->evaluated_offsets_cache[curves.start()];
+ const int offset_next = this->runtime->evaluated_offsets_cache[curves.one_after_last()];
+ return {offset, offset_next - offset};
+}
+
+void CurvesGeometry::ensure_evaluated_offsets() const
{
if (!this->runtime->offsets_cache_dirty) {
- return this->runtime->evaluated_offsets_cache;
+ return;
}
/* A double checked lock. */
std::scoped_lock lock{this->runtime->offsets_cache_mutex};
if (!this->runtime->offsets_cache_dirty) {
- return this->runtime->evaluated_offsets_cache;
+ return;
}
threading::isolate_task([&]() {
- this->runtime->evaluated_offsets_cache.resize(this->curves_size() + 1);
+ this->runtime->evaluated_offsets_cache.resize(this->curves_num() + 1);
if (this->has_curve_with_type(CURVE_TYPE_BEZIER)) {
- this->runtime->bezier_evaluated_offsets.resize(this->points_size());
+ this->runtime->bezier_evaluated_offsets.resize(this->points_num());
}
else {
this->runtime->bezier_evaluated_offsets.clear_and_make_inline();
@@ -496,6 +539,11 @@ Span<int> CurvesGeometry::evaluated_offsets() const
});
this->runtime->offsets_cache_dirty = false;
+}
+
+Span<int> CurvesGeometry::evaluated_offsets() const
+{
+ this->ensure_evaluated_offsets();
return this->runtime->evaluated_offsets_cache;
}
@@ -536,7 +584,7 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const
return;
}
- this->runtime->nurbs_basis_cache.resize(this->curves_size());
+ this->runtime->nurbs_basis_cache.resize(this->curves_num());
MutableSpan<curves::nurbs::BasisCache> basis_caches(this->runtime->nurbs_basis_cache);
VArray<bool> cyclic = this->cyclic();
@@ -545,8 +593,8 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const
threading::parallel_for(nurbs_mask.index_range(), 64, [&](const IndexRange range) {
for (const int curve_index : nurbs_mask.slice(range)) {
- const IndexRange points = this->range_for_curve(curve_index);
- const IndexRange evaluated_points = this->evaluated_range_for_curve(curve_index);
+ const IndexRange points = this->points_for_curve(curve_index);
+ const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
const int8_t order = orders[curve_index];
const bool is_cyclic = cyclic[curve_index];
@@ -564,6 +612,8 @@ void CurvesGeometry::ensure_nurbs_basis_cache() const
}
});
});
+
+ this->runtime->nurbs_basis_cache_dirty = false;
}
Span<float3> CurvesGeometry::evaluated_positions() const
@@ -579,7 +629,7 @@ Span<float3> CurvesGeometry::evaluated_positions() const
}
threading::isolate_task([&]() {
- this->runtime->evaluated_position_cache.resize(this->evaluated_points_size());
+ this->runtime->evaluated_position_cache.resize(this->evaluated_points_num());
MutableSpan<float3> evaluated_positions = this->runtime->evaluated_position_cache;
VArray<int8_t> types = this->curve_types();
@@ -598,8 +648,8 @@ Span<float3> CurvesGeometry::evaluated_positions() const
threading::parallel_for(this->curves_range(), 128, [&](IndexRange curves_range) {
for (const int curve_index : curves_range) {
- const IndexRange points = this->range_for_curve(curve_index);
- const IndexRange evaluated_points = this->evaluated_range_for_curve(curve_index);
+ const IndexRange points = this->points_for_curve(curve_index);
+ const IndexRange evaluated_points = this->evaluated_points_for_curve(curve_index);
switch (types[curve_index]) {
case CURVE_TYPE_CATMULL_ROM:
@@ -639,22 +689,54 @@ Span<float3> CurvesGeometry::evaluated_positions() const
return this->runtime->evaluated_position_cache;
}
+void CurvesGeometry::interpolate_to_evaluated(const int curve_index,
+ const GSpan src,
+ GMutableSpan dst) const
+{
+ BLI_assert(!this->runtime->offsets_cache_dirty);
+ BLI_assert(!this->runtime->nurbs_basis_cache_dirty);
+ const IndexRange points = this->points_for_curve(curve_index);
+ BLI_assert(src.size() == points.size());
+ BLI_assert(dst.size() == this->evaluated_points_for_curve(curve_index).size());
+ switch (this->curve_types()[curve_index]) {
+ case CURVE_TYPE_CATMULL_ROM:
+ curves::catmull_rom::interpolate_to_evaluated(
+ src, this->cyclic()[curve_index], this->resolution()[curve_index], dst);
+ return;
+ case CURVE_TYPE_POLY:
+ dst.type().copy_assign_n(src.data(), dst.data(), src.size());
+ return;
+ case CURVE_TYPE_BEZIER:
+ curves::bezier::interpolate_to_evaluated(
+ src, this->runtime->bezier_evaluated_offsets.as_span().slice(points), dst);
+ return;
+ case CURVE_TYPE_NURBS:
+ curves::nurbs::interpolate_to_evaluated(this->runtime->nurbs_basis_cache[curve_index],
+ this->nurbs_orders()[curve_index],
+ this->nurbs_weights().slice(points),
+ src,
+ dst);
+ return;
+ }
+ BLI_assert_unreachable();
+}
+
/** \} */
/* -------------------------------------------------------------------- */
/** \name Operations
* \{ */
-void CurvesGeometry::resize(const int point_size, const int curve_size)
+void CurvesGeometry::resize(const int points_num, const int curves_num)
{
- if (point_size != this->point_size) {
- CustomData_realloc(&this->point_data, point_size);
- this->point_size = point_size;
+ if (points_num != this->point_size) {
+ CustomData_realloc(&this->point_data, points_num);
+ this->point_size = points_num;
}
- if (curve_size != this->curve_size) {
- CustomData_realloc(&this->curve_data, curve_size);
- this->curve_size = curve_size;
- this->curve_offsets = (int *)MEM_reallocN(this->curve_offsets, sizeof(int) * (curve_size + 1));
+ if (curves_num != this->curve_size) {
+ CustomData_realloc(&this->curve_data, curves_num);
+ this->curve_size = curves_num;
+ this->curve_offsets = (int *)MEM_reallocN(this->curve_offsets, sizeof(int) * (curves_num + 1));
}
this->tag_topology_changed();
this->update_customdata_pointers();
@@ -727,7 +809,7 @@ static std::optional<bounds::MinMaxResult<float3>> curves_bounds(const CurvesGeo
{
Span<float3> positions = curves.positions();
if (curves.radius) {
- Span<float> radii{curves.radius, curves.points_size()};
+ Span<float> radii{curves.radius, curves.points_num()};
return bounds::min_max_with_radii(positions, radii);
}
return bounds::min_max(positions);
@@ -784,7 +866,7 @@ static CurvesGeometry copy_with_removed_curves(const CurvesGeometry &curves,
new_curve_ranges.append(IndexRange(new_tot_curves, curve_range.size()));
new_tot_curves += curve_range.size();
- const IndexRange old_point_range = curves.range_for_curves(curve_range);
+ const IndexRange old_point_range = curves.points_for_curves(curve_range);
old_point_ranges.append(old_point_range);
new_point_ranges.append(IndexRange(new_tot_points, old_point_range.size()));
new_tot_points += old_point_range.size();
@@ -889,7 +971,7 @@ static void reverse_curve_point_data(const CurvesGeometry &curves,
{
threading::parallel_for(curve_selection.index_range(), 256, [&](IndexRange range) {
for (const int curve_i : curve_selection.slice(range)) {
- data.slice(curves.range_for_curve(curve_i)).reverse();
+ data.slice(curves.points_for_curve(curve_i)).reverse();
}
});
}
@@ -902,7 +984,7 @@ static void reverse_swap_curve_point_data(const CurvesGeometry &curves,
{
threading::parallel_for(curve_selection.index_range(), 256, [&](IndexRange range) {
for (const int curve_i : curve_selection.slice(range)) {
- const IndexRange points = curves.range_for_curve(curve_i);
+ const IndexRange points = curves.points_for_curve(curve_i);
MutableSpan<T> a = data_a.slice(points);
MutableSpan<T> b = data_b.slice(points);
for (const int i : IndexRange(points.size() / 2)) {
@@ -926,7 +1008,7 @@ static bool layer_matches_name_and_type(const CustomDataLayer &layer,
void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse)
{
- CustomData_duplicate_referenced_layers(&this->point_data, this->points_size());
+ CustomData_duplicate_referenced_layers(&this->point_data, this->points_num());
/* Collect the Bezier handle attributes while iterating through the point custom data layers;
* they need special treatment later. */
@@ -940,22 +1022,22 @@ void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse)
if (positions_left.is_empty() &&
layer_matches_name_and_type(layer, ATTR_HANDLE_POSITION_LEFT, CD_PROP_FLOAT3)) {
- positions_left = {static_cast<float3 *>(layer.data), this->points_size()};
+ positions_left = {static_cast<float3 *>(layer.data), this->points_num()};
continue;
}
if (positions_right.is_empty() &&
layer_matches_name_and_type(layer, ATTR_HANDLE_POSITION_RIGHT, CD_PROP_FLOAT3)) {
- positions_right = {static_cast<float3 *>(layer.data), this->points_size()};
+ positions_right = {static_cast<float3 *>(layer.data), this->points_num()};
continue;
}
if (types_left.is_empty() &&
layer_matches_name_and_type(layer, ATTR_HANDLE_TYPE_LEFT, CD_PROP_INT8)) {
- types_left = {static_cast<int8_t *>(layer.data), this->points_size()};
+ types_left = {static_cast<int8_t *>(layer.data), this->points_num()};
continue;
}
if (types_right.is_empty() &&
layer_matches_name_and_type(layer, ATTR_HANDLE_TYPE_RIGHT, CD_PROP_INT8)) {
- types_right = {static_cast<int8_t *>(layer.data), this->points_size()};
+ types_right = {static_cast<int8_t *>(layer.data), this->points_num()};
continue;
}
@@ -963,7 +1045,7 @@ void CurvesGeometry::reverse_curves(const IndexMask curves_to_reverse)
attribute_math::convert_to_static_type(data_type, [&](auto dummy) {
using T = decltype(dummy);
reverse_curve_point_data<T>(
- *this, curves_to_reverse, {static_cast<T *>(layer.data), this->points_size()});
+ *this, curves_to_reverse, {static_cast<T *>(layer.data), this->points_num()});
});
}
@@ -1001,8 +1083,8 @@ static void adapt_curve_domain_point_to_curve_impl(const CurvesGeometry &curves,
MutableSpan<T> r_values)
{
attribute_math::DefaultMixer<T> mixer(r_values);
- for (const int i_curve : IndexRange(curves.curves_size())) {
- for (const int i_point : curves.range_for_curve(i_curve)) {
+ for (const int i_curve : IndexRange(curves.curves_num())) {
+ for (const int i_point : curves.points_for_curve(i_curve)) {
mixer.mix_in(i_curve, old_values[i_point]);
}
}
@@ -1022,8 +1104,8 @@ void adapt_curve_domain_point_to_curve_impl(const CurvesGeometry &curves,
MutableSpan<bool> r_values)
{
r_values.fill(true);
- for (const int i_curve : IndexRange(curves.curves_size())) {
- for (const int i_point : curves.range_for_curve(i_curve)) {
+ for (const int i_curve : IndexRange(curves.curves_num())) {
+ for (const int i_point : curves.points_for_curve(i_curve)) {
if (!old_values[i_point]) {
r_values[i_curve] = false;
break;
@@ -1039,7 +1121,7 @@ static GVArray adapt_curve_domain_point_to_curve(const CurvesGeometry &curves,
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
if constexpr (!std::is_void_v<attribute_math::DefaultMixer<T>>) {
- Array<T> values(curves.curves_size());
+ Array<T> values(curves.curves_num());
adapt_curve_domain_point_to_curve_impl<T>(curves, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
}
@@ -1059,8 +1141,8 @@ static void adapt_curve_domain_curve_to_point_impl(const CurvesGeometry &curves,
const VArray<T> &old_values,
MutableSpan<T> r_values)
{
- for (const int i_curve : IndexRange(curves.curves_size())) {
- r_values.slice(curves.range_for_curve(i_curve)).fill(old_values[i_curve]);
+ for (const int i_curve : IndexRange(curves.curves_num())) {
+ r_values.slice(curves.points_for_curve(i_curve)).fill(old_values[i_curve]);
}
}
@@ -1070,7 +1152,7 @@ static GVArray adapt_curve_domain_curve_to_point(const CurvesGeometry &curves,
GVArray new_varray;
attribute_math::convert_to_static_type(varray.type(), [&](auto dummy) {
using T = decltype(dummy);
- Array<T> values(curves.points_size());
+ Array<T> values(curves.points_num());
adapt_curve_domain_curve_to_point_impl<T>(curves, varray.typed<T>(), values);
new_varray = VArray<T>::ForContainer(std::move(values));
});
diff --git a/source/blender/blenkernel/intern/curves_geometry_test.cc b/source/blender/blenkernel/intern/curves_geometry_test.cc
index 1b3b3f54451..e4dc9eead60 100644
--- a/source/blender/blenkernel/intern/curves_geometry_test.cc
+++ b/source/blender/blenkernel/intern/curves_geometry_test.cc
@@ -46,7 +46,7 @@ TEST(curves_geometry, Move)
CurvesGeometry other = std::move(curves);
/* The old curves should be empty, and the offsets are expected to be null. */
- EXPECT_EQ(curves.points_size(), 0); /* NOLINT: bugprone-use-after-move */
+ EXPECT_EQ(curves.points_num(), 0); /* NOLINT: bugprone-use-after-move */
EXPECT_EQ(curves.curve_offsets, nullptr); /* NOLINT: bugprone-use-after-move */
/* Just a basic check that the new curves work okay. */
@@ -63,6 +63,28 @@ TEST(curves_geometry, Move)
EXPECT_EQ(second_other.offsets().data(), offsets_data);
}
+TEST(curves_geometry, TypeCount)
+{
+ CurvesGeometry curves = create_basic_curves(100, 10);
+ curves.curve_types().copy_from({
+ CURVE_TYPE_BEZIER,
+ CURVE_TYPE_NURBS,
+ CURVE_TYPE_NURBS,
+ CURVE_TYPE_NURBS,
+ CURVE_TYPE_CATMULL_ROM,
+ CURVE_TYPE_CATMULL_ROM,
+ CURVE_TYPE_CATMULL_ROM,
+ CURVE_TYPE_POLY,
+ CURVE_TYPE_POLY,
+ CURVE_TYPE_POLY,
+ });
+ std::array<int, CURVE_TYPES_NUM> counts = curves.count_curve_types();
+ EXPECT_EQ(counts[CURVE_TYPE_CATMULL_ROM], 3);
+ EXPECT_EQ(counts[CURVE_TYPE_POLY], 3);
+ EXPECT_EQ(counts[CURVE_TYPE_BEZIER], 1);
+ EXPECT_EQ(counts[CURVE_TYPE_NURBS], 3);
+}
+
TEST(curves_geometry, CatmullRomEvaluation)
{
CurvesGeometry curves(4, 1);
@@ -206,7 +228,7 @@ TEST(curves_geometry, CatmullRomTwoPointCyclic)
/* The cyclic value should be ignored when there are only two control points. There should
* be 12 evaluated points for the single segment and an extra for the last point. */
- EXPECT_EQ(curves.evaluated_points_size(), 13);
+ EXPECT_EQ(curves.evaluated_points_num(), 13);
}
TEST(curves_geometry, BezierPositionEvaluation)
@@ -383,4 +405,77 @@ TEST(curves_geometry, NURBSEvaluation)
}
}
+TEST(curves_geometry, BezierGenericEvaluation)
+{
+ CurvesGeometry curves(3, 1);
+ curves.curve_types().fill(CURVE_TYPE_BEZIER);
+ curves.resolution().fill(8);
+ curves.offsets().last() = 3;
+
+ MutableSpan<float3> handles_left = curves.handle_positions_left();
+ MutableSpan<float3> handles_right = curves.handle_positions_right();
+ MutableSpan<float3> positions = curves.positions();
+ positions.first() = {-1, 0, 0};
+ handles_right.first() = {-1, 1, 0};
+ handles_left[1] = {0, 0, 0};
+ positions[1] = {1, 0, 0};
+ handles_right[1] = {2, 0, 0};
+ handles_left.last() = {1, 1, 0};
+ positions.last() = {2, 1, 0};
+
+ /* Dangling handles shouldn't be used in a non-cyclic curve. */
+ handles_left.first() = {100, 100, 100};
+ handles_right.last() = {100, 100, 100};
+
+ Span<float3> evaluated_positions = curves.evaluated_positions();
+ static const Array<float3> result_1{{
+ {-1.0f, 0.0f, 0.0f},
+ {-0.955078f, 0.287109f, 0.0f},
+ {-0.828125f, 0.421875f, 0.0f},
+ {-0.630859f, 0.439453f, 0.0f},
+ {-0.375f, 0.375f, 0.0f},
+ {-0.0722656f, 0.263672f, 0.0f},
+ {0.265625f, 0.140625f, 0.0f},
+ {0.626953f, 0.0410156f, 0.0f},
+ {1.0f, 0.0f, 0.0f},
+ {1.28906f, 0.0429688f, 0.0f},
+ {1.4375f, 0.15625f, 0.0f},
+ {1.49219f, 0.316406f, 0.0f},
+ {1.5f, 0.5f, 0.0f},
+ {1.50781f, 0.683594f, 0.0f},
+ {1.5625f, 0.84375f, 0.0f},
+ {1.71094f, 0.957031f, 0.0f},
+ {2.0f, 1.0f, 0.0f},
+ }};
+ for (const int i : evaluated_positions.index_range()) {
+ EXPECT_V3_NEAR(evaluated_positions[i], result_1[i], 1e-5f);
+ }
+
+ Array<float> radii{{0.0f, 1.0f, 2.0f}};
+ Array<float> evaluated_radii(17);
+ curves.interpolate_to_evaluated(0, radii.as_span(), evaluated_radii.as_mutable_span());
+ static const Array<float> result_2{{
+ 0.0f,
+ 0.125f,
+ 0.25f,
+ 0.375f,
+ 0.5f,
+ 0.625f,
+ 0.75f,
+ 0.875f,
+ 1.0f,
+ 1.125f,
+ 1.25f,
+ 1.375f,
+ 1.5f,
+ 1.625f,
+ 1.75f,
+ 1.875f,
+ 2.0f,
+ }};
+ for (const int i : evaluated_radii.index_range()) {
+ EXPECT_NEAR(evaluated_radii[i], result_2[i], 1e-6f);
+ }
+}
+
} // namespace blender::bke::tests
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index e5424b39091..702488fb93b 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -62,6 +62,10 @@ BLI_STATIC_ASSERT(ARRAY_SIZE(((CustomData *)nullptr)->typemap) == CD_NUMTYPES, "
static CLG_LogRef LOG = {"bke.customdata"};
+/* -------------------------------------------------------------------- */
+/** \name Mesh Mask Utilities
+ * \{ */
+
void CustomData_MeshMasks_update(CustomData_MeshMasks *mask_dst,
const CustomData_MeshMasks *mask_src)
{
@@ -82,7 +86,12 @@ bool CustomData_MeshMasks_are_matching(const CustomData_MeshMasks *mask_ref,
((mask_required->lmask & mask_ref->lmask) == mask_required->lmask));
}
-/********************* Layer type information **********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Layer Type Information
+ * \{ */
+
struct LayerTypeInfo {
int size; /* the memory size of one element of this layer's data */
@@ -164,6 +173,12 @@ struct LayerTypeInfo {
int (*layers_max)();
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#MDeformVert, #CD_MDEFORMVERT)
+ * \{ */
+
static void layerCopy_mdeformvert(const void *source, void *dest, int count)
{
int i, size = sizeof(MDeformVert);
@@ -315,6 +330,12 @@ static void layerInterp_mdeformvert(const void **sources,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#vec3f, #CD_NORMAL)
+ * \{ */
+
static void layerInterp_normal(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
@@ -371,6 +392,12 @@ static void layerCopyValue_normal(const void *source,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#MTFace, #CD_MTFACE)
+ * \{ */
+
static void layerCopy_tface(const void *source, void *dest, int count)
{
const MTFace *source_tf = (const MTFace *)source;
@@ -436,6 +463,12 @@ static int layerMaxNum_tface()
return MAX_MTFACE;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#MFloatProperty, #CD_PROP_FLOAT)
+ * \{ */
+
static void layerCopy_propFloat(const void *source, void *dest, int count)
{
memcpy(dest, source, sizeof(MFloatProperty) * count);
@@ -473,16 +506,34 @@ static bool layerValidate_propFloat(void *data, const uint totitems, const bool
return has_errors;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#MIntProperty, #CD_PROP_INT32)
+ * \{ */
+
static void layerCopy_propInt(const void *source, void *dest, int count)
{
memcpy(dest, source, sizeof(MIntProperty) * count);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#MStringProperty, #CD_PROP_STRING)
+ * \{ */
+
static void layerCopy_propString(const void *source, void *dest, int count)
{
memcpy(dest, source, sizeof(MStringProperty) * count);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#OrigSpaceFace, #CD_ORIGSPACE)
+ * \{ */
+
static void layerCopy_origspace_face(const void *source, void *dest, int count)
{
const OrigSpaceFace *source_tf = (const OrigSpaceFace *)source;
@@ -541,6 +592,12 @@ static void layerDefault_origspace_face(void *data, int count)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#MDisps, #CD_MDISPS)
+ * \{ */
+
static void layerSwap_mdisps(void *data, const int *ci)
{
MDisps *s = static_cast<MDisps *>(data);
@@ -653,6 +710,13 @@ static size_t layerFilesize_mdisps(CDataFile *UNUSED(cdf), const void *data, int
return size;
}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (`float`, #CD_PAINT_MASK)
+ * \{ */
+
static void layerInterp_paint_mask(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
@@ -668,6 +732,12 @@ static void layerInterp_paint_mask(const void **sources,
*(float *)dest = mask;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#GridPaintMask, #CD_GRID_PAINT_MASK)
+ * \{ */
+
static void layerCopy_grid_paint_mask(const void *source, void *dest, int count)
{
const GridPaintMask *s = static_cast<const GridPaintMask *>(source);
@@ -1179,6 +1249,12 @@ static void layerInterp_shapekey(const void **sources,
copy_v3_v3((float *)dest, co);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#MVertSkin, #CD_MVERT_SKIN)
+ * \{ */
+
static void layerDefault_mvert_skin(void *data, int count)
{
MVertSkin *vs = static_cast<MVertSkin *>(data);
@@ -1216,6 +1292,12 @@ static void layerInterp_mvert_skin(const void **sources,
vs_dst->flag &= ~MVERT_SKIN_ROOT;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (`short[4][3]`, #CD_TESSLOOPNORMAL)
+ * \{ */
+
static void layerSwap_flnor(void *data, const int *corner_indices)
{
short(*flnors)[4][3] = static_cast<short(*)[4][3]>(data);
@@ -1229,6 +1311,12 @@ static void layerSwap_flnor(void *data, const int *corner_indices)
memcpy(flnors, nors, sizeof(nors));
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (`int`, #CD_FACEMAP)
+ * \{ */
+
static void layerDefault_fmap(void *data, int count)
{
int *fmap_num = (int *)data;
@@ -1237,6 +1325,12 @@ static void layerDefault_fmap(void *data, int count)
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#MPropCol, #CD_PROP_COLOR)
+ * \{ */
+
static void layerCopyValue_propcol(const void *source,
void *dest,
const int mixmode,
@@ -1360,6 +1454,12 @@ static int layerMaxNum_propcol()
return MAX_MCOL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#vec3f, #CD_PROP_FLOAT3)
+ * \{ */
+
static void layerInterp_propfloat3(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
@@ -1407,6 +1507,12 @@ static bool layerValidate_propfloat3(void *data, const uint totitems, const bool
return has_errors;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (#vec2f, #CD_PROP_FLOAT2)
+ * \{ */
+
static void layerInterp_propfloat2(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
@@ -1452,6 +1558,12 @@ static bool layerValidate_propfloat2(void *data, const uint totitems, const bool
return has_errors;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Callbacks for (`bool`, #CD_PROP_BOOL)
+ * \{ */
+
static void layerInterp_propbool(const void **sources,
const float *weights,
const float *UNUSED(sub_weights),
@@ -2053,7 +2165,12 @@ void customData_mask_layers__print(const CustomData_MeshMasks *mask)
}
}
-/********************* CustomData functions *********************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name CustomData Functions
+ * \{ */
+
static void customData_update_offsets(CustomData *data);
static CustomDataLayer *customData_add_layer__internal(CustomData *data,
@@ -4471,14 +4588,18 @@ void CustomData_layers__print(CustomData *data)
printf("}\n");
}
-/****************************** External Files *******************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name External Files
+ * \{ */
-static void customdata_external_filename(char filename[FILE_MAX],
+static void customdata_external_filename(char filepath[FILE_MAX],
ID *id,
CustomDataExternal *external)
{
- BLI_strncpy(filename, external->filename, FILE_MAX);
- BLI_path_abs(filename, ID_BLEND_PATH_FROM_GLOBAL(id));
+ BLI_strncpy(filepath, external->filepath, FILE_MAX);
+ BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(id));
}
void CustomData_external_reload(CustomData *data, ID *UNUSED(id), CustomDataMask mask, int totelem)
@@ -4503,7 +4624,7 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
{
CustomDataExternal *external = data->external;
CustomDataLayer *layer;
- char filename[FILE_MAX];
+ char filepath[FILE_MAX];
int update = 0;
if (!external) {
@@ -4529,12 +4650,12 @@ void CustomData_external_read(CustomData *data, ID *id, CustomDataMask mask, int
return;
}
- customdata_external_filename(filename, id, external);
+ customdata_external_filename(filepath, id, external);
CDataFile *cdf = cdf_create(CDF_TYPE_MESH);
- if (!cdf_read_open(cdf, filename)) {
+ if (!cdf_read_open(cdf, filepath)) {
cdf_free(cdf);
- CLOG_ERROR(&LOG, "Failed to read %s layer from %s.", layerType_getName(layer->type), filename);
+ CLOG_ERROR(&LOG, "Failed to read %s layer from %s.", layerType_getName(layer->type), filepath);
return;
}
@@ -4577,7 +4698,7 @@ void CustomData_external_write(
{
CustomDataExternal *external = data->external;
int update = 0;
- char filename[FILE_MAX];
+ char filepath[FILE_MAX];
if (!external) {
return;
@@ -4602,7 +4723,7 @@ void CustomData_external_write(
/* make sure data is read before we try to write */
CustomData_external_read(data, id, mask, totelem);
- customdata_external_filename(filename, id, external);
+ customdata_external_filename(filepath, id, external);
CDataFile *cdf = cdf_create(CDF_TYPE_MESH);
@@ -4622,8 +4743,8 @@ void CustomData_external_write(
}
}
- if (!cdf_write_open(cdf, filename)) {
- CLOG_ERROR(&LOG, "Failed to open %s for writing.", filename);
+ if (!cdf_write_open(cdf, filepath)) {
+ CLOG_ERROR(&LOG, "Failed to open %s for writing.", filepath);
cdf_free(cdf);
return;
}
@@ -4651,7 +4772,7 @@ void CustomData_external_write(
}
if (i != data->totlayer) {
- CLOG_ERROR(&LOG, "Failed to write data to %s.", filename);
+ CLOG_ERROR(&LOG, "Failed to write data to %s.", filepath);
cdf_write_close(cdf);
cdf_free(cdf);
return;
@@ -4676,7 +4797,7 @@ void CustomData_external_write(
}
void CustomData_external_add(
- CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filename)
+ CustomData *data, ID *UNUSED(id), int type, int UNUSED(totelem), const char *filepath)
{
CustomDataExternal *external = data->external;
@@ -4695,7 +4816,7 @@ void CustomData_external_add(
external = MEM_cnew<CustomDataExternal>(__func__);
data->external = external;
}
- BLI_strncpy(external->filename, filename, sizeof(external->filename));
+ BLI_strncpy(external->filepath, filepath, sizeof(external->filepath));
layer->flag |= CD_FLAG_EXTERNAL | CD_FLAG_IN_MEMORY;
}
@@ -4735,7 +4856,12 @@ bool CustomData_external_test(CustomData *data, int type)
return (layer->flag & CD_FLAG_EXTERNAL) != 0;
}
-/* ********** Mesh-to-mesh data transfer ********** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Mesh-to-Mesh Data Transfer
+ * \{ */
+
static void copy_bit_flag(void *dst, const void *src, const size_t data_size, const uint64_t flag)
{
#define COPY_BIT_FLAG(_type, _dst, _src, _f) \
@@ -5014,6 +5140,12 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap,
MEM_SAFE_FREE(tmp_data_src);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Custom Data IO
+ * \{ */
+
static void write_mdisps(BlendWriter *writer, int count, MDisps *mdlist, int external)
{
if (mdlist) {
@@ -5208,6 +5340,12 @@ void CustomData_blend_read(BlendDataReader *reader, CustomData *data, int count)
CustomData_update_typemap(data);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Custom Data Debugging
+ * \{ */
+
#ifndef NDEBUG
void CustomData_debug_info_from_layers(const CustomData *data, const char *indent, DynStr *dynstr)
@@ -5238,8 +5376,16 @@ void CustomData_debug_info_from_layers(const CustomData *data, const char *inden
#endif /* NDEBUG */
+/** \} */
+
namespace blender::bke {
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Custom Data C++ API
+ * \{ */
+
const blender::CPPType *custom_data_type_to_cpp_type(const CustomDataType type)
{
switch (type) {
@@ -5289,4 +5435,6 @@ CustomDataType cpp_type_to_custom_data_type(const blender::CPPType &type)
return static_cast<CustomDataType>(-1);
}
+/** \} */
+
} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 8ec7bbea0e5..0f5814c0a23 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -3266,7 +3266,7 @@ static void dynamic_paint_output_surface_image_wetmap_cb(
}
void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface,
- char *filename,
+ const char *filepath,
short output_layer)
{
ImBuf *ibuf = NULL;
@@ -3286,7 +3286,7 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface,
format = R_IMF_IMTYPE_PNG;
}
#endif
- BLI_strncpy(output_file, filename, sizeof(output_file));
+ BLI_strncpy(output_file, filepath, sizeof(output_file));
BKE_image_path_ensure_ext_from_imtype(output_file, format);
/* Validate output file path */
diff --git a/source/blender/blenkernel/intern/geometry_component_curves.cc b/source/blender/blenkernel/intern/geometry_component_curves.cc
index 7cf6fc5a03e..27689d70c77 100644
--- a/source/blender/blenkernel/intern/geometry_component_curves.cc
+++ b/source/blender/blenkernel/intern/geometry_component_curves.cc
@@ -236,10 +236,10 @@ int CurveComponent::attribute_domain_size(const AttributeDomain domain) const
const blender::bke::CurvesGeometry &geometry = blender::bke::CurvesGeometry::wrap(
curves_->geometry);
if (domain == ATTR_DOMAIN_POINT) {
- return geometry.points_size();
+ return geometry.points_num();
}
if (domain == ATTR_DOMAIN_CURVE) {
- return geometry.curves_size();
+ return geometry.curves_num();
}
return 0;
}
diff --git a/source/blender/blenkernel/intern/geometry_component_mesh.cc b/source/blender/blenkernel/intern/geometry_component_mesh.cc
index 76c8a0054b3..2bfe984462c 100644
--- a/source/blender/blenkernel/intern/geometry_component_mesh.cc
+++ b/source/blender/blenkernel/intern/geometry_component_mesh.cc
@@ -944,20 +944,71 @@ class VArrayImpl_For_VertexWeights final : public VMutableArrayImpl<float> {
if (dverts_ == nullptr) {
return 0.0f;
}
- const MDeformVert &dvert = dverts_[index];
- for (const MDeformWeight &weight : Span(dvert.dw, dvert.totweight)) {
- if (weight.def_nr == dvert_index_) {
- return weight.weight;
- }
+ if (const MDeformWeight *weight = this->find_weight_at_index(index)) {
+ return weight->weight;
}
return 0.0f;
- ;
}
void set(const int64_t index, const float value) override
{
- MDeformWeight *weight = BKE_defvert_ensure_index(&dverts_[index], dvert_index_);
- weight->weight = value;
+ MDeformVert &dvert = dverts_[index];
+ if (value == 0.0f) {
+ if (MDeformWeight *weight = this->find_weight_at_index(index)) {
+ weight->weight = 0.0f;
+ }
+ }
+ else {
+ MDeformWeight *weight = BKE_defvert_ensure_index(&dvert, dvert_index_);
+ weight->weight = value;
+ }
+ }
+
+ void set_all(Span<float> src) override
+ {
+ for (const int64_t index : src.index_range()) {
+ this->set(index, src[index]);
+ }
+ }
+
+ void materialize(IndexMask mask, MutableSpan<float> r_span) const override
+ {
+ if (dverts_ == nullptr) {
+ return r_span.fill_indices(mask, 0.0f);
+ }
+ for (const int64_t index : mask) {
+ if (const MDeformWeight *weight = this->find_weight_at_index(index)) {
+ r_span[index] = weight->weight;
+ }
+ else {
+ r_span[index] = 0.0f;
+ }
+ }
+ }
+
+ void materialize_to_uninitialized(IndexMask mask, MutableSpan<float> r_span) const override
+ {
+ this->materialize(mask, r_span);
+ }
+
+ private:
+ MDeformWeight *find_weight_at_index(const int64_t index)
+ {
+ for (MDeformWeight &weight : MutableSpan(dverts_[index].dw, dverts_[index].totweight)) {
+ if (weight.def_nr == dvert_index_) {
+ return &weight;
+ }
+ }
+ return nullptr;
+ }
+ const MDeformWeight *find_weight_at_index(const int64_t index) const
+ {
+ for (const MDeformWeight &weight : Span(dverts_[index].dw, dverts_[index].totweight)) {
+ if (weight.def_nr == dvert_index_) {
+ return &weight;
+ }
+ }
+ return nullptr;
}
};
diff --git a/source/blender/blenkernel/intern/gpencil_geom.cc b/source/blender/blenkernel/intern/gpencil_geom.cc
index a5eff1f9d5a..a0b6ab2d654 100644
--- a/source/blender/blenkernel/intern/gpencil_geom.cc
+++ b/source/blender/blenkernel/intern/gpencil_geom.cc
@@ -980,74 +980,116 @@ bool BKE_gpencil_stroke_shrink(bGPDstroke *gps, const float dist, const short mo
/** \name Stroke Smooth Positions
* \{ */
-bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf, const bool smooth_caps)
+bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps,
+ int i,
+ float influence,
+ int iterations,
+ const bool smooth_caps,
+ const bool keep_shape,
+ bGPDstroke *r_gps)
{
- bGPDspoint *pt = &gps->points[i];
- float sco[3] = {0.0f};
- const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
-
- /* Do nothing if not enough points to smooth out */
- if (gps->totpoints <= 2) {
+ /* If nothing to do, return early */
+ if (gps->totpoints <= 2 || iterations <= 0) {
return false;
}
- /* Only affect endpoints by a fraction of the normal strength,
- * to prevent the stroke from shrinking too much
+ /* Overview of the algorithm here and in the following smooth functions:
+ * The smooth functions return the new attribute in question for a single point.
+ * The result is stored in r_gps->points[i], while the data is read from gps.
+ * To get a correct result, duplicate the stroke point data and read from the copy,
+ * while writing to the real stroke. Not doing that will result in acceptable, but
+ * asymmetric results.
+ * This algorithm works as long as all points are being smoothed. If there is
+ * points that should not get smoothed, use the old repeat smooth pattern with
+ * the parameter "iterations" set to 1 or 2. (2 matches the old algorithm).
*/
- if ((!smooth_caps) && (!is_cyclic && ELEM(i, 0, gps->totpoints - 1))) {
- inf *= 0.1f;
- }
-
- /* Compute smoothed coordinate by taking the ones nearby */
- /* XXX: This is potentially slow,
- * and suffers from accumulation error as earlier points are handled before later ones. */
- {
- /* XXX: this is hardcoded to look at 2 points on either side of the current one
- * (i.e. 5 items total). */
- const int steps = 2;
- const float average_fac = 1.0f / (float)(steps * 2 + 1);
- int step;
-
- /* add the point itself */
- madd_v3_v3fl(sco, &pt->x, average_fac);
-
- /* n-steps before/after current point */
- /* XXX: review how the endpoints are treated by this algorithm. */
- /* XXX: falloff measures should also introduce some weighting variations,
- * so that further-out points get less weight. */
- for (step = 1; step <= steps; step++) {
- bGPDspoint *pt1, *pt2;
- int before = i - step;
- int after = i + step;
-
- if (is_cyclic) {
- if (before < 0) {
- /* Sub to end point (before is already negative). */
- before = gps->totpoints + before;
- CLAMP(before, 0, gps->totpoints - 1);
- }
- if (after > gps->totpoints - 1) {
- /* Add to start point. */
- after = after - gps->totpoints;
- CLAMP(after, 0, gps->totpoints - 1);
+
+ const bGPDspoint *pt = &gps->points[i];
+ const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
+ /* If smooth_caps is false, the caps will not be translated by smoothing. */
+ if (!smooth_caps && !is_cyclic && ELEM(i, 0, gps->totpoints - 1)) {
+ copy_v3_v3(&r_gps->points[i].x, &pt->x);
+ return true;
+ }
+
+ /* This function uses a binomial kernel, which is the discrete version of gaussian blur.
+ * The weight for a vertex at the relative index i is
+ * w = nCr(n, j + n/2) / 2^n = (n/1 * (n-1)/2 * ... * (n-j-n/2)/(j+n/2)) / 2^n
+ * All weights together sum up to 1
+ * This is equivalent to doing multiple iterations of averaging neighbors,
+ * where n = iterations * 2 and -n/2 <= j <= n/2
+ *
+ * Now the problem is that nCr(n, j + n/2) is very hard to compute for n > 500, since even
+ * double precision isn't sufficient. A very good robust approximation for n > 20 is
+ * nCr(n, j + n/2) / 2^n = sqrt(2/(pi*n)) * exp(-2*j*j/n)
+ *
+ * There is one more problem left: The old smooth algorithm was doing a more aggressive
+ * smooth. To solve that problem, choose a different n/2, which does not match the range and
+ * normalize the weights on finish. This may cause some artifacts at low values.
+ *
+ * keep_shape is a new option to stop the stroke from severly deforming.
+ * It uses different partially negative weights.
+ * w = 2 * (nCr(n, j + n/2) / 2^n) - (nCr(3*n, j + n) / 2^(3*n))
+ * ~ 2 * sqrt(2/(pi*n)) * exp(-2*j*j/n) - sqrt(2/(pi*3*n)) * exp(-2*j*j/(3*n))
+ * All weigths still sum up to 1.
+ * Note these weights only work because the averaging is done in relative coordinates.
+ */
+ float sco[3] = {0.0f, 0.0f, 0.0f};
+ float tmp[3];
+ const int n_half = keep_shape ? (iterations * iterations) / 8 + iterations :
+ (iterations * iterations) / 4 + 2 * iterations + 12;
+ double w = keep_shape ? 2.0 : 1.0;
+ double w2 = keep_shape ?
+ (1.0 / M_SQRT3) * exp((2 * iterations * iterations) / (double)(n_half * 3)) :
+ 0.0;
+ double total_w = 0.0;
+ for (int step = iterations; step > 0; step--) {
+ int before = i - step;
+ int after = i + step;
+ float w_before = (float)(w - w2);
+ float w_after = (float)(w - w2);
+
+ if (is_cyclic) {
+ before = (before % gps->totpoints + gps->totpoints) % gps->totpoints;
+ after = after % gps->totpoints;
+ }
+ else {
+ if (before < 0) {
+ if (!smooth_caps) {
+ w_before *= -before / (float)i;
}
+ before = 0;
}
- else {
- CLAMP_MIN(before, 0);
- CLAMP_MAX(after, gps->totpoints - 1);
+ if (after > gps->totpoints - 1) {
+ if (!smooth_caps) {
+ w_after *= (after - (gps->totpoints - 1)) / (float)(gps->totpoints - 1 - i);
+ }
+ after = gps->totpoints - 1;
}
+ }
- pt1 = &gps->points[before];
- pt2 = &gps->points[after];
+ /* Add both these points in relative coordinates to the weighted average sum. */
+ sub_v3_v3v3(tmp, &gps->points[before].x, &pt->x);
+ madd_v3_v3fl(sco, tmp, w_before);
+ sub_v3_v3v3(tmp, &gps->points[after].x, &pt->x);
+ madd_v3_v3fl(sco, tmp, w_after);
- /* add both these points to the average-sum (s += p[i]/n) */
- madd_v3_v3fl(sco, &pt1->x, average_fac);
- madd_v3_v3fl(sco, &pt2->x, average_fac);
- }
+ total_w += w_before;
+ total_w += w_after;
+
+ w *= (n_half + step) / (double)(n_half + 1 - step);
+ w2 *= (n_half * 3 + step) / (double)(n_half * 3 + 1 - step);
}
+ total_w += w - w2;
+ /* The accumulated weight total_w should be
+ * ~sqrt(M_PI * n_half) * exp((iterations * iterations) / n_half) < 100
+ * here, but sometimes not quite. */
+ mul_v3_fl(sco, (float)(1.0 / total_w));
+ /* Shift back to global coordinates. */
+ add_v3_v3(sco, &pt->x);
- /* Based on influence factor, blend between original and optimal smoothed coordinate */
- interp_v3_v3v3(&pt->x, &pt->x, sco, inf);
+ /* Based on influence factor, blend between original and optimal smoothed coordinate. */
+ interp_v3_v3v3(&r_gps->points[i].x, &pt->x, sco, influence);
return true;
}
@@ -1058,74 +1100,54 @@ bool BKE_gpencil_stroke_smooth_point(bGPDstroke *gps, int i, float inf, const bo
/** \name Stroke Smooth Strength
* \{ */
-bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_strength(
+ bGPDstroke *gps, int i, float influence, int iterations, bGPDstroke *r_gps)
{
- bGPDspoint *ptb = &gps->points[point_index];
- const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
-
- /* Do nothing if not enough points */
- if ((gps->totpoints <= 2) || (point_index < 1)) {
+ /* If nothing to do, return early */
+ if (gps->totpoints <= 2 || iterations <= 0) {
return false;
}
- /* Only affect endpoints by a fraction of the normal influence */
- float inf = influence;
- if (!is_cyclic && ELEM(point_index, 0, gps->totpoints - 1)) {
- inf *= 0.01f;
- }
- /* Limit max influence to reduce pop effect. */
- CLAMP_MAX(inf, 0.98f);
-
- float total = 0.0f;
- float max_strength = 0.0f;
- const int steps = 4;
- const float average_fac = 1.0f / (float)(steps * 2 + 1);
- int step;
- /* add the point itself */
- total += ptb->strength * average_fac;
- max_strength = ptb->strength;
+ /* See BKE_gpencil_stroke_smooth_point for details on the algorithm. */
- /* n-steps before/after current point */
- for (step = 1; step <= steps; step++) {
- bGPDspoint *pt1, *pt2;
- int before = point_index - step;
- int after = point_index + step;
+ const bGPDspoint *pt = &gps->points[i];
+ const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
+ float strength = 0.0f;
+ const int n_half = (iterations * iterations) / 4 + iterations;
+ double w = 1.0;
+ double total_w = 0.0;
+ for (int step = iterations; step > 0; step--) {
+ int before = i - step;
+ int after = i + step;
+ float w_before = (float)w;
+ float w_after = (float)w;
if (is_cyclic) {
- if (before < 0) {
- /* Sub to end point (before is already negative). */
- before = gps->totpoints + before;
- CLAMP(before, 0, gps->totpoints - 1);
- }
- if (after > gps->totpoints - 1) {
- /* Add to start point. */
- after = after - gps->totpoints;
- CLAMP(after, 0, gps->totpoints - 1);
- }
+ before = (before % gps->totpoints + gps->totpoints) % gps->totpoints;
+ after = after % gps->totpoints;
}
else {
CLAMP_MIN(before, 0);
CLAMP_MAX(after, gps->totpoints - 1);
}
- pt1 = &gps->points[before];
- pt2 = &gps->points[after];
- /* add both these points to the average-sum (s += p[i]/n) */
- total += pt1->strength * average_fac;
- total += pt2->strength * average_fac;
- /* Save max value. */
- if (max_strength < pt1->strength) {
- max_strength = pt1->strength;
- }
- if (max_strength < pt2->strength) {
- max_strength = pt2->strength;
- }
+ /* Add both these points in relative coordinates to the weighted average sum. */
+ strength += w_before * (gps->points[before].strength - pt->strength);
+ strength += w_after * (gps->points[after].strength - pt->strength);
+
+ total_w += w_before;
+ total_w += w_after;
+
+ w *= (n_half + step) / (double)(n_half + 1 - step);
}
+ total_w += w;
+ /* The accumulated weight total_w should be
+ * ~sqrt(M_PI * n_half) * exp((iterations * iterations) / n_half) < 100
+ * here, but sometimes not quite. */
+ strength /= total_w;
/* Based on influence factor, blend between original and optimal smoothed value. */
- ptb->strength = interpf(ptb->strength, total, inf);
- /* Clamp to maximum stroke strength to avoid weird results. */
- CLAMP_MAX(ptb->strength, max_strength);
+ r_gps->points[i].strength = pt->strength + strength * influence;
return true;
}
@@ -1136,74 +1158,55 @@ bool BKE_gpencil_stroke_smooth_strength(bGPDstroke *gps, int point_index, float
/** \name Stroke Smooth Thickness
* \{ */
-bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_thickness(
+ bGPDstroke *gps, int i, float influence, int iterations, bGPDstroke *r_gps)
{
- bGPDspoint *ptb = &gps->points[point_index];
- const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
-
- /* Do nothing if not enough points */
- if ((gps->totpoints <= 2) || (point_index < 1)) {
+ /* If nothing to do, return early */
+ if (gps->totpoints <= 2 || iterations <= 0) {
return false;
}
- /* Only affect endpoints by a fraction of the normal influence */
- float inf = influence;
- if (!is_cyclic && ELEM(point_index, 0, gps->totpoints - 1)) {
- inf *= 0.01f;
- }
- /* Limit max influence to reduce pop effect. */
- CLAMP_MAX(inf, 0.98f);
-
- float total = 0.0f;
- float max_pressure = 0.0f;
- const int steps = 4;
- const float average_fac = 1.0f / (float)(steps * 2 + 1);
- int step;
- /* add the point itself */
- total += ptb->pressure * average_fac;
- max_pressure = ptb->pressure;
+ /* See BKE_gpencil_stroke_smooth_point for details on the algorithm. */
- /* n-steps before/after current point */
- for (step = 1; step <= steps; step++) {
- bGPDspoint *pt1, *pt2;
- int before = point_index - step;
- int after = point_index + step;
+ const bGPDspoint *pt = &gps->points[i];
+ const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
+ float pressure = 0.0f;
+ const int n_half = (iterations * iterations) / 4 + iterations;
+ double w = 1.0;
+ double total_w = 0.0;
+ for (int step = iterations; step > 0; step--) {
+ int before = i - step;
+ int after = i + step;
+ float w_before = (float)w;
+ float w_after = (float)w;
if (is_cyclic) {
- if (before < 0) {
- /* Sub to end point (before is already negative). */
- before = gps->totpoints + before;
- CLAMP(before, 0, gps->totpoints - 1);
- }
- if (after > gps->totpoints - 1) {
- /* Add to start point. */
- after = after - gps->totpoints;
- CLAMP(after, 0, gps->totpoints - 1);
- }
+ before = (before % gps->totpoints + gps->totpoints) % gps->totpoints;
+ after = after % gps->totpoints;
}
else {
CLAMP_MIN(before, 0);
CLAMP_MAX(after, gps->totpoints - 1);
}
- pt1 = &gps->points[before];
- pt2 = &gps->points[after];
- /* add both these points to the average-sum (s += p[i]/n) */
- total += pt1->pressure * average_fac;
- total += pt2->pressure * average_fac;
- /* Save max value. */
- if (max_pressure < pt1->pressure) {
- max_pressure = pt1->pressure;
- }
- if (max_pressure < pt2->pressure) {
- max_pressure = pt2->pressure;
- }
+ /* Add both these points in relative coordinates to the weighted average sum. */
+ pressure += w_before * (gps->points[before].pressure - pt->pressure);
+ pressure += w_after * (gps->points[after].pressure - pt->pressure);
+
+ total_w += w_before;
+ total_w += w_after;
+
+ w *= (n_half + step) / (double)(n_half + 1 - step);
}
+ total_w += w;
+ /* The accumulated weight total_w should be
+ * ~sqrt(M_PI * n_half) * exp((iterations * iterations) / n_half) < 100
+ * here, but sometimes not quite. */
+ pressure /= total_w;
/* Based on influence factor, blend between original and optimal smoothed value. */
- ptb->pressure = interpf(ptb->pressure, total, inf);
- /* Clamp to maximum stroke thickness to avoid weird results. */
- CLAMP_MAX(ptb->pressure, max_pressure);
+ r_gps->points[i].pressure = pt->pressure + pressure * influence;
+
return true;
}
@@ -1213,57 +1216,127 @@ bool BKE_gpencil_stroke_smooth_thickness(bGPDstroke *gps, int point_index, float
/** \name Stroke Smooth UV
* \{ */
-bool BKE_gpencil_stroke_smooth_uv(bGPDstroke *gps, int point_index, float influence)
+bool BKE_gpencil_stroke_smooth_uv(
+ struct bGPDstroke *gps, int i, float influence, int iterations, struct bGPDstroke *r_gps)
{
- bGPDspoint *ptb = &gps->points[point_index];
+ /* If nothing to do, return early */
+ if (gps->totpoints <= 2 || iterations <= 0) {
+ return false;
+ }
+
+ /* See BKE_gpencil_stroke_smooth_point for details on the algorithm. */
+
+ const bGPDspoint *pt = &gps->points[i];
const bool is_cyclic = (gps->flag & GP_STROKE_CYCLIC) != 0;
- /* Do nothing if not enough points */
- if (gps->totpoints <= 2) {
- return false;
+ /* If don't change the caps. */
+ if (!is_cyclic && ELEM(i, 0, gps->totpoints - 1)) {
+ r_gps->points[i].uv_rot = pt->uv_rot;
+ r_gps->points[i].uv_fac = pt->uv_fac;
+ return true;
}
- /* Compute theoretical optimal value */
- bGPDspoint *pta, *ptc;
- int before = point_index - 1;
- int after = point_index + 1;
+ float uv_rot = 0.0f;
+ float uv_fac = 0.0f;
+ const int n_half = iterations * iterations + iterations;
+ double w = 1.0;
+ double total_w = 0.0;
+ for (int step = iterations; step > 0; step--) {
+ int before = i - step;
+ int after = i + step;
+ float w_before = (float)w;
+ float w_after = (float)w;
- if (is_cyclic) {
- if (before < 0) {
- /* Sub to end point (before is already negative). */
- before = gps->totpoints + before;
- CLAMP(before, 0, gps->totpoints - 1);
+ if (is_cyclic) {
+ before = (before % gps->totpoints + gps->totpoints) % gps->totpoints;
+ after = after % gps->totpoints;
}
- if (after > gps->totpoints - 1) {
- /* Add to start point. */
- after = after - gps->totpoints;
- CLAMP(after, 0, gps->totpoints - 1);
+ else {
+ if (before < 0) {
+ w_before *= -before / (float)i;
+ before = 0;
+ }
+ if (after > gps->totpoints - 1) {
+ w_after *= (after - (gps->totpoints - 1)) / (float)(gps->totpoints - 1 - i);
+ after = gps->totpoints - 1;
+ }
}
- }
- else {
- CLAMP_MIN(before, 0);
- CLAMP_MAX(after, gps->totpoints - 1);
- }
- pta = &gps->points[before];
- ptc = &gps->points[after];
- /* the optimal value is the corresponding to the interpolation of the pressure
- * at the distance of point b
- */
- float fac = line_point_factor_v3(&ptb->x, &pta->x, &ptc->x);
- /* sometimes the factor can be wrong due stroke geometry, so use middle point */
- if ((fac < 0.0f) || (fac > 1.0f)) {
- fac = 0.5f;
+ /* Add both these points in relative coordinates to the weighted average sum. */
+ uv_rot += w_before * (gps->points[before].uv_rot - pt->uv_rot);
+ uv_rot += w_after * (gps->points[after].uv_rot - pt->uv_rot);
+ uv_fac += w_before * (gps->points[before].uv_fac - pt->uv_fac);
+ uv_fac += w_after * (gps->points[after].uv_fac - pt->uv_fac);
+
+ total_w += w_before;
+ total_w += w_after;
+
+ w *= (n_half + step) / (double)(n_half + 1 - step);
}
- float optimal = interpf(ptc->uv_rot, pta->uv_rot, fac);
+ total_w += w;
+ /* The accumulated weight total_w should be
+ * ~sqrt(M_PI * n_half) * exp((iterations * iterations) / n_half) < 100
+ * here, but sometimes not quite. */
+ uv_rot /= total_w;
+ uv_fac /= total_w;
- /* Based on influence factor, blend between original and optimal */
- ptb->uv_rot = interpf(optimal, ptb->uv_rot, influence);
- CLAMP(ptb->uv_rot, -M_PI_2, M_PI_2);
+ /* Based on influence factor, blend between original and optimal smoothed value. */
+ r_gps->points[i].uv_rot = pt->uv_rot + uv_rot * influence;
+ r_gps->points[i].uv_fac = pt->uv_fac + uv_fac * influence;
return true;
}
+void BKE_gpencil_stroke_smooth(bGPDstroke *gps,
+ const float influence,
+ const int iterations,
+ const bool smooth_position,
+ const bool smooth_strength,
+ const bool smooth_thickness,
+ const bool smooth_uv,
+ const bool keep_shape,
+ const float *weights)
+{
+ if (influence <= 0 || iterations <= 0) {
+ return;
+ }
+
+ /* Make a copy of the point data to avoid directionality of the smooth operation. */
+ bGPDstroke gps_old = *gps;
+ gps_old.points = (bGPDspoint *)MEM_dupallocN(gps->points);
+
+ /* Smooth stroke. */
+ for (int i = 0; i < gps->totpoints; i++) {
+ float val = influence;
+ if (weights != NULL) {
+ val *= weights[i];
+ if (val <= 0.0f) {
+ continue;
+ }
+ }
+
+ /* TODO: Currently the weights only control the influence, but is would be much better if they
+ * would control the distribution used in smooth, similar to how the ends are handled. */
+
+ /* Perform smoothing. */
+ if (smooth_position) {
+ BKE_gpencil_stroke_smooth_point(&gps_old, i, val, iterations, false, keep_shape, gps);
+ }
+ if (smooth_strength) {
+ BKE_gpencil_stroke_smooth_strength(&gps_old, i, val, iterations, gps);
+ }
+ if (smooth_thickness) {
+ BKE_gpencil_stroke_smooth_thickness(&gps_old, i, val, iterations, gps);
+ }
+ if (smooth_uv) {
+ BKE_gpencil_stroke_smooth_uv(&gps_old, i, val, iterations, gps);
+ }
+ }
+
+ /* Free the copied points array. */
+ MEM_freeN(gps_old.points);
+}
+
void BKE_gpencil_stroke_2d_flat(const bGPDspoint *points,
int totpoints,
float (*points2d)[2],
@@ -3443,7 +3516,7 @@ void BKE_gpencil_stroke_join(bGPDstroke *gps_a,
for (i = start; i < end; i++) {
pt = &gps_a->points[i];
pt->pressure += (avg_pressure - pt->pressure) * ratio;
- BKE_gpencil_stroke_smooth_point(gps_a, i, ratio * 0.6f, false);
+ BKE_gpencil_stroke_smooth_point(gps_a, i, ratio * 0.6f, 2, false, true, gps_a);
ratio += step;
/* In the center, reverse the ratio. */
diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc
index cfdd048495d..3eade265bf2 100644
--- a/source/blender/blenkernel/intern/image.cc
+++ b/source/blender/blenkernel/intern/image.cc
@@ -9,6 +9,7 @@
#include <cmath>
#include <cstdio>
#include <cstring>
+#include <ctime>
#include <fcntl.h>
#ifndef WIN32
# include <unistd.h>
@@ -16,7 +17,8 @@
# include <io.h>
#endif
-#include <ctime>
+#include <regex>
+#include <string>
#include "BLI_array.hh"
@@ -237,7 +239,7 @@ static void image_foreach_cache(ID *id,
auto gputexture_offset = [image](int target, int eye, int resolution) {
constexpr size_t base_offset = offsetof(Image, gputexture);
- const auto first = &image->gputexture[0][0][0];
+ struct GPUTexture **first = &image->gputexture[0][0][0];
const size_t array_offset = sizeof(*first) *
(&image->gputexture[target][eye][resolution] - first);
return base_offset + array_offset;
@@ -466,7 +468,9 @@ constexpr IDTypeInfo get_type_info()
IDTypeInfo IDType_ID_IM = get_type_info();
/* prototypes */
-static int image_num_files(struct Image *ima);
+static int image_num_viewfiles(Image *ima);
+static ImBuf *image_load_image_file(
+ Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence);
static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock);
static void image_update_views_format(Image *ima, ImageUser *iuser);
static void image_add_view(Image *ima, const char *viewname, const char *filepath);
@@ -487,9 +491,9 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
/** \name Image Cache
* \{ */
-typedef struct ImageCacheKey {
+struct ImageCacheKey {
int index;
-} ImageCacheKey;
+};
static unsigned int imagecache_hashhash(const void *key_v)
{
@@ -1275,9 +1279,9 @@ bool BKE_image_memorypack(Image *ima)
void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
{
- const int totfiles = image_num_files(ima);
+ const int tot_viewfiles = image_num_viewfiles(ima);
- if (totfiles == 1) {
+ if (tot_viewfiles == 1) {
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
MEM_mallocN(sizeof(ImagePackedFile), "Image packed file"));
BLI_addtail(&ima->packedfiles, imapf);
@@ -1311,9 +1315,9 @@ void BKE_image_packfiles_from_mem(ReportList *reports,
char *data,
const size_t data_len)
{
- const int totfiles = image_num_files(ima);
+ const int tot_viewfiles = image_num_viewfiles(ima);
- if (totfiles != 1) {
+ if (tot_viewfiles != 1) {
BKE_report(reports, RPT_ERROR, "Cannot pack multiview images from raw data currently...");
}
else {
@@ -2942,9 +2946,9 @@ void BKE_image_signal(Main *bmain, Image *ima, ImageUser *iuser, int signal)
case IMA_SIGNAL_RELOAD:
/* try to repack file */
if (BKE_image_has_packedfile(ima)) {
- const int totfiles = image_num_files(ima);
+ const int tot_viewfiles = image_num_viewfiles(ima);
- if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
+ if (tot_viewfiles != BLI_listbase_count_at_most(&ima->packedfiles, tot_viewfiles + 1)) {
/* in case there are new available files to be loaded */
image_free_packedfiles(ima);
BKE_image_packfiles(nullptr, ima, ID_BLEND_PATH(bmain, &ima->id));
@@ -3111,14 +3115,15 @@ bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *tile_start, i
int max_udim = 0;
int id;
- struct direntry *dir;
- uint totfile = BLI_filelist_dir_contents(dirname, &dir);
- for (int i = 0; i < totfile; i++) {
- if (!(dir[i].type & S_IFREG)) {
+ struct direntry *dirs;
+ const uint dirs_num = BLI_filelist_dir_contents(dirname, &dirs);
+ for (int i = 0; i < dirs_num; i++) {
+ if (!(dirs[i].type & S_IFREG)) {
continue;
}
- if (!BKE_image_get_tile_number_from_filepath(dir[i].relname, udim_pattern, tile_format, &id)) {
+ if (!BKE_image_get_tile_number_from_filepath(
+ dirs[i].relname, udim_pattern, tile_format, &id)) {
continue;
}
@@ -3131,7 +3136,7 @@ bool BKE_image_get_tile_info(char *filepath, ListBase *tiles, int *tile_start, i
min_udim = min_ii(min_udim, id);
max_udim = max_ii(max_udim, id);
}
- BLI_filelist_free(dir, totfile);
+ BLI_filelist_free(dirs, dirs_num);
MEM_SAFE_FREE(udim_pattern);
if (is_udim && min_udim <= IMA_UDIM_MAX) {
@@ -3316,69 +3321,24 @@ void BKE_image_ensure_tile_token(char *filename)
return;
}
- /* Is there a sequence of digits in the filename? */
- ushort digits;
- char head[FILE_MAX], tail[FILE_MAX];
- BLI_path_sequence_decode(filename, head, tail, &digits);
- if (digits == 4) {
- sprintf(filename, "%s<UDIM>%s", head, tail);
- return;
- }
-
- /* Is there a sequence like u##_v#### in the filename? */
- uint cur = 0;
- uint name_end = strlen(filename);
- uint u_digits = 0;
- uint v_digits = 0;
- uint u_start = (uint)-1;
- bool u_found = false;
- bool v_found = false;
- bool sep_found = false;
- while (cur < name_end) {
- if (filename[cur] == 'u') {
- u_found = true;
- u_digits = 0;
- u_start = cur;
- }
- else if (filename[cur] == 'v') {
- v_found = true;
- v_digits = 0;
- }
- else if (u_found && !v_found) {
- if (isdigit(filename[cur]) && u_digits < 2) {
- u_digits++;
- }
- else if (filename[cur] == '_') {
- sep_found = true;
- }
- else {
- u_found = false;
- }
- }
- else if (u_found && u_digits > 0 && v_found) {
- if (isdigit(filename[cur])) {
- if (v_digits < 4) {
- v_digits++;
- }
- else {
- u_found = false;
- v_found = false;
- }
- }
- else if (v_digits > 0) {
- break;
- }
- }
+ std::string path(filename);
+ std::smatch match;
- cur++;
+ /* General 4-digit "udim" pattern. As this format is susceptible to ambiguity
+ * with other digit sequences, we can leverage the supported range of roughly
+ * 1000 through 2000 to provide better detection.
+ */
+ std::regex pattern(R"((^|.*?\D)([12]\d{3})(\D.*))");
+ if (std::regex_search(path, match, pattern)) {
+ BLI_strncpy(filename, match.format("$1<UDIM>$3").c_str(), FILE_MAX);
+ return;
}
- if (u_found && sep_found && v_found && (u_digits + v_digits > 1)) {
- const char *token = "<UVTILE>";
- const size_t token_length = strlen(token);
- memmove(filename + u_start + token_length, filename + cur, name_end - cur);
- memcpy(filename + u_start, token, token_length);
- filename[u_start + token_length + (name_end - cur)] = '\0';
+ /* General `u##_v###` `uvtile` pattern. */
+ pattern = std::regex(R"((.*)(u\d{1,2}_v\d{1,3})(\D.*))");
+ if (std::regex_search(path, match, pattern)) {
+ BLI_strncpy(filename, match.format("$1<UVTILE>$3").c_str(), FILE_MAX);
+ return;
}
}
@@ -3393,15 +3353,15 @@ bool BKE_image_tile_filepath_exists(const char *filepath)
char *udim_pattern = BKE_image_get_tile_strformat(filepath, &tile_format);
bool found = false;
- struct direntry *dir;
- uint totfile = BLI_filelist_dir_contents(dirname, &dir);
- for (int i = 0; i < totfile; i++) {
- if (!(dir[i].type & S_IFREG)) {
+ struct direntry *dirs;
+ const uint dirs_num = BLI_filelist_dir_contents(dirname, &dirs);
+ for (int i = 0; i < dirs_num; i++) {
+ if (!(dirs[i].type & S_IFREG)) {
continue;
}
int id;
- if (!BKE_image_get_tile_number_from_filepath(dir[i].path, udim_pattern, tile_format, &id)) {
+ if (!BKE_image_get_tile_number_from_filepath(dirs[i].path, udim_pattern, tile_format, &id)) {
continue;
}
@@ -3412,7 +3372,7 @@ bool BKE_image_tile_filepath_exists(const char *filepath)
found = true;
break;
}
- BLI_filelist_free(dir, totfile);
+ BLI_filelist_free(dirs, dirs_num);
MEM_SAFE_FREE(udim_pattern);
return found;
@@ -3781,7 +3741,7 @@ static int imbuf_alpha_flags_for_image(Image *ima)
/**
* \return the number of files will vary according to the stereo format.
*/
-static int image_num_files(Image *ima)
+static int image_num_viewfiles(Image *ima)
{
const bool is_multiview = BKE_image_is_multiview(ima);
@@ -3796,117 +3756,6 @@ static int image_num_files(Image *ima)
return BLI_listbase_count(&ima->views);
}
-static ImBuf *load_sequence_single(
- Image *ima, ImageUser *iuser, int frame, const int view_id, bool *r_cache_ibuf)
-{
- struct ImBuf *ibuf;
- char name[FILE_MAX];
- int flag;
- ImageUser iuser_t{};
-
- *r_cache_ibuf = true;
-
- ima->lastframe = frame;
-
- if (iuser) {
- iuser_t = *iuser;
- }
- else {
- /* BKE_image_user_file_path() uses this value for file name for sequences. */
- iuser_t.framenr = frame;
- /* TODO(sergey): Do we need to initialize something else here? */
- }
-
- iuser_t.view = view_id;
- BKE_image_user_file_path(&iuser_t, ima, name);
-
- flag = IB_rect | IB_multilayer | IB_metadata;
- flag |= imbuf_alpha_flags_for_image(ima);
-
- /* read ibuf */
- ibuf = IMB_loadiffname(name, flag, ima->colorspace_settings.name);
-
-#if 0
- if (ibuf) {
- printf(AT " loaded %s\n", name);
- }
- else {
- printf(AT " missed %s\n", name);
- }
-#endif
-
- if (ibuf) {
-#ifdef WITH_OPENEXR
- if (ibuf->ftype == IMB_FTYPE_OPENEXR && ibuf->userdata) {
- /* Handle multilayer and multiview cases, don't assign ibuf here.
- * will be set layer in BKE_image_acquire_ibuf from ima->rr. */
- if (IMB_exr_has_multilayer(ibuf->userdata)) {
- image_create_multilayer(ima, ibuf, frame);
- ima->type = IMA_TYPE_MULTILAYER;
- IMB_freeImBuf(ibuf);
- ibuf = nullptr;
- /* Null ibuf in the cache means the image failed to load. However for multilayer we load
- * pixels into RenderResult instead and intentionally leave ibuf null. */
- *r_cache_ibuf = false;
- }
- }
- else {
- image_init_after_load(ima, iuser, ibuf);
- }
-#else
- image_init_after_load(ima, iuser, ibuf);
-#endif
- }
-
- return ibuf;
-}
-
-static ImBuf *image_load_sequence_file(Image *ima, ImageUser *iuser, int entry, int frame)
-{
- struct ImBuf *ibuf = nullptr;
- const bool is_multiview = BKE_image_is_multiview(ima);
- const int totfiles = image_num_files(ima);
-
- if (!is_multiview) {
- bool put_in_cache;
- ibuf = load_sequence_single(ima, iuser, frame, 0, &put_in_cache);
- if (put_in_cache) {
- image_assign_ibuf(ima, ibuf, 0, entry);
- }
- }
- else {
- const int totviews = BLI_listbase_count(&ima->views);
- Array<ImBuf *> ibuf_arr(totviews);
- Array<bool> cache_ibuf_arr(totviews);
-
- for (int i = 0; i < totfiles; i++) {
- ibuf_arr[i] = load_sequence_single(ima, iuser, frame, i, &cache_ibuf_arr[i]);
- }
-
- if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D) {
- IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
- }
-
- /* return the original requested ImBuf */
- ibuf = ibuf_arr[(iuser ? iuser->multi_index : 0)];
-
- for (int i = 0; i < totviews; i++) {
- if (cache_ibuf_arr[i]) {
- image_assign_ibuf(ima, ibuf_arr[i], i, entry);
- }
- }
-
- /* "remove" the others (decrease their refcount) */
- for (int i = 0; i < totviews; i++) {
- if (ibuf_arr[i] != ibuf) {
- IMB_freeImBuf(ibuf_arr[i]);
- }
- }
- }
-
- return ibuf;
-}
-
static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int entry, int frame)
{
struct ImBuf *ibuf = nullptr;
@@ -3925,7 +3774,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int e
ima->rr = nullptr;
}
- ibuf = image_load_sequence_file(ima, iuser, entry, frame);
+ ibuf = image_load_image_file(ima, iuser, entry, frame, true);
if (ibuf) { /* actually an error */
ima->type = IMA_TYPE_IMAGE;
@@ -4012,12 +3861,12 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
{
struct ImBuf *ibuf = nullptr;
const bool is_multiview = BKE_image_is_multiview(ima);
- const int totfiles = image_num_files(ima);
+ const int tot_viewfiles = image_num_viewfiles(ima);
- if (totfiles != BLI_listbase_count_at_most(&ima->anims, totfiles + 1)) {
+ if (tot_viewfiles != BLI_listbase_count_at_most(&ima->anims, tot_viewfiles + 1)) {
image_free_anims(ima);
- for (int i = 0; i < totfiles; i++) {
+ for (int i = 0; i < tot_viewfiles; i++) {
/* allocate the ImageAnim */
ImageAnim *ia = MEM_cnew<ImageAnim>("Image Anim");
BLI_addtail(&ima->anims, ia);
@@ -4032,7 +3881,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
const int totviews = BLI_listbase_count(&ima->views);
Array<ImBuf *> ibuf_arr(totviews);
- for (int i = 0; i < totfiles; i++) {
+ for (int i = 0; i < tot_viewfiles; i++) {
ibuf_arr[i] = load_movie_single(ima, iuser, frame, i);
}
@@ -4063,23 +3912,21 @@ static ImBuf *load_image_single(Image *ima,
int cfra,
const int view_id,
const bool has_packed,
+ const bool is_sequence,
bool *r_cache_ibuf)
{
char filepath[FILE_MAX];
struct ImBuf *ibuf = nullptr;
- int flag;
+ int flag = IB_rect | IB_multilayer;
*r_cache_ibuf = true;
/* is there a PackedFile with this image ? */
- if (has_packed) {
- ImagePackedFile *imapf;
-
- flag = IB_rect | IB_multilayer;
- flag |= imbuf_alpha_flags_for_image(ima);
-
- imapf = static_cast<ImagePackedFile *>(BLI_findlink(&ima->packedfiles, view_id));
+ if (has_packed && !is_sequence) {
+ ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
+ BLI_findlink(&ima->packedfiles, view_id));
if (imapf->packedfile) {
+ flag |= imbuf_alpha_flags_for_image(ima);
ibuf = IMB_ibImageFromMemory((unsigned char *)imapf->packedfile->data,
imapf->packedfile->size,
flag,
@@ -4088,14 +3935,17 @@ static ImBuf *load_image_single(Image *ima,
}
}
else {
- ImageUser iuser_t{};
-
- flag = IB_rect | IB_multilayer | IB_metadata;
- flag |= imbuf_alpha_flags_for_image(ima);
+ if (is_sequence) {
+ ima->lastframe = cfra;
+ }
/* get the correct filepath */
- BKE_image_user_frame_calc(ima, iuser, cfra);
+ const bool is_tiled = (ima->source == IMA_SRC_TILED);
+ if (!(is_sequence || is_tiled)) {
+ BKE_image_user_frame_calc(ima, iuser, cfra);
+ }
+ ImageUser iuser_t{};
if (iuser) {
iuser_t = *iuser;
}
@@ -4108,6 +3958,8 @@ static ImBuf *load_image_single(Image *ima,
BKE_image_user_file_path(&iuser_t, ima, filepath);
/* read ibuf */
+ flag |= IB_metadata;
+ flag |= imbuf_alpha_flags_for_image(ima);
ibuf = IMB_loadiffname(filepath, flag, ima->colorspace_settings.name);
}
@@ -4132,7 +3984,7 @@ static ImBuf *load_image_single(Image *ima,
image_init_after_load(ima, iuser, ibuf);
/* Make packed file for auto-pack. */
- if ((has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) {
+ if (!is_sequence && (has_packed == false) && (G.fileflags & G_FILE_AUTOPACK)) {
ImagePackedFile *imapf = static_cast<ImagePackedFile *>(
MEM_mallocN(sizeof(ImagePackedFile), "Image Pack-file"));
BLI_addtail(&ima->packedfiles, imapf);
@@ -4150,18 +4002,23 @@ static ImBuf *load_image_single(Image *ima,
/* warning, 'iuser' can be null
* NOTE: Image->views was already populated (in image_update_views_format)
*/
-static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
+static ImBuf *image_load_image_file(
+ Image *ima, ImageUser *iuser, int entry, int cfra, bool is_sequence)
{
struct ImBuf *ibuf = nullptr;
const bool is_multiview = BKE_image_is_multiview(ima);
- const int totfiles = image_num_files(ima);
+ const bool is_tiled = (ima->source == IMA_SRC_TILED);
+ const int tot_viewfiles = image_num_viewfiles(ima);
bool has_packed = BKE_image_has_packedfile(ima);
- /* always ensure clean ima */
- BKE_image_free_buffers(ima);
+ if (!(is_sequence || is_tiled)) {
+ /* ensure clean ima */
+ BKE_image_free_buffers(ima);
+ }
/* this should never happen, but just playing safe */
- if (has_packed) {
+ if (!is_sequence && has_packed) {
+ const int totfiles = tot_viewfiles * BLI_listbase_count(&ima->tiles);
if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
image_free_packedfiles(ima);
has_packed = false;
@@ -4170,9 +4027,10 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
if (!is_multiview) {
bool put_in_cache;
- ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, &put_in_cache);
+ ibuf = load_image_single(ima, iuser, cfra, 0, has_packed, is_sequence, &put_in_cache);
if (put_in_cache) {
- image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
+ const int index = (is_sequence || is_tiled) ? 0 : IMA_NO_INDEX;
+ image_assign_ibuf(ima, ibuf, index, entry);
}
}
else {
@@ -4182,28 +4040,29 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
Array<ImBuf *> ibuf_arr(totviews);
Array<bool> cache_ibuf_arr(totviews);
- for (int i = 0; i < totfiles; i++) {
- ibuf_arr[i] = load_image_single(ima, iuser, cfra, i, has_packed, &cache_ibuf_arr[i]);
+ for (int i = 0; i < tot_viewfiles; i++) {
+ ibuf_arr[i] = load_image_single(
+ ima, iuser, cfra, i, has_packed, is_sequence, &cache_ibuf_arr[i]);
}
/* multi-views/multi-layers OpenEXR files directly populate ima, and return null ibuf... */
if (BKE_image_is_stereo(ima) && ima->views_format == R_IMF_VIEWS_STEREO_3D && ibuf_arr[0] &&
- totfiles == 1 && totviews >= 2) {
+ tot_viewfiles == 1 && totviews >= 2) {
IMB_ImBufFromStereo3d(ima->stereo3d_format, ibuf_arr[0], &ibuf_arr[0], &ibuf_arr[1]);
}
/* return the original requested ImBuf */
- int i = (iuser && iuser->multi_index < totviews) ? iuser->multi_index : 0;
- ibuf = ibuf_arr[i];
+ const int ibuf_index = (iuser && iuser->multi_index < totviews) ? iuser->multi_index : 0;
+ ibuf = ibuf_arr[ibuf_index];
- for (i = 0; i < totviews; i++) {
+ for (int i = 0; i < totviews; i++) {
if (cache_ibuf_arr[i]) {
- image_assign_ibuf(ima, ibuf_arr[i], i, 0);
+ image_assign_ibuf(ima, ibuf_arr[i], i, entry);
}
}
/* "remove" the others (decrease their refcount) */
- for (i = 0; i < totviews; i++) {
+ for (int i = 0; i < totviews; i++) {
if (ibuf_arr[i] != ibuf) {
IMB_freeImBuf(ibuf_arr[i]);
}
@@ -4218,7 +4077,7 @@ static ImBuf *image_get_ibuf_multilayer(Image *ima, ImageUser *iuser)
ImBuf *ibuf = nullptr;
if (ima->rr == nullptr) {
- ibuf = image_load_image_file(ima, iuser, 0);
+ ibuf = image_load_image_file(ima, iuser, 0, 0, false);
if (ibuf) { /* actually an error */
ima->type = IMA_TYPE_IMAGE;
return ibuf;
@@ -4595,7 +4454,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
else if (ima->source == IMA_SRC_SEQUENCE) {
if (ima->type == IMA_TYPE_IMAGE) {
/* Regular files, ibufs in flip-book, allows saving. */
- ibuf = image_load_sequence_file(ima, iuser, entry, entry);
+ ibuf = image_load_image_file(ima, iuser, entry, entry, true);
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
@@ -4606,7 +4465,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
else if (ima->source == IMA_SRC_TILED) {
if (ima->type == IMA_TYPE_IMAGE) {
/* Regular files, ibufs in flip-book, allows saving */
- ibuf = image_load_sequence_file(ima, iuser, entry, 0);
+ ibuf = image_load_image_file(ima, iuser, entry, 0, false);
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
@@ -4617,7 +4476,8 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
else if (ima->source == IMA_SRC_FILE) {
if (ima->type == IMA_TYPE_IMAGE) {
- ibuf = image_load_image_file(ima, iuser, entry); /* cfra only for '#', this global is OK */
+ ibuf = image_load_image_file(
+ ima, iuser, 0, entry, false); /* cfra only for '#', this global is OK */
}
/* no else; on load the ima type can change */
if (ima->type == IMA_TYPE_MULTILAYER) {
@@ -5096,7 +4956,7 @@ void BKE_image_user_file_path_ex(ImageUser *iuser, Image *ima, char *filepath, b
bool BKE_image_has_alpha(Image *image)
{
void *lock;
- ImBuf *ibuf = BKE_image_acquire_ibuf(image, NULL, &lock);
+ ImBuf *ibuf = BKE_image_acquire_ibuf(image, nullptr, &lock);
const int planes = (ibuf ? ibuf->planes : 0);
BKE_image_release_ibuf(image, ibuf, lock);
diff --git a/source/blender/blenkernel/intern/image_format.cc b/source/blender/blenkernel/intern/image_format.cc
index 44aa9e21195..3ff0b3da963 100644
--- a/source/blender/blenkernel/intern/image_format.cc
+++ b/source/blender/blenkernel/intern/image_format.cc
@@ -5,7 +5,7 @@
* \ingroup bke
*/
-#include <string.h>
+#include <cstring>
#include "DNA_defaults.h"
#include "DNA_scene_types.h"
@@ -120,6 +120,12 @@ int BKE_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options)
return IMB_FTYPE_JP2;
}
#endif
+#ifdef WITH_WEBP
+ if (imtype == R_IMF_IMTYPE_WEBP) {
+ r_options->quality = 90;
+ return IMB_FTYPE_WEBP;
+ }
+#endif
r_options->quality = 90;
return IMB_FTYPE_JPG;
@@ -177,6 +183,11 @@ char BKE_ftype_to_imtype(const int ftype, const ImbFormatOptions *options)
return R_IMF_IMTYPE_JP2;
}
#endif
+#ifdef WITH_WEBP
+ if (ftype == IMB_FTYPE_WEBP) {
+ return R_IMF_IMTYPE_WEBP;
+ }
+#endif
return R_IMF_IMTYPE_JPEG90;
}
@@ -220,6 +231,7 @@ bool BKE_imtype_supports_quality(const char imtype)
case R_IMF_IMTYPE_JPEG90:
case R_IMF_IMTYPE_JP2:
case R_IMF_IMTYPE_AVIJPEG:
+ case R_IMF_IMTYPE_WEBP:
return true;
}
return false;
@@ -259,6 +271,7 @@ char BKE_imtype_valid_channels(const char imtype, bool write_file)
case R_IMF_IMTYPE_DDS:
case R_IMF_IMTYPE_JP2:
case R_IMF_IMTYPE_DPX:
+ case R_IMF_IMTYPE_WEBP:
chan_flag |= IMA_CHAN_FLAG_ALPHA;
break;
}
@@ -379,6 +392,11 @@ char BKE_imtype_from_arg(const char *imtype_arg)
return R_IMF_IMTYPE_JP2;
}
#endif
+#ifdef WITH_WEBP
+ if (STREQ(imtype_arg, "WEBP")) {
+ return R_IMF_IMTYPE_WEBP;
+ }
+#endif
return R_IMF_IMTYPE_INVALID;
}
@@ -494,6 +512,12 @@ static bool do_add_image_extension(char *string,
}
}
#endif
+#ifdef WITH_WEBP
+ else if (imtype == R_IMF_IMTYPE_WEBP) {
+ if (!BLI_path_extension_check(string, extension_test = ".webp"))
+ extension = extension_test;
+ }
+#endif
else { // R_IMF_IMTYPE_AVIRAW, R_IMF_IMTYPE_AVIJPEG, R_IMF_IMTYPE_JPEG90 etc
if (!(BLI_path_extension_check_n(string, extension_test = ".jpg", ".jpeg", nullptr))) {
extension = extension_test;
@@ -732,6 +756,12 @@ void BKE_image_format_to_imbuf(ImBuf *ibuf, const ImageFormatData *imf)
}
}
#endif
+#ifdef WITH_WEBP
+ else if (imtype == R_IMF_IMTYPE_WEBP) {
+ ibuf->ftype = IMB_FTYPE_WEBP;
+ ibuf->foptions.quality = quality;
+ }
+#endif
else {
/* #R_IMF_IMTYPE_JPEG90, etc. default to JPEG. */
if (quality < 10) {
@@ -864,6 +894,12 @@ void BKE_image_format_from_imbuf(ImageFormatData *im_format, const ImBuf *imbuf)
}
}
#endif
+#ifdef WITH_WEBP
+ else if (ftype == IMB_FTYPE_WEBP) {
+ im_format->imtype = R_IMF_IMTYPE_WEBP;
+ im_format->quality = quality;
+ }
+#endif
else {
im_format->imtype = R_IMF_IMTYPE_JPEG90;
diff --git a/source/blender/blenkernel/intern/image_partial_update.cc b/source/blender/blenkernel/intern/image_partial_update.cc
index 4606a14ab69..c77ee77a5f2 100644
--- a/source/blender/blenkernel/intern/image_partial_update.cc
+++ b/source/blender/blenkernel/intern/image_partial_update.cc
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2021 Blender Foundation. */
/**
- * \file image_gpu_partial_update.cc
+ * \file
* \ingroup bke
*
* To reduce the overhead of image processing this file contains a mechanism to detect areas of the
diff --git a/source/blender/blenkernel/intern/image_save.cc b/source/blender/blenkernel/intern/image_save.cc
index f530183f967..0d7d238f3b2 100644
--- a/source/blender/blenkernel/intern/image_save.cc
+++ b/source/blender/blenkernel/intern/image_save.cc
@@ -391,6 +391,10 @@ static bool image_save_single(ReportList *reports,
}
}
+ if (rr) {
+ BKE_image_release_renderresult(opts->scene, ima);
+ }
+
return ok;
}
@@ -693,7 +697,7 @@ bool BKE_image_render_write(ReportList *reports,
RenderResult *rr,
const Scene *scene,
const bool stamp,
- const char *filename)
+ const char *filepath_basis)
{
bool ok = true;
@@ -711,8 +715,8 @@ bool BKE_image_render_write(ReportList *reports,
const float dither = scene->r.dither_intensity;
if (image_format.views_format == R_IMF_VIEWS_MULTIVIEW && is_exr_rr) {
- ok = BKE_image_render_write_exr(reports, rr, filename, &image_format, true, nullptr, -1);
- image_render_print_save_message(reports, filename, ok, errno);
+ ok = BKE_image_render_write_exr(reports, rr, filepath_basis, &image_format, true, nullptr, -1);
+ image_render_print_save_message(reports, filepath_basis, ok, errno);
}
/* mono, legacy code */
@@ -722,10 +726,10 @@ bool BKE_image_render_write(ReportList *reports,
rv = rv->next, view_id++) {
char filepath[FILE_MAX];
if (is_mono) {
- STRNCPY(filepath, filename);
+ STRNCPY(filepath, filepath_basis);
}
else {
- BKE_scene_multiview_view_filepath_get(&scene->r, filename, rv->name, filepath);
+ BKE_scene_multiview_view_filepath_get(&scene->r, filepath_basis, rv->name, filepath);
}
if (is_exr_rr) {
@@ -768,7 +772,7 @@ bool BKE_image_render_write(ReportList *reports,
BLI_assert(image_format.views_format == R_IMF_VIEWS_STEREO_3D);
char filepath[FILE_MAX];
- STRNCPY(filepath, filename);
+ STRNCPY(filepath, filepath_basis);
if (image_format.imtype == R_IMF_IMTYPE_MULTILAYER) {
printf("Stereo 3D not supported for MultiLayer image: %s\n", filepath);
diff --git a/source/blender/blenkernel/intern/image_test.cc b/source/blender/blenkernel/intern/image_test.cc
new file mode 100644
index 00000000000..9c15fc62d21
--- /dev/null
+++ b/source/blender/blenkernel/intern/image_test.cc
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2022 Blender Foundation. */
+
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+
+#include "BKE_image.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "testing/testing.h"
+
+namespace blender::bke::tests {
+
+TEST(udim, image_ensure_tile_token)
+{
+ auto verify = [](const char *original, const char *expected) {
+ char result[FILE_MAX];
+
+ BLI_strncpy(result, original, sizeof(result));
+ BKE_image_ensure_tile_token(result);
+ EXPECT_STREQ(result, expected);
+ };
+
+ /* Already present tokens. */
+ verify("test.<UDIM>.png", "test.<UDIM>.png");
+ verify("test.<UVTILE>.png", "test.<UVTILE>.png");
+
+ /* UDIM pattern detection. */
+ verify("test.1002.png", "test.<UDIM>.png");
+ verify("test-1002-ao.png", "test-<UDIM>-ao.png");
+ verify("test_1002_ao.png", "test_<UDIM>_ao.png");
+ verify("test.1002.ver0023.png", "test.<UDIM>.ver0023.png");
+ verify("test.ver0023.1002.png", "test.ver0023.<UDIM>.png");
+ verify("1002test.png", "<UDIM>test.png");
+ verify("test1002.png", "test<UDIM>.png");
+
+ /* UVTILE pattern detection. */
+ verify("uv-test.u2_v10.png", "uv-test.<UVTILE>.png");
+ verify("uv-test-u2_v10-ao.png", "uv-test-<UVTILE>-ao.png");
+ verify("uv-test_u2_v10_ao.png", "uv-test_<UVTILE>_ao.png");
+ verify("uv-test.u10_v100.png", "uv-test.<UVTILE>.png");
+ verify("u_v-test.u2_v10.png", "u_v-test.<UVTILE>.png");
+ verify("u2_v10uv-test.png", "<UVTILE>uv-test.png");
+ verify("u2_v10u_v-test.png", "<UVTILE>u_v-test.png");
+
+ /* Incorrect patterns. */
+ for (const char *incorrect : {"test.123.png",
+ "test.12345.png",
+ "test.uv.png",
+ "test.u1v.png",
+ "test.uv1.png",
+ "test.u_v.png",
+ "test.u1_v.png",
+ "test.u_v2.png",
+ "test.u2v3.png",
+ "test.u123_v1.png",
+ "test.u1_v12345.png"}) {
+ /* These should not result in modifications happening. */
+ verify(incorrect, incorrect);
+ }
+}
+
+TEST(udim, image_get_tile_strformat)
+{
+ eUDIM_TILE_FORMAT tile_format;
+ char *udim_pattern;
+
+ /* Parameter validation. */
+ udim_pattern = BKE_image_get_tile_strformat(nullptr, &tile_format);
+ EXPECT_EQ(udim_pattern, nullptr);
+
+ udim_pattern = BKE_image_get_tile_strformat("", nullptr);
+ EXPECT_EQ(udim_pattern, nullptr);
+
+ /* Typical usage. */
+ udim_pattern = BKE_image_get_tile_strformat("", &tile_format);
+ EXPECT_EQ(tile_format, UDIM_TILE_FORMAT_NONE);
+ EXPECT_EQ(udim_pattern, nullptr);
+
+ udim_pattern = BKE_image_get_tile_strformat("test.<UNKNOWN>.png", &tile_format);
+ EXPECT_EQ(tile_format, UDIM_TILE_FORMAT_NONE);
+ EXPECT_EQ(udim_pattern, nullptr);
+
+ udim_pattern = BKE_image_get_tile_strformat("test.<UDIM>.png", &tile_format);
+ EXPECT_EQ(tile_format, UDIM_TILE_FORMAT_UDIM);
+ EXPECT_STREQ(udim_pattern, "test.%d.png");
+ MEM_freeN(udim_pattern);
+
+ udim_pattern = BKE_image_get_tile_strformat("test.<UVTILE>.png", &tile_format);
+ EXPECT_EQ(tile_format, UDIM_TILE_FORMAT_UVTILE);
+ EXPECT_STREQ(udim_pattern, "test.u%d_v%d.png");
+ MEM_freeN(udim_pattern);
+}
+
+TEST(udim, image_get_tile_number_from_filepath)
+{
+ eUDIM_TILE_FORMAT tile_format;
+ char *udim_pattern;
+ int tile_number;
+
+ udim_pattern = BKE_image_get_tile_strformat("test.<UDIM>.png", &tile_format);
+ EXPECT_EQ(tile_format, UDIM_TILE_FORMAT_UDIM);
+ EXPECT_NE(udim_pattern, nullptr);
+
+ /* Parameter validation. */
+ EXPECT_FALSE(
+ BKE_image_get_tile_number_from_filepath(nullptr, udim_pattern, tile_format, &tile_number));
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "test.1004.png", nullptr, tile_format, &tile_number));
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "test.1004.png", udim_pattern, UDIM_TILE_FORMAT_NONE, &tile_number));
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "test.1004.png", udim_pattern, tile_format, nullptr));
+
+ /* UDIM tile format tests. */
+ EXPECT_TRUE(BKE_image_get_tile_number_from_filepath(
+ "test.1004.png", udim_pattern, tile_format, &tile_number));
+ EXPECT_EQ(tile_number, 1004);
+
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "has_no_number.png", udim_pattern, tile_format, &tile_number));
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "test.X.png", udim_pattern, tile_format, &tile_number));
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "wrong.1004.png", udim_pattern, tile_format, &tile_number));
+
+ MEM_freeN(udim_pattern);
+
+ /* UVTILE tile format tests. */
+ udim_pattern = BKE_image_get_tile_strformat("test.<UVTILE>.png", &tile_format);
+ EXPECT_EQ(tile_format, UDIM_TILE_FORMAT_UVTILE);
+ EXPECT_NE(udim_pattern, nullptr);
+
+ EXPECT_TRUE(BKE_image_get_tile_number_from_filepath(
+ "test.u2_v2.png", udim_pattern, tile_format, &tile_number));
+ EXPECT_EQ(tile_number, 1012);
+
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "has_no_number.png", udim_pattern, tile_format, &tile_number));
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "test.u1_vX.png", udim_pattern, tile_format, &tile_number));
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "test.uX_v1.png", udim_pattern, tile_format, &tile_number));
+ EXPECT_FALSE(BKE_image_get_tile_number_from_filepath(
+ "wrong.u2_v2.png", udim_pattern, tile_format, &tile_number));
+
+ MEM_freeN(udim_pattern);
+}
+
+TEST(udim, image_set_filepath_from_tile_number)
+{
+ eUDIM_TILE_FORMAT tile_format;
+ char *udim_pattern;
+
+ udim_pattern = BKE_image_get_tile_strformat("test.<UDIM>.png", &tile_format);
+ EXPECT_EQ(tile_format, UDIM_TILE_FORMAT_UDIM);
+ EXPECT_NE(udim_pattern, nullptr);
+
+ char filepath[FILE_MAX];
+
+ /* Parameter validation. */
+ BLI_strncpy(filepath, "xxxx", FILE_MAX);
+
+ BKE_image_set_filepath_from_tile_number(nullptr, udim_pattern, tile_format, 1028);
+ BKE_image_set_filepath_from_tile_number(filepath, nullptr, tile_format, 1028);
+ EXPECT_STREQ(filepath, "xxxx");
+ BKE_image_set_filepath_from_tile_number(filepath, udim_pattern, UDIM_TILE_FORMAT_NONE, 1028);
+ EXPECT_STREQ(filepath, "xxxx");
+
+ /* UDIM tile format tests. */
+ BKE_image_set_filepath_from_tile_number(filepath, udim_pattern, tile_format, 1028);
+ EXPECT_STREQ(filepath, "test.1028.png");
+ MEM_freeN(udim_pattern);
+
+ /* UVTILE tile format tests. */
+ udim_pattern = BKE_image_get_tile_strformat("test.<UVTILE>.png", &tile_format);
+ EXPECT_EQ(tile_format, UDIM_TILE_FORMAT_UVTILE);
+ EXPECT_NE(udim_pattern, nullptr);
+
+ BKE_image_set_filepath_from_tile_number(filepath, udim_pattern, tile_format, 1028);
+ EXPECT_STREQ(filepath, "test.u8_v3.png");
+ MEM_freeN(udim_pattern);
+}
+
+} // namespace blender::bke::tests
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index 782d5442c99..5afc3c0be3b 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -199,7 +199,7 @@ static void mesh_foreach_path(ID *id, BPathForeachPathData *bpath_data)
{
Mesh *me = (Mesh *)id;
if (me->ldata.external) {
- BKE_bpath_foreach_path_fixed_process(bpath_data, me->ldata.external->filename);
+ BKE_bpath_foreach_path_fixed_process(bpath_data, me->ldata.external->filepath);
}
}
diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc
index 40c6fbcf67e..dc9ec002d1a 100644
--- a/source/blender/blenkernel/intern/mesh_convert.cc
+++ b/source/blender/blenkernel/intern/mesh_convert.cc
@@ -910,18 +910,20 @@ static void curve_to_mesh_eval_ensure(Object &object)
*
* So we create temporary copy of the object which will use same data as the original bevel, but
* will have no modifiers. */
- Object bevel_object = {{nullptr}};
+ Object bevel_object;
+ blender::dna::zero_memory(bevel_object);
if (curve.bevobj != nullptr) {
- memcpy(&bevel_object, curve.bevobj, sizeof(bevel_object));
+ blender::dna::copy_memory(bevel_object, *curve.bevobj);
BLI_listbase_clear(&bevel_object.modifiers);
BKE_object_runtime_reset(&bevel_object);
curve.bevobj = &bevel_object;
}
/* Same thing for taper. */
- Object taper_object = {{nullptr}};
+ Object taper_object;
+ blender::dna::zero_memory(taper_object);
if (curve.taperobj != nullptr) {
- memcpy(&taper_object, curve.taperobj, sizeof(taper_object));
+ blender::dna::copy_memory(taper_object, *curve.taperobj);
BLI_listbase_clear(&taper_object.modifiers);
BKE_object_runtime_reset(&taper_object);
curve.taperobj = &taper_object;
@@ -1066,7 +1068,7 @@ static Mesh *mesh_new_from_mesh_object_with_layers(Depsgraph *depsgraph,
}
Object object_for_eval;
- memcpy(&object_for_eval, object, sizeof(object_for_eval));
+ blender::dna::copy_memory(object_for_eval, *object);
if (object_for_eval.runtime.data_orig != nullptr) {
object_for_eval.data = object_for_eval.runtime.data_orig;
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.cc b/source/blender/blenkernel/intern/mesh_evaluate.cc
index da0bd1f021d..6c5a5de31fc 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.cc
+++ b/source/blender/blenkernel/intern/mesh_evaluate.cc
@@ -695,7 +695,7 @@ static void bm_corners_to_loops_ex(ID *id,
if (CustomData_external_test(fdata, CD_MDISPS)) {
if (id && fdata->external) {
- CustomData_external_add(ldata, id, CD_MDISPS, totloop, fdata->external->filename);
+ CustomData_external_add(ldata, id, CD_MDISPS, totloop, fdata->external->filepath);
}
}
diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c
index e9c26c80141..9c4098e2db6 100644
--- a/source/blender/blenkernel/intern/mesh_mapping.c
+++ b/source/blender/blenkernel/intern/mesh_mapping.c
@@ -561,7 +561,7 @@ void BKE_mesh_origindex_map_create_looptri(MeshElemMap **r_map,
typedef bool (*MeshRemap_CheckIslandBoundary)(const struct MPoly *mpoly,
const struct MLoop *mloop,
const struct MEdge *medge,
- const int nbr_edge_users,
+ const int edge_user_count,
const struct MPoly *mpoly_array,
const struct MeshElemMap *edge_poly_map,
void *user_data);
@@ -764,14 +764,14 @@ static void poly_edge_loop_islands_calc(const MEdge *medge,
static bool poly_is_island_boundary_smooth_cb(const MPoly *mp,
const MLoop *UNUSED(ml),
const MEdge *me,
- const int nbr_edge_users,
+ const int edge_user_count,
const MPoly *mpoly_array,
const MeshElemMap *edge_poly_map,
void *UNUSED(user_data))
{
/* Edge is sharp if one of its polys is flat, or edge itself is sharp,
* or edge is not used by exactly two polygons. */
- if ((mp->flag & ME_SMOOTH) && !(me->flag & ME_SHARP) && (nbr_edge_users == 2)) {
+ if ((mp->flag & ME_SMOOTH) && !(me->flag & ME_SHARP) && (edge_user_count == 2)) {
/* In that case, edge appears to be smooth, but we need to check its other poly too. */
const MPoly *mp_other = (mp == &mpoly_array[edge_poly_map->indices[0]]) ?
&mpoly_array[edge_poly_map->indices[1]] :
@@ -935,7 +935,7 @@ typedef struct MeshCheckIslandBoundaryUv {
static bool mesh_check_island_boundary_uv(const MPoly *UNUSED(mp),
const MLoop *ml,
const MEdge *me,
- const int UNUSED(nbr_edge_users),
+ const int UNUSED(edge_user_count),
const MPoly *UNUSED(mpoly_array),
const MeshElemMap *UNUSED(edge_poly_map),
void *user_data)
diff --git a/source/blender/blenkernel/intern/mesh_normals.cc b/source/blender/blenkernel/intern/mesh_normals.cc
index 7633a3155ba..ba1004e8371 100644
--- a/source/blender/blenkernel/intern/mesh_normals.cc
+++ b/source/blender/blenkernel/intern/mesh_normals.cc
@@ -532,7 +532,7 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr,
lnors_spacearr->loops_pool = (LinkNode *)BLI_memarena_alloc(
mem, sizeof(LinkNode) * (size_t)numLoops);
- lnors_spacearr->num_spaces = 0;
+ lnors_spacearr->spaces_num = 0;
}
BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX));
lnors_spacearr->data_type = data_type;
@@ -550,7 +550,7 @@ void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr,
{
BLI_assert(lnors_spacearr->data_type == lnors_spacearr_tls->data_type);
BLI_assert(lnors_spacearr->mem != lnors_spacearr_tls->mem);
- lnors_spacearr->num_spaces += lnors_spacearr_tls->num_spaces;
+ lnors_spacearr->spaces_num += lnors_spacearr_tls->spaces_num;
BLI_memarena_merge(lnors_spacearr->mem, lnors_spacearr_tls->mem);
BLI_memarena_free(lnors_spacearr_tls->mem);
lnors_spacearr_tls->mem = nullptr;
@@ -559,7 +559,7 @@ void BKE_lnor_spacearr_tls_join(MLoopNorSpaceArray *lnors_spacearr,
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
{
- lnors_spacearr->num_spaces = 0;
+ lnors_spacearr->spaces_num = 0;
lnors_spacearr->lspacearr = nullptr;
lnors_spacearr->loops_pool = nullptr;
if (lnors_spacearr->mem != nullptr) {
@@ -569,7 +569,7 @@ void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr)
{
- lnors_spacearr->num_spaces = 0;
+ lnors_spacearr->spaces_num = 0;
lnors_spacearr->lspacearr = nullptr;
lnors_spacearr->loops_pool = nullptr;
BLI_memarena_free(lnors_spacearr->mem);
@@ -578,7 +578,7 @@ void BKE_lnor_spacearr_free(MLoopNorSpaceArray *lnors_spacearr)
MLoopNorSpace *BKE_lnor_space_create(MLoopNorSpaceArray *lnors_spacearr)
{
- lnors_spacearr->num_spaces++;
+ lnors_spacearr->spaces_num++;
return (MLoopNorSpace *)BLI_memarena_calloc(lnors_spacearr->mem, sizeof(MLoopNorSpace));
}
@@ -613,19 +613,19 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space,
/* Compute ref alpha, average angle of all available edge vectors to lnor. */
if (edge_vectors) {
float alpha = 0.0f;
- int nbr = 0;
+ int count = 0;
while (!BLI_stack_is_empty(edge_vectors)) {
const float *vec = (const float *)BLI_stack_peek(edge_vectors);
alpha += saacosf(dot_v3v3(vec, lnor));
BLI_stack_discard(edge_vectors);
- nbr++;
+ count++;
}
- /* NOTE: In theory, this could be `nbr > 2`,
+ /* NOTE: In theory, this could be `count > 2`,
* but there is one case where we only have two edges for two loops:
* a smooth vertex with only two edges and two faces (our Monkey's nose has that, e.g.).
*/
- BLI_assert(nbr >= 2); /* This piece of code shall only be called for more than one loop. */
- lnor_space->ref_alpha = alpha / (float)nbr;
+ BLI_assert(count >= 2); /* This piece of code shall only be called for more than one loop. */
+ lnor_space->ref_alpha = alpha / (float)count;
}
else {
lnor_space->ref_alpha = (saacosf(dot_v3v3(vec_ref, lnor)) +
@@ -1134,7 +1134,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
/* We validate clnors data on the fly - cheapest way to do! */
int clnors_avg[2] = {0, 0};
short(*clnor_ref)[2] = nullptr;
- int clnors_nbr = 0;
+ int clnors_count = 0;
bool clnors_invalid = false;
/* Temp loop normal stack. */
@@ -1194,7 +1194,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
if (clnors_data) {
/* Accumulate all clnors, if they are not all equal we have to fix that! */
short(*clnor)[2] = &clnors_data[mlfan_vert_index];
- if (clnors_nbr) {
+ if (clnors_count) {
clnors_invalid |= ((*clnor_ref)[0] != (*clnor)[0] || (*clnor_ref)[1] != (*clnor)[1]);
}
else {
@@ -1202,7 +1202,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
}
clnors_avg[0] += (*clnor)[0];
clnors_avg[1] += (*clnor)[1];
- clnors_nbr++;
+ clnors_count++;
/* We store here a pointer to all custom lnors processed. */
BLI_SMALLSTACK_PUSH(clnors, (short *)*clnor);
}
@@ -1262,8 +1262,8 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
if (clnors_invalid) {
short *clnor;
- clnors_avg[0] /= clnors_nbr;
- clnors_avg[1] /= clnors_nbr;
+ clnors_avg[0] /= clnors_count;
+ clnors_avg[1] /= clnors_count;
/* Fix/update all clnors of this fan with computed average value. */
if (G.debug & G_DEBUG) {
printf("Invalid clnors in this fan!\n");
@@ -1952,7 +1952,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
BLI_BITMAP_DISABLE(done_loops, i);
}
else {
- int nbr_nors = 0;
+ int avg_nor_count = 0;
float avg_nor[3];
short clnor_data_tmp[2], *clnor_data;
@@ -1962,7 +1962,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
const int nidx = use_vertices ? (int)mloops[lidx].v : lidx;
float *nor = r_custom_loopnors[nidx];
- nbr_nors++;
+ avg_nor_count++;
add_v3_v3(avg_nor, nor);
BLI_SMALLSTACK_PUSH(clnors_data, (short *)r_clnors_data[lidx]);
@@ -1970,7 +1970,7 @@ static void mesh_normals_loop_custom_set(const MVert *mverts,
BLI_BITMAP_DISABLE(done_loops, lidx);
}
- mul_v3_fl(avg_nor, 1.0f / (float)nbr_nors);
+ mul_v3_fl(avg_nor, 1.0f / (float)avg_nor_count);
BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], avg_nor, clnor_data_tmp);
while ((clnor_data = (short *)BLI_SMALLSTACK_POP(clnors_data))) {
@@ -2088,8 +2088,8 @@ void BKE_mesh_normals_loop_to_vertex(const int numVerts,
const float (*clnors)[3],
float (*r_vert_clnors)[3])
{
- int *vert_loops_nbr = (int *)MEM_calloc_arrayN(
- (size_t)numVerts, sizeof(*vert_loops_nbr), __func__);
+ int *vert_loops_count = (int *)MEM_calloc_arrayN(
+ (size_t)numVerts, sizeof(*vert_loops_count), __func__);
copy_vn_fl((float *)r_vert_clnors, 3 * numVerts, 0.0f);
@@ -2099,14 +2099,14 @@ void BKE_mesh_normals_loop_to_vertex(const int numVerts,
const uint v = ml->v;
add_v3_v3(r_vert_clnors[v], clnors[i]);
- vert_loops_nbr[v]++;
+ vert_loops_count[v]++;
}
for (i = 0; i < numVerts; i++) {
- mul_v3_fl(r_vert_clnors[i], 1.0f / (float)vert_loops_nbr[i]);
+ mul_v3_fl(r_vert_clnors[i], 1.0f / (float)vert_loops_count[i]);
}
- MEM_freeN(vert_loops_nbr);
+ MEM_freeN(vert_loops_count);
}
#undef LNOR_SPACE_TRIGO_THRESHOLD
diff --git a/source/blender/blenkernel/intern/mesh_validate.cc b/source/blender/blenkernel/intern/mesh_validate.cc
index 4374659bff8..6af765d7de5 100644
--- a/source/blender/blenkernel/intern/mesh_validate.cc
+++ b/source/blender/blenkernel/intern/mesh_validate.cc
@@ -577,7 +577,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
else if (mp->loopstart + mp->totloop > totloop) {
/* Invalid loop data. */
PRINT_ERR(
- "\tPoly %u uses loops out of range (loopstart: %d, loopend: %d, max nbr of loops: %u)",
+ "\tPoly %u uses loops out of range "
+ "(loopstart: %d, loopend: %d, max number of loops: %u)",
sp->index,
mp->loopstart,
mp->loopstart + mp->totloop - 1,
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index 1e3b5d77fa7..4714a79de58 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -766,7 +766,7 @@ static void object_blend_read_data(BlendDataReader *reader, ID *id)
hmd->indexar = hook->indexar;
hmd->object = hook->parent;
memcpy(hmd->parentinv, hook->parentinv, sizeof(hmd->parentinv));
- hmd->totindex = hook->totindex;
+ hmd->indexar_num = hook->totindex;
BLI_addhead(&ob->modifiers, hmd);
BLI_remlink(&ob->hooks, hook);
@@ -1236,7 +1236,7 @@ IDTypeInfo IDType_ID_OB = {
void BKE_object_workob_clear(Object *workob)
{
- memset(workob, 0, sizeof(Object));
+ blender::dna::zero_memory(*workob);
workob->scale[0] = workob->scale[1] = workob->scale[2] = 1.0f;
workob->dscale[0] = workob->dscale[1] = workob->dscale[2] = 1.0f;
@@ -3946,7 +3946,7 @@ bool BKE_object_minmax_dupli(Depsgraph *depsgraph,
/* pass */
}
else {
- Object temp_ob = *dob->ob;
+ Object temp_ob = blender::dna::shallow_copy(*dob->ob);
/* Do not modify the original boundbox. */
temp_ob.runtime.bb = nullptr;
BKE_object_replace_data_on_shallow_copy(&temp_ob, dob->ob_data);
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 4c5fefefd8e..e7ed100ed03 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -174,16 +174,16 @@ PackedFile *BKE_packedfile_new_from_memory(void *mem, int memlen)
return pf;
}
-PackedFile *BKE_packedfile_new(ReportList *reports, const char *filename, const char *basepath)
+PackedFile *BKE_packedfile_new(ReportList *reports, const char *filepath, const char *basepath)
{
PackedFile *pf = NULL;
int file, filelen;
char name[FILE_MAX];
void *data;
- /* render result has no filename and can be ignored
+ /* render result has no filepath and can be ignored
* any other files with no name can be ignored too */
- if (filename[0] == '\0') {
+ if (filepath[0] == '\0') {
return pf;
}
@@ -191,7 +191,7 @@ PackedFile *BKE_packedfile_new(ReportList *reports, const char *filename, const
/* convert relative filenames to absolute filenames */
- BLI_strncpy(name, filename, sizeof(name));
+ BLI_strncpy(name, filepath, sizeof(name));
BLI_path_abs(name, basepath);
/* open the file
@@ -285,7 +285,7 @@ void BKE_packedfile_pack_all(Main *bmain, ReportList *reports, bool verbose)
int BKE_packedfile_write_to_file(ReportList *reports,
const char *ref_file_name,
- const char *filename,
+ const char *filepath,
PackedFile *pf,
const bool guimode)
{
@@ -299,7 +299,7 @@ int BKE_packedfile_write_to_file(ReportList *reports,
if (guimode) {
} // XXX waitcursor(1);
- BLI_strncpy(name, filename, sizeof(name));
+ BLI_strncpy(name, filepath, sizeof(name));
BLI_path_abs(name, ref_file_name);
if (BLI_exists(name)) {
@@ -358,7 +358,7 @@ int BKE_packedfile_write_to_file(ReportList *reports,
}
enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
- const char *filename,
+ const char *filepath,
PackedFile *pf)
{
BLI_stat_t st;
@@ -366,7 +366,7 @@ enum ePF_FileCompare BKE_packedfile_compare_to_file(const char *ref_file_name,
char buf[4096];
char name[FILE_MAX];
- BLI_strncpy(name, filename, sizeof(name));
+ BLI_strncpy(name, filepath, sizeof(name));
BLI_path_abs(name, ref_file_name);
if (BLI_stat(name, &st) == -1) {
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index c47b22dcd34..9ea1336a95a 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -2661,8 +2661,8 @@ void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params
int from = PART_FROM_FACE;
totparent = (int)(totchild * part->parents * 0.3f);
- if (use_render_params && part->child_nbr && part->ren_child_nbr) {
- totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
+ if (use_render_params && part->child_percent && part->child_render_percent) {
+ totparent *= (float)part->child_percent / (float)part->child_render_percent;
}
/* hard limit, workaround for it being ignored above */
@@ -2736,8 +2736,8 @@ static bool psys_thread_context_init_path(ParticleThreadContext *ctx,
if (totchild && part->childtype == PART_CHILD_FACES) {
totparent = (int)(totchild * part->parents * 0.3f);
- if (use_render_params && part->child_nbr && part->ren_child_nbr) {
- totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
+ if (use_render_params && part->child_percent && part->child_render_percent) {
+ totparent *= (float)part->child_percent / (float)part->child_render_percent;
}
/* part->parents could still be 0 so we can't test with totparent */
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 83fb52ce1ef..d2c3776d4ea 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -64,14 +64,14 @@ static void distribute_simple_children(Scene *scene,
{
ChildParticle *cpa = NULL;
int i, p;
- int child_nbr = psys_get_child_number(scene, psys, use_render_params);
- int totpart = psys_get_tot_child(scene, psys, use_render_params);
+ const int child_num = psys_get_child_number(scene, psys, use_render_params);
+ const int totpart = psys_get_tot_child(scene, psys, use_render_params);
RNG *rng = BLI_rng_new_srandom(31415926 + psys->seed + psys->child_seed);
alloc_child_particles(psys, totpart);
cpa = psys->child;
- for (i = 0; i < child_nbr; i++) {
+ for (i = 0; i < child_num; i++) {
for (p = 0; p < psys->totpart; p++, cpa++) {
float length = 2.0;
cpa->parent = p;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 3a1aefec2d3..7fdc60a265b 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -98,9 +98,9 @@ float psys_get_current_display_percentage(ParticleSystem *psys, const bool use_r
ParticleSettings *part = psys->part;
if ((use_render_params &&
- !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
- (part->child_nbr && part->childtype) || /* display percentage applies to children */
- (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
+ !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
+ (part->child_percent && part->childtype) || /* display percentage applies to children */
+ (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
{
return 1.0f;
}
@@ -280,20 +280,20 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
int psys_get_child_number(Scene *scene, ParticleSystem *psys, const bool use_render_params)
{
- int nbr;
+ int child_num;
if (!psys->part->childtype) {
return 0;
}
if (use_render_params) {
- nbr = psys->part->ren_child_nbr;
+ child_num = psys->part->child_render_percent;
}
else {
- nbr = psys->part->child_nbr;
+ child_num = psys->part->child_percent;
}
- return get_render_child_particle_number(&scene->r, nbr, use_render_params);
+ return get_render_child_particle_number(&scene->r, child_num, use_render_params);
}
int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render_params)
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.cc
index 6797538d190..cebe4482eb7 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.cc
@@ -8,9 +8,9 @@
/* Allow using deprecated functionality for .blend file I/O. */
#define DNA_DEPRECATED_ALLOW
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
+#include <cstddef>
+#include <cstdio>
+#include <cstring>
#include "MEM_guardedalloc.h"
@@ -183,11 +183,11 @@ static void scene_init_data(ID *id)
/* multiview - stereo */
BKE_scene_add_render_view(scene, STEREO_LEFT_NAME);
- srv = scene->r.views.first;
+ srv = static_cast<SceneRenderView *>(scene->r.views.first);
BLI_strncpy(srv->suffix, STEREO_LEFT_SUFFIX, sizeof(srv->suffix));
BKE_scene_add_render_view(scene, STEREO_RIGHT_NAME);
- srv = scene->r.views.last;
+ srv = static_cast<SceneRenderView *>(scene->r.views.last);
BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix));
BKE_sound_reset_scene_runtime(scene);
@@ -218,14 +218,14 @@ static void scene_init_data(ID *id)
/* Master Collection */
scene->master_collection = BKE_collection_master_add();
- BKE_view_layer_add(scene, "ViewLayer", NULL, VIEWLAYER_ADD_NEW);
+ BKE_view_layer_add(scene, "ViewLayer", nullptr, VIEWLAYER_ADD_NEW);
}
static void scene_copy_markers(Scene *scene_dst, const Scene *scene_src, const int flag)
{
BLI_duplicatelist(&scene_dst->markers, &scene_src->markers);
LISTBASE_FOREACH (TimeMarker *, marker, &scene_dst->markers) {
- if (marker->prop != NULL) {
+ if (marker->prop != nullptr) {
marker->prop = IDP_CopyProperty_ex(marker->prop, flag);
}
}
@@ -240,9 +240,9 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* We always need allocation of our private ID data. */
const int flag_private_id_data = flag & ~LIB_ID_CREATE_NO_ALLOCATE;
- scene_dst->ed = NULL;
- scene_dst->depsgraph_hash = NULL;
- scene_dst->fps_info = NULL;
+ scene_dst->ed = nullptr;
+ scene_dst->depsgraph_hash = nullptr;
+ scene_dst->fps_info = nullptr;
/* Master Collection */
if (scene_src->master_collection) {
@@ -254,8 +254,8 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* View Layers */
BLI_duplicatelist(&scene_dst->view_layers, &scene_src->view_layers);
- for (ViewLayer *view_layer_src = scene_src->view_layers.first,
- *view_layer_dst = scene_dst->view_layers.first;
+ for (ViewLayer *view_layer_src = static_cast<ViewLayer *>(scene_src->view_layers.first),
+ *view_layer_dst = static_cast<ViewLayer *>(scene_dst->view_layers.first);
view_layer_src;
view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next) {
BKE_view_layer_copy_data(scene_dst, scene_src, view_layer_dst, view_layer_src, flag_subdata);
@@ -299,7 +299,8 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* make a private copy of the avicodecdata */
if (scene_src->r.avicodecdata) {
- scene_dst->r.avicodecdata = MEM_dupallocN(scene_src->r.avicodecdata);
+ scene_dst->r.avicodecdata = static_cast<AviCodecData *>(
+ MEM_dupallocN(scene_src->r.avicodecdata));
scene_dst->r.avicodecdata->lpFormat = MEM_dupallocN(scene_dst->r.avicodecdata->lpFormat);
scene_dst->r.avicodecdata->lpParms = MEM_dupallocN(scene_dst->r.avicodecdata->lpParms);
}
@@ -312,7 +313,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
/* Copy sequencer, this is local data! */
if (scene_src->ed) {
- scene_dst->ed = MEM_callocN(sizeof(*scene_dst->ed), __func__);
+ scene_dst->ed = MEM_cnew<Editing>(__func__);
scene_dst->ed->seqbasep = &scene_dst->ed->seqbase;
SEQ_sequence_base_dupli_recursive(scene_src,
scene_dst,
@@ -326,7 +327,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
BKE_previewimg_id_copy(&scene_dst->id, &scene_src->id);
}
else {
- scene_dst->preview = NULL;
+ scene_dst->preview = nullptr;
}
BKE_scene_copy_data_eevee(scene_dst, scene_src);
@@ -335,7 +336,7 @@ static void scene_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int
static void scene_free_markers(Scene *scene, bool do_id_user)
{
LISTBASE_FOREACH_MUTABLE (TimeMarker *, marker, &scene->markers) {
- if (marker->prop != NULL) {
+ if (marker->prop != nullptr) {
IDP_FreePropertyContent_ex(marker->prop, do_id_user);
MEM_freeN(marker->prop);
}
@@ -357,22 +358,22 @@ static void scene_free_data(ID *id)
if (scene->nodetree) {
ntreeFreeEmbeddedTree(scene->nodetree);
MEM_freeN(scene->nodetree);
- scene->nodetree = NULL;
+ scene->nodetree = nullptr;
}
if (scene->rigidbody_world) {
/* Prevent rigidbody freeing code to follow other IDs pointers, this should never be allowed
* nor necessary from here, and with new undo code, those pointers may be fully invalid or
* worse, pointing to data actually belonging to new BMain! */
- scene->rigidbody_world->constraints = NULL;
- scene->rigidbody_world->group = NULL;
+ scene->rigidbody_world->constraints = nullptr;
+ scene->rigidbody_world->group = nullptr;
BKE_rigidbody_free_world(scene);
}
if (scene->r.avicodecdata) {
free_avicodecdata(scene->r.avicodecdata);
MEM_freeN(scene->r.avicodecdata);
- scene->r.avicodecdata = NULL;
+ scene->r.avicodecdata = nullptr;
}
scene_free_markers(scene, do_id_user);
@@ -380,7 +381,7 @@ static void scene_free_data(ID *id)
BLI_freelistN(&scene->r.views);
BKE_toolsettings_free(scene->toolsettings);
- scene->toolsettings = NULL;
+ scene->toolsettings = nullptr;
BKE_scene_free_depsgraph_hash(scene);
@@ -395,10 +396,7 @@ static void scene_free_data(ID *id)
BKE_previewimg_free(&scene->preview);
BKE_curvemapping_free_data(&scene->r.mblur_shutter_curve);
- for (ViewLayer *view_layer = scene->view_layers.first, *view_layer_next; view_layer;
- view_layer = view_layer_next) {
- view_layer_next = view_layer->next;
-
+ LISTBASE_FOREACH_MUTABLE (ViewLayer *, view_layer, &scene->view_layers) {
BLI_remlink(&scene->view_layers, view_layer);
BKE_view_layer_free_ex(view_layer, do_id_user);
}
@@ -412,21 +410,21 @@ static void scene_free_data(ID *id)
BKE_collection_free_data(scene->master_collection);
BKE_libblock_free_data_py(&scene->master_collection->id);
MEM_freeN(scene->master_collection);
- scene->master_collection = NULL;
+ scene->master_collection = nullptr;
}
if (scene->eevee.light_cache_data) {
EEVEE_lightcache_free(scene->eevee.light_cache_data);
- scene->eevee.light_cache_data = NULL;
+ scene->eevee.light_cache_data = nullptr;
}
if (scene->display.shading.prop) {
IDP_FreeProperty(scene->display.shading.prop);
- scene->display.shading.prop = NULL;
+ scene->display.shading.prop = nullptr;
}
/* These are freed on doversion. */
- BLI_assert(scene->layer_properties == NULL);
+ BLI_assert(scene->layer_properties == nullptr);
}
static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSED(rbw),
@@ -443,14 +441,14 @@ static void scene_foreach_rigidbodyworldSceneLooper(struct RigidBodyWorld *UNUSE
* This code is shared by both the regular `foreach_id` looper, and the code trying to restore or
* preserve ID pointers like brushes across undo-steps.
*/
-typedef enum eSceneForeachUndoPreserveProcess {
+enum eSceneForeachUndoPreserveProcess {
/* Undo when preserving tool-settings from old scene, we also want to try to preserve that ID
* pointer from its old scene's value. */
SCENE_FOREACH_UNDO_RESTORE,
/* Undo when preserving tool-settings from old scene, we want to keep the new value of that ID
* pointer. */
SCENE_FOREACH_UNDO_NO_RESTORE,
-} eSceneForeachUndoPreserveProcess;
+};
static void scene_foreach_toolsettings_id_pointer_process(
ID **id_p,
@@ -464,9 +462,10 @@ static void scene_foreach_toolsettings_id_pointer_process(
ID *id_old = *id_old_p;
/* Old data has not been remapped to new values of the pointers, if we want to keep the old
* pointer here we need its new address. */
- ID *id_old_new = id_old != NULL ? BLO_read_get_new_id_address(reader, id_old->lib, id_old) :
- NULL;
- if (id_old_new != NULL) {
+ ID *id_old_new = id_old != nullptr ?
+ BLO_read_get_new_id_address(reader, id_old->lib, id_old) :
+ nullptr;
+ if (id_old_new != nullptr) {
BLI_assert(ELEM(id_old, id_old_new, id_old_new->orig_id));
*id_old_p = id_old_new;
if (cb_flag & IDWALK_CB_USER) {
@@ -489,7 +488,7 @@ static void scene_foreach_toolsettings_id_pointer_process(
/* Special handling is needed here, as `scene_foreach_toolsettings` (and its dependency
* `scene_foreach_paint`) are also used by `scene_undo_preserve`, where `LibraryForeachIDData
- * *data` is NULL. */
+ * *data` is nullptr. */
#define BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER( \
__data, __id, __do_undo_restore, __action, __reader, __id_old, __cb_flag) \
{ \
@@ -498,7 +497,7 @@ static void scene_foreach_toolsettings_id_pointer_process(
(ID **)&(__id), __action, __reader, (ID **)&(__id_old), __cb_flag); \
} \
else { \
- BLI_assert((__data) != NULL); \
+ BLI_assert((__data) != nullptr); \
BKE_LIB_FOREACHID_PROCESS_IDSUPER(__data, __id, __cb_flag); \
} \
} \
@@ -511,7 +510,7 @@ static void scene_foreach_toolsettings_id_pointer_process(
__func_call; \
} \
else { \
- BLI_assert((__data) != NULL); \
+ BLI_assert((__data) != nullptr); \
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(__data, __func_call); \
} \
} \
@@ -536,10 +535,10 @@ static void scene_foreach_paint(LibraryForeachIDData *data,
* this is equivalent to simply looping over slots from `paint`.
* - In case we do `undo_restore`, we only want to consider the slots from the old one, since
* those are the one we keep in the end.
- * + In case the new data has less valid slots, we feed in a dummy NULL pointer.
+ * + In case the new data has less valid slots, we feed in a dummy null pointer.
* + In case the new data has more valid slots, the extra ones are ignored.
*/
- Brush *brush_tmp = NULL;
+ Brush *brush_tmp = nullptr;
Brush **brush_p = i < paint->tool_slots_len ? &paint->tool_slots[i].brush : &brush_tmp;
BKE_LIB_FOREACHID_UNDO_PRESERVE_PROCESS_IDSUPER(data,
*brush_p,
@@ -725,7 +724,7 @@ static void scene_foreach_layer_collection(LibraryForeachIDData *data, ListBase
LISTBASE_FOREACH (LayerCollection *, lc, lb) {
/* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad
* anyway... */
- const int cb_flag = (lc->collection != NULL &&
+ const int cb_flag = (lc->collection != nullptr &&
(lc->collection->id.flag & LIB_EMBEDDED_DATA) != 0) ?
IDWALK_CB_EMBEDDED :
IDWALK_CB_NOP;
@@ -760,7 +759,7 @@ static bool seq_foreach_member_id_cb(Sequence *seq, void *user_data)
}
if (seq->type == SEQ_TYPE_TEXT && seq->effectdata) {
- TextVars *text_data = seq->effectdata;
+ TextVars *text_data = static_cast<TextVars *>(seq->effectdata);
FOREACHID_PROCESS_IDSUPER(data, text_data->text_font, IDWALK_CB_USER);
}
@@ -792,8 +791,8 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data,
BKE_keyingsets_foreach_id(data, &scene->keyingsets));
- /* This pointer can be NULL during old files reading, better be safe than sorry. */
- if (scene->master_collection != NULL) {
+ /* This pointer can be nullptr during old files reading, better be safe than sorry. */
+ if (scene->master_collection != nullptr) {
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
data, BKE_library_foreach_ID_embedded(data, (ID **)&scene->master_collection));
}
@@ -839,7 +838,7 @@ static void scene_foreach_id(ID *id, LibraryForeachIDData *data)
ToolSettings *toolsett = scene->toolsettings;
if (toolsett) {
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
- data, scene_foreach_toolsettings(data, toolsett, false, NULL, toolsett));
+ data, scene_foreach_toolsettings(data, toolsett, false, nullptr, toolsett));
}
if (scene->rigidbody_world) {
@@ -855,11 +854,10 @@ static void scene_foreach_cache(ID *id,
void *user_data)
{
Scene *scene = (Scene *)id;
- IDCacheKey key = {
- .id_session_uuid = id->session_uuid,
- .offset_in_ID = offsetof(Scene, eevee.light_cache_data),
- .cache_v = scene->eevee.light_cache_data,
- };
+ IDCacheKey key{};
+ key.id_session_uuid = id->session_uuid;
+ key.offset_in_ID = offsetof(Scene, eevee.light_cache_data);
+ key.cache_v = scene->eevee.light_cache_data;
function_callback(id,
&key,
@@ -902,7 +900,7 @@ static bool seq_foreach_path_callback(Sequence *seq, void *user_data)
static void scene_foreach_path(ID *id, BPathForeachPathData *bpath_data)
{
Scene *scene = (Scene *)id;
- if (scene->ed != NULL) {
+ if (scene->ed != nullptr) {
SEQ_for_each_callback(&scene->ed->seqbase, seq_foreach_path_callback, bpath_data);
}
}
@@ -1012,7 +1010,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
LISTBASE_FOREACH (TimeMarker *, marker, &sce->markers) {
BLO_write_struct(writer, TimeMarker, marker);
- if (marker->prop != NULL) {
+ if (marker->prop != nullptr) {
IDP_BlendWrite(writer, marker->prop);
}
}
@@ -1069,7 +1067,7 @@ static void scene_blend_write(BlendWriter *writer, ID *id, const void *id_addres
BKE_screen_view3d_shading_blend_write(writer, &sce->display.shading);
/* Freed on doversion. */
- BLI_assert(sce->layer_properties == NULL);
+ BLI_assert(sce->layer_properties == nullptr);
}
static void direct_link_paint_helper(BlendDataReader *reader, const Scene *scene, Paint **paint)
@@ -1102,8 +1100,8 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
{
Scene *sce = (Scene *)id;
- sce->depsgraph_hash = NULL;
- sce->fps_info = NULL;
+ sce->depsgraph_hash = nullptr;
+ sce->fps_info = nullptr;
memset(&sce->customdata_mask, 0, sizeof(sce->customdata_mask));
memset(&sce->customdata_mask_modal, 0, sizeof(sce->customdata_mask_modal));
@@ -1144,10 +1142,10 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
BKE_paint_blend_read_data(reader, sce, &sce->toolsettings->imapaint.paint);
- sce->toolsettings->particle.paintcursor = NULL;
- sce->toolsettings->particle.scene = NULL;
- sce->toolsettings->particle.object = NULL;
- sce->toolsettings->gp_sculpt.paintcursor = NULL;
+ sce->toolsettings->particle.paintcursor = nullptr;
+ sce->toolsettings->particle.scene = nullptr;
+ sce->toolsettings->particle.object = nullptr;
+ sce->toolsettings->gp_sculpt.paintcursor = nullptr;
/* relink grease pencil interpolation curves */
BLO_read_data_address(reader, &sce->toolsettings->gp_interpolate.custom_ipo);
@@ -1181,9 +1179,9 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
Editing *ed = sce->ed;
BLO_read_data_address(reader, &ed->act_seq);
- ed->cache = NULL;
- ed->prefetch_job = NULL;
- ed->runtime.sequence_lookup = NULL;
+ ed->cache = nullptr;
+ ed->prefetch_job = nullptr;
+ ed->runtime.sequence_lookup = nullptr;
/* recursive link sequences, lb will be correctly initialized */
link_recurs_seq(reader, &ed->seqbase);
@@ -1275,9 +1273,9 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
if (rbw) {
BLO_read_data_address(reader, &rbw->shared);
- if (rbw->shared == NULL) {
+ if (rbw->shared == nullptr) {
/* Link deprecated caches if they exist, so we can use them for versioning.
- * We should only do this when rbw->shared == NULL, because those pointers
+ * We should only do this when rbw->shared == nullptr, because those pointers
* are always set (for compatibility with older Blenders). We mustn't link
* the same pointcache twice. */
BKE_ptcache_blend_read_data(reader, &rbw->ptcaches, &rbw->pointcache, false);
@@ -1291,7 +1289,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
/* must nullify the reference to physics sim object, since it no-longer exist
* (and will need to be recalculated)
*/
- rbw->shared->physics_world = NULL;
+ rbw->shared->physics_world = nullptr;
/* link caches */
BKE_ptcache_blend_read_data(reader, &rbw->shared->ptcaches, &rbw->shared->pointcache, false);
@@ -1301,13 +1299,13 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
rbw->ltime = (float)rbw->shared->pointcache->startframe;
}
}
- rbw->objects = NULL;
+ rbw->objects = nullptr;
rbw->numbodies = 0;
/* set effector weights */
BLO_read_data_address(reader, &rbw->effector_weights);
if (!rbw->effector_weights) {
- rbw->effector_weights = BKE_effector_add_weights(NULL);
+ rbw->effector_weights = BKE_effector_add_weights(nullptr);
}
}
@@ -1352,7 +1350,7 @@ static void scene_blend_read_data(BlendDataReader *reader, ID *id)
static void composite_patch(bNodeTree *ntree, Scene *scene)
{
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
- if (node->id == NULL &&
+ if (node->id == nullptr &&
((node->type == CMP_NODE_R_LAYERS) ||
(node->type == CMP_NODE_CRYPTOMATTE && node->custom1 == CMP_CRYPTOMATTE_SRC_RENDER))) {
node->id = &scene->id;
@@ -1423,14 +1421,14 @@ static void scene_blend_read_lib(BlendLibReader *reader, ID *id)
LISTBASE_FOREACH_MUTABLE (Base *, base_legacy, &sce->base) {
BLO_read_id_address(reader, sce->id.lib, &base_legacy->object);
- if (base_legacy->object == NULL) {
+ if (base_legacy->object == nullptr) {
BLO_reportf_wrap(BLO_read_lib_reports(reader),
RPT_WARNING,
TIP_("LIB: object lost from scene: '%s'"),
sce->id.name + 2);
BLI_remlink(&sce->base, base_legacy);
if (base_legacy == sce->basact) {
- sce->basact = NULL;
+ sce->basact = nullptr;
}
MEM_freeN(base_legacy);
}
@@ -1494,7 +1492,7 @@ static void scene_blend_read_lib(BlendLibReader *reader, ID *id)
}
#ifdef USE_SETSCENE_CHECK
- if (sce->set != NULL) {
+ if (sce->set != nullptr) {
sce->flag |= SCE_READFILE_LIBLINK_NEED_SETSCENE_CHECK;
}
#endif
@@ -1588,12 +1586,12 @@ static void scene_undo_preserve(BlendLibReader *reader, ID *id_new, ID *id_old)
Scene *scene_old = (Scene *)id_old;
SWAP(View3DCursor, scene_old->cursor, scene_new->cursor);
- if (scene_new->toolsettings != NULL && scene_old->toolsettings != NULL) {
+ if (scene_new->toolsettings != nullptr && scene_old->toolsettings != nullptr) {
/* First try to restore ID pointers that can be and should be preserved (like brushes or
* palettes), and counteract the swap of the whole ToolSettings structs below for the others
* (like object ones). */
scene_foreach_toolsettings(
- NULL, scene_new->toolsettings, true, reader, scene_old->toolsettings);
+ nullptr, scene_new->toolsettings, true, reader, scene_old->toolsettings);
SWAP(ToolSettings, *scene_old->toolsettings, *scene_new->toolsettings);
}
}
@@ -1602,46 +1600,50 @@ static void scene_lib_override_apply_post(ID *id_dst, ID *UNUSED(id_src))
{
Scene *scene = (Scene *)id_dst;
- if (scene->rigidbody_world != NULL) {
+ if (scene->rigidbody_world != nullptr) {
PTCacheID pid;
- BKE_ptcache_id_from_rigidbody(&pid, NULL, scene->rigidbody_world);
+ BKE_ptcache_id_from_rigidbody(&pid, nullptr, scene->rigidbody_world);
LISTBASE_FOREACH (PointCache *, point_cache, pid.ptcaches) {
point_cache->flag |= PTCACHE_FLAG_INFO_DIRTY;
}
}
}
-IDTypeInfo IDType_ID_SCE = {
- .id_code = ID_SCE,
- .id_filter = FILTER_ID_SCE,
- .main_listbase_index = INDEX_ID_SCE,
- .struct_size = sizeof(Scene),
- .name = "Scene",
- .name_plural = "scenes",
- .translation_context = BLT_I18NCONTEXT_ID_SCENE,
- .flags = 0,
- .asset_type_info = NULL,
+constexpr IDTypeInfo get_type_info()
+{
+ IDTypeInfo info{};
+ info.id_code = ID_SCE;
+ info.id_filter = FILTER_ID_SCE;
+ info.main_listbase_index = INDEX_ID_SCE;
+ info.struct_size = sizeof(Scene);
+ info.name = "Scene";
+ info.name_plural = "scenes";
+ info.translation_context = BLT_I18NCONTEXT_ID_SCENE;
+ info.flags = 0;
+ info.asset_type_info = nullptr;
- .init_data = scene_init_data,
- .copy_data = scene_copy_data,
- .free_data = scene_free_data,
- /* For now default `BKE_lib_id_make_local_generic()` should work, may need more work though to
- * support all possible corner cases. */
- .make_local = NULL,
- .foreach_id = scene_foreach_id,
- .foreach_cache = scene_foreach_cache,
- .foreach_path = scene_foreach_path,
- .owner_get = NULL,
+ info.init_data = scene_init_data;
+ info.copy_data = scene_copy_data;
+ info.free_data = scene_free_data;
+ /* For now default `BKE_lib_id_make_local_generic()` should work, may need more work though to
+ * support all possible corner cases. */
+ info.make_local = nullptr;
+ info.foreach_id = scene_foreach_id;
+ info.foreach_cache = scene_foreach_cache;
+ info.foreach_path = scene_foreach_path;
+ info.owner_get = nullptr;
- .blend_write = scene_blend_write,
- .blend_read_data = scene_blend_read_data,
- .blend_read_lib = scene_blend_read_lib,
- .blend_read_expand = scene_blend_read_expand,
+ info.blend_write = scene_blend_write;
+ info.blend_read_data = scene_blend_read_data;
+ info.blend_read_lib = scene_blend_read_lib;
+ info.blend_read_expand = scene_blend_read_expand;
- .blend_read_undo_preserve = scene_undo_preserve,
+ info.blend_read_undo_preserve = scene_undo_preserve;
- .lib_override_apply_post = scene_lib_override_apply_post,
-};
+ info.lib_override_apply_post = scene_lib_override_apply_post;
+ return info;
+}
+IDTypeInfo IDType_ID_SCE = get_type_info();
const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE";
const char *RE_engine_id_BLENDER_WORKBENCH = "BLENDER_WORKBENCH";
@@ -1652,12 +1654,12 @@ void free_avicodecdata(AviCodecData *acd)
if (acd) {
if (acd->lpFormat) {
MEM_freeN(acd->lpFormat);
- acd->lpFormat = NULL;
+ acd->lpFormat = nullptr;
acd->cbFormat = 0;
}
if (acd->lpParms) {
MEM_freeN(acd->lpParms);
- acd->lpParms = NULL;
+ acd->lpParms = nullptr;
acd->cbParms = 0;
}
}
@@ -1668,11 +1670,7 @@ static void remove_sequencer_fcurves(Scene *sce)
AnimData *adt = BKE_animdata_from_id(&sce->id);
if (adt && adt->action) {
- FCurve *fcu, *nextfcu;
-
- for (fcu = adt->action->curves.first; fcu; fcu = nextfcu) {
- nextfcu = fcu->next;
-
+ LISTBASE_FOREACH_MUTABLE (FCurve *, fcu, &adt->action->curves) {
if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) {
action_groups_remove_channel(adt->action, fcu);
BKE_fcurve_free(fcu);
@@ -1683,51 +1681,51 @@ static void remove_sequencer_fcurves(Scene *sce)
ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
{
- if (toolsettings == NULL) {
- return NULL;
+ if (toolsettings == nullptr) {
+ return nullptr;
}
- ToolSettings *ts = MEM_dupallocN(toolsettings);
+ ToolSettings *ts = static_cast<ToolSettings *>(MEM_dupallocN(toolsettings));
if (ts->vpaint) {
- ts->vpaint = MEM_dupallocN(ts->vpaint);
+ ts->vpaint = static_cast<VPaint *>(MEM_dupallocN(ts->vpaint));
BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag);
}
if (ts->wpaint) {
- ts->wpaint = MEM_dupallocN(ts->wpaint);
+ ts->wpaint = static_cast<VPaint *>(MEM_dupallocN(ts->wpaint));
BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag);
}
if (ts->sculpt) {
- ts->sculpt = MEM_dupallocN(ts->sculpt);
+ ts->sculpt = static_cast<Sculpt *>(MEM_dupallocN(ts->sculpt));
BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag);
}
if (ts->uvsculpt) {
- ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
+ ts->uvsculpt = static_cast<UvSculpt *>(MEM_dupallocN(ts->uvsculpt));
BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag);
}
if (ts->gp_paint) {
- ts->gp_paint = MEM_dupallocN(ts->gp_paint);
+ ts->gp_paint = static_cast<GpPaint *>(MEM_dupallocN(ts->gp_paint));
BKE_paint_copy(&ts->gp_paint->paint, &ts->gp_paint->paint, flag);
}
if (ts->gp_vertexpaint) {
- ts->gp_vertexpaint = MEM_dupallocN(ts->gp_vertexpaint);
+ ts->gp_vertexpaint = static_cast<GpVertexPaint *>(MEM_dupallocN(ts->gp_vertexpaint));
BKE_paint_copy(&ts->gp_vertexpaint->paint, &ts->gp_vertexpaint->paint, flag);
}
if (ts->gp_sculptpaint) {
- ts->gp_sculptpaint = MEM_dupallocN(ts->gp_sculptpaint);
+ ts->gp_sculptpaint = static_cast<GpSculptPaint *>(MEM_dupallocN(ts->gp_sculptpaint));
BKE_paint_copy(&ts->gp_sculptpaint->paint, &ts->gp_sculptpaint->paint, flag);
}
if (ts->gp_weightpaint) {
- ts->gp_weightpaint = MEM_dupallocN(ts->gp_weightpaint);
+ ts->gp_weightpaint = static_cast<GpWeightPaint *>(MEM_dupallocN(ts->gp_weightpaint));
BKE_paint_copy(&ts->gp_weightpaint->paint, &ts->gp_weightpaint->paint, flag);
}
if (ts->curves_sculpt) {
- ts->curves_sculpt = MEM_dupallocN(ts->curves_sculpt);
+ ts->curves_sculpt = static_cast<CurvesSculpt *>(MEM_dupallocN(ts->curves_sculpt));
BKE_paint_copy(&ts->curves_sculpt->paint, &ts->curves_sculpt->paint, flag);
}
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
- ts->particle.paintcursor = NULL;
- ts->particle.scene = NULL;
- ts->particle.object = NULL;
+ ts->particle.paintcursor = nullptr;
+ ts->particle.scene = nullptr;
+ ts->particle.object = nullptr;
/* duplicate Grease Pencil interpolation curve */
ts->gp_interpolate.custom_ipo = BKE_curvemapping_copy(ts->gp_interpolate.custom_ipo);
@@ -1743,7 +1741,7 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
void BKE_toolsettings_free(ToolSettings *toolsettings)
{
- if (toolsettings == NULL) {
+ if (toolsettings == nullptr) {
return;
}
if (toolsettings->vpaint) {
@@ -1811,7 +1809,7 @@ void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src)
{
/* Copy eevee data between scenes. */
sce_dst->eevee = sce_src->eevee;
- sce_dst->eevee.light_cache_data = NULL;
+ sce_dst->eevee.light_cache_data = nullptr;
sce_dst->eevee.light_cache_info[0] = '\0';
/* TODO: Copy the cache. */
}
@@ -1862,7 +1860,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
/* make a private copy of the avicodecdata */
if (sce->r.avicodecdata) {
- sce_copy->r.avicodecdata = MEM_dupallocN(sce->r.avicodecdata);
+ sce_copy->r.avicodecdata = static_cast<AviCodecData *>(MEM_dupallocN(sce->r.avicodecdata));
sce_copy->r.avicodecdata->lpFormat = MEM_dupallocN(sce_copy->r.avicodecdata->lpFormat);
sce_copy->r.avicodecdata->lpParms = MEM_dupallocN(sce_copy->r.avicodecdata->lpParms);
}
@@ -1870,14 +1868,14 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
BKE_sound_reset_scene_runtime(sce_copy);
/* grease pencil */
- sce_copy->gpd = NULL;
+ sce_copy->gpd = nullptr;
- sce_copy->preview = NULL;
+ sce_copy->preview = nullptr;
return sce_copy;
}
- eDupli_ID_Flags duplicate_flags = U.dupflag | USER_DUP_OBJECT;
+ eDupli_ID_Flags duplicate_flags = (eDupli_ID_Flags)(U.dupflag | USER_DUP_OBJECT);
sce_copy = (Scene *)BKE_id_copy(bmain, (ID *)sce);
id_us_min(&sce_copy->id);
@@ -1900,7 +1898,7 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
/* In case root duplicated ID is linked, assume we want to get a local copy of it and
* duplicate all expected linked data. */
if (ID_IS_LINKED(sce)) {
- duplicate_flags |= USER_DUP_LINKED_ID;
+ duplicate_flags = (eDupli_ID_Flags)(duplicate_flags | USER_DUP_LINKED_ID);
}
}
@@ -1919,22 +1917,25 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type)
/* Deep-duplicate collections and objects (using preferences' settings for which sub-data to
* duplicate along the object itself). */
- BKE_collection_duplicate(
- bmain, NULL, sce_copy->master_collection, duplicate_flags, LIB_ID_DUPLICATE_IS_SUBPROCESS);
+ BKE_collection_duplicate(bmain,
+ nullptr,
+ sce_copy->master_collection,
+ duplicate_flags,
+ LIB_ID_DUPLICATE_IS_SUBPROCESS);
/* Rigid body world collections may not be instantiated as scene's collections, ensure they
* also get properly duplicated. */
- if (sce_copy->rigidbody_world != NULL) {
- if (sce_copy->rigidbody_world->group != NULL) {
+ if (sce_copy->rigidbody_world != nullptr) {
+ if (sce_copy->rigidbody_world->group != nullptr) {
BKE_collection_duplicate(bmain,
- NULL,
+ nullptr,
sce_copy->rigidbody_world->group,
duplicate_flags,
LIB_ID_DUPLICATE_IS_SUBPROCESS);
}
- if (sce_copy->rigidbody_world->constraints != NULL) {
+ if (sce_copy->rigidbody_world->constraints != nullptr) {
BKE_collection_duplicate(bmain,
- NULL,
+ nullptr,
sce_copy->rigidbody_world->constraints,
duplicate_flags,
LIB_ID_DUPLICATE_IS_SUBPROCESS);
@@ -1995,9 +1996,7 @@ bool BKE_scene_can_be_removed(const Main *bmain, const Scene *scene)
Scene *BKE_scene_add(Main *bmain, const char *name)
{
- Scene *sce;
-
- sce = BKE_id_new(bmain, ID_SCE, name);
+ Scene *sce = static_cast<Scene *>(BKE_id_new(bmain, ID_SCE, name));
id_us_min(&sce->id);
id_us_ensure_real(&sce->id);
@@ -2023,25 +2022,22 @@ Object *BKE_scene_object_find_by_name(const Scene *scene, const char *name)
}
}
}
- return NULL;
+ return nullptr;
}
void BKE_scene_set_background(Main *bmain, Scene *scene)
{
- Object *ob;
-
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
/* deselect objects (for dataselect) */
- for (ob = bmain->objects.first; ob; ob = ob->id.next) {
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
ob->flag &= ~SELECT;
}
/* copy layers and flags from bases to objects */
LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
LISTBASE_FOREACH (Base *, base, &view_layer->object_bases) {
- ob = base->object;
/* collection patch... */
BKE_scene_object_base_flag_sync_from_base(base);
}
@@ -2060,7 +2056,7 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
}
printf("Can't find scene: '%s' in file: '%s'\n", name, BKE_main_blendfile_path(bmain));
- return NULL;
+ return nullptr;
}
int BKE_scene_base_iter_next(
@@ -2071,9 +2067,9 @@ int BKE_scene_base_iter_next(
/* init */
if (val == 0) {
iter->phase = F_START;
- iter->dupob = NULL;
- iter->duplilist = NULL;
- iter->dupli_refob = NULL;
+ iter->dupob = nullptr;
+ iter->duplilist = nullptr;
+ iter->dupli_refob = nullptr;
}
else {
/* run_again is set when a duplilist has been ended */
@@ -2084,7 +2080,7 @@ int BKE_scene_base_iter_next(
if (iter->phase == F_START) {
ViewLayer *view_layer = (depsgraph) ? DEG_get_evaluated_view_layer(depsgraph) :
BKE_view_layer_context_active_PLACEHOLDER(*scene);
- *base = view_layer->object_bases.first;
+ *base = static_cast<Base *>(view_layer->object_bases.first);
if (*base) {
*ob = (*base)->object;
iter->phase = F_SCENE;
@@ -2095,7 +2091,7 @@ int BKE_scene_base_iter_next(
(*scene) = (*scene)->set;
ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene);
if (view_layer_set->object_bases.first) {
- *base = view_layer_set->object_bases.first;
+ *base = static_cast<Base *>(view_layer_set->object_bases.first);
*ob = (*base)->object;
iter->phase = F_SCENE;
break;
@@ -2116,7 +2112,7 @@ int BKE_scene_base_iter_next(
(*scene) = (*scene)->set;
ViewLayer *view_layer_set = BKE_view_layer_default_render(*scene);
if (view_layer_set->object_bases.first) {
- *base = view_layer_set->object_bases.first;
+ *base = static_cast<Base *>(view_layer_set->object_bases.first);
*ob = (*base)->object;
break;
}
@@ -2126,7 +2122,7 @@ int BKE_scene_base_iter_next(
}
}
- if (*base == NULL) {
+ if (*base == nullptr) {
iter->phase = F_START;
}
else {
@@ -2135,16 +2131,16 @@ int BKE_scene_base_iter_next(
/* Collections cannot be duplicated for meta-balls yet,
* this enters eternal loop because of
* makeDispListMBall getting called inside of collection_duplilist */
- if ((*base)->object->instance_collection == NULL) {
+ if ((*base)->object->instance_collection == nullptr) {
iter->duplilist = object_duplilist(depsgraph, (*scene), (*base)->object);
- iter->dupob = iter->duplilist->first;
+ iter->dupob = static_cast<DupliObject *>(iter->duplilist->first);
if (!iter->dupob) {
free_object_duplilist(iter->duplilist);
- iter->duplilist = NULL;
+ iter->duplilist = nullptr;
}
- iter->dupli_refob = NULL;
+ iter->dupli_refob = nullptr;
}
}
}
@@ -2174,11 +2170,11 @@ int BKE_scene_base_iter_next(
if (iter->dupli_refob) {
/* Restore last object's real matrix. */
copy_m4_m4(iter->dupli_refob->obmat, iter->omat);
- iter->dupli_refob = NULL;
+ iter->dupli_refob = nullptr;
}
free_object_duplilist(iter->duplilist);
- iter->duplilist = NULL;
+ iter->duplilist = nullptr;
run_again = true;
}
}
@@ -2195,7 +2191,7 @@ bool BKE_scene_has_view_layer(const Scene *scene, const ViewLayer *layer)
Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *collection)
{
- for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
LISTBASE_FOREACH (ViewLayer *, layer, &scene->view_layers) {
if (BKE_view_layer_has_collection(layer, collection)) {
return scene;
@@ -2203,21 +2199,21 @@ Scene *BKE_scene_find_from_collection(const Main *bmain, const Collection *colle
}
}
- return NULL;
+ return nullptr;
}
#ifdef DURIAN_CAMERA_SWITCH
Object *BKE_scene_camera_switch_find(Scene *scene)
{
if (scene->r.mode & R_NO_CAMERA_SWITCH) {
- return NULL;
+ return nullptr;
}
const int ctime = (int)BKE_scene_ctime_get(scene);
int frame = -(MAXFRAME + 1);
int min_frame = MAXFRAME + 1;
- Object *camera = NULL;
- Object *first_camera = NULL;
+ Object *camera = nullptr;
+ Object *first_camera = nullptr;
LISTBASE_FOREACH (TimeMarker *, m, &scene->markers) {
if (m->camera && (m->camera->visibility_flag & OB_HIDE_RENDER) == 0) {
@@ -2237,7 +2233,7 @@ Object *BKE_scene_camera_switch_find(Scene *scene)
}
}
- if (camera == NULL) {
+ if (camera == nullptr) {
/* If there's no marker to the left of current frame,
* use camera from left-most marker to solve all sort
* of Schrodinger uncertainties.
@@ -2270,7 +2266,10 @@ const char *BKE_scene_find_marker_name(const Scene *scene, int frame)
const TimeMarker *m1, *m2;
/* search through markers for match */
- for (m1 = markers->first, m2 = markers->last; m1 && m2; m1 = m1->next, m2 = m2->prev) {
+ for (m1 = static_cast<const TimeMarker *>(markers->first),
+ m2 = static_cast<const TimeMarker *>(markers->last);
+ m1 && m2;
+ m1 = m1->next, m2 = m2->prev) {
if (m1->frame == frame) {
return m1->name;
}
@@ -2284,14 +2283,14 @@ const char *BKE_scene_find_marker_name(const Scene *scene, int frame)
}
}
- return NULL;
+ return nullptr;
}
const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame)
{
- const TimeMarker *marker, *best_marker = NULL;
+ const TimeMarker *best_marker = nullptr;
int best_frame = -MAXFRAME * 2;
- for (marker = scene->markers.first; marker; marker = marker->next) {
+ LISTBASE_FOREACH (const TimeMarker *, marker, &scene->markers) {
if (marker->frame == frame) {
return marker->name;
}
@@ -2302,7 +2301,7 @@ const char *BKE_scene_find_last_marker_name(const Scene *scene, int frame)
}
}
- return best_marker ? best_marker->name : NULL;
+ return best_marker ? best_marker->name : nullptr;
}
int BKE_scene_frame_snap_by_seconds(Scene *scene, double interval_in_seconds, int frame)
@@ -2335,7 +2334,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
Scene *sce_iter;
int a, totscene;
- if (sce->set == NULL) {
+ if (sce->set == nullptr) {
return true;
}
totscene = BLI_listbase_count(&bmain->scenes);
@@ -2344,7 +2343,7 @@ bool BKE_scene_validate_setscene(Main *bmain, Scene *sce)
/* more iterations than scenes means we have a cycle */
if (a > totscene) {
/* the tested scene gets zero'ed, that's typically current scene */
- sce->set = NULL;
+ sce->set = nullptr;
return false;
}
}
@@ -2437,9 +2436,8 @@ int BKE_scene_orientation_get_index_from_flag(Scene *scene, int flag)
static bool check_rendered_viewport_visible(Main *bmain)
{
- wmWindowManager *wm = bmain->wm.first;
- wmWindow *window;
- for (window = wm->windows.first; window != NULL; window = window->next) {
+ wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
+ LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) {
const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
Scene *scene = window->scene;
RenderEngineType *type = RE_engines_find(scene->r.engine);
@@ -2448,8 +2446,8 @@ static bool check_rendered_viewport_visible(Main *bmain)
continue;
}
- for (ScrArea *area = screen->areabase.first; area != NULL; area = area->next) {
- View3D *v3d = area->spacedata.first;
+ LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
+ View3D *v3d = static_cast<View3D *>(area->spacedata.first);
if (area->spacetype != SPACE_VIEW3D) {
continue;
}
@@ -2462,7 +2460,7 @@ static bool check_rendered_viewport_visible(Main *bmain)
}
/* TODO(campbell): shouldn't we be able to use 'DEG_get_view_layer' here?
- * Currently this is NULL on load, so don't. */
+ * Currently this is nullptr on load, so don't. */
static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_layer)
{
/* This is needed to prepare mesh to be used by the render
@@ -2476,18 +2474,15 @@ static void prepare_mesh_for_viewport_render(Main *bmain, const ViewLayer *view_
Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (obedit) {
- Mesh *mesh = obedit->data;
+ Mesh *mesh = static_cast<Mesh *>(obedit->data);
if ((obedit->type == OB_MESH) &&
((obedit->id.recalc & ID_RECALC_ALL) || (mesh->id.recalc & ID_RECALC_ALL))) {
if (check_rendered_viewport_visible(bmain)) {
BMesh *bm = mesh->edit_mesh->bm;
- BM_mesh_bm_to_me(bmain,
- bm,
- mesh,
- (&(struct BMeshToMeshParams){
- .calc_object_remap = true,
- .update_shapekey_indices = true,
- }));
+ BMeshToMeshParams params{};
+ params.calc_object_remap = true;
+ params.update_shapekey_indices = true;
+ BM_mesh_bm_to_me(bmain, bm, mesh, &params);
DEG_id_tag_update(&mesh->id, 0);
}
}
@@ -2697,13 +2692,11 @@ void BKE_scene_view_layer_graph_evaluated_ensure(Main *bmain, Scene *scene, View
SceneRenderView *BKE_scene_add_render_view(Scene *sce, const char *name)
{
- SceneRenderView *srv;
-
if (!name) {
name = DATA_("RenderView");
}
- srv = MEM_callocN(sizeof(SceneRenderView), "new render view");
+ SceneRenderView *srv = MEM_cnew<SceneRenderView>(__func__);
BLI_strncpy(srv->name, name, sizeof(srv->name));
BLI_uniquename(&sce->r.views,
srv,
@@ -2751,17 +2744,17 @@ int get_render_subsurf_level(const RenderData *r, int lvl, bool for_render)
return lvl;
}
-int get_render_child_particle_number(const RenderData *r, int num, bool for_render)
+int get_render_child_particle_number(const RenderData *r, int child_num, bool for_render)
{
if (r->mode & R_SIMPLIFY) {
if (for_render) {
- return (int)(r->simplify_particles_render * num);
+ return (int)(r->simplify_particles_render * child_num);
}
- return (int)(r->simplify_particles * num);
+ return (int)(r->simplify_particles * child_num);
}
- return num;
+ return child_num;
}
Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
@@ -2770,7 +2763,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
/* Common case, step to the next. */
return base->next;
}
- if ((base == NULL) && (view_layer != NULL)) {
+ if ((base == nullptr) && (view_layer != nullptr)) {
/* First time looping, return the scenes first base. */
/* For the first loop we should get the layer from workspace when available. */
if (view_layer->object_bases.first) {
@@ -2792,7 +2785,7 @@ Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
}
}
- return NULL;
+ return nullptr;
}
bool BKE_scene_use_shading_nodes_custom(Scene *scene)
@@ -2823,10 +2816,10 @@ bool BKE_scene_uses_cycles(const Scene *scene)
}
/* This enumeration has to match the one defined in the Cycles addon. */
-typedef enum eCyclesFeatureSet {
+enum eCyclesFeatureSet {
CYCLES_FEATURES_SUPPORTED = 0,
CYCLES_FEATURES_EXPERIMENTAL = 1,
-} eCyclesFeatureSet;
+};
bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
{
@@ -2845,7 +2838,7 @@ bool BKE_scene_uses_cycles_experimental_features(Scene *scene)
void BKE_scene_base_flag_to_objects(ViewLayer *view_layer)
{
- Base *base = view_layer->object_bases.first;
+ Base *base = static_cast<Base *>(view_layer->object_bases.first);
while (base) {
BKE_scene_object_base_flag_sync_from_base(base);
@@ -2954,7 +2947,6 @@ double BKE_scene_unit_scale(const UnitSettings *unit, const int unit_type, doubl
int BKE_scene_multiview_num_views_get(const RenderData *rd)
{
- SceneRenderView *srv;
int totviews = 0;
if ((rd->scemode & R_MULTIVIEW) == 0) {
@@ -2962,18 +2954,20 @@ int BKE_scene_multiview_num_views_get(const RenderData *rd)
}
if (rd->views_format == SCE_VIEWS_FORMAT_STEREO_3D) {
- srv = BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name));
+ SceneRenderView *srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, STEREO_LEFT_NAME, offsetof(SceneRenderView, name)));
if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) {
totviews++;
}
- srv = BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name));
+ srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, STEREO_RIGHT_NAME, offsetof(SceneRenderView, name)));
if ((srv && srv->viewflag & SCE_VIEW_DISABLE) == 0) {
totviews++;
}
}
else {
- for (srv = rd->views.first; srv; srv = srv->next) {
+ LISTBASE_FOREACH (SceneRenderView *, srv, &rd->views) {
if ((srv->viewflag & SCE_VIEW_DISABLE) == 0) {
totviews++;
}
@@ -3001,7 +2995,7 @@ bool BKE_scene_multiview_is_stereo3d(const RenderData *rd)
bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const SceneRenderView *srv)
{
- if (srv == NULL) {
+ if (srv == nullptr) {
return false;
}
@@ -3027,8 +3021,6 @@ bool BKE_scene_multiview_is_render_view_active(const RenderData *rd, const Scene
bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *viewname)
{
- SceneRenderView *srv;
-
if ((rd->scemode & R_MULTIVIEW) == 0) {
return true;
}
@@ -3037,7 +3029,7 @@ bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *
return true;
}
- for (srv = rd->views.first; srv; srv = srv->next) {
+ LISTBASE_FOREACH (const SceneRenderView *, srv, &rd->views) {
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
return STREQ(viewname, srv->name);
}
@@ -3048,8 +3040,6 @@ bool BKE_scene_multiview_is_render_view_first(const RenderData *rd, const char *
bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *viewname)
{
- SceneRenderView *srv;
-
if ((rd->scemode & R_MULTIVIEW) == 0) {
return true;
}
@@ -3058,7 +3048,7 @@ bool BKE_scene_multiview_is_render_view_last(const RenderData *rd, const char *v
return true;
}
- for (srv = rd->views.last; srv; srv = srv->prev) {
+ LISTBASE_FOREACH_BACKWARD (const SceneRenderView *, srv, &rd->views) {
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
return STREQ(viewname, srv->name);
}
@@ -3073,10 +3063,10 @@ SceneRenderView *BKE_scene_multiview_render_view_findindex(const RenderData *rd,
size_t nr;
if ((rd->scemode & R_MULTIVIEW) == 0) {
- return NULL;
+ return nullptr;
}
- for (srv = rd->views.first, nr = 0; srv; srv = srv->next) {
+ for (srv = static_cast<SceneRenderView *>(rd->views.first), nr = 0; srv; srv = srv->next) {
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
if (nr++ == view_id) {
return srv;
@@ -3110,7 +3100,7 @@ int BKE_scene_multiview_view_id_get(const RenderData *rd, const char *viewname)
return 0;
}
- for (srv = rd->views.first, nr = 0; srv; srv = srv->next) {
+ for (srv = static_cast<SceneRenderView *>(rd->views.first), nr = 0; srv; srv = srv->next) {
if (BKE_scene_multiview_is_render_view_active(rd, srv)) {
if (STREQ(viewname, srv->name)) {
return nr;
@@ -3139,7 +3129,8 @@ void BKE_scene_multiview_view_filepath_get(const RenderData *rd,
SceneRenderView *srv;
char suffix[FILE_MAX];
- srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name));
+ srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)));
if (srv) {
BLI_strncpy(suffix, srv->suffix, sizeof(suffix));
}
@@ -3155,11 +3146,12 @@ const char *BKE_scene_multiview_view_suffix_get(const RenderData *rd, const char
{
SceneRenderView *srv;
- if ((viewname == NULL) || (viewname[0] == '\0')) {
+ if ((viewname == nullptr) || (viewname[0] == '\0')) {
return viewname;
}
- srv = BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name));
+ srv = static_cast<SceneRenderView *>(
+ BLI_findstring(&rd->views, viewname, offsetof(SceneRenderView, name)));
if (srv) {
return srv->suffix;
}
@@ -3182,7 +3174,6 @@ void BKE_scene_multiview_view_prefix_get(Scene *scene,
char *r_prefix,
const char **r_ext)
{
- SceneRenderView *srv;
size_t index_act;
const char *suf_act;
const char delims[] = {'.', '\0'};
@@ -3191,13 +3182,13 @@ void BKE_scene_multiview_view_prefix_get(Scene *scene,
/* begin of extension */
index_act = BLI_str_rpartition(name, delims, r_ext, &suf_act);
- if (*r_ext == NULL) {
+ if (*r_ext == nullptr) {
return;
}
BLI_assert(index_act > 0);
UNUSED_VARS_NDEBUG(index_act);
- for (srv = scene->r.views.first; srv; srv = srv->next) {
+ LISTBASE_FOREACH (SceneRenderView *, srv, &scene->r.views) {
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
const size_t len = strlen(srv->suffix);
const size_t ext_len = strlen(*r_ext);
@@ -3250,16 +3241,16 @@ int BKE_scene_multiview_num_videos_get(const RenderData *rd)
/* Manipulation of depsgraph storage. */
/* This is a key which identifies depsgraph. */
-typedef struct DepsgraphKey {
+struct DepsgraphKey {
const ViewLayer *view_layer;
/* TODO(sergey): Need to include window somehow (same layer might be in a
* different states in different windows).
*/
-} DepsgraphKey;
+};
static unsigned int depsgraph_key_hash(const void *key_v)
{
- const DepsgraphKey *key = key_v;
+ const DepsgraphKey *key = static_cast<const DepsgraphKey *>(key_v);
unsigned int hash = BLI_ghashutil_ptrhash(key->view_layer);
/* TODO(sergey): Include hash from other fields in the key. */
return hash;
@@ -3267,21 +3258,21 @@ static unsigned int depsgraph_key_hash(const void *key_v)
static bool depsgraph_key_compare(const void *key_a_v, const void *key_b_v)
{
- const DepsgraphKey *key_a = key_a_v;
- const DepsgraphKey *key_b = key_b_v;
+ const DepsgraphKey *key_a = static_cast<const DepsgraphKey *>(key_a_v);
+ const DepsgraphKey *key_b = static_cast<const DepsgraphKey *>(key_b_v);
/* TODO(sergey): Compare rest of. */
return !(key_a->view_layer == key_b->view_layer);
}
static void depsgraph_key_free(void *key_v)
{
- DepsgraphKey *key = key_v;
+ DepsgraphKey *key = static_cast<DepsgraphKey *>(key_v);
MEM_freeN(key);
}
static void depsgraph_key_value_free(void *value)
{
- Depsgraph *depsgraph = value;
+ Depsgraph *depsgraph = static_cast<Depsgraph *>(value);
DEG_graph_free(depsgraph);
}
@@ -3293,23 +3284,23 @@ void BKE_scene_allocate_depsgraph_hash(Scene *scene)
void BKE_scene_ensure_depsgraph_hash(Scene *scene)
{
- if (scene->depsgraph_hash == NULL) {
+ if (scene->depsgraph_hash == nullptr) {
BKE_scene_allocate_depsgraph_hash(scene);
}
}
void BKE_scene_free_depsgraph_hash(Scene *scene)
{
- if (scene->depsgraph_hash == NULL) {
+ if (scene->depsgraph_hash == nullptr) {
return;
}
BLI_ghash_free(scene->depsgraph_hash, depsgraph_key_free, depsgraph_key_value_free);
- scene->depsgraph_hash = NULL;
+ scene->depsgraph_hash = nullptr;
}
void BKE_scene_free_view_layer_depsgraph(Scene *scene, ViewLayer *view_layer)
{
- if (scene->depsgraph_hash != NULL) {
+ if (scene->depsgraph_hash != nullptr) {
DepsgraphKey key = {view_layer};
BLI_ghash_remove(scene->depsgraph_hash, &key, depsgraph_key_free, depsgraph_key_value_free);
}
@@ -3321,17 +3312,17 @@ static Depsgraph **scene_get_depsgraph_p(Scene *scene,
ViewLayer *view_layer,
const bool allocate_ghash_entry)
{
- /* bmain may be NULL here! */
- BLI_assert(scene != NULL);
- BLI_assert(view_layer != NULL);
+ /* bmain may be nullptr here! */
+ BLI_assert(scene != nullptr);
+ BLI_assert(view_layer != nullptr);
BLI_assert(BKE_scene_has_view_layer(scene, view_layer));
/* Make sure hash itself exists. */
if (allocate_ghash_entry) {
BKE_scene_ensure_depsgraph_hash(scene);
}
- if (scene->depsgraph_hash == NULL) {
- return NULL;
+ if (scene->depsgraph_hash == nullptr) {
+ return nullptr;
}
DepsgraphKey key;
@@ -3350,23 +3341,23 @@ static Depsgraph **scene_get_depsgraph_p(Scene *scene,
}
/* Depsgraph was not found in the ghash, but the key still needs allocating. */
- *key_ptr = MEM_mallocN(sizeof(DepsgraphKey), __func__);
+ *key_ptr = MEM_new<DepsgraphKey>(__func__);
**key_ptr = key;
- *depsgraph_ptr = NULL;
+ *depsgraph_ptr = nullptr;
return depsgraph_ptr;
}
static Depsgraph **scene_ensure_depsgraph_p(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
- BLI_assert(bmain != NULL);
+ BLI_assert(bmain != nullptr);
Depsgraph **depsgraph_ptr = scene_get_depsgraph_p(scene, view_layer, true);
- if (depsgraph_ptr == NULL) {
+ if (depsgraph_ptr == nullptr) {
/* The scene has no depsgraph hash. */
- return NULL;
+ return nullptr;
}
- if (*depsgraph_ptr != NULL) {
+ if (*depsgraph_ptr != nullptr) {
/* The depsgraph was found, no need to allocate. */
return depsgraph_ptr;
}
@@ -3393,25 +3384,25 @@ Depsgraph *BKE_scene_get_depsgraph(const Scene *scene, const ViewLayer *view_lay
{
BLI_assert(BKE_scene_has_view_layer(scene, view_layer));
- if (scene->depsgraph_hash == NULL) {
- return NULL;
+ if (scene->depsgraph_hash == nullptr) {
+ return nullptr;
}
DepsgraphKey key;
key.view_layer = view_layer;
- return BLI_ghash_lookup(scene->depsgraph_hash, &key);
+ return static_cast<Depsgraph *>(BLI_ghash_lookup(scene->depsgraph_hash, &key));
}
Depsgraph *BKE_scene_ensure_depsgraph(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
Depsgraph **depsgraph_ptr = scene_ensure_depsgraph_p(bmain, scene, view_layer);
- return (depsgraph_ptr != NULL) ? *depsgraph_ptr : NULL;
+ return (depsgraph_ptr != nullptr) ? *depsgraph_ptr : nullptr;
}
static char *scene_undo_depsgraph_gen_key(Scene *scene, ViewLayer *view_layer, char *key_full)
{
- if (key_full == NULL) {
- key_full = MEM_callocN(MAX_ID_NAME + FILE_MAX + MAX_NAME, __func__);
+ if (key_full == nullptr) {
+ key_full = static_cast<char *>(MEM_callocN(MAX_ID_NAME + FILE_MAX + MAX_NAME, __func__));
}
size_t key_full_offset = BLI_strncpy_rlen(key_full, scene->id.name, MAX_ID_NAME);
@@ -3430,24 +3421,23 @@ GHash *BKE_scene_undo_depsgraphs_extract(Main *bmain)
GHash *depsgraph_extract = BLI_ghash_new(
BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, __func__);
- for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
- if (scene->depsgraph_hash == NULL) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ if (scene->depsgraph_hash == nullptr) {
/* In some cases, e.g. when undo has to perform multiple steps at once, no depsgraph will
- * be built so this pointer may be NULL. */
+ * be built so this pointer may be nullptr. */
continue;
}
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL;
- view_layer = view_layer->next) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
DepsgraphKey key;
key.view_layer = view_layer;
Depsgraph **depsgraph = (Depsgraph **)BLI_ghash_lookup_p(scene->depsgraph_hash, &key);
- if (depsgraph != NULL && *depsgraph != NULL) {
- char *key_full = scene_undo_depsgraph_gen_key(scene, view_layer, NULL);
+ if (depsgraph != nullptr && *depsgraph != nullptr) {
+ char *key_full = scene_undo_depsgraph_gen_key(scene, view_layer, nullptr);
/* We steal the depsgraph from the scene. */
BLI_ghash_insert(depsgraph_extract, key_full, *depsgraph);
- *depsgraph = NULL;
+ *depsgraph = nullptr;
}
}
}
@@ -3457,22 +3447,21 @@ GHash *BKE_scene_undo_depsgraphs_extract(Main *bmain)
void BKE_scene_undo_depsgraphs_restore(Main *bmain, GHash *depsgraph_extract)
{
- for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
- for (ViewLayer *view_layer = scene->view_layers.first; view_layer != NULL;
- view_layer = view_layer->next) {
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LISTBASE_FOREACH (ViewLayer *, view_layer, &scene->view_layers) {
char key_full[MAX_ID_NAME + FILE_MAX + MAX_NAME] = {0};
scene_undo_depsgraph_gen_key(scene, view_layer, key_full);
Depsgraph **depsgraph_extract_ptr = (Depsgraph **)BLI_ghash_lookup_p(depsgraph_extract,
key_full);
- if (depsgraph_extract_ptr == NULL) {
+ if (depsgraph_extract_ptr == nullptr) {
continue;
}
- BLI_assert(*depsgraph_extract_ptr != NULL);
+ BLI_assert(*depsgraph_extract_ptr != nullptr);
Depsgraph **depsgraph_scene_ptr = scene_get_depsgraph_p(scene, view_layer, true);
- BLI_assert(depsgraph_scene_ptr != NULL);
- BLI_assert(*depsgraph_scene_ptr == NULL);
+ BLI_assert(depsgraph_scene_ptr != nullptr);
+ BLI_assert(*depsgraph_scene_ptr == nullptr);
/* We steal the depsgraph back from our 'extract' storage to the scene. */
Depsgraph *depsgraph = *depsgraph_extract_ptr;
@@ -3482,7 +3471,7 @@ void BKE_scene_undo_depsgraphs_restore(Main *bmain, GHash *depsgraph_extract)
DEG_graph_tag_relations_update(depsgraph);
*depsgraph_scene_ptr = depsgraph;
- *depsgraph_extract_ptr = NULL;
+ *depsgraph_extract_ptr = nullptr;
}
}
@@ -3515,7 +3504,7 @@ void BKE_scene_transform_orientation_remove(Scene *scene, TransformOrientation *
TransformOrientation *BKE_scene_transform_orientation_find(const Scene *scene, const int index)
{
- return BLI_findlink(&scene->transform_spaces, index);
+ return static_cast<TransformOrientation *>(BLI_findlink(&scene->transform_spaces, index));
}
int BKE_scene_transform_orientation_get_index(const Scene *scene,
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index 7d0c6598440..f17450ac3f4 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -1166,18 +1166,18 @@ static void studiolight_add_files_from_datafolder(const int folder_id,
const char *subfolder,
int flag)
{
- struct direntry *dir;
+ struct direntry *dirs;
const char *folder = BKE_appdir_folder_id(folder_id, subfolder);
if (folder) {
- uint totfile = BLI_filelist_dir_contents(folder, &dir);
+ const uint dirs_num = BLI_filelist_dir_contents(folder, &dirs);
int i;
- for (i = 0; i < totfile; i++) {
- if (dir[i].type & S_IFREG) {
- studiolight_add_file(dir[i].path, flag);
+ for (i = 0; i < dirs_num; i++) {
+ if (dirs[i].type & S_IFREG) {
+ studiolight_add_file(dirs[i].path, flag);
}
}
- BLI_filelist_free(dir, totfile);
- dir = NULL;
+ BLI_filelist_free(dirs, dirs_num);
+ dirs = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/subdiv.c b/source/blender/blenkernel/intern/subdiv.c
index 7b1ebd5df1f..ee1976d5946 100644
--- a/source/blender/blenkernel/intern/subdiv.c
+++ b/source/blender/blenkernel/intern/subdiv.c
@@ -106,7 +106,7 @@ Subdiv *BKE_subdiv_new_from_converter(const SubdivSettings *settings,
* The thing here is: OpenSubdiv can only deal with faces, but our
* side of subdiv also deals with loose vertices and edges. */
}
- Subdiv *subdiv = MEM_callocN(sizeof(Subdiv), "subdiv from converetr");
+ Subdiv *subdiv = MEM_callocN(sizeof(Subdiv), "subdiv from converter");
subdiv->settings = *settings;
subdiv->topology_refiner = osd_topology_refiner;
subdiv->evaluator = NULL;