diff options
-rw-r--r-- | source/blender/blenkernel/BKE_idtype.h | 142 | ||||
-rw-r--r-- | source/blender/blenkernel/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/idtype.c | 81 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lib_id.c | 255 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lib_id_delete.c | 10 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 448 | ||||
-rw-r--r-- | source/creator/creator.c | 2 | ||||
-rw-r--r-- | tests/gtests/blenloader/blendfile_loading_base_test.cc | 3 |
8 files changed, 636 insertions, 307 deletions
diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h new file mode 100644 index 00000000000..ba0cf04dfc6 --- /dev/null +++ b/source/blender/blenkernel/BKE_idtype.h @@ -0,0 +1,142 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + */ + +#ifndef __BKE_IDTYPE_H__ +#define __BKE_IDTYPE_H__ + +/** \file + * \ingroup bke + * + * ID type structure, helping to factorize common operations and data for all data-block types. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct ID; +struct Main; + +/** IDTypeInfo.flags. */ +enum { + /** Indicates that the given IDType does not support copying. */ + IDTYPE_FLAGS_NO_COPY = 1 << 0, + /** Indicates that the given IDType does not support linking/appending from a library file. */ + IDTYPE_FLAGS_NO_LIBLINKING = 1 << 1, + /** Indicates that the given IDType does not support making a library-linked ID local. */ + IDTYPE_FLAGS_NO_MAKELOCAL = 1 << 2, +}; + +/* ********** Prototypes for IDTypeInfo callbacks. ********** */ + +typedef void (*IDTypeInitDataFunction)(struct ID *id); + +/** \param flag: Copying options (see BKE_lib_id.h's LIB_ID_COPY_... flags for more). */ +typedef void (*IDTypeCopyDataFunction)(struct Main *bmain, + struct ID *id_dst, + const struct ID *id_src, + const int flag); + +typedef void (*IDTypeFreeDataFunction)(struct ID *id); + +/** \param flag: See BKE_lib_id.h's LIB_ID_MAKELOCAL_... flags. */ +typedef void (*IDTypeMakeLocalFunction)(struct Main *bmain, struct ID *id, const int flags); + +typedef struct IDTypeInfo { + /* ********** General IDType data. ********** */ + + /** + * Unique identifier of this type, either as a short or an array of two chars, see DNA_ID.h's + * ID_XX enums. + */ + short id_code; + /** + * Bitflag matching id_code, used for filtering (e.g. in file browser), see DNA_ID.h's + * FILTER_ID_XX enums. + */ + int id_filter; + + /** + * Define the position of this data-block type in the virtual list of all data in a Main that is + * returned by `set_listbasepointers()`. + * Very important, this has to be unique and below INDEX_ID_MAX, see DNA_ID.h. + */ + short main_listbase_index; + + /** Memory size of a data-block of that type. */ + size_t struct_size; + + /** The user visible name for this data-block, also used as default name for a new data-block. */ + const char *name; + /** Plural version of the user-visble name. */ + const char *name_plural; + /** Translation context to use for UI messages related to that type of data-block. */ + const char *translation_context; + + /** Generic info flags about that data-block type. */ + int flags; + + /* ********** ID management callbacks ********** */ + + /* TODO: Note about callbacks: Ideally we could also handle here `BKE_lib_query`'s behavior, as + * well as read/write of files. However, this is a bit more involved than basic ID management + * callbacks, so we'll check on this later. */ + + /** + * Initialize a new, empty calloc'ed data-block. May be NULL if there is nothing to do. + */ + IDTypeInitDataFunction init_data; + + /** + * Copy the given data-block's data from source to destination. May be NULL if mere memcopy of + * the ID struct itself is enough. + */ + IDTypeCopyDataFunction copy_data; + + /** + * Free the data of the data-block (NOT the ID itself). May be NULL if there is nothing to do. + */ + IDTypeFreeDataFunction free_data; + + /** + * Make a linked data-block local. May be NULL if default behavior from + * `BKE_lib_id_make_local_generic()` is enough. + */ + IDTypeMakeLocalFunction make_local; +} IDTypeInfo; + +/* ********** Declaration of each IDTypeInfo. ********** */ + +/* Those are defined in the respective BKE files. */ +extern IDTypeInfo IDType_ID_OB; + +/* ********** Helpers/Utils API. ********** */ + +/* Module initialization. */ +void BKE_idtype_init(void); + +/* General helpers. */ +const struct IDTypeInfo *BKE_idtype_get_info_from_idcode(const short id_code); +const struct IDTypeInfo *BKE_idtype_get_info_from_id(const struct ID *id); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_IDTYPE_H__ */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 0a3b2450390..87ac82aaa55 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -125,6 +125,7 @@ set(SRC intern/idcode.c intern/idprop.c intern/idprop_utils.c + intern/idtype.c intern/image.c intern/image_gen.c intern/image_save.c @@ -292,6 +293,7 @@ set(SRC BKE_icons.h BKE_idcode.h BKE_idprop.h + BKE_idtype.h BKE_image.h BKE_image_save.h BKE_ipo.h diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c new file mode 100644 index 00000000000..494d83535b4 --- /dev/null +++ b/source/blender/blenkernel/intern/idtype.c @@ -0,0 +1,81 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2005 by the Blender Foundation. + * All rights reserved. + * Modifier stack implementation. + * + * BKE_modifier.h contains the function prototypes for this file. + */ + +/** \file + * \ingroup bke + */ + +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" + +#include "CLG_log.h" + +#include "BLT_translation.h" + +#include "DNA_ID.h" + +#include "BKE_idcode.h" + +#include "BKE_idtype.h" + +// static CLG_LogRef LOG = {"bke.idtype"}; + +static IDTypeInfo *id_types[INDEX_ID_MAX] = {NULL}; + +static void id_type_init(void) +{ +#define INIT_TYPE(_id_code) \ + { \ + BLI_assert(IDType_##_id_code.main_listbase_index == INDEX_##_id_code); \ + id_types[INDEX_##_id_code] = &IDType_##_id_code; \ + } \ + (void)0 + + INIT_TYPE(ID_OB); + +#undef INIT_TYPE +} + +void BKE_idtype_init(void) +{ + /* Initialize data-block types. */ + id_type_init(); +} + +const IDTypeInfo *BKE_idtype_get_info_from_idcode(const short id_code) +{ + int id_index = BKE_idcode_to_index(id_code); + + if (id_index >= 0 && id_index < INDEX_ID_MAX && id_types[id_index] != NULL && + id_types[id_index]->name[0] != '\0') { + return id_types[id_index]; + } + else { + return NULL; + } +} + +const IDTypeInfo *BKE_idtype_get_info_from_id(const ID *id) +{ + return BKE_idtype_get_info_from_idcode(GS(id->name)); +} diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 73a03294c51..416de844691 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -91,6 +91,7 @@ #include "BKE_gpencil.h" #include "BKE_idcode.h" #include "BKE_idprop.h" +#include "BKE_idtype.h" #include "BKE_image.h" #include "BKE_key.h" #include "BKE_light.h" @@ -447,6 +448,23 @@ bool BKE_lib_id_make_local(Main *bmain, ID *id, const bool test, const int flags return false; } + const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id); + + if (idtype_info != NULL) { + if ((idtype_info->flags & IDTYPE_FLAGS_NO_MAKELOCAL) == 0) { + if (!test) { + if (idtype_info->make_local != NULL) { + idtype_info->make_local(bmain, id, flags); + } + else { + BKE_lib_id_make_local_generic(bmain, id, flags); + } + } + return true; + } + return false; + } + switch ((ID_Type)GS(id->name)) { case ID_SCE: if (!test) { @@ -689,115 +707,131 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag) if (id == NULL) { return false; } - if (!BKE_id_copy_is_allowed(id)) { - return false; + + const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id); + + if (idtype_info != NULL) { + if ((idtype_info->flags & IDTYPE_FLAGS_NO_COPY) != 0) { + return false; + } + + BKE_libblock_copy_ex(bmain, id, r_newid, flag); + + if (idtype_info->copy_data != NULL) { + idtype_info->copy_data(bmain, *r_newid, id, flag); + } } + else { + if (!BKE_id_copy_is_allowed(id)) { + return false; + } - BKE_libblock_copy_ex(bmain, id, r_newid, flag); + BKE_libblock_copy_ex(bmain, id, r_newid, flag); - switch ((ID_Type)GS(id->name)) { - case ID_SCE: - BKE_scene_copy_data(bmain, (Scene *)*r_newid, (Scene *)id, flag); - break; - case ID_OB: - BKE_object_copy_data(bmain, (Object *)*r_newid, (Object *)id, flag); - break; - case ID_ME: - BKE_mesh_copy_data(bmain, (Mesh *)*r_newid, (Mesh *)id, flag); - break; - case ID_CU: - BKE_curve_copy_data(bmain, (Curve *)*r_newid, (Curve *)id, flag); - break; - case ID_MB: - BKE_mball_copy_data(bmain, (MetaBall *)*r_newid, (MetaBall *)id, flag); - break; - case ID_MA: - BKE_material_copy_data(bmain, (Material *)*r_newid, (Material *)id, flag); - break; - case ID_TE: - BKE_texture_copy_data(bmain, (Tex *)*r_newid, (Tex *)id, flag); - break; - case ID_IM: - BKE_image_copy_data(bmain, (Image *)*r_newid, (Image *)id, flag); - break; - case ID_LT: - BKE_lattice_copy_data(bmain, (Lattice *)*r_newid, (Lattice *)id, flag); - break; - case ID_LA: - BKE_light_copy_data(bmain, (Light *)*r_newid, (Light *)id, flag); - break; - case ID_SPK: - BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag); - break; - case ID_LP: - BKE_lightprobe_copy_data(bmain, (LightProbe *)*r_newid, (LightProbe *)id, flag); - break; - case ID_CA: - BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag); - break; - case ID_KE: - BKE_key_copy_data(bmain, (Key *)*r_newid, (Key *)id, flag); - break; - case ID_WO: - BKE_world_copy_data(bmain, (World *)*r_newid, (World *)id, flag); - break; - case ID_TXT: - BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag); - break; - case ID_GR: - BKE_collection_copy_data(bmain, (Collection *)*r_newid, (Collection *)id, flag); - break; - case ID_AR: - BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag); - break; - case ID_AC: - BKE_action_copy_data(bmain, (bAction *)*r_newid, (bAction *)id, flag); - break; - case ID_NT: - BKE_node_tree_copy_data(bmain, (bNodeTree *)*r_newid, (bNodeTree *)id, flag); - break; - case ID_BR: - BKE_brush_copy_data(bmain, (Brush *)*r_newid, (Brush *)id, flag); - break; - case ID_PA: - BKE_particlesettings_copy_data( - bmain, (ParticleSettings *)*r_newid, (ParticleSettings *)id, flag); - break; - case ID_GD: - BKE_gpencil_copy_data((bGPdata *)*r_newid, (bGPdata *)id, flag); - break; - case ID_MC: - BKE_movieclip_copy_data(bmain, (MovieClip *)*r_newid, (MovieClip *)id, flag); - break; - case ID_MSK: - BKE_mask_copy_data(bmain, (Mask *)*r_newid, (Mask *)id, flag); - break; - case ID_LS: - BKE_linestyle_copy_data( - bmain, (FreestyleLineStyle *)*r_newid, (FreestyleLineStyle *)id, flag); - break; - case ID_PAL: - BKE_palette_copy_data(bmain, (Palette *)*r_newid, (Palette *)id, flag); - break; - case ID_PC: - BKE_paint_curve_copy_data(bmain, (PaintCurve *)*r_newid, (PaintCurve *)id, flag); - break; - case ID_CF: - BKE_cachefile_copy_data(bmain, (CacheFile *)*r_newid, (CacheFile *)id, flag); - break; - 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_SCR: - case ID_WM: - case ID_WS: - case ID_IP: - BLI_assert(0); /* Should have been rejected at start of function! */ - break; + switch ((ID_Type)GS(id->name)) { + case ID_SCE: + BKE_scene_copy_data(bmain, (Scene *)*r_newid, (Scene *)id, flag); + break; + case ID_OB: + BKE_object_copy_data(bmain, (Object *)*r_newid, (Object *)id, flag); + break; + case ID_ME: + BKE_mesh_copy_data(bmain, (Mesh *)*r_newid, (Mesh *)id, flag); + break; + case ID_CU: + BKE_curve_copy_data(bmain, (Curve *)*r_newid, (Curve *)id, flag); + break; + case ID_MB: + BKE_mball_copy_data(bmain, (MetaBall *)*r_newid, (MetaBall *)id, flag); + break; + case ID_MA: + BKE_material_copy_data(bmain, (Material *)*r_newid, (Material *)id, flag); + break; + case ID_TE: + BKE_texture_copy_data(bmain, (Tex *)*r_newid, (Tex *)id, flag); + break; + case ID_IM: + BKE_image_copy_data(bmain, (Image *)*r_newid, (Image *)id, flag); + break; + case ID_LT: + BKE_lattice_copy_data(bmain, (Lattice *)*r_newid, (Lattice *)id, flag); + break; + case ID_LA: + BKE_light_copy_data(bmain, (Light *)*r_newid, (Light *)id, flag); + break; + case ID_SPK: + BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag); + break; + case ID_LP: + BKE_lightprobe_copy_data(bmain, (LightProbe *)*r_newid, (LightProbe *)id, flag); + break; + case ID_CA: + BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag); + break; + case ID_KE: + BKE_key_copy_data(bmain, (Key *)*r_newid, (Key *)id, flag); + break; + case ID_WO: + BKE_world_copy_data(bmain, (World *)*r_newid, (World *)id, flag); + break; + case ID_TXT: + BKE_text_copy_data(bmain, (Text *)*r_newid, (Text *)id, flag); + break; + case ID_GR: + BKE_collection_copy_data(bmain, (Collection *)*r_newid, (Collection *)id, flag); + break; + case ID_AR: + BKE_armature_copy_data(bmain, (bArmature *)*r_newid, (bArmature *)id, flag); + break; + case ID_AC: + BKE_action_copy_data(bmain, (bAction *)*r_newid, (bAction *)id, flag); + break; + case ID_NT: + BKE_node_tree_copy_data(bmain, (bNodeTree *)*r_newid, (bNodeTree *)id, flag); + break; + case ID_BR: + BKE_brush_copy_data(bmain, (Brush *)*r_newid, (Brush *)id, flag); + break; + case ID_PA: + BKE_particlesettings_copy_data( + bmain, (ParticleSettings *)*r_newid, (ParticleSettings *)id, flag); + break; + case ID_GD: + BKE_gpencil_copy_data((bGPdata *)*r_newid, (bGPdata *)id, flag); + break; + case ID_MC: + BKE_movieclip_copy_data(bmain, (MovieClip *)*r_newid, (MovieClip *)id, flag); + break; + case ID_MSK: + BKE_mask_copy_data(bmain, (Mask *)*r_newid, (Mask *)id, flag); + break; + case ID_LS: + BKE_linestyle_copy_data( + bmain, (FreestyleLineStyle *)*r_newid, (FreestyleLineStyle *)id, flag); + break; + case ID_PAL: + BKE_palette_copy_data(bmain, (Palette *)*r_newid, (Palette *)id, flag); + break; + case ID_PC: + BKE_paint_curve_copy_data(bmain, (PaintCurve *)*r_newid, (PaintCurve *)id, flag); + break; + case ID_CF: + BKE_cachefile_copy_data(bmain, (CacheFile *)*r_newid, (CacheFile *)id, flag); + break; + 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_SCR: + case ID_WM: + case ID_WS: + case ID_IP: + BLI_assert(0); /* Should have been rejected at start of function! */ + break; + } } /* Update ID refcount, remap pointers to self in new ID. */ @@ -1298,6 +1332,15 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl */ void BKE_libblock_init_empty(ID *id) { + const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id); + + if (idtype_info != NULL) { + if (idtype_info->init_data != NULL) { + idtype_info->init_data(id); + } + return; + } + /* Note that only ID types that are not valid when filled of zero should have a callback here. */ switch ((ID_Type)GS(id->name)) { case ID_SCE: diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c index f2fa6946d4b..d47510ea9af 100644 --- a/source/blender/blenkernel/intern/lib_id_delete.c +++ b/source/blender/blenkernel/intern/lib_id_delete.c @@ -66,6 +66,7 @@ #include "BKE_font.h" #include "BKE_gpencil.h" #include "BKE_idprop.h" +#include "BKE_idtype.h" #include "BKE_image.h" #include "BKE_ipo.h" #include "BKE_key.h" @@ -124,6 +125,15 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user) void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag)) { + const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_id(id); + + if (idtype_info != NULL) { + if (idtype_info->free_data != NULL) { + idtype_info->free_data(id); + } + return; + } + const short type = GS(id->name); switch (type) { case ID_SCE: diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index a742d0bb29f..3fded3e5881 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -85,6 +85,7 @@ #include "BKE_fcurve.h" #include "BKE_gpencil_modifier.h" #include "BKE_icons.h" +#include "BKE_idtype.h" #include "BKE_key.h" #include "BKE_light.h" #include "BKE_layer.h" @@ -144,6 +145,248 @@ static CLG_LogRef LOG = {"bke.object"}; static ThreadMutex vparent_lock = BLI_MUTEX_INITIALIZER; #endif +static void copy_object_pose(Object *obn, const Object *ob, const int flag); +static void copy_object_lod(Object *obn, const Object *ob, const int flag); + +static void object_init_data(ID *id) +{ + Object *ob = (Object *)id; + BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(ob, id)); + + MEMCPY_STRUCT_AFTER(ob, DNA_struct_default_get(Object), id); + + ob->type = OB_EMPTY; + + ob->trackflag = OB_POSY; + ob->upflag = OB_POSZ; + + /* Animation Visualization defaults */ + animviz_settings_init(&ob->avs); +} + +static void object_copy_data(Main *bmain, ID *id_dst, const ID *id_src, const int flag) +{ + Object *ob_dst = (Object *)id_dst; + const Object *ob_src = (const Object *)id_src; + ModifierData *md; + GpencilModifierData *gmd; + ShaderFxData *fx; + + /* Do not copy runtime data. */ + BKE_object_runtime_reset_on_copy(ob_dst, flag); + + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; + + if (ob_src->totcol) { + ob_dst->mat = MEM_dupallocN(ob_src->mat); + ob_dst->matbits = MEM_dupallocN(ob_src->matbits); + ob_dst->totcol = ob_src->totcol; + } + else if (ob_dst->mat != NULL || ob_dst->matbits != NULL) { + /* This shall not be needed, but better be safe than sorry. */ + BLI_assert(!"Object copy: non-NULL material pointers with zero counter, should not happen."); + ob_dst->mat = NULL; + ob_dst->matbits = NULL; + } + + if (ob_src->iuser) { + ob_dst->iuser = MEM_dupallocN(ob_src->iuser); + } + + if (ob_src->runtime.bb) { + ob_dst->runtime.bb = MEM_dupallocN(ob_src->runtime.bb); + } + + BLI_listbase_clear(&ob_dst->modifiers); + + for (md = ob_src->modifiers.first; md; md = md->next) { + ModifierData *nmd = modifier_new(md->type); + BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); + modifier_copyData_ex(md, nmd, flag_subdata); + BLI_addtail(&ob_dst->modifiers, nmd); + } + + BLI_listbase_clear(&ob_dst->greasepencil_modifiers); + + for (gmd = ob_src->greasepencil_modifiers.first; gmd; gmd = gmd->next) { + 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); + + for (fx = ob_src->shader_fx.first; fx; fx = fx->next) { + ShaderFxData *nfx = BKE_shaderfx_new(fx->type); + BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name)); + BKE_shaderfx_copyData_ex(fx, nfx, flag_subdata); + BLI_addtail(&ob_dst->shader_fx, nfx); + } + + if (ob_src->pose) { + copy_object_pose(ob_dst, ob_src, flag_subdata); + /* backwards compat... non-armatures can get poses in older files? */ + if (ob_src->type == OB_ARMATURE) { + const bool do_pose_id_user = (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0; + BKE_pose_rebuild(bmain, ob_dst, ob_dst->data, do_pose_id_user); + } + } + defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase); + BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps); + BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true); + + ob_dst->mode = ob_dst->type != OB_GPENCIL ? OB_MODE_OBJECT : ob_dst->mode; + ob_dst->sculpt = NULL; + + if (ob_src->pd) { + ob_dst->pd = MEM_dupallocN(ob_src->pd); + if (ob_dst->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_object_copy_particlesystems(ob_dst, ob_src, flag_subdata); + + BLI_listbase_clear((ListBase *)&ob_dst->drawdata); + BLI_listbase_clear(&ob_dst->pc_ids); + + ob_dst->avs = ob_src->avs; + ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath); + + copy_object_lod(ob_dst, ob_src, flag_subdata); + + /* Do not copy object's preview + * (mostly due to the fact renderers create temp copy of objects). */ + if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ + BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id); + } + else { + ob_dst->preview = NULL; + } +} + +static void object_free_data(ID *id) +{ + Object *ob = (Object *)id; + BKE_animdata_free((ID *)ob, false); + + DRW_drawdata_free((ID *)ob); + + /* BKE_<id>_free shall never touch to ID->us. Never ever. */ + BKE_object_free_modifiers(ob, LIB_ID_CREATE_NO_USER_REFCOUNT); + BKE_object_free_shaderfx(ob, LIB_ID_CREATE_NO_USER_REFCOUNT); + + MEM_SAFE_FREE(ob->mat); + MEM_SAFE_FREE(ob->matbits); + MEM_SAFE_FREE(ob->iuser); + MEM_SAFE_FREE(ob->runtime.bb); + + BLI_freelistN(&ob->defbase); + BLI_freelistN(&ob->fmaps); + if (ob->pose) { + BKE_pose_free_ex(ob->pose, false); + ob->pose = NULL; + } + if (ob->mpath) { + animviz_free_motionpath(ob->mpath); + ob->mpath = NULL; + } + + BKE_constraints_free_ex(&ob->constraints, false); + + BKE_partdeflect_free(ob->pd); + BKE_rigidbody_free_object(ob, NULL); + BKE_rigidbody_free_constraint(ob); + + sbFree(ob); + + BKE_sculptsession_free(ob); + + BLI_freelistN(&ob->pc_ids); + + BLI_freelistN(&ob->lodlevels); + + /* Free runtime curves data. */ + if (ob->runtime.curve_cache) { + BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev); + if (ob->runtime.curve_cache->path) { + free_path(ob->runtime.curve_cache->path); + } + MEM_freeN(ob->runtime.curve_cache); + ob->runtime.curve_cache = NULL; + } + + BKE_previewimg_free(&ob->preview); +} + +static void object_make_local(Main *bmain, ID *id, const int flags) +{ + Object *ob = (Object *)id; + const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0; + const bool clear_proxy = (flags & LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING) == 0; + bool is_local = false, is_lib = false; + + /* - only lib users: do nothing (unless force_local is set) + * - only local users: set flag + * - mixed: make copy + * In case we make a whole lib's content local, + * we always want to localize, and we skip remapping (done later). + */ + + if (!ID_IS_LINKED(ob)) { + return; + } + + BKE_library_ID_test_usages(bmain, ob, &is_local, &is_lib); + + if (lib_local || is_local) { + if (!is_lib) { + BKE_lib_id_clear_library_data(bmain, &ob->id); + BKE_lib_id_expand_local(bmain, &ob->id); + if (clear_proxy) { + if (ob->proxy_from != NULL) { + ob->proxy_from->proxy = NULL; + ob->proxy_from->proxy_group = NULL; + } + ob->proxy = ob->proxy_from = ob->proxy_group = NULL; + } + } + else { + Object *ob_new = BKE_object_copy(bmain, ob); + + ob_new->id.us = 0; + ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = NULL; + + /* setting newid is mandatory for complex make_lib_local logic... */ + ID_NEW_SET(ob, ob_new); + + if (!lib_local) { + BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE); + } + } + } +} + +IDTypeInfo IDType_ID_OB = { + .id_code = ID_OB, + .id_filter = FILTER_ID_OB, + .main_listbase_index = INDEX_ID_OB, + .struct_size = sizeof(Object), + .name = "Object", + .name_plural = "objects", + .translation_context = BLT_I18NCONTEXT_ID_OBJECT, + .flags = 0, + + .init_data = object_init_data, + .copy_data = object_copy_data, + .free_data = object_free_data, + .make_local = object_make_local, +}; + void BKE_object_workob_clear(Object *workob) { memset(workob, 0, sizeof(Object)); @@ -542,55 +785,7 @@ void BKE_object_free_caches(Object *object) /** Free (or release) any data used by this object (does not free the object itself). */ void BKE_object_free(Object *ob) { - BKE_animdata_free((ID *)ob, false); - - DRW_drawdata_free((ID *)ob); - - /* BKE_<id>_free shall never touch to ID->us. Never ever. */ - BKE_object_free_modifiers(ob, LIB_ID_CREATE_NO_USER_REFCOUNT); - BKE_object_free_shaderfx(ob, LIB_ID_CREATE_NO_USER_REFCOUNT); - - MEM_SAFE_FREE(ob->mat); - MEM_SAFE_FREE(ob->matbits); - MEM_SAFE_FREE(ob->iuser); - MEM_SAFE_FREE(ob->runtime.bb); - - BLI_freelistN(&ob->defbase); - BLI_freelistN(&ob->fmaps); - if (ob->pose) { - BKE_pose_free_ex(ob->pose, false); - ob->pose = NULL; - } - if (ob->mpath) { - animviz_free_motionpath(ob->mpath); - ob->mpath = NULL; - } - - BKE_constraints_free_ex(&ob->constraints, false); - - BKE_partdeflect_free(ob->pd); - BKE_rigidbody_free_object(ob, NULL); - BKE_rigidbody_free_constraint(ob); - - sbFree(ob); - - BKE_sculptsession_free(ob); - - BLI_freelistN(&ob->pc_ids); - - BLI_freelistN(&ob->lodlevels); - - /* Free runtime curves data. */ - if (ob->runtime.curve_cache) { - BKE_curve_bevelList_free(&ob->runtime.curve_cache->bev); - if (ob->runtime.curve_cache->path) { - free_path(ob->runtime.curve_cache->path); - } - MEM_freeN(ob->runtime.curve_cache); - ob->runtime.curve_cache = NULL; - } - - BKE_previewimg_free(&ob->preview); + object_free_data(&ob->id); } /* actual check for internal data, not context or flags */ @@ -872,9 +1067,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) void BKE_object_init(Object *ob, const short ob_type) { - BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(ob, id)); - - MEMCPY_STRUCT_AFTER(ob, DNA_struct_default_get(Object), id); + object_init_data(&ob->id); ob->type = ob_type; @@ -886,13 +1079,6 @@ void BKE_object_init(Object *ob, const short ob_type) ob->trackflag = OB_NEGZ; ob->upflag = OB_POSY; } - else { - ob->trackflag = OB_POSY; - ob->upflag = OB_POSZ; - } - - /* Animation Visualization defaults */ - animviz_settings_init(&ob->avs); } /* more general add: creates minimum required data, but without vertices etc. */ @@ -1363,105 +1549,7 @@ void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src) */ void BKE_object_copy_data(Main *bmain, Object *ob_dst, const Object *ob_src, const int flag) { - ModifierData *md; - GpencilModifierData *gmd; - ShaderFxData *fx; - - /* Do not copy runtime data. */ - BKE_object_runtime_reset_on_copy(ob_dst, flag); - - /* We never handle usercount here for own data. */ - const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; - - if (ob_src->totcol) { - ob_dst->mat = MEM_dupallocN(ob_src->mat); - ob_dst->matbits = MEM_dupallocN(ob_src->matbits); - ob_dst->totcol = ob_src->totcol; - } - else if (ob_dst->mat != NULL || ob_dst->matbits != NULL) { - /* This shall not be needed, but better be safe than sorry. */ - BLI_assert(!"Object copy: non-NULL material pointers with zero counter, should not happen."); - ob_dst->mat = NULL; - ob_dst->matbits = NULL; - } - - if (ob_src->iuser) { - ob_dst->iuser = MEM_dupallocN(ob_src->iuser); - } - - if (ob_src->runtime.bb) { - ob_dst->runtime.bb = MEM_dupallocN(ob_src->runtime.bb); - } - - BLI_listbase_clear(&ob_dst->modifiers); - - for (md = ob_src->modifiers.first; md; md = md->next) { - ModifierData *nmd = modifier_new(md->type); - BLI_strncpy(nmd->name, md->name, sizeof(nmd->name)); - modifier_copyData_ex(md, nmd, flag_subdata); - BLI_addtail(&ob_dst->modifiers, nmd); - } - - BLI_listbase_clear(&ob_dst->greasepencil_modifiers); - - for (gmd = ob_src->greasepencil_modifiers.first; gmd; gmd = gmd->next) { - 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); - - for (fx = ob_src->shader_fx.first; fx; fx = fx->next) { - ShaderFxData *nfx = BKE_shaderfx_new(fx->type); - BLI_strncpy(nfx->name, fx->name, sizeof(nfx->name)); - BKE_shaderfx_copyData_ex(fx, nfx, flag_subdata); - BLI_addtail(&ob_dst->shader_fx, nfx); - } - - if (ob_src->pose) { - copy_object_pose(ob_dst, ob_src, flag_subdata); - /* backwards compat... non-armatures can get poses in older files? */ - if (ob_src->type == OB_ARMATURE) { - const bool do_pose_id_user = (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0; - BKE_pose_rebuild(bmain, ob_dst, ob_dst->data, do_pose_id_user); - } - } - defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase); - BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps); - BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true); - - ob_dst->mode = ob_dst->type != OB_GPENCIL ? OB_MODE_OBJECT : ob_dst->mode; - ob_dst->sculpt = NULL; - - if (ob_src->pd) { - ob_dst->pd = MEM_dupallocN(ob_src->pd); - if (ob_dst->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_object_copy_particlesystems(ob_dst, ob_src, flag_subdata); - - BLI_listbase_clear((ListBase *)&ob_dst->drawdata); - BLI_listbase_clear(&ob_dst->pc_ids); - - ob_dst->avs = ob_src->avs; - ob_dst->mpath = animviz_copy_motionpath(ob_src->mpath); - - copy_object_lod(ob_dst, ob_src, flag_subdata); - - /* Do not copy object's preview - * (mostly due to the fact renderers create temp copy of objects). */ - if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ - BKE_previewimg_id_copy(&ob_dst->id, &ob_src->id); - } - else { - ob_dst->preview = NULL; - } + object_copy_data(bmain, &ob_dst->id, &ob_src->id, flag); } /* copy objects, will re-initialize cached simulation data */ @@ -1743,49 +1831,7 @@ Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag) void BKE_object_make_local(Main *bmain, Object *ob, const int flags) { - const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0; - const bool clear_proxy = (flags & LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING) == 0; - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing (unless force_local is set) - * - only local users: set flag - * - mixed: make copy - * In case we make a whole lib's content local, - * we always want to localize, and we skip remapping (done later). - */ - - if (!ID_IS_LINKED(ob)) { - return; - } - - BKE_library_ID_test_usages(bmain, ob, &is_local, &is_lib); - - if (lib_local || is_local) { - if (!is_lib) { - BKE_lib_id_clear_library_data(bmain, &ob->id); - BKE_lib_id_expand_local(bmain, &ob->id); - if (clear_proxy) { - if (ob->proxy_from != NULL) { - ob->proxy_from->proxy = NULL; - ob->proxy_from->proxy_group = NULL; - } - ob->proxy = ob->proxy_from = ob->proxy_group = NULL; - } - } - else { - Object *ob_new = BKE_object_copy(bmain, ob); - - ob_new->id.us = 0; - ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = NULL; - - /* setting newid is mandatory for complex make_lib_local logic... */ - ID_NEW_SET(ob, ob_new); - - if (!lib_local) { - BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } - } + object_make_local(bmain, &ob->id, flags); } /* Returns true if the Object is from an external blend file (libdata) */ diff --git a/source/creator/creator.c b/source/creator/creator.c index cf25be95472..14db899b4fd 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -55,6 +55,7 @@ #include "BKE_context.h" #include "BKE_font.h" #include "BKE_global.h" +#include "BKE_idtype.h" #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_gpencil_modifier.h" @@ -366,6 +367,7 @@ int main(int argc, BKE_blender_globals_init(); /* blender.c */ + BKE_idtype_init(); IMB_init(); BKE_cachefiles_init(); BKE_images_init(); diff --git a/tests/gtests/blenloader/blendfile_loading_base_test.cc b/tests/gtests/blenloader/blendfile_loading_base_test.cc index c4e873c255f..4f871bc7ddf 100644 --- a/tests/gtests/blenloader/blendfile_loading_base_test.cc +++ b/tests/gtests/blenloader/blendfile_loading_base_test.cc @@ -24,6 +24,7 @@ extern "C" { #include "BKE_blender.h" #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_idtype.h" #include "BKE_image.h" #include "BKE_main.h" #include "BKE_modifier.h" @@ -65,6 +66,8 @@ void BlendfileLoadingBaseTest::SetUpTestCase() DNA_sdna_current_init(); BKE_blender_globals_init(); + + BKE_idtype_init(); IMB_init(); BKE_images_init(); BKE_modifier_init(); |