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