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:
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
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue