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...
This commit is contained in:
Bastien Montagne 2016-09-23 13:05:11 +02:00
parent 2372e67dd6
commit 776a8548f0
Notes: blender-bot 2023-02-14 07:35:03 +01:00
Referenced by commit dd0de53d29, Fix T49466: Stupid typo in logicbricks new copy code from rB776a8548f03a
Referenced by commit 7c53260109, Fix crash in own recent rB776a8548f03a049.
Referenced by issue #49430, append scene with gamelogic broken
4 changed files with 169 additions and 6 deletions

View File

@ -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);

View File

@ -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)) {

View File

@ -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? */

View File

@ -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)
{