Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/object.c
| Show First 20 Lines • Show All 212 Lines • ▼ Show 20 Lines | static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag) | ||||
| if (ob_src->iuser) { | if (ob_src->iuser) { | ||||
| ob_dst->iuser = MEM_dupallocN(ob_src->iuser); | ob_dst->iuser = MEM_dupallocN(ob_src->iuser); | ||||
| } | } | ||||
| if (ob_src->runtime.bb) { | if (ob_src->runtime.bb) { | ||||
| ob_dst->runtime.bb = MEM_dupallocN(ob_src->runtime.bb); | ob_dst->runtime.bb = MEM_dupallocN(ob_src->runtime.bb); | ||||
| } | } | ||||
| BLI_listbase_clear(&ob_dst->modifiers); | |||||
| LISTBASE_FOREACH (ModifierData *, md, &ob_src->modifiers) { | |||||
| ModifierData *nmd = BKE_modifier_new(md->type); | |||||
| BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); | |||||
| BKE_modifier_copydata_ex(md, nmd, flag_subdata); | |||||
| BLI_addtail(&ob_dst->modifiers, nmd); | |||||
| } | |||||
| BLI_listbase_clear(&ob_dst->greasepencil_modifiers); | |||||
| LISTBASE_FOREACH (GpencilModifierData *, gmd, &ob_src->greasepencil_modifiers) { | |||||
| GpencilModifierData *nmd = BKE_gpencil_modifier_new(gmd->type); | |||||
| BLI_strncpy(nmd->name, gmd->name, sizeof(nmd->name)); | |||||
| BKE_gpencil_modifier_copydata_ex(gmd, nmd, flag_subdata); | |||||
| BLI_addtail(&ob_dst->greasepencil_modifiers, nmd); | |||||
| } | |||||
| BLI_listbase_clear(&ob_dst->shader_fx); | BLI_listbase_clear(&ob_dst->shader_fx); | ||||
| LISTBASE_FOREACH (ShaderFxData *, fx, &ob_src->shader_fx) { | LISTBASE_FOREACH (ShaderFxData *, fx, &ob_src->shader_fx) { | ||||
| ShaderFxData *nfx = BKE_shaderfx_new(fx->type); | ShaderFxData *nfx = BKE_shaderfx_new(fx->type); | ||||
| BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name)); | BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name)); | ||||
| BKE_shaderfx_copydata_ex(fx, nfx, flag_subdata); | BKE_shaderfx_copydata_ex(fx, nfx, flag_subdata); | ||||
| BLI_addtail(&ob_dst->shader_fx, nfx); | BLI_addtail(&ob_dst->shader_fx, nfx); | ||||
| } | } | ||||
| if (ob_src->pose) { | if (ob_src->pose) { | ||||
| Show All 12 Lines | static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag) | ||||
| ob_dst->sculpt = NULL; | ob_dst->sculpt = NULL; | ||||
| if (ob_src->pd) { | if (ob_src->pd) { | ||||
| ob_dst->pd = MEM_dupallocN(ob_src->pd); | ob_dst->pd = MEM_dupallocN(ob_src->pd); | ||||
| if (ob_dst->pd->rng) { | if (ob_dst->pd->rng) { | ||||
| ob_dst->pd->rng = MEM_dupallocN(ob_src->pd->rng); | ob_dst->pd->rng = MEM_dupallocN(ob_src->pd->rng); | ||||
| } | } | ||||
| } | } | ||||
| BKE_object_copy_softbody(ob_dst, ob_src, flag_subdata); | |||||
| BKE_rigidbody_object_copy(bmain, ob_dst, ob_src, flag_subdata); | BKE_rigidbody_object_copy(bmain, ob_dst, ob_src, flag_subdata); | ||||
| BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata); | BLI_listbase_clear(&ob_dst->modifiers); | ||||
| BLI_listbase_clear(&ob_dst->greasepencil_modifiers); | |||||
| /* Note: Also takes care of softbody and particle systems copying. */ | |||||
| BKE_object_modifier_stack_copy(ob_dst, ob_src, true, flag_subdata); | |||||
| BLI_listbase_clear((ListBase *)&ob_dst->drawdata); | BLI_listbase_clear((ListBase *)&ob_dst->drawdata); | ||||
| BLI_listbase_clear(&ob_dst->pc_ids); | BLI_listbase_clear(&ob_dst->pc_ids); | ||||
| ob_dst->avs = ob_src->avs; | ob_dst->avs = ob_src->avs; | ||||
| ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath); | ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath); | ||||
| /* Do not copy object's preview | /* Do not copy object's preview | ||||
| ▲ Show 20 Lines • Show All 1,068 Lines • ▼ Show 20 Lines | if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) { | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool BKE_object_copy_modifier(struct Object *ob_dst, const struct Object *ob_src, ModifierData *md) | static bool object_modifier_type_copy_check(ModifierType md_type) | ||||
| { | { | ||||
| if (ELEM(md->type, eModifierType_Hook, eModifierType_Collision)) { | return !ELEM(md_type, eModifierType_Hook, eModifierType_Collision); | ||||
| return false; | |||||
| } | } | ||||
| if (!BKE_object_support_modifier_type_check(ob_dst, md->type)) { | /** Find a `psys` matching given `psys_src` in `ob_dst` (i.e. sharing the same ParticleSettings | ||||
| * ID), or add one, and return valid `psys` from `ob_dst`. | |||||
| * | |||||
| * \note Order handling is fairly weak here. This code assumes that it is called **before** the | |||||
| * modifier using the psys is actually copied, and that this copied modifier will be added at the | |||||
| * end of the stack. That way we can be sure that the particle modifier will be before the one | |||||
| * using its particle system in the stack. | |||||
| */ | |||||
| static ParticleSystem *object_copy_modifier_particle_system_ensure(Main *bmain, | |||||
| Scene *scene, | |||||
| Object *ob_dst, | |||||
| ParticleSystem *psys_src) | |||||
| { | |||||
| ParticleSystem *psys_dst = NULL; | |||||
| /* Check if a particle system with the same particle settings | |||||
| * already exists on the destination object. */ | |||||
| LISTBASE_FOREACH (ParticleSystem *, psys, &ob_dst->particlesystem) { | |||||
| if (psys->part == psys_src->part) { | |||||
| psys_dst = psys; | |||||
| break; | |||||
| } | |||||
| } | |||||
| /* If it does not exist, copy the particle system to the destination object. */ | |||||
| if (psys_dst == NULL) { | |||||
| ModifierData *md = object_copy_particle_system(bmain, scene, ob_dst, psys_src); | |||||
| psys_dst = ((ParticleSystemModifierData *)md)->psys; | |||||
| } | |||||
| return psys_dst; | |||||
| } | |||||
| /** Copy a single modifier. | |||||
| * | |||||
| * \note **Do not** use this function to copy a whole modifier stack (see note below too). Use | |||||
| * `BKE_object_modifier_stack_copy` instead. | |||||
| * | |||||
| * \note Complex modifiers relaying on other data (like e.g. dynamic paint or fluid using particle | |||||
HooglyBoogly: typo `synamic` -> `dynamic` | |||||
| * systems) are not always 100% 'correctly' copied here, since we have to use heuristics to decide | |||||
| * which particle system to use or add in `ob_dst`, and it's placement in the stack, etc. If used | |||||
| * more than once, this function should preferably be called in stack order. */ | |||||
| bool BKE_object_copy_modifier( | |||||
| Main *bmain, Scene *scene, Object *ob_dst, const Object *ob_src, ModifierData *md_src) | |||||
| { | |||||
| BLI_assert(ob_dst->type != OB_GPENCIL); | |||||
| const ModifierTypeInfo *mti = BKE_modifier_get_info(md_src->type); | |||||
| if (!object_modifier_type_copy_check(md_src->type)) { | |||||
| /* We never allow copying those modifiers here. */ | |||||
Done Inline ActionsWe never allow to copy -> We never allow copying HooglyBoogly: `We never allow to copy` -> `We never allow copying` | |||||
| return false; | |||||
| } | |||||
| if (!BKE_object_support_modifier_type_check(ob_dst, md_src->type)) { | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (mti->flags & eModifierTypeFlag_Single) { | |||||
| if (BKE_modifiers_findby_type(ob_dst, md_src->type) != NULL) { | |||||
| return false; | |||||
| } | |||||
| } | |||||
| switch (md->type) { | ParticleSystem *psys_src = NULL; | ||||
| ParticleSystem *psys_dst = NULL; | |||||
| switch (md_src->type) { | |||||
| case eModifierType_Softbody: | case eModifierType_Softbody: | ||||
| BKE_object_copy_softbody(ob_dst, ob_src, 0); | BKE_object_copy_softbody(ob_dst, ob_src, 0); | ||||
| break; | break; | ||||
| case eModifierType_Skin: | case eModifierType_Skin: | ||||
| /* ensure skin-node customdata exists */ | /* ensure skin-node customdata exists */ | ||||
| BKE_mesh_ensure_skin_customdata(ob_dst->data); | BKE_mesh_ensure_skin_customdata(ob_dst->data); | ||||
| break; | break; | ||||
| case eModifierType_Fluid: { | |||||
| FluidModifierData *fmd = (FluidModifierData *)md_src; | |||||
| if (fmd->type == MOD_FLUID_TYPE_FLOW) { | |||||
| if (fmd->flow != NULL && fmd->flow->psys != NULL) { | |||||
| psys_src = fmd->flow->psys; | |||||
| psys_dst = object_copy_modifier_particle_system_ensure(bmain, scene, ob_dst, psys_src); | |||||
| } | |||||
| } | |||||
| break; | |||||
| } | |||||
| case eModifierType_DynamicPaint: { | |||||
| DynamicPaintModifierData *dpmd = (DynamicPaintModifierData *)md_src; | |||||
| if (dpmd->brush != NULL && dpmd->brush->psys != NULL) { | |||||
| psys_src = dpmd->brush->psys; | |||||
| psys_dst = object_copy_modifier_particle_system_ensure(bmain, scene, ob_dst, psys_src); | |||||
| } | |||||
| break; | |||||
| } | |||||
| default: | |||||
| break; | |||||
| } | } | ||||
| ModifierData *nmd = BKE_modifier_new(md->type); | ModifierData *md_dst; | ||||
| BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); | if (md_src->type == eModifierType_ParticleSystem) { | ||||
| md_dst = object_copy_particle_system( | |||||
| bmain, scene, ob_dst, ((ParticleSystemModifierData *)md_src)->psys); | |||||
| } | |||||
| else { | |||||
| md_dst = BKE_modifier_new(md_src->type); | |||||
| if (md->type == eModifierType_Multires) { | BLI_strncpy(md_dst->name, md_src->name, sizeof(md_dst->name)); | ||||
| if (md_src->type == eModifierType_Multires) { | |||||
| /* Has to be done after mod creation, but *before* we actually copy its settings! */ | /* Has to be done after mod creation, but *before* we actually copy its settings! */ | ||||
| multiresModifier_sync_levels_ex( | multiresModifier_sync_levels_ex( | ||||
| ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd); | ob_dst, (MultiresModifierData *)md_src, (MultiresModifierData *)md_dst); | ||||
| } | } | ||||
| BKE_modifier_copydata(md, nmd); | BKE_modifier_copydata(md_src, md_dst); | ||||
| BLI_addtail(&ob_dst->modifiers, nmd); | |||||
| BKE_modifier_unique_name(&ob_dst->modifiers, nmd); | switch (md_dst->type) { | ||||
| BKE_object_modifier_set_active(ob_dst, nmd); | case eModifierType_Fluid: | ||||
| if (psys_dst != NULL) { | |||||
| FluidModifierData *fmd_dst = (FluidModifierData *)md_dst; | |||||
| BLI_assert(fmd_dst->type == MOD_FLUID_TYPE_FLOW && fmd_dst->flow != NULL && | |||||
| fmd_dst->flow->psys != NULL); | |||||
| fmd_dst->flow->psys = psys_dst; | |||||
| } | |||||
| break; | |||||
| case eModifierType_DynamicPaint: | |||||
| if (psys_dst != NULL) { | |||||
| DynamicPaintModifierData *dpmd_dst = (DynamicPaintModifierData *)md_dst; | |||||
| BLI_assert(dpmd_dst->brush != NULL && dpmd_dst->brush->psys != NULL); | |||||
| dpmd_dst->brush->psys = psys_dst; | |||||
| } | |||||
| break; | |||||
| default: | |||||
| break; | |||||
| } | |||||
| BLI_addtail(&ob_dst->modifiers, md_dst); | |||||
| BKE_modifier_unique_name(&ob_dst->modifiers, md_dst); | |||||
| } | |||||
| BKE_object_modifier_set_active(ob_dst, md_dst); | |||||
| return true; | return true; | ||||
| } | } | ||||
| bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, GpencilModifierData *md) | /** Copy a single GPencil modifier. | ||||
| * | |||||
| * \note **Do not** use this function to copy a whole modifier stack. Use | |||||
| * `BKE_object_modifier_stack_copy` instead. */ | |||||
| bool BKE_object_copy_gpencil_modifier(struct Object *ob_dst, GpencilModifierData *gmd_src) | |||||
| { | { | ||||
| GpencilModifierData *nmd = BKE_gpencil_modifier_new(md->type); | BLI_assert(ob_dst->type == OB_GPENCIL); | ||||
| BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); | |||||
| const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(md->type); | GpencilModifierData *gmd_dst = BKE_gpencil_modifier_new(gmd_src->type); | ||||
| mti->copyData(md, nmd); | BLI_strncpy(gmd_dst->name, gmd_src->name, sizeof(gmd_dst->name)); | ||||
| BLI_addtail(&ob_dst->greasepencil_modifiers, nmd); | const GpencilModifierTypeInfo *mti = BKE_gpencil_modifier_get_info(gmd_src->type); | ||||
| BKE_gpencil_modifier_unique_name(&ob_dst->greasepencil_modifiers, nmd); | mti->copyData(gmd_src, gmd_dst); | ||||
| BLI_addtail(&ob_dst->greasepencil_modifiers, gmd_dst); | |||||
| BKE_gpencil_modifier_unique_name(&ob_dst->greasepencil_modifiers, gmd_dst); | |||||
| return true; | return true; | ||||
| } | } | ||||
| void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src) | /** | ||||
| * Copy the whole stack of modifiers from one object into another. | |||||
| * | |||||
| * \warning **Does not** clear modifier stack and related data (particle systems, softbody, | |||||
| * etc.) in `ob_dst`, if needed calling code must do it. | |||||
| * | |||||
| * @param do_copy_all If true, even modifiers that should not suport copying (like Hook one) will | |||||
| * be duplicated. | |||||
| */ | |||||
| bool BKE_object_modifier_stack_copy(Object *ob_dst, | |||||
| const Object *ob_src, | |||||
| const bool do_copy_all, | |||||
| const int flag_subdata) | |||||
| { | { | ||||
| BKE_object_free_modifiers(ob_dst, 0); | if ((ob_dst->type == OB_GPENCIL) != (ob_src->type == OB_GPENCIL)) { | ||||
| BLI_assert(!"Trying to copy a modifier stack between a GPencil object and another type."); | |||||
| return false; | |||||
| } | |||||
| if (!ELEM(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE, OB_GPENCIL)) { | if (!BLI_listbase_is_empty(&ob_dst->modifiers) || | ||||
| /* only objects listed above can have modifiers and linking them to objects | !BLI_listbase_is_empty(&ob_dst->greasepencil_modifiers)) { | ||||
| * which doesn't have modifiers stack is quite silly */ | BLI_assert( | ||||
| return; | !"Trying to copy a modifier stack into an object having a non-empty modifier stack."); | ||||
| return false; | |||||
| } | } | ||||
| /* No grease pencil modifiers. */ | LISTBASE_FOREACH (ModifierData *, md_src, &ob_src->modifiers) { | ||||
| if ((ob_src->type != OB_GPENCIL) && (ob_dst->type != OB_GPENCIL)) { | if (!do_copy_all && !object_modifier_type_copy_check(md_src->type)) { | ||||
| LISTBASE_FOREACH (ModifierData *, md, &ob_src->modifiers) { | continue; | ||||
| BKE_object_copy_modifier(ob_dst, ob_src, md); | } | ||||
| if (!BKE_object_support_modifier_type_check(ob_dst, md_src->type)) { | |||||
| continue; | |||||
| } | } | ||||
| ModifierData *md_dst = BKE_modifier_new(md_src->type); | |||||
| BLI_strncpy(md_dst->name, md_src->name, sizeof(md_dst->name)); | |||||
| BKE_modifier_copydata_ex(md_src, md_dst, flag_subdata); | |||||
| BLI_addtail(&ob_dst->modifiers, md_dst); | |||||
| } | } | ||||
| /* Copy grease pencil modifiers. */ | LISTBASE_FOREACH (GpencilModifierData *, gmd_src, &ob_src->greasepencil_modifiers) { | ||||
| if ((ob_src->type == OB_GPENCIL) && (ob_dst->type == OB_GPENCIL)) { | GpencilModifierData *gmd_dst = BKE_gpencil_modifier_new(gmd_src->type); | ||||
| LISTBASE_FOREACH (GpencilModifierData *, md, &ob_src->greasepencil_modifiers) { | BLI_strncpy(gmd_dst->name, gmd_src->name, sizeof(gmd_dst->name)); | ||||
| BKE_object_copy_gpencil_modifier(ob_dst, md); | BKE_gpencil_modifier_copydata_ex(gmd_src, gmd_dst, flag_subdata); | ||||
| BLI_addtail(&ob_dst->greasepencil_modifiers, gmd_dst); | |||||
| } | } | ||||
| /* This could be copied from anywhere, since no other modifier actually use this data. But for | |||||
| * consistency do it together with particle systems. */ | |||||
| BKE_object_copy_softbody(ob_dst, ob_src, flag_subdata); | |||||
| /* It is mandatory that this happens after copying modifiers, as it will update their `psys` | |||||
| * pointers accordingly. */ | |||||
| BKE_object_copy_particlesystems(ob_dst, ob_src, flag_subdata); | |||||
| return true; | |||||
| } | } | ||||
| BKE_object_copy_particlesystems(ob_dst, ob_src, 0); | void BKE_object_link_modifiers(Object *ob_dst, const Object *ob_src) | ||||
| { | |||||
| BKE_object_free_modifiers(ob_dst, 0); | |||||
| /* TODO: smoke?, cloth? */ | BKE_object_modifier_stack_copy(ob_dst, ob_src, false, 0); | ||||
| } | } | ||||
| /** | /** | ||||
| * Copy CCG related data. Used to sync copy of mesh with reshaped original mesh. | * Copy CCG related data. Used to sync copy of mesh with reshaped original mesh. | ||||
| */ | */ | ||||
| static void copy_ccg_data(Mesh *mesh_destination, Mesh *mesh_source, int layer_type) | static void copy_ccg_data(Mesh *mesh_destination, Mesh *mesh_source, int layer_type) | ||||
| { | { | ||||
| BLI_assert(mesh_destination->totloop == mesh_source->totloop); | BLI_assert(mesh_destination->totloop == mesh_source->totloop); | ||||
| ▲ Show 20 Lines • Show All 661 Lines • ▼ Show 20 Lines | Object *BKE_object_add_for_data( | ||||
| BKE_collection_object_add(bmain, layer_collection->collection, ob); | BKE_collection_object_add(bmain, layer_collection->collection, ob); | ||||
| Base *base = BKE_view_layer_base_find(view_layer, ob); | Base *base = BKE_view_layer_base_find(view_layer, ob); | ||||
| BKE_view_layer_base_select_and_set_active(view_layer, base); | BKE_view_layer_base_select_and_set_active(view_layer, base); | ||||
| return ob; | return ob; | ||||
| } | } | ||||
| void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src, const int flag) | void BKE_object_copy_softbody(Object *ob_dst, const Object *ob_src, const int flag) | ||||
| { | { | ||||
| SoftBody *sb = ob_src->soft; | SoftBody *sb = ob_src->soft; | ||||
| bool tagged_no_main = ob_dst->id.tag & LIB_TAG_NO_MAIN; | bool tagged_no_main = ob_dst->id.tag & LIB_TAG_NO_MAIN; | ||||
| ob_dst->softflag = ob_src->softflag; | ob_dst->softflag = ob_src->softflag; | ||||
| if (sb == NULL) { | if (sb == NULL) { | ||||
| ob_dst->soft = NULL; | ob_dst->soft = NULL; | ||||
| return; | return; | ||||
| Show All 27 Lines | else { | ||||
| } | } | ||||
| } | } | ||||
| sbn->keys = NULL; | sbn->keys = NULL; | ||||
| sbn->totkey = sbn->totpointkey = 0; | sbn->totkey = sbn->totpointkey = 0; | ||||
| sbn->scratch = NULL; | sbn->scratch = NULL; | ||||
| if (tagged_no_main == 0) { | if (!tagged_no_main) { | ||||
| sbn->shared = MEM_dupallocN(sb->shared); | sbn->shared = MEM_dupallocN(sb->shared); | ||||
| sbn->shared->pointcache = BKE_ptcache_copy_list( | sbn->shared->pointcache = BKE_ptcache_copy_list( | ||||
| &sbn->shared->ptcaches, &sb->shared->ptcaches, flag); | &sbn->shared->ptcaches, &sb->shared->ptcaches, flag); | ||||
| } | } | ||||
| if (sb->effector_weights) { | if (sb->effector_weights) { | ||||
| sbn->effector_weights = MEM_dupallocN(sb->effector_weights); | sbn->effector_weights = MEM_dupallocN(sb->effector_weights); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 3,323 Lines • Show Last 20 Lines | |||||
typo synamic -> dynamic