Blender  V2.93
node_geo_attribute_mix.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 "BKE_material.h"
18 
19 #include "DNA_material_types.h"
20 
21 #include "UI_interface.h"
22 #include "UI_resources.h"
23 
24 #include "node_geometry_util.hh"
25 
27  {SOCK_GEOMETRY, N_("Geometry")},
28  {SOCK_STRING, N_("Factor")},
29  {SOCK_FLOAT, N_("Factor"), 0.5, 0.0, 0.0, 0.0, 0.0, 1.0, PROP_FACTOR},
30  {SOCK_STRING, N_("A")},
31  {SOCK_FLOAT, N_("A"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX},
32  {SOCK_VECTOR, N_("A"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX},
33  {SOCK_RGBA, N_("A"), 0.5, 0.5, 0.5, 1.0},
34  {SOCK_STRING, N_("B")},
35  {SOCK_FLOAT, N_("B"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX},
36  {SOCK_VECTOR, N_("B"), 0.0, 0.0, 0.0, 0.0, -FLT_MAX, FLT_MAX},
37  {SOCK_RGBA, N_("B"), 0.5, 0.5, 0.5, 1.0},
38  {SOCK_STRING, N_("Result")},
39  {-1, ""},
40 };
41 
43  {SOCK_GEOMETRY, N_("Geometry")},
44  {-1, ""},
45 };
46 
48 {
49  uiLayoutSetPropSep(layout, true);
50  uiLayoutSetPropDecorate(layout, false);
51  uiItemR(layout, ptr, "blend_type", 0, "", ICON_NONE);
52  uiLayout *col = uiLayoutColumn(layout, false);
53  uiItemR(col, ptr, "input_type_factor", 0, IFACE_("Factor"), ICON_NONE);
54  uiItemR(col, ptr, "input_type_a", 0, IFACE_("A"), ICON_NONE);
55  uiItemR(col, ptr, "input_type_b", 0, IFACE_("B"), ICON_NONE);
56 }
57 
58 namespace blender::nodes {
59 
60 static void do_mix_operation_float(const int blend_mode,
61  const FloatReadAttribute &factors,
62  const FloatReadAttribute &inputs_a,
63  const FloatReadAttribute &inputs_b,
64  FloatWriteAttribute results)
65 {
66  const int size = results.size();
67  for (const int i : IndexRange(size)) {
68  const float factor = factors[i];
69  float3 a{inputs_a[i]};
70  const float3 b{inputs_b[i]};
71  ramp_blend(blend_mode, a, factor, b);
72  const float result = a.x;
73  results.set(i, result);
74  }
75 }
76 
77 static void do_mix_operation_float3(const int blend_mode,
78  const FloatReadAttribute &factors,
79  const Float3ReadAttribute &inputs_a,
80  const Float3ReadAttribute &inputs_b,
81  Float3WriteAttribute results)
82 {
83  const int size = results.size();
84  for (const int i : IndexRange(size)) {
85  const float factor = factors[i];
86  float3 a = inputs_a[i];
87  const float3 b = inputs_b[i];
88  ramp_blend(blend_mode, a, factor, b);
89  results.set(i, a);
90  }
91 }
92 
93 static void do_mix_operation_color4f(const int blend_mode,
94  const FloatReadAttribute &factors,
95  const Color4fReadAttribute &inputs_a,
96  const Color4fReadAttribute &inputs_b,
97  Color4fWriteAttribute results)
98 {
99  const int size = results.size();
100  for (const int i : IndexRange(size)) {
101  const float factor = factors[i];
102  Color4f a = inputs_a[i];
103  const Color4f b = inputs_b[i];
104  ramp_blend(blend_mode, a, factor, b);
105  results.set(i, a);
106  }
107 }
108 
109 static void do_mix_operation(const CustomDataType result_type,
110  int blend_mode,
111  const FloatReadAttribute &attribute_factor,
112  const ReadAttribute &attribute_a,
113  const ReadAttribute &attribute_b,
114  WriteAttribute &attribute_result)
115 {
116  if (result_type == CD_PROP_FLOAT) {
118  blend_mode, attribute_factor, attribute_a, attribute_b, attribute_result);
119  }
120  else if (result_type == CD_PROP_FLOAT3) {
122  blend_mode, attribute_factor, attribute_a, attribute_b, attribute_result);
123  }
124  else if (result_type == CD_PROP_COLOR) {
126  blend_mode, attribute_factor, attribute_a, attribute_b, attribute_result);
127  }
128 }
129 
131  const GeoNodeExecParams &params,
132  StringRef result_name)
133 {
134  /* Use the domain of the result attribute if it already exists. */
135  ReadAttributePtr result_attribute = component.attribute_try_get_for_read(result_name);
136  if (result_attribute) {
137  return result_attribute->domain();
138  }
139 
140  /* Otherwise use the highest priority domain from existing input attributes, or the default. */
141  return params.get_highest_priority_input_domain({"A", "B"}, component, ATTR_DOMAIN_POINT);
142 }
143 
145 {
146  const bNode &node = params.node();
147  const NodeAttributeMix *node_storage = (const NodeAttributeMix *)node.storage;
148  const std::string result_name = params.get_input<std::string>("Result");
149 
150  /* Use the highest complexity data type among the inputs and outputs, that way the node will
151  * never "remove information". Use CD_PROP_BOOL as the lowest complexity data type, but in any
152  * real situation it won't be returned. */
154  params.get_input_attribute_data_type("A", component, CD_PROP_BOOL),
155  params.get_input_attribute_data_type("B", component, CD_PROP_BOOL),
156  params.get_input_attribute_data_type("Result", component, CD_PROP_BOOL),
157  });
158 
159  const AttributeDomain result_domain = get_result_domain(component, params, result_name);
160 
161  OutputAttributePtr attribute_result = component.attribute_try_get_for_output(
162  result_name, result_domain, result_type);
163  if (!attribute_result) {
164  return;
165  }
166 
167  FloatReadAttribute attribute_factor = params.get_input_attribute<float>(
168  "Factor", component, result_domain, 0.5f);
169  ReadAttributePtr attribute_a = params.get_input_attribute(
170  "A", component, result_domain, result_type, nullptr);
171  ReadAttributePtr attribute_b = params.get_input_attribute(
172  "B", component, result_domain, result_type, nullptr);
173 
174  do_mix_operation(result_type,
175  node_storage->blend_type,
176  attribute_factor,
177  *attribute_a,
178  *attribute_b,
179  *attribute_result);
180  attribute_result.save();
181 }
182 
184 {
185  GeometrySet geometry_set = params.extract_input<GeometrySet>("Geometry");
186 
187  geometry_set = geometry_set_realize_instances(geometry_set);
188 
189  if (geometry_set.has<MeshComponent>()) {
191  }
192  if (geometry_set.has<PointCloudComponent>()) {
194  }
195 
196  params.set_output("Geometry", geometry_set);
197 }
198 
200 {
202  "attribute mix node");
203  data->blend_type = MA_RAMP_BLEND;
204  data->input_type_factor = GEO_NODE_ATTRIBUTE_INPUT_FLOAT;
207  node->storage = data;
208 }
209 
211 {
212  NodeAttributeMix *node_storage = (NodeAttributeMix *)node->storage;
214  *node, "Factor", (GeometryNodeAttributeInputMode)node_storage->input_type_factor);
216  *node, "A", (GeometryNodeAttributeInputMode)node_storage->input_type_a);
218  *node, "B", (GeometryNodeAttributeInputMode)node_storage->input_type_b);
219 }
220 
221 } // namespace blender::nodes
222 
224 {
225  static bNodeType ntype;
226 
227  geo_node_type_base(&ntype, GEO_NODE_ATTRIBUTE_MIX, "Attribute Mix", NODE_CLASS_ATTRIBUTE, 0);
233  &ntype, "NodeAttributeMix", node_free_standard_storage, node_copy_standard_storage);
235  nodeRegisterType(&ntype);
236 }
AttributeDomain
Definition: BKE_attribute.h:41
@ ATTR_DOMAIN_POINT
Definition: BKE_attribute.h:43
General operations, lookup, etc. for materials.
void ramp_blend(int type, float r_col[3], const float fac, const float col[3])
Definition: material.c:1395
void node_type_socket_templates(struct bNodeType *ntype, struct bNodeSocketTemplate *inputs, struct bNodeSocketTemplate *outputs)
Definition: node.cc:4527
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4623
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 GEO_NODE_ATTRIBUTE_MIX
Definition: BKE_node.h:1388
#define NODE_CLASS_ATTRIBUTE
Definition: BKE_node.h:360
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1298
#define UNUSED(x)
#define IFACE_(msgid)
#define N_(msgid)
static uint8 component(Color32 c, uint i)
Definition: ColorBlock.cpp:126
CustomDataType
@ CD_PROP_FLOAT
@ CD_PROP_FLOAT3
@ CD_PROP_COLOR
@ CD_PROP_BOOL
#define MA_RAMP_BLEND
@ SOCK_VECTOR
@ SOCK_FLOAT
@ SOCK_GEOMETRY
@ SOCK_STRING
@ SOCK_RGBA
GeometryNodeAttributeInputMode
@ GEO_NODE_ATTRIBUTE_INPUT_ATTRIBUTE
@ GEO_NODE_ATTRIBUTE_INPUT_FLOAT
@ PROP_FACTOR
Definition: RNA_types.h:131
#define C
Definition: RandGen.cpp:39
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
OperationNode * node
bNodeTree * ntree
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static unsigned a[3]
Definition: RandGen.cpp:92
TypedReadAttribute< Color4f > Color4fReadAttribute
TypedWriteAttribute< float3 > Float3WriteAttribute
TypedWriteAttribute< Color4f > Color4fWriteAttribute
TypedReadAttribute< float > FloatReadAttribute
TypedReadAttribute< float3 > Float3ReadAttribute
GeometrySet geometry_set_realize_instances(const GeometrySet &geometry_set)
TypedWriteAttribute< float > FloatWriteAttribute
std::unique_ptr< ReadAttribute > ReadAttributePtr
CustomDataType attribute_data_type_highest_complexity(Span< CustomDataType > data_types)
static void do_mix_operation_float3(const int blend_mode, const FloatReadAttribute &factors, const Float3ReadAttribute &inputs_a, const Float3ReadAttribute &inputs_b, Float3WriteAttribute results)
void update_attribute_input_socket_availabilities(bNode &node, const StringRef name, const GeometryNodeAttributeInputMode mode, const bool name_is_available)
static void do_mix_operation_color4f(const int blend_mode, const FloatReadAttribute &factors, const Color4fReadAttribute &inputs_a, const Color4fReadAttribute &inputs_b, Color4fWriteAttribute results)
static void do_mix_operation(const CustomDataType result_type, int blend_mode, const FloatReadAttribute &attribute_factor, const ReadAttribute &attribute_a, const ReadAttribute &attribute_b, WriteAttribute &attribute_result)
static AttributeDomain get_result_domain(const GeometryComponent &component, StringRef source_name, StringRef result_name)
static void attribute_mix_calc(GeometryComponent &component, const GeoNodeExecParams &params)
static void geo_node_attribute_mix_init(bNodeTree *UNUSED(ntree), bNode *node)
static void geo_node_attribute_mix_update(bNodeTree *UNUSED(ntree), bNode *node)
static void geo_node_attribute_mix_exec(GeoNodeExecParams params)
static void do_mix_operation_float(const int blend_mode, const FloatReadAttribute &factors, const FloatReadAttribute &inputs_a, const FloatReadAttribute &inputs_b, FloatWriteAttribute results)
static bNodeSocketTemplate geo_node_attribute_mix_in[]
static bNodeSocketTemplate geo_node_mix_attribute_out[]
void register_node_type_geo_attribute_mix()
static void geo_node_attribute_mix_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
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