Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/library.c
| Show First 20 Lines • Show All 377 Lines • ▼ Show 20 Lines | |||||
| { | { | ||||
| /* We don't care whether ID is directly or indirectly linked in case we are making a whole lib local... */ | /* We don't care whether ID is directly or indirectly linked in case we are making a whole lib local... */ | ||||
| if (!lib_local && (id->tag & LIB_TAG_INDIRECT)) { | if (!lib_local && (id->tag & LIB_TAG_INDIRECT)) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| switch ((ID_Type)GS(id->name)) { | switch ((ID_Type)GS(id->name)) { | ||||
| case ID_SCE: | case ID_SCE: | ||||
| /* Partially implemented (has no copy...). */ | |||||
| if (!test) BKE_scene_make_local(bmain, (Scene *)id, lib_local); | if (!test) BKE_scene_make_local(bmain, (Scene *)id, lib_local); | ||||
| return true; | return true; | ||||
| case ID_OB: | case ID_OB: | ||||
| if (!test) BKE_object_make_local(bmain, (Object *)id, lib_local); | if (!test) BKE_object_make_local(bmain, (Object *)id, lib_local); | ||||
| return true; | return true; | ||||
| case ID_ME: | case ID_ME: | ||||
| if (!test) BKE_mesh_make_local(bmain, (Mesh *)id, lib_local); | if (!test) BKE_mesh_make_local(bmain, (Mesh *)id, lib_local); | ||||
| return true; | return true; | ||||
| Show All 23 Lines | case ID_CA: | ||||
| return true; | return true; | ||||
| case ID_SPK: | case ID_SPK: | ||||
| if (!test) BKE_speaker_make_local(bmain, (Speaker *)id, lib_local); | if (!test) BKE_speaker_make_local(bmain, (Speaker *)id, lib_local); | ||||
| return true; | return true; | ||||
| case ID_WO: | case ID_WO: | ||||
| if (!test) BKE_world_make_local(bmain, (World *)id, lib_local); | if (!test) BKE_world_make_local(bmain, (World *)id, lib_local); | ||||
| return true; | return true; | ||||
| case ID_VF: | case ID_VF: | ||||
| /* Partially implemented (has no copy...). */ | |||||
| if (!test) BKE_vfont_make_local(bmain, (VFont *)id, lib_local); | if (!test) BKE_vfont_make_local(bmain, (VFont *)id, lib_local); | ||||
| return true; | return true; | ||||
| case ID_TXT: | case ID_TXT: | ||||
| if (!test) BKE_text_make_local(bmain, (Text *)id, lib_local); | if (!test) BKE_text_make_local(bmain, (Text *)id, lib_local); | ||||
| return true; | return true; | ||||
| case ID_SO: | case ID_SO: | ||||
| /* Partially implemented (has no copy...). */ | |||||
| if (!test) BKE_sound_make_local(bmain, (bSound *)id, lib_local); | if (!test) BKE_sound_make_local(bmain, (bSound *)id, lib_local); | ||||
| return true; | return true; | ||||
| case ID_GR: | case ID_GR: | ||||
| if (!test) BKE_group_make_local(bmain, (Group *)id, lib_local); | if (!test) BKE_group_make_local(bmain, (Group *)id, lib_local); | ||||
| return true; | return true; | ||||
| case ID_AR: | case ID_AR: | ||||
| if (!test) BKE_armature_make_local(bmain, (bArmature *)id, lib_local); | if (!test) BKE_armature_make_local(bmain, (bArmature *)id, lib_local); | ||||
| return true; | return true; | ||||
| Show All 37 Lines | case ID_WM: | ||||
| return false; /* can't be linked */ | return false; /* can't be linked */ | ||||
| case ID_IP: | case ID_IP: | ||||
| return false; /* deprecated */ | return false; /* deprecated */ | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| struct IDCopyLibManagementData { | |||||
| const ID *id_src; | |||||
| int flag; | |||||
| }; | |||||
| /* Increases usercount as required, and remap self ID pointers. */ | |||||
| static int id_copy_libmanagement_cb(void *user_data, ID *id_self, ID **id_pointer, int cb_flag) | |||||
| { | |||||
| struct IDCopyLibManagementData *data = user_data; | |||||
| ID *id = *id_pointer; | |||||
| /* Remap self-references to new copied ID. */ | |||||
| if (id == data->id_src) { | |||||
| id = *id_pointer = id_self; | |||||
| } | |||||
| /* Increase used IDs refcount if needed and required. */ | |||||
| if ((data->flag & LIB_ID_COPY_NO_USER_REFCOUNT) == 0 && (cb_flag & IDWALK_CB_USER)) { | |||||
| id_us_plus(id); | |||||
| } | |||||
| return IDWALK_RET_NOP; | |||||
| } | |||||
| /** | /** | ||||
| * Invokes the appropriate copy method for the block and returns the result in | * Generic entry point for copying a datablock (new API). | ||||
| * newid, unless test. Returns true if the block can be copied. | * | ||||
| * \note Copy is only affecting given data-block (no ID used by copied one will be affected, besides usercount). | |||||
| * There is only one exception, if LIB_ID_COPY_ACTIONS is defined, actions used by animdata will be duplicated. | |||||
| * | |||||
| * \note Usercount of new copy is always set to 1. | |||||
| * | |||||
| * \param bmain Main database, may be NULL only if LIB_ID_COPY_NO_MAIN is specified. | |||||
| * \param id Source datablock. | |||||
| * \param r_newid Pointer to new (copied) ID pointer. | |||||
| * \param flag Set of copy options, see DNA_ID.h enum for details (leave to zero for default, full copy). | |||||
| * \param test If set, do not do any copy, just test whether copy is supported. | |||||
| * \return False when copying that ID type is not supported, true otherwise. | |||||
| */ | */ | ||||
| bool id_copy(Main *bmain, const ID *id, ID **newid, bool test) | /* XXX TODO remove test thing, *all* IDs should be copyable that way! */ | ||||
| bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, const bool test) | |||||
| { | { | ||||
| if (!test) { | #define LIB_ID_TYPES_NOCOPY ID_LI, ID_SCR, ID_WM, /* Not supported */ \ | ||||
| *newid = NULL; | ID_IP /* Deprecated */ | ||||
| BLI_assert(test || (r_newid != NULL)); | |||||
| if (r_newid != NULL) { | |||||
| *r_newid = NULL; | |||||
| } | |||||
| if (id == NULL) { | |||||
| return false; | |||||
| } | } | ||||
| /* conventions: | if (ELEM(GS(id->name), LIB_ID_TYPES_NOCOPY)) { | ||||
| * - make shallow copy, only this ID block | return false; | ||||
| * - id.us of the new ID is set to 1 */ | } | ||||
| else if (test) { | |||||
| return true; | |||||
| } | |||||
| BKE_libblock_copy_ex(bmain, id, r_newid, flag); | |||||
| switch ((ID_Type)GS(id->name)) { | switch ((ID_Type)GS(id->name)) { | ||||
| case ID_SCE: | |||||
| BKE_scene_copy_data(bmain, (Scene *)*r_newid, (Scene *)id, flag); | |||||
| break; | |||||
| case ID_OB: | case ID_OB: | ||||
| if (!test) *newid = (ID *)BKE_object_copy(bmain, (Object *)id); | BKE_object_copy_data(bmain, (Object *)*r_newid, (Object *)id, flag); | ||||
| return true; | break; | ||||
| case ID_ME: | case ID_ME: | ||||
| if (!test) *newid = (ID *)BKE_mesh_copy(bmain, (Mesh *)id); | BKE_mesh_copy_data(bmain, (Mesh *)*r_newid, (Mesh *)id, flag); | ||||
| return true; | break; | ||||
| case ID_CU: | case ID_CU: | ||||
| if (!test) *newid = (ID *)BKE_curve_copy(bmain, (Curve *)id); | BKE_curve_copy_data(bmain, (Curve *)*r_newid, (Curve *)id, flag); | ||||
| return true; | break; | ||||
| case ID_MB: | case ID_MB: | ||||
| if (!test) *newid = (ID *)BKE_mball_copy(bmain, (MetaBall *)id); | BKE_mball_copy_data(bmain, (MetaBall *)*r_newid, (MetaBall *)id, flag); | ||||
| return true; | break; | ||||
| case ID_MA: | case ID_MA: | ||||
| if (!test) *newid = (ID *)BKE_material_copy(bmain, (Material *)id); | BKE_material_copy_data(bmain, (Material *)*r_newid, (Material *)id, flag); | ||||
| return true; | break; | ||||
| case ID_TE: | case ID_TE: | ||||
| if (!test) *newid = (ID *)BKE_texture_copy(bmain, (Tex *)id); | BKE_texture_copy_data(bmain, (Tex *)*r_newid, (Tex *)id, flag); | ||||
| return true; | break; | ||||
| case ID_IM: | case ID_IM: | ||||
| if (!test) *newid = (ID *)BKE_image_copy(bmain, (Image *)id); | BKE_image_copy_data(bmain, (Image *)*r_newid, (Image *)id, flag); | ||||
| return true; | break; | ||||
| case ID_LT: | case ID_LT: | ||||
| if (!test) *newid = (ID *)BKE_lattice_copy(bmain, (Lattice *)id); | BKE_lattice_copy_data(bmain, (Lattice *)*r_newid, (Lattice *)id, flag); | ||||
| return true; | break; | ||||
| case ID_LA: | case ID_LA: | ||||
| if (!test) *newid = (ID *)BKE_lamp_copy(bmain, (Lamp *)id); | BKE_lamp_copy_data(bmain, (Lamp *)*r_newid, (Lamp *)id, flag); | ||||
| return true; | break; | ||||
| case ID_SPK: | case ID_SPK: | ||||
| if (!test) *newid = (ID *)BKE_speaker_copy(bmain, (Speaker *)id); | BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag); | ||||
| return true; | break; | ||||
| case ID_CA: | case ID_CA: | ||||
| if (!test) *newid = (ID *)BKE_camera_copy(bmain, (Camera *)id); | BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag); | ||||
| return true; | break; | ||||
| case ID_KE: | case ID_KE: | ||||
| if (!test) *newid = (ID *)BKE_key_copy(bmain, (Key *)id); | BKE_key_copy_data(bmain, (Key *)*r_newid, (Key *)id, flag); | ||||
| return true; | break; | ||||
| case ID_WO: | case ID_WO: | ||||
| if (!test) *newid = (ID *)BKE_world_copy(bmain, (World *)id); | BKE_world_copy_data(bmain, (World *)*r_newid, (World *)id, flag); | ||||
| return true; | break; | ||||
| case ID_TXT: | case ID_TXT: | ||||
| if (!test) *newid = (ID *)BKE_text_copy(bmain, (Text *)id); | BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag); | ||||
| return true; | break; | ||||
| case ID_GR: | case ID_GR: | ||||
| if (!test) *newid = (ID *)BKE_group_copy(bmain, (Group *)id); | BKE_group_copy_data(bmain, (Group *)*r_newid, (Group *)id, flag); | ||||
| return true; | break; | ||||
| case ID_AR: | case ID_AR: | ||||
| if (!test) *newid = (ID *)BKE_armature_copy(bmain, (bArmature *)id); | BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag); | ||||
| return true; | break; | ||||
| case ID_AC: | case ID_AC: | ||||
| if (!test) *newid = (ID *)BKE_action_copy(bmain, (bAction *)id); | BKE_action_copy_data(bmain, (bAction *)*r_newid, (bAction *)id, flag); | ||||
| return true; | break; | ||||
| case ID_NT: | case ID_NT: | ||||
| if (!test) *newid = (ID *)ntreeCopyTree(bmain, (bNodeTree *)id); | BKE_node_tree_copy_data(bmain, (bNodeTree *)*r_newid, (bNodeTree *)id, flag); | ||||
| return true; | break; | ||||
| case ID_BR: | case ID_BR: | ||||
| if (!test) *newid = (ID *)BKE_brush_copy(bmain, (Brush *)id); | BKE_brush_copy_data(bmain, (Brush *)*r_newid, (Brush *)id, flag); | ||||
| return true; | break; | ||||
| case ID_PA: | case ID_PA: | ||||
| if (!test) *newid = (ID *)BKE_particlesettings_copy(bmain, (ParticleSettings *)id); | BKE_particlesettings_copy_data(bmain, (ParticleSettings *)*r_newid, (ParticleSettings *)id, flag); | ||||
| return true; | break; | ||||
| case ID_GD: | case ID_GD: | ||||
| if (!test) *newid = (ID *)BKE_gpencil_data_duplicate(bmain, (bGPdata *)id, false); | BKE_gpencil_copy_data(bmain, (bGPdata *)*r_newid, (bGPdata *)id, flag); | ||||
| return true; | break; | ||||
| case ID_MC: | case ID_MC: | ||||
| if (!test) *newid = (ID *)BKE_movieclip_copy(bmain, (MovieClip *)id); | BKE_movieclip_copy_data(bmain, (MovieClip *)*r_newid, (MovieClip *)id, flag); | ||||
| return true; | break; | ||||
| case ID_MSK: | case ID_MSK: | ||||
| if (!test) *newid = (ID *)BKE_mask_copy(bmain, (Mask *)id); | BKE_mask_copy_data(bmain, (Mask *)*r_newid, (Mask *)id, flag); | ||||
| return true; | break; | ||||
| case ID_LS: | case ID_LS: | ||||
| if (!test) *newid = (ID *)BKE_linestyle_copy(bmain, (FreestyleLineStyle *)id); | BKE_linestyle_copy_data(bmain, (FreestyleLineStyle *)*r_newid, (FreestyleLineStyle *)id, flag); | ||||
| return true; | break; | ||||
| case ID_PAL: | case ID_PAL: | ||||
| if (!test) *newid = (ID *)BKE_palette_copy(bmain, (Palette *)id); | BKE_palette_copy_data(bmain, (Palette *)*r_newid, (Palette *)id, flag); | ||||
| return true; | break; | ||||
| case ID_PC: | case ID_PC: | ||||
| if (!test) *newid = (ID *)BKE_paint_curve_copy(bmain, (PaintCurve *)id); | BKE_paint_curve_copy_data(bmain, (PaintCurve *)*r_newid, (PaintCurve *)id, flag); | ||||
| return true; | break; | ||||
| case ID_CF: | case ID_CF: | ||||
| if (!test) *newid = (ID *)BKE_cachefile_copy(bmain, (CacheFile *)id); | BKE_cachefile_copy_data(bmain, (CacheFile *)*r_newid, (CacheFile *)id, flag); | ||||
| return true; | break; | ||||
| case ID_SCE: | case ID_SO: | ||||
| BKE_sound_copy_data(bmain, (bSound *)*r_newid, (bSound *)id, flag); | |||||
| break; | |||||
| case ID_VF: | |||||
| BKE_vfont_copy_data(bmain, (VFont *)*r_newid, (VFont *)id, flag); | |||||
| break; | |||||
| case ID_LI: | case ID_LI: | ||||
| case ID_SCR: | case ID_SCR: | ||||
| case ID_WM: | case ID_WM: | ||||
| return false; /* can't be copied from here */ | |||||
| case ID_VF: | |||||
| case ID_SO: | |||||
| return false; /* not implemented */ | |||||
| case ID_IP: | case ID_IP: | ||||
| return false; /* deprecated */ | BLI_assert(0); /* Should have been rejected at start of function! */ | ||||
| break; | |||||
| } | } | ||||
| return false; | /* Update ID refcount, remap pointers to self in new ID. */ | ||||
| struct IDCopyLibManagementData data = {.id_src=id, .flag=flag}; | |||||
| BKE_library_foreach_ID_link(bmain, *r_newid, id_copy_libmanagement_cb, &data, IDWALK_NOP); | |||||
| /* Do not make new copy local in case we are copying outside of main... | |||||
| * XXX TODO: is this behavior OK, or should we need own flag to control that? */ | |||||
| if ((flag & LIB_ID_COPY_NO_MAIN) == 0) { | |||||
| BKE_id_copy_ensure_local(bmain, id, *r_newid); | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /** | |||||
| * Invokes the appropriate copy method for the block and returns the result in | |||||
| * newid, unless test. Returns true if the block can be copied. | |||||
| */ | |||||
| bool id_copy(Main *bmain, const ID *id, ID **newid, bool test) | |||||
| { | |||||
| return BKE_id_copy_ex(bmain, id, newid, 0, test); | |||||
| } | } | ||||
| /** Does *not* set ID->newid pointer. */ | /** Does *not* set ID->newid pointer. */ | ||||
| bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) | bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) | ||||
| { | { | ||||
| ID *newid = NULL; | ID *newid = NULL; | ||||
| PointerRNA idptr; | PointerRNA idptr; | ||||
| ▲ Show 20 Lines • Show All 340 Lines • ▼ Show 20 Lines | if (id) { | ||||
| BLI_addtail(lb, id); | BLI_addtail(lb, id); | ||||
| id->us = 1; | id->us = 1; | ||||
| id->icon_id = 0; | id->icon_id = 0; | ||||
| *( (short *)id->name) = type; | *( (short *)id->name) = type; | ||||
| new_id(lb, id, name); | new_id(lb, id, name); | ||||
| /* alphabetic insertion: is in new_id */ | /* alphabetic insertion: is in new_id */ | ||||
| BKE_main_unlock(bmain); | BKE_main_unlock(bmain); | ||||
| } | } | ||||
| /* TODO to be removed from here! */ | |||||
| DAG_id_type_tag(bmain, type); | DAG_id_type_tag(bmain, type); | ||||
| return id; | return id; | ||||
| } | } | ||||
| /** | /** | ||||
| * Initialize an ID of given type, such that it has valid 'empty' data. | * Initialize an ID of given type, such that it has valid 'empty' data. | ||||
| * ID is assumed to be just calloc'ed. | * ID is assumed to be just calloc'ed. | ||||
| */ | */ | ||||
| ▲ Show 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | case ID_IP: | ||||
| break; | break; | ||||
| default: | default: | ||||
| BLI_assert(0); /* Should never reach this point... */ | BLI_assert(0); /* Should never reach this point... */ | ||||
| } | } | ||||
| } | } | ||||
| /* by spec, animdata is first item after ID */ | /* by spec, animdata is first item after ID */ | ||||
| /* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */ | /* and, trust that BKE_animdata_from_id() will only find AnimData for valid ID-types */ | ||||
| static void id_copy_animdata(ID *id, const bool do_action) | static void id_copy_animdata(Main *bmain, ID *id, const bool do_action) | ||||
| { | { | ||||
| AnimData *adt = BKE_animdata_from_id(id); | AnimData *adt = BKE_animdata_from_id(id); | ||||
| if (adt) { | if (adt) { | ||||
| IdAdtTemplate *iat = (IdAdtTemplate *)id; | IdAdtTemplate *iat = (IdAdtTemplate *)id; | ||||
| iat->adt = BKE_animdata_copy(iat->adt, do_action); /* could be set to false, need to investigate */ | iat->adt = BKE_animdata_copy(bmain, iat->adt, do_action); /* could be set to false, need to investigate */ | ||||
| } | } | ||||
| } | } | ||||
| /* material nodes use this since they are not treated as libdata */ | /* material nodes use this since they are not treated as libdata */ | ||||
| void BKE_libblock_copy_data(ID *id, const ID *id_from, const bool do_action) | void BKE_libblock_copy_data(Main *bmain, ID *id, const ID *id_from, const int flag) | ||||
| { | { | ||||
| if (id_from->properties) | if (id_from->properties) | ||||
| id->properties = IDP_CopyProperty(id_from->properties); | id->properties = IDP_CopyProperty_ex(id_from->properties, flag); | ||||
| /* the duplicate should get a copy of the animdata */ | /* the duplicate should get a copy of the animdata */ | ||||
| id_copy_animdata(id, do_action); | id_copy_animdata(bmain, id, (flag & LIB_ID_COPY_ACTIONS) != 0); | ||||
| } | } | ||||
| /* used everywhere in blenkernel */ | void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) | ||||
| void *BKE_libblock_copy(Main *bmain, const ID *id) | |||||
| { | { | ||||
| ID *idn; | ID *idn = *r_newid; | ||||
| size_t idn_len; | |||||
| idn = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2); | /* Grrrrrrrrr... Not adding 'root' nodetrees to bmain.... grrrrrrrrrrrrrrrrrrrr! */ | ||||
| /* This is taken from original ntree copy code, might be weak actually? */ | |||||
| const bool use_nodetree_alloc_exception = ((GS(id->name) == ID_NT) && (bmain != NULL) && | |||||
| (BLI_findindex(&bmain->nodetree, id) < 0)); | |||||
| assert(idn != NULL); | BLI_assert((flag & LIB_ID_COPY_NO_MAIN) != 0 || bmain != NULL); | ||||
| BLI_assert((flag & LIB_ID_COPY_NO_MAIN) != 0 || (flag & LIB_ID_COPY_NO_ALLOCATE) == 0); | |||||
| BLI_assert((flag & LIB_ID_COPY_NO_MAIN) == 0 || (flag & LIB_ID_COPY_NO_USER_REFCOUNT) != 0); | |||||
| if ((flag & LIB_ID_COPY_NO_ALLOCATE) != 0) { | |||||
| /* r_newid already contains pointer to allocated memory. */ | |||||
| /* TODO do we want to memset(0) whole mem before filling it? */ | |||||
| BLI_strncpy(idn->name, id->name, sizeof(idn->name)); | |||||
| idn->us = 1; | |||||
| /* TODO Do we want/need to copy more from ID struct itself? */ | |||||
| } | |||||
| else if ((flag & LIB_ID_COPY_NO_MAIN) != 0 || use_nodetree_alloc_exception) { | |||||
| /* Allocate r_newid but do not register it in Main database. */ | |||||
| idn = BKE_libblock_alloc_notest(GS(id->name)); | |||||
| BLI_strncpy(idn->name, id->name, sizeof(idn->name)); | |||||
| idn->us = 1; | |||||
| } | |||||
| else { | |||||
| idn = BKE_libblock_alloc(bmain, GS(id->name), id->name + 2); | |||||
| } | |||||
| BLI_assert(idn != NULL); | |||||
| idn_len = MEM_allocN_len(idn); | const size_t id_len = BKE_libblock_get_alloc_info(GS(idn->name), NULL); | ||||
| if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */ | const size_t id_offset = sizeof(ID); | ||||
| if ((int)id_len - (int)id_offset > 0) { /* signed to allow neg result */ /* XXX ????? */ | |||||
| const char *cp = (const char *)id; | const char *cp = (const char *)id; | ||||
| char *cpn = (char *)idn; | char *cpn = (char *)idn; | ||||
| memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID)); | memcpy(cpn + id_offset, cp + id_offset, id_len - id_offset); | ||||
| } | } | ||||
| BKE_libblock_copy_data(idn, id, false); | /* TODO we can remove that one later and bring its code here. */ | ||||
| BKE_libblock_copy_data(bmain, idn, id, flag); | |||||
| return idn; | if ((flag & LIB_ID_COPY_NO_MAIN) != 0) { | ||||
| idn->tag |= LIB_TAG_FREE_NO_MAIN; | |||||
| } | |||||
| if ((flag & LIB_ID_COPY_NO_USER_REFCOUNT) != 0) { | |||||
| idn->tag |= LIB_TAG_FREE_NO_USER_REFCOUNT; | |||||
| } | |||||
| if ((flag & LIB_ID_COPY_NO_ALLOCATE) != 0) { | |||||
| idn->tag |= LIB_TAG_FREE_NOT_ALLOCATED; | |||||
| } | } | ||||
| void *BKE_libblock_copy_nolib(const ID *id, const bool do_action) | if ((flag & LIB_ID_COPY_NO_DEG_TAG) == 0 && (flag & LIB_ID_COPY_NO_MAIN) == 0) { | ||||
| { | DAG_id_type_tag(bmain, GS(idn->name)); | ||||
| ID *idn; | } | ||||
| size_t idn_len; | |||||
| idn = BKE_libblock_alloc_notest(GS(id->name)); | *r_newid = idn; | ||||
| assert(idn != NULL); | } | ||||
| BLI_strncpy(idn->name, id->name, sizeof(idn->name)); | /* used everywhere in blenkernel */ | ||||
| void *BKE_libblock_copy(Main *bmain, const ID *id) | |||||
| { | |||||
| ID *idn; | |||||
| idn_len = MEM_allocN_len(idn); | BKE_libblock_copy_ex(bmain, id, &idn, 0); | ||||
| if ((int)idn_len - (int)sizeof(ID) > 0) { /* signed to allow neg result */ | |||||
| const char *cp = (const char *)id; | |||||
| char *cpn = (char *)idn; | |||||
| memcpy(cpn + sizeof(ID), cp + sizeof(ID), idn_len - sizeof(ID)); | return idn; | ||||
| } | } | ||||
| idn->us = 1; | void *BKE_libblock_copy_nolib(const ID *id, const bool do_action) | ||||
| { | |||||
| ID *idn; | |||||
| BKE_libblock_copy_data(idn, id, do_action); | BKE_libblock_copy_ex(NULL, id, &idn, LIB_ID_COPY_NO_MAIN | LIB_ID_COPY_NO_USER_REFCOUNT | (do_action ? LIB_ID_COPY_ACTIONS : 0)); | ||||
| return idn; | return idn; | ||||
| } | } | ||||
| void BKE_library_free(Library *lib) | void BKE_library_free(Library *lib) | ||||
| { | { | ||||
| if (lib->packedfile) | if (lib->packedfile) | ||||
| freePackedFile(lib->packedfile); | freePackedFile(lib->packedfile); | ||||
| ▲ Show 20 Lines • Show All 1,044 Lines • Show Last 20 Lines | |||||