[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