| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is Copyright (C) 2009 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup edinterface | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |  * | 
					
						
							|  |  |  |  * This file defines an eyedropper for picking 3D depth value (primary use is depth-of-field). | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Defines: | 
					
						
							|  |  |  |  * - #UI_OT_eyedropper_depth | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-11 17:53:13 +02:00
										 |  |  | #include "DNA_camera_types.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_screen_types.h"
 | 
					
						
							|  |  |  | #include "DNA_space_types.h"
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | #include "DNA_view3d_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_math_vector.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "BLI_string.h"
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_screen.h"
 | 
					
						
							|  |  |  | #include "BKE_unit.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "RNA_access.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "UI_interface.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ED_screen.h"
 | 
					
						
							|  |  |  | #include "ED_space_api.h"
 | 
					
						
							|  |  |  | #include "ED_view3d.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "interface_eyedropper_intern.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "interface_intern.h"
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * \note #DepthDropper is only internal name to avoid confusion with other kinds of eye-droppers. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | typedef struct DepthDropper { | 
					
						
							|  |  |  |   PointerRNA ptr; | 
					
						
							|  |  |  |   PropertyRNA *prop; | 
					
						
							| 
									
										
										
										
											2019-01-17 16:39:38 +11:00
										 |  |  |   bool is_undo; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-18 09:31:39 +11:00
										 |  |  |   bool is_set; | 
					
						
							| 
									
										
										
										
											2021-02-05 16:23:34 +11:00
										 |  |  |   float init_depth; /* For resetting on cancel. */ | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-05 16:23:34 +11:00
										 |  |  |   bool accum_start; /* Has mouse been pressed. */ | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   float accum_depth; | 
					
						
							|  |  |  |   int accum_tot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   ARegionType *art; | 
					
						
							|  |  |  |   void *draw_handle_pixel; | 
					
						
							|  |  |  |   char name[200]; | 
					
						
							|  |  |  | } DepthDropper; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-06 16:56:42 +01:00
										 |  |  | static void depthdropper_draw_cb(const struct bContext *C, ARegion *region, void *arg) | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   DepthDropper *ddr = arg; | 
					
						
							| 
									
										
										
										
											2021-03-17 08:48:05 +01:00
										 |  |  |   eyedropper_draw_cursor_text_region(C, region, ddr->name); | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int depthdropper_init(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   int index_dummy; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   SpaceType *st; | 
					
						
							|  |  |  |   ARegionType *art; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   st = BKE_spacetype_from_id(SPACE_VIEW3D); | 
					
						
							|  |  |  |   art = BKE_regiontype_from_id(st, RGN_TYPE_WINDOW); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-17 15:43:00 +11:00
										 |  |  |   DepthDropper *ddr = MEM_callocN(sizeof(DepthDropper), __func__); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-17 16:39:38 +11:00
										 |  |  |   uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   /* fallback to the active camera's dof */ | 
					
						
							|  |  |  |   if (ddr->prop == NULL) { | 
					
						
							|  |  |  |     RegionView3D *rv3d = CTX_wm_region_view3d(C); | 
					
						
							|  |  |  |     if (rv3d && rv3d->persp == RV3D_CAMOB) { | 
					
						
							|  |  |  |       View3D *v3d = CTX_wm_view3d(C); | 
					
						
							|  |  |  |       if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) { | 
					
						
							| 
									
										
										
										
											2019-07-11 17:53:13 +02:00
										 |  |  |         Camera *camera = (Camera *)v3d->camera->data; | 
					
						
							|  |  |  |         RNA_pointer_create(&camera->id, &RNA_CameraDOFSettings, &camera->dof, &ddr->ptr); | 
					
						
							|  |  |  |         ddr->prop = RNA_struct_find_property(&ddr->ptr, "focus_distance"); | 
					
						
							| 
									
										
										
										
											2019-01-23 16:41:40 +11:00
										 |  |  |         ddr->is_undo = true; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-01-23 16:41:40 +11:00
										 |  |  |   else { | 
					
						
							|  |  |  |     ddr->is_undo = UI_but_flag_is_set(but, UI_BUT_UNDO); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   if ((ddr->ptr.data == NULL) || (ddr->prop == NULL) || | 
					
						
							|  |  |  |       (RNA_property_editable(&ddr->ptr, ddr->prop) == false) || | 
					
						
							|  |  |  |       (RNA_property_type(ddr->prop) != PROP_FLOAT)) { | 
					
						
							| 
									
										
										
										
											2019-01-17 15:43:00 +11:00
										 |  |  |     MEM_freeN(ddr); | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-01-17 15:43:00 +11:00
										 |  |  |   op->customdata = ddr; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   ddr->art = art; | 
					
						
							|  |  |  |   ddr->draw_handle_pixel = ED_region_draw_cb_activate( | 
					
						
							|  |  |  |       art, depthdropper_draw_cb, ddr, REGION_DRAW_POST_PIXEL); | 
					
						
							|  |  |  |   ddr->init_depth = RNA_property_float_get(&ddr->ptr, ddr->prop); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void depthdropper_exit(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   WM_cursor_modal_restore(CTX_wm_window(C)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (op->customdata) { | 
					
						
							|  |  |  |     DepthDropper *ddr = (DepthDropper *)op->customdata; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (ddr->art) { | 
					
						
							|  |  |  |       ED_region_draw_cb_exit(ddr->art, ddr->draw_handle_pixel); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     MEM_freeN(op->customdata); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     op->customdata = NULL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* *** depthdropper id helper functions *** */ | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * \brief get the ID from the screen. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void depthdropper_depth_sample_pt( | 
					
						
							|  |  |  |     bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* we could use some clever */ | 
					
						
							| 
									
										
										
										
											2017-12-12 16:13:06 +11:00
										 |  |  |   bScreen *screen = CTX_wm_screen(C); | 
					
						
							| 
									
										
										
										
											2020-04-03 13:25:03 +02:00
										 |  |  |   ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my); | 
					
						
							| 
									
										
										
										
											2017-12-12 16:13:06 +11:00
										 |  |  |   Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   ScrArea *area_prev = CTX_wm_area(C); | 
					
						
							| 
									
										
										
										
											2020-04-03 12:51:03 +02:00
										 |  |  |   ARegion *region_prev = CTX_wm_region(C); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   ddr->name[0] = '\0'; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 13:25:03 +02:00
										 |  |  |   if (area) { | 
					
						
							|  |  |  |     if (area->spacetype == SPACE_VIEW3D) { | 
					
						
							|  |  |  |       ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my); | 
					
						
							| 
									
										
										
										
											2020-03-06 16:56:42 +01:00
										 |  |  |       if (region) { | 
					
						
							| 
									
										
										
										
											2019-07-25 16:36:22 +02:00
										 |  |  |         struct Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C); | 
					
						
							| 
									
										
										
										
											2020-04-03 13:25:03 +02:00
										 |  |  |         View3D *v3d = area->spacedata.first; | 
					
						
							| 
									
										
										
										
											2020-03-06 16:56:42 +01:00
										 |  |  |         RegionView3D *rv3d = region->regiondata; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |         /* weak, we could pass in some reference point */ | 
					
						
							|  |  |  |         const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3]; | 
					
						
							| 
									
										
										
										
											2020-03-06 16:56:42 +01:00
										 |  |  |         const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin}; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |         float co[3]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-03 13:25:03 +02:00
										 |  |  |         CTX_wm_area_set(C, area); | 
					
						
							| 
									
										
										
										
											2020-03-06 16:56:42 +01:00
										 |  |  |         CTX_wm_region_set(C, region); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |         /* grr, always draw else we leave stale text */ | 
					
						
							| 
									
										
										
										
											2020-03-06 16:56:42 +01:00
										 |  |  |         ED_region_tag_redraw(region); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |         view3d_operator_needs_opengl(C); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-06 16:56:42 +01:00
										 |  |  |         if (ED_view3d_autodist(depsgraph, region, v3d, mval, co, true, NULL)) { | 
					
						
							|  |  |  |           const float mval_center_fl[2] = {(float)region->winx / 2, (float)region->winy / 2}; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |           float co_align[3]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |           /* quick way to get view-center aligned point */ | 
					
						
							| 
									
										
										
										
											2020-03-06 16:56:42 +01:00
										 |  |  |           ED_view3d_win_to_3d(v3d, region, co, mval_center_fl, co_align); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |           *r_depth = len_v3v3(view_co, co_align); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-09 08:41:15 -05:00
										 |  |  |           BKE_unit_value_as_string(ddr->name, | 
					
						
							|  |  |  |                                    sizeof(ddr->name), | 
					
						
							|  |  |  |                                    (double)*r_depth, | 
					
						
							|  |  |  |                                    4, | 
					
						
							|  |  |  |                                    B_UNIT_LENGTH, | 
					
						
							|  |  |  |                                    &scene->unit, | 
					
						
							|  |  |  |                                    false); | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   CTX_wm_area_set(C, area_prev); | 
					
						
							| 
									
										
										
										
											2020-04-03 12:51:03 +02:00
										 |  |  |   CTX_wm_region_set(C, region_prev); | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* sets the sample depth RGB, maintaining A */ | 
					
						
							|  |  |  | static void depthdropper_depth_set(bContext *C, DepthDropper *ddr, const float depth) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   RNA_property_float_set(&ddr->ptr, ddr->prop, depth); | 
					
						
							| 
									
										
										
										
											2019-01-18 09:31:39 +11:00
										 |  |  |   ddr->is_set = true; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   RNA_property_update(C, &ddr->ptr, ddr->prop); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* set sample from accumulated values */ | 
					
						
							|  |  |  | static void depthdropper_depth_set_accum(bContext *C, DepthDropper *ddr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float depth = ddr->accum_depth; | 
					
						
							|  |  |  |   if (ddr->accum_tot) { | 
					
						
							|  |  |  |     depth /= (float)ddr->accum_tot; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   depthdropper_depth_set(C, ddr, depth); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* single point sample & set */ | 
					
						
							|  |  |  | static void depthdropper_depth_sample(bContext *C, DepthDropper *ddr, int mx, int my) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float depth = -1.0f; | 
					
						
							|  |  |  |   if (depth != -1.0f) { | 
					
						
							|  |  |  |     depthdropper_depth_sample_pt(C, ddr, mx, my, &depth); | 
					
						
							|  |  |  |     depthdropper_depth_set(C, ddr, depth); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void depthdropper_depth_sample_accum(bContext *C, DepthDropper *ddr, int mx, int my) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   float depth = -1.0f; | 
					
						
							|  |  |  |   depthdropper_depth_sample_pt(C, ddr, mx, my, &depth); | 
					
						
							|  |  |  |   if (depth != -1.0f) { | 
					
						
							|  |  |  |     ddr->accum_depth += depth; | 
					
						
							|  |  |  |     ddr->accum_tot++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void depthdropper_cancel(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DepthDropper *ddr = op->customdata; | 
					
						
							| 
									
										
										
										
											2019-01-18 09:31:39 +11:00
										 |  |  |   if (ddr->is_set) { | 
					
						
							|  |  |  |     depthdropper_depth_set(C, ddr, ddr->init_depth); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   depthdropper_exit(C, op); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* main modal status check */ | 
					
						
							|  |  |  | static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   DepthDropper *ddr = (DepthDropper *)op->customdata; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   /* handle modal keymap */ | 
					
						
							|  |  |  |   if (event->type == EVT_MODAL_MAP) { | 
					
						
							|  |  |  |     switch (event->val) { | 
					
						
							|  |  |  |       case EYE_MODAL_CANCEL: | 
					
						
							|  |  |  |         depthdropper_cancel(C, op); | 
					
						
							|  |  |  |         return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |       case EYE_MODAL_SAMPLE_CONFIRM: { | 
					
						
							| 
									
										
										
										
											2019-01-17 16:39:38 +11:00
										 |  |  |         const bool is_undo = ddr->is_undo; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |         if (ddr->accum_tot == 0) { | 
					
						
							|  |  |  |           depthdropper_depth_sample(C, ddr, event->x, event->y); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |           depthdropper_depth_set_accum(C, ddr); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         depthdropper_exit(C, op); | 
					
						
							| 
									
										
										
										
											2019-01-17 16:39:38 +11:00
										 |  |  |         /* Could support finished & undo-skip. */ | 
					
						
							|  |  |  |         return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |       case EYE_MODAL_SAMPLE_BEGIN: | 
					
						
							|  |  |  |         /* enable accum and make first sample */ | 
					
						
							|  |  |  |         ddr->accum_start = true; | 
					
						
							|  |  |  |         depthdropper_depth_sample_accum(C, ddr, event->x, event->y); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       case EYE_MODAL_SAMPLE_RESET: | 
					
						
							|  |  |  |         ddr->accum_tot = 0; | 
					
						
							|  |  |  |         ddr->accum_depth = 0.0f; | 
					
						
							|  |  |  |         depthdropper_depth_sample_accum(C, ddr, event->x, event->y); | 
					
						
							|  |  |  |         depthdropper_depth_set_accum(C, ddr); | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (event->type == MOUSEMOVE) { | 
					
						
							|  |  |  |     if (ddr->accum_start) { | 
					
						
							|  |  |  |       /* button is pressed so keep sampling */ | 
					
						
							|  |  |  |       depthdropper_depth_sample_accum(C, ddr, event->x, event->y); | 
					
						
							|  |  |  |       depthdropper_depth_set_accum(C, ddr); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   return OPERATOR_RUNNING_MODAL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Modal Operator init */ | 
					
						
							|  |  |  | static int depthdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* init */ | 
					
						
							|  |  |  |   if (depthdropper_init(C, op)) { | 
					
						
							| 
									
										
										
										
											2020-05-20 22:04:59 +10:00
										 |  |  |     wmWindow *win = CTX_wm_window(C); | 
					
						
							|  |  |  |     /* Workaround for de-activating the button clearing the cursor, see T76794 */ | 
					
						
							|  |  |  |     UI_context_active_but_clear(C, win, CTX_wm_region(C)); | 
					
						
							|  |  |  |     WM_cursor_modal_set(win, WM_CURSOR_EYEDROPPER); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |     /* add temp handler */ | 
					
						
							|  |  |  |     WM_event_add_modal_handler(C, op); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |     return OPERATOR_RUNNING_MODAL; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:10 +02:00
										 |  |  |   return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Repeat operator */ | 
					
						
							|  |  |  | static int depthdropper_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* init */ | 
					
						
							|  |  |  |   if (depthdropper_init(C, op)) { | 
					
						
							|  |  |  |     /* cleanup */ | 
					
						
							|  |  |  |     depthdropper_exit(C, op); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |     return OPERATOR_FINISHED; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2020-07-03 14:20:10 +02:00
										 |  |  |   return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 11:47:00 +02:00
										 |  |  | static bool depthdropper_poll(bContext *C) | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | { | 
					
						
							|  |  |  |   PointerRNA ptr; | 
					
						
							|  |  |  |   PropertyRNA *prop; | 
					
						
							|  |  |  |   int index_dummy; | 
					
						
							|  |  |  |   uiBut *but; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   /* check if there's an active button taking depth value */ | 
					
						
							|  |  |  |   if ((CTX_wm_window(C) != NULL) && | 
					
						
							|  |  |  |       (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) && | 
					
						
							|  |  |  |       (but->type == UI_BTYPE_NUM) && (prop != NULL)) { | 
					
						
							|  |  |  |     if ((RNA_property_type(prop) == PROP_FLOAT) && | 
					
						
							|  |  |  |         (RNA_property_subtype(prop) & PROP_UNIT_LENGTH) && | 
					
						
							|  |  |  |         (RNA_property_array_check(prop) == false)) { | 
					
						
							| 
									
										
										
										
											2020-09-02 19:10:18 +02:00
										 |  |  |       return true; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     RegionView3D *rv3d = CTX_wm_region_view3d(C); | 
					
						
							|  |  |  |     if (rv3d && rv3d->persp == RV3D_CAMOB) { | 
					
						
							|  |  |  |       View3D *v3d = CTX_wm_view3d(C); | 
					
						
							|  |  |  |       if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) { | 
					
						
							| 
									
										
										
										
											2020-09-02 19:10:18 +02:00
										 |  |  |         return true; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-02 19:10:18 +02:00
										 |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void UI_OT_eyedropper_depth(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Eyedropper Depth"; | 
					
						
							|  |  |  |   ot->idname = "UI_OT_eyedropper_depth"; | 
					
						
							|  |  |  |   ot->description = "Sample depth from the 3D view"; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->invoke = depthdropper_invoke; | 
					
						
							|  |  |  |   ot->modal = depthdropper_modal; | 
					
						
							|  |  |  |   ot->cancel = depthdropper_cancel; | 
					
						
							|  |  |  |   ot->exec = depthdropper_exec; | 
					
						
							|  |  |  |   ot->poll = depthdropper_poll; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   /* flags */ | 
					
						
							| 
									
										
										
										
											2019-01-17 16:39:38 +11:00
										 |  |  |   ot->flag = OPTYPE_UNDO | OPTYPE_BLOCKING | OPTYPE_INTERNAL; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-12 15:16:13 +11:00
										 |  |  |   /* properties */ | 
					
						
							|  |  |  | } |