Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/interface_templates.c
| Show First 20 Lines • Show All 107 Lines • ▼ Show 20 Lines | |||||
| /********************** Search Callbacks *************************/ | /********************** Search Callbacks *************************/ | ||||
| typedef struct TemplateID { | typedef struct TemplateID { | ||||
| PointerRNA ptr; | PointerRNA ptr; | ||||
| PropertyRNA *prop; | PropertyRNA *prop; | ||||
| ListBase *idlb; | ListBase *idlb; | ||||
| short idcode; | |||||
| short filter; | |||||
| int prv_rows, prv_cols; | int prv_rows, prv_cols; | ||||
| bool preview; | bool preview; | ||||
| } TemplateID; | } TemplateID; | ||||
| /* Search browse menu, assign */ | /* Search browse menu, assign */ | ||||
| static void id_search_call_cb(bContext *C, void *arg_template, void *item) | static void id_search_call_cb(bContext *C, void *arg_template, void *item) | ||||
| { | { | ||||
| TemplateID *template_ui = (TemplateID *)arg_template; | TemplateID *template_ui = (TemplateID *)arg_template; | ||||
| /* ID */ | /* ID */ | ||||
| if (item) { | if (item) { | ||||
| PointerRNA idptr; | PointerRNA idptr; | ||||
| RNA_id_pointer_create(item, &idptr); | RNA_id_pointer_create(item, &idptr); | ||||
| RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr); | RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr); | ||||
| RNA_property_update(C, &template_ui->ptr, template_ui->prop); | RNA_property_update(C, &template_ui->ptr, template_ui->prop); | ||||
| } | } | ||||
| } | } | ||||
| /* ID Search browse menu, do the search */ | static bool id_search_add( | ||||
| static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items) | const bContext *C, TemplateID *template_ui, | ||||
| const int flag, const char *str, uiSearchItems *items, | |||||
| ID *id) | |||||
| { | { | ||||
| TemplateID *template_ui = (TemplateID *)arg_template; | ID *id_from = template_ui->ptr.id.data; | ||||
| ListBase *lb = template_ui->idlb; | |||||
| ID *id, *id_from = template_ui->ptr.id.data; | |||||
| int iconid; | |||||
| int flag = RNA_property_flag(template_ui->prop); | |||||
| /* ID listbase */ | |||||
| for (id = lb->first; id; id = id->next) { | |||||
| if (!((flag & PROP_ID_SELF_CHECK) && id == id_from)) { | if (!((flag & PROP_ID_SELF_CHECK) && id == id_from)) { | ||||
| /* use filter */ | /* use filter */ | ||||
| if (RNA_property_type(template_ui->prop) == PROP_POINTER) { | if (RNA_property_type(template_ui->prop) == PROP_POINTER) { | ||||
| PointerRNA ptr; | PointerRNA ptr; | ||||
| RNA_id_pointer_create(id, &ptr); | RNA_id_pointer_create(id, &ptr); | ||||
| if (RNA_property_pointer_poll(&template_ui->ptr, template_ui->prop, &ptr) == 0) | if (RNA_property_pointer_poll(&template_ui->ptr, template_ui->prop, &ptr) == 0) { | ||||
| continue; | return true; | ||||
| } | |||||
| } | } | ||||
| /* hide dot-datablocks, but only if filter does not force it visible */ | /* hide dot-datablocks, but only if filter does not force it visible */ | ||||
| if (U.uiflag & USER_HIDE_DOT) | if (U.uiflag & USER_HIDE_DOT) { | ||||
| if ((id->name[2] == '.') && (str[0] != '.')) | if ((id->name[2] == '.') && (str[0] != '.')) { | ||||
| continue; | return true; | ||||
| } | |||||
| } | |||||
| if (*str == '\0' || BLI_strcasestr(id->name + 2, str)) { | if (*str == '\0' || BLI_strcasestr(id->name + 2, str)) { | ||||
| /* +1 is needed because BKE_id_ui_prefix used 3 letter prefix | /* +1 is needed because BKE_id_ui_prefix used 3 letter prefix | ||||
| * followed by ID_NAME-2 characters from id->name | * followed by ID_NAME-2 characters from id->name | ||||
| */ | */ | ||||
| char name_ui[MAX_ID_NAME + 1]; | char name_ui[MAX_ID_NAME + 1]; | ||||
| BKE_id_ui_prefix(name_ui, id); | BKE_id_ui_prefix(name_ui, id); | ||||
| iconid = ui_id_icon_get(C, id, template_ui->preview); | int iconid = ui_id_icon_get(C, id, template_ui->preview); | ||||
| if (false == UI_search_item_add(items, name_ui, id, iconid)) | if (false == UI_search_item_add(items, name_ui, id, iconid)) { | ||||
| return false; | |||||
| } | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| /* ID Search browse menu, do the search */ | |||||
| static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items) | |||||
| { | |||||
| TemplateID *template_ui = (TemplateID *)arg_template; | |||||
| ListBase *lb = template_ui->idlb; | |||||
| ID *id; | |||||
| int flag = RNA_property_flag(template_ui->prop); | |||||
| /* ID listbase */ | |||||
| for (id = lb->first; id; id = id->next) { | |||||
| if (!id_search_add(C, template_ui, flag, str, items, id)) { | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * A version of 'id_search_cb' that lists scene objects. | |||||
| */ | |||||
| static void id_search_cb_objects_from_scene(const bContext *C, void *arg_template, const char *str, uiSearchItems *items) | |||||
| { | |||||
| TemplateID *template_ui = (TemplateID *)arg_template; | |||||
| Scene *scene = NULL; | |||||
| ID *id_from = template_ui->ptr.id.data; | |||||
| if (id_from && GS(id_from->name) == ID_SCE) { | |||||
| scene = (Scene *)id_from; | |||||
| } | |||||
| else { | |||||
| scene = CTX_data_scene(C); | |||||
| } | |||||
| int flag = RNA_property_flag(template_ui->prop); | |||||
| for (Base *base = scene->base.first; base; base = base->next) { | |||||
| if (!id_search_add(C, template_ui, flag, str, items, &base->object->id)) { | |||||
| break; | |||||
| } | |||||
| } | |||||
campbellbarton: Note that the order here won't be alphabetical,
best use this loop to tag, then loop over all… | |||||
| } | } | ||||
| /* 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 char search[256]; | ||||
| static TemplateID template_ui; | static TemplateID template_ui; | ||||
| PointerRNA idptr; | PointerRNA idptr; | ||||
| wmWindow *win = CTX_wm_window(C); | wmWindow *win = CTX_wm_window(C); | ||||
| uiBlock *block; | uiBlock *block; | ||||
| uiBut *but; | uiBut *but; | ||||
| void (*id_search_cb_p)(const bContext *, void *, const char *, uiSearchItems *) = id_search_cb; | |||||
| /* clear initial search string, then all items show */ | /* clear initial search string, then all items show */ | ||||
| search[0] = 0; | search[0] = 0; | ||||
| /* arg_litem is malloced, can be freed by parent button */ | /* arg_litem is malloced, can be freed by parent button */ | ||||
| template_ui = *((TemplateID *)arg_litem); | template_ui = *((TemplateID *)arg_litem); | ||||
| /* get active id for showing first item */ | /* get active id for showing first item */ | ||||
| idptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop); | idptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop); | ||||
| if (template_ui.filter) { | |||||
| /* Currently only used for objects. */ | |||||
| if (template_ui.idcode == ID_OB) { | |||||
| if (template_ui.filter == UI_TEMPLATE_ID_FILTER_AVAILABLE) { | |||||
| id_search_cb_p = id_search_cb_objects_from_scene; | |||||
| } | |||||
| } | |||||
| } | |||||
| block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); | block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); | ||||
| UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); | UI_block_flag_enable(block, UI_BLOCK_LOOP | UI_BLOCK_SEARCH_MENU); | ||||
| /* preview thumbnails */ | /* preview thumbnails */ | ||||
| if (template_ui.prv_rows > 0 && template_ui.prv_cols > 0) { | if (template_ui.prv_rows > 0 && template_ui.prv_cols > 0) { | ||||
| int w = 4 * U.widget_unit * template_ui.prv_cols; | int w = 4 * U.widget_unit * template_ui.prv_cols; | ||||
| int h = 5 * U.widget_unit * template_ui.prv_rows; | int h = 5 * U.widget_unit * template_ui.prv_rows; | ||||
| /* fake button, it holds space for search items */ | /* fake button, it holds space for search items */ | ||||
| uiDefBut(block, UI_BTYPE_LABEL, 0, "", 10, 26, w, h, NULL, 0, 0, 0, 0, NULL); | 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, | but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, UI_UNIT_Y, | ||||
| template_ui.prv_rows, template_ui.prv_cols, ""); | template_ui.prv_rows, template_ui.prv_cols, ""); | ||||
| UI_but_func_search_set( | UI_but_func_search_set( | ||||
| but, ui_searchbox_create_generic, id_search_cb, | but, ui_searchbox_create_generic, id_search_cb_p, | ||||
| &template_ui, id_search_call_cb, idptr.data); | &template_ui, id_search_call_cb, idptr.data); | ||||
| } | } | ||||
| /* list view */ | /* list view */ | ||||
| else { | else { | ||||
| const int searchbox_width = UI_searchbox_size_x(); | const int searchbox_width = UI_searchbox_size_x(); | ||||
| const int searchbox_height = UI_searchbox_size_y(); | const int searchbox_height = UI_searchbox_size_y(); | ||||
| /* fake button, it holds space for search items */ | /* 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); | 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, ""); | but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, searchbox_width, UI_UNIT_Y - 1, 0, 0, ""); | ||||
| UI_but_func_search_set( | UI_but_func_search_set( | ||||
| but, ui_searchbox_create_generic, id_search_cb, | but, ui_searchbox_create_generic, id_search_cb_p, | ||||
| &template_ui, id_search_call_cb, idptr.data); | &template_ui, id_search_call_cb, idptr.data); | ||||
| } | } | ||||
| UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); | UI_block_bounds_set_normal(block, 0.3f * U.widget_unit); | ||||
| UI_block_direction_set(block, UI_DIR_DOWN); | UI_block_direction_set(block, UI_DIR_DOWN); | ||||
| /* give search-field focus */ | /* give search-field focus */ | ||||
| ▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | static const char *template_id_context(StructRNA *type) | ||||
| if (type) { | if (type) { | ||||
| return BKE_idcode_to_translation_context(RNA_type_to_ID_code(type)); | return BKE_idcode_to_translation_context(RNA_type_to_ID_code(type)); | ||||
| } | } | ||||
| return BLT_I18NCONTEXT_DEFAULT; | return BLT_I18NCONTEXT_DEFAULT; | ||||
| } | } | ||||
| #endif | #endif | ||||
| static void template_ID( | static void template_ID( | ||||
| bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, short idcode, int flag, | bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, int flag, | ||||
| 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_ui->ptr, template_ui->prop); | const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop); | ||||
| ▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | if (id && (flag & UI_ID_DELETE)) { | ||||
| if (but) { | if (but) { | ||||
| if ((idfrom && idfrom->lib) || !editable) { | if ((idfrom && idfrom->lib) || !editable) { | ||||
| UI_but_flag_enable(but, UI_BUT_DISABLED); | UI_but_flag_enable(but, UI_BUT_DISABLED); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (idcode == ID_TE) | if (template_ui->idcode == ID_TE) { | ||||
| uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop); | uiTemplateTextureShow(layout, C, &template_ui->ptr, template_ui->prop); | ||||
| } | |||||
| UI_block_align_end(block); | UI_block_align_end(block); | ||||
| } | } | ||||
| static void ui_template_id( | static void ui_template_id( | ||||
| uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, | 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) | const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols, int filter) | ||||
| { | { | ||||
| TemplateID *template_ui; | TemplateID *template_ui; | ||||
| PropertyRNA *prop; | PropertyRNA *prop; | ||||
| StructRNA *type; | StructRNA *type; | ||||
| short idcode; | short idcode; | ||||
| prop = RNA_struct_find_property(ptr, propname); | prop = RNA_struct_find_property(ptr, propname); | ||||
| if (!prop || RNA_property_type(prop) != PROP_POINTER) { | if (!prop || RNA_property_type(prop) != PROP_POINTER) { | ||||
| RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); | RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname); | ||||
| return; | return; | ||||
| } | } | ||||
| template_ui = MEM_callocN(sizeof(TemplateID), "TemplateID"); | template_ui = MEM_callocN(sizeof(TemplateID), "TemplateID"); | ||||
| template_ui->ptr = *ptr; | template_ui->ptr = *ptr; | ||||
| template_ui->prop = prop; | template_ui->prop = prop; | ||||
| template_ui->prv_rows = prv_rows; | template_ui->prv_rows = prv_rows; | ||||
| template_ui->prv_cols = prv_cols; | template_ui->prv_cols = prv_cols; | ||||
| if ((flag & UI_ID_PIN) == 0) { | |||||
| template_ui->filter = filter; | |||||
| } | |||||
| else { | |||||
| template_ui->filter = 0; | |||||
| } | |||||
| if (newop) | if (newop) | ||||
| flag |= UI_ID_ADD_NEW; | flag |= UI_ID_ADD_NEW; | ||||
| if (openop) | if (openop) | ||||
| flag |= UI_ID_OPEN; | flag |= UI_ID_OPEN; | ||||
| type = RNA_property_pointer_type(ptr, prop); | type = RNA_property_pointer_type(ptr, prop); | ||||
| idcode = RNA_type_to_ID_code(type); | idcode = RNA_type_to_ID_code(type); | ||||
| template_ui->idcode = idcode; | |||||
| template_ui->idlb = which_libbase(CTX_data_main(C), idcode); | template_ui->idlb = which_libbase(CTX_data_main(C), idcode); | ||||
| /* create UI elements for this template | /* create UI elements for this template | ||||
| * - template_ID makes a copy of the template data and assigns it to the relevant buttons | * - template_ID makes a copy of the template data and assigns it to the relevant buttons | ||||
| */ | */ | ||||
| if (template_ui->idlb) { | if (template_ui->idlb) { | ||||
| uiLayoutRow(layout, true); | uiLayoutRow(layout, true); | ||||
| template_ID(C, layout, template_ui, type, idcode, flag, newop, openop, unlinkop); | template_ID(C, layout, template_ui, type, flag, newop, openop, unlinkop); | ||||
| } | } | ||||
| MEM_freeN(template_ui); | MEM_freeN(template_ui); | ||||
| } | } | ||||
| void uiTemplateID( | void uiTemplateID( | ||||
| uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, | uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, | ||||
| const char *openop, const char *unlinkop) | const char *openop, const char *unlinkop, int filter) | ||||
| { | { | ||||
| ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, | ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, | ||||
| UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0); | UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE, 0, 0, filter); | ||||
| } | } | ||||
| void uiTemplateIDBrowse( | void uiTemplateIDBrowse( | ||||
| uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, | uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, | ||||
| const char *openop, const char *unlinkop) | const char *openop, const char *unlinkop, int filter) | ||||
| { | { | ||||
| ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0); | ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE | UI_ID_RENAME, 0, 0, filter); | ||||
| } | } | ||||
| void uiTemplateIDPreview( | void uiTemplateIDPreview( | ||||
| uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, | uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, | ||||
| const char *openop, const char *unlinkop, int rows, int cols) | const char *openop, const char *unlinkop, int rows, int cols, int filter) | ||||
| { | { | ||||
| ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, | ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, | ||||
| UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols); | UI_ID_BROWSE | UI_ID_RENAME | UI_ID_DELETE | UI_ID_PREVIEWS, rows, cols, filter); | ||||
| } | } | ||||
| /************************ ID Chooser Template ***************************/ | /************************ ID Chooser Template ***************************/ | ||||
| /** | /** | ||||
| * This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use | * This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use | ||||
| * | * | ||||
| * - propname: property identifier for property that ID-pointer gets stored to | * - propname: property identifier for property that ID-pointer gets stored to | ||||
| ▲ Show 20 Lines • Show All 3,323 Lines • ▼ Show 20 Lines | if (RNA_property_type(prop) != PROP_POINTER) { | ||||
| return; | return; | ||||
| } | } | ||||
| PointerRNA fileptr = RNA_property_pointer_get(ptr, prop); | PointerRNA fileptr = RNA_property_pointer_get(ptr, prop); | ||||
| CacheFile *file = fileptr.data; | CacheFile *file = fileptr.data; | ||||
| uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr); | uiLayoutSetContextPointer(layout, "edit_cachefile", &fileptr); | ||||
| uiTemplateID(layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL); | uiTemplateID(layout, C, ptr, propname, NULL, "CACHEFILE_OT_open", NULL, UI_TEMPLATE_ID_FILTER_NONE); | ||||
| if (!file) { | if (!file) { | ||||
| return; | return; | ||||
| } | } | ||||
| SpaceButs *sbuts = CTX_wm_space_buts(C); | SpaceButs *sbuts = CTX_wm_space_buts(C); | ||||
| uiLayout *row = uiLayoutRow(layout, false); | uiLayout *row = uiLayoutRow(layout, false); | ||||
| Show All 39 Lines | |||||
Note that the order here won't be alphabetical,
best use this loop to tag, then loop over all id's to fill the list.
If there are no other issues I'll do this before committing.