diff options
Diffstat (limited to 'source/blender/editors/interface/interface_templates.c')
-rw-r--r-- | source/blender/editors/interface/interface_templates.c | 568 |
1 files changed, 467 insertions, 101 deletions
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 82a502db0ad..75b657e1e29 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -56,11 +56,12 @@ #include "BKE_colorband.h" #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idcode.h" #include "BKE_idprop.h" +#include "BKE_layer.h" #include "BKE_library.h" +#include "BKE_library_override.h" #include "BKE_linestyle.h" #include "BKE_main.h" #include "BKE_modifier.h" @@ -72,6 +73,9 @@ #include "BKE_sca.h" #include "BKE_screen.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "ED_screen.h" #include "ED_object.h" #include "ED_render.h" @@ -91,11 +95,126 @@ // #define USE_OP_RESET_BUT // we may want to make this optional, disable for now. +/* 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) { } +/** + * 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 *************************/ void uiTemplateHeader(uiLayout *layout, bContext *C) @@ -231,30 +350,25 @@ static void id_search_cb_objects_from_scene(const bContext *C, void *arg_templat } BKE_main_id_flag_listbase(lb, LIB_TAG_DOIT, false); - for (Base *base = scene->base.first; base; base = base->next) { - base->object->id.tag |= LIB_TAG_DOIT; + + FOREACH_SCENE_OBJECT_BEGIN(scene, ob_iter) + { + ob_iter->id.tag |= LIB_TAG_DOIT; } + FOREACH_SCENE_OBJECT_END; id_search_cb_tagged(C, arg_template, str, items); } /* ID Search browse menu, open */ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) { - static char search[256]; static TemplateID template_ui; - PointerRNA idptr; - wmWindow *win = CTX_wm_window(C); - uiBlock *block; - uiBut *but; + PointerRNA active_item_ptr; void (*id_search_cb_p)(const bContext *, void *, const char *, uiSearchItems *) = id_search_cb; - /* clear initial search string, then all items show */ - search[0] = 0; /* arg_litem is malloced, can be freed by parent button */ template_ui = *((TemplateID *)arg_litem); - - /* get active id for showing first item */ - idptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop); + active_item_ptr = RNA_property_pointer_get(&template_ui.ptr, template_ui.prop); if (template_ui.filter) { /* Currently only used for objects. */ @@ -265,46 +379,9 @@ static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem) } } - 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_ui.prv_rows > 0 && template_ui.prv_cols > 0) { - int w = 4 * U.widget_unit * template_ui.prv_cols; - int h = 5 * U.widget_unit * template_ui.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_ui.prv_rows, template_ui.prv_cols, ""); - UI_but_func_search_set( - but, ui_searchbox_create_generic, id_search_cb_p, - &template_ui, 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_p, - &template_ui, 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; + return template_common_search_menu( + C, ar, id_search_cb_p, &template_ui, id_search_call_cb, active_item_ptr.data, + template_ui.prv_rows, template_ui.prv_cols); } /************************ ID Template ***************************/ @@ -382,14 +459,34 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) case UI_ID_LOCAL: if (id) { Main *bmain = CTX_data_main(C); - if (id_make_local(bmain, id, false, false)) { - BKE_main_id_clear_newpoins(bmain); + if (CTX_wm_window(C)->eventstate->shift) { + ID *override_id = BKE_override_static_create_from_id(bmain, id); + if (override_id != NULL) { + BKE_main_id_clear_newpoins(bmain); - /* reassign to get get proper updates/notifiers */ - idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); - RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr); - RNA_property_update(C, &template_ui->ptr, template_ui->prop); + /* Assign new pointer, takes care of updates/notifiers */ + RNA_id_pointer_create(override_id, &idptr); + } } + else { + if (id_make_local(bmain, id, false, false)) { + BKE_main_id_clear_newpoins(bmain); + + /* reassign to get get proper updates/notifiers */ + idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); + } + } + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr); + RNA_property_update(C, &template_ui->ptr, template_ui->prop); + } + break; + case UI_ID_OVERRIDE: + if (id && id->override_static) { + BKE_override_static_free(&id->override_static); + /* reassign to get get proper updates/notifiers */ + idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); + RNA_property_pointer_set(&template_ui->ptr, template_ui->prop, idptr); + RNA_property_update(C, &template_ui->ptr, template_ui->prop); } break; case UI_ID_ALONE: @@ -403,13 +500,13 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) Scene *scene = CTX_data_scene(C); ED_object_single_user(bmain, scene, (struct Object *)id); WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } else { if (id) { Main *bmain = CTX_data_main(C); id_single_user(C, id, &template_ui->ptr, template_ui->prop); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } } } @@ -421,7 +518,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) } } -static const char *template_id_browse_tip(StructRNA *type) +static const char *template_id_browse_tip(const StructRNA *type) { if (type) { switch (RNA_type_to_ID_code(type)) { @@ -453,6 +550,8 @@ static const char *template_id_browse_tip(StructRNA *type) case ID_PAL: return N_("Browse Palette Data to be linked"); case ID_PC: return N_("Browse Paint Curve Data to be linked"); case ID_CF: return N_("Browse Cache Files to be linked"); + case ID_WS: return N_("Browse Workspace to be linked"); + case ID_LP: return N_("Browse LightProbe to be linked"); } } return N_("Browse ID data to be linked"); @@ -476,12 +575,16 @@ static void template_ID( bContext *C, uiLayout *layout, TemplateID *template_ui, StructRNA *type, int flag, const char *newop, const char *openop, const char *unlinkop) { + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); + uiBut *but; uiBlock *block; PointerRNA idptr; // ListBase *lb; // UNUSED ID *id, *idfrom; const bool editable = RNA_property_editable(&template_ui->ptr, template_ui->prop); + const bool use_previews = template_ui->preview = (flag & UI_ID_PREVIEWS) != 0; idptr = RNA_property_pointer_get(&template_ui->ptr, template_ui->prop); id = idptr.data; @@ -494,29 +597,11 @@ static void template_ID( if (idptr.type) type = idptr.type; - if (flag & UI_ID_PREVIEWS) { - template_ui->preview = true; - - but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template_ui), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, - TIP_(template_id_browse_tip(type))); - ui_def_but_icon(but, id ? ui_id_icon_get(C, id, true) : RNA_struct_ui_icon(type), - UI_HAS_ICON | UI_BUT_ICON_PREVIEW); - - if ((idfrom && idfrom->lib) || !editable) - UI_but_flag_enable(but, UI_BUT_DISABLED); - - uiLayoutRow(layout, true); - } - else if (flag & UI_ID_BROWSE) { - but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template_ui), "", 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); + if (flag & UI_ID_BROWSE) { + template_add_button_search_menu( + C, layout, block, &template_ui->ptr, template_ui->prop, + id_search_menu, MEM_dupallocN(template_ui), TIP_(template_id_browse_tip(type)), + use_previews, editable); } /* text button with name */ @@ -526,8 +611,9 @@ static void template_ID( //text_idbutton(id, name); name[0] = '\0'; - but = uiDefButR(block, UI_BTYPE_TEXT, 0, name, 0, 0, UI_UNIT_X * 6, UI_UNIT_Y, - &idptr, "name", -1, 0, 0, -1, -1, RNA_struct_ui_description(type)); + 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)); UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_RENAME)); if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT); @@ -538,13 +624,25 @@ static void template_ID( UI_but_flag_enable(but, UI_BUT_DISABLED); } else { + const bool disabled = (!id_make_local(CTX_data_main(C), id, true /* test */, false) || + (idfrom && idfrom->lib)); but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, - NULL, 0, 0, 0, 0, TIP_("Direct linked library data-block, click to make local")); - if (!id_make_local(CTX_data_main(C), id, true /* test */, false) || (idfrom && idfrom->lib)) + NULL, 0, 0, 0, 0, + TIP_("Direct linked library data-block, click to make local, " + "Shift + Click to create a static override")); + if (disabled) { UI_but_flag_enable(but, UI_BUT_DISABLED); + } + else { + UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL)); + } } - - UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_LOCAL)); + } + else if (ID_IS_STATIC_OVERRIDE(id)) { + but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_OVERRIDE, 0, 0, UI_UNIT_X, UI_UNIT_Y, + NULL, 0, 0, 0, 0, + TIP_("Static override of linked library data-block, click to make fully local")); + UI_but_funcN_set(but, template_id_cb, MEM_dupallocN(template_ui), SET_INT_IN_POINTER(UI_ID_OVERRIDE)); } if (id->us > 1) { @@ -564,7 +662,7 @@ static void template_ID( (idfrom && idfrom->lib) || (!editable) || /* object in editmode - don't change data */ - (idfrom && GS(idfrom->name) == ID_OB && (((Object *)idfrom)->mode & OB_MODE_EDIT))) + (idfrom && GS(idfrom->name) == ID_OB && (eval_ctx.object_mode & OB_MODE_EDIT))) { UI_but_flag_enable(but, UI_BUT_DISABLED); } @@ -572,7 +670,7 @@ static void template_ID( if (user_alert) UI_but_flag_enable(but, UI_BUT_REDALERT); - if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) { + if (id->lib == NULL && !(ELEM(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB, ID_WS))) { uiDefButR(block, UI_BTYPE_TOGGLE, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL); } } @@ -606,6 +704,8 @@ static void template_ID( BLT_I18NCONTEXT_ID_PARTICLESETTINGS, BLT_I18NCONTEXT_ID_GPENCIL, BLT_I18NCONTEXT_ID_FREESTYLELINESTYLE, + BLT_I18NCONTEXT_ID_WORKSPACE, + BLT_I18NCONTEXT_ID_LIGHTPROBE, ); if (newop) { @@ -821,6 +921,208 @@ void uiTemplateAnyID( 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; + + 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); + if (template_search != NULL) { + 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); + + if (template_search != NULL) { + 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 ********************/ /* ---------- */ @@ -874,7 +1176,7 @@ static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v) ob->partype = PAROBJECT; WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); ED_undo_push(C, "Modifier convert to real"); } @@ -908,7 +1210,8 @@ static int modifier_is_simulation(ModifierData *md) } static uiLayout *draw_modifier( - uiLayout *layout, Scene *scene, Object *ob, + uiLayout *layout, + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -1018,7 +1321,7 @@ static uiLayout *draw_modifier( /* When Modifier is a simulation, show button to switch to context rather than the delete button. */ if (modifier_can_delete(md) && (!modifier_is_simulation(md) || - STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME))) + STREQ(scene->view_render.engine_id, RE_engine_id_BLENDER_GAME))) { uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove"); } @@ -1045,7 +1348,7 @@ static uiLayout *draw_modifier( if (md->type == eModifierType_ParticleSystem) { ParticleSystem *psys = ((ParticleSystemModifierData *)md)->psys; - if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) { + if (!(eval_ctx->object_mode & OB_MODE_PARTICLE_EDIT)) { if (ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB)) uiItemO(row, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Convert"), ICON_NONE, "OBJECT_OT_duplicates_make_real"); @@ -1094,6 +1397,8 @@ static uiLayout *draw_modifier( uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) { + EvaluationContext eval_ctx; + CTX_data_eval_ctx(C, &eval_ctx); Scene *scene = CTX_data_scene(C); Object *ob; ModifierData *md, *vmd; @@ -1124,7 +1429,7 @@ uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr) for (i = 0; vmd; i++, vmd = vmd->next) { if (md == vmd) - return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex); + return draw_modifier(layout, &eval_ctx, scene, ob, md, i, cageIndex, lastCageIndex); else if (vmd->mode & eModifierMode_Virtual) i--; } @@ -1155,7 +1460,7 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event) Main *bmain = CTX_data_main(C); if (ob->pose) BKE_pose_tag_recalc(bmain, ob->pose); /* checks & sorts pose channels */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); break; } #endif @@ -1169,8 +1474,8 @@ static void do_constraint_panels(bContext *C, void *ob_pt, int event) * object_test_constraints(ob); * if (ob->pose) BKE_pose_update_constraint_flags(ob->pose); */ - if (ob->type == OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); - else DAG_id_tag_update(&ob->id, OB_RECALC_OB); + if (ob->type == OB_ARMATURE) DEG_id_tag_update(&ob->id, OB_RECALC_DATA | OB_RECALC_OB); + else DEG_id_tag_update(&ob->id, OB_RECALC_OB); WM_event_add_notifier(C, NC_OBJECT | ND_CONSTRAINT, ob); } @@ -3935,6 +4240,7 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) if (propptr.data) { uiBut *but = uiLayoutGetBlock(layout)->buttons.last; + WM_operator_properties_sanitize(&propptr, false); template_keymap_item_properties(layout, NULL, &propptr); /* attach callbacks to compensate for missing properties update, @@ -3951,6 +4257,66 @@ void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr) } } +/********************************* Overrides *************************************/ + +void uiTemplateOverrideProperty( + uiLayout *layout, PointerRNA *collection_props_ptr, PointerRNA *scene_props_ptr, const char *propname, + const char *name, const char *text_ctxt, int translate, int icon, + const char *custom_template) +{ + bool is_set = false; + uiLayout *row, *col; + + PointerRNA *ptr; + PropertyRNA *prop; + + IDProperty *collection_props = collection_props_ptr->data; + + if (IDP_GetPropertyFromGroup(collection_props, propname)) { + prop = RNA_struct_find_property(collection_props_ptr, propname); + ptr = collection_props_ptr; + is_set = RNA_property_is_set(ptr, prop); + } + else { + /* property doesn't exist yet */ + prop = RNA_struct_find_property(scene_props_ptr, propname); + ptr = scene_props_ptr; + } + + /* Get translated name (label). */ + name = RNA_translate_ui_text(name, text_ctxt, NULL, prop, translate); + + row = uiLayoutRow(layout, false); + col = uiLayoutColumn(row, false); + + uiLayoutSetEnabled(col, is_set); + + if (custom_template && STREQ(custom_template, "icon_view")) { + uiTemplateIconView(col, ptr, propname, false, 5.0f); + } + else { + uiItemFullR(col, ptr, prop, -1, 0, 0, name, icon); + } + + col = uiLayoutColumn(row, false); + uiBut *but; + uiBlock *block = uiLayoutGetBlock(col); + UI_block_emboss_set(block, UI_EMBOSS_NONE); + + if (is_set) { + but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_unuse_property_button", WM_OP_EXEC_DEFAULT, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + } + else { + but = uiDefIconButO(block, UI_BTYPE_BUT, "UI_OT_use_property_button", WM_OP_EXEC_DEFAULT, ICON_ZOOMIN, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL); + /* XXX - Using existing data struct to pass another RNAPointer */ + but->rnasearchpoin = *scene_props_ptr; + } + + but->rnapoin = *collection_props_ptr; + but->rnaprop = prop; + UI_block_emboss_set(block, UI_EMBOSS); +} + /********************************* Color management *************************************/ void uiTemplateColorspaceSettings(uiLayout *layout, PointerRNA *ptr, const char *propname) |