Skip to content

Commit f50fa92

Browse files
committed
Change capture/transfer behavior
1 parent a360f26 commit f50fa92

File tree

2 files changed

+16
-31
lines changed

2 files changed

+16
-31
lines changed

api/types.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,11 @@ def z(self):
169169

170170
def capture(self, value, **kwargs):
171171
data_type = socket_type_to_data_type(value._socket.type)
172-
captured = self.capture_attribute(data_type=data_type, value=value, **kwargs)
173-
return lambda **kwargs: captured.geometry.transfer_attribute(data_type=data_type, attribute=captured.attribute, **kwargs)
172+
geometry, attribute = self.capture_attribute(data_type=data_type, value=value, **kwargs)
173+
return geometry, attribute
174+
def transfer(self, attribute, **kwargs):
175+
data_type = socket_type_to_data_type(attribute._socket.type)
176+
return self.transfer_attribute(data_type=data_type, attribute=attribute, **kwargs)
174177

175178
for standard_socket in list(filter(lambda x: 'NodeSocket' in x, dir(bpy.types))):
176179
name = standard_socket.replace('NodeSocket', '')
Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,48 @@
11
# Attributes
22

3-
An important concept in Geometry Nodes is attributes. Many trees transfer attributes between geometry, using a combination of *Capture Attribute* and *Transfer Attribute*.
3+
An important concept in Geometry Nodes is attributes. Many trees capture attributes or transfer them from one geometry to another.
44

5-
Unfortunately, it takes quite a bit of code to use this common pattern.
5+
When using these methods, the `data_type` argument must be correctly specified for the transfer to work as intended.
66

77
```python
88
@tree("Skin")
99
def skin():
1010
# Create a cube
1111
c = cube()
12-
# Capture the position
13-
cube_position_attribute = c.capture_attribute(
14-
data_type=CaptureAttribute.DataType.FLOAT_VECTOR,
15-
value=position()
16-
)
1712
# Create a sphere
1813
sphere = uv_sphere()
1914
# Transfer the position to the sphere
20-
transferred_position = cube_position_attribute.geometry.transfer_attribute(
15+
transferred_position = c.transfer_attribute(
2116
data_type=TransferAttribute.DataType.FLOAT_VECTOR,
22-
attribute=cube_position_attribute.attribute
17+
attribute=position()
2318
)
2419
# Make the sphere conform to the shape of the cube
2520
return sphere.set_position(position=transferred_position)
2621
```
2722

28-
Thankfully, a convenient `capture(...)` method is available on `Geometry`, which simplifies this function quite a bit.
23+
To improve the usability of these nodes, `capture(...)` and `transfer(...)` methods are provided on `Geometry` that simply take the attribute and any other optional arguments.
2924

3025
```python
3126
@tree("Skin")
3227
def skin():
3328
# Create a cube
3429
c = cube()
35-
# Capture the position
36-
cube_position = c.capture(position())
3730
# Create a sphere
3831
sphere = uv_sphere()
3932
# Make the sphere conform to the shape of the cube
40-
return sphere.set_position(position=cube_position())
33+
return sphere.set_position(position=c.transfer(position()))
4134
```
4235

43-
## How it Works
44-
45-
Internally, `capture(...)` works just like the more manual approach.
46-
47-
1. Capture the attribute from the source
48-
49-
In the example above, we capture the `position()` from the cube.
50-
The data type is automatically inferred from the input. If you want to customize other options, simply pass them as keyword arguments to `capture(...)`.
36+
The same is available for `capture(...)`.
5137

5238
```python
53-
cube_position = c.capture(position())
54-
cube_position = c.capture(position(), domain=CaptureAttribute.Domain.FACE) # Optionally pass other arguments available on `capture_attribute`.
39+
geometry_with_attribute, attribute = c.capture(position())
5540
```
5641

57-
2. Transfer the attribute to the target
42+
> You must use the `Geometry` returned from `capture(...)` for the anonymous attribute it creates to be usable.
5843
59-
`capture(...)` returns another function that calls `transfer_attribute` with the correct arguments passed automatically.
60-
Call this returned function (which we store in the variable `cube_position`) to transfer the attribute.
61-
In this example we also set the transferred cube position back onto the sphere.
44+
Any additional keyword arguments can be passed as normal.
6245

6346
```python
64-
sphere.set_position(position=cube_position())
65-
sphere.set_position(position=cube_position(mapping=TransferAttribute.Mapping.NEAREST)) # Optionally pass other arguments available on `transfer_attribute`.
47+
c.transfer(position(), mapping=TransferAttribute.Mapping.INDEX)
6648
```

0 commit comments

Comments
 (0)