style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / editors / object / object_group.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) Blender Foundation
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/object/object_group.c
29  *  \ingroup edobj
30  */
31
32
33 #include <string.h>
34
35 #include "BLI_blenlib.h"
36 #include "BLI_utildefines.h"
37
38 #include "DNA_group_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41
42 #include "BKE_context.h"
43 #include "BKE_depsgraph.h"
44 #include "BKE_group.h"
45 #include "BKE_main.h"
46 #include "BKE_report.h"
47
48 #include "ED_screen.h"
49 #include "ED_object.h"
50
51 #include "WM_api.h"
52 #include "WM_types.h"
53
54 #include "RNA_access.h"
55 #include "RNA_define.h"
56 #include "RNA_enum_types.h"
57
58 #include "object_intern.h"
59
60 /********************* 3d view operators ***********************/
61
62 static int objects_add_active_exec(bContext *C, wmOperator *op)
63 {
64         Main *bmain= CTX_data_main(C);
65         Scene *scene= CTX_data_scene(C);
66         Object *ob= OBACT;
67         Group *group;
68         int ok = 0;
69         
70         if (!ob) return OPERATOR_CANCELLED;
71         
72         /* linking to same group requires its own loop so we can avoid
73          * looking up the active objects groups each time */
74
75         for (group= bmain->group.first; group; group=group->id.next) {
76                 if (object_in_group(ob, group)) {
77                         /* Assign groups to selected objects */
78                         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
79                                 add_to_group(group, base->object, scene, base);
80                                 ok = 1;
81                         }
82                         CTX_DATA_END;
83                 }
84         }
85         
86         if (!ok) BKE_report(op->reports, RPT_ERROR, "Active Object contains no groups");
87         
88         DAG_scene_sort(bmain, scene);
89         WM_event_add_notifier(C, NC_GROUP|NA_EDITED, NULL);
90         
91         return OPERATOR_FINISHED;
92 }
93
94 void GROUP_OT_objects_add_active(wmOperatorType *ot)
95 {
96         /* identifiers */
97         ot->name = "Add Selected To Active Group";
98         ot->description = "Add the object to an object group that contains the active object";
99         ot->idname = "GROUP_OT_objects_add_active";
100         
101         /* api callbacks */
102         ot->exec = objects_add_active_exec;     
103         ot->poll = ED_operator_objectmode;
104
105         /* flags */
106         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
107 }
108
109 static int objects_remove_active_exec(bContext *C, wmOperator *op)
110 {
111         Main *bmain= CTX_data_main(C);
112         Scene *scene= CTX_data_scene(C);
113         Object *ob= OBACT;
114         Group *group;
115         int ok = 0;
116         
117         if (!ob) return OPERATOR_CANCELLED;
118         
119         /* linking to same group requires its own loop so we can avoid
120          * looking up the active objects groups each time */
121
122         for (group= bmain->group.first; group; group=group->id.next) {
123                 if (object_in_group(ob, group)) {
124                         /* Assign groups to selected objects */
125                         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
126                                 rem_from_group(group, base->object, scene, base);
127                                 ok = 1;
128                         }
129                         CTX_DATA_END;
130                 }
131         }
132         
133         if (!ok) BKE_report(op->reports, RPT_ERROR, "Active Object contains no groups");
134         
135         DAG_scene_sort(bmain, scene);
136         WM_event_add_notifier(C, NC_GROUP|NA_EDITED, NULL);
137         
138         return OPERATOR_FINISHED;
139 }
140
141 void GROUP_OT_objects_remove_active(wmOperatorType *ot)
142 {
143         /* identifiers */
144         ot->name = "Remove Selected From Active Group";
145         ot->description = "Remove the object from an object group that contains the active object";
146         ot->idname = "GROUP_OT_objects_remove_active";
147         
148         /* api callbacks */
149         ot->exec = objects_remove_active_exec;  
150         ot->poll = ED_operator_objectmode;
151         
152         /* flags */
153         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
154 }
155
156 static int group_objects_remove_exec(bContext *C, wmOperator *UNUSED(op))
157 {
158         Main *bmain= CTX_data_main(C);
159         Scene *scene= CTX_data_scene(C);
160         Group *group= NULL;
161
162         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
163                 group = NULL;
164                 while ((group = find_group(base->object, group)))
165                         rem_from_group(group, base->object, scene, base);
166         }
167         CTX_DATA_END;
168
169         DAG_scene_sort(bmain, scene);
170         WM_event_add_notifier(C, NC_GROUP|NA_EDITED, NULL);
171         
172         return OPERATOR_FINISHED;
173 }
174
175 void GROUP_OT_objects_remove(wmOperatorType *ot)
176 {
177         /* identifiers */
178         ot->name = "Remove From Groups";
179         ot->description = "Remove selected objects from all groups";
180         ot->idname = "GROUP_OT_objects_remove";
181         
182         /* api callbacks */
183         ot->exec = group_objects_remove_exec;   
184         ot->poll = ED_operator_objectmode;
185         
186         /* flags */
187         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
188 }
189
190 static int group_create_exec(bContext *C, wmOperator *op)
191 {
192         Main *bmain= CTX_data_main(C);
193         Scene *scene= CTX_data_scene(C);
194         Group *group= NULL;
195         char name[MAX_ID_NAME-2]; /* id name */
196         
197         RNA_string_get(op->ptr, "name", name);
198         
199         group= add_group(name);
200                 
201         CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) {
202                 add_to_group(group, base->object, scene, base);
203         }
204         CTX_DATA_END;
205
206         DAG_scene_sort(bmain, scene);
207         WM_event_add_notifier(C, NC_GROUP|NA_EDITED, NULL);
208         
209         return OPERATOR_FINISHED;
210 }
211
212 void GROUP_OT_create(wmOperatorType *ot)
213 {
214         /* identifiers */
215         ot->name = "Create New Group";
216         ot->description = "Create an object group from selected objects";
217         ot->idname = "GROUP_OT_create";
218         
219         /* api callbacks */
220         ot->exec = group_create_exec;   
221         ot->poll = ED_operator_objectmode;
222         
223         /* flags */
224         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
225         
226         RNA_def_string(ot->srna, "name", "Group", MAX_ID_NAME-2, "Name", "Name of the new group");
227 }
228
229 /****************** properties window operators *********************/
230
231 static int group_add_exec(bContext *C, wmOperator *UNUSED(op))
232 {
233         Scene *scene= CTX_data_scene(C);
234         Object *ob= ED_object_context(C);
235         Group *group;
236
237         if (ob == NULL)
238                 return OPERATOR_CANCELLED;
239
240         group= add_group("Group");
241         add_to_group(group, ob, scene, NULL);
242
243         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
244
245         return OPERATOR_FINISHED;
246 }
247
248 void OBJECT_OT_group_add(wmOperatorType *ot)
249 {
250         /* identifiers */
251         ot->name = "Add to Group";
252         ot->idname = "OBJECT_OT_group_add";
253         ot->description = "Add an object to a new group";
254         
255         /* api callbacks */
256         ot->exec = group_add_exec;
257
258         /* flags */
259         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
260 }
261
262 static int group_link_exec(bContext *C, wmOperator *op)
263 {
264         Scene *scene= CTX_data_scene(C);
265         Object *ob= ED_object_context(C);
266         Group *group= BLI_findlink(&CTX_data_main(C)->group, RNA_enum_get(op->ptr, "group"));
267
268         if (ELEM(NULL, ob, group))
269                 return OPERATOR_CANCELLED;
270
271         add_to_group(group, ob, scene, NULL);
272
273         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
274
275         return OPERATOR_FINISHED;
276 }
277
278 void OBJECT_OT_group_link(wmOperatorType *ot)
279 {
280         PropertyRNA *prop;
281
282         /* identifiers */
283         ot->name = "Link to Group";
284         ot->idname = "OBJECT_OT_group_link";
285         ot->description = "Add an object to an existing group";
286         
287         /* api callbacks */
288         ot->exec = group_link_exec;
289         ot->invoke = WM_enum_search_invoke;
290
291         /* flags */
292         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
293
294         /* properties */
295         prop= RNA_def_enum(ot->srna, "group", DummyRNA_NULL_items, 0, "Group", "");
296         RNA_def_enum_funcs(prop, RNA_group_local_itemf);
297         ot->prop = prop;
298 }
299
300 static int group_remove_exec(bContext *C, wmOperator *UNUSED(op))
301 {
302         Scene *scene= CTX_data_scene(C);
303         Object *ob= ED_object_context(C);
304         Group *group= CTX_data_pointer_get_type(C, "group", &RNA_Group).data;
305
306         if (!ob || !group)
307                 return OPERATOR_CANCELLED;
308
309         rem_from_group(group, ob, scene, NULL); /* base will be used if found */
310
311         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
312         
313         return OPERATOR_FINISHED;
314 }
315
316 void OBJECT_OT_group_remove(wmOperatorType *ot)
317 {
318         /* identifiers */
319         ot->name = "Remove Group";
320         ot->idname = "OBJECT_OT_group_remove";
321         
322         /* api callbacks */
323         ot->exec = group_remove_exec;
324
325         /* flags */
326         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
327 }
328