Blender  V3.3
view3d_navigate_zoom_border.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "DNA_camera_types.h"
8 
9 #include "MEM_guardedalloc.h"
10 
11 #include "BLI_math.h"
12 #include "BLI_rect.h"
13 
14 #include "BKE_context.h"
15 #include "BKE_report.h"
16 
17 #include "DEG_depsgraph_query.h"
18 
19 #include "WM_api.h"
20 
21 #include "RNA_access.h"
22 
23 #include "view3d_intern.h"
24 #include "view3d_navigate.h" /* own include */
25 
26 /* -------------------------------------------------------------------- */
31 {
32  ARegion *region = CTX_wm_region(C);
33  View3D *v3d = CTX_wm_view3d(C);
35  const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
36 
37  /* Zooms in on a border drawn by the user */
38  rcti rect;
39  float dvec[3], vb[2], xscale, yscale;
40  float dist_range[2];
41 
42  /* SMOOTHVIEW */
43  float new_dist;
44  float new_ofs[3];
45 
46  /* ZBuffer depth vars */
47  float depth_close = FLT_MAX;
48  float cent[2], p[3];
49 
50  /* NOTE: otherwise opengl won't work. */
52 
53  /* get box select values using rna */
55 
56  /* check if zooming in/out view */
57  const bool zoom_in = !RNA_boolean_get(op->ptr, "zoom_out");
58 
59  ED_view3d_dist_range_get(v3d, dist_range);
60 
63  {
64  /* avoid allocating the whole depth buffer */
65  ViewDepths depth_temp = {0};
66 
67  /* avoid view3d_update_depths() for speed. */
68  view3d_depths_rect_create(region, &rect, &depth_temp);
69 
70  /* find the closest Z pixel */
71  depth_close = view3d_depth_near(&depth_temp);
72 
73  MEM_SAFE_FREE(depth_temp.depths);
74  }
75 
76  /* Resize border to the same ratio as the window. */
77  {
78  const float region_aspect = (float)region->winx / (float)region->winy;
79  if (((float)BLI_rcti_size_x(&rect) / (float)BLI_rcti_size_y(&rect)) < region_aspect) {
80  BLI_rcti_resize_x(&rect, (int)(BLI_rcti_size_y(&rect) * region_aspect));
81  }
82  else {
83  BLI_rcti_resize_y(&rect, (int)(BLI_rcti_size_x(&rect) / region_aspect));
84  }
85  }
86 
87  cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
88  cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
89 
90  if (rv3d->is_persp) {
91  float p_corner[3];
92 
93  /* no depths to use, we can't do anything! */
94  if (depth_close == FLT_MAX) {
95  BKE_report(op->reports, RPT_ERROR, "Depth too large");
96  return OPERATOR_CANCELLED;
97  }
98  /* convert border to 3d coordinates */
99  if ((!ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) ||
100  (!ED_view3d_unproject_v3(region, rect.xmin, rect.ymin, depth_close, p_corner))) {
101  return OPERATOR_CANCELLED;
102  }
103 
104  sub_v3_v3v3(dvec, p, p_corner);
105  negate_v3_v3(new_ofs, p);
106 
107  new_dist = len_v3(dvec);
108 
109  /* Account for the lens, without this a narrow lens zooms in too close. */
110  new_dist *= (v3d->lens / DEFAULT_SENSOR_WIDTH);
111 
112  /* ignore dist_range min */
113  dist_range[0] = v3d->clip_start * 1.5f;
114  }
115  else { /* orthographic */
116  /* find the current window width and height */
117  vb[0] = region->winx;
118  vb[1] = region->winy;
119 
120  new_dist = rv3d->dist;
121 
122  /* convert the drawn rectangle into 3d space */
123  if (depth_close != FLT_MAX &&
124  ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p)) {
125  negate_v3_v3(new_ofs, p);
126  }
127  else {
128  float xy_delta[2];
129  float zfac;
130 
131  /* We can't use the depth, fallback to the old way that doesn't set the center depth */
132  copy_v3_v3(new_ofs, rv3d->ofs);
133 
134  {
135  float tvec[3];
136  negate_v3_v3(tvec, new_ofs);
137  zfac = ED_view3d_calc_zfac(rv3d, tvec);
138  }
139 
140  xy_delta[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f;
141  xy_delta[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f;
142  ED_view3d_win_to_delta(region, xy_delta, zfac, dvec);
143  /* center the view to the center of the rectangle */
144  sub_v3_v3(new_ofs, dvec);
145  }
146 
147  /* work out the ratios, so that everything selected fits when we zoom */
148  xscale = (BLI_rcti_size_x(&rect) / vb[0]);
149  yscale = (BLI_rcti_size_y(&rect) / vb[1]);
150  new_dist *= max_ff(xscale, yscale);
151  }
152 
153  if (!zoom_in) {
154  sub_v3_v3v3(dvec, new_ofs, rv3d->ofs);
155  new_dist = rv3d->dist * (rv3d->dist / new_dist);
156  add_v3_v3v3(new_ofs, rv3d->ofs, dvec);
157  }
158 
159  /* clamp after because we may have been zooming out */
160  CLAMP(new_dist, dist_range[0], dist_range[1]);
161 
162  const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
163  if (rv3d->persp == RV3D_CAMOB) {
165  if (is_camera_lock) {
167  }
168  else {
170  }
171  }
172 
174  v3d,
175  region,
176  smooth_viewtx,
177  &(const V3D_SmoothParams){
178  .ofs = new_ofs,
179  .dist = &new_dist,
180  .undo_str = op->type->name,
181  });
182 
183  if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
185  }
186 
187  return OPERATOR_FINISHED;
188 }
189 
191 {
192  /* identifiers */
193  ot->name = "Zoom to Border";
194  ot->description = "Zoom in the view to the nearest object contained in the border";
195  ot->idname = "VIEW3D_OT_zoom_border";
196 
197  /* api callbacks */
202 
204 
205  /* flags */
206  ot->flag = 0;
207 
208  /* properties */
210 }
211 
typedef float(TangentPoint)[2]
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
struct RegionView3D * CTX_wm_region_view3d(const bContext *C)
Definition: context.c:793
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
MINLINE float max_ff(float a, float b)
MINLINE void sub_v3_v3(float r[3], const float a[3])
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE void negate_v3_v3(float r[3], const float a[3])
MINLINE void add_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE float len_v3(const float a[3]) ATTR_WARN_UNUSED_RESULT
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
Definition: BLI_rect.h:190
void BLI_rcti_resize_y(struct rcti *rect, int y)
Definition: rct.c:593
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition: BLI_rect.h:186
void BLI_rcti_resize_x(struct rcti *rect, int x)
Definition: rct.c:587
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
#define DEFAULT_SENSOR_WIDTH
#define RV3D_LOCK_FLAGS(rv3d)
#define RV3D_CAMOB
@ RV3D_BOXVIEW
#define RV3D_PERSP
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
bool ED_view3d_camera_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d)
void ED_view3d_win_to_delta(const struct ARegion *region, const float xy_delta[2], float zfac, float r_out[3])
void ED_view3d_dist_range_get(const struct View3D *v3d, float r_dist_range[2])
bool ED_view3d_unproject_v3(const struct ARegion *region, float regionx, float regiony, float regionz, float world[3])
@ V3D_DEPTH_NO_GPENCIL
Definition: ED_view3d.h:182
void ED_view3d_persp_switch_from_camera(const struct Depsgraph *depsgraph, struct View3D *v3d, struct RegionView3D *rv3d, char persp)
float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3])
void ED_view3d_camera_lock_init(const struct Depsgraph *depsgraph, struct View3D *v3d, struct RegionView3D *rv3d)
void view3d_operator_needs_opengl(const struct bContext *C)
void ED_view3d_depth_override(struct Depsgraph *depsgraph, struct ARegion *region, struct View3D *v3d, struct Object *obact, eV3DDepthOverrideMode mode, struct ViewDepths **r_depths)
Definition: view3d_draw.c:2294
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Bright Control the brightness and contrast of the input color Vector Map an input vectors to used to fine tune the interpolation of the input Camera Retrieve information about the camera and how it relates to the current shading point s position CLAMP
#define C
Definition: RandGen.cpp:25
const Depsgraph * depsgraph
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
float clip_start
float * depths
Definition: ED_view3d.h:80
int ymin
Definition: DNA_vec_types.h:64
int ymax
Definition: DNA_vec_types.h:64
int xmin
Definition: DNA_vec_types.h:63
int xmax
Definition: DNA_vec_types.h:63
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:927
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
void view3d_depths_rect_create(ARegion *region, rcti *rect, ViewDepths *r_d)
Definition: view3d_draw.c:2206
float view3d_depth_near(ViewDepths *d)
Definition: view3d_draw.c:2271
void view3d_boxview_sync(struct ScrArea *area, struct ARegion *region)
Definition: view3d_utils.c:890
bool view3d_zoom_or_dolly_poll(bContext *C)
void ED_view3d_smooth_view(struct bContext *C, struct View3D *v3d, struct ARegion *region, int smooth_viewtx, const V3D_SmoothParams *sview)
void VIEW3D_OT_zoom_border(wmOperatorType *ot)
static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_gesture_box_cancel(bContext *C, wmOperator *op)
int WM_gesture_box_invoke(bContext *C, wmOperator *op, const wmEvent *event)
int WM_gesture_box_modal(bContext *C, wmOperator *op, const wmEvent *event)
void WM_operator_properties_border_to_rcti(struct wmOperator *op, rcti *rect)
void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot)
int WM_operator_smooth_viewtx_get(const wmOperator *op)