diff options
Diffstat (limited to 'source/blender/editors/interface')
14 files changed, 916 insertions, 678 deletions
diff --git a/source/blender/editors/interface/CMakeLists.txt b/source/blender/editors/interface/CMakeLists.txt index 07ba3b90e11..882db88879d 100644 --- a/source/blender/editors/interface/CMakeLists.txt +++ b/source/blender/editors/interface/CMakeLists.txt @@ -44,6 +44,7 @@ set(SRC interface.c interface_align.c interface_anim.c + interface_context_menu.c interface_draw.c interface_eyedropper.c interface_eyedropper_color.c @@ -56,7 +57,6 @@ set(SRC interface_layout.c interface_ops.c interface_panel.c - interface_regions.c interface_region_color_picker.c interface_region_hud.c interface_region_menu_pie.c @@ -65,6 +65,7 @@ set(SRC interface_region_popup.c interface_region_search.c interface_region_tooltip.c + interface_regions.c interface_style.c interface_templates.c interface_utils.c diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 8c37054098b..a36f534807c 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -4031,6 +4031,16 @@ int UI_blocklist_min_y_get(ListBase *lb) return min; } +bool UI_block_is_empty(const uiBlock *block) +{ + for (const uiBut *but = block->buttons.first; but; but = but->next) { + if (!ELEM(but->type, UI_BTYPE_SEPR, UI_BTYPE_SEPR_LINE)) { + return false; + } + } + return true; +} + void UI_block_direction_set(uiBlock *block, char direction) { block->direction = direction; @@ -4780,4 +4790,3 @@ void UI_exit(void) ui_resources_free(); ui_but_clipboard_free(); } - diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c new file mode 100644 index 00000000000..cda81ba79cf --- /dev/null +++ b/source/blender/editors/interface/interface_context_menu.c @@ -0,0 +1,756 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/editors/interface/interface_context_menu.c + * \ingroup edinterface + * + * Generic context popup menus. + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_utildefines.h" + +#include "BLT_translation.h" + +#include "BKE_addon.h" +#include "BKE_context.h" +#include "BKE_idprop.h" +#include "BKE_screen.h" + +#include "ED_screen.h" +#include "ED_keyframing.h" + +#include "UI_interface.h" + +#include "interface_intern.h" + +#include "RNA_access.h" + +#include "WM_api.h" +#include "WM_types.h" + +/* This hack is needed because we don't have a good way to re-reference keymap items once added: T42944 */ +#define USE_KEYMAP_ADD_HACK + +/* -------------------------------------------------------------------- */ +/** \name Button Context Menu + * \{ */ + +static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) +{ + uiBut *but = (uiBut *)arg1; + + if (but->optype) { + char shortcut_str[128]; + + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + + /* complex code to change name of button */ + if (WM_key_event_operator_string( + C, but->optype->idname, but->opcontext, prop, true, + shortcut_str, sizeof(shortcut_str))) + { + ui_but_add_shortcut(but, shortcut_str, true); + } + else { + /* simply strip the shortcut */ + ui_but_add_shortcut(but, NULL, true); + } + } +} + +static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) +{ + wmWindowManager *wm = CTX_wm_manager(C); + uiBlock *block; + uiBut *but = (uiBut *)arg; + wmKeyMap *km; + wmKeyMapItem *kmi; + PointerRNA ptr; + uiLayout *layout; + uiStyle *style = UI_style_get_dpi(); + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + + kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km); + BLI_assert(kmi != NULL); + + RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); + + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); + UI_block_func_handle_set(block, but_shortcut_name_func, but); + UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); + UI_block_direction_set(block, UI_DIR_CENTER_Y); + + layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); + + uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); + + UI_block_bounds_set_popup(block, 6, -50, 26); + + return block; +} + +#ifdef USE_KEYMAP_ADD_HACK +static int g_kmi_id_hack; +#endif + +static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) +{ + wmWindowManager *wm = CTX_wm_manager(C); + uiBlock *block; + uiBut *but = (uiBut *)arg; + wmKeyMap *km; + wmKeyMapItem *kmi; + PointerRNA ptr; + uiLayout *layout; + uiStyle *style = UI_style_get_dpi(); + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + int kmi_id; + + /* XXX this guess_opname can potentially return a different keymap than being found on adding later... */ + km = WM_keymap_guess_opname(C, but->optype->idname); + kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0); + kmi_id = kmi->id; + + /* copy properties, prop can be NULL for reset */ + if (prop) + prop = IDP_CopyProperty(prop); + WM_keymap_properties_reset(kmi, prop); + + /* update and get pointers again */ + WM_keyconfig_update(wm); + + km = WM_keymap_guess_opname(C, but->optype->idname); + kmi = WM_keymap_item_find_id(km, kmi_id); + + RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); + + block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); + UI_block_func_handle_set(block, but_shortcut_name_func, but); + UI_block_direction_set(block, UI_DIR_CENTER_Y); + + layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); + + uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); + + UI_block_bounds_set_popup(block, 6, -50, 26); + +#ifdef USE_KEYMAP_ADD_HACK + g_kmi_id_hack = kmi_id; +#endif + return block; +} + +static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) +{ + uiBut *but = (uiBut *)arg1; + wmKeyMap *km; + wmKeyMapItem *kmi; +#ifndef USE_KEYMAP_ADD_HACK + IDProperty *prop; +#endif + int kmi_id; + +#ifdef USE_KEYMAP_ADD_HACK + km = WM_keymap_guess_opname(C, but->optype->idname); + kmi_id = g_kmi_id_hack; + UNUSED_VARS(but); +#else + prop = (but->opptr) ? but->opptr->data : NULL; + kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km); +#endif + + kmi = WM_keymap_item_find_id(km, kmi_id); + WM_keymap_remove_item(km, kmi); +} + +static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiBut *but = (uiBut *)arg1; + UI_popup_block_invoke(C, menu_change_shortcut, but); +} + +static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiBut *but = (uiBut *)arg1; + wmKeyMap *km; + wmKeyMapItem *kmi; + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + + kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km); + BLI_assert(kmi != NULL); + + WM_keymap_remove_item(km, kmi); + + but_shortcut_name_func(C, but, 0); +} + +static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiBut *but = (uiBut *)arg1; + UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL); +} + +static void popup_user_menu_add_or_replace_func(bContext *C, void *arg1, void *UNUSED(arg2)) +{ + uiBut *but = arg1; + bUserMenu *um = ED_screen_user_menu_ensure(C); + + char drawstr[sizeof(but->drawstr)]; + STRNCPY(drawstr, but->drawstr); + if (but->flag & UI_BUT_HAS_SEP_CHAR) { + char *sep = strrchr(drawstr, UI_SEP_CHAR); + if (sep) { + *sep = '\0'; + } + } + ED_screen_user_menu_item_add_operator( + &um->items, drawstr, + but->optype, but->opptr ? but->opptr->data : NULL, but->opcontext); +} + +static void popup_user_menu_remove_func(bContext *UNUSED(C), void *arg1, void *arg2) +{ + bUserMenu *um = arg1; + bUserMenuItem *umi = arg2; + ED_screen_user_menu_item_remove(&um->items, umi); +} + +static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop) +{ + const PropertySubType subtype = RNA_property_subtype(prop); + wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true); + char filepath[FILE_MAX]; + char dir[FILE_MAXDIR]; + char file[FILE_MAXFILE]; + PointerRNA props_ptr; + + BLI_assert(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)); + UNUSED_VARS_NDEBUG(subtype); + + RNA_property_string_get(ptr, prop, filepath); + BLI_split_dirfile(filepath, dir, file, sizeof(dir), sizeof(file)); + + if (file[0]) { + BLI_assert(subtype == PROP_FILEPATH); + uiItemFullO_ptr( + layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open File Externally"), + ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr); + RNA_string_set(&props_ptr, "filepath", filepath); + } + + uiItemFullO_ptr( + layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Location Externally"), + ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr); + RNA_string_set(&props_ptr, "filepath", dir); +} + +bool ui_popup_context_menu_for_button(bContext *C, uiBut *but) +{ + /* having this menu for some buttons makes no sense */ + if (but->type == UI_BTYPE_IMAGE) { + return false; + } + + uiPopupMenu *pup; + uiLayout *layout; + + { + uiStringInfo label = {BUT_GET_LABEL, NULL}; + + /* highly unlikely getting the label ever fails */ + UI_but_string_info_get(C, but, &label, NULL); + + pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE); + layout = UI_popup_menu_layout(pup); + if (label.strinfo) { + MEM_freeN(label.strinfo); + } + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); + } + + if (but->rnapoin.data && but->rnaprop) { + PointerRNA *ptr = &but->rnapoin; + PropertyRNA *prop = but->rnaprop; + const PropertyType type = RNA_property_type(prop); + const PropertySubType subtype = RNA_property_subtype(prop); + bool is_anim = RNA_property_animateable(ptr, prop); + bool is_editable = RNA_property_editable(ptr, prop); + /*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */ + bool is_set = RNA_property_is_set(ptr, prop); + + /* second slower test, saved people finding keyframe items in menus when its not possible */ + if (is_anim) + is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop); + + /* determine if we can key a single component of an array */ + const bool is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0; + const bool is_array_component = (is_array && but->rnaindex != -1); + + const int static_override_status = RNA_property_static_override_status(ptr, prop, -1); + const bool is_static_overridable = (static_override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; + + const int dynamic_override_status = RNA_property_dynamic_override_status(ptr, prop, -1); + const bool is_dynamic_overridable = (dynamic_override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; + + /* Keyframes */ + if (but->flag & UI_BUT_ANIMATED_KEY) { + /* Set the (button_pointer, button_prop) and pointer data for Python access to the hovered ui element. */ + uiLayoutSetContextFromBut(layout, but); + + /* replace/delete keyfraemes */ + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"), + ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"), + ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"), + ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Keyframe"), + ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 0); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"), + ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"), + ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1); + } + + /* keyframe settings */ + uiItemS(layout); + + + } + else if (but->flag & UI_BUT_DRIVEN) { + /* pass */ + } + else if (is_anim) { + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"), + ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"), + ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"), + ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); + } + } + + if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) { + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), + ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"), + ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), + ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1); + } + } + + /* Drivers */ + if (but->flag & UI_BUT_DRIVEN) { + uiItemS(layout); + + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"), + ICON_X, "ANIM_OT_driver_button_remove", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"), + ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"), + ICON_X, "ANIM_OT_driver_button_remove", "all", 1); + } + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"), + ICON_NONE, "ANIM_OT_copy_driver_button"); + if (ANIM_driver_can_paste()) { + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), + ICON_NONE, "ANIM_OT_paste_driver_button"); + } + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"), + ICON_DRIVER, "ANIM_OT_driver_button_edit"); + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), + ICON_NONE, "SCREEN_OT_drivers_editor_show"); + } + else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) { + /* pass */ + } + else if (is_anim) { + uiItemS(layout); + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"), + ICON_DRIVER, "ANIM_OT_driver_button_add"); + + if (ANIM_driver_can_paste()) { + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), + ICON_NONE, "ANIM_OT_paste_driver_button"); + } + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), + ICON_NONE, "SCREEN_OT_drivers_editor_show"); + } + + /* Keying Sets */ + /* TODO: check on modifyability of Keying Set when doing this */ + if (is_anim) { + uiItemS(layout); + + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"), + ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"), + ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 0); + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), + ICON_NONE, "ANIM_OT_keyingset_button_remove"); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"), + ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1); + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), + ICON_NONE, "ANIM_OT_keyingset_button_remove"); + } + } + + /* Dynamic Override Operators */ + if (is_editable && is_dynamic_overridable) { + uiItemS(layout); + uiItemFullO(layout, "SCENE_OT_view_layer_override_add", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); + } + + if (is_static_overridable) { + wmOperatorType *ot; + PointerRNA op_ptr; + /* Override Operators */ + uiItemS(layout); + + if (but->flag & UI_BUT_OVERRIDEN) { + if (is_array_component) { +#if 0 /* Disabled for now. */ + ot = WM_operatortype_find("UI_OT_override_type_set_button", false); + uiItemFullO_ptr( + layout, ot, "Overrides Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", true); + uiItemFullO_ptr( + layout, ot, "Single Override Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); +#endif + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"), + ICON_X, "UI_OT_override_remove_button", "all", true); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"), + ICON_X, "UI_OT_override_remove_button", "all", false); + } + else { +#if 0 /* Disabled for now. */ + uiItemFullO( + layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); +#endif + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"), + ICON_X, "UI_OT_override_remove_button", "all", true); + } + } + else { + if (is_array_component) { + ot = WM_operatortype_find("UI_OT_override_type_set_button", false); + uiItemFullO_ptr( + layout, ot, "Define Overrides", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", true); + uiItemFullO_ptr( + layout, ot, "Define Single Override", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); + } + else { + uiItemFullO( + layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); + RNA_boolean_set(&op_ptr, "all", false); + } + } + } + + uiItemS(layout); + + /* Property Operators */ + + /* Copy Property Value + * Paste Property Value */ + + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"), + ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"), + ICON_NONE, "UI_OT_reset_default_button", "all", 0); + } + else { + uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"), + ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1); + } + if (is_editable /*&& is_idprop*/ && is_set) { + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"), + ICON_NONE, "UI_OT_unset_property_button"); + } + + if (is_array_component) { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy All To Selected"), + ICON_NONE, "UI_OT_copy_to_selected_button", "all", true); + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Single To Selected"), + ICON_NONE, "UI_OT_copy_to_selected_button", "all", false); + } + else { + uiItemBooleanO( + layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"), + ICON_NONE, "UI_OT_copy_to_selected_button", "all", true); + } + + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"), + ICON_NONE, "UI_OT_copy_data_path_button"); + + uiItemS(layout); + + if (type == PROP_STRING && ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) { + ui_but_menu_add_path_operators(layout, ptr, prop); + uiItemS(layout); + } + } + + /* Operator buttons */ + if (but->optype) { + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *but2; + IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; + int w = uiLayoutGetWidth(layout); + wmKeyMap *km; + /* We want to know if this op has a shortcut, be it hotkey or not. */ + wmKeyMapItem *kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, false, &km); + + /* We do have a shortcut, but only keyboard ones are editbale that way... */ + if (kmi) { + if (ISKEYBOARD(kmi->type)) { +#if 0 /* would rather use a block but, but gets weirdly positioned... */ + uiDefBlockBut( + block, menu_change_shortcut, but, "Change Shortcut", + 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, ""); +#endif + + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_HAND, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, popup_change_shortcut_func, but, NULL); + + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_NONE, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, remove_shortcut_func, but, NULL); + } + else { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_HAND, IFACE_("Non-Keyboard Shortcut"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, + TIP_("Only keyboard shortcuts can be edited that way, " + "please use User Preferences otherwise")); + UI_but_flag_enable(but2, UI_BUT_DISABLED); + } + } + /* only show 'add' if there's a suitable key map for it to go in */ + else if (WM_keymap_guess_opname(C, but->optype->idname)) { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_HAND, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); + } + + uiItemS(layout); + + { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_MENU_PANEL, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Favorites Menu"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, + "Add to a user defined context menu (stored in the user preferences)"); + UI_but_func_set(but2, popup_user_menu_add_or_replace_func, but, NULL); + + bUserMenu *um = ED_screen_user_menu_find(C); + if (um) { + bUserMenuItem_Op *umi_op = ED_screen_user_menu_item_find_operator( + &um->items, but->optype, prop, but->opcontext); + if (umi_op != NULL) { + but2 = uiDefIconTextBut( + block, UI_BTYPE_BUT, 0, ICON_CANCEL, + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Favorites Menu"), + 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); + UI_but_func_set(but2, popup_user_menu_remove_func, um, umi_op); + } + } + } + + /* Set the operator pointer for python access */ + uiLayoutSetContextFromBut(layout, but); + + uiItemS(layout); + } + + /* Show header tools for header buttons. */ + if (ui_block_is_menu(but->block) == false) { + ARegion *ar = CTX_wm_region(C); + if (ar && (ar->regiontype == RGN_TYPE_HEADER)) { + uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); + uiItemS(layout); + } + } + + { /* Docs */ + char buf[512]; + + if (UI_but_online_manual_id(but, buf, sizeof(buf))) { + PointerRNA ptr_props; + uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), + ICON_URL, "WM_OT_doc_view_manual_ui_context"); + + uiItemFullO( + layout, "WM_OT_doc_view", + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), + ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr_props); + RNA_string_set(&ptr_props, "doc_id", buf); + + /* XXX inactive option, not for public! */ +#if 0 + uiItemFullO( + layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, + NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr_props); + RNA_string_set(&ptr_props, "doc_id", buf); + RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); +#endif + } + } + + if (but->optype) { + uiItemO(layout, NULL, + ICON_NONE, "UI_OT_copy_python_command_button"); + } + + /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */ + if (U.flag & USER_DEVELOPER_UI) { + if (ui_block_is_menu(but->block) == false) { + uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); + } + } + + if (BKE_addon_find(&U.addons, "ui_translate")) { + uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); + } + + MenuType *mt = WM_menutype_find("WM_MT_button_context", true); + if (mt) { + UI_menutype_draw(C, mt, uiLayoutColumn(layout, false)); + } + + return UI_popup_menu_end_or_cancel(C, pup); +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Panel Context Menu + * \{ */ + +/** + * menu to show when right clicking on the panel header + */ +void ui_popup_context_menu_for_panel(bContext *C, ARegion *ar, Panel *pa) +{ + bScreen *sc = CTX_wm_screen(C); + const bool has_panel_category = UI_panel_category_is_visible(ar); + const bool any_item_visible = has_panel_category; + PointerRNA ptr; + uiPopupMenu *pup; + uiLayout *layout; + + if (!any_item_visible) { + return; + } + + RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr); + + pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE); + layout = UI_popup_menu_layout(pup); + + if (has_panel_category) { + char tmpstr[80]; + BLI_snprintf(tmpstr, sizeof(tmpstr), "%s" UI_SEP_CHAR_S "%s", IFACE_("Pin"), IFACE_("Shift+Left Mouse")); + uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE); + + /* evil, force shortcut flag */ + { + uiBlock *block = uiLayoutGetBlock(layout); + uiBut *but = block->buttons.last; + but->flag |= UI_BUT_HAS_SEP_CHAR; + } + } + UI_popup_menu_end(C, pup); +} + +/** \} */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 1ff05fa85cc..bb54f26131a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -27,7 +27,6 @@ * \ingroup edinterface */ - #include <float.h> #include <limits.h> #include <math.h> @@ -40,22 +39,18 @@ #include "DNA_brush_types.h" -#include "DNA_object_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "BLI_math.h" #include "BLI_listbase.h" #include "BLI_linklist.h" -#include "BLI_path_util.h" #include "BLI_string.h" #include "BLI_string_utf8.h" #include "BLI_string_cursor_utf8.h" #include "BLI_rect.h" #include "BLI_utildefines.h" -#include "BLT_translation.h" - #include "PIL_time.h" #include "BKE_colorband.h" @@ -63,7 +58,6 @@ #include "BKE_brush.h" #include "BKE_colortools.h" #include "BKE_context.h" -#include "BKE_idprop.h" #include "BKE_report.h" #include "BKE_screen.h" #include "BKE_tracking.h" @@ -72,7 +66,6 @@ #include "ED_screen.h" #include "ED_undo.h" -#include "ED_keyframing.h" #include "UI_interface.h" #include "UI_view2d.h" @@ -89,6 +82,7 @@ #ifdef WITH_INPUT_IME # include "wm_window.h" +# include "BLT_translation.h" # include "BLT_lang.h" #endif @@ -111,9 +105,6 @@ #define UI_MAX_PASSWORD_STR 128 -/* This hack is needed because we don't have a good way to re-reference keymap items once added: T42944 */ -#define USE_KEYMAP_ADD_HACK - /* proto */ static int ui_do_but_EXIT(bContext *C, uiBut *but, struct uiHandleButtonData *data, const wmEvent *event); static bool ui_but_find_select_in_enum__cmp(const uiBut *but_a, const uiBut *but_b); @@ -1300,7 +1291,6 @@ typedef struct uiDragToggleHandle { bool is_init; bool is_set; float but_cent_start[2]; - eButType but_type_start; bool xy_lock[2]; int xy_init[2]; @@ -1308,7 +1298,7 @@ typedef struct uiDragToggleHandle { } uiDragToggleHandle; static bool ui_drag_toggle_set_xy_xy( - bContext *C, ARegion *ar, const bool is_set, const eButType but_type_start, + bContext *C, ARegion *ar, const bool is_set, const int xy_src[2], const int xy_dst[2]) { /* popups such as layers won't re-evaluate on redraw */ @@ -1332,7 +1322,7 @@ static bool ui_drag_toggle_set_xy_xy( if (BLI_rctf_isect_segment(&but->rect, xy_a_block, xy_b_block)) { /* execute the button */ - if (ui_drag_toggle_but_is_supported(but) && but->type == but_type_start) { + if (ui_drag_toggle_but_is_supported(but)) { /* is it pressed? */ bool is_set_but = ui_drag_toggle_but_is_pushed(but); if (is_set_but != is_set) { @@ -1404,7 +1394,7 @@ static void ui_drag_toggle_set(bContext *C, uiDragToggleHandle *drag_info, const /* touch all buttons between last mouse coord and this one */ - do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->but_type_start, drag_info->xy_last, xy); + do_draw = ui_drag_toggle_set_xy_xy(C, ar, drag_info->is_set, drag_info->xy_last, xy); if (do_draw) { ED_region_tag_redraw(ar); @@ -1783,7 +1773,6 @@ static bool ui_but_drag_init( drag_info->is_set = ui_drag_toggle_but_is_pushed(but); drag_info->but_cent_start[0] = BLI_rctf_cent_x(&but->rect); drag_info->but_cent_start[1] = BLI_rctf_cent_y(&but->rect); - drag_info->but_type_start = but->type; copy_v2_v2_int(drag_info->xy_init, &event->x); copy_v2_v2_int(drag_info->xy_last, &event->x); @@ -6495,602 +6484,6 @@ static int ui_do_but_TRACKPREVIEW( return WM_UI_HANDLER_CONTINUE; } -static void but_shortcut_name_func(bContext *C, void *arg1, int UNUSED(event)) -{ - uiBut *but = (uiBut *)arg1; - - if (but->optype) { - char shortcut_str[128]; - - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - - /* complex code to change name of button */ - if (WM_key_event_operator_string( - C, but->optype->idname, but->opcontext, prop, true, - shortcut_str, sizeof(shortcut_str))) - { - ui_but_add_shortcut(but, shortcut_str, true); - } - else { - /* simply strip the shortcut */ - ui_but_add_shortcut(but, NULL, true); - } - } -} - -static uiBlock *menu_change_shortcut(bContext *C, ARegion *ar, void *arg) -{ - wmWindowManager *wm = CTX_wm_manager(C); - uiBlock *block; - uiBut *but = (uiBut *)arg; - wmKeyMap *km; - wmKeyMapItem *kmi; - PointerRNA ptr; - uiLayout *layout; - uiStyle *style = UI_style_get_dpi(); - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - - kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km); - BLI_assert(kmi != NULL); - - RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_func_handle_set(block, but_shortcut_name_func, but); - UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT); - UI_block_direction_set(block, UI_DIR_CENTER_Y); - - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); - - uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); - - UI_block_bounds_set_popup(block, 6, -50, 26); - - return block; -} - -#ifdef USE_KEYMAP_ADD_HACK -static int g_kmi_id_hack; -#endif - -static uiBlock *menu_add_shortcut(bContext *C, ARegion *ar, void *arg) -{ - wmWindowManager *wm = CTX_wm_manager(C); - uiBlock *block; - uiBut *but = (uiBut *)arg; - wmKeyMap *km; - wmKeyMapItem *kmi; - PointerRNA ptr; - uiLayout *layout; - uiStyle *style = UI_style_get_dpi(); - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - int kmi_id; - - /* XXX this guess_opname can potentially return a different keymap than being found on adding later... */ - km = WM_keymap_guess_opname(C, but->optype->idname); - kmi = WM_keymap_add_item(km, but->optype->idname, AKEY, KM_PRESS, 0, 0); - kmi_id = kmi->id; - - /* copy properties, prop can be NULL for reset */ - if (prop) - prop = IDP_CopyProperty(prop); - WM_keymap_properties_reset(kmi, prop); - - /* update and get pointers again */ - WM_keyconfig_update(wm); - - km = WM_keymap_guess_opname(C, but->optype->idname); - kmi = WM_keymap_item_find_id(km, kmi_id); - - RNA_pointer_create(&wm->id, &RNA_KeyMapItem, kmi, &ptr); - - block = UI_block_begin(C, ar, "_popup", UI_EMBOSS); - UI_block_func_handle_set(block, but_shortcut_name_func, but); - UI_block_direction_set(block, UI_DIR_CENTER_Y); - - layout = UI_block_layout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0, 200, 20, 0, style); - - uiItemR(layout, &ptr, "type", UI_ITEM_R_FULL_EVENT | UI_ITEM_R_IMMEDIATE, "", ICON_NONE); - - UI_block_bounds_set_popup(block, 6, -50, 26); - -#ifdef USE_KEYMAP_ADD_HACK - g_kmi_id_hack = kmi_id; -#endif - return block; -} - -static void menu_add_shortcut_cancel(struct bContext *C, void *arg1) -{ - uiBut *but = (uiBut *)arg1; - wmKeyMap *km; - wmKeyMapItem *kmi; -#ifndef USE_KEYMAP_ADD_HACK - IDProperty *prop; -#endif - int kmi_id; - -#ifdef USE_KEYMAP_ADD_HACK - km = WM_keymap_guess_opname(C, but->optype->idname); - kmi_id = g_kmi_id_hack; - UNUSED_VARS(but); -#else - prop = (but->opptr) ? but->opptr->data : NULL; - kmi_id = WM_key_event_operator_id(C, but->optype->idname, but->opcontext, prop, true, &km); -#endif - - kmi = WM_keymap_item_find_id(km, kmi_id); - WM_keymap_remove_item(km, kmi); -} - -static void popup_change_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) -{ - uiBut *but = (uiBut *)arg1; - UI_popup_block_invoke(C, menu_change_shortcut, but); -} - -static void remove_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) -{ - uiBut *but = (uiBut *)arg1; - wmKeyMap *km; - wmKeyMapItem *kmi; - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - - kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, true, &km); - BLI_assert(kmi != NULL); - - WM_keymap_remove_item(km, kmi); - - but_shortcut_name_func(C, but, 0); -} - -static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2)) -{ - uiBut *but = (uiBut *)arg1; - UI_popup_block_ex(C, menu_add_shortcut, NULL, menu_add_shortcut_cancel, but, NULL); -} - -/** - * menu to chow when right clicking on the panel header - */ -void ui_panel_menu(bContext *C, ARegion *ar, Panel *pa) -{ - bScreen *sc = CTX_wm_screen(C); - const bool has_panel_category = UI_panel_category_is_visible(ar); - const bool any_item_visible = has_panel_category; - PointerRNA ptr; - uiPopupMenu *pup; - uiLayout *layout; - - if (!any_item_visible) { - return; - } - - RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr); - - pup = UI_popup_menu_begin(C, IFACE_("Panel"), ICON_NONE); - layout = UI_popup_menu_layout(pup); - - if (has_panel_category) { - char tmpstr[80]; - BLI_snprintf(tmpstr, sizeof(tmpstr), "%s" UI_SEP_CHAR_S "%s", IFACE_("Pin"), IFACE_("Shift+Left Mouse")); - uiItemR(layout, &ptr, "use_pin", 0, tmpstr, ICON_NONE); - - /* evil, force shortcut flag */ - { - uiBlock *block = uiLayoutGetBlock(layout); - uiBut *but = block->buttons.last; - but->flag |= UI_BUT_HAS_SEP_CHAR; - } - } - UI_popup_menu_end(C, pup); -} - -static void ui_but_menu_add_path_operators(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop) -{ - const PropertySubType subtype = RNA_property_subtype(prop); - wmOperatorType *ot = WM_operatortype_find("WM_OT_path_open", true); - char filepath[FILE_MAX]; - char dir[FILE_MAXDIR]; - char file[FILE_MAXFILE]; - PointerRNA props_ptr; - - BLI_assert(ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)); - UNUSED_VARS_NDEBUG(subtype); - - RNA_property_string_get(ptr, prop, filepath); - BLI_split_dirfile(filepath, dir, file, sizeof(dir), sizeof(file)); - - if (file[0]) { - BLI_assert(subtype == PROP_FILEPATH); - uiItemFullO_ptr( - layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open File Externally"), - ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr); - RNA_string_set(&props_ptr, "filepath", filepath); - } - - uiItemFullO_ptr( - layout, ot, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Location Externally"), - ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, &props_ptr); - RNA_string_set(&props_ptr, "filepath", dir); -} - -static bool ui_but_menu(bContext *C, uiBut *but) -{ - uiPopupMenu *pup; - uiLayout *layout; - MenuType *mt = WM_menutype_find("WM_MT_button_context", true); - bool is_array, is_array_component; - uiStringInfo label = {BUT_GET_LABEL, NULL}; - wmOperatorType *ot; - PointerRNA op_ptr; - -/* if ((but->rnapoin.data && but->rnaprop) == 0 && but->optype == NULL)*/ -/* return 0;*/ - - /* having this menu for some buttons makes no sense */ - if (but->type == UI_BTYPE_IMAGE) { - return false; - } - - /* highly unlikely getting the label ever fails */ - UI_but_string_info_get(C, but, &label, NULL); - - pup = UI_popup_menu_begin(C, label.strinfo ? label.strinfo : "", ICON_NONE); - layout = UI_popup_menu_layout(pup); - if (label.strinfo) - MEM_freeN(label.strinfo); - - uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT); - - if (but->rnapoin.data && but->rnaprop) { - PointerRNA *ptr = &but->rnapoin; - PropertyRNA *prop = but->rnaprop; - const PropertyType type = RNA_property_type(prop); - const PropertySubType subtype = RNA_property_subtype(prop); - bool is_anim = RNA_property_animateable(ptr, prop); - bool is_editable = RNA_property_editable(ptr, prop); - /*bool is_idprop = RNA_property_is_idprop(prop);*/ /* XXX does not work as expected, not strictly needed */ - bool is_set = RNA_property_is_set(ptr, prop); - - const int static_override_status = RNA_property_static_override_status(ptr, prop, -1); - const bool is_static_overridable = (static_override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; - - const int dynamic_override_status = RNA_property_dynamic_override_status(ptr, prop, -1); - const bool is_dynamic_overridable = (dynamic_override_status & RNA_OVERRIDE_STATUS_OVERRIDABLE) != 0; - - /* second slower test, saved people finding keyframe items in menus when its not possible */ - if (is_anim) - is_anim = RNA_property_path_from_ID_check(&but->rnapoin, but->rnaprop); - - /* determine if we can key a single component of an array */ - is_array = RNA_property_array_length(&but->rnapoin, but->rnaprop) != 0; - is_array_component = (is_array && but->rnaindex != -1); - - /* Keyframes */ - if (but->flag & UI_BUT_ANIMATED_KEY) { - /* replace/delete keyfraemes */ - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframes"), - ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Single Keyframe"), - ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframes"), - ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Keyframe"), - ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Replace Keyframe"), - ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Keyframe"), - ICON_NONE, "ANIM_OT_keyframe_delete_button", "all", 1); - } - - /* keyframe settings */ - uiItemS(layout); - - - } - else if (but->flag & UI_BUT_DRIVEN) { - /* pass */ - } - else if (is_anim) { - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframes"), - ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Single Keyframe"), - ICON_NONE, "ANIM_OT_keyframe_insert_button", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Insert Keyframe"), - ICON_KEY_HLT, "ANIM_OT_keyframe_insert_button", "all", 1); - } - } - - if ((but->flag & UI_BUT_ANIMATED) && (but->rnapoin.type != &RNA_NlaStrip)) { - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), - ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Single Keyframes"), - ICON_NONE, "ANIM_OT_keyframe_clear_button", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Clear Keyframes"), - ICON_KEY_DEHLT, "ANIM_OT_keyframe_clear_button", "all", 1); - } - } - - /* Drivers */ - if (but->flag & UI_BUT_DRIVEN) { - uiItemS(layout); - - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Drivers"), - ICON_X, "ANIM_OT_driver_button_remove", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Single Driver"), - ICON_NONE, "ANIM_OT_driver_button_remove", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Delete Driver"), - ICON_X, "ANIM_OT_driver_button_remove", "all", 1); - } - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Driver"), - ICON_NONE, "ANIM_OT_copy_driver_button"); - if (ANIM_driver_can_paste()) { - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), - ICON_NONE, "ANIM_OT_paste_driver_button"); - } - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Edit Driver"), - ICON_DRIVER, "ANIM_OT_driver_button_edit"); - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), - ICON_NONE, "SCREEN_OT_drivers_editor_show"); - } - else if (but->flag & (UI_BUT_ANIMATED_KEY | UI_BUT_ANIMATED)) { - /* pass */ - } - else if (is_anim) { - uiItemS(layout); - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Driver"), - ICON_DRIVER, "ANIM_OT_driver_button_add"); - - if (ANIM_driver_can_paste()) { - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Paste Driver"), - ICON_NONE, "ANIM_OT_paste_driver_button"); - } - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Open Drivers Editor"), - ICON_NONE, "SCREEN_OT_drivers_editor_show"); - } - - /* Keying Sets */ - /* TODO: check on modifyability of Keying Set when doing this */ - if (is_anim) { - uiItemS(layout); - - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add All to Keying Set"), - ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Single to Keying Set"), - ICON_NONE, "ANIM_OT_keyingset_button_add", "all", 0); - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), - ICON_NONE, "ANIM_OT_keyingset_button_remove"); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add to Keying Set"), - ICON_KEYINGSET, "ANIM_OT_keyingset_button_add", "all", 1); - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove from Keying Set"), - ICON_NONE, "ANIM_OT_keyingset_button_remove"); - } - } - - /* Dynamic Override Operators */ - if (is_editable && is_dynamic_overridable) { - uiItemS(layout); - uiItemFullO(layout, "SCENE_OT_view_layer_override_add", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); - } - - if (is_static_overridable) { - /* Static Override Operators */ - uiItemS(layout); - - if (but->flag & UI_BUT_OVERRIDEN) { - if (is_array_component) { -#if 0 /* Disabled for now. */ - ot = WM_operatortype_find("UI_OT_override_type_set_button", false); - uiItemFullO_ptr(layout, ot, "Overrides Type", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", true); - uiItemFullO_ptr(layout, ot, "Single Override Type", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", false); -#endif - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Overrides"), - ICON_X, "UI_OT_override_remove_button", "all", true); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Single Override"), - ICON_X, "UI_OT_override_remove_button", "all", false); - } - else { -#if 0 /* Disabled for now. */ - uiItemFullO(layout, "UI_OT_override_type_set_button", "Override Type", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", false); -#endif - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Override"), - ICON_X, "UI_OT_override_remove_button", "all", true); - } - } - else { - if (is_array_component) { - ot = WM_operatortype_find("UI_OT_override_type_set_button", false); - uiItemFullO_ptr(layout, ot, "Define Overrides", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", true); - uiItemFullO_ptr(layout, ot, "Define Single Override", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", false); - } - else { - uiItemFullO(layout, "UI_OT_override_type_set_button", "Define Override", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &op_ptr); - RNA_boolean_set(&op_ptr, "all", false); - } - } - } - - uiItemS(layout); - - /* Property Operators */ - - /* Copy Property Value - * Paste Property Value */ - - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset All to Default Values"), - ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset Single to Default Value"), - ICON_NONE, "UI_OT_reset_default_button", "all", 0); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Reset to Default Value"), - ICON_LOOP_BACK, "UI_OT_reset_default_button", "all", 1); - } - if (is_editable /*&& is_idprop*/ && is_set) { - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Unset"), - ICON_NONE, "UI_OT_unset_property_button"); - } - - if (is_array_component) { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy All To Selected"), - ICON_NONE, "UI_OT_copy_to_selected_button", "all", true); - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Single To Selected"), - ICON_NONE, "UI_OT_copy_to_selected_button", "all", false); - } - else { - uiItemBooleanO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy To Selected"), - ICON_NONE, "UI_OT_copy_to_selected_button", "all", true); - } - - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy Data Path"), - ICON_NONE, "UI_OT_copy_data_path_button"); - - uiItemS(layout); - - if (type == PROP_STRING && ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) { - ui_but_menu_add_path_operators(layout, ptr, prop); - uiItemS(layout); - } - } - - /* Operator buttons */ - if (but->optype) { - uiBlock *block = uiLayoutGetBlock(layout); - uiBut *but2; - IDProperty *prop = (but->opptr) ? but->opptr->data : NULL; - int w = uiLayoutGetWidth(layout); - wmKeyMap *km; - /* We want to know if this op has a shortcut, be it hotkey or not. */ - wmKeyMapItem *kmi = WM_key_event_operator(C, but->optype->idname, but->opcontext, prop, false, &km); - - /* We do have a shortcut, but only keyboard ones are editbale that way... */ - if (kmi) { - if (ISKEYBOARD(kmi->type)) { -#if 0 /* would rather use a block but, but gets weirdly positioned... */ - uiDefBlockBut(block, menu_change_shortcut, but, "Change Shortcut", - 0, 0, uiLayoutGetWidth(layout), UI_UNIT_Y, ""); -#endif - - but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Change Shortcut"), - 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - UI_but_func_set(but2, popup_change_shortcut_func, but, NULL); - - but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_NONE, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Remove Shortcut"), - 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - UI_but_func_set(but2, remove_shortcut_func, but, NULL); - } - else { - but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND, IFACE_("Non-Keyboard Shortcut"), - 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, - TIP_("Only keyboard shortcuts can be edited that way, " - "please use User Preferences otherwise")); - UI_but_flag_enable(but2, UI_BUT_DISABLED); - } - } - /* only show 'add' if there's a suitable key map for it to go in */ - else if (WM_keymap_guess_opname(C, but->optype->idname)) { - but2 = uiDefIconTextBut(block, UI_BTYPE_BUT, 0, ICON_HAND, - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Add Shortcut"), - 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, ""); - UI_but_func_set(but2, popup_add_shortcut_func, but, NULL); - } - - /* Set the operator pointer for python access */ - uiLayoutSetContextFromBut(layout, but); - - uiItemS(layout); - } - - /* Show header tools for header buttons. */ - if (ui_block_is_menu(but->block) == false) { - ARegion *ar = CTX_wm_region(C); - if (ar && (ar->regiontype == RGN_TYPE_HEADER)) { - uiItemMenuF(layout, IFACE_("Header"), ICON_NONE, ED_screens_header_tools_menu_create, NULL); - uiItemS(layout); - } - } - - { /* Docs */ - char buf[512]; - - if (UI_but_online_manual_id(but, buf, sizeof(buf))) { - PointerRNA ptr_props; - uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Manual"), - ICON_URL, "WM_OT_doc_view_manual_ui_context"); - - uiItemFullO( - layout, "WM_OT_doc_view", - CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), - ICON_NONE, NULL, WM_OP_EXEC_DEFAULT, 0, &ptr_props); - RNA_string_set(&ptr_props, "doc_id", buf); - - /* XXX inactive option, not for public! */ -#if 0 - uiItemFullO( - layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, - NULL, WM_OP_INVOKE_DEFAULT, 0, &ptr_props); - RNA_string_set(&ptr_props, "doc_id", buf); - RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); -#endif - } - } - - if (but->optype) { - uiItemO(layout, NULL, - ICON_NONE, "UI_OT_copy_python_command_button"); - } - - /* perhaps we should move this into (G.debug & G_DEBUG) - campbell */ - if (ui_block_is_menu(but->block) == false) { - uiItemFullO(layout, "UI_OT_editsource", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); - } - uiItemFullO(layout, "UI_OT_edittranslation_init", NULL, ICON_NONE, NULL, WM_OP_INVOKE_DEFAULT, 0, NULL); - - mt = WM_menutype_find("WM_MT_button_context", true); - if (mt) { - UI_menutype_draw(C, mt, uiLayoutColumn(layout, false)); - } - - UI_popup_menu_end(C, pup); - - return true; -} - static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *event) { uiHandleButtonData *data; @@ -7134,7 +6527,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * (event->val == KM_PRESS)) { /* RMB has two options now */ - if (ui_but_menu(C, but)) { + if (ui_popup_context_menu_for_button(C, but)) { return WM_UI_HANDLER_BREAK; } } @@ -9602,6 +8995,11 @@ static int ui_handle_menu_event( } #endif + /* Don't handle double click events, rehandle as regular press/release. */ + if (retval == WM_UI_HANDLER_CONTINUE && event->val == KM_DBL_CLICK) { + return retval; + } + /* if we set a menu return value, ensure we continue passing this on to * lower menus and buttons, so always set continue then, and if we are * inside the region otherwise, ensure we swallow the event */ @@ -10182,6 +9580,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE { ARegion *ar; uiBut *but; + int retval = WM_UI_HANDLER_CONTINUE; ar = CTX_wm_menu(C); if (!ar) @@ -10225,29 +9624,32 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE if ((but_other->flag & UI_BUT_DISABLED) == 0) { ui_handle_button_activate(C, ar, but_other, BUTTON_ACTIVATE_OVER); button_activate_state(C, but_other, BUTTON_STATE_MENU_OPEN); + retval = WM_UI_HANDLER_BREAK; } } else if (data->state == BUTTON_STATE_MENU_OPEN) { - int retval; - /* handle events for menus and their buttons recursively, * this will handle events from the top to the bottom menu */ - if (data->menu) + if (data->menu) { retval = ui_handle_menus_recursive(C, event, data->menu, 0, false, false, false); + } /* handle events for the activated button */ if ((data->menu && (retval == WM_UI_HANDLER_CONTINUE)) || (event->type == TIMER)) { - if (data->menu && data->menu->menuretval) + if (data->menu && data->menu->menuretval) { ui_handle_button_return_submenu(C, event, but); - else - ui_handle_button_event(C, event, but); + retval = WM_UI_HANDLER_BREAK; + } + else { + retval = ui_handle_button_event(C, event, but); + } } } else { /* handle events for the activated button */ - ui_handle_button_event(C, event, but); + retval = ui_handle_button_event(C, event, but); } } @@ -10258,6 +9660,14 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *UNUSE /* delayed apply callbacks */ ui_apply_but_funcs_after(C); + /* Don't handle double-click events, + * these will be converted into regular clicks which we handle. */ + if (retval == WM_UI_HANDLER_CONTINUE) { + if (event->val == KM_DBL_CLICK) { + return WM_UI_HANDLER_CONTINUE; + } + } + /* we block all events, this is modal interaction */ return WM_UI_HANDLER_BREAK; } diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 539dd05b242..a8feaedf717 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -858,10 +858,10 @@ static void ui_studiolight_kill_icon_preview_job(wmWindowManager *wm, int icon_i icon->obj = NULL; } -static void ui_studiolight_free_function(StudioLight * sl, void* data) +static void ui_studiolight_free_function(StudioLight *sl, void *data) { wmWindowManager *wm = data; - + // get icons_id, get icons and kill wm jobs if (sl->icon_id_radiance) { ui_studiolight_kill_icon_preview_job(wm, sl->icon_id_radiance); @@ -920,7 +920,7 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi di->data.buffer.image = img; wmJob *wm_job = WM_jobs_get(wm, CTX_wm_window(C), icon, "StudioLight Icon", 0, WM_JOB_TYPE_STUDIOLIGHT); - Icon** tmp = MEM_callocN(sizeof(Icon*), __func__); + Icon **tmp = MEM_callocN(sizeof(Icon *), __func__); *tmp = icon; WM_jobs_customdata_set(wm_job, tmp, MEM_freeN); WM_jobs_timer(wm_job, 0.01, 0, NC_WINDOW); @@ -1647,4 +1647,3 @@ void UI_icon_draw_preview_aspect_size(float x, float y, int icon_id, float aspec { icon_draw_size(x, y, icon_id, aspect, alpha, NULL, ICON_SIZE_PREVIEW, size, false); } - diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 6f029b81e92..f29d73e564b 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -706,7 +706,6 @@ float ui_block_calc_pie_segment(struct uiBlock *block, const float event_xy[2]); void ui_but_add_shortcut(uiBut *but, const char *key_str, const bool do_strip); void ui_but_clipboard_free(void); -void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa); uiBut *ui_but_find_old(uiBlock *block_old, const uiBut *but_new); uiBut *ui_but_find_new(uiBlock *block_old, const uiBut *but_new); @@ -818,6 +817,10 @@ void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, fl void ui_but_anim_decorate_cb(struct bContext *C, void *arg_but, void *arg_dummy); void ui_but_anim_decorate_update_from_flag(uiBut *but); +/* interface_context_menu.c */ +bool ui_popup_context_menu_for_button(struct bContext *C, uiBut *but); +void ui_popup_context_menu_for_panel(struct bContext *C, struct ARegion *ar, struct Panel *pa); + /* interface_eyedropper.c */ struct wmKeyMap *eyedropper_modal_keymap(struct wmKeyConfig *keyconf); struct wmKeyMap *eyedropper_colorband_modal_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 3784ab635be..05af133616e 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -67,6 +67,9 @@ /* Show an icon button after each RNA button to use to quickly set keyframes, * this is a way to display animation/driven/override status, see T54951. */ #define UI_PROP_DECORATE +/* Alternate draw mode where some buttons can use single icon width, + * giving more room for the text at the expense of nicely aligned text. */ +#define UI_PROP_SEP_ICON_WIDTH_EXCEPTION /************************ Structs and Defines *************************/ @@ -1595,9 +1598,19 @@ void uiItemFullR(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, int index } else { const PropertySubType subtype = RNA_property_subtype(prop); - uiLayout *layout_split = uiLayoutSplit( - layout_row ? layout_row : layout, - UI_ITEM_PROP_SEP_DIVIDE, true); + uiLayout *layout_split; +#ifdef UI_PROP_SEP_ICON_WIDTH_EXCEPTION + if (type == PROP_BOOLEAN && (icon == ICON_NONE) && !icon_only) { + w = UI_UNIT_X; + layout_split = uiLayoutRow(layout_row ? layout_row : layout, true); + } + else +#endif /* UI_PROP_SEP_ICON_WIDTH_EXCEPTION */ + { + layout_split = uiLayoutSplit( + layout_row ? layout_row : layout, + UI_ITEM_PROP_SEP_DIVIDE, true); + } layout_split->space = 0; uiLayout *layout_sub = uiLayoutColumn(layout_split, true); layout_sub->space = 0; @@ -3171,12 +3184,12 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem) .litem_y = litem->y, .space_x = space_x, .space_y = space_y, - }), + }), &((UILayoutGridFlowOutput) { .tot_items = &gflow->tot_items, .global_avg_w = &avg_w, .global_max_h = &max_h, - })); + })); if (gflow->tot_items == 0) { litem->w = litem->h = 0; @@ -3258,11 +3271,11 @@ static void ui_litem_estimate_grid_flow(uiLayout *litem) .space_y = space_y, .tot_columns = gflow->tot_columns, .tot_rows = gflow->tot_rows, - }), + }), &((UILayoutGridFlowOutput) { .tot_w = &tot_w, .tot_h = &tot_h, - })); + })); litem->w = tot_w; litem->h = tot_h; @@ -3306,13 +3319,13 @@ static void ui_litem_layout_grid_flow(uiLayout *litem) .space_y = space_y, .tot_columns = gflow->tot_columns, .tot_rows = gflow->tot_rows, - }), + }), &((UILayoutGridFlowOutput) { .cos_x_array = cos_x, .cos_y_array = cos_y, .widths_array = widths, .heights_array = heights, - })); + })); for (item = litem->items.first, i = 0; item; item = item->next, i++) { const int col = gflow->row_major ? i % gflow->tot_columns : i / gflow->tot_rows; diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 6fcede58737..aad48d13277 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1004,6 +1004,7 @@ static int editsource_exec(bContext *C, wmOperator *op) ui_editsource_active_but_set(but); /* redraw and get active button python info */ + ED_region_do_layout(C, ar); ED_region_do_draw(C, ar); ar->do_draw = false; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index e383ae42f8c..5d029685810 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -2254,7 +2254,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar, cons } else if (event->type == RIGHTMOUSE) { if (mouse_state == PANEL_MOUSE_INSIDE_HEADER) { - ui_panel_menu(C, ar, block->panel); + ui_popup_context_menu_for_panel(C, ar, block->panel); retval = WM_UI_HANDLER_BREAK; break; } diff --git a/source/blender/editors/interface/interface_region_hud.c b/source/blender/editors/interface/interface_region_hud.c index 569f50a9c75..1a49010ad9d 100644 --- a/source/blender/editors/interface/interface_region_hud.c +++ b/source/blender/editors/interface/interface_region_hud.c @@ -329,7 +329,10 @@ void ED_area_type_hud_ensure(bContext *C, ScrArea *sa) /* We shouldn't need to do this every time :S */ /* XXX, this is evil! - it also makes the menu show on first draw. :( */ + ARegion *ar_prev = CTX_wm_region(C); + CTX_wm_region_set((bContext *)C, ar); hud_region_layout(C, ar); + CTX_wm_region_set((bContext *)C, ar_prev); } /** \} */ diff --git a/source/blender/editors/interface/interface_region_menu_popup.c b/source/blender/editors/interface/interface_region_menu_popup.c index a6046e551c6..b9222a75803 100644 --- a/source/blender/editors/interface/interface_region_menu_popup.c +++ b/source/blender/editors/interface/interface_region_menu_popup.c @@ -458,6 +458,21 @@ void UI_popup_menu_end(bContext *C, uiPopupMenu *pup) MEM_freeN(pup); } +bool UI_popup_menu_end_or_cancel(bContext *C, uiPopupMenu *pup) +{ + if (!UI_block_is_empty(pup->block)) { + UI_popup_menu_end(C, pup); + return true; + } + else { + UI_block_layout_resolve(pup->block, NULL, NULL); + MEM_freeN(pup->block->handle); + UI_block_free(C, pup->block); + MEM_freeN(pup); + return false; + } +} + uiLayout *UI_popup_menu_layout(uiPopupMenu *pup) { return pup->layout; diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 22487f29977..c2bea466015 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1356,8 +1356,7 @@ static uiLayout *draw_modifier( UI_block_emboss_set(block, UI_EMBOSS); /* modifier name */ - md->scene = scene; - if (mti->isDisabled && mti->isDisabled(md, 0)) { + if (mti->isDisabled && mti->isDisabled(scene, md, 0)) { uiLayoutSetRedAlert(row, true); } uiItemR(row, &ptr, "name", 0, "", ICON_NONE); @@ -1748,7 +1747,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* enabled */ UI_block_emboss_set(block, UI_EMBOSS_NONE); uiItemR(row, &ptr, "mute", 0, "", - (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF); + (con->flag & CONSTRAINT_OFF) ? ICON_HIDE_ON : ICON_HIDE_OFF); UI_block_emboss_set(block, UI_EMBOSS); uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT); @@ -4263,18 +4262,18 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) /* make a box around the report to make it stand out */ UI_block_align_begin(block); - but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); + but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", 0, 0, UI_UNIT_X + 5, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); /* set the report's bg color in but->col - UI_BTYPE_ROUNDBOX feature */ rgb_float_to_uchar(but->col, rti->col); but->col[3] = 255; - but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + but = uiDefBut(block, UI_BTYPE_ROUNDBOX, 0, "", UI_UNIT_X + 5, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); - but->col[0] = but->col[1] = but->col[2] = unit_float_to_uchar_clamp(rti->grayscale); - but->col[3] = 255; UI_block_align_end(block); + UI_GetThemeColorShade3ubv(TH_BACK, 20, but->col); + but->col[3] = 255; /* icon and report message on top */ icon = UI_icon_from_report_type(report->type); @@ -4292,10 +4291,28 @@ void uiTemplateReportsBanner(uiLayout *layout, bContext *C) UI_block_emboss_set(block, UI_EMBOSS); - uiDefBut(block, UI_BTYPE_LABEL, 0, report->message, UI_UNIT_X + 10, 0, UI_UNIT_X + width, UI_UNIT_Y, + uiDefBut(block, UI_BTYPE_LABEL, 0, report->message, UI_UNIT_X + 5, 0, UI_UNIT_X + width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, ""); } + +void uiTemplateCursorKeymap(uiLayout *layout, struct bContext *C) +{ + wmWindow *win = CTX_wm_window(C); + for (int i = 0; i < 3; i++) { + uiLayout *box = uiLayoutRow(layout, true); + for (int j = 0; j < 2; j++) { + const char *msg = WM_window_cursor_keymap_status_get(win, i, j); + if ((j == 0) || (msg != NULL)) { + uiItemL(box, msg, j == 0 ? (ICON_MOUSE_LMB + i) : ICON_MOUSE_DRAG); + } + } + if (i != 2) { + uiItemSpacer(layout); + } + } +} + /********************************* Keymap *************************************/ static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(unused)) diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index 4bc3aaaf842..a6f58fc056a 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -230,16 +230,16 @@ static const uint g_shape_preset_hold_action_face[2][3] = {{2, 0, 1}, {3, 5, 4}} static const int tria_ofs[ROUNDBOX_TRIA_MAX] = { [ROUNDBOX_TRIA_NONE] = 0, [ROUNDBOX_TRIA_ARROWS] = 0, - [ROUNDBOX_TRIA_SCROLL] = 6, - [ROUNDBOX_TRIA_MENU] = 22, - [ROUNDBOX_TRIA_CHECK] = 28, - [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 34, + [ROUNDBOX_TRIA_SCROLL] = 12, + [ROUNDBOX_TRIA_MENU] = 28, + [ROUNDBOX_TRIA_CHECK] = 34, + [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 40, }; static const int tria_vcount[ROUNDBOX_TRIA_MAX] = { [ROUNDBOX_TRIA_NONE] = 0, - [ROUNDBOX_TRIA_ARROWS] = 3, + [ROUNDBOX_TRIA_ARROWS] = 6, [ROUNDBOX_TRIA_SCROLL] = 16, - [ROUNDBOX_TRIA_MENU] = 3, + [ROUNDBOX_TRIA_MENU] = 6, [ROUNDBOX_TRIA_CHECK] = 6, [ROUNDBOX_TRIA_HOLD_ACTION_ARROW] = 3, }; @@ -296,8 +296,8 @@ static uint32_t set_tria_vertex( int tria_type, int tria_v, int tria_id, int jit_v) { uint32_t *data = GWN_vertbuf_raw_step(vflag_step); - if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS, ROUNDBOX_TRIA_MENU)) { - tria_v += tria_id * 3; + if (ELEM(tria_type, ROUNDBOX_TRIA_ARROWS)) { + tria_v += tria_id * tria_vcount[ROUNDBOX_TRIA_ARROWS]; } *data = tria_ofs[tria_type] + tria_v; *data |= jit_v << 6; @@ -308,7 +308,7 @@ static uint32_t set_tria_vertex( static void roundbox_batch_add_tria(Gwn_VertBufRaw *vflag_step, int tria, uint32_t last_data) { - const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW) ? 1 : 2; + const int tria_num = ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU) ? 1 : 2; /* for each tria */ for (int t = 0; t < tria_num; ++t) { for (int j = 0; j < WIDGET_AA_JITTER; j++) { @@ -335,7 +335,7 @@ Gwn_Batch *ui_batch_roundbox_widget_get(int tria) vcount += ((WIDGET_CURVE_RESOLU * 2) * 2) * WIDGET_AA_JITTER; /* emboss */ if (tria) { vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria1 */ - if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW)) { + if (!ELEM(tria, ROUNDBOX_TRIA_CHECK, ROUNDBOX_TRIA_HOLD_ACTION_ARROW, ROUNDBOX_TRIA_MENU)) { vcount += (tria_vcount[tria] + 2) * WIDGET_AA_JITTER; /* tria2 */ } } @@ -1500,6 +1500,8 @@ float UI_text_clip_middle_ex( BLF_disable(fstyle->uifont_id, BLF_KERNING_DEFAULT); } + BLI_assert(strwidth <= okwidth); + return strwidth; } @@ -2657,18 +2659,22 @@ static void widget_state_pie_menu_item(uiWidgetType *wt, int state) copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); wt->wcol.inner[3] = 64; } - /* regular disabled */ - else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); - } - /* regular active */ - else if (state & UI_SELECT) { - copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); - } - else if (state & UI_ACTIVE) { - copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + else { + /* regular active */ + if (state & (UI_SELECT | UI_ACTIVE)) { + copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + } + else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { + /* regular disabled */ + widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); + } + + if (state & UI_SELECT) { + copy_v4_v4_char(wt->wcol.outline, wt->wcol.inner_sel); + } + else if (state & UI_ACTIVE) { + copy_v4_v4_char(wt->wcol.inner, wt->wcol.item); + } } } @@ -2685,14 +2691,19 @@ static void widget_state_menu_item(uiWidgetType *wt, int state) copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); wt->wcol.inner[3] = 64; } - /* regular disabled */ - else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { - widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); - } - /* regular active */ - else if (state & UI_ACTIVE) { - copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); - copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + else { + /* regular active */ + if (state & UI_ACTIVE) { + copy_v3_v3_char(wt->wcol.text, wt->wcol.text_sel); + } + else if (state & (UI_BUT_DISABLED | UI_BUT_INACTIVE)) { + /* regular disabled */ + widget_state_blend(wt->wcol.text, wt->wcol.inner, 0.5f); + } + + if (state & UI_ACTIVE) { + copy_v4_v4_char(wt->wcol.inner, wt->wcol.inner_sel); + } } } diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 8bd41b874f5..a04b25672de 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -48,9 +48,9 @@ #include "BKE_addon.h" #include "BKE_appdir.h" #include "BKE_colorband.h" -#include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_main.h" +#include "BKE_mesh_runtime.h" #include "BIF_gl.h" @@ -1856,9 +1856,9 @@ void init_userdef_do_versions(Main *bmain) U.fcu_inactive_alpha = 0.25f; } - /* signal for derivedmesh to use colorband */ + /* signal for evaluated mesh to use colorband */ /* run in case this was on and is now off in the user prefs [#28096] */ - vDM_ColorBand_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced); + BKE_mesh_runtime_color_band_store((U.flag & USER_CUSTOM_RANGE) ? (&U.coba_weight) : NULL, UI_GetTheme()->tv3d.vertex_unreferenced); if (!USER_VERSION_ATLEAST(192, 0)) { strcpy(U.sounddir, "/"); @@ -2920,7 +2920,7 @@ void init_userdef_do_versions(Main *bmain) U.flag &= ~( USER_FLAG_DEPRECATED_1 | USER_FLAG_DEPRECATED_2 | USER_FLAG_DEPRECATED_3 | USER_FLAG_DEPRECATED_6 | USER_FLAG_DEPRECATED_7 | - USER_FLAG_DEPRECATED_9 | USER_FLAG_DEPRECATED_10); + USER_FLAG_DEPRECATED_9 | USER_DEVELOPER_UI); U.uiflag &= ~( USER_UIFLAG_DEPRECATED_7); U.transopts &= ~( |