Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Lucke <jacques@blender.org>2021-01-14 17:52:08 +0300
committerJacques Lucke <jacques@blender.org>2021-01-14 17:52:08 +0300
commite5ee7e9a2df93d7f28f9e1f8bc0eb2d33dfadfb4 (patch)
treef36c7d02bc3441c75b6233fcaa4b0611df883248 /source/blender/blenkernel/BKE_geometry_set.hh
parent53bd58993e2f6d35452242762402c20343d6eef3 (diff)
Geometry Nodes: don't delete existing attribute before new attribute is computed
This fixes the behavior of some nodes when the same attribute name is used for input and output. If both attributes have a different type, they can't exist at the same time. Therefore, the input attribute has to be removed in order to create the output attribute. Previously, the input attribute was remove before it was used in any computations. Now, the output is written to a temporary buffer and only later saved in the geometry component. This allows both attributes to coexist within the node. The temporary attribute is only create when necessary. The normal case without name collisions still works the same as before. Differential Revision: https://developer.blender.org/D10109 Ref T83793.
Diffstat (limited to 'source/blender/blenkernel/BKE_geometry_set.hh')
-rw-r--r--source/blender/blenkernel/BKE_geometry_set.hh73
1 files changed, 66 insertions, 7 deletions
diff --git a/source/blender/blenkernel/BKE_geometry_set.hh b/source/blender/blenkernel/BKE_geometry_set.hh
index 9dc2b80d4d4..57fad6bcdf6 100644
--- a/source/blender/blenkernel/BKE_geometry_set.hh
+++ b/source/blender/blenkernel/BKE_geometry_set.hh
@@ -65,6 +65,62 @@ template<> struct DefaultHash<GeometryComponentType> {
};
} // namespace blender
+class GeometryComponent;
+
+/**
+ * An #OutputAttributePtr wraps a #WriteAttributePtr that might not be stored in its final
+ * destination yet. Therefore, once the attribute has been filled with data, the #save method has
+ * to be called, to store the attribute where it belongs (possibly by replacing an existing
+ * attribute with the same name).
+ *
+ * This is useful for example in the Attribute Color Ramp node, when the same attribute name is
+ * used as input and output. Typically the input is a float attribute, and the output is a color.
+ * Those two attributes cannot exist at the same time, due to a name collision. To handle this
+ * situation well, first the output colors have to be computed before the input floats are deleted.
+ * Therefore, the outputs have to be written to a temporary buffer that replaces the existing
+ * attribute once all computations are done.
+ */
+class OutputAttributePtr {
+ private:
+ blender::bke::WriteAttributePtr attribute_;
+
+ public:
+ OutputAttributePtr() = default;
+ OutputAttributePtr(blender::bke::WriteAttributePtr attribute);
+ OutputAttributePtr(GeometryComponent &component,
+ AttributeDomain domain,
+ std::string name,
+ CustomDataType data_type);
+
+ ~OutputAttributePtr();
+
+ /* Returns false, when this wrapper is empty. */
+ operator bool() const
+ {
+ return static_cast<bool>(attribute_);
+ }
+
+ /* Get a reference to the underlying #WriteAttribute. */
+ blender::bke::WriteAttribute &get()
+ {
+ BLI_assert(attribute_);
+ return *attribute_;
+ }
+
+ blender::bke::WriteAttribute &operator*()
+ {
+ return *attribute_;
+ }
+
+ blender::bke::WriteAttribute *operator->()
+ {
+ return attribute_.get();
+ }
+
+ void save();
+ void apply_span_and_save();
+};
+
/**
* This is the base class for specialized geometry component types.
*/
@@ -185,14 +241,17 @@ class GeometryComponent {
}
/**
- * Returns the attribute with the given parameters if it exists.
- * If an exact match does not exist, other attributes with the same name are deleted and a new
- * attribute is created if possible.
+ * If an attribute with the given params exist, it is returned.
+ * If no attribute with the given name exists, it is created and returned.
+ * If an attribute with the given name but different domain or type exists, a temporary attribute
+ * is created that has to be saved after the output has been computed. This avoids deleting
+ * another attribute, before a computation is finished.
+ *
+ * This might return no attribute when the attribute cannot exist on the component.
*/
- blender::bke::WriteAttributePtr attribute_try_ensure_for_write(
- const blender::StringRef attribute_name,
- const AttributeDomain domain,
- const CustomDataType data_type);
+ OutputAttributePtr attribute_try_get_for_output(const blender::StringRef attribute_name,
+ const AttributeDomain domain,
+ const CustomDataType data_type);
};
template<typename T>