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
path: root/source
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2022-03-11 20:34:03 +0300
committerHans Goudey <h.goudey@me.com>2022-03-11 20:34:03 +0300
commit22807d2075b0bcc7b5ae655ba43b08a4e44b002b (patch)
tree190043a64dfd78722804a40bd9b3ad835b851e16 /source
parent3b28c785d4e438428af3aa513d56f5fd394498e4 (diff)
Curves: Move constructor/assignment
Add the ability to move `CurvesGeometry` without copying its attributes and data. The benefit is more intuitive management of the data-block copying, and less overhead for copying in some cases. The "moved-from" source is left in an empty but valid state. A test file is added to test the move constructor.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_curves.hh2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/curves_geometry.cc40
-rw-r--r--source/blender/blenkernel/intern/curves_geometry_test.cc66
-rw-r--r--source/blender/makesdna/DNA_curves_types.h4
5 files changed, 112 insertions, 1 deletions
diff --git a/source/blender/blenkernel/BKE_curves.hh b/source/blender/blenkernel/BKE_curves.hh
index 6cab9c8ff90..875cf48ed43 100644
--- a/source/blender/blenkernel/BKE_curves.hh
+++ b/source/blender/blenkernel/BKE_curves.hh
@@ -62,7 +62,9 @@ class CurvesGeometry : public ::CurvesGeometry {
*/
CurvesGeometry(int point_size, int curve_size);
CurvesGeometry(const CurvesGeometry &other);
+ CurvesGeometry(CurvesGeometry &&other);
CurvesGeometry &operator=(const CurvesGeometry &other);
+ CurvesGeometry &operator=(CurvesGeometry &&other);
~CurvesGeometry();
static CurvesGeometry &wrap(::CurvesGeometry &dna_struct)
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 3828d442f58..bd632380ada 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -807,6 +807,7 @@ if(WITH_GTESTS)
intern/asset_test.cc
intern/bpath_test.cc
intern/cryptomatte_test.cc
+ intern/curves_geometry_test.cc
intern/fcurve_test.cc
intern/idprop_serialize_test.cc
intern/image_partial_update_test.cc
diff --git a/source/blender/blenkernel/intern/curves_geometry.cc b/source/blender/blenkernel/intern/curves_geometry.cc
index afa0e6e452d..dd91e788e5a 100644
--- a/source/blender/blenkernel/intern/curves_geometry.cc
+++ b/source/blender/blenkernel/intern/curves_geometry.cc
@@ -84,6 +84,42 @@ CurvesGeometry &CurvesGeometry::operator=(const CurvesGeometry &other)
return *this;
}
+/* The source should be empty, but in a valid state so that using it further will work. */
+static void move_curves_geometry(CurvesGeometry &dst, CurvesGeometry &src)
+{
+ dst.point_size = src.point_size;
+ std::swap(dst.point_data, src.point_data);
+ CustomData_free(&src.point_data, src.point_size);
+ src.point_size = 0;
+
+ dst.curve_size = src.curve_size;
+ std::swap(dst.curve_data, dst.curve_data);
+ CustomData_free(&src.curve_data, src.curve_size);
+ src.curve_size = 0;
+
+ std::swap(dst.curve_offsets, src.curve_offsets);
+ MEM_SAFE_FREE(src.curve_offsets);
+
+ std::swap(dst.runtime, src.runtime);
+
+ src.update_customdata_pointers();
+ dst.update_customdata_pointers();
+}
+
+CurvesGeometry::CurvesGeometry(CurvesGeometry &&other)
+ : CurvesGeometry(other.point_size, other.curve_size)
+{
+ move_curves_geometry(*this, other);
+}
+
+CurvesGeometry &CurvesGeometry::operator=(CurvesGeometry &&other)
+{
+ if (this != &other) {
+ move_curves_geometry(*this, other);
+ }
+ return *this;
+}
+
CurvesGeometry::~CurvesGeometry()
{
CustomData_free(&this->point_data, this->point_size);
@@ -124,6 +160,8 @@ int CurvesGeometry::evaluated_points_size() const
IndexRange CurvesGeometry::range_for_curve(const int index) const
{
+ BLI_assert(this->curve_size > 0);
+ BLI_assert(this->curve_offsets != nullptr);
const int offset = this->curve_offsets[index];
const int offset_next = this->curve_offsets[index + 1];
return {offset, offset_next - offset};
@@ -131,6 +169,8 @@ IndexRange CurvesGeometry::range_for_curve(const int index) const
IndexRange CurvesGeometry::range_for_curves(const IndexRange curves) const
{
+ BLI_assert(this->curve_size > 0);
+ BLI_assert(this->curve_offsets != nullptr);
const int offset = this->curve_offsets[curves.start()];
const int offset_next = this->curve_offsets[curves.one_after_last()];
return {offset, offset_next - offset};
diff --git a/source/blender/blenkernel/intern/curves_geometry_test.cc b/source/blender/blenkernel/intern/curves_geometry_test.cc
new file mode 100644
index 00000000000..3a43c0c8102
--- /dev/null
+++ b/source/blender/blenkernel/intern/curves_geometry_test.cc
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "BKE_curves.hh"
+
+#include "testing/testing.h"
+
+namespace blender::bke::tests {
+
+static CurvesGeometry create_basic_curves(const int points_size, const int curves_size)
+{
+ CurvesGeometry curves(points_size, curves_size);
+
+ const int curve_length = points_size / curves_size;
+ for (const int i : curves.curves_range()) {
+ curves.offsets()[i] = points_size * curve_length;
+ }
+ curves.offsets().last() = points_size;
+
+ for (const int i : curves.points_range()) {
+ curves.positions()[i] = {float(i), float(i % curve_length), 0.0f};
+ }
+
+ return curves;
+}
+
+TEST(curves_geometry, Empty)
+{
+ CurvesGeometry empty(0, 0);
+ empty.cyclic();
+ float3 min;
+ float3 max;
+ EXPECT_FALSE(empty.bounds_min_max(min, max));
+}
+
+TEST(curves_geometry, Move)
+{
+ CurvesGeometry curves = create_basic_curves(100, 10);
+
+ const int *offsets_data = curves.offsets().data();
+ const float3 *positions_data = curves.positions().data();
+
+ 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.curve_offsets, nullptr); /* NOLINT: bugprone-use-after-move */
+
+ /* Just a basic check that the new curves work okay. */
+ float3 min;
+ float3 max;
+ EXPECT_TRUE(other.bounds_min_max(min, max));
+
+ curves = std::move(other);
+
+ CurvesGeometry second_other(std::move(curves));
+
+ /* The data should not have been reallocated ever. */
+ EXPECT_EQ(second_other.positions().data(), positions_data);
+ EXPECT_EQ(second_other.offsets().data(), offsets_data);
+}
+
+} // namespace blender::bke::tests
diff --git a/source/blender/makesdna/DNA_curves_types.h b/source/blender/makesdna/DNA_curves_types.h
index 98d2aa4b295..d3e69315265 100644
--- a/source/blender/makesdna/DNA_curves_types.h
+++ b/source/blender/makesdna/DNA_curves_types.h
@@ -69,7 +69,8 @@ typedef struct CurvesGeometry {
/**
* The start index of each curve in the point data. The size of each curve can be calculated by
* subtracting the offset from the next offset. That is valid even for the last curve because
- * this array is allocated with a length one larger than the number of splines.
+ * this array is allocated with a length one larger than the number of splines. This is allowed
+ * to be null when there are no curves.
*
* \note This is *not* stored in #CustomData because its size is one larger than #curve_data.
*/
@@ -77,6 +78,7 @@ typedef struct CurvesGeometry {
/**
* All attributes stored on control points (#ATTR_DOMAIN_POINT).
+ * This might not contain a layer for positions if there are no points.
*/
CustomData point_data;