diff options
-rw-r--r-- | source/blender/blenkernel/BKE_sca.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/library_remap.c | 5 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 8 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/sca.c | 156 |
4 files changed, 169 insertions, 6 deletions
diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h index 1743a4431fd..a504f1bac3d 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 f4563649302..b468e6436c8 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 cdd7560e3c4..d87c257d555 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 a468420f87d..c357b2ef9f7 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) { |