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
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/* -------------------------------------------------------------------- */
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 CTX_data_ensure_evaluated_depsgraph(C), region, v3d, nullptr, V3D_DEPTH_NO_GPENCIL, nullptr);
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 {
102 return OPERATOR_CANCELLED;
103 }
104
105 sub_v3_v3v3(dvec, p, p_corner);
106 negate_v3_v3(new_ofs, p);
107
108 new_dist = len_v3(dvec);
109
110 /* Account for the lens, without this a narrow lens zooms in too close. */
111 new_dist *= (v3d->lens / DEFAULT_SENSOR_WIDTH);
112
113 /* ignore dist_range min */
114 dist_range[0] = v3d->clip_start * 1.5f;
115 }
116 else { /* orthographic */
117 /* find the current window width and height */
118 vb[0] = region->winx;
119 vb[1] = region->winy;
120
121 new_dist = rv3d->dist;
122
123 /* convert the drawn rectangle into 3d space */
124 if (depth_close != FLT_MAX && ED_view3d_unproject_v3(region, cent[0], cent[1], depth_close, p))
125 {
126 negate_v3_v3(new_ofs, p);
127 }
128 else {
129 float xy_delta[2];
130 float zfac;
131
132 /* We can't use the depth, fallback to the old way that doesn't set the center depth */
133 copy_v3_v3(new_ofs, rv3d->ofs);
134
135 {
136 float tvec[3];
137 negate_v3_v3(tvec, new_ofs);
138 zfac = ED_view3d_calc_zfac(rv3d, tvec);
139 }
140
141 xy_delta[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f;
142 xy_delta[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f;
143 ED_view3d_win_to_delta(region, xy_delta, zfac, dvec);
144 /* center the view to the center of the rectangle */
145 sub_v3_v3(new_ofs, dvec);
146 }
147
148 /* work out the ratios, so that everything selected fits when we zoom */
149 xscale = (BLI_rcti_size_x(&rect) / vb[0]);
150 yscale = (BLI_rcti_size_y(&rect) / vb[1]);
151 new_dist *= max_ff(xscale, yscale);
152 }
153
154 if (!zoom_in) {
155 sub_v3_v3v3(dvec, new_ofs, rv3d->ofs);
156 new_dist = rv3d->dist * (rv3d->dist / new_dist);
157 add_v3_v3v3(new_ofs, rv3d->ofs, dvec);
158 }
159
160 /* clamp after because we may have been zooming out */
161 CLAMP(new_dist, dist_range[0], dist_range[1]);
162
163 const bool is_camera_lock = ED_view3d_camera_lock_check(v3d, rv3d);
164 if (rv3d->persp == RV3D_CAMOB) {
166 if (is_camera_lock) {
168 }
169 else {
171 }
172 }
173 V3D_SmoothParams sview_params = {};
174 sview_params.ofs = new_ofs;
175 sview_params.dist = &new_dist;
176 sview_params.undo_str = op->type->name;
177
178 ED_view3d_smooth_view(C, v3d, region, smooth_viewtx, &sview_params);
179
180 if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
182 }
183
184 return OPERATOR_FINISHED;
185}
186
188{
189 /* identifiers */
190 ot->name = "Zoom to Border";
191 ot->description = "Zoom in the view to the nearest object contained in the border";
192 ot->idname = "VIEW3D_OT_zoom_border";
193
194 /* api callbacks */
199
201
202 /* flags */
203 ot->flag = 0;
204
205 /* properties */
207}
208
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_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_depth_override(Depsgraph *depsgraph, ARegion *region, View3D *v3d, Object *obact, eV3DDepthOverrideMode mode, ViewDepths **r_depths)
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)
const Depsgraph * 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
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* modal)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1036
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
void(* cancel)(bContext *C, wmOperator *op)
Definition WM_types.hh:1028
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)