Geometry Nodes: support customizing warning propagation

Previously, all errors, warnings and info messages were propagated from the node
that generates it to the top level node group. This is a good default, but may
not always be desirable. For example, someone may build a node group asset that
generates some warning that is irrelevant to the user to the asset. Now, the
asset author can selectively disable propagating warnings from that node.

Each node has a new `Warning Propagation` setting. It controls if warnings from
this node should be propagated to the parent group node. By default, everything
is propagated. One can also choose to propagate nothing, only errors or only
errors and warnings.

Note, this does not affect whether the warning is shown in the node itself, only
if the warning is propagated one level up!
Pull Request: https://projects.blender.org/blender/blender/pulls/126786
This commit is contained in:
Jacques Lucke
2024-08-30 12:06:48 +02:00
parent b4a6610c88
commit 1ee6a8fad5
8 changed files with 94 additions and 10 deletions

View File

@@ -689,10 +689,17 @@ class NODE_PT_active_node_generic(Panel):
def draw(self, context):
layout = self.layout
node = context.active_node
tree = node.id_data
layout.use_property_split = True
layout.use_property_decorate = False
layout.prop(node, "name", icon='NODE')
layout.prop(node, "label", icon='NODE')
if tree.type == "GEOMETRY":
layout.prop(node, "warning_propagation")
class NODE_PT_active_node_color(Panel):
bl_space_type = 'NODE_EDITOR'

View File

@@ -571,7 +571,7 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
}
geo_log::GeoTreeLog &tree_log = eval_log.log->get_tree_log(compute_context.hash());
tree_log.ensure_node_warnings();
tree_log.ensure_node_warnings(node_tree);
for (const geo_log::NodeWarning &warning : tree_log.all_warnings) {
if (warning.type == geo_log::NodeWarningType::Info) {
BKE_report(op->reports, RPT_INFO, warning.message.c_str());

View File

@@ -4773,7 +4773,7 @@ static void draw_nodetree(const bContext &C,
tree_draw_ctx.geo_log_by_zone = geo_log::GeoModifierLog::get_tree_log_by_zone_for_node_editor(
*snode);
for (geo_log::GeoTreeLog *log : tree_draw_ctx.geo_log_by_zone.values()) {
log->ensure_node_warnings();
log->ensure_node_warnings(&ntree);
log->ensure_node_run_time();
}
const WorkSpace *workspace = CTX_wm_workspace(&C);

View File

@@ -348,6 +348,13 @@ typedef struct bNodePanelState {
#endif
} bNodePanelState;
typedef enum NodeWarningPropagation {
NODE_WARNING_PROPAGATION_ALL = 0,
NODE_WARNING_PROPAGATION_NONE = 1,
NODE_WARNING_PROPAGATION_ONLY_ERRORS = 2,
NODE_WARNING_PROPAGATION_ONLY_ERRORS_AND_WARNINGS = 3,
} NodeWarningPropagation;
typedef struct bNode {
struct bNode *next, *prev;
@@ -394,6 +401,12 @@ typedef struct bNode {
int16_t custom1, custom2;
float custom3, custom4;
/**
* #NodeWarningPropagation.
*/
int8_t warning_propagation;
char _pad[7];
/**
* Optional link to libdata.
*

View File

@@ -10299,6 +10299,18 @@ static void rna_def_node(BlenderRNA *brna)
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem warning_propagation_items[] = {
{NODE_WARNING_PROPAGATION_ALL, "ALL", 0, "All", ""},
{NODE_WARNING_PROPAGATION_NONE, "NONE", 0, "None", ""},
{NODE_WARNING_PROPAGATION_ONLY_ERRORS, "ERRORS", 0, "Errors", ""},
{NODE_WARNING_PROPAGATION_ONLY_ERRORS_AND_WARNINGS,
"ERRORS_AND_WARNINGS",
0,
"Errors and Warnings",
""},
{0, nullptr, 0, nullptr, nullptr},
};
srna = RNA_def_struct(brna, "Node", nullptr);
RNA_def_struct_ui_text(srna, "Node", "Node in a node tree");
RNA_def_struct_sdna(srna, "bNode");
@@ -10411,6 +10423,14 @@ static void rna_def_node(BlenderRNA *brna)
RNA_def_property_struct_type(prop, "Node");
RNA_def_property_ui_text(prop, "Parent", "Parent this node is attached to");
prop = RNA_def_property(srna, "warning_propagation", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, warning_propagation_items);
RNA_def_property_ui_text(
prop,
"Warning Propagation",
"The kinds of messages that should be propagated from this node to the parent group node");
RNA_def_property_update(prop, 0, "rna_Node_update");
prop = RNA_def_property(srna, "use_custom_color", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", NODE_CUSTOM_COLOR);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);

View File

@@ -2341,7 +2341,7 @@ static void panel_draw(const bContext *C, Panel *panel)
/* Draw node warnings. */
geo_log::GeoTreeLog *tree_log = get_root_tree_log(*nmd);
if (tree_log != nullptr) {
tree_log->ensure_node_warnings();
tree_log->ensure_node_warnings(nmd->node_group);
for (const geo_log::NodeWarning &warning : tree_log->all_warnings) {
if (warning.type != geo_log::NodeWarningType::Info) {
uiItemL(layout,

View File

@@ -313,7 +313,7 @@ class GeoTreeLog {
GeoTreeLog(GeoModifierLog *modifier_log, Vector<GeoTreeLogger *> tree_loggers);
~GeoTreeLog();
void ensure_node_warnings();
void ensure_node_warnings(const bNodeTree *tree);
void ensure_node_run_time();
void ensure_socket_values();
void ensure_viewer_node_logs();

View File

@@ -266,15 +266,41 @@ void GeoTreeLogger::log_viewer_node(const bNode &viewer_node, bke::GeometrySet g
this->viewer_node_logs.append(*this->allocator, {viewer_node.identifier, std::move(log)});
}
void GeoTreeLog::ensure_node_warnings()
static bool warning_is_propagated(const NodeWarningPropagation propagation,
const NodeWarningType warning_type)
{
switch (propagation) {
case NODE_WARNING_PROPAGATION_ALL:
return true;
case NODE_WARNING_PROPAGATION_NONE:
return false;
case NODE_WARNING_PROPAGATION_ONLY_ERRORS:
return warning_type == NodeWarningType::Error;
case NODE_WARNING_PROPAGATION_ONLY_ERRORS_AND_WARNINGS:
return ELEM(warning_type, NodeWarningType::Error, NodeWarningType::Warning);
}
BLI_assert_unreachable();
return true;
}
void GeoTreeLog::ensure_node_warnings(const bNodeTree *tree)
{
if (reduced_node_warnings_) {
return;
}
for (GeoTreeLogger *tree_logger : tree_loggers_) {
for (const GeoTreeLogger::WarningWithNode &warnings : tree_logger->node_warnings) {
this->nodes.lookup_or_add_default(warnings.node_id).warnings.add(warnings.warning);
this->all_warnings.add(warnings.warning);
for (const GeoTreeLogger::WarningWithNode &warning : tree_logger->node_warnings) {
NodeWarningPropagation propagation = NODE_WARNING_PROPAGATION_ALL;
if (tree) {
if (const bNode *node = tree->node_by_id(warning.node_id)) {
propagation = NodeWarningPropagation(node->warning_propagation);
}
}
this->nodes.lookup_or_add_default(warning.node_id).warnings.add(warning.warning);
if (warning_is_propagated(propagation, warning.warning.type)) {
this->all_warnings.add(warning.warning);
}
}
}
for (const ComputeContextHash &child_hash : children_hashes_) {
@@ -282,13 +308,31 @@ void GeoTreeLog::ensure_node_warnings()
if (child_log.tree_loggers_.is_empty()) {
continue;
}
child_log.ensure_node_warnings();
NodeWarningPropagation propagation = NODE_WARNING_PROPAGATION_ALL;
const bNodeTree *child_tree = nullptr;
const std::optional<int32_t> &parent_node_id = child_log.tree_loggers_[0]->parent_node_id;
if (tree && parent_node_id) {
if (const bNode *node = tree->node_by_id(*parent_node_id)) {
propagation = NodeWarningPropagation(node->warning_propagation);
if (node->is_group() && node->id) {
child_tree = reinterpret_cast<const bNodeTree *>(node->id);
}
else if (bke::all_zone_output_node_types().contains(node->type)) {
child_tree = tree;
}
}
}
child_log.ensure_node_warnings(child_tree);
if (parent_node_id.has_value()) {
this->nodes.lookup_or_add_default(*parent_node_id)
.warnings.add_multiple(child_log.all_warnings);
}
this->all_warnings.add_multiple(child_log.all_warnings);
for (const NodeWarning &warning : child_log.all_warnings) {
if (warning_is_propagated(propagation, warning.type)) {
this->all_warnings.add(warning);
continue;
}
}
}
reduced_node_warnings_ = true;
}