Blender  V3.3
view3d_navigate_dolly.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BLI_math.h"
8 
9 #include "BKE_context.h"
10 #include "BKE_report.h"
11 
12 #include "DEG_depsgraph.h"
13 
14 #include "WM_api.h"
15 
16 #include "RNA_access.h"
17 
18 #include "ED_screen.h"
19 
20 #include "view3d_intern.h"
21 #include "view3d_navigate.h" /* own include */
22 
23 /* -------------------------------------------------------------------- */
30 /* This is an exact copy of #viewzoom_modal_keymap. */
32 {
33  static const EnumPropertyItem modal_items[] = {
34  {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
35 
36  {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
37  {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
38 
39  {0, NULL, 0, NULL, NULL},
40  };
41 
42  wmKeyMap *keymap = WM_modalkeymap_find(keyconf, "View3D Dolly Modal");
43 
44  /* this function is called for each spacetype, only needs to add map once */
45  if (keymap && keymap->modal_items) {
46  return;
47  }
48 
49  keymap = WM_modalkeymap_ensure(keyconf, "View3D Dolly Modal", modal_items);
50 
51  /* disabled mode switching for now, can re-implement better, later on */
52 #if 0
54  &(const KeyMapItem_Params){
55  .type = LEFTMOUSE,
56  .value = KM_RELEASE,
57  .modifier = KM_ANY,
58  .direction = KM_ANY,
59  },
62  &(const KeyMapItem_Params){
63  .type = EVT_LEFTCTRLKEY,
64  .value = KM_RELEASE,
65  .modifier = KM_ANY,
66  .direction = KM_ANY,
67  },
70  &(const KeyMapItem_Params){
71  .type = EVT_LEFTSHIFTKEY,
72  .value = KM_PRESS,
73  .modifier = KM_ANY,
74  .direction = KM_ANY,
75  },
77 #endif
78 
79  /* assign map to operators */
80  WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
81 }
82 
84 {
85  View3D *v3d = CTX_wm_view3d(C);
87  if (ED_view3d_offset_lock_check(v3d, rv3d)) {
88  BKE_report(op->reports, RPT_WARNING, "Cannot dolly when the view offset is locked");
89  return true;
90  }
91  return false;
92 }
93 
94 static void view_dolly_to_vector_3d(ARegion *region,
95  const float orig_ofs[3],
96  const float dvec[3],
97  float dfac)
98 {
99  RegionView3D *rv3d = region->regiondata;
100  madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
101 }
102 
103 static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const bool zoom_invert)
104 {
105  float zfac = 1.0;
106 
107  {
108  float len1, len2;
109 
110  if (U.uiflag & USER_ZOOM_HORIZ) {
111  len1 = (vod->region->winrct.xmax - xy[0]) + 5;
112  len2 = (vod->region->winrct.xmax - vod->init.event_xy[0]) + 5;
113  }
114  else {
115  len1 = (vod->region->winrct.ymax - xy[1]) + 5;
116  len2 = (vod->region->winrct.ymax - vod->init.event_xy[1]) + 5;
117  }
118  if (zoom_invert) {
119  SWAP(float, len1, len2);
120  }
121 
122  zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist);
123  }
124 
125  if (zfac != 1.0f) {
126  view_dolly_to_vector_3d(vod->region, vod->init.ofs, vod->init.mousevec, zfac);
127  }
128 
129  if (RV3D_LOCK_FLAGS(vod->rv3d) & RV3D_BOXVIEW) {
130  view3d_boxview_sync(vod->area, vod->region);
131  }
132 
133  ED_view3d_camera_lock_sync(vod->depsgraph, vod->v3d, vod->rv3d);
134 
136 }
137 
138 static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
139 {
140  ViewOpsData *vod = op->customdata;
141  short event_code = VIEW_PASS;
142  bool use_autokey = false;
144 
145  /* execute the events */
146  if (event->type == MOUSEMOVE) {
147  event_code = VIEW_APPLY;
148  }
149  else if (event->type == EVT_MODAL_MAP) {
150  switch (event->val) {
151  case VIEW_MODAL_CONFIRM:
152  event_code = VIEW_CONFIRM;
153  break;
155  WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP_INVOKE_DEFAULT, NULL, event);
156  event_code = VIEW_CONFIRM;
157  break;
159  WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_OP_INVOKE_DEFAULT, NULL, event);
160  event_code = VIEW_CONFIRM;
161  break;
162  }
163  }
164  else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
165  event_code = VIEW_CONFIRM;
166  }
167 
168  if (event_code == VIEW_APPLY) {
169  viewdolly_apply(vod, event->xy, (U.uiflag & USER_ZOOM_INVERT) != 0);
171  use_autokey = true;
172  }
173  }
174  else if (event_code == VIEW_CONFIRM) {
175  use_autokey = true;
177  }
178 
179  if (use_autokey) {
180  ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
181  }
182 
183  if (ret & OPERATOR_FINISHED) {
184  ED_view3d_camera_lock_undo_push(op->type->name, vod->v3d, vod->rv3d, C);
185  viewops_data_free(C, vod);
186  op->customdata = NULL;
187  }
188 
189  return ret;
190 }
191 
193 {
194  View3D *v3d;
195  RegionView3D *rv3d;
196  ScrArea *area;
197  ARegion *region;
198  float mousevec[3];
199 
200  const int delta = RNA_int_get(op->ptr, "delta");
201 
202  if (op->customdata) {
203  ViewOpsData *vod = op->customdata;
204 
205  area = vod->area;
206  region = vod->region;
207  copy_v3_v3(mousevec, vod->init.mousevec);
208  }
209  else {
210  area = CTX_wm_area(C);
211  region = CTX_wm_region(C);
212  negate_v3_v3(mousevec, ((RegionView3D *)region->regiondata)->viewinv[2]);
213  normalize_v3(mousevec);
214  }
215 
216  v3d = area->spacedata.first;
217  rv3d = region->regiondata;
218 
219  const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
220 
221  /* overwrite the mouse vector with the view direction (zoom into the center) */
222  if ((use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
223  normalize_v3_v3(mousevec, rv3d->viewinv[2]);
224  negate_v3(mousevec);
225  }
226 
227  view_dolly_to_vector_3d(region, rv3d->ofs, mousevec, delta < 0 ? 1.8f : 0.2f);
228 
229  if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
230  view3d_boxview_sync(area, region);
231  }
232 
234 
235  ED_region_tag_redraw(region);
236 
238  op->customdata = NULL;
239 
240  return OPERATOR_FINISHED;
241 }
242 
243 /* copied from viewzoom_invoke(), changes here may apply there */
244 static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
245 {
246  ViewOpsData *vod;
247 
248  if (viewdolly_offset_lock_check(C, op)) {
249  return OPERATOR_CANCELLED;
250  }
251 
252  const bool use_cursor_init = RNA_boolean_get(op->ptr, "use_cursor_init");
253 
254  vod = op->customdata = viewops_data_create(
255  C,
256  event,
258  (use_cursor_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
259 
261 
262  /* needs to run before 'viewops_data_create' so the backup 'rv3d->ofs' is correct */
263  /* switch from camera view when: */
264  if (vod->rv3d->persp != RV3D_PERSP) {
265  if (vod->rv3d->persp == RV3D_CAMOB) {
266  /* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
269  }
270  else {
271  vod->rv3d->persp = RV3D_PERSP;
272  }
274  }
275 
276  /* if one or the other zoom position aren't set, set from event */
277  if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_is_set(op->ptr, "my")) {
278  RNA_int_set(op->ptr, "mx", event->xy[0]);
279  RNA_int_set(op->ptr, "my", event->xy[1]);
280  }
281 
282  if (RNA_struct_property_is_set(op->ptr, "delta")) {
283  viewdolly_exec(C, op);
284  }
285  else {
286  /* overwrite the mouse vector with the view direction (zoom into the center) */
287  if ((use_cursor_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
288  negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
289  normalize_v3(vod->init.mousevec);
290  }
291 
292  if (event->type == MOUSEZOOM) {
293  /* Bypass Zoom invert flag for track pads (pass false always) */
294 
295  if (U.uiflag & USER_ZOOM_HORIZ) {
296  vod->init.event_xy[0] = vod->prev.event_xy[0] = event->xy[0];
297  }
298  else {
299  /* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
300  vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->xy[0] -
301  event->prev_xy[0];
302  }
303  viewdolly_apply(vod, event->prev_xy, (U.uiflag & USER_ZOOM_INVERT) == 0);
304 
306  op->customdata = NULL;
307  return OPERATOR_FINISHED;
308  }
309 
310  /* add temp handler */
312  return OPERATOR_RUNNING_MODAL;
313  }
314  return OPERATOR_FINISHED;
315 }
316 
318 {
320  op->customdata = NULL;
321 }
322 
324 {
325  /* identifiers */
326  ot->name = "Dolly View";
327  ot->description = "Dolly in/out in the view";
328  ot->idname = "VIEW3D_OT_dolly";
329 
330  /* api callbacks */
336 
337  /* flags */
339 
340  /* properties */
343 }
344 
struct ScrArea * CTX_wm_area(const bContext *C)
Definition: context.c:738
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
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 normalize_v3(float r[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 negate_v3(float r[3])
MINLINE float normalize_v3_v3(float r[3], const float a[3])
MINLINE void madd_v3_v3v3fl(float r[3], const float a[3], const float b[3], float f)
#define SWAP(type, a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
@ USER_ZOOM_INVERT
@ USER_ZOOM_TO_MOUSEPOS
@ USER_ZOOM_HORIZ
#define RV3D_LOCK_FLAGS(rv3d)
#define RV3D_CAMOB
@ RV3D_BOXVIEW
#define RV3D_PERSP
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
bScreen * ED_screen_animation_playing(const struct wmWindowManager *wm)
void ED_region_tag_redraw(struct ARegion *region)
Definition: area.c:655
bool ED_view3d_camera_lock_sync(const struct Depsgraph *depsgraph, struct View3D *v3d, struct RegionView3D *rv3d)
bool ED_view3d_offset_lock_check(const struct View3D *v3d, const struct RegionView3D *rv3d)
bool ED_view3d_camera_lock_autokey(struct View3D *v3d, struct RegionView3D *rv3d, struct bContext *C, bool do_rotate, bool do_translate)
Definition: view3d_utils.c:665
void ED_view3d_persp_switch_from_camera(const struct Depsgraph *depsgraph, struct View3D *v3d, struct RegionView3D *rv3d, char persp)
bool ED_view3d_camera_lock_undo_push(const char *str, View3D *v3d, struct RegionView3D *rv3d, struct bContext *C)
Definition: view3d_utils.c:726
#define C
Definition: RandGen.cpp:25
@ KM_ANY
Definition: WM_types.h:265
@ KM_PRESS
Definition: WM_types.h:267
@ KM_RELEASE
Definition: WM_types.h:268
@ OPTYPE_BLOCKING
Definition: WM_types.h:150
@ OPTYPE_DEPENDS_ON_CURSOR
Definition: WM_types.h:184
@ OPTYPE_GRAB_CURSOR_XY
Definition: WM_types.h:154
@ WM_OP_INVOKE_DEFAULT
Definition: WM_types.h:201
unsigned int U
Definition: btGjkEpa3.h:78
const Depsgraph * depsgraph
@ VIEW_CONFIRM
Definition: image_ops.c:583
@ VIEW_PASS
Definition: image_ops.c:581
@ VIEW_APPLY
Definition: image_ops.c:582
static void area(int d1, int d2, int e1, int e2, float weights[2])
return ret
void RNA_int_set(PointerRNA *ptr, const char *name, int value)
Definition: rna_access.c:4921
int RNA_int_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4910
bool RNA_struct_property_is_set(PointerRNA *ptr, const char *identifier)
Definition: rna_access.c:5301
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
void * regiondata
float viewinv[4][4]
struct RegionView3D * rv3d
struct ViewOpsData::@577 prev
struct Depsgraph * depsgraph
struct ARegion * region
struct ViewOpsData::@576 init
struct ScrArea * area
float mousevec[3]
struct View3D * v3d
float ofs[3]
int ymax
Definition: DNA_vec_types.h:64
int xmax
Definition: DNA_vec_types.h:63
short val
Definition: WM_types.h:680
int xy[2]
Definition: WM_types.h:682
int prev_xy[2]
Definition: WM_types.h:728
short type
Definition: WM_types.h:678
const void * modal_items
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_boxview_sync(struct ScrArea *area, struct ARegion *region)
Definition: view3d_utils.c:890
void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPropFlag flag)
void viewops_data_free(bContext *C, ViewOpsData *vod)
ViewOpsData * viewops_data_create(bContext *C, const wmEvent *event, enum eViewOpsFlag viewops_flag)
bool view3d_rotation_poll(bContext *C)
enum eViewOpsFlag viewops_flag_from_prefs(void)
@ VIEWROT_MODAL_SWITCH_ROTATE
@ VIEWROT_MODAL_SWITCH_MOVE
@ VIEW_MODAL_CONFIRM
@ VIEWOPS_FLAG_USE_MOUSE_INIT
@ VIEWOPS_FLAG_ORBIT_SELECT
void ED_view3d_smooth_view_force_finish(struct bContext *C, struct View3D *v3d, struct ARegion *region)
@ V3D_OP_PROP_USE_MOUSE_INIT
@ V3D_OP_PROP_DELTA
@ V3D_OP_PROP_MOUSE_CO
static void viewdolly_cancel(bContext *C, wmOperator *op)
static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void view_dolly_to_vector_3d(ARegion *region, const float orig_ofs[3], const float dvec[3], float dfac)
static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const bool zoom_invert)
static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int viewdolly_exec(bContext *C, wmOperator *op)
void viewdolly_modal_keymap(wmKeyConfig *keyconf)
void VIEW3D_OT_dolly(wmOperatorType *ot)
int xy[2]
Definition: wm_draw.c:135
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
int WM_operator_name_call(bContext *C, const char *opstring, wmOperatorCallContext context, PointerRNA *properties, const wmEvent *event)
@ EVT_MODAL_MAP
@ MOUSEZOOM
@ EVT_LEFTCTRLKEY
@ MOUSEMOVE
@ LEFTMOUSE
@ EVT_LEFTSHIFTKEY
wmOperatorType * ot
Definition: wm_files.c:3479
wmKeyMap * WM_modalkeymap_find(wmKeyConfig *keyconf, const char *idname)
Definition: wm_keymap.c:914
void WM_modalkeymap_assign(wmKeyMap *km, const char *opname)
Definition: wm_keymap.c:985
wmKeyMapItem * WM_modalkeymap_add_item(wmKeyMap *km, const KeyMapItem_Params *params, int value)
Definition: wm_keymap.c:927
wmKeyMap * WM_modalkeymap_ensure(wmKeyConfig *keyconf, const char *idname, const EnumPropertyItem *items)
Definition: wm_keymap.c:888