Docs: Add to and cleanup attribute API docs
Most of the comment block is similar to the text in the source code documentation wiki. It's helpful to have some text in a header file too, so it's closer for programmers already looking at the code. This also uses more consistent syntax and wording in the comments about the attribute API in `GeometryComponent`. Ref T93753 Differential Revision: https://developer.blender.org/D13661
This commit is contained in:
parent
ceed8f7c06
commit
dd3a72f275
Notes:
blender-bot
2023-02-13 16:53:39 +01:00
Referenced by issue #93753, Technical docs about geometry nodes in the wiki
|
@ -30,6 +30,39 @@
|
|||
#include "BLI_float3.hh"
|
||||
#include "BLI_function_ref.hh"
|
||||
|
||||
/**
|
||||
* This file defines classes that help to provide access to attribute data on a #GeometryComponent.
|
||||
* The API for retrieving attributes is defined in `BKE_geometry_set.hh`, but this comment has some
|
||||
* general comments about the system.
|
||||
*
|
||||
* Attributes are stored in geometry data, though they can also be stored in instances. Their
|
||||
* storage is often tied to `CustomData`, which is a system to store "layers" of data with specific
|
||||
* types and names. However, since `CustomData` was added to Blender before attributes were
|
||||
* conceptualized, it combines the "legacy" style of task-specific attribute types with generic
|
||||
* types like "Float". The attribute API here only provides access to generic types.
|
||||
*
|
||||
* Attributes are retrieved from geometry components by providing an "id" (#AttributeIDRef). This
|
||||
* is most commonly just an attribute name. The attribute API on geometry components has some more
|
||||
* advanced capabilities:
|
||||
* 1. Read-only access: With a `const` geometry component, an attribute on the geometry cannot be
|
||||
* modified, so the `for_write` and `for_output` versions of the API are not available. This is
|
||||
* extremely important for writing coherent bug-free code. When an attribute is retrieved with
|
||||
* write access, via #WriteAttributeLookup or #OutputAttribute, the geometry component must be
|
||||
* tagged to clear caches that depend on the changed data.
|
||||
* 2. Domain interpolation: When retrieving an attribute, a domain (#AttributeDomain) can be
|
||||
* provided. If the attribute is stored on a different domain and conversion is possible, a
|
||||
* version of the data interpolated to the requested domain will be provided. These conversions
|
||||
* are implemented in each #GeometryComponent by `attribute_try_adapt_domain_impl`.
|
||||
* 3. Implicit type conversion: In addition to interpolating domains, attribute types can be
|
||||
* converted, using the conversions in `BKE_type_conversions.hh`. The #VArray / #GVArray system
|
||||
* makes it possible to only convert necessary indices on-demand.
|
||||
* 4. Anonymous attributes: The "id" used to look up an attribute can also be an anonymous
|
||||
* attribute reference. Currently anonymous attributes are only used in geometry nodes.
|
||||
* 5. Abstracted storage: Since the data returned from the API is usually a virtual array,
|
||||
* it doesn't have to be stored contiguously (even though that is generally preferred). This
|
||||
* allows accessing "legacy" attributes like `material_index`, which is stored in `MPoly`.
|
||||
*/
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
/**
|
||||
|
|
|
@ -93,41 +93,64 @@ class GeometryComponent {
|
|||
|
||||
GeometryComponentType type() const;
|
||||
|
||||
/* Return true when any attribute with this name exists, including built in attributes. */
|
||||
/**
|
||||
* Return true when any attribute with this name exists, including built in attributes.
|
||||
*/
|
||||
bool attribute_exists(const blender::bke::AttributeIDRef &attribute_id) const;
|
||||
|
||||
/* Return the data type and domain of an attribute with the given name if it exists. */
|
||||
/**
|
||||
* Return the data type and domain of an attribute with the given name if it exists.
|
||||
*/
|
||||
std::optional<AttributeMetaData> attribute_get_meta_data(
|
||||
const blender::bke::AttributeIDRef &attribute_id) const;
|
||||
|
||||
/* Returns true when the geometry component supports this attribute domain. */
|
||||
/**
|
||||
* Return true when the geometry component supports this attribute domain.
|
||||
* \note Conceptually this function is static, the result is always the same for different
|
||||
* instances of the same geometry component type.
|
||||
*/
|
||||
bool attribute_domain_supported(const AttributeDomain domain) const;
|
||||
/* Can only be used with supported domain types. */
|
||||
/**
|
||||
* Return the length of a specific domain, or 0 if the domain is not supported.
|
||||
*/
|
||||
virtual int attribute_domain_size(const AttributeDomain domain) const;
|
||||
|
||||
/**
|
||||
* Return true if the attribute name corresponds to a built-in attribute with a hardcoded domain
|
||||
* and data type.
|
||||
*/
|
||||
bool attribute_is_builtin(const blender::StringRef attribute_name) const;
|
||||
bool attribute_is_builtin(const blender::bke::AttributeIDRef &attribute_id) const;
|
||||
|
||||
/* Get read-only access to the highest priority attribute with the given name.
|
||||
* Returns null if the attribute does not exist. */
|
||||
/**
|
||||
* Get read-only access to an attribute with the given name or id, on the highest priority domain
|
||||
* if there is a name collision.
|
||||
* \return null if the attribute does not exist.
|
||||
*/
|
||||
blender::bke::ReadAttributeLookup attribute_try_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id) const;
|
||||
|
||||
/* Get read and write access to the highest priority attribute with the given name.
|
||||
* Returns null if the attribute does not exist. */
|
||||
/**
|
||||
* Get read and write access to an attribute with the given name or id, on the highest priority
|
||||
* domain if there is a name collision.
|
||||
* \note #WriteAttributeLookup.tag_modified_fn must be called after modifying data.
|
||||
* \return null if the attribute does not exist
|
||||
*/
|
||||
blender::bke::WriteAttributeLookup attribute_try_get_for_write(
|
||||
const blender::bke::AttributeIDRef &attribute_id);
|
||||
|
||||
/* Get a read-only attribute for the domain based on the given attribute. This can be used to
|
||||
/**
|
||||
* Get a read-only attribute for the domain based on the given attribute. This can be used to
|
||||
* interpolate from one domain to another.
|
||||
* Returns null if the interpolation is not implemented. */
|
||||
* \return null if the interpolation is not implemented.
|
||||
*/
|
||||
blender::fn::GVArray attribute_try_adapt_domain(const blender::fn::GVArray &varray,
|
||||
const AttributeDomain from_domain,
|
||||
const AttributeDomain to_domain) const
|
||||
{
|
||||
return this->attribute_try_adapt_domain_impl(varray, from_domain, to_domain);
|
||||
}
|
||||
|
||||
/* Use instead of the method above when the type is known at compile time for type safety. */
|
||||
template<typename T>
|
||||
blender::VArray<T> attribute_try_adapt_domain(const blender::VArray<T> &varray,
|
||||
const AttributeDomain from_domain,
|
||||
|
@ -137,17 +160,19 @@ class GeometryComponent {
|
|||
.template typed<T>();
|
||||
}
|
||||
|
||||
/* Returns true when the attribute has been deleted. */
|
||||
/** Returns true when the attribute has been deleted. */
|
||||
bool attribute_try_delete(const blender::bke::AttributeIDRef &attribute_id);
|
||||
|
||||
/* Returns true when the attribute has been created. */
|
||||
/** Returns true when the attribute has been created. */
|
||||
bool attribute_try_create(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const AttributeInit &initializer);
|
||||
|
||||
/* Try to create the builtin attribute with the given name. No data type or domain has to be
|
||||
* provided, because those are fixed for builtin attributes. */
|
||||
/**
|
||||
* Try to create the builtin attribute with the given name. No data type or domain has to be
|
||||
* provided, because those are fixed for builtin attributes.
|
||||
*/
|
||||
bool attribute_try_create_builtin(const blender::StringRef attribute_name,
|
||||
const AttributeInit &initializer);
|
||||
|
||||
|
@ -160,34 +185,41 @@ class GeometryComponent {
|
|||
|
||||
virtual bool is_empty() const;
|
||||
|
||||
/* Get a virtual array to read the data of an attribute on the given domain and data type.
|
||||
* Returns null when the attribute does not exist or cannot be converted to the requested domain
|
||||
* and data type. */
|
||||
/**
|
||||
* Get a virtual array that refers to the data of an attribute, interpolated to the given domain
|
||||
* and converted to the data type. Returns null when the attribute does not exist or cannot be
|
||||
* interpolated or converted.
|
||||
*/
|
||||
blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type) const;
|
||||
|
||||
/* Get a virtual array to read the data of an attribute on the given domain. The data type is
|
||||
* left unchanged. Returns null when the attribute does not exist or cannot be adapted to the
|
||||
* requested domain. */
|
||||
/**
|
||||
* Get a virtual array that refers to the data of an attribute, interpolated to the given domain.
|
||||
* The data type is left unchanged. Returns null when the attribute does not exist or cannot be
|
||||
* interpolated.
|
||||
*/
|
||||
blender::fn::GVArray attribute_try_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain) const;
|
||||
|
||||
/* Get a virtual array to read data of an attribute with the given data type. The domain is
|
||||
* left unchanged. Returns null when the attribute does not exist or cannot be converted to the
|
||||
* requested data type. */
|
||||
/**
|
||||
* Get a virtual array that refers to the data of an attribute converted to the given data type.
|
||||
* The attribute's domain is left unchanged. Returns null when the attribute does not exist or
|
||||
* cannot be converted.
|
||||
*/
|
||||
blender::bke::ReadAttributeLookup attribute_try_get_for_read(
|
||||
const blender::bke::AttributeIDRef &attribute_id, const CustomDataType data_type) const;
|
||||
|
||||
/* Get a virtual array to read the data of an attribute. If that is not possible, the returned
|
||||
* virtual array will contain a default value. This never returns null. */
|
||||
/**
|
||||
* Get a virtual array that refers to the data of an attribute, interpolated to the given domain
|
||||
* and converted to the data type. If that is not possible, the returned virtual array will
|
||||
* contain a default value. This never returns null.
|
||||
*/
|
||||
blender::fn::GVArray attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value = nullptr) const;
|
||||
|
||||
/* Should be used instead of the method above when the requested data type is known at compile
|
||||
* time for better type safety. */
|
||||
/* Use instead of the method above when the type is known at compile time for type safety. */
|
||||
template<typename T>
|
||||
blender::VArray<T> attribute_get_for_read(const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
|
@ -214,16 +246,7 @@ class GeometryComponent {
|
|||
const AttributeDomain domain,
|
||||
const CustomDataType data_type,
|
||||
const void *default_value = nullptr);
|
||||
|
||||
/* Same as attribute_try_get_for_output, but should be used when the original values in the
|
||||
* attributes are not read, i.e. the attribute is used only for output. Since values are not read
|
||||
* from this attribute, no default value is necessary. */
|
||||
blender::bke::OutputAttribute attribute_try_get_for_output_only(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type);
|
||||
|
||||
/* Statically typed method corresponding to the equally named generic one. */
|
||||
/* Use instead of the method above when the type is known at compile time for type safety. */
|
||||
template<typename T>
|
||||
blender::bke::OutputAttribute_Typed<T> attribute_try_get_for_output(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
|
@ -235,7 +258,17 @@ class GeometryComponent {
|
|||
return this->attribute_try_get_for_output(attribute_id, domain, data_type, &default_value);
|
||||
}
|
||||
|
||||
/* Statically typed method corresponding to the equally named generic one. */
|
||||
/**
|
||||
* Same as #attribute_try_get_for_output, but should be used when the original values in the
|
||||
* attributes are not read, i.e. the attribute is used only for output. The can be faster because
|
||||
* it can avoid interpolation and conversion of existing values. Since values are not read from
|
||||
* this attribute, no default value is necessary.
|
||||
*/
|
||||
blender::bke::OutputAttribute attribute_try_get_for_output_only(
|
||||
const blender::bke::AttributeIDRef &attribute_id,
|
||||
const AttributeDomain domain,
|
||||
const CustomDataType data_type);
|
||||
/* Use instead of the method above when the type is known at compile time for type safety. */
|
||||
template<typename T>
|
||||
blender::bke::OutputAttribute_Typed<T> attribute_try_get_for_output_only(
|
||||
const blender::bke::AttributeIDRef &attribute_id, const AttributeDomain domain)
|
||||
|
|
Loading…
Reference in New Issue