[Bf-blender-cvs] [c22d04fe2fc] gpencil-new-data-proposal: Rework gp frame api

Falk David noreply at git.blender.org
Tue May 10 12:25:33 CEST 2022


Commit: c22d04fe2fcb14401011cd9fcdae5f18d432a0b6
Author: Falk David
Date:   Mon May 9 19:53:54 2022 +0200
Branches: gpencil-new-data-proposal
https://developer.blender.org/rBc22d04fe2fcb14401011cd9fcdae5f18d432a0b6

Rework gp frame api

===================================================================

M	source/blender/blenkernel/intern/gpencil_new_proposal_test.cc

===================================================================

diff --git a/source/blender/blenkernel/intern/gpencil_new_proposal_test.cc b/source/blender/blenkernel/intern/gpencil_new_proposal_test.cc
index 810decdb856..651cf51d076 100644
--- a/source/blender/blenkernel/intern/gpencil_new_proposal_test.cc
+++ b/source/blender/blenkernel/intern/gpencil_new_proposal_test.cc
@@ -5,6 +5,7 @@
  */
 
 #include <algorithm>
+#include <optional>
 
 #include "BKE_curves.hh"
 
@@ -73,26 +74,23 @@ class GPFrame : public ::GPFrame {
   {
   }
 
-  GPFrame(int layer_index) : GPFrame(layer_index, -1)
+  GPFrame(int start_frame) : GPFrame(start_frame, -1)
   {
   }
 
-  GPFrame(int layer_index, int start_frame)
+  GPFrame(int start_frame, int end_frame)
   {
-    this->layer_index = layer_index;
     this->start = start_frame;
-
-    /* Unused for now. */
-    this->end = -1;
-
-    this->strokes = MEM_new<CurvesGeometry>(__func__);
+    this->end = end_frame;
+    this->strokes = nullptr;
   }
 
-  GPFrame(const GPFrame &other) : GPFrame(other.layer_index, other.start)
+  GPFrame(const GPFrame &other) : GPFrame(other.start, other.end)
   {
     if (other.strokes != nullptr) {
       this->strokes_as_curves() = CurvesGeometry::wrap(*other.strokes);
     }
+    this->layer_index = other.layer_index;
   }
 
   GPFrame &operator=(const GPFrame &other)
@@ -102,14 +100,16 @@ class GPFrame : public ::GPFrame {
     }
     this->layer_index = other.layer_index;
     this->start = other.start;
+    this->end = other.end;
     return *this;
   }
 
-  GPFrame(GPFrame &&other) : GPFrame(other.layer_index, other.start)
+  GPFrame(GPFrame &&other) : GPFrame(other.start, other.end)
   {
     if (this != &other) {
       std::swap(this->strokes, other.strokes);
     }
+    this->layer_index = other.layer_index;
   }
 
   GPFrame &operator=(GPFrame &&other)
@@ -119,6 +119,7 @@ class GPFrame : public ::GPFrame {
     }
     this->layer_index = other.layer_index;
     this->start = other.start;
+    this->end = other.end;
     return *this;
   }
 
@@ -157,11 +158,17 @@ class GPFrame : public ::GPFrame {
 
   int strokes_num() const
   {
+    if (this->strokes == nullptr) {
+      return 0;
+    }
     return this->strokes->curve_size;
   }
 
   GPStroke add_new_stroke(int num_points)
   {
+    if (this->strokes == nullptr) {
+      this->strokes = MEM_new<CurvesGeometry>(__func__);
+    }
     CurvesGeometry &strokes = this->strokes_as_curves();
     strokes.resize(strokes.points_num() + num_points, strokes.curves_num() + 1);
     return {num_points, strokes.offsets().last()};
@@ -256,7 +263,7 @@ class GPData : public ::GPData {
   IndexMask frames_on_layer(int layer_index) const
   {
     if (layer_index < 0 || layer_index > this->layers_size) {
-      return {};
+      return IndexMask();
     }
 
     /* If the indices are cached for this layer, use the cache. */
@@ -275,6 +282,15 @@ class GPData : public ::GPData {
     return mask;
   }
 
+  IndexMask frames_on_layer(GPLayer &layer) const
+  {
+    int index = this->layers().first_index_try(layer);
+    if (index == -1) {
+      return IndexMask();
+    }
+    return frames_on_layer(index);
+  }
+
   IndexMask frames_on_active_layer() const
   {
     return frames_on_layer(this->active_layer_index);
@@ -290,7 +306,7 @@ class GPData : public ::GPData {
     return {(GPLayer *)this->layers_array, this->layers_size};
   }
 
-  const int add_layer(GPLayer &new_layer)
+  int add_layer(GPLayer &new_layer)
   {
     /* Ensure that the layer array has enough space. */
     if (!ensure_layer_array_has_size_at_least(this->layers_size + 1)) {
@@ -298,61 +314,51 @@ class GPData : public ::GPData {
     }
 
     /* Move new_layer to the end in the array. */
-    this->layers_for_write().last() = new_layer;
+    this->layers_for_write().last() = std::move(new_layer);
     return this->layers_size - 1;
   }
 
-  int frame_index_at(const int layer_idx, const int start_frame_number)
+  GPFrame *add_frame_on_layer(int layer_index, int frame_start)
   {
+    /* TODO: Check for collisions. */
+
+    if (!ensure_frame_array_has_size_at_least(this->frames_size + 1)) {
+      return nullptr;
+    }
+
+    GPFrame frame(frame_start);
+    frame.layer_index = layer_index;
+    this->frames_for_write().last() = std::move(frame);/* TODO: Check for collisions. */
+
+    /* Sort frame array. */
+    update_frames_array();
+
     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;
+                               std::pair<int, int>(layer_index, frame.start));
+    if (it == this->frames().end() || it->start != frame.start) {
+      return nullptr;
     }
-    return it - this->frames().begin();
+    return &this->frames_for_write()[std::distance(this->frames().begin(), it)];
   }
 
-  /**
-   * Find a GPFrame in the frame_array given by the layer index and the frame number in logarithmic
-   * time. If the frame is found, returns a pointer/iterator to it, otherwise nullptr.
-   *
-   * Note: This assumes that the array is sorted.
-   */
-  const GPFrame *frame_at(const int layer_idx, const int start_frame_number)
+  GPFrame *add_frame_on_layer(GPLayer &layer, int frame_start)
   {
-    int index = frame_index_at(layer_idx, start_frame_number);
+    int index = this->layers().first_index_try(layer);
     if (index == -1) {
       return nullptr;
     }
-    return &this->frames()[index];
+    return add_frame_on_layer(index, frame_start);
   }
 
-  void create_new_frame_on_layer(const int layer_index, const int start_frame_number)
+  int strokes_num() const
   {
-    BLI_assert(layer_index >= 0 && layer_index < this->layers_size);
-    /* Allocate new space for the frame. */
-    if (!ensure_frame_array_has_size_at_least(this->frames_size + 1)) {
-      /* TODO: handle this properly. */
-      BLI_assert(false);
-      return;
+    /* TODO: could be done with parallel_for */
+    int count = 0;
+    for (const GPFrame &gpf : this->frames()) {
+      count += gpf.strokes_num();
     }
-
-    /* Create a new frame and append it at the end. */
-    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();
-  }
-
-  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);
-    /* Find the frame in the array and return it. */
-    const GPFrame *gpf = this->frame_at(layer_index, start_frame_number);
-    BLI_assert(gpf != nullptr);
-    return *gpf;
+    return count;
   }
 
  private:
@@ -493,10 +499,16 @@ TEST(gpencil_proposal, AddFrameToLayer)
   GPLayer layer2("TestLayer2");
 
   data.add_layer(layer1);
-  const int layer2_idx = data.add_layer(layer2);
-  data.create_new_frame_on_layer(layer2_idx, 0);
-  const GPFrame *frame = data.frame_at(layer2_idx, 0);
+  data.add_layer(layer2);
+
+  GPFrame *frame = data.add_frame_on_layer(layer2, 0);
+
+  EXPECT_EQ(data.frames_size, 1);
+  EXPECT_EQ(data.frames().last().layer_index, 1);
   EXPECT_EQ(frame->layer_index, 1);
+
+  frame->start = 20;
+  EXPECT_EQ(data.frames().last().start, 20);
 }
 
 TEST(gpencil_proposal, CheckFramesSorted1)
@@ -509,9 +521,8 @@ TEST(gpencil_proposal, CheckFramesSorted1)
 
   const int layer1_idx = data.add_layer(layer1);
   for (int i : IndexRange(5)) {
-    const GPFrame &frame = data.get_new_frame_on_layer(layer1_idx, frame_numbers1[i]);
-    int idx = data.frames().first_index(frame);
-    EXPECT_EQ(data.frames()[idx].start, frame_numbers1[i]);
+    GPFrame *frame = data.add_frame_on_layer(layer1_idx, frame_numbers1[i]);
+    EXPECT_EQ(frame->start, frame_numbers1[i]);
   }
 
   for (const int i : data.frames().index_range()) {
@@ -532,8 +543,8 @@ TEST(gpencil_proposal, CheckFramesSorted2)
   const int layer1_idx = data.add_layer(layer1);
   const int layer2_idx = data.add_layer(layer2);
   for (int i : IndexRange(5)) {
-    data.create_new_frame_on_layer(layer1_idx, frame_numbers_layer1[i]);
-    data.create_new_frame_on_layer(layer2_idx, frame_numbers_layer2[i]);
+    data.add_frame_on_layer(layer1_idx, frame_numbers_layer1[i]);
+    data.add_frame_on_layer(layer2_idx, frame_numbers_layer2[i]);
   }
 
   for (const int i : data.frames().index_range()) {
@@ -557,8 +568,8 @@ TEST(gpencil_proposal, IterateOverFramesOnLayer)
   const int layer1_idx = data.add_layer(layer1);
   const int layer2_idx = data.add_layer(layer2);
   for (int i : IndexRange(5)) {
-    data.create_new_frame_on_layer(layer1_idx, frame_numbers_layer1[i]);
-    data.create_new_frame_on_layer(layer2_idx, frame_numbers_layer2[i]);
+    data.add_frame_on_layer(layer1_idx, frame_numbers_layer1[i]);
+    data.add_frame_on_layer(layer2_idx, frame_numbers_layer2[i]);
   }
 
   IndexMask indices_frames_layer1 = data.frames_on_layer(layer1_idx);
@@ -580,10 +591,12 @@ TEST(gpencil_proposal, AddSingleStroke)
   GPLayer layer1("TestLayer1");
 
   const int layer1_idx = data.add_layer(layer1);
-  GPFrame frame = data.get_new_frame_on_layer(layer1_idx, 0);
-  GPStroke stroke = frame.add_new_stroke(100);
 
-  EXPECT_EQ(frame.strokes_num(), 1);
+  GPFrame *frame = data.add_frame_on_layer(layer1_idx, 0);
+  GPStroke stroke = frame->add_new_stroke(100);
+
+  EXPECT_EQ(data.strokes_num(), 1);
+  EXPECT_EQ(frame->strokes_num(), 1);
   EXPECT_EQ(stroke.points_num(), 100);
 }



More information about the Bf-blender-cvs mailing list