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