[Bf-blender-cvs] [0ac9bbc98fe] gpencil-new-data-proposal: Move classes to header and add conversion file

Falk David noreply at git.blender.org
Wed Nov 23 12:55:35 CET 2022


Commit: 0ac9bbc98fe231a6a9b1616c482d050816ef63dd
Author: Falk David
Date:   Wed Nov 23 12:55:02 2022 +0100
Branches: gpencil-new-data-proposal
https://developer.blender.org/rB0ac9bbc98fe231a6a9b1616c482d050816ef63dd

Move classes to header and add conversion file

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

M	source/blender/blenkernel/CMakeLists.txt
A	source/blender/blenkernel/intern/gpencil_new_proposal.cc
M	source/blender/blenkernel/intern/gpencil_new_proposal.hh
A	source/blender/blenkernel/intern/gpencil_new_proposal_conversion.cc
M	source/blender/blenkernel/intern/gpencil_new_proposal_test.cc

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

diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 8d3e7022770..60bb4ad0b0e 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -147,6 +147,8 @@ set(SRC
   intern/gpencil_curve.c
   intern/gpencil_geom.cc
   intern/gpencil_modifier.c
+  intern/gpencil_new_proposal.cc
+  intern/gpencil_new_proposal_conversion.cc
   intern/gpencil_update_cache.c
   intern/icons.cc
   intern/icons_rasterize.c
diff --git a/source/blender/blenkernel/intern/gpencil_new_proposal.cc b/source/blender/blenkernel/intern/gpencil_new_proposal.cc
new file mode 100644
index 00000000000..0199b5b57fe
--- /dev/null
+++ b/source/blender/blenkernel/intern/gpencil_new_proposal.cc
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include <algorithm>
+
+#include "BKE_curves.hh"
+#include "BKE_gpencil.h"
+
+#include "BLI_index_mask_ops.hh"
+#include "BLI_math_vec_types.hh"
+
+#include "DNA_gpencil_types.h"
+
+#include "gpencil_new_proposal.hh"
+
+namespace blender::bke {
+
+}  // namespace blender::bke
\ No newline at end of file
diff --git a/source/blender/blenkernel/intern/gpencil_new_proposal.hh b/source/blender/blenkernel/intern/gpencil_new_proposal.hh
index 3f328ee36e6..c918237b726 100644
--- a/source/blender/blenkernel/intern/gpencil_new_proposal.hh
+++ b/source/blender/blenkernel/intern/gpencil_new_proposal.hh
@@ -6,6 +6,10 @@
 
 #pragma once
 
+#include "BKE_curves.hh"
+
+#include "BLI_index_mask_ops.hh"
+
 #include "DNA_ID.h"
 #include "DNA_curves_types.h"
 #include "DNA_customdata_types.h"
@@ -144,6 +148,701 @@ typedef struct GreasePencil {
   /* ... */
 } GreasePencil;
 
+namespace blender::bke {
+
+class GPLayerGroup : ::GPLayerGroup { /* Unused for now. Placeholder class. */
+ public:
+  GPLayerGroup()
+  {
+    this->children = nullptr;
+    this->children_size = 0;
+    this->layer_indices = nullptr;
+    this->layer_indices_size = 0;
+  }
+
+  GPLayerGroup(const StringRefNull name) : GPLayerGroup()
+  {
+    BLI_assert(name.size() < 128);
+    strcpy(this->name, name.c_str());
+  }
+
+  ~GPLayerGroup()
+  {
+    /* Recursivly free the children of this layer group first. */
+    for (int i = 0; i < this->children_size; i++) {
+      MEM_delete(&this->children[i]);
+    }
+    /* Then free its data. */
+    MEM_SAFE_FREE(this->children);
+    MEM_SAFE_FREE(this->layer_indices);
+  }
+
+  IndexMask layers_index_mask()
+  {
+    return {reinterpret_cast<int64_t>(this->layer_indices), this->layer_indices_size};
+  }
+};
+
+class GPDataRuntime {
+ public:
+  /* mutable void *sbuffer */
+
+  /**
+   * Cache that maps the index of a layer to the index mask of the frames in that layer.
+   */
+  mutable Map<int, Vector<int64_t>> frame_index_masks_cache;
+  mutable std::mutex frame_index_masks_cache_mutex;
+
+  IndexMask frame_index_masks_cache_for_layer(int layer_index)
+  {
+    return frame_index_masks_cache.lookup(layer_index).as_span();
+  }
+};
+
+/**
+ * A wrapper class around a single curve in GPFrame.strokes (CurvesGeometry). It holds the offset
+ * of where to find the stroke in the frame and it's size.
+ * This class is only meant to facilitate the handling of individual strokes.
+ */
+class GPStroke {
+ public:
+  GPStroke(CurvesGeometry *geometry, int num_points, int offset)
+      : geometry_(geometry), points_num_(num_points), offset_(offset){};
+
+  ~GPStroke() = default;
+
+  int points_num() const
+  {
+    return points_num_;
+  }
+
+  /**
+   * Start index of this stroke in the points array of geometry_.
+   */
+  int points_offset() const
+  {
+    return offset_;
+  }
+
+  Span<float3> points_positions() const
+  {
+    return {geometry_->positions().begin() + offset_, points_num_};
+  }
+
+  MutableSpan<float3> points_positions_for_write() const
+  {
+    return {geometry_->positions_for_write().begin() + offset_, points_num_};
+  }
+
+  void transform(float4x4 matrix)
+  {
+    threading::parallel_for(
+        points_positions_for_write().index_range(), 512, [&](const IndexRange range) {
+          for (float3 &position : points_positions_for_write().slice(range)) {
+            position = matrix * position;
+          }
+        });
+  }
+
+ private:
+  CurvesGeometry *geometry_ = nullptr;
+  int points_num_ = 0;
+  int offset_;
+};
+
+class GPFrame : public ::GPFrame {
+ public:
+  GPFrame() : GPFrame(-1, -1)
+  {
+  }
+
+  GPFrame(int start_frame) : GPFrame(start_frame, -1)
+  {
+  }
+
+  GPFrame(int start_frame, int end_frame)
+  {
+    this->start_time = start_frame;
+    this->end_time = end_frame;
+    this->strokes = nullptr;
+  }
+
+  GPFrame(const GPFrame &other) : GPFrame(other.start_time, other.end_time)
+  {
+    if (other.strokes != nullptr) {
+      /* Make sure old strokes are freed before copying. */
+      MEM_SAFE_FREE(this->strokes);
+      this->strokes = MEM_new<CurvesGeometry>(__func__);
+
+      *reinterpret_cast<CurvesGeometry *>(this->strokes) = CurvesGeometry::wrap(*other.strokes);
+    }
+    this->layer_index = other.layer_index;
+  }
+
+  GPFrame &operator=(const GPFrame &other)
+  {
+    if (this != &other && other.strokes != nullptr) {
+      /* Make sure old strokes are freed before copying. */
+      MEM_SAFE_FREE(this->strokes);
+      this->strokes = MEM_new<CurvesGeometry>(__func__);
+
+      *reinterpret_cast<CurvesGeometry *>(this->strokes) = CurvesGeometry::wrap(*other.strokes);
+    }
+    this->layer_index = other.layer_index;
+    this->start_time = other.start_time;
+    this->end_time = other.end_time;
+    return *this;
+  }
+
+  GPFrame(GPFrame &&other) : GPFrame(other.start_time, other.end_time)
+  {
+    if (this != &other) {
+      std::swap(this->strokes, other.strokes);
+      other.strokes = nullptr;
+    }
+    this->layer_index = other.layer_index;
+  }
+
+  GPFrame &operator=(GPFrame &&other)
+  {
+    if (this != &other) {
+      std::swap(this->strokes, other.strokes);
+      other.strokes = nullptr;
+    }
+    this->layer_index = other.layer_index;
+    this->start_time = other.start_time;
+    this->end_time = other.end_time;
+    return *this;
+  }
+
+  ~GPFrame()
+  {
+    MEM_delete(reinterpret_cast<CurvesGeometry *>(this->strokes));
+    this->strokes = nullptr;
+  }
+
+  bool operator<(const GPFrame &other) const
+  {
+    if (this->start_time == other.start_time) {
+      return this->layer_index < other.layer_index;
+    }
+    return this->start_time < other.start_time;
+  }
+
+  /* Assumes that elem.first is the layer index and elem.second is the start time. */
+  bool operator<(const std::pair<int, int> elem) const
+  {
+    if (this->start_time == elem.second) {
+      return this->layer_index < elem.first;
+    }
+    return this->start_time < elem.second;
+  }
+
+  bool operator==(const GPFrame &other) const
+  {
+    return this->layer_index == other.layer_index && this->start_time == other.start_time;
+  }
+
+  CurvesGeometry &strokes_as_curves()
+  {
+    return CurvesGeometry::wrap(*this->strokes);
+  }
+
+  int strokes_num() const
+  {
+    if (this->strokes == nullptr) {
+      return 0;
+    }
+    return this->strokes->curve_num;
+  }
+
+  int points_num() const
+  {
+    if (this->strokes == nullptr) {
+      return 0;
+    }
+    return this->strokes->point_num;
+  }
+
+  Vector<GPStroke> strokes_for_write()
+  {
+    Vector<GPStroke> strokes;
+    for (const int i : this->strokes_as_curves().offsets().drop_back(1).index_range()) {
+      int offset = this->strokes_as_curves().offsets()[i];
+      int length = this->strokes_as_curves().offsets()[i + 1] - offset;
+      strokes.append({reinterpret_cast<CurvesGeometry *>(this->strokes), length, offset});
+    }
+    return strokes;
+  }
+
+  GPStroke add_new_stroke(int new_points_num)
+  {
+    if (this->strokes == nullptr) {
+      this->strokes = MEM_new<CurvesGeometry>(__func__);
+    }
+    CurvesGeometry &strokes = this->strokes_as_curves();
+    int orig_last_offset = strokes.offsets().last();
+
+    strokes.resize(strokes.points_num() + new_points_num, strokes.curves_num() + 1);
+    strokes.offsets_for_write().last() = strokes.points_num();
+
+    /* Use poly type by default. */
+    strokes.curve_types_for_write().last() = CURVE_TYPE_POLY;
+
+    strokes.tag_topology_changed();
+    return {reinterpret_cast<CurvesGeometry *>(this->strokes), new_points_num, orig_last_offset};
+  }
+};
+
+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 {
+ public:
+  GPData() : GPData(0, 0)
+  {
+  }
+
+  GPData(const int layers_size, const int frame_size)
+  {
+    BLI_assert(layers_size >= 0);
+    BLI_assert(frame_size >= 0);
+
+    this->frames_size = frame_size;
+    this->layers_size = layers_size;
+
+    if (this->frames_size > 0) {
+      this->frames_array = reinterpret_cast<::GPFrame *>(
+          MEM_malloc_arrayN(this->frames_size, sizeof(::GPFrame), __func__));
+      default_construct_n(reinterpret_cast<GPFrame *>(this->frames_array), this->frames_size);
+    }
+    else {
+      this->frames_array = nullptr;
+    }
+    CustomData_reset(&this->frame_data);
+
+    if (this->layers_size > 0) {
+      this->layers_array = reinterpret_cast<::GPLayer *>(
+          MEM_malloc_arrayN(this->layers_size, sizeof(::GPLayer), __func__));
+      default_construct_n(reinterpret_cast<GPLayer *>(this->layers_array), this->layers_size);
+      this->active_layer_index = 0;
+    }
+    else {
+      this->layers_array = nullptr;
+      this->active_layer_index = -1;
+    }
+
+    this->default_group = MEM_new<::GPLayerGroup>(__func__);
+
+    this->runtime = MEM_new<GPDataRuntime>(__func__);
+  }
+
+  GPData(const GPData &other) : GPData(other.layers_size, other.frames_size)
+  {
+    copy_gpdata(*this, other);
+  }
+
+  GPData &operator=(const GPData &other)
+  {
+    if (this != &other) {
+      copy_gpdata(*this, other);
+    }
+    return *this;
+  }
+
+  GPData(GPData &&other) : GPD

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list