Blender  V3.3
node_geo_mesh_primitive_cylinder.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "DNA_mesh_types.h"
4 #include "DNA_meshdata_types.h"
5 
6 #include "BKE_material.h"
7 #include "BKE_mesh.h"
8 
9 #include "UI_interface.h"
10 #include "UI_resources.h"
11 
12 #include "node_geometry_util.hh"
13 
15 
17 
19 {
20  b.add_input<decl::Int>(N_("Vertices"))
21  .default_value(32)
22  .min(3)
23  .max(512)
24  .description(N_("The number of vertices on the top and bottom circles"));
25  b.add_input<decl::Int>(N_("Side Segments"))
26  .default_value(1)
27  .min(1)
28  .max(512)
29  .description(N_("The number of rectangular segments along each side"));
30  b.add_input<decl::Int>(N_("Fill Segments"))
31  .default_value(1)
32  .min(1)
33  .max(512)
34  .description(N_("The number of concentric rings used to fill the round faces"));
35  b.add_input<decl::Float>(N_("Radius"))
36  .default_value(1.0f)
37  .min(0.0f)
38  .subtype(PROP_DISTANCE)
39  .description(N_("The radius of the cylinder"));
40  b.add_input<decl::Float>(N_("Depth"))
41  .default_value(2.0f)
42  .min(0.0f)
43  .subtype(PROP_DISTANCE)
44  .description(N_("The height of the cylinder"));
45  b.add_output<decl::Geometry>(N_("Mesh"));
46  b.add_output<decl::Bool>(N_("Top")).field_source();
47  b.add_output<decl::Bool>(N_("Side")).field_source();
48  b.add_output<decl::Bool>(N_("Bottom")).field_source();
49 }
50 
51 static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
52 {
53  uiLayoutSetPropSep(layout, true);
54  uiLayoutSetPropDecorate(layout, false);
55  uiItemR(layout, ptr, "fill_type", 0, nullptr, ICON_NONE);
56 }
57 
59 {
60  NodeGeometryMeshCylinder *node_storage = MEM_cnew<NodeGeometryMeshCylinder>(__func__);
61 
63 
64  node->storage = node_storage;
65 }
66 
68 {
69  bNodeSocket *vertices_socket = (bNodeSocket *)node->inputs.first;
70  bNodeSocket *rings_socket = vertices_socket->next;
71  bNodeSocket *fill_subdiv_socket = rings_socket->next;
72 
73  const NodeGeometryMeshCylinder &storage = node_storage(*node);
75  const bool has_fill = fill != GEO_NODE_MESH_CIRCLE_FILL_NONE;
76  nodeSetSocketAvailability(ntree, fill_subdiv_socket, has_fill);
77 }
78 
80 {
81  const NodeGeometryMeshCylinder &storage = node_storage(params.node());
83 
84  const float radius = params.extract_input<float>("Radius");
85  const float depth = params.extract_input<float>("Depth");
86  const int circle_segments = params.extract_input<int>("Vertices");
87  if (circle_segments < 3) {
88  params.error_message_add(NodeWarningType::Info, TIP_("Vertices must be at least 3"));
89  params.set_default_remaining_outputs();
90  return;
91  }
92 
93  const int side_segments = params.extract_input<int>("Side Segments");
94  if (side_segments < 1) {
95  params.error_message_add(NodeWarningType::Info, TIP_("Side Segments must be at least 1"));
96  params.set_default_remaining_outputs();
97  return;
98  }
99 
100  const bool no_fill = fill == GEO_NODE_MESH_CIRCLE_FILL_NONE;
101  const int fill_segments = no_fill ? 1 : params.extract_input<int>("Fill Segments");
102  if (fill_segments < 1) {
103  params.error_message_add(NodeWarningType::Info, TIP_("Fill Segments must be at least 1"));
104  params.set_default_remaining_outputs();
105  return;
106  }
107 
108  ConeAttributeOutputs attribute_outputs;
109  if (params.output_is_required("Top")) {
110  attribute_outputs.top_id = StrongAnonymousAttributeID("top_selection");
111  }
112  if (params.output_is_required("Bottom")) {
113  attribute_outputs.bottom_id = StrongAnonymousAttributeID("bottom_selection");
114  }
115  if (params.output_is_required("Side")) {
116  attribute_outputs.side_id = StrongAnonymousAttributeID("side_selection");
117  }
118 
119  /* The cylinder is a special case of the cone mesh where the top and bottom radius are equal. */
121  radius,
122  depth,
123  circle_segments,
124  side_segments,
125  fill_segments,
126  fill,
127  attribute_outputs);
128 
129  if (attribute_outputs.top_id) {
130  params.set_output("Top",
131  AnonymousAttributeFieldInput::Create<bool>(
132  std::move(attribute_outputs.top_id), params.attribute_producer_name()));
133  }
134  if (attribute_outputs.bottom_id) {
135  params.set_output(
136  "Bottom",
137  AnonymousAttributeFieldInput::Create<bool>(std::move(attribute_outputs.bottom_id),
138  params.attribute_producer_name()));
139  }
140  if (attribute_outputs.side_id) {
141  params.set_output("Side",
142  AnonymousAttributeFieldInput::Create<bool>(
143  std::move(attribute_outputs.side_id), params.attribute_producer_name()));
144  }
145 
146  params.set_output("Mesh", GeometrySet::create_with_mesh(mesh));
147 }
148 
149 } // namespace blender::nodes::node_geo_mesh_primitive_cylinder_cc
150 
152 {
154 
155  static bNodeType ntype;
160  &ntype, "NodeGeometryMeshCylinder", node_free_standard_storage, node_copy_standard_storage);
164  nodeRegisterType(&ntype);
165 }
General operations, lookup, etc. for materials.
void node_type_update(struct bNodeType *ntype, void(*updatefunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4443
#define NODE_STORAGE_FUNCS(StorageT)
Definition: BKE_node.h:1563
void nodeSetSocketAvailability(struct bNodeTree *ntree, struct bNodeSocket *sock, bool is_available)
Definition: node.cc:3664
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4390
#define NODE_CLASS_GEOMETRY
Definition: BKE_node.h:359
#define GEO_NODE_MESH_PRIMITIVE_CYLINDER
Definition: BKE_node.h:1394
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:4426
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define UNUSED(x)
#define TIP_(msgid)
GeometryNodeMeshCircleFillType
@ GEO_NODE_MESH_CIRCLE_FILL_NGON
@ GEO_NODE_MESH_CIRCLE_FILL_NONE
in reality light always falls off quadratically Particle Info
@ PROP_DISTANCE
Definition: RNA_types.h:149
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)
OperationNode * node
bNodeTree * ntree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
OwnedAnonymousAttributeID< true > StrongAnonymousAttributeID
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
Mesh * create_cylinder_or_cone_mesh(float radius_top, float radius_bottom, float depth, int circle_segments, int side_segments, int fill_segments, GeometryNodeMeshCircleFillType fill_type, ConeAttributeOutputs &attribute_outputs)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void node_init(const struct bContext *C, bNodeTree *ntree, bNode *node)
Definition: node.cc:1082
void register_node_type_geo_mesh_primitive_cylinder()
void geo_node_type_base(bNodeType *ntype, int type, const char *name, short nclass)
void node_copy_standard_storage(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, const bNode *src_node)
Definition: node_util.c:55
void node_free_standard_storage(bNode *node)
Definition: node_util.c:43
static GeometrySet create_with_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
struct bNodeSocket * next
Defines a node type.
Definition: BKE_node.h:226
NodeGeometryExecFunction geometry_node_execute
Definition: BKE_node.h:316
void(* draw_buttons)(struct uiLayout *, struct bContext *C, struct PointerRNA *ptr)
Definition: BKE_node.h:244
NodeDeclareFunction declare
Definition: BKE_node.h:324
StrongAnonymousAttributeID bottom_id
StrongAnonymousAttributeID side_id
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480