Move `Library.runtime` to be a pointer, move the related `LibraryRuntime` struct to `BKE_library.hh`. Similar to e.g. Mesh.runtime, that pointer is expected to always be valid, and is allocated at readtime or when creating a new Library ID. Related smaller changes: * Write code now uses standard ID writing codepath for Library IDs too. * Runtime pointer is reset to nullptr before writing. * Looking up a library by its absolute path is now handled through a dedicated utils, `search_filepath_abs`, instead of using `BLI_findstring`. Pull Request: https://projects.blender.org/blender/blender/pulls/134188
212 lines
6.0 KiB
C++
212 lines
6.0 KiB
C++
/* SPDX-FileCopyrightText: 2013 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
/** \file
|
|
* \ingroup editor_physics
|
|
* \brief Rigid Body constraint editing operators
|
|
*/
|
|
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
|
|
#include "DNA_collection_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_rigidbody_types.h"
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "BKE_collection.hh"
|
|
#include "BKE_context.hh"
|
|
#include "BKE_layer.hh"
|
|
#include "BKE_lib_id.hh"
|
|
#include "BKE_library.hh"
|
|
#include "BKE_report.hh"
|
|
#include "BKE_rigidbody.h"
|
|
|
|
#include "DEG_depsgraph.hh"
|
|
#include "DEG_depsgraph_build.hh"
|
|
|
|
#include "RNA_access.hh"
|
|
#include "RNA_define.hh"
|
|
#include "RNA_enum_types.hh"
|
|
|
|
#include "WM_api.hh"
|
|
#include "WM_types.hh"
|
|
|
|
#include "ED_object.hh"
|
|
#include "ED_physics.hh"
|
|
#include "ED_screen.hh"
|
|
|
|
#include "physics_intern.hh"
|
|
|
|
/* ********************************************** */
|
|
/* Helper API's for RigidBody Constraint Editing */
|
|
|
|
static bool operator_rigidbody_constraints_editable_poll(Scene *scene)
|
|
{
|
|
if (scene == nullptr || !ID_IS_EDITABLE(scene) || ID_IS_OVERRIDE_LIBRARY(scene) ||
|
|
(scene->rigidbody_world != nullptr && scene->rigidbody_world->constraints != nullptr &&
|
|
(!ID_IS_EDITABLE(scene->rigidbody_world->constraints) ||
|
|
ID_IS_OVERRIDE_LIBRARY(scene->rigidbody_world->constraints))))
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static bool ED_operator_rigidbody_con_active_poll(bContext *C)
|
|
{
|
|
Scene *scene = CTX_data_scene(C);
|
|
if (!operator_rigidbody_constraints_editable_poll(scene)) {
|
|
return false;
|
|
}
|
|
|
|
if (ED_operator_object_active_editable(C)) {
|
|
Object *ob = blender::ed::object::context_active_object(C);
|
|
return (ob && ob->rigidbody_constraint);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
static bool ED_operator_rigidbody_con_add_poll(bContext *C)
|
|
{
|
|
Scene *scene = CTX_data_scene(C);
|
|
if (!operator_rigidbody_constraints_editable_poll(scene)) {
|
|
return false;
|
|
}
|
|
return ED_operator_object_active_editable(C);
|
|
}
|
|
|
|
bool ED_rigidbody_constraint_add(
|
|
Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
|
|
{
|
|
RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
|
|
|
|
/* check that object doesn't already have a constraint */
|
|
if (ob->rigidbody_constraint) {
|
|
BKE_reportf(
|
|
reports, RPT_INFO, "Object '%s' already has a Rigid Body Constraint", ob->id.name + 2);
|
|
return false;
|
|
}
|
|
/* create constraint group if it doesn't already exits */
|
|
if (rbw->constraints == nullptr) {
|
|
rbw->constraints = BKE_collection_add(bmain, nullptr, "RigidBodyConstraints");
|
|
id_us_plus(&rbw->constraints->id);
|
|
}
|
|
/* make rigidbody constraint settings */
|
|
ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
|
|
|
|
/* add constraint to rigid body constraint group */
|
|
BKE_collection_object_add(bmain, rbw->constraints, ob);
|
|
|
|
DEG_relations_tag_update(bmain);
|
|
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
|
|
DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_SYNC_TO_EVAL);
|
|
|
|
return true;
|
|
}
|
|
|
|
void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
|
|
{
|
|
BKE_rigidbody_remove_constraint(bmain, scene, ob, false);
|
|
|
|
DEG_relations_tag_update(bmain);
|
|
DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
|
|
}
|
|
|
|
/* ********************************************** */
|
|
/* Active Object Add/Remove Operators */
|
|
|
|
/* ************ Add Rigid Body Constraint ************** */
|
|
|
|
static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
|
|
{
|
|
Main *bmain = CTX_data_main(C);
|
|
Scene *scene = CTX_data_scene(C);
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
|
|
BKE_view_layer_synced_ensure(scene, view_layer);
|
|
Object *ob = BKE_view_layer_active_object_get(view_layer);
|
|
int type = RNA_enum_get(op->ptr, "type");
|
|
bool changed;
|
|
|
|
/* sanity checks */
|
|
if (ELEM(nullptr, scene, rbw)) {
|
|
BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to add Rigid Body Constraint to");
|
|
return OPERATOR_CANCELLED;
|
|
}
|
|
/* apply to active object */
|
|
changed = ED_rigidbody_constraint_add(bmain, scene, ob, type, op->reports);
|
|
|
|
if (changed) {
|
|
/* send updates */
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, nullptr);
|
|
|
|
/* done */
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
return OPERATOR_CANCELLED;
|
|
}
|
|
|
|
void RIGIDBODY_OT_constraint_add(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->idname = "RIGIDBODY_OT_constraint_add";
|
|
ot->name = "Add Rigid Body Constraint";
|
|
ot->description = "Add Rigid Body Constraint to active object";
|
|
|
|
/* callbacks */
|
|
ot->exec = rigidbody_con_add_exec;
|
|
ot->poll = ED_operator_rigidbody_con_add_poll;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
/* properties */
|
|
ot->prop = RNA_def_enum(ot->srna,
|
|
"type",
|
|
rna_enum_rigidbody_constraint_type_items,
|
|
RBC_TYPE_FIXED,
|
|
"Rigid Body Constraint Type",
|
|
"");
|
|
}
|
|
|
|
/* ************ Remove Rigid Body Constraint ************** */
|
|
|
|
static int rigidbody_con_remove_exec(bContext *C, wmOperator *op)
|
|
{
|
|
Main *bmain = CTX_data_main(C);
|
|
Scene *scene = CTX_data_scene(C);
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
BKE_view_layer_synced_ensure(scene, view_layer);
|
|
Object *ob = BKE_view_layer_active_object_get(view_layer);
|
|
|
|
/* apply to active object */
|
|
if (ELEM(nullptr, ob, ob->rigidbody_constraint)) {
|
|
BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body Constraint to remove");
|
|
return OPERATOR_CANCELLED;
|
|
}
|
|
ED_rigidbody_constraint_remove(bmain, scene, ob);
|
|
|
|
/* send updates */
|
|
WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, nullptr);
|
|
|
|
/* done */
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
void RIGIDBODY_OT_constraint_remove(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->idname = "RIGIDBODY_OT_constraint_remove";
|
|
ot->name = "Remove Rigid Body Constraint";
|
|
ot->description = "Remove Rigid Body Constraint from Object";
|
|
|
|
/* callbacks */
|
|
ot->exec = rigidbody_con_remove_exec;
|
|
ot->poll = ED_operator_rigidbody_con_active_poll;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
}
|