Merge branch 'blender-v4.1-release'

This commit is contained in:
Hans Goudey 2024-03-18 16:44:47 -04:00
commit 5001a1a4a7
3 changed files with 146 additions and 17 deletions

View file

@ -1495,6 +1495,7 @@ void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *re
if ((lapp_context->params->flag & FILE_LINK) != 0) {
blendfile_link_append_proxies_convert(lapp_context->params->bmain, reports);
BKE_main_mesh_legacy_convert_auto_smooth(*lapp_context->params->bmain);
}
BKE_main_namemap_clear(lapp_context->params->bmain);

View file

@ -34,6 +34,7 @@
#include "BKE_customdata.hh"
#include "BKE_global.hh"
#include "BKE_idprop.hh"
#include "BKE_lib_id.hh"
#include "BKE_main.hh"
#include "BKE_mesh.hh"
#include "BKE_mesh_legacy_convert.hh"
@ -2233,17 +2234,105 @@ static bNodeTree *add_auto_smooth_node_tree(Main &bmain)
nodeSetSelected(node, false);
}
BKE_ntree_update_main_tree(&bmain, group, nullptr);
return group;
}
static ModifierData *create_auto_smooth_modifier(Object &object,
const FunctionRef<bNodeTree *()> get_node_group,
const float angle)
static VectorSet<const bNodeSocket *> build_socket_indices(const Span<const bNode *> nodes)
{
VectorSet<const bNodeSocket *> result;
for (const bNode *node : nodes) {
LISTBASE_FOREACH (const bNodeSocket *, socket, &node->inputs) {
result.add_new(socket);
}
LISTBASE_FOREACH (const bNodeSocket *, socket, &node->outputs) {
result.add_new(socket);
}
}
return result;
}
/* Checks if the node group is the same as the one generated by #create_auto_smooth_modifier. */
static bool is_auto_smooth_node_tree(const bNodeTree &group)
{
if (group.type != NTREE_GEOMETRY) {
return false;
}
const Span<const bNode *> nodes = group.all_nodes();
if (nodes.size() != 10) {
return false;
}
if (!group.geometry_node_asset_traits) {
return false;
}
if (group.geometry_node_asset_traits->flag != GEO_NODE_ASSET_MODIFIER) {
return false;
}
const std::array<StringRef, 10> idnames({"NodeGroupOutput",
"NodeGroupInput",
"NodeGroupInput",
"GeometryNodeSetShadeSmooth",
"GeometryNodeSetShadeSmooth",
"GeometryNodeInputMeshEdgeAngle",
"GeometryNodeInputEdgeSmooth",
"GeometryNodeInputShadeSmooth",
"FunctionNodeBooleanMath",
"FunctionNodeCompare"});
for (const int i : nodes.index_range()) {
if (nodes[i]->idname != idnames[i]) {
return false;
}
}
if (nodes[3]->custom1 != int16_t(bke::AttrDomain::Edge)) {
return false;
}
if (static_cast<bNodeSocket *>(nodes[4]->inputs.last)
->default_value_typed<bNodeSocketValueBoolean>()
->value != true)
{
return false;
}
if (nodes[4]->custom1 != int16_t(bke::AttrDomain::Face)) {
return false;
}
if (nodes[8]->custom1 != NODE_BOOLEAN_MATH_AND) {
return false;
}
if (static_cast<NodeFunctionCompare *>(nodes[9]->storage)->operation != NODE_COMPARE_LESS_EQUAL)
{
return false;
}
if (BLI_listbase_count(&group.links) != 9) {
return false;
}
const std::array<int, 9> link_from_socket_indices({16, 15, 3, 36, 19, 5, 18, 11, 22});
const std::array<int, 9> link_to_socket_indices({23, 0, 24, 20, 21, 8, 9, 12, 10});
const VectorSet<const bNodeSocket *> socket_indices = build_socket_indices(nodes);
int i;
LISTBASE_FOREACH_INDEX (const bNodeLink *, link, &group.links, i) {
if (socket_indices.index_of(link->fromsock) != link_from_socket_indices[i]) {
return false;
}
if (socket_indices.index_of(link->tosock) != link_to_socket_indices[i]) {
return false;
}
}
return true;
}
static ModifierData *create_auto_smooth_modifier(
Object &object,
const FunctionRef<bNodeTree *(Library *library)> get_node_group,
const float angle)
{
auto *md = reinterpret_cast<NodesModifierData *>(BKE_modifier_new(eModifierType_Nodes));
STRNCPY(md->modifier.name, DATA_("Auto Smooth"));
BKE_modifier_unique_name(&object.modifiers, &md->modifier);
md->node_group = get_node_group();
md->node_group = get_node_group(object.id.lib);
id_us_plus(&md->node_group->id);
md->settings.properties = idprop::create_group("Nodes Modifier Settings").release();
IDProperty *angle_prop = idprop::create("Socket_1", angle).release();
@ -2263,14 +2352,43 @@ static ModifierData *create_auto_smooth_modifier(Object &object,
void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
{
using namespace blender;
using namespace blender::bke;
/* Add the node group lazily and share it among all objects in the main database. */
bNodeTree *node_group = nullptr;
const auto add_node_group = [&]() {
node_group = add_auto_smooth_node_tree(bmain);
BKE_ntree_update_main_tree(&bmain, node_group, nullptr);
return node_group;
/* Add the node group lazily and share it among all objects in the same library. */
Map<Library *, bNodeTree *> group_by_library;
const auto add_node_group = [&](Library *library) {
if (bNodeTree **group = group_by_library.lookup_ptr(library)) {
/* Node tree has already been found/created for this versioning call. */
return *group;
}
/* Try to find an existing group added by previous versioning to avoid adding duplicates. */
LISTBASE_FOREACH (bNodeTree *, existing_group, &bmain.nodetrees) {
if (existing_group->id.lib != library) {
continue;
}
if (is_auto_smooth_node_tree(*existing_group)) {
group_by_library.add_new(library, existing_group);
return existing_group;
}
}
bNodeTree *new_group = add_auto_smooth_node_tree(bmain);
/* Remove the default user. The count is tracked manually when assigning to modifiers. */
id_us_min(&new_group->id);
if (new_group->id.lib != library) {
/* Move the node group to the requested library so that library data-blocks don't point to
* local data-blocks. This requires making sure the name is unique in that library and
* changing the name maps to be consistent with the new state. */
new_group->id.lib = library;
BKE_id_new_name_validate(&bmain, &bmain.nodetrees, &new_group->id, nullptr, false);
if (library) {
new_group->id.tag |= LIB_TAG_INDIRECT;
}
}
group_by_library.add_new(library, new_group);
return new_group;
};
LISTBASE_FOREACH (Object *, object, &bmain.objects) {
@ -2282,7 +2400,6 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
if (!(mesh->flag & ME_AUTOSMOOTH_LEGACY)) {
continue;
}
mesh->flag &= ~ME_AUTOSMOOTH_LEGACY;
/* Auto-smooth disabled sharp edge tagging when the evaluated mesh had custom normals.
* When the original mesh has custom normals, that's a good sign the evaluated mesh will
@ -2299,6 +2416,12 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
if (ELEM(md->type, eModifierType_WeightedNormal, eModifierType_NormalEdit)) {
has_custom_normals = true;
}
if (md->type == eModifierType_Bevel) {
BevelModifierData *bmd = reinterpret_cast<BevelModifierData *>(md);
if (bmd->flags & MOD_BEVEL_HARDEN_NORMALS) {
has_custom_normals = true;
}
}
if (md->type == eModifierType_WeightedNormal) {
WeightedNormalModifierData *nmd = reinterpret_cast<WeightedNormalModifierData *>(md);
if ((nmd->flag & MOD_WEIGHTEDNORMAL_KEEP_SHARP) != 0) {
@ -2311,13 +2434,11 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
/* Some modifiers always generate custom normals which disabled sharp edge tagging, making
* adding a modifier at the end unnecessary. Conceptually this is similar to checking if the
* evaluated mesh had custom normals. */
ModifierData *last_md = static_cast<ModifierData *>(object->modifiers.last);
if (last_md) {
if (ELEM(last_md->type, eModifierType_WeightedNormal, eModifierType_NormalEdit)) {
continue;
}
if (has_custom_normals) {
continue;
}
ModifierData *last_md = static_cast<ModifierData *>(object->modifiers.last);
ModifierData *new_md = create_auto_smooth_modifier(*object, add_node_group, angle);
if (last_md && last_md->type == eModifierType_Subsurf && has_custom_normals &&
(reinterpret_cast<SubsurfModifierData *>(last_md)->flags &
@ -2331,6 +2452,10 @@ void BKE_main_mesh_legacy_convert_auto_smooth(Main &bmain)
BLI_addtail(&object->modifiers, new_md);
}
}
LISTBASE_FOREACH (Mesh *, mesh, &bmain.meshes) {
mesh->flag &= ~ME_AUTOSMOOTH_LEGACY;
}
}
namespace blender::bke {

View file

@ -531,7 +531,10 @@ void do_versions_after_setup(Main *new_bmain, BlendFileReadReport *reports)
BKE_lib_override_library_main_hierarchy_root_ensure(new_bmain);
}
if (!blendfile_or_libraries_versions_atleast(new_bmain, 401, 2)) {
if (!blendfile_or_libraries_versions_atleast(new_bmain, 402, 22)) {
/* Initial auto smooth versioning started at (401, 2), but a bug caused the legacy flag to not
* be cleared, so it is re-run in a later version when the bug is fixed and the versioning has
* been made idempotent. */
BKE_main_mesh_legacy_convert_auto_smooth(*new_bmain);
}
}