Blender V4.5
blenkernel/intern/object.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9/* Allow using deprecated functionality for .blend file I/O. */
10#define DNA_DEPRECATED_ALLOW
11
12#include <cmath>
13#include <cstdio>
14#include <cstring>
15#include <optional>
16
17#include "CLG_log.h"
18
19#include "MEM_guardedalloc.h"
20
21#include "DNA_anim_types.h"
22#include "DNA_armature_types.h"
23#include "DNA_camera_types.h"
26#include "DNA_curve_types.h"
27#include "DNA_defaults.h"
29#include "DNA_effect_types.h"
30#include "DNA_fluid_types.h"
34#include "DNA_key_types.h"
35#include "DNA_lattice_types.h"
36#include "DNA_light_types.h"
38#include "DNA_material_types.h"
39#include "DNA_mesh_types.h"
40#include "DNA_meta_types.h"
41#include "DNA_movieclip_types.h"
42#include "DNA_nla_types.h"
44#include "DNA_object_types.h"
46#include "DNA_rigidbody_types.h"
47#include "DNA_scene_types.h"
48#include "DNA_shader_fx_types.h"
49#include "DNA_view3d_types.h"
50
51#include "BLI_kdtree.h"
52#include "BLI_linklist.h"
53#include "BLI_listbase.h"
54#include "BLI_math_matrix.h"
55#include "BLI_math_rotation.h"
57#include "BLI_string.h"
58#include "BLI_threads.h"
59#include "BLI_utildefines.h"
60
61#include "BLT_translation.hh"
62
63#include "BKE_action.hh"
64#include "BKE_anim_data.hh"
65#include "BKE_anim_path.h"
67#include "BKE_animsys.h"
68#include "BKE_armature.hh"
69#include "BKE_asset.hh"
70#include "BKE_bpath.hh"
71#include "BKE_camera.h"
72#include "BKE_collection.hh"
73#include "BKE_constraint.h"
74#include "BKE_crazyspace.hh"
75#include "BKE_curve.hh"
76#include "BKE_curves.hh"
77#include "BKE_deform.hh"
78#include "BKE_displist.h"
79#include "BKE_duplilist.hh"
80#include "BKE_editmesh.hh"
81#include "BKE_editmesh_cache.hh"
82#include "BKE_effect.h"
83#include "BKE_fcurve.hh"
84#include "BKE_geometry_set.hh"
86#include "BKE_global.hh"
88#include "BKE_gpencil_legacy.h"
90#include "BKE_grease_pencil.hh"
91#include "BKE_idprop.hh"
92#include "BKE_idtype.hh"
93#include "BKE_image.hh"
94#include "BKE_key.hh"
95#include "BKE_lattice.hh"
96#include "BKE_layer.hh"
97#include "BKE_lib_id.hh"
98#include "BKE_lib_query.hh"
99#include "BKE_lib_remap.hh"
100#include "BKE_library.hh"
101#include "BKE_light.h"
102#include "BKE_lightprobe.h"
103#include "BKE_linestyle.h"
104#include "BKE_main.hh"
105#include "BKE_material.hh"
106#include "BKE_mball.hh"
107#include "BKE_mesh.hh"
108#include "BKE_mesh_wrapper.hh"
109#include "BKE_modifier.hh"
110#include "BKE_multires.hh"
111#include "BKE_node.hh"
112#include "BKE_object.hh"
113#include "BKE_object_types.hh"
114#include "BKE_paint.hh"
115#include "BKE_particle.h"
116#include "BKE_pointcache.h"
117#include "BKE_pointcloud.hh"
118#include "BKE_pose_backup.h"
119#include "BKE_preview_image.hh"
120#include "BKE_rigidbody.h"
121#include "BKE_scene.hh"
122#include "BKE_shader_fx.h"
123#include "BKE_softbody.h"
124#include "BKE_speaker.h"
125#include "BKE_subdiv_ccg.hh"
126#include "BKE_subsurf.hh"
127#include "BKE_vfont.hh"
128#include "BKE_volume.hh"
129
130#include "DEG_depsgraph.hh"
131#include "DEG_depsgraph_query.hh"
132
133#include "DRW_engine.hh"
134
135#include "BLO_read_write.hh"
136#include "BLO_readfile.hh"
137
138#include "SEQ_sequencer.hh"
139
140#include "ANIM_action_legacy.hh"
141
142#include "RNA_prototypes.hh"
143
144#ifdef WITH_PYTHON
145# include "BPY_extern.hh"
146#endif
147
148using blender::Bounds;
149using blender::float3;
152using blender::Span;
153using blender::Vector;
154
155static CLG_LogRef LOG = {"bke.object"};
156
163#define VPARENT_THREADING_HACK
164
165#ifdef VPARENT_THREADING_HACK
167#endif
168
169static void copy_object_pose(Object *obn, const Object *ob, const int flag);
170
171static void object_init_data(ID *id)
172{
173 Object *ob = (Object *)id;
175
177
178 ob->type = OB_EMPTY;
179
180 ob->trackflag = OB_POSY;
181 ob->upflag = OB_POSZ;
182 ob->runtime = MEM_new<blender::bke::ObjectRuntime>(__func__);
183
184 /* Animation Visualization defaults */
186}
187
188static void object_copy_data(Main *bmain,
189 std::optional<Library *> /*owner_library*/,
190 ID *id_dst,
191 const ID *id_src,
192 const int flag)
193{
194 Object *ob_dst = (Object *)id_dst;
195 const Object *ob_src = (const Object *)id_src;
196
197 ob_dst->runtime = MEM_new<blender::bke::ObjectRuntime>(__func__, *ob_src->runtime);
199
200 /* We never handle user-count here for own data. */
201 const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
202
203 if (ob_src->totcol) {
204 ob_dst->mat = (Material **)MEM_dupallocN(ob_src->mat);
205 ob_dst->matbits = (char *)MEM_dupallocN(ob_src->matbits);
206 ob_dst->totcol = ob_src->totcol;
207 }
208 else if (ob_dst->mat != nullptr || ob_dst->matbits != nullptr) {
209 /* This shall not be needed, but better be safe than sorry. */
211 0, "Object copy: non-nullptr material pointers with zero counter, should not happen.");
212 ob_dst->mat = nullptr;
213 ob_dst->matbits = nullptr;
214 }
215
216 if (ob_src->iuser) {
217 ob_dst->iuser = (ImageUser *)MEM_dupallocN(ob_src->iuser);
218 }
219
221 LISTBASE_FOREACH (ShaderFxData *, fx, &ob_src->shader_fx) {
222 ShaderFxData *nfx = BKE_shaderfx_new(fx->type);
223 STRNCPY(nfx->name, fx->name);
224 BKE_shaderfx_copydata_ex(fx, nfx, flag_subdata);
225 BLI_addtail(&ob_dst->shader_fx, nfx);
226 }
227
228 if (ob_src->pose) {
229 copy_object_pose(ob_dst, ob_src, flag_subdata);
230 /* backwards compat... non-armatures can get poses in older files? */
231 if (ob_src->type == OB_ARMATURE) {
232 const bool do_pose_id_user = (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0;
233 BKE_pose_rebuild(bmain, ob_dst, (bArmature *)ob_dst->data, do_pose_id_user);
234 }
235 }
236
237 BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true);
238
239 ob_dst->mode = OB_MODE_OBJECT;
240 ob_dst->sculpt = nullptr;
241
242 if (ob_src->pd) {
243 ob_dst->pd = (PartDeflect *)MEM_dupallocN(ob_src->pd);
244 }
245 BKE_rigidbody_object_copy(bmain, ob_dst, ob_src, flag_subdata);
246
249 /* NOTE: Also takes care of soft-body and particle systems copying. */
250 BKE_object_modifier_stack_copy(ob_dst, ob_src, true, flag_subdata);
252
253 BLI_listbase_clear(&ob_dst->pc_ids);
254
255 ob_dst->avs = ob_src->avs;
256 ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath);
257
258 if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
259 BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id);
260 }
261 else {
262 ob_dst->preview = nullptr;
263 }
264
265 if (ob_src->lightgroup) {
267 }
268 if (ob_src->light_linking) {
270 }
271
273 if (ob_src->lightprobe_cache) {
274 /* Reference the original object data. */
276 ob_dst->lightprobe_cache->shared = true;
277 }
278 }
279 else {
280 if (ob_src->lightprobe_cache) {
281 /* Duplicate the original object data. */
283 ob_dst->lightprobe_cache->shared = false;
284 }
285 }
286}
287
288static void object_free_data(ID *id)
289{
290 Object *ob = (Object *)id;
291
292 /* BKE_<id>_free shall never touch to ID->us. Never ever. */
295
296 MEM_SAFE_FREE(ob->mat);
298 MEM_SAFE_FREE(ob->iuser);
299
300 if (ob->pose) {
301 BKE_pose_free_ex(ob->pose, false);
302 ob->pose = nullptr;
303 }
304 if (ob->mpath) {
306 ob->mpath = nullptr;
307 }
308
310
312 BKE_rigidbody_free_object(ob, nullptr);
314
315 sbFree(ob);
316
318
319 BLI_freelistN(&ob->pc_ids);
320
321 /* Free runtime curves data. */
322 if (ob->runtime->curve_cache) {
323 BKE_curve_bevelList_free(&ob->runtime->curve_cache->bev);
324 if (ob->runtime->curve_cache->anim_path_accum_length) {
325 MEM_freeN(ob->runtime->curve_cache->anim_path_accum_length);
326 }
327 MEM_freeN(ob->runtime->curve_cache);
328 ob->runtime->curve_cache = nullptr;
329 }
330
332
335
337
338 MEM_delete(ob->runtime);
339}
340
341static void library_foreach_modifiersForeachIDLink(void *user_data,
342 Object * /*object*/,
343 ID **id_pointer,
344 const LibraryForeachIDCallbackFlag cb_flag)
345{
348 data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
349}
350
352 void *user_data,
353 Object * /*object*/,
354 ID **id_pointer,
355 const LibraryForeachIDCallbackFlag cb_flag)
356{
359 data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
360}
361
362static void library_foreach_shaderfxForeachIDLink(void *user_data,
363 Object * /*object*/,
364 ID **id_pointer,
365 const LibraryForeachIDCallbackFlag cb_flag)
366{
369 data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
370}
371
373 ID **id_pointer,
374 bool is_reference,
375 void *user_data)
376{
378 const LibraryForeachIDCallbackFlag cb_flag = is_reference ? IDWALK_CB_USER : IDWALK_CB_NOP;
380 data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
381}
382
384 ID **id_pointer,
385 void *user_data,
386 const LibraryForeachIDCallbackFlag cb_flag)
387{
390 data, BKE_lib_query_foreachid_process(data, id_pointer, cb_flag));
391}
392
394{
395 Object *object = reinterpret_cast<Object *>(id);
397
398 /* object data special case */
399 if (object->type == OB_EMPTY) {
400 /* empty can have nullptr or Image */
402 }
403 else {
404 /* when set, this can't be nullptr */
405 if (object->data) {
407 }
408 }
409
413
414 for (int i = 0; i < object->totcol; i++) {
416 }
417
419
420 if (object->pd) {
423 }
424
425 if (object->pose) {
426 LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
428 data, IDP_foreach_property(pchan->prop, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
429 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
430 }));
432 data,
434 pchan->system_properties, IDP_TYPE_FILTER_ID, [&](IDProperty *prop) {
435 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, data);
436 }));
437
440 data,
442 &pchan->constraints, library_foreach_constraintObjectLooper, flag, data));
443 }
444 }
445
446 if (object->rigidbody_constraint) {
451 }
452
456 data,
460 data,
465
469 }
470
471 if (object->soft) {
473
474 if (object->soft->effector_weights) {
477 }
478 }
479
480 if (object->light_linking) {
485 }
486
490
492
493 LISTBASE_FOREACH (bConstraintChannel *, chan, &object->constraintChannels) {
495 }
496
497 LISTBASE_FOREACH (bActionStrip *, strip, &object->nlastrips) {
501 LISTBASE_FOREACH (bActionModifier *, amod, &strip->modifiers) {
503 }
504 }
505
507
510 /* Note that `proxy_from` is purposefully skipped here, as this should be considered as pure
511 * runtime data. */
512
514 if (paf && paf->group) {
516 }
517
518 FluidsimModifierData *fluidmd = reinterpret_cast<FluidsimModifierData *>(
520 if (fluidmd && fluidmd->fss) {
522 }
523 }
524}
525
526static void object_foreach_path_pointcache(ListBase *ptcache_list,
527 BPathForeachPathData *bpath_data)
528{
529 for (PointCache *cache = (PointCache *)ptcache_list->first; cache != nullptr;
530 cache = cache->next)
531 {
532 if (cache->flag & PTCACHE_DISK_CACHE) {
533 BKE_bpath_foreach_path_fixed_process(bpath_data, cache->path, sizeof(cache->path));
534 }
535 }
536}
537
538static void object_foreach_path(ID *id, BPathForeachPathData *bpath_data)
539{
540 Object *ob = reinterpret_cast<Object *>(id);
541
543 /* TODO: Move that to #ModifierTypeInfo. */
544 switch (md->type) {
546 FluidsimModifierData *fluidmd = reinterpret_cast<FluidsimModifierData *>(md);
547 if (fluidmd->fss) {
549 bpath_data, fluidmd->fss->surfdataPath, sizeof(fluidmd->fss->surfdataPath));
550 }
551 break;
552 }
553 case eModifierType_Fluid: {
554 FluidModifierData *fmd = reinterpret_cast<FluidModifierData *>(md);
555 if (fmd->type & MOD_FLUID_TYPE_DOMAIN && fmd->domain) {
557 bpath_data, fmd->domain->cache_directory, sizeof(fmd->domain->cache_directory));
558 }
559 break;
560 }
561 case eModifierType_Cloth: {
562 ClothModifierData *clmd = reinterpret_cast<ClothModifierData *>(md);
563 object_foreach_path_pointcache(&clmd->ptcaches, bpath_data);
564 break;
565 }
566 case eModifierType_Ocean: {
567 OceanModifierData *omd = reinterpret_cast<OceanModifierData *>(md);
568 BKE_bpath_foreach_path_fixed_process(bpath_data, omd->cachepath, sizeof(omd->cachepath));
569 break;
570 }
572 MeshCacheModifierData *mcmd = reinterpret_cast<MeshCacheModifierData *>(md);
573 BKE_bpath_foreach_path_fixed_process(bpath_data, mcmd->filepath, sizeof(mcmd->filepath));
574 break;
575 }
576 default:
577 break;
578 }
579 }
580
581 if (ob->soft != nullptr) {
583 }
584
586 object_foreach_path_pointcache(&psys->ptcaches, bpath_data);
587 }
588}
589
590static void object_foreach_cache(ID *id,
591 IDTypeForeachCacheFunctionCallback function_callback,
592 void *user_data)
593{
594 Object *ob = reinterpret_cast<Object *>(id);
596 if (const ModifierTypeInfo *info = BKE_modifier_get_info(ModifierType(md->type))) {
597 if (info->foreach_cache) {
598 info->foreach_cache(ob, md, [&](const IDCacheKey &cache_key, void **cache_p, uint flags) {
599 function_callback(id, &cache_key, cache_p, flags, user_data);
600 });
601 }
602 }
603 }
604}
605
606static void object_blend_write(BlendWriter *writer, ID *id, const void *id_address)
607{
608 Object *ob = (Object *)id;
609
610 const bool is_undo = BLO_write_is_undo(writer);
611
612 /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
613 ob->runtime = nullptr;
614 /* #Object::sculpt is also a runtime struct that should be stored in #Object::runtime. */
615 ob->sculpt = nullptr;
616
617 if (is_undo) {
618 /* For undo we stay in object mode during undo presses, so keep edit-mode disabled on save as
619 * well, can help reducing false detection of changed data-blocks. */
620 ob->mode &= ~OB_MODE_EDIT;
621 }
622
623 /* write LibData */
624 BLO_write_id_struct(writer, Object, id_address, &ob->id);
625 BKE_id_blend_write(writer, &ob->id);
626
627 /* direct data */
628 BLO_write_pointer_array(writer, ob->totcol, ob->mat);
629 BLO_write_char_array(writer, ob->totcol, ob->matbits);
630
631 bArmature *arm = nullptr;
632 if (ob->type == OB_ARMATURE) {
633 arm = (bArmature *)ob->data;
634 }
635
636 if (ob->pose) {
637 BKE_pose_blend_write(writer, ob->pose, arm);
638 }
641
642 BLO_write_struct(writer, PartDeflect, ob->pd);
643 if (ob->soft) {
644 /* Set deprecated pointers to prevent crashes of older Blenders */
645 ob->soft->pointcache = ob->soft->shared->pointcache;
646 ob->soft->ptcaches = ob->soft->shared->ptcaches;
647 BLO_write_struct(writer, SoftBody, ob->soft);
651 }
652
653 if (ob->rigidbody_object) {
654 /* TODO: if any extra data is added to handle duplis, will need separate function then */
656 }
657 if (ob->rigidbody_constraint) {
659 }
660
661 if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
662 BLO_write_struct(writer, ImageUser, ob->iuser);
663 }
664
666 BKE_modifier_blend_write(writer, &ob->id, &ob->modifiers);
668
670
672
673 if (ob->lightgroup) {
675 }
676 if (ob->light_linking) {
678 }
679
680 if (ob->lightprobe_cache) {
683 }
684}
685
686/* XXX deprecated - old animation system */
687static void direct_link_nlastrips(BlendDataReader *reader, ListBase *strips)
688{
689 BLO_read_struct_list(reader, bActionStrip, strips);
690
691 LISTBASE_FOREACH (bActionStrip *, strip, strips) {
692 BLO_read_struct_list(reader, bActionModifier, &strip->modifiers);
693 }
694}
695
697{
698 Object *ob = (Object *)id;
699
700 ob->runtime = MEM_new<blender::bke::ObjectRuntime>(__func__);
701
702 PartEff *paf;
703
704 /* XXX This should not be needed - but seems like it can happen in some cases,
705 * so for now play safe. */
706 ob->proxy_from = nullptr;
707
708 const bool is_undo = BLO_read_data_is_undo(reader);
709 if (ob->id.tag & (ID_TAG_EXTERN | ID_TAG_INDIRECT)) {
710 /* Do not allow any non-object mode for linked data.
711 * See #34776, #42780, #81027 for more information. */
713 }
714 else if (is_undo) {
715 /* For undo we want to stay in object mode during undo presses, so keep some edit modes
716 * disabled.
717 * TODO: Check if we should not disable more edit modes here? */
719 }
720
721 BLO_read_struct(reader, bPose, &ob->pose);
722 BKE_pose_blend_read_data(reader, &ob->id, ob->pose);
723
724 BLO_read_struct(reader, bMotionPath, &ob->mpath);
725 if (ob->mpath) {
727 }
728
729 /* Only for versioning, vertex group names are now stored on object data. */
730 BLO_read_struct_list(reader, bDeformGroup, &ob->defbase);
731 BLO_read_struct_list(reader, bFaceMap, &ob->fmaps);
732
733 /* XXX deprecated - old animation system <<< */
734 direct_link_nlastrips(reader, &ob->nlastrips);
735 BLO_read_struct_list(reader, bConstraintChannel, &ob->constraintChannels);
736 /* >>> XXX deprecated - old animation system */
737
738 BLO_read_pointer_array(reader, ob->totcol, (void **)&ob->mat);
739 BLO_read_char_array(reader, ob->totcol, &ob->matbits);
740
741 /* do it here, below old data gets converted */
742 BKE_modifier_blend_read_data(reader, &ob->modifiers, ob);
744 BKE_shaderfx_blend_read_data(reader, &ob->shader_fx, ob);
745
746 BLO_read_struct_list(reader, PartEff, &ob->effect);
747 paf = (PartEff *)ob->effect.first;
748 while (paf) {
749 if (paf->type == EFF_PARTICLE) {
750 paf->keys = nullptr;
751 }
752 if (paf->type == EFF_WAVE) {
753 WaveEff *wav = (WaveEff *)paf;
754 PartEff *next = paf->next;
756
757 wmd->damp = wav->damp;
758 wmd->flag = wav->flag;
759 wmd->height = wav->height;
760 wmd->lifetime = wav->lifetime;
761 wmd->narrow = wav->narrow;
762 wmd->speed = wav->speed;
763 wmd->startx = wav->startx;
764 wmd->starty = wav->startx;
765 wmd->timeoffs = wav->timeoffs;
766 wmd->width = wav->width;
767
768 BLI_addtail(&ob->modifiers, wmd);
770
771 BLI_remlink(&ob->effect, paf);
772 MEM_freeN(paf);
773
774 paf = next;
775 continue;
776 }
777 if (paf->type == EFF_BUILD) {
778 BuildEff *baf = (BuildEff *)paf;
779 PartEff *next = paf->next;
781
782 bmd->start = baf->sfra;
783 bmd->length = baf->len;
784 bmd->randomize = 0;
785 bmd->seed = 1;
786
787 BLI_addtail(&ob->modifiers, bmd);
789
790 BLI_remlink(&ob->effect, paf);
791 MEM_freeN(paf);
792
793 paf = next;
794 continue;
795 }
796 paf = paf->next;
797 }
798
799 BLO_read_struct(reader, PartDeflect, &ob->pd);
801 BLO_read_struct(reader, SoftBody, &ob->soft);
802 if (ob->soft) {
803 SoftBody *sb = ob->soft;
804
805 sb->bpoint = nullptr; /* init pointers so it gets rebuilt nicely */
806 sb->bspring = nullptr;
807 sb->scratch = nullptr;
808 /* although not used anymore */
809 /* still have to be loaded to be compatible with old files */
810 BLO_read_pointer_array(reader, sb->totkey, (void **)&sb->keys);
811 if (sb->keys) {
812 for (int a = 0; a < sb->totkey; a++) {
813 BLO_read_struct(reader, SBVertex, &sb->keys[a]);
814 }
815 }
816
818 if (!sb->effector_weights) {
820 }
821
823 if (sb->shared == nullptr) {
824 /* Link deprecated caches if they exist, so we can use them for versioning.
825 * We should only do this when `sb->shared == nullptr`, because those pointers
826 * are always set (for compatibility with older Blenders). We mustn't link
827 * the same point-cache twice. */
828 BKE_ptcache_blend_read_data(reader, &sb->ptcaches, &sb->pointcache, false);
829 }
830 else {
831 /* link caches */
832 BKE_ptcache_blend_read_data(reader, &sb->shared->ptcaches, &sb->shared->pointcache, false);
833 }
834 }
835 BLO_read_struct(reader, FluidsimSettings, &ob->fluidsimSettings); /* NT */
836
838 if (ob->rigidbody_object) {
839 RigidBodyOb *rbo = ob->rigidbody_object;
840 /* Allocate runtime-only struct */
841 rbo->shared = MEM_callocN<RigidBodyOb_Shared>("RigidBodyObShared");
842 }
844 if (ob->rigidbody_constraint) {
846 }
847
850
852
853 BLO_read_struct_list(reader, ObHook, &ob->hooks);
854 while (ob->hooks.first) {
855 ObHook *hook = (ObHook *)ob->hooks.first;
857
858 BLO_read_int32_array(reader, hook->totindex, &hook->indexar);
859
860 /* Do conversion here because if we have loaded
861 * a hook we need to make sure it gets converted
862 * and freed, regardless of version.
863 */
864 copy_v3_v3(hmd->cent, hook->cent);
865 hmd->falloff = hook->falloff;
866 hmd->force = hook->force;
867 hmd->indexar = hook->indexar;
868 hmd->object = hook->parent;
869 memcpy(hmd->parentinv, hook->parentinv, sizeof(hmd->parentinv));
870 hmd->indexar_num = hook->totindex;
871
872 BLI_addhead(&ob->modifiers, hmd);
873 BLI_remlink(&ob->hooks, hook);
874
877
878 MEM_freeN(hook);
879 }
880
881 BLO_read_struct(reader, ImageUser, &ob->iuser);
882 if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE && !ob->iuser) {
884 }
885
886 BLO_read_struct_list(reader, LinkData, &ob->pc_ids);
887
888 /* in case this value changes in future, clamp else we get undefined behavior */
890
891 /* Some files were incorrectly written with a dangling pointer to this runtime data. */
892 ob->sculpt = nullptr;
893
894 /* When loading undo steps, for objects in modes that use `sculpt`, recreate the mode runtime
895 * data. For regular non-undo reading, this is currently handled by mode switching after the
896 * initial file read. */
897 if (BLO_read_data_is_undo(reader) && (ob->mode & OB_MODE_ALL_SCULPT)) {
899 }
900
901 BLO_read_struct(reader, PreviewImage, &ob->preview);
903
906
908 if (ob->lightprobe_cache) {
910 }
911}
912
914{
915 Object *ob = reinterpret_cast<Object *>(id);
916
917 Main *bmain = BLO_read_lib_get_main(reader);
919
920 if (ob->data == nullptr && ob->type != OB_EMPTY) {
921 /* NOTE: This case is not expected to happen anymore, since in when a linked ID disappears, an
922 * empty placeholder is created for it by readfile code. Only some serious corruption of data
923 * should be able to trigger this code nowadays. */
924
925 ob->type = OB_EMPTY;
926
927 if (ob->pose) {
928 /* This code is now executed after _all_ ID pointers have been lib-linked,so it's safe to do
929 * a proper cleanup. Further more, since user count of IDs is not done in read-code anymore,
930 * `BKE_pose_free_ex(ob->pose, false)` can be called (instead of
931 * `BKE_pose_free_ex(ob->pose)`), avoiding any access to other IDs altogether. */
932 BKE_pose_free_ex(ob->pose, false);
933 ob->pose = nullptr;
934 ob->mode &= ~OB_MODE_POSE;
935 }
936
937 if (ob->id.lib) {
939 RPT_INFO,
940 RPT_("Can't find object data of %s lib %s"),
941 ob->id.name + 2,
942 ob->id.lib->filepath);
943 }
944 else {
945 BLO_reportf_wrap(reports, RPT_INFO, RPT_("Object %s lost data"), ob->id.name + 2);
946 }
947 reports->count.missing_obdata++;
948 }
949
950 if (ob->data && ELEM(ob->type, OB_FONT, OB_CURVES_LEGACY, OB_SURF)) {
951 /* NOTE: This case may happen when linked curve data changes it's type,
952 * since a #Curve may be used for Text/Surface/Curve.
953 * Since the same ID type is used for all of these.
954 * Within a file (no library linking) this should never happen.
955 * see: #139133. */
956
957 BLI_assert(GS(static_cast<ID *>(ob->data)->name) == ID_CU_LEGACY);
958 /* Don't recalculate any internal curve data is this is low level logic
959 * intended to avoid errors when switching between font/curve types. */
960 BKE_curve_type_test(ob, false);
961 }
962
963 /* When the object is local and the data is library its possible
964 * the material list size gets out of sync. #22663. */
965 if (ob->data && ob->id.lib != static_cast<ID *>(ob->data)->lib) {
966 BKE_object_materials_sync_length(bmain, ob, static_cast<ID *>(ob->data));
967 }
968
969 /* Performs quite extensive rebuilding & validation of object-level Pose data from the Armature
970 * obdata. */
972
974}
975
977{
978 PartEff *paf;
979
980 paf = (PartEff *)ob->effect.first;
981 while (paf) {
982 if (paf->type == EFF_PARTICLE) {
983 return paf;
984 }
985 paf = paf->next;
986 }
987 return nullptr;
988}
989
990static void object_lib_override_apply_post(ID *id_dst, ID *id_src)
991{
992 /* id_dst is the new local override copy of the linked reference data. id_src is the old override
993 * data stored on disk, used as source data for override operations. */
994 Object *object_dst = (Object *)id_dst;
995 Object *object_src = (Object *)id_src;
996
997 ListBase pidlist_dst, pidlist_src;
998 BKE_ptcache_ids_from_object(&pidlist_dst, object_dst, nullptr, 0);
999 BKE_ptcache_ids_from_object(&pidlist_src, object_src, nullptr, 0);
1000
1001 /* Problem with point caches is that several status flags (like OUTDATED or BAKED) are read-only
1002 * at RNA level, and therefore not overridable per-se.
1003 *
1004 * This code is a workaround this to check all point-caches from both source and destination
1005 * objects in parallel, and transfer those flags when it makes sense.
1006 *
1007 * This allows to keep baked caches across lib-overrides applies.
1008 *
1009 * NOTE: This is fairly hackish and weak, but so is the point-cache system as its whole. A more
1010 * robust solution would be e.g. to have a specific RNA entry point to deal with such cases
1011 * (maybe a new flag to allow override code to set values of some read-only properties?).
1012 */
1013 PTCacheID *pid_src, *pid_dst;
1014 for (pid_dst = (PTCacheID *)pidlist_dst.first, pid_src = (PTCacheID *)pidlist_src.first;
1015 pid_dst != nullptr;
1016 pid_dst = pid_dst->next, pid_src = (pid_src != nullptr) ? pid_src->next : nullptr)
1017 {
1018 /* If pid's do not match, just tag info of caches in dst as dirty and continue. */
1019 if (pid_src == nullptr) {
1020 continue;
1021 }
1022 if (pid_dst->type != pid_src->type || pid_dst->file_type != pid_src->file_type ||
1023 pid_dst->default_step != pid_src->default_step || pid_dst->max_step != pid_src->max_step ||
1024 pid_dst->data_types != pid_src->data_types || pid_dst->info_types != pid_src->info_types)
1025 {
1026 LISTBASE_FOREACH (PointCache *, point_cache_src, pid_src->ptcaches) {
1027 point_cache_src->flag |= PTCACHE_FLAG_INFO_DIRTY;
1028 }
1029 continue;
1030 }
1031
1032 PointCache *point_cache_dst, *point_cache_src;
1033 for (point_cache_dst = (PointCache *)pid_dst->ptcaches->first,
1034 point_cache_src = (PointCache *)pid_src->ptcaches->first;
1035 point_cache_dst != nullptr;
1036 point_cache_dst = point_cache_dst->next,
1037 point_cache_src = (point_cache_src != nullptr) ? point_cache_src->next : nullptr)
1038 {
1039 /* Always force updating info about caches of applied lib-overrides. */
1040 point_cache_dst->flag |= PTCACHE_FLAG_INFO_DIRTY;
1041 if (point_cache_src == nullptr || !STREQ(point_cache_dst->name, point_cache_src->name)) {
1042 continue;
1043 }
1044 if ((point_cache_src->flag & PTCACHE_BAKED) != 0) {
1045 point_cache_dst->flag |= PTCACHE_BAKED;
1046 }
1047 if ((point_cache_src->flag & PTCACHE_OUTDATED) == 0) {
1048 point_cache_dst->flag &= ~PTCACHE_OUTDATED;
1049 }
1050 }
1051 }
1052 BLI_freelistN(&pidlist_dst);
1053 BLI_freelistN(&pidlist_src);
1054}
1055
1057{
1058 using namespace blender::bke;
1059 float3 dimensions;
1060 BKE_object_dimensions_get(ob, dimensions);
1061 if (is_zero_v3(dimensions)) {
1062 return nullptr;
1063 }
1064 return idprop::create("dimensions", Span(&dimensions.x, 3)).release();
1065}
1066
1067static void object_asset_metadata_ensure(void *asset_ptr, AssetMetaData *asset_data)
1068{
1069 Object *ob = (Object *)asset_ptr;
1070 BLI_assert(GS(ob->id.name) == ID_OB);
1071
1072 /* Update dimensions hint for the asset. */
1073 if (IDProperty *dimensions_prop = object_asset_dimensions_property(ob)) {
1074 BKE_asset_metadata_idprop_ensure(asset_data, dimensions_prop);
1075 }
1076}
1077
1079 /*pre_save_fn*/ object_asset_metadata_ensure,
1080 /*on_mark_asset_fn*/ object_asset_metadata_ensure,
1081 /*on_clear_asset_fn*/ nullptr,
1082};
1083
1085 /*id_code*/ Object::id_type,
1086 /*id_filter*/ FILTER_ID_OB,
1087 /* Could be more specific, but simpler to just always say 'yes' here. */
1088 /*dependencies_id_types*/ FILTER_ID_ALL,
1089 /*main_listbase_index*/ INDEX_ID_OB,
1090 /*struct_size*/ sizeof(Object),
1091 /*name*/ "Object",
1092 /*name_plural*/ N_("objects"),
1093 /*translation_context*/ BLT_I18NCONTEXT_ID_OBJECT,
1094 /*flags*/ 0,
1095 /*asset_type_info*/ &AssetType_OB,
1096
1097 /*init_data*/ object_init_data,
1098 /*copy_data*/ object_copy_data,
1099 /*free_data*/ object_free_data,
1100 /*make_local*/ nullptr,
1101 /*foreach_id*/ object_foreach_id,
1102 /*foreach_cache*/ object_foreach_cache,
1103 /*foreach_path*/ object_foreach_path,
1104 /*owner_pointer_get*/ nullptr,
1105
1106 /*blend_write*/ object_blend_write,
1107 /*blend_read_data*/ object_blend_read_data,
1108 /*blend_read_after_liblink*/ object_blend_read_after_liblink,
1109
1110 /*blend_read_undo_preserve*/ nullptr,
1111
1112 /*lib_override_apply_post*/ object_lib_override_apply_post,
1113};
1114
1116{
1117 *workob = blender::dna::shallow_zero_initialize();
1118
1119 workob->scale[0] = workob->scale[1] = workob->scale[2] = 1.0f;
1120 workob->dscale[0] = workob->dscale[1] = workob->dscale[2] = 1.0f;
1121 workob->rotmode = ROT_MODE_EUL;
1122}
1123
1125{
1126 while (ParticleSystem *psys = (ParticleSystem *)BLI_pophead(&ob->particlesystem)) {
1127 psys_free(ob, psys);
1128 }
1129}
1130
1132{
1133 sbFree(ob);
1134}
1135
1137{
1138 if (ob->runtime->curve_cache) {
1139 BKE_displist_free(&ob->runtime->curve_cache->disp);
1140 BKE_curve_bevelList_free(&ob->runtime->curve_cache->bev);
1141 if (ob->runtime->curve_cache->anim_path_accum_length) {
1142 MEM_freeN(ob->runtime->curve_cache->anim_path_accum_length);
1143 }
1144 BKE_nurbList_free(&ob->runtime->curve_cache->deformed_nurbs);
1145 MEM_freeN(ob->runtime->curve_cache);
1146 ob->runtime->curve_cache = nullptr;
1147 }
1148}
1149
1151{
1152 while (ModifierData *md = (ModifierData *)BLI_pophead(&ob->modifiers)) {
1154 }
1155
1156 while (
1158 {
1160 }
1161 /* Particle modifiers were freed, so free the particle-systems as well. */
1163
1164 /* Same for soft-body */
1166
1167 /* modifiers may have stored data in the DM cache */
1169}
1170
1172{
1173 while (ShaderFxData *fx = (ShaderFxData *)BLI_pophead(&ob->shader_fx)) {
1175 }
1176}
1177
1179{
1180 /* reset functionality */
1181 if (hmd->object) {
1183
1184 if (hmd->subtarget[0] && pchan) {
1185 float imat[4][4], mat[4][4];
1186
1187 /* Calculate the world-space matrix for the pose-channel target first,
1188 * then carry on as usual. */
1189 mul_m4_m4m4(mat, hmd->object->object_to_world().ptr(), pchan->pose_mat);
1190
1191 invert_m4_m4(imat, mat);
1192 mul_m4_m4m4(hmd->parentinv, imat, ob->object_to_world().ptr());
1193 }
1194 else {
1195 invert_m4_m4(hmd->object->runtime->world_to_object.ptr(),
1196 hmd->object->object_to_world().ptr());
1198 hmd->parentinv, hmd->object->world_to_object().ptr(), ob->object_to_world().ptr());
1199 }
1200 }
1201}
1202
1204{
1205 if (hmd->object == nullptr) {
1206 return;
1207 }
1208 /* reset functionality */
1210
1211 if (hmd->subtarget[0] && pchan) {
1212 float imat[4][4], mat[4][4];
1213
1214 /* Calculate the world-space matrix for the pose-channel target first,
1215 * then carry on as usual. */
1216 mul_m4_m4m4(mat, hmd->object->object_to_world().ptr(), pchan->pose_mat);
1217
1218 invert_m4_m4(imat, mat);
1219 mul_m4_m4m4(hmd->parentinv, imat, ob->object_to_world().ptr());
1220 }
1221 else {
1222 invert_m4_m4(hmd->object->runtime->world_to_object.ptr(),
1223 hmd->object->object_to_world().ptr());
1224 mul_m4_m4m4(hmd->parentinv, hmd->object->world_to_object().ptr(), ob->object_to_world().ptr());
1225 }
1226}
1227
1229{
1230 LISTBASE_FOREACH (ModifierData *, md_iter, &ob->modifiers) {
1231 md_iter->flag &= ~eModifierFlag_Active;
1232 }
1233
1234 if (md != nullptr) {
1235 BLI_assert(BLI_findindex(&ob->modifiers, md) != -1);
1237 }
1238}
1239
1241{
1242 /* In debug mode, check for only one active modifier. */
1243#ifndef NDEBUG
1244 int active_count = 0;
1246 if (md->flag & eModifierFlag_Active) {
1247 active_count++;
1248 }
1249 }
1250 BLI_assert(ELEM(active_count, 0, 1));
1251#endif
1252
1254 if (md->flag & eModifierFlag_Active) {
1255 return md;
1256 }
1257 }
1258
1259 return nullptr;
1260}
1261
1263{
1264 return ELEM(ob->type,
1265 OB_MESH,
1266 OB_CURVES,
1268 OB_SURF,
1269 OB_FONT,
1270 OB_LATTICE,
1272 OB_VOLUME,
1274}
1275
1276bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
1277{
1278 const ModifierTypeInfo *mti = BKE_modifier_get_info((ModifierType)modifier_type);
1279
1280 /* Surface and lattice objects don't output geometry sets. */
1281 if (mti->modify_geometry_set != nullptr && ELEM(ob->type, OB_SURF, OB_LATTICE)) {
1282 return false;
1283 }
1284
1285 if (ELEM(ob->type, OB_POINTCLOUD, OB_CURVES)) {
1287 }
1288 if (ob->type == OB_VOLUME) {
1289 return mti->modify_geometry_set != nullptr;
1290 }
1292 if (ob->type == OB_LATTICE && (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly) == 0) {
1293 return false;
1294 }
1295
1296 if (!((mti->flags & eModifierTypeFlag_AcceptsCVs) ||
1297 (ob->type == OB_MESH && (mti->flags & eModifierTypeFlag_AcceptsMesh))))
1298 {
1299 return false;
1300 }
1301
1302 return true;
1303 }
1305 return true;
1306 }
1307
1308 return false;
1309}
1310
1312{
1314}
1315
1326 const Scene *scene,
1327 Object *ob_dst,
1328 ParticleSystem *psys_src)
1329{
1330 ParticleSystem *psys_dst = nullptr;
1331
1332 /* Check if a particle system with the same particle settings
1333 * already exists on the destination object. */
1334 LISTBASE_FOREACH (ParticleSystem *, psys, &ob_dst->particlesystem) {
1335 if (psys->part == psys_src->part) {
1336 psys_dst = psys;
1337 break;
1338 }
1339 }
1340
1341 /* If it does not exist, copy the particle system to the destination object. */
1342 if (psys_dst == nullptr) {
1343 ModifierData *md = object_copy_particle_system(bmain, scene, ob_dst, psys_src);
1344 psys_dst = ((ParticleSystemModifierData *)md)->psys;
1345 }
1346
1347 return psys_dst;
1348}
1349
1351 const Scene *scene,
1352 Object *ob_dst,
1353 const Object *ob_src,
1354 const ModifierData *md_src)
1355{
1358 /* We never allow copying those modifiers here. */
1359 return false;
1360 }
1361 if (!BKE_object_support_modifier_type_check(ob_dst, md_src->type)) {
1362 return false;
1363 }
1364 if (mti->flags & eModifierTypeFlag_Single) {
1365 if (BKE_modifiers_findby_type(ob_dst, (ModifierType)md_src->type) != nullptr) {
1366 return false;
1367 }
1368 }
1369
1370 ParticleSystem *psys_src = nullptr;
1371 ParticleSystem *psys_dst = nullptr;
1372
1373 switch (md_src->type) {
1375 BKE_object_copy_softbody(ob_dst, ob_src, 0);
1376 break;
1377 case eModifierType_Skin:
1378 /* ensure skin-node customdata exists */
1380 break;
1381 case eModifierType_Fluid: {
1382 const FluidModifierData *fmd = (const FluidModifierData *)md_src;
1383 if (fmd->type == MOD_FLUID_TYPE_FLOW) {
1384 if (fmd->flow != nullptr && fmd->flow->psys != nullptr) {
1385 psys_src = fmd->flow->psys;
1386 psys_dst = object_copy_modifier_particle_system_ensure(bmain, scene, ob_dst, psys_src);
1387 }
1388 }
1389 break;
1390 }
1392 const DynamicPaintModifierData *dpmd = (const DynamicPaintModifierData *)md_src;
1393 if (dpmd->brush != nullptr && dpmd->brush->psys != nullptr) {
1394 psys_src = dpmd->brush->psys;
1395 psys_dst = object_copy_modifier_particle_system_ensure(bmain, scene, ob_dst, psys_src);
1396 }
1397 break;
1398 }
1399 default:
1400 break;
1401 }
1402
1403 ModifierData *md_dst;
1404 if (md_src->type == eModifierType_ParticleSystem) {
1406 bmain, scene, ob_dst, ((const ParticleSystemModifierData *)md_src)->psys);
1407 }
1408 else {
1409 md_dst = BKE_modifier_new(md_src->type);
1410
1411 STRNCPY(md_dst->name, md_src->name);
1412
1413 if (md_src->type == eModifierType_Multires) {
1414 /* Has to be done after mod creation, but *before* we actually copy its settings! */
1416 ob_dst, (const MultiresModifierData *)md_src, (MultiresModifierData *)md_dst);
1417 }
1418
1419 BKE_modifier_copydata(md_src, md_dst);
1420
1421 switch (md_dst->type) {
1423 if (psys_dst != nullptr) {
1424 FluidModifierData *fmd_dst = (FluidModifierData *)md_dst;
1425 BLI_assert(fmd_dst->type == MOD_FLUID_TYPE_FLOW && fmd_dst->flow != nullptr &&
1426 fmd_dst->flow->psys != nullptr);
1427 fmd_dst->flow->psys = psys_dst;
1428 }
1429 break;
1431 if (psys_dst != nullptr) {
1433 BLI_assert(dpmd_dst->brush != nullptr && dpmd_dst->brush->psys != nullptr);
1434 dpmd_dst->brush->psys = psys_dst;
1435 }
1436 break;
1437 default:
1438 break;
1439 }
1440
1441 ModifierData *next_md = nullptr;
1443 if (md->flag & eModifierFlag_PinLast) {
1444 next_md = md;
1445 }
1446 else {
1447 break;
1448 }
1449 }
1450 BLI_insertlinkbefore(&ob_dst->modifiers, next_md, md_dst);
1451 BKE_modifier_unique_name(&ob_dst->modifiers, md_dst);
1452 BKE_modifiers_persistent_uid_init(*ob_dst, *md_dst);
1453 }
1454
1455 BKE_object_modifier_set_active(ob_dst, md_dst);
1456
1457 return true;
1458}
1459
1461 const Object *ob_src,
1462 const bool do_copy_all,
1463 const int flag_subdata)
1464{
1465 if (!BLI_listbase_is_empty(&ob_dst->modifiers) ||
1467 {
1469 false,
1470 "Trying to copy a modifier stack into an object having a non-empty modifier stack.");
1471 return false;
1472 }
1473
1474 LISTBASE_FOREACH (ModifierData *, md_src, &ob_src->modifiers) {
1475 if (!do_copy_all && !object_modifier_type_copy_check((ModifierType)md_src->type)) {
1476 continue;
1477 }
1478 if (!BKE_object_support_modifier_type_check(ob_dst, md_src->type)) {
1479 continue;
1480 }
1481
1482 ModifierData *md_dst = BKE_modifier_copy_ex(md_src, flag_subdata);
1483 BLI_addtail(&ob_dst->modifiers, md_dst);
1484 }
1485
1486 /* This could be copied from anywhere, since no other modifier actually use this data. But for
1487 * consistency do it together with particle systems. */
1488 BKE_object_copy_softbody(ob_dst, ob_src, flag_subdata);
1489
1490 /* It is mandatory that this happens after copying modifiers, as it will update their `psys`
1491 * pointers accordingly. */
1492 BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata);
1493
1494 return true;
1495}
1496
1497void BKE_object_link_modifiers(Object *ob_dst, const Object *ob_src)
1498{
1499 BKE_object_free_modifiers(ob_dst, 0);
1500
1501 BKE_object_modifier_stack_copy(ob_dst, ob_src, false, 0);
1502}
1503
1507static void copy_ccg_data(Mesh *mesh_destination,
1508 Mesh *mesh_source,
1509 const eCustomDataType layer_type)
1510{
1511 BLI_assert(mesh_destination->corners_num == mesh_source->corners_num);
1512 CustomData *data_destination = &mesh_destination->corner_data;
1513 CustomData *data_source = &mesh_source->corner_data;
1514 const int num_elements = mesh_source->corners_num;
1515 if (!CustomData_has_layer(data_source, layer_type)) {
1516 return;
1517 }
1518 const int layer_index = CustomData_get_layer_index(data_destination, layer_type);
1519 CustomData_free_layer(data_destination, layer_type, layer_index);
1520 BLI_assert(!CustomData_has_layer(data_destination, layer_type));
1522 data_destination, eCustomDataType(layer_type), CD_SET_DEFAULT, num_elements);
1523 BLI_assert(CustomData_has_layer(data_destination, layer_type));
1524 CustomData_copy_layer_type_data(data_source, data_destination, layer_type, 0, 0, num_elements);
1525}
1526
1528{
1529 /* Currently CCG is only created for Mesh objects. */
1530 if (object->type != OB_MESH) {
1531 return;
1532 }
1533 /* If object does not own evaluated mesh we can not access it since it might be freed already
1534 * (happens on dependency graph free where order of evaluated IDs free is undefined).
1535 *
1536 * Good news is: such mesh does not have modifiers applied, so no need to worry about CCG. */
1537 if (!object->runtime->is_data_eval_owned) {
1538 return;
1539 }
1540 /* Object was never evaluated, so can not have CCG subdivision surface. If it were evaluated, do
1541 * not try to compute OpenSubDiv on the CPU as it is not needed here. */
1543 if (mesh_eval == nullptr) {
1544 return;
1545 }
1546 SubdivCCG *subdiv_ccg = mesh_eval->runtime->subdiv_ccg.get();
1547 if (subdiv_ccg == nullptr) {
1548 return;
1549 }
1550 /* Check whether there is anything to be reshaped. */
1551 if (!subdiv_ccg->dirty.coords && !subdiv_ccg->dirty.hidden) {
1552 return;
1553 }
1554 const int tot_level = mesh_eval->runtime->subdiv_ccg_tot_level;
1555 Object *object_orig = DEG_get_original(object);
1556 Mesh *mesh_orig = (Mesh *)object_orig->data;
1557 multiresModifier_reshapeFromCCG(tot_level, mesh_orig, subdiv_ccg);
1558 /* NOTE: we need to reshape into an original mesh from main database,
1559 * allowing:
1560 *
1561 * - Update copies of that mesh at any moment.
1562 * - Save the file without doing extra reshape.
1563 * - All the users of the mesh have updated displacement.
1564 *
1565 * However, the tricky part here is that we only know about sculpted
1566 * state of a mesh on an object level, and object is being updated after
1567 * mesh data-block is updated. This forces us to:
1568 *
1569 * - Update mesh data-block from object evaluation, which is technically
1570 * forbidden, but there is no other place for this yet.
1571 * - Reshape to the original mesh from main database, and then copy updated
1572 * layer to copy of that mesh (since copy of the mesh has decoupled
1573 * custom data layers).
1574 *
1575 * All this is defeating all the designs we need to follow to allow safe
1576 * threaded evaluation, but this is as good as we can make it within the
1577 * current sculpt/evaluated mesh design. This is also how we've survived
1578 * with old #DerivedMesh based solutions. So, while this is all wrong and
1579 * needs reconsideration, doesn't seem to be a big stopper for real
1580 * production artists.
1581 */
1582 /* TODO(sergey): Solve this somehow, to be fully stable for threaded
1583 * evaluation environment.
1584 */
1585 /* NOTE: runtime.data_orig is what was before assigning mesh_eval,
1586 * it is orig as in what was in object_eval->data before evaluating
1587 * modifier stack.
1588 *
1589 * mesh_cow is a copy-on-written version of `object_orig->data`.
1590 */
1591 Mesh *mesh_cow = (Mesh *)object->runtime->data_orig;
1592 copy_ccg_data(mesh_cow, mesh_orig, CD_MDISPS);
1593 copy_ccg_data(mesh_cow, mesh_orig, CD_GRID_PAINT_MASK);
1594 /* Everything is now up-to-date. */
1595 subdiv_ccg->dirty.coords = false;
1596 subdiv_ccg->dirty.hidden = false;
1597}
1598
1599void BKE_object_eval_assign_data(Object *object_eval, ID *data_eval, bool is_owned)
1600{
1601 BLI_assert(object_eval->id.tag & ID_TAG_COPIED_ON_EVAL);
1602 BLI_assert(object_eval->runtime->data_eval == nullptr);
1603 BLI_assert(data_eval->tag & ID_TAG_NO_MAIN);
1604
1605 if (is_owned) {
1606 /* Set flag for debugging. */
1608 }
1609
1610 /* Assigned evaluated data. */
1611 object_eval->runtime->data_eval = data_eval;
1612 object_eval->runtime->is_data_eval_owned = is_owned;
1613
1614 /* Overwrite data of evaluated object, if the data-block types match. */
1615 ID *data = (ID *)object_eval->data;
1616 if (GS(data->name) == GS(data_eval->name)) {
1617 /* NOTE: we are not supposed to invoke evaluation for original objects,
1618 * but some areas are still being ported, so we play safe here. */
1619 if (object_eval->id.tag & ID_TAG_COPIED_ON_EVAL) {
1620 object_eval->data = data_eval;
1621 }
1622 }
1623
1624 /* Is set separately currently. */
1625 object_eval->runtime->geometry_set_eval = nullptr;
1626}
1627
1629{
1630 ob->runtime->bounds_eval.reset();
1631
1633
1634 if (ob->runtime->editmesh_eval_cage &&
1635 ob->runtime->editmesh_eval_cage != reinterpret_cast<Mesh *>(ob->runtime->data_eval))
1636 {
1637 BKE_id_free(nullptr, ob->runtime->editmesh_eval_cage);
1638 }
1639 ob->runtime->editmesh_eval_cage = nullptr;
1640
1641 if (ob->runtime->data_eval != nullptr) {
1642 if (ob->runtime->is_data_eval_owned) {
1643 ID *data_eval = ob->runtime->data_eval;
1644 if (GS(data_eval->name) == ID_ME) {
1645 BKE_id_free(nullptr, (Mesh *)data_eval);
1646 }
1647 else {
1648 BKE_libblock_free_data(data_eval, false);
1649 BKE_libblock_free_datablock(data_eval, 0);
1650 MEM_freeN(data_eval);
1651 }
1652 }
1653 ob->runtime->data_eval = nullptr;
1654 }
1655 if (ob->runtime->mesh_deform_eval != nullptr) {
1656 Mesh *mesh_deform_eval = ob->runtime->mesh_deform_eval;
1657 BKE_id_free(nullptr, mesh_deform_eval);
1658 ob->runtime->mesh_deform_eval = nullptr;
1659 }
1660
1661 /* Restore initial pointer for copy-on-evaluation data-blocks, object->data
1662 * might be pointing to an evaluated data-block data was just freed above. */
1663 if (ob->runtime->data_orig != nullptr) {
1664 ob->data = ob->runtime->data_orig;
1665 }
1666
1671
1673
1674 if (ob->runtime->geometry_set_eval != nullptr) {
1675 delete ob->runtime->geometry_set_eval;
1676 ob->runtime->geometry_set_eval = nullptr;
1677 }
1678}
1679
1681{
1682 short update_flag = 0;
1683
1684 /* Free particle system caches holding paths. */
1685 if (object->particlesystem.first) {
1686 LISTBASE_FOREACH (ParticleSystem *, psys, &object->particlesystem) {
1687 psys_free_path_cache(psys, psys->edit);
1688 update_flag |= ID_RECALC_PSYS_REDO;
1689 }
1690 }
1691
1692 /* Free memory used by cached derived meshes in the particle system modifiers. */
1693 LISTBASE_FOREACH (ModifierData *, md, &object->modifiers) {
1694 if (md->type == eModifierType_ParticleSystem) {
1696 if (psmd->mesh_final) {
1697 BKE_id_free(nullptr, psmd->mesh_final);
1698 psmd->mesh_final = nullptr;
1699 if (psmd->mesh_original) {
1700 BKE_id_free(nullptr, psmd->mesh_original);
1701 psmd->mesh_original = nullptr;
1702 }
1704 update_flag |= ID_RECALC_GEOMETRY;
1705 }
1706 }
1707 }
1708
1709 /* NOTE: If object is coming from a duplicator, it might be a temporary
1710 * object created by dependency graph, which shares pointers with original
1711 * object. In this case we can not free anything.
1712 */
1713 if ((object->base_flag & BASE_FROM_DUPLI) == 0) {
1715 update_flag |= ID_RECALC_GEOMETRY;
1716 }
1717
1718 /* Tag object for update, so once memory critical operation is over and
1719 * scene update routines are back to its business the object will be
1720 * guaranteed to be in a known state.
1721 */
1722 if (update_flag != 0) {
1723 DEG_id_tag_update(&object->id, update_flag);
1724 }
1725}
1726
1728{
1729 if (ob->data == nullptr) {
1730 return false;
1731 }
1732
1733 switch (ob->type) {
1734 case OB_MESH:
1735 return ((Mesh *)ob->data)->runtime->edit_mesh != nullptr;
1736 case OB_ARMATURE:
1737 return ((bArmature *)ob->data)->edbo != nullptr;
1738 case OB_FONT:
1739 return ((Curve *)ob->data)->editfont != nullptr;
1740 case OB_MBALL:
1741 return ((MetaBall *)ob->data)->editelems != nullptr;
1742 case OB_LATTICE:
1743 return ((Lattice *)ob->data)->editlatt != nullptr;
1744 case OB_SURF:
1745 case OB_CURVES_LEGACY:
1746 return ((Curve *)ob->data)->editnurb != nullptr;
1747 case OB_CURVES:
1748 case OB_POINTCLOUD:
1749 case OB_GREASE_PENCIL:
1750 return ob->mode == OB_MODE_EDIT;
1751 default:
1752 return false;
1753 }
1754}
1755
1760
1761bool BKE_object_data_is_in_editmode(const Object *ob, const ID *id)
1762{
1763 const short type = GS(id->name);
1765 switch (type) {
1766 case ID_ME:
1767 return ((const Mesh *)id)->runtime->edit_mesh != nullptr;
1768 case ID_CU_LEGACY:
1769 return ((((const Curve *)id)->editnurb != nullptr) ||
1770 (((const Curve *)id)->editfont != nullptr));
1771 case ID_MB:
1772 return ((const MetaBall *)id)->editelems != nullptr;
1773 case ID_LT:
1774 return ((const Lattice *)id)->editlatt != nullptr;
1775 case ID_AR:
1776 return ((const bArmature *)id)->edbo != nullptr;
1777 case ID_CV:
1778 case ID_PT:
1779 case ID_GP:
1780 if (ob) {
1781 return BKE_object_is_in_editmode(ob);
1782 }
1783 return false;
1784 default:
1786 return false;
1787 }
1788}
1789
1791{
1792 const short type = GS(id->name);
1793 switch (type) {
1794 case ID_ME: {
1795 if (BMEditMesh *em = ((Mesh *)id)->runtime->edit_mesh.get()) {
1796 return &em->needs_flush_to_id;
1797 }
1798 break;
1799 }
1800 case ID_CU_LEGACY: {
1801 if (((Curve *)id)->ob_type == OB_FONT) {
1802 EditFont *ef = ((Curve *)id)->editfont;
1803 if (ef != nullptr) {
1804 return &ef->needs_flush_to_id;
1805 }
1806 }
1807 else {
1808 EditNurb *editnurb = ((Curve *)id)->editnurb;
1809 if (editnurb) {
1810 return &editnurb->needs_flush_to_id;
1811 }
1812 }
1813 break;
1814 }
1815 case ID_MB: {
1816 MetaBall *mb = (MetaBall *)id;
1817 return &mb->needs_flush_to_id;
1818 }
1819 case ID_LT: {
1820 EditLatt *editlatt = ((Lattice *)id)->editlatt;
1821 if (editlatt) {
1822 return &editlatt->needs_flush_to_id;
1823 }
1824 break;
1825 }
1826 case ID_AR: {
1827 bArmature *arm = (bArmature *)id;
1828 return &arm->needs_flush_to_id;
1829 }
1830 case ID_GP:
1831 case ID_PT:
1832 case ID_CV:
1833 return nullptr;
1834 default:
1836 return nullptr;
1837 }
1838 return nullptr;
1839}
1840
1842{
1843 if (ob->type == OB_MESH) {
1844 Mesh *mesh = (Mesh *)ob->data;
1845 return ((ob->mode & OB_MODE_WEIGHT_PAINT) && (mesh->runtime->edit_mesh == nullptr) &&
1847 }
1848
1849 return false;
1850}
1851
1852bool BKE_object_has_mode_data(const Object *ob, eObjectMode object_mode)
1853{
1854 if (object_mode & OB_MODE_EDIT) {
1855 if (BKE_object_is_in_editmode(ob)) {
1856 return true;
1857 }
1858 }
1859 else if (object_mode & OB_MODE_VERTEX_PAINT) {
1860 if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
1861 return true;
1862 }
1863 }
1864 else if (object_mode & OB_MODE_WEIGHT_PAINT) {
1865 if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
1866 return true;
1867 }
1868 }
1869 else if (object_mode & OB_MODE_SCULPT) {
1870 if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
1871 return true;
1872 }
1873 }
1874 else if (object_mode & OB_MODE_POSE) {
1875 if (ob->pose != nullptr) {
1876 return true;
1877 }
1878 }
1879 return false;
1880}
1881
1883{
1884 return ((ob->mode == object_mode) || (ob->mode & object_mode) != 0);
1885}
1886
1887int BKE_object_visibility(const Object *ob, const int dag_eval_mode)
1888{
1890 return 0;
1891 }
1892
1893 /* Test which components the object has. */
1894 int visibility = OB_VISIBLE_SELF;
1895 if (ob->particlesystem.first) {
1897 }
1898 else if (ob->transflag & OB_DUPLI) {
1899 visibility |= OB_VISIBLE_INSTANCES;
1900 }
1901
1903 visibility |= OB_VISIBLE_INSTANCES;
1904 }
1905
1906 /* Optional hiding of self if there are particles or instancers. */
1907 if (visibility & (OB_VISIBLE_PARTICLES | OB_VISIBLE_INSTANCES)) {
1908 switch ((eEvaluationMode)dag_eval_mode) {
1909 case DAG_EVAL_VIEWPORT:
1911 visibility &= ~OB_VISIBLE_SELF;
1912 }
1913 break;
1914 case DAG_EVAL_RENDER:
1916 visibility &= ~OB_VISIBLE_SELF;
1917 }
1918 break;
1919 }
1920 }
1921
1922 return visibility;
1923}
1924
1925bool BKE_object_exists_check(Main *bmain, const Object *obtest)
1926{
1927 if (obtest == nullptr) {
1928 return false;
1929 }
1930
1931 LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
1932 if (ob == obtest) {
1933 return true;
1934 }
1935 }
1936
1937 return false;
1938}
1939
1940/* *************************************************** */
1941
1942static const char *get_obdata_defname(int type)
1943{
1944 switch (type) {
1945 case OB_MESH:
1946 return DATA_("Mesh");
1947 case OB_CURVES_LEGACY:
1948 return DATA_("Curve");
1949 case OB_SURF:
1950 return DATA_("Surf");
1951 case OB_FONT:
1952 return DATA_("Text");
1953 case OB_MBALL:
1954 return DATA_("Mball");
1955 case OB_CAMERA:
1956 return DATA_("Camera");
1957 case OB_LAMP:
1958 return CTX_DATA_(BLT_I18NCONTEXT_ID_LIGHT, "Light");
1959 case OB_LATTICE:
1960 return DATA_("Lattice");
1961 case OB_ARMATURE:
1962 return DATA_("Armature");
1963 case OB_SPEAKER:
1964 return DATA_("Speaker");
1965 case OB_CURVES:
1966 return DATA_("Curves");
1967 case OB_POINTCLOUD:
1968 return DATA_("PointCloud");
1969 case OB_VOLUME:
1970 return CTX_DATA_(BLT_I18NCONTEXT_ID_ID, "Volume");
1971 case OB_EMPTY:
1972 return CTX_DATA_(BLT_I18NCONTEXT_ID_ID, "Empty");
1973 case OB_LIGHTPROBE:
1974 return DATA_("LightProbe");
1975 case OB_GREASE_PENCIL:
1976 return DATA_("GreasePencil");
1977 default:
1978 CLOG_ERROR(&LOG, "Internal error, bad type: %d", type);
1979 return CTX_DATA_(BLT_I18NCONTEXT_ID_ID, "Empty");
1980 }
1981}
1982
1983static void object_init(Object *ob, const short ob_type)
1984{
1985 object_init_data(&ob->id);
1986
1987 ob->type = ob_type;
1988
1989 if (ob->type != OB_EMPTY) {
1990 zero_v2(ob->ima_ofs);
1991 }
1992
1993 if (ELEM(ob->type, OB_LAMP, OB_CAMERA, OB_SPEAKER)) {
1994 ob->trackflag = OB_NEGZ;
1995 ob->upflag = OB_POSY;
1996 }
1997
1998 if (ob->type == OB_GREASE_PENCIL) {
2000 }
2001
2002 if (ob->type == OB_LAMP) {
2003 /* Lights are invisible to camera rays and are assumed to be a
2004 * shadow catcher by default. */
2006 }
2007}
2008
2009void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
2010{
2011 if (name == nullptr) {
2012 name = get_obdata_defname(type);
2013 }
2014
2015 switch (type) {
2016 case OB_MESH:
2017 return BKE_mesh_add(bmain, name);
2018 case OB_CURVES_LEGACY:
2019 return BKE_curve_add(bmain, name, OB_CURVES_LEGACY);
2020 case OB_SURF:
2021 return BKE_curve_add(bmain, name, OB_SURF);
2022 case OB_FONT:
2023 return BKE_curve_add(bmain, name, OB_FONT);
2024 case OB_MBALL:
2025 return BKE_mball_add(bmain, name);
2026 case OB_CAMERA:
2027 return BKE_camera_add(bmain, name);
2028 case OB_LAMP:
2029 return BKE_light_add(bmain, name);
2030 case OB_LATTICE:
2031 return BKE_lattice_add(bmain, name);
2032 case OB_ARMATURE:
2033 return BKE_armature_add(bmain, name);
2034 case OB_SPEAKER:
2035 return BKE_speaker_add(bmain, name);
2036 case OB_LIGHTPROBE:
2037 return BKE_lightprobe_add(bmain, name);
2038 case OB_CURVES:
2039 return BKE_curves_add(bmain, name);
2040 case OB_POINTCLOUD:
2041 return BKE_pointcloud_add(bmain, name);
2042 case OB_VOLUME:
2043 return BKE_volume_add(bmain, name);
2044 case OB_GREASE_PENCIL:
2045 return BKE_grease_pencil_add(bmain, name);
2046 case OB_EMPTY:
2047 return nullptr;
2048 default:
2049 CLOG_ERROR(&LOG, "Internal error, bad type: %d", type);
2050 return nullptr;
2051 }
2052}
2053
2055{
2056 /* Keep in sync with #OB_DATA_SUPPORT_ID macro. */
2057 switch (GS(id->name)) {
2058 case ID_ME:
2059 return OB_MESH;
2060 case ID_CU_LEGACY:
2061 return reinterpret_cast<const Curve *>(id)->ob_type;
2062 case ID_MB:
2063 return OB_MBALL;
2064 case ID_LA:
2065 return OB_LAMP;
2066 case ID_SPK:
2067 return OB_SPEAKER;
2068 case ID_CA:
2069 return OB_CAMERA;
2070 case ID_LT:
2071 return OB_LATTICE;
2072 case ID_AR:
2073 return OB_ARMATURE;
2074 case ID_LP:
2075 return OB_LIGHTPROBE;
2076 case ID_CV:
2077 return OB_CURVES;
2078 case ID_PT:
2079 return OB_POINTCLOUD;
2080 case ID_VO:
2081 return OB_VOLUME;
2082 case ID_GP:
2083 return OB_GREASE_PENCIL;
2084 default:
2085 return -1;
2086 }
2087}
2088
2089Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
2090{
2091 if (!name) {
2092 name = get_obdata_defname(type);
2093 }
2094
2095 /* We cannot use #BKE_id_new here as we need some custom initialization code. */
2096 Object *ob = (Object *)BKE_libblock_alloc(bmain, ID_OB, name, bmain ? 0 : LIB_ID_CREATE_NO_MAIN);
2097
2098 /* We increase object user count when linking to Collections. */
2099 id_us_min(&ob->id);
2100
2101 /* default object vars */
2102 object_init(ob, type);
2103
2104 return ob;
2105}
2106
2108 Main *bmain, const Scene *scene, ViewLayer *view_layer, int type, const char *name)
2109{
2110 Object *ob = BKE_object_add_only_object(bmain, type, name);
2111 ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
2112 BKE_view_layer_base_deselect_all(scene, view_layer);
2113
2116 return ob;
2117}
2118
2120 Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
2121{
2122 Object *ob = object_add_common(bmain, scene, view_layer, type, name);
2123
2124 LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
2125 BKE_collection_viewlayer_object_add(bmain, view_layer, layer_collection->collection, ob);
2126
2127 /* NOTE: There is no way to be sure that #BKE_collection_viewlayer_object_add will actually
2128 * manage to find a valid collection in given `view_layer` to add the new object to. */
2129 BKE_view_layer_synced_ensure(scene, view_layer);
2130 Base *base = BKE_view_layer_base_find(view_layer, ob);
2131 if (base != nullptr) {
2133 }
2134
2135 return ob;
2136}
2137
2139 Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name, Object *ob_src)
2140{
2141 Object *ob = object_add_common(bmain, scene, view_layer, type, name);
2142 BKE_collection_object_add_from(bmain, scene, ob_src, ob);
2143
2144 BKE_view_layer_synced_ensure(scene, view_layer);
2145 Base *base = BKE_view_layer_base_find(view_layer, ob);
2147
2148 return ob;
2149}
2150
2152 const Scene *scene,
2153 ViewLayer *view_layer,
2154 int type,
2155 const char *name,
2156 ID *data,
2157 bool do_id_user)
2158{
2159 /* same as object_add_common, except we don't create new ob->data */
2160 Object *ob = BKE_object_add_only_object(bmain, type, name);
2161 ob->data = (void *)data;
2162 if (do_id_user) {
2164 }
2165
2166 BKE_view_layer_base_deselect_all(scene, view_layer);
2169
2170 LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer);
2171 BKE_collection_object_add(bmain, layer_collection->collection, ob);
2172
2173 BKE_view_layer_synced_ensure(scene, view_layer);
2174 Base *base = BKE_view_layer_base_find(view_layer, ob);
2176
2177 return ob;
2178}
2179
2180void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src, const int flag)
2181{
2182 SoftBody *sb = ob_src->soft;
2183 const bool is_orig = (flag & LIB_ID_COPY_SET_COPIED_ON_WRITE) == 0;
2184
2185 ob_dst->softflag = ob_src->softflag;
2186 if (sb == nullptr) {
2187 ob_dst->soft = nullptr;
2188 return;
2189 }
2190
2191 SoftBody *sbn = (SoftBody *)MEM_dupallocN(sb);
2192
2193 if ((flag & LIB_ID_COPY_CACHES) == 0) {
2194 sbn->totspring = sbn->totpoint = 0;
2195 sbn->bpoint = nullptr;
2196 sbn->bspring = nullptr;
2197 }
2198 else {
2199 sbn->totspring = sb->totspring;
2200 sbn->totpoint = sb->totpoint;
2201
2202 if (sbn->bpoint) {
2203 int i;
2204
2205 sbn->bpoint = (BodyPoint *)MEM_dupallocN(sbn->bpoint);
2206
2207 for (i = 0; i < sbn->totpoint; i++) {
2208 if (sbn->bpoint[i].springs) {
2209 sbn->bpoint[i].springs = (int *)MEM_dupallocN(sbn->bpoint[i].springs);
2210 }
2211 }
2212 }
2213
2214 if (sb->bspring) {
2215 sbn->bspring = (BodySpring *)MEM_dupallocN(sb->bspring);
2216 }
2217 }
2218
2219 sbn->keys = nullptr;
2220 sbn->totkey = sbn->totpointkey = 0;
2221
2222 sbn->scratch = nullptr;
2223
2224 if (is_orig) {
2227 &sbn->shared->ptcaches, &sb->shared->ptcaches, flag);
2228 }
2229
2230 if (sb->effector_weights) {
2232 }
2233
2234 ob_dst->soft = sbn;
2235}
2236
2238{
2240
2241 psys_copy_particles(psysn, psys);
2242
2243 if (psys->clmd) {
2246 psys->hair_in_mesh = psys->hair_out_mesh = nullptr;
2247 }
2248
2249 BLI_duplicatelist(&psysn->targets, &psys->targets);
2250
2251 psysn->pathcache = nullptr;
2252 psysn->childcache = nullptr;
2253 psysn->edit = nullptr;
2254 psysn->pdd = nullptr;
2255 psysn->effectors = nullptr;
2256 psysn->tree = nullptr;
2257 psysn->bvhtree = nullptr;
2258 psysn->batch_cache = nullptr;
2259
2262
2264 /* XXX Disabled, fails when evaluating depsgraph after copying ID with no main for preview
2265 * creation. */
2266 // BLI_assert((psys->flag & PSYS_SHARED_CACHES) == 0);
2267 psysn->flag |= PSYS_SHARED_CACHES;
2268 BLI_assert(psysn->pointcache != nullptr);
2269 }
2270 else {
2271 psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag);
2272 }
2273
2274 /* XXX(@ideasman42): from reading existing code this seems correct but intended usage of
2275 * point-cache should with cloth should be added in 'ParticleSystem'. */
2276 if (psysn->clmd) {
2277 psysn->clmd->point_cache = psysn->pointcache;
2278 }
2279
2280 if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
2281 id_us_plus((ID *)psysn->part);
2282 }
2283
2284 return psysn;
2285}
2286
2287void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src, const int flag)
2288{
2289 if (ob_dst->type != OB_MESH) {
2290 /* currently only mesh objects can have soft body */
2291 return;
2292 }
2293
2295 LISTBASE_FOREACH (ParticleSystem *, psys, &ob_src->particlesystem) {
2297
2298 BLI_addtail(&ob_dst->particlesystem, npsys);
2299
2300 /* need to update particle modifiers too */
2301 LISTBASE_FOREACH (ModifierData *, md, &ob_dst->modifiers) {
2302 if (md->type == eModifierType_ParticleSystem) {
2304 if (psmd->psys == psys) {
2305 psmd->psys = npsys;
2306 }
2307 }
2308 else if (md->type == eModifierType_DynamicPaint) {
2310 if (pmd->brush) {
2311 if (pmd->brush->psys == psys) {
2312 pmd->brush->psys = npsys;
2313 }
2314 }
2315 }
2316 else if (md->type == eModifierType_Fluid) {
2318
2319 if (fmd->type == MOD_FLUID_TYPE_FLOW) {
2320 if (fmd->flow) {
2321 if (fmd->flow->psys == psys) {
2322 fmd->flow->psys = npsys;
2323 }
2324 }
2325 }
2326 }
2327 }
2328 }
2329}
2330
2331static void copy_object_pose(Object *obn, const Object *ob, const int flag)
2332{
2333 /* NOTE: need to clear `obn->pose` pointer first,
2334 * so that #BKE_pose_copy_data works (otherwise there's a crash) */
2335 obn->pose = nullptr;
2336 BKE_pose_copy_data_ex(&obn->pose, ob->pose, flag, true); /* true = copy constraints */
2337
2338 LISTBASE_FOREACH (bPoseChannel *, chan, &obn->pose->chanbase) {
2339 chan->flag &= ~(POSE_LOC | POSE_ROT | POSE_SCALE);
2340
2341 /* XXX Remapping object pointing onto itself should be handled by generic
2342 * BKE_library_remap stuff, but...
2343 * the flush_constraint_targets callback am not sure about, so will delay that for now. */
2344 LISTBASE_FOREACH (bConstraint *, con, &chan->constraints) {
2345 ListBase targets = {nullptr, nullptr};
2346
2347 if (BKE_constraint_targets_get(con, &targets)) {
2348 LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
2349 if (ct->tar == ob) {
2350 ct->tar = obn;
2351 }
2352 }
2353
2354 BKE_constraint_targets_flush(con, &targets, false);
2355 }
2356 }
2357 }
2358}
2359
2361{
2362 if ((ob) && (ob->type == OB_ARMATURE) && (ob->pose) && (ob->mode & OB_MODE_POSE)) {
2363 return true;
2364 }
2365
2366 return false;
2367}
2368
2370{
2371 if (ob == nullptr) {
2372 return nullptr;
2373 }
2374
2376 return ob;
2377 }
2378
2380
2381 /* Only use selected check when non-active. */
2383 return ob;
2384 }
2385
2386 return nullptr;
2387}
2388
2390{
2391 /* When not in weight paint mode. */
2392 if (ob) {
2393 switch (ob->type) {
2394 case OB_MESH: {
2395 if ((ob->mode & OB_MODE_WEIGHT_PAINT) == 0) {
2396 return nullptr;
2397 }
2398 break;
2399 }
2400 case OB_GREASE_PENCIL: {
2401 if ((ob->mode & OB_MODE_WEIGHT_GREASE_PENCIL) == 0) {
2402 return nullptr;
2403 }
2404 break;
2405 }
2406 }
2407 }
2409}
2410
2412 const Scene *scene,
2413 ViewLayer *view_layer,
2414 View3D *v3d)
2415{
2416 Object *ob_armature = BKE_object_pose_armature_get(ob);
2417 if (ob_armature) {
2418 BKE_view_layer_synced_ensure(scene, view_layer);
2419 Base *base = BKE_view_layer_base_find(view_layer, ob_armature);
2420 if (base) {
2421 if (BASE_VISIBLE(v3d, base)) {
2422 return ob_armature;
2423 }
2424 }
2425 }
2426 return nullptr;
2427}
2428
2430 ViewLayer *view_layer,
2431 View3D *v3d,
2432 bool unique)
2433{
2434 BKE_view_layer_synced_ensure(scene, view_layer);
2435 Object *ob_active = BKE_view_layer_active_object_get(view_layer);
2436 Object *ob_pose = BKE_object_pose_armature_get(ob_active);
2437 if (ob_pose == ob_active) {
2438 ObjectsInModeParams ob_params{};
2439 ob_params.object_mode = OB_MODE_POSE;
2440 ob_params.no_dup_data = unique;
2441
2442 return BKE_view_layer_array_from_objects_in_mode_params(scene, view_layer, v3d, &ob_params);
2443 }
2444 if (ob_pose != nullptr) {
2445 return {ob_pose};
2446 }
2447
2448 return {};
2449}
2451 ViewLayer *view_layer,
2452 View3D *v3d)
2453{
2454 return BKE_object_pose_array_get_ex(scene, view_layer, v3d, true);
2455}
2457{
2458 return BKE_object_pose_array_get_ex(scene, view_layer, v3d, false);
2459}
2460
2462 ViewLayer *view_layer,
2463 View3D *v3d,
2464 bool unique)
2465{
2466 BKE_view_layer_synced_ensure(scene, view_layer);
2467 Base *base_active = BKE_view_layer_active_base_get(view_layer);
2468 Object *ob_pose = base_active ? BKE_object_pose_armature_get(base_active->object) : nullptr;
2469 Base *base_pose = nullptr;
2470
2471 if (base_active) {
2472 if (ob_pose == base_active->object) {
2473 base_pose = base_active;
2474 }
2475 else {
2476 base_pose = BKE_view_layer_base_find(view_layer, ob_pose);
2477 }
2478 }
2479
2480 if (base_active && (base_pose == base_active)) {
2481 ObjectsInModeParams ob_params{};
2482 ob_params.object_mode = OB_MODE_POSE;
2483 ob_params.no_dup_data = unique;
2484
2485 return BKE_view_layer_array_from_bases_in_mode_params(scene, view_layer, v3d, &ob_params);
2486 }
2487 if (base_pose != nullptr) {
2488 return {base_pose};
2489 }
2490
2491 return {};
2492}
2494 ViewLayer *view_layer,
2495 View3D *v3d)
2496{
2497 return BKE_object_pose_base_array_get_ex(scene, view_layer, v3d, true);
2498}
2500 ViewLayer *view_layer,
2501 View3D *v3d)
2502{
2503 return BKE_object_pose_base_array_get_ex(scene, view_layer, v3d, false);
2504}
2505
2506void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
2507{
2508 copy_v3_v3(ob_tar->loc, ob_src->loc);
2509 copy_v3_v3(ob_tar->rot, ob_src->rot);
2510 copy_v4_v4(ob_tar->quat, ob_src->quat);
2511 copy_v3_v3(ob_tar->rotAxis, ob_src->rotAxis);
2512 ob_tar->rotAngle = ob_src->rotAngle;
2513 ob_tar->rotmode = ob_src->rotmode;
2514 copy_v3_v3(ob_tar->scale, ob_src->scale);
2515}
2516
2518 Object *ob,
2519 eDupli_ID_Flags dupflag,
2520 /*eLibIDDuplicateFlags*/ uint duplicate_options)
2521{
2522 const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
2523 const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
2524 int copy_flags = LIB_ID_COPY_DEFAULT;
2525
2526 if (!is_subprocess) {
2528 }
2529 else {
2530 /* In case copying object is a sub-process of collection (or scene) copying, do not try to
2531 * re-assign RB objects to existing RBW collections. */
2533 }
2534 if (is_root_id) {
2535 /* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
2536 * all expected linked data. */
2537 if (ID_IS_LINKED(ob)) {
2538 dupflag |= USER_DUP_LINKED_ID;
2539 }
2540 duplicate_options &= ~LIB_ID_DUPLICATE_IS_ROOT_ID;
2541 }
2542
2543 Material ***matarar;
2544
2545 Object *obn = (Object *)BKE_id_copy_for_duplicate(bmain, &ob->id, dupflag, copy_flags);
2546
2547 /* 0 == full linked. */
2548 if (dupflag == 0) {
2549 return obn;
2550 }
2551
2552 if (dupflag & USER_DUP_MAT) {
2553 for (int i = 0; i < obn->totcol; i++) {
2554 BKE_id_copy_for_duplicate(bmain, (ID *)obn->mat[i], dupflag, copy_flags);
2555 }
2556 }
2557 if (dupflag & USER_DUP_PSYS) {
2559 BKE_id_copy_for_duplicate(bmain, (ID *)psys->part, dupflag, copy_flags);
2560 }
2561 }
2562
2563 ID *id_old = (ID *)obn->data;
2564 ID *id_new = nullptr;
2565 const bool need_to_duplicate_obdata = (id_old != nullptr) && (id_old->newid == nullptr);
2566
2567 switch (obn->type) {
2568 case OB_MESH:
2569 if (dupflag & USER_DUP_MESH) {
2570 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2571 }
2572 break;
2573 case OB_CURVES_LEGACY:
2574 if (dupflag & USER_DUP_CURVE) {
2575 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2576 }
2577 break;
2578 case OB_SURF:
2579 if (dupflag & USER_DUP_SURF) {
2580 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2581 }
2582 break;
2583 case OB_FONT:
2584 if (dupflag & USER_DUP_FONT) {
2585 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2586 }
2587 break;
2588 case OB_MBALL:
2589 if (dupflag & USER_DUP_MBALL) {
2590 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2591 }
2592 break;
2593 case OB_LAMP:
2594 if (dupflag & USER_DUP_LAMP) {
2595 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2596 }
2597 break;
2598 case OB_ARMATURE:
2599 if (dupflag & USER_DUP_ARM) {
2600 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2601 }
2602 break;
2603 case OB_LATTICE:
2604 if (dupflag & USER_DUP_LATTICE) {
2605 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2606 }
2607 break;
2608 case OB_CAMERA:
2609 if (dupflag & USER_DUP_CAMERA) {
2610 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2611 }
2612 break;
2613 case OB_LIGHTPROBE:
2614 if (dupflag & USER_DUP_LIGHTPROBE) {
2615 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2616 }
2617 break;
2618 case OB_SPEAKER:
2619 if (dupflag & USER_DUP_SPEAKER) {
2620 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2621 }
2622 break;
2623 case OB_GREASE_PENCIL:
2624 if (dupflag & USER_DUP_GPENCIL) {
2625 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2626 }
2627 break;
2628 case OB_CURVES:
2629 if (dupflag & USER_DUP_CURVES) {
2630 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2631 }
2632 break;
2633 case OB_POINTCLOUD:
2634 if (dupflag & USER_DUP_POINTCLOUD) {
2635 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2636 }
2637 break;
2638 case OB_VOLUME:
2639 if (dupflag & USER_DUP_VOLUME) {
2640 id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
2641 }
2642 break;
2643 }
2644
2645 /* If obdata has been copied, we may also have to duplicate the materials assigned to it. */
2646 if (need_to_duplicate_obdata && !ELEM(id_new, nullptr, id_old)) {
2647 if (dupflag & USER_DUP_MAT) {
2648 matarar = BKE_object_material_array_p(obn);
2649 if (matarar) {
2650 for (int i = 0; i < obn->totcol; i++) {
2651 BKE_id_copy_for_duplicate(bmain, (ID *)(*matarar)[i], dupflag, copy_flags);
2652 }
2653 }
2654 }
2655 }
2656
2657 if (!is_subprocess) {
2658 /* This code will follow into all ID links using an ID tagged with ID_TAG_NEW. */
2659 /* Unfortunate, but with some types (e.g. meshes), an object is considered in Edit mode if its
2660 * obdata contains edit mode runtime data. This can be the case of all newly duplicated
2661 * objects, as even though duplicate code move the object back in Object mode, they are still
2662 * using the original obdata ID, leading to them being falsly detected as being in Edit mode,
2663 * and therefore not remapping their obdata to the newly duplicated one.
2664 * See #139715. */
2666
2667#ifndef NDEBUG
2668 /* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
2669 ID *id_iter;
2670 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
2671 BLI_assert((id_iter->tag & ID_TAG_NEW) == 0);
2672 }
2674#endif
2675
2676 /* Cleanup. */
2678 }
2679
2680 if (obn->type == OB_ARMATURE) {
2682 if (obn->pose) {
2683 BKE_pose_tag_recalc(bmain, obn->pose);
2684 }
2685 // BKE_pose_rebuild(bmain, obn, obn->data, true);
2686 }
2687
2688 if (obn->data != nullptr) {
2690 }
2691
2692 return obn;
2693}
2694
2696{
2697 return (ob && ID_IS_LINKED(ob));
2698}
2699
2701{
2702 /* Linked objects with local obdata are forbidden! */
2703 BLI_assert(!ob || !ob->data || (ID_IS_LINKED(ob) ? ID_IS_LINKED(ob->data) : true));
2704 return (ob && ob->data && ID_IS_LINKED(ob->data));
2705}
2706
2708{
2709 /* apply radius as a scale to types that support it */
2710 switch (ob->type) {
2711 case OB_EMPTY: {
2712 ob->empty_drawsize *= size;
2713 break;
2714 }
2715 case OB_FONT: {
2716 Curve *cu = (Curve *)ob->data;
2717 cu->fsize *= size;
2718 break;
2719 }
2720 case OB_CAMERA: {
2721 Camera *cam = (Camera *)ob->data;
2722 cam->drawsize *= size;
2723 break;
2724 }
2725 case OB_LAMP: {
2726 Light *lamp = (Light *)ob->data;
2727 lamp->radius *= size;
2728 lamp->area_size *= size;
2729 lamp->area_sizey *= size;
2730 lamp->area_sizez *= size;
2731 break;
2732 }
2733 /* Only lattice (not mesh, curve, mball...),
2734 * because its got data when newly added */
2735 case OB_LATTICE: {
2736 Lattice *lt = (Lattice *)ob->data;
2737 float mat[4][4];
2738
2739 unit_m4(mat);
2740 scale_m4_fl(mat, size);
2741
2742 BKE_lattice_transform(lt, (float(*)[4])mat, false);
2743 break;
2744 }
2745 }
2746}
2747
2748/* -------------------------------------------------------------------- */
2751
2752void BKE_object_scale_to_mat3(const Object *ob, float mat[3][3])
2753{
2754 float3 vec;
2755 mul_v3_v3v3(vec, ob->scale, ob->dscale);
2756 size_to_mat3(mat, vec);
2757}
2758
2759void BKE_object_rot_to_mat3(const Object *ob, float mat[3][3], bool use_drot)
2760{
2761 float rmat[3][3], dmat[3][3];
2762
2763 /* 'dmat' is the delta-rotation matrix, which will get (pre)multiplied
2764 * with the rotation matrix to yield the appropriate rotation
2765 */
2766
2767 /* Rotations may either be quaternions, eulers (with various rotation orders), or axis-angle. */
2768 if (ob->rotmode > 0) {
2769 /* Euler rotations
2770 * (will cause gimbal lock, but this can be alleviated a bit with rotation orders). */
2771 eulO_to_mat3(rmat, ob->rot, ob->rotmode);
2772 eulO_to_mat3(dmat, ob->drot, ob->rotmode);
2773 }
2774 else if (ob->rotmode == ROT_MODE_AXISANGLE) {
2775 /* axis-angle - not really that great for 3D-changing orientations */
2776 axis_angle_to_mat3(rmat, ob->rotAxis, ob->rotAngle);
2777 axis_angle_to_mat3(dmat, ob->drotAxis, ob->drotAngle);
2778 }
2779 else {
2780 /* Quaternions are normalized before use to eliminate scaling issues. */
2781 float tquat[4];
2782
2783 normalize_qt_qt(tquat, ob->quat);
2784 quat_to_mat3(rmat, tquat);
2785
2786 normalize_qt_qt(tquat, ob->dquat);
2787 quat_to_mat3(dmat, tquat);
2788 }
2789
2790 /* combine these rotations */
2791 if (use_drot) {
2792 mul_m3_m3m3(mat, dmat, rmat);
2793 }
2794 else {
2795 copy_m3_m3(mat, rmat);
2796 }
2797}
2798
2799void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], bool use_compat)
2800{
2801 BLI_ASSERT_UNIT_M3(mat);
2802
2803 switch (ob->rotmode) {
2804 case ROT_MODE_QUAT: {
2805 float dquat[4];
2806 mat3_normalized_to_quat(ob->quat, mat);
2807 normalize_qt_qt(dquat, ob->dquat);
2808 invert_qt_normalized(dquat);
2809 mul_qt_qtqt(ob->quat, dquat, ob->quat);
2810 break;
2811 }
2812 case ROT_MODE_AXISANGLE: {
2813 float quat[4];
2814 float dquat[4];
2815
2816 /* Without `drot` we could apply 'mat' directly. */
2817 mat3_normalized_to_quat(quat, mat);
2818 axis_angle_to_quat(dquat, ob->drotAxis, ob->drotAngle);
2819 invert_qt_normalized(dquat);
2820 mul_qt_qtqt(quat, dquat, quat);
2821 quat_to_axis_angle(ob->rotAxis, &ob->rotAngle, quat);
2822 break;
2823 }
2824 default: /* euler */
2825 {
2826 float quat[4];
2827 float dquat[4];
2828
2829 /* Without `drot` we could apply 'mat' directly. */
2830 mat3_normalized_to_quat(quat, mat);
2831 eulO_to_quat(dquat, ob->drot, ob->rotmode);
2832 invert_qt_normalized(dquat);
2833 mul_qt_qtqt(quat, dquat, quat);
2834 /* End `drot` correction. */
2835
2836 if (use_compat) {
2837 quat_to_compatible_eulO(ob->rot, ob->rot, ob->rotmode, quat);
2838 }
2839 else {
2840 quat_to_eulO(ob->rot, ob->rotmode, quat);
2841 }
2842 break;
2843 }
2844 }
2845}
2846
2848{
2849
2850#define TFMCPY(_v) (obtfm->_v = ob->_v)
2851#define TFMCPY3D(_v) copy_v3_v3(obtfm->_v, ob->_v)
2852#define TFMCPY4D(_v) copy_v4_v4(obtfm->_v, ob->_v)
2853
2854 TFMCPY3D(loc);
2855 TFMCPY3D(dloc);
2856 TFMCPY3D(scale);
2857 TFMCPY3D(dscale);
2858 TFMCPY3D(rot);
2859 TFMCPY3D(drot);
2860 TFMCPY4D(quat);
2861 TFMCPY4D(dquat);
2862 TFMCPY3D(rotAxis);
2863 TFMCPY3D(drotAxis);
2864 TFMCPY(rotAngle);
2865 TFMCPY(drotAngle);
2866
2867#undef TFMCPY
2868#undef TFMCPY3D
2869#undef TFMCPY4D
2870}
2871
2873 const ObjectTfmProtectedChannels *obtfm,
2874 const short protectflag)
2875{
2876 uint i;
2877
2878 for (i = 0; i < 3; i++) {
2879 if (protectflag & (OB_LOCK_LOCX << i)) {
2880 ob->loc[i] = obtfm->loc[i];
2881 ob->dloc[i] = obtfm->dloc[i];
2882 }
2883
2884 if (protectflag & (OB_LOCK_SCALEX << i)) {
2885 ob->scale[i] = obtfm->scale[i];
2886 ob->dscale[i] = obtfm->dscale[i];
2887 }
2888
2889 if (protectflag & (OB_LOCK_ROTX << i)) {
2890 ob->rot[i] = obtfm->rot[i];
2891 ob->drot[i] = obtfm->drot[i];
2892
2893 ob->quat[i + 1] = obtfm->quat[i + 1];
2894 ob->dquat[i + 1] = obtfm->dquat[i + 1];
2895
2896 ob->rotAxis[i] = obtfm->rotAxis[i];
2897 ob->drotAxis[i] = obtfm->drotAxis[i];
2898 }
2899 }
2900
2901 if ((protectflag & OB_LOCK_ROT4D) && (protectflag & OB_LOCK_ROTW)) {
2902 ob->quat[0] = obtfm->quat[0];
2903 ob->dquat[0] = obtfm->dquat[0];
2904
2905 ob->rotAngle = obtfm->rotAngle;
2906 ob->drotAngle = obtfm->drotAngle;
2907 }
2908}
2909
2910void BKE_object_tfm_copy(Object *object_dst, const Object *object_src)
2911{
2912#define TFMCPY(_v) (object_dst->_v = object_src->_v)
2913#define TFMCPY3D(_v) copy_v3_v3(object_dst->_v, object_src->_v)
2914#define TFMCPY4D(_v) copy_v4_v4(object_dst->_v, object_src->_v)
2915
2916 TFMCPY3D(loc);
2917 TFMCPY3D(dloc);
2918 TFMCPY3D(scale);
2919 TFMCPY3D(dscale);
2920 TFMCPY3D(rot);
2921 TFMCPY3D(drot);
2922 TFMCPY4D(quat);
2923 TFMCPY4D(dquat);
2924 TFMCPY3D(rotAxis);
2925 TFMCPY3D(drotAxis);
2926 TFMCPY(rotAngle);
2927 TFMCPY(drotAngle);
2928
2929#undef TFMCPY
2930#undef TFMCPY3D
2931#undef TFMCPY4D
2932}
2933
2934void BKE_object_to_mat3(const Object *ob, float r_mat[3][3]) /* no parent */
2935{
2936 float smat[3][3];
2937 float rmat[3][3];
2938
2939 /* Scale. */
2940 BKE_object_scale_to_mat3(ob, smat);
2941
2942 /* Rotation. */
2943 BKE_object_rot_to_mat3(ob, rmat, true);
2944 mul_m3_m3m3(r_mat, rmat, smat);
2945}
2946
2947void BKE_object_to_mat4(const Object *ob, float r_mat[4][4])
2948{
2949 float tmat[3][3];
2950
2951 BKE_object_to_mat3(ob, tmat);
2952
2953 copy_m4_m3(r_mat, tmat);
2954
2955 add_v3_v3v3(r_mat[3], ob->loc, ob->dloc);
2956}
2957
2958void BKE_object_matrix_local_get(Object *ob, float r_mat[4][4])
2959{
2960 if (ob->parent) {
2961 float par_imat[4][4];
2962
2963 BKE_object_get_parent_matrix(ob, ob->parent, par_imat);
2964 invert_m4(par_imat);
2965 mul_m4_m4m4(r_mat, par_imat, ob->object_to_world().ptr());
2966 }
2967 else {
2968 copy_m4_m4(r_mat, ob->object_to_world().ptr());
2969 }
2970}
2971
2975static bool ob_parcurve(const Object *ob, Object *par, float r_mat[4][4])
2976{
2977 Curve *cu = (Curve *)par->data;
2978 float vec[4], quat[4], radius, ctime;
2979
2980 /* NOTE: Curve cache is supposed to be evaluated here already, however there
2981 * are cases where we can not guarantee that. This includes, for example,
2982 * dependency cycles. We can't correct anything from here, since that would
2983 * cause threading conflicts.
2984 *
2985 * TODO(sergey): Some of the legit looking cases like #56619 need to be
2986 * looked into, and maybe curve cache (and other dependencies) are to be
2987 * evaluated prior to conversion. */
2988 if (par->runtime->curve_cache == nullptr) {
2989 return false;
2990 }
2991 if (par->runtime->curve_cache->anim_path_accum_length == nullptr) {
2992 return false;
2993 }
2994
2995 /* `ctime` is now a proper var setting of Curve which gets set by Animato like any other var
2996 * that's animated, but this will only work if it actually is animated.
2997 *
2998 * We divide the curve-time calculated in the previous step by the length of the path,
2999 * to get a time factor, which then gets clamped to lie within 0.0 - 1.0 range. */
3000 if (cu->pathlen) {
3001 ctime = cu->ctime / cu->pathlen;
3002 }
3003 else {
3004 ctime = cu->ctime;
3005 }
3006
3007 if (cu->flag & CU_PATH_CLAMP) {
3008 CLAMP(ctime, 0.0f, 1.0f);
3009 }
3010
3011 unit_m4(r_mat);
3012
3013 /* vec: 4 items! */
3015 par, ctime, vec, nullptr, (cu->flag & CU_FOLLOW) ? quat : nullptr, &radius, nullptr))
3016 {
3017 if (cu->flag & CU_FOLLOW) {
3019 quat, std::clamp<short>(ob->trackflag, 0, 5), std::clamp<short>(ob->upflag, 0, 2));
3020 normalize_qt(quat);
3021 quat_to_mat4(r_mat, quat);
3022 }
3023 if (cu->flag & CU_PATH_RADIUS) {
3024 float tmat[4][4], rmat[4][4];
3025 scale_m4_fl(tmat, radius);
3026 mul_m4_m4m4(rmat, tmat, r_mat);
3027 copy_m4_m4(r_mat, rmat);
3028 }
3029 copy_v3_v3(r_mat[3], vec);
3030 }
3031
3032 return true;
3033}
3034
3035static void ob_parbone(const Object *ob, const Object *par, float r_mat[4][4])
3036{
3037 float3 vec;
3038
3039 if (par->type != OB_ARMATURE) {
3040 unit_m4(r_mat);
3041 return;
3042 }
3043
3044 /* Make sure the bone is still valid */
3045 const bPoseChannel *pchan = BKE_pose_channel_find_name(par->pose, ob->parsubstr);
3046 if (!pchan || !pchan->bone) {
3047 CLOG_WARN(
3048 &LOG, "Parent Bone: '%s' for Object: '%s' doesn't exist", ob->parsubstr, ob->id.name + 2);
3049 unit_m4(r_mat);
3050 return;
3051 }
3052
3053 /* get bone transform */
3054 if (pchan->bone->flag & BONE_RELATIVE_PARENTING) {
3055 /* the new option uses the root - expected behavior, but differs from old... */
3056 /* XXX check on version patching? */
3057 copy_m4_m4(r_mat, pchan->chan_mat);
3058 }
3059 else {
3060 copy_m4_m4(r_mat, pchan->pose_mat);
3061
3062 /* but for backwards compatibility, the child has to move to the tail */
3063 copy_v3_v3(vec, r_mat[1]);
3064 mul_v3_fl(vec, pchan->bone->length);
3065 add_v3_v3(r_mat[3], vec);
3066 }
3067}
3068
3069static void give_parvert(const Object *par, int nr, float vec[3], const bool use_evaluated_indices)
3070{
3071 zero_v3(vec);
3072
3073 if (par->type == OB_MESH) {
3074 const Mesh *mesh = (const Mesh *)par->data;
3075 const BMEditMesh *em = mesh->runtime->edit_mesh.get();
3076 const Mesh *mesh_eval = (em) ? BKE_object_get_editmesh_eval_final(par) :
3078
3079 if (mesh_eval) {
3080 const Span<float3> positions = mesh_eval->vert_positions();
3081 int count = 0;
3082 int numVerts = mesh_eval->verts_num;
3083
3084 if (em && mesh_eval->runtime->wrapper_type == ME_WRAPPER_TYPE_BMESH) {
3085 numVerts = em->bm->totvert;
3086 if (em->bm->elem_table_dirty & BM_VERT) {
3087#ifdef VPARENT_THREADING_HACK
3088 std::scoped_lock lock(vparent_lock);
3089 if (em->bm->elem_table_dirty & BM_VERT) {
3091 }
3092#else
3093 BLI_assert_msg(0, "Not safe for threading");
3095#endif
3096 }
3097 if (nr < numVerts) {
3098 if (mesh_eval && mesh_eval->runtime->edit_data &&
3099 !mesh_eval->runtime->edit_data->vert_positions.is_empty())
3100 {
3101 add_v3_v3(vec, mesh_eval->runtime->edit_data->vert_positions[nr]);
3102 }
3103 else {
3104 const BMVert *v = BM_vert_at_index(em->bm, nr);
3105 add_v3_v3(vec, v->co);
3106 }
3107 count++;
3108 }
3109 }
3110 else if (use_evaluated_indices && CustomData_has_layer(&mesh_eval->vert_data, CD_ORIGINDEX))
3111 {
3112 const int *index = (const int *)CustomData_get_layer(&mesh_eval->vert_data, CD_ORIGINDEX);
3113 /* Get the average of all verts with (original index == nr). */
3114 for (int i = 0; i < numVerts; i++) {
3115 if (index[i] == nr) {
3116 add_v3_v3(vec, positions[i]);
3117 count++;
3118 }
3119 }
3120 }
3121 else {
3122 if (nr < numVerts) {
3123 add_v3_v3(vec, positions[nr]);
3124 count++;
3125 }
3126 }
3127
3128 if (count == 0) {
3129 /* keep as 0, 0, 0 */
3130 }
3131 else if (count > 0) {
3132 mul_v3_fl(vec, 1.0f / count);
3133 }
3134 else {
3135 /* use first index if its out of range */
3136 if (mesh_eval->verts_num) {
3137 copy_v3_v3(vec, positions[0]);
3138 }
3139 }
3140 }
3141 else {
3142 CLOG_ERROR(&LOG,
3143 "Evaluated mesh is needed to solve parenting, "
3144 "object position can be wrong now");
3145 }
3146 }
3147 else if (ELEM(par->type, OB_CURVES_LEGACY, OB_SURF)) {
3148 ListBase *nurb;
3149
3150 /* It is possible that a cycle in the dependency graph was resolved in a way that caused this
3151 * object to be evaluated before its dependencies. In this case the curve cache may be null. */
3152 if (par->runtime->curve_cache && par->runtime->curve_cache->deformed_nurbs.first != nullptr) {
3153 nurb = &par->runtime->curve_cache->deformed_nurbs;
3154 }
3155 else {
3156 Curve *cu = (Curve *)par->data;
3157 nurb = BKE_curve_nurbs_get(cu);
3158 }
3159
3160 BKE_nurbList_index_get_co(nurb, nr, vec);
3161 }
3162 else if (par->type == OB_LATTICE) {
3163 Lattice *latt = (Lattice *)par->data;
3164 DispList *dl = par->runtime->curve_cache ?
3165 BKE_displist_find(&par->runtime->curve_cache->disp, DL_VERTS) :
3166 nullptr;
3167 float(*co)[3] = dl ? (float(*)[3])dl->verts : nullptr;
3168 int tot;
3169
3170 if (latt->editlatt) {
3171 latt = latt->editlatt->latt;
3172 }
3173
3174 tot = latt->pntsu * latt->pntsv * latt->pntsw;
3175
3176 /* ensure dl is correct size */
3177 BLI_assert(dl == nullptr || dl->nr == tot);
3178
3179 if (nr < tot) {
3180 if (co) {
3181 copy_v3_v3(vec, co[nr]);
3182 }
3183 else {
3184 copy_v3_v3(vec, latt->def[nr].vec);
3185 }
3186 }
3187 }
3188}
3189
3190static void ob_parvert3(const Object *ob, const Object *par, float r_mat[4][4])
3191{
3192 /* in local ob space */
3193 if (OB_TYPE_SUPPORT_PARVERT(par->type)) {
3194 float cmat[3][3], v1[3], v2[3], v3[3], q[4];
3195 const bool use_evaluated_indices = !(ob->transflag & OB_PARENT_USE_FINAL_INDICES);
3196
3197 give_parvert(par, ob->par1, v1, use_evaluated_indices);
3198 give_parvert(par, ob->par2, v2, use_evaluated_indices);
3199 give_parvert(par, ob->par3, v3, use_evaluated_indices);
3200
3201 tri_to_quat(q, v1, v2, v3);
3202 quat_to_mat3(cmat, q);
3203 copy_m4_m3(r_mat, cmat);
3204
3205 mid_v3_v3v3v3(r_mat[3], v1, v2, v3);
3206 }
3207 else {
3208 unit_m4(r_mat);
3209 }
3210}
3211
3212void BKE_object_get_parent_matrix(const Object *ob, Object *par, float r_parentmat[4][4])
3213{
3214 float tmat[4][4];
3215 float vec[3];
3216 const bool use_evaluated_indices = !(ob->transflag & OB_PARENT_USE_FINAL_INDICES);
3217 switch (ob->partype & PARTYPE) {
3218 case PAROBJECT: {
3219 bool ok = false;
3220 if (par->type == OB_CURVES_LEGACY) {
3221 if ((((Curve *)par->data)->flag & CU_PATH) && ob_parcurve(ob, par, tmat)) {
3222 ok = true;
3223 }
3224 }
3225
3226 if (ok) {
3227 mul_m4_m4m4(r_parentmat, par->object_to_world().ptr(), tmat);
3228 }
3229 else {
3230 copy_m4_m4(r_parentmat, par->object_to_world().ptr());
3231 }
3232
3233 break;
3234 }
3235 case PARBONE:
3236 ob_parbone(ob, par, tmat);
3237 mul_m4_m4m4(r_parentmat, par->object_to_world().ptr(), tmat);
3238 break;
3239
3240 case PARVERT1:
3241 unit_m4(r_parentmat);
3242 give_parvert(par, ob->par1, vec, use_evaluated_indices);
3243 mul_v3_m4v3(r_parentmat[3], par->object_to_world().ptr(), vec);
3244 break;
3245 case PARVERT3:
3246 ob_parvert3(ob, par, tmat);
3247
3248 mul_m4_m4m4(r_parentmat, par->object_to_world().ptr(), tmat);
3249 break;
3250
3251 case PARSKEL:
3252 copy_m4_m4(r_parentmat, par->object_to_world().ptr());
3253 break;
3254 }
3255}
3256
3258
3259/* -------------------------------------------------------------------- */
3262
3267static void solve_parenting(const Object *ob,
3268 Object *par,
3269 const bool set_origin,
3270 float r_obmat[4][4],
3271 float r_originmat[3][3])
3272{
3273 float totmat[4][4];
3274 float tmat[4][4];
3275 float locmat[4][4];
3276
3277 BKE_object_to_mat4(ob, locmat);
3278
3279 BKE_object_get_parent_matrix(ob, par, totmat);
3280
3281 /* total */
3282 mul_m4_m4m4(tmat, totmat, ob->parentinv);
3283 mul_m4_m4m4(r_obmat, tmat, locmat);
3284
3285 if (r_originmat) {
3286 /* Usable `r_originmat`. */
3287 copy_m3_m4(r_originmat, tmat);
3288 }
3289
3290 /* origin, for help line */
3291 if (set_origin) {
3292 if ((ob->partype & PARTYPE) == PARSKEL) {
3293 copy_v3_v3(ob->runtime->parent_display_origin, par->object_to_world().location());
3294 }
3295 else {
3296 copy_v3_v3(ob->runtime->parent_display_origin, totmat[3]);
3297 }
3298 }
3299}
3300
3301static void object_where_is_calc_ex(Depsgraph *depsgraph,
3302 Scene *scene,
3303 Object *ob,
3304 float ctime,
3305 RigidBodyWorld *rbw,
3306 float r_originmat[3][3])
3307{
3308 if (ob->parent) {
3309 Object *par = ob->parent;
3310
3311 /* calculate parent matrix */
3312 solve_parenting(ob, par, true, ob->runtime->object_to_world.ptr(), r_originmat);
3313 }
3314 else {
3315 BKE_object_to_mat4(ob, ob->runtime->object_to_world.ptr());
3316 }
3317
3318 /* try to fall back to the scene rigid body world if none given */
3319 rbw = rbw ? rbw : scene->rigidbody_world;
3320 /* read values pushed into RBO from sim/cache... */
3321 BKE_rigidbody_sync_transforms(rbw, ob, ctime);
3322
3323 /* solve constraints */
3324 if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
3325 bConstraintOb *cob;
3327 BKE_constraints_solve(depsgraph, &ob->constraints, cob, ctime);
3329 }
3330
3331 /* set negative scale flag in object */
3332 if (is_negative_m4(ob->object_to_world().ptr())) {
3333 ob->transflag |= OB_NEG_SCALE;
3334 }
3335 else {
3336 ob->transflag &= ~OB_NEG_SCALE;
3337 }
3338}
3339
3340void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *ob, float ctime)
3341{
3342 /* Execute drivers and animation. */
3343 const bool flush_to_original = DEG_is_active(depsgraph);
3345 ctime);
3347 &ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ALL, flush_to_original);
3348 object_where_is_calc_ex(depsgraph, scene, ob, ctime, nullptr, nullptr);
3349}
3350
3351void BKE_object_where_is_calc_mat4(const Object *ob, float r_obmat[4][4])
3352{
3353 if (ob->parent) {
3354 Object *par = ob->parent;
3355 solve_parenting(ob, par, false, r_obmat, nullptr);
3356 }
3357 else {
3358 BKE_object_to_mat4(ob, r_obmat);
3359 }
3360}
3361
3363 Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
3364{
3365 float ctime = DEG_get_ctime(depsgraph);
3366 object_where_is_calc_ex(depsgraph, scene, ob, ctime, rbw, r_originmat);
3367}
3368void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
3369{
3370 float ctime = DEG_get_ctime(depsgraph);
3371 object_where_is_calc_ex(depsgraph, scene, ob, ctime, nullptr, nullptr);
3372}
3373
3375{
3376 blender::bke::ObjectRuntime workob_runtime;
3377 Object workob;
3378 BKE_object_workob_clear(&workob);
3379 workob.runtime = &workob_runtime;
3380
3381 unit_m4(workob.runtime->object_to_world.ptr());
3382 unit_m4(workob.parentinv);
3383 unit_m4(workob.constinv);
3384
3385 /* Since this is used while calculating parenting,
3386 * at this moment ob_eval->parent is still nullptr. */
3388
3389 workob.trackflag = ob->trackflag;
3390 workob.upflag = ob->upflag;
3391
3392 workob.partype = ob->partype;
3393 workob.par1 = ob->par1;
3394 workob.par2 = ob->par2;
3395 workob.par3 = ob->par3;
3396
3397 /* The effects of constraints should NOT be included in the parent-inverse matrix. Constraints
3398 * are supposed to be applied after the object's local loc/rot/scale. If the (inverted) effect of
3399 * constraints would be included in the parent inverse matrix, these would be applied before the
3400 * object's local loc/rot/scale instead of after. For example, a "Copy Rotation" constraint would
3401 * rotate the object's local translation as well. See #82156. */
3402
3403 STRNCPY(workob.parsubstr, ob->parsubstr);
3404
3405 BKE_object_where_is_calc(depsgraph, scene, &workob);
3406
3407 return workob.object_to_world();
3408}
3409
3411 const float mat[4][4],
3412 Object *parent,
3413 const float parentinv[4][4],
3414 const bool use_compat)
3415{
3416 /* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */
3417
3418 float rot[3][3];
3419
3420 if (parent != nullptr) {
3421 float rmat[4][4], diff_mat[4][4], imat[4][4], parent_mat[4][4];
3422
3423 BKE_object_get_parent_matrix(ob, parent, parent_mat);
3424
3425 mul_m4_m4m4(diff_mat, parent_mat, parentinv);
3426 invert_m4_m4(imat, diff_mat);
3427 mul_m4_m4m4(rmat, imat, mat); /* get the parent relative matrix */
3428
3429 /* same as below, use rmat rather than mat */
3430 mat4_to_loc_rot_size(ob->loc, rot, ob->scale, rmat);
3431 }
3432 else {
3433 mat4_to_loc_rot_size(ob->loc, rot, ob->scale, mat);
3434 }
3435
3436 BKE_object_mat3_to_rot(ob, rot, use_compat);
3437
3438 sub_v3_v3(ob->loc, ob->dloc);
3439
3440 if (ob->dscale[0] != 0.0f) {
3441 ob->scale[0] /= ob->dscale[0];
3442 }
3443 if (ob->dscale[1] != 0.0f) {
3444 ob->scale[1] /= ob->dscale[1];
3445 }
3446 if (ob->dscale[2] != 0.0f) {
3447 ob->scale[2] /= ob->dscale[2];
3448 }
3449
3450 /* BKE_object_mat3_to_rot handles delta rotations */
3451}
3452
3454 const float mat[4][4],
3455 const bool use_compat,
3456 const bool use_parent)
3457{
3458 BKE_object_apply_mat4_ex(ob, mat, use_parent ? ob->parent : nullptr, ob->parentinv, use_compat);
3459}
3460
3462{
3463 /*
3464 * Use parent's world transform as the child's origin.
3465 *
3466 * Let:
3467 * `local = identity`
3468 * `world = orthonormalized(parent)`
3469 *
3470 * Then:
3471 * `world = parent @ parentinv @ local`
3472 * `inv(parent) @ world = parentinv`
3473 * `parentinv = inv(parent) @ world`
3474 *
3475 * NOTE: If `ob->object_to_world().ptr()` has shear, then this `parentinv` is insufficient
3476 * because `parent @ parentinv => shearless result`
3477 *
3478 * Thus, local will have shear which cannot be decomposed into TRS:
3479 * `local = inv(parent @ parentinv) @ world`
3480 *
3481 * This is currently not supported for consistency in the handling of shear during the other
3482 * parenting ops: Parent (Keep Transform), Clear [Parent] and Keep Transform.
3483 */
3484 float par_locrot[4][4], par_imat[4][4];
3485 BKE_object_get_parent_matrix(ob, ob->parent, par_locrot);
3486 invert_m4_m4(par_imat, par_locrot);
3487
3488 orthogonalize_m4_stable(par_locrot, 0, true);
3489
3490 mul_m4_m4m4(ob->parentinv, par_imat, par_locrot);
3491
3492 /* Now, preserve `world` given the new `parentinv`.
3493 *
3494 * `world = parent @ parentinv @ local`
3495 * `inv(parent) @ world = parentinv @ local`
3496 * `inv(parentinv) @ inv(parent) @ world = local`
3497 *
3498 * `local = inv(parentinv) @ inv(parent) @ world`
3499 */
3500 float ob_local[4][4];
3501 copy_m4_m4(ob_local, ob->parentinv);
3502 invert_m4(ob_local);
3503 mul_m4_m4_post(ob_local, par_imat);
3504 mul_m4_m4_post(ob_local, ob->object_to_world().ptr());
3505
3506 /* Send use_compat=False so the rotation is predictable. */
3507 BKE_object_apply_mat4(ob, ob_local, false, false);
3508}
3509
3511
3512/* -------------------------------------------------------------------- */
3515
3516void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float max[3])
3517{
3518 bb->vec[0][0] = bb->vec[1][0] = bb->vec[2][0] = bb->vec[3][0] = min[0];
3519 bb->vec[4][0] = bb->vec[5][0] = bb->vec[6][0] = bb->vec[7][0] = max[0];
3520
3521 bb->vec[0][1] = bb->vec[1][1] = bb->vec[4][1] = bb->vec[5][1] = min[1];
3522 bb->vec[2][1] = bb->vec[3][1] = bb->vec[6][1] = bb->vec[7][1] = max[1];
3523
3524 bb->vec[0][2] = bb->vec[3][2] = bb->vec[4][2] = bb->vec[7][2] = min[2];
3525 bb->vec[1][2] = bb->vec[2][2] = bb->vec[5][2] = bb->vec[6][2] = max[2];
3526}
3527
3528void BKE_boundbox_minmax(const BoundBox &bb, const float4x4 &matrix, float3 &r_min, float3 &r_max)
3529{
3530 using namespace blender;
3531 for (const int i : IndexRange(ARRAY_SIZE(bb.vec))) {
3532 math::min_max(math::transform_point(matrix, float3(bb.vec[i])), r_min, r_max);
3533 }
3534}
3535
3536std::optional<blender::Bounds<blender::float3>> BKE_object_boundbox_get(const Object *ob)
3537{
3538 switch (ob->type) {
3539 case OB_MESH:
3540 return static_cast<const Mesh *>(ob->data)->bounds_min_max();
3541 case OB_CURVES_LEGACY:
3542 case OB_SURF:
3543 case OB_FONT:
3544 return BKE_curve_minmax(static_cast<const Curve *>(ob->data), true);
3545 case OB_MBALL:
3547 case OB_LATTICE:
3548 return BKE_lattice_minmax(static_cast<const Lattice *>(ob->data));
3549 case OB_ARMATURE:
3550 return BKE_armature_min_max(ob);
3551 case OB_CURVES:
3552 return static_cast<const Curves *>(ob->data)->geometry.wrap().bounds_min_max();
3553 case OB_POINTCLOUD:
3554 return static_cast<const PointCloud *>(ob->data)->bounds_min_max();
3555 case OB_VOLUME:
3556 return BKE_volume_min_max(static_cast<const Volume *>(ob->data));
3557 case OB_GREASE_PENCIL:
3558 return static_cast<const GreasePencil *>(ob->data)->bounds_min_max_eval();
3559 }
3560 return std::nullopt;
3561}
3562
3563std::optional<Bounds<float3>> BKE_object_boundbox_eval_cached_get(const Object *ob)
3564{
3565 if (ob->runtime->bounds_eval) {
3566 return *ob->runtime->bounds_eval;
3567 }
3568 return BKE_object_boundbox_get(ob);
3569}
3570
3571std::optional<Bounds<float3>> BKE_object_evaluated_geometry_bounds(const Object *ob)
3572{
3573 if (const blender::bke::GeometrySet *geometry = ob->runtime->geometry_set_eval) {
3574 const bool use_radius = ob->type != OB_CURVES_LEGACY;
3575 const bool use_subdiv = true;
3576 return geometry->compute_boundbox_without_instances(use_radius, use_subdiv);
3577 }
3578 if (const CurveCache *curve_cache = ob->runtime->curve_cache) {
3579 float3 min(std::numeric_limits<float>::max());
3580 float3 max(std::numeric_limits<float>::lowest());
3581 BKE_displist_minmax(&curve_cache->disp, min, max);
3582 return Bounds<float3>{min, max};
3583 }
3584 return std::nullopt;
3585}
3586
3588
3589/* -------------------------------------------------------------------- */
3594
3595static float3 boundbox_to_dimensions(const Object *ob, const std::optional<Bounds<float3>> bounds)
3596{
3597 using namespace blender;
3598 if (!bounds) {
3599 return float3(0);
3600 }
3601 const float3 scale = math::to_scale(ob->object_to_world());
3602 return scale * (bounds->max - bounds->min);
3603}
3604
3605void BKE_object_dimensions_get(const Object *ob, float r_vec[3])
3606{
3608}
3609
3614
3616 const float value[3],
3617 int axis_mask,
3618 const float ob_scale_orig[3],
3619 const float ob_obmat_orig[4][4])
3620{
3621 if (const std::optional<Bounds<float3>> bounds = BKE_object_boundbox_eval_cached_get(ob)) {
3622 float3 len = bounds->max - bounds->min;
3623
3624 for (int i = 0; i < 3; i++) {
3625 if (((1 << i) & axis_mask) == 0) {
3626
3627 if (ob_scale_orig != nullptr) {
3628 const float scale_delta = len_v3(ob_obmat_orig[i]) / ob_scale_orig[i];
3629 if (isfinite(scale_delta)) {
3630 len[i] *= scale_delta;
3631 }
3632 }
3633
3634 const float scale = copysignf(value[i] / len[i], ob->scale[i]);
3635 if (isfinite(scale)) {
3636 ob->scale[i] = scale;
3637 }
3638 }
3639 }
3640 }
3641}
3642
3643void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask)
3644{
3645 BKE_object_dimensions_set_ex(ob, value, axis_mask, nullptr, nullptr);
3646}
3647
3648void BKE_object_minmax(Object *ob, float3 &r_min, float3 &r_max)
3649{
3650 using namespace blender;
3651 const float4x4 &object_to_world = ob->object_to_world();
3652 if (const std::optional<Bounds<float3>> bounds = BKE_object_boundbox_get(ob)) {
3653 math::min_max(math::transform_point(object_to_world, bounds->min), r_min, r_max);
3654 math::min_max(math::transform_point(object_to_world, bounds->max), r_min, r_max);
3655 return;
3656 }
3657
3658 float3 size = ob->scale;
3659 if (ob->type == OB_EMPTY) {
3660 size *= ob->empty_drawsize;
3661 }
3662
3663 math::min_max(object_to_world.location() + size, r_min, r_max);
3664 math::min_max(object_to_world.location() - size, r_min, r_max);
3665}
3666
3667void BKE_object_empty_draw_type_set(Object *ob, const int value)
3668{
3669 ob->empty_drawtype = value;
3670
3671 if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) {
3672 if (!ob->iuser) {
3673 ob->iuser = MEM_callocN<ImageUser>("image user");
3674 ob->iuser->flag |= IMA_ANIM_ALWAYS;
3675 ob->iuser->frames = 100;
3676 ob->iuser->sfra = 1;
3677 }
3678 }
3679 else {
3680 MEM_SAFE_FREE(ob->iuser);
3681 }
3682}
3683
3685{
3686 const char visibility_flag = ob->empty_image_visibility_flag;
3687 if (rv3d->is_persp) {
3688 return (visibility_flag & OB_EMPTY_IMAGE_HIDE_PERSPECTIVE) == 0;
3689 }
3690
3691 return (visibility_flag & OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC) == 0;
3692}
3693
3695{
3696 /* Caller is expected to check this. */
3698
3699 const char visibility_flag = ob->empty_image_visibility_flag;
3700
3701 if ((visibility_flag & (OB_EMPTY_IMAGE_HIDE_BACK | OB_EMPTY_IMAGE_HIDE_FRONT)) != 0) {
3702 float eps, dot;
3703 if (rv3d->is_persp) {
3704 /* NOTE: we could normalize the 'view_dir' then use 'eps'
3705 * however the issue with empty objects being visible when viewed from the side
3706 * is only noticeable in orthographic views. */
3707 float3 view_dir;
3708 sub_v3_v3v3(view_dir, rv3d->viewinv[3], ob->object_to_world().location());
3709 dot = dot_v3v3(ob->object_to_world().ptr()[2], view_dir);
3710 eps = 0.0f;
3711 }
3712 else {
3713 dot = dot_v3v3(ob->object_to_world().ptr()[2], rv3d->viewinv[2]);
3714 eps = 1e-5f;
3715 }
3716 if (visibility_flag & OB_EMPTY_IMAGE_HIDE_BACK) {
3717 if (dot < eps) {
3718 return false;
3719 }
3720 }
3721 if (visibility_flag & OB_EMPTY_IMAGE_HIDE_FRONT) {
3722 if (dot > -eps) {
3723 return false;
3724 }
3725 }
3726 }
3727
3728 if (visibility_flag & OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED) {
3729 float3 proj, ob_z_axis;
3730 normalize_v3_v3(ob_z_axis, ob->object_to_world().ptr()[2]);
3731 project_plane_v3_v3v3(proj, ob_z_axis, rv3d->viewinv[2]);
3732 const float proj_length_sq = len_squared_v3(proj);
3733 if (proj_length_sq > 1e-5f) {
3734 return false;
3735 }
3736 }
3737
3738 return true;
3739}
3740
3741bool BKE_object_minmax_empty_drawtype(const Object *ob, float r_min[3], float r_max[3])
3742{
3743 BLI_assert(ob->type == OB_EMPTY);
3744 float3 min(0), max(0);
3745
3746 bool ok = false;
3747 const float radius = ob->empty_drawsize;
3748
3749 switch (ob->empty_drawtype) {
3750 case OB_ARROWS: {
3751 max = float3(radius);
3752 ok = true;
3753 break;
3754 }
3755 case OB_PLAINAXES:
3756 case OB_CUBE:
3757 case OB_EMPTY_SPHERE: {
3758 min = float3(-radius);
3759 max = float3(radius);
3760 ok = true;
3761 break;
3762 }
3763 case OB_CIRCLE: {
3764 max[0] = max[2] = radius;
3765 min[0] = min[2] = -radius;
3766 ok = true;
3767 break;
3768 }
3769 case OB_SINGLE_ARROW: {
3770 max[2] = radius;
3771 ok = true;
3772 break;
3773 }
3774 case OB_EMPTY_CONE: {
3775 min = float3(-radius, 0.0f, -radius);
3776 max = float3(radius, radius * 2.0f, radius);
3777 ok = true;
3778 break;
3779 }
3780 case OB_EMPTY_IMAGE: {
3781 const float *ofs = ob->ima_ofs;
3782 /* NOTE: this is the best approximation that can be calculated without loading the image.
3783 */
3784 min[0] = ofs[0] * radius;
3785 min[1] = ofs[1] * radius;
3786 max[0] = radius + (ofs[0] * radius);
3787 max[1] = radius + (ofs[1] * radius);
3788 /* Since the image aspect can shrink the bounds towards the object origin,
3789 * adjust the min/max to account for that. */
3790 for (int i = 0; i < 2; i++) {
3791 CLAMP_MAX(min[i], 0.0f);
3792 CLAMP_MIN(max[i], 0.0f);
3793 }
3794 ok = true;
3795 break;
3796 }
3797 }
3798
3799 if (ok) {
3800 copy_v3_v3(r_min, min);
3801 copy_v3_v3(r_max, max);
3802 }
3803 return ok;
3804}
3805
3807 Scene *scene,
3808 Object *ob,
3809 float3 &r_min,
3810 float3 &r_max,
3811 const bool use_hidden)
3812{
3813 using namespace blender;
3814 bool ok = false;
3815 if ((ob->transflag & OB_DUPLI) == 0 && ob->runtime->geometry_set_eval == nullptr) {
3816 return ok;
3817 }
3818
3819 ListBase *lb = object_duplilist(depsgraph, scene, ob);
3820 LISTBASE_FOREACH (DupliObject *, dob, lb) {
3821 if (((use_hidden == false) && (dob->no_draw != 0)) || dob->ob_data == nullptr) {
3822 /* pass */
3823 }
3824 else {
3825 Object temp_ob = blender::dna::shallow_copy(*dob->ob);
3826 blender::bke::ObjectRuntime runtime = *dob->ob->runtime;
3827 temp_ob.runtime = &runtime;
3828
3829 /* Do not modify the original bounding-box. */
3830 temp_ob.runtime->bounds_eval.reset();
3831 BKE_object_replace_data_on_shallow_copy(&temp_ob, dob->ob_data);
3832 if (const std::optional<Bounds<float3>> bounds = BKE_object_boundbox_get(&temp_ob)) {
3833 BoundBox bb;
3835 BKE_boundbox_minmax(bb, float4x4(dob->mat), r_min, r_max);
3836 ok = true;
3837 }
3838 }
3839 }
3840 free_object_duplilist(lb); /* does restore */
3841
3842 return ok;
3843}
3844
3846 const float obmat[4][4],
3847 void (*func_cb)(const float[3], void *),
3848 void *user_data)
3849{
3850 /* TODO: point-cloud and curves object support. */
3851 const Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
3852 float3 co;
3853
3854 if (mesh_eval != nullptr) {
3855 const Span<float3> positions = BKE_mesh_wrapper_vert_coords(mesh_eval);
3856 for (const int i : positions.index_range()) {
3857 mul_v3_m4v3(co, obmat, positions[i]);
3858 func_cb(co, user_data);
3859 }
3860 }
3861 else if (ob->type == OB_GREASE_PENCIL) {
3862 using namespace blender::bke::greasepencil;
3863 GreasePencil &grease_pencil = *static_cast<GreasePencil *>(ob->data);
3864 for (const Layer *layer : grease_pencil.layers()) {
3865 if (!layer->is_visible()) {
3866 continue;
3867 }
3868 const float4x4 layer_to_world = layer->to_world_space(*ob);
3869 if (const Drawing *drawing = grease_pencil.get_drawing_at(*layer,
3870 grease_pencil.runtime->eval_frame))
3871 {
3872 const blender::bke::CurvesGeometry &curves = drawing->strokes();
3873 const Span<float3> positions = curves.evaluated_positions();
3875 positions.index_range(), 4096, [&](const blender::IndexRange range) {
3876 for (const int i : range) {
3877 func_cb(blender::math::transform_point(layer_to_world, positions[i]), user_data);
3878 }
3879 });
3880 }
3881 }
3882 }
3883 else if (ob->runtime->curve_cache && ob->runtime->curve_cache->disp.first) {
3884 LISTBASE_FOREACH (DispList *, dl, &ob->runtime->curve_cache->disp) {
3885 const float *v3 = dl->verts;
3886 int totvert = dl->nr;
3887 int i;
3888
3889 for (i = 0; i < totvert; i++, v3 += 3) {
3890 mul_v3_m4v3(co, obmat, v3);
3891 func_cb(co, user_data);
3892 }
3893 }
3894 }
3895}
3896
3898 void (*func_cb)(const float[3], void *),
3899 void *user_data)
3900{
3901 DEGObjectIterSettings deg_iter_settings{};
3902 deg_iter_settings.depsgraph = depsgraph;
3905 DEG_OBJECT_ITER_BEGIN (&deg_iter_settings, ob) {
3906 if ((ob->base_flag & BASE_SELECTED) != 0) {
3907 BKE_object_foreach_display_point(ob, ob->object_to_world().ptr(), func_cb, user_data);
3908 }
3909 }
3911}
3912
3914
3915/* -------------------------------------------------------------------- */
3918
3923 float loc[3], dloc[3];
3924 float scale[3], dscale[3];
3925 float rot[3], drot[3];
3926 float quat[4], dquat[4];
3927 float rotAxis[3], drotAxis[3];
3929 float obmat[4][4];
3930 float parentinv[4][4];
3931 float constinv[4][4];
3932 float imat[4][4];
3933};
3934
3936{
3937 ObTfmBack *obtfm = MEM_mallocN<ObTfmBack>("ObTfmBack");
3938 copy_v3_v3(obtfm->loc, ob->loc);
3939 copy_v3_v3(obtfm->dloc, ob->dloc);
3940 copy_v3_v3(obtfm->scale, ob->scale);
3941 copy_v3_v3(obtfm->dscale, ob->dscale);
3942 copy_v3_v3(obtfm->rot, ob->rot);
3943 copy_v3_v3(obtfm->drot, ob->drot);
3944 copy_qt_qt(obtfm->quat, ob->quat);
3945 copy_qt_qt(obtfm->dquat, ob->dquat);
3946 copy_v3_v3(obtfm->rotAxis, ob->rotAxis);
3947 copy_v3_v3(obtfm->drotAxis, ob->drotAxis);
3948 obtfm->rotAngle = ob->rotAngle;
3949 obtfm->drotAngle = ob->drotAngle;
3950 copy_m4_m4(obtfm->obmat, ob->object_to_world().ptr());
3951 copy_m4_m4(obtfm->parentinv, ob->parentinv);
3952 copy_m4_m4(obtfm->constinv, ob->constinv);
3953 copy_m4_m4(obtfm->imat, ob->world_to_object().ptr());
3954
3955 return (void *)obtfm;
3956}
3957
3958void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
3959{
3960 ObTfmBack *obtfm = (ObTfmBack *)obtfm_pt;
3961 copy_v3_v3(ob->loc, obtfm->loc);
3962 copy_v3_v3(ob->dloc, obtfm->dloc);
3963 copy_v3_v3(ob->scale, obtfm->scale);
3964 copy_v3_v3(ob->dscale, obtfm->dscale);
3965 copy_v3_v3(ob->rot, obtfm->rot);
3966 copy_v3_v3(ob->drot, obtfm->drot);
3967 copy_qt_qt(ob->quat, obtfm->quat);
3968 copy_qt_qt(ob->dquat, obtfm->dquat);
3969 copy_v3_v3(ob->rotAxis, obtfm->rotAxis);
3970 copy_v3_v3(ob->drotAxis, obtfm->drotAxis);
3971 ob->rotAngle = obtfm->rotAngle;
3972 ob->drotAngle = obtfm->drotAngle;
3973 copy_m4_m4(ob->runtime->object_to_world.ptr(), obtfm->obmat);
3974 copy_m4_m4(ob->parentinv, obtfm->parentinv);
3975 copy_m4_m4(ob->constinv, obtfm->constinv);
3976 copy_m4_m4(ob->runtime->world_to_object.ptr(), obtfm->imat);
3977}
3978
3980
3981/* -------------------------------------------------------------------- */
3984
3985void BKE_object_protected_location_set(Object *ob, const float location[3])
3986{
3987 if ((ob->protectflag & OB_LOCK_LOCX) == 0) {
3988 ob->loc[0] = location[0];
3989 }
3990 if ((ob->protectflag & OB_LOCK_LOCY) == 0) {
3991 ob->loc[1] = location[1];
3992 }
3993 if ((ob->protectflag & OB_LOCK_LOCZ) == 0) {
3994 ob->loc[2] = location[2];
3995 }
3996}
3997
3998void BKE_object_protected_scale_set(Object *ob, const float scale[3])
3999{
4000 if ((ob->protectflag & OB_LOCK_SCALEX) == 0) {
4001 ob->scale[0] = scale[0];
4002 }
4003 if ((ob->protectflag & OB_LOCK_SCALEY) == 0) {
4004 ob->scale[1] = scale[1];
4005 }
4006 if ((ob->protectflag & OB_LOCK_SCALEZ) == 0) {
4007 ob->scale[2] = scale[2];
4008 }
4009}
4010
4012{
4013 if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
4014 ob->quat[0] = quat[0];
4015 }
4016 if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
4017 ob->quat[1] = quat[1];
4018 }
4019 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
4020 ob->quat[2] = quat[2];
4021 }
4022 if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
4023 ob->quat[3] = quat[3];
4024 }
4025}
4026
4028{
4029 if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
4030 ob->rot[0] = euler[0];
4031 }
4032 if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
4033 ob->rot[1] = euler[1];
4034 }
4035 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
4036 ob->rot[2] = euler[2];
4037 }
4038}
4039
4041 const float axis[3],
4042 const float angle)
4043{
4044 if ((ob->protectflag & OB_LOCK_ROTX) == 0) {
4045 ob->rotAxis[0] = axis[0];
4046 }
4047 if ((ob->protectflag & OB_LOCK_ROTY) == 0) {
4048 ob->rotAxis[1] = axis[1];
4049 }
4050 if ((ob->protectflag & OB_LOCK_ROTZ) == 0) {
4051 ob->rotAxis[2] = axis[2];
4052 }
4053 if ((ob->protectflag & OB_LOCK_ROTW) == 0) {
4054 ob->rotAngle = angle;
4055 }
4056}
4057
4059
4060/* -------------------------------------------------------------------- */
4063
4065 Scene *scene,
4066 Object *ob,
4067 RigidBodyWorld *rbw)
4068{
4069 const ID *object_data = (ID *)ob->data;
4070 const bool recalc_object = (ob->id.recalc & ID_RECALC_ALL) != 0;
4071 const bool recalc_data = (object_data != nullptr) ?
4072 ((object_data->recalc & ID_RECALC_ALL) != 0) :
4073 false;
4074 if (!recalc_object && !recalc_data) {
4075 return;
4076 }
4077 /* Speed optimization for animation lookups. */
4078 if (ob->pose != nullptr) {
4082 }
4083 }
4084 if (recalc_data) {
4085 if (ob->type == OB_ARMATURE) {
4086 /* this happens for reading old files and to match library armatures
4087 * with poses we do it ahead of BKE_object_where_is_calc to ensure animation
4088 * is evaluated on the rebuilt pose, otherwise we get incorrect poses
4089 * on file load */
4090 if (ob->pose == nullptr || (ob->pose->flag & POSE_RECALC)) {
4091 /* No need to pass `bmain` here, we assume we do not need to rebuild DEG from here. */
4092 BKE_pose_rebuild(nullptr, ob, (bArmature *)ob->data, true);
4093 }
4094 }
4095 }
4096 /* XXX new animsys warning: depsgraph tag ID_RECALC_GEOMETRY should not skip drivers,
4097 * which is only in BKE_object_where_is_calc now */
4098 /* XXX: should this case be ID_RECALC_TRANSFORM instead? */
4099 if (recalc_object || recalc_data) {
4100 if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
4101 printf("recalcob %s\n", ob->id.name + 2);
4102 }
4103 BKE_object_where_is_calc_ex(depsgraph, scene, rbw, ob, nullptr);
4104 }
4105
4106 if (recalc_data) {
4108 }
4109}
4110
4111void BKE_object_handle_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
4112{
4113 BKE_object_handle_update_ex(depsgraph, scene, ob, nullptr);
4114}
4115
4117{
4118 BLI_assert((ob->sculpt == nullptr) && (ob->mode & OB_MODE_ALL_SCULPT));
4119 ob->sculpt = MEM_new<SculptSession>(__func__);
4120 ob->sculpt->mode_type = (eObjectMode)ob->mode;
4121}
4122
4124 char **r_texspace_flag,
4125 float **r_texspace_location,
4126 float **r_texspace_size)
4127{
4128 if (ob->data == nullptr) {
4129 return false;
4130 }
4131
4132 switch (GS(((ID *)ob->data)->name)) {
4133 case ID_ME: {
4135 (Mesh *)ob->data, r_texspace_flag, r_texspace_location, r_texspace_size);
4136 break;
4137 }
4138 case ID_CU_LEGACY: {
4139 Curve *cu = (Curve *)ob->data;
4141 if (r_texspace_flag) {
4142 *r_texspace_flag = &cu->texspace_flag;
4143 }
4144 if (r_texspace_location) {
4145 *r_texspace_location = cu->texspace_location;
4146 }
4147 if (r_texspace_size) {
4148 *r_texspace_size = cu->texspace_size;
4149 }
4150 break;
4151 }
4152 case ID_MB: {
4153 MetaBall *mb = (MetaBall *)ob->data;
4154 if (r_texspace_flag) {
4155 *r_texspace_flag = &mb->texspace_flag;
4156 }
4157 if (r_texspace_location) {
4158 *r_texspace_location = mb->texspace_location;
4159 }
4160 if (r_texspace_size) {
4161 *r_texspace_size = mb->texspace_size;
4162 }
4163 break;
4164 }
4165 default:
4166 return false;
4167 }
4168 return true;
4169}
4170
4172{
4173 /* First attempt to retrieve the evaluated mesh from the evaluated geometry set. Most
4174 * object types either store it there or add a reference to it if it's owned elsewhere. */
4175 blender::bke::GeometrySet *geometry_set_eval = object->runtime->geometry_set_eval;
4176 if (geometry_set_eval) {
4177 /* Some areas expect to be able to modify the evaluated mesh in limited ways. Theoretically
4178 * this should be avoided, or at least protected with a lock, so a const mesh could be
4179 * returned from this function. We use a const_cast instead of #get_mesh_for_write, because
4180 * that might result in a copy of the mesh when it is shared. */
4181 Mesh *mesh = const_cast<Mesh *>(geometry_set_eval->get_mesh());
4182 if (mesh) {
4183 return mesh;
4184 }
4185 }
4186
4187 /* Some object types do not yet add the evaluated mesh to an evaluated geometry set, if they do
4188 * not support evaluating to multiple data types. Eventually this should be removed, when all
4189 * object types use #geometry_set_eval. */
4190 ID *data_eval = object->runtime->data_eval;
4191 if (data_eval && GS(data_eval->name) == ID_ME) {
4192 return reinterpret_cast<Mesh *>(data_eval);
4193 }
4194
4195 return nullptr;
4196}
4197
4199{
4200 if (!DEG_object_geometry_is_evaluated(*object)) {
4201 return nullptr;
4202 }
4204}
4205
4207{
4209 if (!mesh) {
4210 return nullptr;
4211 }
4213}
4214
4216{
4217 if (!DEG_object_geometry_is_evaluated(*object_eval)) {
4218 return nullptr;
4219 }
4220 return BKE_object_get_evaluated_mesh_unchecked(object_eval);
4221}
4222
4224{
4225 BLI_assert(object->type == OB_MESH);
4226 if (const ID *data_orig = object->runtime->data_orig) {
4228 BLI_assert(object->id.orig_id != nullptr);
4229 BLI_assert(data_orig->orig_id == ((const Object *)object->id.orig_id)->data);
4230 BLI_assert((data_orig->tag & ID_TAG_COPIED_ON_EVAL) != 0);
4231 BLI_assert((data_orig->tag & ID_TAG_COPIED_ON_EVAL_FINAL_RESULT) == 0);
4232 if (GS(data_orig->name) != ID_ME) {
4233 return nullptr;
4234 }
4235 return reinterpret_cast<const Mesh *>(data_orig);
4236 }
4237 BLI_assert((object->id.tag & ID_TAG_COPIED_ON_EVAL) == 0);
4238 return static_cast<const Mesh *>(object->data);
4239}
4240
4242{
4243 Mesh *result = nullptr;
4244 if (object->id.orig_id == nullptr) {
4245 BLI_assert((object->id.tag & ID_TAG_COPIED_ON_EVAL) == 0);
4246 result = (Mesh *)object->data;
4247 }
4248 else {
4249 BLI_assert((object->id.tag & ID_TAG_COPIED_ON_EVAL) != 0);
4250 result = (Mesh *)((Object *)object->id.orig_id)->data;
4251 }
4252 BLI_assert(result != nullptr);
4254 return result;
4255}
4256
4258{
4259 BLI_assert(!DEG_is_original(object));
4260 BLI_assert(object->type == OB_MESH);
4261
4262 const Mesh *mesh = static_cast<const Mesh *>(object->data);
4263 if (mesh->runtime->edit_mesh == nullptr) {
4264 /* Happens when requesting material of evaluated 3d font object: the evaluated object get
4265 * converted to mesh, and it does not have edit mesh. */
4266 return nullptr;
4267 }
4268
4269 return reinterpret_cast<Mesh *>(object->runtime->data_eval);
4270}
4271
4273{
4274 BLI_assert(!DEG_is_original(object));
4275 BLI_assert(object->type == OB_MESH);
4276
4277 return object->runtime->editmesh_eval_cage;
4278}
4279
4281{
4282 BLI_assert(!DEG_is_original(object));
4283 BLI_assert(object->type == OB_MESH);
4284 return object->runtime->mesh_deform_eval;
4285}
4286
4288{
4289 ID *data = (ID *)object->data;
4290 if (data == nullptr || GS(data->name) != ID_LT) {
4291 return nullptr;
4292 }
4293
4294 Lattice *lt = (Lattice *)data;
4295 if (lt->editlatt) {
4296 return lt->editlatt->latt;
4297 }
4298
4299 return lt;
4300}
4301
4303{
4304 ID *data_eval = object->runtime->data_eval;
4305
4306 if (data_eval == nullptr || GS(data_eval->name) != ID_LT) {
4307 return nullptr;
4308 }
4309
4310 Lattice *lt_eval = (Lattice *)data_eval;
4311 if (lt_eval->editlatt) {
4312 return lt_eval->editlatt->latt;
4313 }
4314
4315 return lt_eval;
4316}
4317
4319
4320/* -------------------------------------------------------------------- */
4323
4324static int pc_cmp(const void *a, const void *b)
4325{
4326 const LinkData *ad = (const LinkData *)a, *bd = (const LinkData *)b;
4327 if (POINTER_AS_INT(ad->data) > POINTER_AS_INT(bd->data)) {
4328 return 1;
4329 }
4330
4331 return 0;
4332}
4333
4335{
4336 /* TODO: Review the usages of this function, currently with copy-on-eval it will be called for
4337 * orig object and then again for evaluated copies of it, think this is bad since there is no
4338 * guarantee that we get the same stack index in both cases? Order is important since this index
4339 * is used for filenames on disk. */
4340
4341 LinkData *link = nullptr;
4342 int i = 0;
4343
4345
4346 for (link = (LinkData *)ob->pc_ids.first, i = 0; link; link = link->next, i++) {
4347 int index = POINTER_AS_INT(link->data);
4348
4349 if (i < index) {
4350 break;
4351 }
4352 }
4353
4354 link = MEM_callocN<LinkData>("PCLink");
4355 link->data = POINTER_FROM_INT(i);
4356 BLI_addtail(&ob->pc_ids, link);
4357
4358 return i;
4359}
4360
4361static int pc_findindex(ListBase *listbase, int index)
4362{
4363 int number = 0;
4364
4365 if (listbase == nullptr) {
4366 return -1;
4367 }
4368
4369 LinkData *link = (LinkData *)listbase->first;
4370 while (link) {
4371 if (POINTER_AS_INT(link->data) == index) {
4372 return number;
4373 }
4374
4375 number++;
4376 link = link->next;
4377 }
4378
4379 return -1;
4380}
4381
4383{
4384 int list_index = pc_findindex(&ob->pc_ids, index);
4385 LinkData *link = (LinkData *)BLI_findlink(&ob->pc_ids, list_index);
4386 BLI_freelinkN(&ob->pc_ids, link);
4387}
4388
4390
4391/* -------------------------------------------------------------------- */
4394
4396static KeyBlock *insert_meshkey(Main *bmain, Object *ob, const char *name, const bool from_mix)
4397{
4398 Mesh *mesh = (Mesh *)ob->data;
4399 Key *key = mesh->key;
4400 KeyBlock *kb;
4401 int newkey = 0;
4402
4403 if (key == nullptr) {
4404 key = mesh->key = BKE_key_add(bmain, (ID *)mesh);
4405 key->type = KEY_RELATIVE;
4406 newkey = 1;
4407 }
4408
4409 if (newkey || from_mix == false) {
4410 /* create from mesh */
4411 kb = BKE_keyblock_add_ctime(key, name, false);
4413 }
4414 else {
4415 /* copy from current values */
4416 int totelem;
4417 float *data = BKE_key_evaluate_object(ob, &totelem);
4418
4419 /* create new block with prepared data */
4420 kb = BKE_keyblock_add_ctime(key, name, false);
4421 kb->data = data;
4422 kb->totelem = totelem;
4423 }
4424
4425 return kb;
4426}
4427
4428static KeyBlock *insert_lattkey(Main *bmain, Object *ob, const char *name, const bool from_mix)
4429{
4430 Lattice *lt = (Lattice *)ob->data;
4431 Key *key = lt->key;
4432 KeyBlock *kb;
4433 int newkey = 0;
4434
4435 if (key == nullptr) {
4436 key = lt->key = BKE_key_add(bmain, (ID *)lt);
4437 key->type = KEY_RELATIVE;
4438 newkey = 1;
4439 }
4440
4441 if (newkey || from_mix == false) {
4442 kb = BKE_keyblock_add_ctime(key, name, false);
4443 if (!newkey) {
4444 KeyBlock *basekb = (KeyBlock *)key->block.first;
4445 kb->data = MEM_dupallocN(basekb->data);
4446 kb->totelem = basekb->totelem;
4447 }
4448 else {
4450 }
4451 }
4452 else {
4453 /* copy from current values */
4454 int totelem;
4455 float *data = BKE_key_evaluate_object(ob, &totelem);
4456
4457 /* create new block with prepared data */
4458 kb = BKE_keyblock_add_ctime(key, name, false);
4459 kb->totelem = totelem;
4460 kb->data = data;
4461 }
4462
4463 return kb;
4464}
4465
4466static KeyBlock *insert_curvekey(Main *bmain, Object *ob, const char *name, const bool from_mix)
4467{
4468 Curve *cu = (Curve *)ob->data;
4469 Key *key = cu->key;
4470 KeyBlock *kb;
4471 ListBase *lb = BKE_curve_nurbs_get(cu);
4472 int newkey = 0;
4473
4474 if (key == nullptr) {
4475 key = cu->key = BKE_key_add(bmain, (ID *)cu);
4476 key->type = KEY_RELATIVE;
4477 newkey = 1;
4478 }
4479
4480 if (newkey || from_mix == false) {
4481 /* create from curve */
4482 kb = BKE_keyblock_add_ctime(key, name, false);
4483 if (!newkey) {
4484 KeyBlock *basekb = (KeyBlock *)key->block.first;
4485 kb->data = MEM_dupallocN(basekb->data);
4486 kb->totelem = basekb->totelem;
4487 }
4488 else {
4490 }
4491 }
4492 else {
4493 /* copy from current values */
4494 int totelem;
4495 float *data = BKE_key_evaluate_object(ob, &totelem);
4496
4497 /* create new block with prepared data */
4498 kb = BKE_keyblock_add_ctime(key, name, false);
4499 kb->totelem = totelem;
4500 kb->data = data;
4501 }
4502
4503 return kb;
4504}
4505
4507
4508/* -------------------------------------------------------------------- */
4511
4513 Object *ob,
4514 const char *name,
4515 const bool from_mix)
4516{
4517 KeyBlock *key = nullptr;
4518
4519 switch (ob->type) {
4520 case OB_MESH:
4521 key = insert_meshkey(bmain, ob, name, from_mix);
4522 break;
4523 case OB_CURVES_LEGACY:
4524 case OB_SURF:
4525 key = insert_curvekey(bmain, ob, name, from_mix);
4526 break;
4527 case OB_LATTICE:
4528 key = insert_lattkey(bmain, ob, name, from_mix);
4529 break;
4530 default:
4531 break;
4532 }
4533
4534 /* Set the first active when none is set when called from RNA. */
4535 if (key != nullptr) {
4536 if (ob->shapenr <= 0) {
4537 ob->shapenr = 1;
4538 }
4539 }
4540
4541 return key;
4542}
4543
4545{
4546 Key **key_p, *key;
4547
4548 key_p = BKE_key_from_object_p(ob);
4549 if (ELEM(nullptr, key_p, *key_p)) {
4550 return false;
4551 }
4552
4553 key = *key_p;
4554 *key_p = nullptr;
4555
4556 BKE_id_free_us(bmain, key);
4557
4558 return true;
4559}
4560
4562{
4563 Key *key = BKE_key_from_object(ob);
4564 short kb_index;
4565
4566 if (key == nullptr) {
4567 return false;
4568 }
4569
4570 BKE_animdata_drivers_remove_for_rna_struct(key->id, RNA_ShapeKey, kb);
4571
4572 kb_index = BLI_findindex(&key->block, kb);
4573 BLI_assert(kb_index != -1);
4574
4575 LISTBASE_FOREACH (KeyBlock *, rkb, &key->block) {
4576 if (rkb->relative == kb_index) {
4577 /* remap to the 'Basis' */
4578 rkb->relative = 0;
4579 }
4580 else if (rkb->relative >= kb_index) {
4581 /* Fix positional shift of the keys when kb is deleted from the list */
4582 rkb->relative -= 1;
4583 }
4584 }
4585
4586 BLI_remlink(&key->block, kb);
4587 key->totkey--;
4588 if (key->refkey == kb) {
4589 key->refkey = (KeyBlock *)key->block.first;
4590
4591 if (key->refkey) {
4592 /* apply new basis key on original data */
4593 switch (ob->type) {
4594 case OB_MESH: {
4595 Mesh *mesh = (Mesh *)ob->data;
4596 BKE_keyblock_convert_to_mesh(key->refkey, mesh->vert_positions_for_write());
4597 break;
4598 }
4599 case OB_CURVES_LEGACY:
4600 case OB_SURF:
4602 key->refkey, (Curve *)ob->data, BKE_curve_nurbs_get((Curve *)ob->data));
4603 break;
4604 case OB_LATTICE:
4606 break;
4607 }
4608 }
4609 }
4610
4611 if (kb->data) {
4612 MEM_freeN(kb->data);
4613 }
4614 MEM_freeN(kb);
4615
4616 /* Unset active when all are freed. */
4617 if (BLI_listbase_is_empty(&key->block)) {
4618 ob->shapenr = 0;
4619 }
4620 else if (ob->shapenr > 1) {
4621 ob->shapenr--;
4622 }
4623
4624 if (key->totkey == 0) {
4625 BKE_object_shapekey_free(bmain, ob);
4626 }
4627
4628 return true;
4629}
4630
4632
4633/* -------------------------------------------------------------------- */
4636
4637bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
4638{
4639 /* test if 'ob' is a parent somewhere in par's parents */
4640 if (par == nullptr) {
4641 return false;
4642 }
4643 if (ob == par) {
4644 return true;
4645 }
4646 return BKE_object_parent_loop_check(par->parent, ob);
4647}
4648
4650{
4651 if (ob->flag & flag) {
4652 return true;
4653 }
4654 if (ob->parent) {
4656 }
4657
4658 return false;
4659}
4660
4661bool BKE_object_is_child_recursive(const Object *ob_parent, const Object *ob_child)
4662{
4663 for (ob_child = ob_child->parent; ob_child; ob_child = ob_child->parent) {
4664 if (ob_child == ob_parent) {
4665 return true;
4666 }
4667 }
4668 return false;
4669}
4670
4672{
4673 /* Always test on original object since evaluated object may no longer
4674 * have shape keys or modifiers that were used to evaluate it. */
4675 ob = DEG_get_original(ob);
4676
4677 int flag = 0;
4678
4679 if (BKE_key_from_object(ob)) {
4681 }
4682 else {
4683 ModifierData *md;
4684 VirtualModifierData virtual_modifier_data;
4685 /* cloth */
4686 for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
4688 md = md->next)
4689 {
4690 if ((flag & eModifierMode_Render) == 0 &&
4692 {
4694 }
4695
4696 if ((flag & eModifierMode_Realtime) == 0 &&
4698 {
4700 }
4701 }
4702 }
4703
4704 return flag;
4705}
4706
4707bool BKE_object_moves_in_time(const Object *object, bool recurse_parent)
4708{
4709 /* If object has any sort of animation data assume it is moving. */
4711 return true;
4712 }
4713 if (!BLI_listbase_is_empty(&object->constraints)) {
4714 return true;
4715 }
4716 if (recurse_parent && object->parent != nullptr) {
4717 return BKE_object_moves_in_time(object->parent, true);
4718 }
4719 return false;
4720}
4721
4722static bool object_moves_in_time(const Object *object)
4723{
4724 return BKE_object_moves_in_time(object, true);
4725}
4726
4727static bool object_deforms_in_time(Object *object)
4728{
4729 if (BKE_key_from_object(object) != nullptr) {
4730 return true;
4731 }
4732 if (!BLI_listbase_is_empty(&object->modifiers)) {
4733 return true;
4734 }
4735 return object_moves_in_time(object);
4736}
4737
4739{
4740 /* TODO(sergey): Consider generalizing this a bit so all modifier logic
4741 * is concentrated in MOD_{modifier}.c file,
4742 */
4743 if (md->type == eModifierType_Array) {
4745 /* TODO(sergey): Check if curve is deformed. */
4746 return (amd->start_cap != nullptr && object_moves_in_time(amd->start_cap)) ||
4747 (amd->end_cap != nullptr && object_moves_in_time(amd->end_cap)) ||
4748 (amd->curve_ob != nullptr && object_moves_in_time(amd->curve_ob)) ||
4749 (amd->offset_ob != nullptr && object_moves_in_time(amd->offset_ob));
4750 }
4751 if (md->type == eModifierType_Mirror) {
4753 return mmd->mirror_ob != nullptr &&
4755 }
4756 if (md->type == eModifierType_Screw) {
4758 return smd->ob_axis != nullptr && object_moves_in_time(smd->ob_axis);
4759 }
4761 /* NOTE: Not ideal because it's unknown whether topology changes or not.
4762 * This will be detected later, so by assuming it's only deformation
4763 * going on here we allow baking deform-only mesh to Alembic and have
4764 * proper motion blur after that.
4765 */
4766 return true;
4767 }
4768 if (md->type == eModifierType_Nodes) {
4769 /* Not ideal for performance to always assume this is animated,
4770 * but hard to detect in general. The better long term solution is likely
4771 * to replace BKE_object_is_deform_modified by a test if the object was
4772 * modified by the depsgraph when changing frames. */
4773 return true;
4774 }
4775 return false;
4776}
4777
4779{
4780 /* TODO(sergey): This is a bit code duplication with depsgraph, but
4781 * would be nicer to solve this as a part of new dependency graph
4782 * work, so we avoid conflicts and so.
4783 */
4784 if (ob->adt != nullptr) {
4785 AnimData *adt = ob->adt;
4786 if (adt->action != nullptr) {
4788 if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
4789 return true;
4790 }
4791 }
4792 }
4793 LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
4794 if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) {
4795 return true;
4796 }
4797 }
4798 }
4799 return false;
4800}
4801
4803{
4804 /* Always test on original object since evaluated object may no longer
4805 * have shape keys or modifiers that were used to evaluate it. */
4806 ob = DEG_get_original(ob);
4807
4808 ModifierData *md;
4809 VirtualModifierData virtual_modifier_data;
4810 int flag = 0;
4811 const bool is_modifier_animated = modifiers_has_animation_check(ob);
4812
4813 if (BKE_key_from_object(ob)) {
4815 }
4816
4817 if (ob->type == OB_CURVES_LEGACY) {
4818 Curve *cu = (Curve *)ob->data;
4819 if (cu->taperobj != nullptr && object_deforms_in_time(cu->taperobj)) {
4821 }
4822 }
4823
4824 /* cloth */
4825 for (md = BKE_modifiers_get_virtual_modifierlist(ob, &virtual_modifier_data);
4827 md = md->next)
4828 {
4830 bool can_deform = mti->type == ModifierTypeType::OnlyDeform || is_modifier_animated;
4831
4832 if (!can_deform) {
4833 can_deform = constructive_modifier_is_deform_modified(ob, md);
4834 }
4835
4836 if (can_deform) {
4837 if (!(flag & eModifierMode_Render) &&
4839 {
4841 }
4842
4843 if (!(flag & eModifierMode_Realtime) &&
4845 {
4847 }
4848 }
4849 }
4850
4851 return flag;
4852}
4853
4855{
4856 int num_scenes = 0;
4857 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
4858 if (BKE_collection_has_object_recursive(scene->master_collection, ob)) {
4859 num_scenes++;
4860 }
4861 }
4862 return num_scenes;
4863}
4864
4865MovieClip *BKE_object_movieclip_get(Scene *scene, const Object *ob, bool use_default)
4866{
4867 MovieClip *clip = use_default ? scene->clip : nullptr;
4868 bConstraint *con = (bConstraint *)ob->constraints.first, *scon = nullptr;
4869
4870 while (con) {
4871 if (con->type == CONSTRAINT_TYPE_CAMERASOLVER) {
4872 if (scon == nullptr || (scon->flag & CONSTRAINT_OFF)) {
4873 scon = con;
4874 }
4875 }
4876
4877 con = con->next;
4878 }
4879
4880 if (scon) {
4881 bCameraSolverConstraint *solver = (bCameraSolverConstraint *)scon->data;
4882 if ((solver->flag & CAMERASOLVER_ACTIVECLIP) == 0) {
4883 clip = solver->clip;
4884 }
4885 else {
4886 clip = scene->clip;
4887 }
4888 }
4889
4890 return clip;
4891}
4892
4894{
4895 return ELEM(ob->type,
4896 OB_MESH,
4898 OB_SURF,
4899 OB_FONT,
4900 OB_MBALL,
4901 OB_CURVES,
4903 OB_VOLUME,
4905}
4906
4908
4909/* -------------------------------------------------------------------- */
4912
4914{
4915 *object->runtime = {};
4916}
4917
4918void BKE_object_runtime_reset_on_copy(Object *object, const int /*flag*/)
4919{
4920 blender::bke::ObjectRuntime *runtime = object->runtime;
4921 runtime->data_eval = nullptr;
4922 runtime->mesh_deform_eval = nullptr;
4923 runtime->curve_cache = nullptr;
4924 runtime->object_as_temp_mesh = nullptr;
4925 runtime->pose_backup = nullptr;
4926 runtime->object_as_temp_curve = nullptr;
4927 runtime->geometry_set_eval = nullptr;
4928
4929 runtime->crazyspace_deform_imats = {};
4930 runtime->crazyspace_deform_cos = {};
4931}
4932
4934{
4935 /* Currently this is all that's needed. */
4937
4939}
4940
4942
4943/* -------------------------------------------------------------------- */
4946
4951{
4952 Object *ob_arm = nullptr;
4953
4954 if (ob->parent && ob->partype == PARSKEL && ob->parent->type == OB_ARMATURE) {
4955 ob_arm = ob->parent;
4956 }
4957 else {
4959 if (mod->type == eModifierType_Armature) {
4960 ob_arm = ((ArmatureModifierData *)mod)->object;
4961 }
4962 }
4963 }
4964
4965 return ob_arm;
4966}
4967
4968static bool obrel_list_test(Object *ob)
4969{
4970 return ob && !(ob->id.tag & ID_TAG_DOIT);
4971}
4972
4973static void obrel_list_add(LinkNode **links, Object *ob)
4974{
4975 BLI_linklist_prepend(links, ob);
4976 ob->id.tag |= ID_TAG_DOIT;
4977}
4978
4980 ViewLayer *view_layer,
4981 eObjectSet objectSet,
4982 eObRelationTypes includeFilter)
4983{
4984 LinkNode *links = nullptr;
4985
4986 /* Remove markers from all objects */
4987 BKE_view_layer_synced_ensure(scene, view_layer);
4989 base->object->id.tag &= ~ID_TAG_DOIT;
4990 }
4991
4992 /* iterate over all selected and visible objects */
4994 if (objectSet == OB_SET_ALL) {
4995 /* as we get all anyways just add it */
4996 Object *ob = base->object;
4997 obrel_list_add(&links, ob);
4998 }
4999 else {
5000 if ((objectSet == OB_SET_SELECTED && BASE_SELECTED_EDITABLE(((View3D *)nullptr), base)) ||
5001 (objectSet == OB_SET_VISIBLE && BASE_EDITABLE(((View3D *)nullptr), base)))
5002 {
5003 Object *ob = base->object;
5004
5005 if (obrel_list_test(ob)) {
5006 obrel_list_add(&links, ob);
5007 }
5008
5009 /* parent relationship */
5010 if (includeFilter & (OB_REL_PARENT | OB_REL_PARENT_RECURSIVE)) {
5011 Object *parent = ob->parent;
5012 if (obrel_list_test(parent)) {
5013
5014 obrel_list_add(&links, parent);
5015
5016 /* recursive parent relationship */
5017 if (includeFilter & OB_REL_PARENT_RECURSIVE) {
5018 parent = parent->parent;
5019 while (obrel_list_test(parent)) {
5020
5021 obrel_list_add(&links, parent);
5022 parent = parent->parent;
5023 }
5024 }
5025 }
5026 }
5027
5028 /* child relationship */
5029 if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
5030 LISTBASE_FOREACH (Base *, local_base, BKE_view_layer_object_bases_get(view_layer)) {
5031 if (BASE_EDITABLE(((View3D *)nullptr), local_base)) {
5032
5033 Object *child = local_base->object;
5034 if (obrel_list_test(child)) {
5035 if ((includeFilter & OB_REL_CHILDREN_RECURSIVE &&
5036 BKE_object_is_child_recursive(ob, child)) ||
5037 (includeFilter & OB_REL_CHILDREN && child->parent && child->parent == ob))
5038 {
5039 obrel_list_add(&links, child);
5040 }
5041 }
5042 }
5043 }
5044 }
5045
5046 /* include related armatures */
5047 if (includeFilter & OB_REL_MOD_ARMATURE) {
5048 Object *arm = obrel_armature_find(ob);
5049 if (obrel_list_test(arm)) {
5050 obrel_list_add(&links, arm);
5051 }
5052 }
5053 }
5054 }
5055 }
5056
5057 return links;
5058}
5059
5061{
5062 LinkNode *collection_linknode = nullptr;
5063 Collection *collection = nullptr;
5064 while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
5065 BLI_linklist_prepend(&collection_linknode, collection);
5066 }
5067
5068 return collection_linknode;
5069}
5070
5071void BKE_object_groups_clear(Main *bmain, Scene *scene, Object *ob)
5072{
5073 Collection *collection = nullptr;
5074 while ((collection = BKE_collection_object_find(bmain, scene, collection, ob))) {
5075 BKE_collection_object_remove(bmain, collection, ob, false);
5077 }
5078}
5079
5081
5082/* -------------------------------------------------------------------- */
5085
5086KDTree_3d *BKE_object_as_kdtree(Object *ob, int *r_tot)
5087{
5088 KDTree_3d *tree = nullptr;
5089 uint tot = 0;
5090
5091 switch (ob->type) {
5092 case OB_MESH: {
5093 Mesh *mesh = (Mesh *)ob->data;
5094 uint i;
5095
5096 const Mesh *mesh_eval = BKE_object_get_mesh_deform_eval(ob) ?
5099 const int *index;
5100
5101 if (mesh_eval &&
5102 (index = (const int *)CustomData_get_layer(&mesh_eval->vert_data, CD_ORIGINDEX)))
5103 {
5104 const Span<float3> positions = mesh->vert_positions();
5105
5106 /* Tree over-allocates in case where some verts have #ORIGINDEX_NONE. */
5107 tot = 0;
5108 tree = BLI_kdtree_3d_new(positions.size());
5109
5110 /* We don't how many verts from the DM we can use. */
5111 for (i = 0; i < positions.size(); i++) {
5112 if (index[i] != ORIGINDEX_NONE) {
5113 float co[3];
5114 mul_v3_m4v3(co, ob->object_to_world().ptr(), positions[i]);
5115 BLI_kdtree_3d_insert(tree, index[i], co);
5116 tot++;
5117 }
5118 }
5119 }
5120 else {
5121 const Span<float3> positions = mesh->vert_positions();
5122
5123 tot = positions.size();
5124 tree = BLI_kdtree_3d_new(tot);
5125
5126 for (i = 0; i < tot; i++) {
5127 float co[3];
5128 mul_v3_m4v3(co, ob->object_to_world().ptr(), positions[i]);
5129 BLI_kdtree_3d_insert(tree, i, co);
5130 }
5131 }
5132
5133 BLI_kdtree_3d_balance(tree);
5134 break;
5135 }
5136 case OB_CURVES_LEGACY:
5137 case OB_SURF: {
5138 /* TODO: take deformation into account */
5139 Curve *cu = (Curve *)ob->data;
5140 uint i, a;
5141
5142 Nurb *nu;
5143
5145 tree = BLI_kdtree_3d_new(tot);
5146 i = 0;
5147
5148 nu = (Nurb *)cu->nurb.first;
5149 while (nu) {
5150 if (nu->bezt) {
5151 BezTriple *bezt;
5152
5153 bezt = nu->bezt;
5154 a = nu->pntsu;
5155 while (a--) {
5156 float co[3];
5157 mul_v3_m4v3(co, ob->object_to_world().ptr(), bezt->vec[1]);
5158 BLI_kdtree_3d_insert(tree, i++, co);
5159 bezt++;
5160 }
5161 }
5162 else {
5163 BPoint *bp;
5164
5165 bp = nu->bp;
5166 a = nu->pntsu * nu->pntsv;
5167 while (a--) {
5168 float co[3];
5169 mul_v3_m4v3(co, ob->object_to_world().ptr(), bp->vec);
5170 BLI_kdtree_3d_insert(tree, i++, co);
5171 bp++;
5172 }
5173 }
5174 nu = nu->next;
5175 }
5176
5177 BLI_kdtree_3d_balance(tree);
5178 break;
5179 }
5180 case OB_LATTICE: {
5181 /* TODO: take deformation into account */
5182 Lattice *lt = (Lattice *)ob->data;
5183 BPoint *bp;
5184 uint i;
5185
5186 tot = lt->pntsu * lt->pntsv * lt->pntsw;
5187 tree = BLI_kdtree_3d_new(tot);
5188 i = 0;
5189
5190 for (bp = lt->def; i < tot; bp++) {
5191 float co[3];
5192 mul_v3_m4v3(co, ob->object_to_world().ptr(), bp->vec);
5193 BLI_kdtree_3d_insert(tree, i++, co);
5194 }
5195
5196 BLI_kdtree_3d_balance(tree);
5197 break;
5198 }
5199 }
5200
5201 *r_tot = tot;
5202 return tree;
5203}
5204
5206
5207/* -------------------------------------------------------------------- */
5210
5215{
5216 ListBase pidlist;
5217 BKE_ptcache_ids_from_object(&pidlist, ob, nullptr, 0);
5218
5219 LISTBASE_FOREACH (PTCacheID *, pid, &pidlist) {
5220 if (pid->cache) {
5221 if (state) {
5222 pid->cache->flag |= PTCACHE_IGNORE_CLEAR;
5223 }
5224 else {
5225 pid->cache->flag &= ~PTCACHE_IGNORE_CLEAR;
5226 }
5227 }
5228 }
5229
5230 BLI_freelistN(&pidlist);
5231}
5232
5239
5249 Object *ob,
5250 const bool update_mesh,
5251 const int parent_recursion_limit)
5252{
5253 /* NOTE: this function must not modify the object
5254 * since this is used for setting up depsgraph relationships.
5255 *
5256 * Although the #ObjectModifierUpdateContext::update_or_tag_fn callback may change the object
5257 * as this is needed to implement #BKE_object_modifier_update_subframe. */
5258
5259 /* NOTE(@ideasman42): `parent_recursion_limit` is used to prevent this function attempting to
5260 * scan object hierarchies infinitely, needed since constraint targets are also included.
5261 * A more elegant alternative may be to track which objects have been handled.
5262 * Since #BKE_object_modifier_update_subframe is documented not to be used
5263 * for new code (if possible), leave as-is. */
5264
5266
5269
5270 /* if other is dynamic paint canvas, don't update */
5271 if (pmd && pmd->canvas) {
5272 return true;
5273 }
5274 }
5275 else if (ctx.modifier_type == eModifierType_Fluid) {
5277
5278 if (fmd && (fmd->type & MOD_FLUID_TYPE_DOMAIN) != 0) {
5279 return true;
5280 }
5281 }
5282
5283 /* if object has parents, update them too */
5284 if (parent_recursion_limit) {
5285 const int recursion = parent_recursion_limit - 1;
5286 bool no_update = false;
5287 if (ob->parent) {
5288 no_update |= object_modifier_recurse_for_update_subframe(ctx, ob->parent, false, recursion);
5289 }
5290 if (ob->track) {
5291 no_update |= object_modifier_recurse_for_update_subframe(ctx, ob->track, false, recursion);
5292 }
5293
5294 /* Skip sub-frame if object is parented to vertex of a dynamic paint canvas. */
5295 if (no_update && ELEM(ob->partype, PARVERT1, PARVERT3)) {
5296 return false;
5297 }
5298
5299 /* also update constraint targets */
5301 ListBase targets = {nullptr, nullptr};
5302
5303 if (BKE_constraint_targets_get(con, &targets)) {
5304 LISTBASE_FOREACH (bConstraintTarget *, ct, &targets) {
5305 if (ct->tar) {
5306 object_modifier_recurse_for_update_subframe(ctx, ct->tar, false, recursion);
5307 }
5308 }
5309 /* free temp targets */
5310 BKE_constraint_targets_flush(con, &targets, false);
5311 }
5312 }
5313 }
5314
5315 ctx.update_or_tag_fn(ob, update_mesh);
5316
5317 return false;
5318}
5319
5321 Object *ob,
5322 const bool update_mesh,
5323 const int parent_recursion_limit,
5324 const /*ModifierType*/ int modifier_type,
5325 blender::FunctionRef<void(Object *object, bool update_mesh)> update_or_tag_fn)
5326{
5328 ModifierType(modifier_type),
5329 update_or_tag_fn,
5330 };
5331 object_modifier_recurse_for_update_subframe(ctx, ob, update_mesh, parent_recursion_limit);
5332}
5333
5335 Scene *scene,
5336 Object *ob,
5337 const bool update_mesh,
5338 const int parent_recursion_limit,
5339 const float frame,
5340 const /*ModifierType*/ int modifier_type)
5341{
5342 const bool flush_to_original = DEG_is_active(depsgraph);
5343
5344 auto update_or_tag_fn = [depsgraph, scene, frame, flush_to_original](Object *ob,
5345 const bool update_mesh) {
5346 /* NOTE: changes here may require updates to #DEG_add_collision_relations
5347 * so the depsgraph is handling updates correctly. */
5348
5349 /* was originally ID_RECALC_ALL - TODO: which flags are really needed??? */
5350 /* TODO(sergey): What about animation? */
5352 frame);
5353
5354 ob->id.recalc |= ID_RECALC_ALL;
5355 if (update_mesh) {
5357 &ob->id, ob->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
5358 /* Ignore cache clear during sub-frame updates to not mess up cache validity. */
5359 object_cacheIgnoreClear(ob, true);
5361 object_cacheIgnoreClear(ob, false);
5362 }
5363 else {
5364 BKE_object_where_is_calc_time(depsgraph, scene, ob, frame);
5365 }
5366
5367 /* for curve following objects, parented curve has to be updated too */
5368 if (ob->type == OB_CURVES_LEGACY) {
5369 Curve *cu = (Curve *)ob->data;
5371 &cu->id, cu->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
5372 }
5373 /* and armatures... */
5374 if (ob->type == OB_ARMATURE) {
5375 bArmature *arm = (bArmature *)ob->data;
5377 &arm->id, arm->adt, &anim_eval_context, ADT_RECALC_ANIM, flush_to_original);
5378 BKE_pose_where_is(depsgraph, scene, ob);
5379 }
5380 };
5381
5383 ob, update_mesh, parent_recursion_limit, modifier_type, update_or_tag_fn);
5384}
5385
5387{
5388 Object *ob = (Object *)bmain->objects.first;
5389 int select_id = 1;
5390 while (ob) {
5391 ob->runtime->select_id = select_id++;
5392 ob = (Object *)ob->id.next;
5393 }
5394}
5395
5397
5398/* -------------------------------------------------------------------- */
5401
5402Mesh *BKE_object_to_mesh(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
5403{
5405
5406 Mesh *mesh = BKE_mesh_new_from_object(depsgraph, object, preserve_all_data_layers, false, true);
5407 object->runtime->object_as_temp_mesh = mesh;
5408 return mesh;
5409}
5410
5412{
5413 if (object->runtime->object_as_temp_mesh == nullptr) {
5414 return;
5415 }
5416 BKE_id_free(nullptr, object->runtime->object_as_temp_mesh);
5417 object->runtime->object_as_temp_mesh = nullptr;
5418}
5419
5420Curve *BKE_object_to_curve(Object *object, Depsgraph *depsgraph, bool apply_modifiers)
5421{
5423
5424 Curve *curve = BKE_curve_new_from_object(object, depsgraph, apply_modifiers);
5425 object->runtime->object_as_temp_curve = curve;
5426 return curve;
5427}
5428
5430{
5431 if (object->runtime->object_as_temp_curve == nullptr) {
5432 return;
5433 }
5434 BKE_id_free(nullptr, object->runtime->object_as_temp_curve);
5435 object->runtime->object_as_temp_curve = nullptr;
5436}
5437
5442
5444{
5445 ModifierData *md = (ModifierData *)(ob->modifiers.last);
5446
5447 while (md) {
5448 if (md->type == eModifierType_Subsurf) {
5449 break;
5450 }
5451
5452 md = md->prev;
5453 }
5454
5455 return (SubsurfModifierData *)(md);
5456}
5457
5459{
5460 ob->type = BKE_object_obdata_to_type(new_data);
5461 ob->data = (void *)new_data;
5462 ob->runtime->geometry_set_eval = nullptr;
5463 ob->runtime->data_eval = new_data;
5464 ob->runtime->bounds_eval.reset();
5465 ob->id.py_instance = nullptr;
5466}
5467
5469
5470const blender::float4x4 &Object::object_to_world() const
5471{
5472 return this->runtime->object_to_world;
5473}
5474const blender::float4x4 &Object::world_to_object() const
5475{
5476 return this->runtime->world_to_object;
5477}
Functions for backward compatibility with the legacy Action API.
Blender kernel action and pose functionality.
void void void void BKE_pose_blend_read_after_liblink(BlendLibReader *reader, Object *ob, bPose *pose) ATTR_NONNULL(1
void BKE_pose_tag_recalc(Main *bmain, bPose *pose) ATTR_NONNULL(1
void void void BKE_pose_blend_read_data(BlendDataReader *reader, ID *id_owner, bPose *pose) ATTR_NONNULL(1
void BKE_pose_free_ex(bPose *pose, bool do_id_user)
void BKE_pose_update_constraint_flags(bPose *pose) ATTR_NONNULL(1)
void BKE_pose_channels_hash_ensure(bPose *pose) ATTR_NONNULL(1)
bPoseChannel * BKE_pose_channel_find_name(const bPose *pose, const char *name)
void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, int flag, bool copy_constraints)
void BKE_pose_check_uids_unique_and_report(const bPose *pose)
void void BKE_pose_blend_write(BlendWriter *writer, bPose *pose, bArmature *arm) ATTR_NONNULL(1
bool BKE_animdata_id_is_animated(const ID *id)
Definition anim_data.cc:237
bool BKE_where_on_path(const struct Object *ob, float ctime, float r_vec[4], float r_dir[3], float r_quat[4], float *r_radius, float *r_weight)
void animviz_free_motionpath(struct bMotionPath *mpath)
void animviz_motionpath_blend_write(struct BlendWriter *writer, struct bMotionPath *mpath)
void animviz_motionpath_blend_read_data(struct BlendDataReader *reader, struct bMotionPath *mpath)
void animviz_settings_init(struct bAnimVizSettings *avs)
struct bMotionPath * animviz_copy_motionpath(const struct bMotionPath *mpath_src)
AnimationEvalContext BKE_animsys_eval_context_construct(struct Depsgraph *depsgraph, float eval_time) ATTR_WARN_UNUSED_RESULT
Definition anim_sys.cc:735
@ ADT_RECALC_ANIM
@ ADT_RECALC_ALL
void BKE_animsys_evaluate_animdata(struct ID *id, struct AnimData *adt, const struct AnimationEvalContext *anim_eval_context, eAnimData_Recalc recalc, bool flush_to_original)
bool BKE_animdata_drivers_remove_for_rna_struct(struct ID &owner_id, struct StructRNA &type, void *data)
void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, bool do_id_user)
Definition armature.cc:2877
void BKE_pose_where_is(Depsgraph *depsgraph, Scene *scene, Object *ob)
Definition armature.cc:3051
std::optional< blender::Bounds< blender::float3 > > BKE_armature_min_max(const Object *ob)
Definition armature.cc:3134
bArmature * BKE_armature_add(Main *bmain, const char *name)
Definition armature.cc:538
void BKE_asset_metadata_idprop_ensure(AssetMetaData *asset_data, IDProperty *prop)
Definition asset.cc:168
bool BKE_bpath_foreach_path_fixed_process(BPathForeachPathData *bpath_data, char *path, size_t path_maxncpy)
Definition bpath.cc:125
Camera data-block and utility functions.
struct Camera * BKE_camera_add(struct Main *bmain, const char *name)
bool BKE_collection_object_remove(Main *bmain, Collection *collection, Object *ob, bool free_us)
bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
bool BKE_collection_viewlayer_object_add(Main *bmain, const ViewLayer *view_layer, Collection *collection, Object *ob)
Collection * BKE_collection_object_find(Main *bmain, Scene *scene, Collection *collection, Object *ob)
void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
void BKE_constraints_free_ex(struct ListBase *list, bool do_id_user)
void BKE_constraints_solve(struct Depsgraph *depsgraph, struct ListBase *conlist, struct bConstraintOb *cob, float ctime)
void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targets, bool no_copy)
void BKE_constraint_blend_write(struct BlendWriter *writer, struct ListBase *conlist)
int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targets)
void BKE_constraint_blend_read_data(struct BlendDataReader *reader, struct ID *id_owner, struct ListBase *lb)
void BKE_constraints_copy_ex(struct ListBase *dst, const struct ListBase *src, int flag, bool do_extern)
void BKE_constraints_clear_evalob(struct bConstraintOb *cob)
void BKE_constraints_id_loop(struct ListBase *list, ConstraintIDFunc func, const int flag, void *userdata)
struct bConstraintOb * BKE_constraints_make_evalob(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, void *subdata, short datatype)
void BKE_crazyspace_api_eval_clear(Object *object)
void BKE_curve_texspace_ensure(Curve *cu)
Definition curve.cc:506
void BKE_curve_bevelList_free(ListBase *bev)
Definition curve.cc:2520
ListBase * BKE_curve_nurbs_get(Curve *cu)
Definition curve.cc:4962
Curve * BKE_curve_new_from_object(Object *object, Depsgraph *depsgraph, bool apply_modifiers)
std::optional< blender::Bounds< blender::float3 > > BKE_curve_minmax(const Curve *cu, bool use_radius)
Definition curve.cc:5101
void BKE_nurbList_free(ListBase *lb)
Definition curve.cc:601
Curve * BKE_curve_add(Main *bmain, const char *name, int type)
Definition curve.cc:411
int BKE_nurbList_verts_count_without_handles(const ListBase *nurb)
Definition curve.cc:557
bool BKE_nurbList_index_get_co(ListBase *nurb, int index, float r_co[3])
Definition curve.cc:515
void BKE_curve_type_test(Object *ob, bool dimension_update)
Definition curve.cc:458
struct Curves * BKE_curves_add(struct Main *bmain, const char *name)
Low-level operations for curves.
const void * CustomData_get_layer(const CustomData *data, eCustomDataType type)
@ CD_SET_DEFAULT
bool CustomData_free_layer(CustomData *data, eCustomDataType type, int index)
int CustomData_get_layer_index(const CustomData *data, eCustomDataType type)
void CustomData_copy_layer_type_data(const CustomData *source, CustomData *destination, eCustomDataType type, int source_index, int destination_index, int count)
#define ORIGINDEX_NONE
bool CustomData_has_layer(const CustomData *data, eCustomDataType type)
void * CustomData_add_layer(CustomData *data, eCustomDataType type, eCDAllocType alloctype, int totelem)
support for deformation groups and hooks.
display list (or rather multi purpose list) stuff.
void BKE_displist_free(struct ListBase *lb)
Definition displist.cc:64
@ DL_VERTS
DispList * BKE_displist_find(struct ListBase *lb, int type)
Definition displist.cc:71
void BKE_displist_minmax(const struct ListBase *dispbase, float min[3], float max[3])
void free_object_duplilist(ListBase *lb)
ListBase * object_duplilist(Depsgraph *depsgraph, Scene *sce, Object *ob, blender::Set< const Object * > *include_objects=nullptr)
void BKE_partdeflect_free(struct PartDeflect *pd)
Definition effect.cc:119
struct EffectorWeights * BKE_effector_add_weights(struct Collection *collection)
Definition effect.cc:58
@ G_DEBUG_DEPSGRAPH_EVAL
void BKE_gpencil_modifier_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb, struct Object *ob)
void BKE_gpencil_modifiers_foreach_ID_link(struct Object *ob, GreasePencilIDWalkFunc walk, void *user_data)
void BKE_gpencil_modifier_free_ex(struct GpencilModifierData *md, int flag)
Low-level operations for grease pencil.
GreasePencil * BKE_grease_pencil_add(Main *bmain, const char *name)
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
void(*)(ID *id, const IDCacheKey *cache_key, void **cache_p, uint flags, void *user_data) IDTypeForeachCacheFunctionCallback
IDTypeInfo IDType_ID_OB
void BKE_keyblock_convert_to_lattice(const KeyBlock *kb, Lattice *lt)
Definition key.cc:2035
Key * BKE_key_add(Main *bmain, ID *id)
Definition key.cc:258
void BKE_keyblock_convert_to_mesh(const KeyBlock *kb, blender::MutableSpan< blender::float3 > vert_positions)
Definition key.cc:2219
void BKE_keyblock_convert_from_mesh(const Mesh *mesh, const Key *key, KeyBlock *kb)
Definition key.cc:2203
void BKE_keyblock_convert_from_curve(const Curve *cu, KeyBlock *kb, const ListBase *nurb)
Definition key.cc:2134
KeyBlock * BKE_keyblock_add_ctime(Key *key, const char *name, bool do_force)
Definition key.cc:1895
void BKE_keyblock_convert_from_lattice(const Lattice *lt, KeyBlock *kb)
Definition key.cc:2009
float * BKE_key_evaluate_object(Object *ob, int *r_totelem)
Definition key.cc:1644
void BKE_keyblock_convert_to_curve(KeyBlock *kb, Curve *cu, ListBase *nurb)
Definition key.cc:2180
Key ** BKE_key_from_object_p(Object *ob)
Definition key.cc:1815
Key * BKE_key_from_object(Object *ob)
Definition key.cc:1824
void BKE_lattice_transform(Lattice *lt, const float mat[4][4], bool do_keys)
Definition lattice.cc:636
std::optional< blender::Bounds< blender::float3 > > BKE_lattice_minmax(const Lattice *lt)
Definition lattice.cc:616
Lattice * BKE_lattice_add(Main *bmain, const char *name)
Definition lattice.cc:392
LayerCollection * BKE_layer_collection_get_active(ViewLayer *view_layer)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
void BKE_view_layer_base_deselect_all(const Scene *scene, ViewLayer *view_layer)
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_mode_params(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, const ObjectsInModeParams *params)
Base * BKE_view_layer_active_base_get(ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
void BKE_view_layer_base_select_and_set_active(ViewLayer *view_layer, Base *selbase)
blender::Vector< Base * > BKE_view_layer_array_from_bases_in_mode_params(const Scene *scene, ViewLayer *view_layer, const View3D *v3d, const ObjectsInModeParams *params)
ID * BKE_id_copy_for_duplicate(Main *bmain, ID *id, eDupli_ID_Flags duplicate_flags, int copy_flags)
Definition lib_id.cc:777
void BKE_id_free_us(Main *bmain, void *idv) ATTR_NONNULL()
void BKE_libblock_free_datablock(ID *id, int flag) ATTR_NONNULL()
void * BKE_libblock_alloc(Main *bmain, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1428
void BKE_id_free(Main *bmain, void *idv)
void id_us_plus(ID *id)
Definition lib_id.cc:353
@ LIB_ID_COPY_NO_PREVIEW
@ LIB_ID_COPY_CACHES
@ LIB_ID_COPY_SET_COPIED_ON_WRITE
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_CREATE_NO_MAIN
@ LIB_ID_COPY_DEFAULT
@ LIB_ID_COPY_RIGID_BODY_NO_COLLECTION_HANDLING
void BKE_libblock_free_data(ID *id, bool do_id_user) ATTR_NONNULL()
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:1981
void id_us_min(ID *id)
Definition lib_id.cc:361
@ LIB_ID_DUPLICATE_IS_ROOT_ID
@ LIB_ID_DUPLICATE_IS_SUBPROCESS
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2611
#define BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(data_, func_call_)
void BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, LibraryForeachIDCallbackFlag cb_flag)
Definition lib_query.cc:78
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
LibraryForeachIDCallbackFlag
@ IDWALK_CB_NEVER_SELF
@ IDWALK_CB_USER
@ IDWALK_CB_OVERRIDE_LIBRARY_HIERARCHY_DEFAULT
@ IDWALK_CB_NEVER_NULL
@ IDWALK_CB_NOP
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:129
@ IDWALK_DO_DEPRECATED_POINTERS
#define BKE_LIB_FOREACHID_PROCESS_ID_NOCHECK(data_, id_, cb_flag_)
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL()
Definition lib_remap.cc:919
@ ID_REMAP_FORCE_OBDATA_IN_EDITMODE
General operations, lookup, etc. for blender lights.
Light * BKE_light_add(Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT
General operations for probes.
void BKE_lightprobe_cache_free(struct Object *object)
void BKE_lightprobe_cache_blend_read(struct BlendDataReader *reader, struct LightProbeObjectCache *cache)
void BKE_lightprobe_cache_blend_write(struct BlendWriter *writer, struct LightProbeObjectCache *cache)
struct LightProbe * BKE_lightprobe_add(struct Main *bmain, const char *name)
LightProbeObjectCache * BKE_lightprobe_cache_copy(LightProbeObjectCache *src_cache)
Blender kernel freestyle line style functionality.
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:563
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:557
General operations, lookup, etc. for materials.
void BKE_object_materials_sync_length(Main *bmain, Object *ob, ID *id)
Material *** BKE_object_material_array_p(Object *ob)
MetaBall * BKE_mball_add(Main *bmain, const char *name)
Definition mball.cc:178
void BKE_mesh_ensure_skin_customdata(Mesh *mesh)
Mesh * BKE_mesh_add(Main *bmain, const char *name)
Mesh * BKE_mesh_new_from_object(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers, bool preserve_origindex, bool ensure_subdivision)
void BKE_mesh_texspace_get_reference(Mesh *mesh, char **r_texspace_flag, float **r_texspace_location, float **r_texspace_size)
@ ME_WRAPPER_TYPE_BMESH
blender::Span< blender::float3 > BKE_mesh_wrapper_vert_coords(const Mesh *mesh)
Mesh * BKE_mesh_wrapper_ensure_subdivision(Mesh *mesh)
void BKE_modifier_blend_write(BlendWriter *writer, const ID *id_owner, ListBase *modbase)
bool BKE_modifier_is_enabled(const Scene *scene, ModifierData *md, int required_mode)
void BKE_modifier_copydata_ex(const ModifierData *md, ModifierData *target, int flag)
ModifierData * BKE_modifiers_findby_type(const Object *ob, ModifierType type)
const ModifierTypeInfo * BKE_modifier_get_info(ModifierType type)
void BKE_modifiers_persistent_uid_init(const Object &object, ModifierData &md)
@ eModifierTypeFlag_Single
@ eModifierTypeFlag_AcceptsCVs
@ eModifierTypeFlag_AcceptsGreasePencil
@ eModifierTypeFlag_AcceptsVertexCosOnly
@ eModifierTypeFlag_AcceptsMesh
void BKE_modifier_blend_read_data(BlendDataReader *reader, ListBase *lb, Object *ob)
void void void BKE_modifiers_foreach_ID_link(Object *ob, IDWalkFunc walk, void *user_data)
ModifierData * BKE_modifier_copy_ex(const ModifierData *md, int flag)
void BKE_modifier_unique_name(ListBase *modifiers, ModifierData *md)
bool BKE_modifiers_persistent_uids_are_valid(const Object &object)
void BKE_modifier_free_ex(ModifierData *md, int flag)
ModifierData * BKE_modifiers_get_virtual_modifierlist(const Object *ob, VirtualModifierData *data)
ModifierData * BKE_modifier_new(int type)
Object * BKE_modifiers_is_deformed_by_armature(Object *ob)
void BKE_modifier_copydata(const ModifierData *md, ModifierData *target)
void multiresModifier_sync_levels_ex(Object *ob_dst, const MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst)
Definition multires.cc:1317
bool multiresModifier_reshapeFromCCG(int tot_level, Mesh *coarse_mesh, SubdivCCG *subdiv_ccg)
General operations, lookup, etc. for blender objects.
eObRelationTypes
@ OB_REL_MOD_ARMATURE
@ OB_REL_PARENT
@ OB_REL_CHILDREN_RECURSIVE
@ OB_REL_PARENT_RECURSIVE
@ OB_REL_CHILDREN
bool BKE_object_is_in_editmode(const Object *ob)
@ OB_VISIBLE_INSTANCES
@ OB_VISIBLE_SELF
@ OB_VISIBLE_PARTICLES
eObjectSet
@ OB_SET_SELECTED
@ OB_SET_VISIBLE
@ OB_SET_ALL
void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_sculptsession_free(Object *ob)
Definition paint.cc:2192
void BKE_particle_system_blend_read_data(struct BlendDataReader *reader, struct ListBase *particles)
Definition particle.cc:5344
void BKE_particle_system_blend_read_after_liblink(struct BlendLibReader *reader, struct Object *ob, struct ID *id, struct ListBase *particles)
Definition particle.cc:5432
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit)
Definition particle.cc:906
void BKE_particle_partdeflect_blend_read_data(struct BlendDataReader *reader, struct PartDeflect *pd)
Definition particle.cc:318
void BKE_particle_system_blend_write(struct BlendWriter *writer, struct ListBase *particles)
Definition particle.cc:5299
void psys_free(struct Object *ob, struct ParticleSystem *psys)
Definition particle.cc:977
struct ModifierData * object_copy_particle_system(struct Main *bmain, const struct Scene *scene, struct Object *ob, const struct ParticleSystem *psys_orig)
void BKE_particlesystem_id_loop(struct ParticleSystem *psys, ParticleSystemIDFunc func, void *userdata)
void psys_copy_particles(struct ParticleSystem *psys_dst, struct ParticleSystem *psys_src)
Definition particle.cc:1055
void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis)
struct PointCache * BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const struct ListBase *ptcaches_old, int flag)
void BKE_ptcache_blend_read_data(struct BlendDataReader *reader, struct ListBase *ptcaches, struct PointCache **ocache, int force_disk)
void BKE_ptcache_blend_write(struct BlendWriter *writer, struct ListBase *ptcaches)
General operations for point clouds.
PointCloud * BKE_pointcloud_add(Main *bmain, const char *name)
void BKE_pose_backup_clear(struct Object *ob)
void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv)
void BKE_previewimg_free(PreviewImage **prv)
void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
API for Blender-side Rigid Body stuff.
void BKE_rigidbody_free_constraint(struct Object *ob)
Definition rigidbody.cc:215
void BKE_rigidbody_free_object(struct Object *ob, struct RigidBodyWorld *rbw)
Definition rigidbody.cc:164
void BKE_rigidbody_object_copy(struct Main *bmain, struct Object *ob_dst, const struct Object *ob_src, int flag)
void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime)
void BKE_shaderfx_foreach_ID_link(struct Object *ob, ShaderFxIDWalkFunc walk, void *user_data)
Definition shader_fx.cc:240
void BKE_shaderfx_free_ex(struct ShaderFxData *fx, int flag)
Definition shader_fx.cc:90
void BKE_shaderfx_blend_write(struct BlendWriter *writer, struct ListBase *fxbase)
Definition shader_fx.cc:259
struct ShaderFxData * BKE_shaderfx_new(int type)
Definition shader_fx.cc:54
void BKE_shaderfx_blend_read_data(struct BlendDataReader *reader, struct ListBase *lb, struct Object *ob)
Definition shader_fx.cc:275
void BKE_shaderfx_copydata_ex(struct ShaderFxData *fx, struct ShaderFxData *target, int flag)
Definition shader_fx.cc:186
void sbFree(struct Object *ob)
Definition softbody.cc:3162
General operations for speakers.
struct Speaker * BKE_speaker_add(struct Main *bmain, const char *name)
Definition speaker.cc:81
Volume data-block.
Volume * BKE_volume_add(Main *bmain, const char *name)
std::optional< blender::Bounds< blender::float3 > > BKE_volume_min_max(const Volume *volume)
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
A KD-tree for nearest neighbor search.
int BLI_findindex(const ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:586
void * BLI_findlink(const ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:534
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
#define LISTBASE_FOREACH_BACKWARD(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void BLI_addhead(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:91
void void BLI_listbase_sort(ListBase *listbase, int(*cmp)(const void *, const void *)) ATTR_NONNULL(1
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
void * BLI_pophead(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:252
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:371
#define BLI_ASSERT_UNIT_M3(m)
void mul_m4_m4m4(float R[4][4], const float A[4][4], const float B[4][4])
void size_to_mat3(float R[3][3], const float size[3])
void copy_m3_m3(float m1[3][3], const float m2[3][3])
void copy_m3_m4(float m1[3][3], const float m2[4][4])
void copy_m4_m3(float m1[4][4], const float m2[3][3])
void mat4_to_loc_rot_size(float loc[3], float rot[3][3], float size[3], const float wmat[4][4])
void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize)
void scale_m4_fl(float R[4][4], float scale)
void copy_m4_m4(float m1[4][4], const float m2[4][4])
void mul_v3_m4v3(float r[3], const float mat[4][4], const float vec[3])
bool is_negative_m4(const float mat[4][4])
bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
bool invert_m4(float mat[4][4])
void mul_m3_m3m3(float R[3][3], const float A[3][3], const float B[3][3])
void mul_m4_m4_post(float R[4][4], const float B[4][4])
void unit_m4(float m[4][4])
void quat_to_compatible_eulO(float eul[3], const float oldrot[3], short order, const float quat[4])
float tri_to_quat(float q[4], const float a[3], const float b[3], const float c[3])
void invert_qt_normalized(float q[4])
void axis_angle_to_quat(float r[4], const float axis[3], float angle)
void quat_to_mat3(float m[3][3], const float q[4])
void quat_to_eulO(float e[3], short order, const float q[4])
float normalize_qt(float q[4])
void quat_to_mat4(float m[4][4], const float q[4])
void eulO_to_quat(float q[4], const float e[3], short order)
float normalize_qt_qt(float r[4], const float q[4])
void mul_qt_qtqt(float q[4], const float a[4], const float b[4])
void quat_to_axis_angle(float axis[3], float *angle, const float q[4])
void quat_apply_track(float quat[4], short axis, short upflag)
void eulO_to_mat3(float M[3][3], const float e[3], short order)
void copy_qt_qt(float q[4], const float a[4])
void axis_angle_to_mat3(float R[3][3], const float axis[3], float angle)
void mat3_normalized_to_quat(float q[4], const float mat[3][3])
MINLINE void copy_v4_v4(float r[4], const float a[4])
MINLINE float len_squared_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_fl(float r[3], float f)
MINLINE void copy_v3_v3(float r[3], const float a[3])
void project_plane_v3_v3v3(float out[3], const float p[3], const float v_plane[3])
MINLINE float dot_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void mul_v3_v3v3(float r[3], const float v1[3], const float v2[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE bool is_zero_v3(const float v[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void zero_v2(float r[2])
MINLINE void zero_v3(float r[3])
MINLINE void add_v3_v3(float r[3], const float a[3])
void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
unsigned int uint
#define CLAMP(a, b, c)
#define CLAMP_MAX(a, c)
#define ARRAY_SIZE(arr)
#define POINTER_FROM_INT(i)
#define POINTER_AS_INT(i)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
#define STREQ(a, b)
#define CLAMP_MIN(a, b)
Main * BLO_read_lib_get_main(BlendLibReader *reader)
Definition readfile.cc:5510
bool BLO_read_data_is_undo(BlendDataReader *reader)
Definition readfile.cc:5485
void BLO_read_int32_array(BlendDataReader *reader, int64_t array_size, int32_t **ptr_p)
Definition readfile.cc:5306
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
BlendFileReadReport * BLO_read_lib_reports(BlendLibReader *reader)
Definition readfile.cc:5515
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_write_struct_list(writer, struct_name, list_ptr)
void BLO_read_char_array(BlendDataReader *reader, int64_t array_size, char **ptr_p)
Definition readfile.cc:5278
#define BLO_read_struct(reader, struct_name, ptr_p)
void BLO_write_pointer_array(BlendWriter *writer, int64_t num, const void *data_ptr)
void BLO_read_pointer_array(BlendDataReader *reader, int64_t array_size, void **ptr_p)
Definition readfile.cc:5402
bool BLO_write_is_undo(BlendWriter *writer)
void BLO_write_char_array(BlendWriter *writer, int64_t num, const char *data_ptr)
void BLO_reportf_wrap(BlendFileReadReport *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
external readfile function prototypes.
#define RPT_(msgid)
#define BLT_I18NCONTEXT_ID_ID
#define BLT_I18NCONTEXT_ID_LIGHT
#define BLT_I18NCONTEXT_ID_OBJECT
#define CTX_DATA_(context, msgid)
#define DATA_(msgid)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
void DEG_id_tag_update(ID *id, unsigned int flags)
eEvaluationMode
@ DAG_EVAL_RENDER
@ DAG_EVAL_VIEWPORT
bool DEG_is_active(const Depsgraph *depsgraph)
Definition depsgraph.cc:323
float DEG_get_ctime(const Depsgraph *graph)
#define DEG_OBJECT_ITER_BEGIN(settings_, instance_)
bool DEG_is_original(const T *id)
#define DEG_OBJECT_ITER_END
bool DEG_object_geometry_is_evaluated(const Object &object)
T * DEG_get_original(T *id)
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY
@ DEG_ITER_OBJECT_FLAG_VISIBLE
@ DEG_ITER_OBJECT_FLAG_DUPLI
@ ID_RECALC_TRANSFORM
Definition DNA_ID.h:962
@ ID_RECALC_PSYS_REDO
Definition DNA_ID.h:989
@ ID_RECALC_SYNC_TO_EVAL
Definition DNA_ID.h:1026
@ ID_RECALC_EDITORS
Definition DNA_ID.h:1019
@ ID_RECALC_ANIMATION
Definition DNA_ID.h:985
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ ID_RECALC_ALL
Definition DNA_ID.h:1096
@ INDEX_ID_OB
Definition DNA_ID.h:1248
@ ID_TAG_NEW
Definition DNA_ID.h:827
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:905
@ ID_TAG_INDIRECT
Definition DNA_ID.h:756
@ ID_TAG_EXTERN
Definition DNA_ID.h:750
@ ID_TAG_COPIED_ON_EVAL_FINAL_RESULT
Definition DNA_ID.h:915
@ ID_TAG_DOIT
Definition DNA_ID.h:944
@ ID_TAG_NO_MAIN
Definition DNA_ID.h:886
@ ID_CA
@ ID_AR
@ ID_VO
@ ID_LA
@ ID_CV
@ ID_LP
@ ID_CU_LEGACY
@ ID_ME
@ ID_SPK
@ ID_MB
@ ID_LT
@ ID_OB
@ ID_GP
@ ID_PT
@ IDP_TYPE_FILTER_ID
@ ROT_MODE_QUAT
@ ROT_MODE_MAX
@ ROT_MODE_AXISANGLE
@ ROT_MODE_MIN
@ ROT_MODE_EUL
@ POSE_SCALE
@ POSE_ROT
@ POSE_LOC
@ POSE_CONSTRAINTS_NEED_UPDATE_FLAGS
@ POSE_RECALC
@ BONE_RELATIVE_PARENTING
Object groups, one object can be in many groups at once.
@ CONSTRAINT_OFF
@ CONSTRAINT_TYPE_CAMERASOLVER
@ CONSTRAINT_OBTYPE_OBJECT
@ CAMERASOLVER_ACTIVECLIP
@ CU_FOLLOW
@ CU_PATH
@ CU_PATH_RADIUS
@ CU_PATH_CLAMP
@ CD_GRID_PAINT_MASK
#define DNA_struct_default_get(struct_name)
@ EFF_BUILD
@ EFF_WAVE
@ EFF_PARTICLE
@ IMA_ANIM_ALWAYS
@ KEY_RELATIVE
@ BASE_FROM_DUPLI
@ BASE_ENABLED_AND_MAYBE_VISIBLE_IN_VIEWPORT
#define ME_EDIT_PAINT_SEL_MODE(_me)
@ eModifierFlag_PinLast
@ eModifierFlag_Active
@ eModifierMode_Render
@ eModifierMode_Realtime
@ eParticleSystemFlag_file_loaded
@ MOD_FLUID_TYPE_DOMAIN
@ MOD_FLUID_TYPE_FLOW
@ eModifierType_ParticleSystem
@ eModifierType_Fluidsim
@ eModifierType_Subsurf
@ eModifierType_Mirror
@ eModifierType_Skin
@ eModifierType_Wave
@ eModifierType_Cloth
@ eModifierType_Fluid
@ eModifierType_MeshSequenceCache
@ eModifierType_Hook
@ eModifierType_Screw
@ eModifierType_Ocean
@ eModifierType_Armature
@ eModifierType_Nodes
@ eModifierType_Collision
@ eModifierType_DynamicPaint
@ eModifierType_MeshCache
@ eModifierType_Array
@ eModifierType_Softbody
@ eModifierType_Multires
@ eModifierType_Build
#define OB_MODE_ALL_MODE_DATA
eObjectMode
@ OB_MODE_PARTICLE_EDIT
@ OB_MODE_EDIT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_SCULPT
@ OB_MODE_POSE
@ OB_MODE_OBJECT
@ OB_MODE_WEIGHT_GREASE_PENCIL
@ OB_MODE_VERTEX_PAINT
#define OB_MODE_ALL_SCULPT
Object is a sort of wrapper for general info.
@ OB_DUPLI
@ OB_NO_CONSTRAINTS
@ OB_NEG_SCALE
@ OB_PARENT_USE_FINAL_INDICES
@ OB_EMPTY_CONE
@ OB_SINGLE_ARROW
@ OB_PLAINAXES
@ OB_ARROWS
@ OB_CIRCLE
@ OB_CUBE
@ OB_EMPTY_IMAGE
@ OB_EMPTY_SPHERE
@ OB_HIDE_CAMERA
@ OB_SHADOW_CATCHER
@ OB_NEGZ
@ OB_POSY
@ OB_POSZ
@ OB_LOCK_ROTZ
@ OB_LOCK_ROT4D
@ OB_LOCK_SCALEZ
@ OB_LOCK_ROTX
@ OB_LOCK_SCALEX
@ OB_LOCK_ROTW
@ OB_LOCK_LOCY
@ OB_LOCK_LOCZ
@ OB_LOCK_ROTY
@ OB_LOCK_SCALEY
@ OB_LOCK_LOCX
#define OB_TYPE_SUPPORT_PARVERT(_type)
@ OB_DUPLI_FLAG_VIEWPORT
@ OB_DUPLI_FLAG_RENDER
@ OB_SPEAKER
@ OB_LATTICE
@ OB_MBALL
@ OB_EMPTY
@ OB_SURF
@ OB_CAMERA
@ OB_FONT
@ OB_GREASE_PENCIL
@ OB_ARMATURE
@ OB_LAMP
@ OB_MESH
@ OB_POINTCLOUD
@ OB_VOLUME
@ OB_CURVES_LEGACY
@ OB_CURVES
@ OB_LIGHTPROBE
#define OB_DATA_SUPPORT_EDITMODE(_type)
@ OB_USE_GPENCIL_LIGHTS
@ OB_EMPTY_IMAGE_HIDE_FRONT
@ OB_EMPTY_IMAGE_HIDE_NON_AXIS_ALIGNED
@ OB_EMPTY_IMAGE_HIDE_ORTHOGRAPHIC
@ OB_EMPTY_IMAGE_HIDE_BACK
@ OB_EMPTY_IMAGE_HIDE_PERSPECTIVE
@ PARVERT1
@ PARSKEL
@ PAROBJECT
@ PARTYPE
@ PARVERT3
@ PARBONE
#define OB_TYPE_SUPPORT_VGROUP(_type)
@ PSYS_SHARED_CACHES
@ PTCACHE_IGNORE_CLEAR
@ PTCACHE_BAKED
@ PTCACHE_FLAG_INFO_DIRTY
@ PTCACHE_OUTDATED
@ PTCACHE_DISK_CACHE
Types and defines for representing Rigid Body entities.
#define BASE_SELECTED(v3d, base)
#define BASE_SELECTED_EDITABLE(v3d, base)
@ SCE_SELECT_VERTEX
#define BASE_EDITABLE(v3d, base)
#define BASE_VISIBLE(v3d, base)
eDupli_ID_Flags
@ USER_DUP_MAT
@ USER_DUP_SURF
@ USER_DUP_LIGHTPROBE
@ USER_DUP_MBALL
@ USER_DUP_LINKED_ID
@ USER_DUP_CURVE
@ USER_DUP_CAMERA
@ USER_DUP_VOLUME
@ USER_DUP_SPEAKER
@ USER_DUP_PSYS
@ USER_DUP_GPENCIL
@ USER_DUP_CURVES
@ USER_DUP_LAMP
@ USER_DUP_ARM
@ USER_DUP_MESH
@ USER_DUP_POINTCLOUD
@ USER_DUP_FONT
@ USER_DUP_LATTICE
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
Read Guarded memory(de)allocation.
ReportList * reports
Definition WM_types.hh:1025
volatile int lock
void BKE_object_matrix_local_get(Object *ob, float r_mat[4][4])
static void ob_parvert3(const Object *ob, const Object *par, float r_mat[4][4])
void BKE_object_where_is_calc_mat4(const Object *ob, float r_obmat[4][4])
void BKE_object_protected_location_set(Object *ob, const float location[3])
bool BKE_object_obdata_texspace_get(Object *ob, char **r_texspace_flag, float **r_texspace_location, float **r_texspace_size)
static void object_asset_metadata_ensure(void *asset_ptr, AssetMetaData *asset_data)
static blender::Mutex vparent_lock
static void object_blend_write(BlendWriter *writer, ID *id, const void *id_address)
void BKE_object_to_mesh_clear(Object *object)
void BKE_object_groups_clear(Main *bmain, Scene *scene, Object *ob)
void BKE_object_empty_draw_type_set(Object *ob, const int value)
bool BKE_object_is_libdata(const Object *ob)
void BKE_object_to_curve_clear(Object *object)
bool BKE_object_has_mode_data(const Object *ob, eObjectMode object_mode)
static KeyBlock * insert_curvekey(Main *bmain, Object *ob, const char *name, const bool from_mix)
Vector< Object * > BKE_object_pose_array_get_unique(const Scene *scene, ViewLayer *view_layer, View3D *v3d)
static IDProperty * object_asset_dimensions_property(Object *ob)
const Mesh * BKE_object_get_editmesh_eval_cage(const Object *object)
blender::float4x4 BKE_object_calc_parent(Depsgraph *depsgraph, Scene *scene, Object *ob)
static Object * object_add_common(Main *bmain, const Scene *scene, ViewLayer *view_layer, int type, const char *name)
KDTree_3d * BKE_object_as_kdtree(Object *ob, int *r_tot)
static void object_blend_read_after_liblink(BlendLibReader *reader, ID *id)
bool BKE_object_flag_test_recursive(const Object *ob, short flag)
#define TFMCPY4D(_v)
void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src, const int flag)
LinkNode * BKE_object_relational_superset(const Scene *scene, ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter)
void BKE_object_sculpt_data_create(Object *ob)
void BKE_object_modifier_set_active(Object *ob, ModifierData *md)
void BKE_object_protected_rotation_axisangle_set(Object *ob, const float axis[3], const float angle)
static void library_foreach_modifiersForeachIDLink(void *user_data, Object *, ID **id_pointer, const LibraryForeachIDCallbackFlag cb_flag)
PartEff * BKE_object_do_version_give_parteff_245(Object *ob)
MovieClip * BKE_object_movieclip_get(Scene *scene, const Object *ob, bool use_default)
void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
static void object_where_is_calc_ex(Depsgraph *depsgraph, Scene *scene, Object *ob, float ctime, RigidBodyWorld *rbw, float r_originmat[3][3])
Vector< Base * > BKE_object_pose_base_array_get_unique(const Scene *scene, ViewLayer *view_layer, View3D *v3d)
bool BKE_object_is_in_editmode(const Object *ob)
bool BKE_object_exists_check(Main *bmain, const Object *obtest)
void BKE_object_handle_update_ex(Depsgraph *depsgraph, Scene *scene, Object *ob, RigidBodyWorld *rbw)
Vector< Base * > BKE_object_pose_base_array_get(const Scene *scene, ViewLayer *view_layer, View3D *v3d)
static KeyBlock * insert_lattkey(Main *bmain, Object *ob, const char *name, const bool from_mix)
void BKE_boundbox_minmax(const BoundBox &bb, const float4x4 &matrix, float3 &r_min, float3 &r_max)
static bool ob_parcurve(const Object *ob, Object *par, float r_mat[4][4])
#define TFMCPY3D(_v)
static bool object_modifier_type_copy_check(ModifierType md_type)
static void object_init(Object *ob, const short ob_type)
void BKE_object_scale_to_mat3(const Object *ob, float mat[3][3])
void BKE_object_update_select_id(Main *bmain)
Object * BKE_object_add_from(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name, Object *ob_src)
int BKE_object_obdata_to_type(const ID *id)
void BKE_object_check_uids_unique_and_report(const Object *object)
void BKE_object_dimensions_set(Object *ob, const float value[3], int axis_mask)
const Mesh * BKE_object_get_pre_modified_mesh(const Object *object)
void BKE_object_tfm_protected_backup(const Object *ob, ObjectTfmProtectedChannels *obtfm)
static void object_copy_data(Main *bmain, std::optional< Library * >, ID *id_dst, const ID *id_src, const int flag)
void BKE_object_replace_data_on_shallow_copy(Object *ob, ID *new_data)
void BKE_object_workob_clear(Object *workob)
void BKE_object_dimensions_eval_cached_get(const Object *ob, float r_vec[3])
static void object_lib_override_apply_post(ID *id_dst, ID *id_src)
std::optional< Bounds< float3 > > BKE_object_boundbox_eval_cached_get(const Object *ob)
void BKE_object_get_parent_matrix(const Object *ob, Object *par, float r_parentmat[4][4])
static void object_foreach_path(ID *id, BPathForeachPathData *bpath_data)
bool BKE_object_minmax_empty_drawtype(const Object *ob, float r_min[3], float r_max[3])
static AssetTypeInfo AssetType_OB
void BKE_object_copy_particlesystems(Object *ob_dst, const Object *ob_src, const int flag)
bool BKE_object_supports_modifiers(const Object *ob)
void * BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
char * BKE_object_data_editmode_flush_ptr_get(ID *id)
void BKE_object_runtime_reset(Object *object)
void BKE_object_tfm_copy(Object *object_dst, const Object *object_src)
static void object_update_from_subsurf_ccg(Object *object)
Object * BKE_object_add_only_object(Main *bmain, int type, const char *name)
Object * BKE_object_add(Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name)
bool BKE_object_pose_context_check(const Object *ob)
static int pc_cmp(const void *a, const void *b)
Mesh * BKE_object_get_evaluated_mesh(const Object *object_eval)
static void library_foreach_constraintObjectLooper(bConstraint *, ID **id_pointer, bool is_reference, void *user_data)
Object * BKE_object_add_for_data(Main *bmain, const Scene *scene, ViewLayer *view_layer, int type, const char *name, ID *data, bool do_id_user)
void BKE_scene_foreach_display_point(Depsgraph *depsgraph, void(*func_cb)(const float[3], void *), void *user_data)
bool BKE_object_shapekey_free(Main *bmain, Object *ob)
static Object * obrel_armature_find(Object *ob)
int BKE_object_is_deform_modified(Scene *scene, Object *ob)
void BKE_object_apply_mat4(Object *ob, const float mat[4][4], const bool use_compat, const bool use_parent)
static void library_foreach_gpencil_modifiersForeachIDLink(void *user_data, Object *, ID **id_pointer, const LibraryForeachIDCallbackFlag cb_flag)
int BKE_object_insert_ptcache(Object *ob)
static void ob_parbone(const Object *ob, const Object *par, float r_mat[4][4])
static void object_cacheIgnoreClear(Object *ob, int state)
bool BKE_object_moves_in_time(const Object *object, bool recurse_parent)
static ParticleSystem * object_copy_modifier_particle_system_ensure(Main *bmain, const Scene *scene, Object *ob_dst, ParticleSystem *psys_src)
int BKE_object_scenes_users_get(Main *bmain, Object *ob)
bool BKE_object_shapekey_remove(Main *bmain, Object *ob, KeyBlock *kb)
static KeyBlock * insert_meshkey(Main *bmain, Object *ob, const char *name, const bool from_mix)
Object * BKE_object_pose_armature_get(Object *ob)
void BKE_object_free_modifiers(Object *ob, const int flag)
static bool modifiers_has_animation_check(const Object *ob)
void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
void BKE_object_dimensions_set_ex(Object *ob, const float value[3], int axis_mask, const float ob_scale_orig[3], const float ob_obmat_orig[4][4])
const Mesh * BKE_object_get_mesh_deform_eval(const Object *object)
void BKE_object_runtime_free_data(Object *object)
static bool object_modifier_recurse_for_update_subframe(const ObjectModifierUpdateContext &ctx, Object *ob, const bool update_mesh, const int parent_recursion_limit)
static void solve_parenting(const Object *ob, Object *par, const bool set_origin, float r_obmat[4][4], float r_originmat[3][3])
blender::Vector< Base * > BKE_object_pose_base_array_get_ex(const Scene *scene, ViewLayer *view_layer, View3D *v3d, bool unique)
void BKE_boundbox_init_from_minmax(BoundBox *bb, const float min[3], const float max[3])
bool BKE_object_supports_material_slots(Object *ob)
bool BKE_object_obdata_is_libdata(const Object *ob)
static void copy_object_pose(Object *obn, const Object *ob, const int flag)
static void object_blend_read_data(BlendDataReader *reader, ID *id)
static bool object_moves_in_time(const Object *object)
ModifierData * BKE_object_active_modifier(const Object *ob)
SubsurfModifierData * BKE_object_get_last_subsurf_modifier(const Object *ob)
void BKE_object_free_particlesystems(Object *ob)
void BKE_object_free_curve_cache(Object *ob)
void BKE_object_obdata_size_init(Object *ob, const float size)
static void library_foreach_particlesystemsObjectLooper(ParticleSystem *, ID **id_pointer, void *user_data, const LibraryForeachIDCallbackFlag cb_flag)
void BKE_object_where_is_calc_ex(Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
bool BKE_object_data_is_in_editmode(const Object *ob, const ID *id)
void BKE_object_mat3_to_rot(Object *ob, float mat[3][3], bool use_compat)
static void object_init_data(ID *id)
static void direct_link_nlastrips(BlendDataReader *reader, ListBase *strips)
Object * BKE_object_pose_armature_get_with_wpaint_check(Object *ob)
bool BKE_object_is_mode_compat(const Object *ob, eObjectMode object_mode)
void BKE_object_runtime_reset_on_copy(Object *object, const int)
void BKE_object_foreach_display_point(Object *ob, const float obmat[4][4], void(*func_cb)(const float[3], void *), void *user_data)
Mesh * BKE_object_to_mesh(Depsgraph *depsgraph, Object *object, bool preserve_all_data_layers)
void BKE_object_apply_mat4_ex(Object *ob, const float mat[4][4], Object *parent, const float parentinv[4][4], const bool use_compat)
void BKE_object_link_modifiers(Object *ob_dst, const Object *ob_src)
Vector< Object * > BKE_object_pose_array_get(const Scene *scene, ViewLayer *view_layer, View3D *v3d)
const Mesh * BKE_object_get_editmesh_eval_final(const Object *object)
Vector< Object * > BKE_object_pose_array_get_ex(const Scene *scene, ViewLayer *view_layer, View3D *v3d, bool unique)
bool BKE_object_is_child_recursive(const Object *ob_parent, const Object *ob_child)
Object * BKE_object_duplicate(Main *bmain, Object *ob, eDupli_ID_Flags dupflag, uint duplicate_options)
static int pc_findindex(ListBase *listbase, int index)
Mesh * BKE_object_get_evaluated_mesh_no_subsurf_unchecked(const Object *object)
bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
bool BKE_object_modifier_stack_copy(Object *ob_dst, const Object *ob_src, const bool do_copy_all, const int flag_subdata)
bool BKE_object_empty_image_frame_is_visible_in_view3d(const Object *ob, const RegionView3D *rv3d)
Mesh * BKE_object_get_evaluated_mesh_no_subsurf(const Object *object)
static void give_parvert(const Object *par, int nr, float vec[3], const bool use_evaluated_indices)
KeyBlock * BKE_object_shapekey_insert(Main *bmain, Object *ob, const char *name, const bool from_mix)
bool BKE_object_copy_modifier(Main *bmain, const Scene *scene, Object *ob_dst, const Object *ob_src, const ModifierData *md_src)
int BKE_object_visibility(const Object *ob, const int dag_eval_mode)
void BKE_object_minmax(Object *ob, float3 &r_min, float3 &r_max)
Lattice * BKE_object_get_lattice(const Object *object)
void BKE_object_modifier_gpencil_hook_reset(Object *ob, HookGpencilModifierData *hmd)
void BKE_object_protected_rotation_quaternion_set(Object *ob, const float quat[4])
void BKE_object_protected_rotation_euler_set(Object *ob, const float euler[3])
bool BKE_object_is_in_wpaint_select_vert(const Object *ob)
void BKE_object_apply_parent_inverse(Object *ob)
bool BKE_object_minmax_dupli(Depsgraph *depsgraph, Scene *scene, Object *ob, float3 &r_min, float3 &r_max, const bool use_hidden)
std::optional< blender::Bounds< blender::float3 > > BKE_object_boundbox_get(const Object *ob)
Mesh * BKE_object_get_evaluated_mesh_unchecked(const Object *object_eval)
Mesh * BKE_object_get_original_mesh(const Object *object)
void BKE_object_to_mat4(const Object *ob, float r_mat[4][4])
Curve * BKE_object_to_curve(Object *object, Depsgraph *depsgraph, bool apply_modifiers)
Lattice * BKE_object_get_evaluated_lattice(const Object *object)
static bool constructive_modifier_is_deform_modified(Object *ob, ModifierData *md)
void BKE_object_eval_assign_data(Object *object_eval, ID *data_eval, bool is_owned)
void * BKE_object_tfm_backup(Object *ob)
void BKE_object_tfm_protected_restore(Object *ob, const ObjectTfmProtectedChannels *obtfm, const short protectflag)
static bool object_deforms_in_time(Object *object)
void BKE_object_modifier_update_subframe_only_callback(Object *ob, const bool update_mesh, const int parent_recursion_limit, const int modifier_type, blender::FunctionRef< void(Object *object, bool update_mesh)> update_or_tag_fn)
Object * BKE_object_pose_armature_get_visible(Object *ob, const Scene *scene, ViewLayer *view_layer, View3D *v3d)
static void object_foreach_cache(ID *id, IDTypeForeachCacheFunctionCallback function_callback, void *user_data)
void BKE_object_to_mat3(const Object *ob, float r_mat[3][3])
void BKE_object_handle_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
static const char * get_obdata_defname(int type)
void BKE_object_delete_ptcache(Object *ob, int index)
void BKE_object_free_caches(Object *object)
bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
static void object_foreach_id(ID *id, LibraryForeachIDData *data)
LinkNode * BKE_object_groups(Main *bmain, Scene *scene, Object *ob)
void BKE_object_dimensions_get(const Object *ob, float r_vec[3])
static float3 boundbox_to_dimensions(const Object *ob, const std::optional< Bounds< float3 > > bounds)
void BKE_object_where_is_calc_time(Depsgraph *depsgraph, Scene *scene, Object *ob, float ctime)
static void library_foreach_shaderfxForeachIDLink(void *user_data, Object *, ID **id_pointer, const LibraryForeachIDCallbackFlag cb_flag)
bool BKE_object_is_in_editmode_vgroup(const Object *ob)
#define TFMCPY(_v)
static void copy_ccg_data(Mesh *mesh_destination, Mesh *mesh_source, const eCustomDataType layer_type)
bool BKE_object_empty_image_data_is_visible_in_view3d(const Object *ob, const RegionView3D *rv3d)
void BKE_object_modifier_update_subframe(Depsgraph *depsgraph, Scene *scene, Object *ob, const bool update_mesh, const int parent_recursion_limit, const float frame, const int modifier_type)
static void object_free_data(ID *id)
void BKE_object_where_is_calc(Depsgraph *depsgraph, Scene *scene, Object *ob)
void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
void BKE_object_rot_to_mat3(const Object *ob, float mat[3][3], bool use_drot)
int BKE_object_is_modified(Scene *scene, Object *ob)
ParticleSystem * BKE_object_copy_particlesystem(ParticleSystem *psys, const int flag)
void BKE_object_protected_scale_set(Object *ob, const float scale[3])
static bool obrel_list_test(Object *ob)
static void obrel_list_add(LinkNode **links, Object *ob)
void BKE_object_free_derived_caches(Object *ob)
void BKE_object_free_softbody(Object *ob)
std::optional< Bounds< float3 > > BKE_object_evaluated_geometry_bounds(const Object *ob)
static void object_foreach_path_pointcache(ListBase *ptcache_list, BPathForeachPathData *bpath_data)
void BKE_object_free_shaderfx(Object *ob, const int flag)
BMesh const char void * data
void BM_mesh_elem_table_ensure(BMesh *bm, const char htype)
BLI_INLINE BMVert * BM_vert_at_index(BMesh *bm, const int index)
#define BM_VERT
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
BPy_StructRNA * depsgraph
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition btDbvt.cpp:299
constexpr int64_t size() const
Definition BLI_span.hh:252
constexpr IndexRange index_range() const
Definition BLI_span.hh:401
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
#define copysignf(x, y)
KDTree_3d * tree
#define rot(x, k)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
#define printf(...)
#define FILTER_ID_OB
#define FILTER_ID_ALL
#define MEM_SAFE_FREE(v)
#define ID_IS_LINKED(_id)
#define GS(a)
int count
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
#define LOG(severity)
Definition log.h:32
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static ulong * next
static ulong state[N]
#define G(x, y, z)
Vector< FCurve * > fcurves_for_assigned_action(AnimData *adt)
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRef prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
bool object_has_geometry_set_instances(const Object &object)
void min_max(const T &value, T &min, T &max)
VecBase< T, 3 > to_scale(const MatBase< T, NumCol, NumRow > &mat)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:93
MatBase< float, 4, 4 > float4x4
std::mutex Mutex
Definition BLI_mutex.hh:47
VecBase< float, 3 > float3
const btScalar eps
Definition poly34.cpp:11
#define min(a, b)
Definition sort.cc:36
bAction * action
ListBase drivers
struct Object * start_cap
struct Object * offset_ob
struct Object * curve_ob
struct Object * end_cap
The meta-data of an asset. By creating and giving this for a data-block (ID.asset_data),...
int totvert
char elem_table_dirty
float vec[4]
struct Object * object
float vec[3][3]
int * springs
float vec[8][3]
float drawsize
struct ListBase ptcaches
struct PointCache * point_cache
struct AnimData * adt
char texspace_flag
struct Key * key
ListBase nurb
float fsize
float ctime
float texspace_size[3]
float texspace_location[3]
struct Object * taperobj
float * verts
struct DynamicPaintCanvasSettings * canvas
struct DynamicPaintBrushSettings * brush
char needs_flush_to_id
Definition BKE_vfont.hh:73
char needs_flush_to_id
struct Lattice * latt
char needs_flush_to_id
struct Collection * group
struct ParticleSystem * psys
struct FluidDomainSettings * domain
struct FluidFlowSettings * flow
struct FluidsimSettings * fss
GreasePencilRuntimeHandle * runtime
struct Object * object
Definition DNA_ID.h:404
unsigned int recalc
Definition DNA_ID.h:427
void * py_instance
Definition DNA_ID.h:483
int tag
Definition DNA_ID.h:424
struct Library * lib
Definition DNA_ID.h:410
struct ID * newid
Definition DNA_ID.h:408
void * next
Definition DNA_ID.h:407
char name[66]
Definition DNA_ID.h:415
struct ID_Runtime runtime
Definition DNA_ID.h:493
void * data
int totkey
char type
ListBase block
KeyBlock * refkey
struct Key * key
struct EditLatt * editlatt
struct BPoint * def
struct Collection * collection
char filepath[1024]
Definition DNA_ID.h:507
struct Collection * blocker_collection
struct Collection * receiver_collection
float area_sizez
float area_sizey
float radius
float area_size
void * data
struct LinkData * next
void * last
void * first
ListBase scenes
Definition BKE_main.hh:245
ListBase objects
Definition BKE_main.hh:247
int corners_num
MeshRuntimeHandle * runtime
CustomData corner_data
CustomData vert_data
int verts_num
char texspace_flag
float texspace_size[3]
float texspace_location[3]
char needs_flush_to_id
struct Object * mirror_ob
struct ModifierData * next
struct ModifierData * prev
void(* modify_geometry_set)(ModifierData *md, const ModifierEvalContext *ctx, blender::bke::GeometrySet *geometry_set)
ModifierTypeFlag flags
ModifierTypeType type
struct Nurb * next
BezTriple * bezt
BPoint * bp
struct Object * parent
float cent[3]
float parentinv[4][4]
blender::FunctionRef< void(Object *object, bool update_mesh)> update_or_tag_fn
ListBase particlesystem
struct Object * track
short transflag
ListBase constraints
struct Collection * instance_collection
short base_flag
struct bPose * pose
struct LightProbeObjectCache * lightprobe_cache
ObjectRuntimeHandle * runtime
float drot[3]
ListBase modifiers
float dquat[4]
struct RigidBodyOb * rigidbody_object
float constinv[4][4]
ListBase greasepencil_modifiers
struct PreviewImage * preview
struct Material ** mat
float loc[3]
char * matbits
struct PartDeflect * pd
float dloc[3]
float scale[3]
struct SoftBody * soft
float rot[3]
float parentinv[4][4]
char empty_drawtype
ListBase shader_fx
ImageUser * iuser
short visibility_flag
float drotAxis[3]
float empty_drawsize
bMotionPath * mpath
float quat[4]
LightLinking * light_linking
ListBase pc_ids
float rotAxis[3]
float drotAngle
struct AnimData * adt
float dscale[3]
short protectflag
struct Object * parent
short trackflag
char duplicator_visibility_flag
struct SculptSession * sculpt
struct RigidBodyCon * rigidbody_constraint
struct LightgroupMembership * lightgroup
char parsubstr[64]
char empty_image_visibility_flag
bAnimVizSettings avs
float ima_ofs[2]
unsigned int data_types
unsigned int info_types
unsigned int type
struct ListBase * ptcaches
unsigned int default_step
unsigned int file_type
unsigned int max_step
struct PTCacheID * next
struct Object * f_source
Particle * keys
struct PartEff * next
struct Collection * group
struct ParticleSystem * psys
struct PTCacheEdit * edit
struct ListBase ptcaches
struct ListBase targets
ParticleSettings * part
struct ListBase * effectors
struct PointCache * pointcache
struct BVHTree * bvhtree
struct ClothModifierData * clmd
struct ParticleCacheKey ** childcache
struct Mesh * hair_in_mesh
struct KDTree_3d * tree
struct Mesh * hair_out_mesh
struct ParticleDrawData * pdd
struct ParticleCacheKey ** pathcache
struct PointCache * next
float viewinv[4][4]
struct Object * ob1
struct Object * ob2
struct RigidBodyOb_Shared * shared
struct RigidBodyWorld * rigidbody_world
struct MovieClip * clip
struct Object * ob_axis
eObjectMode mode_type
Definition BKE_paint.hh:511
struct PointCache * pointcache
struct SoftBody_Shared * shared
struct Collection * collision_group
struct EffectorWeights * effector_weights
struct BodySpring * bspring
struct SBScratch * scratch
struct BodyPoint * bpoint
struct SubdivCCG::@215250027323141210226117165130145372352306247373 dirty
struct AnimData * adt
struct bConstraint * next
struct Bone * bone
float chan_mat[4][4]
float pose_mat[4][4]
ListBase chanbase
const Mesh * get_mesh() const
Array< float3x3, 0 > crazyspace_deform_imats
Array< float3, 0 > crazyspace_deform_cos
float x
Definition sky_float3.h:27
i
Definition text_draw.cc:230
max
Definition text_draw.cc:251
uint len
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:139