6d61c8c5819cd7e1c48ff845a67ecb1c6c0c0783
[blender-staging.git] / source / blender / editors / screen / screen_context.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) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "DNA_object_types.h"
31 #include "DNA_armature_types.h"
32 #include "DNA_action_types.h"
33 #include "DNA_scene_types.h"
34 #include "DNA_screen_types.h"
35
36 #include "BKE_context.h"
37 #include "BKE_utildefines.h"
38 #include "BKE_global.h"
39 #include "BKE_action.h"
40
41 #include "RNA_access.h"
42
43 #include "ED_object.h"
44 #include "ED_armature.h"
45
46 int ed_screen_context(const bContext *C, const char *member, bContextDataResult *result)
47 {
48         bScreen *sc= CTX_wm_screen(C);
49         Scene *scene= sc->scene;
50         Base *base;
51
52 #if 0   /* Using the context breaks adding objects in the UI. Need to find out why - campbell */
53         Object *obact= CTX_data_active_object(C);
54         Object *obedit= CTX_data_edit_object(C);
55         base= CTX_data_active_base(C);
56 #else
57         Object *obedit= scene->obedit; 
58         Object *obact= OBACT;
59         base= BASACT;
60 #endif
61
62         if(CTX_data_dir(member)) {
63                 static const char *dir[] = {
64                         "scene", "selected_objects", "selected_bases",
65                         "selected_editable_objects", "selected_editable_bases",
66                         "visible_bones", "editable_bones", "selected_bones", "selected_editable_bones",
67                         "visible_pose_bones", "selected_pose_bones", "active_bone", "active_pose_bone",
68                         "active_base", "active_object", "object", "edit_object",
69                         "sculpt_object", "vertex_paint_object", "weight_paint_object",
70                         "texture_paint_object", "particle_edit_object", NULL};
71
72                 CTX_data_dir_set(result, dir);
73                 return 1;
74         }
75         else if(CTX_data_equals(member, "scene")) {
76                 CTX_data_id_pointer_set(result, &scene->id);
77                 return 1;
78         }
79         else if(CTX_data_equals(member, "selected_objects") || CTX_data_equals(member, "selected_bases")) {
80                 int selected_objects= CTX_data_equals(member, "selected_objects");
81
82                 for(base=scene->base.first; base; base=base->next) {
83                         if((base->flag & SELECT) && (base->lay & scene->lay)) {
84                                 if(selected_objects)
85                                         CTX_data_id_list_add(result, &base->object->id);
86                                 else
87                                         CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
88                         }
89                 }
90
91                 return 1;
92         }
93         else if(CTX_data_equals(member, "selected_editable_objects") || CTX_data_equals(member, "selected_editable_bases")) {
94                 int selected_editable_objects= CTX_data_equals(member, "selected_editable_objects");
95
96                 for(base=scene->base.first; base; base=base->next) {
97                         if((base->flag & SELECT) && (base->lay & scene->lay)) {
98                                 if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) {
99                                         if(0==object_is_libdata(base->object)) {
100                                                 if(selected_editable_objects)
101                                                         CTX_data_id_list_add(result, &base->object->id);
102                                                 else
103                                                         CTX_data_list_add(result, &scene->id, &RNA_ObjectBase, base);
104                                         }
105                                 }
106                         }
107                 }
108
109                 return 1;
110         }
111         else if(CTX_data_equals(member, "visible_bones") || CTX_data_equals(member, "editable_bones")) {
112                 bArmature *arm= (obedit) ? obedit->data : NULL;
113                 EditBone *ebone, *flipbone=NULL;
114                 int editable_bones= CTX_data_equals(member, "editable_bones");
115                 
116                 if (arm && arm->edbo) {
117                         /* Attention: X-Axis Mirroring is also handled here... */
118                         for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
119                                 /* first and foremost, bone must be visible and selected */
120                                 if (EBONE_VISIBLE(arm, ebone)) {
121                                         /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
122                                          * so that most users of this data don't need to explicitly check for it themselves.
123                                          * 
124                                          * We need to make sure that these mirrored copies are not selected, otherwise some
125                                          * bones will be operated on twice.
126                                          */
127                                         if (arm->flag & ARM_MIRROR_EDIT)
128                                                 flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
129                                         
130                                         /* if we're filtering for editable too, use the check for that instead, as it has selection check too */
131                                         if (editable_bones) {
132                                                 /* only selected + editable */
133                                                 if (EBONE_EDITABLE(ebone)) {
134                                                         CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
135                                                 
136                                                         if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
137                                                                 CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
138                                                 }
139                                         }
140                                         else {
141                                                 /* only include bones if visible */
142                                                 CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
143                                                 
144                                                 if ((flipbone) && EBONE_VISIBLE(arm, flipbone)==0)
145                                                         CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
146                                         }
147                                 }
148                         }       
149                         
150                         return 1;
151                 }
152         }
153         else if(CTX_data_equals(member, "selected_bones") || CTX_data_equals(member, "selected_editable_bones")) {
154                 bArmature *arm= (obedit) ? obedit->data : NULL;
155                 EditBone *ebone, *flipbone=NULL;
156                 int selected_editable_bones= CTX_data_equals(member, "selected_editable_bones");
157                 
158                 if (arm && arm->edbo) {
159                         /* Attention: X-Axis Mirroring is also handled here... */
160                         for (ebone= arm->edbo->first; ebone; ebone= ebone->next) {
161                                 /* first and foremost, bone must be visible and selected */
162                                 if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_SELECTED)) {
163                                         /* Get 'x-axis mirror equivalent' bone if the X-Axis Mirroring option is enabled
164                                          * so that most users of this data don't need to explicitly check for it themselves.
165                                          * 
166                                          * We need to make sure that these mirrored copies are not selected, otherwise some
167                                          * bones will be operated on twice.
168                                          */
169                                         if (arm->flag & ARM_MIRROR_EDIT)
170                                                 flipbone = ED_armature_bone_get_mirrored(arm->edbo, ebone);
171                                         
172                                         /* if we're filtering for editable too, use the check for that instead, as it has selection check too */
173                                         if (selected_editable_bones) {
174                                                 /* only selected + editable */
175                                                 if (EBONE_EDITABLE(ebone)) {
176                                                         CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
177                                                 
178                                                         if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
179                                                                 CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
180                                                 }
181                                         }
182                                         else {
183                                                 /* only include bones if selected */
184                                                 CTX_data_list_add(result, &arm->id, &RNA_EditBone, ebone);
185                                                 
186                                                 if ((flipbone) && !(flipbone->flag & BONE_SELECTED))
187                                                         CTX_data_list_add(result, &arm->id, &RNA_EditBone, flipbone);
188                                         }
189                                 }
190                         }       
191                         
192                         return 1;
193                 }
194         }
195         else if(CTX_data_equals(member, "visible_pose_bones")) {
196                 bArmature *arm= (obact) ? obact->data : NULL;
197                 bPoseChannel *pchan;
198                 
199                 if (obact && obact->pose && arm) {
200                         for (pchan= obact->pose->chanbase.first; pchan; pchan= pchan->next) {
201                                 /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
202                                 if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
203                                         CTX_data_list_add(result, &obact->id, &RNA_PoseBone, pchan);
204                                 }
205                         }
206                         
207                         return 1;
208                 }
209         }
210         else if(CTX_data_equals(member, "selected_pose_bones")) {
211                 bArmature *arm= (obact) ? obact->data : NULL;
212                 bPoseChannel *pchan;
213                 
214                 if (obact && obact->pose && arm) {
215                         for (pchan= obact->pose->chanbase.first; pchan; pchan= pchan->next) {
216                                 /* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
217                                 if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
218                                         if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone)
219                                                 CTX_data_list_add(result, &obact->id, &RNA_PoseBone, pchan);
220                                 }
221                         }
222                         
223                         return 1;
224                 }
225         }
226         else if(CTX_data_equals(member, "active_bone")) {
227                 if(obact && obact->type == OB_ARMATURE) {
228                         bArmature *arm= obact->data;
229                         if(arm->edbo) {
230                                 if(arm->act_edbone) {
231                                         CTX_data_pointer_set(result, &arm->id, &RNA_EditBone, arm->act_edbone);
232                                         return 1;
233                                 }
234                         }
235                         else {
236                                 if(arm->act_bone) {
237                                         CTX_data_pointer_set(result, &arm->id, &RNA_Bone, arm->act_bone);
238                                         return 1;
239                                 }
240                         }
241                 }
242         }
243         else if(CTX_data_equals(member, "active_pose_bone")) {
244                 bPoseChannel *pchan;
245                 
246                 pchan= get_active_posechannel(obact);
247                 if (pchan) {
248                         CTX_data_pointer_set(result, &obact->id, &RNA_PoseBone, pchan);
249                         return 1;
250                 }
251         }
252         else if(CTX_data_equals(member, "active_base")) {
253                 if(base)
254                         CTX_data_pointer_set(result, &scene->id, &RNA_ObjectBase, base);
255
256                 return 1;
257         }
258         else if(CTX_data_equals(member, "active_object")) {
259                 if(obact)
260                         CTX_data_id_pointer_set(result, &obact->id);
261
262                 return 1;
263         }
264         else if(CTX_data_equals(member, "object")) {
265                 if(obact)
266                         CTX_data_id_pointer_set(result, &obact->id);
267
268                 return 1;
269         }
270         else if(CTX_data_equals(member, "edit_object")) {
271                 /* convenience for now, 1 object per scene in editmode */
272                 if(obedit)
273                         CTX_data_id_pointer_set(result, &obedit->id);
274                 
275                 return 1;
276         }
277         else if(CTX_data_equals(member, "sculpt_object")) {
278                 if(obact && (obact->mode & OB_MODE_SCULPT))
279                         CTX_data_id_pointer_set(result, &obact->id);
280
281                 return 1;
282         }
283         else if(CTX_data_equals(member, "vertex_paint_object")) {
284                 if(obact && (obact->mode & OB_MODE_VERTEX_PAINT))
285                         CTX_data_id_pointer_set(result, &obact->id);
286
287                 return 1;
288         }
289         else if(CTX_data_equals(member, "weight_paint_object")) {
290                 if(obact && (obact->mode & OB_MODE_WEIGHT_PAINT))
291                         CTX_data_id_pointer_set(result, &obact->id);
292
293                 return 1;
294         }
295         else if(CTX_data_equals(member, "texture_paint_object")) {
296                 if(obact && (obact->mode & OB_MODE_TEXTURE_PAINT))
297                         CTX_data_id_pointer_set(result, &obact->id);
298
299                 return 1;
300         }
301         else if(CTX_data_equals(member, "particle_edit_object")) {
302                 if(obact && (obact->mode & OB_MODE_PARTICLE_EDIT))
303                         CTX_data_id_pointer_set(result, &obact->id);
304
305                 return 1;
306         }
307         else {
308                 return 0; /* not found */
309         }
310
311         return -1; /* found but not available */
312 }
313