Blender V5.0
node_group_operator.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
8
9#include "BLI_array_utils.hh"
10#include "BLI_index_mask.hh"
11#include "BLI_listbase.h"
12#include "BLI_path_utils.hh"
13#include "BLI_rect.h"
14#include "BLI_string_utf8.h"
15
16#include "DNA_key_types.h"
17#include "ED_curves.hh"
18#include "ED_grease_pencil.hh"
19#include "ED_object.hh"
20#include "ED_screen.hh"
21#include "ED_select_utils.hh"
22#include "ED_view3d.hh"
23
24#include "WM_api.hh"
25
26#include "BKE_asset.hh"
29#include "BKE_context.hh"
30#include "BKE_curves.hh"
31#include "BKE_customdata.hh"
32#include "BKE_editmesh.hh"
33#include "BKE_geometry_set.hh"
34#include "BKE_grease_pencil.hh"
35#include "BKE_layer.hh"
36#include "BKE_lib_id.hh"
37#include "BKE_lib_query.hh"
38#include "BKE_main.hh"
39#include "BKE_material.hh"
40#include "BKE_mesh.hh"
41#include "BKE_mesh_wrapper.hh"
42#include "BKE_node_runtime.hh"
43#include "BKE_object.hh"
44#include "BKE_paint.hh"
45#include "BKE_paint_bvh.hh"
46#include "BKE_pointcloud.hh"
47#include "BKE_report.hh"
48#include "BKE_scene.hh"
49#include "BKE_screen.hh"
50#include "BKE_workspace.hh"
51
52#include "DNA_object_types.h"
53#include "DNA_scene_types.h"
54
55#include "DEG_depsgraph.hh"
58
59#include "RNA_access.hh"
60#include "RNA_define.hh"
61
63#include "UI_resources.hh"
64
65#include "ED_asset.hh"
67#include "ED_geometry.hh"
68#include "ED_mesh.hh"
69#include "ED_sculpt.hh"
70
71#include "BLT_translation.hh"
72
78
79#include "AS_asset_catalog.hh"
82#include "AS_asset_library.hh"
84
85#include "geometry_intern.hh"
86
87#include <fmt/format.h>
88
90
91namespace blender::ed::geometry {
92
93/* -------------------------------------------------------------------- */
96
99 ReportList *reports)
100{
101 Main &bmain = *CTX_data_main(&C);
102 if (bNodeTree *group = reinterpret_cast<bNodeTree *>(
104 {
105 return group;
106 }
107
110 if (!asset) {
111 return nullptr;
112 }
113 return reinterpret_cast<bNodeTree *>(asset::asset_local_id_ensure_imported(bmain, *asset));
114}
115
116static const bNodeTree *get_node_group(const bContext &C, PointerRNA &ptr, ReportList *reports)
117{
118 const bNodeTree *group = get_asset_or_local_node_group(C, ptr, reports);
119 if (!group) {
120 return nullptr;
121 }
122 if (group->type != NTREE_GEOMETRY) {
123 if (reports) {
124 BKE_report(reports, RPT_ERROR, "Asset is not a geometry node group");
125 }
126 return nullptr;
127 }
128 return group;
129}
130
132
139{
140 static GeoOperatorLog log;
141 return log;
142}
143
148
150static void find_socket_log_contexts(const Main &bmain,
151 Set<ComputeContextHash> &r_socket_log_contexts)
152{
153 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain.wm.first);
154 if (wm == nullptr) {
155 return;
156 }
157 LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) {
158 const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
159 LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
160 const SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
161 if (sl->spacetype == SPACE_NODE) {
162 const SpaceNode &snode = *reinterpret_cast<const SpaceNode *>(sl);
163 if (snode.edittree == nullptr) {
164 continue;
165 }
167 continue;
168 }
169 bke::ComputeContextCache compute_context_cache;
172 compute_context_cache);
173 for (const ComputeContextHash &hash : hash_by_zone.values()) {
174 r_socket_log_contexts.add(hash);
175 }
176 }
177 }
178 }
179}
180
182{
183 const int layer_index = CustomData_get_layer_index(&mesh.vert_data, CD_MDEFORMVERT);
184 if (layer_index == -1) {
185 return nullptr;
186 }
187 return mesh.vert_data.layers[layer_index].sharing_info;
188}
189
196 VectorSet<ImplicitSharingPtr<>> sharing_infos_;
197
198 public:
200 {
201 if (mesh.runtime->face_offsets_sharing_info) {
202 this->freeze_shared_state(*mesh.runtime->face_offsets_sharing_info);
203 }
204 mesh.attributes().foreach_attribute([&](const bke::AttributeIter &iter) {
205 const bke::GAttributeReader attribute = iter.get();
206 if (attribute.varray.size() == 0) {
207 return;
208 }
209 if (attribute.sharing_info) {
210 this->freeze_shared_state(*attribute.sharing_info);
211 }
212 });
213 if (const ImplicitSharingInfo *sharing_info = get_vertex_group_sharing_info(mesh)) {
214 this->freeze_shared_state(*sharing_info);
215 }
216 }
217
218 void freeze_shared_state(const ImplicitSharingInfo &sharing_info)
219 {
220 if (sharing_infos_.add(ImplicitSharingPtr<>{&sharing_info})) {
221 sharing_info.add_user();
222 }
223 }
224};
225
226static std::string shape_key_attribute_name(const KeyBlock &kb)
227{
228 return fmt::format(".kb:{}", kb.name);
229}
230
232static void add_shape_keys_as_attributes(Mesh &mesh, const Key &key)
233{
234 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
235 LISTBASE_FOREACH (const KeyBlock *, kb, &key.block) {
236 if (kb == key.refkey) {
237 /* The basis key will just receive values from the mesh positions. */
238 continue;
239 }
240 const Span<float3> key_data(static_cast<float3 *>(kb->data), kb->totelem);
241 attributes.add<float3>(shape_key_attribute_name(*kb),
244 }
245}
246
247/* Copy shape key attributes back to the key data-block. */
249{
250 const bke::AttributeAccessor attributes = mesh.attributes();
251 LISTBASE_FOREACH (KeyBlock *, kb, &key.block) {
252 const VArray attr = *attributes.lookup<float3>(shape_key_attribute_name(*kb),
254 if (!attr) {
255 continue;
256 }
257 MEM_freeN(kb->data);
258 kb->data = MEM_malloc_arrayN(attr.size(), sizeof(float3), __func__);
259 kb->totelem = attr.size();
260 attr.materialize({static_cast<float3 *>(kb->data), attr.size()});
261 }
262 if (KeyBlock *kb = key.refkey) {
263 const Span<float3> positions = mesh.vert_positions();
264 MEM_freeN(kb->data);
265 kb->data = MEM_malloc_arrayN(positions.size(), sizeof(float3), __func__);
266 kb->totelem = positions.size();
267 array_utils::copy(positions, MutableSpan(static_cast<float3 *>(kb->data), positions.size()));
268 }
269}
270
271static void remove_shape_key_attributes(Mesh &mesh, const Key &key)
272{
273 bke::MutableAttributeAccessor attributes = mesh.attributes_for_write();
274 LISTBASE_FOREACH (KeyBlock *, kb, &key.block) {
275 attributes.remove(shape_key_attribute_name(*kb));
276 }
277}
278
286 Object &object,
287 nodes::GeoNodesOperatorData &operator_data,
288 Vector<MeshState> &orig_mesh_states)
289{
290 switch (object.type) {
291 case OB_CURVES: {
292 Curves *curves = BKE_curves_copy_for_eval(static_cast<const Curves *>(object.data));
294 }
295 case OB_POINTCLOUD: {
297 static_cast<const PointCloud *>(object.data));
299 }
300 case OB_MESH: {
301 Mesh *mesh = static_cast<Mesh *>(object.data);
302
303 if (std::shared_ptr<BMEditMesh> &em = mesh->runtime->edit_mesh) {
305 operator_data.active_edge_index = BM_mesh_active_edge_index_get(em->bm);
306 operator_data.active_face_index = BM_mesh_active_face_index_get(em->bm, false, true);
307 EDBM_mesh_load_ex(DEG_get_bmain(&depsgraph), &object, true);
308 EDBM_mesh_free_data(mesh->runtime->edit_mesh.get());
309 em->bm = nullptr;
310 }
311
312 if (bke::pbvh::Tree *pbvh = bke::object::pbvh_get(object)) {
313 /* Currently many sculpt mode operations do not tag normals dirty (see use of
314 * #Mesh::tag_positions_changed_no_normals()), so access within geometry nodes cannot
315 * know that normals are out of date and recalculate them. Update them here instead. */
316 bke::pbvh::update_normals(depsgraph, object, *pbvh);
317 }
318
319 if (Key *key = mesh->key) {
320 /* Add the shape key attributes to the original mesh before the evaluated copy. Applying
321 * the result of the operator in sculpt mode uses the attributes on the original mesh to
322 * detect which changes. */
324 }
325
326 Mesh *mesh_copy = BKE_mesh_copy_for_eval(*mesh);
327 orig_mesh_states.append_as(*mesh_copy);
328 return bke::GeometrySet::from_mesh(mesh_copy);
329 }
330 case OB_GREASE_PENCIL: {
331 const GreasePencil *grease_pencil = static_cast<const GreasePencil *>(object.data);
332 if (const bke::greasepencil::Layer *active_layer = grease_pencil->get_active_layer()) {
333 operator_data.active_layer_index = *grease_pencil->get_layer_index(*active_layer);
334 }
335 GreasePencil *grease_pencil_copy = BKE_grease_pencil_copy_for_eval(grease_pencil);
336 grease_pencil_copy->runtime->eval_frame = int(DEG_get_ctime(&depsgraph));
337 return bke::GeometrySet::from_grease_pencil(grease_pencil_copy);
338 }
339 default:
340 return {};
341 }
342}
343
345 const wmOperator &op,
346 const Depsgraph &depsgraph,
347 Main &bmain,
348 Scene &scene,
349 Object &object,
350 const RegionView3D *rv3d,
352{
353 geometry.ensure_owns_direct_data();
354 switch (object.type) {
355 case OB_CURVES: {
356 Curves &curves = *static_cast<Curves *>(object.data);
357 Curves *new_curves = geometry.get_curves_for_write();
358 if (!new_curves) {
359 curves.geometry.wrap() = {};
360 break;
361 }
362
363 /* Anonymous attributes shouldn't be available on the applied geometry. */
364 new_curves->geometry.wrap().attributes_for_write().remove_anonymous();
365
366 curves.geometry.wrap() = std::move(new_curves->geometry.wrap());
367 BKE_object_material_from_eval_data(&bmain, &object, &new_curves->id);
369 break;
370 }
371 case OB_POINTCLOUD: {
372 PointCloud &points = *static_cast<PointCloud *>(object.data);
373 PointCloud *new_points =
374 geometry.get_component_for_write<bke::PointCloudComponent>().release();
375 if (!new_points) {
376 new_points->attribute_storage.wrap() = {};
377 points.totpoint = 0;
378 break;
379 }
380
381 /* Anonymous attributes shouldn't be available on the applied geometry. */
382 new_points->attributes_for_write().remove_anonymous();
383
384 BKE_object_material_from_eval_data(&bmain, &object, &new_points->id);
385 BKE_pointcloud_nomain_to_pointcloud(new_points, &points);
387 break;
388 }
389 case OB_MESH: {
390 Mesh &mesh = *static_cast<Mesh *>(object.data);
391
392 Mesh *new_mesh = geometry.get_component_for_write<bke::MeshComponent>().release();
393 if (new_mesh) {
394 /* Anonymous attributes shouldn't be available on the applied geometry. */
395 new_mesh->attributes_for_write().remove_anonymous();
396 BKE_object_material_from_eval_data(&bmain, &object, &new_mesh->id);
397 }
398 else {
399 new_mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
400 }
401
402 if (Key *key = mesh.key) {
403 /* Copy the evaluated shape key attributes back to the key data-block. */
404 store_attributes_to_shape_keys(*new_mesh, *key);
405 }
406
407 if (object.mode == OB_MODE_SCULPT) {
408 sculpt_paint::store_mesh_from_eval(op, scene, depsgraph, rv3d, object, new_mesh);
409 if (Key *key = mesh.key) {
410 /* Make sure to free the shape key attributes after `sculpt_paint::store_mesh_from_eval`
411 * because that uses the attributes to detect changes, for a critical performance
412 * optimization when only changing specific attributes. */
414 }
415 }
416 else {
417 if (Key *key = mesh.key) {
418 /* Make sure to free the attributes before converting to #BMesh for edit mode; removing
419 * attributes on #BMesh requires reallocating the dynamic AoS storage. */
420 remove_shape_key_attributes(*new_mesh, *key);
421 }
422 if (object.mode == OB_MODE_EDIT) {
423 EDBM_mesh_make_from_mesh(&object, new_mesh, scene.toolsettings->selectmode, true);
424 BKE_editmesh_looptris_and_normals_calc(mesh.runtime->edit_mesh.get());
425 BKE_id_free(nullptr, new_mesh);
427 }
428 else {
429 BKE_mesh_nomain_to_mesh(new_mesh, &mesh, &object, false);
431 }
432 }
433
434 break;
435 }
436 case OB_GREASE_PENCIL: {
437 const int eval_frame = int(DEG_get_ctime(&depsgraph));
438
439 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
440 Vector<int> editable_layer_indices;
441 for (const int layer_i : grease_pencil.layers().index_range()) {
442 const bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
443 if (!layer.is_editable()) {
444 continue;
445 }
446 editable_layer_indices.append(layer_i);
447 }
448
449 bool inserted_new_keyframe = false;
450 for (const int layer_i : editable_layer_indices) {
451 bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
452 /* TODO: For now, we always create a blank keyframe, but it might be good to expose this as
453 * an option and allow to duplicate the previous key. */
454 const bool duplicate_previous_key = false;
456 scene, grease_pencil, layer, duplicate_previous_key, inserted_new_keyframe);
457 }
458 GreasePencil *new_grease_pencil =
459 geometry.get_component_for_write<bke::GreasePencilComponent>().get_for_write();
460 if (!new_grease_pencil) {
461 /* Clear the Grease Pencil geometry. */
462 for (const int layer_i : editable_layer_indices) {
463 bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
464 if (bke::greasepencil::Drawing *drawing_orig = grease_pencil.get_drawing_at(layer,
465 eval_frame))
466 {
467 drawing_orig->strokes_for_write() = {};
468 drawing_orig->tag_topology_changed();
469 }
470 }
471 }
472 else {
473 IndexMaskMemory memory;
474 const IndexMask editable_layers = IndexMask::from_indices(editable_layer_indices.as_span(),
475 memory);
477 *new_grease_pencil, eval_frame, editable_layers, grease_pencil);
478
479 /* There might be layers with empty names after evaluation. Make sure to rename them. */
481 BKE_object_material_from_eval_data(&bmain, &object, &new_grease_pencil->id);
482 }
483
484 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
485 if (inserted_new_keyframe) {
487 }
488 }
489 }
490}
491
497static void gather_node_group_ids(const bNodeTree &node_tree, Set<ID *> &ids)
498{
499 const int orig_size = ids.size();
500 BLI_assert(node_tree.runtime->geometry_nodes_eval_dependencies);
501 for (ID *id : node_tree.runtime->geometry_nodes_eval_dependencies->ids.values()) {
502 ids.add(id);
503 }
504 if (ids.size() != orig_size) {
505 /* Only evaluate the node group if it references data-blocks. In that case it needs to be
506 * evaluated so that ID pointers are switched to point to evaluated data-blocks. */
507 ids.add(const_cast<ID *>(&node_tree.id));
508 }
509}
510
512 const StringRef identifier)
513{
514 for (const bNodeTreeInterfaceSocket *input : node_group.interface_inputs()) {
515 if (input->identifier == identifier) {
516 return input;
517 }
518 }
519 return nullptr;
520}
521
522static std::optional<ID_Type> socket_type_to_id_type(const eNodeSocketDatatype socket_type)
523{
524 switch (socket_type) {
525 case SOCK_CUSTOM:
526 case SOCK_FLOAT:
527 case SOCK_VECTOR:
528 case SOCK_RGBA:
529 case SOCK_SHADER:
530 case SOCK_BOOLEAN:
531 case SOCK_INT:
532 case SOCK_STRING:
533 case SOCK_GEOMETRY:
534 case SOCK_ROTATION:
535 case SOCK_MENU:
536 case SOCK_MATRIX:
537 case SOCK_BUNDLE:
538 case SOCK_CLOSURE:
539 return std::nullopt;
540 case SOCK_OBJECT:
541 return ID_OB;
542 case SOCK_IMAGE:
543 return ID_IM;
544 case SOCK_COLLECTION:
545 return ID_GR;
546 case SOCK_TEXTURE:
547 return ID_TE;
548 case SOCK_MATERIAL:
549 return ID_MA;
550 }
551 return std::nullopt;
552}
553
560 const bNodeTree &node_group,
561 const IDProperty &properties)
562{
565 &const_cast<IDProperty &>(properties), IDP_TYPE_FILTER_STRING, [&](IDProperty *prop) {
567 prop->name);
568 if (!input) {
569 return;
570 }
571 const std::optional<ID_Type> id_type = socket_type_to_id_type(
572 input->socket_typeinfo()->type);
573 if (!id_type) {
574 return;
575 }
576 const char *id_name = IDP_string_get(prop);
577 ID *id = BKE_libblock_find_name(&const_cast<Main &>(bmain), *id_type, id_name);
578 if (!id) {
579 return;
580 }
581 ids.add(prop->name, id);
582 });
583 return ids;
584}
585
586static Depsgraph *build_extra_depsgraph(const Depsgraph &depsgraph_active, const Set<ID *> &ids)
587{
588 Depsgraph *depsgraph = DEG_graph_new(DEG_get_bmain(&depsgraph_active),
589 DEG_get_input_scene(&depsgraph_active),
590 DEG_get_input_view_layer(&depsgraph_active),
591 DEG_get_mode(&depsgraph_active));
594 return depsgraph;
595}
596
598 const Map<StringRef, ID *> &input_ids)
599{
600 IDProperty *properties = bke::idprop::create_group("Exec Properties").release();
601 IDP_foreach_property(&const_cast<IDProperty &>(op_properties), 0, [&](IDProperty *prop) {
602 if (ID *id = input_ids.lookup_default(prop->name, nullptr)) {
603 IDP_AddToGroup(properties, bke::idprop::create(prop->name, id).release());
604 }
605 else {
606 IDP_AddToGroup(properties, IDP_CopyProperty(prop));
607 }
608 });
609 return properties;
610}
611
613 IDProperty &properties, const nodes::GeoNodesOperatorDepsgraphs &depsgraphs)
614{
615 IDP_foreach_property(&properties, IDP_TYPE_FILTER_ID, [&](IDProperty *property) {
616 if (ID *id = IDP_ID_get(property)) {
617 if (ID_TYPE_USE_COPY_ON_EVAL(GS(id->name))) {
618 property->data.pointer = const_cast<ID *>(depsgraphs.get_evaluated_id(*id));
619 }
620 }
621 });
622}
623
624static bool object_has_editable_data(const Main &bmain, const Object &object)
625{
626 if (!ELEM(object.type, OB_CURVES, OB_POINTCLOUD, OB_MESH, OB_GREASE_PENCIL)) {
627 return false;
628 }
629 if (!BKE_id_is_editable(&bmain, static_cast<const ID *>(object.data))) {
630 return false;
631 }
632 return true;
633}
634
636 const Main &bmain,
637 const eObjectMode mode)
638{
639 Vector<Object *> objects;
640 Set<const ID *> unique_object_data;
641
642 auto handle_object = [&](Object *object) {
643 if (object->mode != mode) {
644 return;
645 }
646 if (!unique_object_data.add(static_cast<const ID *>(object->data))) {
647 return;
648 }
649 if (!object_has_editable_data(bmain, *object)) {
650 return;
651 }
652 objects.append(object);
653 };
654
655 if (mode == OB_MODE_OBJECT) {
656 CTX_DATA_BEGIN (&C, Object *, object, selected_objects) {
657 handle_object(object);
658 }
660 }
661 else {
662 Scene *scene = CTX_data_scene(&C);
663 ViewLayer *view_layer = CTX_data_view_layer(&C);
664 View3D *v3d = CTX_wm_view3d(&C);
665 Object *active_object = CTX_data_active_object(&C);
666 if (v3d && active_object) {
667 FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, active_object->type, mode, ob) {
668 handle_object(ob);
669 }
671 }
672 }
673 return objects;
674}
675
677{
678 Main *bmain = CTX_data_main(C);
679 Scene *scene = CTX_data_scene(C);
680 Object *active_object = CTX_data_active_object(C);
681 if (!active_object) {
682 return OPERATOR_CANCELLED;
683 }
684 const eObjectMode mode = eObjectMode(active_object->mode);
685
686 const bNodeTree *node_tree_orig = get_node_group(*C, *op->ptr, op->reports);
687 if (!node_tree_orig) {
688 return OPERATOR_CANCELLED;
689 }
690
691 const Vector<Object *> objects = gather_supported_objects(*C, *bmain, mode);
692
693 Depsgraph *depsgraph_active = CTX_data_ensure_evaluated_depsgraph(C);
694 Set<ID *> extra_ids;
695 gather_node_group_ids(*node_tree_orig, extra_ids);
696 const Map<StringRef, ID *> input_ids = gather_input_ids(
697 *bmain, *node_tree_orig, *op->properties);
698 for (ID *id : input_ids.values()) {
699 /* Skip IDs that are already fully evaluated in the active depsgraph. */
700 if (!DEG_id_is_fully_evaluated(depsgraph_active, id)) {
701 extra_ids.add(id);
702 }
703 }
704
705 const nodes::GeoNodesOperatorDepsgraphs depsgraphs{
706 depsgraph_active,
707 extra_ids.is_empty() ? nullptr : build_extra_depsgraph(*depsgraph_active, extra_ids),
708 };
709
710 IDProperty *properties = replace_strings_with_id_pointers(*op->properties, input_ids);
711 BLI_SCOPED_DEFER([&]() { IDP_FreeProperty_ex(properties, false); });
712
713 replace_inputs_evaluated_data_blocks(*properties, depsgraphs);
714
715 const bNodeTree *node_tree = nullptr;
716 if (depsgraphs.extra) {
717 node_tree = DEG_get_evaluated(depsgraphs.extra, node_tree_orig);
718 }
719 else {
720 node_tree = node_tree_orig;
721 }
722
723 const nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info =
725 if (lf_graph_info == nullptr) {
726 BKE_report(op->reports, RPT_ERROR, "Cannot evaluate node group");
727 return OPERATOR_CANCELLED;
728 }
729
730 if (!node_tree->group_output_node()) {
731 BKE_report(op->reports, RPT_ERROR, "Node group must have a group output node");
732 return OPERATOR_CANCELLED;
733 }
734 if (node_tree->interface_outputs().is_empty() ||
735 !STREQ(node_tree->interface_outputs()[0]->socket_type, "NodeSocketGeometry"))
736 {
737 BKE_report(op->reports, RPT_ERROR, "Node group's first output must be a geometry");
738 return OPERATOR_CANCELLED;
739 }
740
741 bke::OperatorComputeContext compute_context;
742 Set<ComputeContextHash> socket_log_contexts;
744 eval_log.log = std::make_unique<geo_log::GeoNodesLog>();
745 eval_log.node_group_name = node_tree->id.name + 2;
746 find_socket_log_contexts(*bmain, socket_log_contexts);
747
748 /* May be null if operator called from outside 3D view context. */
749 const RegionView3D *rv3d = CTX_wm_region_view3d(C);
750 Vector<MeshState> orig_mesh_states;
751
752 for (Object *object : objects) {
753 nodes::GeoNodesOperatorData operator_eval_data{};
754 operator_eval_data.mode = mode;
755 operator_eval_data.depsgraphs = &depsgraphs;
756 operator_eval_data.self_object_orig = object;
757 operator_eval_data.scene_orig = scene;
758 RNA_int_get_array(op->ptr, "mouse_position", operator_eval_data.mouse_position);
759 RNA_int_get_array(op->ptr, "region_size", operator_eval_data.region_size);
760 RNA_float_get_array(op->ptr, "cursor_position", operator_eval_data.cursor_position);
761 RNA_float_get_array(op->ptr, "cursor_rotation", &operator_eval_data.cursor_rotation.w);
763 op->ptr, "viewport_projection_matrix", operator_eval_data.viewport_winmat.base_ptr());
765 op->ptr, "viewport_view_matrix", operator_eval_data.viewport_viewmat.base_ptr());
766 operator_eval_data.viewport_is_perspective = RNA_boolean_get(op->ptr,
767 "viewport_is_perspective");
768
769 nodes::GeoNodesCallData call_data{};
770 call_data.operator_data = &operator_eval_data;
771 call_data.eval_log = eval_log.log.get();
772 if (object == active_object) {
773 /* Only log values from the active object. */
774 call_data.socket_log_contexts = &socket_log_contexts;
775 }
776
778 *depsgraph_active, *object, operator_eval_data, orig_mesh_states);
779
781 *node_tree, properties, compute_context, call_data, std::move(geometry_orig));
782
784 *C, *op, *depsgraph_active, *bmain, *scene, *object, rv3d, std::move(new_geometry));
786 }
787
788 geo_log::GeoTreeLog &tree_log = eval_log.log->get_tree_log(compute_context.hash());
789 tree_log.ensure_node_warnings(*bmain);
790 for (const geo_log::NodeWarning &warning : tree_log.all_warnings) {
791 if (warning.type == nodes::NodeWarningType::Info) {
792 BKE_report(op->reports, RPT_INFO, warning.message.c_str());
793 }
794 else {
795 BKE_report(op->reports, RPT_WARNING, warning.message.c_str());
796 }
797 }
798
799 return OPERATOR_FINISHED;
800}
801
814 wmOperator &op,
815 const wmEvent &event)
816{
817 Scene *scene = CTX_data_scene(&C);
818 /* NOTE: `region` and `rv3d` may be null when called from a script. */
819 const ARegion *region = CTX_wm_region(&C);
820 const RegionView3D *rv3d = CTX_wm_region_view3d(&C);
821
822 /* Mouse position node inputs. */
823 RNA_int_set_array(op.ptr, "mouse_position", event.mval);
825 op.ptr,
826 "region_size",
827 region ? int2(BLI_rcti_size_x(&region->winrct), BLI_rcti_size_y(&region->winrct)) : int2(0));
828
829 /* 3D cursor node inputs. */
830 const View3DCursor &cursor = scene->cursor;
831 RNA_float_set_array(op.ptr, "cursor_position", cursor.location);
832 math::Quaternion cursor_rotation = cursor.rotation();
833 RNA_float_set_array(op.ptr, "cursor_rotation", &cursor_rotation.w);
834
835 /* Viewport transform node inputs. */
837 "viewport_projection_matrix",
838 rv3d ? float4x4(rv3d->winmat).base_ptr() : float4x4::identity().base_ptr());
840 "viewport_view_matrix",
841 rv3d ? float4x4(rv3d->viewmat).base_ptr() : float4x4::identity().base_ptr());
842 RNA_boolean_set(op.ptr, "viewport_is_perspective", rv3d ? bool(rv3d->is_persp) : true);
843}
844
846{
847 const bNodeTree *node_tree = get_node_group(*C, *op->ptr, op->reports);
848 if (!node_tree) {
849 return OPERATOR_CANCELLED;
850 }
851
853
854 nodes ::update_input_properties_from_node_tree(
855 *node_tree, op->properties, *op->properties, true);
857
858 return run_node_group_exec(C, op);
859}
860
862 wmOperatorType * /*ot*/,
864{
867 if (!asset) {
868 return "";
869 }
870 if (!asset->get_metadata().description) {
871 return "";
872 }
873 return asset->get_metadata().description;
874}
875
877{
878 uiLayout *layout = op->layout;
879 layout->use_property_split_set(true);
880 layout->use_property_decorate_set(false);
881 Main *bmain = CTX_data_main(C);
882 PointerRNA bmain_ptr = RNA_main_pointer_create(bmain);
883
884 const bNodeTree *node_tree = get_node_group(*C, *op->ptr, nullptr);
885 if (!node_tree) {
886 return;
887 }
888
889 bke::OperatorComputeContext compute_context;
891
892 geo_log::GeoTreeLog *tree_log = eval_log.log ?
893 &eval_log.log->get_tree_log(compute_context.hash()) :
894 nullptr;
896 *C, *op, const_cast<bNodeTree &>(*node_tree), tree_log);
897}
898
900{
901 bool result = false;
902 RNA_STRUCT_BEGIN (ptr, prop) {
903 int flag = RNA_property_flag(prop);
904 if ((flag & PROP_HIDDEN) == 0) {
905 result = true;
906 break;
907 }
908 }
910 return result;
911}
912
914{
915 std::string local_name = RNA_string_get(ptr, "name");
916 if (!local_name.empty()) {
917 return local_name;
918 }
919 std::string library_asset_identifier = RNA_string_get(ptr, "relative_asset_identifier");
920 StringRef ref(library_asset_identifier);
921 return ref.drop_prefix(ref.find_last_of(SEP_STR) + 1);
922}
923
925{
926 if (!ptr) {
927 return false;
928 }
929 Main &bmain = *CTX_data_main(&C);
930 if (bNodeTree *group = reinterpret_cast<bNodeTree *>(
932 {
933 return group->geometry_node_asset_traits &&
934 (group->geometry_node_asset_traits->flag & GEO_NODE_ASSET_WAIT_FOR_CURSOR) != 0;
935 }
936
939 if (!asset) {
940 return false;
941 }
942 const IDProperty *traits_flag = BKE_asset_metadata_idprop_find(
943 &asset->get_metadata(), "geometry_node_asset_traits_flag");
944 if (traits_flag == nullptr || !(IDP_int_get(traits_flag) & GEO_NODE_ASSET_WAIT_FOR_CURSOR)) {
945 return false;
946 }
947 return true;
948}
949
951{
952 PropertyRNA *prop;
953 ot->name = "Run Node Group";
954 ot->idname = __func__;
955 ot->description = "Execute a node group on geometry";
956
957 /* A proper poll is not possible, since it doesn't have access to the operator's properties. */
958 ot->invoke = run_node_group_invoke;
959 ot->exec = run_node_group_exec;
960 ot->get_description = run_node_group_get_description;
961 ot->ui = run_node_group_ui;
962 ot->ui_poll = run_node_ui_poll;
963 ot->get_name = run_node_group_get_name;
964 ot->depends_on_cursor = run_node_group_depends_on_cursor;
965
967
970
971 /* See comment for #store_input_node_values_rna_props. */
972 prop = RNA_def_int_array(ot->srna,
973 "mouse_position",
974 2,
975 nullptr,
976 INT_MIN,
977 INT_MAX,
978 "Mouse Position",
979 "Mouse coordinates in region space",
980 INT_MIN,
981 INT_MAX);
983 prop = RNA_def_int_array(
984 ot->srna, "region_size", 2, nullptr, 0, INT_MAX, "Region Size", "", 0, INT_MAX);
986 prop = RNA_def_float_array(ot->srna,
987 "cursor_position",
988 3,
989 nullptr,
990 -FLT_MAX,
991 FLT_MAX,
992 "3D Cursor Position",
993 "",
994 -FLT_MAX,
995 FLT_MAX);
997 prop = RNA_def_float_array(ot->srna,
998 "cursor_rotation",
999 4,
1000 nullptr,
1001 -FLT_MAX,
1002 FLT_MAX,
1003 "3D Cursor Rotation",
1004 "",
1005 -FLT_MAX,
1006 FLT_MAX);
1008 prop = RNA_def_float_array(ot->srna,
1009 "viewport_projection_matrix",
1010 16,
1011 nullptr,
1012 -FLT_MAX,
1013 FLT_MAX,
1014 "Viewport Projection Transform",
1015 "",
1016 -FLT_MAX,
1017 FLT_MAX);
1019 prop = RNA_def_float_array(ot->srna,
1020 "viewport_view_matrix",
1021 16,
1022 nullptr,
1023 -FLT_MAX,
1024 FLT_MAX,
1025 "Viewport View Transform",
1026 "",
1027 -FLT_MAX,
1028 FLT_MAX);
1030 prop = RNA_def_boolean(
1031 ot->srna, "viewport_is_perspective", false, "Viewport Is Perspective", "");
1033}
1034
1036
1037/* -------------------------------------------------------------------- */
1040
1041static bool asset_menu_poll(const bContext *C, MenuType * /*mt*/)
1042{
1043 return CTX_wm_view3d(C);
1044}
1045
1047 const eObjectMode mode)
1048{
1049 switch (type) {
1050 case OB_MESH: {
1051 switch (mode) {
1052 case OB_MODE_OBJECT:
1054 case OB_MODE_EDIT:
1056 case OB_MODE_SCULPT:
1058 default:
1059 break;
1060 }
1061 break;
1062 }
1063 case OB_CURVES: {
1064 switch (mode) {
1065 case OB_MODE_OBJECT:
1067 case OB_MODE_EDIT:
1071 default:
1072 break;
1073 }
1074 break;
1075 }
1076 case OB_POINTCLOUD: {
1077 switch (mode) {
1078 case OB_MODE_OBJECT:
1080 case OB_MODE_EDIT:
1082 default:
1083 break;
1084 }
1085 break;
1086 }
1087 case OB_GREASE_PENCIL: {
1088 switch (mode) {
1089 case OB_MODE_OBJECT:
1091 case OB_MODE_EDIT:
1097 default:
1098 break;
1099 }
1100 }
1101 default:
1102 break;
1103 }
1106}
1107
1109{
1110 return asset_flag_for_context(ObjectType(active_object.type), eObjectMode(active_object.mode));
1111}
1112
1114{
1115 switch (type) {
1116 case OB_MESH: {
1117 switch (mode) {
1118 case OB_MODE_OBJECT: {
1120 return &tree;
1121 }
1122 case OB_MODE_EDIT: {
1124 return &tree;
1125 }
1126 case OB_MODE_SCULPT: {
1128 return &tree;
1129 }
1130 default:
1131 return nullptr;
1132 }
1133 }
1134 case OB_CURVES: {
1135 switch (mode) {
1136 case OB_MODE_OBJECT: {
1138 return &tree;
1139 }
1140 case OB_MODE_EDIT: {
1142 return &tree;
1143 }
1144 case OB_MODE_SCULPT_CURVES: {
1146 return &tree;
1147 }
1148 default:
1149 return nullptr;
1150 }
1151 }
1152 case OB_POINTCLOUD: {
1153 switch (mode) {
1154 case OB_MODE_OBJECT: {
1156 return &tree;
1157 }
1158 case OB_MODE_EDIT: {
1160 return &tree;
1161 }
1162 default:
1163 return nullptr;
1164 }
1165 }
1166 case OB_GREASE_PENCIL: {
1167 switch (mode) {
1168 case OB_MODE_OBJECT: {
1170 return &tree;
1171 }
1172 case OB_MODE_EDIT: {
1174 return &tree;
1175 }
1178 return &tree;
1179 }
1182 return &tree;
1183 }
1184 default:
1185 return nullptr;
1186 }
1187 }
1188 default:
1189 return nullptr;
1190 }
1191}
1192
1194{
1195 return get_static_item_tree(ObjectType(active_object.type), eObjectMode(active_object.mode));
1196}
1197
1199{
1201 for (const eObjectMode mode : {OB_MODE_OBJECT,
1207 {
1208 if (asset::AssetItemTree *tree = get_static_item_tree(type, mode)) {
1209 tree->dirty = true;
1210 }
1211 }
1212 }
1213}
1214
1215static asset::AssetItemTree build_catalog_tree(const bContext &C, const Object &active_object)
1216{
1217 asset::AssetFilterSettings type_filter{};
1218 type_filter.id_types = FILTER_ID_NT;
1220 auto meta_data_filter = [&](const AssetMetaData &meta_data) {
1221 const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
1222 if (tree_type == nullptr || IDP_int_get(tree_type) != NTREE_GEOMETRY) {
1223 return false;
1224 }
1225 const IDProperty *traits_flag = BKE_asset_metadata_idprop_find(
1226 &meta_data, "geometry_node_asset_traits_flag");
1227 if (traits_flag == nullptr || (IDP_int_get(traits_flag) & flag) != flag) {
1228 return false;
1229 }
1230 return true;
1231 };
1234 return asset::build_filtered_all_catalog_tree(library, C, type_filter, meta_data_filter);
1235}
1236
1242static Set<std::string> get_builtin_menus(const ObjectType object_type, const eObjectMode mode)
1243{
1244 Set<std::string> menus;
1245 switch (object_type) {
1246 case OB_CURVES:
1247 menus.add_new("View");
1248 menus.add_new("Select");
1249 menus.add_new("Curves");
1250 break;
1251 case OB_POINTCLOUD:
1252 menus.add_new("View");
1253 menus.add_new("Select");
1254 menus.add_new("Point Cloud");
1255 break;
1256 case OB_MESH:
1257 switch (mode) {
1258 case OB_MODE_OBJECT:
1259 menus.add_new("View");
1260 menus.add_new("Select");
1261 menus.add_new("Add");
1262 menus.add_new("Object");
1263 menus.add_new("Object/Apply");
1264 menus.add_new("Object/Convert");
1265 menus.add_new("Object/Quick Effects");
1266 break;
1267 case OB_MODE_EDIT:
1268 menus.add_new("View");
1269 menus.add_new("Select");
1270 menus.add_new("Add");
1271 menus.add_new("Mesh");
1272 menus.add_new("Mesh/Extrude");
1273 menus.add_new("Mesh/Clean Up");
1274 menus.add_new("Mesh/Delete");
1275 menus.add_new("Mesh/Merge");
1276 menus.add_new("Mesh/Normals");
1277 menus.add_new("Mesh/Shading");
1278 menus.add_new("Mesh/Split");
1279 menus.add_new("Mesh/Weights");
1280 menus.add_new("Vertex");
1281 menus.add_new("Edge");
1282 menus.add_new("Face");
1283 menus.add_new("Face/Face Data");
1284 menus.add_new("UV");
1285 menus.add_new("UV/Unwrap");
1286 break;
1287 case OB_MODE_SCULPT:
1288 menus.add_new("View");
1289 menus.add_new("Sculpt");
1290 menus.add_new("Mask");
1291 menus.add_new("Face Sets");
1292 break;
1294 menus.add_new("View");
1295 menus.add_new("Paint");
1296 break;
1298 menus.add_new("View");
1299 menus.add_new("Weights");
1300 break;
1301 default:
1302 break;
1303 }
1304 break;
1305 case OB_GREASE_PENCIL: {
1306 switch (mode) {
1307 case OB_MODE_OBJECT:
1308 menus.add_new("View");
1309 menus.add_new("Select");
1310 menus.add_new("Add");
1311 menus.add_new("Object");
1312 menus.add_new("Object/Apply");
1313 menus.add_new("Object/Convert");
1314 menus.add_new("Object/Quick Effects");
1315 break;
1316 case OB_MODE_EDIT:
1317 menus.add_new("View");
1318 menus.add_new("Select");
1319 menus.add_new("Grease Pencil");
1320 menus.add_new("Stroke");
1321 menus.add_new("Point");
1322 break;
1324 menus.add_new("View");
1325 break;
1327 menus.add_new("View");
1328 menus.add_new("Draw");
1329 break;
1330 default:
1331 break;
1332 }
1333 }
1334 default:
1335 break;
1336 }
1337 return menus;
1338}
1339
1340static void catalog_assets_draw(const bContext *C, Menu *menu)
1341{
1342 const Object *active_object = CTX_data_active_object(C);
1343 if (!active_object) {
1344 return;
1345 }
1347 if (!tree) {
1348 return;
1349 }
1350 const std::optional<StringRefNull> menu_path = CTX_data_string_get(C, "asset_catalog_path");
1351 if (!menu_path) {
1352 return;
1353 }
1354 const Span<asset_system::AssetRepresentation *> assets = tree->assets_per_path.lookup(
1355 menu_path->data());
1356 const asset_system::AssetCatalogTreeItem *catalog_item = tree->catalogs.find_item(
1357 menu_path->data());
1358 BLI_assert(catalog_item != nullptr);
1359
1360 uiLayout *layout = menu->layout;
1361 bool add_separator = true;
1362
1363 wmOperatorType *ot = WM_operatortype_find("GEOMETRY_OT_execute_node_group", true);
1364 for (const asset_system::AssetRepresentation *asset : assets) {
1365 if (add_separator) {
1366 layout->separator();
1367 add_separator = false;
1368 }
1369 PointerRNA props_ptr = layout->op(ot,
1370 IFACE_(asset->get_name()),
1371 ICON_NONE,
1373 UI_ITEM_NONE);
1375 }
1376
1377 const Set<std::string> builtin_menus = get_builtin_menus(ObjectType(active_object->type),
1378 eObjectMode(active_object->mode));
1379
1382 if (!all_library) {
1383 return;
1384 }
1385
1386 catalog_item->foreach_child([&](const asset_system::AssetCatalogTreeItem &item) {
1387 if (builtin_menus.contains_as(item.catalog_path().str())) {
1388 return;
1389 }
1390 if (add_separator) {
1391 layout->separator();
1392 add_separator = false;
1393 }
1394 asset::draw_menu_for_catalog(item, "GEO_MT_node_operator_catalog_assets", *layout);
1395 });
1396}
1397
1399{
1400 MenuType type{};
1401 STRNCPY_UTF8(type.idname, "GEO_MT_node_operator_catalog_assets");
1402 type.poll = asset_menu_poll;
1406 return type;
1407}
1408
1410{
1411 Main &bmain = *CTX_data_main(&C);
1412 const Object *active_object = CTX_data_active_object(&C);
1413 if (!active_object) {
1414 return false;
1415 }
1417 LISTBASE_FOREACH (const bNodeTree *, group, &bmain.nodetrees) {
1418 /* Assets are displayed in other menus, and non-local data-blocks aren't added to this menu. */
1419 if (group->id.library_weak_reference || group->id.asset_data) {
1420 continue;
1421 }
1422 if (!group->geometry_node_asset_traits ||
1423 (group->geometry_node_asset_traits->flag & flag) != flag)
1424 {
1425 continue;
1426 }
1427 return true;
1428 }
1429 return false;
1430}
1431
1433{
1434 const Object *active_object = CTX_data_active_object(C);
1435 if (!active_object) {
1436 return;
1437 }
1439 if (!tree) {
1440 return;
1441 }
1442 uiLayout *layout = menu->layout;
1443 wmOperatorType *ot = WM_operatortype_find("GEOMETRY_OT_execute_node_group", true);
1444 for (const asset_system::AssetRepresentation *asset : tree->unassigned_assets) {
1445 PointerRNA props_ptr = layout->op(ot,
1446 IFACE_(asset->get_name()),
1447 ICON_NONE,
1449 UI_ITEM_NONE);
1451 }
1452
1454
1455 bool first = true;
1456 bool add_separator = !tree->unassigned_assets.is_empty();
1457 Main &bmain = *CTX_data_main(C);
1458 LISTBASE_FOREACH (const bNodeTree *, group, &bmain.nodetrees) {
1459 /* Assets are displayed in other menus, and non-local data-blocks aren't added to this menu. */
1460 if (group->id.library_weak_reference || group->id.asset_data) {
1461 continue;
1462 }
1463 if (!group->geometry_node_asset_traits ||
1464 (group->geometry_node_asset_traits->flag & flag) != flag)
1465 {
1466 continue;
1467 }
1468
1469 if (add_separator) {
1470 layout->separator();
1471 add_separator = false;
1472 }
1473 if (first) {
1474 layout->label(IFACE_("Non-Assets"), ICON_NONE);
1475 first = false;
1476 }
1477
1478 PointerRNA props_ptr = layout->op(
1479 ot, group->id.name + 2, ICON_NONE, wm::OpCallContext::InvokeRegionWin, UI_ITEM_NONE);
1480 WM_operator_properties_id_lookup_set_from_id(&props_ptr, &group->id);
1481 /* Also set the name so it can be used for #run_node_group_get_name. */
1482 RNA_string_set(&props_ptr, "name", group->id.name + 2);
1483 }
1484}
1485
1487{
1488 MenuType type{};
1489 STRNCPY_UTF8(type.label, N_("Unassigned Node Tools"));
1490 STRNCPY_UTF8(type.idname, "GEO_MT_node_operator_unassigned");
1491 type.poll = asset_menu_poll;
1495 type.description = N_(
1496 "Tool node group assets not assigned to a catalog.\n"
1497 "Catalogs can be assigned in the Asset Browser");
1498 return type;
1499}
1500
1502 const bContext &C,
1503 const StringRef catalog_path)
1504{
1505 const Object *active_object = CTX_data_active_object(&C);
1506 if (!active_object) {
1507 return;
1508 }
1510 if (!tree) {
1511 return;
1512 }
1513 const asset_system::AssetCatalogTreeItem *item = tree->catalogs.find_item(catalog_path);
1514 if (!item) {
1515 return;
1516 }
1519 if (!all_library) {
1520 return;
1521 }
1522 uiLayout *col = &layout.column(false);
1523 col->context_string_set("asset_catalog_path", item->catalog_path().str());
1524 col->menu_contents("GEO_MT_node_operator_catalog_assets");
1525}
1526
1528{
1529 const Object *active_object = CTX_data_active_object(&C);
1530 if (!active_object) {
1531 return;
1532 }
1534 if (!tree) {
1535 return;
1536 }
1537 if (tree->dirty) {
1538 *tree = build_catalog_tree(C, *active_object);
1539 }
1540
1541 const Set<std::string> builtin_menus = get_builtin_menus(ObjectType(active_object->type),
1542 eObjectMode(active_object->mode));
1543
1544 tree->catalogs.foreach_root_item([&](const asset_system::AssetCatalogTreeItem &item) {
1545 if (!builtin_menus.contains_as(item.catalog_path().str())) {
1546 asset::draw_menu_for_catalog(item, "GEO_MT_node_operator_catalog_assets", layout);
1547 }
1548 });
1549
1550 if (!tree->unassigned_assets.is_empty() || unassigned_local_poll(C)) {
1551 layout.menu("GEO_MT_node_operator_unassigned", "", ICON_FILE_HIDDEN);
1552 }
1553}
1554
1556
1557} // namespace blender::ed::geometry
Main runtime representation of an asset.
IDProperty * BKE_asset_metadata_idprop_find(const AssetMetaData *asset_data, const char *name) ATTR_WARN_UNUSED_RESULT
Definition asset.cc:179
#define CTX_DATA_BEGIN(C, Type, instance, member)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
#define CTX_DATA_END
std::optional< blender::StringRefNull > CTX_data_string_get(const bContext *C, const char *member)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
struct Curves * BKE_curves_copy_for_eval(const struct Curves *curves_src)
Low-level operations for curves.
CustomData interface, see also DNA_customdata_types.h.
int CustomData_get_layer_index(const CustomData *data, eCustomDataType type)
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
Definition editmesh.cc:95
Low-level operations for grease pencil.
GreasePencil * BKE_grease_pencil_copy_for_eval(const GreasePencil *grease_pencil_src)
#define IDP_ID_get(prop)
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
#define IDP_int_get(prop)
#define IDP_string_get(prop)
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:717
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:863
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1245
#define FOREACH_OBJECT_IN_MODE_END
Definition BKE_layer.hh:382
#define FOREACH_OBJECT_IN_MODE_BEGIN(_scene, _view_layer, _v3d, _object_type, _object_mode, _instance)
Definition BKE_layer.hh:377
ID * BKE_libblock_find_name(Main *bmain, short type, const char *name, const std::optional< Library * > lib=std::nullopt) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition lib_id.cc:1710
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2523
void BKE_id_free(Main *bmain, void *idv)
General operations, lookup, etc. for materials.
void BKE_object_material_from_eval_data(Main *bmain, Object *ob_orig, const ID *data_eval)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob, bool process_shape_keys=true)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
General operations, lookup, etc. for blender objects.
A BVH for high poly meshes.
General operations for point clouds.
PointCloud * BKE_pointcloud_copy_for_eval(const PointCloud *pointcloud_src)
void BKE_pointcloud_nomain_to_pointcloud(PointCloud *pointcloud_src, PointCloud *pointcloud_dst)
@ RPT_INFO
Definition BKE_report.hh:35
@ RPT_ERROR
Definition BKE_report.hh:39
@ RPT_WARNING
Definition BKE_report.hh:38
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:153
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:614
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
#define BLI_SCOPED_DEFER(function_to_defer)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition BLI_rect.h:198
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:194
#define STRNCPY_UTF8(dst, src)
#define ELEM(...)
#define STREQ(a, b)
#define IFACE_(msgid)
void DEG_id_tag_update(ID *id, unsigned int flags)
Depsgraph * DEG_graph_new(Main *bmain, Scene *scene, ViewLayer *view_layer, eEvaluationMode mode)
Definition depsgraph.cc:278
void DEG_evaluate_on_refresh(Depsgraph *graph, DepsgraphEvaluateSyncWriteback sync_writeback=DEG_EVALUATE_SYNC_WRITEBACK_NO)
void DEG_graph_build_from_ids(Depsgraph *graph, blender::Span< ID * > ids)
float DEG_get_ctime(const Depsgraph *graph)
bool DEG_id_is_fully_evaluated(const Depsgraph *depsgraph, const ID *id_eval)
eEvaluationMode DEG_get_mode(const Depsgraph *graph)
ViewLayer * DEG_get_input_view_layer(const Depsgraph *graph)
Main * DEG_get_bmain(const Depsgraph *graph)
Scene * DEG_get_input_scene(const Depsgraph *graph)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
#define ID_TYPE_USE_COPY_ON_EVAL(_id_type)
Definition DNA_ID.h:740
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
#define FILTER_ID_NT
Definition DNA_ID.h:1213
@ ID_TE
@ ID_IM
@ ID_NT
@ ID_MA
@ ID_GR
@ ID_OB
@ IDP_TYPE_FILTER_STRING
@ IDP_TYPE_FILTER_ID
@ CD_MDEFORMVERT
GeometryNodeAssetTraitFlag
@ GEO_NODE_ASSET_MESH
@ GEO_NODE_ASSET_SCULPT
@ GEO_NODE_ASSET_WAIT_FOR_CURSOR
@ GEO_NODE_ASSET_PAINT
@ GEO_NODE_ASSET_GREASE_PENCIL
@ GEO_NODE_ASSET_CURVE
@ GEO_NODE_ASSET_POINTCLOUD
@ GEO_NODE_ASSET_EDIT
@ GEO_NODE_ASSET_TOOL
@ GEO_NODE_ASSET_OBJECT
@ NTREE_GEOMETRY
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_TEXTURE
@ SOCK_VECTOR
@ SOCK_CLOSURE
@ SOCK_BOOLEAN
@ SOCK_MATERIAL
@ SOCK_SHADER
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_CUSTOM
@ SOCK_BUNDLE
@ SOCK_GEOMETRY
@ SOCK_ROTATION
@ SOCK_OBJECT
@ SOCK_STRING
@ SOCK_RGBA
@ SOCK_MENU
eObjectMode
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_SCULPT
@ OB_MODE_SCULPT_CURVES
@ OB_MODE_PAINT_GREASE_PENCIL
@ OB_MODE_SCULPT_GREASE_PENCIL
@ OB_MODE_OBJECT
@ OB_MODE_VERTEX_PAINT
Object is a sort of wrapper for general info.
@ OB_GREASE_PENCIL
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES
@ SPACE_NODE
@ SNODE_GEOMETRY_TOOL
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
void EDBM_mesh_load_ex(Main *bmain, Object *ob, bool free_data)
void EDBM_mesh_free_data(BMEditMesh *em)
void EDBM_mesh_make_from_mesh(Object *ob, Mesh *src_mesh, int select_mode, bool add_key_index)
#define RNA_STRUCT_BEGIN(sptr, prop)
#define RNA_STRUCT_END
@ PROP_HIDDEN
Definition RNA_types.hh:338
#define C
Definition RandGen.cpp:29
#define UI_ITEM_NONE
#define NC_GEOM
Definition WM_types.hh:393
#define ND_DATA
Definition WM_types.hh:509
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
#define NA_EDITED
Definition WM_types.hh:584
#define NC_GPENCIL
Definition WM_types.hh:399
BMesh const char void * data
int BM_mesh_active_face_index_get(BMesh *bm, bool is_sloppy, bool is_selected)
int BM_mesh_active_edge_index_get(BMesh *bm)
int BM_mesh_active_vert_index_get(BMesh *bm)
BPy_StructRNA * depsgraph
const ComputeContextHash & hash() const
static IndexMask from_indices(Span< T > indices, IndexMaskMemory &memory)
ValueIterator values() const &
Definition BLI_map.hh:884
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:295
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:570
Iterator begin() const
Definition BLI_set.hh:480
int64_t size() const
Definition BLI_set.hh:587
bool contains_as(const ForwardKey &key) const
Definition BLI_set.hh:314
Iterator end() const
Definition BLI_set.hh:490
bool add(const Key &key)
Definition BLI_set.hh:248
bool is_empty() const
Definition BLI_set.hh:595
void add_new(const Key &key)
Definition BLI_set.hh:233
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr int64_t find_last_of(StringRef chars, int64_t pos=INT64_MAX) const
constexpr StringRef drop_prefix(int64_t n) const
void materialize(MutableSpan< T > r_span) const
static VArray from_span(Span< T > values)
void append(const T &value)
Span< T > as_span() const
void append_as(ForwardValue &&...value)
void foreach_child(ItemIterFn callback) const
GAttributeReader lookup(const StringRef attribute_id) const
GAttributeReader get() const
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
bool remove(const StringRef attribute_id)
void freeze_shared_state(const ImplicitSharingInfo &sharing_info)
static Map< const bke::bNodeTreeZone *, ComputeContextHash > get_context_hash_by_zone_for_node_editor(const SpaceNode &snode, bke::ComputeContextCache &compute_context_cache)
void ensure_node_warnings(const NodesModifierData &nmd)
KDTree_3d * tree
#define GS(x)
uint col
#define input
#define log
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
void copy(const GVArray &src, GMutableSpan dst, int64_t grain_size=4096)
AssetLibraryReference all_library_reference()
void all_library_reload_catalogs_if_dirty()
void ensure_non_empty_layer_names(Main &bmain, GreasePencil &grease_pencil)
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRef prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRef prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
pbvh::Tree * pbvh_get(Object &object)
Definition paint.cc:3052
void update_normals(const Depsgraph &depsgraph, Object &object_orig, Tree &pbvh)
Definition pbvh.cc:1257
asset_system::AssetLibrary * library_get_once_available(const AssetLibraryReference &library_reference)
void asset_reading_region_listen_fn(const wmRegionListenerParams *params)
AssetItemTree build_filtered_all_catalog_tree(const AssetLibraryReference &library_ref, const bContext &C, const AssetFilterSettings &filter_settings, FunctionRef< bool(const AssetMetaData &)> meta_data_filter={})
void operator_asset_reference_props_register(StructRNA &srna)
void draw_menu_for_catalog(const asset_system::AssetCatalogTreeItem &item, const StringRefNull menu_name, uiLayout &layout)
const asset_system::AssetRepresentation * operator_asset_reference_props_get_asset_from_all_library(const bContext &C, PointerRNA &ptr, ReportList *reports)
void operator_asset_reference_props_set(const asset_system::AssetRepresentation &asset, PointerRNA &ptr)
ID * asset_local_id_ensure_imported(Main &bmain, const asset_system::AssetRepresentation &asset, const std::optional< eAssetImportMethod > import_method=std::nullopt)
static void remove_shape_key_attributes(Mesh &mesh, const Key &key)
void GEOMETRY_OT_execute_node_group(wmOperatorType *ot)
static void find_socket_log_contexts(const Main &bmain, Set< ComputeContextHash > &r_socket_log_contexts)
static bool asset_menu_poll(const bContext *C, MenuType *)
static wmOperatorStatus run_node_group_exec(bContext *C, wmOperator *op)
static GeometryNodeAssetTraitFlag asset_flag_for_context(const ObjectType type, const eObjectMode mode)
static bool unassigned_local_poll(const bContext &C)
static std::string shape_key_attribute_name(const KeyBlock &kb)
static Vector< Object * > gather_supported_objects(const bContext &C, const Main &bmain, const eObjectMode mode)
static void add_shape_keys_as_attributes(Mesh &mesh, const Key &key)
static const ImplicitSharingInfo * get_vertex_group_sharing_info(const Mesh &mesh)
MenuType node_group_operator_assets_menu_unassigned()
static bke::GeometrySet get_original_geometry_eval_copy(Depsgraph &depsgraph, Object &object, nodes::GeoNodesOperatorData &operator_data, Vector< MeshState > &orig_mesh_states)
const GeoOperatorLog & node_group_operator_static_eval_log()
static asset::AssetItemTree * get_static_item_tree(const ObjectType type, const eObjectMode mode)
static IDProperty * replace_strings_with_id_pointers(const IDProperty &op_properties, const Map< StringRef, ID * > &input_ids)
static Map< StringRef, ID * > gather_input_ids(const Main &bmain, const bNodeTree &node_group, const IDProperty &properties)
static void catalog_assets_draw(const bContext *C, Menu *menu)
static void catalog_assets_draw_unassigned(const bContext *C, Menu *menu)
static bool object_has_editable_data(const Main &bmain, const Object &object)
static void store_result_geometry(const bContext &C, const wmOperator &op, const Depsgraph &depsgraph, Main &bmain, Scene &scene, Object &object, const RegionView3D *rv3d, bke::GeometrySet geometry)
static wmOperatorStatus run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void store_input_node_values_rna_props(const bContext &C, wmOperator &op, const wmEvent &event)
static std::string run_node_group_get_description(bContext *C, wmOperatorType *, PointerRNA *ptr)
static Depsgraph * build_extra_depsgraph(const Depsgraph &depsgraph_active, const Set< ID * > &ids)
static std::string run_node_group_get_name(wmOperatorType *, PointerRNA *ptr)
static asset::AssetItemTree build_catalog_tree(const bContext &C, const Object &active_object)
static bool run_node_group_depends_on_cursor(bContext &C, wmOperatorType &, PointerRNA *ptr)
static void run_node_group_ui(bContext *C, wmOperator *op)
static GeoOperatorLog & get_static_eval_log()
static std::optional< ID_Type > socket_type_to_id_type(const eNodeSocketDatatype socket_type)
static const bNodeTree * get_node_group(const bContext &C, PointerRNA &ptr, ReportList *reports)
void ui_template_node_operator_asset_menu_items(uiLayout &layout, const bContext &C, const StringRef catalog_path)
static void store_attributes_to_shape_keys(const Mesh &mesh, Key &key)
static Set< std::string > get_builtin_menus(const ObjectType object_type, const eObjectMode mode)
static const bNodeTreeInterfaceSocket * find_group_input_by_identifier(const bNodeTree &node_group, const StringRef identifier)
static const bNodeTree * get_asset_or_local_node_group(const bContext &C, PointerRNA &ptr, ReportList *reports)
void ui_template_node_operator_asset_root_items(uiLayout &layout, const bContext &C)
static bool run_node_ui_poll(wmOperatorType *, PointerRNA *ptr)
static void gather_node_group_ids(const bNodeTree &node_tree, Set< ID * > &ids)
static void replace_inputs_evaluated_data_blocks(IDProperty &properties, const nodes::GeoNodesOperatorDepsgraphs &depsgraphs)
bool ensure_active_keyframe(const Scene &scene, GreasePencil &grease_pencil, bke::greasepencil::Layer &layer, const bool duplicate_previous_key, bool &r_inserted_keyframe)
void apply_eval_grease_pencil_data(const GreasePencil &eval_grease_pencil, const int eval_frame, const IndexMask &orig_layers, GreasePencil &orig_grease_pencil)
void store_mesh_from_eval(const wmOperator &op, const Scene &scene, const Depsgraph &depsgraph, const RegionView3D *rv3d, Object &object, Mesh *new_mesh)
Definition sculpt.cc:5292
QuaternionBase< float > Quaternion
bke::GeometrySet execute_geometry_nodes_on_geometry(const bNodeTree &btree, const IDProperty *properties, const ComputeContext &base_compute_context, GeoNodesCallData &call_data, bke::GeometrySet input_geometry)
const GeometryNodesLazyFunctionGraphInfo * ensure_geometry_nodes_lazy_function_graph(const bNodeTree &btree)
void update_output_properties_from_node_tree(const bNodeTree &tree, const IDProperty *old_properties, IDProperty &properties)
void draw_geometry_nodes_operator_redo_ui(const bContext &C, wmOperator &op, bNodeTree &tree, geo_eval_log::GeoTreeLog *tree_log)
MatBase< float, 4, 4 > float4x4
VecBase< int32_t, 2 > int2
VecBase< float, 3 > float3
#define hash
Definition noise_c.cc:154
void RNA_int_set_array(PointerRNA *ptr, const char *name, const int *values)
void RNA_int_get_array(PointerRNA *ptr, const char *name, int *values)
void RNA_string_set(PointerRNA *ptr, const char *name, const char *value)
void RNA_boolean_set(PointerRNA *ptr, const char *name, bool value)
void RNA_float_get_array(PointerRNA *ptr, const char *name, float *values)
int RNA_property_flag(PropertyRNA *prop)
std::string RNA_string_get(PointerRNA *ptr, const char *name)
PointerRNA RNA_main_pointer_create(Main *main)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
void RNA_float_set_array(PointerRNA *ptr, const char *name, const float *values)
PropertyRNA * RNA_def_int_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const int *default_value, const int hardmin, const int hardmax, const char *ui_name, const char *ui_description, const int softmin, const int softmax)
PropertyRNA * RNA_def_float_array(StructOrFunctionRNA *cont_, const char *identifier, const int len, const float *default_value, const float hardmin, const float hardmax, const char *ui_name, const char *ui_description, const float softmin, const float softmax)
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, const bool default_value, const char *ui_name, const char *ui_description)
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
#define FLT_MAX
Definition stdcycles.h:14
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
CurvesGeometry geometry
GreasePencilRuntimeHandle * runtime
char name[64]
Definition DNA_ID.h:164
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
char name[64]
ListBase block
KeyBlock * refkey
void * first
ListBase wm
Definition BKE_main.hh:307
ListBase nodetrees
Definition BKE_main.hh:301
MenuTypeFlag flag
const char * description
char label[BKE_ST_MAXNAME]
bool(* poll)(const bContext *C, MenuType *mt)
char idname[BKE_ST_MAXNAME]
void(* draw)(const bContext *C, Menu *menu)
void(* listener)(const wmRegionListenerParams *params)
uiLayout * layout
MeshRuntimeHandle * runtime
struct AttributeStorage attribute_storage
float viewmat[4][4]
float winmat[4][4]
struct ToolSettings * toolsettings
View3DCursor cursor
char node_tree_sub_type
struct bNodeTree * edittree
bNodeTreeRuntimeHandle * runtime
ListBase areabase
const T * base_ptr() const
const ImplicitSharingInfo * sharing_info
static GeometrySet from_grease_pencil(GreasePencil *grease_pencil, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet from_mesh(Mesh *mesh, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet from_pointcloud(PointCloud *pointcloud, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
std::unique_ptr< nodes::geo_eval_log::GeoNodesLog > log
const Set< ComputeContextHash > * socket_log_contexts
void use_property_decorate_set(bool is_sep)
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, blender::wm::OpCallContext context, eUI_Item_Flag flag)
void menu(MenuType *mt, std::optional< blender::StringRef > name, int icon)
void use_property_split_set(bool value)
int mval[2]
Definition WM_types.hh:763
struct ReportList * reports
IDProperty * properties
struct uiLayout * layout
struct PointerRNA * ptr
#define SEP_STR
Definition unit.cc:39
#define N_(msgid)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4238
wmOperatorType * ot
Definition wm_files.cc:4237
ID * WM_operator_properties_id_lookup_from_name_or_session_uid(Main *bmain, PointerRNA *ptr, const ID_Type type)
void WM_operator_properties_id_lookup(wmOperatorType *ot, const bool add_name_prop)
void WM_operator_properties_id_lookup_set_from_id(PointerRNA *ptr, const ID *id)
wmOperatorType * WM_operatortype_find(const char *idname, bool quiet)
uint8_t flag
Definition wm_window.cc:145