[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