Blender V5.0
grease_pencil_attributes.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2024 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
7
9
12
14
15static const auto &changed_tags()
16{
17 static Map<StringRef, AttrUpdateOnChange> attributes;
18 return attributes;
19}
20
21static const auto &builtin_attributes()
22{
23 static auto attributes = []() {
25 return map;
26 }();
27 return attributes;
28}
29
30static int get_domain_size(const void *owner, const AttrDomain domain)
31{
32 const GreasePencil &grease_pencil = *static_cast<const GreasePencil *>(owner);
33 return domain == AttrDomain::Layer ? grease_pencil.layers().size() : 0;
34}
35
37{
39 fn.domain_supported = [](const void * /*owner*/, const AttrDomain domain) {
40 return domain == AttrDomain::Layer;
41 };
42 fn.domain_size = get_domain_size;
43 fn.builtin_domain_and_type = [](const void * /*owner*/, const StringRef /*name*/)
44 -> std::optional<AttributeDomainAndType> { return std::nullopt; };
45 fn.lookup = [](const void *owner, const StringRef name) -> GAttributeReader {
46 const GreasePencil &grease_pencil = *static_cast<const GreasePencil *>(owner);
47 const AttributeStorage &storage = grease_pencil.attribute_storage.wrap();
48 const Attribute *attribute = storage.lookup(name);
49 if (!attribute) {
50 return {};
51 }
52 const int domain_size = get_domain_size(owner, AttrDomain::Layer);
53 return attribute_to_reader(*attribute, AttrDomain::Layer, domain_size);
54 };
55 fn.get_builtin_default = [](const void * /*owner*/, StringRef name) -> GPointer {
56 const AttrBuiltinInfo &info = builtin_attributes().lookup(name);
57 return info.default_value;
58 };
59 fn.adapt_domain = [](const void * /*owner*/,
60 const GVArray &varray,
61 const AttrDomain from_domain,
62 const AttrDomain to_domain) {
63 if (from_domain == to_domain && from_domain == AttrDomain::Layer) {
64 return varray;
65 }
66 return GVArray{};
67 };
68 fn.foreach_attribute = [](const void *owner,
69 const FunctionRef<void(const AttributeIter &)> fn,
70 const AttributeAccessor &accessor) {
71 const GreasePencil &grease_pencil = *static_cast<const GreasePencil *>(owner);
72 const AttributeStorage &storage = grease_pencil.attribute_storage.wrap();
73 storage.foreach_with_stop([&](const Attribute &attribute) {
74 const auto get_fn = [&]() {
75 const int domain_size = get_domain_size(owner, AttrDomain::Layer);
76 return attribute_to_reader(attribute, AttrDomain::Layer, domain_size);
77 };
78 AttributeIter iter(attribute.name(), attribute.domain(), attribute.data_type(), get_fn);
79 iter.is_builtin = builtin_attributes().contains(attribute.name());
80 iter.accessor = &accessor;
81 fn(iter);
82 return !iter.is_stopped();
83 });
84 };
85 fn.lookup_validator = [](const void * /*owner*/, const StringRef name) -> AttributeValidator {
86 const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name);
87 if (!info) {
88 return {};
89 }
90 return info->validator;
91 };
92 fn.lookup_for_write = [](void *owner, const StringRef name) -> GAttributeWriter {
93 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(owner);
94 AttributeStorage &storage = grease_pencil.attribute_storage.wrap();
95 Attribute *attribute = storage.lookup(name);
96 if (!attribute) {
97 return {};
98 }
99 const int domain_size = get_domain_size(owner, AttrDomain::Layer);
100 return attribute_to_writer(&grease_pencil, {}, domain_size, *attribute);
101 };
102 fn.remove = [](void *owner, const StringRef name) -> bool {
103 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(owner);
104 AttributeStorage &storage = grease_pencil.attribute_storage.wrap();
105 if (const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name)) {
106 if (!info->deletable) {
107 return false;
108 }
109 }
110 const std::optional<AttrUpdateOnChange> fn = changed_tags().lookup_try(name);
111 const bool removed = storage.remove(name);
112 if (!removed) {
113 return false;
114 }
115 if (fn) {
116 (*fn)(owner);
117 }
118 return true;
119 };
120 fn.add = [](void *owner,
121 const StringRef name,
122 const AttrDomain domain,
123 const bke::AttrType type,
124 const AttributeInit &initializer) {
125 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(owner);
126 const int domain_size = get_domain_size(owner, domain);
127 AttributeStorage &storage = grease_pencil.attribute_storage.wrap();
128 if (const AttrBuiltinInfo *info = builtin_attributes().lookup_ptr(name)) {
129 if (info->domain != domain || info->type != type) {
130 return false;
131 }
132 }
133 if (storage.lookup(name)) {
134 return false;
135 }
136 storage.add(name, domain, type, attribute_init_to_data(type, domain_size, initializer));
137 if (initializer.type != AttributeInit::Type::Construct) {
138 if (const std::optional<AttrUpdateOnChange> fn = changed_tags().lookup_try(name)) {
139 (*fn)(owner);
140 }
141 }
142 return true;
143 };
144
145 return fn;
146}
147
153
154} // namespace blender::bke::greasepencil
Low-level operations for grease pencil.
const AttributeAccessor * accessor
Attribute & add(std::string name, bke::AttrDomain domain, bke::AttrType data_type, Attribute::DataVariant data)
Attribute * lookup(StringRef name)
void foreach_with_stop(FunctionRef< bool(Attribute &)> fn)
static int get_domain_size(const void *owner, const AttrDomain domain)
const AttributeAccessorFunctions & get_attribute_accessor_functions()
static AttributeAccessorFunctions get_grease_pencil_accessor_functions()
static const auto & builtin_attributes()
GAttributeReader attribute_to_reader(const Attribute &attribute, const AttrDomain domain, const int64_t domain_size)
Attribute::DataVariant attribute_init_to_data(const bke::AttrType data_type, const int64_t domain_size, const AttributeInit &initializer)
GAttributeWriter attribute_to_writer(void *owner, const Map< StringRef, AttrUpdateOnChange > &changed_tags, const int64_t domain_size, Attribute &attribute)
const char * name
struct AttributeStorage attribute_storage