Blender V5.0
node_geo_mesh_primitive_line.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
6
7#include "BKE_material.hh"
8
9#include "NOD_rna_define.hh"
10
11#include "RNA_access.hh"
12
14#include "UI_resources.hh"
15
17
19
20#include "node_geometry_util.hh"
21
23
25
27{
28 b.add_input<decl::Int>("Count").default_value(10).min(1).max(10000).description(
29 "Number of vertices on the line");
30 b.add_input<decl::Float>("Resolution")
31 .default_value(1.0f)
32 .min(0.1f)
33 .subtype(PROP_DISTANCE)
34 .description("Length of each individual edge");
35 b.add_input<decl::Vector>("Start Location")
37 .description("Position of the first vertex");
38 b.add_input<decl::Vector>("Offset")
39 .default_value({0.0f, 0.0f, 1.0f})
40 .subtype(PROP_TRANSLATION)
41 .description(
42 "In offset mode, the distance between each socket on each axis. In end points mode, the "
43 "position of the final vertex");
44 b.add_output<decl::Geometry>("Mesh");
45}
46
47static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
48{
49 layout->use_property_split_set(true);
50 layout->use_property_decorate_set(false);
51 layout->prop(ptr, "mode", UI_ITEM_NONE, "", ICON_NONE);
53 layout->prop(ptr, "count_mode", UI_ITEM_NONE, "", ICON_NONE);
54 }
55}
56
57static void node_init(bNodeTree * /*tree*/, bNode *node)
58{
60
63
64 node->storage = node_storage;
65}
66
67static void node_update(bNodeTree *ntree, bNode *node)
68{
69 bNodeSocket *count_socket = static_cast<bNodeSocket *>(node->inputs.first);
70 bNodeSocket *resolution_socket = count_socket->next;
71 bNodeSocket *start_socket = resolution_socket->next;
72 bNodeSocket *end_and_offset_socket = start_socket->next;
73
74 const NodeGeometryMeshLine &storage = node_storage(*node);
77 storage.count_mode;
78
79 node_sock_label(end_and_offset_socket,
80 (mode == GEO_NODE_MESH_LINE_MODE_END_POINTS) ? N_("End Location") :
81 N_("Offset"));
82
84 *resolution_socket,
88 *count_socket,
90 count_mode == GEO_NODE_MESH_LINE_COUNT_TOTAL);
91}
92
94{
95 const NodeDeclaration &declaration = *params.node_type().static_declaration;
96 if (params.in_out() == SOCK_OUT) {
98 return;
99 }
100 if (params.node_tree().typeinfo->validate_link(eNodeSocketDatatype(params.other_socket().type),
101 SOCK_FLOAT))
102 {
103 params.add_item(IFACE_("Count"), [](LinkSearchOpParams &params) {
104 bNode &node = params.add_node("GeometryNodeMeshLine");
105 node_storage(node).mode = GEO_NODE_MESH_LINE_MODE_OFFSET;
106 params.connect_available_socket(node, "Count");
107 });
108 params.add_item(IFACE_("Resolution"), [](LinkSearchOpParams &params) {
109 bNode &node = params.add_node("GeometryNodeMeshLine");
110 node_storage(node).mode = GEO_NODE_MESH_LINE_MODE_OFFSET;
111 node_storage(node).count_mode = GEO_NODE_MESH_LINE_COUNT_RESOLUTION;
112 params.connect_available_socket(node, "Resolution");
113 });
114 params.add_item(IFACE_("Start Location"), [](LinkSearchOpParams &params) {
115 bNode &node = params.add_node("GeometryNodeMeshLine");
116 params.connect_available_socket(node, "Start Location");
117 });
118 params.add_item(IFACE_("Offset"), [](LinkSearchOpParams &params) {
119 bNode &node = params.add_node("GeometryNodeMeshLine");
120 params.connect_available_socket(node, "Offset");
121 });
122 /* The last socket is reused in end points mode. */
123 params.add_item(IFACE_("End Location"), [](LinkSearchOpParams &params) {
124 bNode &node = params.add_node("GeometryNodeMeshLine");
125 node_storage(node).mode = GEO_NODE_MESH_LINE_MODE_END_POINTS;
126 params.connect_available_socket(node, "Offset");
127 });
128 }
129}
130
132{
133 const NodeGeometryMeshLine &storage = node_storage(params.node());
136 storage.count_mode;
137
138 Mesh *mesh = nullptr;
139 const float3 start = params.extract_input<float3>("Start Location");
141 /* The label switches to "End Location", but the same socket is used. */
142 const float3 end = params.extract_input<float3>("Offset");
143 const float3 total_delta = end - start;
144
145 if (count_mode == GEO_NODE_MESH_LINE_COUNT_RESOLUTION) {
146 /* Don't allow asymptotic count increase for low resolution values. */
147 const float resolution = std::max(params.extract_input<float>("Resolution"), 0.0001f);
148 const int count = math::length(total_delta) / resolution + 1;
149 const float3 delta = math::normalize(total_delta) * resolution;
150 mesh = geometry::create_line_mesh(start, delta, count);
151 }
152 else if (count_mode == GEO_NODE_MESH_LINE_COUNT_TOTAL) {
153 const int count = params.extract_input<int>("Count");
154 if (count == 1) {
155 mesh = geometry::create_line_mesh(start, float3(0), count);
156 }
157 else {
158 const float3 delta = total_delta / float(count - 1);
159 mesh = geometry::create_line_mesh(start, delta, count);
160 }
161 }
162 }
163 else if (mode == GEO_NODE_MESH_LINE_MODE_OFFSET) {
164 const float3 delta = params.extract_input<float3>("Offset");
165 const int count = params.extract_input<int>("Count");
166 mesh = geometry::create_line_mesh(start, delta, count);
167 }
168
169 if (mesh) {
170 BKE_id_material_eval_ensure_default_slot(reinterpret_cast<ID *>(mesh));
171 }
172
173 params.set_output("Mesh", GeometrySet::from_mesh(mesh));
174}
175
176static void node_rna(StructRNA *srna)
177{
178 static EnumPropertyItem mode_items[] = {
180 "OFFSET",
181 0,
182 "Offset",
183 "Specify the offset from one vertex to the next"},
185 "END_POINTS",
186 0,
187 "End Points",
188 "Specify the line's start and end points"},
189 {0, nullptr, 0, nullptr, nullptr},
190 };
191
192 static EnumPropertyItem count_mode_items[] = {
194 "TOTAL",
195 0,
196 "Count",
197 "Specify the total number of vertices"},
199 "RESOLUTION",
200 0,
201 "Resolution",
202 "Specify the distance between vertices"},
203 {0, nullptr, 0, nullptr, nullptr},
204 };
205
207 "mode",
208 "Mode",
209 "",
210 mode_items,
213
215 "count_mode",
216 "Count Mode",
217 "",
218 count_mode_items,
219 NOD_storage_enum_accessors(count_mode),
221}
222
223static void node_register()
224{
225 static blender::bke::bNodeType ntype;
226
227 geo_node_type_base(&ntype, "GeometryNodeMeshLine", GEO_NODE_MESH_PRIMITIVE_LINE);
228 ntype.ui_name = "Mesh Line";
229 ntype.ui_description = "Generate vertices in a line and connect them with edges";
230 ntype.enum_name_legacy = "MESH_PRIMITIVE_LINE";
232 ntype.declare = node_declare;
233 ntype.initfunc = node_init;
235 ntype, "NodeGeometryMeshLine", node_free_standard_storage, node_copy_standard_storage);
238 ntype.updatefunc = node_update;
241
242 node_rna(ntype.rna_ext.srna);
243}
245
246} // namespace blender::nodes::node_geo_mesh_primitive_line_cc
General operations, lookup, etc. for materials.
void BKE_id_material_eval_ensure_default_slot(ID *id)
#define NODE_STORAGE_FUNCS(StorageT)
Definition BKE_node.hh:1240
#define NODE_CLASS_GEOMETRY
Definition BKE_node.hh:461
#define GEO_NODE_MESH_PRIMITIVE_LINE
#define IFACE_(msgid)
GeometryNodeMeshLineCountMode
@ GEO_NODE_MESH_LINE_COUNT_RESOLUTION
@ GEO_NODE_MESH_LINE_COUNT_TOTAL
@ SOCK_OUT
GeometryNodeMeshLineMode
@ GEO_NODE_MESH_LINE_MODE_END_POINTS
@ GEO_NODE_MESH_LINE_MODE_OFFSET
eNodeSocketDatatype
@ SOCK_FLOAT
#define NOD_REGISTER_NODE(REGISTER_FUNC)
#define NOD_storage_enum_accessors(member)
@ PROP_DISTANCE
Definition RNA_types.hh:256
@ PROP_TRANSLATION
Definition RNA_types.hh:261
#define UI_ITEM_NONE
Vector< SocketDeclaration * > outputs
nullptr float
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
int count
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void node_register_type(bNodeType &ntype)
Definition node.cc:2416
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
Definition node.cc:4739
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5414
Mesh * create_line_mesh(float3 start, float3 delta, int count)
T length(const VecBase< T, Size > &a)
MatBase< T, NumCol, NumRow > normalize(const MatBase< T, NumCol, NumRow > &a)
static void node_update(bNodeTree *ntree, bNode *node)
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
static void node_layout(uiLayout *layout, bContext *, PointerRNA *ptr)
void search_link_ops_for_declarations(GatherLinkSearchOpParams &params, Span< SocketDeclaration * > declarations)
PropertyRNA * RNA_def_node_enum(StructRNA *srna, const char *identifier, const char *ui_name, const char *ui_description, const EnumPropertyItem *static_items, const EnumRNAAccessors accessors, std::optional< int > default_value, const EnumPropertyItemFunc item_func, const bool allow_animation)
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_sock_label(bNodeSocket *sock, const char *name)
Definition node_util.cc:73
void node_free_standard_storage(bNode *node)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
int RNA_enum_get(PointerRNA *ptr, const char *name)
#define min(a, b)
Definition sort.cc:36
StructRNA * srna
Definition DNA_ID.h:414
void * first
struct bNodeSocket * next
ListBase inputs
void * storage
Defines a node type.
Definition BKE_node.hh:238
std::string ui_description
Definition BKE_node.hh:244
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:289
NodeGeometryExecFunction geometry_node_execute
Definition BKE_node.hh:354
const char * enum_name_legacy
Definition BKE_node.hh:247
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:259
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:378
NodeDeclareFunction declare
Definition BKE_node.hh:362
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:281
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
void use_property_decorate_set(bool is_sep)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
max
Definition text_draw.cc:251
#define N_(msgid)
PointerRNA * ptr
Definition wm_files.cc:4238