Blender  V3.3
node_geo_collection_info.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include "BLI_math_matrix.h"
4 
5 #include "DNA_collection_types.h"
6 
7 #include "UI_interface.h"
8 #include "UI_resources.h"
9 
10 #include "BKE_collection.h"
11 
12 #include "node_geometry_util.hh"
13 
14 #include <algorithm>
15 
17 
19 
21 {
22  b.add_input<decl::Collection>(N_("Collection")).hide_label();
23  b.add_input<decl::Bool>(N_("Separate Children"))
24  .description(
25  N_("Output each child of the collection as a separate instance, sorted alphabetically"));
26  b.add_input<decl::Bool>(N_("Reset Children"))
27  .description(
28  N_("Reset the transforms of every child instance in the output. Only used when Separate "
29  "Children is enabled"));
30  b.add_output<decl::Geometry>(N_("Geometry"));
31 }
32 
33 static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
34 {
35  uiItemR(layout, ptr, "transform_space", UI_ITEM_R_EXPAND, nullptr, ICON_NONE);
36 }
37 
39 {
40  NodeGeometryCollectionInfo *data = MEM_cnew<NodeGeometryCollectionInfo>(__func__);
41  data->transform_space = GEO_NODE_TRANSFORM_SPACE_ORIGINAL;
42  node->storage = data;
43 }
44 
46  int handle;
47  char *name;
49 };
50 
52 {
53  Collection *collection = params.get_input<Collection *>("Collection");
54 
55  if (collection == nullptr) {
56  params.set_default_remaining_outputs();
57  return;
58  }
59  const Object *self_object = params.self_object();
60  const bool is_recursive = BKE_collection_has_object_recursive_instanced(collection,
61  (Object *)self_object);
62  if (is_recursive) {
63  params.error_message_add(NodeWarningType::Error, "Collection contains current object");
64  params.set_default_remaining_outputs();
65  return;
66  }
67 
68  const NodeGeometryCollectionInfo &storage = node_storage(params.node());
69  const bool use_relative_transform = (storage.transform_space ==
71 
72  GeometrySet geometry_set_out;
73  InstancesComponent &instances = geometry_set_out.get_component_for_write<InstancesComponent>();
74 
75  const bool separate_children = params.get_input<bool>("Separate Children");
76  if (separate_children) {
77  const bool reset_children = params.get_input<bool>("Reset Children");
78  Vector<Collection *> children_collections;
79  LISTBASE_FOREACH (CollectionChild *, collection_child, &collection->children) {
80  children_collections.append(collection_child->collection);
81  }
82  Vector<Object *> children_objects;
83  LISTBASE_FOREACH (CollectionObject *, collection_object, &collection->gobject) {
84  children_objects.append(collection_object->ob);
85  }
86 
87  instances.reserve(children_collections.size() + children_objects.size());
89  entries.reserve(children_collections.size() + children_objects.size());
90 
91  for (Collection *child_collection : children_collections) {
93  if (!reset_children) {
94  add_v3_v3(transform.values[3], child_collection->instance_offset);
95  if (use_relative_transform) {
96  mul_m4_m4_pre(transform.values, self_object->imat);
97  }
98  else {
99  sub_v3_v3(transform.values[3], collection->instance_offset);
100  }
101  }
102  const int handle = instances.add_reference(*child_collection);
103  entries.append({handle, &(child_collection->id.name[2]), transform});
104  }
105  for (Object *child_object : children_objects) {
106  const int handle = instances.add_reference(*child_object);
108  if (!reset_children) {
109  if (use_relative_transform) {
110  transform = self_object->imat;
111  }
112  else {
113  sub_v3_v3(transform.values[3], collection->instance_offset);
114  }
115  mul_m4_m4_post(transform.values, child_object->obmat);
116  }
117  entries.append({handle, &(child_object->id.name[2]), transform});
118  }
119 
120  std::sort(entries.begin(),
121  entries.end(),
122  [](const InstanceListEntry &a, const InstanceListEntry &b) {
123  return BLI_strcasecmp_natural(a.name, b.name) < 0;
124  });
125  for (const InstanceListEntry &entry : entries) {
126  instances.add_instance(entry.handle, entry.transform);
127  }
128  }
129  else {
131  if (use_relative_transform) {
132  copy_v3_v3(transform.values[3], collection->instance_offset);
133  mul_m4_m4_pre(transform.values, self_object->imat);
134  }
135 
136  const int handle = instances.add_reference(*collection);
137  instances.add_instance(handle, transform);
138  }
139 
140  params.set_output("Geometry", geometry_set_out);
141 }
142 
143 } // namespace blender::nodes::node_geo_collection_info_cc
144 
146 {
148 
149  static bNodeType ntype;
150 
151  geo_node_type_base(&ntype, GEO_NODE_COLLECTION_INFO, "Collection Info", NODE_CLASS_INPUT);
154  node_type_storage(&ntype,
155  "NodeGeometryCollectionInfo",
160  nodeRegisterType(&ntype);
161 }
bool BKE_collection_has_object_recursive_instanced(struct Collection *collection, struct Object *ob)
Definition: collection.c:931
#define NODE_STORAGE_FUNCS(StorageT)
Definition: BKE_node.h:1563
void node_type_init(struct bNodeType *ntype, void(*initfunc)(struct bNodeTree *ntree, struct bNode *node))
Definition: node.cc:4390
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
#define NODE_CLASS_INPUT
Definition: BKE_node.h:345
#define GEO_NODE_COLLECTION_INFO
Definition: BKE_node.h:1388
void nodeRegisterType(struct bNodeType *ntype)
Definition: node.cc:1357
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
void mul_m4_m4_pre(float R[4][4], const float A[4][4])
Definition: math_matrix.c:372
void mul_m4_m4_post(float R[4][4], const float B[4][4])
Definition: math_matrix.c:380
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
#define UNUSED(x)
Object groups, one object can be in many groups at once.
@ GEO_NODE_TRANSFORM_SPACE_RELATIVE
@ GEO_NODE_TRANSFORM_SPACE_ORIGINAL
@ UI_ITEM_R_EXPAND
void uiItemR(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int flag, const char *name, int icon)
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
void sort(btMatrix3x3 &U, btVector3 &sigma, btMatrix3x3 &V, int t)
Helper function of 3X3 SVD for sorting singular values.
int add_reference(const InstanceReference &reference)
void add_instance(int instance_handle, const blender::float4x4 &transform)
void reserve(int min_capacity)
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
void reserve(const int64_t min_capacity)
Definition: BLI_vector.hh:340
OperationNode * node
void * tree
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
static unsigned a[3]
Definition: RandGen.cpp:78
static void node_declare(NodeDeclarationBuilder &b)
static void node_node_init(bNodeTree *UNUSED(tree), bNode *node)
static void node_layout(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
static void node_geo_exec(GeoNodeExecParams params)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
void register_node_type_geo_collection_info()
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
float instance_offset[3]
GeometryComponent & get_component_for_write(GeometryComponentType component_type)
float imat[4][4]
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
static float4x4 identity()
Definition: BLI_float4x4.hh:80
#define N_(msgid)
PointerRNA * ptr
Definition: wm_files.c:3480