[Bf-blender-cvs] [d66cb83c935] gpencil-new-data-proposal: Refactor GPFrame to use pointer to CurvesGeometry
Falk David
noreply at git.blender.org
Tue May 10 12:25:33 CEST 2022
Commit: d66cb83c9354b795d7782c95eeb3b5f78951a4c5
Author: Falk David
Date: Mon May 9 16:37:28 2022 +0200
Branches: gpencil-new-data-proposal
https://developer.blender.org/rBd66cb83c9354b795d7782c95eeb3b5f78951a4c5
Refactor GPFrame to use pointer to CurvesGeometry
===================================================================
M source/blender/blenkernel/intern/gpencil_new_proposal.hh
M source/blender/blenkernel/intern/gpencil_new_proposal_test.cc
===================================================================
diff --git a/source/blender/blenkernel/intern/gpencil_new_proposal.hh b/source/blender/blenkernel/intern/gpencil_new_proposal.hh
index 27f3a0ae191..a649b2e078b 100644
--- a/source/blender/blenkernel/intern/gpencil_new_proposal.hh
+++ b/source/blender/blenkernel/intern/gpencil_new_proposal.hh
@@ -64,7 +64,7 @@ typedef struct GPFrame {
* The curves in this frame. Each individual curve is a single stroke. The CurvesGeometry
* structure also stores attributes on the strokes and points.
*/
- CurvesGeometry strokes;
+ CurvesGeometry *strokes;
/**
* The frame flag.
diff --git a/source/blender/blenkernel/intern/gpencil_new_proposal_test.cc b/source/blender/blenkernel/intern/gpencil_new_proposal_test.cc
index 37001ec1141..810decdb856 100644
--- a/source/blender/blenkernel/intern/gpencil_new_proposal_test.cc
+++ b/source/blender/blenkernel/intern/gpencil_new_proposal_test.cc
@@ -37,49 +37,96 @@ class GPLayerGroup : ::GPLayerGroup {
class GPDataRuntime {
public:
- /* mutable void *sbuffer */;
-};
+ /* mutable void *sbuffer */
-class GPLayer : public ::GPLayer {
- public:
- GPLayer() : GPLayer("GP_Layer")
- {
- }
+ /**
+ * Cache that maps the index of a layer to the index mask of the frames in that layer.
+ */
+ mutable Map<int, Vector<int64_t>> cached_frame_index_masks;
- GPLayer(const StringRefNull name)
+ IndexMask get_cached_frame_index_mask(int layer_index)
{
- strcpy(this->name, name.c_str());
+ return cached_frame_index_masks.lookup(layer_index).as_span();
}
+};
- ~GPLayer() = default;
+class GPStroke {
+ public:
+ GPStroke(int num_points, int offset_index)
+ : num_points_(num_points), offset_index_(offset_index){};
- bool operator==(const GPLayer &other) const
+ ~GPStroke() = default;
+
+ int points_num() const
{
- return STREQ(this->name, other.name);
+ return num_points_;
}
+
+ private:
+ int num_points_;
+ int offset_index_;
};
class GPFrame : public ::GPFrame {
public:
- GPFrame()
+ GPFrame() : GPFrame(-1, -1)
{
- this->layer_index = this->start = this->end = -1;
}
- GPFrame(int layer_index)
+ GPFrame(int layer_index) : GPFrame(layer_index, -1)
{
- this->layer_index = layer_index;
- this->start = this->end = -1;
}
GPFrame(int layer_index, int start_frame)
{
this->layer_index = layer_index;
this->start = start_frame;
+
+ /* Unused for now. */
this->end = -1;
+
+ this->strokes = MEM_new<CurvesGeometry>(__func__);
+ }
+
+ GPFrame(const GPFrame &other) : GPFrame(other.layer_index, other.start)
+ {
+ if (other.strokes != nullptr) {
+ this->strokes_as_curves() = CurvesGeometry::wrap(*other.strokes);
+ }
+ }
+
+ GPFrame &operator=(const GPFrame &other)
+ {
+ if (this != &other && other.strokes != nullptr) {
+ this->strokes_as_curves() = CurvesGeometry::wrap(*other.strokes);
+ }
+ this->layer_index = other.layer_index;
+ this->start = other.start;
+ return *this;
+ }
+
+ GPFrame(GPFrame &&other) : GPFrame(other.layer_index, other.start)
+ {
+ if (this != &other) {
+ std::swap(this->strokes, other.strokes);
+ }
}
- ~GPFrame() = default;
+ GPFrame &operator=(GPFrame &&other)
+ {
+ if (this != &other) {
+ std::swap(this->strokes, other.strokes);
+ }
+ this->layer_index = other.layer_index;
+ this->start = other.start;
+ return *this;
+ }
+
+ ~GPFrame()
+ {
+ MEM_delete(reinterpret_cast<CurvesGeometry *>(this->strokes));
+ this->strokes = nullptr;
+ }
bool operator<(const GPFrame &other) const
{
@@ -89,10 +136,55 @@ class GPFrame : public ::GPFrame {
return this->start < other.start;
}
+ /* Assumes that elem.first is the layer index and elem.second is the frame start. */
+ bool operator<(const std::pair<int, int> elem) const
+ {
+ if (this->start == elem.second) {
+ return this->layer_index < elem.first;
+ }
+ return this->start < elem.second;
+ }
+
bool operator==(const GPFrame &other) const
{
return this->layer_index == other.layer_index && this->start == other.start;
}
+
+ CurvesGeometry &strokes_as_curves()
+ {
+ return CurvesGeometry::wrap(*this->strokes);
+ }
+
+ int strokes_num() const
+ {
+ return this->strokes->curve_size;
+ }
+
+ GPStroke add_new_stroke(int num_points)
+ {
+ CurvesGeometry &strokes = this->strokes_as_curves();
+ strokes.resize(strokes.points_num() + num_points, strokes.curves_num() + 1);
+ return {num_points, strokes.offsets().last()};
+ }
+};
+
+class GPLayer : public ::GPLayer {
+ public:
+ GPLayer() : GPLayer("GP_Layer")
+ {
+ }
+
+ GPLayer(const StringRefNull name)
+ {
+ strcpy(this->name, name.c_str());
+ }
+
+ ~GPLayer() = default;
+
+ bool operator==(const GPLayer &other) const
+ {
+ return STREQ(this->name, other.name);
+ }
};
class GPData : public ::GPData {
@@ -112,6 +204,7 @@ class GPData : public ::GPData {
if (this->frames_size > 0) {
this->frames_array = reinterpret_cast<::GPFrame *>(
MEM_calloc_arrayN(this->frames_size, sizeof(::GPFrame), __func__));
+ default_construct_n(reinterpret_cast<GPFrame *>(this->frames_array), this->frames_size);
}
else {
this->frames_array = nullptr;
@@ -136,10 +229,12 @@ class GPData : public ::GPData {
~GPData()
{
/* Free frames and frame custom data. */
+ destruct_n(reinterpret_cast<GPFrame *>(this->frames_array), this->frames_size);
MEM_SAFE_FREE(this->frames_array);
CustomData_free(&this->frame_data, this->frames_size);
/* Free layer and layer groups. */
+ destruct_n(reinterpret_cast<GPLayer *>(this->layers_array), this->layers_size);
MEM_SAFE_FREE(this->layers_array);
MEM_delete(reinterpret_cast<GPLayerGroup *>(this->default_group));
this->default_group = nullptr;
@@ -160,18 +255,29 @@ class GPData : public ::GPData {
IndexMask frames_on_layer(int layer_index) const
{
+ if (layer_index < 0 || layer_index > this->layers_size) {
+ return {};
+ }
+
+ /* If the indices are cached for this layer, use the cache. */
+ if (this->runtime->cached_frame_index_masks.contains(layer_index)) {
+ return this->runtime->get_cached_frame_index_mask(layer_index);
+ }
+
Vector<int64_t> indices;
- return index_mask_ops::find_indices_based_on_predicate(
+ const IndexMask mask = index_mask_ops::find_indices_based_on_predicate(
IndexMask(this->frames_size), 1024, indices, [&](const int index) {
return this->frames()[index].layer_index == layer_index;
});
+
+ /* Cache the resulting index mask. */
+ this->runtime->cached_frame_index_masks.add(layer_index, std::move(indices));
+ return mask;
}
- IndexMask frames_on_layer(GPLayer &gpl) const
+ IndexMask frames_on_active_layer() const
{
- int layer_index = this->layers().first_index_try(gpl);
- BLI_assert(layer_index != -1);
- return frames_on_layer(layer_index);
+ return frames_on_layer(this->active_layer_index);
}
Span<GPLayer> layers() const
@@ -184,16 +290,27 @@ class GPData : public ::GPData {
return {(GPLayer *)this->layers_array, this->layers_size};
}
- const bool add_layer(GPLayer &new_layer)
+ const int add_layer(GPLayer &new_layer)
{
- // Ensure that the layer array has enough space.
+ /* Ensure that the layer array has enough space. */
if (!ensure_layer_array_has_size_at_least(this->layers_size + 1)) {
- return false;
+ return -1;
}
- // Move new_layer to the end in the array.
+ /* Move new_layer to the end in the array. */
this->layers_for_write().last() = new_layer;
- return true;
+ return this->layers_size - 1;
+ }
+
+ int frame_index_at(const int layer_idx, const int start_frame_number)
+ {
+ auto it = std::lower_bound(this->frames().begin(),
+ this->frames().end(),
+ std::pair<int, int>(layer_idx, start_frame_number));
+ if (it == this->frames().end() || it->start != start_frame_number) {
+ return -1;
+ }
+ return it - this->frames().begin();
}
/**
@@ -204,35 +321,31 @@ class GPData : public ::GPData {
*/
const GPFrame *frame_at(const int layer_idx, const int start_frame_number)
{
- auto it = std::lower_bound(
- this->frames().begin(), this->frames().end(), GPFrame(layer_idx, start_frame_number));
- if (it == this->frames().end() || it->start != start_frame_number) {
+ int index = frame_index_at(layer_idx, start_frame_number);
+ if (index == -1) {
return nullptr;
}
- return it;
+ return &this->frames()[index];
}
void create_new_frame_on_layer(const int layer_index, const int start_frame_number)
{
BLI_assert(layer_index >= 0 && layer_index < this->layers_size);
/* Allocate new space for the frame. */
- ensure_frame_array_has_size_at_least(this->frames_size + 1);
+ if (!ensure_frame_array_has_size_at_least(this->frames_size + 1)) {
+ /* TODO: handle this properly. */
+ BLI_assert(false);
+ return;
+ }
/* Create a new frame and append it at the end. */
- GPFrame new_frame(layer_index, start_frame_number);
- this->frames_for_write().last() = new_frame;
+ this->frames_for_write().last().layer_index = layer_index;
+ this->frames_for_write().last().start = start_frame_number;
/* Sort the frame array. */
update_frames_array();
}
- void create_new_frame_on_layer(GPLayer &layer, const int start_frame_number)
- {
- int index = this->layers().first_index_try(layer);
- BLI_assert(index != -1);
- create_new_frame_on_layer(index, start_frame_number);
- }
-
const GPFrame &get_new_frame_on_layer(const int layer_index, const int start_frame_number)
{
create_new_frame_on_layer(layer_index, start_frame_number);
@@ -242,13 +355,6 @@ class GPData : public ::GPData {
return *gpf;
}
- const GPFrame &get_new_frame_on_layer(GPLayer &layer, const int start_frame_number)
- {
- int index = this->layers().first_index_try(layer);
- BLI_assert(index != -1);
- return get_new_frame_on_layer(index, start_frame_number);
- }
-
private:
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list