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/blenkernel
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/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_node_ui_storage.hh95
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/node.cc10
-rw-r--r--source/blender/blenkernel/intern/node_ui_storage.cc104
4 files changed, 210 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_node_ui_storage.hh b/source/blender/blenkernel/BKE_node_ui_storage.hh
new file mode 100644
index 00000000000..0b8ef60a603
--- /dev/null
+++ b/source/blender/blenkernel/BKE_node_ui_storage.hh
@@ -0,0 +1,95 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include "BLI_hash.hh"
+#include "BLI_map.hh"
+#include "BLI_session_uuid.h"
+
+#include "DNA_ID.h"
+#include "DNA_modifier_types.h"
+#include "DNA_session_uuid_types.h"
+
+struct bNode;
+struct bNodeTree;
+struct Object;
+struct ModifierData;
+
+using blender::Map;
+
+/**
+ * Contains the context necessary to determine when to display settings for a certain node tree
+ * that may be used for multiple modifiers and objects. The object name and modifier session UUID
+ * are used instead of pointers because they are re-allocated between evaluations.
+ *
+ * \note This does not yet handle the context of nested node trees.
+ */
+class NodeTreeEvaluationContext {
+ private:
+ std::string object_name_;
+ SessionUUID modifier_session_uuid_;
+
+ public:
+ NodeTreeEvaluationContext(const Object &object, const ModifierData &modifier)
+ {
+ object_name_ = reinterpret_cast<const ID &>(object).name;
+ modifier_session_uuid_ = modifier.session_uuid;
+ }
+
+ uint64_t hash() const
+ {
+ const uint64_t hash1 = blender::DefaultHash<std::string>{}(object_name_);
+ const uint64_t hash2 = BLI_session_uuid_hash_uint64(&modifier_session_uuid_);
+ return hash1 ^ (hash2 * 33); /* Copied from DefaultHash for std::pair. */
+ }
+
+ bool operator==(const NodeTreeEvaluationContext &other) const
+ {
+ return other.object_name_ == object_name_ &&
+ BLI_session_uuid_is_equal(&other.modifier_session_uuid_, &modifier_session_uuid_);
+ }
+};
+
+enum class NodeWarningType {
+ Error,
+ Warning,
+ Info,
+};
+
+struct NodeWarning {
+ NodeWarningType type;
+ std::string message;
+};
+
+struct NodeUIStorage {
+ blender::Vector<NodeWarning> warnings;
+};
+
+struct NodeTreeUIStorage {
+ Map<NodeTreeEvaluationContext, Map<std::string, NodeUIStorage>> context_map;
+};
+
+void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree,
+ const NodeTreeEvaluationContext &context);
+
+void BKE_nodetree_ui_storage_ensure(bNodeTree &ntree);
+
+void BKE_nodetree_error_message_add(bNodeTree &ntree,
+ const NodeTreeEvaluationContext &context,
+ const bNode &node,
+ const NodeWarningType type,
+ std::string message);
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index ead01dbd6cb..f288bf9aabc 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -200,6 +200,7 @@ set(SRC
intern/multires_versioning.c
intern/nla.c
intern/node.cc
+ intern/node_ui_storage.cc
intern/object.c
intern/object_deform.c
intern/object_dupli.c
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index e34afd1ce17..f455f83f5c5 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -49,6 +49,7 @@
#include "BLI_ghash.h"
#include "BLI_listbase.h"
+#include "BLI_map.hh"
#include "BLI_math.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
@@ -68,6 +69,7 @@
#include "BKE_lib_query.h"
#include "BKE_main.h"
#include "BKE_node.h"
+#include "BKE_node_ui_storage.hh"
#include "BLI_ghash.h"
#include "BLI_threads.h"
@@ -215,6 +217,10 @@ static void ntree_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, c
/* node tree will generate its own interface type */
ntree_dst->interface_type = nullptr;
+
+ /* Don't copy error messages in the runtime struct.
+ * They should be filled during execution anyway. */
+ ntree_dst->ui_storage = nullptr;
}
static void ntree_free_data(ID *id)
@@ -268,6 +274,8 @@ static void ntree_free_data(ID *id)
if (ntree->id.tag & LIB_TAG_LOCALIZED) {
BKE_libblock_free_data(&ntree->id, true);
}
+
+ delete ntree->ui_storage;
}
static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket *sock)
@@ -557,6 +565,7 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres
ntree->interface_type = nullptr;
ntree->progress = nullptr;
ntree->execdata = nullptr;
+ ntree->ui_storage = nullptr;
BLO_write_id_struct(writer, bNodeTree, id_address, &ntree->id);
@@ -588,6 +597,7 @@ void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
ntree->progress = nullptr;
ntree->execdata = nullptr;
+ ntree->ui_storage = nullptr;
BLO_read_data_address(reader, &ntree->adt);
BKE_animdata_blend_read_data(reader, ntree->adt);
diff --git a/source/blender/blenkernel/intern/node_ui_storage.cc b/source/blender/blenkernel/intern/node_ui_storage.cc
new file mode 100644
index 00000000000..4c8a5c824c4
--- /dev/null
+++ b/source/blender/blenkernel/intern/node_ui_storage.cc
@@ -0,0 +1,104 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "CLG_log.h"
+
+#include "BLI_map.hh"
+#include "BLI_string_ref.hh"
+#include "BLI_vector.hh"
+
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+
+#include "BKE_node_ui_storage.hh"
+
+static CLG_LogRef LOG = {"bke.node_ui_storage"};
+
+using blender::Map;
+using blender::StringRef;
+using blender::Vector;
+
+void BKE_nodetree_ui_storage_ensure(bNodeTree &ntree)
+{
+ if (ntree.ui_storage == nullptr) {
+ ntree.ui_storage = new NodeTreeUIStorage();
+ }
+}
+
+/**
+ * Removes only the UI data associated with a particular evaluation context. The same node tree
+ * can be used for execution in multiple places, but the entire UI storage can't be removed when
+ * one execution starts, or all of the data associated with the node tree would be lost.
+ */
+void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree,
+ const NodeTreeEvaluationContext &context)
+{
+ NodeTreeUIStorage *ui_storage = ntree.ui_storage;
+ if (ui_storage != nullptr) {
+ ui_storage->context_map.remove(context);
+ }
+}
+
+static void node_error_message_log(bNodeTree &ntree,
+ const bNode &node,
+ const StringRef message,
+ const NodeWarningType type)
+{
+ switch (type) {
+ case NodeWarningType::Error:
+ CLOG_ERROR(&LOG,
+ "Node Tree: \"%s\", Node: \"%s\", %s",
+ ntree.id.name + 2,
+ node.name,
+ message.data());
+ break;
+ case NodeWarningType::Warning:
+ CLOG_WARN(&LOG,
+ "Node Tree: \"%s\", Node: \"%s\", %s",
+ ntree.id.name + 2,
+ node.name,
+ message.data());
+ break;
+ case NodeWarningType::Info:
+ CLOG_INFO(&LOG,
+ 2,
+ "Node Tree: \"%s\", Node: \"%s\", %s",
+ ntree.id.name + 2,
+ node.name,
+ message.data());
+ break;
+ }
+}
+
+void BKE_nodetree_error_message_add(bNodeTree &ntree,
+ const NodeTreeEvaluationContext &context,
+ const bNode &node,
+ const NodeWarningType type,
+ std::string message)
+{
+ BLI_assert(ntree.ui_storage != nullptr);
+ NodeTreeUIStorage &ui_storage = *ntree.ui_storage;
+
+ node_error_message_log(ntree, node, message, type);
+
+ Map<std::string, NodeUIStorage> &node_tree_ui_storage =
+ ui_storage.context_map.lookup_or_add_default(context);
+
+ NodeUIStorage &node_ui_storage = node_tree_ui_storage.lookup_or_add_default_as(
+ StringRef(node.name));
+
+ node_ui_storage.warnings.append({type, std::move(message)});
+}