Cleanup: style, use braces for editors
[blender.git] / source / blender / editors / physics / rigidbody_constraint.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2013 Blender Foundation
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup editor_physics
22  * \brief Rigid Body constraint editing operators
23  */
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "DNA_object_types.h"
29 #include "DNA_rigidbody_types.h"
30 #include "DNA_scene_types.h"
31
32 #include "BKE_collection.h"
33 #include "BKE_context.h"
34 #include "BKE_library.h"
35 #include "BKE_main.h"
36 #include "BKE_report.h"
37 #include "BKE_rigidbody.h"
38
39 #include "DEG_depsgraph.h"
40 #include "DEG_depsgraph_build.h"
41
42 #include "RNA_access.h"
43 #include "RNA_define.h"
44 #include "RNA_enum_types.h"
45
46 #include "WM_api.h"
47 #include "WM_types.h"
48
49 #include "ED_physics.h"
50 #include "ED_screen.h"
51
52 #include "physics_intern.h"
53
54 /* ********************************************** */
55 /* Helper API's for RigidBody Constraint Editing */
56
57 static bool ED_operator_rigidbody_con_active_poll(bContext *C)
58 {
59   if (ED_operator_object_active_editable(C)) {
60     Object *ob = CTX_data_active_object(C);
61     return (ob && ob->rigidbody_constraint);
62   }
63   else {
64     return 0;
65   }
66 }
67
68 bool ED_rigidbody_constraint_add(
69     Main *bmain, Scene *scene, Object *ob, int type, ReportList *reports)
70 {
71   RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
72
73   /* check that object doesn't already have a constraint */
74   if (ob->rigidbody_constraint) {
75     BKE_reportf(
76         reports, RPT_INFO, "Object '%s' already has a Rigid Body Constraint", ob->id.name + 2);
77     return false;
78   }
79   /* create constraint group if it doesn't already exits */
80   if (rbw->constraints == NULL) {
81     rbw->constraints = BKE_collection_add(bmain, NULL, "RigidBodyConstraints");
82     id_fake_user_set(&rbw->constraints->id);
83   }
84   /* make rigidbody constraint settings */
85   ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type);
86
87   /* add constraint to rigid body constraint group */
88   BKE_collection_object_add(bmain, rbw->constraints, ob);
89
90   DEG_relations_tag_update(bmain);
91   DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
92   DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
93
94   return true;
95 }
96
97 void ED_rigidbody_constraint_remove(Main *bmain, Scene *scene, Object *ob)
98 {
99   RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
100
101   BKE_rigidbody_remove_constraint(scene, ob);
102   if (rbw) {
103     BKE_collection_object_remove(bmain, rbw->constraints, ob, false);
104     DEG_id_tag_update(&rbw->constraints->id, ID_RECALC_COPY_ON_WRITE);
105   }
106
107   DEG_relations_tag_update(bmain);
108   DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM);
109 }
110
111 /* ********************************************** */
112 /* Active Object Add/Remove Operators */
113
114 /* ************ Add Rigid Body Constraint ************** */
115
116 static int rigidbody_con_add_exec(bContext *C, wmOperator *op)
117 {
118   Main *bmain = CTX_data_main(C);
119   Scene *scene = CTX_data_scene(C);
120   ViewLayer *view_layer = CTX_data_view_layer(C);
121   RigidBodyWorld *rbw = BKE_rigidbody_get_world(scene);
122   Object *ob = OBACT(view_layer);
123   int type = RNA_enum_get(op->ptr, "type");
124   bool changed;
125
126   /* sanity checks */
127   if (ELEM(NULL, scene, rbw)) {
128     BKE_report(op->reports, RPT_ERROR, "No Rigid Body World to add Rigid Body Constraint to");
129     return OPERATOR_CANCELLED;
130   }
131   /* apply to active object */
132   changed = ED_rigidbody_constraint_add(bmain, scene, ob, type, op->reports);
133
134   if (changed) {
135     /* send updates */
136     WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
137
138     /* done */
139     return OPERATOR_FINISHED;
140   }
141   else {
142     return OPERATOR_CANCELLED;
143   }
144 }
145
146 void RIGIDBODY_OT_constraint_add(wmOperatorType *ot)
147 {
148   /* identifiers */
149   ot->idname = "RIGIDBODY_OT_constraint_add";
150   ot->name = "Add Rigid Body Constraint";
151   ot->description = "Add Rigid Body Constraint to active object";
152
153   /* callbacks */
154   ot->exec = rigidbody_con_add_exec;
155   ot->poll = ED_operator_object_active_editable;
156
157   /* flags */
158   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
159
160   /* properties */
161   ot->prop = RNA_def_enum(ot->srna,
162                           "type",
163                           rna_enum_rigidbody_constraint_type_items,
164                           RBC_TYPE_FIXED,
165                           "Rigid Body Constraint Type",
166                           "");
167 }
168
169 /* ************ Remove Rigid Body Constraint ************** */
170
171 static int rigidbody_con_remove_exec(bContext *C, wmOperator *op)
172 {
173   Main *bmain = CTX_data_main(C);
174   Scene *scene = CTX_data_scene(C);
175   ViewLayer *view_layer = CTX_data_view_layer(C);
176   Object *ob = OBACT(view_layer);
177
178   /* apply to active object */
179   if (ELEM(NULL, ob, ob->rigidbody_constraint)) {
180     BKE_report(op->reports, RPT_ERROR, "Object has no Rigid Body Constraint to remove");
181     return OPERATOR_CANCELLED;
182   }
183   else {
184     ED_rigidbody_constraint_remove(bmain, scene, ob);
185   }
186
187   /* send updates */
188   WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, NULL);
189
190   /* done */
191   return OPERATOR_FINISHED;
192 }
193
194 void RIGIDBODY_OT_constraint_remove(wmOperatorType *ot)
195 {
196   /* identifiers */
197   ot->idname = "RIGIDBODY_OT_constraint_remove";
198   ot->name = "Remove Rigid Body Constraint";
199   ot->description = "Remove Rigid Body Constraint from Object";
200
201   /* callbacks */
202   ot->exec = rigidbody_con_remove_exec;
203   ot->poll = ED_operator_rigidbody_con_active_poll;
204
205   /* flags */
206   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
207 }