Blender  V2.93
BKE_attribute_access.hh
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #pragma once
18 
19 #include <mutex>
20 
21 #include "FN_cpp_type.hh"
22 #include "FN_generic_span.hh"
23 
24 #include "BKE_attribute.h"
25 
26 #include "BLI_color.hh"
27 #include "BLI_float2.hh"
28 #include "BLI_float3.hh"
29 
30 namespace blender::bke {
31 
32 using fn::CPPType;
33 
38 
52  protected:
56  const int64_t size_;
57 
58  /* Protects the span below, so that no two threads initialize it at the same time. */
60  /* When it is not null, it points to the attribute array or a temporary array that contains all
61  * the attribute values. */
62  mutable void *array_buffer_ = nullptr;
63  /* Is true when the buffer above is owned by the attribute accessor. */
64  mutable bool array_is_temporary_ = false;
65 
66  public:
68  : domain_(domain),
71  size_(size)
72  {
73  }
74 
75  virtual ~ReadAttribute();
76 
78  {
79  return domain_;
80  }
81 
82  const CPPType &cpp_type() const
83  {
84  return cpp_type_;
85  }
86 
88  {
89  return custom_data_type_;
90  }
91 
92  int64_t size() const
93  {
94  return size_;
95  }
96 
97  void get(const int64_t index, void *r_value) const
98  {
99  BLI_assert(index < size_);
100  this->get_internal(index, r_value);
101  }
102 
103  /* Get a span that contains all attribute values. */
104  fn::GSpan get_span() const;
105 
106  template<typename T> Span<T> get_span() const
107  {
108  return this->get_span().typed<T>();
109  }
110 
111  protected:
112  /* r_value is expected to be uninitialized. */
113  virtual void get_internal(const int64_t index, void *r_value) const = 0;
114 
115  virtual void initialize_span() const;
116 };
117 
123  protected:
127  const int64_t size_;
128 
129  /* When not null, this points either to the attribute array or to a temporary array. */
130  void *array_buffer_ = nullptr;
131  /* True, when the buffer points to a temporary array. */
132  bool array_is_temporary_ = false;
133  /* This helps to protect against forgetting to apply changes done to the array. */
135 
136  public:
138  : domain_(domain),
141  size_(size)
142  {
143  }
144 
145  virtual ~WriteAttribute();
146 
148  {
149  return domain_;
150  }
151 
152  const CPPType &cpp_type() const
153  {
154  return cpp_type_;
155  }
156 
158  {
159  return custom_data_type_;
160  }
161 
162  int64_t size() const
163  {
164  return size_;
165  }
166 
167  void get(const int64_t index, void *r_value) const
168  {
169  BLI_assert(index < size_);
170  this->get_internal(index, r_value);
171  }
172 
173  void set(const int64_t index, const void *value)
174  {
175  BLI_assert(index < size_);
176  this->set_internal(index, value);
177  }
178 
179  /* Get a span that new attribute values can be written into. When all values have been changed,
180  * #apply_span has to be called. */
182  /* The span returned by this method might not contain the current attribute values. */
184  /* Write the changes to the span into the actual attribute, if they aren't already. */
185  void apply_span();
186 
187  template<typename T> MutableSpan<T> get_span()
188  {
189  return this->get_span().typed<T>();
190  }
191 
193  {
194  return this->get_span_for_write_only().typed<T>();
195  }
196 
197  protected:
198  virtual void get_internal(const int64_t index, void *r_value) const = 0;
199  virtual void set_internal(const int64_t index, const void *value) = 0;
200 
201  virtual void initialize_span(const bool write_only);
202  virtual void apply_span_if_necessary();
203 };
204 
205 using ReadAttributePtr = std::unique_ptr<ReadAttribute>;
206 using WriteAttributePtr = std::unique_ptr<WriteAttribute>;
207 
208 /* This provides type safe access to an attribute.
209  * The underlying ReadAttribute is owned optionally. */
210 template<typename T> class TypedReadAttribute {
211  private:
212  std::unique_ptr<const ReadAttribute> owned_attribute_;
213  const ReadAttribute *attribute_;
214 
215  public:
217  {
218  owned_attribute_ = std::move(attribute);
219  BLI_assert(owned_attribute_);
220  }
221 
222  TypedReadAttribute(const ReadAttribute &attribute) : attribute_(&attribute)
223  {
224  BLI_assert(attribute_->cpp_type().is<T>());
225  }
226 
227  int64_t size() const
228  {
229  return attribute_->size();
230  }
231 
232  T operator[](const int64_t index) const
233  {
234  BLI_assert(index < attribute_->size());
235  T value;
236  value.~T();
237  attribute_->get(index, &value);
238  return value;
239  }
240 
241  /* Get a span to that contains all attribute values for faster and more convenient access. */
243  {
244  return attribute_->get_span().template typed<T>();
245  }
246 };
247 
248 /* This provides type safe access to an attribute.
249  * The underlying WriteAttribute is owned optionally. */
250 template<typename T> class TypedWriteAttribute {
251  private:
252  std::unique_ptr<WriteAttribute> owned_attribute_;
253  WriteAttribute *attribute_;
254 
255  public:
257  {
258  owned_attribute_ = std::move(attribute);
259  BLI_assert(owned_attribute_);
260  }
261 
262  TypedWriteAttribute(WriteAttribute &attribute) : attribute_(&attribute)
263  {
264  BLI_assert(attribute_->cpp_type().is<T>());
265  }
266 
267  int64_t size() const
268  {
269  return attribute_->size();
270  }
271 
272  T operator[](const int64_t index) const
273  {
274  BLI_assert(index < attribute_->size());
275  T value;
276  value.~T();
277  attribute_->get(index, &value);
278  return value;
279  }
280 
281  void set(const int64_t index, const T &value)
282  {
283  attribute_->set(index, &value);
284  }
285 
286  /* Get a span that new values can be written into. Once all values have been updated #apply_span
287  * has to be called. */
289  {
290  return attribute_->get_span().typed<T>();
291  }
292  /* The span returned by this method might not contain the current attribute values. */
294  {
295  return attribute_->get_span_for_write_only().typed<T>();
296  }
297 
298  /* Write back all changes to the actual attribute, if necessary. */
299  void apply_span()
300  {
301  attribute_->apply_span();
302  }
303 };
304 
317 
318 } // namespace blender::bke
Generic geometry attributes built on CustomData.
AttributeDomain
Definition: BKE_attribute.h:41
#define BLI_assert(a)
Definition: BLI_assert.h:58
ThreadMutex mutex
CustomDataType
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
virtual void get_internal(const int64_t index, void *r_value) const =0
virtual void initialize_span() const
CustomDataType custom_data_type() const
const CPPType & cpp_type() const
void get(const int64_t index, void *r_value) const
AttributeDomain domain() const
const CustomDataType custom_data_type_
ReadAttribute(AttributeDomain domain, const CPPType &cpp_type, const int64_t size)
T operator[](const int64_t index) const
TypedReadAttribute(ReadAttributePtr attribute)
TypedReadAttribute(const ReadAttribute &attribute)
TypedWriteAttribute(WriteAttribute &attribute)
TypedWriteAttribute(WriteAttributePtr attribute)
T operator[](const int64_t index) const
void set(const int64_t index, const T &value)
const CustomDataType custom_data_type_
AttributeDomain domain() const
virtual void set_internal(const int64_t index, const void *value)=0
void get(const int64_t index, void *r_value) const
void set(const int64_t index, const void *value)
virtual void get_internal(const int64_t index, void *r_value) const =0
MutableSpan< T > get_span_for_write_only()
WriteAttribute(AttributeDomain domain, const CPPType &cpp_type, const int64_t size)
virtual void initialize_span(const bool write_only)
fn::GMutableSpan get_span_for_write_only()
CustomDataType custom_data_type() const
const CPPType & cpp_type() const
MutableSpan< T > typed() const
Span< T > typed() const
#define T
CustomDataType cpp_type_to_custom_data_type(const CPPType &type)
AttributeDomain attribute_domain_highest_priority(Span< AttributeDomain > domains)
std::unique_ptr< WriteAttribute > WriteAttributePtr
const CPPType * custom_data_type_to_cpp_type(const CustomDataType type)
std::unique_ptr< ReadAttribute > ReadAttributePtr
CustomDataType attribute_data_type_highest_complexity(Span< CustomDataType > data_types)
__int64 int64_t
Definition: stdint.h:92