[Bf-blender-cvs] [776a854] master: Fix T49430: append scene with gamelogic broken.

Bastien Montagne noreply at git.blender.org
Fri Sep 23 14:25:49 CEST 2016


Commit: 776a8548f03a049d56f19943e6bc4590ecd53028
Author: Bastien Montagne
Date:   Fri Sep 23 13:05:11 2016 +0200
Branches: master
https://developer.blender.org/rB776a8548f03a049d56f19943e6bc4590ecd53028

Fix T49430: append scene with gamelogic broken.

In fact, it was the whole remapping process that was broken in logic bricks area,
due to terrible design of links between those bricks...

Object copying was also broken in that case, fixed as well.

To be backported to 2.78.

Note that issue was actually probably there since ages, hidden behind dirty hacks
used in previous append code (though likely visible in some corner cases).

Listen kids: do not, never, ever, do what has been done for links between logic bricks. Never. Ever.
Even as pure runtime data it would have been bad, but as stored data...

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

M	source/blender/blenkernel/BKE_sca.h
M	source/blender/blenkernel/intern/library_remap.c
M	source/blender/blenkernel/intern/object.c
M	source/blender/blenkernel/intern/sca.c

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

diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h
index 1743a44..a504f1b 100644
--- a/source/blender/blenkernel/BKE_sca.h
+++ b/source/blender/blenkernel/BKE_sca.h
@@ -31,8 +31,9 @@
  *  \ingroup bke
  */
 
-struct bSensor;
+struct Main;
 struct Object;
+struct bSensor;
 struct bController;
 struct bActuator;
 
@@ -68,6 +69,9 @@ void clear_sca_new_poins(void);
 void set_sca_new_poins_ob(struct Object *ob);
 void set_sca_new_poins(void);
 
+void BKE_sca_logic_links_remap(struct Main *bmain, struct Object *ob_old, struct Object *ob_new);
+void BKE_sca_logic_copy(struct Object *ob_new, struct Object *ob);
+
 void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up);
 void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up);
 void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up);
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index f456364..b468e64 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -99,6 +99,7 @@
 #include "BKE_object.h"
 #include "BKE_paint.h"
 #include "BKE_particle.h"
+#include "BKE_sca.h"
 #include "BKE_speaker.h"
 #include "BKE_sound.h"
 #include "BKE_screen.h"
@@ -448,6 +449,10 @@ ATTR_NONNULL(1) static void libblock_remap_data(
 		}
 	}
 
+	if (old_id && GS(old_id->name) == ID_OB) {
+		BKE_sca_logic_links_remap(bmain, (Object *)old_id, (Object *)new_id);
+	}
+
 	/* XXX We may not want to always 'transfer' fakeuser from old to new id... Think for now it's desired behavior
 	 *     though, we can always add an option (flag) to control this later if needed. */
 	if (old_id && (old_id->flag & LIB_FAKEUSER)) {
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index cdd7560..d87c257 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1118,11 +1118,9 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
 
 	BLI_listbase_clear(&obn->prop);
 	BKE_bproperty_copy_list(&obn->prop, &ob->prop);
-	
-	copy_sensors(&obn->sensors, &ob->sensors);
-	copy_controllers(&obn->controllers, &ob->controllers);
-	copy_actuators(&obn->actuators, &ob->actuators);
-	
+
+	BKE_sca_logic_copy(obn, ob);
+
 	if (ob->pose) {
 		copy_object_pose(obn, ob);
 		/* backwards compat... non-armatures can get poses in older files? */
diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c
index a468420..c357b2e 100644
--- a/source/blender/blenkernel/intern/sca.c
+++ b/source/blender/blenkernel/intern/sca.c
@@ -44,7 +44,9 @@
 #include "DNA_object_types.h"
 
 #include "BLI_blenlib.h"
+#include "BLI_ghash.h"
 #include "BLI_math.h"
+
 #include "BKE_global.h"
 #include "BKE_main.h"
 #include "BKE_library.h"
@@ -653,6 +655,160 @@ void set_sca_new_poins(void)
 	}
 }
 
+/**
+ * Try to remap logic links to new object... Very, *very* weak.
+ */
+/* XXX Logick bricks... I don't have words to say what I think about this behavior.
+ *     They have silent hidden ugly inter-objects dependencies (a sensor can link into any other
+ *     object's controllers, and same between controllers and actuators, without *any* explicit reference
+ *     to data-block involved).
+ *     This is bad, bad, bad!!!
+ *     ...and forces us to add yet another very ugly hack to get remapping with logic bricks working. */
+void BKE_sca_logic_links_remap(Main *bmain, Object *ob_old, Object *ob_new)
+{
+	GHash *controllers_map = ob_old->controllers.first ?
+	                             BLI_ghash_ptr_new_ex(__func__, BLI_listbase_count(&ob_old->controllers)) : NULL;
+	GHash *actuators_map = ob_old->actuators.first ?
+	                           BLI_ghash_ptr_new_ex(__func__, BLI_listbase_count(&ob_old->actuators)) : NULL;
+
+	if (!(controllers_map || actuators_map)) {
+		return;
+	}
+
+	/* We try to remap old controllers/actuators to new ones - in a very basic way. */
+	for (bController *cont_old = ob_old->controllers.first, *cont_new = ob_new->controllers.first;
+	     cont_old;
+	     cont_old = cont_old->next)
+	{
+		bController *cont_new2 = cont_new;
+
+		if (cont_old->mynew != NULL) {
+			cont_new2 = cont_old->mynew;
+			if (!(cont_new2 == cont_new || BLI_findindex(&ob_new->controllers, cont_new2) >= 0)) {
+				cont_new2 = NULL;
+			}
+		}
+		else if (cont_new && cont_old->type != cont_new->type) {
+			cont_new2 = NULL;
+		}
+
+		BLI_ghash_insert(controllers_map, cont_old, cont_new2);
+
+		if (cont_new) {
+			cont_new = cont_new->next;
+		}
+	}
+
+	for (bActuator *act_old = ob_old->actuators.first, *act_new = ob_new->actuators.first;
+	     act_old;
+	     act_old = act_old->next)
+	{
+		bActuator *act_new2 = act_new;
+
+		if (act_old->mynew != NULL) {
+			act_new2 = act_old->mynew;
+			if (!(act_new2 == act_new || BLI_findindex(&ob_new->actuators, act_new2) >= 0)) {
+				act_new2 = NULL;
+			}
+		}
+		else if (act_new && act_old->type != act_new->type) {
+			act_new2 = NULL;
+		}
+
+		BLI_ghash_insert(actuators_map, act_old, act_new2);
+
+		if (act_new) {
+			act_new = act_new->next;
+		}
+	}
+
+	for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
+		if (controllers_map != NULL) {
+			for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) {
+				for (int a = 0; a < sens->totlinks; a++) {
+					if (sens->links[a]) {
+						bController *old_link = sens->links[a];
+						bController **new_link_p = (bController **)BLI_ghash_lookup_p(controllers_map, old_link);
+
+						if (new_link_p == NULL) {
+							/* old_link is *not* in map's keys (i.e. not to any ob_old->controllers),
+							 * which means we ignore it totally here. */
+						}
+						else if (*new_link_p == NULL) {
+							unlink_logicbricks((void **)&old_link, (void ***)&(sens->links), &sens->totlinks);
+							a--;
+						}
+						else {
+							sens->links[a] = *new_link_p;
+						}
+					}
+				}
+			}
+		}
+
+		if (actuators_map != NULL) {
+			for (bController *cont = ob->controllers.first; cont; cont = cont->next) {
+				for (int a = 0; a < cont->totlinks; a++) {
+					if (cont->links[a]) {
+						bActuator *old_link = cont->links[a];
+						bActuator **new_link_p = (bActuator **)BLI_ghash_lookup_p(actuators_map, old_link);
+
+						if (new_link_p == NULL) {
+							/* old_link is *not* in map's keys (i.e. not to any ob_old->actuators),
+							 * which means we ignore it totally here. */
+						}
+						else if (*new_link_p == NULL) {
+							unlink_logicbricks((void **)&old_link, (void ***)&(cont->links), &cont->totlinks);
+							a--;
+						}
+						else {
+							cont->links[a] = *new_link_p;
+						}
+					}
+				}
+			}
+		}
+	}
+
+	if (controllers_map) {
+		BLI_ghash_free(controllers_map, NULL, NULL);
+	}
+	if (actuators_map) {
+		BLI_ghash_free(actuators_map, NULL, NULL);
+	}
+}
+
+/**
+ * Handle the copying of logic data into a new object, including internal logic links update.
+ * External links (links between logic bricks of different objects) must be handled separately.
+ */
+void BKE_sca_logic_copy(Object *ob_new, Object *ob)
+{
+	copy_sensors(&ob_new->sensors, &ob->sensors);
+	copy_controllers(&ob_new->controllers, &ob->controllers);
+	copy_actuators(&ob_new->actuators, &ob->actuators);
+
+	for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) {
+		if (sens->flag & SENS_NEW) {
+			for (int a = 0; a < sens->totlinks; a++) {
+				if (sens->links[a] && sens->links[a]->mynew) {
+					sens->links[a] = sens->links[a]->mynew;
+				}
+			}
+		}
+	}
+
+	for (bController *cont = ob->controllers.first; cont; cont = cont->next) {
+		if (cont->flag & CONT_NEW) {
+			for (int a = 0; a < cont->totlinks; a++) {
+				if (cont->links[a] && cont->links[a]->mynew) {
+					cont->links[a] = cont->links[a]->mynew;
+				}
+			}
+		}
+	}
+}
+
 /* ******************** INTERFACE ******************* */
 void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up)
 {




More information about the Bf-blender-cvs mailing list