Blender V4.3
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
9#include "BLI_path_utils.hh"
10#include "BLI_rect.h"
11#include "BLI_string.h"
12
13#include "ED_curves.hh"
14#include "ED_object.hh"
15#include "ED_screen.hh"
16#include "ED_select_utils.hh"
17#include "ED_view3d.hh"
18
19#include "WM_api.hh"
20
21#include "BKE_asset.hh"
22#include "BKE_attribute_math.hh"
24#include "BKE_context.hh"
25#include "BKE_curves.hh"
26#include "BKE_customdata.hh"
27#include "BKE_editmesh.hh"
28#include "BKE_geometry_set.hh"
29#include "BKE_layer.hh"
30#include "BKE_lib_id.hh"
31#include "BKE_lib_query.hh"
32#include "BKE_main.hh"
33#include "BKE_material.h"
34#include "BKE_mesh.hh"
35#include "BKE_mesh_wrapper.hh"
36#include "BKE_node_runtime.hh"
37#include "BKE_object.hh"
38#include "BKE_pointcloud.hh"
39#include "BKE_report.hh"
40#include "BKE_scene.hh"
41#include "BKE_screen.hh"
42#include "BKE_workspace.hh"
43
44#include "DNA_object_types.h"
45#include "DNA_scene_types.h"
46
47#include "DEG_depsgraph.hh"
50
51#include "RNA_access.hh"
52#include "RNA_define.hh"
53
54#include "UI_interface.hh"
55#include "UI_resources.hh"
56
57#include "ED_asset.hh"
59#include "ED_geometry.hh"
60#include "ED_mesh.hh"
61#include "ED_sculpt.hh"
62
63#include "BLT_translation.hh"
64
66
69
70#include "AS_asset_catalog.hh"
73#include "AS_asset_library.hh"
75#include "BKE_paint.hh"
76
77#include "geometry_intern.hh"
78
80
81namespace blender::ed::geometry {
82
83/* -------------------------------------------------------------------- */
89 ReportList *reports)
90{
91 Main &bmain = *CTX_data_main(&C);
92 if (bNodeTree *group = reinterpret_cast<bNodeTree *>(
94 {
95 return group;
96 }
97
100 if (!asset) {
101 return nullptr;
102 }
103 return reinterpret_cast<bNodeTree *>(asset::asset_local_id_ensure_imported(bmain, *asset));
104}
105
106static const bNodeTree *get_node_group(const bContext &C, PointerRNA &ptr, ReportList *reports)
107{
108 const bNodeTree *group = get_asset_or_local_node_group(C, ptr, reports);
109 if (!group) {
110 return nullptr;
111 }
112 if (group->type != NTREE_GEOMETRY) {
113 if (reports) {
114 BKE_report(reports, RPT_ERROR, "Asset is not a geometry node group");
115 }
116 return nullptr;
117 }
118 return group;
119}
120
122
129{
130 static GeoOperatorLog log;
131 return log;
132}
133
138
140static void find_socket_log_contexts(const Main &bmain,
141 Set<ComputeContextHash> &r_socket_log_contexts)
142{
143 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain.wm.first);
144 if (wm == nullptr) {
145 return;
146 }
147 LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) {
148 const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
149 LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
150 const SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
151 if (sl->spacetype == SPACE_NODE) {
152 const SpaceNode &snode = *reinterpret_cast<const SpaceNode *>(sl);
153 if (snode.edittree == nullptr) {
154 continue;
155 }
156 ComputeContextBuilder compute_context_builder;
157 compute_context_builder.push<bke::OperatorComputeContext>();
159 geo_log::GeoModifierLog::get_context_hash_by_zone_for_node_editor(
160 snode, compute_context_builder);
161 for (const ComputeContextHash &hash : hash_by_zone.values()) {
162 r_socket_log_contexts.add(hash);
163 }
164 }
165 }
166 }
167}
168
176 nodes::GeoNodesOperatorData &operator_data)
177{
178 switch (object.type) {
179 case OB_CURVES: {
180 Curves *curves = BKE_curves_copy_for_eval(static_cast<const Curves *>(object.data));
181 return bke::GeometrySet::from_curves(curves);
182 }
183 case OB_POINTCLOUD: {
185 static_cast<const PointCloud *>(object.data));
187 }
188 case OB_MESH: {
189 const Mesh *mesh = static_cast<const Mesh *>(object.data);
190 if (std::shared_ptr<BMEditMesh> &em = mesh->runtime->edit_mesh) {
192 operator_data.active_edge_index = BM_mesh_active_edge_index_get(em->bm);
193 operator_data.active_face_index = BM_mesh_active_face_index_get(em->bm, false, true);
194 Mesh *mesh_copy = BKE_mesh_wrapper_from_editmesh(em, nullptr, mesh);
196 Mesh *final_copy = BKE_mesh_copy_for_eval(*mesh_copy);
197 BKE_id_free(nullptr, mesh_copy);
198 return bke::GeometrySet::from_mesh(final_copy);
199 }
201 }
202 default:
203 return {};
204 }
205}
206
208 const wmOperator &op, Main &bmain, Scene &scene, Object &object, bke::GeometrySet geometry)
209{
210 geometry.ensure_owns_direct_data();
211 switch (object.type) {
212 case OB_CURVES: {
213 Curves &curves = *static_cast<Curves *>(object.data);
214 Curves *new_curves = geometry.get_curves_for_write();
215 if (!new_curves) {
216 curves.geometry.wrap() = {};
217 break;
218 }
219
220 /* Anonymous attributes shouldn't be available on the applied geometry. */
221 new_curves->geometry.wrap().attributes_for_write().remove_anonymous();
222
223 curves.geometry.wrap() = std::move(new_curves->geometry.wrap());
224 BKE_object_material_from_eval_data(&bmain, &object, &new_curves->id);
225 break;
226 }
227 case OB_POINTCLOUD: {
228 PointCloud &points = *static_cast<PointCloud *>(object.data);
229 PointCloud *new_points =
230 geometry.get_component_for_write<bke::PointCloudComponent>().release();
231 if (!new_points) {
232 CustomData_free(&points.pdata, points.totpoint);
233 points.totpoint = 0;
234 break;
235 }
236
237 /* Anonymous attributes shouldn't be available on the applied geometry. */
238 new_points->attributes_for_write().remove_anonymous();
239
240 BKE_object_material_from_eval_data(&bmain, &object, &new_points->id);
241 BKE_pointcloud_nomain_to_pointcloud(new_points, &points);
242 break;
243 }
244 case OB_MESH: {
245 Mesh &mesh = *static_cast<Mesh *>(object.data);
246
247 const bool has_shape_keys = mesh.key != nullptr;
248
249 if (object.mode == OB_MODE_SCULPT) {
250 sculpt_paint::undo::geometry_begin(scene, object, &op);
251 }
252
253 Mesh *new_mesh = geometry.get_component_for_write<bke::MeshComponent>().release();
254 if (!new_mesh) {
256 }
257 else {
258 /* Anonymous attributes shouldn't be available on the applied geometry. */
259 new_mesh->attributes_for_write().remove_anonymous();
260
261 BKE_object_material_from_eval_data(&bmain, &object, &new_mesh->id);
262 if (object.mode == OB_MODE_EDIT) {
263 EDBM_mesh_make_from_mesh(&object, new_mesh, scene.toolsettings->selectmode, true);
264 BKE_editmesh_looptris_and_normals_calc(mesh.runtime->edit_mesh.get());
265 BKE_id_free(nullptr, new_mesh);
266 }
267 else {
268 BKE_mesh_nomain_to_mesh(new_mesh, &mesh, &object);
269 }
270 }
271
272 if (has_shape_keys && !mesh.key) {
273 BKE_report(op.reports, RPT_WARNING, "Mesh shape key data removed");
274 }
275
276 if (object.mode == OB_MODE_SCULPT) {
279 }
280 break;
281 }
282 }
283}
284
291{
292 const int orig_size = ids.size();
293
294 bool needs_own_transform_relation = false;
295 bool needs_scene_camera_relation = false;
297 node_tree, ids, needs_own_transform_relation, needs_scene_camera_relation);
298 if (ids.size() != orig_size) {
299 /* Only evaluate the node group if it references data-blocks. In that case it needs to be
300 * evaluated so that ID pointers are switched to point to evaluated data-blocks. */
301 ids.add(const_cast<ID *>(&node_tree.id));
302 }
303}
304
306 const StringRef identifier)
307{
308 for (const bNodeTreeInterfaceSocket *input : node_group.interface_inputs()) {
309 if (input->identifier == identifier) {
310 return input;
311 }
312 }
313 return nullptr;
314}
315
316static std::optional<ID_Type> socket_type_to_id_type(const eNodeSocketDatatype socket_type)
317{
318 switch (socket_type) {
319 case SOCK_CUSTOM:
320 case SOCK_FLOAT:
321 case SOCK_VECTOR:
322 case SOCK_RGBA:
323 case SOCK_SHADER:
324 case SOCK_BOOLEAN:
325 case SOCK_INT:
326 case SOCK_STRING:
327 case SOCK_GEOMETRY:
328 case SOCK_ROTATION:
329 case SOCK_MENU:
330 case SOCK_MATRIX:
331 return std::nullopt;
332 case SOCK_OBJECT:
333 return ID_OB;
334 case SOCK_IMAGE:
335 return ID_IM;
336 case SOCK_COLLECTION:
337 return ID_GR;
338 case SOCK_TEXTURE:
339 return ID_TE;
340 case SOCK_MATERIAL:
341 return ID_MA;
342 }
343 return std::nullopt;
344}
345
352 const bNodeTree &node_group,
353 const IDProperty &properties)
354{
357 &const_cast<IDProperty &>(properties), IDP_TYPE_FILTER_STRING, [&](IDProperty *prop) {
359 prop->name);
360 if (!input) {
361 return;
362 }
363 const std::optional<ID_Type> id_type = socket_type_to_id_type(
364 eNodeSocketDatatype(input->socket_typeinfo()->type));
365 if (!id_type) {
366 return;
367 }
368 const char *id_name = IDP_String(prop);
369 ID *id = BKE_libblock_find_name(&const_cast<Main &>(bmain), *id_type, id_name);
370 if (!id) {
371 return;
372 }
373 ids.add(prop->name, id);
374 });
375 return ids;
376}
377
378static Depsgraph *build_extra_depsgraph(const Depsgraph &depsgraph_active, const Set<ID *> &ids)
379{
380 Depsgraph *depsgraph = DEG_graph_new(DEG_get_bmain(&depsgraph_active),
381 DEG_get_input_scene(&depsgraph_active),
382 DEG_get_input_view_layer(&depsgraph_active),
383 DEG_get_mode(&depsgraph_active));
386 return depsgraph;
387}
388
390 const Map<StringRef, ID *> &input_ids)
391{
392 IDProperty *properties = bke::idprop::create_group("Exec Properties").release();
393 IDP_foreach_property(&const_cast<IDProperty &>(op_properties), 0, [&](IDProperty *prop) {
394 if (ID *id = input_ids.lookup_default(prop->name, nullptr)) {
395 IDP_AddToGroup(properties, bke::idprop::create(prop->name, id).release());
396 }
397 else {
398 IDP_AddToGroup(properties, IDP_CopyProperty(prop));
399 }
400 });
401 return properties;
402}
403
405 IDProperty &properties, const nodes::GeoNodesOperatorDepsgraphs &depsgraphs)
406{
407 IDP_foreach_property(&properties, IDP_TYPE_FILTER_ID, [&](IDProperty *property) {
408 if (ID *id = IDP_Id(property)) {
409 property->data.pointer = const_cast<ID *>(depsgraphs.get_evaluated_id(*id));
410 }
411 });
412}
413
414static bool object_has_editable_data(const Main &bmain, const Object &object)
415{
416 if (!ELEM(object.type, OB_CURVES, OB_POINTCLOUD, OB_MESH)) {
417 return false;
418 }
419 if (!BKE_id_is_editable(&bmain, static_cast<const ID *>(object.data))) {
420 return false;
421 }
422 return true;
423}
424
426 const Main &bmain,
427 const eObjectMode mode)
428{
429 Vector<Object *> objects;
430 Set<const ID *> unique_object_data;
431
432 auto handle_object = [&](Object *object) {
433 if (object->mode != mode) {
434 return;
435 }
436 if (!unique_object_data.add(static_cast<const ID *>(object->data))) {
437 return;
438 }
439 if (!object_has_editable_data(bmain, *object)) {
440 return;
441 }
442 objects.append(object);
443 };
444
445 if (mode == OB_MODE_OBJECT) {
446 CTX_DATA_BEGIN (&C, Object *, object, selected_objects) {
447 handle_object(object);
448 }
450 }
451 else {
452 Scene *scene = CTX_data_scene(&C);
453 ViewLayer *view_layer = CTX_data_view_layer(&C);
454 View3D *v3d = CTX_wm_view3d(&C);
455 Object *active_object = CTX_data_active_object(&C);
456 if (v3d && active_object) {
457 FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, active_object->type, mode, ob) {
458 handle_object(ob);
459 }
461 }
462 }
463 return objects;
464}
465
467{
468 Main *bmain = CTX_data_main(C);
469 Scene *scene = CTX_data_scene(C);
470 Object *active_object = CTX_data_active_object(C);
471 if (!active_object) {
472 return OPERATOR_CANCELLED;
473 }
474 const eObjectMode mode = eObjectMode(active_object->mode);
475
476 const bNodeTree *node_tree_orig = get_node_group(*C, *op->ptr, op->reports);
477 if (!node_tree_orig) {
478 return OPERATOR_CANCELLED;
479 }
480
481 const Vector<Object *> objects = gather_supported_objects(*C, *bmain, mode);
482
483 Depsgraph *depsgraph_active = CTX_data_ensure_evaluated_depsgraph(C);
484 Set<ID *> extra_ids;
485 gather_node_group_ids(*node_tree_orig, extra_ids);
486 const Map<StringRef, ID *> input_ids = gather_input_ids(
487 *bmain, *node_tree_orig, *op->properties);
488 for (ID *id : input_ids.values()) {
489 /* Skip IDs that are already fully evaluated in the active depsgraph. */
490 if (!DEG_id_is_fully_evaluated(depsgraph_active, id)) {
491 extra_ids.add(id);
492 }
493 }
494
495 const nodes::GeoNodesOperatorDepsgraphs depsgraphs{
496 depsgraph_active,
497 extra_ids.is_empty() ? nullptr : build_extra_depsgraph(*depsgraph_active, extra_ids),
498 };
499
500 IDProperty *properties = replace_strings_with_id_pointers(*op->properties, input_ids);
501 BLI_SCOPED_DEFER([&]() { IDP_FreeProperty_ex(properties, false); });
502
503 replace_inputs_evaluated_data_blocks(*properties, depsgraphs);
504
505 const bNodeTree *node_tree = nullptr;
506 if (depsgraphs.extra) {
507 node_tree = reinterpret_cast<const bNodeTree *>(
508 DEG_get_evaluated_id(depsgraphs.extra, const_cast<ID *>(&node_tree_orig->id)));
509 }
510 else {
511 node_tree = node_tree_orig;
512 }
513
514 const nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info =
516 if (lf_graph_info == nullptr) {
517 BKE_report(op->reports, RPT_ERROR, "Cannot evaluate node group");
518 return OPERATOR_CANCELLED;
519 }
520
521 if (!node_tree->group_output_node()) {
522 BKE_report(op->reports, RPT_ERROR, "Node group must have a group output node");
523 return OPERATOR_CANCELLED;
524 }
525 if (node_tree->interface_outputs().is_empty() ||
526 !STREQ(node_tree->interface_outputs()[0]->socket_type, "NodeSocketGeometry"))
527 {
528 BKE_report(op->reports, RPT_ERROR, "Node group's first output must be a geometry");
529 return OPERATOR_CANCELLED;
530 }
531
532 bke::OperatorComputeContext compute_context;
533 Set<ComputeContextHash> socket_log_contexts;
535 eval_log.log = std::make_unique<geo_log::GeoModifierLog>();
536 eval_log.node_group_name = node_tree->id.name + 2;
537 find_socket_log_contexts(*bmain, socket_log_contexts);
538
539 for (Object *object : objects) {
540 nodes::GeoNodesOperatorData operator_eval_data{};
541 operator_eval_data.mode = mode;
542 operator_eval_data.depsgraphs = &depsgraphs;
543 operator_eval_data.self_object_orig = object;
544 operator_eval_data.scene_orig = scene;
545 RNA_int_get_array(op->ptr, "mouse_position", operator_eval_data.mouse_position);
546 RNA_int_get_array(op->ptr, "region_size", operator_eval_data.region_size);
547 RNA_float_get_array(op->ptr, "cursor_position", operator_eval_data.cursor_position);
548 RNA_float_get_array(op->ptr, "cursor_rotation", &operator_eval_data.cursor_rotation.w);
550 op->ptr, "viewport_projection_matrix", operator_eval_data.viewport_winmat.base_ptr());
552 op->ptr, "viewport_view_matrix", operator_eval_data.viewport_viewmat.base_ptr());
553 operator_eval_data.viewport_is_perspective = RNA_boolean_get(op->ptr,
554 "viewport_is_perspective");
555
556 nodes::GeoNodesCallData call_data{};
557 call_data.operator_data = &operator_eval_data;
558 call_data.eval_log = eval_log.log.get();
559 if (object == active_object) {
560 /* Only log values from the active object. */
561 call_data.socket_log_contexts = &socket_log_contexts;
562 }
563
564 bke::GeometrySet geometry_orig = get_original_geometry_eval_copy(*object, operator_eval_data);
565
567 *node_tree, properties, compute_context, call_data, std::move(geometry_orig));
568
569 store_result_geometry(*op, *bmain, *scene, *object, std::move(new_geometry));
570
571 DEG_id_tag_update(static_cast<ID *>(object->data), ID_RECALC_GEOMETRY);
572 WM_event_add_notifier(C, NC_GEOM | ND_DATA, object->data);
573 }
574
575 geo_log::GeoTreeLog &tree_log = eval_log.log->get_tree_log(compute_context.hash());
577 for (const geo_log::NodeWarning &warning : tree_log.all_warnings) {
578 if (warning.type == geo_log::NodeWarningType::Info) {
579 BKE_report(op->reports, RPT_INFO, warning.message.c_str());
580 }
581 else {
582 BKE_report(op->reports, RPT_WARNING, warning.message.c_str());
583 }
584 }
585
586 return OPERATOR_FINISHED;
587}
588
601 wmOperator &op,
602 const wmEvent &event)
603{
604 Scene *scene = CTX_data_scene(&C);
605 /* NOTE: `region` and `rv3d` may be null when called from a script. */
606 const ARegion *region = CTX_wm_region(&C);
607 const RegionView3D *rv3d = CTX_wm_region_view3d(&C);
608
609 /* Mouse position node inputs. */
610 RNA_int_set_array(op.ptr, "mouse_position", event.mval);
612 op.ptr,
613 "region_size",
614 region ? int2(BLI_rcti_size_x(&region->winrct), BLI_rcti_size_y(&region->winrct)) : int2(0));
615
616 /* 3D cursor node inputs. */
617 const View3DCursor &cursor = scene->cursor;
618 RNA_float_set_array(op.ptr, "cursor_position", cursor.location);
619 math::Quaternion cursor_rotation = cursor.rotation();
620 RNA_float_set_array(op.ptr, "cursor_rotation", &cursor_rotation.w);
621
622 /* Viewport transform node inputs. */
624 "viewport_projection_matrix",
625 rv3d ? float4x4(rv3d->winmat).base_ptr() : float4x4::identity().base_ptr());
627 "viewport_view_matrix",
628 rv3d ? float4x4(rv3d->viewmat).base_ptr() : float4x4::identity().base_ptr());
629 RNA_boolean_set(op.ptr, "viewport_is_perspective", rv3d ? bool(rv3d->is_persp) : true);
630}
631
632static int run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent *event)
633{
634 const bNodeTree *node_tree = get_node_group(*C, *op->ptr, op->reports);
635 if (!node_tree) {
636 return OPERATOR_CANCELLED;
637 }
638
639 store_input_node_values_rna_props(*C, *op, *event);
640
641 nodes ::update_input_properties_from_node_tree(
642 *node_tree, op->properties, *op->properties, true);
644
645 return run_node_group_exec(C, op);
646}
647
649 wmOperatorType * /*ot*/,
651{
654 if (!asset) {
655 return "";
656 }
657 if (!asset->get_metadata().description) {
658 return "";
659 }
660 return asset->get_metadata().description;
661}
662
664 PointerRNA *md_ptr,
665 const bNodeTreeInterfaceSocket &socket)
666{
668 const eNodeSocketDatatype socket_type = eNodeSocketDatatype(typeinfo->type);
669
670 char socket_id_esc[MAX_NAME * 2];
671 BLI_str_escape(socket_id_esc, socket.identifier, sizeof(socket_id_esc));
672 const std::string rna_path = "[\"" + std::string(socket_id_esc) + "\"]";
673 const std::string rna_path_use_attribute = "[\"" + std::string(socket_id_esc) +
675 const std::string rna_path_attribute_name = "[\"" + std::string(socket_id_esc) +
677
678 /* We're handling this manually in this case. */
679 uiLayoutSetPropDecorate(layout, false);
680
681 uiLayout *split = uiLayoutSplit(layout, 0.4f, false);
682 uiLayout *name_row = uiLayoutRow(split, false);
684
685 const bool use_attribute = RNA_boolean_get(md_ptr, rna_path_use_attribute.c_str());
686 if (socket_type == SOCK_BOOLEAN && !use_attribute) {
687 uiItemL(name_row, "", ICON_NONE);
688 }
689 else {
690 uiItemL(name_row, socket.name ? socket.name : "", ICON_NONE);
691 }
692
693 uiLayout *prop_row = uiLayoutRow(split, true);
694 if (socket_type == SOCK_BOOLEAN) {
695 uiLayoutSetPropSep(prop_row, false);
697 }
698
699 if (use_attribute) {
700 /* TODO: Add attribute search. */
701 uiItemR(prop_row, md_ptr, rna_path_attribute_name.c_str(), UI_ITEM_NONE, "", ICON_NONE);
702 }
703 else {
704 const char *name = socket_type == SOCK_BOOLEAN ? (socket.name ? socket.name : "") : "";
705 uiItemR(prop_row, md_ptr, rna_path.c_str(), UI_ITEM_NONE, name, ICON_NONE);
706 }
707
708 uiItemR(
709 prop_row, md_ptr, rna_path_use_attribute.c_str(), UI_ITEM_R_ICON_ONLY, "", ICON_SPREADSHEET);
710}
711
713 uiLayout *layout,
714 IDProperty *op_properties,
715 PointerRNA *bmain_ptr,
716 PointerRNA *op_ptr,
717 const bNodeTreeInterfaceSocket &socket,
718 const int socket_index)
719{
721 const eNodeSocketDatatype socket_type = eNodeSocketDatatype(typeinfo->type);
722
723 /* The property should be created in #MOD_nodes_update_interface with the correct type. */
724 IDProperty *property = IDP_GetPropertyFromGroup(op_properties, socket.identifier);
725
726 /* IDProperties can be removed with python, so there could be a situation where
727 * there isn't a property for a socket or it doesn't have the correct type. */
728 if (property == nullptr || !nodes::id_property_type_matches_socket(socket, *property, true)) {
729 return;
730 }
731
732 char socket_id_esc[MAX_NAME * 2];
733 BLI_str_escape(socket_id_esc, socket.identifier, sizeof(socket_id_esc));
734
735 char rna_path[sizeof(socket_id_esc) + 4];
736 SNPRINTF(rna_path, "[\"%s\"]", socket_id_esc);
737
738 uiLayout *row = uiLayoutRow(layout, true);
739 uiLayoutSetPropDecorate(row, false);
740
741 /* Use #uiItemPointerR to draw pointer properties because #uiItemR would not have enough
742 * information about what type of ID to select for editing the values. This is because
743 * pointer IDProperties contain no information about their type. */
744 const char *name = socket.name ? socket.name : "";
745 switch (socket_type) {
746 case SOCK_OBJECT:
747 uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "objects", name, ICON_OBJECT_DATA);
748 break;
749 case SOCK_COLLECTION:
751 row, op_ptr, rna_path, bmain_ptr, "collections", name, ICON_OUTLINER_COLLECTION);
752 break;
753 case SOCK_MATERIAL:
754 uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "materials", name, ICON_MATERIAL);
755 break;
756 case SOCK_TEXTURE:
757 uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "textures", name, ICON_TEXTURE);
758 break;
759 case SOCK_IMAGE:
760 uiItemPointerR(row, op_ptr, rna_path, bmain_ptr, "images", name, ICON_IMAGE);
761 break;
762 default:
763 if (nodes::input_has_attribute_toggle(node_tree, socket_index)) {
764 add_attribute_search_or_value_buttons(row, op_ptr, socket);
765 }
766 else {
767 uiItemR(row, op_ptr, rna_path, UI_ITEM_NONE, name, ICON_NONE);
768 }
769 }
770 if (!nodes::input_has_attribute_toggle(node_tree, socket_index)) {
771 uiItemL(row, "", ICON_BLANK1);
772 }
773}
774
776{
777 uiLayout *layout = op->layout;
778 uiLayoutSetPropSep(layout, true);
779 uiLayoutSetPropDecorate(layout, false);
780 Main *bmain = CTX_data_main(C);
781 PointerRNA bmain_ptr = RNA_main_pointer_create(bmain);
782
783 const bNodeTree *node_tree = get_node_group(*C, *op->ptr, nullptr);
784 if (!node_tree) {
785 return;
786 }
787
788 node_tree->ensure_interface_cache();
789 int input_index = 0;
790 for (const bNodeTreeInterfaceSocket *io_socket : node_tree->interface_inputs()) {
792 *node_tree, layout, op->properties, &bmain_ptr, op->ptr, *io_socket, input_index);
793 ++input_index;
794 }
795}
796
798{
799 bool result = false;
800 RNA_STRUCT_BEGIN (ptr, prop) {
801 int flag = RNA_property_flag(prop);
802 if ((flag & PROP_HIDDEN) == 0) {
803 result = true;
804 break;
805 }
806 }
808 return result;
809}
810
812{
813 int len;
814 char *local_name = RNA_string_get_alloc(ptr, "name", nullptr, 0, &len);
815 BLI_SCOPED_DEFER([&]() { MEM_SAFE_FREE(local_name); })
816 if (len > 0) {
817 return std::string(local_name, len);
818 }
819 char *library_asset_identifier = RNA_string_get_alloc(
820 ptr, "relative_asset_identifier", nullptr, 0, &len);
821 BLI_SCOPED_DEFER([&]() { MEM_SAFE_FREE(library_asset_identifier); })
822 StringRef ref(library_asset_identifier, len);
823 return ref.drop_prefix(ref.find_last_of(SEP_STR) + 1);
824}
825
827{
828 if (!ptr) {
829 return false;
830 }
831 Main &bmain = *CTX_data_main(&C);
832 if (bNodeTree *group = reinterpret_cast<bNodeTree *>(
834 {
835 return group->geometry_node_asset_traits &&
836 (group->geometry_node_asset_traits->flag & GEO_NODE_ASSET_WAIT_FOR_CURSOR) != 0;
837 }
838
841 if (!asset) {
842 return false;
843 }
844 const IDProperty *traits_flag = BKE_asset_metadata_idprop_find(
845 &asset->get_metadata(), "geometry_node_asset_traits_flag");
846 if (traits_flag == nullptr || !(IDP_Int(traits_flag) & GEO_NODE_ASSET_WAIT_FOR_CURSOR)) {
847 return false;
848 }
849 return true;
850}
851
853{
854 PropertyRNA *prop;
855 ot->name = "Run Node Group";
856 ot->idname = __func__;
857 ot->description = "Execute a node group on geometry";
858
859 /* A proper poll is not possible, since it doesn't have access to the operator's properties. */
867
869
872
873 /* See comment for #store_input_node_values_rna_props. */
874 prop = RNA_def_int_array(ot->srna,
875 "mouse_position",
876 2,
877 nullptr,
878 INT_MIN,
879 INT_MAX,
880 "Mouse Position",
881 "Mouse coordinates in region space",
882 INT_MIN,
883 INT_MAX);
885 prop = RNA_def_int_array(
886 ot->srna, "region_size", 2, nullptr, 0, INT_MAX, "Region Size", "", 0, INT_MAX);
889 "cursor_position",
890 3,
891 nullptr,
892 FLT_MIN,
893 FLT_MAX,
894 "3D Cursor Position",
895 "",
896 FLT_MIN,
897 FLT_MAX);
900 "cursor_rotation",
901 4,
902 nullptr,
903 FLT_MIN,
904 FLT_MAX,
905 "3D Cursor Rotation",
906 "",
907 FLT_MIN,
908 FLT_MAX);
911 "viewport_projection_matrix",
912 16,
913 nullptr,
914 FLT_MIN,
915 FLT_MAX,
916 "Viewport Projection Transform",
917 "",
918 FLT_MIN,
919 FLT_MAX);
922 "viewport_view_matrix",
923 16,
924 nullptr,
925 FLT_MIN,
926 FLT_MAX,
927 "Viewport View Transform",
928 "",
929 FLT_MIN,
930 FLT_MAX);
932 prop = RNA_def_boolean(
933 ot->srna, "viewport_is_perspective", false, "Viewport Is Perspective", "");
935}
936
939/* -------------------------------------------------------------------- */
943static bool asset_menu_poll(const bContext *C, MenuType * /*mt*/)
944{
945 return CTX_wm_view3d(C);
946}
947
949 const eObjectMode mode)
950{
951 switch (type) {
952 case OB_MESH: {
953 switch (mode) {
954 case OB_MODE_OBJECT:
956 case OB_MODE_EDIT:
958 case OB_MODE_SCULPT:
960 default:
961 break;
962 }
963 break;
964 }
965 case OB_CURVES: {
966 switch (mode) {
967 case OB_MODE_OBJECT:
969 case OB_MODE_EDIT:
973 default:
974 break;
975 }
976 break;
977 }
978 case OB_POINTCLOUD: {
979 switch (mode) {
980 case OB_MODE_OBJECT:
982 case OB_MODE_EDIT:
984 default:
985 break;
986 }
987 break;
988 }
989 default:
990 break;
991 }
994}
995
997{
998 return asset_flag_for_context(ObjectType(active_object.type), eObjectMode(active_object.mode));
999}
1000
1002{
1003 switch (type) {
1004 case OB_MESH: {
1005 switch (mode) {
1006 case OB_MODE_OBJECT: {
1008 return &tree;
1009 }
1010 case OB_MODE_EDIT: {
1012 return &tree;
1013 }
1014 case OB_MODE_SCULPT: {
1016 return &tree;
1017 }
1018 default:
1019 return nullptr;
1020 }
1021 }
1022 case OB_CURVES: {
1023 switch (mode) {
1024 case OB_MODE_OBJECT: {
1026 return &tree;
1027 }
1028 case OB_MODE_EDIT: {
1030 return &tree;
1031 }
1032 case OB_MODE_SCULPT_CURVES: {
1034 return &tree;
1035 }
1036 default:
1037 return nullptr;
1038 }
1039 }
1040 case OB_POINTCLOUD: {
1041 switch (mode) {
1042 case OB_MODE_OBJECT: {
1044 return &tree;
1045 }
1046 case OB_MODE_EDIT: {
1048 return &tree;
1049 }
1050 default:
1051 return nullptr;
1052 }
1053 }
1054 default:
1055 return nullptr;
1056 }
1057}
1058
1060{
1061 return get_static_item_tree(ObjectType(active_object.type), eObjectMode(active_object.mode));
1062}
1063
1065{
1066 for (const ObjectType type : {OB_MESH, OB_CURVES, OB_POINTCLOUD}) {
1067 for (const eObjectMode mode :
1069 {
1070 if (asset::AssetItemTree *tree = get_static_item_tree(type, mode)) {
1071 tree->dirty = true;
1072 }
1073 }
1074 }
1075}
1076
1077static asset::AssetItemTree build_catalog_tree(const bContext &C, const Object &active_object)
1078{
1079 asset::AssetFilterSettings type_filter{};
1080 type_filter.id_types = FILTER_ID_NT;
1082 auto meta_data_filter = [&](const AssetMetaData &meta_data) {
1083 const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
1084 if (tree_type == nullptr || IDP_Int(tree_type) != NTREE_GEOMETRY) {
1085 return false;
1086 }
1087 const IDProperty *traits_flag = BKE_asset_metadata_idprop_find(
1088 &meta_data, "geometry_node_asset_traits_flag");
1089 if (traits_flag == nullptr || (IDP_Int(traits_flag) & flag) != flag) {
1090 return false;
1091 }
1092 return true;
1093 };
1096 return asset::build_filtered_all_catalog_tree(library, C, type_filter, meta_data_filter);
1097}
1098
1104static Set<std::string> get_builtin_menus(const ObjectType object_type, const eObjectMode mode)
1105{
1106 Set<std::string> menus;
1107 switch (object_type) {
1108 case OB_CURVES:
1109 menus.add_new("View");
1110 menus.add_new("Select");
1111 menus.add_new("Curves");
1112 break;
1113 case OB_POINTCLOUD:
1114 menus.add_new("View");
1115 menus.add_new("Select");
1116 menus.add_new("Point Cloud");
1117 break;
1118 case OB_MESH:
1119 switch (mode) {
1120 case OB_MODE_OBJECT:
1121 menus.add_new("View");
1122 menus.add_new("Select");
1123 menus.add_new("Add");
1124 menus.add_new("Object");
1125 menus.add_new("Object/Apply");
1126 menus.add_new("Object/Convert");
1127 menus.add_new("Object/Quick Effects");
1128 break;
1129 case OB_MODE_EDIT:
1130 menus.add_new("View");
1131 menus.add_new("Select");
1132 menus.add_new("Add");
1133 menus.add_new("Mesh");
1134 menus.add_new("Mesh/Extrude");
1135 menus.add_new("Mesh/Clean Up");
1136 menus.add_new("Mesh/Delete");
1137 menus.add_new("Mesh/Merge");
1138 menus.add_new("Mesh/Normals");
1139 menus.add_new("Mesh/Shading");
1140 menus.add_new("Mesh/Split");
1141 menus.add_new("Mesh/Weights");
1142 menus.add_new("Vertex");
1143 menus.add_new("Edge");
1144 menus.add_new("Face");
1145 menus.add_new("Face/Face Data");
1146 menus.add_new("UV");
1147 menus.add_new("UV/Unwrap");
1148 break;
1149 case OB_MODE_SCULPT:
1150 menus.add_new("View");
1151 menus.add_new("Sculpt");
1152 menus.add_new("Mask");
1153 menus.add_new("Face Sets");
1154 break;
1156 menus.add_new("View");
1157 menus.add_new("Paint");
1158 break;
1160 menus.add_new("View");
1161 menus.add_new("Weights");
1162 break;
1163 default:
1164 break;
1165 }
1166 default:
1167 break;
1168 }
1169 return menus;
1170}
1171
1172static void catalog_assets_draw(const bContext *C, Menu *menu)
1173{
1174 const Object *active_object = CTX_data_active_object(C);
1175 if (!active_object) {
1176 return;
1177 }
1179 if (!tree) {
1180 return;
1181 }
1182 const std::optional<StringRefNull> menu_path = CTX_data_string_get(C, "asset_catalog_path");
1183 if (!menu_path) {
1184 return;
1185 }
1186 const Span<asset_system::AssetRepresentation *> assets = tree->assets_per_path.lookup(
1187 menu_path->data());
1188 const asset_system::AssetCatalogTreeItem *catalog_item = tree->catalogs.find_item(
1189 menu_path->data());
1190 BLI_assert(catalog_item != nullptr);
1191
1192 uiLayout *layout = menu->layout;
1193 bool add_separator = true;
1194
1195 wmOperatorType *ot = WM_operatortype_find("GEOMETRY_OT_execute_node_group", true);
1196 for (const asset_system::AssetRepresentation *asset : assets) {
1197 if (add_separator) {
1198 uiItemS(layout);
1199 add_separator = false;
1200 }
1201 PointerRNA props_ptr;
1202 uiItemFullO_ptr(layout,
1203 ot,
1204 IFACE_(asset->get_name().c_str()),
1205 ICON_NONE,
1206 nullptr,
1209 &props_ptr);
1211 }
1212
1213 const Set<std::string> builtin_menus = get_builtin_menus(ObjectType(active_object->type),
1214 eObjectMode(active_object->mode));
1215
1218 if (!all_library) {
1219 return;
1220 }
1221
1222 catalog_item->foreach_child([&](const asset_system::AssetCatalogTreeItem &item) {
1223 if (builtin_menus.contains_as(item.catalog_path().str())) {
1224 return;
1225 }
1226 if (add_separator) {
1227 uiItemS(layout);
1228 add_separator = false;
1229 }
1230 asset::draw_menu_for_catalog(item, "GEO_MT_node_operator_catalog_assets", *layout);
1231 });
1232}
1233
1235{
1236 MenuType type{};
1237 STRNCPY(type.idname, "GEO_MT_node_operator_catalog_assets");
1238 type.poll = asset_menu_poll;
1239 type.draw = catalog_assets_draw;
1242 return type;
1243}
1244
1245static bool unassigned_local_poll(const bContext &C)
1246{
1247 Main &bmain = *CTX_data_main(&C);
1248 const Object *active_object = CTX_data_active_object(&C);
1249 if (!active_object) {
1250 return false;
1251 }
1253 LISTBASE_FOREACH (const bNodeTree *, group, &bmain.nodetrees) {
1254 /* Assets are displayed in other menus, and non-local data-blocks aren't added to this menu. */
1255 if (group->id.library_weak_reference || group->id.asset_data) {
1256 continue;
1257 }
1258 if (!group->geometry_node_asset_traits ||
1259 (group->geometry_node_asset_traits->flag & flag) != flag)
1260 {
1261 continue;
1262 }
1263 return true;
1264 }
1265 return false;
1266}
1267
1269{
1270 const Object *active_object = CTX_data_active_object(C);
1271 if (!active_object) {
1272 return;
1273 }
1275 if (!tree) {
1276 return;
1277 }
1278 uiLayout *layout = menu->layout;
1279 wmOperatorType *ot = WM_operatortype_find("GEOMETRY_OT_execute_node_group", true);
1280 for (const asset_system::AssetRepresentation *asset : tree->unassigned_assets) {
1281 PointerRNA props_ptr;
1282 uiItemFullO_ptr(layout,
1283 ot,
1284 IFACE_(asset->get_name().c_str()),
1285 ICON_NONE,
1286 nullptr,
1289 &props_ptr);
1291 }
1292
1294
1295 bool first = true;
1296 bool add_separator = !tree->unassigned_assets.is_empty();
1297 Main &bmain = *CTX_data_main(C);
1298 LISTBASE_FOREACH (const bNodeTree *, group, &bmain.nodetrees) {
1299 /* Assets are displayed in other menus, and non-local data-blocks aren't added to this menu. */
1300 if (group->id.library_weak_reference || group->id.asset_data) {
1301 continue;
1302 }
1303 if (!group->geometry_node_asset_traits ||
1304 (group->geometry_node_asset_traits->flag & flag) != flag)
1305 {
1306 continue;
1307 }
1308
1309 if (add_separator) {
1310 uiItemS(layout);
1311 add_separator = false;
1312 }
1313 if (first) {
1314 uiItemL(layout, IFACE_("Non-Assets"), ICON_NONE);
1315 first = false;
1316 }
1317
1318 PointerRNA props_ptr;
1319 uiItemFullO_ptr(layout,
1320 ot,
1321 group->id.name + 2,
1322 ICON_NONE,
1323 nullptr,
1326 &props_ptr);
1327 WM_operator_properties_id_lookup_set_from_id(&props_ptr, &group->id);
1328 /* Also set the name so it can be used for #run_node_group_get_name. */
1329 RNA_string_set(&props_ptr, "name", group->id.name + 2);
1330 }
1331}
1332
1334{
1335 MenuType type{};
1336 STRNCPY(type.idname, "GEO_MT_node_operator_unassigned");
1337 type.poll = asset_menu_poll;
1341 type.description = N_(
1342 "Tool node group assets not assigned to a catalog.\n"
1343 "Catalogs can be assigned in the Asset Browser");
1344 return type;
1345}
1346
1348 const bContext &C,
1349 const StringRef catalog_path)
1350{
1351 const Object *active_object = CTX_data_active_object(&C);
1352 if (!active_object) {
1353 return;
1354 }
1356 if (!tree) {
1357 return;
1358 }
1359 const asset_system::AssetCatalogTreeItem *item = tree->catalogs.find_item(catalog_path);
1360 if (!item) {
1361 return;
1362 }
1365 if (!all_library) {
1366 return;
1367 }
1368 uiLayout *col = uiLayoutColumn(&layout, false);
1369 uiLayoutSetContextString(col, "asset_catalog_path", item->catalog_path().str());
1370 uiItemMContents(col, "GEO_MT_node_operator_catalog_assets");
1371}
1372
1374{
1375 const Object *active_object = CTX_data_active_object(&C);
1376 if (!active_object) {
1377 return;
1378 }
1380 if (!tree) {
1381 return;
1382 }
1383 if (tree->dirty) {
1384 *tree = build_catalog_tree(C, *active_object);
1385 }
1386
1387 const Set<std::string> builtin_menus = get_builtin_menus(ObjectType(active_object->type),
1388 eObjectMode(active_object->mode));
1389
1390 tree->catalogs.foreach_root_item([&](const asset_system::AssetCatalogTreeItem &item) {
1391 if (!builtin_menus.contains_as(item.catalog_path().str())) {
1392 asset::draw_menu_for_catalog(item, "GEO_MT_node_operator_catalog_assets", layout);
1393 }
1394 });
1395
1396 if (!tree->unassigned_assets.is_empty() || unassigned_local_poll(C)) {
1397 uiItemM(&layout, "GEO_MT_node_operator_unassigned", "", ICON_FILE_HIDDEN);
1398 }
1399}
1400
1403} // 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:186
#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.
void CustomData_free(CustomData *data, int totelem)
void BKE_editmesh_looptris_and_normals_calc(BMEditMesh *em)
Definition editmesh.cc:83
#define IDP_Int(prop)
#define IDP_Id(prop)
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:763
#define IDP_String(prop)
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1221
#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:1657
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2456
void BKE_id_free(Main *bmain, void *idv)
General operations, lookup, etc. for materials.
void BKE_object_material_from_eval_data(struct Main *bmain, struct Object *ob_orig, const struct ID *data_eval)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
void BKE_mesh_clear_geometry(Mesh *mesh)
Mesh * BKE_mesh_wrapper_from_editmesh(std::shared_ptr< BMEditMesh > em, const CustomData_MeshMasks *cd_mask_extra, const Mesh *me_settings)
void BKE_mesh_wrapper_ensure_mdata(Mesh *mesh)
General operations, lookup, etc. for blender objects.
void BKE_sculptsession_free_pbvh(Object &object)
Definition paint.cc:2099
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)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:613
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
#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:193
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
#define STRNCPY(dst, src)
Definition BLI_string.h:593
#define SNPRINTF(dst, format,...)
Definition BLI_string.h:597
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#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:273
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)
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)
ID * DEG_get_evaluated_id(const Depsgraph *depsgraph, ID *id)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
#define FILTER_ID_NT
Definition DNA_ID.h:1180
@ ID_TE
@ ID_IM
@ ID_NT
@ ID_MA
@ ID_GR
@ ID_OB
@ IDP_TYPE_FILTER_STRING
@ IDP_TYPE_FILTER_ID
#define MAX_NAME
Definition DNA_defs.h:50
@ NTREE_GEOMETRY
GeometryNodeAssetTraitFlag
@ GEO_NODE_ASSET_MESH
@ GEO_NODE_ASSET_POINT_CLOUD
@ GEO_NODE_ASSET_SCULPT
@ GEO_NODE_ASSET_WAIT_FOR_CURSOR
@ GEO_NODE_ASSET_CURVE
@ GEO_NODE_ASSET_EDIT
@ GEO_NODE_ASSET_TOOL
@ GEO_NODE_ASSET_OBJECT
eNodeSocketDatatype
@ SOCK_INT
@ SOCK_TEXTURE
@ SOCK_VECTOR
@ SOCK_BOOLEAN
@ SOCK_MATERIAL
@ SOCK_SHADER
@ SOCK_MATRIX
@ SOCK_FLOAT
@ SOCK_IMAGE
@ SOCK_COLLECTION
@ SOCK_CUSTOM
@ 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_OBJECT
@ OB_MODE_VERTEX_PAINT
Object is a sort of wrapper for general info.
@ OB_MESH
@ OB_POINTCLOUD
@ OB_CURVES
@ SPACE_NODE
void EDBM_mesh_make_from_mesh(Object *ob, Mesh *src_mesh, int select_mode, bool add_key_index)
#define MEM_SAFE_FREE(v)
#define RNA_STRUCT_BEGIN(sptr, prop)
#define RNA_STRUCT_END
@ PROP_HIDDEN
Definition RNA_types.hh:239
@ UI_LAYOUT_ALIGN_RIGHT
@ UI_LAYOUT_ALIGN_EXPAND
void uiItemL(uiLayout *layout, const char *name, int icon)
uiLayout * uiLayoutRow(uiLayout *layout, bool align)
void uiLayoutSetAlignment(uiLayout *layout, char alignment)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
void uiItemS(uiLayout *layout)
void uiItemFullO_ptr(uiLayout *layout, wmOperatorType *ot, const char *name, int icon, IDProperty *properties, wmOperatorCallContext context, eUI_Item_Flag flag, PointerRNA *r_opptr)
#define UI_ITEM_NONE
void uiItemPointerR(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *searchptr, const char *searchpropname, const char *name, int icon)
void uiItemMContents(uiLayout *layout, const char *menuname)
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
uiLayout * uiLayoutSplit(uiLayout *layout, float percentage, bool align)
void uiLayoutSetContextString(uiLayout *layout, const char *name, blender::StringRef value)
void uiItemM(uiLayout *layout, const char *menuname, const char *name, int icon)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_ICON_ONLY
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_GEOM
Definition WM_types.hh:360
#define ND_DATA
Definition WM_types.hh:475
@ WM_OP_INVOKE_REGION_WIN
Definition WM_types.hh:219
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)
const ComputeContextHash & hash() const
bool add(const Key &key, const Value &value)
Definition BLI_map.hh:271
Value lookup_default(const Key &key, const Value &default_value) const
Definition BLI_map.hh:531
ValueIterator values() const
Definition BLI_map.hh:846
Iterator begin() const
Definition BLI_set.hh:461
int64_t size() const
Definition BLI_set.hh:564
bool contains_as(const ForwardKey &key) const
Definition BLI_set.hh:295
Iterator end() const
Definition BLI_set.hh:471
bool add(const Key &key)
Definition BLI_set.hh:248
bool is_empty() const
Definition BLI_set.hh:572
void add_new(const Key &key)
Definition BLI_set.hh:233
void foreach_child(ItemIterFn callback) const
void ensure_node_warnings(const bNodeTree *tree)
std::string id_name(void *id)
const Depsgraph * depsgraph
int len
KDTree_3d * tree
uint col
ccl_device_inline float3 log(float3 v)
AssetLibraryReference all_library_reference()
void all_library_reload_catalogs_if_dirty()
std::unique_ptr< IDProperty, IDPropertyDeleter > create_group(StringRefNull prop_name, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_GROUP.
bNodeSocketType * node_socket_type_find(const char *idname)
Definition node.cc:1763
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={})
ID * asset_local_id_ensure_imported(Main &bmain, const asset_system::AssetRepresentation &asset)
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)
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 void add_attribute_search_or_value_buttons(uiLayout *layout, PointerRNA *md_ptr, const bNodeTreeInterfaceSocket &socket)
static GeometryNodeAssetTraitFlag asset_flag_for_context(const ObjectType type, const eObjectMode mode)
static bool unassigned_local_poll(const bContext &C)
static Vector< Object * > gather_supported_objects(const bContext &C, const Main &bmain, const eObjectMode mode)
MenuType node_group_operator_assets_menu_unassigned()
static int run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const GeoOperatorLog & node_group_operator_static_eval_log()
static asset::AssetItemTree * get_static_item_tree(const ObjectType type, const eObjectMode mode)
static void store_result_geometry(const wmOperator &op, Main &bmain, Scene &scene, Object &object, bke::GeometrySet geometry)
static IDProperty * replace_strings_with_id_pointers(const IDProperty &op_properties, const Map< StringRef, ID * > &input_ids)
static int run_node_group_exec(bContext *C, wmOperator *op)
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 bke::GeometrySet get_original_geometry_eval_copy(Object &object, nodes::GeoNodesOperatorData &operator_data)
static bool object_has_editable_data(const Main &bmain, const Object &object)
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 draw_property_for_socket(const bNodeTree &node_tree, uiLayout *layout, IDProperty *op_properties, PointerRNA *bmain_ptr, PointerRNA *op_ptr, const bNodeTreeInterfaceSocket &socket, const int socket_index)
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)
void geometry_begin(const Scene &scene, Object &ob, const wmOperator *op)
StringRef input_attribute_name_suffix()
StringRef input_use_attribute_suffix()
bool input_has_attribute_toggle(const bNodeTree &node_tree, const int socket_index)
void find_node_tree_dependencies(const bNodeTree &tree, Set< ID * > &r_ids, bool &r_needs_own_transform_relation, bool &r_needs_scene_camera_relation)
bool id_property_type_matches_socket(const bNodeTreeInterfaceSocket &socket, const IDProperty &property, const bool use_name_for_ids)
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)
VecBase< int32_t, 2 > int2
#define hash
Definition noise.c: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)
char * RNA_string_get_alloc(PointerRNA *ptr, const char *name, char *fixedbuf, int fixedlen, int *r_len)
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
void * pointer
Definition DNA_ID.h:145
char name[64]
Definition DNA_ID.h:163
IDPropertyData data
Definition DNA_ID.h:168
Definition DNA_ID.h:413
void * first
ListBase wm
Definition BKE_main.hh:239
ListBase nodetrees
Definition BKE_main.hh:234
uiLayout * layout
struct Key * key
float viewmat[4][4]
float winmat[4][4]
struct bNodeTree * edittree
const T * base_ptr() const
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)
Defines a socket type.
Definition BKE_node.hh:151
std::unique_ptr< nodes::geo_eval_log::GeoModifierLog > log
int mval[2]
Definition WM_types.hh:728
const char * name
Definition WM_types.hh:990
std::string(* get_description)(bContext *C, wmOperatorType *ot, PointerRNA *ptr)
Definition WM_types.hh:1074
bool(* depends_on_cursor)(bContext &C, wmOperatorType &ot, PointerRNA *ptr)
Definition WM_types.hh:1077
const char * idname
Definition WM_types.hh:992
std::string(* get_name)(wmOperatorType *ot, PointerRNA *ptr)
Definition WM_types.hh:1068
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
bool(* ui_poll)(wmOperatorType *ot, PointerRNA *ptr)
Definition WM_types.hh:1058
const char * description
Definition WM_types.hh:996
void(* ui)(bContext *C, wmOperator *op)
Definition WM_types.hh:1053
StructRNA * srna
Definition WM_types.hh:1080
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:4126
wmOperatorType * ot
Definition wm_files.cc:4125
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:138