Blender V5.0
view3d_navigate_smoothview.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_listbase.h"
14#include "BLI_math_rotation.h"
15#include "BLI_math_vector.h"
16
17#include "BKE_context.hh"
18
20
21#include "WM_api.hh"
22
23#include "ED_screen.hh"
24
25#include "view3d_intern.hh"
26#include "view3d_navigate.hh" /* Own include. */
27
29 bContext *C, View3D *v3d, RegionView3D *rv3d, const bool use_autokey, const float factor);
30
31/* -------------------------------------------------------------------- */
45
47{
48 const View3D *v3d = static_cast<const View3D *>(area->spacedata.first);
49 Object *camera = v3d->camera;
50 if (!camera) {
51 return;
52 }
53
54 /* Tag the camera object so it's known smooth-view is applied to the view-ports camera
55 * (needed to detect when a locked camera is being manipulated).
56 * NOTE: It doesn't matter if the actual object being manipulated is the camera or not. */
57 camera->id.tag &= ~ID_TAG_DOIT;
58
59 LISTBASE_FOREACH (const ARegion *, region, &area->regionbase) {
60 if (region->regiontype != RGN_TYPE_WINDOW) {
61 continue;
62 }
63 const RegionView3D *rv3d = static_cast<const RegionView3D *>(region->regiondata);
64 if (ED_view3d_camera_lock_undo_test(v3d, rv3d, C)) {
65 camera->id.tag |= ID_TAG_DOIT;
66 break;
67 }
68 }
69}
70
72 const ScrArea *area,
73 const char *undo_str,
74 const bool undo_grouped)
75{
76 View3D *v3d = static_cast<View3D *>(area->spacedata.first);
77 Object *camera = v3d->camera;
78 if (!camera) {
79 return;
80 }
81 if (camera->id.tag & ID_TAG_DOIT) {
82 /* Smooth view didn't touch the camera. */
83 camera->id.tag &= ~ID_TAG_DOIT;
84 return;
85 }
86
87 if ((U.uiflag & USER_GLOBALUNDO) == 0) {
88 return;
89 }
90
91 /* NOTE(@ideasman42): It is not possible that a single viewport references different cameras
92 * so even in the case there is a quad-view with multiple camera views set, these will all
93 * reference the same camera. In this case it doesn't matter which region is used.
94 * If in the future multiple cameras are supported, this logic can be extended. */
95 const ARegion *region_camera = nullptr;
96
97 /* An undo push should be performed. */
98 bool is_interactive = false;
99 LISTBASE_FOREACH (const ARegion *, region, &area->regionbase) {
100 if (region->regiontype != RGN_TYPE_WINDOW) {
101 continue;
102 }
103 const RegionView3D *rv3d = static_cast<const RegionView3D *>(region->regiondata);
104 if (ED_view3d_camera_lock_undo_test(v3d, rv3d, C)) {
105 region_camera = region;
106 if (rv3d->sms) {
107 is_interactive = true;
108 }
109 }
110 }
111
112 if (region_camera == nullptr) {
113 return;
114 }
115
116 RegionView3D *rv3d = static_cast<RegionView3D *>(region_camera->regiondata);
117
118 /* Fast forward, undo push, then rewind. */
119 if (is_interactive) {
120 view3d_smoothview_apply_with_interp(C, v3d, rv3d, false, 1.0f);
121 }
122
123 if (undo_grouped) {
124 ED_view3d_camera_lock_undo_grouped_push(undo_str, v3d, rv3d, C);
125 }
126 else {
127 ED_view3d_camera_lock_undo_push(undo_str, v3d, rv3d, C);
128 }
129
130 if (is_interactive) {
131 view3d_smoothview_apply_with_interp(C, v3d, rv3d, false, 0.0f);
132 }
133}
134
136
137/* -------------------------------------------------------------------- */
146
148 float dist;
149 float lens;
150 float quat[4];
151 float ofs[3];
152};
153
184
186 const View3D *v3d,
187 const RegionView3D *rv3d)
188{
189 copy_v3_v3(sms_state->ofs, rv3d->ofs);
190 copy_qt_qt(sms_state->quat, rv3d->viewquat);
191 sms_state->dist = rv3d->dist;
192 sms_state->lens = v3d->lens;
193}
194
196 View3D *v3d,
197 RegionView3D *rv3d)
198{
199 copy_v3_v3(rv3d->ofs, sms_state->ofs);
200 copy_qt_qt(rv3d->viewquat, sms_state->quat);
201 rv3d->dist = sms_state->dist;
202 v3d->lens = sms_state->lens;
203}
204
206 /* Avoid passing in the context. */
207 const Depsgraph *depsgraph,
208 wmWindowManager *wm,
209 wmWindow *win,
210 ScrArea *area,
211 View3D *v3d,
212 ARegion *region,
213 const int smooth_viewtx,
214 const V3D_SmoothParams *sview)
215{
216 /* Will start a timer if appropriate. */
217
218 /* In this case use #ED_view3d_smooth_view_undo_begin & end functions
219 * instead of passing in undo. */
220 BLI_assert_msg(sview->undo_str == nullptr,
221 "Only the 'ED_view3d_smooth_view' version of this function handles undo!");
222
223 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
224 SmoothView3DStore sms = {{0}};
225
226 /* Initialize `sms`. */
227 view3d_smooth_view_state_backup(&sms.dst, v3d, rv3d);
228 view3d_smooth_view_state_backup(&sms.src, v3d, rv3d);
229 /* If smooth-view runs multiple times. */
230 if (rv3d->sms == nullptr) {
231 view3d_smooth_view_state_backup(&sms.org, v3d, rv3d);
232 }
233 else {
234 sms.org = rv3d->sms->org;
235 }
236 sms.org_view = rv3d->view;
238
239 // sms.to_camera = false; /* Initialized to zero anyway. */
240
241 /* NOTE: Regarding camera locking: This is a little confusing but works OK.
242 * We may be changing the view 'as if' there is no active camera, but in fact
243 * there is an active camera which is locked to the view.
244 *
245 * In the case where smooth view is moving _to_ a camera we don't want that
246 * camera to be moved or changed, so only when the camera is not being set should
247 * we allow camera option locking to initialize the view settings from the camera. */
248 if (sview->camera == nullptr && sview->camera_old == nullptr) {
250 }
251
252 /* Store the options we want to end with. */
253 if (sview->ofs) {
254 copy_v3_v3(sms.dst.ofs, sview->ofs);
255 }
256 if (sview->quat) {
257 copy_qt_qt(sms.dst.quat, sview->quat);
258 }
259 if (sview->dist) {
260 sms.dst.dist = *sview->dist;
261 }
262 if (sview->lens) {
263 sms.dst.lens = *sview->lens;
264 }
265
266 if (sview->dyn_ofs) {
267 BLI_assert(sview->ofs == nullptr);
268 BLI_assert(sview->quat != nullptr);
269
270 copy_v3_v3(sms.dyn_ofs, sview->dyn_ofs);
271 sms.use_dyn_ofs = true;
272
273 /* Calculate the final destination offset. */
274 view3d_orbit_apply_dyn_ofs(sms.dst.ofs, sms.src.ofs, sms.src.quat, sms.dst.quat, sms.dyn_ofs);
275 }
276
277 if (sview->camera) {
278 Object *ob_camera_eval = DEG_get_evaluated(depsgraph, sview->camera);
279 if (sview->ofs != nullptr) {
281 ob_camera_eval->object_to_world().ptr(), sview->ofs, VIEW3D_DIST_FALLBACK);
282 }
283 ED_view3d_from_object(ob_camera_eval, sms.dst.ofs, sms.dst.quat, &sms.dst.dist, &sms.dst.lens);
284 /* Restore view3d values in end. */
285 sms.to_camera = true;
286 }
287
288 if ((sview->camera_old == sview->camera) && /* Camera. */
289 (sms.dst.dist == rv3d->dist) && /* Distance. */
290 (sms.dst.lens == v3d->lens) && /* Lens. */
291 equals_v3v3(sms.dst.ofs, rv3d->ofs) && /* Offset. */
292 equals_v4v4(sms.dst.quat, rv3d->viewquat) /* Rotation. */
293 )
294 {
295 /* Early return if nothing changed. */
296 return;
297 }
298
299 /* Skip smooth viewing for external render engine draw. */
300 if (smooth_viewtx && !(v3d->shading.type == OB_RENDER && rv3d->view_render)) {
301
302 /* Original values. */
303 if (sview->camera_old) {
304 Object *ob_camera_old_eval = DEG_get_evaluated(depsgraph, sview->camera_old);
305 if (sview->ofs != nullptr) {
306 /* This assignment will temporarily set the #RegionView3D::dist to zero.
307 * While this isn't typically allowed, it's not a bug to set this temporarily,
308 * doing so shouldn't crash or cause an invalid display, see !143946. */
310 ob_camera_old_eval->object_to_world().ptr(), sview->ofs, 0.0f);
311 }
313 ob_camera_old_eval, sms.src.ofs, sms.src.quat, &sms.src.dist, &sms.src.lens);
314 }
315 /* Grid draw as floor. */
316 if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
317 /* Use existing if exists, means multiple calls to smooth view
318 * won't lose the original 'view' setting. */
319 rv3d->view = RV3D_VIEW_USER;
320 }
321
322 sms.time_allowed = double(smooth_viewtx / 1000.0);
323
324 /* If this is view rotation only we can decrease the time allowed by the angle between
325 * quaternions this means small rotations won't lag. */
326 if (sview->quat && !sview->ofs && !sview->dist) {
327 /* Scale the time allowed by the rotation (180 degrees == 1.0). */
329 M_PI;
330 }
331
332 /* Ensure it shows correct. */
333 if (sms.to_camera) {
334 /* Use orthographic if we move from an orthographic view to an orthographic camera. */
335 Object *ob_camera_eval = DEG_get_evaluated(depsgraph, sview->camera);
336 rv3d->persp = ((rv3d->is_persp == false) && (ob_camera_eval->type == OB_CAMERA) &&
337 (static_cast<Camera *>(ob_camera_eval->data)->type == CAM_ORTHO)) ?
338 RV3D_ORTHO :
340 }
341
342 rv3d->rflag |= RV3D_NAVIGATING;
343
344 /* Not essential but in some cases the caller will tag the area for redraw, and in that
345 * case we can get a flicker of the 'org' user view but we want to see 'src'. */
346 view3d_smooth_view_state_restore(&sms.src, v3d, rv3d);
347
348 /* Keep track of running timer! */
349 if (rv3d->sms == nullptr) {
350 rv3d->sms = MEM_mallocN<SmoothView3DStore>("smoothview v3d");
351 }
352 *rv3d->sms = sms;
353 if (rv3d->smooth_timer) {
354 WM_event_timer_remove(wm, win, rv3d->smooth_timer);
355 }
356 /* #TIMER1 is hard-coded in key-map. */
357 rv3d->smooth_timer = WM_event_timer_add(wm, win, TIMER1, 1.0 / 100.0);
358 }
359 else {
360 /* Animation is disabled, apply immediately. */
361 if (sms.to_camera == false) {
362 copy_v3_v3(rv3d->ofs, sms.dst.ofs);
363 copy_qt_qt(rv3d->viewquat, sms.dst.quat);
364 rv3d->dist = sms.dst.dist;
365 v3d->lens = sms.dst.lens;
366
368 }
369
370 if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
371 view3d_boxview_copy(area, region);
372 }
373
374 ED_region_tag_redraw(region);
375
377 }
378
379 if (sms.to_camera == false) {
380 /* See comments in #ED_view3d_smooth_view_undo_begin for why this is needed. */
381 if (v3d->camera) {
382 v3d->camera->id.tag &= ~ID_TAG_DOIT;
383 }
384 }
385}
386
388 View3D *v3d,
389 ARegion *region,
390 const int smooth_viewtx,
391 const V3D_SmoothParams *sview)
392{
395 wmWindow *win = CTX_wm_window(C);
396 ScrArea *area = CTX_wm_area(C);
397
398 /* #ED_view3d_smooth_view_ex asserts this is not set as it doesn't support undo. */
399 V3D_SmoothParams sview_no_undo = *sview;
400 sview_no_undo.undo_str = nullptr;
401 sview_no_undo.undo_grouped = false;
402
403 const bool do_undo = (sview->undo_str != nullptr);
404 if (do_undo) {
406 }
407
408 ED_view3d_smooth_view_ex(depsgraph, wm, win, area, v3d, region, smooth_viewtx, &sview_no_undo);
409
410 if (do_undo) {
412 }
413}
414
419 bContext *C, View3D *v3d, RegionView3D *rv3d, const bool use_autokey, const float factor)
420{
421 SmoothView3DStore *sms = rv3d->sms;
422
423 interp_qt_qtqt(rv3d->viewquat, sms->src.quat, sms->dst.quat, factor);
424
425 if (sms->use_dyn_ofs) {
427 rv3d->ofs, sms->src.ofs, sms->src.quat, rv3d->viewquat, sms->dyn_ofs);
428 }
429 else {
430 interp_v3_v3v3(rv3d->ofs, sms->src.ofs, sms->dst.ofs, factor);
431 }
432
433 rv3d->dist = interpf(sms->dst.dist, sms->src.dist, factor);
434 v3d->lens = interpf(sms->dst.lens, sms->src.lens, factor);
435
437 if (ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d)) {
438 if (use_autokey) {
439 ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
440 }
441 }
442}
443
448 wmWindow *win,
449 View3D *v3d,
450 RegionView3D *rv3d,
451 bContext *C_for_camera_lock)
452{
453 SmoothView3DStore *sms = rv3d->sms;
454
455 /* If we went to camera, store the original. */
456 if (sms->to_camera) {
457 rv3d->persp = RV3D_CAMOB;
458 view3d_smooth_view_state_restore(&sms->org, v3d, rv3d);
459 }
460 else {
461 view3d_smooth_view_state_restore(&sms->dst, v3d, rv3d);
462
463 if (C_for_camera_lock) {
464 const Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C_for_camera_lock);
465 if (ED_view3d_camera_lock_sync(depsgraph, v3d, rv3d)) {
466 ED_view3d_camera_lock_autokey(v3d, rv3d, C_for_camera_lock, true, true);
467 }
468 }
469 }
470
471 if ((RV3D_LOCK_FLAGS(rv3d) & RV3D_LOCK_ROTATION) == 0) {
472 rv3d->view = sms->org_view;
474 }
475
476 MEM_freeN(rv3d->sms);
477 rv3d->sms = nullptr;
478
479 WM_event_timer_remove(wm, win, rv3d->smooth_timer);
480 rv3d->smooth_timer = nullptr;
481 rv3d->rflag &= ~RV3D_NAVIGATING;
482
483 /* Event handling won't know if a UI item has been moved under the pointer. */
485
486 /* NOTE: this doesn't work right because the `v3d->lens` is used in orthographic mode,
487 * when switching camera in quad-view the other orthographic views would zoom & reset.
488 *
489 * For now only redraw all regions when smooth-view finishes. */
491}
492
499
501{
503 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
504 SmoothView3DStore *sms = rv3d->sms;
505 float factor;
506
507 if (sms->time_allowed != 0.0) {
508 factor = float(rv3d->smooth_timer->time_duration / sms->time_allowed);
509 }
510 else {
511 factor = 1.0f;
512 }
513 if (factor >= 1.0f) {
515 }
516 else {
517 /* Ease in/out smoothing. */
518 factor = (3.0f * factor * factor - 2.0f * factor * factor * factor);
519 const bool use_autokey = ED_screen_animation_playing(wm);
520 view3d_smoothview_apply_with_interp(C, v3d, rv3d, use_autokey, factor);
521 }
522
523 if (RV3D_LOCK_FLAGS(rv3d) & RV3D_BOXVIEW) {
525 }
526
527 ED_region_tag_redraw(region);
528}
529
531 wmOperator * /*op*/,
532 const wmEvent *event)
533{
534 View3D *v3d = CTX_wm_view3d(C);
535 ARegion *region = CTX_wm_region(C);
536 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
537
538 /* Escape if not our timer. */
539 if (rv3d->smooth_timer == nullptr || rv3d->smooth_timer != event->customdata) {
541 }
542
544
545 return OPERATOR_FINISHED;
546}
547
549 wmWindowManager *wm,
550 wmWindow *win,
551 const Scene *scene,
552 View3D *v3d,
553 ARegion *region,
554 bContext *C_for_camera_lock)
555{
556 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
557 BLI_assert(rv3d && rv3d->sms);
558
559 view3d_smoothview_apply_and_finish_ex(wm, win, v3d, rv3d, C_for_camera_lock);
560
561 if (depsgraph) {
562 /* Force update of view matrix so tools that run immediately after
563 * can use them without redrawing first. */
564 ED_view3d_update_viewmat(depsgraph, scene, v3d, region, nullptr, nullptr, nullptr, false);
565 }
566}
567
569{
570 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
571 if (rv3d && rv3d->sms) {
572
574 Scene *scene = CTX_data_scene(C);
576 wmWindow *win = CTX_wm_window(C);
577
578 view3d_smooth_view_force_finish_ex(depsgraph, wm, win, scene, v3d, region, C);
579 }
580}
581
583 wmWindowManager *wm,
584 wmWindow *win,
585 const Scene *scene,
586 View3D *v3d,
587 ARegion *region)
588{
589
590 /* NOTE(@ideasman42): Ideally we would *always* apply the camera lock.
591 * Failing to do so results in incorrect behavior when a user performs
592 * a camera-locked view-port manipulation & immediately enters local-view
593 * before the operation is completed.
594 * In this case the camera isn't key-framed when it should be.
595 *
596 * A generic solution that supports forcing modal operators to finish their
597 * work may be best, but needs to be investigated.
598 *
599 * It's worth noting this *is* a corner case, while not ideal,
600 * rarely happens unless a motivated users is trying to cause it to fail.
601 * Even when it does occur, it simply misses completing & auto-keying the action. */
602
603 RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
604 if (rv3d && rv3d->sms) {
605 view3d_smooth_view_force_finish_ex(depsgraph, wm, win, scene, v3d, region, nullptr);
606 }
607}
608
610{
611 /* Identifiers. */
612 ot->name = "Smooth View";
613 ot->idname = "VIEW3D_OT_smoothview";
614
615 /* API callbacks. */
618
619 /* Flags. */
620 ot->flag = OPTYPE_INTERNAL;
621}
622
624{
625 MEM_SAFE_FREE(rv3d->sms);
626}
627
Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
ScrArea * CTX_wm_area(const bContext *C)
wmWindow * CTX_wm_window(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
MINLINE float interpf(float target, float origin, float t)
#define M_PI
float angle_signed_normalized_qtqt(const float q1[4], const float q2[4])
void interp_qt_qtqt(float q[4], const float a[4], const float b[4], float t)
void copy_qt_qt(float q[4], const float a[4])
MINLINE bool equals_v3v3(const float v1[3], const float v2[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void copy_v3_v3(float r[3], const float a[3])
void interp_v3_v3v3(float r[3], const float a[3], const float b[3], float t)
MINLINE bool equals_v4v4(const float v1[4], const float v2[4]) ATTR_WARN_UNUSED_RESULT
T * DEG_get_evaluated(const Depsgraph *depsgraph, T *id)
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
@ CAM_ORTHO
@ OB_RENDER
@ OB_CAMERA
@ RGN_TYPE_WINDOW
@ USER_GLOBALUNDO
@ RV3D_VIEW_USER
#define RV3D_LOCK_FLAGS(rv3d)
@ RV3D_NAVIGATING
@ RV3D_CAMOB
@ RV3D_PERSP
@ RV3D_ORTHO
@ RV3D_LOCK_ROTATION
@ RV3D_BOXVIEW
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
bool ED_operator_view3d_active(bContext *C)
bScreen * ED_screen_animation_playing(const wmWindowManager *wm)
void ED_region_tag_redraw(ARegion *region)
Definition area.cc:618
bool ED_view3d_camera_lock_sync(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
void ED_view3d_from_object(const Object *ob, float ofs[3], float quat[4], const float *dist, float *lens)
#define VIEW3D_DIST_FALLBACK
float ED_view3d_offset_distance(const float mat[4][4], const float ofs[3], float fallback_dist)
bool ED_view3d_camera_lock_undo_push(const char *str, const View3D *v3d, const RegionView3D *rv3d, bContext *C)
void ED_view3d_camera_lock_init(const Depsgraph *depsgraph, View3D *v3d, RegionView3D *rv3d)
bool ED_view3d_camera_lock_autokey(View3D *v3d, RegionView3D *rv3d, bContext *C, bool do_rotate, bool do_translate)
void ED_view3d_update_viewmat(const Depsgraph *depsgraph, const Scene *scene, View3D *v3d, ARegion *region, const float viewmat[4][4], const float winmat[4][4], const rcti *rect, bool offscreen)
bool ED_view3d_camera_lock_undo_test(const View3D *v3d, const RegionView3D *rv3d, bContext *C)
bool ED_view3d_camera_lock_undo_grouped_push(const char *str, const View3D *v3d, const RegionView3D *rv3d, bContext *C)
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
@ OPTYPE_INTERNAL
Definition WM_types.hh:202
#define ND_SPACE_VIEW3D
Definition WM_types.hh:528
#define NC_SPACE
Definition WM_types.hh:392
#define U
BPy_StructRNA * depsgraph
nullptr float
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define fabsf
void * regiondata
int tag
Definition DNA_ID.h:442
void * first
struct SmoothView3DStore * sms
struct ViewRender * view_render
struct wmTimer * smooth_timer
ListBase spacedata
ListBase regionbase
const char * undo_str
const float * dyn_ofs
struct Object * camera
View3DShading shading
void * customdata
Definition WM_types.hh:807
double time_duration
Definition WM_types.hh:968
void view3d_boxview_copy(ScrArea *area, ARegion *region)
void view3d_orbit_apply_dyn_ofs(float r_ofs[3], const float ofs_old[3], const float viewquat_old[4], const float viewquat_new[4], const float dyn_ofs[3])
void ED_view3d_smooth_view_undo_begin(bContext *C, const ScrArea *area)
void ED_view3d_smooth_view_undo_end(bContext *C, const ScrArea *area, const char *undo_str, const bool undo_grouped)
void ED_view3d_smooth_view_force_finish_no_camera_lock(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, const Scene *scene, View3D *v3d, ARegion *region)
static void view3d_smoothview_apply_and_finish_ex(wmWindowManager *wm, wmWindow *win, View3D *v3d, RegionView3D *rv3d, bContext *C_for_camera_lock)
static void view3d_smoothview_apply_from_timer(bContext *C, View3D *v3d, ARegion *region)
static void view3d_smoothview_apply_with_interp(bContext *C, View3D *v3d, RegionView3D *rv3d, const bool use_autokey, const float factor)
static void view3d_smooth_view_state_backup(SmoothView3DState *sms_state, const View3D *v3d, const RegionView3D *rv3d)
static void view3d_smooth_view_state_restore(const SmoothView3DState *sms_state, View3D *v3d, RegionView3D *rv3d)
static void view3d_smoothview_apply_and_finish(bContext *C, View3D *v3d, RegionView3D *rv3d)
void ED_view3d_smooth_view(bContext *C, View3D *v3d, ARegion *region, const int smooth_viewtx, const V3D_SmoothParams *sview)
void ED_view3d_smooth_view_ex(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, ScrArea *area, View3D *v3d, ARegion *region, const int smooth_viewtx, const V3D_SmoothParams *sview)
static wmOperatorStatus view3d_smoothview_invoke(bContext *C, wmOperator *, const wmEvent *event)
void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *region)
static void view3d_smooth_view_force_finish_ex(const Depsgraph *depsgraph, wmWindowManager *wm, wmWindow *win, const Scene *scene, View3D *v3d, ARegion *region, bContext *C_for_camera_lock)
void VIEW3D_OT_smoothview(wmOperatorType *ot)
void view3d_smooth_free(RegionView3D *rv3d)
void WM_main_add_notifier(uint type, void *reference)
void WM_event_add_mousemove(wmWindow *win)
@ TIMER1
wmOperatorType * ot
Definition wm_files.cc:4237
wmTimer * WM_event_timer_add(wmWindowManager *wm, wmWindow *win, const wmEventType event_type, const double time_step)
void WM_event_timer_remove(wmWindowManager *wm, wmWindow *, wmTimer *timer)