Blender  V2.59
interface_ops.c
Go to the documentation of this file.
00001 /*
00002  * $Id: interface_ops.c 36644 2011-05-12 16:47:36Z campbellbarton $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2009 Blender Foundation.
00021  * All rights reserved.
00022  * 
00023  * Contributor(s): Blender Foundation, Joshua Leung
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00033 #include <stdio.h>
00034 #include <math.h>
00035 #include <string.h>
00036 
00037 #include "MEM_guardedalloc.h"
00038 
00039 #include "DNA_scene_types.h"
00040 #include "DNA_screen_types.h"
00041 #include "DNA_text_types.h" /* for UI_OT_reports_to_text */
00042 
00043 #include "BLI_blenlib.h"
00044 #include "BLI_math_color.h"
00045 #include "BLI_utildefines.h"
00046 
00047 #include "BKE_context.h"
00048 #include "BKE_global.h"
00049 #include "BKE_text.h" /* for UI_OT_reports_to_text */
00050 #include "BKE_report.h"
00051 
00052 #include "RNA_access.h"
00053 #include "RNA_define.h"
00054 
00055 #include "BIF_gl.h"
00056 
00057 #include "UI_interface.h"
00058 
00059 #include "interface_intern.h"
00060 
00061 #include "WM_api.h"
00062 #include "WM_types.h"
00063 
00064 
00065 
00066 /* ********************************************************** */
00067 
00068 typedef struct Eyedropper {
00069         PointerRNA ptr;
00070         PropertyRNA *prop;
00071         int index;
00072 } Eyedropper;
00073 
00074 static int eyedropper_init(bContext *C, wmOperator *op)
00075 {
00076         Eyedropper *eye;
00077         
00078         op->customdata= eye= MEM_callocN(sizeof(Eyedropper), "Eyedropper");
00079         
00080         uiContextActiveProperty(C, &eye->ptr, &eye->prop, &eye->index);
00081         
00082         return (eye->ptr.data && eye->prop && RNA_property_editable(&eye->ptr, eye->prop));
00083 }
00084  
00085 static void eyedropper_exit(bContext *C, wmOperator *op)
00086 {
00087         WM_cursor_restore(CTX_wm_window(C));
00088         
00089         if(op->customdata)
00090                 MEM_freeN(op->customdata);
00091         op->customdata= NULL;
00092 }
00093 
00094 static int eyedropper_cancel(bContext *C, wmOperator *op)
00095 {
00096         eyedropper_exit(C, op);
00097         return OPERATOR_CANCELLED;
00098 }
00099 
00100 static void eyedropper_sample(bContext *C, Eyedropper *eye, int mx, int my)
00101 {
00102         if(RNA_property_type(eye->prop) == PROP_FLOAT) {
00103                 const int color_manage = CTX_data_scene(C)->r.color_mgt_flag & R_COLOR_MANAGEMENT;
00104                 float col[4];
00105         
00106                 RNA_property_float_get_array(&eye->ptr, eye->prop, col);
00107                 
00108                 glReadBuffer(GL_FRONT);
00109                 glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, col);
00110                 glReadBuffer(GL_BACK);
00111         
00112                 if (RNA_property_array_length(&eye->ptr, eye->prop) < 3) return;
00113 
00114                 /* convert from screen (srgb) space to linear rgb space */
00115                 if (color_manage && RNA_property_subtype(eye->prop) == PROP_COLOR)
00116                         srgb_to_linearrgb_v3_v3(col, col);
00117                 
00118                 RNA_property_float_set_array(&eye->ptr, eye->prop, col);
00119                 
00120                 RNA_property_update(C, &eye->ptr, eye->prop);
00121         }
00122 }
00123 
00124 /* main modal status check */
00125 static int eyedropper_modal(bContext *C, wmOperator *op, wmEvent *event)
00126 {
00127         Eyedropper *eye = (Eyedropper *)op->customdata;
00128         
00129         switch(event->type) {
00130                 case ESCKEY:
00131                 case RIGHTMOUSE:
00132                         return eyedropper_cancel(C, op);
00133                 case LEFTMOUSE:
00134                         if(event->val==KM_RELEASE) {
00135                                 eyedropper_sample(C, eye, event->x, event->y);
00136                                 eyedropper_exit(C, op);
00137                                 return OPERATOR_FINISHED;
00138                         }
00139                         break;
00140         }
00141         
00142         return OPERATOR_RUNNING_MODAL;
00143 }
00144 
00145 /* Modal Operator init */
00146 static int eyedropper_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
00147 {
00148         /* init */
00149         if (eyedropper_init(C, op)) {
00150                 WM_cursor_modal(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
00151 
00152                 /* add temp handler */
00153                 WM_event_add_modal_handler(C, op);
00154                 
00155                 return OPERATOR_RUNNING_MODAL;
00156         } else {
00157                 eyedropper_exit(C, op);
00158                 return OPERATOR_CANCELLED;
00159         }
00160 }
00161 
00162 /* Repeat operator */
00163 static int eyedropper_exec (bContext *C, wmOperator *op)
00164 {
00165         /* init */
00166         if (eyedropper_init(C, op)) {
00167                 
00168                 /* do something */
00169                 
00170                 /* cleanup */
00171                 eyedropper_exit(C, op);
00172                 
00173                 return OPERATOR_FINISHED;
00174         } else {
00175                 return OPERATOR_CANCELLED;
00176         }
00177 }
00178 
00179 static int eyedropper_poll(bContext *C)
00180 {
00181         if (!CTX_wm_window(C)) return 0;
00182         else return 1;
00183 }
00184 
00185 static void UI_OT_eyedropper(wmOperatorType *ot)
00186 {
00187         /* identifiers */
00188         ot->name= "Eyedropper";
00189         ot->idname= "UI_OT_eyedropper";
00190         ot->description= "Sample a color from the Blender Window to store in a property";
00191         
00192         /* api callbacks */
00193         ot->invoke= eyedropper_invoke;
00194         ot->modal= eyedropper_modal;
00195         ot->cancel= eyedropper_cancel;
00196         ot->exec= eyedropper_exec;
00197         ot->poll= eyedropper_poll;
00198         
00199         /* flags */
00200         ot->flag= OPTYPE_BLOCKING;
00201         
00202         /* properties */
00203 }
00204 
00205 /* Reset Default Theme ------------------------ */
00206 
00207 static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
00208 {
00209         ui_theme_init_default();
00210         WM_event_add_notifier(C, NC_WINDOW, NULL);
00211         
00212         return OPERATOR_FINISHED;
00213 }
00214 
00215 static void UI_OT_reset_default_theme(wmOperatorType *ot)
00216 {
00217         /* identifiers */
00218         ot->name= "Reset to Default Theme";
00219         ot->idname= "UI_OT_reset_default_theme";
00220         ot->description= "Reset to the default theme colors";
00221         
00222         /* callbacks */
00223         ot->exec= reset_default_theme_exec;
00224         
00225         /* flags */
00226         ot->flag= OPTYPE_REGISTER;
00227 }
00228 
00229 /* Copy Data Path Operator ------------------------ */
00230 
00231 static int copy_data_path_button_exec(bContext *C, wmOperator *UNUSED(op))
00232 {
00233         PointerRNA ptr;
00234         PropertyRNA *prop;
00235         char *path;
00236         int success= 0;
00237         int index;
00238 
00239         /* try to create driver using property retrieved from UI */
00240         uiContextActiveProperty(C, &ptr, &prop, &index);
00241 
00242         if (ptr.id.data && ptr.data && prop) {
00243                 path= RNA_path_from_ID_to_property(&ptr, prop);
00244                 
00245                 if (path) {
00246                         WM_clipboard_text_set(path, FALSE);
00247                         MEM_freeN(path);
00248                 }
00249         }
00250 
00251         /* since we're just copying, we don't really need to do anything else...*/
00252         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
00253 }
00254 
00255 static void UI_OT_copy_data_path_button(wmOperatorType *ot)
00256 {
00257         /* identifiers */
00258         ot->name= "Copy Data Path";
00259         ot->idname= "UI_OT_copy_data_path_button";
00260         ot->description= "Copy the RNA data path for this property to the clipboard";
00261 
00262         /* callbacks */
00263         ot->exec= copy_data_path_button_exec;
00264         //op->poll= ??? // TODO: need to have some valid property before this can be done
00265 
00266         /* flags */
00267         ot->flag= OPTYPE_REGISTER;
00268 }
00269 
00270 /* Reset to Default Values Button Operator ------------------------ */
00271 
00272 static int reset_default_button_poll(bContext *C)
00273 {
00274         PointerRNA ptr;
00275         PropertyRNA *prop;
00276         int index;
00277 
00278         uiContextActiveProperty(C, &ptr, &prop, &index);
00279         
00280         return (ptr.data && prop && RNA_property_editable(&ptr, prop));
00281 }
00282 
00283 static int reset_default_button_exec(bContext *C, wmOperator *op)
00284 {
00285         PointerRNA ptr;
00286         PropertyRNA *prop;
00287         int success= 0;
00288         int index, all = RNA_boolean_get(op->ptr, "all");
00289 
00290         /* try to reset the nominated setting to its default value */
00291         uiContextActiveProperty(C, &ptr, &prop, &index);
00292         
00293         /* if there is a valid property that is editable... */
00294         if (ptr.data && prop && RNA_property_editable(&ptr, prop)) {
00295                 if(RNA_property_reset(&ptr, prop, (all)? -1: index)) {
00296                         /* perform updates required for this property */
00297                         RNA_property_update(C, &ptr, prop);
00298                         success= 1;
00299                 }
00300         }
00301         
00302         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
00303 }
00304 
00305 static void UI_OT_reset_default_button(wmOperatorType *ot)
00306 {
00307         /* identifiers */
00308         ot->name= "Reset to Default Value";
00309         ot->idname= "UI_OT_reset_default_button";
00310         ot->description= "Reset this property's value to its default value";
00311 
00312         /* callbacks */
00313         ot->poll= reset_default_button_poll;
00314         ot->exec= reset_default_button_exec;
00315 
00316         /* flags */
00317         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00318         
00319         /* properties */
00320         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array.");
00321 }
00322 
00323 /* Copy To Selected Operator ------------------------ */
00324 
00325 static int copy_to_selected_list(bContext *C, PointerRNA *ptr, ListBase *lb)
00326 {
00327         if(RNA_struct_is_a(ptr->type, &RNA_Object))
00328                 *lb = CTX_data_collection_get(C, "selected_editable_objects");
00329         else if(RNA_struct_is_a(ptr->type, &RNA_EditBone))
00330                 *lb = CTX_data_collection_get(C, "selected_editable_bones");
00331         else if(RNA_struct_is_a(ptr->type, &RNA_PoseBone))
00332                 *lb = CTX_data_collection_get(C, "selected_pose_bones");
00333         else if(RNA_struct_is_a(ptr->type, &RNA_Sequence))
00334                 *lb = CTX_data_collection_get(C, "selected_editable_sequences");
00335         else
00336                 return 0;
00337         
00338         return 1;
00339 }
00340 
00341 static int copy_to_selected_button_poll(bContext *C)
00342 {
00343         PointerRNA ptr;
00344         PropertyRNA *prop;
00345         int index, success= 0;
00346 
00347         uiContextActiveProperty(C, &ptr, &prop, &index);
00348 
00349         if (ptr.data && prop) {
00350                 CollectionPointerLink *link;
00351                 ListBase lb;
00352 
00353                 if(copy_to_selected_list(C, &ptr, &lb)) {
00354                         for(link= lb.first; link; link=link->next)
00355                                 if(link->ptr.data != ptr.data && RNA_property_editable(&link->ptr, prop))
00356                                         success= 1;
00357 
00358                         BLI_freelistN(&lb);
00359                 }
00360         }
00361 
00362         return success;
00363 }
00364 
00365 static int copy_to_selected_button_exec(bContext *C, wmOperator *op)
00366 {
00367         PointerRNA ptr;
00368         PropertyRNA *prop;
00369         int success= 0;
00370         int index, all = RNA_boolean_get(op->ptr, "all");
00371 
00372         /* try to reset the nominated setting to its default value */
00373         uiContextActiveProperty(C, &ptr, &prop, &index);
00374         
00375         /* if there is a valid property that is editable... */
00376         if (ptr.data && prop) {
00377                 CollectionPointerLink *link;
00378                 ListBase lb;
00379 
00380                 if(copy_to_selected_list(C, &ptr, &lb)) {
00381                         for(link= lb.first; link; link=link->next) {
00382                                 if(link->ptr.data != ptr.data && RNA_property_editable(&link->ptr, prop)) {
00383                                         if(RNA_property_copy(&link->ptr, &ptr, prop, (all)? -1: index)) {
00384                                                 RNA_property_update(C, &link->ptr, prop);
00385                                                 success= 1;
00386                                         }
00387                                 }
00388                         }
00389 
00390                         BLI_freelistN(&lb);
00391                 }
00392         }
00393         
00394         return (success)? OPERATOR_FINISHED: OPERATOR_CANCELLED;
00395 }
00396 
00397 static void UI_OT_copy_to_selected_button(wmOperatorType *ot)
00398 {
00399         /* identifiers */
00400         ot->name= "Copy To Selected";
00401         ot->idname= "UI_OT_copy_to_selected_button";
00402         ot->description= "Copy property from this object to selected objects or bones";
00403 
00404         /* callbacks */
00405         ot->poll= copy_to_selected_button_poll;
00406         ot->exec= copy_to_selected_button_exec;
00407 
00408         /* flags */
00409         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
00410 
00411         /* properties */
00412         RNA_def_boolean(ot->srna, "all", 1, "All", "Reset to default values all elements of the array.");
00413 }
00414 
00415 /* Reports to Textblock Operator ------------------------ */
00416 
00417 /* FIXME: this is just a temporary operator so that we can see all the reports somewhere 
00418  * when there are too many to display...
00419  */
00420 
00421 static int reports_to_text_poll(bContext *C)
00422 {
00423         return CTX_wm_reports(C) != NULL;
00424 }
00425 
00426 static int reports_to_text_exec(bContext *C, wmOperator *UNUSED(op))
00427 {
00428         ReportList *reports = CTX_wm_reports(C);
00429         Text *txt;
00430         char *str;
00431         
00432         /* create new text-block to write to */
00433         txt = add_empty_text("Recent Reports");
00434         
00435         /* convert entire list to a display string, and add this to the text-block
00436          *      - if commandline debug option enabled, show debug reports too
00437          *      - otherwise, up to info (which is what users normally see)
00438          */
00439         str = BKE_reports_string(reports, (G.f & G_DEBUG)? RPT_DEBUG : RPT_INFO);
00440         
00441         write_text(txt, str);
00442         MEM_freeN(str);
00443         
00444         return OPERATOR_FINISHED;
00445 }
00446 
00447 static void UI_OT_reports_to_textblock(wmOperatorType *ot)
00448 {
00449         /* identifiers */
00450         ot->name= "Reports to Text Block";
00451         ot->idname= "UI_OT_reports_to_textblock";
00452         ot->description= "Write the reports ";
00453         
00454         /* callbacks */
00455         ot->poll= reports_to_text_poll;
00456         ot->exec= reports_to_text_exec;
00457 }
00458 
00459 /* ********************************************************* */
00460 /* Registration */
00461 
00462 void UI_buttons_operatortypes(void)
00463 {
00464         WM_operatortype_append(UI_OT_eyedropper);
00465         WM_operatortype_append(UI_OT_reset_default_theme);
00466         WM_operatortype_append(UI_OT_copy_data_path_button);
00467         WM_operatortype_append(UI_OT_reset_default_button);
00468         WM_operatortype_append(UI_OT_copy_to_selected_button);
00469         WM_operatortype_append(UI_OT_reports_to_textblock); // XXX: temp?
00470 }
00471