62 bool any_vertex_group_data =
false;
67 if (vertex_group_names.
add_as(dg->name)) {
73 if (!any_vertex_group_data) {
74 return vertex_group_names;
81 const Mesh &src_mesh = *
static_cast<const Mesh *
>(objects_to_join[
i]->
data);
102 return vertex_group_names;
112 const Object &src_object = *objects_to_join[
i];
114 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
115 const Span<float3> src_positions = src_mesh.vert_positions();
129 for (
const Object *
object : objects_to_join) {
130 const Mesh &
mesh = *
static_cast<const Mesh *
>(
object->data);
143 const Object &src_object = *objects_to_join[
i];
144 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
148 dst_attr.
span.slice(corner_ranges[
i]).fill(
short2(0));
153 dst_attr.
span.slice(corner_ranges[
i]).fill(
short2(0));
156 src.
typed<
short2>().varray.materialize(dst_attr.
span.slice(corner_ranges[
i]));
165 const Object &src_object = *objects_to_join[
i];
166 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
171 dst_attr.
span.slice(vert_ranges[
i]));
176 dst_attr.
span.slice(face_ranges[
i]));
181 dst_attr.
span.slice(corner_ranges[
i]));
196 const float4x4 &world_to_active_mesh,
199 const int dst_verts_num = vert_ranges.
total_size();
202 if (
Key *key = active_mesh.
key) {
205 kb->totelem = dst_verts_num;
211 const auto ensure_dst_key = [&]() {
212 if (!active_mesh.
key) {
218 const Span<float3> active_mesh_positions = active_mesh.vert_positions();
221 const Key *src_key =
static_cast<const Mesh *
>(objects_to_join[
i]->
data)->key;
227 if (key_names.
add_as(src_kb->name)) {
231 dst_kb->
totelem = dst_verts_num;
247 Key *dst_key = active_mesh.
key;
253 const Object &src_object = *objects_to_join[
i];
255 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
256 const Span<float3> src_positions = src_mesh.vert_positions();
300 attr_info.
add(attr.
name, {attr.domain, attr.data_type});
305 for (
const int i : attr_info.
names.index_range()) {
318 if (
const std::optional<bke::AttributeMetaData> meta_data = dst_attributes.
lookup_meta_data(
321 if (meta_data->domain != domain || meta_data->data_type != data_type) {
324 owner, dst_attributes,
name, meta_data->domain, meta_data->data_type,
nullptr);
339 const Mesh &src_mesh = *
static_cast<const Mesh *
>(objects_to_join[
i]->
data);
346 return vert_ranges[
i];
348 return edge_ranges[
i];
350 return face_ranges[
i];
352 return corner_ranges[
i];
371 const Object &src_object = *objects_to_join[
i];
372 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
373 if (src_mesh.
totcol == 0) {
374 materials.
add(
nullptr);
381 materials.
add(material);
387 if (materials.
size() <= 1) {
388 dst_attributes.
remove(
"material_index");
399 const Object &src_object = *objects_to_join[
i];
401 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
404 const VArray<int> material_indices = *src_attributes.
lookup<
int>(
"material_index",
410 dst_attr.
span.slice(dst_range).fill(materials.
index_of(first_material));
414 if (src_mesh.
totcol == 0) {
425 index_map[material_index] = dst_index == -1 ? 0 : dst_index;
430 const int src = std::clamp(material_indices[face], 0,
max);
431 dst_attr.
span[dst_range[face]] = index_map[src];
447 if (std::none_of(objects_to_join.
begin(), objects_to_join.
end(), [](
const Object *
object) {
448 const Mesh &mesh = *static_cast<const Mesh *>(object->data);
449 return mesh.attributes().contains(
".sculpt_face_set");
458 if (!dst_face_sets) {
462 int max_face_set = 0;
464 const Object &src_object = *objects_to_join[
i];
466 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
468 const VArraySpan src_face_sets = *src_attributes.
lookup<
int>(
".sculpt_face_set",
471 dst_face_sets.
span.slice(dst_range).fill(max_face_set);
475 dst_face_sets.
span[dst_range[face]] = src_face_sets[face] + max_face_set;
477 max_face_set = std::max(
479 *std::max_element(src_face_sets.
begin(), src_face_sets.
begin() + dst_range.
size()));
498 if (!active_object || active_object->
type !=
OB_MESH) {
507 if (ob_iter->type ==
OB_MESH) {
508 objects_to_join.
append(ob_iter);
515 const int active_index = objects_to_join.
as_span().first_index_try(active_object);
516 if (active_index == -1) {
520 objects_to_join.
remove(active_index);
521 objects_to_join.
prepend(active_object);
530 vert_offset_data[
i] =
mesh.verts_num;
531 edge_offset_data[
i] =
mesh.edges_num;
532 face_offset_data[
i] =
mesh.faces_num;
533 corner_offset_data[
i] =
mesh.corners_num;
548 active_object->
parent =
nullptr;
550 active_object->object_to_world().ptr(),
568 "Joining results in %d vertices, limit is %ld",
584 join_shape_keys(bmain, objects_to_join, vert_ranges, world_to_active_object, *active_mesh);
585 join_positions(objects_to_join, vert_ranges, world_to_active_object, *dst_mesh);
587 objects_to_join, vert_ranges, face_ranges, corner_ranges, world_to_active_object, *dst_mesh);
591 const Object &src_object = *objects_to_join[
i];
593 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
594 const Span<int2> src_edges = src_mesh.edges();
596 dst_edges[dst_range[edge]] = src_edges[edge] + int(vert_ranges[
i].start());
602 const Object &src_object = *objects_to_join[
i];
604 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
605 const Span<int> src_corner_verts = src_mesh.corner_verts();
607 dst_corner_verts[dst_range[corner]] = src_corner_verts[corner] + int(vert_ranges[
i].start());
613 const Object &src_object = *objects_to_join[
i];
615 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
616 const Span<int> src_corner_edges = src_mesh.corner_edges();
618 dst_corner_edges[dst_range[corner]] = src_corner_edges[corner] + int(edge_ranges[
i].start());
625 const Object &src_object = *objects_to_join[
i];
627 const Mesh &src_mesh = *
static_cast<const Mesh *
>(src_object.
data);
628 const Span<int> src_face_offsets = src_mesh.face_offsets();
630 dst_face_offsets[dst_range[face]] = src_face_offsets[face] + corner_ranges[
i].start();
641 objects_to_join, vert_ranges, *dst_mesh);
658 if (std::any_of(objects_to_join.
begin(), objects_to_join.
end(), [](
const Object *
object) {
659 const Mesh &src_mesh = *static_cast<const Mesh *>(object->data);
660 return CustomData_has_layer(&src_mesh.corner_data, CD_MDISPS);
666 const Mesh &src_mesh = *
static_cast<const Mesh *
>(objects_to_join[
i]->
data);
673 if (std::any_of(objects_to_join.
begin(), objects_to_join.
end(), [](
const Object *
object) {
674 const Mesh &src_mesh = *static_cast<const Mesh *>(object->data);
675 return CustomData_has_layer(&src_mesh.corner_data, CD_GRID_PAINT_MASK);
681 const Mesh &src_mesh = *
static_cast<const Mesh *
>(objects_to_join[
i]->
data);
690 Object &src_object = *objects_to_join[
i];
700 for (
Object *
object : objects_to_join.
as_span().drop_front(1)) {
720 if (active_object->
totcol == 0 && materials.
size() == 1 && materials[0] ==
nullptr) {
724 const int totcol = materials.
size();
743 if (
Key *key = active_mesh->
key) {
void BKE_id_attributes_default_color_set(struct ID *id, std::optional< blender::StringRef > name)
std::optional< blender::StringRef > BKE_id_attributes_default_color_name(const struct ID *id)
std::optional< blender::StringRef > BKE_id_attributes_active_color_name(const struct ID *id)
void BKE_id_attributes_active_color_set(struct ID *id, std::optional< blender::StringRef > name)
#define CTX_DATA_BEGIN(C, Type, instance, member)
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Main * CTX_data_main(const bContext *C)
CustomData interface, see also DNA_customdata_types.h.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
void CustomData_copy_elements(eCustomDataType type, const void *src_data, void *dst_data, int count)
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
Key * BKE_key_add(Main *bmain, ID *id)
KeyBlock * BKE_keyblock_add(Key *key, const char *name)
void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src)
copy shape-key attributes, but not key data or name/UID.
KeyBlock * BKE_keyblock_find_name(Key *key, const char name[])
void BKE_key_sort(Key *key)
General operations, lookup, etc. for materials.
void BKE_objects_materials_sync_length_all(Main *bmain, ID *id)
Material * BKE_object_material_get(Object *ob, short act)
Mesh * BKE_mesh_new_nomain(int verts_num, int edges_num, int faces_num, int corners_num)
void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob, bool process_shape_keys=true)
void multiresModifier_prepare_join(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *to_ob)
MultiresModifierData * get_multires_modifier(Scene *scene, Object *ob, bool use_first)
General operations, lookup, etc. for blender objects.
void BKE_object_apply_mat4_ex(Object *ob, const float mat[4][4], Object *parent, const float parentinv[4][4], bool use_compat)
void BKE_object_free_derived_caches(Object *ob)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_assert_unreachable()
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define LISTBASE_FOREACH(type, var, list)
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
void invert_m4_m4_safe_ortho(float inverse[4][4], const float mat[4][4])
void DEG_id_tag_update(ID *id, unsigned int flags)
void DEG_relations_tag_update(Main *bmain)
Object is a sort of wrapper for general info.
Read Guarded memory(de)allocation.
#define MEM_reallocN(vmemh, len)
BMesh const char void * data
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
static AttributeOwner from_id(ID *id)
IndexRange index_range() const
void reinitialize(const int64_t new_size)
GMutableSpan slice(const int64_t start, int64_t size) const
const CPPType & type() const
void materialize(void *dst) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr IndexRange drop_front(int64_t n) const
constexpr MutableSpan slice(const int64_t start, const int64_t size) const
constexpr void copy_from(Span< T > values) const
constexpr MutableSpan take_front(const int64_t n) const
constexpr T & last(const int64_t n=0) const
bool contains(const Key &key) const
constexpr const T * data() const
constexpr const T * end() const
constexpr IndexRange index_range() const
constexpr const T * begin() const
constexpr bool is_empty() const
void materialize(MutableSpan< T > r_span) const
int64_t index_of_try(const Key &key) const
int64_t index_of_as(const ForwardKey &key) const
bool add_as(ForwardKey &&key)
int64_t index_of(const Key &key) const
bool contains(const Key &key) const
void add_new(const Key &key)
void prepend(const T &value)
bool contains(const T &value) const
void append(const T &value)
void remove(const int64_t index)
IndexRange index_range() const
Span< T > as_span() const
VectorData< T, Allocator > release()
GAttributeReader lookup_or_default(StringRef attribute_id, AttrDomain domain, AttrType data_type, const void *default_value=nullptr) const
GAttributeReader lookup(const StringRef attribute_id) const
Set< StringRefNull > all_ids() const
std::optional< AttributeMetaData > lookup_meta_data(StringRef attribute_id) const
bool add(const StringRef attribute_id, const AttrDomain domain, const AttrType data_type, const AttributeInit &initializer)
GSpanAttributeWriter lookup_or_add_for_write_span(StringRef attribute_id, AttrDomain domain, AttrType data_type, const AttributeInit &initializer=AttributeInitDefaultValue())
bool remove(const StringRef attribute_id)
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
GSpanAttributeWriter lookup_for_write_span(StringRef attribute_id)
std::optional< bke::AttrDomain > result_domain
void add_mesh(const Mesh &mesh)
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
bool is_corner_fan_normals(const AttributeMetaData &meta_data)
AttrType cpp_type_to_attribute_type(const CPPType &type)
bool convert_attribute(AttributeOwner &owner, bke::MutableAttributeAccessor attributes, const StringRef name, const bke::AttrDomain dst_domain, const bke::AttrType dst_type, ReportList *reports)
static void join_generic_attributes(const Span< const Object * > objects_to_join, const VectorSet< std::string > &all_vertex_group_names, const OffsetIndices< int > vert_ranges, const OffsetIndices< int > edge_ranges, const OffsetIndices< int > face_ranges, const OffsetIndices< int > corner_ranges, Mesh &dst_mesh)
wmOperatorStatus join_objects_exec(bContext *C, wmOperator *op)
static void join_positions(const Span< const Object * > objects_to_join, const OffsetIndices< int > vert_ranges, const float4x4 &world_to_dst_mesh, Mesh &dst_mesh)
static void join_face_sets(const Span< const Object * > objects_to_join, const OffsetIndices< int > face_ranges, Mesh &dst_mesh)
static VectorSet< Material * > join_materials(const Span< const Object * > objects_to_join, const OffsetIndices< int > face_ranges, Mesh &dst_mesh)
static void join_shape_keys(Main *bmain, const Span< const Object * > objects_to_join, const OffsetIndices< int > vert_ranges, const float4x4 &world_to_active_mesh, Mesh &active_mesh)
static VectorSet< std::string > join_vertex_groups(const Span< const Object * > objects_to_join, const OffsetIndices< int > vert_ranges, Mesh &dst_mesh)
static void join_normals(const Span< const Object * > objects_to_join, const OffsetIndices< int > vert_ranges, const OffsetIndices< int > face_ranges, const OffsetIndices< int > corner_ranges, const float4x4 &world_to_dst_mesh, Mesh &dst_mesh)
bool iter_other(Main *bmain, Object *orig_ob, bool include_orig, bool(*callback)(Object *ob, void *callback_data), void *callback_data)
bool multires_update_totlevels(Object *ob, void *totlevel_v)
void base_free_and_unlink(Main *bmain, Scene *scene, Object *ob)
void transform_normals(const float3x3 &transform, MutableSpan< float3 > normals)
void transform_points(const float4x4 &transform, MutableSpan< float3 > points, bool use_threading=true)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
MatBase< float, 4, 4 > float4x4
MatBase< float, 3, 3 > float3x3
VecBase< float, 3 > float3
blender::VecBase< int16_t, 2 > short2
ListBase vertex_group_names
const c_style_mat & ptr() const
AttributeReader< T > typed() const
void add(const StringRef name, const AttributeDomainAndType &kind)
Vector< AttributeDomainAndType, 16 > kinds
VectorSet< StringRef, 16 > names
MutableVArraySpan< T > span
struct ReportList * reports
void WM_event_add_notifier(const bContext *C, uint type, void *reference)