Merge branch 'blender-v4.5-release'

This commit is contained in:
Jacques Lucke
2025-06-12 12:32:46 +02:00
7 changed files with 97 additions and 6 deletions

View File

@@ -4425,6 +4425,69 @@ static void do_version_flip_node_options_to_inputs(bNodeTree *node_tree, bNode *
}
}
static void clamp_subdivision_node_level_input(bNodeTree &tree)
{
blender::Map<bNodeSocket *, bNodeLink *> links_to_level_and_max_inputs;
LISTBASE_FOREACH (bNodeLink *, link, &tree.links) {
if (link->tosock) {
if (ELEM(blender::StringRef(link->tosock->identifier), "Level", "Max")) {
links_to_level_and_max_inputs.add(link->tosock, link);
}
}
}
LISTBASE_FOREACH_MUTABLE (bNode *, node, &tree.nodes) {
if (!ELEM(node->type_legacy, GEO_NODE_SUBDIVISION_SURFACE, GEO_NODE_SUBDIVIDE_MESH)) {
continue;
}
bNodeSocket *level_input = blender::bke::node_find_socket(*node, SOCK_IN, "Level");
if (!level_input || level_input->type != SOCK_INT) {
continue;
}
bNodeLink *link = links_to_level_and_max_inputs.lookup_default(level_input, nullptr);
if (link) {
bNode *origin_node = link->fromnode;
if (origin_node->type_legacy == SH_NODE_CLAMP) {
bNodeSocket *max_input_socket = blender::bke::node_find_socket(
*origin_node, SOCK_IN, "Max");
if (max_input_socket->type == SOCK_FLOAT &&
!links_to_level_and_max_inputs.contains(max_input_socket))
{
if (max_input_socket->default_value_typed<bNodeSocketValueFloat>()->value <= 11.0f) {
/* There is already a clamp node, so no need to add another one. */
continue;
}
}
}
/* Insert clamp node. */
bNode &clamp_node = version_node_add_empty(tree, "ShaderNodeClamp");
clamp_node.parent = node->parent;
clamp_node.location[0] = node->location[0] - 25;
clamp_node.location[1] = node->location[1];
bNodeSocket &clamp_value_input = version_node_add_socket(
tree, clamp_node, SOCK_IN, "NodeSocketFloat", "Value");
bNodeSocket &clamp_min_input = version_node_add_socket(
tree, clamp_node, SOCK_IN, "NodeSocketFloat", "Min");
bNodeSocket &clamp_max_input = version_node_add_socket(
tree, clamp_node, SOCK_IN, "NodeSocketFloat", "Max");
bNodeSocket &clamp_value_output = version_node_add_socket(
tree, clamp_node, SOCK_OUT, "NodeSocketFloat", "Result");
static_cast<bNodeSocketValueFloat *>(clamp_min_input.default_value)->value = 0.0f;
static_cast<bNodeSocketValueFloat *>(clamp_max_input.default_value)->value = 11.0f;
link->tosock = &clamp_value_input;
version_node_add_link(tree, clamp_node, clamp_value_output, *node, *level_input);
}
else {
/* Clamp value directly. */
bNodeSocketValueInt *value = level_input->default_value_typed<bNodeSocketValueInt>();
value->value = std::clamp(value->value, 0, 11);
}
}
version_socket_update_is_used(&tree);
}
void do_versions_after_linking_450(FileData * /*fd*/, Main *bmain)
{
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 8)) {
@@ -6254,6 +6317,15 @@ void blo_do_versions_450(FileData * /*fd*/, Library * /*lib*/, Main *bmain)
fix_curve_nurbs_knot_mode_custom(bmain);
}
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 87)) {
FOREACH_NODETREE_BEGIN (bmain, tree, id) {
if (tree->type == NTREE_GEOMETRY) {
clamp_subdivision_node_level_input(*tree);
}
}
FOREACH_NODETREE_END;
}
/**
* Always bump subversion in BKE_blender_version.h when adding versioning
* code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check.

View File

@@ -2683,11 +2683,18 @@ static wmOperatorStatus grease_pencil_paste_strokes_exec(bContext *C, wmOperator
const bool keep_world_transform = RNA_boolean_get(op->ptr, "keep_world_transform");
const bool paste_on_back = RNA_boolean_get(op->ptr, "paste_back");
const Clipboard &clipboard = ensure_grease_pencil_clipboard();
Clipboard &clipboard = ensure_grease_pencil_clipboard();
if (clipboard.layers.is_empty()) {
return OPERATOR_CANCELLED;
}
/* Make sure everything on the clipboard is selected, in the correct selection domain. */
threading::parallel_for_each(clipboard.layers, [&](Clipboard::ClipboardLayer &layer) {
bke::GSpanAttributeWriter selection = ed::curves::ensure_selection_attribute(
layer.curves, selection_domain, CD_PROP_BOOL);
selection.finish();
});
if (type == PasteType::Active) {
Layer *active_layer = grease_pencil.get_active_layer();
if (!active_layer) {

View File

@@ -27,7 +27,7 @@ static void cmp_node_rgb_declare(NodeDeclarationBuilder &b)
.default_value({0.5f, 0.5f, 0.5f, 1.0f})
.custom_draw([](CustomSocketDrawParams &params) {
uiLayoutSetAlignment(&params.layout, UI_LAYOUT_ALIGN_EXPAND);
uiLayout &col = params.layout.column(true);
uiLayout &col = params.layout.column(false);
uiTemplateColorPicker(
&col, &params.socket_ptr, "default_value", true, false, false, false);
col.prop(&params.socket_ptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE);

View File

@@ -15,7 +15,7 @@ static void node_declare(NodeDeclarationBuilder &b)
{
b.add_output<decl::Color>("Color").custom_draw([](CustomSocketDrawParams &params) {
uiLayoutSetAlignment(&params.layout, UI_LAYOUT_ALIGN_EXPAND);
uiLayout &col = params.layout.column(true);
uiLayout &col = params.layout.column(false);
uiTemplateColorPicker(&col, &params.node_ptr, "value", true, false, false, true);
col.prop(&params.node_ptr, "value", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
});

View File

@@ -58,11 +58,17 @@ static void node_geo_exec(GeoNodeExecParams params)
GeometrySet geometry_set = params.extract_input<GeometrySet>("Mesh");
#ifdef WITH_OPENSUBDIV
/* See CCGSUBSURF_LEVEL_MAX for max limit. */
const int level = clamp_i(params.extract_input<int>("Level"), 0, 11);
const int level = std::max(params.extract_input<int>("Level"), 0);
if (level == 0) {
params.set_output("Mesh", std::move(geometry_set));
return;
}
/* At this limit, a subdivided single triangle would be too large to be stored in #Mesh. */
if (level >= 16) {
params.error_message_add(NodeWarningType::Error, TIP_("The subdivision level is too large"));
params.set_default_remaining_outputs();
return;
}
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (const Mesh *mesh = geometry_set.get_mesh()) {

View File

@@ -186,12 +186,18 @@ static void node_geo_exec(GeoNodeExecParams params)
const NodeGeometrySubdivisionSurface &storage = node_storage(params.node());
const int uv_smooth = storage.uv_smooth;
const int boundary_smooth = storage.boundary_smooth;
const int level = std::clamp(params.extract_input<int>("Level"), 0, 11);
const int level = std::max(params.extract_input<int>("Level"), 0);
const bool use_limit_surface = params.extract_input<bool>("Limit Surface");
if (level == 0) {
params.set_output("Mesh", std::move(geometry_set));
return;
}
/* At this limit, a subdivided single triangle would be too large to be stored in #Mesh. */
if (level >= 16) {
params.error_message_add(NodeWarningType::Error, TIP_("The subdivision level is too large"));
params.set_default_remaining_outputs();
return;
}
geometry_set.modify_geometry_sets([&](GeometrySet &geometry_set) {
if (const Mesh *mesh = geometry_set.get_mesh()) {

View File

@@ -19,7 +19,7 @@ static void node_declare(NodeDeclarationBuilder &b)
.default_value({0.5f, 0.5f, 0.5f, 1.0f})
.custom_draw([](CustomSocketDrawParams &params) {
uiLayoutSetAlignment(&params.layout, UI_LAYOUT_ALIGN_EXPAND);
uiLayout &col = params.layout.column(true);
uiLayout &col = params.layout.column(false);
uiTemplateColorPicker(
&col, &params.socket_ptr, "default_value", true, false, false, false);
col.prop(&params.socket_ptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE);