Merge branch 'blender-v4.5-release'
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 ¶ms) {
|
||||
uiLayoutSetAlignment(¶ms.layout, UI_LAYOUT_ALIGN_EXPAND);
|
||||
uiLayout &col = params.layout.column(true);
|
||||
uiLayout &col = params.layout.column(false);
|
||||
uiTemplateColorPicker(
|
||||
&col, ¶ms.socket_ptr, "default_value", true, false, false, false);
|
||||
col.prop(¶ms.socket_ptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE);
|
||||
|
||||
@@ -15,7 +15,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
{
|
||||
b.add_output<decl::Color>("Color").custom_draw([](CustomSocketDrawParams ¶ms) {
|
||||
uiLayoutSetAlignment(¶ms.layout, UI_LAYOUT_ALIGN_EXPAND);
|
||||
uiLayout &col = params.layout.column(true);
|
||||
uiLayout &col = params.layout.column(false);
|
||||
uiTemplateColorPicker(&col, ¶ms.node_ptr, "value", true, false, false, true);
|
||||
col.prop(¶ms.node_ptr, "value", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
|
||||
});
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -19,7 +19,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
||||
.default_value({0.5f, 0.5f, 0.5f, 1.0f})
|
||||
.custom_draw([](CustomSocketDrawParams ¶ms) {
|
||||
uiLayoutSetAlignment(¶ms.layout, UI_LAYOUT_ALIGN_EXPAND);
|
||||
uiLayout &col = params.layout.column(true);
|
||||
uiLayout &col = params.layout.column(false);
|
||||
uiTemplateColorPicker(
|
||||
&col, ¶ms.socket_ptr, "default_value", true, false, false, false);
|
||||
col.prop(¶ms.socket_ptr, "default_value", UI_ITEM_R_SLIDER, "", ICON_NONE);
|
||||
|
||||
Reference in New Issue
Block a user