Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Goudey <h.goudey@me.com>2021-02-17 02:15:08 +0300
committerHans Goudey <h.goudey@me.com>2021-02-17 02:15:08 +0300
commit461d4fc1aae200a6310a254b6e7c08070d9e94a7 (patch)
treef2ac642a29497855d879a022bc249a242a05b666 /source/blender/editors
parentc9c4802c1c26d1125d9bb41ff9187b61e167cc42 (diff)
Geometry Nodes: Node error messages
This patch adds icons to the right side of nodes when they encounter a a problem. When hovered, a tooltip displays describing the encountered while evaluating the node. Some examples are: attribute doesn't exist, mesh has no faces, incorrect attribute type, etc. Exposing more messages to the system will be an ongoing process. Multiple warnings per node are supported. The system is implemented somewhat generically so that the basic structure can also be used to store more information from evaluation for the interface, like a list of available attributes. Currently the messages are just button tooltips. They could be styled differently in the future. Another limitation is that every instance of a node group in a parent node tree will have the same error messages, the "evaluation context" used to decide when to display the tooltips must be extended to support node tree paths. Differential Revision: https://developer.blender.org/D10290
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/space_node/node_draw.cc145
1 files changed, 144 insertions, 1 deletions
diff --git a/source/blender/editors/space_node/node_draw.cc b/source/blender/editors/space_node/node_draw.cc
index 8662217961c..f85d29f99d5 100644
--- a/source/blender/editors/space_node/node_draw.cc
+++ b/source/blender/editors/space_node/node_draw.cc
@@ -27,6 +27,7 @@
#include "DNA_light_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_material_types.h"
+#include "DNA_modifier_types.h"
#include "DNA_node_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -34,7 +35,11 @@
#include "DNA_world_types.h"
#include "BLI_blenlib.h"
+#include "BLI_map.hh"
#include "BLI_math.h"
+#include "BLI_span.hh"
+#include "BLI_string_ref.hh"
+#include "BLI_vector.hh"
#include "BLT_translation.h"
@@ -42,6 +47,8 @@
#include "BKE_lib_id.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_node_ui_storage.hh"
+#include "BKE_object.h"
#include "DEG_depsgraph.h"
@@ -74,6 +81,11 @@
# include "COM_compositor.h"
#endif
+using blender::Map;
+using blender::Span;
+using blender::StringRef;
+using blender::Vector;
+
extern "C" {
/* XXX interface.h */
extern void ui_draw_dropshadow(
@@ -1178,6 +1190,135 @@ void node_draw_sockets(const View2D *v2d,
}
}
+static int node_error_type_to_icon(const NodeWarningType type)
+{
+ switch (type) {
+ case NodeWarningType::Error:
+ return ICON_ERROR;
+ case NodeWarningType::Warning:
+ return ICON_ERROR;
+ case NodeWarningType::Info:
+ return ICON_INFO;
+ }
+
+ BLI_assert(false);
+ return ICON_ERROR;
+}
+
+static uint8_t node_error_type_priority(const NodeWarningType type)
+{
+ switch (type) {
+ case NodeWarningType::Error:
+ return 3;
+ case NodeWarningType::Warning:
+ return 2;
+ case NodeWarningType::Info:
+ return 1;
+ }
+
+ BLI_assert(false);
+ return 0;
+}
+
+static NodeWarningType node_error_highest_priority(Span<NodeWarning> warnings)
+{
+ uint8_t highest_priority = 0;
+ NodeWarningType highest_priority_type = NodeWarningType::Info;
+ for (const NodeWarning &warning : warnings) {
+ const uint8_t priority = node_error_type_priority(warning.type);
+ if (priority > highest_priority) {
+ highest_priority = priority;
+ highest_priority_type = warning.type;
+ }
+ }
+ return highest_priority_type;
+}
+
+static char *node_errrors_tooltip_fn(bContext *UNUSED(C), void *argN, const char *UNUSED(tip))
+{
+ const NodeUIStorage **storage_pointer_alloc = static_cast<const NodeUIStorage **>(argN);
+ const NodeUIStorage *node_ui_storage = *storage_pointer_alloc;
+ Span<NodeWarning> warnings = node_ui_storage->warnings;
+
+ std::string complete_string;
+
+ for (const NodeWarning &warning : warnings.drop_back(1)) {
+ complete_string += warning.message;
+ complete_string += '\n';
+ }
+
+ complete_string += warnings.last().message;
+
+ /* Remove the last period-- the tooltip system adds this automatically. */
+ if (complete_string.back() == '.') {
+ complete_string.pop_back();
+ }
+
+ return BLI_strdupn(complete_string.c_str(), complete_string.size());
+}
+
+#define NODE_HEADER_ICON_SIZE (0.8f * U.widget_unit)
+
+static const NodeUIStorage *node_ui_storage_get_from_context(const bContext *C,
+ const bNodeTree &ntree,
+ const bNode &node)
+{
+ const NodeTreeUIStorage *ui_storage = ntree.ui_storage;
+ if (ui_storage == nullptr) {
+ return nullptr;
+ }
+
+ const Object *active_object = CTX_data_active_object(C);
+ const ModifierData *active_modifier = BKE_object_active_modifier(active_object);
+ if (active_object == nullptr || active_modifier == nullptr) {
+ return nullptr;
+ }
+
+ const NodeTreeEvaluationContext context(*active_object, *active_modifier);
+ const Map<std::string, NodeUIStorage> *storage = ui_storage->context_map.lookup_ptr(context);
+ if (storage == nullptr) {
+ return nullptr;
+ }
+
+ return storage->lookup_ptr_as(StringRef(node.name));
+}
+
+static void node_add_error_message_button(
+ const bContext *C, bNodeTree &ntree, bNode &node, const rctf &rect, float &icon_offset)
+{
+ const NodeUIStorage *node_ui_storage = node_ui_storage_get_from_context(C, ntree, node);
+ if (node_ui_storage == nullptr) {
+ return;
+ }
+
+ /* The UI API forces us to allocate memory for each error button, because the
+ * ownership of #UI_but_func_tooltip_set's argument is transferred to the button. */
+ const NodeUIStorage **storage_pointer_alloc = (const NodeUIStorage **)MEM_mallocN(
+ sizeof(NodeUIStorage *), __func__);
+ *storage_pointer_alloc = node_ui_storage;
+
+ const NodeWarningType display_type = node_error_highest_priority(node_ui_storage->warnings);
+
+ icon_offset -= NODE_HEADER_ICON_SIZE;
+ UI_block_emboss_set(node.block, UI_EMBOSS_NONE);
+ uiBut *but = uiDefIconBut(node.block,
+ UI_BTYPE_BUT,
+ 0,
+ node_error_type_to_icon(display_type),
+ icon_offset,
+ rect.ymax - NODE_DY,
+ NODE_HEADER_ICON_SIZE,
+ UI_UNIT_Y,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ nullptr);
+ UI_but_func_tooltip_set(but, node_errrors_tooltip_fn, storage_pointer_alloc);
+ UI_block_emboss_set(node.block, UI_EMBOSS);
+}
+
static void node_draw_basis(const bContext *C,
const View2D *v2d,
const SpaceNode *snode,
@@ -1186,7 +1327,7 @@ static void node_draw_basis(const bContext *C,
bNodeInstanceKey key)
{
/* float socket_size = NODE_SOCKSIZE*U.dpi/72; */ /* UNUSED */
- const float iconbutw = 0.8f * U.widget_unit;
+ const float iconbutw = NODE_HEADER_ICON_SIZE;
/* skip if out of view */
if (BLI_rctf_isect(&node->totr, &v2d->cur, nullptr) == false) {
@@ -1297,6 +1438,8 @@ static void node_draw_basis(const bContext *C,
UI_block_emboss_set(node->block, UI_EMBOSS);
}
+ node_add_error_message_button(C, *ntree, *node, *rct, iconofs);
+
/* title */
if (node->flag & SELECT) {
UI_GetThemeColor4fv(TH_SELECT, color);