Geometry Nodes: expose node warnings on modifier in Python API

This exposes warnings that are propagated to the modifier in the Python API.
This allows people to show these warnings in custom UIs for their node groups.

Warnings are accessed like this:
```python
for warning in modifier.node_warnings:
    print(warning.message)
    print(warning.type)
```

Note that this only works on the geometry nodes modifier. These warnings may
be extended with more information in the future. E.g. it could be useful to know
which node created the warning.

Pull Request: https://projects.blender.org/blender/blender/pulls/127193
This commit is contained in:
Jacques Lucke
2024-09-05 19:45:40 +02:00
parent a4d9bcf106
commit 809fed764a
4 changed files with 120 additions and 8 deletions

View File

@@ -55,6 +55,7 @@ DEF_ENUM(rna_enum_modifier_triangulate_ngon_method_items)
DEF_ENUM(rna_enum_modifier_shrinkwrap_mode_items)
DEF_ENUM(rna_enum_shrinkwrap_type_items)
DEF_ENUM(rna_enum_shrinkwrap_face_cull_items)
DEF_ENUM(rna_enum_node_warning_type_items)
DEF_ENUM(rna_enum_image_type_items)
DEF_ENUM(rna_enum_image_color_mode_items)

View File

@@ -244,6 +244,7 @@ set(INC
../../depsgraph
../../draw
../../gpu
../../functions
../../ikplugin
../../imbuf
../../io/usd

View File

@@ -26,6 +26,7 @@
#include "BKE_animsys.h"
#include "BKE_attribute.hh"
#include "BKE_compute_contexts.hh"
#include "BKE_curveprofile.h"
#include "BKE_customdata.hh"
#include "BKE_data_transfer.h"
@@ -48,6 +49,7 @@
#include "WM_types.hh"
#include "MOD_nodes.hh"
#include "NOD_geometry_nodes_log.hh"
const EnumPropertyItem rna_enum_object_modifier_type_items[] = {
RNA_ENUM_ITEM_HEADING(N_("Modify"), nullptr),
@@ -565,6 +567,13 @@ const EnumPropertyItem rna_enum_shrinkwrap_face_cull_items[] = {
{0, nullptr, 0, nullptr, nullptr},
};
const EnumPropertyItem rna_enum_node_warning_type_items[] = {
{int(blender::nodes::geo_eval_log::NodeWarningType::Error), "ERROR", 0, "Error", ""},
{int(blender::nodes::geo_eval_log::NodeWarningType::Warning), "WARNING", 0, "Warning", ""},
{int(blender::nodes::geo_eval_log::NodeWarningType::Info), "INFO", 0, "Info", ""},
{0, nullptr, 0, nullptr, nullptr},
};
#ifndef RNA_RUNTIME
/* use eWarp_Falloff_*** & eHook_Falloff_***, they're in sync */
static const EnumPropertyItem modifier_warp_falloff_items[] = {
@@ -1938,6 +1947,73 @@ static void rna_NodesModifier_node_group_update(Main *bmain, Scene *scene, Point
MOD_nodes_update_interface(object, nmd);
}
static blender::nodes::geo_eval_log::GeoTreeLog *get_nodes_modifier_log(NodesModifierData &nmd)
{
if (!nmd.runtime->eval_log) {
return nullptr;
}
blender::bke::ModifierComputeContext compute_context{nullptr, nmd.modifier.name};
return &nmd.runtime->eval_log->get_tree_log(compute_context.hash());
}
static blender::Span<blender::nodes::geo_eval_log::NodeWarning> get_node_modifier_warnings(
NodesModifierData &nmd)
{
if (auto *log = get_nodes_modifier_log(nmd)) {
log->ensure_node_warnings(nmd.node_group);
return log->all_warnings;
}
return {};
}
static void rna_NodesModifier_node_warnings_iterator_begin(CollectionPropertyIterator *iter,
PointerRNA *ptr)
{
NodesModifierData *nmd = static_cast<NodesModifierData *>(ptr->data);
iter->internal.count.item = 0;
iter->valid = !get_node_modifier_warnings(*nmd).is_empty();
}
static void rna_NodesModifier_node_warnings_iterator_next(CollectionPropertyIterator *iter)
{
NodesModifierData *nmd = static_cast<NodesModifierData *>(iter->parent.data);
iter->internal.count.item++;
iter->valid = get_node_modifier_warnings(*nmd).size() > iter->internal.count.item;
}
static PointerRNA rna_NodesModifier_node_warnings_iterator_get(CollectionPropertyIterator *iter)
{
NodesModifierData *nmd = static_cast<NodesModifierData *>(iter->parent.data);
blender::Span warnings = get_node_modifier_warnings(*nmd);
return RNA_pointer_create(iter->parent.owner_id,
&RNA_NodesModifierWarning,
(void *)&warnings[iter->internal.count.item]);
}
static int rna_NodesModifier_node_warnings_length(PointerRNA *ptr)
{
NodesModifierData *nmd = static_cast<NodesModifierData *>(ptr->data);
return get_node_modifier_warnings(*nmd).size();
}
static void rna_NodesModifierWarning_message_get(PointerRNA *ptr, char *r_value)
{
const auto *warning = static_cast<const blender::nodes::geo_eval_log::NodeWarning *>(ptr->data);
strcpy(r_value, warning->message.c_str());
}
static int rna_NodesModifierWarning_message_length(PointerRNA *ptr)
{
const auto *warning = static_cast<const blender::nodes::geo_eval_log::NodeWarning *>(ptr->data);
return warning->message.size();
}
static int rna_NodesModifierWarning_type_get(PointerRNA *ptr)
{
const auto *warning = static_cast<const blender::nodes::geo_eval_log::NodeWarning *>(ptr->data);
return int(warning->type);
}
static IDProperty **rna_NodesModifier_properties(PointerRNA *ptr)
{
NodesModifierData *nmd = static_cast<NodesModifierData *>(ptr->data);
@@ -7900,6 +7976,31 @@ static void rna_def_modifier_nodes_panels(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Panels", "State of all panels defined by the node group");
}
static void rna_def_modifier_nodes_warning(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "NodesModifierWarning", nullptr);
RNA_def_struct_ui_text(srna,
"Nodes Modifier Warning",
"Warning created during evaluation of a geometry nodes modifier");
prop = RNA_def_property(srna, "message", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Message", nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_string_funcs(prop,
"rna_NodesModifierWarning_message_get",
"rna_NodesModifierWarning_message_length",
nullptr);
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_ui_text(prop, "Type", nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_items(prop, rna_enum_node_warning_type_items);
RNA_def_property_enum_funcs(prop, "rna_NodesModifierWarning_type_get", nullptr, nullptr);
}
static void rna_def_modifier_nodes(BlenderRNA *brna)
{
StructRNA *srna;
@@ -7913,6 +8014,8 @@ static void rna_def_modifier_nodes(BlenderRNA *brna)
rna_def_modifier_nodes_panel(brna);
rna_def_modifier_nodes_panels(brna);
rna_def_modifier_nodes_warning(brna);
srna = RNA_def_struct(brna, "NodesModifier", "Modifier");
RNA_def_struct_ui_text(srna, "Nodes Modifier", "");
RNA_def_struct_sdna(srna, "NodesModifierData");
@@ -7950,6 +8053,18 @@ static void rna_def_modifier_nodes(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
RNA_def_property_update(prop, NC_OBJECT | ND_MODIFIER, nullptr);
prop = RNA_def_property(srna, "node_warnings", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_funcs(prop,
"rna_NodesModifier_node_warnings_iterator_begin",
"rna_NodesModifier_node_warnings_iterator_next",
nullptr,
"rna_NodesModifier_node_warnings_iterator_get",
"rna_NodesModifier_node_warnings_length",
nullptr,
nullptr,
nullptr);
RNA_def_property_struct_type(prop, "NodesModifierWarning");
rna_def_modifier_panel_open_prop(srna, "open_output_attributes_panel", 0);
rna_def_modifier_panel_open_prop(srna, "open_manage_panel", 1);
rna_def_modifier_panel_open_prop(srna, "open_bake_panel", 2);

View File

@@ -9,6 +9,8 @@
#include "NOD_rna_define.hh"
#include "RNA_enum_types.hh"
namespace blender::nodes::node_geo_warning_cc {
static void node_declare(NodeDeclarationBuilder &b)
@@ -71,18 +73,11 @@ static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
static void node_rna(StructRNA *srna)
{
static EnumPropertyItem warning_type_items[] = {
{int(NodeWarningType::Error), "ERROR", 0, "Error", ""},
{int(NodeWarningType::Warning), "WARNING", 0, "Warning", ""},
{int(NodeWarningType::Info), "INFO", 0, "Info", ""},
{0, nullptr, 0, nullptr, nullptr},
};
RNA_def_node_enum(srna,
"warning_type",
"Warning Type",
"",
warning_type_items,
rna_enum_node_warning_type_items,
NOD_inline_enum_accessors(custom1));
}