|
Blender
V2.59
|
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