Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/object/object_add.c
| Show First 20 Lines • Show All 2,202 Lines • ▼ Show 20 Lines | |||||
| * U.dupflag for default operations or you can construct a flag as python does | * U.dupflag for default operations or you can construct a flag as python does | ||||
| * if the dupflag is 0 then no data will be copied (linked duplicate) */ | * if the dupflag is 0 then no data will be copied (linked duplicate) */ | ||||
| /* used below, assumes id.new is correct */ | /* used below, assumes id.new is correct */ | ||||
| /* leaves selection of base/object unaltered */ | /* leaves selection of base/object unaltered */ | ||||
| /* Does set ID->newid pointers. */ | /* Does set ID->newid pointers. */ | ||||
| static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag) | static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, ViewLayer *view_layer, Object *ob, int dupflag) | ||||
| { | { | ||||
| #define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; } | |||||
| #define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; } | |||||
| Base *base, *basen = NULL; | Base *base, *basen = NULL; | ||||
| Material ***matarar; | |||||
| Object *obn; | Object *obn; | ||||
| ID *id; | |||||
| int a, didit; | |||||
| if (ob->mode & OB_MODE_POSE) { | if (ob->mode & OB_MODE_POSE) { | ||||
| ; /* nothing? */ | ; /* nothing? */ | ||||
| } | } | ||||
| else { | else { | ||||
| obn = ID_NEW_SET(ob, BKE_object_copy(bmain, ob)); | obn = ID_NEW_SET(ob, BKE_object_duplicate(bmain, ob, dupflag)); | ||||
| DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); | DEG_id_tag_update(&obn->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY); | ||||
| base = BKE_view_layer_base_find(view_layer, ob); | base = BKE_view_layer_base_find(view_layer, ob); | ||||
| if ((base != NULL) && (base->flag & BASE_VISIBLE)) { | if ((base != NULL) && (base->flag & BASE_VISIBLE)) { | ||||
| BKE_collection_object_add_from(bmain, scene, ob, obn); | BKE_collection_object_add_from(bmain, scene, ob, obn); | ||||
| } | } | ||||
| else { | else { | ||||
| LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); | LayerCollection *layer_collection = BKE_layer_collection_get_active(view_layer); | ||||
| Show All 11 Lines | else { | ||||
| // XXX: is 2) really a good measure here? | // XXX: is 2) really a good measure here? | ||||
| if (ob->rigidbody_object || ob->rigidbody_constraint) { | if (ob->rigidbody_object || ob->rigidbody_constraint) { | ||||
| Collection *collection; | Collection *collection; | ||||
| for (collection = bmain->collection.first; collection; collection = collection->id.next) { | for (collection = bmain->collection.first; collection; collection = collection->id.next) { | ||||
| if (BKE_collection_has_object(collection, ob)) | if (BKE_collection_has_object(collection, ob)) | ||||
| BKE_collection_object_add(bmain, collection, obn); | BKE_collection_object_add(bmain, collection, obn); | ||||
| } | } | ||||
| } | } | ||||
| /* duplicates using userflags */ | |||||
| if (dupflag & USER_DUP_ACT) { | |||||
| BKE_animdata_copy_id_action(bmain, &obn->id, true); | |||||
| } | |||||
| if (dupflag & USER_DUP_MAT) { | |||||
| for (a = 0; a < obn->totcol; a++) { | |||||
| id = (ID *)obn->mat[a]; | |||||
| if (id) { | |||||
| ID_NEW_REMAP_US(obn->mat[a]) | |||||
| else { | |||||
| obn->mat[a] = ID_NEW_SET(obn->mat[a], BKE_material_copy(bmain, obn->mat[a])); | |||||
| } | |||||
| id_us_min(id); | |||||
| if (dupflag & USER_DUP_ACT) { | |||||
| BKE_animdata_copy_id_action(bmain, &obn->mat[a]->id, true); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| if (dupflag & USER_DUP_PSYS) { | |||||
| ParticleSystem *psys; | |||||
| for (psys = obn->particlesystem.first; psys; psys = psys->next) { | |||||
| id = (ID *) psys->part; | |||||
| if (id) { | |||||
| ID_NEW_REMAP_US(psys->part) | |||||
| else { | |||||
| psys->part = ID_NEW_SET(psys->part, BKE_particlesettings_copy(bmain, psys->part)); | |||||
| } | |||||
| if (dupflag & USER_DUP_ACT) { | |||||
| BKE_animdata_copy_id_action(bmain, &psys->part->id, true); | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| } | |||||
| } | |||||
| id = obn->data; | |||||
| didit = 0; | |||||
| switch (obn->type) { | |||||
| case OB_MESH: | |||||
| if (dupflag & USER_DUP_MESH) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_mesh_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_CURVE: | |||||
| if (dupflag & USER_DUP_CURVE) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_SURF: | |||||
| if (dupflag & USER_DUP_SURF) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_FONT: | |||||
| if (dupflag & USER_DUP_FONT) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_MBALL: | |||||
| if (dupflag & USER_DUP_MBALL) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_mball_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_LAMP: | |||||
| if (dupflag & USER_DUP_LAMP) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_light_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_ARMATURE: | |||||
| DEG_id_tag_update(&obn->id, ID_RECALC_GEOMETRY); | |||||
| if (obn->pose) | |||||
| BKE_pose_tag_recalc(bmain, obn->pose); | |||||
| if (dupflag & USER_DUP_ARM) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data)); | |||||
| BKE_pose_rebuild(bmain, obn, obn->data, true); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_LATTICE: | |||||
| if (dupflag != 0) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_lattice_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_CAMERA: | |||||
| if (dupflag != 0) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_camera_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_LIGHTPROBE: | |||||
| if (dupflag != 0) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_lightprobe_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_SPEAKER: | |||||
| if (dupflag != 0) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_speaker_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| case OB_GPENCIL: | |||||
| if (dupflag != 0) { | |||||
| ID_NEW_REMAP_US2(obn->data) | |||||
| else { | |||||
| obn->data = ID_NEW_SET(obn->data, BKE_gpencil_copy(bmain, obn->data)); | |||||
| didit = 1; | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| break; | |||||
| } | |||||
| /* check if obdata is copied */ | |||||
| if (didit) { | |||||
| Key *key = BKE_key_from_object(obn); | |||||
| Key *oldkey = BKE_key_from_object(ob); | |||||
| if (oldkey != NULL) { | |||||
| ID_NEW_SET(oldkey, key); | |||||
| } | |||||
| if (dupflag & USER_DUP_ACT) { | |||||
| BKE_animdata_copy_id_action(bmain, (ID *)obn->data, true); | |||||
| if (key) { | |||||
| BKE_animdata_copy_id_action(bmain, (ID *)key, true); | |||||
| } | |||||
| } | |||||
| if (dupflag & USER_DUP_MAT) { | |||||
| matarar = give_matarar(obn); | |||||
| if (matarar) { | |||||
| for (a = 0; a < obn->totcol; a++) { | |||||
| id = (ID *)(*matarar)[a]; | |||||
| if (id) { | |||||
| ID_NEW_REMAP_US((*matarar)[a]) | |||||
| else { | |||||
| (*matarar)[a] = ID_NEW_SET((*matarar)[a], BKE_material_copy(bmain, (*matarar)[a])); | |||||
| } | |||||
| id_us_min(id); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | } | ||||
| return basen; | return basen; | ||||
| #undef ID_NEW_REMAP_US | |||||
| #undef ID_NEW_REMAP_US2 | |||||
| } | } | ||||
| /* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */ | /* single object duplicate, if dupflag==0, fully linked, else it uses the flags given */ | ||||
| /* leaves selection of base/object unaltered. | /* leaves selection of base/object unaltered. | ||||
| * note: don't call this within a loop since clear_* funcs loop over the entire database. | * note: don't call this within a loop since clear_* funcs loop over the entire database. | ||||
| * note: caller must do DAG_relations_tag_update(bmain); | * note: caller must do DAG_relations_tag_update(bmain); | ||||
| * this is not done automatic since we may duplicate many objects in a batch */ | * this is not done automatic since we may duplicate many objects in a batch */ | ||||
| Base *ED_object_add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag) | Base *ED_object_add_duplicate(Main *bmain, Scene *scene, ViewLayer *view_layer, Base *base, int dupflag) | ||||
| ▲ Show 20 Lines • Show All 274 Lines • Show Last 20 Lines | |||||