Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface_templates.c
| Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | |||||
| #include "WM_types.h" | #include "WM_types.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "UI_interface_icons.h" | #include "UI_interface_icons.h" | ||||
| #include "interface_intern.h" | #include "interface_intern.h" | ||||
| #include "PIL_time.h" | #include "PIL_time.h" | ||||
| /* defines for templateID/TemplateSearch */ | |||||
| #define TEMPLATE_SEARCH_TEXTBUT_WIDTH (UI_UNIT_X * 6) | |||||
| #define TEMPLATE_SEARCH_TEXTBUT_HEIGHT UI_UNIT_Y | |||||
| void UI_template_fix_linking(void) | void UI_template_fix_linking(void) | ||||
| { | { | ||||
| } | } | ||||
| /** | |||||
| * Add a block button for the search menu for templateID and templateSearch. | |||||
| */ | |||||
| static void template_add_button_search_menu( | |||||
| const bContext *C, uiLayout *layout, uiBlock *block, | |||||
| PointerRNA *ptr, PropertyRNA *prop, | |||||
| uiBlockCreateFunc block_func, void *block_argN, const char * const tip, | |||||
| const bool use_previews, const bool editable) | |||||
| { | |||||
| PointerRNA active_ptr = RNA_property_pointer_get(ptr, prop); | |||||
| ID *id = (active_ptr.data && RNA_struct_is_ID(active_ptr.type)) ? active_ptr.data : NULL; | |||||
| const ID *idfrom = ptr->id.data; | |||||
| const StructRNA *type = active_ptr.type ? active_ptr.type : RNA_property_pointer_type(ptr, prop); | |||||
| uiBut *but; | |||||
| if (use_previews) { | |||||
| ARegion *region = CTX_wm_region(C); | |||||
| const bool use_big_size = (region->regiontype != RGN_TYPE_HEADER); /* silly check, could be more generic */ | |||||
| /* Ugly exception for screens here, drawing their preview in icon size looks ugly/useless */ | |||||
| const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR)); | |||||
| const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f); | |||||
| const short height = UI_UNIT_Y * (use_big_size ? 6: 1); | |||||
| but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, width, height, tip); | |||||
| if (use_preview_icon) { | |||||
| int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type); | |||||
| ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); | |||||
| } | |||||
| else { | |||||
| ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); | |||||
| UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); | |||||
| } | |||||
| if ((idfrom && idfrom->lib) || !editable) | |||||
| UI_but_flag_enable(but, UI_BUT_DISABLED); | |||||
| if (use_big_size) { | |||||
| uiLayoutRow(layout, true); | |||||
| } | |||||
| } | |||||
| else { | |||||
| but = uiDefBlockButN(block, block_func, block_argN, "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, tip); | |||||
| ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); | |||||
| if (id) { | |||||
| /* default dragging of icon for id browse buttons */ | |||||
| UI_but_drag_set_id(but, id); | |||||
| } | |||||
| UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); | |||||
| if ((idfrom && idfrom->lib) || !editable) | |||||
| UI_but_flag_enable(but, UI_BUT_DISABLED); | |||||
| } | |||||
| } | |||||
| static uiBlock *template_common_search_menu( | |||||
| const bContext *C, ARegion *region, | |||||
| uiButSearchFunc search_func, void *search_arg, | |||||
| uiButHandleFunc handle_func, void *active_item, | |||||
| const int preview_rows, const int preview_cols) | |||||
| { | |||||
| static char search[256]; | |||||
| wmWindow *win = CTX_wm_window(C); | |||||
| uiBlock *block; | |||||
| uiBut *but; | |||||
| /* clear initial search string, then all items show */ | |||||
| search[0] = 0; | |||||
| block = UI_block_begin(C, region, "_popup", UI_EMBOSS); | |||||
| UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); | |||||
| /* preview thumbnails */ | |||||
| if (preview_rows > 0 && preview_cols > 0) { | |||||
| const int w = 4 * U.widget_unit * preview_cols; | |||||
| const int h = 5 * U.widget_unit * preview_rows; | |||||
| /* fake button, it holds space for search items */ | |||||
| uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL); | |||||
| but = uiDefSearchBut( | |||||
| block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y, | |||||
| preview_rows, preview_cols, ""); | |||||
| } | |||||
| /* list view */ | |||||
| else { | |||||
| const int searchbox_width = UI_searchbox_size_x(); | |||||
| const int searchbox_height = UI_searchbox_size_y(); | |||||
| /* fake button, it holds space for search items */ | |||||
| uiDefBut( | |||||
| block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, | |||||
| NULL, 0, 0, 0, 0, NULL); | |||||
| but = uiDefSearchBut( | |||||
| block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, | |||||
| searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); | |||||
| } | |||||
| UI_but_func_search_set( | |||||
| but, ui_searchbox_create_generic, search_func, | |||||
| search_arg, handle_func, active_item); | |||||
| UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); | |||||
| UI_block_direction_set(block, UI_DIR_DOWN); | |||||
| /* give search-field focus */ | |||||
| UI_but_focus_on_enter_event(win, but); | |||||
| /* this type of search menu requires undo */ | |||||
| but->flag |= UI_BUT_UNDO; | |||||
| return block; | |||||
| } | |||||
| /********************** Header Template *************************/ | /********************** Header Template *************************/ | ||||
| void uiTemplateHeader(uiLayout *layout, bContext *C) | void uiTemplateHeader(uiLayout *layout, bContext *C) | ||||
| { | { | ||||
| uiBlock *block; | uiBlock *block; | ||||
| block = uiLayoutAbsoluteBlock(layout); | block = uiLayoutAbsoluteBlock(layout); | ||||
| ED_area_header_switchbutton(C, block, 0); | ED_area_header_switchbutton(C, block, 0); | ||||
| ▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | if (!((flag & PROP_ID_SELF_CHECK) && id == id_from)) { | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* ID Search browse menu, open */ | /* ID Search browse menu, open */ | ||||
| static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) | static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) | ||||
| { | { | ||||
| static char search[256]; | |||||
| static TemplateID template; | static TemplateID template; | ||||
| PointerRNA idptr; | PointerRNA active_item_ptr; | ||||
| wmWindow *win = CTX_wm_window(C); | |||||
| uiBlock *block; | |||||
| uiBut *but; | |||||
| /* clear initial search string, then all items show */ | |||||
| search[0] = 0; | |||||
| /* arg_litem is malloced, can be freed by parent button */ | /* arg_litem is malloced, can be freed by parent button */ | ||||
| template = *((TemplateID *)arg_litem); | template = *((TemplateID *)arg_litem); | ||||
| active_item_ptr = RNA_property_pointer_get(&template.ptr, template.prop); | |||||
| /* get active id for showing first item */ | return template_common_search_menu( | ||||
| idptr = RNA_property_pointer_get(&template.ptr, template.prop); | C, ar, id_search_cb, &template, id_search_call_cb, active_item_ptr.data, | ||||
| template.prv_rows, template.prv_cols); | |||||
| block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); | |||||
| UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); | |||||
| /* preview thumbnails */ | |||||
| if (template.prv_rows > 0 && template.prv_cols > 0) { | |||||
| int w = 4 * U.widget_unit * template.prv_cols; | |||||
| int h = 5 * U.widget_unit * template.prv_rows; | |||||
| /* fake button, it holds space for search items */ | |||||
| uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL); | |||||
| but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y, | |||||
| template.prv_rows, template.prv_cols, ""); | |||||
| UI_but_func_search_set( | |||||
| but, ui_searchbox_create_generic, id_search_cb, | |||||
| &template, id_search_call_cb, idptr.data); | |||||
| } | |||||
| /* list view */ | |||||
| else { | |||||
| const int searchbox_width = UI_searchbox_size_x(); | |||||
| const int searchbox_height = UI_searchbox_size_y(); | |||||
| /* fake button, it holds space for search items */ | |||||
| uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 15, searchbox_width, searchbox_height, NULL, 0, 0, 0, 0, NULL); | |||||
| but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); | |||||
| UI_but_func_search_set( | |||||
| but, ui_searchbox_create_generic, id_search_cb, | |||||
| &template, id_search_call_cb, idptr.data); | |||||
| } | |||||
| UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); | |||||
| UI_block_direction_set(block, UI_DIR_DOWN); | |||||
| /* give search-field focus */ | |||||
| UI_but_focus_on_enter_event(win, but); | |||||
| /* this type of search menu requires undo */ | |||||
| but->flag |= UI_BUT_UNDO; | |||||
| return block; | |||||
| } | } | ||||
| /************************ ID Template ***************************/ | /************************ ID Template ***************************/ | ||||
| /* This is for browsing and editing the ID-blocks used */ | /* This is for browsing and editing the ID-blocks used */ | ||||
| /* for new/open operators */ | /* for new/open operators */ | ||||
| void UI_context_active_but_prop_get_templateID( | void UI_context_active_but_prop_get_templateID( | ||||
| bContext *C, | bContext *C, | ||||
| ▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | case UI_ID_ALONE: | ||||
| break; | break; | ||||
| #if 0 | #if 0 | ||||
| case UI_ID_AUTO_NAME: | case UI_ID_AUTO_NAME: | ||||
| break; | break; | ||||
| #endif | #endif | ||||
| } | } | ||||
| } | } | ||||
| static const char *template_id_browse_tip(StructRNA *type) | static const char *template_id_browse_tip(const StructRNA *type) | ||||
| { | { | ||||
| if (type) { | if (type) { | ||||
| switch (RNA_type_to_ID_code(type)) { | switch (RNA_type_to_ID_code(type)) { | ||||
| case ID_SCE: return N_("Browse Scene to be linked"); | case ID_SCE: return N_("Browse Scene to be linked"); | ||||
| case ID_OB: return N_("Browse Object to be linked"); | case ID_OB: return N_("Browse Object to be linked"); | ||||
| case ID_ME: return N_("Browse Mesh Data to be linked"); | case ID_ME: return N_("Browse Mesh Data to be linked"); | ||||
| case ID_CU: return N_("Browse Curve Data to be linked"); | case ID_CU: return N_("Browse Curve Data to be linked"); | ||||
| case ID_MB: return N_("Browse Metaball Data to be linked"); | case ID_MB: return N_("Browse Metaball Data to be linked"); | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | static void template_ID( | ||||
| const char *newop, const char *openop, const char *unlinkop) | const char *newop, const char *openop, const char *unlinkop) | ||||
| { | { | ||||
| uiBut *but; | uiBut *but; | ||||
| uiBlock *block; | uiBlock *block; | ||||
| PointerRNA idptr; | PointerRNA idptr; | ||||
| // ListBase *lb; // UNUSED | // ListBase *lb; // UNUSED | ||||
| ID *id, *idfrom; | ID *id, *idfrom; | ||||
| const bool editable = RNA_property_editable(&template->ptr, template->prop); | const bool editable = RNA_property_editable(&template->ptr, template->prop); | ||||
| const bool use_previews = template->preview = (flag & UI_ID_PREVIEWS) != 0; | |||||
| idptr = RNA_property_pointer_get(&template->ptr, template->prop); | idptr = RNA_property_pointer_get(&template->ptr, template->prop); | ||||
| id = idptr.data; | id = idptr.data; | ||||
| idfrom = template->ptr.id.data; | idfrom = template->ptr.id.data; | ||||
| // lb = template->idlb; | // lb = template->idlb; | ||||
| block = uiLayoutGetBlock(layout); | block = uiLayoutGetBlock(layout); | ||||
| UI_block_align_begin(block); | UI_block_align_begin(block); | ||||
| if (idptr.type) | if (idptr.type) | ||||
| type = idptr.type; | type = idptr.type; | ||||
| if (flag & UI_ID_PREVIEWS) { | if (flag & UI_ID_BROWSE) { | ||||
| ARegion *region = CTX_wm_region(C); | template_add_button_search_menu( | ||||
| const bool use_big_size = (region->regiontype != RGN_TYPE_HEADER); /* silly check, could be more generic */ | C, layout, block, &template->ptr, template->prop, | ||||
| /* Ugly exception for screens here, drawing their preview in icon size looks ugly/useless */ | id_search_menu, MEM_dupallocN(template), TIP_(template_id_browse_tip(type)), | ||||
| const bool use_preview_icon = use_big_size || (id && (GS(id->name) != ID_SCR)); | use_previews, editable); | ||||
| const short width = UI_UNIT_X * (use_big_size ? 6 : 1.6f); | |||||
| const short height = UI_UNIT_Y * (use_big_size ? 6: 1); | |||||
| template->preview = true; | |||||
| but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, width, height, | |||||
| TIP_(template_id_browse_tip(type))); | |||||
| if (use_preview_icon) { | |||||
| int icon = id ? ui_id_icon_get(C, id, use_big_size) : RNA_struct_ui_icon(type); | |||||
| ui_def_but_icon(but, icon, UI_HAS_ICON | UI_BUT_ICON_PREVIEW); | |||||
| } | |||||
| else { | |||||
| ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); | |||||
| UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); | |||||
| } | |||||
| if ((idfrom && idfrom->lib) || !editable) | |||||
| UI_but_flag_enable(but, UI_BUT_DISABLED); | |||||
| if (use_big_size) { | |||||
| uiLayoutRow(layout, true); | |||||
| } | |||||
| } | |||||
| else if (flag & UI_ID_BROWSE) { | |||||
| but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 1.6, UI_UNIT_Y, | |||||
| TIP_(template_id_browse_tip(type))); | |||||
| ui_def_but_icon(but, RNA_struct_ui_icon(type), UI_HAS_ICON); | |||||
| /* default dragging of icon for id browse buttons */ | |||||
| UI_but_drag_set_id(but, id); | |||||
| UI_but_drawflag_enable(but, UI_BUT_ICON_LEFT); | |||||
| if ((idfrom && idfrom->lib) || !editable) | |||||
| UI_but_flag_enable(but, UI_BUT_DISABLED); | |||||
| } | } | ||||
| /* text button with name */ | /* text button with name */ | ||||
| if (id) { | if (id) { | ||||
| char name[UI_MAX_NAME_STR]; | char name[UI_MAX_NAME_STR]; | ||||
| const bool user_alert = (id->us <= 0); | const bool user_alert = (id->us <= 0); | ||||
| //text_idbutton(id, name); | //text_idbutton(id, name); | ||||
| name[0] = '\0'; | name[0] = '\0'; | ||||
| but = uiDefButR(block, UI_BTYPE_TEXT, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, | but = uiDefButR( | ||||
| block, UI_BTYPE_TEXT, 0, name, 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT, | |||||
| &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); | &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); | ||||
| UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); | UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME)); | ||||
| if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT); | if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT); | ||||
| if (id->lib) { | if (id->lib) { | ||||
| if (id->tag & LIB_TAG_INDIRECT) { | if (id->tag & LIB_TAG_INDIRECT) { | ||||
| but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, | but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, | ||||
| NULL, 0, 0, 0, 0, TIP_("Indirect library data-block, cannot change")); | NULL, 0, 0, 0, 0, TIP_("Indirect library data-block, cannot change")); | ||||
| UI_but_flag_enable(but, UI_BUT_DISABLED); | UI_but_flag_enable(but, UI_BUT_DISABLED); | ||||
| ▲ Show 20 Lines • Show All 269 Lines • ▼ Show 20 Lines | void uiTemplateAnyID( | ||||
| /* ID-Block Selector - just use pointer widget... */ | /* ID-Block Selector - just use pointer widget... */ | ||||
| sub = uiLayoutRow(row, true); /* HACK: special group to counteract the effects of the previous */ | sub = uiLayoutRow(row, true); /* HACK: special group to counteract the effects of the previous */ | ||||
| uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); /* enum, which now pushes everything too far right */ | uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_EXPAND); /* enum, which now pushes everything too far right */ | ||||
| uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE); | uiItemFullR(sub, ptr, propID, 0, 0, 0, "", ICON_NONE); | ||||
| } | } | ||||
| /********************* Search Template ********************/ | |||||
| typedef struct TemplateSearch { | |||||
| uiRNACollectionSearch search_data; | |||||
| bool use_previews; | |||||
| int preview_rows, preview_cols; | |||||
| } TemplateSearch; | |||||
| static void template_search_handle_cb(bContext *C, void *arg_template, void *item) | |||||
| { | |||||
| TemplateSearch *template_search = arg_template; | |||||
| uiRNACollectionSearch *coll_search = &template_search->search_data; | |||||
| StructRNA *type = RNA_property_pointer_type(&coll_search->target_ptr, coll_search->target_prop); | |||||
| PointerRNA item_ptr; | |||||
| RNA_pointer_create(NULL, type, item, &item_ptr); | |||||
| RNA_property_pointer_set(&coll_search->target_ptr, coll_search->target_prop, item_ptr); | |||||
| RNA_property_update(C, &coll_search->target_ptr, coll_search->target_prop); | |||||
| } | |||||
| static uiBlock *template_search_menu(bContext *C, ARegion *region, void *arg_template) | |||||
| { | |||||
| static TemplateSearch template_search; | |||||
| PointerRNA active_ptr; | |||||
| /* arg_template is malloced, can be freed by parent button */ | |||||
| template_search = *((TemplateSearch *)arg_template); | |||||
| active_ptr = RNA_property_pointer_get(&template_search.search_data.target_ptr, | |||||
| template_search.search_data.target_prop); | |||||
| return template_common_search_menu( | |||||
| C, region, ui_rna_collection_search_cb, &template_search, | |||||
| template_search_handle_cb, active_ptr.data, | |||||
| template_search.preview_rows, template_search.preview_cols); | |||||
| } | |||||
| static void template_search_add_button_searchmenu( | |||||
| const bContext *C, uiLayout *layout, uiBlock *block, | |||||
| TemplateSearch *template_search, const bool editable) | |||||
| { | |||||
| const char *ui_description = RNA_property_ui_description(template_search->search_data.target_prop); | |||||
| template_add_button_search_menu( | |||||
| C, layout, block, | |||||
| &template_search->search_data.target_ptr, template_search->search_data.target_prop, | |||||
| template_search_menu, MEM_dupallocN(template_search), ui_description, | |||||
| template_search->use_previews, editable); | |||||
| } | |||||
| static void template_search_add_button_name( | |||||
| uiBlock *block, PointerRNA *active_ptr, const StructRNA *type) | |||||
| { | |||||
| uiDefAutoButR( | |||||
| block, active_ptr, RNA_struct_name_property(type), 0, "", ICON_NONE, | |||||
| 0, 0, TEMPLATE_SEARCH_TEXTBUT_WIDTH, TEMPLATE_SEARCH_TEXTBUT_HEIGHT); | |||||
| } | |||||
| static void template_search_add_button_operator( | |||||
| uiBlock *block, const char * const operator_name, | |||||
| const int opcontext, const int icon, const bool editable) | |||||
| { | |||||
| if (!operator_name) { | |||||
| return; | |||||
| } | |||||
| uiBut *but = uiDefIconButO( | |||||
| block, UI_BTYPE_BUT, operator_name, opcontext, icon, | |||||
| 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); | |||||
| if (!editable) { | |||||
| UI_but_drawflag_enable(but, UI_BUT_DISABLED); | |||||
| } | |||||
| } | |||||
| static void template_search_buttons( | |||||
| const bContext *C, uiLayout *layout, TemplateSearch *template_search, | |||||
| const char *newop, const char *unlinkop) | |||||
| { | |||||
| uiBlock *block = uiLayoutGetBlock(layout); | |||||
| uiRNACollectionSearch *search_data = &template_search->search_data; | |||||
| StructRNA *type = RNA_property_pointer_type(&search_data->target_ptr, search_data->target_prop); | |||||
| const bool editable = RNA_property_editable(&search_data->target_ptr, search_data->target_prop); | |||||
| PointerRNA active_ptr = RNA_property_pointer_get(&search_data->target_ptr, search_data->target_prop); | |||||
| if (active_ptr.type) { | |||||
| /* can only get correct type when there is an active item */ | |||||
| type = active_ptr.type; | |||||
| } | |||||
| uiLayoutRow(layout, true); | |||||
| UI_block_align_begin(block); | |||||
| template_search_add_button_searchmenu(C, layout, block, template_search, editable); | |||||
| template_search_add_button_name(block, &active_ptr, type); | |||||
| template_search_add_button_operator(block, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, editable); | |||||
| template_search_add_button_operator(block, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, editable); | |||||
| UI_block_align_end(block); | |||||
| } | |||||
| static PropertyRNA *template_search_get_searchprop( | |||||
| PointerRNA *targetptr, PropertyRNA *targetprop, | |||||
| PointerRNA *searchptr, const char * const searchpropname) | |||||
| { | |||||
| PropertyRNA *searchprop; | |||||
| if (searchptr && !searchptr->data) { | |||||
| searchptr = NULL; | |||||
| } | |||||
| if (!searchptr && !searchpropname) { | |||||
| /* both NULL means we don't use a custom rna collection to search in */ | |||||
| } | |||||
| else if (!searchptr && searchpropname) { | |||||
| RNA_warning("searchpropname defined (%s) but searchptr is missing", searchpropname); | |||||
| } | |||||
| else if (searchptr && !searchpropname) { | |||||
| RNA_warning("searchptr defined (%s) but searchpropname is missing", RNA_struct_identifier(searchptr->type)); | |||||
| } | |||||
| else if (!(searchprop = RNA_struct_find_property(searchptr, searchpropname))) { | |||||
| RNA_warning("search collection property not found: %s.%s", | |||||
| RNA_struct_identifier(searchptr->type), searchpropname); | |||||
| } | |||||
| else if (RNA_property_type(searchprop) != PROP_COLLECTION) { | |||||
| RNA_warning("search collection property is not a collection type: %s.%s", | |||||
| RNA_struct_identifier(searchptr->type), searchpropname); | |||||
| } | |||||
| /* check if searchprop has same type as targetprop */ | |||||
| else if (RNA_property_pointer_type(searchptr, searchprop) != RNA_property_pointer_type(targetptr, targetprop)) { | |||||
| RNA_warning("search collection items from %s.%s are not of type %s", | |||||
| RNA_struct_identifier(searchptr->type), searchpropname, | |||||
| RNA_struct_identifier(RNA_property_pointer_type(targetptr, targetprop))); | |||||
| } | |||||
| else { | |||||
| return searchprop; | |||||
| } | |||||
| return NULL; | |||||
| } | |||||
| static TemplateSearch *template_search_setup( | |||||
| PointerRNA *ptr, const char * const propname, | |||||
| PointerRNA *searchptr, const char * const searchpropname) | |||||
| { | |||||
| TemplateSearch *template_search; | |||||
| PropertyRNA *prop, *searchprop; | |||||
| prop = RNA_struct_find_property(ptr, propname); | |||||
| if (!prop || RNA_property_type(prop) != PROP_POINTER) { | |||||
| RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); | |||||
| return NULL; | |||||
| } | |||||
| searchprop = template_search_get_searchprop(ptr, prop, searchptr, searchpropname); | |||||
| template_search = MEM_callocN(sizeof(*template_search), __func__); | |||||
| template_search->search_data.target_ptr = *ptr; | |||||
| template_search->search_data.target_prop = prop; | |||||
| template_search->search_data.search_ptr = *searchptr; | |||||
| template_search->search_data.search_prop = searchprop; | |||||
| template_search->search_data.but_changed = SET_INT_IN_POINTER(false); | |||||
| return template_search; | |||||
| } | |||||
| /** | |||||
| * Search menu to pick an item from a collection. | |||||
| * A version of uiTemplateID that works for non-ID types. | |||||
| */ | |||||
| void uiTemplateSearch( | |||||
| uiLayout *layout, bContext *C, | |||||
| PointerRNA *ptr, const char *propname, | |||||
| PointerRNA *searchptr, const char *searchpropname, | |||||
| const char *newop, const char *unlinkop) | |||||
| { | |||||
| TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname); | |||||
| template_search_buttons(C, layout, template_search, newop, unlinkop); | |||||
| MEM_freeN(template_search); | |||||
| } | |||||
| void uiTemplateSearchPreview( | |||||
| uiLayout *layout, bContext *C, | |||||
| PointerRNA *ptr, const char *propname, | |||||
| PointerRNA *searchptr, const char *searchpropname, | |||||
| const char *newop, const char *unlinkop, | |||||
| const int rows, const int cols) | |||||
| { | |||||
| TemplateSearch *template_search = template_search_setup(ptr, propname, searchptr, searchpropname); | |||||
| template_search->use_previews = true; | |||||
| template_search->preview_rows = rows; | |||||
| template_search->preview_cols = cols; | |||||
| template_search_buttons(C, layout, template_search, newop, unlinkop); | |||||
| MEM_freeN(template_search); | |||||
| } | |||||
| /********************* RNA Path Builder Template ********************/ | /********************* RNA Path Builder Template ********************/ | ||||
| /* ---------- */ | /* ---------- */ | ||||
| /** | /** | ||||
| * This is creating/editing RNA-Paths | * This is creating/editing RNA-Paths | ||||
| * | * | ||||
| * - ptr: struct which holds the path property | * - ptr: struct which holds the path property | ||||
| ▲ Show 20 Lines • Show All 3,241 Lines • Show Last 20 Lines | |||||