Blender V4.5
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_index_mask.hh"
10#include "BLI_listbase.h"
11#include "BLI_path_utils.hh"
12#include "BLI_rect.h"
13#include "BLI_string.h"
14
15#include "ED_curves.hh"
16#include "ED_grease_pencil.hh"
17#include "ED_object.hh"
18#include "ED_screen.hh"
19#include "ED_select_utils.hh"
20#include "ED_view3d.hh"
21
22#include "WM_api.hh"
23
24#include "BKE_asset.hh"
27#include "BKE_context.hh"
28#include "BKE_curves.hh"
29#include "BKE_customdata.hh"
30#include "BKE_editmesh.hh"
31#include "BKE_geometry_set.hh"
32#include "BKE_grease_pencil.hh"
33#include "BKE_layer.hh"
34#include "BKE_lib_id.hh"
35#include "BKE_lib_query.hh"
36#include "BKE_main.hh"
37#include "BKE_material.hh"
38#include "BKE_mesh.hh"
39#include "BKE_mesh_wrapper.hh"
40#include "BKE_node_runtime.hh"
41#include "BKE_object.hh"
42#include "BKE_paint.hh"
43#include "BKE_paint_bvh.hh"
44#include "BKE_pointcloud.hh"
45#include "BKE_report.hh"
46#include "BKE_scene.hh"
47#include "BKE_screen.hh"
48#include "BKE_workspace.hh"
49
50#include "DNA_object_types.h"
51#include "DNA_scene_types.h"
52
53#include "DEG_depsgraph.hh"
56
57#include "RNA_access.hh"
58#include "RNA_define.hh"
59
60#include "UI_interface.hh"
61#include "UI_resources.hh"
62
63#include "ED_asset.hh"
65#include "ED_geometry.hh"
66#include "ED_mesh.hh"
67#include "ED_sculpt.hh"
68
69#include "BLT_translation.hh"
70
76
77#include "AS_asset_catalog.hh"
80#include "AS_asset_library.hh"
82
83#include "geometry_intern.hh"
84
85#include <fmt/format.h>
86
88
89namespace blender::ed::geometry {
90
91/* -------------------------------------------------------------------- */
94
98{
99 Main &bmain = *CTX_data_main(&C);
100 if (bNodeTree *group = reinterpret_cast<bNodeTree *>(
102 {
103 return group;
104 }
105
108 if (!asset) {
109 return nullptr;
110 }
111 return reinterpret_cast<bNodeTree *>(asset::asset_local_id_ensure_imported(bmain, *asset));
112}
113
115{
117 if (!group) {
118 return nullptr;
119 }
120 if (group->type != NTREE_GEOMETRY) {
121 if (reports) {
122 BKE_report(reports, RPT_ERROR, "Asset is not a geometry node group");
123 }
124 return nullptr;
125 }
126 return group;
127}
128
130
137{
138 static GeoOperatorLog log;
139 return log;
140}
141
146
148static void find_socket_log_contexts(const Main &bmain,
149 Set<ComputeContextHash> &r_socket_log_contexts)
150{
151 wmWindowManager *wm = static_cast<wmWindowManager *>(bmain.wm.first);
152 if (wm == nullptr) {
153 return;
154 }
155 LISTBASE_FOREACH (const wmWindow *, window, &wm->windows) {
156 const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
157 LISTBASE_FOREACH (const ScrArea *, area, &screen->areabase) {
158 const SpaceLink *sl = static_cast<SpaceLink *>(area->spacedata.first);
159 if (sl->spacetype == SPACE_NODE) {
160 const SpaceNode &snode = *reinterpret_cast<const SpaceNode *>(sl);
161 if (snode.edittree == nullptr) {
162 continue;
163 }
165 continue;
166 }
167 bke::ComputeContextCache compute_context_cache;
170 compute_context_cache);
171 for (const ComputeContextHash &hash : hash_by_zone.values()) {
172 r_socket_log_contexts.add(hash);
173 }
174 }
175 }
176 }
177}
178
180{
181 const int layer_index = CustomData_get_layer_index(&mesh.vert_data, CD_MDEFORMVERT);
182 if (layer_index == -1) {
183 return nullptr;
184 }
185 return mesh.vert_data.layers[layer_index].sharing_info;
186}
187
194 VectorSet<ImplicitSharingPtr<>> sharing_infos_;
195
196 public:
198 {
199 if (mesh.runtime->face_offsets_sharing_info) {
200 this->freeze_shared_state(*mesh.runtime->face_offsets_sharing_info);
201 }
202 mesh.attributes().foreach_attribute([&](const bke::AttributeIter &iter) {
203 const bke::GAttributeReader attribute = iter.get();
204 if (attribute.varray.size() == 0) {
205 return;
206 }
207 if (attribute.sharing_info) {
208 this->freeze_shared_state(*attribute.sharing_info);
209 }
210 });
211 if (const ImplicitSharingInfo *sharing_info = get_vertex_group_sharing_info(mesh)) {
212 this->freeze_shared_state(*sharing_info);
213 }
214 }
215
216 void freeze_shared_state(const ImplicitSharingInfo &sharing_info)
217 {
218 if (sharing_infos_.add(ImplicitSharingPtr<>{&sharing_info})) {
219 sharing_info.add_user();
220 }
221 }
222};
223
231 Object &object,
232 nodes::GeoNodesOperatorData &operator_data,
233 Vector<MeshState> &orig_mesh_states)
234{
235 switch (object.type) {
236 case OB_CURVES: {
237 Curves *curves = BKE_curves_copy_for_eval(static_cast<const Curves *>(object.data));
239 }
240 case OB_POINTCLOUD: {
242 static_cast<const PointCloud *>(object.data));
244 }
245 case OB_MESH: {
246 const Mesh *mesh = static_cast<const Mesh *>(object.data);
247 if (std::shared_ptr<BMEditMesh> &em = mesh->runtime->edit_mesh) {
249 operator_data.active_edge_index = BM_mesh_active_edge_index_get(em->bm);
250 operator_data.active_face_index = BM_mesh_active_face_index_get(em->bm, false, true);
251 Mesh *mesh_copy = BKE_mesh_wrapper_from_editmesh(em, nullptr, mesh);
253 Mesh *final_copy = BKE_mesh_copy_for_eval(*mesh_copy);
254 BKE_id_free(nullptr, mesh_copy);
255 return bke::GeometrySet::from_mesh(final_copy);
256 }
257 if (bke::pbvh::Tree *pbvh = bke::object::pbvh_get(object)) {
258 /* Currently many sculpt mode operations do not tag normals dirty (see use of
259 * #Mesh::tag_positions_changed_no_normals()), so access within geometry nodes cannot
260 * know that normals are out of date and recalculate them. Update them here instead. */
261 bke::pbvh::update_normals(depsgraph, object, *pbvh);
262 }
263 Mesh *mesh_copy = BKE_mesh_copy_for_eval(*mesh);
264 orig_mesh_states.append_as(*mesh_copy);
265 return bke::GeometrySet::from_mesh(mesh_copy);
266 }
267 case OB_GREASE_PENCIL: {
268 const GreasePencil *grease_pencil = static_cast<const GreasePencil *>(object.data);
269 if (const bke::greasepencil::Layer *active_layer = grease_pencil->get_active_layer()) {
270 operator_data.active_layer_index = *grease_pencil->get_layer_index(*active_layer);
271 }
272 GreasePencil *grease_pencil_copy = BKE_grease_pencil_copy_for_eval(grease_pencil);
273 grease_pencil_copy->runtime->eval_frame = int(DEG_get_ctime(&depsgraph));
274 return bke::GeometrySet::from_grease_pencil(grease_pencil_copy);
275 }
276 default:
277 return {};
278 }
279}
280
282 const wmOperator &op,
283 const Depsgraph &depsgraph,
284 Main &bmain,
285 Scene &scene,
286 Object &object,
287 const RegionView3D *rv3d,
289{
290 geometry.ensure_owns_direct_data();
291 switch (object.type) {
292 case OB_CURVES: {
293 Curves &curves = *static_cast<Curves *>(object.data);
294 Curves *new_curves = geometry.get_curves_for_write();
295 if (!new_curves) {
296 curves.geometry.wrap() = {};
297 break;
298 }
299
300 /* Anonymous attributes shouldn't be available on the applied geometry. */
301 new_curves->geometry.wrap().attributes_for_write().remove_anonymous();
302
303 curves.geometry.wrap() = std::move(new_curves->geometry.wrap());
304 BKE_object_material_from_eval_data(&bmain, &object, &new_curves->id);
306 break;
307 }
308 case OB_POINTCLOUD: {
309 PointCloud &points = *static_cast<PointCloud *>(object.data);
310 PointCloud *new_points =
311 geometry.get_component_for_write<bke::PointCloudComponent>().release();
312 if (!new_points) {
313 CustomData_free(&points.pdata);
314 points.totpoint = 0;
315 break;
316 }
317
318 /* Anonymous attributes shouldn't be available on the applied geometry. */
319 new_points->attributes_for_write().remove_anonymous();
320
321 BKE_object_material_from_eval_data(&bmain, &object, &new_points->id);
322 BKE_pointcloud_nomain_to_pointcloud(new_points, &points);
324 break;
325 }
326 case OB_MESH: {
327 Mesh &mesh = *static_cast<Mesh *>(object.data);
328
329 const bool has_shape_keys = mesh.key != nullptr;
330
331 Mesh *new_mesh = geometry.get_component_for_write<bke::MeshComponent>().release();
332 if (new_mesh) {
333 /* Anonymous attributes shouldn't be available on the applied geometry. */
334 new_mesh->attributes_for_write().remove_anonymous();
335 BKE_object_material_from_eval_data(&bmain, &object, &new_mesh->id);
336 }
337 else {
338 new_mesh = BKE_mesh_new_nomain(0, 0, 0, 0);
339 }
340
341 if (object.mode == OB_MODE_SCULPT) {
342 sculpt_paint::store_mesh_from_eval(op, scene, depsgraph, rv3d, object, new_mesh);
343 }
344 else if (object.mode == OB_MODE_EDIT) {
345 EDBM_mesh_make_from_mesh(&object, new_mesh, scene.toolsettings->selectmode, true);
346 BKE_editmesh_looptris_and_normals_calc(mesh.runtime->edit_mesh.get());
347 BKE_id_free(nullptr, new_mesh);
349 }
350 else {
351 BKE_mesh_nomain_to_mesh(new_mesh, &mesh, &object);
353 }
354
355 if (has_shape_keys && !mesh.key) {
356 BKE_report(op.reports, RPT_WARNING, "Mesh shape key data removed");
357 }
358 break;
359 }
360 case OB_GREASE_PENCIL: {
361 const int eval_frame = int(DEG_get_ctime(&depsgraph));
362
363 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(object.data);
364 Vector<int> editable_layer_indices;
365 for (const int layer_i : grease_pencil.layers().index_range()) {
366 const bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
367 if (!layer.is_editable()) {
368 continue;
369 }
370 editable_layer_indices.append(layer_i);
371 }
372
373 bool inserted_new_keyframe = false;
374 for (const int layer_i : editable_layer_indices) {
375 bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
376 /* TODO: For now, we always create a blank keyframe, but it might be good to expose this as
377 * an option and allow to duplicate the previous key. */
378 const bool duplicate_previous_key = false;
380 scene, grease_pencil, layer, duplicate_previous_key, inserted_new_keyframe);
381 }
382 GreasePencil *new_grease_pencil =
383 geometry.get_component_for_write<bke::GreasePencilComponent>().get_for_write();
384 if (!new_grease_pencil) {
385 /* Clear the Grease Pencil geometry. */
386 for (const int layer_i : editable_layer_indices) {
387 bke::greasepencil::Layer &layer = grease_pencil.layer(layer_i);
388 if (bke::greasepencil::Drawing *drawing_orig = grease_pencil.get_drawing_at(layer,
389 eval_frame))
390 {
391 drawing_orig->strokes_for_write() = {};
392 drawing_orig->tag_topology_changed();
393 }
394 }
395 }
396 else {
397 IndexMaskMemory memory;
398 const IndexMask editable_layers = IndexMask::from_indices(editable_layer_indices.as_span(),
399 memory);
401 *new_grease_pencil, eval_frame, editable_layers, grease_pencil);
402
403 /* There might be layers with empty names after evaluation. Make sure to rename them. */
405 BKE_object_material_from_eval_data(&bmain, &object, &new_grease_pencil->id);
406 }
407
408 DEG_id_tag_update(&grease_pencil.id, ID_RECALC_GEOMETRY);
409 if (inserted_new_keyframe) {
411 }
412 }
413 }
414}
415
421static void gather_node_group_ids(const bNodeTree &node_tree, Set<ID *> &ids)
422{
423 const int orig_size = ids.size();
424 BLI_assert(node_tree.runtime->geometry_nodes_eval_dependencies);
425 for (ID *id : node_tree.runtime->geometry_nodes_eval_dependencies->ids.values()) {
426 ids.add(id);
427 }
428 if (ids.size() != orig_size) {
429 /* Only evaluate the node group if it references data-blocks. In that case it needs to be
430 * evaluated so that ID pointers are switched to point to evaluated data-blocks. */
431 ids.add(const_cast<ID *>(&node_tree.id));
432 }
433}
434
436 const StringRef identifier)
437{
438 for (const bNodeTreeInterfaceSocket *input : node_group.interface_inputs()) {
439 if (input->identifier == identifier) {
440 return input;
441 }
442 }
443 return nullptr;
444}
445
446static std::optional<ID_Type> socket_type_to_id_type(const eNodeSocketDatatype socket_type)
447{
448 switch (socket_type) {
449 case SOCK_CUSTOM:
450 case SOCK_FLOAT:
451 case SOCK_VECTOR:
452 case SOCK_RGBA:
453 case SOCK_SHADER:
454 case SOCK_BOOLEAN:
455 case SOCK_INT:
456 case SOCK_STRING:
457 case SOCK_GEOMETRY:
458 case SOCK_ROTATION:
459 case SOCK_MENU:
460 case SOCK_MATRIX:
461 case SOCK_BUNDLE:
462 case SOCK_CLOSURE:
463 return std::nullopt;
464 case SOCK_OBJECT:
465 return ID_OB;
466 case SOCK_IMAGE:
467 return ID_IM;
468 case SOCK_COLLECTION:
469 return ID_GR;
470 case SOCK_TEXTURE:
471 return ID_TE;
472 case SOCK_MATERIAL:
473 return ID_MA;
474 }
475 return std::nullopt;
476}
477
484 const bNodeTree &node_group,
485 const IDProperty &properties)
486{
489 &const_cast<IDProperty &>(properties), IDP_TYPE_FILTER_STRING, [&](IDProperty *prop) {
491 prop->name);
492 if (!input) {
493 return;
494 }
495 const std::optional<ID_Type> id_type = socket_type_to_id_type(
496 input->socket_typeinfo()->type);
497 if (!id_type) {
498 return;
499 }
500 const char *id_name = IDP_String(prop);
501 ID *id = BKE_libblock_find_name(&const_cast<Main &>(bmain), *id_type, id_name);
502 if (!id) {
503 return;
504 }
505 ids.add(prop->name, id);
506 });
507 return ids;
508}
509
510static Depsgraph *build_extra_depsgraph(const Depsgraph &depsgraph_active, const Set<ID *> &ids)
511{
512 Depsgraph *depsgraph = DEG_graph_new(DEG_get_bmain(&depsgraph_active),
513 DEG_get_input_scene(&depsgraph_active),
514 DEG_get_input_view_layer(&depsgraph_active),
515 DEG_get_mode(&depsgraph_active));
518 return depsgraph;
519}
520
522 const Map<StringRef, ID *> &input_ids)
523{
524 IDProperty *properties = bke::idprop::create_group("Exec Properties").release();
525 IDP_foreach_property(&const_cast<IDProperty &>(op_properties), 0, [&](IDProperty *prop) {
526 if (ID *id = input_ids.lookup_default(prop->name, nullptr)) {
527 IDP_AddToGroup(properties, bke::idprop::create(prop->name, id).release());
528 }
529 else {
530 IDP_AddToGroup(properties, IDP_CopyProperty(prop));
531 }
532 });
533 return properties;
534}
535
537 IDProperty &properties, const nodes::GeoNodesOperatorDepsgraphs &depsgraphs)
538{
539 IDP_foreach_property(&properties, IDP_TYPE_FILTER_ID, [&](IDProperty *property) {
540 if (ID *id = IDP_Id(property)) {
541 if (ID_TYPE_USE_COPY_ON_EVAL(GS(id->name))) {
542 property->data.pointer = const_cast<ID *>(depsgraphs.get_evaluated_id(*id));
543 }
544 }
545 });
546}
547
548static bool object_has_editable_data(const Main &bmain, const Object &object)
549{
550 if (!ELEM(object.type, OB_CURVES, OB_POINTCLOUD, OB_MESH, OB_GREASE_PENCIL)) {
551 return false;
552 }
553 if (!BKE_id_is_editable(&bmain, static_cast<const ID *>(object.data))) {
554 return false;
555 }
556 return true;
557}
558
560 const Main &bmain,
561 const eObjectMode mode)
562{
563 Vector<Object *> objects;
564 Set<const ID *> unique_object_data;
565
566 auto handle_object = [&](Object *object) {
567 if (object->mode != mode) {
568 return;
569 }
570 if (!unique_object_data.add(static_cast<const ID *>(object->data))) {
571 return;
572 }
573 if (!object_has_editable_data(bmain, *object)) {
574 return;
575 }
576 objects.append(object);
577 };
578
579 if (mode == OB_MODE_OBJECT) {
580 CTX_DATA_BEGIN (&C, Object *, object, selected_objects) {
581 handle_object(object);
582 }
584 }
585 else {
586 Scene *scene = CTX_data_scene(&C);
587 ViewLayer *view_layer = CTX_data_view_layer(&C);
588 View3D *v3d = CTX_wm_view3d(&C);
589 Object *active_object = CTX_data_active_object(&C);
590 if (v3d && active_object) {
591 FOREACH_OBJECT_IN_MODE_BEGIN (scene, view_layer, v3d, active_object->type, mode, ob) {
592 handle_object(ob);
593 }
595 }
596 }
597 return objects;
598}
599
601{
602 Main *bmain = CTX_data_main(C);
603 Scene *scene = CTX_data_scene(C);
604 Object *active_object = CTX_data_active_object(C);
605 if (!active_object) {
606 return OPERATOR_CANCELLED;
607 }
608 const eObjectMode mode = eObjectMode(active_object->mode);
609
610 const bNodeTree *node_tree_orig = get_node_group(*C, *op->ptr, op->reports);
611 if (!node_tree_orig) {
612 return OPERATOR_CANCELLED;
613 }
614
615 const Vector<Object *> objects = gather_supported_objects(*C, *bmain, mode);
616
617 Depsgraph *depsgraph_active = CTX_data_ensure_evaluated_depsgraph(C);
618 Set<ID *> extra_ids;
619 gather_node_group_ids(*node_tree_orig, extra_ids);
620 const Map<StringRef, ID *> input_ids = gather_input_ids(
621 *bmain, *node_tree_orig, *op->properties);
622 for (ID *id : input_ids.values()) {
623 /* Skip IDs that are already fully evaluated in the active depsgraph. */
624 if (!DEG_id_is_fully_evaluated(depsgraph_active, id)) {
625 extra_ids.add(id);
626 }
627 }
628
629 const nodes::GeoNodesOperatorDepsgraphs depsgraphs{
630 depsgraph_active,
631 extra_ids.is_empty() ? nullptr : build_extra_depsgraph(*depsgraph_active, extra_ids),
632 };
633
634 IDProperty *properties = replace_strings_with_id_pointers(*op->properties, input_ids);
635 BLI_SCOPED_DEFER([&]() { IDP_FreeProperty_ex(properties, false); });
636
637 replace_inputs_evaluated_data_blocks(*properties, depsgraphs);
638
639 const bNodeTree *node_tree = nullptr;
640 if (depsgraphs.extra) {
641 node_tree = DEG_get_evaluated(depsgraphs.extra, node_tree_orig);
642 }
643 else {
644 node_tree = node_tree_orig;
645 }
646
647 const nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info =
649 if (lf_graph_info == nullptr) {
650 BKE_report(op->reports, RPT_ERROR, "Cannot evaluate node group");
651 return OPERATOR_CANCELLED;
652 }
653
654 if (!node_tree->group_output_node()) {
655 BKE_report(op->reports, RPT_ERROR, "Node group must have a group output node");
656 return OPERATOR_CANCELLED;
657 }
658 if (node_tree->interface_outputs().is_empty() ||
659 !STREQ(node_tree->interface_outputs()[0]->socket_type, "NodeSocketGeometry"))
660 {
661 BKE_report(op->reports, RPT_ERROR, "Node group's first output must be a geometry");
662 return OPERATOR_CANCELLED;
663 }
664
665 bke::OperatorComputeContext compute_context;
666 Set<ComputeContextHash> socket_log_contexts;
668 eval_log.log = std::make_unique<geo_log::GeoNodesLog>();
669 eval_log.node_group_name = node_tree->id.name + 2;
670 find_socket_log_contexts(*bmain, socket_log_contexts);
671
672 /* May be null if operator called from outside 3D view context. */
673 const RegionView3D *rv3d = CTX_wm_region_view3d(C);
674 Vector<MeshState> orig_mesh_states;
675
676 for (Object *object : objects) {
677 nodes::GeoNodesOperatorData operator_eval_data{};
678 operator_eval_data.mode = mode;
679 operator_eval_data.depsgraphs = &depsgraphs;
680 operator_eval_data.self_object_orig = object;
681 operator_eval_data.scene_orig = scene;
682 RNA_int_get_array(op->ptr, "mouse_position", operator_eval_data.mouse_position);
683 RNA_int_get_array(op->ptr, "region_size", operator_eval_data.region_size);
684 RNA_float_get_array(op->ptr, "cursor_position", operator_eval_data.cursor_position);
685 RNA_float_get_array(op->ptr, "cursor_rotation", &operator_eval_data.cursor_rotation.w);
687 op->ptr, "viewport_projection_matrix", operator_eval_data.viewport_winmat.base_ptr());
689 op->ptr, "viewport_view_matrix", operator_eval_data.viewport_viewmat.base_ptr());
690 operator_eval_data.viewport_is_perspective = RNA_boolean_get(op->ptr,
691 "viewport_is_perspective");
692
693 nodes::GeoNodesCallData call_data{};
694 call_data.operator_data = &operator_eval_data;
695 call_data.eval_log = eval_log.log.get();
696 if (object == active_object) {
697 /* Only log values from the active object. */
698 call_data.socket_log_contexts = &socket_log_contexts;
699 }
700
702 *depsgraph_active, *object, operator_eval_data, orig_mesh_states);
703
705 *node_tree,
707 compute_context,
708 call_data,
709 std::move(geometry_orig));
710
712 *C, *op, *depsgraph_active, *bmain, *scene, *object, rv3d, std::move(new_geometry));
714 }
715
716 geo_log::GeoTreeLog &tree_log = eval_log.log->get_tree_log(compute_context.hash());
717 tree_log.ensure_node_warnings(*bmain);
718 for (const geo_log::NodeWarning &warning : tree_log.all_warnings) {
719 if (warning.type == nodes::NodeWarningType::Info) {
720 BKE_report(op->reports, RPT_INFO, warning.message.c_str());
721 }
722 else {
723 BKE_report(op->reports, RPT_WARNING, warning.message.c_str());
724 }
725 }
726
727 return OPERATOR_FINISHED;
728}
729
742 wmOperator &op,
743 const wmEvent &event)
744{
745 Scene *scene = CTX_data_scene(&C);
746 /* NOTE: `region` and `rv3d` may be null when called from a script. */
747 const ARegion *region = CTX_wm_region(&C);
748 const RegionView3D *rv3d = CTX_wm_region_view3d(&C);
749
750 /* Mouse position node inputs. */
751 RNA_int_set_array(op.ptr, "mouse_position", event.mval);
753 op.ptr,
754 "region_size",
755 region ? int2(BLI_rcti_size_x(&region->winrct), BLI_rcti_size_y(&region->winrct)) : int2(0));
756
757 /* 3D cursor node inputs. */
758 const View3DCursor &cursor = scene->cursor;
759 RNA_float_set_array(op.ptr, "cursor_position", cursor.location);
760 math::Quaternion cursor_rotation = cursor.rotation();
761 RNA_float_set_array(op.ptr, "cursor_rotation", &cursor_rotation.w);
762
763 /* Viewport transform node inputs. */
765 "viewport_projection_matrix",
766 rv3d ? float4x4(rv3d->winmat).base_ptr() : float4x4::identity().base_ptr());
768 "viewport_view_matrix",
769 rv3d ? float4x4(rv3d->viewmat).base_ptr() : float4x4::identity().base_ptr());
770 RNA_boolean_set(op.ptr, "viewport_is_perspective", rv3d ? bool(rv3d->is_persp) : true);
771}
772
774{
775 const bNodeTree *node_tree = get_node_group(*C, *op->ptr, op->reports);
776 if (!node_tree) {
777 return OPERATOR_CANCELLED;
778 }
779
781
782 nodes ::update_input_properties_from_node_tree(
783 *node_tree, op->properties, *op->properties, true);
785
786 return run_node_group_exec(C, op);
787}
788
790 wmOperatorType * /*ot*/,
792{
795 if (!asset) {
796 return "";
797 }
798 if (!asset->get_metadata().description) {
799 return "";
800 }
801 return asset->get_metadata().description;
802}
803
805{
806 uiLayout *layout = op->layout;
807 uiLayoutSetPropSep(layout, true);
808 uiLayoutSetPropDecorate(layout, false);
809 Main *bmain = CTX_data_main(C);
810 PointerRNA bmain_ptr = RNA_main_pointer_create(bmain);
811
812 const bNodeTree *node_tree = get_node_group(*C, *op->ptr, nullptr);
813 if (!node_tree) {
814 return;
815 }
816
817 bke::OperatorComputeContext compute_context;
819 geo_log::GeoTreeLog &tree_log = eval_log.log->get_tree_log(compute_context.hash());
821 *C, *op, const_cast<bNodeTree &>(*node_tree), &tree_log);
822}
823
825{
826 bool result = false;
827 RNA_STRUCT_BEGIN (ptr, prop) {
828 int flag = RNA_property_flag(prop);
829 if ((flag & PROP_HIDDEN) == 0) {
830 result = true;
831 break;
832 }
833 }
835 return result;
836}
837
839{
840 int len;
841 char *local_name = RNA_string_get_alloc(ptr, "name", nullptr, 0, &len);
842 BLI_SCOPED_DEFER([&]() { MEM_SAFE_FREE(local_name); })
843 if (len > 0) {
844 return std::string(local_name, len);
845 }
846 char *library_asset_identifier = RNA_string_get_alloc(
847 ptr, "relative_asset_identifier", nullptr, 0, &len);
848 BLI_SCOPED_DEFER([&]() { MEM_SAFE_FREE(library_asset_identifier); })
849 StringRef ref(library_asset_identifier, len);
850 return ref.drop_prefix(ref.find_last_of(SEP_STR) + 1);
851}
852
854{
855 if (!ptr) {
856 return false;
857 }
858 Main &bmain = *CTX_data_main(&C);
859 if (bNodeTree *group = reinterpret_cast<bNodeTree *>(
861 {
862 return group->geometry_node_asset_traits &&
863 (group->geometry_node_asset_traits->flag & GEO_NODE_ASSET_WAIT_FOR_CURSOR) != 0;
864 }
865
868 if (!asset) {
869 return false;
870 }
871 const IDProperty *traits_flag = BKE_asset_metadata_idprop_find(
872 &asset->get_metadata(), "geometry_node_asset_traits_flag");
873 if (traits_flag == nullptr || !(IDP_Int(traits_flag) & GEO_NODE_ASSET_WAIT_FOR_CURSOR)) {
874 return false;
875 }
876 return true;
877}
878
880{
881 PropertyRNA *prop;
882 ot->name = "Run Node Group";
883 ot->idname = __func__;
884 ot->description = "Execute a node group on geometry";
885
886 /* A proper poll is not possible, since it doesn't have access to the operator's properties. */
887 ot->invoke = run_node_group_invoke;
888 ot->exec = run_node_group_exec;
889 ot->get_description = run_node_group_get_description;
890 ot->ui = run_node_group_ui;
891 ot->ui_poll = run_node_ui_poll;
892 ot->get_name = run_node_group_get_name;
893 ot->depends_on_cursor = run_node_group_depends_on_cursor;
894
896
899
900 /* See comment for #store_input_node_values_rna_props. */
901 prop = RNA_def_int_array(ot->srna,
902 "mouse_position",
903 2,
904 nullptr,
905 INT_MIN,
906 INT_MAX,
907 "Mouse Position",
908 "Mouse coordinates in region space",
909 INT_MIN,
910 INT_MAX);
912 prop = RNA_def_int_array(
913 ot->srna, "region_size", 2, nullptr, 0, INT_MAX, "Region Size", "", 0, INT_MAX);
915 prop = RNA_def_float_array(ot->srna,
916 "cursor_position",
917 3,
918 nullptr,
919 -FLT_MAX,
920 FLT_MAX,
921 "3D Cursor Position",
922 "",
923 -FLT_MAX,
924 FLT_MAX);
926 prop = RNA_def_float_array(ot->srna,
927 "cursor_rotation",
928 4,
929 nullptr,
930 -FLT_MAX,
931 FLT_MAX,
932 "3D Cursor Rotation",
933 "",
934 -FLT_MAX,
935 FLT_MAX);
937 prop = RNA_def_float_array(ot->srna,
938 "viewport_projection_matrix",
939 16,
940 nullptr,
941 -FLT_MAX,
942 FLT_MAX,
943 "Viewport Projection Transform",
944 "",
945 -FLT_MAX,
946 FLT_MAX);
948 prop = RNA_def_float_array(ot->srna,
949 "viewport_view_matrix",
950 16,
951 nullptr,
952 -FLT_MAX,
953 FLT_MAX,
954 "Viewport View Transform",
955 "",
956 -FLT_MAX,
957 FLT_MAX);
959 prop = RNA_def_boolean(
960 ot->srna, "viewport_is_perspective", false, "Viewport Is Perspective", "");
962}
963
965
966/* -------------------------------------------------------------------- */
969
970static bool asset_menu_poll(const bContext *C, MenuType * /*mt*/)
971{
972 return CTX_wm_view3d(C);
973}
974
976 const eObjectMode mode)
977{
978 switch (type) {
979 case OB_MESH: {
980 switch (mode) {
981 case OB_MODE_OBJECT:
983 case OB_MODE_EDIT:
985 case OB_MODE_SCULPT:
987 default:
988 break;
989 }
990 break;
991 }
992 case OB_CURVES: {
993 switch (mode) {
994 case OB_MODE_OBJECT:
996 case OB_MODE_EDIT:
1000 default:
1001 break;
1002 }
1003 break;
1004 }
1005 case OB_POINTCLOUD: {
1006 switch (mode) {
1007 case OB_MODE_OBJECT:
1009 case OB_MODE_EDIT:
1011 default:
1012 break;
1013 }
1014 break;
1015 }
1016 case OB_GREASE_PENCIL: {
1017 switch (mode) {
1018 case OB_MODE_OBJECT:
1020 case OB_MODE_EDIT:
1026 default:
1027 break;
1028 }
1029 }
1030 default:
1031 break;
1032 }
1035}
1036
1038{
1039 return asset_flag_for_context(ObjectType(active_object.type), eObjectMode(active_object.mode));
1040}
1041
1043{
1044 switch (type) {
1045 case OB_MESH: {
1046 switch (mode) {
1047 case OB_MODE_OBJECT: {
1049 return &tree;
1050 }
1051 case OB_MODE_EDIT: {
1053 return &tree;
1054 }
1055 case OB_MODE_SCULPT: {
1057 return &tree;
1058 }
1059 default:
1060 return nullptr;
1061 }
1062 }
1063 case OB_CURVES: {
1064 switch (mode) {
1065 case OB_MODE_OBJECT: {
1067 return &tree;
1068 }
1069 case OB_MODE_EDIT: {
1071 return &tree;
1072 }
1073 case OB_MODE_SCULPT_CURVES: {
1075 return &tree;
1076 }
1077 default:
1078 return nullptr;
1079 }
1080 }
1081 case OB_POINTCLOUD: {
1082 switch (mode) {
1083 case OB_MODE_OBJECT: {
1085 return &tree;
1086 }
1087 case OB_MODE_EDIT: {
1089 return &tree;
1090 }
1091 default:
1092 return nullptr;
1093 }
1094 }
1095 case OB_GREASE_PENCIL: {
1096 switch (mode) {
1097 case OB_MODE_OBJECT: {
1099 return &tree;
1100 }
1101 case OB_MODE_EDIT: {
1103 return &tree;
1104 }
1107 return &tree;
1108 }
1111 return &tree;
1112 }
1113 default:
1114 return nullptr;
1115 }
1116 }
1117 default:
1118 return nullptr;
1119 }
1120}
1121
1123{
1124 return get_static_item_tree(ObjectType(active_object.type), eObjectMode(active_object.mode));
1125}
1126
1128{
1130 for (const eObjectMode mode : {OB_MODE_OBJECT,
1136 {
1137 if (asset::AssetItemTree *tree = get_static_item_tree(type, mode)) {
1138 tree->dirty = true;
1139 }
1140 }
1141 }
1142}
1143
1144static asset::AssetItemTree build_catalog_tree(const bContext &C, const Object &active_object)
1145{
1146 asset::AssetFilterSettings type_filter{};
1147 type_filter.id_types = FILTER_ID_NT;
1149 auto meta_data_filter = [&](const AssetMetaData &meta_data) {
1150 const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
1151 if (tree_type == nullptr || IDP_Int(tree_type) != NTREE_GEOMETRY) {
1152 return false;
1153 }
1154 const IDProperty *traits_flag = BKE_asset_metadata_idprop_find(
1155 &meta_data, "geometry_node_asset_traits_flag");
1156 if (traits_flag == nullptr || (IDP_Int(traits_flag) & flag) != flag) {
1157 return false;
1158 }
1159 return true;
1160 };
1163 return asset::build_filtered_all_catalog_tree(library, C, type_filter, meta_data_filter);
1164}
1165
1171static Set<std::string> get_builtin_menus(const ObjectType object_type, const eObjectMode mode)
1172{
1173 Set<std::string> menus;
1174 switch (object_type) {
1175 case OB_CURVES:
1176 menus.add_new("View");
1177 menus.add_new("Select");
1178 menus.add_new("Curves");
1179 break;
1180 case OB_POINTCLOUD:
1181 menus.add_new("View");
1182 menus.add_new("Select");
1183 menus.add_new("Point Cloud");
1184 break;
1185 case OB_MESH:
1186 switch (mode) {
1187 case OB_MODE_OBJECT:
1188 menus.add_new("View");
1189 menus.add_new("Select");
1190 menus.add_new("Add");
1191 menus.add_new("Object");
1192 menus.add_new("Object/Apply");
1193 menus.add_new("Object/Convert");
1194 menus.add_new("Object/Quick Effects");
1195 break;
1196 case OB_MODE_EDIT:
1197 menus.add_new("View");
1198 menus.add_new("Select");
1199 menus.add_new("Add");
1200 menus.add_new("Mesh");
1201 menus.add_new("Mesh/Extrude");
1202 menus.add_new("Mesh/Clean Up");
1203 menus.add_new("Mesh/Delete");
1204 menus.add_new("Mesh/Merge");
1205 menus.add_new("Mesh/Normals");
1206 menus.add_new("Mesh/Shading");
1207 menus.add_new("Mesh/Split");
1208 menus.add_new("Mesh/Weights");
1209 menus.add_new("Vertex");
1210 menus.add_new("Edge");
1211 menus.add_new("Face");
1212 menus.add_new("Face/Face Data");
1213 menus.add_new("UV");
1214 menus.add_new("UV/Unwrap");
1215 break;
1216 case OB_MODE_SCULPT:
1217 menus.add_new("View");
1218 menus.add_new("Sculpt");
1219 menus.add_new("Mask");
1220 menus.add_new("Face Sets");
1221 break;
1223 menus.add_new("View");
1224 menus.add_new("Paint");
1225 break;
1227 menus.add_new("View");
1228 menus.add_new("Weights");
1229 break;
1230 default:
1231 break;
1232 }
1233 break;
1234 case OB_GREASE_PENCIL: {
1235 switch (mode) {
1236 case OB_MODE_OBJECT:
1237 menus.add_new("View");
1238 menus.add_new("Select");
1239 menus.add_new("Add");
1240 menus.add_new("Object");
1241 menus.add_new("Object/Apply");
1242 menus.add_new("Object/Convert");
1243 menus.add_new("Object/Quick Effects");
1244 break;
1245 case OB_MODE_EDIT:
1246 menus.add_new("View");
1247 menus.add_new("Select");
1248 menus.add_new("Grease Pencil");
1249 menus.add_new("Stroke");
1250 menus.add_new("Point");
1251 break;
1253 menus.add_new("View");
1254 break;
1256 menus.add_new("View");
1257 menus.add_new("Draw");
1258 break;
1259 default:
1260 break;
1261 }
1262 }
1263 default:
1264 break;
1265 }
1266 return menus;
1267}
1268
1269static void catalog_assets_draw(const bContext *C, Menu *menu)
1270{
1271 const Object *active_object = CTX_data_active_object(C);
1272 if (!active_object) {
1273 return;
1274 }
1276 if (!tree) {
1277 return;
1278 }
1279 const std::optional<StringRefNull> menu_path = CTX_data_string_get(C, "asset_catalog_path");
1280 if (!menu_path) {
1281 return;
1282 }
1283 const Span<asset_system::AssetRepresentation *> assets = tree->assets_per_path.lookup(
1284 menu_path->data());
1285 const asset_system::AssetCatalogTreeItem *catalog_item = tree->catalogs.find_item(
1286 menu_path->data());
1287 BLI_assert(catalog_item != nullptr);
1288
1289 uiLayout *layout = menu->layout;
1290 bool add_separator = true;
1291
1292 wmOperatorType *ot = WM_operatortype_find("GEOMETRY_OT_execute_node_group", true);
1293 for (const asset_system::AssetRepresentation *asset : assets) {
1294 if (add_separator) {
1295 layout->separator();
1296 add_separator = false;
1297 }
1298 PointerRNA props_ptr = layout->op(
1299 ot, IFACE_(asset->get_name()), ICON_NONE, WM_OP_INVOKE_REGION_WIN, UI_ITEM_NONE);
1301 }
1302
1303 const Set<std::string> builtin_menus = get_builtin_menus(ObjectType(active_object->type),
1304 eObjectMode(active_object->mode));
1305
1308 if (!all_library) {
1309 return;
1310 }
1311
1312 catalog_item->foreach_child([&](const asset_system::AssetCatalogTreeItem &item) {
1313 if (builtin_menus.contains_as(item.catalog_path().str())) {
1314 return;
1315 }
1316 if (add_separator) {
1317 layout->separator();
1318 add_separator = false;
1319 }
1320 asset::draw_menu_for_catalog(item, "GEO_MT_node_operator_catalog_assets", *layout);
1321 });
1322}
1323
1325{
1326 MenuType type{};
1327 STRNCPY(type.idname, "GEO_MT_node_operator_catalog_assets");
1328 type.poll = asset_menu_poll;
1332 return type;
1333}
1334
1336{
1337 Main &bmain = *CTX_data_main(&C);
1338 const Object *active_object = CTX_data_active_object(&C);
1339 if (!active_object) {
1340 return false;
1341 }
1343 LISTBASE_FOREACH (const bNodeTree *, group, &bmain.nodetrees) {
1344 /* Assets are displayed in other menus, and non-local data-blocks aren't added to this menu. */
1345 if (group->id.library_weak_reference || group->id.asset_data) {
1346 continue;
1347 }
1348 if (!group->geometry_node_asset_traits ||
1349 (group->geometry_node_asset_traits->flag & flag) != flag)
1350 {
1351 continue;
1352 }
1353 return true;
1354 }
1355 return false;
1356}
1357
1359{
1360 const Object *active_object = CTX_data_active_object(C);
1361 if (!active_object) {
1362 return;
1363 }
1365 if (!tree) {
1366 return;
1367 }
1368 uiLayout *layout = menu->layout;
1369 wmOperatorType *ot = WM_operatortype_find("GEOMETRY_OT_execute_node_group", true);
1370 for (const asset_system::AssetRepresentation *asset : tree->unassigned_assets) {
1371 PointerRNA props_ptr = layout->op(
1372 ot, IFACE_(asset->get_name()), ICON_NONE, WM_OP_INVOKE_REGION_WIN, UI_ITEM_NONE);
1374 }
1375
1377
1378 bool first = true;
1379 bool add_separator = !tree->unassigned_assets.is_empty();
1380 Main &bmain = *CTX_data_main(C);
1381 LISTBASE_FOREACH (const bNodeTree *, group, &bmain.nodetrees) {
1382 /* Assets are displayed in other menus, and non-local data-blocks aren't added to this menu. */
1383 if (group->id.library_weak_reference || group->id.asset_data) {
1384 continue;
1385 }
1386 if (!group->geometry_node_asset_traits ||
1387 (group->geometry_node_asset_traits->flag & flag) != flag)
1388 {
1389 continue;
1390 }
1391
1392 if (add_separator) {
1393 layout->separator();
1394 add_separator = false;
1395 }
1396 if (first) {
1397 layout->label(IFACE_("Non-Assets"), ICON_NONE);
1398 first = false;
1399 }
1400
1401 PointerRNA props_ptr = layout->op(
1402 ot, group->id.name + 2, ICON_NONE, WM_OP_INVOKE_REGION_WIN, UI_ITEM_NONE);
1403 WM_operator_properties_id_lookup_set_from_id(&props_ptr, &group->id);
1404 /* Also set the name so it can be used for #run_node_group_get_name. */
1405 RNA_string_set(&props_ptr, "name", group->id.name + 2);
1406 }
1407}
1408
1410{
1411 MenuType type{};
1412 STRNCPY(type.label, "Unassigned Node Tools");
1413 STRNCPY(type.idname, "GEO_MT_node_operator_unassigned");
1414 type.poll = asset_menu_poll;
1418 type.description = N_(
1419 "Tool node group assets not assigned to a catalog.\n"
1420 "Catalogs can be assigned in the Asset Browser");
1421 return type;
1422}
1423
1425 const bContext &C,
1426 const StringRef catalog_path)
1427{
1428 const Object *active_object = CTX_data_active_object(&C);
1429 if (!active_object) {
1430 return;
1431 }
1433 if (!tree) {
1434 return;
1435 }
1436 const asset_system::AssetCatalogTreeItem *item = tree->catalogs.find_item(catalog_path);
1437 if (!item) {
1438 return;
1439 }
1442 if (!all_library) {
1443 return;
1444 }
1445 uiLayout *col = &layout.column(false);
1446 uiLayoutSetContextString(col, "asset_catalog_path", item->catalog_path().str());
1447 uiItemMContents(col, "GEO_MT_node_operator_catalog_assets");
1448}
1449
1451{
1452 const Object *active_object = CTX_data_active_object(&C);
1453 if (!active_object) {
1454 return;
1455 }
1457 if (!tree) {
1458 return;
1459 }
1460 if (tree->dirty) {
1461 *tree = build_catalog_tree(C, *active_object);
1462 }
1463
1464 const Set<std::string> builtin_menus = get_builtin_menus(ObjectType(active_object->type),
1465 eObjectMode(active_object->mode));
1466
1467 tree->catalogs.foreach_root_item([&](const asset_system::AssetCatalogTreeItem &item) {
1468 if (!builtin_menus.contains_as(item.catalog_path().str())) {
1469 asset::draw_menu_for_catalog(item, "GEO_MT_node_operator_catalog_assets", layout);
1470 }
1471 });
1472
1473 if (!tree->unassigned_assets.is_empty() || unassigned_local_poll(C)) {
1474 layout.menu("GEO_MT_node_operator_unassigned", "", ICON_FILE_HIDDEN);
1475 }
1476}
1477
1479
1480} // 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.
void CustomData_free(CustomData *data)
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_Int(prop)
#define IDP_Id(prop)
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
#define IDP_String(prop)
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:725
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:873
void IDP_FreeProperty_ex(IDProperty *prop, bool do_id_user)
Definition idprop.cc:1237
#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:1679
bool BKE_id_is_editable(const Main *bmain, const ID *id)
Definition lib_id.cc:2503
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)
Mesh * BKE_mesh_copy_for_eval(const Mesh &source)
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.
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)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:126
bScreen * BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) GETTER_ATTRS
Definition workspace.cc:612
#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
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
#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)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ 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_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:324
#define C
Definition RandGen.cpp:29
void uiLayoutSetContextString(uiLayout *layout, blender::StringRef name, blender::StringRef value)
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep)
#define UI_ITEM_NONE
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
void uiItemMContents(uiLayout *layout, blender::StringRef menuname)
#define NC_GEOM
Definition WM_types.hh:390
#define ND_DATA
Definition WM_types.hh:506
#define NA_EDITED
Definition WM_types.hh:581
ReportList * reports
Definition WM_types.hh:1025
#define NC_GPENCIL
Definition WM_types.hh:396
@ WM_OP_INVOKE_REGION_WIN
Definition WM_types.hh:239
@ OPTYPE_UNDO
Definition WM_types.hh:182
@ OPTYPE_REGISTER
Definition WM_types.hh:180
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
void append(const T &value)
Span< T > as_span() const
void append_as(ForwardValue &&...value)
void foreach_child(ItemIterFn callback) const
GAttributeReader get() const
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)
std::string id_name(void *id)
KDTree_3d * tree
uint col
#define log
#define input
#define ID_TYPE_USE_COPY_ON_EVAL(_id_type)
#define MEM_SAFE_FREE(v)
#define GS(a)
#define FILTER_ID_NT
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:2912
void update_normals(const Depsgraph &depsgraph, Object &object_orig, Tree &pbvh)
Definition pbvh.cc:1073
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 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 Vector< Object * > gather_supported_objects(const bContext &C, const Main &bmain, const eObjectMode mode)
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 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:5277
QuaternionBase< float > Quaternion
bke::GeometrySet execute_geometry_nodes_on_geometry(const bNodeTree &btree, const PropertiesVectorSet &properties_set, const ComputeContext &base_compute_context, GeoNodesCallData &call_data, bke::GeometrySet input_geometry)
PropertiesVectorSet build_properties_vector_set(const IDProperty *properties)
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
#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)
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
GreasePencilRuntimeHandle * runtime
char name[64]
Definition DNA_ID.h:154
Definition DNA_ID.h:404
char name[66]
Definition DNA_ID.h:415
void * first
ListBase wm
Definition BKE_main.hh:276
ListBase nodetrees
Definition BKE_main.hh:270
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 CustomData pdata
float viewmat[4][4]
float winmat[4][4]
struct ToolSettings * toolsettings
View3DCursor cursor
struct bNodeTree * edittree
char geometry_nodes_type
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
PointerRNA op(wmOperatorType *ot, std::optional< blender::StringRef > name, int icon, wmOperatorCallContext context, eUI_Item_Flag flag)
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void separator(float factor=1.0f, LayoutSeparatorType type=LayoutSeparatorType::Auto)
void menu(MenuType *mt, std::optional< blender::StringRef > name, int icon)
int mval[2]
Definition WM_types.hh:760
struct ReportList * reports
IDProperty * properties
struct uiLayout * layout
struct PointerRNA * ptr
#define SEP_STR
Definition unit.cc:39
uint len
#define N_(msgid)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
PointerRNA * ptr
Definition wm_files.cc:4227
wmOperatorType * ot
Definition wm_files.cc:4226
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:139