4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
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.
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.
20 * The Original Code is Copyright (C) 2009 Blender Foundation.
21 * All rights reserved.
23 * Contributor(s): Blender Foundation, Joshua Leung
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file blender/editors/interface/interface_ops.c
29 * \ingroup edinterface
37 #include "MEM_guardedalloc.h"
39 #include "DNA_scene_types.h"
40 #include "DNA_screen_types.h"
41 #include "DNA_text_types.h" /* for UI_OT_reports_to_text */
43 #include "BLI_blenlib.h"
44 #include "BLI_math_color.h"
45 #include "BLI_utildefines.h"
47 #include "BKE_context.h"
48 #include "BKE_global.h"
49 #include "BKE_text.h" /* for UI_OT_reports_to_text */
50 #include "BKE_report.h"
52 #include "RNA_access.h"
53 #include "RNA_define.h"
57 #include "UI_interface.h"
59 #include "interface_intern.h"
66 /* ********************************************************** */
68 typedef struct Eyedropper {
74 static int eyedropper_init(bContext *C, wmOperator *op)
78 op->customdata= eye= MEM_callocN(sizeof(Eyedropper), "Eyedropper");
80 uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index);
82 return (eye->ptr.data && eye->prop && RNA_property_editable(&eye->ptr, eye->prop));
85 static void eyedropper_exit(bContext *C, wmOperator *op)
87 WM_cursor_restore(CTX_wm_window(C));
90 MEM_freeN(op->customdata);
94 static int eyedropper_cancel(bContext *C, wmOperator *op)
96 eyedropper_exit(C, op);
97 return OPERATOR_CANCELLED;
100 static void eyedropper_sample(bContext *C, Eyedropper *eye, int mx, int my)
102 if(RNA_property_type(eye->prop) == PROP_FLOAT) {
103 const int color_manage = CTX_data_scene(C)->r.color_mgt_flag & R_COLOR_MANAGEMENT;
106 RNA_property_float_get_array(&eye->ptr, eye->prop, col);
108 glReadBuffer(GL_FRONT);
109 glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, col);
110 glReadBuffer(GL_BACK);
112 if (RNA_property_array_length(&eye->ptr, eye->prop) < 3) return;
114 /* convert from screen (srgb) space to linear rgb space */
115 if (color_manage && RNA_property_subtype(eye->prop) == PROP_COLOR)
116 srgb_to_linearrgb_v3_v3(col, col);
118 RNA_property_float_set_array(&eye->ptr, eye->prop, col);
120 RNA_property_update(C, &eye->ptr, eye->prop);
124 /* main modal status check */
125 static int eyedropper_modal(bContext *C, wmOperator *op, wmEvent *event)
127 Eyedropper *eye = (Eyedropper *)op->customdata;
129 switch(event->type) {
132 return eyedropper_cancel(C, op);
134 if(event->val==KM_RELEASE) {
135 eyedropper_sample(C, eye, event->x, event->y);
136 eyedropper_exit(C, op);
137 return OPERATOR_FINISHED;
142 return OPERATOR_RUNNING_MODAL;
145 /* Modal Operator init */
146 static int eyedropper_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
149 if (eyedropper_init(C, op)) {
150 WM_cursor_modal(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
152 /* add temp handler */
153 WM_event_add_modal_handler(C, op);
155 return OPERATOR_RUNNING_MODAL;
157 eyedropper_exit(C, op);
158 return OPERATOR_CANCELLED;
162 /* Repeat operator */
163 static int eyedropper_exec (bContext *C, wmOperator *op)
166 if (eyedropper_init(C, op)) {
171 eyedropper_exit(C, op);
173 return OPERATOR_FINISHED;
175 return OPERATOR_CANCELLED;
179 static int eyedropper_poll(bContext *C)
181 if (!CTX_wm_window(C)) return 0;
185 static void UI_OT_eyedropper(wmOperatorType *ot)
188 ot->name= "Eyedropper";
189 ot->idname= "UI_OT_eyedropper";
190 ot->description= "Sample a color from the Blender Window to store in a property";
193 ot->invoke= eyedropper_invoke;
194 ot->modal= eyedropper_modal;
195 ot->cancel= eyedropper_cancel;
196 ot->exec= eyedropper_exec;
197 ot->poll= eyedropper_poll;
200 ot->flag= OPTYPE_BLOCKING;
205 /* Reset Default Theme ------------------------ */
207 static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
209 ui_theme_init_default();
210 WM_event_add_notifier(C, NC_WINDOW, NULL);
212 return OPERATOR_FINISHED;
215 static void UI_OT_reset_default_theme(wmOperatorType *ot)
218 ot->name= "Reset to Default Theme";
219 ot->idname= "UI_OT_reset_default_theme";
220 ot->description= "Reset to the default theme colors";
223 ot->exec= reset_default_theme_exec;
226 ot->flag= OPTYPE_REGISTER;
229 /* Copy Data Path Operator ------------------------ */
231 static int copy_data_path_button_exec(bContext *C, wmOperator *UNUSED(op))
239 /* try to create driver using property retrieved from UI */
240 uiContextActiveProperty(C, &ptr, &prop, &index);
242 if (ptr.id.data && ptr.data && prop) {
243 path= RNA_path_from_ID_to_property(&ptr, prop);
246 WM_clipboard_text_set(path, FALSE);
251 /* since we're just copying, we don't really need to do anything else...*/
252 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
255 static void UI_OT_copy_data_path_button(wmOperatorType *ot)
258 ot->name= "Copy Data Path";
259 ot->idname= "UI_OT_copy_data_path_button";
260 ot->description= "Copy the RNA data path for this property to the clipboard";
263 ot->exec= copy_data_path_button_exec;
264 //op->poll= ??? // TODO: need to have some valid property before this can be done
267 ot->flag= OPTYPE_REGISTER;
270 /* Reset to Default Values Button Operator ------------------------ */
272 static int reset_default_button_poll(bContext *C)
278 uiContextActiveProperty(C, &ptr, &prop, &index);
280 return (ptr.data && prop && RNA_property_editable(&ptr, prop));
283 static int reset_default_button_exec(bContext *C, wmOperator *op)
288 int index, all = RNA_boolean_get(op->ptr, "all");
290 /* try to reset the nominated setting to its default value */
291 uiContextActiveProperty(C, &ptr, &prop, &index);
293 /* if there is a valid property that is editable... */
294 if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
295 if(RNA_property_reset(&ptr, prop, (all)? -1: index)) {
296 /* perform updates required for this property */
297 RNA_property_update(C, &ptr, prop);
302 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
305 static void UI_OT_reset_default_button(wmOperatorType *ot)
308 ot->name= "Reset to Default Value";
309 ot->idname= "UI_OT_reset_default_button";
310 ot->description= "Reset this property's value to its default value";
313 ot->poll= reset_default_button_poll;
314 ot->exec= reset_default_button_exec;
317 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
320 RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array.");
323 /* Copy To Selected Operator ------------------------ */
325 static int copy_to_selected_list(bContext *C, PointerRNA *ptr, ListBase *lb)
327 if(RNA_struct_is_a(ptr->type, &RNA_Object))
328 *lb = CTX_data_collection_get(C, "selected_editable_objects");
329 else if(RNA_struct_is_a(ptr->type, &RNA_EditBone))
330 *lb = CTX_data_collection_get(C, "selected_editable_bones");
331 else if(RNA_struct_is_a(ptr->type, &RNA_PoseBone))
332 *lb = CTX_data_collection_get(C, "selected_pose_bones");
333 else if(RNA_struct_is_a(ptr->type, &RNA_Sequence))
334 *lb = CTX_data_collection_get(C, "selected_editable_sequences");
341 static int copy_to_selected_button_poll(bContext *C)
345 int index, success= 0;
347 uiContextActiveProperty(C, &ptr, &prop, &index);
349 if (ptr.data && prop) {
350 CollectionPointerLink *link;
353 if(copy_to_selected_list(C, &ptr, &lb)) {
354 for(link= lb.first; link; link=link->next)
355 if(link->ptr.data != ptr.data && RNA_property_editable(&link->ptr, prop))
365 static int copy_to_selected_button_exec(bContext *C, wmOperator *op)
370 int index, all = RNA_boolean_get(op->ptr, "all");
372 /* try to reset the nominated setting to its default value */
373 uiContextActiveProperty(C, &ptr, &prop, &index);
375 /* if there is a valid property that is editable... */
376 if (ptr.data && prop) {
377 CollectionPointerLink *link;
380 if(copy_to_selected_list(C, &ptr, &lb)) {
381 for(link= lb.first; link; link=link->next) {
382 if(link->ptr.data != ptr.data && RNA_property_editable(&link->ptr, prop)) {
383 if(RNA_property_copy(&link->ptr, &ptr, prop, (all)? -1: index)) {
384 RNA_property_update(C, &link->ptr, prop);
394 return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
397 static void UI_OT_copy_to_selected_button(wmOperatorType *ot)
400 ot->name= "Copy To Selected";
401 ot->idname= "UI_OT_copy_to_selected_button";
402 ot->description= "Copy property from this object to selected objects or bones";
405 ot->poll= copy_to_selected_button_poll;
406 ot->exec= copy_to_selected_button_exec;
409 ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
412 RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array.");
415 /* Reports to Textblock Operator ------------------------ */
417 /* FIXME: this is just a temporary operator so that we can see all the reports somewhere
418 * when there are too many to display...
421 static int reports_to_text_poll(bContext *C)
423 return CTX_wm_reports(C) != NULL;
426 static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
428 ReportList *reports = CTX_wm_reports(C);
432 /* create new text-block to write to */
433 txt = add_empty_text("Recent Reports");
435 /* convert entire list to a display string, and add this to the text-block
436 * - if commandline debug option enabled, show debug reports too
437 * - otherwise, up to info (which is what users normally see)
439 str = BKE_reports_string(reports, (G.f & G_DEBUG)? RPT_DEBUG : RPT_INFO);
441 write_text(txt, str);
444 return OPERATOR_FINISHED;
447 static void UI_OT_reports_to_textblock(wmOperatorType *ot)
450 ot->name= "Reports to Text Block";
451 ot->idname= "UI_OT_reports_to_textblock";
452 ot->description= "Write the reports ";
455 ot->poll= reports_to_text_poll;
456 ot->exec= reports_to_text_exec;
459 /* ********************************************************* */
462 void UI_buttons_operatortypes(void)
464 WM_operatortype_append(UI_OT_eyedropper);
465 WM_operatortype_append(UI_OT_reset_default_theme);
466 WM_operatortype_append(UI_OT_copy_data_path_button);
467 WM_operatortype_append(UI_OT_reset_default_button);
468 WM_operatortype_append(UI_OT_copy_to_selected_button);
469 WM_operatortype_append(UI_OT_reports_to_textblock); // XXX: temp?