more lint includes
[blender.git] / source / blender / editors / interface / interface_ops.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) 2009 Blender Foundation.
21  * All rights reserved.
22  * 
23  * Contributor(s): Blender Foundation, Joshua Leung
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <stdio.h>
29 #include <math.h>
30 #include <string.h>
31
32
33 #include "MEM_guardedalloc.h"
34
35 #include "DNA_scene_types.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_math_color.h"
39
40 #include "BKE_context.h"
41 #include "BKE_utildefines.h"
42
43 #include "RNA_access.h"
44 #include "RNA_define.h"
45
46 #include "WM_api.h"
47 #include "WM_types.h"
48
49 #include "BIF_gl.h"
50
51
52 #include "UI_interface.h"
53
54 /* ********************************************************** */
55
56 typedef struct Eyedropper {
57         PointerRNA ptr;
58         PropertyRNA *prop;
59         int index;
60 } Eyedropper;
61
62 static int eyedropper_init(bContext *C, wmOperator *op)
63 {
64         Eyedropper *eye;
65         
66         op->customdata= eye= MEM_callocN(sizeof(Eyedropper), "Eyedropper");
67         
68         uiAnimContextProperty(C, &eye->ptr, &eye->prop, &eye->index);
69         
70         return (eye->ptr.data && eye->prop && RNA_property_editable(&eye->ptr, eye->prop));
71 }
72  
73 static void eyedropper_exit(bContext *C, wmOperator *op)
74 {
75         WM_cursor_restore(CTX_wm_window(C));
76         
77         if(op->customdata)
78                 MEM_freeN(op->customdata);
79         op->customdata= NULL;
80 }
81
82 static int eyedropper_cancel(bContext *C, wmOperator *op)
83 {
84         eyedropper_exit(C, op);
85         return OPERATOR_CANCELLED;
86 }
87
88 static void eyedropper_sample(bContext *C, Eyedropper *eye, short mx, short my)
89 {
90         if(RNA_property_type(eye->prop) == PROP_FLOAT) {
91                 const int color_manage = CTX_data_scene(C)->r.color_mgt_flag & R_COLOR_MANAGEMENT;
92                 float col[4];
93         
94                 RNA_property_float_get_array(&eye->ptr, eye->prop, col);
95                 
96                 glReadBuffer(GL_FRONT);
97                 glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, col);
98                 glReadBuffer(GL_BACK);
99         
100                 if (RNA_property_array_length(&eye->ptr, eye->prop) < 3) return;
101
102                 /* convert from screen (srgb) space to linear rgb space */
103                 if (color_manage && RNA_property_subtype(eye->prop) == PROP_COLOR)
104                         srgb_to_linearrgb_v3_v3(col, col);
105                 
106                 RNA_property_float_set_array(&eye->ptr, eye->prop, col);
107                 
108                 RNA_property_update(C, &eye->ptr, eye->prop);
109         }
110 }
111
112 /* main modal status check */
113 static int eyedropper_modal(bContext *C, wmOperator *op, wmEvent *event)
114 {
115         Eyedropper *eye = (Eyedropper *)op->customdata;
116         
117         switch(event->type) {
118                 case ESCKEY:
119                 case RIGHTMOUSE:
120                         return eyedropper_cancel(C, op);
121                 case LEFTMOUSE:
122                         if(event->val==KM_RELEASE) {
123                                 eyedropper_sample(C, eye, event->x, event->y);
124                                 eyedropper_exit(C, op);
125                                 return OPERATOR_FINISHED;
126                         }
127                         break;
128         }
129         
130         return OPERATOR_RUNNING_MODAL;
131 }
132
133 /* Modal Operator init */
134 static int eyedropper_invoke(bContext *C, wmOperator *op, wmEvent *event)
135 {
136         /* init */
137         if (eyedropper_init(C, op)) {
138                 WM_cursor_modal(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
139
140                 /* add temp handler */
141                 WM_event_add_modal_handler(C, op);
142                 
143                 return OPERATOR_RUNNING_MODAL;
144         } else {
145                 eyedropper_exit(C, op);
146                 return OPERATOR_CANCELLED;
147         }
148 }
149
150 /* Repeat operator */
151 static int eyedropper_exec (bContext *C, wmOperator *op)
152 {
153         /* init */
154         if (eyedropper_init(C, op)) {
155                 
156                 /* do something */
157                 
158                 /* cleanup */
159                 eyedropper_exit(C, op);
160                 
161                 return OPERATOR_FINISHED;
162         } else {
163                 return OPERATOR_CANCELLED;
164         }
165 }
166
167 static int eyedropper_poll(bContext *C)
168 {
169         if (!CTX_wm_window(C)) return 0;
170         else return 1;
171 }
172
173 void UI_OT_eyedropper(wmOperatorType *ot)
174 {
175         /* identifiers */
176         ot->name= "Eyedropper";
177         ot->idname= "UI_OT_eyedropper";
178         ot->description= "Sample a color from the Blender Window to store in a property";
179         
180         /* api callbacks */
181         ot->invoke= eyedropper_invoke;
182         ot->modal= eyedropper_modal;
183         ot->cancel= eyedropper_cancel;
184         ot->exec= eyedropper_exec;
185         ot->poll= eyedropper_poll;
186         
187         /* flags */
188         ot->flag= OPTYPE_BLOCKING;
189         
190         /* properties */
191 }
192
193
194 /* Copy Data Path Operator ------------------------ */
195
196 static int copy_data_path_button_exec(bContext *C, wmOperator *op)
197 {
198         PointerRNA ptr;
199         PropertyRNA *prop;
200         char *path;
201         int success= 0;
202         int index;
203
204         /* try to create driver using property retrieved from UI */
205         uiAnimContextProperty(C, &ptr, &prop, &index);
206
207         if (ptr.data && prop) {
208                 path= RNA_path_from_ID_to_property(&ptr, prop);
209                 
210                 if (path) {
211                         WM_clipboard_text_set(path, FALSE);
212                         MEM_freeN(path);
213                 }
214         }
215
216         /* since we're just copying, we don't really need to do anything else...*/
217         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
218 }
219
220 void UI_OT_copy_data_path_button(wmOperatorType *ot)
221 {
222         /* identifiers */
223         ot->name= "Copy Data Path";
224         ot->idname= "UI_OT_copy_data_path_button";
225         ot->description= "Copy the RNA data path for this property to the clipboard";
226
227         /* callbacks */
228         ot->exec= copy_data_path_button_exec;
229         //op->poll= ??? // TODO: need to have some valid property before this can be done
230
231         /* flags */
232         ot->flag= OPTYPE_REGISTER;
233 }
234
235 /* Reset to Default Values Button Operator ------------------------ */
236
237 static int reset_default_button_poll(bContext *C)
238 {
239         PointerRNA ptr;
240         PropertyRNA *prop;
241         int index;
242
243         uiAnimContextProperty(C, &ptr, &prop, &index);
244         
245         return (ptr.data && prop && RNA_property_editable(&ptr, prop));
246 }
247
248 static int reset_default_button_exec(bContext *C, wmOperator *op)
249 {
250         PointerRNA ptr;
251         PropertyRNA *prop;
252         int success= 0;
253         int index, all = RNA_boolean_get(op->ptr, "all");
254
255         /* try to reset the nominated setting to its default value */
256         uiAnimContextProperty(C, &ptr, &prop, &index);
257         
258         /* if there is a valid property that is editable... */
259         if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
260                 if(RNA_property_reset(&ptr, prop, (all)? -1: index)) {
261                         /* perform updates required for this property */
262                         RNA_property_update(C, &ptr, prop);
263                         success= 1;
264                 }
265         }
266         
267         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
268 }
269
270 void UI_OT_reset_default_button(wmOperatorType *ot)
271 {
272         /* identifiers */
273         ot->name= "Reset to Default Value";
274         ot->idname= "UI_OT_reset_default_button";
275         ot->description= "Reset this property's value to its default value";
276
277         /* callbacks */
278         ot->poll= reset_default_button_poll;
279         ot->exec= reset_default_button_exec;
280
281         /* flags */
282         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
283         
284         /* properties */
285         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array.");
286 }
287
288 /* Copy To Selected Operator ------------------------ */
289
290 static int copy_to_selected_list(bContext *C, PointerRNA *ptr, ListBase *lb)
291 {
292         if(RNA_struct_is_a(ptr->type, &RNA_Object))
293                 *lb = CTX_data_collection_get(C, "selected_editable_objects");
294         else if(RNA_struct_is_a(ptr->type, &RNA_EditBone))
295                 *lb = CTX_data_collection_get(C, "selected_editable_bones");
296         else if(RNA_struct_is_a(ptr->type, &RNA_PoseBone))
297                 *lb = CTX_data_collection_get(C, "selected_pose_bones");
298         else
299                 return 0;
300         
301         return 1;
302 }
303
304 static int copy_to_selected_button_poll(bContext *C)
305 {
306         PointerRNA ptr;
307         PropertyRNA *prop;
308         int index, success= 0;
309
310         uiAnimContextProperty(C, &ptr, &prop, &index);
311
312         if (ptr.data && prop) {
313                 CollectionPointerLink *link;
314                 ListBase lb;
315
316                 if(copy_to_selected_list(C, &ptr, &lb)) {
317                         for(link= lb.first; link; link=link->next)
318                                 if(link->ptr.data != ptr.data && RNA_property_editable(&link->ptr, prop))
319                                         success= 1;
320
321                         BLI_freelistN(&lb);
322                 }
323         }
324
325         return success;
326 }
327
328 static int copy_to_selected_button_exec(bContext *C, wmOperator *op)
329 {
330         PointerRNA ptr;
331         PropertyRNA *prop;
332         int success= 0;
333         int index, all = RNA_boolean_get(op->ptr, "all");
334
335         /* try to reset the nominated setting to its default value */
336         uiAnimContextProperty(C, &ptr, &prop, &index);
337         
338         /* if there is a valid property that is editable... */
339         if (ptr.data && prop) {
340                 CollectionPointerLink *link;
341                 ListBase lb;
342
343                 if(copy_to_selected_list(C, &ptr, &lb)) {
344                         for(link= lb.first; link; link=link->next) {
345                                 if(link->ptr.data != ptr.data && RNA_property_editable(&link->ptr, prop)) {
346                                         if(RNA_property_copy(&link->ptr, &ptr, prop, (all)? -1: index)) {
347                                                 RNA_property_update(C, &link->ptr, prop);
348                                                 success= 1;
349                                         }
350                                 }
351                         }
352
353                         BLI_freelistN(&lb);
354                 }
355         }
356         
357         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
358 }
359
360 void UI_OT_copy_to_selected_button(wmOperatorType *ot)
361 {
362         /* identifiers */
363         ot->name= "Copy To Selected";
364         ot->idname= "UI_OT_copy_to_selected_button";
365         ot->description= "Copy property from this object to selected objects or bones";
366
367         /* callbacks */
368         ot->poll= copy_to_selected_button_poll;
369         ot->exec= copy_to_selected_button_exec;
370
371         /* flags */
372         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
373
374         /* properties */
375         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array.");
376 }
377  
378 /* ********************************************************* */
379 /* Registration */
380
381 void UI_buttons_operatortypes(void)
382 {
383         WM_operatortype_append(UI_OT_eyedropper);
384         WM_operatortype_append(UI_OT_copy_data_path_button);
385         WM_operatortype_append(UI_OT_reset_default_button);
386         WM_operatortype_append(UI_OT_copy_to_selected_button);
387 }
388