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