Blender  V2.93
interface_eyedropper_depth.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2009 Blender Foundation.
17  * All rights reserved.
18  */
19 
29 #include "MEM_guardedalloc.h"
30 
31 #include "DNA_camera_types.h"
32 #include "DNA_object_types.h"
33 #include "DNA_screen_types.h"
34 #include "DNA_space_types.h"
35 #include "DNA_view3d_types.h"
36 
37 #include "BLI_math_vector.h"
38 #include "BLI_string.h"
39 
40 #include "BKE_context.h"
41 #include "BKE_screen.h"
42 #include "BKE_unit.h"
43 
44 #include "RNA_access.h"
45 
46 #include "UI_interface.h"
47 
48 #include "WM_api.h"
49 #include "WM_types.h"
50 
51 #include "ED_screen.h"
52 #include "ED_space_api.h"
53 #include "ED_view3d.h"
54 
56 #include "interface_intern.h"
57 
61 typedef struct DepthDropper {
64  bool is_undo;
65 
66  bool is_set;
67  float init_depth; /* For resetting on cancel. */
68 
69  bool accum_start; /* Has mouse been pressed. */
70  float accum_depth;
71  int accum_tot;
72 
75  char name[200];
77 
78 static void depthdropper_draw_cb(const struct bContext *C, ARegion *region, void *arg)
79 {
80  DepthDropper *ddr = arg;
82 }
83 
85 {
86  int index_dummy;
87 
88  SpaceType *st;
89  ARegionType *art;
90 
93 
94  DepthDropper *ddr = MEM_callocN(sizeof(DepthDropper), __func__);
95 
96  uiBut *but = UI_context_active_but_prop_get(C, &ddr->ptr, &ddr->prop, &index_dummy);
97 
98  /* fallback to the active camera's dof */
99  if (ddr->prop == NULL) {
101  if (rv3d && rv3d->persp == RV3D_CAMOB) {
102  View3D *v3d = CTX_wm_view3d(C);
103  if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
104  Camera *camera = (Camera *)v3d->camera->data;
105  RNA_pointer_create(&camera->id, &RNA_CameraDOFSettings, &camera->dof, &ddr->ptr);
106  ddr->prop = RNA_struct_find_property(&ddr->ptr, "focus_distance");
107  ddr->is_undo = true;
108  }
109  }
110  }
111  else {
113  }
114 
115  if ((ddr->ptr.data == NULL) || (ddr->prop == NULL) ||
116  (RNA_property_editable(&ddr->ptr, ddr->prop) == false) ||
117  (RNA_property_type(ddr->prop) != PROP_FLOAT)) {
118  MEM_freeN(ddr);
119  return false;
120  }
121  op->customdata = ddr;
122 
123  ddr->art = art;
126  ddr->init_depth = RNA_property_float_get(&ddr->ptr, ddr->prop);
127 
128  return true;
129 }
130 
132 {
134 
135  if (op->customdata) {
136  DepthDropper *ddr = (DepthDropper *)op->customdata;
137 
138  if (ddr->art) {
140  }
141 
142  MEM_freeN(op->customdata);
143 
144  op->customdata = NULL;
145  }
146 }
147 
148 /* *** depthdropper id helper functions *** */
153  bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
154 {
155  /* we could use some clever */
156  bScreen *screen = CTX_wm_screen(C);
159 
160  ScrArea *area_prev = CTX_wm_area(C);
161  ARegion *region_prev = CTX_wm_region(C);
162 
163  ddr->name[0] = '\0';
164 
165  if (area) {
166  if (area->spacetype == SPACE_VIEW3D) {
168  if (region) {
170  View3D *v3d = area->spacedata.first;
171  RegionView3D *rv3d = region->regiondata;
172  /* weak, we could pass in some reference point */
173  const float *view_co = v3d->camera ? v3d->camera->obmat[3] : rv3d->viewinv[3];
174  const int mval[2] = {mx - region->winrct.xmin, my - region->winrct.ymin};
175  float co[3];
176 
178  CTX_wm_region_set(C, region);
179 
180  /* grr, always draw else we leave stale text */
181  ED_region_tag_redraw(region);
182 
184 
185  if (ED_view3d_autodist(depsgraph, region, v3d, mval, co, true, NULL)) {
186  const float mval_center_fl[2] = {(float)region->winx / 2, (float)region->winy / 2};
187  float co_align[3];
188 
189  /* quick way to get view-center aligned point */
190  ED_view3d_win_to_3d(v3d, region, co, mval_center_fl, co_align);
191 
192  *r_depth = len_v3v3(view_co, co_align);
193 
195  sizeof(ddr->name),
196  (double)*r_depth,
197  4,
199  &scene->unit,
200  false);
201  }
202  else {
203  BLI_strncpy(ddr->name, "Nothing under cursor", sizeof(ddr->name));
204  }
205  }
206  }
207  }
208 
209  CTX_wm_area_set(C, area_prev);
210  CTX_wm_region_set(C, region_prev);
211 }
212 
213 /* sets the sample depth RGB, maintaining A */
214 static void depthdropper_depth_set(bContext *C, DepthDropper *ddr, const float depth)
215 {
216  RNA_property_float_set(&ddr->ptr, ddr->prop, depth);
217  ddr->is_set = true;
218  RNA_property_update(C, &ddr->ptr, ddr->prop);
219 }
220 
221 /* set sample from accumulated values */
223 {
224  float depth = ddr->accum_depth;
225  if (ddr->accum_tot) {
226  depth /= (float)ddr->accum_tot;
227  }
228  depthdropper_depth_set(C, ddr, depth);
229 }
230 
231 /* single point sample & set */
232 static void depthdropper_depth_sample(bContext *C, DepthDropper *ddr, int mx, int my)
233 {
234  float depth = -1.0f;
235  if (depth != -1.0f) {
236  depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
237  depthdropper_depth_set(C, ddr, depth);
238  }
239 }
240 
241 static void depthdropper_depth_sample_accum(bContext *C, DepthDropper *ddr, int mx, int my)
242 {
243  float depth = -1.0f;
244  depthdropper_depth_sample_pt(C, ddr, mx, my, &depth);
245  if (depth != -1.0f) {
246  ddr->accum_depth += depth;
247  ddr->accum_tot++;
248  }
249 }
250 
252 {
253  DepthDropper *ddr = op->customdata;
254  if (ddr->is_set) {
255  depthdropper_depth_set(C, ddr, ddr->init_depth);
256  }
257  depthdropper_exit(C, op);
258 }
259 
260 /* main modal status check */
261 static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
262 {
263  DepthDropper *ddr = (DepthDropper *)op->customdata;
264 
265  /* handle modal keymap */
266  if (event->type == EVT_MODAL_MAP) {
267  switch (event->val) {
268  case EYE_MODAL_CANCEL:
269  depthdropper_cancel(C, op);
270  return OPERATOR_CANCELLED;
272  const bool is_undo = ddr->is_undo;
273  if (ddr->accum_tot == 0) {
274  depthdropper_depth_sample(C, ddr, event->x, event->y);
275  }
276  else {
278  }
279  depthdropper_exit(C, op);
280  /* Could support finished & undo-skip. */
281  return is_undo ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
282  }
284  /* enable accum and make first sample */
285  ddr->accum_start = true;
286  depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
287  break;
289  ddr->accum_tot = 0;
290  ddr->accum_depth = 0.0f;
291  depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
293  break;
294  }
295  }
296  else if (event->type == MOUSEMOVE) {
297  if (ddr->accum_start) {
298  /* button is pressed so keep sampling */
299  depthdropper_depth_sample_accum(C, ddr, event->x, event->y);
301  }
302  }
303 
304  return OPERATOR_RUNNING_MODAL;
305 }
306 
307 /* Modal Operator init */
308 static int depthdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
309 {
310  /* init */
311  if (depthdropper_init(C, op)) {
312  wmWindow *win = CTX_wm_window(C);
313  /* Workaround for de-activating the button clearing the cursor, see T76794 */
316 
317  /* add temp handler */
319 
320  return OPERATOR_RUNNING_MODAL;
321  }
322  return OPERATOR_CANCELLED;
323 }
324 
325 /* Repeat operator */
327 {
328  /* init */
329  if (depthdropper_init(C, op)) {
330  /* cleanup */
331  depthdropper_exit(C, op);
332 
333  return OPERATOR_FINISHED;
334  }
335  return OPERATOR_CANCELLED;
336 }
337 
339 {
340  PointerRNA ptr;
341  PropertyRNA *prop;
342  int index_dummy;
343  uiBut *but;
344 
345  /* check if there's an active button taking depth value */
346  if ((CTX_wm_window(C) != NULL) &&
347  (but = UI_context_active_but_prop_get(C, &ptr, &prop, &index_dummy)) &&
348  (but->type == UI_BTYPE_NUM) && (prop != NULL)) {
349  if ((RNA_property_type(prop) == PROP_FLOAT) &&
351  (RNA_property_array_check(prop) == false)) {
352  return true;
353  }
354  }
355  else {
357  if (rv3d && rv3d->persp == RV3D_CAMOB) {
358  View3D *v3d = CTX_wm_view3d(C);
359  if (v3d->camera && v3d->camera->data && !ID_IS_LINKED(v3d->camera->data)) {
360  return true;
361  }
362  }
363  }
364 
365  return false;
366 }
367 
369 {
370  /* identifiers */
371  ot->name = "Eyedropper Depth";
372  ot->idname = "UI_OT_eyedropper_depth";
373  ot->description = "Sample depth from the 3D view";
374 
375  /* api callbacks */
381 
382  /* flags */
384 
385  /* properties */
386 }
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:714
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
void CTX_wm_region_set(bContext *C, struct ARegion *region)
Definition: context.c:985
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct bScreen * CTX_wm_screen(const bContext *C)
Definition: context.c:709
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:725
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1401
void CTX_wm_area_set(bContext *C, struct ScrArea *area)
Definition: context.c:973
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:769
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
struct ScrArea * BKE_screen_find_area_xy(struct bScreen *screen, const int spacetype, int x, int y)
Definition: screen.c:1018
struct ARegion * BKE_area_find_region_xy(struct ScrArea *area, const int regiontype, int x, int y)
Definition: screen.c:933
struct SpaceType * BKE_spacetype_from_id(int spaceid)
Definition: screen.c:382
struct ARegionType * BKE_regiontype_from_id(const struct SpaceType *st, int regionid)
@ B_UNIT_LENGTH
Definition: BKE_unit.h:79
size_t BKE_unit_value_as_string(char *str, int len_max, double value, int prec, int type, const struct UnitSettings *settings, bool pad)
MINLINE float len_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
Object is a sort of wrapper for general info.
@ RGN_TYPE_WINDOW
@ SPACE_VIEW3D
#define SPACE_TYPE_ANY
#define RV3D_CAMOB
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:667
void * ED_region_draw_cb_activate(struct ARegionType *art, void(*draw)(const struct bContext *, struct ARegion *, void *), void *customdata, int type)
Definition: spacetypes.c:238
#define REGION_DRAW_POST_PIXEL
Definition: ED_space_api.h:67
void ED_region_draw_cb_exit(struct ARegionType *, void *)
Definition: spacetypes.c:253
bool ED_view3d_autodist(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, const int mval[2], float mouse_worldloc[3], const bool alphaoverride, const float fallback_depth_pt[3])
void ED_view3d_win_to_3d(const struct View3D *v3d, const struct ARegion *region, const float depth_pt[3], const float mval[2], float r_out[3])
void view3d_operator_needs_opengl(const struct bContext *C)
Read Guarded memory(de)allocation.
StructRNA RNA_CameraDOFSettings
@ PROP_FLOAT
Definition: RNA_types.h:75
@ PROP_UNIT_LENGTH
Definition: RNA_types.h:85
#define C
Definition: RandGen.cpp:39
@ UI_BUT_UNDO
Definition: UI_interface.h:208
void UI_context_active_but_clear(struct bContext *C, struct wmWindow *win, struct ARegion *region)
uiBut * UI_context_active_but_prop_get(const struct bContext *C, struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index)
@ UI_BTYPE_NUM
Definition: UI_interface.h:341
bool UI_but_flag_is_set(uiBut *but, int flag)
Definition: interface.c:6087
@ OPTYPE_INTERNAL
Definition: WM_types.h:175
@ OPTYPE_BLOCKING
Definition: WM_types.h:157
@ OPTYPE_UNDO
Definition: WM_types.h:155
Scene scene
const Depsgraph * depsgraph
void eyedropper_draw_cursor_text_region(const struct bContext *C, const ARegion *region, const char *name)
static void depthdropper_depth_sample_accum(bContext *C, DepthDropper *ddr, int mx, int my)
static void depthdropper_depth_set_accum(bContext *C, DepthDropper *ddr)
static int depthdropper_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
void UI_OT_eyedropper_depth(wmOperatorType *ot)
static int depthdropper_exec(bContext *C, wmOperator *op)
static void depthdropper_depth_sample_pt(bContext *C, DepthDropper *ddr, int mx, int my, float *r_depth)
get the ID from the screen.
static int depthdropper_modal(bContext *C, wmOperator *op, const wmEvent *event)
static void depthdropper_exit(bContext *C, wmOperator *op)
static void depthdropper_draw_cb(const struct bContext *C, ARegion *region, void *arg)
static void depthdropper_cancel(bContext *C, wmOperator *op)
static bool depthdropper_poll(bContext *C)
static void depthdropper_depth_sample(bContext *C, DepthDropper *ddr, int mx, int my)
static void depthdropper_depth_set(bContext *C, DepthDropper *ddr, const float depth)
struct DepthDropper DepthDropper
static int depthdropper_init(bContext *C, wmOperator *op)
@ EYE_MODAL_SAMPLE_BEGIN
@ EYE_MODAL_SAMPLE_RESET
@ EYE_MODAL_SAMPLE_CONFIRM
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
static void area(int d1, int d2, int e1, int e2, float weights[2])
float RNA_property_float_get(PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2941
bool RNA_property_array_check(PropertyRNA *prop)
Definition: rna_access.c:1223
void RNA_pointer_create(ID *id, StructRNA *type, void *data, PointerRNA *r_ptr)
Definition: rna_access.c:146
PropertyType RNA_property_type(PropertyRNA *prop)
Definition: rna_access.c:1155
PropertyRNA * RNA_struct_find_property(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:866
void RNA_property_update(bContext *C, PointerRNA *ptr, PropertyRNA *prop)
Definition: rna_access.c:2317
void RNA_property_float_set(PointerRNA *ptr, PropertyRNA *prop, float value)
Definition: rna_access.c:2964
PropertySubType RNA_property_subtype(PropertyRNA *prop)
Definition: rna_access.c:1160
bool RNA_property_editable(PointerRNA *ptr, PropertyRNA *prop_orig)
Definition: rna_access.c:2073
void * regiondata
struct CameraDOFSettings dof
float obmat[4][4]
void * data
void * data
Definition: RNA_types.h:52
float viewinv[4][4]
struct UnitSettings unit
struct Object * camera
int ymin
Definition: DNA_vec_types.h:80
int xmin
Definition: DNA_vec_types.h:79
eButType type
int y
Definition: WM_types.h:581
short val
Definition: WM_types.h:579
int x
Definition: WM_types.h:581
short type
Definition: WM_types.h:577
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
void WM_cursor_modal_set(wmWindow *win, int val)
Definition: wm_cursors.c:207
void WM_cursor_modal_restore(wmWindow *win)
Definition: wm_cursors.c:216
@ WM_CURSOR_EYEDROPPER
Definition: wm_cursors.h:51
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
@ EVT_MODAL_MAP
@ MOUSEMOVE
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156