Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Contributor(s): Blender Foundation 2009. 00019 * 00020 * ***** END GPL LICENSE BLOCK ***** 00021 */ 00022 00028 #include <stdlib.h> 00029 #include <stddef.h> 00030 #include <string.h> 00031 00032 #include "MEM_guardedalloc.h" 00033 00034 #include "DNA_anim_types.h" 00035 #include "DNA_dynamicpaint_types.h" 00036 #include "DNA_key_types.h" 00037 #include "DNA_scene_types.h" 00038 #include "DNA_userdef_types.h" 00039 00040 #include "BLI_utildefines.h" 00041 #include "BLI_string.h" 00042 #include "BLI_ghash.h" 00043 00044 #include "BLF_translation.h" 00045 00046 #include "BKE_animsys.h" 00047 #include "BKE_colortools.h" 00048 #include "BKE_context.h" 00049 #include "BKE_dynamicpaint.h" 00050 #include "BKE_global.h" 00051 #include "BKE_library.h" 00052 #include "BKE_main.h" 00053 #include "BKE_object.h" 00054 #include "BKE_material.h" 00055 #include "BKE_texture.h" 00056 #include "BKE_report.h" 00057 #include "BKE_displist.h" 00058 #include "BKE_scene.h" 00059 00060 #include "ED_screen.h" 00061 #include "ED_object.h" 00062 #include "ED_render.h" 00063 00064 #include "RNA_access.h" 00065 #include "RNA_enum_types.h" 00066 00067 #include "WM_api.h" 00068 #include "WM_types.h" 00069 00070 #include "UI_interface.h" 00071 #include "interface_intern.h" 00072 00073 #include "BLF_api.h" 00074 #include "BLF_translation.h" 00075 00076 void UI_template_fix_linking(void) 00077 { 00078 } 00079 00080 /********************** Header Template *************************/ 00081 00082 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus) 00083 { 00084 uiBlock *block; 00085 00086 block= uiLayoutAbsoluteBlock(layout); 00087 if(menus) ED_area_header_standardbuttons(C, block, 0); 00088 else ED_area_header_switchbutton(C, block, 0); 00089 } 00090 00091 /********************** Search Callbacks *************************/ 00092 00093 typedef struct TemplateID { 00094 PointerRNA ptr; 00095 PropertyRNA *prop; 00096 00097 ListBase *idlb; 00098 int prv_rows, prv_cols; 00099 } TemplateID; 00100 00101 /* Search browse menu, assign */ 00102 static void id_search_call_cb(bContext *C, void *arg_template, void *item) 00103 { 00104 TemplateID *template= (TemplateID*)arg_template; 00105 00106 /* ID */ 00107 if(item) { 00108 PointerRNA idptr; 00109 00110 RNA_id_pointer_create(item, &idptr); 00111 RNA_property_pointer_set(&template->ptr, template->prop, idptr); 00112 RNA_property_update(C, &template->ptr, template->prop); 00113 } 00114 } 00115 00116 /* ID Search browse menu, do the search */ 00117 static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items) 00118 { 00119 TemplateID *template= (TemplateID*)arg_template; 00120 ListBase *lb= template->idlb; 00121 ID *id, *id_from= template->ptr.id.data; 00122 int iconid; 00123 int flag= RNA_property_flag(template->prop); 00124 00125 /* ID listbase */ 00126 for(id= lb->first; id; id= id->next) { 00127 if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) { 00128 00129 /* use filter */ 00130 if(RNA_property_type(template->prop)==PROP_POINTER) { 00131 PointerRNA ptr; 00132 RNA_id_pointer_create(id, &ptr); 00133 if(RNA_property_pointer_poll(&template->ptr, template->prop, &ptr)==0) 00134 continue; 00135 } 00136 00137 /* hide dot-datablocks, but only if filter does not force it visible */ 00138 if(U.uiflag & USER_HIDE_DOT) 00139 if ((id->name[2]=='.') && (str[0] != '.')) 00140 continue; 00141 00142 if(BLI_strcasestr(id->name+2, str)) { 00143 char name_ui[MAX_ID_NAME]; 00144 name_uiprefix_id(name_ui, id); 00145 00146 iconid= ui_id_icon_get((bContext*)C, id, 1); 00147 00148 if(!uiSearchItemAdd(items, name_ui, id, iconid)) 00149 break; 00150 } 00151 } 00152 } 00153 } 00154 00155 /* ID Search browse menu, open */ 00156 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) 00157 { 00158 static char search[256]; 00159 static TemplateID template; 00160 PointerRNA idptr; 00161 wmWindow *win= CTX_wm_window(C); 00162 uiBlock *block; 00163 uiBut *but; 00164 00165 /* clear initial search string, then all items show */ 00166 search[0]= 0; 00167 /* arg_litem is malloced, can be freed by parent button */ 00168 template= *((TemplateID*)arg_litem); 00169 00170 /* get active id for showing first item */ 00171 idptr= RNA_property_pointer_get(&template.ptr, template.prop); 00172 00173 block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS); 00174 uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1); 00175 00176 /* preview thumbnails */ 00177 if (template.prv_rows > 0 && template.prv_cols > 0) { 00178 int w = 96 * template.prv_cols; 00179 int h = 96 * template.prv_rows + 20; 00180 00181 /* fake button, it holds space for search items */ 00182 uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL); 00183 00184 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, template.prv_rows, template.prv_cols, ""); 00185 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); 00186 } 00187 /* list view */ 00188 else { 00189 /* fake button, it holds space for search items */ 00190 uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL); 00191 00192 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, ""); 00193 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data); 00194 } 00195 00196 00197 uiBoundsBlock(block, 6); 00198 uiBlockSetDirection(block, UI_DOWN); 00199 uiEndBlock(C, block); 00200 00201 /* give search-field focus */ 00202 uiButSetFocusOnEnter(win, but); 00203 /* this type of search menu requires undo */ 00204 but->flag |= UI_BUT_UNDO; 00205 00206 return block; 00207 } 00208 00209 /************************ ID Template ***************************/ 00210 /* This is for browsing and editing the ID-blocks used */ 00211 00212 /* for new/open operators */ 00213 void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop) 00214 { 00215 TemplateID *template; 00216 ARegion *ar= CTX_wm_region(C); 00217 uiBlock *block; 00218 uiBut *but; 00219 00220 memset(ptr, 0, sizeof(*ptr)); 00221 *prop= NULL; 00222 00223 if(!ar) 00224 return; 00225 00226 for(block=ar->uiblocks.first; block; block=block->next) { 00227 for(but=block->buttons.first; but; but= but->next) { 00228 /* find the button before the active one */ 00229 if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) { 00230 if(but->func_argN) { 00231 template= but->func_argN; 00232 *ptr= template->ptr; 00233 *prop= template->prop; 00234 return; 00235 } 00236 } 00237 } 00238 } 00239 } 00240 00241 00242 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) 00243 { 00244 TemplateID *template= (TemplateID*)arg_litem; 00245 PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop); 00246 ID *id= idptr.data; 00247 int event= GET_INT_FROM_POINTER(arg_event); 00248 00249 switch(event) { 00250 case UI_ID_BROWSE: 00251 case UI_ID_PIN: 00252 RNA_warning("warning, id event %d shouldnt come here", event); 00253 break; 00254 case UI_ID_OPEN: 00255 case UI_ID_ADD_NEW: 00256 /* these call uiIDContextPropertySet */ 00257 break; 00258 case UI_ID_DELETE: 00259 memset(&idptr, 0, sizeof(idptr)); 00260 RNA_property_pointer_set(&template->ptr, template->prop, idptr); 00261 RNA_property_update(C, &template->ptr, template->prop); 00262 00263 if(id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */ 00264 id->us= 0; 00265 00266 break; 00267 case UI_ID_FAKE_USER: 00268 if(id) { 00269 if(id->flag & LIB_FAKEUSER) id_us_plus(id); 00270 else id_us_min(id); 00271 } 00272 else return; 00273 break; 00274 case UI_ID_LOCAL: 00275 if(id) { 00276 if(id_make_local(id, 0)) { 00277 /* reassign to get get proper updates/notifiers */ 00278 idptr= RNA_property_pointer_get(&template->ptr, template->prop); 00279 RNA_property_pointer_set(&template->ptr, template->prop, idptr); 00280 RNA_property_update(C, &template->ptr, template->prop); 00281 } 00282 } 00283 break; 00284 case UI_ID_ALONE: 00285 if(id) { 00286 const int do_scene_obj= (GS(id->name) == ID_OB) && 00287 (template->ptr.type == &RNA_SceneObjects); 00288 00289 /* make copy */ 00290 if(do_scene_obj) { 00291 Scene *scene= CTX_data_scene(C); 00292 ED_object_single_user(scene, (struct Object *)id); 00293 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene); 00294 } 00295 else { 00296 if(id) { 00297 id_single_user(C, id, &template->ptr, template->prop); 00298 } 00299 } 00300 } 00301 break; 00302 #if 0 00303 case UI_ID_AUTO_NAME: 00304 break; 00305 #endif 00306 } 00307 } 00308 00309 static const char *template_id_browse_tip(StructRNA *type) 00310 { 00311 if(type) { 00312 switch(RNA_type_to_ID_code(type)) { 00313 case ID_SCE: return N_("Browse Scene to be linked"); 00314 case ID_OB: return N_("Browse Object to be linked"); 00315 case ID_ME: return N_("Browse Mesh Data to be linked"); 00316 case ID_CU: return N_("Browse Curve Data to be linked"); 00317 case ID_MB: return N_("Browse MetaBall Data to be linked"); 00318 case ID_MA: return N_("Browse Material to be linked"); 00319 case ID_TE: return N_("Browse Texture to be linked"); 00320 case ID_IM: return N_("Browse Image to be linked"); 00321 case ID_LT: return N_("Browse Lattice Data to be linked"); 00322 case ID_LA: return N_("Browse Lamp Data to be linked"); 00323 case ID_CA: return N_("Browse Camera Data to be linked"); 00324 case ID_WO: return N_("Browse World Settings to be linked"); 00325 case ID_SCR: return N_("Choose Screen lay-out"); 00326 case ID_TXT: return N_("Browse Text to be linked"); 00327 case ID_SPK: return N_("Browse Speaker Data to be linked"); 00328 case ID_SO: return N_("Browse Sound to be linked"); 00329 case ID_AR: return N_("Browse Armature data to be linked"); 00330 case ID_AC: return N_("Browse Action to be linked"); 00331 case ID_NT: return N_("Browse Node Tree to be linked"); 00332 case ID_BR: return N_("Browse Brush to be linked"); 00333 case ID_PA: return N_("Browse Particle System to be linked"); 00334 case ID_GD: return N_("Browse Grease Pencil Data to be linked"); 00335 } 00336 } 00337 return N_("Browse ID data to be linked"); 00338 } 00339 00340 static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, const char *newop, const char *openop, const char *unlinkop) 00341 { 00342 uiBut *but; 00343 uiBlock *block; 00344 PointerRNA idptr; 00345 // ListBase *lb; // UNUSED 00346 ID *id, *idfrom; 00347 int editable= RNA_property_editable(&template->ptr, template->prop); 00348 00349 idptr= RNA_property_pointer_get(&template->ptr, template->prop); 00350 id= idptr.data; 00351 idfrom= template->ptr.id.data; 00352 // lb= template->idlb; 00353 00354 block= uiLayoutGetBlock(layout); 00355 uiBlockBeginAlign(block); 00356 00357 if(idptr.type) 00358 type= idptr.type; 00359 00360 if(flag & UI_ID_PREVIEWS) { 00361 00362 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, 00363 TIP_(template_id_browse_tip(type))); 00364 if(type) { 00365 but->icon= RNA_struct_ui_icon(type); 00366 if (id) but->icon = ui_id_icon_get(C, id, 1); 00367 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW); 00368 } 00369 if((idfrom && idfrom->lib) || !editable) 00370 uiButSetFlag(but, UI_BUT_DISABLED); 00371 00372 uiLayoutRow(layout, 1); 00373 } 00374 else if(flag & UI_ID_BROWSE) { 00375 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, 00376 TIP_(template_id_browse_tip(type))); 00377 if(type) { 00378 but->icon= RNA_struct_ui_icon(type); 00379 /* default dragging of icon for id browse buttons */ 00380 uiButSetDragID(but, id); 00381 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_LEFT); 00382 } 00383 00384 if((idfrom && idfrom->lib) || !editable) 00385 uiButSetFlag(but, UI_BUT_DISABLED); 00386 } 00387 00388 /* text button with name */ 00389 if(id) { 00390 char name[UI_MAX_NAME_STR]; 00391 const short user_alert= (id->us <= 0); 00392 00393 //text_idbutton(id, name); 00394 name[0]= '\0'; 00395 but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL); 00396 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); 00397 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT); 00398 00399 if(id->lib) { 00400 if(id->flag & LIB_INDIRECT) { 00401 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0, 00402 TIP_("Indirect library datablock, cannot change")); 00403 uiButSetFlag(but, UI_BUT_DISABLED); 00404 } 00405 else { 00406 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0, 00407 TIP_("Direct linked library datablock, click to make local")); 00408 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib)) 00409 uiButSetFlag(but, UI_BUT_DISABLED); 00410 } 00411 00412 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL)); 00413 } 00414 00415 if(id->us > 1) { 00416 char numstr[32]; 00417 00418 BLI_snprintf(numstr, sizeof(numstr), "%d", id->us); 00419 00420 but= uiDefBut(block, BUT, 0, numstr, 0,0,UI_UNIT_X + ((id->us < 10) ? 0:10), UI_UNIT_Y, NULL, 0, 0, 0, 0, 00421 TIP_("Display number of users of this data (click to make a single-user copy)")); 00422 00423 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE)); 00424 if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable) 00425 uiButSetFlag(but, UI_BUT_DISABLED); 00426 } 00427 00428 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT); 00429 00430 if(id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) { 00431 uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL); 00432 } 00433 } 00434 00435 if(flag & UI_ID_ADD_NEW) { 00436 int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6; 00437 00438 if(newop) { 00439 but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id)? "": IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL); 00440 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); 00441 } 00442 else { 00443 but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); 00444 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW)); 00445 } 00446 00447 if((idfrom && idfrom->lib) || !editable) 00448 uiButSetFlag(but, UI_BUT_DISABLED); 00449 } 00450 00451 if(flag & UI_ID_OPEN) { 00452 int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6; 00453 00454 if(openop) { 00455 but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL); 00456 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN)); 00457 } 00458 else { 00459 but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL); 00460 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN)); 00461 } 00462 00463 if((idfrom && idfrom->lib) || !editable) 00464 uiButSetFlag(but, UI_BUT_DISABLED); 00465 } 00466 00467 /* delete button */ 00468 if(id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK)==0) { 00469 if(unlinkop) { 00470 but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); 00471 /* so we can access the template from operators, font unlinking needs this */ 00472 uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL); 00473 } 00474 else { 00475 but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, 00476 TIP_("Unlink datablock. Shift + Click to set users to zero, data will then not be saved")); 00477 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE)); 00478 00479 if(RNA_property_flag(template->prop) & PROP_NEVER_NULL) 00480 uiButSetFlag(but, UI_BUT_DISABLED); 00481 } 00482 00483 if((idfrom && idfrom->lib) || !editable) 00484 uiButSetFlag(but, UI_BUT_DISABLED); 00485 } 00486 00487 if(idcode == ID_TE) 00488 uiTemplateTextureShow(layout, C, &template->ptr, template->prop); 00489 00490 uiBlockEndAlign(block); 00491 } 00492 00493 static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols) 00494 { 00495 TemplateID *template; 00496 PropertyRNA *prop; 00497 StructRNA *type; 00498 short idcode; 00499 00500 prop= RNA_struct_find_property(ptr, propname); 00501 00502 if(!prop || RNA_property_type(prop) != PROP_POINTER) { 00503 RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); 00504 return; 00505 } 00506 00507 template= MEM_callocN(sizeof(TemplateID), "TemplateID"); 00508 template->ptr= *ptr; 00509 template->prop= prop; 00510 template->prv_rows = prv_rows; 00511 template->prv_cols = prv_cols; 00512 00513 if(newop) 00514 flag |= UI_ID_ADD_NEW; 00515 if(openop) 00516 flag |= UI_ID_OPEN; 00517 00518 type= RNA_property_pointer_type(ptr, prop); 00519 idcode= RNA_type_to_ID_code(type); 00520 template->idlb= which_libbase(CTX_data_main(C), idcode); 00521 00522 /* create UI elements for this template 00523 * - template_ID makes a copy of the template data and assigns it to the relevant buttons 00524 */ 00525 if(template->idlb) { 00526 uiLayoutRow(layout, 1); 00527 template_ID(C, layout, template, type, idcode, flag, newop, openop, unlinkop); 00528 } 00529 00530 MEM_freeN(template); 00531 } 00532 00533 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop) 00534 { 00535 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0); 00536 } 00537 00538 void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop) 00539 { 00540 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0); 00541 } 00542 00543 void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols) 00544 { 00545 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols); 00546 } 00547 00548 /************************ ID Chooser Template ***************************/ 00549 00550 /* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use 00551 * 00552 * - propname: property identifier for property that ID-pointer gets stored to 00553 * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used 00554 */ 00555 void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text) 00556 { 00557 PropertyRNA *propID, *propType; 00558 uiLayout *row; 00559 00560 /* get properties... */ 00561 propID= RNA_struct_find_property(ptr, propname); 00562 propType= RNA_struct_find_property(ptr, proptypename); 00563 00564 if (!propID || RNA_property_type(propID) != PROP_POINTER) { 00565 RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); 00566 return; 00567 } 00568 if (!propType || RNA_property_type(propType) != PROP_ENUM) { 00569 RNA_warning("pointer-type property not found: %s.%s", RNA_struct_identifier(ptr->type), proptypename); 00570 return; 00571 } 00572 00573 /* Start drawing UI Elements using standard defines */ 00574 row= uiLayoutRow(layout, 1); 00575 00576 /* Label - either use the provided text, or will become "ID-Block:" */ 00577 if (text) 00578 uiItemL(row, text, ICON_NONE); 00579 else 00580 uiItemL(row, "ID-Block:", ICON_NONE); 00581 00582 /* ID-Type Selector - just have a menu of icons */ 00583 // FIXME: the icon-only setting doesn't work when we supply a blank name 00584 uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE); 00585 00586 /* ID-Block Selector - just use pointer widget... */ 00587 uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NONE); 00588 } 00589 00590 /********************* RNA Path Builder Template ********************/ 00591 00592 /* ---------- */ 00593 00594 /* This is creating/editing RNA-Paths 00595 * 00596 * - ptr: struct which holds the path property 00597 * - propname: property identifier for property that path gets stored to 00598 * - root_ptr: struct that path gets built from 00599 */ 00600 void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text) 00601 { 00602 PropertyRNA *propPath; 00603 uiLayout *row; 00604 00605 /* check that properties are valid */ 00606 propPath= RNA_struct_find_property(ptr, propname); 00607 if (!propPath || RNA_property_type(propPath) != PROP_STRING) { 00608 RNA_warning("path property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); 00609 return; 00610 } 00611 00612 /* Start drawing UI Elements using standard defines */ 00613 row= uiLayoutRow(layout, 1); 00614 00615 /* Path (existing string) Widget */ 00616 uiItemR(row, ptr, propname, 0, text, ICON_RNA); 00617 00618 // TODO: attach something to this to make allow searching of nested properties to 'build' the path 00619 } 00620 00621 /************************ Modifier Template *************************/ 00622 00623 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata" 00624 00625 #include <string.h> 00626 00627 #include "DNA_object_force.h" 00628 00629 #include "BKE_depsgraph.h" 00630 #include "BKE_modifier.h" 00631 #include "BKE_particle.h" 00632 00633 #include "ED_util.h" 00634 00635 #include "BLI_math.h" 00636 #include "BLI_listbase.h" 00637 00638 #include "ED_object.h" 00639 00640 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v) 00641 { 00642 Scene *scene = CTX_data_scene(C); 00643 Object *ob = ob_v; 00644 ModifierData *md= md_v; 00645 int i, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 0); 00646 00647 /* undo button operation */ 00648 md->mode ^= eModifierMode_OnCage; 00649 00650 for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) { 00651 if(md == md_v) { 00652 if(i >= cageIndex) 00653 md->mode ^= eModifierMode_OnCage; 00654 break; 00655 } 00656 } 00657 00658 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); 00659 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00660 } 00661 00662 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v) 00663 { 00664 Object *ob = ob_v; 00665 ModifierData *md = md_v; 00666 ModifierData *nmd = modifier_new(md->type); 00667 00668 modifier_copyData(md, nmd); 00669 nmd->mode &= ~eModifierMode_Virtual; 00670 00671 BLI_addhead(&ob->modifiers, nmd); 00672 00673 modifier_unique_name(&ob->modifiers, nmd); 00674 00675 ob->partype = PAROBJECT; 00676 00677 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob); 00678 DAG_id_tag_update(&ob->id, OB_RECALC_DATA); 00679 00680 ED_undo_push(C, "Modifier convert to real"); 00681 } 00682 00683 static int modifier_can_delete(ModifierData *md) 00684 { 00685 /* fluid particle modifier can't be deleted here */ 00686 if(md->type == eModifierType_ParticleSystem) 00687 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID) 00688 return 0; 00689 00690 return 1; 00691 } 00692 00693 /* Check wheter Modifier is a simulation or not, this is used for switching to the physics/particles context tab */ 00694 static int modifier_is_simulation(ModifierData *md) 00695 { 00696 /* Physic Tab */ 00697 if (ELEM7(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke, 00698 eModifierType_Softbody, eModifierType_Surface, eModifierType_DynamicPaint)) 00699 { 00700 return 1; 00701 } 00702 /* Particle Tab */ 00703 else if (md->type == eModifierType_ParticleSystem) { 00704 return 2; 00705 } 00706 else { 00707 return 0; 00708 } 00709 } 00710 00711 static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, 00712 ModifierData *md, int index, int cageIndex, int lastCageIndex) 00713 { 00714 ModifierTypeInfo *mti = modifierType_getInfo(md->type); 00715 PointerRNA ptr; 00716 uiBut *but; 00717 uiBlock *block; 00718 uiLayout *box, *column, *row; 00719 uiLayout *result= NULL; 00720 int isVirtual = (md->mode & eModifierMode_Virtual); 00721 char str[128]; 00722 00723 /* create RNA pointer */ 00724 RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr); 00725 00726 column= uiLayoutColumn(layout, 1); 00727 uiLayoutSetContextPointer(column, "modifier", &ptr); 00728 00729 /* rounded header ------------------------------------------------------------------- */ 00730 box= uiLayoutBox(column); 00731 00732 if (isVirtual) { 00733 row= uiLayoutRow(box, 0); 00734 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND); 00735 block= uiLayoutGetBlock(row); 00736 /* VIRTUAL MODIFIER */ 00737 // XXX this is not used now, since these cannot be accessed via RNA 00738 BLI_snprintf(str, sizeof(str), "%s parent deform", md->name); 00739 uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 00740 00741 but = uiDefBut(block, BUT, 0, IFACE_("Make Real"), 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, 00742 TIP_("Convert virtual modifier to a real modifier")); 00743 uiButSetFunc(but, modifiers_convertToReal, ob, md); 00744 } 00745 else { 00746 /* REAL MODIFIER */ 00747 row = uiLayoutRow(box, 0); 00748 block = uiLayoutGetBlock(row); 00749 00750 uiBlockSetEmboss(block, UI_EMBOSSN); 00751 /* Open/Close ................................. */ 00752 uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE); 00753 00754 /* modifier-type icon */ 00755 uiItemL(row, "", RNA_struct_ui_icon(ptr.type)); 00756 uiBlockSetEmboss(block, UI_EMBOSS); 00757 00758 /* modifier name */ 00759 uiItemR(row, &ptr, "name", 0, "", ICON_NONE); 00760 00761 /* mode enabling buttons */ 00762 uiBlockBeginAlign(block); 00763 /* Softbody not allowed in this situation, enforce! */ 00764 if ( ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) 00765 && (md->type!=eModifierType_Surface) ) 00766 { 00767 uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE); 00768 uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE); 00769 00770 if (mti->flags & eModifierTypeFlag_SupportsEditmode) 00771 uiItemR(row, &ptr, "show_in_editmode", 0, "", ICON_NONE); 00772 } 00773 00774 if (ob->type==OB_MESH) { 00775 if (modifier_couldBeCage(scene, md) && (index <= lastCageIndex)) 00776 { 00777 /* -- convert to rna ? */ 00778 but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, 00779 TIP_("Apply modifier to editing cage during Editmode")); 00780 if (index < cageIndex) 00781 uiButSetFlag(but, UI_BUT_DISABLED); 00782 uiButSetFunc(but, modifiers_setOnCage, ob, md); 00783 } 00784 else { 00785 uiBlockEndAlign(block); 00786 00787 /* place holder button */ 00788 uiBlockSetEmboss(block, UI_EMBOSSN); 00789 but= uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, NULL); 00790 uiButSetFlag(but, UI_BUT_DISABLED); 00791 uiBlockSetEmboss(block, UI_EMBOSS); 00792 } 00793 } /* tesselation point for curve-typed objects */ 00794 else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) { 00795 /* some modifiers could work with pre-tesselated curves only */ 00796 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) { 00797 /* add disabled pre-tesselated button, so users could have 00798 message for this modifiers */ 00799 but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, 00800 TIP_("This modifier could be applied on splines' points only")); 00801 uiButSetFlag(but, UI_BUT_DISABLED); 00802 } else if (mti->type != eModifierTypeType_Constructive) { 00803 /* constructive modifiers tesselates curve before applying */ 00804 uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NONE); 00805 } 00806 } 00807 00808 uiBlockEndAlign(block); 00809 00810 /* Up/Down + Delete ........................... */ 00811 uiBlockBeginAlign(block); 00812 uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up"); 00813 uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down"); 00814 uiBlockEndAlign(block); 00815 00816 uiBlockSetEmboss(block, UI_EMBOSSN); 00817 // When Modifier is a simulation, show button to switch to context rather than the delete button. 00818 if (modifier_can_delete(md) && !modifier_is_simulation(md)) 00819 uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove"); 00820 if (modifier_is_simulation(md) == 1) 00821 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PHYSICS"); 00822 else if (modifier_is_simulation(md) == 2) 00823 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PARTICLES"); 00824 uiBlockSetEmboss(block, UI_EMBOSS); 00825 } 00826 00827 00828 /* modifier settings (under the header) --------------------------------------------------- */ 00829 if (!isVirtual && (md->mode & eModifierMode_Expanded)) { 00830 /* apply/convert/copy */ 00831 box= uiLayoutBox(column); 00832 row= uiLayoutRow(box, 0); 00833 00834 if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) { 00835 /* only here obdata, the rest of modifiers is ob level */ 00836 uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE); 00837 00838 if (md->type==eModifierType_ParticleSystem) { 00839 ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys; 00840 00841 if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) { 00842 if(ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) 00843 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_duplicates_make_real"); 00844 else if(psys->part->ren_as == PART_DRAW_PATH) 00845 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_modifier_convert"); 00846 } 00847 } 00848 else { 00849 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); 00850 uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA); 00851 00852 if (modifier_sameTopology(md) && !modifier_nonGeometrical(md)) 00853 uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape"), 0, "apply_as", MODIFIER_APPLY_SHAPE); 00854 } 00855 00856 uiBlockClearButLock(block); 00857 uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE); 00858 00859 if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke)) 00860 uiItemO(row, IFACE_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy"); 00861 } 00862 00863 /* result is the layout block inside the box, that we return so that modifier settings can be drawn */ 00864 result= uiLayoutColumn(box, 0); 00865 block= uiLayoutAbsoluteBlock(box); 00866 } 00867 00868 /* error messages */ 00869 if(md->error) { 00870 box = uiLayoutBox(column); 00871 row = uiLayoutRow(box, 0); 00872 uiItemL(row, md->error, ICON_ERROR); 00873 } 00874 00875 return result; 00876 } 00877 00878 uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) 00879 { 00880 Scene *scene = CTX_data_scene(C); 00881 Object *ob; 00882 ModifierData *md, *vmd; 00883 int i, lastCageIndex, cageIndex; 00884 00885 /* verify we have valid data */ 00886 if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) { 00887 RNA_warning("Expected modifier on object"); 00888 return NULL; 00889 } 00890 00891 ob= ptr->id.data; 00892 md= ptr->data; 00893 00894 if(!ob || !(GS(ob->id.name) == ID_OB)) { 00895 RNA_warning("Expected modifier on object"); 00896 return NULL; 00897 } 00898 00899 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE); 00900 00901 /* find modifier and draw it */ 00902 cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0); 00903 00904 // XXX virtual modifiers are not accesible for python 00905 vmd = modifiers_getVirtualModifierList(ob); 00906 00907 for(i=0; vmd; i++, vmd=vmd->next) { 00908 if(md == vmd) 00909 return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex); 00910 else if(vmd->mode & eModifierMode_Virtual) 00911 i--; 00912 } 00913 00914 return NULL; 00915 } 00916 00917 /************************ Constraint Template *************************/ 00918 00919 #include "DNA_constraint_types.h" 00920 00921 #include "BKE_action.h" 00922 #include "BKE_constraint.h" 00923 00924 #define REDRAWIPO 1 00925 #define REDRAWNLA 2 00926 #define REDRAWBUTSOBJECT 3 00927 #define REDRAWACTION 4 00928 #define B_CONSTRAINT_TEST 5 00929 #define B_CONSTRAINT_CHANGETARGET 6 00930 #define REMAKEIPO 8 00931 #define B_DIFF 9 00932 00933 static void do_constraint_panels(bContext *C, void *ob_pt, int event) 00934 { 00935 Main *bmain= CTX_data_main(C); 00936 Scene *scene= CTX_data_scene(C); 00937 Object *ob= (Object *)ob_pt; 00938 00939 switch(event) { 00940 case B_CONSTRAINT_TEST: 00941 break; // no handling 00942 case B_CONSTRAINT_CHANGETARGET: 00943 if (ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels 00944 DAG_scene_sort(bmain, scene); 00945 break; 00946 default: 00947 break; 00948 } 00949 00950 // note: RNA updates now call this, commenting else it gets called twice. 00951 // if there are problems because of this, then rna needs changed update functions. 00952 // 00953 // object_test_constraints(ob); 00954 // if(ob->pose) update_pose_constraint_flags(ob->pose); 00955 00956 if(ob->type==OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB); 00957 else DAG_id_tag_update(&ob->id, OB_RECALC_OB); 00958 00959 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob); 00960 } 00961 00962 static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v) 00963 { 00964 ED_object_constraint_set_active(ob_v, con_v); 00965 } 00966 00967 /* draw panel showing settings for a constraint */ 00968 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) 00969 { 00970 bPoseChannel *pchan= get_active_posechannel(ob); 00971 bConstraintTypeInfo *cti; 00972 uiBlock *block; 00973 uiLayout *result= NULL, *col, *box, *row; 00974 PointerRNA ptr; 00975 char typestr[32]; 00976 short proxy_protected, xco=0, yco=0; 00977 // int rb_col; // UNUSED 00978 00979 /* get constraint typeinfo */ 00980 cti= constraint_get_typeinfo(con); 00981 if (cti == NULL) { 00982 /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */ 00983 BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? "Null" : "Unknown", sizeof(typestr)); 00984 } 00985 else 00986 BLI_strncpy(typestr, cti->name, sizeof(typestr)); 00987 00988 /* determine whether constraint is proxy protected or not */ 00989 if (proxylocked_constraints_owner(ob, pchan)) 00990 proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0; 00991 else 00992 proxy_protected= 0; 00993 00994 /* unless button has own callback, it adds this callback to button */ 00995 block= uiLayoutGetBlock(layout); 00996 uiBlockSetHandleFunc(block, do_constraint_panels, ob); 00997 uiBlockSetFunc(block, constraint_active_func, ob, con); 00998 00999 RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr); 01000 01001 col= uiLayoutColumn(layout, 1); 01002 uiLayoutSetContextPointer(col, "constraint", &ptr); 01003 01004 box= uiLayoutBox(col); 01005 row = uiLayoutRow(box, 0); 01006 block= uiLayoutGetBlock(box); 01007 01008 /* Draw constraint header */ 01009 01010 /* open/close */ 01011 uiBlockSetEmboss(block, UI_EMBOSSN); 01012 uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE); 01013 uiBlockSetEmboss(block, UI_EMBOSS); 01014 01015 /* name */ 01016 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 01017 01018 if (con->flag & CONSTRAINT_DISABLE) 01019 uiLayoutSetRedAlert(row, 1); 01020 01021 if(proxy_protected == 0) { 01022 uiItemR(row, &ptr, "name", 0, "", ICON_NONE); 01023 } 01024 else 01025 uiItemL(row, con->name, ICON_NONE); 01026 01027 uiLayoutSetRedAlert(row, 0); 01028 01029 /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */ 01030 if (proxy_protected) { 01031 uiBlockSetEmboss(block, UI_EMBOSSN); 01032 01033 /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */ 01034 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco+244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); 01035 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco+262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected")); 01036 01037 uiBlockSetEmboss(block, UI_EMBOSS); 01038 } 01039 else { 01040 short prev_proxylock, show_upbut, show_downbut; 01041 01042 /* Up/Down buttons: 01043 * Proxy-constraints are not allowed to occur after local (non-proxy) constraints 01044 * as that poses problems when restoring them, so disable the "up" button where 01045 * it may cause this situation. 01046 * 01047 * Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose. 01048 */ 01049 if (proxylocked_constraints_owner(ob, pchan)) { 01050 if (con->prev) { 01051 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1; 01052 } 01053 else 01054 prev_proxylock= 0; 01055 } 01056 else 01057 prev_proxylock= 0; 01058 01059 show_upbut= ((prev_proxylock == 0) && (con->prev)); 01060 show_downbut= (con->next) ? 1 : 0; 01061 01062 /* enabled */ 01063 uiBlockSetEmboss(block, UI_EMBOSSN); 01064 uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); 01065 uiBlockSetEmboss(block, UI_EMBOSS); 01066 01067 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); 01068 01069 /* up/down */ 01070 if (show_upbut || show_downbut) { 01071 uiBlockBeginAlign(block); 01072 if (show_upbut) 01073 uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up"); 01074 01075 if (show_downbut) 01076 uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down"); 01077 uiBlockEndAlign(block); 01078 } 01079 01080 /* Close 'button' - emboss calls here disable drawing of 'button' behind X */ 01081 uiBlockSetEmboss(block, UI_EMBOSSN); 01082 uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete"); 01083 uiBlockSetEmboss(block, UI_EMBOSS); 01084 } 01085 01086 /* Set but-locks for protected settings (magic numbers are used here!) */ 01087 if (proxy_protected) 01088 uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint"); 01089 01090 /* Draw constraint data */ 01091 if ((con->flag & CONSTRAINT_EXPAND) == 0) { 01092 (yco) -= 21; 01093 } 01094 else { 01095 box= uiLayoutBox(col); 01096 block= uiLayoutAbsoluteBlock(box); 01097 result= box; 01098 } 01099 01100 /* clear any locks set up for proxies/lib-linking */ 01101 uiBlockClearButLock(block); 01102 01103 return result; 01104 } 01105 01106 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr) 01107 { 01108 Object *ob; 01109 bConstraint *con; 01110 01111 /* verify we have valid data */ 01112 if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) { 01113 RNA_warning("Expected constraint on object"); 01114 return NULL; 01115 } 01116 01117 ob= ptr->id.data; 01118 con= ptr->data; 01119 01120 if(!ob || !(GS(ob->id.name) == ID_OB)) { 01121 RNA_warning("Expected constraint on object"); 01122 return NULL; 01123 } 01124 01125 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE); 01126 01127 /* hrms, the temporal constraint should not draw! */ 01128 if(con->type==CONSTRAINT_TYPE_KINEMATIC) { 01129 bKinematicConstraint *data= con->data; 01130 if(data->flag & CONSTRAINT_IK_TEMP) 01131 return NULL; 01132 } 01133 01134 return draw_constraint(layout, ob, con); 01135 } 01136 01137 01138 /************************* Preview Template ***************************/ 01139 01140 #include "DNA_lamp_types.h" 01141 #include "DNA_material_types.h" 01142 #include "DNA_world_types.h" 01143 01144 #define B_MATPRV 1 01145 01146 static void do_preview_buttons(bContext *C, void *arg, int event) 01147 { 01148 switch(event) { 01149 case B_MATPRV: 01150 WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg); 01151 break; 01152 } 01153 } 01154 01155 void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, MTex *slot) 01156 { 01157 uiLayout *row, *col; 01158 uiBlock *block; 01159 Material *ma= NULL; 01160 Tex *tex = (Tex*)id; 01161 ID *pid, *pparent; 01162 short *pr_texture= NULL; 01163 PointerRNA material_ptr; 01164 PointerRNA texture_ptr; 01165 01166 if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) { 01167 RNA_warning("Expected ID of type material, texture, lamp or world"); 01168 return; 01169 } 01170 01171 /* decide what to render */ 01172 pid= id; 01173 pparent= NULL; 01174 01175 if(id && (GS(id->name) == ID_TE)) { 01176 if(parent && (GS(parent->name) == ID_MA)) 01177 pr_texture= &((Material*)parent)->pr_texture; 01178 else if(parent && (GS(parent->name) == ID_WO)) 01179 pr_texture= &((World*)parent)->pr_texture; 01180 else if(parent && (GS(parent->name) == ID_LA)) 01181 pr_texture= &((Lamp*)parent)->pr_texture; 01182 01183 if(pr_texture) { 01184 if(*pr_texture == TEX_PR_OTHER) 01185 pid= parent; 01186 else if(*pr_texture == TEX_PR_BOTH) 01187 pparent= parent; 01188 } 01189 } 01190 01191 /* layout */ 01192 block= uiLayoutGetBlock(layout); 01193 row= uiLayoutRow(layout, 0); 01194 col= uiLayoutColumn(row, 0); 01195 uiLayoutSetKeepAspect(col, 1); 01196 01197 /* add preview */ 01198 uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, ""); 01199 uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot); 01200 uiBlockSetHandleFunc(block, do_preview_buttons, NULL); 01201 01202 /* add buttons */ 01203 if (pid && show_buttons) { 01204 if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) { 01205 if(GS(pid->name) == ID_MA) ma= (Material*)pid; 01206 else ma= (Material*)pparent; 01207 01208 /* Create RNA Pointer */ 01209 RNA_pointer_create(id, &RNA_Material, ma, &material_ptr); 01210 01211 col = uiLayoutColumn(row, 1); 01212 uiLayoutSetScaleX(col, 1.5); 01213 uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE); 01214 } 01215 01216 if(pr_texture) { 01217 /* Create RNA Pointer */ 01218 RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr); 01219 01220 uiLayoutRow(layout, 1); 01221 uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, ""); 01222 if(GS(parent->name) == ID_MA) 01223 uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); 01224 else if(GS(parent->name) == ID_LA) 01225 uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); 01226 else if(GS(parent->name) == ID_WO) 01227 uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, ""); 01228 uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, ""); 01229 01230 /* Alpha button for texture preview */ 01231 if(*pr_texture!=TEX_PR_OTHER) { 01232 row = uiLayoutRow(layout, 0); 01233 uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NONE); 01234 } 01235 } 01236 } 01237 } 01238 01239 /********************** ColorRamp Template **************************/ 01240 01241 01242 typedef struct RNAUpdateCb { 01243 PointerRNA ptr; 01244 PropertyRNA *prop; 01245 } RNAUpdateCb; 01246 01247 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg)) 01248 { 01249 RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb; 01250 01251 /* we call update here on the pointer property, this way the 01252 owner of the curve mapping can still define it's own update 01253 and notifier, even if the CurveMapping struct is shared. */ 01254 RNA_property_update(C, &cb->ptr, cb->prop); 01255 } 01256 01257 #define B_BANDCOL 1 01258 01259 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v) 01260 { 01261 ColorBand *coba= coba_v; 01262 float pos= 0.5f; 01263 01264 if(coba->tot > 1) { 01265 if(coba->cur > 0) pos= (coba->data[coba->cur-1].pos + coba->data[coba->cur].pos) * 0.5f; 01266 else pos= (coba->data[coba->cur+1].pos + coba->data[coba->cur].pos) * 0.5f; 01267 } 01268 01269 if(colorband_element_add(coba, pos)) { 01270 rna_update_cb(C, cb_v, NULL); 01271 ED_undo_push(C, "Add colorband"); 01272 } 01273 } 01274 01275 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v) 01276 { 01277 ColorBand *coba= coba_v; 01278 01279 if(colorband_element_remove(coba, coba->cur)) { 01280 ED_undo_push(C, "Delete colorband"); 01281 rna_update_cb(C, cb_v, NULL); 01282 } 01283 } 01284 01285 static void colorband_flip_cb(bContext *C, void *cb_v, void *coba_v) 01286 { 01287 CBData data_tmp[MAXCOLORBAND]; 01288 01289 ColorBand *coba= coba_v; 01290 int a; 01291 01292 for(a=0; a<coba->tot; a++) { 01293 data_tmp[a]= coba->data[coba->tot - (a + 1)]; 01294 } 01295 for(a=0; a<coba->tot; a++) { 01296 data_tmp[a].pos = 1.0f - data_tmp[a].pos; 01297 coba->data[a]= data_tmp[a]; 01298 } 01299 01300 /* may as well flip the cur*/ 01301 coba->cur= coba->tot - (coba->cur + 1); 01302 01303 ED_undo_push(C, "Flip colorband"); 01304 01305 rna_update_cb(C, cb_v, NULL); 01306 } 01307 01308 01309 /* offset aligns from bottom, standard width 300, height 115 */ 01310 static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb) 01311 { 01312 uiBut *bt; 01313 uiLayout *row; 01314 const int line1_y= yoffs + 65 + UI_UNIT_Y + 2; /* 2 for some space between the buttons */ 01315 const int line2_y= yoffs + 65; 01316 01317 if(coba==NULL) return; 01318 01319 bt= uiDefBut(block, BUT, 0, IFACE_("Add"), 0+xoffs,line1_y,40,UI_UNIT_Y, NULL, 0, 0, 0, 0, 01320 TIP_("Add a new color stop to the colorband")); 01321 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); 01322 01323 bt= uiDefBut(block, BUT, 0, IFACE_("Delete"), 45+xoffs,line1_y,45,UI_UNIT_Y, NULL, 0, 0, 0, 0, 01324 TIP_("Delete the active position")); 01325 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); 01326 01327 01328 /* XXX, todo for later - convert to operator - campbell */ 01329 bt= uiDefBut(block, BUT, 0, "F", 95+xoffs,line1_y,20,UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip colorband")); 01330 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); 01331 01332 uiDefButS(block, NUM, 0, "", 120+xoffs,line1_y,80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, TIP_("Choose active color stop")); 01333 01334 bt= uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), 01335 210+xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops")); 01336 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); 01337 uiBlockEndAlign(block); 01338 01339 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,line2_y,300,UI_UNIT_Y, coba, 0, 0, 0, 0, ""); 01340 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); 01341 01342 01343 01344 if(coba->tot) { 01345 CBData *cbd= coba->data + coba->cur; 01346 01347 /* better to use rna so we can animate them */ 01348 PointerRNA ptr; 01349 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr); 01350 row= uiLayoutRow(layout, 0); 01351 uiItemR(row, &ptr, "position", 0, "Pos", ICON_NONE); 01352 uiItemR(row, &ptr, "color", 0, "", ICON_NONE); 01353 } 01354 01355 } 01356 01357 static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb) 01358 { 01359 uiBut *bt; 01360 float unit= (butr->xmax-butr->xmin)/14.0f; 01361 float xs= butr->xmin; 01362 01363 uiBlockBeginAlign(block); 01364 bt= uiDefBut(block, BUT, 0, IFACE_("Add"), xs,butr->ymin+UI_UNIT_Y,2.0f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, 01365 TIP_("Add a new color stop to the colorband")); 01366 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba); 01367 bt= uiDefBut(block, BUT, 0, IFACE_("Delete"), xs+2.0f*unit,butr->ymin+UI_UNIT_Y,1.5f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, 01368 TIP_("Delete the active position")); 01369 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba); 01370 bt= uiDefBut(block, BUT, 0, "F", xs+3.5f*unit,butr->ymin+UI_UNIT_Y,0.5f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip the color ramp")); 01371 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba); 01372 uiBlockEndAlign(block); 01373 01374 if(coba->tot) { 01375 CBData *cbd= coba->data + coba->cur; 01376 PointerRNA ptr; 01377 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr); 01378 uiItemR(layout, &ptr, "color", 0, "", ICON_NONE); 01379 } 01380 01381 bt= uiDefButS(block, MENU, 0, TIP_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"), 01382 xs+10.0f*unit, butr->ymin+UI_UNIT_Y, unit*4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, 01383 TIP_("Set interpolation between color stops")); 01384 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); 01385 01386 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,UI_UNIT_Y, coba, 0, 0, 0, 0, ""); 01387 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); 01388 01389 uiBlockEndAlign(block); 01390 } 01391 01392 static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb) 01393 { 01394 if(small) 01395 colorband_buttons_small(layout, block, coba, butr, cb); 01396 else 01397 colorband_buttons_large(layout, block, coba, 0, 0, cb); 01398 } 01399 01400 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, int expand) 01401 { 01402 PropertyRNA *prop= RNA_struct_find_property(ptr, propname); 01403 PointerRNA cptr; 01404 RNAUpdateCb *cb; 01405 uiBlock *block; 01406 rctf rect; 01407 01408 if(!prop || RNA_property_type(prop) != PROP_POINTER) 01409 return; 01410 01411 cptr= RNA_property_pointer_get(ptr, prop); 01412 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp)) 01413 return; 01414 01415 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); 01416 cb->ptr= *ptr; 01417 cb->prop= prop; 01418 01419 rect.xmin= 0; rect.xmax= 200; 01420 rect.ymin= 0; rect.ymax= 190; 01421 01422 block= uiLayoutAbsoluteBlock(layout); 01423 colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb); 01424 01425 MEM_freeN(cb); 01426 } 01427 01428 /********************* Histogram Template ************************/ 01429 01430 void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname) 01431 { 01432 PropertyRNA *prop= RNA_struct_find_property(ptr, propname); 01433 PointerRNA cptr; 01434 RNAUpdateCb *cb; 01435 uiBlock *block; 01436 uiBut *bt; 01437 Histogram *hist; 01438 rctf rect; 01439 01440 if(!prop || RNA_property_type(prop) != PROP_POINTER) 01441 return; 01442 01443 cptr= RNA_property_pointer_get(ptr, prop); 01444 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram)) 01445 return; 01446 01447 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); 01448 cb->ptr= *ptr; 01449 cb->prop= prop; 01450 01451 rect.xmin= 0; rect.xmax= 200; 01452 rect.ymin= 0; rect.ymax= 190; 01453 01454 block= uiLayoutAbsoluteBlock(layout); 01455 //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb); 01456 01457 hist = (Histogram *)cptr.data; 01458 01459 hist->height= (hist->height<=UI_UNIT_Y)?UI_UNIT_Y:hist->height; 01460 01461 bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, ""); 01462 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); 01463 01464 MEM_freeN(cb); 01465 } 01466 01467 /********************* Waveform Template ************************/ 01468 01469 void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname) 01470 { 01471 PropertyRNA *prop= RNA_struct_find_property(ptr, propname); 01472 PointerRNA cptr; 01473 RNAUpdateCb *cb; 01474 uiBlock *block; 01475 uiBut *bt; 01476 Scopes *scopes; 01477 rctf rect; 01478 01479 if(!prop || RNA_property_type(prop) != PROP_POINTER) 01480 return; 01481 01482 cptr= RNA_property_pointer_get(ptr, prop); 01483 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) 01484 return; 01485 scopes = (Scopes *)cptr.data; 01486 01487 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); 01488 cb->ptr= *ptr; 01489 cb->prop= prop; 01490 01491 rect.xmin= 0; rect.xmax= 200; 01492 rect.ymin= 0; rect.ymax= 190; 01493 01494 block= uiLayoutAbsoluteBlock(layout); 01495 01496 scopes->wavefrm_height= (scopes->wavefrm_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->wavefrm_height; 01497 01498 bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, ""); 01499 (void)bt; // UNUSED 01500 01501 MEM_freeN(cb); 01502 } 01503 01504 /********************* Vectorscope Template ************************/ 01505 01506 void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propname) 01507 { 01508 PropertyRNA *prop= RNA_struct_find_property(ptr, propname); 01509 PointerRNA cptr; 01510 RNAUpdateCb *cb; 01511 uiBlock *block; 01512 uiBut *bt; 01513 Scopes *scopes; 01514 rctf rect; 01515 01516 if(!prop || RNA_property_type(prop) != PROP_POINTER) 01517 return; 01518 01519 cptr= RNA_property_pointer_get(ptr, prop); 01520 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes)) 01521 return; 01522 scopes = (Scopes *)cptr.data; 01523 01524 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); 01525 cb->ptr= *ptr; 01526 cb->prop= prop; 01527 01528 rect.xmin= 0; rect.xmax= 200; 01529 rect.ymin= 0; rect.ymax= 190; 01530 01531 block= uiLayoutAbsoluteBlock(layout); 01532 01533 scopes->vecscope_height= (scopes->vecscope_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->vecscope_height; 01534 01535 bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, ""); 01536 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); 01537 01538 MEM_freeN(cb); 01539 } 01540 01541 /********************* CurveMapping Template ************************/ 01542 01543 01544 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(arg)) 01545 { 01546 CurveMapping *cumap = cumap_v; 01547 float d; 01548 01549 /* we allow 20 times zoom */ 01550 if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) { 01551 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin); 01552 cumap->curr.xmin+= d; 01553 cumap->curr.xmax-= d; 01554 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin); 01555 cumap->curr.ymin+= d; 01556 cumap->curr.ymax-= d; 01557 } 01558 01559 ED_region_tag_redraw(CTX_wm_region(C)); 01560 } 01561 01562 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(unused)) 01563 { 01564 CurveMapping *cumap = cumap_v; 01565 float d, d1; 01566 01567 /* we allow 20 times zoom, but dont view outside clip */ 01568 if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) { 01569 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin); 01570 01571 if(cumap->flag & CUMA_DO_CLIP) 01572 if(cumap->curr.xmin-d < cumap->clipr.xmin) 01573 d1= cumap->curr.xmin - cumap->clipr.xmin; 01574 cumap->curr.xmin-= d1; 01575 01576 d1= d; 01577 if(cumap->flag & CUMA_DO_CLIP) 01578 if(cumap->curr.xmax+d > cumap->clipr.xmax) 01579 d1= -cumap->curr.xmax + cumap->clipr.xmax; 01580 cumap->curr.xmax+= d1; 01581 01582 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin); 01583 01584 if(cumap->flag & CUMA_DO_CLIP) 01585 if(cumap->curr.ymin-d < cumap->clipr.ymin) 01586 d1= cumap->curr.ymin - cumap->clipr.ymin; 01587 cumap->curr.ymin-= d1; 01588 01589 d1= d; 01590 if(cumap->flag & CUMA_DO_CLIP) 01591 if(cumap->curr.ymax+d > cumap->clipr.ymax) 01592 d1= -cumap->curr.ymax + cumap->clipr.ymax; 01593 cumap->curr.ymax+= d1; 01594 } 01595 01596 ED_region_tag_redraw(CTX_wm_region(C)); 01597 } 01598 01599 static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *UNUSED(arg)) 01600 { 01601 CurveMapping *cumap = cumap_v; 01602 01603 curvemapping_changed(cumap, 0); 01604 } 01605 01606 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v) 01607 { 01608 CurveMapping *cumap = cumap_v; 01609 01610 curvemap_remove(cumap->cm+cumap->cur, SELECT); 01611 curvemapping_changed(cumap, 0); 01612 01613 rna_update_cb(C, cb_v, NULL); 01614 } 01615 01616 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */ 01617 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v) 01618 { 01619 CurveMapping *cumap = cumap_v; 01620 uiBlock *block; 01621 uiBut *bt; 01622 float width= 8*UI_UNIT_X; 01623 01624 block = uiBeginBlock(C, ar, __func__, UI_EMBOSS); 01625 01626 /* use this for a fake extra empy space around the buttons */ 01627 uiDefBut(block, LABEL, 0, "", -4, 16, width+8, 6*UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); 01628 01629 bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping", 01630 0,5*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->flag, 0.0, 0.0, 10, 0, ""); 01631 uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL); 01632 01633 uiBlockBeginAlign(block); 01634 uiDefButF(block, NUM, 0, IFACE_("Min X "), 0,4*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, ""); 01635 uiDefButF(block, NUM, 0, IFACE_("Min Y "), 0,3*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, ""); 01636 uiDefButF(block, NUM, 0, IFACE_("Max X "), 0,2*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, ""); 01637 uiDefButF(block, NUM, 0, IFACE_("Max Y "), 0,UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, ""); 01638 01639 uiBlockSetDirection(block, UI_RIGHT); 01640 01641 uiEndBlock(C, block); 01642 return block; 01643 } 01644 01645 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event) 01646 { 01647 CurveMapping *cumap = cumap_v; 01648 CurveMap *cuma= cumap->cm+cumap->cur; 01649 01650 switch(event) { 01651 case 0: /* reset */ 01652 curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE); 01653 curvemapping_changed(cumap, 0); 01654 break; 01655 case 1: 01656 cumap->curr= cumap->clipr; 01657 break; 01658 case 2: /* set vector */ 01659 curvemap_sethandle(cuma, 1); 01660 curvemapping_changed(cumap, 0); 01661 break; 01662 case 3: /* set auto */ 01663 curvemap_sethandle(cuma, 0); 01664 curvemapping_changed(cumap, 0); 01665 break; 01666 case 4: /* extend horiz */ 01667 cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE; 01668 curvemapping_changed(cumap, 0); 01669 break; 01670 case 5: /* extend extrapolate */ 01671 cuma->flag |= CUMA_EXTEND_EXTRAPOLATE; 01672 curvemapping_changed(cumap, 0); 01673 break; 01674 } 01675 ED_region_tag_redraw(CTX_wm_region(C)); 01676 } 01677 01678 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v) 01679 { 01680 uiBlock *block; 01681 short yco= 0, menuwidth=10*UI_UNIT_X; 01682 01683 block= uiBeginBlock(C, ar, __func__, UI_EMBOSS); 01684 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); 01685 01686 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); 01687 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); 01688 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); 01689 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, ""); 01690 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, ""); 01691 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); 01692 01693 uiBlockSetDirection(block, UI_RIGHT); 01694 uiTextBoundsBlock(block, 50); 01695 01696 uiEndBlock(C, block); 01697 return block; 01698 } 01699 01700 static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v) 01701 { 01702 uiBlock *block; 01703 short yco= 0, menuwidth=10*UI_UNIT_X; 01704 01705 block= uiBeginBlock(C, ar, __func__, UI_EMBOSS); 01706 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v); 01707 01708 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, ""); 01709 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, ""); 01710 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, ""); 01711 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"), 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, ""); 01712 01713 uiBlockSetDirection(block, UI_RIGHT); 01714 uiTextBoundsBlock(block, 50); 01715 01716 uiEndBlock(C, block); 01717 return block; 01718 } 01719 01720 static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2)) 01721 { 01722 ED_region_tag_redraw(CTX_wm_region(C)); 01723 } 01724 01725 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v) 01726 { 01727 CurveMapping *cumap = cumap_v; 01728 int a; 01729 01730 cumap->preset = CURVE_PRESET_LINE; 01731 for(a=0; a<CM_TOT; a++) 01732 curvemap_reset(cumap->cm+a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE); 01733 01734 cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f; 01735 cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f; 01736 curvemapping_set_black_white(cumap, NULL, NULL); 01737 01738 curvemapping_changed(cumap, 0); 01739 01740 rna_update_cb(C, cb_v, NULL); 01741 } 01742 01743 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */ 01744 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb) 01745 { 01746 CurveMapping *cumap= ptr->data; 01747 uiLayout *row, *sub, *split; 01748 uiBlock *block; 01749 uiBut *bt; 01750 float dx= UI_UNIT_X; 01751 int icon, size; 01752 int bg=-1; 01753 01754 block= uiLayoutGetBlock(layout); 01755 01756 /* curve chooser */ 01757 row= uiLayoutRow(layout, 0); 01758 01759 if(labeltype=='v') { 01760 /* vector */ 01761 sub= uiLayoutRow(row, 1); 01762 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); 01763 01764 if(cumap->cm[0].curve) { 01765 bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); 01766 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01767 } 01768 if(cumap->cm[1].curve) { 01769 bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); 01770 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01771 } 01772 if(cumap->cm[2].curve) { 01773 bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); 01774 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01775 } 01776 } 01777 else if(labeltype=='c') { 01778 /* color */ 01779 sub= uiLayoutRow(row, 1); 01780 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); 01781 01782 if(cumap->cm[3].curve) { 01783 bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, ""); 01784 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01785 } 01786 if(cumap->cm[0].curve) { 01787 bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); 01788 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01789 } 01790 if(cumap->cm[1].curve) { 01791 bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); 01792 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01793 } 01794 if(cumap->cm[2].curve) { 01795 bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); 01796 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01797 } 01798 } 01799 else if (labeltype == 'h') { 01800 /* HSV */ 01801 sub= uiLayoutRow(row, 1); 01802 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT); 01803 01804 if(cumap->cm[0].curve) { 01805 bt= uiDefButI(block, ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, ""); 01806 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01807 } 01808 if(cumap->cm[1].curve) { 01809 bt= uiDefButI(block, ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, ""); 01810 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01811 } 01812 if(cumap->cm[2].curve) { 01813 bt= uiDefButI(block, ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, ""); 01814 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL); 01815 } 01816 } 01817 else 01818 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT); 01819 01820 if (labeltype=='h') 01821 bg = UI_GRAD_H; 01822 01823 /* operation buttons */ 01824 sub= uiLayoutRow(row, 1); 01825 01826 uiBlockSetEmboss(block, UI_EMBOSSN); 01827 01828 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom in")); 01829 uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL); 01830 01831 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom out")); 01832 uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL); 01833 01834 if(brush) 01835 bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools")); 01836 else 01837 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools")); 01838 01839 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); 01840 01841 if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT; 01842 bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options")); 01843 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL); 01844 01845 bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete points")); 01846 uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap); 01847 01848 uiBlockSetEmboss(block, UI_EMBOSS); 01849 01850 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL); 01851 01852 /* curve itself */ 01853 size= uiLayoutGetWidth(layout); 01854 row= uiLayoutRow(layout, 0); 01855 uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, ""); 01856 01857 /* black/white levels */ 01858 if(levels) { 01859 split= uiLayoutSplit(layout, 0, 0); 01860 uiItemR(uiLayoutColumn(split, 0), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE); 01861 uiItemR(uiLayoutColumn(split, 0), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE); 01862 01863 uiLayoutRow(layout, 0); 01864 bt=uiDefBut(block, BUT, 0, IFACE_("Reset"), 0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, 01865 TIP_("Reset Black/White point and curves")); 01866 uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap); 01867 } 01868 01869 uiBlockSetNFunc(block, NULL, NULL, NULL); 01870 } 01871 01872 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, int levels, int brush) 01873 { 01874 RNAUpdateCb *cb; 01875 PropertyRNA *prop= RNA_struct_find_property(ptr, propname); 01876 PointerRNA cptr; 01877 01878 if(!prop) { 01879 RNA_warning("curve property not found: %s.%s", 01880 RNA_struct_identifier(ptr->type), propname); 01881 return; 01882 } 01883 01884 if(RNA_property_type(prop) != PROP_POINTER) { 01885 RNA_warning("curve is not a pointer: %s.%s", 01886 RNA_struct_identifier(ptr->type), propname); 01887 return; 01888 } 01889 01890 cptr= RNA_property_pointer_get(ptr, prop); 01891 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping)) 01892 return; 01893 01894 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb"); 01895 cb->ptr= *ptr; 01896 cb->prop= prop; 01897 01898 curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb); 01899 01900 MEM_freeN(cb); 01901 } 01902 01903 /********************* ColorWheel Template ************************/ 01904 01905 #define WHEEL_SIZE 100 01906 01907 void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic) 01908 { 01909 PropertyRNA *prop= RNA_struct_find_property(ptr, propname); 01910 uiBlock *block= uiLayoutGetBlock(layout); 01911 uiLayout *col, *row; 01912 uiBut *but; 01913 float softmin, softmax, step, precision; 01914 01915 if (!prop) { 01916 RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); 01917 return; 01918 } 01919 01920 RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision); 01921 01922 col = uiLayoutColumn(layout, 0); 01923 row= uiLayoutRow(col, 1); 01924 01925 but= uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, ""); 01926 01927 if(lock) { 01928 but->flag |= UI_BUT_COLOR_LOCK; 01929 } 01930 01931 if(lock_luminosity) { 01932 float color[4]; /* incase of alpha */ 01933 but->flag |= UI_BUT_VEC_SIZE_LOCK; 01934 RNA_property_float_get_array(ptr, prop, color); 01935 but->a2= len_v3(color); 01936 } 01937 01938 if(cubic) 01939 but->flag |= UI_BUT_COLOR_CUBIC; 01940 01941 uiItemS(row); 01942 01943 if (value_slider) 01944 uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); 01945 } 01946 01947 /********************* Layer Buttons Template ************************/ 01948 01949 static void handle_layer_buttons(bContext *C, void *arg1, void *arg2) 01950 { 01951 uiBut *but = arg1; 01952 int cur = GET_INT_FROM_POINTER(arg2); 01953 wmWindow *win= CTX_wm_window(C); 01954 int i, tot, shift= win->eventstate->shift; 01955 01956 if(!shift) { 01957 tot= RNA_property_array_length(&but->rnapoin, but->rnaprop); 01958 01959 /* Normally clicking only selects one layer */ 01960 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, TRUE); 01961 for(i = 0; i < tot; ++i) { 01962 if(i != cur) 01963 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, FALSE); 01964 } 01965 } 01966 01967 /* view3d layer change should update depsgraph (invisible object changed maybe) */ 01968 /* see view3d_header.c */ 01969 } 01970 01971 // TODO: 01972 // - for now, grouping of layers is determined by dividing up the length of 01973 // the array of layer bitflags 01974 01975 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname, 01976 PointerRNA *used_ptr, const char *used_propname, int active_layer) 01977 { 01978 uiLayout *uRow, *uCol; 01979 PropertyRNA *prop, *used_prop= NULL; 01980 int groups, cols, layers; 01981 int group, col, layer, row; 01982 int cols_per_group = 5; 01983 01984 prop= RNA_struct_find_property(ptr, propname); 01985 if (!prop) { 01986 RNA_warning("layers property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); 01987 return; 01988 } 01989 01990 /* the number of layers determines the way we group them 01991 * - we want 2 rows only (for now) 01992 * - the number of columns (cols) is the total number of buttons per row 01993 * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be 01994 * - for now, only split into groups if group will have at least 5 items 01995 */ 01996 layers= RNA_property_array_length(ptr, prop); 01997 cols= (layers / 2) + (layers % 2); 01998 groups= ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group); 01999 02000 if(used_ptr && used_propname) { 02001 used_prop= RNA_struct_find_property(used_ptr, used_propname); 02002 if (!used_prop) { 02003 RNA_warning("used layers property not found: %s.%s", RNA_struct_identifier(ptr->type), used_propname); 02004 return; 02005 } 02006 02007 if(RNA_property_array_length(used_ptr, used_prop) < layers) 02008 used_prop = NULL; 02009 } 02010 02011 /* layers are laid out going across rows, with the columns being divided into groups */ 02012 02013 for (group= 0; group < groups; group++) { 02014 uCol= uiLayoutColumn(layout, 1); 02015 02016 for (row= 0; row < 2; row++) { 02017 uiBlock *block; 02018 uiBut *but; 02019 02020 uRow= uiLayoutRow(uCol, 1); 02021 block= uiLayoutGetBlock(uRow); 02022 layer= groups*cols_per_group*row + cols_per_group*group; 02023 02024 /* add layers as toggle buts */ 02025 for (col= 0; (col < cols_per_group) && (layer < layers); col++, layer++) { 02026 int icon = 0; 02027 int butlay = 1 << layer; 02028 02029 if(active_layer & butlay) 02030 icon = ICON_LAYER_ACTIVE; 02031 else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer)) 02032 icon = ICON_LAYER_USED; 02033 02034 but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X/2, UI_UNIT_Y/2); 02035 uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer)); 02036 but->type= TOG; 02037 } 02038 } 02039 } 02040 } 02041 02042 02043 /************************* List Template **************************/ 02044 02045 static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big) 02046 { 02047 ID *id= NULL; 02048 int icon; 02049 02050 if(!itemptr->data) 02051 return rnaicon; 02052 02053 /* try ID, material or texture slot */ 02054 if(RNA_struct_is_ID(itemptr->type)) { 02055 id= itemptr->id.data; 02056 } 02057 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) { 02058 id= RNA_pointer_get(itemptr, "material").data; 02059 } 02060 else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) { 02061 id= RNA_pointer_get(itemptr, "texture").data; 02062 } 02063 else if(RNA_struct_is_a(itemptr->type, &RNA_DynamicPaintSurface)) { 02064 DynamicPaintSurface *surface= (DynamicPaintSurface*)itemptr->data; 02065 02066 if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) return ICON_TEXTURE_SHADED; 02067 else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) return ICON_OUTLINER_DATA_MESH; 02068 else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE; 02069 } 02070 02071 /* get icon from ID */ 02072 if(id) { 02073 icon= ui_id_icon_get(C, id, big); 02074 02075 if(icon) 02076 return icon; 02077 } 02078 02079 return rnaicon; 02080 } 02081 02082 static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id) 02083 { 02084 uiBlock *block= uiLayoutGetBlock(layout); 02085 uiBut *but; 02086 uiLayout *split, *overlap, *sub, *row; 02087 char *namebuf; 02088 const char *name; 02089 int icon; 02090 02091 overlap= uiLayoutOverlap(layout); 02092 02093 /* list item behind label & other buttons */ 02094 sub= uiLayoutRow(overlap, 0); 02095 02096 but= uiDefButR_prop(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); 02097 uiButSetFlag(but, UI_BUT_NO_TOOLTIP); 02098 02099 sub= uiLayoutRow(overlap, 0); 02100 02101 /* retrieve icon and name */ 02102 icon= list_item_icon_get(C, itemptr, rnaicon, 0); 02103 if(icon == ICON_NONE || icon == ICON_DOT) 02104 icon= 0; 02105 02106 namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL); 02107 name= (namebuf)? namebuf: ""; 02108 02109 /* hardcoded types */ 02110 if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) { 02111 uiItemL(sub, name, icon); 02112 uiBlockSetEmboss(block, UI_EMBOSSN); 02113 uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL); 02114 uiBlockSetEmboss(block, UI_EMBOSS); 02115 } 02116 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) { 02117 uiItemL(sub, name, icon); 02118 uiBlockSetEmboss(block, UI_EMBOSS); 02119 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL); 02120 } 02121 else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) { 02122 uiItemL(sub, name, icon); 02123 uiBlockSetEmboss(block, UI_EMBOSS); 02124 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL); 02125 } 02126 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) { 02127 /* provision to draw active node name */ 02128 Material *ma, *manode; 02129 Scene *scene= CTX_data_scene(C); 02130 Object *ob= (Object*)ptr->id.data; 02131 int index= (Material**)itemptr->data - ob->mat; 02132 02133 /* default item with material base name */ 02134 uiItemL(sub, name, icon); 02135 02136 ma= give_current_material(ob, index+1); 02137 if (ma && !scene_use_new_shading_nodes(scene)){ 02138 manode= give_node_material(ma); 02139 if(manode) { 02140 char str[MAX_ID_NAME + 12]; 02141 BLI_snprintf(str, sizeof(str), "Node %s", manode->id.name+2); 02142 uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1)); 02143 } 02144 else if(ma->use_nodes) { 02145 uiItemL(sub, "Node <none>", ICON_NONE); 02146 } 02147 } 02148 } 02149 else if(itemptr->type == &RNA_ShapeKey) { 02150 Object *ob= (Object*)activeptr->data; 02151 Key *key= (Key*)itemptr->id.data; 02152 02153 split= uiLayoutSplit(sub, 0.75f, 0); 02154 02155 uiItemL(split, name, icon); 02156 02157 uiBlockSetEmboss(block, UI_EMBOSSN); 02158 row= uiLayoutRow(split, 1); 02159 if(i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE); 02160 else uiItemR(row, itemptr, "value", 0, "", ICON_NONE); 02161 02162 if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH)) 02163 uiLayoutSetActive(row, 0); 02164 //uiItemR(row, itemptr, "mute", 0, "", ICON_MUTE_IPO_OFF); 02165 uiBlockSetEmboss(block, UI_EMBOSS); 02166 } 02167 else if(itemptr->type == &RNA_VertexGroup) { 02168 bDeformGroup *dg= (bDeformGroup *)itemptr->data; 02169 uiItemL(sub, name, icon); 02170 /* RNA does not allow nice lock icons, use lower level buttons */ 02171 #if 0 02172 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "lock_weight", 0, 0, 0, 0, 0, NULL); 02173 #else 02174 uiBlockSetEmboss(block, UI_EMBOSSN); 02175 uiDefIconButBitC(block, TOG, DG_LOCK_WEIGHT, 0, (dg->flag & DG_LOCK_WEIGHT) ? ICON_LOCKED : ICON_UNLOCKED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &dg->flag, 0, 0, 0, 0, "Maintain relative weights while painting"); 02176 uiBlockSetEmboss(block, UI_EMBOSS); 02177 #endif 02178 } 02179 else if(itemptr->type == &RNA_KeyingSetPath) { 02180 KS_Path *ksp = (KS_Path*)itemptr->data; 02181 02182 /* icon needs to be the type of ID which is currently active */ 02183 RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon); 02184 02185 /* nothing else special to do... */ 02186 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */ 02187 } 02188 else if(itemptr->type == &RNA_DynamicPaintSurface) { 02189 char name_final[96]; 02190 const char *enum_name; 02191 PropertyRNA *prop = RNA_struct_find_property(itemptr, "surface_type"); 02192 DynamicPaintSurface *surface= (DynamicPaintSurface*)itemptr->data; 02193 02194 RNA_property_enum_name(C, itemptr, prop, RNA_property_enum_get(itemptr, prop), &enum_name); 02195 02196 BLI_snprintf(name_final, sizeof(name_final), "%s (%s)",name,enum_name); 02197 uiItemL(sub, name_final, icon); 02198 if (dynamicPaint_surfaceHasColorPreview(surface)) { 02199 uiBlockSetEmboss(block, UI_EMBOSSN); 02200 uiDefIconButR(block, OPTION, 0, (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON, 02201 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL); 02202 uiBlockSetEmboss(block, UI_EMBOSS); 02203 } 02204 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0, NULL); 02205 } 02206 else if(itemptr->type == &RNA_MovieTrackingObject) { 02207 MovieTrackingObject *tracking_object= (MovieTrackingObject*)itemptr->data; 02208 02209 split= uiLayoutSplit(sub, 0.75f, 0); 02210 if(tracking_object->flag&TRACKING_OBJECT_CAMERA) { 02211 uiItemL(split, name, ICON_CAMERA_DATA); 02212 } 02213 else { 02214 uiItemL(split, name, ICON_OBJECT_DATA); 02215 } 02216 } 02217 02218 /* There is a last chance to display custom controls (in addition to the name/label): 02219 * If the given item property group features a string property named as prop_list, 02220 * this tries to add controls for all properties of the item listed in that string property. 02221 * (colon-separated names). 02222 * 02223 * This is especially useful for python. E.g., if you list a collection of this property 02224 * group: 02225 * 02226 * class TestPropertyGroup(bpy.types.PropertyGroup): 02227 * bool = BoolProperty(default=False) 02228 * integer = IntProperty() 02229 * string = StringProperty() 02230 * 02231 * # A string of all identifiers (colon-separated) which property’s controls should be 02232 * # displayed in a template_list. 02233 * template_list_controls = StringProperty(default="integer:bool:string", options={"HIDDEN"}) 02234 * 02235 * … you’ll get a numfield for the integer prop, a check box for the bool prop, and a textfield 02236 * for the string prop, after the name of each item of the collection. 02237 */ 02238 else if (prop_list_id) { 02239 row = uiLayoutRow(sub, 1); 02240 uiItemL(row, name, icon); 02241 02242 /* XXX: Check, as sometimes we get an itemptr looking like 02243 * {id = {data = 0x0}, type = 0x0, data = 0x0} 02244 * which would obviously produce a sigsev… */ 02245 if (itemptr->type) { 02246 /* If the special property is set for the item, and it is a collection… */ 02247 PropertyRNA *prop_list= RNA_struct_find_property(itemptr, prop_list_id); 02248 02249 if(prop_list && RNA_property_type(prop_list) == PROP_STRING) { 02250 int prop_names_len; 02251 char *prop_names = RNA_property_string_get_alloc(itemptr, prop_list, NULL, 0, &prop_names_len); 02252 char *prop_names_end= prop_names + prop_names_len; 02253 char *id= prop_names; 02254 char *id_next; 02255 while (id < prop_names_end) { 02256 if ((id_next= strchr(id, ':'))) *id_next++= '\0'; 02257 else id_next= prop_names_end; 02258 uiItemR(row, itemptr, id, 0, NULL, 0); 02259 id= id_next; 02260 } 02261 MEM_freeN(prop_names); 02262 } 02263 } 02264 } 02265 02266 else 02267 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */ 02268 02269 /* free name */ 02270 if(namebuf) 02271 MEM_freeN(namebuf); 02272 } 02273 02274 void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype) 02275 { 02276 //Scene *scene= CTX_data_scene(C); 02277 PropertyRNA *prop= NULL, *activeprop; 02278 PropertyType type, activetype; 02279 StructRNA *ptype; 02280 uiLayout *box, *row, *col; 02281 uiBlock *block; 02282 uiBut *but; 02283 Panel *pa; 02284 const char *name; 02285 char numstr[32]; 02286 int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max; 02287 02288 /* validate arguments */ 02289 block= uiLayoutGetBlock(layout); 02290 pa= block->panel; 02291 02292 if(!pa) { 02293 RNA_warning("Only works inside a panel"); 02294 return; 02295 } 02296 02297 if(!activeptr->data) 02298 return; 02299 02300 if(ptr->data) { 02301 prop= RNA_struct_find_property(ptr, propname); 02302 if(!prop) { 02303 RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); 02304 return; 02305 } 02306 } 02307 02308 activeprop= RNA_struct_find_property(activeptr, activepropname); 02309 if(!activeprop) { 02310 RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), activepropname); 02311 return; 02312 } 02313 02314 if(prop) { 02315 type= RNA_property_type(prop); 02316 if(type != PROP_COLLECTION) { 02317 RNA_warning("uiExpected collection property"); 02318 return; 02319 } 02320 } 02321 02322 activetype= RNA_property_type(activeprop); 02323 if(activetype != PROP_INT) { 02324 RNA_warning("Expected integer property"); 02325 return; 02326 } 02327 02328 /* get icon */ 02329 if(ptr->data && prop) { 02330 ptype= RNA_property_pointer_type(ptr, prop); 02331 rnaicon= RNA_struct_ui_icon(ptype); 02332 } 02333 02334 /* get active data */ 02335 activei= RNA_property_int_get(activeptr, activeprop); 02336 02337 if(listtype == 'i') { 02338 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop); 02339 col= uiLayoutColumn(box, 1); 02340 row= uiLayoutRow(col, 0); 02341 02342 if(ptr->data && prop) { 02343 /* create list items */ 02344 RNA_PROP_BEGIN(ptr, itemptr, prop) { 02345 /* create button */ 02346 if(!(i % 9)) 02347 row= uiLayoutRow(col, 0); 02348 02349 icon= list_item_icon_get(C, &itemptr, rnaicon, 1); 02350 but= uiDefIconButR_prop(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, ""); 02351 uiButSetFlag(but, UI_BUT_NO_TOOLTIP); 02352 02353 02354 i++; 02355 } 02356 RNA_PROP_END; 02357 } 02358 } 02359 else if(listtype == 'c') { 02360 /* compact layout */ 02361 02362 row= uiLayoutRow(layout, 1); 02363 02364 if(ptr->data && prop) { 02365 /* create list items */ 02366 RNA_PROP_BEGIN(ptr, itemptr, prop) { 02367 found= (activei == i); 02368 02369 if(found) { 02370 /* create button */ 02371 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); 02372 icon= list_item_icon_get(C, &itemptr, rnaicon, 0); 02373 uiItemL(row, (name)? name: "", icon); 02374 02375 if(name) 02376 MEM_freeN((void *)name); 02377 } 02378 02379 i++; 02380 } 02381 RNA_PROP_END; 02382 } 02383 02384 /* if not found, add in dummy button */ 02385 if(i == 0) 02386 uiItemL(row, "", ICON_NONE); 02387 02388 /* next/prev button */ 02389 BLI_snprintf(numstr, sizeof(numstr), "%d :", i); 02390 but= uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, ""); 02391 if(i == 0) 02392 uiButSetFlag(but, UI_BUT_DISABLED); 02393 } 02394 else { 02395 /* default rows */ 02396 if(rows == 0) 02397 rows= 5; 02398 if (maxrows == 0) 02399 maxrows = 5; 02400 if(pa->list_grip_size != 0) 02401 rows= pa->list_grip_size; 02402 02403 /* layout */ 02404 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop); 02405 row= uiLayoutRow(box, 0); 02406 col = uiLayoutColumn(row, 1); 02407 02408 /* init numbers */ 02409 RNA_property_int_range(activeptr, activeprop, &min, &max); 02410 02411 if(prop) 02412 len= RNA_property_collection_length(ptr, prop); 02413 items= CLAMPIS(len, rows, MAX2(rows, maxrows)); 02414 02415 /* if list length changes and active is out of view, scroll to it */ 02416 if(pa->list_last_len != len) 02417 if((activei < pa->list_scroll || activei >= pa->list_scroll+items)) 02418 pa->list_scroll= activei; 02419 02420 pa->list_scroll= MIN2(pa->list_scroll, len-items); 02421 pa->list_scroll= MAX2(pa->list_scroll, 0); 02422 pa->list_size= items; 02423 pa->list_last_len= len; 02424 02425 if(ptr->data && prop) { 02426 /* create list items */ 02427 RNA_PROP_BEGIN(ptr, itemptr, prop) { 02428 if(i >= pa->list_scroll && i<pa->list_scroll+items) 02429 list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop, prop_list); 02430 02431 i++; 02432 } 02433 RNA_PROP_END; 02434 } 02435 02436 /* add dummy buttons to fill space */ 02437 while(i < pa->list_scroll+items) { 02438 if(i >= pa->list_scroll) 02439 uiItemL(col, "", ICON_NONE); 02440 i++; 02441 } 02442 02443 /* add scrollbar */ 02444 if(len > items) { 02445 col= uiLayoutColumn(row, 0); 02446 uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, ""); 02447 } 02448 } 02449 } 02450 02451 /************************* Operator Search Template **************************/ 02452 02453 static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2) 02454 { 02455 wmOperatorType *ot= arg2; 02456 02457 if(ot) 02458 WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL); 02459 } 02460 02461 static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items) 02462 { 02463 GHashIterator *iter= WM_operatortype_iter(); 02464 02465 for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) { 02466 wmOperatorType *ot= BLI_ghashIterator_getValue(iter); 02467 02468 if(BLI_strcasestr(ot->name, str)) { 02469 if(WM_operator_poll((bContext*)C, ot)) { 02470 char name[256]; 02471 int len= strlen(ot->name); 02472 02473 /* display name for menu, can hold hotkey */ 02474 BLI_strncpy(name, ot->name, sizeof(name)); 02475 02476 /* check for hotkey */ 02477 if(len < sizeof(name)-6) { 02478 if (WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, TRUE, 02479 &name[len+1], sizeof(name)-len-1)) 02480 { 02481 name[len]= '|'; 02482 } 02483 } 02484 02485 if(0==uiSearchItemAdd(items, name, ot, 0)) 02486 break; 02487 } 02488 } 02489 } 02490 BLI_ghashIterator_free(iter); 02491 } 02492 02493 void uiTemplateOperatorSearch(uiLayout *layout) 02494 { 02495 uiBlock *block; 02496 uiBut *but; 02497 static char search[256]= ""; 02498 02499 block= uiLayoutGetBlock(layout); 02500 uiBlockSetCurLayout(block, layout); 02501 02502 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, ""); 02503 uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL); 02504 } 02505 02506 /************************* Running Jobs Template **************************/ 02507 02508 #define B_STOPRENDER 1 02509 #define B_STOPCAST 2 02510 #define B_STOPANIM 3 02511 #define B_STOPCOMPO 4 02512 #define B_STOPSEQ 5 02513 #define B_STOPCLIP 6 02514 02515 static void do_running_jobs(bContext *C, void *UNUSED(arg), int event) 02516 { 02517 switch(event) { 02518 case B_STOPRENDER: 02519 G.afbreek= 1; 02520 break; 02521 case B_STOPCAST: 02522 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL); 02523 break; 02524 case B_STOPANIM: 02525 WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL); 02526 break; 02527 case B_STOPCOMPO: 02528 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); 02529 break; 02530 case B_STOPSEQ: 02531 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); 02532 break; 02533 case B_STOPCLIP: 02534 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL); 02535 break; 02536 } 02537 } 02538 02539 void uiTemplateRunningJobs(uiLayout *layout, bContext *C) 02540 { 02541 bScreen *screen= CTX_wm_screen(C); 02542 wmWindowManager *wm= CTX_wm_manager(C); 02543 ScrArea *sa= CTX_wm_area(C); 02544 uiBlock *block; 02545 void *owner= NULL; 02546 int handle_event; 02547 02548 block= uiLayoutGetBlock(layout); 02549 uiBlockSetCurLayout(block, layout); 02550 02551 uiBlockSetHandleFunc(block, do_running_jobs, NULL); 02552 02553 if(sa->spacetype==SPACE_NODE) { 02554 if(WM_jobs_test(wm, sa)) 02555 owner = sa; 02556 handle_event= B_STOPCOMPO; 02557 } else if (sa->spacetype==SPACE_SEQ) { 02558 if(WM_jobs_test(wm, sa)) 02559 owner = sa; 02560 handle_event = B_STOPSEQ; 02561 } else if(sa->spacetype==SPACE_CLIP) { 02562 if(WM_jobs_test(wm, sa)) 02563 owner = sa; 02564 handle_event= B_STOPCLIP; 02565 } else { 02566 Scene *scene; 02567 /* another scene can be rendering too, for example via compositor */ 02568 for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next) 02569 if(WM_jobs_test(wm, scene)) 02570 break; 02571 owner = scene; 02572 handle_event= B_STOPRENDER; 02573 } 02574 02575 if(owner) { 02576 uiLayout *ui_abs; 02577 02578 ui_abs= uiLayoutAbsolute(layout, 0); 02579 (void)ui_abs; // UNUSED 02580 02581 uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, 02582 0, UI_UNIT_Y*0.1, UI_UNIT_X*0.8, UI_UNIT_Y*0.8, NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job")); 02583 uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner), 02584 UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress")); 02585 02586 uiLayoutRow(layout, 0); 02587 } 02588 if(WM_jobs_test(wm, screen)) 02589 uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, 02590 TIP_("Stop screencast")); 02591 if(screen->animtimer) 02592 uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, TIP_("Anim Player"), 0,0,100,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, 02593 TIP_("Stop animation playback")); 02594 } 02595 02596 /************************* Reports for Last Operator Template **************************/ 02597 02598 void uiTemplateReportsBanner(uiLayout *layout, bContext *C) 02599 { 02600 ReportList *reports = CTX_wm_reports(C); 02601 Report *report= BKE_reports_last_displayable(reports); 02602 ReportTimerInfo *rti; 02603 02604 uiLayout *ui_abs; 02605 uiBlock *block; 02606 uiBut *but; 02607 uiStyle *style= UI_GetStyle(); 02608 int width; 02609 int icon=0; 02610 02611 /* if the report display has timed out, don't show */ 02612 if (!reports->reporttimer) return; 02613 02614 rti= (ReportTimerInfo *)reports->reporttimer->customdata; 02615 02616 if (!rti || rti->widthfac==0.0f || !report) return; 02617 02618 ui_abs= uiLayoutAbsolute(layout, 0); 02619 block= uiLayoutGetBlock(ui_abs); 02620 02621 width = BLF_width(style->widget.uifont_id, report->message); 02622 width = MIN2(rti->widthfac*width, width); 02623 width = MAX2(width, 10); 02624 02625 /* make a box around the report to make it stand out */ 02626 uiBlockBeginAlign(block); 02627 but= uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X+10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); 02628 /* set the report's bg color in but->col - ROUNDBOX feature */ 02629 but->col[0]= FTOCHAR(rti->col[0]); 02630 but->col[1]= FTOCHAR(rti->col[1]); 02631 but->col[2]= FTOCHAR(rti->col[2]); 02632 but->col[3]= 255; 02633 02634 but= uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); 02635 but->col[0]= but->col[1]= but->col[2]= FTOCHAR(rti->greyscale); 02636 but->col[3]= 255; 02637 02638 uiBlockEndAlign(block); 02639 02640 02641 /* icon and report message on top */ 02642 if(report->type & RPT_ERROR_ALL) 02643 icon = ICON_ERROR; 02644 else if(report->type & RPT_WARNING_ALL) 02645 icon = ICON_ERROR; 02646 else if(report->type & RPT_INFO_ALL) 02647 icon = ICON_INFO; 02648 02649 /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report 02650 * to be shown instead of icon when appropriate... 02651 */ 02652 uiBlockSetEmboss(block, UI_EMBOSSN); 02653 02654 if (reports->list.first != reports->list.last) 02655 uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, TIP_("Click to see rest of reports in textblock: 'Recent Reports'")); 02656 else 02657 uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); 02658 02659 uiBlockSetEmboss(block, UI_EMBOSS); 02660 02661 uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); 02662 } 02663 02664 /********************************* Keymap *************************************/ 02665 02666 static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(unused)) 02667 { 02668 wmKeyMapItem *kmi= (wmKeyMapItem*)kmi_p; 02669 WM_keyconfig_update_tag(NULL, kmi); 02670 } 02671 02672 static void template_keymap_item_properties(uiLayout *layout, const char *title, PointerRNA *ptr) 02673 { 02674 uiLayout *flow; 02675 02676 uiItemS(layout); 02677 02678 if(title) 02679 uiItemL(layout, title, ICON_NONE); 02680 02681 flow= uiLayoutColumnFlow(layout, 2, 0); 02682 02683 RNA_STRUCT_BEGIN(ptr, prop) { 02684 int flag= RNA_property_flag(prop); 02685 02686 if(flag & PROP_HIDDEN) 02687 continue; 02688 02689 /* recurse for nested properties */ 02690 if(RNA_property_type(prop) == PROP_POINTER) { 02691 PointerRNA propptr= RNA_property_pointer_get(ptr, prop); 02692 const char *name= RNA_property_ui_name(prop); 02693 02694 if(propptr.data && RNA_struct_is_a(propptr.type, &RNA_OperatorProperties)) { 02695 template_keymap_item_properties(layout, name, &propptr); 02696 continue; 02697 } 02698 } 02699 02700 /* add property */ 02701 uiItemR(flow, ptr, RNA_property_identifier(prop), 0, NULL, ICON_NONE); 02702 } 02703 RNA_STRUCT_END; 02704 } 02705 02706 void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) 02707 { 02708 PointerRNA propptr= RNA_pointer_get(ptr, "properties"); 02709 02710 if(propptr.data) { 02711 uiBut *but= uiLayoutGetBlock(layout)->buttons.last; 02712 02713 template_keymap_item_properties(layout, NULL, &propptr); 02714 02715 /* attach callbacks to compensate for missing properties update, 02716 we don't know which keymap (item) is being modified there */ 02717 for(; but; but=but->next) 02718 uiButSetFunc(but, keymap_item_modified, ptr->data, NULL); 02719 } 02720 } 02721