[Bf-blender-cvs] [6e5e3b7] master: Fix T37599: Crash making linked objects local and undo

Sergey Sharybin noreply at git.blender.org
Fri Mar 28 12:14:48 CET 2014


Commit: 6e5e3b73f37f952420d87a3d8acd07a7f68dd5a3
Author: Sergey Sharybin
Date:   Wed Mar 26 16:55:20 2014 +0600
https://developer.blender.org/rB6e5e3b73f37f952420d87a3d8acd07a7f68dd5a3

Fix T37599: Crash making linked objects local and undo

Root of the issues comes to the fact that it's possible to produce
a situation when library object data uses local object. This is
actually forbidden and not supported by .blend IO.

Made it so Make Local wouldn't produce such an unsupported states.

Reviewers: brecht

Differential Revision: https://developer.blender.org/D372

===================================================================

A	source/blender/blenkernel/BKE_library_query.h
M	source/blender/blenkernel/CMakeLists.txt
A	source/blender/blenkernel/intern/library_query.c
M	source/blender/editors/object/object_relations.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
new file mode 100644
index 0000000..50958f8
--- /dev/null
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -0,0 +1,57 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2014 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey SHarybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_LIBRARY_QUERY_H__
+#define __BKE_LIBRARY_QUERY_H__
+
+/** \file BKE_library_query.h
+ *  \ingroup bke
+ *  \since March 2014
+ *  \author sergey
+ */
+
+struct ID;
+
+/* Tips for the callback for cases it's gonna to modify the pointer. */
+enum {
+	IDWALK_NOP = 0,
+	IDWALK_NEVER_NULL = (1 << 0),
+	IDWALK_NEVER_SELF = (1 << 1),
+};
+
+/* Call a callback for each ID link which the given ID uses.
+ *
+ * Return 'false' if you want to stop iteration.
+ */
+typedef bool (*LibraryIDLinkCallback) (void *user_data, struct ID **id_pointer, int cd_flag);
+
+/* Flags for the foreach function itself. */
+enum {
+	IDWALK_READONLY = (1 << 0),
+};
+
+/* Loop over all of the ID's this datablock links to. */
+void BKE_library_foreach_ID_link(struct ID *id, LibraryIDLinkCallback callback, void *user_data, int flag);
+
+#endif  /* __BKE_LIBRARY_QUERY_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 2a0f642..749a5eb 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -107,6 +107,7 @@ set(SRC
 	intern/lamp.c
 	intern/lattice.c
 	intern/library.c
+	intern/library_query.c
 	intern/linestyle.c
 	intern/mask.c
 	intern/mask_evaluate.c
@@ -214,6 +215,7 @@ set(SRC
 	BKE_lamp.h
 	BKE_lattice.h
 	BKE_library.h
+	BKE_library_query.h
 	BKE_linestyle.h
 	BKE_main.h
 	BKE_mask.h
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
new file mode 100644
index 0000000..f67b1ac
--- /dev/null
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -0,0 +1,460 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2014 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Sergey Sharybin.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/library_query.c
+ *  \ingroup bke
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_anim_types.h"
+#include "DNA_brush_types.h"
+#include "DNA_camera_types.h"
+#include "DNA_constraint_types.h"
+#include "DNA_group_types.h"
+#include "DNA_gpencil_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lamp_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_meta_types.h"
+#include "DNA_movieclip_types.h"
+#include "DNA_mask_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_force.h"
+#include "DNA_sequence_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_speaker_types.h"
+#include "DNA_sound_types.h"
+#include "DNA_vfont_types.h"
+#include "DNA_world_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_animsys.h"
+#include "BKE_constraint.h"
+#include "BKE_fcurve.h"
+#include "BKE_library_query.h"
+#include "BKE_modifier.h"
+#include "BKE_particle.h"
+#include "BKE_sequencer.h"
+#include "BKE_tracking.h"
+
+#define FOREACH_CALLBACK_INVOKE_ID_PP(self_id, id_pp, flag, callback, user_data, cb_flag) \
+	{ \
+		ID *old_id = *id_pp; \
+		bool keep_working = callback(user_data, id_pp, cb_flag); \
+		if (flag & IDWALK_READONLY) { \
+			BLI_assert(*id_pp == old_id); \
+		} \
+		if (keep_working == false) { \
+			/* REAL DANGER! Beware of this return! */ \
+			/* TODO(sergey): Make it less creepy without too much duplicated code.. */ \
+			return; \
+		} \
+	} (void) 0
+
+#define FOREACH_CALLBACK_INVOKE_ID(self_id, id, flag, callback, user_data, cb_flag) \
+	FOREACH_CALLBACK_INVOKE_ID_PP(self_id, &(id), flag, callback, user_data, cb_flag) \
+
+#define FOREACH_CALLBACK_INVOKE(self_id, id_super, flag, callback, user_data, cb_flag) \
+	{ \
+		CHECK_TYPE(&((id_super)->id), ID *); \
+		FOREACH_CALLBACK_INVOKE_ID_PP(self_id, (ID **)&id_super, flag, callback, user_data, cb_flag); \
+	} (void) 0
+
+typedef struct LibraryForeachIDData {
+	ID *self_id;
+	int flag;
+	LibraryIDLinkCallback callback;
+	void *user_data;
+} LibraryForeachIDData;
+
+static void library_foreach_modifiersForeachIDLink(void *user_data, Object *UNUSED(object),
+                                                   ID **id_pointer)
+{
+	LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
+	FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, IDWALK_NOP);
+}
+
+static void library_foreach_constraintObjectLooper(bConstraint *UNUSED(con), ID **id_pointer,
+                                                   short UNUSED(isReference), void *user_data)
+{
+	LibraryForeachIDData *data = (LibraryForeachIDData *) user_data;
+	FOREACH_CALLBACK_INVOKE_ID_PP(data->self_id, id_pointer, data->flag, data->callback, data->user_data, IDWALK_NOP);
+}
+
+static void library_foreach_animationData(LibraryForeachIDData *data, AnimData *adt)
+{
+	FCurve *fcu;
+
+	for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
+		ChannelDriver *driver = fcu->driver;
+		DriverVar *dvar;
+
+		for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
+			/* only used targets */
+			DRIVER_TARGETS_USED_LOOPER(dvar)
+			{
+				FOREACH_CALLBACK_INVOKE_ID(data->self_id, dtar->id, data->flag, data->callback, data->user_data, IDWALK_NOP);
+			}
+			DRIVER_TARGETS_LOOPER_END
+		}
+	}
+}
+
+
+static void library_foreach_mtex(LibraryForeachIDData *data, MTex *mtex)
+{
+	FOREACH_CALLBACK_INVOKE(data->self_id, mtex->object, data->flag, data->callback, data->user_data, IDWALK_NOP);
+	FOREACH_CALLBACK_INVOKE(data->self_id, mtex->tex, data->flag, data->callback, data->user_data, IDWALK_NOP);
+}
+
+
+/**
+ * Loop over all of the ID's this datablock links to.
+ *
+ * \note: May be extended to be recursive in the future.
+ */
+void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *user_data, int flag)
+{
+	AnimData *adt;
+	LibraryForeachIDData data;
+	int i;
+
+	data.self_id = id;
+	data.flag = flag;
+	data.callback = callback;
+	data.user_data = user_data;
+
+	adt = BKE_animdata_from_id(id);
+	if (adt) {
+		library_foreach_animationData(&data, adt);
+	}
+
+#define CALLBACK_INVOKE_ID(check_id, cb_flag) \
+	FOREACH_CALLBACK_INVOKE_ID(id, check_id, flag, callback, user_data, cb_flag)
+
+#define CALLBACK_INVOKE(check_id_super, cb_flag) \
+	FOREACH_CALLBACK_INVOKE(id, check_id_super, flag, callback, user_data, cb_flag)
+
+	switch (GS(id->name)) {
+		case ID_SCE:
+		{
+			Scene *scene = (Scene *) id;
+			Base *base;
+
+			CALLBACK_INVOKE(scene->camera, IDWALK_NOP);
+			CALLBACK_INVOKE(scene->world, IDWALK_NOP);
+			CALLBACK_INVOKE(scene->set, IDWALK_NOP);
+			if (scene->basact) {
+				CALLBACK_INVOKE(scene->basact->object, IDWALK_NOP);
+			}
+			CALLBACK_INVOKE(scene->obedit, IDWALK_NOP);
+
+			if (scene->ed) {
+				Sequence *seq;
+				SEQP_BEGIN(scene->ed, seq)
+				{
+					CALLBACK_INVOKE(seq->scene, IDWALK_NOP);
+					CALLBACK_INVOKE(seq->scene_camera, IDWALK_NOP);
+					CALLBACK_INVOKE(seq->clip, IDWALK_NOP);
+					CALLBACK_INVOKE(seq->mask, IDWALK_NOP);
+				}
+				SEQ_END
+			}
+
+			CALLBACK_INVOKE(scene->gpd, IDWALK_NOP);
+
+			for (base = scene->base.first; base; base = base->next) {
+				CALLBACK_INVOKE(base->object, IDWALK_NOP);
+			}
+		}
+
+		case ID_OB:
+		{
+			Object *object = (Object *) id;
+			CALLBACK_INVOKE(object->parent, IDWALK_NOP);
+			CALLBACK_INVOKE(object->track, IDWALK_NOP);
+			CALLBACK_INVOKE(object->proxy, IDWALK_NOP);
+			CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP);
+			CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP);
+			CALLBACK_INVOKE(object->poselib, IDWALK_NOP);
+			for (i = 0; i < object->totcol; i++) {
+				CALLBACK_INVOKE(object->mat[i], IDWALK_NOP);
+			}
+			CALLBACK_INVOKE(object->gpd, IDWALK_NOP);
+			CALLBACK_INVOKE(object->dup_group, IDWALK_NOP);
+			if (object->particlesystem.first) {
+				ParticleSystem *particle_system;
+				for (particle_system = object->particlesystem.first;
+				     particle_system;
+				     particle_system = particle_system->next)
+				{
+					CALLBACK_INVOKE(particle_system->target_ob, IDWALK_NOP);
+					CALLBACK_INVOKE(particle_system->parent, IDWALK_NOP);
+				}
+			}
+
+			if (object->pose) {
+				bPoseChannel *pose_channel;
+				for (pose_channel = object->pose->chanbase.first;
+				     pose_channel;
+				     pose_channel = pose_channel->next)
+				{
+					CALLBACK_INVOKE(pose_channel->custom, IDWALK_NOP);
+

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list