Blender V4.3
idprop_serialize.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include <optional>
6
7#include "DNA_ID.h"
8
9#include "BKE_idprop.hh"
10
11#include "BLI_listbase.h"
12#include "BLI_serialize.hh"
13
14namespace blender::bke::idprop {
15using namespace blender::io::serialize;
16
17/* Forward declarations */
18class IDPropertySerializer;
19struct DictionaryEntryParser;
20static IDProperty *idprop_from_value(const DictionaryValue &value);
21static const IDPropertySerializer &serializer_for(eIDPropertyType property_type);
22static const IDPropertySerializer &serializer_for(StringRef idprop_typename);
23
24/* -------------------------------------------------------------------- */
28/* Definitions */
29static constexpr StringRef IDP_KEY_NAME("name");
30static constexpr StringRef IDP_KEY_TYPE("type");
31static constexpr StringRef IDP_KEY_SUBTYPE("subtype");
32static constexpr StringRef IDP_KEY_VALUE("value");
33
34static constexpr StringRef IDP_PROPERTY_TYPENAME_STRING("IDP_STRING");
35static constexpr StringRef IDP_PROPERTY_TYPENAME_BOOL("IDP_BOOL");
36static constexpr StringRef IDP_PROPERTY_TYPENAME_INT("IDP_INT");
37static constexpr StringRef IDP_PROPERTY_TYPENAME_FLOAT("IDP_FLOAT");
38static constexpr StringRef IDP_PROPERTY_TYPENAME_DOUBLE("IDP_DOUBLE");
39static constexpr StringRef IDP_PROPERTY_TYPENAME_ARRAY("IDP_ARRAY");
40static constexpr StringRef IDP_PROPERTY_TYPENAME_GROUP("IDP_GROUP");
41static constexpr StringRef IDP_PROPERTY_TYPENAME_UNKNOWN("IDP_UNKNOWN");
42
49 public:
50 constexpr IDPropertySerializer() = default;
51
56 virtual std::string type_name() const = 0;
57
61 virtual std::optional<eIDPropertyType> property_type() const = 0;
62
66 virtual std::shared_ptr<DictionaryValue> idprop_to_dictionary(
67 const IDProperty *id_property) const = 0;
68
72 virtual std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
73 DictionaryEntryParser &entry_reader) const = 0;
74
80 virtual bool supports_serializing() const
81 {
82 return true;
83 }
84
85 protected:
91 std::shared_ptr<DictionaryValue> create_dictionary(const IDProperty *id_property) const
92 {
93 std::shared_ptr<DictionaryValue> result = std::make_shared<DictionaryValue>();
94 result->append_str(IDP_KEY_NAME, id_property->name);
95 result->append_str(IDP_KEY_TYPE, this->type_name());
96 return result;
97 }
98};
99
105
106 public:
107 explicit DictionaryEntryParser(const DictionaryValue &value) : lookup(value.create_lookup()) {}
108
109 std::optional<eIDPropertyType> get_type() const
110 {
111 return get_id_property_type(IDP_KEY_TYPE);
112 }
113
114 std::optional<eIDPropertyType> get_subtype() const
115 {
116 return get_id_property_type(IDP_KEY_SUBTYPE);
117 }
118
119 std::optional<std::string> get_name() const
120 {
121 return get_string(IDP_KEY_NAME);
122 }
123
124 std::optional<std::string> get_string_value() const
125 {
126 return get_string(IDP_KEY_VALUE);
127 }
128
129 std::optional<bool> get_bool_value() const
130 {
131 return get_bool(IDP_KEY_VALUE);
132 }
133
134 std::optional<int32_t> get_int_value() const
135 {
136 return get_int(IDP_KEY_VALUE);
137 }
138
139 std::optional<float> get_float_value() const
140 {
141 return get_float(IDP_KEY_VALUE);
142 }
143
144 std::optional<double> get_double_value() const
145 {
146 return get_double(IDP_KEY_VALUE);
147 }
148
149 std::optional<int> get_enum_value() const
150 {
151 return get_enum(IDP_KEY_VALUE);
152 }
153
155 {
156 return get_array(IDP_KEY_VALUE);
157 }
158
159 std::optional<Vector<int32_t>> get_array_int_value() const
160 {
161 return get_array_primitive<int32_t, IntValue>(IDP_KEY_VALUE);
162 }
163
164 std::optional<Vector<float>> get_array_float_value() const
165 {
166 return get_array_primitive<float, DoubleValue>(IDP_KEY_VALUE);
167 }
168
169 std::optional<Vector<double>> get_array_double_value() const
170 {
171 return get_array_primitive<double, DoubleValue>(IDP_KEY_VALUE);
172 }
173
174 private:
175 std::optional<std::string> get_string(StringRef key) const
176 {
177 const std::shared_ptr<Value> *value = lookup.lookup_ptr(key);
178 if (value == nullptr) {
179 return std::nullopt;
180 }
181 if (value->get()->type() != eValueType::String) {
182 return std::nullopt;
183 }
184 return value->get()->as_string_value()->value();
185 }
186
187 const ArrayValue *get_array(StringRef key) const
188 {
189 const std::shared_ptr<Value> *value = lookup.lookup_ptr(key);
190 if (value == nullptr) {
191 return nullptr;
192 }
193 if (value->get()->type() != eValueType::Array) {
194 return nullptr;
195 }
196 return value->get()->as_array_value();
197 }
198
199 std::optional<bool> get_bool(StringRef key) const
200 {
201 const std::shared_ptr<Value> *value = lookup.lookup_ptr(key);
202 if (value == nullptr) {
203 return std::nullopt;
204 }
205 if (value->get()->type() != eValueType::Boolean) {
206 return std::nullopt;
207 }
208 return value->get()->as_boolean_value()->value();
209 }
210
211 std::optional<int32_t> get_int(StringRef key) const
212 {
213 const std::shared_ptr<Value> *value = lookup.lookup_ptr(key);
214 if (value == nullptr) {
215 return std::nullopt;
216 }
217 if (value->get()->type() != eValueType::Int) {
218 return std::nullopt;
219 }
220 return value->get()->as_int_value()->value();
221 }
222
223 std::optional<int32_t> get_enum(StringRef key) const
224 {
225 const std::shared_ptr<Value> *value = lookup.lookup_ptr(key);
226 if (value == nullptr) {
227 return std::nullopt;
228 }
229 if (value->get()->type() != eValueType::Int) {
230 return std::nullopt;
231 }
232 return value->get()->as_int_value()->value();
233 }
234
235 std::optional<double> get_double(StringRef key) const
236 {
237 const std::shared_ptr<Value> *value = lookup.lookup_ptr(key);
238 if (value == nullptr) {
239 return std::nullopt;
240 }
241 if (value->get()->type() != eValueType::Double) {
242 return std::nullopt;
243 }
244 return value->get()->as_double_value()->value();
245 }
246
247 std::optional<float> get_float(StringRef key) const
248 {
249 return static_cast<std::optional<float>>(get_double(key));
250 }
251
252 template<typename PrimitiveType, typename ValueType>
253 std::optional<Vector<PrimitiveType>> get_array_primitive(StringRef key) const
254 {
255 const std::shared_ptr<Value> *value = lookup.lookup_ptr(key);
256 if (value == nullptr) {
257 return std::nullopt;
258 }
259 if (value->get()->type() != eValueType::Array) {
260 return std::nullopt;
261 }
262
263 Vector<PrimitiveType> result;
264 for (const std::shared_ptr<Value> &element : value->get()->as_array_value()->elements()) {
265 const ValueType *value_type = static_cast<const ValueType *>(element.get());
266 PrimitiveType primitive_value = value_type->value();
267 result.append_as(primitive_value);
268 }
269
270 return result;
271 }
272
273 std::optional<eIDPropertyType> get_id_property_type(StringRef key) const
274 {
275 std::optional<std::string> string_value = get_string(key);
276 if (!string_value.has_value()) {
277 return std::nullopt;
278 }
279 const IDPropertySerializer &serializer = serializer_for(*string_value);
280 return serializer.property_type();
281 }
282};
283
286 public:
287 constexpr IDPStringSerializer() = default;
288
289 std::string type_name() const override
290 {
292 }
293
294 std::optional<eIDPropertyType> property_type() const override
295 {
296 return IDP_STRING;
297 }
298
299 std::shared_ptr<DictionaryValue> idprop_to_dictionary(
300 const IDProperty *id_property) const override
301 {
302 std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
303 result->append_str(IDP_KEY_VALUE, IDP_String(id_property));
304 return result;
305 }
306
307 std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
308 DictionaryEntryParser &entry_reader) const override
309 {
310 BLI_assert(*(entry_reader.get_type()) == IDP_STRING);
311 std::optional<std::string> name = entry_reader.get_name();
312 if (!name.has_value()) {
313 return nullptr;
314 }
315 std::optional<std::string> string_value = entry_reader.get_string_value();
316 if (!string_value.has_value()) {
317 return nullptr;
318 }
319 return create(name->c_str(), string_value->c_str());
320 }
321};
322
325 public:
326 constexpr IDPBoolSerializer() = default;
327
328 std::string type_name() const override
329 {
331 }
332
333 std::optional<eIDPropertyType> property_type() const override
334 {
335 return IDP_BOOLEAN;
336 }
337
338 std::shared_ptr<DictionaryValue> idprop_to_dictionary(
339 const IDProperty *id_property) const override
340 {
341 std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
342 result->append(IDP_KEY_VALUE, std::make_shared<BooleanValue>(IDP_Bool(id_property) != 0));
343 return result;
344 }
345
346 std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
347 DictionaryEntryParser &entry_reader) const override
348 {
349 BLI_assert(*(entry_reader.get_type()) == IDP_BOOLEAN);
350 std::optional<std::string> name = entry_reader.get_name();
351 if (!name.has_value()) {
352 return nullptr;
353 }
354 std::optional<bool> extracted_value = entry_reader.get_bool_value();
355 if (!extracted_value.has_value()) {
356 return nullptr;
357 }
358 return create_bool(name->c_str(), *extracted_value);
359 }
360};
361
364 public:
365 constexpr IDPIntSerializer() = default;
366
367 std::string type_name() const override
368 {
370 }
371
372 std::optional<eIDPropertyType> property_type() const override
373 {
374 return IDP_INT;
375 }
376
377 std::shared_ptr<DictionaryValue> idprop_to_dictionary(
378 const IDProperty *id_property) const override
379 {
380 std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
381 result->append_int(IDP_KEY_VALUE, IDP_Int(id_property));
382 return result;
383 }
384
385 std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
386 DictionaryEntryParser &entry_reader) const override
387 {
388 BLI_assert(*(entry_reader.get_type()) == IDP_INT);
389 std::optional<std::string> name = entry_reader.get_name();
390 if (!name.has_value()) {
391 return nullptr;
392 }
393 std::optional<int32_t> extracted_value = entry_reader.get_int_value();
394 if (!extracted_value.has_value()) {
395 return nullptr;
396 }
397 return create(name->c_str(), *extracted_value);
398 }
399};
400
403 public:
404 constexpr IDPFloatSerializer() = default;
405
406 std::string type_name() const override
407 {
409 }
410
411 std::optional<eIDPropertyType> property_type() const override
412 {
413 return IDP_FLOAT;
414 }
415
416 std::shared_ptr<DictionaryValue> idprop_to_dictionary(
417 const IDProperty *id_property) const override
418 {
419 std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
420 result->append_double(IDP_KEY_VALUE, IDP_Float(id_property));
421 return result;
422 }
423
424 std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
425 DictionaryEntryParser &entry_reader) const override
426 {
427 BLI_assert(*(entry_reader.get_type()) == IDP_FLOAT);
428 std::optional<std::string> name = entry_reader.get_name();
429 if (!name.has_value()) {
430 return nullptr;
431 }
432 std::optional<float> extracted_value = entry_reader.get_float_value();
433 if (!extracted_value.has_value()) {
434 return nullptr;
435 }
436 return create(name->c_str(), *extracted_value);
437 }
438};
439
442 public:
443 constexpr IDPDoubleSerializer() = default;
444
445 std::string type_name() const override
446 {
448 }
449
450 std::optional<eIDPropertyType> property_type() const override
451 {
452 return IDP_DOUBLE;
453 }
454
455 std::shared_ptr<DictionaryValue> idprop_to_dictionary(
456 const IDProperty *id_property) const override
457 {
458 std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
459 result->append_double(IDP_KEY_VALUE, IDP_Double(id_property));
460 return result;
461 }
462
463 std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
464 DictionaryEntryParser &entry_reader) const override
465 {
466 BLI_assert(*(entry_reader.get_type()) == IDP_DOUBLE);
467 std::optional<std::string> name = entry_reader.get_name();
468 if (!name.has_value()) {
469 return nullptr;
470 }
471 std::optional<double> extracted_value = entry_reader.get_double_value();
472 if (!extracted_value.has_value()) {
473 return nullptr;
474 }
475 return create(name->c_str(), *extracted_value);
476 }
477};
478
481 public:
482 constexpr IDPArraySerializer() = default;
483
484 std::string type_name() const override
485 {
487 }
488
489 std::optional<eIDPropertyType> property_type() const override
490 {
491 return IDP_ARRAY;
492 }
493
494 std::shared_ptr<DictionaryValue> idprop_to_dictionary(
495 const IDProperty *id_property) const override
496 {
497 std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
498 const IDPropertySerializer &subtype_serializer = serializer_for(
499 static_cast<eIDPropertyType>(id_property->subtype));
500 result->append_str(IDP_KEY_SUBTYPE, subtype_serializer.type_name());
501
502 ArrayValue &array = *result->append_array(IDP_KEY_VALUE);
503 switch (static_cast<eIDPropertyType>(id_property->subtype)) {
504 case IDP_INT: {
505 int32_t *values = static_cast<int32_t *>(IDP_Array(id_property));
506 add_values<int32_t, IntValue>(array, Span<int32_t>(values, id_property->len));
507 break;
508 }
509 case IDP_FLOAT: {
510 float *values = static_cast<float *>(IDP_Array(id_property));
511 add_values<float, DoubleValue>(array, Span<float>(values, id_property->len));
512 break;
513 }
514 case IDP_DOUBLE: {
515 double *values = static_cast<double *>(IDP_Array(id_property));
516 add_values<double, DoubleValue>(array, Span<double>(values, id_property->len));
517 break;
518 }
519 case IDP_GROUP: {
520 IDProperty *values = static_cast<IDProperty *>(IDP_Array(id_property));
521 add_values(array, Span<IDProperty>(values, id_property->len));
522 break;
523 }
524 default: {
525 /* IDP_ARRAY only supports IDP_INT, IDP_FLOAT, IDP_DOUBLE and IDP_GROUP. */
527 break;
528 }
529 }
530
531 return result;
532 }
533
534 std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
535 DictionaryEntryParser &entry_reader) const override
536 {
537 BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
538 std::optional<eIDPropertyType> property_subtype = entry_reader.get_subtype();
539 if (!property_subtype.has_value()) {
540 return nullptr;
541 }
542
543 switch (*property_subtype) {
544 case IDP_INT:
545 return idprop_array_int_from_value(entry_reader);
546 case IDP_FLOAT:
547 return idprop_array_float_from_value(entry_reader);
548 case IDP_DOUBLE:
549 return idprop_array_double_from_value(entry_reader);
550 default:
551 return nullptr;
552 }
553 }
554
555 private:
557 template</* C-primitive type of the values to add. Possible types are `float`, `int32_t` or
558 * `double`. */
559 typename PrimitiveType,
560 /* Type of value that can store the PrimitiveType in the Array. */
561 typename ValueType>
562 void add_values(ArrayValue &array, Span<PrimitiveType> values) const
563 {
564 for (PrimitiveType value : values) {
565 array.append(std::make_shared<ValueType>(value));
566 }
567 }
568
569 void add_values(ArrayValue &array, Span<IDProperty> values) const
570 {
571 for (const IDProperty &id_property : values) {
572 const IDPropertySerializer &value_serializer = serializer_for(
573 static_cast<eIDPropertyType>(id_property.type));
574 if (!value_serializer.supports_serializing()) {
575 continue;
576 }
577 array.append(value_serializer.idprop_to_dictionary(&id_property));
578 }
579 }
580
581 std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_int_from_value(
582 DictionaryEntryParser &entry_reader) const
583 {
584 BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
585 BLI_assert(*(entry_reader.get_subtype()) == IDP_INT);
586 std::optional<std::string> name = entry_reader.get_name();
587 if (!name.has_value()) {
588 return nullptr;
589 }
590 std::optional<Vector<int32_t>> extracted_value = entry_reader.get_array_int_value();
591 if (!extracted_value.has_value()) {
592 return nullptr;
593 }
594 return create(name->c_str(), *extracted_value);
595 }
596
597 std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_float_from_value(
598 DictionaryEntryParser &entry_reader) const
599 {
600 BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
601 BLI_assert(*(entry_reader.get_subtype()) == IDP_FLOAT);
602 std::optional<std::string> name = entry_reader.get_name();
603 if (!name.has_value()) {
604 return nullptr;
605 }
606 std::optional<Vector<float>> extracted_value = entry_reader.get_array_float_value();
607 if (!extracted_value.has_value()) {
608 return nullptr;
609 }
610 return create(name->c_str(), *extracted_value);
611 }
612
613 std::unique_ptr<IDProperty, IDPropertyDeleter> idprop_array_double_from_value(
614 DictionaryEntryParser &entry_reader) const
615 {
616 BLI_assert(*(entry_reader.get_type()) == IDP_ARRAY);
617 BLI_assert(*(entry_reader.get_subtype()) == IDP_DOUBLE);
618 std::optional<std::string> name = entry_reader.get_name();
619 if (!name.has_value()) {
620 return nullptr;
621 }
622 std::optional<Vector<double>> extracted_value = entry_reader.get_array_double_value();
623 if (!extracted_value.has_value()) {
624 return nullptr;
625 }
626 return create(name->c_str(), *extracted_value);
627 }
628};
629
632 public:
633 constexpr IDPGroupSerializer() = default;
634
635 std::string type_name() const override
636 {
638 }
639
640 std::optional<eIDPropertyType> property_type() const override
641 {
642 return IDP_GROUP;
643 }
644
645 std::shared_ptr<DictionaryValue> idprop_to_dictionary(
646 const IDProperty *id_property) const override
647 {
648 std::shared_ptr<DictionaryValue> result = create_dictionary(id_property);
649
650 std::shared_ptr<ArrayValue> array = std::make_shared<ArrayValue>();
651 LISTBASE_FOREACH (IDProperty *, sub_property, &id_property->data.group) {
652 const IDPropertySerializer &sub_property_serializer = serializer_for(
653 static_cast<eIDPropertyType>(sub_property->type));
654 array->append(sub_property_serializer.idprop_to_dictionary(sub_property));
655 }
656
657 result->append(IDP_KEY_VALUE, std::move(array));
658 return result;
659 }
660
661 std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
662 DictionaryEntryParser &entry_reader) const override
663 {
664 BLI_assert(*(entry_reader.get_type()) == IDP_GROUP);
665 std::optional<std::string> name = entry_reader.get_name();
666 if (!name.has_value()) {
667 return nullptr;
668 }
669
670 const ArrayValue *array = entry_reader.get_array_value();
671 if (array == nullptr) {
672 return nullptr;
673 }
674
675 std::unique_ptr<IDProperty, IDPropertyDeleter> result = create_group(name->c_str());
676 for (const std::shared_ptr<Value> &element : array->elements()) {
677 if (element->type() != eValueType::Dictionary) {
678 continue;
679 }
680 const DictionaryValue *subobject = element->as_dictionary_value();
681 IDProperty *subproperty = idprop_from_value(*subobject);
682 IDP_AddToGroup(result.get(), subproperty);
683 }
684
685 return result;
686 }
687};
688
693 public:
694 constexpr IDPUnknownSerializer() = default;
695 std::string type_name() const override
696 {
698 }
699 std::optional<eIDPropertyType> property_type() const override
700 {
701 return std::nullopt;
702 }
703
704 std::shared_ptr<DictionaryValue> idprop_to_dictionary(
705 const IDProperty * /*id_property*/) const override
706 {
708 return nullptr;
709 }
710
711 bool supports_serializing() const override
712 {
713 return false;
714 }
715
716 std::unique_ptr<IDProperty, IDPropertyDeleter> entry_to_idprop(
717 DictionaryEntryParser & /*entry_reader*/) const override
718 {
719 return nullptr;
720 }
721};
722
723/* Serializers are constructed statically to remove construction/destruction. */
732
735{
736 switch (property_type) {
737 case IDP_STRING:
739
740 case IDP_BOOLEAN:
741 return IDP_SERIALIZER_BOOL;
742
743 case IDP_INT:
744 return IDP_SERIALIZER_INT;
745
746 case IDP_FLOAT:
748
749 case IDP_DOUBLE:
751
752 case IDP_ARRAY:
754
755 case IDP_GROUP:
757
758 default:
759 BLI_assert_msg(false, "Trying to convert an unsupported/unknown property type to a string");
761 }
762}
763
765static const IDPropertySerializer &serializer_for(StringRef idprop_typename)
766{
767 if (idprop_typename == IDP_PROPERTY_TYPENAME_STRING) {
769 }
770 if (idprop_typename == IDP_PROPERTY_TYPENAME_BOOL) {
771 return IDP_SERIALIZER_BOOL;
772 }
773 if (idprop_typename == IDP_PROPERTY_TYPENAME_INT) {
774 return IDP_SERIALIZER_INT;
775 }
776 if (idprop_typename == IDP_PROPERTY_TYPENAME_FLOAT) {
778 }
779 if (idprop_typename == IDP_PROPERTY_TYPENAME_DOUBLE) {
781 }
782 if (idprop_typename == IDP_PROPERTY_TYPENAME_ARRAY) {
784 }
785 if (idprop_typename == IDP_PROPERTY_TYPENAME_GROUP) {
787 }
789}
790
791/* \} */
792
793/* -------------------------------------------------------------------- */
796std::unique_ptr<ArrayValue> convert_to_serialize_values(const IDProperty *properties)
797{
798 BLI_assert(properties != nullptr);
799 std::unique_ptr<ArrayValue> result = std::make_unique<ArrayValue>();
800 const IDProperty *current_property = properties;
801 while (current_property != nullptr) {
802 const IDPropertySerializer &serializer = serializer_for(
803 static_cast<eIDPropertyType>(current_property->type));
804 if (serializer.supports_serializing()) {
805 result->append(serializer.idprop_to_dictionary(current_property));
806 }
807 current_property = current_property->next;
808 }
809
810 return result;
811}
812
813/* \} */
814
815/* -------------------------------------------------------------------- */
820{
821 DictionaryEntryParser entry_reader(value);
822 std::optional<eIDPropertyType> property_type = entry_reader.get_type();
823 if (!property_type.has_value()) {
824 return nullptr;
825 }
826
827 const IDPropertySerializer &serializer = serializer_for(*property_type);
828 return serializer.entry_to_idprop(entry_reader).release();
829}
830
832{
833 IDProperty *result = nullptr;
834 IDProperty *previous_added = nullptr;
835
836 for (const std::shared_ptr<Value> &element : value.elements()) {
837 if (element->type() != eValueType::Dictionary) {
838 continue;
839 }
840 const DictionaryValue *object_value = element->as_dictionary_value();
841 IDProperty *last_created = idprop_from_value(*object_value);
842 if (last_created == nullptr) {
843 continue;
844 }
845
846 if (result == nullptr) {
847 result = last_created;
848 }
849
850 if (previous_added) {
851 previous_added->next = last_created;
852 }
853 last_created->prev = previous_added;
854 previous_added = last_created;
855 }
856
857 return result;
858}
859
861{
862 if (value.type() != eValueType::Array) {
863 return nullptr;
864 }
865
866 return idprop_from_value(*value.as_array_value());
867}
868
869/* \} */
870
871} // namespace blender::bke::idprop
#define IDP_Float(prop)
#define IDP_Int(prop)
#define IDP_Bool(prop)
#define IDP_String(prop)
#define IDP_Double(prop)
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:722
#define IDP_Array(prop)
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define LISTBASE_FOREACH(type, var, list)
ID and Library types, which are fundamental for SDNA.
eIDPropertyType
@ IDP_DOUBLE
@ IDP_FLOAT
@ IDP_STRING
@ IDP_BOOLEAN
@ IDP_INT
@ IDP_GROUP
@ IDP_ARRAY
void append(const array< T > &from)
const Value * lookup_ptr(const Key &key) const
Definition BLI_map.hh:484
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *id_property) const override
create dictionary containing the given id_property.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *id_property) const override
create dictionary containing the given id_property.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *id_property) const override
create dictionary containing the given id_property.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *id_property) const override
create dictionary containing the given id_property.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *id_property) const override
create dictionary containing the given id_property.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *id_property) const override
create dictionary containing the given id_property.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const override
convert the entry to an id property.
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *id_property) const override
create dictionary containing the given id_property.
Dummy serializer for unknown and unsupported types.
std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &) const override
convert the entry to an id property.
std::string type_name() const override
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
std::optional< eIDPropertyType > property_type() const override
return the IDPropertyType for (de)serializing.
bool supports_serializing() const override
Can the serializer be used?
std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *) const override
create dictionary containing the given id_property.
Base class for (de)serializing IDProperties.
virtual std::shared_ptr< DictionaryValue > idprop_to_dictionary(const IDProperty *id_property) const =0
create dictionary containing the given id_property.
std::shared_ptr< DictionaryValue > create_dictionary(const IDProperty *id_property) const
Create a new DictionaryValue instance.
virtual std::string type_name() const =0
return the type name for (de)serializing. Type name is stored in the type or subtype attribute of the...
virtual std::optional< eIDPropertyType > property_type() const =0
return the IDPropertyType for (de)serializing.
virtual std::unique_ptr< IDProperty, IDPropertyDeleter > entry_to_idprop(DictionaryEntryParser &entry_reader) const =0
convert the entry to an id property.
virtual bool supports_serializing() const
Can the serializer be used?
const DictionaryValue * as_dictionary_value() const
Definition serialize.cc:60
PrimitiveType
static constexpr StringRef IDP_KEY_SUBTYPE("subtype")
static constexpr StringRef IDP_PROPERTY_TYPENAME_FLOAT("IDP_FLOAT")
static constexpr IDPUnknownSerializer IDP_SERIALIZER_UNKNOWN
static constexpr StringRef IDP_PROPERTY_TYPENAME_STRING("IDP_STRING")
static constexpr IDPStringSerializer IDP_SERIALIZER_STRING
static constexpr StringRef IDP_PROPERTY_TYPENAME_BOOL("IDP_BOOL")
static constexpr StringRef IDP_KEY_VALUE("value")
static const IDPropertySerializer & serializer_for(eIDPropertyType property_type)
get the serializer for the given property type.
static constexpr IDPArraySerializer IDP_SERIALIZER_ARRAY
static constexpr StringRef IDP_PROPERTY_TYPENAME_DOUBLE("IDP_DOUBLE")
static constexpr IDPGroupSerializer IDP_SERIALIZER_GROUP
static constexpr StringRef IDP_PROPERTY_TYPENAME_UNKNOWN("IDP_UNKNOWN")
static constexpr StringRef IDP_PROPERTY_TYPENAME_GROUP("IDP_GROUP")
static IDProperty * idprop_from_value(const DictionaryValue &value)
static constexpr StringRef IDP_KEY_TYPE("type")
static constexpr StringRef IDP_PROPERTY_TYPENAME_INT("IDP_INT")
static constexpr IDPDoubleSerializer IDP_SERIALIZER_DOUBLE
static constexpr IDPFloatSerializer IDP_SERIALIZER_FLOAT
static constexpr StringRef IDP_PROPERTY_TYPENAME_ARRAY("IDP_ARRAY")
std::unique_ptr< IDProperty, IDPropertyDeleter > create_bool(StringRefNull prop_name, bool value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_BOOLEAN, set its name and value.
std::unique_ptr< blender::io::serialize::ArrayValue > convert_to_serialize_values(const IDProperty *properties)
Convert the given properties to Value objects for serialization.
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRefNull prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
static constexpr StringRef IDP_KEY_NAME("name")
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRefNull prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
static constexpr IDPBoolSerializer IDP_SERIALIZER_BOOL
static constexpr IDPIntSerializer IDP_SERIALIZER_INT
IDProperty * convert_from_serialize_value(const blender::io::serialize::Value &value)
Convert the given value to an IDProperty.
std::shared_ptr< const T > get(const GenericKey &key, FunctionRef< std::unique_ptr< T >()> compute_fn)
signed int int32_t
Definition stdint.h:77
ListBase group
Definition DNA_ID.h:146
int len
Definition DNA_ID.h:174
struct IDProperty * next
Definition DNA_ID.h:152
char name[64]
Definition DNA_ID.h:163
IDPropertyData data
Definition DNA_ID.h:168
struct IDProperty * prev
Definition DNA_ID.h:152
char subtype
Definition DNA_ID.h:159
char type
Definition DNA_ID.h:154
Helper class for parsing DictionaryValues.
DictionaryEntryParser(const DictionaryValue &value)
std::optional< std::string > get_string_value() const
std::optional< std::string > get_name() const
std::optional< float > get_float_value() const
std::optional< Vector< double > > get_array_double_value() const
std::optional< eIDPropertyType > get_type() const
std::optional< int32_t > get_int_value() const
std::optional< Vector< float > > get_array_float_value() const
std::optional< double > get_double_value() const
std::optional< Vector< int32_t > > get_array_int_value() const
std::optional< eIDPropertyType > get_subtype() const
std::optional< bool > get_bool_value() const