Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/interface/interface_ops.c')
-rw-r--r--source/blender/editors/interface/interface_ops.c150
1 files changed, 150 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index d2bed210f9c..cc609216e9a 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,153 @@ 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 {
+ /* Make optional. */
+ const bool reveal_hidden = true;
+ /* Select and activate the target. */
+ if (target_type == &RNA_Bone) {
+ ok = ED_object_jump_to_bone(C, base->object, bone_name, reveal_hidden);
+ }
+ else if (target_type == &RNA_Object) {
+ ok = ED_object_jump_to_object(C, base->object, reveal_hidden);
+ }
+ 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 +1559,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