[Bf-blender-cvs] [d227c58e3ec] blender2.8: UI: support jumping to target object/bone
Alexander Gavrilov
noreply at git.blender.org
Tue Nov 20 07:39:00 CET 2018
Commit: d227c58e3ec2020683d9b7e8280f5e48350fd1fd
Author: Alexander Gavrilov
Date: Tue Nov 20 17:34:56 2018 +1100
Branches: blender2.8
https://developer.blender.org/rBd227c58e3ec2020683d9b7e8280f5e48350fd1fd
UI: support jumping to target object/bone
Complex rigs are built from many bones (often overlapping)
connected by constraints.
When investigating or debugging such rigs one often wants to switch to
the target of a constraint, or a parent bone, but it is difficult to do
manually due to overlap confusion.
This adds a right click menu option that automatically selects
and makes the target object or bone active for UI fields where a
suitable reference is readily available.
===================================================================
M source/blender/editors/include/ED_object.h
M source/blender/editors/interface/interface_context_menu.c
M source/blender/editors/interface/interface_handlers.c
M source/blender/editors/interface/interface_ops.c
M source/blender/editors/object/object_select.c
===================================================================
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 29047f02e5a..37b27c461ae 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -302,6 +302,11 @@ const struct EnumPropertyItem *ED_object_vgroup_selection_itemf_helper(
void ED_object_check_force_modifiers(
struct Main *bmain, struct Scene *scene, struct Object *object);
+struct Base *ED_object_find_first_by_data_id(struct ViewLayer *view_layer, struct ID *id);
+
+bool ED_object_jump_to_object(struct bContext *C, struct Object *ob);
+bool ED_object_jump_to_bone(struct bContext *C, struct Object *ob, const char *bone_name);
+
/* object_facemap_ops.c */
void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum);
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 03d941c2387..0ffc97444e1 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -361,7 +361,12 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_DEFAULT);
}
- if (but->type == UI_BTYPE_TAB) {
+ const bool is_disabled = but->flag & UI_BUT_DISABLED;
+
+ if (is_disabled) {
+ /* Suppress editing commands. */
+ }
+ else if (but->type == UI_BTYPE_TAB) {
uiButTab *tab = (uiButTab *)but;
if (tab->menu) {
UI_menutype_draw(C, tab->menu, layout);
@@ -639,6 +644,17 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
}
}
+ /* Pointer properties and string properties with prop_search support jumping to target object/bone. */
+ if (but->rnapoin.data && but->rnaprop) {
+ const PropertyType type = RNA_property_type(but->rnaprop);
+
+ if ((type == PROP_POINTER) || (type == PROP_STRING && but->type == UI_BTYPE_SEARCH_MENU && but->search_func == ui_rna_collection_search_cb)) {
+ uiItemO(layout, CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Jump To Target"),
+ ICON_NONE, "UI_OT_jump_to_target_button");
+ uiItemS(layout);
+ }
+ }
+
/* Favorites Menu */
if (ui_but_is_user_menu_compatible(C, but)) {
uiBlock *block = uiLayoutGetBlock(layout);
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index fffc28d1cdf..2f84045a73f 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -6614,6 +6614,17 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
return WM_UI_HANDLER_BREAK;
}
+ /* handle menu */
+ if ((event->type == RIGHTMOUSE) &&
+ !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
+ (event->val == KM_PRESS))
+ {
+ /* RMB has two options now */
+ if (ui_popup_context_menu_for_button(C, but)) {
+ return WM_UI_HANDLER_BREAK;
+ }
+ }
+
if (is_disabled) {
return WM_UI_HANDLER_CONTINUE;
}
@@ -6627,16 +6638,6 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
if (event->type == EVT_DROP) {
ui_but_drop(C, event, but, data);
}
- /* handle menu */
- else if ((event->type == RIGHTMOUSE) &&
- !IS_EVENT_MOD(event, shift, ctrl, alt, oskey) &&
- (event->val == KM_PRESS))
- {
- /* RMB has two options now */
- if (ui_popup_context_menu_for_button(C, but)) {
- return WM_UI_HANDLER_BREAK;
- }
- }
}
if (but->flag & UI_BUT_DISABLED) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index d2bed210f9c..0b35961483e 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -31,6 +31,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_armature_types.h"
#include "DNA_screen_types.h"
#include "DNA_text_types.h" /* for UI_OT_reports_to_text */
#include "DNA_object_types.h" /* for OB_DATA_SUPPORT_ID */
@@ -65,6 +66,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_object.h"
#include "ED_paint.h"
/* only for UI_OT_editsource */
@@ -802,6 +804,151 @@ static void UI_OT_copy_to_selected_button(wmOperatorType *ot)
RNA_def_boolean(ot->srna, "all", true, "All", "Copy to selected all elements of the array");
}
+
+/* -------------------------------------------------------------------- */
+/** \name Jump to Target Operator
+ * \{ */
+
+/** Jump to the object or bone referenced by the pointer, or check if it is possible. */
+static bool jump_to_target_ptr(bContext *C, PointerRNA ptr, const bool poll)
+{
+ if (RNA_pointer_is_null(&ptr)) {
+ return false;
+ }
+
+ /* Verify pointer type. */
+ char bone_name[MAXBONENAME];
+ const StructRNA *target_type = NULL;
+
+ if (ELEM(ptr.type, &RNA_EditBone, &RNA_PoseBone, &RNA_Bone)) {
+ RNA_string_get(&ptr, "name", bone_name);
+ if (bone_name[0] != '\0') {
+ target_type = &RNA_Bone;
+ }
+ }
+ else if (RNA_struct_is_a(ptr.type, &RNA_Object)) {
+ target_type = &RNA_Object;
+ }
+
+ if (target_type == NULL) {
+ return false;
+ }
+
+ /* Find the containing Object. */
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Base *base = NULL;
+ const short id_type = GS(((ID *)ptr.id.data)->name);
+ if (id_type == ID_OB) {
+ base = BKE_view_layer_base_find(view_layer, ptr.id.data);
+ }
+ else if (OB_DATA_SUPPORT_ID(id_type)) {
+ base = ED_object_find_first_by_data_id(view_layer, ptr.id.data);
+ }
+
+ bool ok = false;
+ if ((base == NULL) ||
+ ((target_type == &RNA_Bone) && (base->object->type != OB_ARMATURE)))
+ {
+ /* pass */
+ }
+ else if (poll) {
+ ok = true;
+ }
+ else {
+ /* Select and activate the target. */
+ if (target_type == &RNA_Bone) {
+ ok = ED_object_jump_to_bone(C, base->object, bone_name);
+ }
+ else if (target_type == &RNA_Object) {
+ ok = ED_object_jump_to_object(C, base->object);
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ return ok;
+}
+
+/**
+ * Jump to the object or bone referred to by the current UI field value.
+ *
+ * \note quite heavy for a poll callback, but the operator is only
+ * used as a right click menu item for certain UI field types, and
+ * this will fail quickly if the context is completely unsuitable.
+ */
+static bool jump_to_target_button(bContext *C, bool poll)
+{
+ PointerRNA ptr, target_ptr;
+ PropertyRNA *prop;
+ int index;
+
+ UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+ /* If there is a valid property... */
+ if (ptr.data && prop) {
+ const PropertyType type = RNA_property_type(prop);
+
+ /* For pointer properties, use their value directly. */
+ if (type == PROP_POINTER) {
+ target_ptr = RNA_property_pointer_get(&ptr, prop);
+
+ return jump_to_target_ptr(C, target_ptr, poll);
+ }
+ /* For string properties with prop_search, look up the search collection item. */
+ else if (type == PROP_STRING) {
+ const uiBut *but = UI_context_active_but_get(C);
+
+ if (but->type == UI_BTYPE_SEARCH_MENU && but->search_func == ui_rna_collection_search_cb) {
+ uiRNACollectionSearch *coll_search = but->search_arg;
+
+ char str_buf[MAXBONENAME];
+ char *str_ptr = RNA_property_string_get_alloc(&ptr, prop, str_buf, sizeof(str_buf), NULL);
+
+ int found = RNA_property_collection_lookup_string(&coll_search->search_ptr, coll_search->search_prop, str_ptr, &target_ptr);
+
+ if (str_ptr != str_buf) {
+ MEM_freeN(str_ptr);
+ }
+
+ if (found) {
+ return jump_to_target_ptr(C, target_ptr, poll);
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+static bool jump_to_target_button_poll(bContext *C)
+{
+ return jump_to_target_button(C, true);
+}
+
+static int jump_to_target_button_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ bool success = jump_to_target_button(C, false);
+
+ return (success) ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
+}
+
+static void UI_OT_jump_to_target_button(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Jump To Target";
+ ot->idname = "UI_OT_jump_to_target_button";
+ ot->description = "Switch to the target object or bone";
+
+ /* callbacks */
+ ot->poll = jump_to_target_button_poll;
+ ot->exec = jump_to_target_button_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+/** \} */
+
/* Reports to Textblock Operator ------------------------ */
/* FIXME: this is just a temporary operator so that we can see all the reports somewhere
@@ -1410,6 +1557,7 @@ void ED_operatortypes_ui(void)
WM_operatortype_append(UI_OT_override_type_set_button);
WM_operatortype_append(UI_OT_override_remove_button);
WM_operatortype_append(UI_OT_copy_to_selected_button);
+ WM_operatortype_append(UI_OT_jump_to_target_button);
WM_operatortype_append(UI_OT_reports_to_textblock); /* XXX: temp? */
WM_operatortype_append(UI_OT_drop_color);
#ifdef WITH_PYTHON
diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c
index c4c86c0bd72..8a82fb2bf06 100644
--- a/source/blender/editors/object/object_select.c
+++ b/source/blender/editors/object/object_select.c
@@ -51,6 +51,8 @@
#include "BLT_translation.h"
+#include "BKE_action.h"
+#include "BKE_armature.h"
#include "BKE_collection.h"
#include "BKE_context.h"
#include "BKE_deform.h"
@@ -70,6 +72,7 @@
#include "WM_api.h"
#include "WM_types.h"
+#include "ED_armature.h"
#include "ED_object.h"
#include "ED_screen.h"
#include "ED_select_utils.h"
@@ -159,6 +162,165 @@ void ED_object_base_activate(bContext *C, Base *base)
DEG_id_tag_update(&CTX_data_scene(C)->id, DEG_TAG_SELECT_UPDATE);
}
+/********************** Jump To Object Utilities **********************/
+
+static int get_base_select_priority(Base *base)
+{
+ if (base->flag & BASE_VISIBLE) {
+ if (base->flag & BASE_SELECTABLE) {
+ return 3;
+ }
+ else {
+ return 2;
+ }
+ }
+ else {
+ return 1;
+ }
+}
+
+/**
+ * If id is not already an Object, try to find an object that uses it as data.
+ * Prefers active, then selected, then visible/selectable.
+ */
+Base *ED_object_find_first_by_data_id(ViewLayer *view_layer
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list