Blender V4.3
view3d_navigate_zoom_border.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "DNA_camera_types.h"
10
11#include "MEM_guardedalloc.h"
12
13#include "BLI_math_vector.h"
14#include "BLI_rect.h"
15
16#include "BKE_context.hh"
17#include "BKE_report.hh"
18
19#include "WM_api.hh"
20
21#include "RNA_access.hh"
22
23#include "view3d_intern.hh"
24#include "view3d_navigate.hh" /* own include */
25
26/* -------------------------------------------------------------------- */
29
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
62 region,
63 v3d,
64 nullptr,
66 true,
67 nullptr);
68 {
69 /* avoid allocating the whole depth buffer */
70 ViewDepths depth_temp = {0};
71
72 /* avoid view3d_update_depths() for speed. */
73 view3d_depths_rect_create(region, &rect, &depth_temp);
74
75 /* find the closest Z pixel */
76 depth_close = view3d_depth_near(&depth_temp);
77
78 MEM_SAFE_FREE(depth_temp.depths);
79 }
80
81 /* Resize border to the same ratio as the window. */
82 {
83 const float region_aspect = float(region->winx) / float(region->winy);
84 if ((float(BLI_rcti_size_x(&rect)) / float(BLI_rcti_size_y(&rect))) < region_aspect) {
85 BLI_rcti_resize_x(&rect, int(BLI_rcti_size_y(&rect) * region_aspect));
86 }
87 else {
88 BLI_rcti_resize_y(&rect, int(BLI_rcti_size_x(&rect) / region_aspect));
89 }
90 }
91
92 cent[0] = (float(rect.xmin) + float(rect.xmax)) / 2;
93 cent[1] = (float(rect.ymin) + float(rect.ymax)) / 2;
94
95 if (rv3d->is_persp) {
96 float p_corner[3];
97
98 /* no depths to use, we can't do anything! */
99 if (depth_close == FLT_MAX) {
100 BKE_report(op->reports, RPT_ERROR, "Depth too large");
101 return OPERATOR_CANCELLED;
102 }
103 /* convert border to 3d coordinates */
104 if (!ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p) ||
105 !ED_view3d_unproject_v3(region, rect.xmin, rect.ymin, depth_close, p_corner))
106 {
107 return OPERATOR_CANCELLED;
108 }
109
110 sub_v3_v3v3(dvec, p, p_corner);
111 negate_v3_v3(new_ofs, p);
112
113 new_dist = len_v3(dvec);
114
115 /* Account for the lens, without this a narrow lens zooms in too close. */
116 new_dist *= (v3d->lens / DEFAULT_SENSOR_WIDTH);
117
118 /* ignore dist_range min */
119 dist_range[0] = v3d->clip_start * 1.5f;
120 }
121 else { /* orthographic */
122 /* find the current window width and height */
123 vb[0] = region->winx;
124 vb[1] = region->winy;
125
126 new_dist = rv3d->dist;
127
128 /* convert the drawn rectangle into 3d space */
129 if (depth_close != FLT_MAX && ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p))
130 {
131 negate_v3_v3(new_ofs, p);
132 }
133 else {
134 float xy_delta[2];
135 float zfac;
136
137 /* We can't use the depth, fallback to the old way that doesn't set the center depth */
138 copy_v3_v3(new_ofs, rv3d->ofs);
139
140 {
141 float tvec[3];
142 negate_v3_v3(tvec, new_ofs);
143 zfac = ED_view3d_calc_zfac(rv3d, tvec);
144 }
145
146 xy_delta[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f;
147 xy_delta[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f;
148 ED_view3d_win_to_delta(region, xy_delta, zfac, dvec);
149 /* center the view to the center of the rectangle */
150 sub_v3_v3(new_ofs, dvec);
151 }
152
153 /* work out the ratios, so that everything selected fits when we zoom */
154 xscale = (BLI_rcti_size_x(&rect) / vb[0]);
155 yscale = (BLI_rcti_size_y(&rect) / vb[1]);
156 new_dist *= max_ff(xscale, yscale);
157 }
158
159 if (!zoom_in) {
160 sub_v3_v3v3(dvec, new_ofs, rv3d->ofs);
161 new_dist = rv3d->dist * (rv3d->dist / new_dist);
162 add_v3_v3v3(new_ofs, rv3d->ofs, dvec);
163 }
164
165 /* clamp after because we may have been zooming out */
166 CLAMP(new_dist, dist_range[0], dist_range[1]);
167
168 const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
169 if (rv3d->persp == RV3D_CAMOB) {
171 if (is_camera_lock) {
173 }
174 else {
176 }
177 }
178 V3D_SmoothParams sview_params = {};
179 sview_params.ofs = new_ofs;
180 sview_params.dist = &new_dist;
181 sview_params.undo_str = op->type->name;
182
183 ED_view3d_smooth_view(C, v3d, region, smooth_viewtx, &sview_params);
184
185 if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
187 }
188
189 return OPERATOR_FINISHED;
190}
191
193{
194 /* identifiers */
195 ot->name = "Zoom to Border";
196 ot->description = "Zoom in the view to the nearest object contained in the border";
197 ot->idname = "VIEW3D_OT_zoom_border";
198
199 /* api callbacks */
200 ot->invoke = WM_gesture_box_invoke;
202 ot->modal = WM_gesture_box_modal;
203 ot->cancel = WM_gesture_box_cancel;
204
206
207 /* flags */
208 ot->flag = 0;
209
210 /* properties */
212}
213
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
RegionView3D * CTX_wm_region_view3d(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition report.cc:125
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:193
void BLI_rcti_resize_y(struct rcti *rect, int y)
Definition rct.c:609
BLI_INLINE int BLI_rcti_size_x(const struct rcti *rct)
Definition BLI_rect.h:189
void BLI_rcti_resize_x(struct rcti *rect, int x)
Definition rct.c:603
#define CLAMP(a, b, c)
#define DEFAULT_SENSOR_WIDTH
#define RV3D_LOCK_FLAGS(rv3d)
@ RV3D_CAMOB
@ RV3D_PERSP
@ RV3D_BOXVIEW
void ED_view3d_depth_override(Depsgraph *depsgraph, ARegion *region, View3D *v3d, Object *obact, eV3DDepthOverrideMode mode, bool use_overlay, ViewDepths **r_depths)
void ED_view3d_persp_switch_from_camera(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d, char persp)
void ED_view3d_dist_range_get(const View3D *v3d, float r_dist_range[2])
void ED_view3d_win_to_delta(const ARegion *region, const float xy_delta[2], float zfac, float r_out[3])
bool ED_view3d_unproject_v3(const ARegion *region, float regionx, float regiony, float regionz, float world[3])
void view3d_operator_needs_opengl(const bContext *C)
float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3])
@ V3D_DEPTH_NO_GPENCIL
Definition ED_view3d.hh:188
bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
BPy_StructRNA * depsgraph
draw_view in_light_buf[] float
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
#define FLT_MAX
Definition stdcycles.h:14
const char * undo_str
float clip_start
float * depths
Definition ED_view3d.hh:85
int ymin
int ymax
int xmin
int xmax
const char * name
Definition WM_types.hh:990
struct ReportList * reports
struct wmOperatorType * type
struct PointerRNA * ptr
void view3d_depths_rect_create(ARegion *region, rcti *rect, ViewDepths *r_d)
float view3d_depth_near(ViewDepths *d)
void view3d_boxview_sync(ScrArea *area, ARegion *region)
bool view3d_zoom_or_dolly_poll(bContext *C)
void ED_view3d_smooth_view(bContext *C, View3D *v3d, 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.cc:4125
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(wmOperator *op, rcti *r_rect)
void WM_operator_properties_gesture_box_zoom(wmOperatorType *ot)
int WM_operator_smooth_viewtx_get(const wmOperator *op)