Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/node_ui_storage.cc
| Show All 33 Lines | |||||
| using blender::Map; | using blender::Map; | ||||
| using blender::StringRef; | using blender::StringRef; | ||||
| using blender::Vector; | using blender::Vector; | ||||
| /* Use a global mutex because otherwise it would have to be stored directly in the | /* Use a global mutex because otherwise it would have to be stored directly in the | ||||
| * bNodeTree struct in DNA. This could change if the node tree had a runtime struct. */ | * bNodeTree struct in DNA. This could change if the node tree had a runtime struct. */ | ||||
| static std::mutex global_ui_storage_mutex; | static std::mutex global_ui_storage_mutex; | ||||
| static void ui_storage_ensure(bNodeTree &ntree) | static NodeTreeUIStorage &ui_storage_ensure(bNodeTree &ntree) | ||||
| { | { | ||||
| /* As an optimization, only acquire a lock if the UI storage doesn't exist, | /* As an optimization, only acquire a lock if the UI storage doesn't exist, | ||||
| * because it only needs to be allocated once for every node tree. */ | * because it only needs to be allocated once for every node tree. */ | ||||
| if (ntree.ui_storage == nullptr) { | if (ntree.ui_storage == nullptr) { | ||||
| std::lock_guard<std::mutex> lock(global_ui_storage_mutex); | std::lock_guard<std::mutex> lock(global_ui_storage_mutex); | ||||
| /* Check again-- another thread may have allocated the storage while this one waited. */ | /* Check again-- another thread may have allocated the storage while this one waited. */ | ||||
| if (ntree.ui_storage == nullptr) { | if (ntree.ui_storage == nullptr) { | ||||
| ntree.ui_storage = new NodeTreeUIStorage(); | ntree.ui_storage = new NodeTreeUIStorage(); | ||||
| } | } | ||||
| } | } | ||||
| return *ntree.ui_storage; | |||||
| } | } | ||||
| const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C, | const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C, | ||||
| const bNodeTree &ntree, | const bNodeTree &ntree, | ||||
| const bNode &node) | const bNode &node) | ||||
| { | { | ||||
| const NodeTreeUIStorage *ui_storage = ntree.ui_storage; | const NodeTreeUIStorage *ui_storage = ntree.ui_storage; | ||||
| if (ui_storage == nullptr) { | if (ui_storage == nullptr) { | ||||
| Show All 24 Lines | |||||
| * can be used for execution in multiple places, but the entire UI storage can't be removed when | * 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. | * 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, | void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree, | ||||
| const NodeTreeEvaluationContext &context) | const NodeTreeEvaluationContext &context) | ||||
| { | { | ||||
| NodeTreeUIStorage *ui_storage = ntree.ui_storage; | NodeTreeUIStorage *ui_storage = ntree.ui_storage; | ||||
| if (ui_storage != nullptr) { | if (ui_storage != nullptr) { | ||||
| std::lock_guard<std::mutex> lock(ui_storage->context_map_mutex); | std::lock_guard<std::mutex> lock(ui_storage->mutex); | ||||
| ui_storage->context_map.remove(context); | ui_storage->context_map.remove(context); | ||||
| } | } | ||||
| } | } | ||||
| static void node_error_message_log(bNodeTree &ntree, | static void node_error_message_log(bNodeTree &ntree, | ||||
| const bNode &node, | const bNode &node, | ||||
| const StringRef message, | const StringRef message, | ||||
| const NodeWarningType type) | const NodeWarningType type) | ||||
| Show All 19 Lines | case NodeWarningType::Info: | ||||
| "Node Tree: \"%s\", Node: \"%s\", %s", | "Node Tree: \"%s\", Node: \"%s\", %s", | ||||
| ntree.id.name + 2, | ntree.id.name + 2, | ||||
| node.name, | node.name, | ||||
| message.data()); | message.data()); | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| static NodeUIStorage &node_ui_storage_ensure(bNodeTree &ntree, | static NodeUIStorage &node_ui_storage_ensure(NodeTreeUIStorage &locked_ui_storage, | ||||
| const NodeTreeEvaluationContext &context, | const NodeTreeEvaluationContext &context, | ||||
| const bNode &node) | const bNode &node) | ||||
| { | { | ||||
| ui_storage_ensure(ntree); | |||||
| NodeTreeUIStorage &ui_storage = *ntree.ui_storage; | |||||
| std::lock_guard<std::mutex> lock(ui_storage.context_map_mutex); | |||||
| Map<std::string, NodeUIStorage> &node_tree_ui_storage = | Map<std::string, NodeUIStorage> &node_tree_ui_storage = | ||||
| ui_storage.context_map.lookup_or_add_default(context); | locked_ui_storage.context_map.lookup_or_add_default(context); | ||||
| NodeUIStorage &node_ui_storage = node_tree_ui_storage.lookup_or_add_default_as( | NodeUIStorage &node_ui_storage = node_tree_ui_storage.lookup_or_add_default_as( | ||||
| StringRef(node.name)); | StringRef(node.name)); | ||||
| return node_ui_storage; | return node_ui_storage; | ||||
| } | } | ||||
| void BKE_nodetree_error_message_add(bNodeTree &ntree, | void BKE_nodetree_error_message_add(bNodeTree &ntree, | ||||
| const NodeTreeEvaluationContext &context, | const NodeTreeEvaluationContext &context, | ||||
| const bNode &node, | const bNode &node, | ||||
| const NodeWarningType type, | const NodeWarningType type, | ||||
| std::string message) | std::string message) | ||||
| { | { | ||||
| NodeTreeUIStorage &ui_storage = ui_storage_ensure(ntree); | |||||
| std::lock_guard lock{ui_storage.mutex}; | |||||
| node_error_message_log(ntree, node, message, type); | node_error_message_log(ntree, node, message, type); | ||||
| NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ntree, context, node); | NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ui_storage, context, node); | ||||
| std::lock_guard lock{node_ui_storage.mutex}; | |||||
| node_ui_storage.warnings.append({type, std::move(message)}); | node_ui_storage.warnings.append({type, std::move(message)}); | ||||
| } | } | ||||
| void BKE_nodetree_attribute_hint_add(bNodeTree &ntree, | void BKE_nodetree_attribute_hint_add(bNodeTree &ntree, | ||||
| const NodeTreeEvaluationContext &context, | const NodeTreeEvaluationContext &context, | ||||
| const bNode &node, | const bNode &node, | ||||
| const StringRef attribute_name, | const StringRef attribute_name, | ||||
| const AttributeDomain domain, | const AttributeDomain domain, | ||||
| const CustomDataType data_type) | const CustomDataType data_type) | ||||
| { | { | ||||
| NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ntree, context, node); | NodeTreeUIStorage &ui_storage = ui_storage_ensure(ntree); | ||||
| std::lock_guard lock{node_ui_storage.mutex}; | std::lock_guard lock{ui_storage.mutex}; | ||||
| NodeUIStorage &node_ui_storage = node_ui_storage_ensure(ui_storage, context, node); | |||||
| node_ui_storage.attribute_hints.add_as( | node_ui_storage.attribute_hints.add_as( | ||||
| AvailableAttributeInfo{attribute_name, domain, data_type}); | AvailableAttributeInfo{attribute_name, domain, data_type}); | ||||
| } | } | ||||