From 3f3d82cfe9cefe4bfd9da3d283dec4a1923ec22d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 20 May 2022 14:30:17 +1000 Subject: UI support for showing candidates for string properties Currently strings are used for cases where a list of identifiers would be useful to show. Add support for string properties to reference a callback to populate candidates to show when editing a string. The user isn't prevented from typing in text not found in this list, it's just useful as a reference. Support for expanding the following strings has been added: - Operator, menu & panel identifiers in the keymap editor. - WM operators that reference data-paths expand using the Python-consoles auto-complete functionality. - Names of keying sets for insert/delete keyframe operators. Details: - `bpy.props.StringProperty` takes an option `search` callback. - A new string callback has been added, set via `RNA_def_property_string_search_func` or `RNA_def_property_string_search_func_runtime`. - Addresses usability issue highlighted by T89560, where setting keying set identifiers as strings isn't practical. - Showing additional right-aligned text in the search results is supported but disabled by default as the text is too cramped in most string search popups where the feature would make sense. It could be enabled as part of other layout tweaks. Reviewed By: brecht Ref D14986 --- source/blender/editors/animation/keyframing.c | 4 ++ source/blender/editors/animation/keyingsets.c | 66 +++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) (limited to 'source/blender/editors/animation') diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 14a3b958ea6..941125b9ad5 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -2051,6 +2051,8 @@ void ANIM_OT_keyframe_insert_by_name(wmOperatorType *ot) /* keyingset to use (idname) */ prop = RNA_def_string( ot->srna, "type", NULL, MAX_ID_NAME - 2, "Keying Set", "The Keying Set to use"); + RNA_def_property_string_search_func_runtime( + prop, ANIM_keyingset_visit_for_search_no_poll, PROP_STRING_SEARCH_SUGGESTION); RNA_def_property_flag(prop, PROP_HIDDEN); ot->prop = prop; } @@ -2246,6 +2248,8 @@ void ANIM_OT_keyframe_delete_by_name(wmOperatorType *ot) /* keyingset to use (idname) */ prop = RNA_def_string( ot->srna, "type", NULL, MAX_ID_NAME - 2, "Keying Set", "The Keying Set to use"); + RNA_def_property_string_search_func_runtime( + prop, ANIM_keyingset_visit_for_search_no_poll, PROP_STRING_SEARCH_SUGGESTION); RNA_def_property_flag(prop, PROP_HIDDEN); ot->prop = prop; } diff --git a/source/blender/editors/animation/keyingsets.c b/source/blender/editors/animation/keyingsets.c index 6fcdd21bad8..97b81277008 100644 --- a/source/blender/editors/animation/keyingsets.c +++ b/source/blender/editors/animation/keyingsets.c @@ -708,6 +708,72 @@ KeyingSet *ANIM_get_keyingset_for_autokeying(const Scene *scene, const char *tra return ANIM_builtin_keyingset_get_named(NULL, transformKSName); } +static void anim_keyingset_visit_for_search_impl(const bContext *C, + StringPropertySearchVisitFunc visit_fn, + void *visit_user_data, + const bool use_poll) +{ + /* Poll requires context. */ + if (use_poll && (C == NULL)) { + return; + } + + Scene *scene = C ? CTX_data_scene(C) : NULL; + KeyingSet *ks; + + /* Active Keying Set. */ + if (!use_poll || (scene && scene->active_keyingset)) { + StringPropertySearchVisitParams visit_params = {NULL}; + visit_params.text = "__ACTIVE__"; + visit_params.info = "Active Keying Set"; + visit_fn(visit_user_data, &visit_params); + } + + /* User-defined Keying Sets. */ + if (scene && scene->keyingsets.first) { + for (ks = scene->keyingsets.first; ks; ks = ks->next) { + if (use_poll && !ANIM_keyingset_context_ok_poll((bContext *)C, ks)) { + continue; + } + StringPropertySearchVisitParams visit_params = {NULL}; + visit_params.text = ks->idname; + visit_params.info = ks->name; + visit_fn(visit_user_data, &visit_params); + } + } + + /* Builtin Keying Sets. */ + for (ks = builtin_keyingsets.first; ks; ks = ks->next) { + if (use_poll && !ANIM_keyingset_context_ok_poll((bContext *)C, ks)) { + continue; + } + StringPropertySearchVisitParams visit_params = {NULL}; + visit_params.text = ks->idname; + visit_params.info = ks->name; + visit_fn(visit_user_data, &visit_params); + } +} + +void ANIM_keyingset_visit_for_search(const bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + const char *UNUSED(edit_text), + StringPropertySearchVisitFunc visit_fn, + void *visit_user_data) +{ + anim_keyingset_visit_for_search_impl(C, visit_fn, visit_user_data, false); +} + +void ANIM_keyingset_visit_for_search_no_poll(const bContext *C, + PointerRNA *UNUSED(ptr), + PropertyRNA *UNUSED(prop), + const char *UNUSED(edit_text), + StringPropertySearchVisitFunc visit_fn, + void *visit_user_data) +{ + anim_keyingset_visit_for_search_impl(C, visit_fn, visit_user_data, true); +} + /* Menu of All Keying Sets ----------------------------- */ const EnumPropertyItem *ANIM_keying_sets_enum_itemf(bContext *C, -- cgit v1.2.3