Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/BKE_idtype.h142
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/idtype.c81
-rw-r--r--source/blender/blenkernel/intern/lib_id.c255
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c10
-rw-r--r--source/blender/blenkernel/intern/object.c448
-rw-r--r--source/creator/creator.c2
-rw-r--r--tests/gtests/blenloader/blendfile_loading_base_test.cc3
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();