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