int id_copy(ID *id, ID **newid, int test) { if (!test) *newid = NULL; /* conventions: * - make shallow copy, only this ID block * - id.us of the new ID is set to 1 */ switch (GS(id->name)) { case ID_SCE: return 0; /* can't be copied from here */ case ID_LI: return 0; /* can't be copied from here */ case ID_OB: if (!test) *newid = (ID *)BKE_object_copy((Object *)id); return 1; case ID_ME: if (!test) *newid = (ID *)BKE_mesh_copy((Mesh *)id); return 1; case ID_CU: if (!test) *newid = (ID *)BKE_curve_copy((Curve *)id); return 1; case ID_MB: if (!test) *newid = (ID *)BKE_mball_copy((MetaBall *)id); return 1; case ID_MA: if (!test) *newid = (ID *)BKE_material_copy((Material *)id); return 1; case ID_TE: if (!test) *newid = (ID *)BKE_texture_copy((Tex *)id); return 1; case ID_IM: if (!test) *newid = (ID *)BKE_image_copy((Image *)id); return 1; case ID_LT: if (!test) *newid = (ID *)BKE_lattice_copy((Lattice *)id); return 1; case ID_LA: if (!test) *newid = (ID *)BKE_lamp_copy((Lamp *)id); return 1; case ID_SPK: if (!test) *newid = (ID *)BKE_speaker_copy((Speaker *)id); return 1; case ID_CA: if (!test) *newid = (ID *)BKE_camera_copy((Camera *)id); return 1; case ID_IP: return 0; /* deprecated */ case ID_KE: if (!test) *newid = (ID *)BKE_key_copy((Key *)id); return 1; case ID_WO: if (!test) *newid = (ID *)BKE_world_copy((World *)id); return 1; case ID_SCR: return 0; /* can't be copied from here */ case ID_VF: return 0; /* not implemented */ case ID_TXT: if (!test) *newid = (ID *)BKE_text_copy((Text *)id); return 1; case ID_SCRIPT: return 0; /* deprecated */ case ID_SO: return 0; /* not implemented */ case ID_GR: if (!test) *newid = (ID *)BKE_group_copy((Group *)id); return 1; case ID_AR: if (!test) *newid = (ID *)BKE_armature_copy((bArmature *)id); return 1; case ID_AC: if (!test) *newid = (ID *)BKE_action_copy((bAction *)id); return 1; case ID_NT: if (!test) *newid = (ID *)ntreeCopyTree((bNodeTree *)id); return 1; case ID_BR: if (!test) *newid = (ID *)BKE_brush_copy((Brush *)id); return 1; case ID_PA: if (!test) *newid = (ID *)BKE_particlesettings_copy((ParticleSettings *)id); return 1; case ID_WM: return 0; /* can't be copied from here */ case ID_GD: return 0; /* not implemented */ } return 0; }
/* This function merges a mesh from the current scene into another main * it does not convert */ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name) { /* Find a mesh in the current main */ ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2)); if (me==NULL) { printf("Could not be found \"%s\"\n", name); return NULL; } /* Watch this!, if its used in the original scene can cause big troubles */ if (me->us > 0) { printf("Mesh has a user \"%s\"\n", name); me = (ID*)BKE_mesh_copy((Mesh*)me); me->us--; } BLI_remlink(&m_maggie->mesh, me); /* even if we made the copy it needs to be removed */ BLI_addtail(&maggie->mesh, me); /* Must copy the materials this uses else we cant free them */ { Mesh *mesh= (Mesh *)me; /* ensure all materials are tagged */ for (int i=0; i<mesh->totcol; i++) if (mesh->mat[i]) mesh->mat[i]->id.flag &= ~LIB_DOIT; for (int i=0; i<mesh->totcol; i++) { Material *mat_old= mesh->mat[i]; /* if its tagged its a replaced material */ if (mat_old && (mat_old->id.flag & LIB_DOIT)==0) { Material *mat_old= mesh->mat[i]; Material *mat_new= BKE_material_copy( mat_old ); mat_new->id.flag |= LIB_DOIT; mat_old->id.us--; BLI_remlink(&m_maggie->mat, mat_new); BLI_addtail(&maggie->mat, mat_new); mesh->mat[i]= mat_new; /* the same material may be used twice */ for (int j=i+1; j<mesh->totcol; j++) { if (mesh->mat[j]==mat_old) { mesh->mat[j]= mat_new; mat_new->id.us++; mat_old->id.us--; } } } } } RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this); kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */ return meshobj; }
/* This function merges a mesh from the current scene into another main * it does not convert */ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const char *name) { /* Find a mesh in the current main */ ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2)); Main *from_maggie = m_maggie; if (me == NULL) { // The mesh wasn't in the current main, try any dynamic (i.e., LibLoaded) ones vector<Main *>::iterator it; for (it = GetMainDynamic().begin(); it != GetMainDynamic().end(); it++) { me = static_cast<ID *>(BLI_findstring(&(*it)->mesh, name, offsetof(ID, name) + 2)); from_maggie = *it; if (me) break; } } if (me == NULL) { printf("Could not be found \"%s\"\n", name); return NULL; } /* Watch this!, if its used in the original scene can cause big troubles */ if (me->us > 0) { #ifdef DEBUG printf("Mesh has a user \"%s\"\n", name); #endif me = (ID*)BKE_mesh_copy_ex(from_maggie, (Mesh*)me); id_us_min(me); } BLI_remlink(&from_maggie->mesh, me); /* even if we made the copy it needs to be removed */ BLI_addtail(&maggie->mesh, me); /* Must copy the materials this uses else we cant free them */ { Mesh *mesh = (Mesh *)me; /* ensure all materials are tagged */ for (int i = 0; i < mesh->totcol; i++) { if (mesh->mat[i]) mesh->mat[i]->id.tag &= ~LIB_TAG_DOIT; } for (int i = 0; i < mesh->totcol; i++) { Material *mat_old = mesh->mat[i]; /* if its tagged its a replaced material */ if (mat_old && (mat_old->id.tag & LIB_TAG_DOIT) == 0) { Material *mat_old = mesh->mat[i]; Material *mat_new = BKE_material_copy(mat_old); mat_new->id.tag |= LIB_TAG_DOIT; id_us_min(&mat_old->id); BLI_remlink(&G.main->mat, mat_new); // BKE_material_copy uses G.main, and there is no BKE_material_copy_ex BLI_addtail(&maggie->mat, mat_new); mesh->mat[i] = mat_new; /* the same material may be used twice */ for (int j = i + 1; j < mesh->totcol; j++) { if (mesh->mat[j] == mat_old) { mesh->mat[j] = mat_new; id_us_plus(&mat_new->id); id_us_min(&mat_old->id); } } } } } m_currentScene = kx_scene; // This needs to be set in case we LibLoaded earlier RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this, false); kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */ return meshobj; }