From 8b5c13ac283324bb2510409f7113c7b3c52670ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Thu, 9 Oct 2025 11:01:25 +0200 Subject: [PATCH 1/3] Anim: do not access clipboard in Paste Global Transform poll function Remove access to the clipboard from the Paste Global Transform operator poll function, as it can cause slowdowns when there is a lot of data on the clipboard. This also means that the parsing code has to be a bit more lenient to the contents of the clipboard. And, because the error message that there is no matrix on the clipboard is now going to be shown more often, I made it a bit more friendly. Pull Request: https://projects.blender.org/blender/blender/pulls/147562 --- .../bl_operators/copy_global_transform.py | 48 ++++++++++++------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/scripts/startup/bl_operators/copy_global_transform.py b/scripts/startup/bl_operators/copy_global_transform.py index 867695f5d9c..3260cd9ebfc 100644 --- a/scripts/startup/bl_operators/copy_global_transform.py +++ b/scripts/startup/bl_operators/copy_global_transform.py @@ -267,13 +267,28 @@ class OBJECT_OT_paste_transform(Operator): if not context.active_pose_bone and not context.active_object: cls.poll_message_set("Select an object or pose bone") return False - - clipboard = context.window_manager.clipboard.strip() - if not (clipboard.startswith("Matrix(") or clipboard.startswith(" Matrix | None: + if value.startswith("Matrix"): + return cls.parse_matrix(value) + if value.startswith(" Matrix | None: + import ast + try: + return Matrix(ast.literal_eval(value[6:])) + except Exception: + # ast.literal_eval() can raise a slew of exceptions, all of + # which means that it's not a matrix on the clipboard. + return None + @staticmethod def parse_print_m4(value: str) -> Optional[Matrix]: """Parse output from Blender's print_m4() function. @@ -285,7 +300,11 @@ class OBJECT_OT_paste_transform(Operator): if len(lines) != 4: return None - floats = tuple(tuple(float(item) for item in line.split()) for line in lines) + try: + floats = tuple(tuple(float(item) for item in line.split()) for line in lines) + except ValueError: + # Apprently not the expected format. + return None return Matrix(floats) @staticmethod @@ -296,22 +315,19 @@ class OBJECT_OT_paste_transform(Operator): if len(lines) != 4: return None - floats = tuple(tuple(float(item.strip()) for item in line.strip()[1:-1].split(',')) for line in lines) + try: + floats = tuple(tuple(float(item.strip()) for item in line.strip()[1:-1].split(',')) for line in lines) + except ValueError: + # Apprently not the expected format. + return None return Matrix(floats) def execute(self, context: Context) -> set[str]: - import ast - clipboard = context.window_manager.clipboard.strip() - if clipboard.startswith("Matrix"): - mat = Matrix(ast.literal_eval(clipboard[6:])) - elif clipboard.startswith(" Date: Thu, 9 Oct 2025 11:02:00 +0200 Subject: [PATCH 2/3] Fix #147484: crash when opening window while rendering The issue here was that the node-tree-update code was accessing data in `bmain` when it shouldn't. The fix is to just use the correct API for this use-case when updating a temporary node tree. It doesn't need `bmain` in this case. Pull Request: https://projects.blender.org/blender/blender/pulls/147611 --- source/blender/blenkernel/intern/node_tree_update.cc | 1 + source/blender/nodes/shader/node_shader_tree.cc | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/intern/node_tree_update.cc b/source/blender/blenkernel/intern/node_tree_update.cc index c30a5040ceb..5eb818e40f9 100644 --- a/source/blender/blenkernel/intern/node_tree_update.cc +++ b/source/blender/blenkernel/intern/node_tree_update.cc @@ -2189,6 +2189,7 @@ void BKE_ntree_update_after_single_tree_change(Main &bmain, void BKE_ntree_update_without_main(bNodeTree &tree) { + BLI_assert(tree.id.tag & ID_TAG_NO_MAIN); if (is_updating) { return; } diff --git a/source/blender/nodes/shader/node_shader_tree.cc b/source/blender/nodes/shader/node_shader_tree.cc index 703f4785168..bb6d803d05a 100644 --- a/source/blender/nodes/shader/node_shader_tree.cc +++ b/source/blender/nodes/shader/node_shader_tree.cc @@ -437,12 +437,12 @@ static bool ntree_shader_implicit_closure_cast(bNodeTree *ntree) } else if ((link->fromsock->type == SOCK_SHADER) && (link->tosock->type != SOCK_SHADER)) { blender::bke::node_remove_link(ntree, *link); - BKE_ntree_update_after_single_tree_change(*G.main, *ntree); + BKE_ntree_update_without_main(*ntree); modified = true; } } if (modified) { - BKE_ntree_update_after_single_tree_change(*G.main, *ntree); + BKE_ntree_update_without_main(*ntree); } return true; } @@ -736,7 +736,7 @@ static void ntree_shader_weight_tree_invert(bNodeTree *ntree, bNode *output_node *output_node, *thickness_output); } - BKE_ntree_update_after_single_tree_change(*G.main, *ntree); + BKE_ntree_update_without_main(*ntree); } static bool closure_node_filter(const bNode *node) @@ -788,7 +788,7 @@ static void ntree_shader_shader_to_rgba_branches(bNodeTree *ntree) continue; } ntree_shader_copy_branch(ntree, shader_to_rgba, closure_node_filter); - BKE_ntree_update_after_single_tree_change(*G.main, *ntree); + BKE_ntree_update_without_main(*ntree); ntree_shader_weight_tree_invert(ntree, shader_to_rgba); } @@ -981,7 +981,7 @@ static void ntree_shader_pruned_unused(bNodeTree *ntree, bNode *output_node) } if (changed) { - BKE_ntree_update_after_single_tree_change(*G.main, *ntree); + BKE_ntree_update_without_main(*ntree); } } From 8eb3fdf398fef31f9a5cfc367d477b6820630ac3 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Thu, 9 Oct 2025 11:23:13 +0200 Subject: [PATCH 3/3] Fix #147587: don't enter custom groups with double click This is the same behavior as with TAB. --- source/blender/editors/space_node/node_group.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/blender/editors/space_node/node_group.cc b/source/blender/editors/space_node/node_group.cc index 1ea1fe0cc2c..e12469df2b4 100644 --- a/source/blender/editors/space_node/node_group.cc +++ b/source/blender/editors/space_node/node_group.cc @@ -242,6 +242,9 @@ static wmOperatorStatus node_group_enter_exit_invoke(bContext *C, if (!node->is_group()) { return OPERATOR_PASS_THROUGH; } + if (node->is_custom_group()) { + return OPERATOR_PASS_THROUGH; + } bNodeTree *group = id_cast(node->id); if (!group || ID_MISSING(group)) { return OPERATOR_PASS_THROUGH;