Blender  V2.93
node_geo_attribute_convert.cc
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
17 #include "UI_interface.h"
18 #include "UI_resources.h"
19 
20 #include "node_geometry_util.hh"
21 
23  {SOCK_GEOMETRY, N_("Geometry")},
24  {SOCK_STRING, N_("Attribute")},
25  {SOCK_STRING, N_("Result")},
26  {-1, ""},
27 };
28 
30  {SOCK_GEOMETRY, N_("Geometry")},
31  {-1, ""},
32 };
33 
35  bContext *UNUSED(C),
36  PointerRNA *ptr)
37 {
38  uiItemR(layout, ptr, "domain", 0, "", ICON_NONE);
39  uiItemR(layout, ptr, "data_type", 0, "", ICON_NONE);
40 }
41 
43 {
45  __func__);
46 
47  data->data_type = CD_PROP_FLOAT;
48  data->domain = ATTR_DOMAIN_AUTO;
49  node->storage = data;
50 }
51 
52 namespace blender::nodes {
53 
55  StringRef source_name,
56  StringRef result_name)
57 {
58  ReadAttributePtr result_attribute = component.attribute_try_get_for_read(result_name);
59  if (result_attribute) {
60  return result_attribute->domain();
61  }
62  ReadAttributePtr source_attribute = component.attribute_try_get_for_read(source_name);
63  if (source_attribute) {
64  return source_attribute->domain();
65  }
66  return ATTR_DOMAIN_POINT;
67 }
68 
70  const StringRef source_name,
71  const StringRef result_name,
72  const AttributeDomain result_domain,
73  const CustomDataType result_type)
74 {
75  if (source_name != result_name) {
76  return false;
77  }
78  ReadAttributePtr read_attribute = component.attribute_try_get_for_read(source_name);
79  if (!read_attribute) {
80  return false;
81  }
82  if (read_attribute->domain() != result_domain) {
83  return false;
84  }
85  if (read_attribute->cpp_type() != *bke::custom_data_type_to_cpp_type(result_type)) {
86  return false;
87  }
88  return true;
89 }
90 
93  const StringRef source_name,
94  const StringRef result_name,
95  const CustomDataType result_type,
96  const AttributeDomain domain)
97 {
98  const AttributeDomain result_domain = (domain == ATTR_DOMAIN_AUTO) ?
100  component, source_name, result_name) :
101  domain;
102 
103  if (conversion_can_be_skipped(component, source_name, result_name, result_domain, result_type)) {
104  return;
105  }
106 
107  ReadAttributePtr source_attribute = component.attribute_try_get_for_read(
108  source_name, result_domain, result_type);
109  if (!source_attribute) {
110  params.error_message_add(NodeWarningType::Error,
111  TIP_("No attribute with name \"") + source_name + "\"");
112  return;
113  }
114 
115  OutputAttributePtr result_attribute = component.attribute_try_get_for_output(
116  result_name, result_domain, result_type);
117  if (!result_attribute) {
118  return;
119  }
120 
121  fn::GSpan source_span = source_attribute->get_span();
122  fn::GMutableSpan result_span = result_attribute->get_span_for_write_only();
123  if (source_span.is_empty() || result_span.is_empty()) {
124  return;
125  }
126  BLI_assert(source_span.size() == result_span.size());
127 
128  const CPPType *cpp_type = bke::custom_data_type_to_cpp_type(result_type);
129  BLI_assert(cpp_type != nullptr);
130 
131  cpp_type->copy_to_initialized_n(source_span.data(), result_span.data(), result_span.size());
132 
133  result_attribute.apply_span_and_save();
134 }
135 
137 {
138  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
139 
140  geometry_set = geometry_set_realize_instances(geometry_set);
141 
142  const std::string result_name = params.extract_input<std::string>("Result");
143  const std::string source_name = params.extract_input<std::string>("Attribute");
144  const NodeAttributeConvert &node_storage = *(const NodeAttributeConvert *)params.node().storage;
145  const CustomDataType data_type = static_cast<CustomDataType>(node_storage.data_type);
146  const AttributeDomain domain = static_cast<AttributeDomain>(node_storage.domain);
147 
148  if (result_name.empty()) {
149  params.set_output("Geometry", geometry_set);
150  return;
151  }
152 
153  if (geometry_set.has<MeshComponent>()) {
155  params,
156  source_name,
157  result_name,
158  data_type,
159  domain);
160  }
161  if (geometry_set.has<PointCloudComponent>()) {
163  params,
164  source_name,
165  result_name,
166  data_type,
167  domain);
168  }
169 
170  params.set_output("Geometry", geometry_set);
171 }
172 
173 } // namespace blender::nodes
174 
176 {
177  static bNodeType ntype;
178 
180  &ntype, GEO_NODE_ATTRIBUTE_CONVERT, "Attribute Convert", NODE_CLASS_ATTRIBUTE, 0);
187  &ntype, "NodeAttributeConvert", node_free_standard_storage, node_copy_standard_storage);
188 
189  nodeRegisterType(&ntype);
190 }
AttributeDomain
Definition: BKE_attribute.h:41
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:43
@ ATTR_DOMAIN_AUTO
Definition: BKE_attribute.h:42
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
Definition: node.cc:4527
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4559
void node_type_storage(struct bNodeType *ntype, const char *storagename, void(*freefunc)(struct bNode *node), void(*copyfunc)(struct bNodeTree *dest_ntree, struct bNode *dest_node, const struct bNode *src_node))
Definition: node.cc:4599
#define NODE_CLASS_ATTRIBUTE
Definition: BKE_node.h:360
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1298
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define UNUSED(x)
#define TIP_(msgid)
#define N_(msgid)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:126
CustomDataType
@ CD_PROP_FLOAT
@ SOCK_GEOMETRY
@ SOCK_STRING
Group RGB to Bright Vector Camera Vector Combine Material Light Line Style Layer Add Ambient Diffuse Glossy Refraction Transparent Toon Principled Hair Volume Principled Light Particle Volume Image Sky Noise Wave Voronoi Brick Texture Vector Combine Vertex Separate Vector White RGB Map Separate Set Z Dilate Combine Combine Color Channel Split ID Combine Luminance Directional Alpha Distance Hue Movie Ellipse Bokeh View Corner Anti Mix RGB Hue Separate TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC TEX_NODE_PROC Boolean Random Edge Subdivision Point Object Attribute Attribute Attribute Color Attribute Attribute Vector Point Attribute Sample Collection Attribute Attribute Combine GEO_NODE_ATTRIBUTE_CONVERT
#define C
Definition: RandGen.cpp:39
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
fn::GMutableSpan get_span_for_write_only()
void copy_to_initialized_n(const void *src, void *dst, int64_t n) const
Definition: FN_cpp_type.hh:399
const void * data() const
bool is_empty() const
int64_t size() const
OperationNode * node
void * tree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
const CPPType * custom_data_type_to_cpp_type(const CustomDataType type)
std::unique_ptr< ReadAttribute > ReadAttributePtr
static void attribute_convert_calc(GeometryComponent &component, const GeoNodeExecParams &params, const StringRef source_name, const StringRef result_name, const CustomDataType result_type, const AttributeDomain domain)
static void geo_node_attribute_convert_exec(GeoNodeExecParams params)
static bool conversion_can_be_skipped(const GeometryComponent &component, const StringRef source_name, const StringRef result_name, const AttributeDomain result_domain, const CustomDataType result_type)
static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef source_name, StringRef result_name)
static void geo_node_attribute_convert_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
void register_node_type_geo_attribute_convert()
static bNodeSocketTemplate geo_node_attribute_convert_in[]
static void geo_node_attribute_convert_init(bNodeTree *UNUSED(tree), bNode *node)
static bNodeSocketTemplate geo_node_attribute_convert_out[]
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass, short flag)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:67
void node_free_standard_storage(bNode *node)
Definition: node_util.c:55
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
bool has(const GeometryComponentType component_type) const
Compact definition of a node socket.
Definition: BKE_node.h:95
Defines a node type.
Definition: BKE_node.h:221
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:327
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:253
PointerRNA * ptr
Definition: wm_files.c:3157