id-data eyedropprt, currently only accessible via the Ekey,
authorCampbell Barton <ideasman42@gmail.com>
Tue, 8 Oct 2013 15:32:54 +0000 (15:32 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 8 Oct 2013 15:32:54 +0000 (15:32 +0000)
We need to investigate ways to add options like this without cluttering the interface.

source/blender/editors/interface/interface_eyedropper.c
source/blender/editors/interface/interface_handlers.c
source/blender/editors/interface/interface_intern.h
source/blender/editors/interface/interface_ops.c

index 1838381636a5393a48571445824dba718f84ba46..56dd18565dc97c1ae46ea9609288b540ccbe43df 100644 (file)
 
 #include "DNA_space_types.h"
 #include "DNA_screen_types.h"
+#include "DNA_object_types.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_math_vector.h"
 
 #include "BKE_context.h"
 #include "BKE_screen.h"
+#include "BKE_report.h"
+#include "BKE_idcode.h"
 
 #include "RNA_access.h"
 
 
 #include "IMB_colormanagement.h"
 
-#include "interface_intern.h"
-
 #include "WM_api.h"
 #include "WM_types.h"
 
+#include "interface_intern.h"
+
 /* for HDR color sampling */
 #include "ED_image.h"
 #include "ED_node.h"
 #include "ED_clip.h"
 
+/* for ID data eyedropper */
+#include "ED_space_api.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Eyedropper
+ */
 
 /** \name Eyedropper (RGB Color)
  * \{ */
@@ -329,5 +341,299 @@ void UI_OT_eyedropper_color(wmOperatorType *ot)
 
        /* properties */
 }
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/* Data Dropper
+ *
+ * note: datadropper is only internal name to avoid confusion in this file
+ */
+
+/** \name Eyedropper (ID data-blocks)
+ * \{ */
+
+typedef struct DataDropper {
+       PointerRNA ptr;
+       PropertyRNA *prop;
+       short idcode;
+       const char *idcode_name;
+
+       ARegionType *art;
+       void *draw_handle_pixel;
+       char name[200];
+} DataDropper;
+
+
+static void datadropper_draw_cb(const struct bContext *C, ARegion *ar, void *arg)
+{
+       DataDropper *ddr = arg;
+       int width;
+       const char *name = ddr->name;
+       wmWindow *win = CTX_wm_window(C);
+       int x = win->eventstate->x;
+       int y = win->eventstate->y;
+
+       if ((name[0] == '\0') ||
+           (BLI_rcti_isect_pt(&ar->winrct, x, y) == false))
+       {
+               return;
+       }
+
+       width = UI_GetStringWidth(name);
+       x = x - ar->winrct.xmin;
+       y = y - ar->winrct.ymin;
+
+       y += 20;
+
+       glColor4ub(0, 0, 0, 50);
+
+       uiSetRoundBox(UI_CNR_ALL | UI_RB_ALPHA);
+       uiRoundBox(x, y, x + width + 8, y + 15, 4);
+
+       glColor4ub(255, 255, 255, 255);
+       UI_DrawString(x + 4, y + 4, name);
+}
+
+
+static int datadropper_init(bContext *C, wmOperator *op)
+{
+       DataDropper *ddr;
+       int index_dummy;
+       StructRNA *type;
+
+       SpaceType *st;
+       ARegionType *art;
+
+       st = BKE_spacetype_from_id(SPACE_VIEW3D);
+       art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW);
+
+       op->customdata = ddr = MEM_callocN(sizeof(DataDropper), "DataDropper");
+
+       uiContextActiveProperty(C, &ddr->ptr, &ddr->prop, &index_dummy);
+
+       if ((ddr->ptr.data == NULL) ||
+           (ddr->prop == NULL) ||
+           (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
+           (RNA_property_type(ddr->prop) != PROP_POINTER))
+       {
+               return false;
+       }
+
+       ddr->art = art;
+       ddr->draw_handle_pixel = ED_region_draw_cb_activate(art, datadropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL);
+
+       type = RNA_property_pointer_type(&ddr->ptr, ddr->prop);
+       ddr->idcode = RNA_type_to_ID_code(type);
+       BLI_assert(ddr->idcode != 0);
+       ddr->idcode_name = BKE_idcode_to_name(ddr->idcode);
+
+       return true;
+}
+
+static void datadropper_exit(bContext *C, wmOperator *op)
+{
+       DataDropper *ddr = (DataDropper *)op->customdata;
+
+       WM_cursor_modal_restore(CTX_wm_window(C));
+
+       ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel);
+
+       if (op->customdata)
+               MEM_freeN(op->customdata);
+       op->customdata = NULL;
+}
+
+static int datadropper_cancel(bContext *C, wmOperator *op)
+{
+       datadropper_exit(C, op);
+       return OPERATOR_CANCELLED;
+}
+
+/* *** datadropper id helper functions *** */
+/**
+ * \brief get the ID from the screen.
+ *
+ */
+static void datadropper_id_sample_pt(bContext *C, DataDropper *ddr, int mx, int my, ID **r_id)
+{
+
+       /* we could use some clever */
+       wmWindow *win = CTX_wm_window(C);
+       ScrArea *sa;
+
+       ScrArea *area_prev = CTX_wm_area(C);
+       ARegion *ar_prev = CTX_wm_region(C);
+
+       ddr->name[0] = '\0';
+
+       for (sa = win->screen->areabase.first; sa; sa = sa->next) {
+               if (BLI_rcti_isect_pt(&sa->totrct, mx, my)) {
+                       if (sa->spacetype == SPACE_VIEW3D) {
+                               ARegion *ar = BKE_area_find_region_type(sa, RGN_TYPE_WINDOW);
+                               if (ar && BLI_rcti_isect_pt(&ar->winrct, mx, my)) {
+                                       int mval[2] = {mx - ar->winrct.xmin,
+                                                      my - ar->winrct.ymin};
+                                       Base *base;
+
+                                       CTX_wm_area_set(C, sa);
+                                       CTX_wm_region_set(C, ar);
+
+                                       /* grr, always draw else we leave stale text */
+                                       ED_region_tag_redraw(ar);
+
+                                       base = ED_view3d_give_base_under_cursor(C, mval);
+                                       if (base) {
+                                               Object *ob = base->object;
+                                               ID *id = NULL;
+                                               if (ddr->idcode == ID_OB) {
+                                                       id = (ID *)ob;
+                                               }
+                                               else if (ob->data) {
+                                                       if (GS(((ID *)ob->data)->name) == ddr->idcode) {
+                                                               id = (ID *)ob->data;
+                                                       }
+                                                       else {
+                                                               BLI_snprintf(ddr->name, sizeof(ddr->name), "Incompatible, expected a %s",
+                                                                            ddr->idcode_name);
+                                                       }
+                                               }
+
+                                               if (id) {
+                                                       BLI_snprintf(ddr->name, sizeof(ddr->name), "%s: %s",
+                                                                    ddr->idcode_name, id->name + 2);
+                                                       *r_id = id;
+                                               }
+
+                                               break;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       CTX_wm_area_set(C, area_prev);
+       CTX_wm_region_set(C, ar_prev);
+}
+
+/* sets the ID, returns success */
+static bool datadropper_id_set(bContext *C, DataDropper *ddr, ID *id)
+{
+       PointerRNA ptr_value;
+
+       RNA_id_pointer_create(id, &ptr_value);
+
+       RNA_property_pointer_set(&ddr->ptr, ddr->prop, ptr_value);
+
+       RNA_property_update(C, &ddr->ptr, ddr->prop);
+
+       ptr_value = RNA_property_pointer_get(&ddr->ptr, ddr->prop);
+
+       return (ptr_value.id.data == id);
+}
+
+/* single point sample & set */
+static bool datadropper_id_sample(bContext *C, DataDropper *ddr, int mx, int my)
+{
+       ID *id = NULL;
+
+       datadropper_id_sample_pt(C, ddr, mx, my, &id);
+       return datadropper_id_set(C, ddr, id);
+}
+
+/* main modal status check */
+static int datadropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+       DataDropper *ddr = (DataDropper *)op->customdata;
+
+       switch (event->type) {
+               case ESCKEY:
+               case RIGHTMOUSE:
+                       return datadropper_cancel(C, op);
+               case LEFTMOUSE:
+                       if (event->val == KM_RELEASE) {
+                               bool success;
+
+                               success = datadropper_id_sample(C, ddr, event->x, event->y);
+                               datadropper_exit(C, op);
+
+                               if (success) {
+                                       return OPERATOR_FINISHED;
+                               }
+                               else {
+                                       BKE_report(op->reports, RPT_WARNING, "Failed to set value");
+                                       return OPERATOR_CANCELLED;
+                               }
+                       }
+                       break;
+               case MOUSEMOVE:
+               {
+                       ID *id = NULL;
+                       datadropper_id_sample_pt(C, ddr, event->x, event->y, &id);
+                       break;
+               }
+       }
+
+       return OPERATOR_RUNNING_MODAL;
+}
+
+/* Modal Operator init */
+static int datadropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+       /* init */
+       if (datadropper_init(C, op)) {
+               WM_cursor_modal_set(CTX_wm_window(C), BC_EYEDROPPER_CURSOR);
+
+               /* add temp handler */
+               WM_event_add_modal_handler(C, op);
+
+               return OPERATOR_RUNNING_MODAL;
+       }
+       else {
+               datadropper_exit(C, op);
+               return OPERATOR_CANCELLED;
+       }
+}
+
+/* Repeat operator */
+static int datadropper_exec(bContext *C, wmOperator *op)
+{
+       /* init */
+       if (datadropper_init(C, op)) {
+               /* cleanup */
+               datadropper_exit(C, op);
+
+               return OPERATOR_FINISHED;
+       }
+       else {
+               return OPERATOR_CANCELLED;
+       }
+}
+
+static int datadropper_poll(bContext *C)
+{
+       if (!CTX_wm_window(C)) return 0;
+       else return 1;
+}
+
+void UI_OT_eyedropper_id(wmOperatorType *ot)
+{
+       /* identifiers */
+       ot->name = "Eyedropper Datablock";
+       ot->idname = "UI_OT_eyedropper_id";
+       ot->description = "Sample a color from the Blender Window to store in a property";
+
+       /* api callbacks */
+       ot->invoke = datadropper_invoke;
+       ot->modal = datadropper_modal;
+       ot->cancel = datadropper_cancel;
+       ot->exec = datadropper_exec;
+       ot->poll = datadropper_poll;
+
+       /* flags */
+       ot->flag = OPTYPE_BLOCKING;
+
+       /* properties */
+}
 
 /** \} */
index 77eb4a81928586012971beb4689c0d2b7ccaea2d..c5faa99e06776a479f5c3a363e4d2e44f11f9791 100644 (file)
@@ -5415,6 +5415,16 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
                                        WM_operator_name_call(C, "UI_OT_eyedropper_color", WM_OP_INVOKE_DEFAULT, NULL);
                                        return WM_UI_HANDLER_BREAK;
                                }
+                               else if (but->type == SEARCH_MENU_UNLINK) {
+                                       if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_POINTER) {
+                                               StructRNA *type = RNA_property_pointer_type(&but->rnapoin, but->rnaprop);
+                                               const short idcode = RNA_type_to_ID_code(type);
+                                               if ((idcode == ID_OB) || OB_DATA_SUPPORT_ID(idcode)) {
+                                                       WM_operator_name_call(C, "UI_OT_eyedropper_id", WM_OP_INVOKE_DEFAULT, NULL);
+                                                       return WM_UI_HANDLER_BREAK;
+                                               }
+                                       }
+                               }
                        }
                }
                /* handle keyframing */
index a8f712944981508690058a47055be6068e87900f..9cc16d82810b8dfe8b321509bfe1963358180403 100644 (file)
@@ -586,5 +586,6 @@ void ui_but_anim_autokey(struct bContext *C, uiBut *but, struct Scene *scene, fl
 
 /* interface_eyedropper.c */
 void UI_OT_eyedropper_color(struct wmOperatorType *ot);
+void UI_OT_eyedropper_id(struct wmOperatorType *ot);
 
 #endif  /* __INTERFACE_INTERN_H__ */
index 1c00479acaf226d595244e9afc00a701759e8ef5..36e965e13d2b44254c83a11d66d5d36051d21dfe 100644 (file)
@@ -843,4 +843,5 @@ void UI_buttons_operatortypes(void)
 
        /* external */
        WM_operatortype_append(UI_OT_eyedropper_color);
+       WM_operatortype_append(UI_OT_eyedropper_id);
 }