Fix T63828, T62005: copy/paste or append loses rigid body object

Previously settings were removed, now add to the rigid body world automatically
even if it's a bit ill defined, since this is confusing for users.

Fundamentally the concept of a rigid body world collection could be revised, and
left only as an optional thing.
This commit is contained in:
Brecht Van Lommel 2019-06-24 14:57:52 +02:00
parent 7d3a28d2d9
commit a5ff780065
Notes: blender-bot 2023-02-14 11:34:30 +01:00
Referenced by issue #63828, Rigid Objects are frozen after copy.
Referenced by issue #62005, Rigid bodies and constraints not working after append
4 changed files with 92 additions and 57 deletions

View File

@ -32,6 +32,7 @@ struct Collection;
struct Depsgraph;
struct Main;
struct Object;
struct ReportList;
struct Scene;
/* -------------- */
@ -94,6 +95,12 @@ void BKE_rigidbody_calc_center_of_mass(struct Object *ob, float r_center[3]);
/* Utilities */
struct RigidBodyWorld *BKE_rigidbody_get_world(struct Scene *scene);
bool BKE_rigidbody_add_object(struct Main *bmain,
struct Scene *scene,
struct Object *ob,
int type,
struct ReportList *reports);
void BKE_rigidbody_ensure_local_object(struct Main *bmain, struct Object *ob);
void BKE_rigidbody_remove_object(struct Main *bmain, struct Scene *scene, struct Object *ob);
void BKE_rigidbody_remove_constraint(struct Scene *scene, struct Object *ob);

View File

@ -57,6 +57,7 @@
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_speaker_types.h"
@ -2038,6 +2039,10 @@ void BKE_library_make_local(Main *bmain,
id_clear_lib_data_ex(bmain, id, true);
BKE_id_expand_local(bmain, id);
id->tag &= ~LIB_TAG_DOIT;
if (GS(id->name) == ID_OB) {
BKE_rigidbody_ensure_local_object(bmain, (Object *)id);
}
}
else {
/* In this specific case, we do want to make ID local even if it has no local usage yet...
@ -2053,6 +2058,10 @@ void BKE_library_make_local(Main *bmain,
}
if (id->newid) {
if (GS(id->newid->name) == ID_OB) {
BKE_rigidbody_ensure_local_object(bmain, (Object *)id->newid);
}
/* Reuse already allocated LinkNode (transferring it from todo_ids to copied_ids). */
BLI_linklist_prepend_nlink(&copied_ids, id, it);
}
@ -2178,25 +2187,6 @@ void BKE_library_make_local(Main *bmain,
}
}
/* Reset rigid body objects. */
for (LinkNode *it = copied_ids; it; it = it->next) {
ID *id = it->link;
if (GS(id->name) == ID_OB) {
Object *ob = (Object *)id;
/* If there was ever any rigidbody settings in the object, we reset it. */
if (ob->rigidbody_object) {
for (Scene *scene_iter = bmain->scenes.first; scene_iter;
scene_iter = scene_iter->id.next) {
if (scene_iter->rigidbody_world) {
BKE_rigidbody_remove_object(bmain, scene_iter, ob);
}
}
BKE_rigidbody_free_object(ob, NULL);
}
}
}
#ifdef DEBUG_TIME
printf("Hack: Forcefully rebuild armature object poses: Done.\n");
TIMEIT_VALUE_PRINT(make_local);

View File

@ -56,6 +56,7 @@
#include "BKE_mesh_runtime.h"
#include "BKE_object.h"
#include "BKE_pointcache.h"
#include "BKE_report.h"
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
#ifdef WITH_BULLET
@ -1296,7 +1297,76 @@ RigidBodyWorld *BKE_rigidbody_get_world(Scene *scene)
return scene->rigidbody_world;
}
void BKE_rigidbody_remove_object(struct Main *bmain, Scene *scene, Object *ob)
static bool rigidbody_add_object_to_scene(Main *bmain, Scene *scene, Object *ob)
{
/* Add rigid body world and group if they don't exist for convenience */
RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
if (rbw == NULL) {
rbw = BKE_rigidbody_create_world(scene);
if (rbw == NULL) {
return false;
}
BKE_rigidbody_validate_sim_world(scene, rbw, false);
scene->rigidbody_world = rbw;
}
if (rbw->group == NULL) {
rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld");
id_fake_user_set(&rbw->group->id);
}
/* Add object to rigid body group. */
BKE_collection_object_add(bmain, rbw->group, ob);
BKE_rigidbody_cache_reset(rbw);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&rbw->group->id, ID_RECALC_COPY_ON_WRITE);
return true;
}
void BKE_rigidbody_ensure_local_object(Main *bmain, Object *ob)
{
if (ob->rigidbody_object == NULL) {
return;
}
/* Add newly local object to scene. */
for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
if (BKE_scene_object_find(scene, ob)) {
rigidbody_add_object_to_scene(bmain, scene, ob);
}
}
}
bool BKE_rigidbody_add_object(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
{
if (ob->type != OB_MESH) {
BKE_report(reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
return false;
}
/* Add object to rigid body world in scene. */
if (!rigidbody_add_object_to_scene(bmain, scene, ob)) {
BKE_report(reports, RPT_ERROR, "Can't create Rigid Body world");
return false;
}
/* make rigidbody object settings */
if (ob->rigidbody_object == NULL) {
ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type);
}
ob->rigidbody_object->type = type;
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
return true;
}
void BKE_rigidbody_remove_object(Main *bmain, Scene *scene, Object *ob)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
RigidBodyCon *rbc;
@ -1343,6 +1413,10 @@ void BKE_rigidbody_remove_object(struct Main *bmain, Scene *scene, Object *ob)
/* flag cache as outdated */
BKE_rigidbody_cache_reset(rbw);
/* Dependency graph update */
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
}
void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)

View File

@ -86,43 +86,7 @@ static bool ED_operator_rigidbody_add_poll(bContext *C)
bool ED_rigidbody_object_add(Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
{
RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
if (ob->type != OB_MESH) {
BKE_report(reports, RPT_ERROR, "Can't add Rigid Body to non mesh object");
return false;
}
/* Add rigid body world and group if they don't exist for convenience */
if (rbw == NULL) {
rbw = BKE_rigidbody_create_world(scene);
if (rbw == NULL) {
BKE_report(reports, RPT_ERROR, "Can't create Rigid Body world");
return false;
}
BKE_rigidbody_validate_sim_world(scene, rbw, false);
scene->rigidbody_world = rbw;
}
if (rbw->group == NULL) {
rbw->group = BKE_collection_add(bmain, NULL, "RigidBodyWorld");
id_fake_user_set(&rbw->group->id);
}
/* make rigidbody object settings */
if (ob->rigidbody_object == NULL) {
ob->rigidbody_object = BKE_rigidbody_create_object(scene, ob, type);
}
ob->rigidbody_object->type = type;
ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE;
/* add object to rigid body group */
BKE_collection_object_add(bmain, rbw->group, ob);
DEG_relations_tag_update(bmain);
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
DEG_id_tag_update(&rbw->group->id, ID_RECALC_COPY_ON_WRITE);
return true;
return BKE_rigidbody_add_object(bmain, scene, ob, type, reports);
}
void ED_rigidbody_object_remove(Main *bmain, Scene *scene, Object *ob)