LEFT | RIGHT |
1 /* | 1 /* |
2 * ***** BEGIN GPL LICENSE BLOCK ***** | 2 * ***** BEGIN GPL LICENSE BLOCK ***** |
3 * | 3 * |
4 * This program is free software; you can redistribute it and/or | 4 * This program is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU General Public License | 5 * modify it under the terms of the GNU General Public License |
6 * as published by the Free Software Foundation; either version 2 | 6 * as published by the Free Software Foundation; either version 2 |
7 * of the License, or (at your option) any later version. | 7 * of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This program is distributed in the hope that it will be useful, | 9 * This program is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 26 matching lines...) Expand all Loading... |
37 #include "DNA_armature_types.h" | 37 #include "DNA_armature_types.h" |
38 #include "DNA_object_types.h" | 38 #include "DNA_object_types.h" |
39 #include "DNA_scene_types.h" | 39 #include "DNA_scene_types.h" |
40 #include "DNA_camera_types.h" | 40 #include "DNA_camera_types.h" |
41 #include "DNA_lamp_types.h" | 41 #include "DNA_lamp_types.h" |
42 | 42 |
43 #include "MEM_guardedalloc.h" | 43 #include "MEM_guardedalloc.h" |
44 | 44 |
45 #include "BLI_blenlib.h" | 45 #include "BLI_blenlib.h" |
46 #include "BLI_math.h" | 46 #include "BLI_math.h" |
47 #include "BLI_rand.h" | |
48 #include "BLI_utildefines.h" | 47 #include "BLI_utildefines.h" |
49 | 48 |
50 #include "BKE_camera.h" | 49 #include "BKE_camera.h" |
51 #include "BKE_context.h" | 50 #include "BKE_context.h" |
52 #include "BKE_image.h" | 51 #include "BKE_image.h" |
53 #include "BKE_library.h" | 52 #include "BKE_library.h" |
54 #include "BKE_object.h" | 53 #include "BKE_object.h" |
55 #include "BKE_paint.h" | 54 #include "BKE_paint.h" |
56 #include "BKE_report.h" | 55 #include "BKE_report.h" |
57 #include "BKE_scene.h" | 56 #include "BKE_scene.h" |
(...skipping 16 matching lines...) Expand all Loading... |
74 #include "ED_particle.h" | 73 #include "ED_particle.h" |
75 #include "ED_screen.h" | 74 #include "ED_screen.h" |
76 #include "ED_transform.h" | 75 #include "ED_transform.h" |
77 #include "ED_mesh.h" | 76 #include "ED_mesh.h" |
78 #include "ED_view3d.h" | 77 #include "ED_view3d.h" |
79 #include "ED_sculpt.h" | 78 #include "ED_sculpt.h" |
80 | 79 |
81 | 80 |
82 #include "PIL_time.h" /* smoothview */ | 81 #include "PIL_time.h" /* smoothview */ |
83 | 82 |
84 #include "view3d_intern.h" // own include | 83 #include "view3d_intern.h" /* own include */ |
| 84 |
| 85 /* for ndof prints */ |
| 86 // #define DEBUG_NDOF_MOTION |
| 87 |
| 88 bool ED_view3d_offset_lock_check(struct View3D *v3d, struct RegionView3D *rv3d) |
| 89 { |
| 90 » return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_
centre); |
| 91 } |
| 92 |
| 93 static bool view3d_operator_offset_lock_check(bContext *C, wmOperator *op) |
| 94 { |
| 95 » View3D *v3d = CTX_wm_view3d(C); |
| 96 » RegionView3D *rv3d = CTX_wm_region_view3d(C); |
| 97 » if (ED_view3d_offset_lock_check(v3d, rv3d)) { |
| 98 » » BKE_report(op->reports, RPT_WARNING, "View offset is locked"); |
| 99 » » return true; |
| 100 » } |
| 101 » else { |
| 102 » » return false; |
| 103 » } |
| 104 } |
85 | 105 |
86 /* ********************** view3d_edit: view manipulations *********************
*/ | 106 /* ********************** view3d_edit: view manipulations *********************
*/ |
87 | 107 |
88 int ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d) | 108 bool ED_view3d_camera_lock_check(View3D *v3d, RegionView3D *rv3d) |
89 { | 109 { |
90 return ((v3d->camera) && | 110 return ((v3d->camera) && |
91 (v3d->camera->id.lib == NULL) && | 111 (v3d->camera->id.lib == NULL) && |
92 (v3d->flag2 & V3D_LOCK_CAMERA) && | 112 (v3d->flag2 & V3D_LOCK_CAMERA) && |
93 (rv3d->persp == RV3D_CAMOB)); | 113 (rv3d->persp == RV3D_CAMOB)); |
94 } | 114 } |
95 | 115 |
96 void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d) | 116 void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d) |
97 { | 117 { |
98 if (ED_view3d_camera_lock_check(v3d, rv3d)) { | 118 if (ED_view3d_camera_lock_check(v3d, rv3d)) { |
| 119 /* using a fallback dist is OK here since ED_view3d_from_object(
) compensates for it */ |
| 120 rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d-
>ofs, VIEW3D_DIST_FALLBACK); |
99 ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &r
v3d->dist, NULL); | 121 ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &r
v3d->dist, NULL); |
100 } | 122 } |
101 } | 123 } |
102 | 124 |
103 /* return TRUE if the camera is moved */ | 125 /* return true if the camera is moved */ |
104 int ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) | 126 bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d) |
105 { | 127 { |
106 if (ED_view3d_camera_lock_check(v3d, rv3d)) { | 128 if (ED_view3d_camera_lock_check(v3d, rv3d)) { |
107 ObjectTfmProtectedChannels obtfm; | 129 ObjectTfmProtectedChannels obtfm; |
108 Object *root_parent; | 130 Object *root_parent; |
109 | 131 |
110 if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent =
v3d->camera->parent)) { | 132 if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent =
v3d->camera->parent)) { |
111 Object *ob_update; | 133 Object *ob_update; |
| 134 float tmat[4][4]; |
| 135 float imat[4][4]; |
112 float view_mat[4][4]; | 136 float view_mat[4][4]; |
113 float diff_mat[4][4]; | 137 float diff_mat[4][4]; |
114 float parent_mat[4][4]; | 138 float parent_mat[4][4]; |
115 | 139 |
116 while (root_parent->parent) { | 140 while (root_parent->parent) { |
117 root_parent = root_parent->parent; | 141 root_parent = root_parent->parent; |
118 } | 142 } |
119 | 143 |
120 ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3
d->dist); | 144 ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3
d->dist); |
121 | 145 |
122 » » » invert_m4_m4(v3d->camera->imat, v3d->camera->obmat); | 146 » » » normalize_m4_m4(tmat, v3d->camera->obmat); |
123 » » » mult_m4_m4m4(diff_mat, view_mat, v3d->camera->imat); | 147 |
124 | 148 » » » invert_m4_m4(imat, tmat); |
125 » » » mult_m4_m4m4(parent_mat, diff_mat, root_parent->obmat); | 149 » » » mul_m4_m4m4(diff_mat, view_mat, imat); |
| 150 |
| 151 » » » mul_m4_m4m4(parent_mat, diff_mat, root_parent->obmat); |
126 | 152 |
127 BKE_object_tfm_protected_backup(root_parent, &obtfm); | 153 BKE_object_tfm_protected_backup(root_parent, &obtfm); |
128 » » » BKE_object_apply_mat4(root_parent, parent_mat, TRUE, FAL
SE); | 154 » » » BKE_object_apply_mat4(root_parent, parent_mat, true, fal
se); |
129 BKE_object_tfm_protected_restore(root_parent, &obtfm, ro
ot_parent->protectflag); | 155 BKE_object_tfm_protected_restore(root_parent, &obtfm, ro
ot_parent->protectflag); |
130 | 156 |
131 ob_update = v3d->camera; | 157 ob_update = v3d->camera; |
132 while (ob_update) { | 158 while (ob_update) { |
133 DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); | 159 DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); |
134 WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, o
b_update); | 160 WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, o
b_update); |
135 ob_update = ob_update->parent; | 161 ob_update = ob_update->parent; |
136 } | 162 } |
137 } | 163 } |
138 else { | 164 else { |
| 165 /* always maintain the same scale */ |
| 166 const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOC
K_SCALEY | OB_LOCK_SCALEZ); |
139 BKE_object_tfm_protected_backup(v3d->camera, &obtfm); | 167 BKE_object_tfm_protected_backup(v3d->camera, &obtfm); |
140 ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewqu
at, rv3d->dist); | 168 ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewqu
at, rv3d->dist); |
141 » » » BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3
d->camera->protectflag); | 169 » » » BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3
d->camera->protectflag | protect_scale_all); |
142 | 170 |
143 DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); | 171 DAG_id_tag_update(&v3d->camera->id, OB_RECALC_OB); |
144 WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->came
ra); | 172 WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->came
ra); |
145 } | 173 } |
146 | 174 |
147 » » return TRUE; | 175 » » return true; |
148 } | 176 } |
149 else { | 177 else { |
150 » » return FALSE; | 178 » » return false; |
151 » } | 179 » } |
152 } | 180 } |
153 | 181 |
| 182 /** |
| 183 * For viewport operators that exit camera persp. |
| 184 * |
| 185 * \note This differs from simply setting ``rv3d->persp = persp`` because it |
| 186 * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera
, |
| 187 * otherwise switching out of camera view may jump to a different part of the sc
ene. |
| 188 */ |
| 189 static void view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, con
st char persp) |
| 190 { |
| 191 » BLI_assert(rv3d->persp == RV3D_CAMOB); |
| 192 » BLI_assert(persp != RV3D_CAMOB); |
| 193 |
| 194 » if (v3d->camera) { |
| 195 » » rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d-
>ofs, VIEW3D_DIST_FALLBACK); |
| 196 » » ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &r
v3d->dist, NULL); |
| 197 » } |
| 198 |
| 199 » if (!ED_view3d_camera_lock_check(v3d, rv3d)) { |
| 200 » » rv3d->persp = persp; |
| 201 » } |
| 202 } |
154 | 203 |
155 /* ********************* box view support ***************** */ | 204 /* ********************* box view support ***************** */ |
156 | 205 |
157 static void view3d_boxview_clip(ScrArea *sa) | 206 static void view3d_boxview_clip(ScrArea *sa) |
158 { | 207 { |
159 ARegion *ar; | 208 ARegion *ar; |
160 BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb"); | 209 BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb"); |
161 float clip[6][4]; | 210 float clip[6][4]; |
162 float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f}; | 211 float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f}; |
163 int val; | 212 int val; |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 } | 346 } |
298 } | 347 } |
299 } | 348 } |
300 | 349 |
301 if (clip) { | 350 if (clip) { |
302 view3d_boxview_clip(sa); | 351 view3d_boxview_clip(sa); |
303 } | 352 } |
304 } | 353 } |
305 | 354 |
306 /* 'clip' is used to know if our clip setting has changed */ | 355 /* 'clip' is used to know if our clip setting has changed */ |
307 void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, short do_clip) | 356 void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip) |
308 { | 357 { |
309 ARegion *ar_sync = NULL; | 358 ARegion *ar_sync = NULL; |
310 RegionView3D *rv3d = ar->regiondata; | 359 RegionView3D *rv3d = ar->regiondata; |
311 short viewlock; | 360 short viewlock; |
312 /* this function copies flags from the first of the 3 other quadview | 361 /* this function copies flags from the first of the 3 other quadview |
313 * regions to the 2 other, so it assumes this is the region whose | 362 * regions to the 2 other, so it assumes this is the region whose |
314 * properties are always being edited, weak */ | 363 * properties are always being edited, weak */ |
315 viewlock = rv3d->viewlock; | 364 viewlock = rv3d->viewlock; |
316 | 365 |
317 if ((viewlock & RV3D_LOCKED) == 0) | 366 if ((viewlock & RV3D_LOCKED) == 0) |
318 viewlock = 0; | 367 viewlock = 0; |
319 else if ((viewlock & RV3D_BOXVIEW) == 0) { | 368 else if ((viewlock & RV3D_BOXVIEW) == 0) { |
320 viewlock &= ~RV3D_BOXCLIP; | 369 viewlock &= ~RV3D_BOXCLIP; |
321 » » do_clip = TRUE; | 370 » » do_clip = true; |
322 } | 371 } |
323 | 372 |
324 for (; ar; ar = ar->prev) { | 373 for (; ar; ar = ar->prev) { |
325 if (ar->alignment == RGN_ALIGN_QSPLIT) { | 374 if (ar->alignment == RGN_ALIGN_QSPLIT) { |
326 rv3d = ar->regiondata; | 375 rv3d = ar->regiondata; |
327 rv3d->viewlock = viewlock; | 376 rv3d->viewlock = viewlock; |
328 | 377 |
329 if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) { | 378 if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) { |
330 rv3d->rflag &= ~RV3D_BOXCLIP; | 379 rv3d->rflag &= ~RV3D_BOXCLIP; |
331 } | 380 } |
332 | 381 |
333 /* use ar_sync so we sync with one of the aligned views
below | 382 /* use ar_sync so we sync with one of the aligned views
below |
334 * else the view jumps on changing view settings like 'c
lip' | 383 * else the view jumps on changing view settings like 'c
lip' |
335 * since it copies from the perspective view */ | 384 * since it copies from the perspective view */ |
336 ar_sync = ar; | 385 ar_sync = ar; |
337 } | 386 } |
338 } | 387 } |
339 | 388 |
340 if (rv3d->viewlock & RV3D_BOXVIEW) { | 389 if (rv3d->viewlock & RV3D_BOXVIEW) { |
341 view3d_boxview_copy(sa, ar_sync ? ar_sync : sa->regionbase.last)
; | 390 view3d_boxview_copy(sa, ar_sync ? ar_sync : sa->regionbase.last)
; |
342 } | 391 } |
343 | 392 |
344 ED_area_tag_redraw(sa); | 393 ED_area_tag_redraw(sa); |
345 } | 394 } |
346 | 395 |
347 /* ************************** init for view ops ********************************
**/ | 396 /* ************************** init for view ops ********************************
**/ |
348 | 397 |
349 typedef struct ViewOpsData { | 398 typedef struct ViewOpsData { |
| 399 /* context pointers (assigned by viewops_data_alloc) */ |
350 ScrArea *sa; | 400 ScrArea *sa; |
351 ARegion *ar; | 401 ARegion *ar; |
352 View3D *v3d; | 402 View3D *v3d; |
353 RegionView3D *rv3d; | 403 RegionView3D *rv3d; |
354 | 404 |
355 /* needed for continuous zoom */ | 405 /* needed for continuous zoom */ |
356 wmTimer *timer; | 406 wmTimer *timer; |
357 double timer_lastdraw; | 407 double timer_lastdraw; |
358 | 408 |
359 float oldquat[4]; | 409 float oldquat[4]; |
360 float viewquat[4]; /* working copy of rv3d->viewquat */ | 410 float viewquat[4]; /* working copy of rv3d->viewquat */ |
361 float trackvec[3]; | 411 float trackvec[3]; |
362 float mousevec[3]; /* dolly only */ | 412 float mousevec[3]; /* dolly only */ |
363 » float reverse, dist0, camzoom0; | 413 » float reverse; |
| 414 » float dist_prev, camzoom_prev; |
364 float grid, far; | 415 float grid, far; |
365 » short axis_snap; /* view rotate only */ | 416 » bool axis_snap; /* view rotate only */ |
| 417 » float zfac; |
366 | 418 |
367 /* use for orbit selection and auto-dist */ | 419 /* use for orbit selection and auto-dist */ |
368 float ofs[3], dyn_ofs[3]; | 420 float ofs[3], dyn_ofs[3]; |
369 » short use_dyn_ofs; | 421 » bool use_dyn_ofs; |
370 | 422 |
371 int origx, origy, oldx, oldy; | 423 int origx, origy, oldx, oldy; |
372 int origkey; /* the key that triggered the operator */ | 424 int origkey; /* the key that triggered the operator */ |
373 | 425 |
374 } ViewOpsData; | 426 } ViewOpsData; |
375 | 427 |
376 #define TRACKBALLSIZE (1.1) | 428 #define TRACKBALLSIZE (1.1) |
377 | 429 |
378 static void calctrackballvec(rcti *rect, int mx, int my, float vec[3]) | 430 static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3]) |
379 { | |
380 » float x, y, radius, d, z, t; | |
381 | |
382 » radius = TRACKBALLSIZE; | |
383 | |
384 » /* normalize x and y */ | |
385 » x = (rect->xmax + rect->xmin) / 2 - mx; | |
386 » x /= (float)((rect->xmax - rect->xmin) / 4); | |
387 » y = (rect->ymax + rect->ymin) / 2 - my; | |
388 » y /= (float)((rect->ymax - rect->ymin) / 2); | |
389 | |
390 » d = sqrt(x * x + y * y); | |
391 » if (d < radius * (float)M_SQRT1_2) { /* Inside sphere */ | |
392 » » z = sqrt(radius * radius - d * d); | |
393 » } | |
394 » else { /* On hyperbola */ | |
395 » » t = radius / (float)M_SQRT2; | |
396 » » z = t * t / d; | |
397 » } | |
398 | |
399 » vec[0] = x; | |
400 » vec[1] = y; | |
401 » vec[2] = -z; /* yah yah! */ | |
402 } | |
403 | |
404 | |
405 static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event) | |
406 { | |
407 » static float lastofs[3] = {0, 0, 0}; | |
408 » RegionView3D *rv3d; | |
409 » ViewOpsData *vod = MEM_callocN(sizeof(ViewOpsData), "viewops data"); | |
410 | |
411 » /* store data */ | |
412 » op->customdata = vod; | |
413 » vod->sa = CTX_wm_area(C); | |
414 » vod->ar = CTX_wm_region(C); | |
415 » vod->v3d = vod->sa->spacedata.first; | |
416 » vod->rv3d = rv3d = vod->ar->regiondata; | |
417 | |
418 » /* set the view from the camera, if view locking is enabled. | |
419 » * we may want to make this optional but for now its needed always */ | |
420 » ED_view3d_camera_lock_init(vod->v3d, vod->rv3d); | |
421 | |
422 » vod->dist0 = rv3d->dist; | |
423 » vod->camzoom0 = rv3d->camzoom; | |
424 » copy_qt_qt(vod->viewquat, rv3d->viewquat); | |
425 » copy_qt_qt(vod->oldquat, rv3d->viewquat); | |
426 » vod->origx = vod->oldx = event->x; | |
427 » vod->origy = vod->oldy = event->y; | |
428 » vod->origkey = event->type; /* the key that triggered the operator. */ | |
429 » vod->use_dyn_ofs = (U.uiflag & USER_ORBIT_SELECTION) ? 1 : 0; | |
430 » copy_v3_v3(vod->ofs, rv3d->ofs); | |
431 | 431 |
432 if (vod->use_dyn_ofs) { | 432 if (vod->use_dyn_ofs) { |
433 /* If there's no selection, lastofs is unmodified and last value
since static */ | 433 /* If there's no selection, lastofs is unmodified and last value
since static */ |
434 » » calculateTransformCenter(C, V3D_CENTROID, lastofs, NULL); | 434 » » calculateTransformCenter(C, V3D_CENTROID, lastofs); |
435 negate_v3_v3(vod->dyn_ofs, lastofs); | 435 negate_v3_v3(vod->dyn_ofs, lastofs); |
436 } | 436 } |
437 else if (U.uiflag & USER_ORBIT_ZBUF) { | 437 else if (U.uiflag & USER_ORBIT_ZBUF) { |
438 | |
439 view3d_operator_needs_opengl(C); /* needed for zbuf drawing */ | |
440 | |
441 if ((vod->use_dyn_ofs = ED_view3d_autodist(CTX_data_scene(C), vo
d->ar, vod->v3d, event->mval, vod->dyn_ofs))) { | |
442 if (rv3d->is_persp) { | |
443 float my_origin[3]; /* original G.vd->ofs */ | |
444 float my_pivot[3]; /* view */ | |
445 float dvec[3]; | |
446 | |
447 // locals for dist correction | |
448 float mat[3][3]; | |
449 float upvec[3]; | |
450 | |
451 negate_v3_v3(my_origin, rv3d->ofs);
/* ofs is flipped */ | |
452 | |
453 /* Set the dist value to be the distance from th
is 3d point | |
454 * this means youll always be able to zoom into
it and panning wont go bad when dist was zero */ | |
455 | |
456 /* remove dist value */ | |
457 upvec[0] = upvec[1] = 0; | |
458 upvec[2] = rv3d->dist; | |
459 copy_m3_m4(mat, rv3d->viewinv); | |
460 | |
461 mul_m3_v3(mat, upvec); | |
462 sub_v3_v3v3(my_pivot, rv3d->ofs, upvec); | |
463 negate_v3(my_pivot); /* ofs is fl
ipped */ | |
464 | |
465 /* find a new ofs value that is along the view a
xis (rather than the mouse location) */ | |
466 closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot,
my_origin); | |
467 vod->dist0 = rv3d->dist = len_v3v3(my_pivot, dve
c); | |
468 | |
469 negate_v3_v3(rv3d->ofs, dvec); | |
470 } | |
471 negate_v3(vod->dyn_ofs); | |
472 copy_v3_v3(vod->ofs, rv3d->ofs); | |
473 } | |
474 } | |
475 | |
476 { | |
477 /* for dolly */ | |
478 float mval_f[2]; | |
479 VECCOPY2D(mval_f, event->mval); | |
480 ED_view3d_win_to_vector(vod->ar, mval_f, vod->mousevec); | |
481 } | |
482 | |
483 /* lookup, we don't pass on v3d to prevent confusement */ | |
484 vod->grid = vod->v3d->grid; | |
485 vod->far = vod->v3d->far; | |
486 | |
487 calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec); | |
488 | |
489 initgrabz(rv3d, -rv3d->ofs[0], -rv3d->ofs[1], -rv3d->ofs[2]); | |
490 | |
491 vod->reverse = 1.0f; | |
492 if (rv3d->persmat[2][1] < 0.0f) | |
493 vod->reverse = -1.0f; | |
494 | |
495 rv3d->rflag |= RV3D_NAVIGATING; | |
496 } | |
497 | |
498 static void viewops_data_free(bContext *C, wmOperator *op) | |
499 { | |
500 ARegion *ar; | |
501 Paint *p = paint_get_active(CTX_data_scene(C)); | |
502 | |
503 if (op->customdata) { | |
504 ViewOpsData *vod = op->customdata; | |
505 ar = vod->ar; | |
506 vod->rv3d->rflag &= ~RV3D_NAVIGATING; | |
507 | |
508 if (vod->timer) | |
509 WM_event_remove_timer(CTX_wm_manager(C), vod->timer->win
, vod->timer); | |
510 | |
511 MEM_freeN(vod); | |
512 op->customdata = NULL; | |
513 } | |
514 else { | |
515 ar = CTX_wm_region(C); | |
516 } | |
517 | |
518 if (p && (p->flags & PAINT_FAST_NAVIGATE)) | |
519 ED_region_tag_redraw(ar); | |
520 } | |
521 | |
522 /* ************************** viewrotate **********************************/ | |
523 | |
524 #define COS45 0.7071068 | |
525 #define SIN45 COS45 | |
526 | |
527 #define NUM_SNAP_QUATS 39 | |
528 | |
529 static const float snapquats[NUM_SNAP_QUATS][5] = { | |
530 /*{q0, q1, q3, q4, view}*/ | |
531 {COS45, -SIN45, 0.0, 0.0, RV3D_VIEW_FRONT}, | |
532 {0.0, 0.0, -SIN45, -SIN45, RV3D_VIEW_BACK}, | |
533 {1.0, 0.0, 0.0, 0.0, RV3D_VIEW_TOP}, | |
534 {0.0, -1.0, 0.0, 0.0, RV3D_VIEW_BOTTOM}, | |
535 {0.5, -0.5, -0.5, -0.5, RV3D_VIEW_RIGHT}, | |
536 {0.5, -0.5, 0.5, 0.5, RV3D_VIEW_LEFT}, | |
537 | |
538 /* some more 45 deg snaps */ | |
539 { 0.6532815, -0.6532815, 0.2705981, 0.2705981, 0}, | |
540 { 0.9238795, 0.0, 0.0, 0.3826834, 0}, | |
541 { 0.0, -0.9238795, 0.3826834, 0.0, 0}, | |
542 { 0.3535534, -0.8535534, 0.3535534, 0.1464466, 0}, | |
543 { 0.8535534, -0.3535534, 0.1464466, 0.3535534, 0}, | |
544 { 0.4999999, -0.4999999, 0.5, 0.5, 0}, | |
545 { 0.2705980, -0.6532815, 0.6532815, 0.2705980, 0}, | |
546 { 0.6532815, -0.2705980, 0.2705980, 0.6532815, 0}, | |
547 { 0.2705978, -0.2705980, 0.6532814, 0.6532814, 0}, | |
548 { 0.3826834, 0.0, 0.0, 0.9238794, 0}, | |
549 { 0.0, -0.3826834, 0.9238794, 0.0, 0}, | |
550 { 0.1464466, -0.3535534, 0.8535534, 0.3535534, 0}, | |
551 { 0.3535534, -0.1464466, 0.3535534, 0.8535534, 0}, | |
552 { 0.0, 0.0, 0.9238794, 0.3826834, 0}, | |
553 {-0.0, 0.0, 0.3826834, 0.9238794, 0}, | |
554 {-0.2705980, 0.2705980, 0.6532813, 0.6532813, 0}, | |
555 {-0.3826834, 0.0, 0.0, 0.9238794, 0}, | |
556 { 0.0, 0.3826834, 0.9238794, 0.0, 0}, | |
557 {-0.1464466, 0.3535534, 0.8535533, 0.3535533, 0}, | |
558 {-0.3535534, 0.1464466, 0.3535533, 0.8535533, 0}, | |
559 {-0.4999999, 0.4999999, 0.4999999, 0.4999999, 0}, | |
560 {-0.2705980, 0.6532815, 0.6532814, 0.2705980, 0}, | |
561 {-0.6532815, 0.2705980, 0.2705980, 0.6532814, 0}, | |
562 {-0.6532813, 0.6532813, 0.2705979, 0.2705979, 0}, | |
563 {-0.9238793, 0.0, 0.0, 0.3826833, 0}, | |
564 { 0.0, 0.9238793, 0.3826833, 0.0, 0}, | |
565 {-0.3535533, 0.8535533, 0.3535533, 0.1464466, 0}, | |
566 {-0.8535533, 0.3535533, 0.1464466, 0.3535533, 0}, | |
567 {-0.3826833, 0.9238794, 0.0, 0.0, 0}, | |
568 {-0.9238794, 0.3826833, 0.0, 0.0, 0}, | |
569 {-COS45, 0.0, 0.0, SIN45, 0}, | |
570 { COS45, 0.0, 0.0, SIN45, 0}, | |
571 { 0.0, 0.0, 0.0, 1.0, 0} | |
572 }; | |
573 | |
574 enum { | |
575 VIEW_PASS = 0, | |
576 VIEW_APPLY, | |
577 VIEW_CONFIRM | |
578 }; | |
579 | |
580 /* NOTE: these defines are saved in keymap files, do not change values but just
add new ones */ | |
581 #define VIEW_MODAL_CONFIRM 1 /* used for all view operations */ | |
582 #define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2 | |
583 #define VIEWROT_MODAL_AXIS_SNAP_DISABLE 3 | |
584 #define VIEWROT_MODAL_SWITCH_ZOOM 4 | |
585 #define VIEWROT_MODAL_SWITCH_MOVE 5 | |
586 #define VIEWROT_MODAL_SWITCH_ROTATE 6 | |
587 | |
588 /* called in transform_ops.c, on each regeneration of keymaps */ | |
589 void viewrotate_modal_keymap(wmKeyConfig *keyconf) | |
590 { | |
591 static EnumPropertyItem modal_items[] = { | |
592 {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, | |
593 | |
594 {VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Enab
le Axis Snap", ""}, | |
595 {VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Dis
able Axis Snap", ""}, | |
596 ················ | |
597 {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom
"}, | |
598 {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move
"}, | |
599 | |
600 {0, NULL, 0, NULL, NULL} | |
601 }; | |
602 | |
603 wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Rotate Modal"); | |
604 | |
605 /* this function is called for each spacetype, only needs to add map onc
e */ | |
606 if (keymap && keymap->modal_items) return; | |
607 | |
608 keymap = WM_modalkeymap_add(keyconf, "View3D Rotate Modal", modal_items)
; | |
609 | |
610 /* items for modal map */ | |
611 WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW
_MODAL_CONFIRM); | |
612 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_
CONFIRM); | |
613 | |
614 WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_PRESS, KM_ANY, 0, VIEWROT
_MODAL_AXIS_SNAP_ENABLE); | |
615 WM_modalkeymap_add_item(keymap, LEFTALTKEY, KM_RELEASE, KM_ANY, 0, VIEWR
OT_MODAL_AXIS_SNAP_DISABLE); | |
616 | |
617 /* disabled mode switching for now, can re-implement better, later on */ | |
618 #if 0 | |
619 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_
MODAL_SWITCH_ZOOM); | |
620 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWRO
T_MODAL_SWITCH_ZOOM); | |
621 WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWR
OT_MODAL_SWITCH_MOVE); | |
622 #endif | |
623 ········ | |
624 /* assign map to operators */ | |
625 WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate"); | |
626 | |
627 } | |
628 | |
629 static void viewrotate_apply(ViewOpsData *vod, int x, int y) | |
630 { | |
631 RegionView3D *rv3d = vod->rv3d; | |
632 | |
633 rv3d->view = RV3D_VIEW_USER; /* need to reset everytime because of view
snapping */ | |
634 | |
635 if (U.flag & USER_TRACKBALL) { | |
636 float phi, si, q1[4], dvec[3], newvec[3]; | |
637 | |
638 calctrackballvec(&vod->ar->winrct, x, y, newvec); | |
639 | |
640 sub_v3_v3v3(dvec, newvec, vod->trackvec); | |
641 | |
642 si = len_v3(dvec); | |
643 si /= (float)(2.0 * TRACKBALLSIZE); | |
644 | |
645 cross_v3_v3v3(q1 + 1, vod->trackvec, newvec); | |
646 normalize_v3(q1 + 1); | |
647 | |
648 /* Allow for rotation beyond the interval [-pi, pi] */ | |
649 while (si > 1.0f) | |
650 si -= 2.0f; | |
651 | |
652 /* This relation is used instead of | |
653 * - phi = asin(si) so that the angle | |
654 * - of rotation is linearly proportional | |
655 * - to the distance that the mouse is | |
656 * - dragged. */ | |
657 phi = si * (float)(M_PI / 2.0); | |
658 | |
659 q1[0] = cos(phi); | |
660 mul_v3_fl(q1 + 1, sin(phi)); | |
661 mul_qt_qtqt(vod->viewquat, q1, vod->oldquat); | |
662 | |
663 if (vod->use_dyn_ofs) { | |
664 /* compute the post multiplication quat, to rotate the o
ffset correctly */ | |
665 copy_qt_qt(q1, vod->oldquat); | |
666 conjugate_qt(q1); | |
667 mul_qt_qtqt(q1, q1, vod->viewquat); | |
668 | |
669 conjugate_qt(q1); /* conj == inv for unit quat */ | |
670 copy_v3_v3(rv3d->ofs, vod->ofs); | |
671 sub_v3_v3(rv3d->ofs, vod->dyn_ofs); | |
672 mul_qt_v3(q1, rv3d->ofs); | |
673 add_v3_v3(rv3d->ofs, vod->dyn_ofs); | |
674 } | |
675 } | |
676 else { | |
677 /* New turntable view code by John Aughey */ | |
678 float q1[4]; | |
679 float m[3][3]; | |
680 float m_inv[3][3]; | |
681 const float zvec_global[3] = {0.0f, 0.0f, 1.0f}; | |
682 float xaxis[3]; | |
683 | |
684 /* Sensitivity will control how fast the viewport rotates. 0.00
7 was | |
685 * obtained experimentally by looking at viewport rotation sensi
tivities | |
686 * on other modeling programs. */ | |
687 /* Perhaps this should be a configurable user parameter. */ | |
688 const float sensitivity = 0.007f; | |
689 | |
690 /* Get the 3x3 matrix and its inverse from the quaternion */ | |
691 quat_to_mat3(m, vod->viewquat); | |
692 invert_m3_m3(m_inv, m); | |
693 | |
694 /* avoid gimble lock */ | |
695 #if 1 | |
696 if (len_squared_v3v3(zvec_global, m_inv[2]) > 0.001f) { | |
697 float fac; | |
698 cross_v3_v3v3(xaxis, zvec_global, m_inv[2]); | |
699 if (dot_v3v3(xaxis, m_inv[0]) < 0) { | |
700 negate_v3(xaxis); | |
701 } | |
702 fac = angle_normalized_v3v3(zvec_global, m_inv[2]) / (fl
oat)M_PI; | |
703 fac = fabsf(fac - 0.5f) * 2; | |
704 fac = fac * fac; | |
705 interp_v3_v3v3(xaxis, xaxis, m_inv[0], fac); | |
706 } | |
707 else { | |
708 copy_v3_v3(xaxis, m_inv[0]); | |
709 } | |
710 #else | |
711 copy_v3_v3(xaxis, m_inv[0]); | |
712 #endif | |
713 | |
714 /* Determine the direction of the x vector (for rotating up and
down) */ | |
715 /* This can likely be computed directly from the quaternion. */ | |
716 | |
717 /* Perform the up/down rotation */ | |
718 axis_angle_to_quat(q1, xaxis, sensitivity * -(y - vod->oldy)); | |
719 mul_qt_qtqt(vod->viewquat, vod->viewquat, q1); | |
720 | |
721 if (vod->use_dyn_ofs) { | |
722 conjugate_qt(q1); /* conj == inv for unit quat */ | |
723 sub_v3_v3(rv3d->ofs, vod->dyn_ofs); | |
724 mul_qt_v3(q1, rv3d->ofs); | |
725 add_v3_v3(rv3d->ofs, vod->dyn_ofs); | |
726 } | |
727 | |
728 /* Perform the orbital rotation */ | |
729 axis_angle_to_quat(q1, zvec_global, sensitivity * vod->reverse *
(x - vod->oldx)); | |
730 mul_qt_qtqt(vod->viewquat, vod->viewquat, q1); | |
731 | |
732 if (vod->use_dyn_ofs) { | |
733 conjugate_qt(q1); | |
734 sub_v3_v3(rv3d->ofs, vod->dyn_ofs); | |
735 mul_qt_v3(q1, rv3d->ofs); | |
736 add_v3_v3(rv3d->ofs, vod->dyn_ofs); | |
737 } | |
738 } | |
739 | |
740 /* check for view snap */ | |
741 if (vod->axis_snap) { | |
742 int i; | |
743 float viewquat_inv[4]; | |
744 float zaxis[3] = {0, 0, 1}; | |
745 invert_qt_qt(viewquat_inv, vod->viewquat); | |
746 | |
747 mul_qt_v3(viewquat_inv, zaxis); | |
748 | |
749 for (i = 0; i < NUM_SNAP_QUATS; i++) { | |
750 | |
751 float view = (int)snapquats[i][4]; | |
752 float viewquat_inv_test[4]; | |
753 float zaxis_test[3] = {0, 0, 1}; | |
754 | |
755 invert_qt_qt(viewquat_inv_test, snapquats[i]); | |
756 mul_qt_v3(viewquat_inv_test, zaxis_test); | |
757 ························ | |
758 if (angle_v3v3(zaxis_test, zaxis) < DEG2RADF(45 / 3)) { | |
759 /* find the best roll */ | |
760 float quat_roll[4], quat_final[4], quat_best[4]; | |
761 float viewquat_align[4]; /* viewquat aligned to
zaxis_test */ | |
762 float viewquat_align_inv[4]; /* viewquat aligned
to zaxis_test */ | |
763 float best_angle = FLT_MAX; | |
764 int j; | |
765 | |
766 /* viewquat_align is the original viewquat align
ed to the snapped axis | |
767 * for testing roll */ | |
768 rotation_between_vecs_to_quat(viewquat_align, za
xis_test, zaxis); | |
769 normalize_qt(viewquat_align); | |
770 mul_qt_qtqt(viewquat_align, vod->viewquat, viewq
uat_align); | |
771 normalize_qt(viewquat_align); | |
772 invert_qt_qt(viewquat_align_inv, viewquat_align)
; | |
773 | |
774 /* find best roll */ | |
775 for (j = 0; j < 8; j++) { | |
776 float angle; | |
777 float xaxis1[3] = {1, 0, 0}; | |
778 float xaxis2[3] = {1, 0, 0}; | |
779 float quat_final_inv[4]; | |
780 | |
781 axis_angle_to_quat(quat_roll, zaxis_test
, (float)j * DEG2RADF(45.0f)); | |
782 normalize_qt(quat_roll); | |
783 | |
784 mul_qt_qtqt(quat_final, snapquats[i], qu
at_roll); | |
785 normalize_qt(quat_final); | |
786 ········································ | |
787 /* compare 2 vector angles to find the l
east roll */ | |
788 invert_qt_qt(quat_final_inv, quat_final)
; | |
789 mul_qt_v3(viewquat_align_inv, xaxis1); | |
790 mul_qt_v3(quat_final_inv, xaxis2); | |
791 angle = angle_v3v3(xaxis1, xaxis2); | |
792 | |
793 if (angle <= best_angle) { | |
794 best_angle = angle; | |
795 copy_qt_qt(quat_best, quat_final
); | |
796 if (j) view = 0; /* view grid a
ssumes certain up axis */ | |
797 } | |
798 } | |
799 | |
800 copy_qt_qt(vod->viewquat, quat_best); | |
801 rv3d->view = view; /* if we snap to a rolled cam
era the grid is invalid */ | |
802 | |
803 break; | |
804 } | |
805 } | |
806 } | |
807 vod->oldx = x; | |
808 vod->oldy = y; | |
809 | |
810 /* avoid precision loss over time */ | |
811 normalize_qt(vod->viewquat); | |
812 | |
813 /* use a working copy so view rotation locking doesnt overwrite the lock
ed | |
814 * rotation back into the view we calculate with */ | |
815 copy_qt_qt(rv3d->viewquat, vod->viewquat); | |
816 | |
817 ED_view3d_camera_lock_sync(vod->v3d, rv3d); | |
818 | |
819 ED_region_tag_redraw(vod->ar); | |
820 } | |
821 | |
822 static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) | |
823 { | |
824 ViewOpsData *vod = op->customdata; | |
825 short event_code = VIEW_PASS; | |
826 | |
827 /* execute the events */ | |
828 if (event->type == MOUSEMOVE) { | |
829 event_code = VIEW_APPLY; | |
830 } | |
831 else if (event->type == EVT_MODAL_MAP) { | |
832 switch (event->val) { | |
833 case VIEW_MODAL_CONFIRM: | |
834 event_code = VIEW_CONFIRM; | |
835 break; | |
836 case VIEWROT_MODAL_AXIS_SNAP_ENABLE: | |
837 vod->axis_snap = TRUE; | |
838 event_code = VIEW_APPLY; | |
839 break; | |
840 case VIEWROT_MODAL_AXIS_SNAP_DISABLE: | |
841 vod->axis_snap = FALSE; | |
842 event_code = VIEW_APPLY; | |
843 break; | |
844 case VIEWROT_MODAL_SWITCH_ZOOM: | |
845 WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP
_INVOKE_DEFAULT, NULL); | |
846 event_code = VIEW_CONFIRM; | |
847 break; | |
848 case VIEWROT_MODAL_SWITCH_MOVE: | |
849 WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP
_INVOKE_DEFAULT, NULL); | |
850 event_code = VIEW_CONFIRM; | |
851 break; | |
852 } | |
853 } | |
854 else if (event->type == vod->origkey && event->val == KM_RELEASE) { | |
855 event_code = VIEW_CONFIRM; | |
856 } | |
857 | |
858 if (event_code == VIEW_APPLY) { | |
859 viewrotate_apply(vod, event->x, event->y); | |
860 } | |
861 else if (event_code == VIEW_CONFIRM) { | |
862 ED_view3d_depth_tag_update(vod->rv3d); | |
863 viewops_data_free(C, op); | |
864 | |
865 return OPERATOR_FINISHED; | |
866 } | |
867 | |
868 return OPERATOR_RUNNING_MODAL; | |
869 } | |
870 | |
871 static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
872 { | |
873 ViewOpsData *vod; | |
874 RegionView3D *rv3d; | |
875 | |
876 /* makes op->customdata */ | |
877 viewops_data_create(C, op, event); | |
878 vod = op->customdata; | |
879 rv3d = vod->rv3d; | |
880 | |
881 if (rv3d->viewlock) { /* poll should check but in some cases fails, see
poll func for details */ | |
882 viewops_data_free(C, op); | |
883 return OPERATOR_PASS_THROUGH; | |
884 } | |
885 | |
886 /* switch from camera view when: */ | |
887 if (rv3d->persp != RV3D_PERSP) { | |
888 | |
889 if (U.uiflag & USER_AUTOPERSP) { | |
890 if (!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { | |
891 rv3d->persp = RV3D_PERSP; | |
892 } | |
893 } | |
894 else if (rv3d->persp == RV3D_CAMOB) { | |
895 | |
896 /* changed since 2.4x, use the camera view */ | |
897 if (vod->v3d->camera) { | |
898 ED_view3d_from_object(vod->v3d->camera, rv3d->of
s, rv3d->viewquat, &rv3d->dist, NULL); | |
899 } | |
900 | |
901 if (!ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) { | |
902 rv3d->persp = rv3d->lpersp; | |
903 } | |
904 } | |
905 ED_region_tag_redraw(vod->ar); | |
906 } | |
907 ········ | |
908 if (event->type == MOUSEPAN) { | |
909 viewrotate_apply(vod, event->prevx, event->prevy); | |
910 ED_view3d_depth_tag_update(rv3d); | |
911 ················ | |
912 viewops_data_free(C, op); | |
913 ················ | |
914 return OPERATOR_FINISHED; | |
915 } | |
916 else if (event->type == MOUSEROTATE) { | |
917 /* MOUSEROTATE performs orbital rotation, so y axis delta is set
to 0 */ | |
918 viewrotate_apply(vod, event->prevx, event->y); | |
919 ED_view3d_depth_tag_update(rv3d); | |
920 ················ | |
921 viewops_data_free(C, op); | |
922 ················ | |
923 return OPERATOR_FINISHED; | |
924 } | |
925 else {·········· | |
926 /* add temp handler */ | |
927 WM_event_add_modal_handler(C, op); | |
928 | |
929 return OPERATOR_RUNNING_MODAL; | |
930 } | |
931 } | |
932 | |
933 static int view3d_camera_active_poll(bContext *C) | |
934 { | |
935 if (ED_operator_view3d_active(C)) { | |
936 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
937 if (rv3d && rv3d->persp == RV3D_CAMOB) { | |
938 return 1; | |
939 } | |
940 } | |
941 | |
942 return 0; | |
943 } | |
944 | |
945 /* test for unlocked camera view in quad view */ | |
946 static int view3d_camera_user_poll(bContext *C) | |
947 { | |
948 View3D *v3d; | |
949 ARegion *ar; | |
950 | |
951 if (ED_view3d_context_user_region(C, &v3d, &ar)) { | |
952 RegionView3D *rv3d = ar->regiondata; | |
953 if (rv3d->persp == RV3D_CAMOB) { | |
954 return 1; | |
955 } | |
956 } | |
957 | |
958 return 0; | |
959 } | |
960 | |
961 static int viewrotate_cancel(bContext *C, wmOperator *op) | |
962 { | |
963 viewops_data_free(C, op); | |
964 | |
965 return OPERATOR_CANCELLED; | |
966 } | |
967 | |
968 void VIEW3D_OT_rotate(wmOperatorType *ot) | |
969 { | |
970 | |
971 /* identifiers */ | |
972 ot->name = "Rotate view"; | |
973 ot->description = "Rotate the view"; | |
974 ot->idname = "VIEW3D_OT_rotate"; | |
975 | |
976 /* api callbacks */ | |
977 ot->invoke = viewrotate_invoke; | |
978 ot->modal = viewrotate_modal; | |
979 ot->poll = ED_operator_region_view3d_active; | |
980 ot->cancel = viewrotate_cancel; | |
981 | |
982 /* flags */ | |
983 ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; | |
984 } | |
985 | |
986 /* NDOF utility functions | |
987 * (should these functions live in this file?) | |
988 */ | |
989 float ndof_to_axis_angle(struct wmNDOFMotionData *ndof, float axis[3]) | |
990 { | |
991 return ndof->dt * normalize_v3_v3(axis, ndof->rvec); | |
992 } | |
993 | |
994 void ndof_to_quat(struct wmNDOFMotionData *ndof, float q[4]) | |
995 { | |
996 float axis[3]; | |
997 float angle; | |
998 | |
999 angle = ndof_to_axis_angle(ndof, axis); | |
1000 axis_angle_to_quat(q, axis, angle); | |
1001 } | |
1002 | |
1003 /* -- "orbit" navigation (trackball/turntable) | |
1004 * -- zooming | |
1005 * -- panning in rotationally-locked views | |
1006 */ | |
1007 static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event
) | |
1008 { | |
1009 if (event->type != NDOF_MOTION) | |
1010 return OPERATOR_CANCELLED; | |
1011 else { | |
1012 View3D *v3d = CTX_wm_view3d(C); | |
1013 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
1014 wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata; | |
1015 | |
1016 ED_view3d_camera_lock_init(v3d, rv3d); | |
1017 | |
1018 rv3d->rot_angle = 0.f; /* off by default, until changed later th
is function */ | |
1019 | |
1020 if (ndof->progress != P_FINISHING) { | |
1021 const float dt = ndof->dt; | |
1022 | |
1023 /* tune these until everything feels right */ | |
1024 const float rot_sensitivity = 1.f; | |
1025 const float zoom_sensitivity = 1.f; | |
1026 const float pan_sensitivity = 1.f; | |
1027 | |
1028 const int has_rotation = rv3d->viewlock != RV3D_LOCKED &
& !is_zero_v3(ndof->rvec); | |
1029 | |
1030 float view_inv[4]; | |
1031 invert_qt_qt(view_inv, rv3d->viewquat); | |
1032 | |
1033 /* #define DEBUG_NDOF_MOTION */ | |
1034 #ifdef DEBUG_NDOF_MOTION | |
1035 printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%
.3f delivered to 3D view\n", | |
1036 ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry,
ndof->rz, ndof->dt); | |
1037 #endif | |
1038 | |
1039 if (ndof->tz) { | |
1040 /* Zoom! | |
1041 * velocity should be proportional to the linear
velocity attained by rotational motion of same strength | |
1042 * [got that?] | |
1043 * proportional to arclength = radius * angle | |
1044 */ | |
1045 float zoom_distance = zoom_sensitivity * rv3d->d
ist * dt * ndof->tz; | |
1046 | |
1047 if (U.ndof_flag & NDOF_ZOOM_INVERT) | |
1048 zoom_distance = -zoom_distance; | |
1049 | |
1050 rv3d->dist += zoom_distance; | |
1051 } | |
1052 | |
1053 if (rv3d->viewlock == RV3D_LOCKED) { | |
1054 /* rotation not allowed -- explore panning optio
ns instead */ | |
1055 float pan_vec[3] = {ndof->tx, ndof->ty, 0.0f}; | |
1056 mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist
* dt); | |
1057 | |
1058 /* transform motion from view to world coordinat
es */ | |
1059 invert_qt_qt(view_inv, rv3d->viewquat); | |
1060 mul_qt_v3(view_inv, pan_vec); | |
1061 | |
1062 /* move center of view opposite of hand motion (
this is camera mode, not object mode) */ | |
1063 sub_v3_v3(rv3d->ofs, pan_vec); | |
1064 } | |
1065 | |
1066 if (has_rotation) { | |
1067 | |
1068 rv3d->view = RV3D_VIEW_USER; | |
1069 | |
1070 if (U.flag & USER_TRACKBALL) { | |
1071 float rot[4]; | |
1072 float axis[3]; | |
1073 float angle = rot_sensitivity * ndof_to_
axis_angle(ndof, axis); | |
1074 | |
1075 if (U.ndof_flag & NDOF_ROLL_INVERT_AXIS) | |
1076 axis[2] = -axis[2]; | |
1077 | |
1078 if (U.ndof_flag & NDOF_TILT_INVERT_AXIS) | |
1079 axis[0] = -axis[0]; | |
1080 | |
1081 if (U.ndof_flag & NDOF_ROTATE_INVERT_AXI
S) | |
1082 axis[1] = -axis[1]; | |
1083 | |
1084 /* transform rotation axis from view to
world coordinates */ | |
1085 mul_qt_v3(view_inv, axis); | |
1086 | |
1087 /* update the onscreen doo-dad */ | |
1088 rv3d->rot_angle = angle; | |
1089 copy_v3_v3(rv3d->rot_axis, axis); | |
1090 | |
1091 axis_angle_to_quat(rot, axis, angle); | |
1092 | |
1093 /* apply rotation */ | |
1094 mul_qt_qtqt(rv3d->viewquat, rv3d->viewqu
at, rot); | |
1095 | |
1096 } | |
1097 else { | |
1098 | |
1099 /* turntable view code by John Aughey, a
dapted for 3D mouse by [mce] */ | |
1100 float angle, rot[4]; | |
1101 float xvec[3] = {1, 0, 0}; | |
1102 | |
1103 /* Determine the direction of the x vect
or (for rotating up and down) */ | |
1104 mul_qt_v3(view_inv, xvec); | |
1105 | |
1106 /* Perform the up/down rotation */ | |
1107 angle = rot_sensitivity * dt * ndof->rx; | |
1108 if (U.ndof_flag & NDOF_TILT_INVERT_AXIS) | |
1109 angle = -angle; | |
1110 rot[0] = cos(angle); | |
1111 mul_v3_v3fl(rot + 1, xvec, sin(angle)); | |
1112 mul_qt_qtqt(rv3d->viewquat, rv3d->viewqu
at, rot); | |
1113 | |
1114 /* Perform the orbital rotation */ | |
1115 angle = rot_sensitivity * dt * ndof->ry; | |
1116 if (U.ndof_flag & NDOF_ROTATE_INVERT_AXI
S) | |
1117 angle = -angle; | |
1118 | |
1119 /* update the onscreen doo-dad */ | |
1120 rv3d->rot_angle = angle; | |
1121 rv3d->rot_axis[0] = 0; | |
1122 rv3d->rot_axis[1] = 0; | |
1123 rv3d->rot_axis[2] = 1; | |
1124 | |
1125 rot[0] = cos(angle); | |
1126 rot[1] = rot[2] = 0.0; | |
1127 rot[3] = sin(angle); | |
1128 mul_qt_qtqt(rv3d->viewquat, rv3d->viewqu
at, rot); | |
1129 } | |
1130 } | |
1131 } | |
1132 | |
1133 ED_view3d_camera_lock_sync(v3d, rv3d); | |
1134 | |
1135 ED_region_tag_redraw(CTX_wm_region(C)); | |
1136 | |
1137 return OPERATOR_FINISHED; | |
1138 } | |
1139 } | |
1140 | |
1141 void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) | |
1142 { | |
1143 /* identifiers */ | |
1144 ot->name = "NDOF Orbit View"; | |
1145 ot->description = "Explore every angle of an object using the 3D mouse"; | |
1146 ot->idname = "VIEW3D_OT_ndof_orbit"; | |
1147 | |
1148 /* api callbacks */ | |
1149 ot->invoke = ndof_orbit_invoke; | |
1150 ot->poll = ED_operator_view3d_active; | |
1151 | |
1152 /* flags */ | |
1153 ot->flag = 0; | |
1154 } | |
1155 | |
1156 /* -- "pan" navigation | |
1157 * -- zoom or dolly? | |
1158 */ | |
1159 static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) | |
1160 { | |
1161 if (event->type != NDOF_MOTION) | |
1162 return OPERATOR_CANCELLED; | |
1163 else { | |
1164 View3D *v3d = CTX_wm_view3d(C); | |
1165 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
1166 wmNDOFMotionData *ndof = (wmNDOFMotionData *) event->customdata; | |
1167 | |
1168 ED_view3d_camera_lock_init(v3d, rv3d); | |
1169 | |
1170 rv3d->rot_angle = 0.f; /* we're panning here! so erase any lefto
ver rotation from other operators */ | |
1171 | |
1172 if (ndof->progress != P_FINISHING) { | |
1173 const float dt = ndof->dt; | |
1174 float view_inv[4]; | |
1175 #if 0 /* ------------------------------------------- zoom with Z */ | |
1176 /* tune these until everything feels right */ | |
1177 const float zoom_sensitivity = 1.f; | |
1178 const float pan_sensitivity = 1.f; | |
1179 | |
1180 float pan_vec[3] = { | |
1181 ndof->tx, ndof->ty, 0 | |
1182 }; | |
1183 | |
1184 /* "zoom in" or "translate"? depends on zoom mode in use
r settings? */ | |
1185 if (ndof->tz) { | |
1186 float zoom_distance = zoom_sensitivity * rv3d->d
ist * dt * ndof->tz; | |
1187 rv3d->dist += zoom_distance; | |
1188 } | |
1189 | |
1190 mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); | |
1191 #else /* ------------------------------------------------------- dolly with Z */ | |
1192 float speed = 10.f; /* blender units per second */ | |
1193 /* ^^ this is ok for default cube scene, but should scal
e with.. something */ | |
1194 | |
1195 /* tune these until everything feels right */ | |
1196 const float forward_sensitivity = 1.f; | |
1197 const float vertical_sensitivity = 0.4f; | |
1198 const float lateral_sensitivity = 0.6f; | |
1199 | |
1200 float pan_vec[3]; | |
1201 | |
1202 if (U.ndof_flag & NDOF_PANX_INVERT_AXIS) | |
1203 pan_vec[0] = -lateral_sensitivity * ndof->tvec[0
]; | |
1204 else | |
1205 pan_vec[0] = lateral_sensitivity * ndof->tvec[0]
; | |
1206 | |
1207 if (U.ndof_flag & NDOF_PANZ_INVERT_AXIS) | |
1208 pan_vec[1] = -vertical_sensitivity * ndof->tvec[
1]; | |
1209 else | |
1210 pan_vec[1] = vertical_sensitivity * ndof->tvec[1
]; | |
1211 | |
1212 if (U.ndof_flag & NDOF_PANY_INVERT_AXIS) | |
1213 pan_vec[2] = -forward_sensitivity * ndof->tvec[2
]; | |
1214 else | |
1215 pan_vec[2] = forward_sensitivity * ndof->tvec[2]
; | |
1216 | |
1217 mul_v3_fl(pan_vec, speed * dt); | |
1218 #endif | |
1219 /* transform motion from view to world coordinates */ | |
1220 invert_qt_qt(view_inv, rv3d->viewquat); | |
1221 mul_qt_v3(view_inv, pan_vec); | |
1222 | |
1223 /* move center of view opposite of hand motion (this is
camera mode, not object mode) */ | |
1224 sub_v3_v3(rv3d->ofs, pan_vec); | |
1225 } | |
1226 | |
1227 ED_view3d_camera_lock_sync(v3d, rv3d); | |
1228 | |
1229 ED_region_tag_redraw(CTX_wm_region(C)); | |
1230 | |
1231 return OPERATOR_FINISHED; | |
1232 } | |
1233 } | |
1234 | |
1235 void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) | |
1236 { | |
1237 /* identifiers */ | |
1238 ot->name = "NDOF Pan View"; | |
1239 ot->description = "Position your viewpoint with the 3D mouse"; | |
1240 ot->idname = "VIEW3D_OT_ndof_pan"; | |
1241 | |
1242 /* api callbacks */ | |
1243 ot->invoke = ndof_pan_invoke; | |
1244 ot->poll = ED_operator_view3d_active; | |
1245 | |
1246 /* flags */ | |
1247 ot->flag = 0; | |
1248 } | |
1249 | |
1250 /* ************************ viewmove ******************************** */ | |
1251 | |
1252 | |
1253 /* NOTE: these defines are saved in keymap files, do not change values but just
add new ones */ | |
1254 | |
1255 /* called in transform_ops.c, on each regeneration of keymaps */ | |
1256 void viewmove_modal_keymap(wmKeyConfig *keyconf) | |
1257 { | |
1258 static EnumPropertyItem modal_items[] = { | |
1259 {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, | |
1260 ················ | |
1261 {VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom
"}, | |
1262 {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to
Rotate"}, | |
1263 | |
1264 {0, NULL, 0, NULL, NULL} | |
1265 }; | |
1266 | |
1267 wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Move Modal"); | |
1268 | |
1269 /* this function is called for each spacetype, only needs to add map onc
e */ | |
1270 if (keymap && keymap->modal_items) return; | |
1271 | |
1272 keymap = WM_modalkeymap_add(keyconf, "View3D Move Modal", modal_items); | |
1273 | |
1274 /* items for modal map */ | |
1275 WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW
_MODAL_CONFIRM); | |
1276 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_
CONFIRM); | |
1277 | |
1278 /* disabled mode switching for now, can re-implement better, later on */ | |
1279 #if 0 | |
1280 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_PRESS, KM_ANY, 0, VIEWROT_
MODAL_SWITCH_ZOOM); | |
1281 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWRO
T_MODAL_SWITCH_ZOOM); | |
1282 WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIE
WROT_MODAL_SWITCH_ROTATE); | |
1283 #endif | |
1284 ········ | |
1285 /* assign map to operators */ | |
1286 WM_modalkeymap_assign(keymap, "VIEW3D_OT_move"); | |
1287 } | |
1288 | |
1289 | |
1290 static void viewmove_apply(ViewOpsData *vod, int x, int y) | |
1291 { | |
1292 if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod
->v3d, vod->rv3d)) { | |
1293 const float zoomfac = BKE_screen_view3d_zoom_to_fac((float)vod->
rv3d->camzoom) * 2.0f; | |
1294 vod->rv3d->camdx += (vod->oldx - x) / (vod->ar->winx * zoomfac); | |
1295 vod->rv3d->camdy += (vod->oldy - y) / (vod->ar->winy * zoomfac); | |
1296 CLAMP(vod->rv3d->camdx, -1.0f, 1.0f); | |
1297 CLAMP(vod->rv3d->camdy, -1.0f, 1.0f); | |
1298 } | |
1299 else { | |
1300 float dvec[3]; | |
1301 float mval_f[2]; | |
1302 | |
1303 mval_f[0] = x - vod->oldx; | |
1304 mval_f[1] = y - vod->oldy; | |
1305 ED_view3d_win_to_delta(vod->ar, mval_f, dvec); | |
1306 | |
1307 add_v3_v3(vod->rv3d->ofs, dvec); | |
1308 | |
1309 if (vod->rv3d->viewlock & RV3D_BOXVIEW) | |
1310 view3d_boxview_sync(vod->sa, vod->ar); | |
1311 } | |
1312 | |
1313 vod->oldx = x; | |
1314 vod->oldy = y; | |
1315 | |
1316 ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); | |
1317 | |
1318 ED_region_tag_redraw(vod->ar); | |
1319 } | |
1320 | |
1321 | |
1322 static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) | |
1323 { | |
1324 | |
1325 ViewOpsData *vod = op->customdata; | |
1326 short event_code = VIEW_PASS; | |
1327 | |
1328 /* execute the events */ | |
1329 if (event->type == MOUSEMOVE) { | |
1330 event_code = VIEW_APPLY; | |
1331 } | |
1332 else if (event->type == EVT_MODAL_MAP) { | |
1333 switch (event->val) { | |
1334 case VIEW_MODAL_CONFIRM: | |
1335 event_code = VIEW_CONFIRM; | |
1336 break; | |
1337 case VIEWROT_MODAL_SWITCH_ZOOM: | |
1338 WM_operator_name_call(C, "VIEW3D_OT_zoom", WM_OP
_INVOKE_DEFAULT, NULL); | |
1339 event_code = VIEW_CONFIRM; | |
1340 break; | |
1341 case VIEWROT_MODAL_SWITCH_ROTATE: | |
1342 WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_
OP_INVOKE_DEFAULT, NULL); | |
1343 event_code = VIEW_CONFIRM; | |
1344 break; | |
1345 } | |
1346 } | |
1347 else if (event->type == vod->origkey && event->val == KM_RELEASE) { | |
1348 event_code = VIEW_CONFIRM; | |
1349 } | |
1350 | |
1351 if (event_code == VIEW_APPLY) { | |
1352 viewmove_apply(vod, event->x, event->y); | |
1353 } | |
1354 else if (event_code == VIEW_CONFIRM) { | |
1355 ED_view3d_depth_tag_update(vod->rv3d); | |
1356 | |
1357 viewops_data_free(C, op); | |
1358 | |
1359 return OPERATOR_FINISHED; | |
1360 } | |
1361 | |
1362 return OPERATOR_RUNNING_MODAL; | |
1363 } | |
1364 | |
1365 static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
1366 { | |
1367 ViewOpsData *vod; | |
1368 | |
1369 /* makes op->customdata */ | |
1370 viewops_data_create(C, op, event); | |
1371 vod = op->customdata; | |
1372 | |
1373 if (event->type == MOUSEPAN) { | |
1374 viewmove_apply(vod, event->prevx, event->prevy); | |
1375 ED_view3d_depth_tag_update(vod->rv3d); | |
1376 ················ | |
1377 viewops_data_free(C, op);··············· | |
1378 ················ | |
1379 return OPERATOR_FINISHED; | |
1380 } | |
1381 else { | |
1382 /* add temp handler */ | |
1383 WM_event_add_modal_handler(C, op); | |
1384 | |
1385 return OPERATOR_RUNNING_MODAL; | |
1386 } | |
1387 } | |
1388 | |
1389 static int viewmove_cancel(bContext *C, wmOperator *op) | |
1390 { | |
1391 viewops_data_free(C, op); | |
1392 | |
1393 return OPERATOR_CANCELLED; | |
1394 } | |
1395 | |
1396 void VIEW3D_OT_move(wmOperatorType *ot) | |
1397 { | |
1398 | |
1399 /* identifiers */ | |
1400 ot->name = "Move view"; | |
1401 ot->description = "Move the view"; | |
1402 ot->idname = "VIEW3D_OT_move"; | |
1403 | |
1404 /* api callbacks */ | |
1405 ot->invoke = viewmove_invoke; | |
1406 ot->modal = viewmove_modal; | |
1407 ot->poll = ED_operator_view3d_active; | |
1408 ot->cancel = viewmove_cancel; | |
1409 | |
1410 /* flags */ | |
1411 ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; | |
1412 } | |
1413 | |
1414 /* ************************ viewzoom ******************************** */ | |
1415 | |
1416 /* viewdolly_modal_keymap has an exact copy of this, apply fixes to both */ | |
1417 /* called in transform_ops.c, on each regeneration of keymaps */ | |
1418 void viewzoom_modal_keymap(wmKeyConfig *keyconf) | |
1419 { | |
1420 static EnumPropertyItem modal_items[] = { | |
1421 {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, | |
1422 ················ | |
1423 {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to
Rotate"}, | |
1424 {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move
"}, | |
1425 | |
1426 {0, NULL, 0, NULL, NULL}}; | |
1427 | |
1428 wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Zoom Modal"); | |
1429 | |
1430 /* this function is called for each spacetype, only needs to add map onc
e */ | |
1431 if (keymap && keymap->modal_items) return; | |
1432 | |
1433 keymap = WM_modalkeymap_add(keyconf, "View3D Zoom Modal", modal_items); | |
1434 | |
1435 /* items for modal map */ | |
1436 WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW
_MODAL_CONFIRM); | |
1437 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_
CONFIRM); | |
1438 | |
1439 /* disabled mode switching for now, can re-implement better, later on */ | |
1440 #if 0 | |
1441 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWRO
T_MODAL_SWITCH_ROTATE); | |
1442 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEW
ROT_MODAL_SWITCH_ROTATE); | |
1443 WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWR
OT_MODAL_SWITCH_MOVE); | |
1444 #endif | |
1445 ········ | |
1446 /* assign map to operators */ | |
1447 WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom"); | |
1448 } | |
1449 | |
1450 static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my) | |
1451 { | |
1452 RegionView3D *rv3d = ar->regiondata; | |
1453 | |
1454 if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) { | |
1455 float dvec[3]; | |
1456 float tvec[3]; | |
1457 float tpos[3]; | |
1458 float mval_f[2]; | |
1459 float new_dist; | |
1460 | |
1461 negate_v3_v3(tpos, rv3d->ofs); | |
1462 | |
1463 /* Project cursor position into 3D space */ | |
1464 initgrabz(rv3d, tpos[0], tpos[1], tpos[2]); | |
1465 | |
1466 mval_f[0] = (float)(((mx - ar->winrct.xmin) * 2) - ar->winx) / 2
.0f; | |
1467 mval_f[1] = (float)(((my - ar->winrct.ymin) * 2) - ar->winy) / 2
.0f; | |
1468 ED_view3d_win_to_delta(ar, mval_f, dvec); | |
1469 | |
1470 /* Calculate view target position for dolly */ | |
1471 add_v3_v3v3(tvec, tpos, dvec); | |
1472 negate_v3(tvec); | |
1473 | |
1474 /* Offset to target position and dolly */ | |
1475 new_dist = rv3d->dist * dfac; | |
1476 | |
1477 copy_v3_v3(rv3d->ofs, tvec); | |
1478 rv3d->dist = new_dist; | |
1479 | |
1480 /* Calculate final offset */ | |
1481 madd_v3_v3v3fl(rv3d->ofs, tvec, dvec, dfac); | |
1482 } | |
1483 else { | |
1484 rv3d->dist *= dfac; | |
1485 } | |
1486 } | |
1487 | |
1488 | |
1489 static void viewzoom_apply(ViewOpsData *vod, int x, int y, const short viewzoom,
const short zoom_invert) | |
1490 { | |
1491 float zfac = 1.0; | |
1492 short use_cam_zoom; | |
1493 | |
1494 use_cam_zoom = (vod->rv3d->persp == RV3D_CAMOB) && !(vod->rv3d->is_persp
&& ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)); | |
1495 | |
1496 if (use_cam_zoom) { | |
1497 float delta; | |
1498 delta = (x - vod->origx + y - vod->origy) / 10.0f; | |
1499 vod->rv3d->camzoom = vod->camzoom0 - delta; | |
1500 | |
1501 CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); | |
1502 } | |
1503 if (viewzoom == USER_ZOOM_CONT) { | |
1504 double time = PIL_check_seconds_timer(); | |
1505 float time_step = (float)(time - vod->timer_lastdraw); | |
1506 float fac; | |
1507 | |
1508 if (U.uiflag & USER_ZOOM_HORIZ) { | |
1509 fac = (float)(x - vod->origx); | |
1510 } | |
1511 else { | |
1512 fac = (float)(y - vod->origy); | |
1513 } | |
1514 | |
1515 if (zoom_invert) { | |
1516 fac = -fac; | |
1517 } | |
1518 | |
1519 // oldstyle zoom | |
1520 zfac = 1.0f + ((fac / 20.0f) * time_step); | |
1521 vod->timer_lastdraw = time; | |
1522 } | |
1523 else if (viewzoom == USER_ZOOM_SCALE) { | |
1524 int ctr[2], len1, len2; | |
1525 // method which zooms based on how far you move the mouse | |
1526 | |
1527 ctr[0] = (vod->ar->winrct.xmax + vod->ar->winrct.xmin) / 2; | |
1528 ctr[1] = (vod->ar->winrct.ymax + vod->ar->winrct.ymin) / 2; | |
1529 | |
1530 len1 = (int)sqrt((ctr[0] - x) * (ctr[0] - x) + (ctr[1] - y) * (c
tr[1] - y)) + 5; | |
1531 len2 = (int)sqrt((ctr[0] - vod->origx) * (ctr[0] - vod->origx) +
(ctr[1] - vod->origy) * (ctr[1] - vod->origy)) + 5; | |
1532 | |
1533 zfac = vod->dist0 * ((float)len2 / len1) / vod->rv3d->dist; | |
1534 } | |
1535 else { /* USER_ZOOM_DOLLY */ | |
1536 float len1, len2; | |
1537 ················ | |
1538 if (U.uiflag & USER_ZOOM_HORIZ) { | |
1539 len1 = (vod->ar->winrct.xmax - x) + 5; | |
1540 len2 = (vod->ar->winrct.xmax - vod->origx) + 5; | |
1541 } | |
1542 else { | |
1543 len1 = (vod->ar->winrct.ymax - y) + 5; | |
1544 len2 = (vod->ar->winrct.ymax - vod->origy) + 5; | |
1545 } | |
1546 if (zoom_invert) { | |
1547 SWAP(float, len1, len2); | |
1548 } | |
1549 ················ | |
1550 if (use_cam_zoom) { | |
1551 zfac = vod->camzoom0 * (2.0f * ((len2 / len1) - 1.0f) +
1.0f) / vod->rv3d->camzoom; | |
1552 zfac = 0; | |
1553 } | |
1554 else { | |
1555 zfac = vod->dist0 * (2.0f * ((len2 / len1) - 1.0f) + 1.0
f) / vod->rv3d->dist; | |
1556 } | |
1557 } | |
1558 | |
1559 if (!use_cam_zoom) { | |
1560 if (zfac != 1.0f && zfac * vod->rv3d->dist > 0.001f * vod->grid
&& | |
1561 zfac * vod->rv3d->dist < 10.0f * vod->far) | |
1562 { | |
1563 view_zoom_mouseloc(vod->ar, zfac, vod->oldx, vod->oldy); | |
1564 } | |
1565 } | |
1566 | |
1567 /* these limits were in old code too */ | |
1568 if (vod->rv3d->dist < 0.001f * vod->grid) vod->rv3d->dist = 0.001f * vod
->grid; | |
1569 if (vod->rv3d->dist > 10.0f * vod->far) vod->rv3d->dist = 10.0f * vod->f
ar; | |
1570 | |
1571 if (vod->rv3d->viewlock & RV3D_BOXVIEW) | |
1572 view3d_boxview_sync(vod->sa, vod->ar); | |
1573 | |
1574 ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); | |
1575 | |
1576 ED_region_tag_redraw(vod->ar); | |
1577 } | |
1578 | |
1579 | |
1580 static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event) | |
1581 { | |
1582 ViewOpsData *vod = op->customdata; | |
1583 short event_code = VIEW_PASS; | |
1584 | |
1585 /* execute the events */ | |
1586 if (event->type == TIMER && event->customdata == vod->timer) { | |
1587 /* continuous zoom */ | |
1588 event_code = VIEW_APPLY; | |
1589 } | |
1590 else if (event->type == MOUSEMOVE) { | |
1591 event_code = VIEW_APPLY; | |
1592 } | |
1593 else if (event->type == EVT_MODAL_MAP) { | |
1594 switch (event->val) { | |
1595 case VIEW_MODAL_CONFIRM: | |
1596 event_code = VIEW_CONFIRM; | |
1597 break; | |
1598 case VIEWROT_MODAL_SWITCH_MOVE: | |
1599 WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP
_INVOKE_DEFAULT, NULL); | |
1600 event_code = VIEW_CONFIRM; | |
1601 break; | |
1602 case VIEWROT_MODAL_SWITCH_ROTATE: | |
1603 WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_
OP_INVOKE_DEFAULT, NULL); | |
1604 event_code = VIEW_CONFIRM; | |
1605 break; | |
1606 } | |
1607 } | |
1608 else if (event->type == vod->origkey && event->val == KM_RELEASE) { | |
1609 event_code = VIEW_CONFIRM; | |
1610 } | |
1611 | |
1612 if (event_code == VIEW_APPLY) { | |
1613 viewzoom_apply(vod, event->x, event->y, U.viewzoom, (U.uiflag &
USER_ZOOM_INVERT) != 0); | |
1614 } | |
1615 else if (event_code == VIEW_CONFIRM) { | |
1616 ED_view3d_depth_tag_update(vod->rv3d); | |
1617 viewops_data_free(C, op); | |
1618 | |
1619 return OPERATOR_FINISHED; | |
1620 } | |
1621 | |
1622 return OPERATOR_RUNNING_MODAL; | |
1623 } | |
1624 | |
1625 static int viewzoom_exec(bContext *C, wmOperator *op) | |
1626 { | |
1627 View3D *v3d; | |
1628 RegionView3D *rv3d; | |
1629 ScrArea *sa; | |
1630 ARegion *ar; | |
1631 short use_cam_zoom; | |
1632 | |
1633 int delta = RNA_int_get(op->ptr, "delta"); | |
1634 int mx, my; | |
1635 | |
1636 if (op->customdata) { | |
1637 ViewOpsData *vod = op->customdata; | |
1638 | |
1639 sa = vod->sa; | |
1640 ar = vod->ar; | |
1641 } | |
1642 else { | |
1643 sa = CTX_wm_area(C); | |
1644 ar = CTX_wm_region(C); | |
1645 } | |
1646 | |
1647 v3d = sa->spacedata.first; | |
1648 rv3d = ar->regiondata; | |
1649 | |
1650 mx = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "m
x") : ar->winx / 2; | |
1651 my = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "m
y") : ar->winy / 2; | |
1652 | |
1653 use_cam_zoom = (rv3d->persp == RV3D_CAMOB) && !(rv3d->is_persp && ED_vie
w3d_camera_lock_check(v3d, rv3d)); | |
1654 | |
1655 if (delta < 0) { | |
1656 /* this min and max is also in viewmove() */ | |
1657 if (use_cam_zoom) { | |
1658 rv3d->camzoom -= 10.0f; | |
1659 if (rv3d->camzoom < RV3D_CAMZOOM_MIN) rv3d->camzoom = RV
3D_CAMZOOM_MIN; | |
1660 } | |
1661 else if (rv3d->dist < 10.0f * v3d->far) { | |
1662 view_zoom_mouseloc(ar, 1.2f, mx, my); | |
1663 } | |
1664 } | |
1665 else { | |
1666 if (use_cam_zoom) { | |
1667 rv3d->camzoom += 10.0f; | |
1668 if (rv3d->camzoom > RV3D_CAMZOOM_MAX) rv3d->camzoom = RV
3D_CAMZOOM_MAX; | |
1669 } | |
1670 else if (rv3d->dist > 0.001f * v3d->grid) { | |
1671 view_zoom_mouseloc(ar, .83333f, mx, my); | |
1672 } | |
1673 } | |
1674 | |
1675 if (rv3d->viewlock & RV3D_BOXVIEW) | |
1676 view3d_boxview_sync(sa, ar); | |
1677 | |
1678 ED_view3d_depth_tag_update(rv3d); | |
1679 | |
1680 ED_view3d_camera_lock_sync(v3d, rv3d); | |
1681 | |
1682 ED_region_tag_redraw(ar); | |
1683 | |
1684 viewops_data_free(C, op); | |
1685 | |
1686 return OPERATOR_FINISHED; | |
1687 } | |
1688 | |
1689 /* this is an exact copy of viewzoom_modal_keymap */ | |
1690 /* called in transform_ops.c, on each regeneration of keymaps */ | |
1691 void viewdolly_modal_keymap(wmKeyConfig *keyconf) | |
1692 { | |
1693 static EnumPropertyItem modal_items[] = { | |
1694 {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""}, | |
1695 | |
1696 {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to
Rotate"}, | |
1697 {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move
"}, | |
1698 | |
1699 {0, NULL, 0, NULL, NULL} | |
1700 }; | |
1701 | |
1702 wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal"); | |
1703 | |
1704 /* this function is called for each spacetype, only needs to add map onc
e */ | |
1705 if (keymap && keymap->modal_items) return; | |
1706 | |
1707 keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items); | |
1708 | |
1709 /* items for modal map */ | |
1710 WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW
_MODAL_CONFIRM); | |
1711 WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_
CONFIRM); | |
1712 | |
1713 /* disabled mode switching for now, can re-implement better, later on */ | |
1714 #if 0 | |
1715 WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWRO
T_MODAL_SWITCH_ROTATE); | |
1716 WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEW
ROT_MODAL_SWITCH_ROTATE); | |
1717 WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWR
OT_MODAL_SWITCH_MOVE); | |
1718 #endif | |
1719 ········ | |
1720 /* assign map to operators */ | |
1721 WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly"); | |
1722 } | |
1723 | |
1724 /* viewdolly_invoke() copied this function, changes here may apply there */ | |
1725 static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
1726 { | |
1727 ViewOpsData *vod; | |
1728 | |
1729 /* makes op->customdata */ | |
1730 viewops_data_create(C, op, event); | |
1731 vod = op->customdata; | |
1732 | |
1733 /* if one or the other zoom position aren't set, set from event */ | |
1734 if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_i
s_set(op->ptr, "my")) { | |
1735 RNA_int_set(op->ptr, "mx", event->x); | |
1736 RNA_int_set(op->ptr, "my", event->y); | |
1737 } | |
1738 | |
1739 if (RNA_struct_property_is_set(op->ptr, "delta")) { | |
1740 viewzoom_exec(C, op); | |
1741 } | |
1742 else { | |
1743 if (event->type == MOUSEZOOM) { | |
1744 /* Bypass Zoom invert flag for track pads (pass FALSE al
ways) */ | |
1745 | |
1746 if (U.uiflag & USER_ZOOM_HORIZ) { | |
1747 vod->origx = vod->oldx = event->x; | |
1748 viewzoom_apply(vod, event->prevx, event->prevy,
USER_ZOOM_DOLLY, FALSE); | |
1749 } | |
1750 else { | |
1751 /* Set y move = x move as MOUSEZOOM uses only x
axis to pass magnification value */ | |
1752 vod->origy = vod->oldy = vod->origy + event->x -
event->prevx; | |
1753 viewzoom_apply(vod, event->prevx, event->prevy,
USER_ZOOM_DOLLY, FALSE); | |
1754 } | |
1755 ED_view3d_depth_tag_update(vod->rv3d); | |
1756 ························ | |
1757 viewops_data_free(C, op); | |
1758 return OPERATOR_FINISHED; | |
1759 } | |
1760 else { | |
1761 if (U.viewzoom == USER_ZOOM_CONT) { | |
1762 /* needs a timer to continue redrawing */ | |
1763 vod->timer = WM_event_add_timer(CTX_wm_manager(C
), CTX_wm_window(C), TIMER, 0.01f); | |
1764 vod->timer_lastdraw = PIL_check_seconds_timer(); | |
1765 } | |
1766 | |
1767 /* add temp handler */ | |
1768 WM_event_add_modal_handler(C, op); | |
1769 | |
1770 return OPERATOR_RUNNING_MODAL; | |
1771 } | |
1772 } | |
1773 return OPERATOR_FINISHED; | |
1774 } | |
1775 | |
1776 static int viewzoom_cancel(bContext *C, wmOperator *op) | |
1777 { | |
1778 viewops_data_free(C, op); | |
1779 | |
1780 return OPERATOR_CANCELLED; | |
1781 } | |
1782 | |
1783 void VIEW3D_OT_zoom(wmOperatorType *ot) | |
1784 { | |
1785 /* identifiers */ | |
1786 ot->name = "Zoom View"; | |
1787 ot->description = "Zoom in/out in the view"; | |
1788 ot->idname = "VIEW3D_OT_zoom"; | |
1789 | |
1790 /* api callbacks */ | |
1791 ot->invoke = viewzoom_invoke; | |
1792 ot->exec = viewzoom_exec; | |
1793 ot->modal = viewzoom_modal; | |
1794 ot->poll = ED_operator_region_view3d_active; | |
1795 ot->cancel = viewzoom_cancel; | |
1796 | |
1797 /* flags */ | |
1798 ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; | |
1799 | |
1800 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN
, INT_MAX); | |
1801 RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT
_MAX); | |
1802 RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT
_MAX); | |
1803 } | |
1804 | |
1805 | |
1806 /* ************************ viewdolly ******************************** */ | |
1807 static void view_dolly_mouseloc(ARegion *ar, float orig_ofs[3], float dvec[3], f
loat dfac) | |
1808 { | |
1809 RegionView3D *rv3d = ar->regiondata; | |
1810 madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac)); | |
1811 } | |
1812 | |
1813 static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv
ert) | |
1814 { | |
1815 float zfac = 1.0; | |
1816 | |
1817 { | |
1818 float len1, len2; | |
1819 | |
1820 if (U.uiflag & USER_ZOOM_HORIZ) { | |
1821 len1 = (vod->ar->winrct.xmax - x) + 5; | |
1822 len2 = (vod->ar->winrct.xmax - vod->origx) + 5; | |
1823 } | |
1824 else { | |
1825 len1 = (vod->ar->winrct.ymax - y) + 5; | |
1826 len2 = (vod->ar->winrct.ymax - vod->origy) + 5; | |
1827 } | |
1828 if (zoom_invert) | |
1829 SWAP(float, len1, len2); | |
1830 | |
1831 zfac = 1.0f + ((len2 - len1) * 0.01f * vod->rv3d->dist); | |
1832 } | |
1833 | |
1834 if (zfac != 1.0f) | |
1835 view_dolly_mouseloc(vod->ar, vod->ofs, vod->mousevec, zfac); | |
1836 | |
1837 if (vod->rv3d->viewlock & RV3D_BOXVIEW) | |
1838 view3d_boxview_sync(vod->sa, vod->ar); | |
1839 | |
1840 ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d); | |
1841 | |
1842 ED_region_tag_redraw(vod->ar); | |
1843 } | |
1844 | |
1845 | |
1846 static int viewdolly_modal(bContext *C, wmOperator *op, wmEvent *event) | |
1847 { | |
1848 ViewOpsData *vod = op->customdata; | |
1849 short event_code = VIEW_PASS; | |
1850 | |
1851 /* execute the events */ | |
1852 if (event->type == MOUSEMOVE) { | |
1853 event_code = VIEW_APPLY; | |
1854 } | |
1855 else if (event->type == EVT_MODAL_MAP) { | |
1856 switch (event->val) { | |
1857 case VIEW_MODAL_CONFIRM: | |
1858 event_code = VIEW_CONFIRM; | |
1859 break; | |
1860 case VIEWROT_MODAL_SWITCH_MOVE: | |
1861 WM_operator_name_call(C, "VIEW3D_OT_move", WM_OP
_INVOKE_DEFAULT, NULL); | |
1862 event_code = VIEW_CONFIRM; | |
1863 break; | |
1864 case VIEWROT_MODAL_SWITCH_ROTATE: | |
1865 WM_operator_name_call(C, "VIEW3D_OT_rotate", WM_
OP_INVOKE_DEFAULT, NULL); | |
1866 event_code = VIEW_CONFIRM; | |
1867 break; | |
1868 } | |
1869 } | |
1870 else if (event->type == vod->origkey && event->val == KM_RELEASE) { | |
1871 event_code = VIEW_CONFIRM; | |
1872 } | |
1873 | |
1874 if (event_code == VIEW_APPLY) { | |
1875 viewdolly_apply(vod, event->x, event->y, (U.uiflag & USER_ZOOM_I
NVERT) != 0); | |
1876 } | |
1877 else if (event_code == VIEW_CONFIRM) { | |
1878 ED_view3d_depth_tag_update(vod->rv3d); | |
1879 viewops_data_free(C, op); | |
1880 | |
1881 return OPERATOR_FINISHED; | |
1882 } | |
1883 | |
1884 return OPERATOR_RUNNING_MODAL; | |
1885 } | |
1886 | |
1887 static int viewdolly_exec(bContext *C, wmOperator *op) | |
1888 { | |
1889 /* View3D *v3d; */ | |
1890 RegionView3D *rv3d; | |
1891 ScrArea *sa; | |
1892 ARegion *ar; | |
1893 float mousevec[3]; | |
1894 | |
1895 int delta = RNA_int_get(op->ptr, "delta"); | |
1896 | |
1897 if (op->customdata) { | |
1898 ViewOpsData *vod = op->customdata; | |
1899 | |
1900 sa = vod->sa; | |
1901 ar = vod->ar; | |
1902 copy_v3_v3(mousevec, vod->mousevec); | |
1903 } | |
1904 else { | |
1905 sa = CTX_wm_area(C); | |
1906 ar = CTX_wm_region(C); | |
1907 negate_v3_v3(mousevec, ((RegionView3D *)ar->regiondata)->viewinv
[2]); | |
1908 normalize_v3(mousevec); | |
1909 } | |
1910 | |
1911 /* v3d= sa->spacedata.first; */ /* UNUSED */ | |
1912 rv3d = ar->regiondata; | |
1913 | |
1914 /* overwrite the mouse vector with the view direction (zoom into the cen
ter) */ | |
1915 if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) { | |
1916 normalize_v3_v3(mousevec, rv3d->viewinv[2]); | |
1917 } | |
1918 | |
1919 if (delta < 0) { | |
1920 view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 1.2f); | |
1921 } | |
1922 else { | |
1923 view_dolly_mouseloc(ar, rv3d->ofs, mousevec, .83333f); | |
1924 } | |
1925 | |
1926 if (rv3d->viewlock & RV3D_BOXVIEW) | |
1927 view3d_boxview_sync(sa, ar); | |
1928 | |
1929 ED_view3d_depth_tag_update(rv3d); | |
1930 ED_region_tag_redraw(ar); | |
1931 | |
1932 viewops_data_free(C, op); | |
1933 | |
1934 return OPERATOR_FINISHED; | |
1935 } | |
1936 | |
1937 /* copied from viewzoom_invoke(), changes here may apply there */ | |
1938 static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
1939 { | |
1940 ViewOpsData *vod; | |
1941 | |
1942 /* makes op->customdata */ | |
1943 viewops_data_create(C, op, event); | |
1944 vod = op->customdata; | |
1945 | |
1946 /* if one or the other zoom position aren't set, set from event */ | |
1947 if (!RNA_struct_property_is_set(op->ptr, "mx") || !RNA_struct_property_i
s_set(op->ptr, "my")) { | |
1948 RNA_int_set(op->ptr, "mx", event->x); | |
1949 RNA_int_set(op->ptr, "my", event->y); | |
1950 } | |
1951 | |
1952 if (RNA_struct_property_is_set(op->ptr, "delta")) { | |
1953 viewdolly_exec(C, op); | |
1954 } | |
1955 else { | |
1956 /* overwrite the mouse vector with the view direction (zoom into
the center) */ | |
1957 if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) { | |
1958 negate_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]); | |
1959 normalize_v3(vod->mousevec); | |
1960 } | |
1961 | |
1962 if (event->type == MOUSEZOOM) { | |
1963 /* Bypass Zoom invert flag for track pads (pass FALSE al
ways) */ | |
1964 | |
1965 if (U.uiflag & USER_ZOOM_HORIZ) { | |
1966 vod->origx = vod->oldx = event->x; | |
1967 viewdolly_apply(vod, event->prevx, event->prevy,
FALSE); | |
1968 } | |
1969 else { | |
1970 | |
1971 /* Set y move = x move as MOUSEZOOM uses only x
axis to pass magnification value */ | |
1972 vod->origy = vod->oldy = vod->origy + event->x -
event->prevx; | |
1973 viewdolly_apply(vod, event->prevx, event->prevy,
FALSE); | |
1974 } | |
1975 ED_view3d_depth_tag_update(vod->rv3d); | |
1976 | |
1977 viewops_data_free(C, op); | |
1978 return OPERATOR_FINISHED; | |
1979 } | |
1980 else { | |
1981 /* add temp handler */ | |
1982 WM_event_add_modal_handler(C, op); | |
1983 | |
1984 return OPERATOR_RUNNING_MODAL; | |
1985 } | |
1986 } | |
1987 return OPERATOR_FINISHED; | |
1988 } | |
1989 | |
1990 /* like ED_operator_region_view3d_active but check its not in ortho view */ | |
1991 static int viewdolly_poll(bContext *C) | |
1992 { | |
1993 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
1994 | |
1995 if (rv3d) { | |
1996 if (rv3d->persp == RV3D_PERSP) { | |
1997 return 1; | |
1998 } | |
1999 else { | |
2000 View3D *v3d = CTX_wm_view3d(C); | |
2001 if (ED_view3d_camera_lock_check(v3d, rv3d)) { | |
2002 return 1; | |
2003 } | |
2004 } | |
2005 } | |
2006 return 0; | |
2007 } | |
2008 | |
2009 static int viewdolly_cancel(bContext *C, wmOperator *op) | |
2010 { | |
2011 viewops_data_free(C, op); | |
2012 | |
2013 return OPERATOR_CANCELLED; | |
2014 } | |
2015 | |
2016 void VIEW3D_OT_dolly(wmOperatorType *ot) | |
2017 { | |
2018 /* identifiers */ | |
2019 ot->name = "Dolly view"; | |
2020 ot->description = "Dolly in/out in the view"; | |
2021 ot->idname = "VIEW3D_OT_dolly"; | |
2022 | |
2023 /* api callbacks */ | |
2024 ot->invoke = viewdolly_invoke; | |
2025 ot->exec = viewdolly_exec; | |
2026 ot->modal = viewdolly_modal; | |
2027 ot->poll = viewdolly_poll; | |
2028 ot->cancel = viewdolly_cancel; | |
2029 | |
2030 /* flags */ | |
2031 ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_POINTER; | |
2032 | |
2033 RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN
, INT_MAX); | |
2034 RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT
_MAX); | |
2035 RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT
_MAX); | |
2036 } | |
2037 | |
2038 | |
2039 | |
2040 static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
2.4x */ | |
2041 { | |
2042 ARegion *ar = CTX_wm_region(C); | |
2043 View3D *v3d = CTX_wm_view3d(C); | |
2044 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
2045 Scene *scene = CTX_data_scene(C); | |
2046 Base *base; | |
2047 float *curs; | |
2048 const short skip_camera = ED_view3d_camera_lock_check(v3d, rv3d); | |
2049 | |
2050 int center = RNA_boolean_get(op->ptr, "center"); | |
2051 | |
2052 float size, min[3], max[3], afm[3]; | |
2053 int ok = 1, onedone = 0; | |
2054 | |
2055 if (center) { | |
2056 /* in 2.4x this also move the cursor to (0, 0, 0) (with shift+c)
. */ | |
2057 curs = give_cursor(scene, v3d); | |
2058 zero_v3(min); | |
2059 zero_v3(max); | |
2060 zero_v3(curs); | |
2061 } | |
2062 else { | |
2063 INIT_MINMAX(min, max); | |
2064 } | |
2065 | |
2066 for (base = scene->base.first; base; base = base->next) { | |
2067 if (BASE_VISIBLE(v3d, base)) { | |
2068 onedone = 1; | |
2069 | |
2070 if (skip_camera && base->object == v3d->camera) { | |
2071 continue; | |
2072 } | |
2073 | |
2074 BKE_object_minmax(base->object, min, max); | |
2075 } | |
2076 } | |
2077 if (!onedone) { | |
2078 ED_region_tag_redraw(ar); | |
2079 /* TODO - should this be cancel? | |
2080 * I think no, because we always move the cursor, with or withou
t | |
2081 * object, but in this case there is no change in the scene, | |
2082 * only the cursor so I choice a ED_region_tag like | |
2083 * smooth_view do for the center_cursor. | |
2084 * See bug #22640 | |
2085 */ | |
2086 return OPERATOR_FINISHED; | |
2087 } | |
2088 | |
2089 sub_v3_v3v3(afm, max, min); | |
2090 size = 0.7f * MAX3(afm[0], afm[1], afm[2]); | |
2091 if (size == 0.0f) ok = 0; | |
2092 | |
2093 if (ok) { | |
2094 float new_dist; | |
2095 float new_ofs[3]; | |
2096 | |
2097 new_dist = size; | |
2098 new_ofs[0] = -(min[0] + max[0]) / 2.0f; | |
2099 new_ofs[1] = -(min[1] + max[1]) / 2.0f; | |
2100 new_ofs[2] = -(min[2] + max[2]) / 2.0f; | |
2101 | |
2102 // correction for window aspect ratio | |
2103 if (ar->winy > 2 && ar->winx > 2) { | |
2104 size = (float)ar->winx / (float)ar->winy; | |
2105 if (size < 1.0f) size = 1.0f / size; | |
2106 new_dist *= size; | |
2107 } | |
2108 | |
2109 if ((rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(
v3d, rv3d)) { | |
2110 rv3d->persp = RV3D_PERSP; | |
2111 smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL
, &new_dist, NULL); | |
2112 } | |
2113 else { | |
2114 smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, &new_
dist, NULL); | |
2115 } | |
2116 } | |
2117 // XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); | |
2118 | |
2119 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); | |
2120 | |
2121 return OPERATOR_FINISHED; | |
2122 } | |
2123 | |
2124 | |
2125 void VIEW3D_OT_view_all(wmOperatorType *ot) | |
2126 { | |
2127 /* identifiers */ | |
2128 ot->name = "View All"; | |
2129 ot->description = "View all objects in scene"; | |
2130 ot->idname = "VIEW3D_OT_view_all"; | |
2131 | |
2132 /* api callbacks */ | |
2133 ot->exec = view3d_all_exec; | |
2134 ot->poll = ED_operator_region_view3d_active; | |
2135 | |
2136 /* flags */ | |
2137 ot->flag = 0; | |
2138 | |
2139 RNA_def_boolean(ot->srna, "center", 0, "Center", ""); | |
2140 } | |
2141 | |
2142 /* like a localview without local!, was centerview() in 2.4x */ | |
2143 static int viewselected_exec(bContext *C, wmOperator *UNUSED(op)) | |
2144 { | |
2145 ARegion *ar = CTX_wm_region(C); | |
2146 View3D *v3d = CTX_wm_view3d(C); | |
2147 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
2148 Scene *scene = CTX_data_scene(C); | |
2149 Object *ob = OBACT; | |
2150 Object *obedit = CTX_data_edit_object(C); | |
2151 float size, min[3], max[3], afm[3]; | |
2152 int ok = 0, ok_dist = 1; | |
2153 const short skip_camera = ED_view3d_camera_lock_check(v3d, rv3d); | |
2154 | |
2155 /* SMOOTHVIEW */ | |
2156 float new_ofs[3]; | |
2157 float new_dist; | |
2158 | |
2159 INIT_MINMAX(min, max); | |
2160 | |
2161 if (ob && (ob->mode & OB_MODE_WEIGHT_PAINT)) { | |
2162 /* hard-coded exception, we look for the one selected armature *
/ | |
2163 /* this is weak code this way, we should make a generic active/s
election callback interface once... */ | |
2164 Base *base; | |
2165 for (base = scene->base.first; base; base = base->next) { | |
2166 if (TESTBASELIB(v3d, base)) { | |
2167 if (base->object->type == OB_ARMATURE) | |
2168 if (base->object->mode & OB_MODE_POSE) | |
2169 break; | |
2170 } | |
2171 } | |
2172 if (base) | |
2173 ob = base->object; | |
2174 } | |
2175 | |
2176 | |
2177 if (obedit) { | |
2178 ok = ED_view3d_minmax_verts(obedit, min, max); /* only select
ed */ | |
2179 } | |
2180 else if (ob && (ob->mode & OB_MODE_POSE)) { | |
2181 if (ob->pose) { | |
2182 bArmature *arm = ob->data; | |
2183 bPoseChannel *pchan; | |
2184 float vec[3]; | |
2185 | |
2186 for (pchan = ob->pose->chanbase.first; pchan; pchan = pc
han->next) { | |
2187 if (pchan->bone->flag & BONE_SELECTED) { | |
2188 if (pchan->bone->layer & arm->layer) { | |
2189 bPoseChannel *pchan_tx = pchan->
custom_tx ? pchan->custom_tx : pchan; | |
2190 ok = 1; | |
2191 mul_v3_m4v3(vec, ob->obmat, pcha
n_tx->pose_head); | |
2192 minmax_v3v3_v3(min, max, vec); | |
2193 mul_v3_m4v3(vec, ob->obmat, pcha
n_tx->pose_tail); | |
2194 minmax_v3v3_v3(min, max, vec); | |
2195 } | |
2196 } | |
2197 } | |
2198 } | |
2199 } | |
2200 else if (paint_facesel_test(ob)) { | |
2201 ok = paintface_minmax(ob, min, max); | |
2202 } | |
2203 else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { | |
2204 ok = PE_minmax(scene, min, max); | |
2205 } | |
2206 else if (ob && (ob->mode & OB_MODE_SCULPT)) { | |
2207 ok = ED_sculpt_minmax(C, min, max); | |
2208 ok_dist = 0; /* don't zoom */ | |
2209 } | |
2210 else { | |
2211 Base *base; | |
2212 for (base = FIRSTBASE; base; base = base->next) { | |
2213 if (TESTBASE(v3d, base)) { | |
2214 | |
2215 if (skip_camera && base->object == v3d->camera)
{ | |
2216 continue; | |
2217 } | |
2218 | |
2219 /* account for duplis */ | |
2220 if (BKE_object_minmax_dupli(scene, base->object,
min, max) == 0) | |
2221 BKE_object_minmax(base->object, min, max
); /* use if duplis not found */ | |
2222 | |
2223 ok = 1; | |
2224 } | |
2225 } | |
2226 } | |
2227 | |
2228 if (ok == 0) return OPERATOR_FINISHED; | |
2229 | |
2230 sub_v3_v3v3(afm, max, min); | |
2231 size = MAX3(afm[0], afm[1], afm[2]); | |
2232 | |
2233 if (ok_dist) { | |
2234 /* fix up zoom distance if needed */ | |
2235 | |
2236 if (rv3d->is_persp) { | |
2237 if (size <= v3d->near * 1.5f) { | |
2238 /* do not zoom closer than the near clipping pla
ne */ | |
2239 size = v3d->near * 1.5f; | |
2240 } | |
2241 } | |
2242 else { /* ortho */ | |
2243 if (size < 0.0001f) { | |
2244 /* bounding box was a single point so do not zoo
m */ | |
2245 ok_dist = 0; | |
2246 } | |
2247 else { | |
2248 /* adjust zoom so it looks nicer */ | |
2249 size *= 0.7f; | |
2250 } | |
2251 } | |
2252 } | |
2253 | |
2254 add_v3_v3v3(new_ofs, min, max); | |
2255 mul_v3_fl(new_ofs, -0.5f); | |
2256 | |
2257 new_dist = size; | |
2258 | |
2259 /* correction for window aspect ratio */ | |
2260 if (ar->winy > 2 && ar->winx > 2) { | |
2261 size = (float)ar->winx / (float)ar->winy; | |
2262 if (size < 1.0f) size = 1.0f / size; | |
2263 new_dist *= size; | |
2264 } | |
2265 | |
2266 if (rv3d->persp == RV3D_CAMOB && !ED_view3d_camera_lock_check(v3d, rv3d)
) { | |
2267 rv3d->persp = RV3D_PERSP; | |
2268 smooth_view(C, v3d, ar, v3d->camera, NULL, new_ofs, NULL, ok_dis
t ? &new_dist : NULL, NULL); | |
2269 } | |
2270 else { | |
2271 smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, ok_dist ? &ne
w_dist : NULL, NULL); | |
2272 } | |
2273 | |
2274 /* smooth view does viewlock RV3D_BOXVIEW copy */ | |
2275 ········ | |
2276 // XXX BIF_view3d_previewrender_signal(curarea, PR_DBASE|PR_DISPRECT); | |
2277 | |
2278 return OPERATOR_FINISHED; | |
2279 } | |
2280 | |
2281 void VIEW3D_OT_view_selected(wmOperatorType *ot) | |
2282 { | |
2283 | |
2284 /* identifiers */ | |
2285 ot->name = "View Selected"; | |
2286 ot->description = "Move the view to the selection center"; | |
2287 ot->idname = "VIEW3D_OT_view_selected"; | |
2288 | |
2289 /* api callbacks */ | |
2290 ot->exec = viewselected_exec; | |
2291 ot->poll = ED_operator_region_view3d_active; | |
2292 | |
2293 /* flags */ | |
2294 ot->flag = 0; | |
2295 } | |
2296 | |
2297 static int view_lock_clear_exec(bContext *C, wmOperator *UNUSED(op)) | |
2298 { | |
2299 View3D *v3d = CTX_wm_view3d(C); | |
2300 | |
2301 if (v3d) { | |
2302 ED_view3D_lock_clear(v3d); | |
2303 | |
2304 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); | |
2305 | |
2306 return OPERATOR_FINISHED; | |
2307 } | |
2308 else { | |
2309 return OPERATOR_CANCELLED; | |
2310 } | |
2311 } | |
2312 | |
2313 void VIEW3D_OT_view_lock_clear(wmOperatorType *ot) | |
2314 { | |
2315 | |
2316 /* identifiers */ | |
2317 ot->name = "View Lock Clear"; | |
2318 ot->description = "Clear all view locking"; | |
2319 ot->idname = "VIEW3D_OT_view_lock_clear"; | |
2320 | |
2321 /* api callbacks */ | |
2322 ot->exec = view_lock_clear_exec; | |
2323 ot->poll = ED_operator_region_view3d_active; | |
2324 | |
2325 /* flags */ | |
2326 ot->flag = 0; | |
2327 } | |
2328 | |
2329 static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op)) | |
2330 { | |
2331 View3D *v3d = CTX_wm_view3d(C); | |
2332 Object *obact = CTX_data_active_object(C); | |
2333 | |
2334 if (v3d) { | |
2335 | |
2336 ED_view3D_lock_clear(v3d); | |
2337 | |
2338 v3d->ob_centre = obact; /* can be NULL */ | |
2339 | |
2340 if (obact && obact->type == OB_ARMATURE) { | |
2341 if (obact->mode & OB_MODE_POSE) { | |
2342 bPoseChannel *pcham_act = BKE_pose_channel_activ
e(obact); | |
2343 if (pcham_act) { | |
2344 BLI_strncpy(v3d->ob_centre_bone, pcham_a
ct->name, sizeof(v3d->ob_centre_bone)); | |
2345 } | |
2346 } | |
2347 else { | |
2348 EditBone *ebone_act = ((bArmature *)obact->data)
->act_edbone; | |
2349 if (ebone_act) { | |
2350 BLI_strncpy(v3d->ob_centre_bone, ebone_a
ct->name, sizeof(v3d->ob_centre_bone)); | |
2351 } | |
2352 } | |
2353 } | |
2354 | |
2355 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); | |
2356 | |
2357 return OPERATOR_FINISHED; | |
2358 } | |
2359 else { | |
2360 return OPERATOR_CANCELLED; | |
2361 } | |
2362 } | |
2363 | |
2364 void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot) | |
2365 { | |
2366 | |
2367 /* identifiers */ | |
2368 ot->name = "View Lock to Active"; | |
2369 ot->description = "Lock the view to the active object/bone"; | |
2370 ot->idname = "VIEW3D_OT_view_lock_to_active"; | |
2371 | |
2372 /* api callbacks */ | |
2373 ot->exec = view_lock_to_active_exec; | |
2374 ot->poll = ED_operator_region_view3d_active; | |
2375 | |
2376 /* flags */ | |
2377 ot->flag = 0; | |
2378 } | |
2379 | |
2380 static int viewcenter_cursor_exec(bContext *C, wmOperator *UNUSED(op)) | |
2381 { | |
2382 View3D *v3d = CTX_wm_view3d(C); | |
2383 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
2384 Scene *scene = CTX_data_scene(C); | |
2385 ········ | |
2386 if (rv3d) { | |
2387 ARegion *ar = CTX_wm_region(C); | |
2388 | |
2389 /* non camera center */ | |
2390 float new_ofs[3]; | |
2391 negate_v3_v3(new_ofs, give_cursor(scene, v3d)); | |
2392 smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, NULL, NULL); | |
2393 ················ | |
2394 /* smooth view does viewlock RV3D_BOXVIEW copy */ | |
2395 } | |
2396 ········ | |
2397 return OPERATOR_FINISHED; | |
2398 } | |
2399 | |
2400 void VIEW3D_OT_view_center_cursor(wmOperatorType *ot) | |
2401 { | |
2402 /* identifiers */ | |
2403 ot->name = "Center View to Cursor"; | |
2404 ot->description = "Center the view so that the cursor is in the middle o
f the view"; | |
2405 ot->idname = "VIEW3D_OT_view_center_cursor"; | |
2406 ········ | |
2407 /* api callbacks */ | |
2408 ot->exec = viewcenter_cursor_exec; | |
2409 ot->poll = ED_operator_view3d_active; | |
2410 ········ | |
2411 /* flags */ | |
2412 ot->flag = 0; | |
2413 } | |
2414 | |
2415 static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was
view3d_home() in 2.4x */ | |
2416 { | |
2417 Scene *scene = CTX_data_scene(C); | |
2418 float xfac, yfac; | |
2419 float size[2]; | |
2420 | |
2421 View3D *v3d; | |
2422 ARegion *ar; | |
2423 RegionView3D *rv3d; | |
2424 | |
2425 /* no NULL check is needed, poll checks */ | |
2426 ED_view3d_context_user_region(C, &v3d, &ar); | |
2427 rv3d = ar->regiondata; | |
2428 | |
2429 rv3d->camdx = rv3d->camdy = 0.0f; | |
2430 | |
2431 ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size); | |
2432 | |
2433 /* 4px is just a little room from the edge of the area */ | |
2434 xfac = (float)ar->winx / (float)(size[0] + 4); | |
2435 yfac = (float)ar->winy / (float)(size[1] + 4); | |
2436 | |
2437 rv3d->camzoom = BKE_screen_view3d_zoom_from_fac(MIN2(xfac, yfac)); | |
2438 CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); | |
2439 | |
2440 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, CTX_wm_view3d(C)); | |
2441 | |
2442 return OPERATOR_FINISHED; | |
2443 } | |
2444 | |
2445 void VIEW3D_OT_view_center_camera(wmOperatorType *ot) | |
2446 { | |
2447 /* identifiers */ | |
2448 ot->name = "View Camera Center"; | |
2449 ot->description = "Center the camera view"; | |
2450 ot->idname = "VIEW3D_OT_view_center_camera"; | |
2451 | |
2452 /* api callbacks */ | |
2453 ot->exec = view3d_center_camera_exec; | |
2454 ot->poll = view3d_camera_user_poll; | |
2455 | |
2456 /* flags */ | |
2457 ot->flag = 0; | |
2458 } | |
2459 | |
2460 /* ********************* Set render border operator ****************** */ | |
2461 | |
2462 static int render_border_exec(bContext *C, wmOperator *op) | |
2463 { | |
2464 View3D *v3d = CTX_wm_view3d(C); | |
2465 ARegion *ar = CTX_wm_region(C); | |
2466 RegionView3D *rv3d = ED_view3d_context_rv3d(C); | |
2467 Scene *scene = CTX_data_scene(C); | |
2468 | |
2469 rcti rect; | |
2470 rctf vb; | |
2471 | |
2472 /* get border select values using rna */ | |
2473 rect.xmin = RNA_int_get(op->ptr, "xmin"); | |
2474 rect.ymin = RNA_int_get(op->ptr, "ymin"); | |
2475 rect.xmax = RNA_int_get(op->ptr, "xmax"); | |
2476 rect.ymax = RNA_int_get(op->ptr, "ymax"); | |
2477 | |
2478 /* calculate range */ | |
2479 ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, FALSE); | |
2480 | |
2481 scene->r.border.xmin = ((float)rect.xmin - vb.xmin) / (vb.xmax - vb.xmin
); | |
2482 scene->r.border.ymin = ((float)rect.ymin - vb.ymin) / (vb.ymax - vb.ymin
); | |
2483 scene->r.border.xmax = ((float)rect.xmax - vb.xmin) / (vb.xmax - vb.xmin
); | |
2484 scene->r.border.ymax = ((float)rect.ymax - vb.ymin) / (vb.ymax - vb.ymin
); | |
2485 | |
2486 /* actually set border */ | |
2487 CLAMP(scene->r.border.xmin, 0.0f, 1.0f); | |
2488 CLAMP(scene->r.border.ymin, 0.0f, 1.0f); | |
2489 CLAMP(scene->r.border.xmax, 0.0f, 1.0f); | |
2490 CLAMP(scene->r.border.ymax, 0.0f, 1.0f); | |
2491 | |
2492 /* drawing a border surrounding the entire camera view switches off bord
er rendering | |
2493 * or the border covers no pixels */ | |
2494 if ((scene->r.border.xmin <= 0.0f && scene->r.border.xmax >= 1.0f && | |
2495 scene->r.border.ymin <= 0.0f && scene->r.border.ymax >= 1.0f) || | |
2496 (scene->r.border.xmin == scene->r.border.xmax || | |
2497 scene->r.border.ymin == scene->r.border.ymax)) | |
2498 { | |
2499 scene->r.mode &= ~R_BORDER; | |
2500 } | |
2501 else { | |
2502 scene->r.mode |= R_BORDER; | |
2503 } | |
2504 ········ | |
2505 WM_event_add_notifier(C, NC_SCENE | ND_RENDER_OPTIONS, NULL); | |
2506 | |
2507 return OPERATOR_FINISHED; | |
2508 | |
2509 } | |
2510 | |
2511 void VIEW3D_OT_render_border(wmOperatorType *ot) | |
2512 { | |
2513 /* identifiers */ | |
2514 ot->name = "Set Render Border"; | |
2515 ot->description = "Set the boundaries of the border render and enables b
order render"; | |
2516 ot->idname = "VIEW3D_OT_render_border"; | |
2517 | |
2518 /* api callbacks */ | |
2519 ot->invoke = WM_border_select_invoke; | |
2520 ot->exec = render_border_exec; | |
2521 ot->modal = WM_border_select_modal; | |
2522 ot->cancel = WM_border_select_cancel; | |
2523 | |
2524 ot->poll = view3d_camera_active_poll; | |
2525 | |
2526 /* flags */ | |
2527 ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | |
2528 | |
2529 /* rna */ | |
2530 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN,
INT_MAX); | |
2531 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN,
INT_MAX); | |
2532 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN,
INT_MAX); | |
2533 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN,
INT_MAX); | |
2534 | |
2535 } | |
2536 /* ********************* Border Zoom operator ****************** */ | |
2537 | |
2538 static int view3d_zoom_border_exec(bContext *C, wmOperator *op) | |
2539 { | |
2540 ARegion *ar = CTX_wm_region(C); | |
2541 View3D *v3d = CTX_wm_view3d(C); | |
2542 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
2543 Scene *scene = CTX_data_scene(C); | |
2544 | |
2545 /* Zooms in on a border drawn by the user */ | |
2546 rcti rect; | |
2547 float dvec[3], vb[2], xscale, yscale, scale; | |
2548 | |
2549 /* SMOOTHVIEW */ | |
2550 float new_dist; | |
2551 float new_ofs[3]; | |
2552 | |
2553 /* ZBuffer depth vars */ | |
2554 bglMats mats; | |
2555 float depth_close = FLT_MAX; | |
2556 double cent[2], p[3]; | |
2557 | |
2558 /* note; otherwise opengl won't work */ | |
2559 view3d_operator_needs_opengl(C); | |
2560 | |
2561 /* get border select values using rna */ | |
2562 rect.xmin = RNA_int_get(op->ptr, "xmin"); | |
2563 rect.ymin = RNA_int_get(op->ptr, "ymin"); | |
2564 rect.xmax = RNA_int_get(op->ptr, "xmax"); | |
2565 rect.ymax = RNA_int_get(op->ptr, "ymax"); | |
2566 | |
2567 /* Get Z Depths, needed for perspective, nice for ortho */ | |
2568 bgl_get_mats(&mats); | |
2569 draw_depth(scene, ar, v3d, NULL); | |
2570 ········ | |
2571 { | |
2572 /* avoid allocating the whole depth buffer */ | |
2573 ViewDepths depth_temp = {0}; | |
2574 | |
2575 /* avoid view3d_update_depths() for speed. */ | |
2576 view3d_update_depths_rect(ar, &depth_temp, &rect); | |
2577 ········ | |
2578 /* find the closest Z pixel */ | |
2579 depth_close = view3d_depth_near(&depth_temp); | |
2580 ········ | |
2581 MEM_freeN(depth_temp.depths); | |
2582 } | |
2583 | |
2584 cent[0] = (((double)rect.xmin) + ((double)rect.xmax)) / 2; | |
2585 cent[1] = (((double)rect.ymin) + ((double)rect.ymax)) / 2; | |
2586 | |
2587 if (rv3d->is_persp) { | |
2588 double p_corner[3]; | |
2589 | |
2590 /* no depths to use, we cant do anything! */ | |
2591 if (depth_close == FLT_MAX) { | |
2592 BKE_report(op->reports, RPT_ERROR, "Depth Too Large"); | |
2593 return OPERATOR_CANCELLED; | |
2594 } | |
2595 /* convert border to 3d coordinates */ | |
2596 if ( (!gluUnProject(cent[0], cent[1], depth_close, | |
2597 mats.modelview, mats.projection, (GLint *)ma
ts.viewport, | |
2598 &p[0], &p[1], &p[2])) || | |
2599 (!gluUnProject((double)rect.xmin, (double)rect.ymin, depth_
close, | |
2600 mats.modelview, mats.projection, (GLint *)ma
ts.viewport, | |
2601 &p_corner[0], &p_corner[1], &p_corner[2]))) | |
2602 { | |
2603 return OPERATOR_CANCELLED; | |
2604 } | |
2605 | |
2606 dvec[0] = p[0] - p_corner[0]; | |
2607 dvec[1] = p[1] - p_corner[1]; | |
2608 dvec[2] = p[2] - p_corner[2]; | |
2609 | |
2610 new_dist = len_v3(dvec); | |
2611 if (new_dist <= v3d->near * 1.5f) new_dist = v3d->near * 1.5f; | |
2612 | |
2613 new_ofs[0] = -p[0]; | |
2614 new_ofs[1] = -p[1]; | |
2615 new_ofs[2] = -p[2]; | |
2616 | |
2617 } | |
2618 else { /* othographic */ | |
2619 /* find the current window width and height */ | |
2620 vb[0] = ar->winx; | |
2621 vb[1] = ar->winy; | |
2622 | |
2623 new_dist = rv3d->dist; | |
2624 | |
2625 /* convert the drawn rectangle into 3d space */ | |
2626 if (depth_close != FLT_MAX && gluUnProject(cent[0], cent[1], dep
th_close, | |
2627 mats.modelview, mats.
projection, (GLint *)mats.viewport, | |
2628 &p[0], &p[1], &p[2])) | |
2629 { | |
2630 new_ofs[0] = -p[0]; | |
2631 new_ofs[1] = -p[1]; | |
2632 new_ofs[2] = -p[2]; | |
2633 } | |
2634 else { | |
2635 float mval_f[2]; | |
2636 /* We cant use the depth, fallback to the old way that d
osnt set the center depth */ | |
2637 copy_v3_v3(new_ofs, rv3d->ofs); | |
2638 | |
2639 initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]); | |
2640 | |
2641 mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f; | |
2642 mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f; | |
2643 ED_view3d_win_to_delta(ar, mval_f, dvec); | |
2644 /* center the view to the center of the rectangle */ | |
2645 sub_v3_v3(new_ofs, dvec); | |
2646 } | |
2647 | |
2648 /* work out the ratios, so that everything selected fits when we
zoom */ | |
2649 xscale = ((rect.xmax - rect.xmin) / vb[0]); | |
2650 yscale = ((rect.ymax - rect.ymin) / vb[1]); | |
2651 scale = (xscale >= yscale) ? xscale : yscale; | |
2652 | |
2653 /* zoom in as required, or as far as we can go */ | |
2654 new_dist = ((new_dist * scale) >= 0.001f * v3d->grid) ? new_dist
* scale : 0.001f * v3d->grid; | |
2655 } | |
2656 | |
2657 smooth_view(C, v3d, ar, NULL, NULL, new_ofs, NULL, &new_dist, NULL); | |
2658 | |
2659 if (rv3d->viewlock & RV3D_BOXVIEW) | |
2660 view3d_boxview_sync(CTX_wm_area(C), ar); | |
2661 | |
2662 return OPERATOR_FINISHED; | |
2663 } | |
2664 | |
2665 static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, wmEvent *event
) | |
2666 { | |
2667 View3D *v3d = CTX_wm_view3d(C); | |
2668 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
2669 | |
2670 /* if in camera view do not exec the operator so we do not conflict with
set render border*/ | |
2671 if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v3d, rv3d
)) | |
2672 return WM_border_select_invoke(C, op, event); | |
2673 else | |
2674 return OPERATOR_PASS_THROUGH; | |
2675 } | |
2676 | |
2677 void VIEW3D_OT_zoom_border(wmOperatorType *ot) | |
2678 { | |
2679 /* identifiers */ | |
2680 ot->name = "Border Zoom"; | |
2681 ot->description = "Zoom in the view to the nearest object contained in t
he border"; | |
2682 ot->idname = "VIEW3D_OT_zoom_border"; | |
2683 | |
2684 /* api callbacks */ | |
2685 ot->invoke = view3d_zoom_border_invoke; | |
2686 ot->exec = view3d_zoom_border_exec; | |
2687 ot->modal = WM_border_select_modal; | |
2688 ot->cancel = WM_border_select_cancel; | |
2689 | |
2690 ot->poll = ED_operator_region_view3d_active; | |
2691 | |
2692 /* flags */ | |
2693 ot->flag = 0; | |
2694 | |
2695 /* rna */ | |
2696 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN,
INT_MAX); | |
2697 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN,
INT_MAX); | |
2698 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN,
INT_MAX); | |
2699 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN,
INT_MAX); | |
2700 | |
2701 } | |
2702 | |
2703 /* sets the view to 1:1 camera/render-pixel */ | |
2704 static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar, View3D *v3d) | |
2705 { | |
2706 RegionView3D *rv3d = ar->regiondata; | |
2707 float size[2]; | |
2708 int im_width = (scene->r.size * scene->r.xsch) / 100; | |
2709 ········ | |
2710 ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size); | |
2711 | |
2712 rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0
]); | |
2713 CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); | |
2714 } | |
2715 | |
2716 static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op)) | |
2717 { | |
2718 Scene *scene = CTX_data_scene(C); | |
2719 | |
2720 View3D *v3d; | |
2721 ARegion *ar; | |
2722 | |
2723 /* no NULL check is needed, poll checks */ | |
2724 ED_view3d_context_user_region(C, &v3d, &ar); | |
2725 | |
2726 view3d_set_1_to_1_viewborder(scene, ar, v3d); | |
2727 | |
2728 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); | |
2729 | |
2730 return OPERATOR_FINISHED; | |
2731 } | |
2732 | |
2733 void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot) | |
2734 { | |
2735 /* identifiers */ | |
2736 ot->name = "Zoom Camera 1:1"; | |
2737 ot->description = "Match the camera to 1:1 to the render output"; | |
2738 ot->idname = "VIEW3D_OT_zoom_camera_1_to_1"; | |
2739 | |
2740 /* api callbacks */ | |
2741 ot->exec = view3d_zoom_1_to_1_camera_exec; | |
2742 ot->poll = view3d_camera_user_poll; | |
2743 | |
2744 /* flags */ | |
2745 ot->flag = 0; | |
2746 } | |
2747 | |
2748 /* ********************* Changing view operator ****************** */ | |
2749 | |
2750 static EnumPropertyItem prop_view_items[] = { | |
2751 {RV3D_VIEW_FRONT, "FRONT", 0, "Front", "View From the Front"}, | |
2752 {RV3D_VIEW_BACK, "BACK", 0, "Back", "View From the Back"}, | |
2753 {RV3D_VIEW_LEFT, "LEFT", 0, "Left", "View From the Left"}, | |
2754 {RV3D_VIEW_RIGHT, "RIGHT", 0, "Right", "View From the Right"}, | |
2755 {RV3D_VIEW_TOP, "TOP", 0, "Top", "View From the Top"}, | |
2756 {RV3D_VIEW_BOTTOM, "BOTTOM", 0, "Bottom", "View From the Bottom"}, | |
2757 {RV3D_VIEW_CAMERA, "CAMERA", 0, "Camera", "View From the active camera"}
, | |
2758 {0, NULL, 0, NULL, NULL} | |
2759 }; | |
2760 | |
2761 | |
2762 /* would like to make this a generic function - outside of transform */ | |
2763 | |
2764 static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar, | |
2765 float q1, float q2, float q3, float q4, | |
2766 short view, int perspo, int align_active) | |
2767 { | |
2768 RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll ch
ecks */ | |
2769 float new_quat[4]; | |
2770 | |
2771 new_quat[0] = q1; new_quat[1] = q2; | |
2772 new_quat[2] = q3; new_quat[3] = q4; | |
2773 normalize_qt(new_quat); | |
2774 | |
2775 if (align_active) { | |
2776 /* align to active object */ | |
2777 Object *obact = CTX_data_active_object(C); | |
2778 if (obact == NULL) { | |
2779 /* no active object, ignore this option */ | |
2780 align_active = FALSE; | |
2781 } | |
2782 else { | |
2783 float obact_quat[4]; | |
2784 float twmat[3][3]; | |
2785 | |
2786 /* same as transform manipulator when normal is set */ | |
2787 ED_getTransformOrientationMatrix(C, twmat, FALSE); | |
2788 | |
2789 mat3_to_quat(obact_quat, twmat); | |
2790 invert_qt(obact_quat); | |
2791 mul_qt_qtqt(new_quat, new_quat, obact_quat); | |
2792 | |
2793 rv3d->view = view = RV3D_VIEW_USER; | |
2794 } | |
2795 } | |
2796 | |
2797 if (align_active == FALSE) { | |
2798 /* normal operation */ | |
2799 if (rv3d->viewlock) { | |
2800 /* only pass on if */ | |
2801 | |
2802 /* nice confusing if-block */ | |
2803 if (!((rv3d->view == RV3D_VIEW_FRONT && view == RV3D_VI
EW_BACK) || | |
2804 (rv3d->view == RV3D_VIEW_BACK && view == RV3D_VI
EW_FRONT) || | |
2805 (rv3d->view == RV3D_VIEW_RIGHT && view == RV3D_VI
EW_LEFT) || | |
2806 (rv3d->view == RV3D_VIEW_LEFT && view == RV3D_VI
EW_RIGHT) || | |
2807 (rv3d->view == RV3D_VIEW_BOTTOM && view == RV3D_VI
EW_TOP) || | |
2808 (rv3d->view == RV3D_VIEW_TOP && view == RV3D_VI
EW_BOTTOM))) | |
2809 { | |
2810 return; | |
2811 } | |
2812 } | |
2813 | |
2814 rv3d->view = view; | |
2815 } | |
2816 | |
2817 if (rv3d->viewlock) { | |
2818 ED_region_tag_redraw(ar); | |
2819 return; | |
2820 } | |
2821 | |
2822 if (rv3d->persp == RV3D_CAMOB && v3d->camera) { | |
2823 | |
2824 if (U.uiflag & USER_AUTOPERSP) rv3d->persp = view ? RV3D_ORTHO :
RV3D_PERSP; | |
2825 else if (rv3d->persp == RV3D_CAMOB) rv3d->persp = perspo; | |
2826 | |
2827 smooth_view(C, v3d, ar, v3d->camera, NULL, rv3d->ofs, new_quat,
NULL, NULL); | |
2828 } | |
2829 else { | |
2830 | |
2831 if (U.uiflag & USER_AUTOPERSP) rv3d->persp = view ? RV3D_ORTHO :
RV3D_PERSP; | |
2832 else if (rv3d->persp == RV3D_CAMOB) rv3d->persp = perspo; | |
2833 | |
2834 smooth_view(C, v3d, ar, NULL, NULL, NULL, new_quat, NULL, NULL); | |
2835 } | |
2836 | |
2837 } | |
2838 | |
2839 static int viewnumpad_exec(bContext *C, wmOperator *op) | |
2840 { | |
2841 View3D *v3d; | |
2842 ARegion *ar; | |
2843 RegionView3D *rv3d; | |
2844 Scene *scene = CTX_data_scene(C); | |
2845 static int perspo = RV3D_PERSP; | |
2846 int viewnum, align_active, nextperspo; | |
2847 | |
2848 /* no NULL check is needed, poll checks */ | |
2849 ED_view3d_context_user_region(C, &v3d, &ar); | |
2850 rv3d = ar->regiondata; | |
2851 | |
2852 viewnum = RNA_enum_get(op->ptr, "type"); | |
2853 align_active = RNA_boolean_get(op->ptr, "align_active"); | |
2854 | |
2855 /* set this to zero, gets handled in axis_set_view */ | |
2856 if (rv3d->viewlock) | |
2857 align_active = 0; | |
2858 | |
2859 /* Use this to test if we started out with a camera */ | |
2860 | |
2861 if (rv3d->persp == RV3D_CAMOB) { | |
2862 nextperspo = rv3d->lpersp; | |
2863 } | |
2864 else { | |
2865 nextperspo = perspo; | |
2866 } | |
2867 | |
2868 switch (viewnum) { | |
2869 case RV3D_VIEW_BOTTOM: | |
2870 axis_set_view(C, v3d, ar, 0.0, -1.0, 0.0, 0.0, | |
2871 viewnum, nextperspo, align_active); | |
2872 break; | |
2873 | |
2874 case RV3D_VIEW_BACK: | |
2875 axis_set_view(C, v3d, ar, 0.0, 0.0, (float)-cos(M_PI / 4
.0), (float)-cos(M_PI / 4.0), | |
2876 viewnum, nextperspo, align_active); | |
2877 break; | |
2878 | |
2879 case RV3D_VIEW_LEFT: | |
2880 axis_set_view(C, v3d, ar, 0.5, -0.5, 0.5, 0.5, | |
2881 viewnum, nextperspo, align_active); | |
2882 break; | |
2883 | |
2884 case RV3D_VIEW_TOP: | |
2885 axis_set_view(C, v3d, ar, 1.0, 0.0, 0.0, 0.0, | |
2886 viewnum, nextperspo, align_active); | |
2887 break; | |
2888 | |
2889 case RV3D_VIEW_FRONT: | |
2890 axis_set_view(C, v3d, ar, (float)cos(M_PI / 4.0), (float
)-sin(M_PI / 4.0), 0.0, 0.0, | |
2891 viewnum, nextperspo, align_active); | |
2892 break; | |
2893 | |
2894 case RV3D_VIEW_RIGHT: | |
2895 axis_set_view(C, v3d, ar, 0.5, -0.5, -0.5, -0.5, | |
2896 viewnum, nextperspo, align_active); | |
2897 break; | |
2898 | |
2899 case RV3D_VIEW_CAMERA: | |
2900 if (rv3d->viewlock == 0) { | |
2901 /* lastview - */ | |
2902 | |
2903 if (rv3d->persp != RV3D_CAMOB) { | |
2904 Object *ob = OBACT; | |
2905 | |
2906 if (!rv3d->smooth_timer) { | |
2907 /* store settings of current vie
w before allowing overwriting with camera view | |
2908 * only if we're not currently i
n a view transition */ | |
2909 copy_qt_qt(rv3d->lviewquat, rv3d
->viewquat); | |
2910 rv3d->lview = rv3d->view; | |
2911 rv3d->lpersp = rv3d->persp; | |
2912 } | |
2913 | |
2914 #if 0 | |
2915 if (G.qual == LR_ALTKEY) { | |
2916 if (oldcamera && is_an_active_ob
ject(oldcamera)) { | |
2917 v3d->camera = oldcamera; | |
2918 } | |
2919 handle_view3d_lock(); | |
2920 } | |
2921 #endif | |
2922 ········································ | |
2923 /* first get the default camera for the
view lock type */ | |
2924 if (v3d->scenelock) { | |
2925 /* sets the camera view if avail
able */ | |
2926 v3d->camera = scene->camera; | |
2927 } | |
2928 else { | |
2929 /* use scene camera if one is no
t set (even though we're unlocked) */ | |
2930 if (v3d->camera == NULL) { | |
2931 v3d->camera = scene->cam
era; | |
2932 } | |
2933 } | |
2934 | |
2935 /* if the camera isn't found, check a nu
mber of options */ | |
2936 if (v3d->camera == NULL && ob && ob->typ
e == OB_CAMERA) | |
2937 v3d->camera = ob; | |
2938 ········································ | |
2939 if (v3d->camera == NULL) | |
2940 v3d->camera = BKE_scene_camera_f
ind(scene); | |
2941 | |
2942 /* couldnt find any useful camera, bail
out */ | |
2943 if (v3d->camera == NULL) | |
2944 return OPERATOR_CANCELLED; | |
2945 ········································ | |
2946 /* important these don't get out of sync
for locked scenes */ | |
2947 if (v3d->scenelock) | |
2948 scene->camera = v3d->camera; | |
2949 | |
2950 /* finally do snazzy view zooming */ | |
2951 rv3d->persp = RV3D_CAMOB; | |
2952 smooth_view(C, v3d, ar, NULL, v3d->camer
a, rv3d->ofs, rv3d->viewquat, &rv3d->dist, &v3d->lens); | |
2953 | |
2954 } | |
2955 else { | |
2956 /* return to settings of last view */ | |
2957 /* does smooth_view too */ | |
2958 axis_set_view(C, v3d, ar, | |
2959 rv3d->lviewquat[0], rv3d->
lviewquat[1], rv3d->lviewquat[2], rv3d->lviewquat[3], | |
2960 rv3d->lview, rv3d->lpersp,
0); | |
2961 } | |
2962 } | |
2963 break; | |
2964 | |
2965 default: | |
2966 break; | |
2967 } | |
2968 | |
2969 if (rv3d->persp != RV3D_CAMOB) perspo = rv3d->persp; | |
2970 | |
2971 return OPERATOR_FINISHED; | |
2972 } | |
2973 | |
2974 | |
2975 void VIEW3D_OT_viewnumpad(wmOperatorType *ot) | |
2976 { | |
2977 PropertyRNA *prop; | |
2978 | |
2979 /* identifiers */ | |
2980 ot->name = "View numpad"; | |
2981 ot->description = "Set the view"; | |
2982 ot->idname = "VIEW3D_OT_viewnumpad"; | |
2983 | |
2984 /* api callbacks */ | |
2985 ot->exec = viewnumpad_exec; | |
2986 ot->poll = ED_operator_rv3d_user_region_poll; | |
2987 | |
2988 /* flags */ | |
2989 ot->flag = 0; | |
2990 | |
2991 prop = RNA_def_enum(ot->srna, "type", prop_view_items, 0, "View", "The T
ype of view"); | |
2992 RNA_def_property_flag(prop, PROP_SKIP_SAVE); | |
2993 prop = RNA_def_boolean(ot->srna, "align_active", 0, "Align Active", "Ali
gn to the active object's axis"); | |
2994 RNA_def_property_flag(prop, PROP_SKIP_SAVE); | |
2995 } | |
2996 | |
2997 static EnumPropertyItem prop_view_orbit_items[] = { | |
2998 {V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around
to the Left"}, | |
2999 {V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view aro
und to the Right"}, | |
3000 {V3D_VIEW_STEPUP, "ORBITUP", 0, "Orbit Up", "Orbit the view Up"}, | |
3001 {V3D_VIEW_STEPDOWN, "ORBITDOWN", 0, "Orbit Down", "Orbit the view Down"}
, | |
3002 {0, NULL, 0, NULL, NULL} | |
3003 }; | |
3004 | |
3005 static int vieworbit_exec(bContext *C, wmOperator *op) | |
3006 { | |
3007 View3D *v3d; | |
3008 ARegion *ar; | |
3009 RegionView3D *rv3d; | |
3010 float phi, q1[4], new_quat[4]; | |
3011 int orbitdir; | |
3012 | |
3013 /* no NULL check is needed, poll checks */ | |
3014 ED_view3d_context_user_region(C, &v3d, &ar); | |
3015 rv3d = ar->regiondata; | |
3016 | |
3017 orbitdir = RNA_enum_get(op->ptr, "type"); | |
3018 | |
3019 if (rv3d->viewlock == 0) { | |
3020 if ((rv3d->persp != RV3D_CAMOB) || ED_view3d_camera_lock_check(v
3d, rv3d)) { | |
3021 if (orbitdir == V3D_VIEW_STEPLEFT || orbitdir == V3D_VIE
W_STEPRIGHT) { | |
3022 float si; | |
3023 /* z-axis */ | |
3024 phi = (float)(M_PI / 360.0) * U.pad_rot_angle; | |
3025 if (orbitdir == V3D_VIEW_STEPRIGHT) phi = -phi; | |
3026 si = (float)sin(phi); | |
3027 q1[0] = (float)cos(phi); | |
3028 q1[1] = q1[2] = 0.0; | |
3029 q1[3] = si; | |
3030 mul_qt_qtqt(new_quat, rv3d->viewquat, q1); | |
3031 rv3d->view = RV3D_VIEW_USER; | |
3032 } | |
3033 else if (orbitdir == V3D_VIEW_STEPDOWN || orbitdir == V3
D_VIEW_STEPUP) { | |
3034 /* horizontal axis */ | |
3035 copy_v3_v3(q1 + 1, rv3d->viewinv[0]); | |
3036 | |
3037 normalize_v3(q1 + 1); | |
3038 phi = (float)(M_PI / 360.0) * U.pad_rot_angle; | |
3039 if (orbitdir == V3D_VIEW_STEPDOWN) phi = -phi; | |
3040 q1[0] = (float)cos(phi); | |
3041 mul_v3_fl(q1 + 1, sin(phi)); | |
3042 mul_qt_qtqt(new_quat, rv3d->viewquat, q1); | |
3043 rv3d->view = RV3D_VIEW_USER; | |
3044 } | |
3045 | |
3046 smooth_view(C, CTX_wm_view3d(C), ar, NULL, NULL, NULL, n
ew_quat, NULL, NULL); | |
3047 } | |
3048 } | |
3049 | |
3050 return OPERATOR_FINISHED; | |
3051 } | |
3052 | |
3053 void VIEW3D_OT_view_orbit(wmOperatorType *ot) | |
3054 { | |
3055 /* identifiers */ | |
3056 ot->name = "View Orbit"; | |
3057 ot->description = "Orbit the view"; | |
3058 ot->idname = "VIEW3D_OT_view_orbit"; | |
3059 | |
3060 /* api callbacks */ | |
3061 ot->exec = vieworbit_exec; | |
3062 ot->poll = ED_operator_rv3d_user_region_poll; | |
3063 | |
3064 /* flags */ | |
3065 ot->flag = 0; | |
3066 RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direc
tion of View Orbit"); | |
3067 } | |
3068 | |
3069 static EnumPropertyItem prop_view_pan_items[] = { | |
3070 {V3D_VIEW_PANLEFT, "PANLEFT", 0, "Pan Left", "Pan the view to the Left"}
, | |
3071 {V3D_VIEW_PANRIGHT, "PANRIGHT", 0, "Pan Right", "Pan the view to the Rig
ht"}, | |
3072 {V3D_VIEW_PANUP, "PANUP", 0, "Pan Up", "Pan the view Up"}, | |
3073 {V3D_VIEW_PANDOWN, "PANDOWN", 0, "Pan Down", "Pan the view Down"}, | |
3074 {0, NULL, 0, NULL, NULL} | |
3075 }; | |
3076 | |
3077 static int viewpan_exec(bContext *C, wmOperator *op) | |
3078 { | |
3079 ARegion *ar = CTX_wm_region(C); | |
3080 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
3081 float vec[3]; | |
3082 float mval_f[2] = {0.0f, 0.0f}; | |
3083 int pandir; | |
3084 | |
3085 pandir = RNA_enum_get(op->ptr, "type"); | |
3086 | |
3087 initgrabz(rv3d, 0.0, 0.0, 0.0); | |
3088 if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; ED_view3d_w
in_to_delta(ar, mval_f, vec); } | |
3089 else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; ED_view3d_w
in_to_delta(ar, mval_f, vec); } | |
3090 else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; ED_view3d_w
in_to_delta(ar, mval_f, vec); } | |
3091 else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; ED_view3d_w
in_to_delta(ar, mval_f, vec); } | |
3092 add_v3_v3(rv3d->ofs, vec); | |
3093 | |
3094 if (rv3d->viewlock & RV3D_BOXVIEW) | |
3095 view3d_boxview_sync(CTX_wm_area(C), ar); | |
3096 | |
3097 ED_region_tag_redraw(ar); | |
3098 | |
3099 return OPERATOR_FINISHED; | |
3100 } | |
3101 | |
3102 void VIEW3D_OT_view_pan(wmOperatorType *ot) | |
3103 { | |
3104 /* identifiers */ | |
3105 ot->name = "View Pan"; | |
3106 ot->description = "Pan the view"; | |
3107 ot->idname = "VIEW3D_OT_view_pan"; | |
3108 | |
3109 /* api callbacks */ | |
3110 ot->exec = viewpan_exec; | |
3111 ot->poll = ED_operator_region_view3d_active; | |
3112 | |
3113 /* flags */ | |
3114 ot->flag = 0; | |
3115 RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction
of View Pan"); | |
3116 } | |
3117 | |
3118 static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op)) | |
3119 { | |
3120 View3D *v3d_dummy; | |
3121 ARegion *ar; | |
3122 RegionView3D *rv3d; | |
3123 | |
3124 /* no NULL check is needed, poll checks */ | |
3125 ED_view3d_context_user_region(C, &v3d_dummy, &ar); | |
3126 rv3d = ar->regiondata; | |
3127 | |
3128 if (rv3d->viewlock == 0) { | |
3129 if (rv3d->persp != RV3D_ORTHO) | |
3130 rv3d->persp = RV3D_ORTHO; | |
3131 else rv3d->persp = RV3D_PERSP; | |
3132 ED_region_tag_redraw(ar); | |
3133 } | |
3134 | |
3135 return OPERATOR_FINISHED; | |
3136 | |
3137 } | |
3138 | |
3139 void VIEW3D_OT_view_persportho(wmOperatorType *ot) | |
3140 { | |
3141 /* identifiers */ | |
3142 ot->name = "View Persp/Ortho"; | |
3143 ot->description = "Switch the current view from perspective/orthographic
"; | |
3144 ot->idname = "VIEW3D_OT_view_persportho"; | |
3145 | |
3146 /* api callbacks */ | |
3147 ot->exec = viewpersportho_exec; | |
3148 ot->poll = ED_operator_rv3d_user_region_poll; | |
3149 | |
3150 /* flags */ | |
3151 ot->flag = 0; | |
3152 } | |
3153 | |
3154 | |
3155 /* ******************** add background image operator **************** */ | |
3156 | |
3157 static BGpic *background_image_add(bContext *C) | |
3158 { | |
3159 View3D *v3d = CTX_wm_view3d(C); | |
3160 | |
3161 return ED_view3D_background_image_new(v3d); | |
3162 } | |
3163 | |
3164 static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op)) | |
3165 { | |
3166 background_image_add(C); | |
3167 | |
3168 return OPERATOR_FINISHED; | |
3169 } | |
3170 | |
3171 static int background_image_add_invoke(bContext *C, wmOperator *op, wmEvent *UNU
SED(event)) | |
3172 { | |
3173 View3D *v3d = CTX_wm_view3d(C); | |
3174 Image *ima = NULL; | |
3175 BGpic *bgpic; | |
3176 char name[MAX_ID_NAME - 2]; | |
3177 ········ | |
3178 /* check input variables */ | |
3179 if (RNA_struct_property_is_set(op->ptr, "filepath")) { | |
3180 char path[FILE_MAX]; | |
3181 ················ | |
3182 RNA_string_get(op->ptr, "filepath", path); | |
3183 ima = BKE_image_load_exists(path); | |
3184 } | |
3185 else if (RNA_struct_property_is_set(op->ptr, "name")) { | |
3186 RNA_string_get(op->ptr, "name", name); | |
3187 ima = (Image *)BKE_libblock_find_name(ID_IM, name); | |
3188 } | |
3189 ········ | |
3190 bgpic = background_image_add(C); | |
3191 ········ | |
3192 if (ima) { | |
3193 bgpic->ima = ima; | |
3194 ················ | |
3195 if (ima->id.us == 0) id_us_plus(&ima->id); | |
3196 else id_lib_extern(&ima->id); | |
3197 ················ | |
3198 if (!(v3d->flag & V3D_DISPBGPICS)) | |
3199 v3d->flag |= V3D_DISPBGPICS; | |
3200 } | |
3201 ········ | |
3202 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); | |
3203 ········ | |
3204 return OPERATOR_FINISHED; | |
3205 } | |
3206 | |
3207 void VIEW3D_OT_background_image_add(wmOperatorType *ot) | |
3208 { | |
3209 /* identifiers */ | |
3210 ot->name = "Add Background Image"; | |
3211 ot->description = "Add a new background image"; | |
3212 ot->idname = "VIEW3D_OT_background_image_add"; | |
3213 | |
3214 /* api callbacks */ | |
3215 ot->invoke = background_image_add_invoke; | |
3216 ot->exec = background_image_add_exec; | |
3217 ot->poll = ED_operator_view3d_active; | |
3218 | |
3219 /* flags */ | |
3220 ot->flag = 0; | |
3221 ········ | |
3222 /* properties */ | |
3223 RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Imag
e name to assign"); | |
3224 RNA_def_string(ot->srna, "filepath", "Path", FILE_MAX, "Filepath", "Path
to image file"); | |
3225 } | |
3226 | |
3227 | |
3228 /* ***** remove image operator ******* */ | |
3229 static int background_image_remove_exec(bContext *C, wmOperator *op) | |
3230 { | |
3231 View3D *v3d = CTX_wm_view3d(C); | |
3232 int index = RNA_int_get(op->ptr, "index"); | |
3233 BGpic *bgpic_rem = BLI_findlink(&v3d->bgpicbase, index); | |
3234 | |
3235 if (bgpic_rem) { | |
3236 ED_view3D_background_image_remove(v3d, bgpic_rem); | |
3237 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); | |
3238 return OPERATOR_FINISHED; | |
3239 } | |
3240 else { | |
3241 return OPERATOR_CANCELLED; | |
3242 } | |
3243 | |
3244 } | |
3245 | |
3246 void VIEW3D_OT_background_image_remove(wmOperatorType *ot) | |
3247 { | |
3248 /* identifiers */ | |
3249 ot->name = "Remove Background Image"; | |
3250 ot->description = "Remove a background image from the 3D view"; | |
3251 ot->idname = "VIEW3D_OT_background_image_remove"; | |
3252 | |
3253 /* api callbacks */ | |
3254 ot->exec = background_image_remove_exec; | |
3255 ot->poll = ED_operator_view3d_active; | |
3256 | |
3257 /* flags */ | |
3258 ot->flag = 0; | |
3259 | |
3260 RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image
index to remove", 0, INT_MAX); | |
3261 } | |
3262 | |
3263 /* ********************* set clipping operator ****************** */ | |
3264 | |
3265 static void calc_clipping_plane(float clip[6][4], BoundBox *clipbb) | |
3266 { | |
3267 int val; | |
3268 | |
3269 for (val = 0; val < 4; val++) { | |
3270 | |
3271 normal_tri_v3(clip[val], clipbb->vec[val], clipbb->vec[val == 3
? 0 : val + 1], clipbb->vec[val + 4]); | |
3272 | |
3273 /* TODO - this is just '-dot_v3v3(clip[val], clipbb->vec[val])'
isnt it? - sould replace */ | |
3274 clip[val][3] = -clip[val][0] * clipbb->vec[val][0] - | |
3275 clip[val][1] * clipbb->vec[val][1] - | |
3276 clip[val][2] * clipbb->vec[val][2]; | |
3277 } | |
3278 } | |
3279 | |
3280 static void calc_local_clipping(float clip_local[][4], BoundBox *clipbb, float m
at[][4]) | |
3281 { | |
3282 BoundBox clipbb_local; | |
3283 float imat[4][4]; | |
3284 int i; | |
3285 | |
3286 invert_m4_m4(imat, mat); | |
3287 | |
3288 for (i = 0; i < 8; i++) { | |
3289 mul_v3_m4v3(clipbb_local.vec[i], imat, clipbb->vec[i]); | |
3290 } | |
3291 | |
3292 calc_clipping_plane(clip_local, &clipbb_local); | |
3293 } | |
3294 | |
3295 void ED_view3d_clipping_local(RegionView3D *rv3d, float mat[][4]) | |
3296 { | |
3297 if (rv3d->rflag & RV3D_CLIPPING) | |
3298 calc_local_clipping(rv3d->clip_local, rv3d->clipbb, mat); | |
3299 } | |
3300 | |
3301 static int view3d_clipping_exec(bContext *C, wmOperator *op) | |
3302 { | |
3303 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
3304 ViewContext vc; | |
3305 bglMats mats; | |
3306 rcti rect; | |
3307 | |
3308 rect.xmin = RNA_int_get(op->ptr, "xmin"); | |
3309 rect.ymin = RNA_int_get(op->ptr, "ymin"); | |
3310 rect.xmax = RNA_int_get(op->ptr, "xmax"); | |
3311 rect.ymax = RNA_int_get(op->ptr, "ymax"); | |
3312 | |
3313 rv3d->rflag |= RV3D_CLIPPING; | |
3314 rv3d->clipbb = MEM_callocN(sizeof(BoundBox), "clipbb"); | |
3315 | |
3316 /* note; otherwise opengl won't work */ | |
3317 view3d_operator_needs_opengl(C); | |
3318 | |
3319 view3d_set_viewcontext(C, &vc); | |
3320 view3d_get_transformation(vc.ar, vc.rv3d, NULL, &mats); /* NULL because
we don't want it in object space */ | |
3321 ED_view3d_calc_clipping(rv3d->clipbb, rv3d->clip, &mats, &rect); | |
3322 | |
3323 return OPERATOR_FINISHED; | |
3324 } | |
3325 | |
3326 static int view3d_clipping_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
3327 { | |
3328 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
3329 ARegion *ar = CTX_wm_region(C); | |
3330 | |
3331 if (rv3d->rflag & RV3D_CLIPPING) { | |
3332 rv3d->rflag &= ~RV3D_CLIPPING; | |
3333 ED_region_tag_redraw(ar); | |
3334 if (rv3d->clipbb) MEM_freeN(rv3d->clipbb); | |
3335 rv3d->clipbb = NULL; | |
3336 return OPERATOR_FINISHED; | |
3337 } | |
3338 else { | |
3339 return WM_border_select_invoke(C, op, event); | |
3340 } | |
3341 } | |
3342 | |
3343 /* toggles */ | |
3344 void VIEW3D_OT_clip_border(wmOperatorType *ot) | |
3345 { | |
3346 | |
3347 /* identifiers */ | |
3348 ot->name = "Clipping Border"; | |
3349 ot->description = "Set the view clipping border"; | |
3350 ot->idname = "VIEW3D_OT_clip_border"; | |
3351 | |
3352 /* api callbacks */ | |
3353 ot->invoke = view3d_clipping_invoke; | |
3354 ot->exec = view3d_clipping_exec; | |
3355 ot->modal = WM_border_select_modal; | |
3356 ot->cancel = WM_border_select_cancel; | |
3357 | |
3358 ot->poll = ED_operator_region_view3d_active; | |
3359 | |
3360 /* flags */ | |
3361 ot->flag = 0; | |
3362 | |
3363 /* rna */ | |
3364 RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN,
INT_MAX); | |
3365 RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN,
INT_MAX); | |
3366 RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN,
INT_MAX); | |
3367 RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN,
INT_MAX); | |
3368 } | |
3369 | |
3370 /* ***************** 3d cursor cursor op ******************* */ | |
3371 | |
3372 /* mx my in region coords */ | |
3373 static int set_3dcursor_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *eve
nt) | |
3374 { | |
3375 Scene *scene = CTX_data_scene(C); | |
3376 ARegion *ar = CTX_wm_region(C); | |
3377 View3D *v3d = CTX_wm_view3d(C); | |
3378 RegionView3D *rv3d = CTX_wm_region_view3d(C); | |
3379 float dx, dy, fz, *fp = NULL, dvec[3], oldcurs[3]; | |
3380 int mval[2]; | |
3381 // short ctrl= 0; // XXX | |
3382 int flip; | |
3383 fp = give_cursor(scene, v3d); | |
3384 | |
3385 // if (obedit && ctrl) lr_click= 1; | |
3386 copy_v3_v3(oldcurs, fp); | |
3387 | |
3388 project_int_noclip(ar, fp, mval); | |
3389 flip = initgrabz(rv3d, fp[0], fp[1], fp[2]); | |
3390 ········ | |
3391 /* reset the depth based on the view offset */ | |
3392 if (flip) { | |
3393 negate_v3_v3(fp, rv3d->ofs); | |
3394 | |
3395 /* re initialize */ | |
3396 project_int_noclip(ar, fp, mval); | |
3397 flip = initgrabz(rv3d, fp[0], fp[1], fp[2]); | |
3398 (void)flip; | |
3399 } | |
3400 | |
3401 if (mval[0] != IS_CLIPPED) { | |
3402 short depth_used = 0; | |
3403 | |
3404 if (U.uiflag & USER_ORBIT_ZBUF) { /* maybe this should be access
ed some other way */ | |
3405 view3d_operator_needs_opengl(C); | |
3406 if (ED_view3d_autodist(scene, ar, v3d, event->mval, fp)) | |
3407 depth_used = 1; | |
3408 } | |
3409 | |
3410 if (depth_used == 0) { | |
3411 float mval_f[2]; | |
3412 VECSUB2D(mval_f, mval, event->mval); | |
3413 ED_view3d_win_to_delta(ar, mval_f, dvec); | |
3414 sub_v3_v3(fp, dvec); | |
3415 } | |
3416 } | |
3417 else { | |
3418 | |
3419 dx = ((float)(event->mval[0] - (ar->winx / 2))) * rv3d->zfac / (
ar->winx / 2); | |
3420 dy = ((float)(event->mval[1] - (ar->winy / 2))) * rv3d->zfac / (
ar->winy / 2); | |
3421 | |
3422 fz = rv3d->persmat[0][3] * fp[0] + rv3d->persmat[1][3] * fp[1] +
rv3d->persmat[2][3] * fp[2] + rv3d->persmat[3][3]; | |
3423 fz = fz / rv3d->zfac; | |
3424 | |
3425 fp[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy + r
v3d->persinv[2][0] * fz) - rv3d->ofs[0]; | |
3426 fp[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy + r
v3d->persinv[2][1] * fz) - rv3d->ofs[1]; | |
3427 fp[2] = (rv3d->persinv[0][2] * dx + rv3d->persinv[1][2] * dy + r
v3d->persinv[2][2] * fz) - rv3d->ofs[2]; | |
3428 } | |
3429 | |
3430 if (v3d && v3d->localvd) | |
3431 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); | |
3432 else | |
3433 WM_event_add_notifier(C, NC_SCENE | NA_EDITED, scene); | |
3434 | |
3435 return OPERATOR_FINISHED; | |
3436 } | |
3437 | |
3438 void VIEW3D_OT_cursor3d(wmOperatorType *ot) | |
3439 { | |
3440 | |
3441 /* identifiers */ | |
3442 ot->name = "Set 3D Cursor"; | |
3443 ot->description = "Set the location of the 3D cursor"; | |
3444 ot->idname = "VIEW3D_OT_cursor3d"; | |
3445 | |
3446 /* api callbacks */ | |
3447 ot->invoke = set_3dcursor_invoke; | |
3448 | |
3449 ot->poll = ED_operator_view3d_active; | |
3450 | |
3451 /* flags */ | |
3452 // ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; | |
3453 | |
3454 /* rna later */ | |
3455 | |
3456 } | |
3457 | |
3458 /* ***************** manipulator op ******************* */ | |
3459 | |
3460 | |
3461 static int manipulator_invoke(bContext *C, wmOperator *op, wmEvent *event) | |
3462 { | |
3463 View3D *v3d = CTX_wm_view3d(C); | |
3464 | |
3465 if (!(v3d->twflag & V3D_USE_MANIPULATOR)) return OPERATOR_PASS_THROUGH; | |
3466 if (!(v3d->twflag & V3D_DRAW_MANIPULATOR)) return OPERATOR_PASS_THROUGH; | |
3467 | |
3468 /* only no modifier or shift */ | |
3469 if (event->keymodifier != 0 && event->keymodifier != KM_SHIFT) return OP
ERATOR_PASS_THROUGH; | |
3470 | |
3471 /* note; otherwise opengl won't work */ | |
3472 view3d_operator_needs_opengl(C); | |
3473 | |
3474 if (0 == BIF_do_manipulator(C, event, op)) | |
3475 return OPERATOR_PASS_THROUGH; | |
3476 | |
3477 return OPERATOR_FINISHED; | |
3478 } | |
3479 | |
3480 void VIEW3D_OT_manipulator(wmOperatorType *ot) | |
3481 { | |
3482 | |
3483 /* identifiers */ | |
3484 ot->name = "3D Manipulator"; | |
3485 ot->description = "Manipulate selected item by axis"; | |
3486 ot->idname = "VIEW3D_OT_manipulator"; | |
3487 | |
3488 /* api callbacks */ | |
3489 ot->invoke = manipulator_invoke; | |
3490 | |
3491 ot->poll = ED_operator_view3d_active; | |
3492 | |
3493 /* properties to pass to transform */ | |
3494 Transform_Properties(ot, P_CONSTRAINT); | |
3495 } | |
3496 | |
3497 static int enable_manipulator_invoke(bContext *C, wmOperator *op, wmEvent *UNUSE
D(event)) | |
3498 { | |
3499 View3D *v3d = CTX_wm_view3d(C); | |
3500 | |
3501 v3d->twtype = 0; | |
3502 ········ | |
3503 if (RNA_boolean_get(op->ptr, "translate")) | |
3504 v3d->twtype |= V3D_MANIP_TRANSLATE; | |
3505 if (RNA_boolean_get(op->ptr, "rotate")) | |
3506 v3d->twtype |= V3D_MANIP_ROTATE; | |
3507 if (RNA_boolean_get(op->ptr, "scale")) | |
3508 v3d->twtype |= V3D_MANIP_SCALE; | |
3509 ················ | |
3510 WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d); | |
3511 | |
3512 return OPERATOR_FINISHED; | |
3513 } | |
3514 | |
3515 void VIEW3D_OT_enable_manipulator(wmOperatorType *ot) | |
3516 { | |
3517 PropertyRNA *prop; | |
3518 | |
3519 /* identifiers */ | |
3520 ot->name = "Enable 3D Manipulator"; | |
3521 ot->description = "Enable the transform manipulator for use"; | |
3522 ot->idname = "VIEW3D_OT_enable_manipulator"; | |
3523 ········ | |
3524 /* api callbacks */ | |
3525 ot->invoke = enable_manipulator_invoke; | |
3526 ot->poll = ED_operator_view3d_active; | |
3527 ········ | |
3528 /* rna later */ | |
3529 prop = RNA_def_boolean(ot->srna, "translate", 0, "Translate", "Enable th
e translate manipulator"); | |
3530 RNA_def_property_flag(prop, PROP_SKIP_SAVE); | |
3531 prop = RNA_def_boolean(ot->srna, "rotate", 0, "Rotate", "Enable the rota
te manipulator"); | |
3532 RNA_def_property_flag(prop, PROP_SKIP_SAVE); | |
3533 prop = RNA_def_boolean(ot->srna, "scale", 0, "Scale", "Enable the scale
manipulator"); | |
3534 RNA_def_property_flag(prop, PROP_SKIP_SAVE); | |
3535 } | |
3536 | |
3537 /* ************************* below the line! *********************** */ | |
3538 | |
3539 | |
3540 static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int marg
in) | |
3541 { | |
3542 ViewDepths depth_temp = {0}; | |
3543 rcti rect; | |
3544 float depth_close; | |
3545 | |
3546 if (margin == 0) { | |
3547 /* Get Z Depths, needed for perspective, nice for ortho */ | |
3548 rect.xmin = mval[0]; | |
3549 rect.ymin = mval[1]; | |
3550 rect.xmax = mval[0] + 1; | |
3551 rect.ymax = mval[1] + 1; | |
3552 } | |
3553 else { | |
3554 rect.xmax = mval[0] + margin; | |
3555 rect.ymax = mval[1] + margin; | |
3556 | |
3557 rect.xmin = mval[0] - margin; | |
3558 rect.ymin = mval[1] - margin; | |
3559 } | |
3560 | |
3561 view3d_update_depths_rect(ar, &depth_temp, &rect); | |
3562 depth_close = view3d_depth_near(&depth_temp); | |
3563 if (depth_temp.depths) MEM_freeN(depth_temp.depths); | |
3564 return depth_close; | |
3565 } | |
3566 | |
3567 /* XXX todo Zooms in on a border drawn by the user */ | |
3568 int ED_view3d_autodist(Scene *scene, ARegion *ar, View3D *v3d, const int mval[2]
, float mouse_worldloc[3]) | |
3569 { | |
3570 bglMats mats; /* ZBuffer depth vars */ | |
3571 float depth_close = FLT_MAX; | |
3572 double cent[2], p[3]; | |
3573 | |
3574 /* Get Z Depths, needed for perspective, nice for ortho */ | |
3575 bgl_get_mats(&mats); | |
3576 draw_depth(scene, ar, v3d, NULL); | |
3577 | |
3578 depth_close = view_autodist_depth_margin(ar, mval, 4); | |
3579 | |
3580 if (depth_close == FLT_MAX) | |
3581 return 0; | |
3582 | |
3583 cent[0] = (double)mval[0]; | |
3584 cent[1] = (double)mval[1]; | |
3585 | |
3586 if (!gluUnProject(cent[0], cent[1], depth_close, | |
3587 mats.modelview, mats.projection, (GLint *)mats.viewpor
t, &p[0], &p[1], &p[2])) | |
3588 { | |
3589 return 0; | |
3590 } | |
3591 | |
3592 mouse_worldloc[0] = (float)p[0]; | |
3593 mouse_worldloc[1] = (float)p[1]; | |
3594 mouse_worldloc[2] = (float)p[2]; | |
3595 return 1; | |
3596 } | |
3597 | |
3598 int ED_view3d_autodist_init(Scene *scene, ARegion *ar, View3D *v3d, int mode) //
, float *autodist ) | |
3599 { | |
3600 /* Get Z Depths, needed for perspective, nice for ortho */ | |
3601 switch (mode) { | |
3602 case 0: | |
3603 draw_depth(scene, ar, v3d, NULL); | |
3604 break; | |
3605 case 1: | |
3606 draw_depth_gpencil(scene, ar, v3d); | |
3607 break; | |
3608 } | |
3609 | |
3610 return 1; | |
3611 } | |
3612 | |
3613 // no 4x4 sampling, run view_autodist_init first | |
3614 int ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldl
oc[3], | |
3615 int margin, float *force_depth) //, float *autodis
t ) | |
3616 { | |
3617 bglMats mats; /* ZBuffer depth vars, could cache? */ | |
3618 float depth; | |
3619 double cent[2], p[3]; | |
3620 | |
3621 /* Get Z Depths, needed for perspective, nice for ortho */ | |
3622 if (force_depth) | |
3623 depth = *force_depth; | |
3624 else | |
3625 depth = view_autodist_depth_margin(ar, mval, margin); | |
3626 | |
3627 if (depth == FLT_MAX) | |
3628 return 0; | |
3629 | |
3630 cent[0] = (double)mval[0]; | |
3631 cent[1] = (double)mval[1]; | |
3632 | |
3633 bgl_get_mats(&mats); | |
3634 | |
3635 if (!gluUnProject(cent[0], cent[1], depth, | |
3636 mats.modelview, mats.projection, (GLint *)mats.viewpor
t, &p[0], &p[1], &p[2])) | |
3637 { | |
3638 return 0; | |
3639 } | |
3640 | |
3641 mouse_worldloc[0] = (float)p[0]; | |
3642 mouse_worldloc[1] = (float)p[1]; | |
3643 mouse_worldloc[2] = (float)p[2]; | |
3644 return 1; | |
3645 } | |
3646 | |
3647 int ED_view3d_autodist_depth(struct ARegion *ar, const int mval[2], int margin,
float *depth) | |
3648 { | |
3649 *depth = view_autodist_depth_margin(ar, mval, margin); | |
3650 | |
3651 return (*depth == FLT_MAX) ? 0 : 1; | |
3652 } | |
3653 | |
3654 static int depth_segment_cb(int x, int y, void *userData) | |
3655 { | |
3656 struct { struct ARegion *ar; int margin; float depth; } *data = userData
; | |
3657 int mval[2]; | |
3658 float depth; | |
3659 | |
3660 mval[0] = x; | |
3661 mval[1] = y; | |
3662 | |
3663 depth = view_autodist_depth_margin(data->ar, mval, data->margin); | |
3664 | |
3665 if (depth != FLT_MAX) { | |
3666 data->depth = depth; | |
3667 return 0; | |
3668 } | |
3669 else { | |
3670 return 1; | |
3671 } | |
3672 } | |
3673 | |
3674 int ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], cons
t int mval_end[2], | |
3675 int margin, float *depth) | |
3676 { | |
3677 struct { struct ARegion *ar; int margin; float depth; } data = {NULL}; | |
3678 int p1[2]; | |
3679 int p2[2]; | |
3680 | |
3681 data.ar = ar; | |
3682 data.margin = margin; | |
3683 data.depth = FLT_MAX; | |
3684 | |
3685 copy_v2_v2_int(p1, mval_sta); | |
3686 copy_v2_v2_int(p2, mval_end); | |
3687 | |
3688 plot_line_v2v2i(p1, p2, depth_segment_cb, &data); | |
3689 | |
3690 *depth = data.depth; | |
3691 | |
3692 return (*depth == FLT_MAX) ? 0 : 1; | |
3693 } | |
3694 | |
3695 /** | |
3696 * Gets the view transformation from a camera | |
3697 * currently dosnt take camzoom into account | |
3698 * | |
3699 * The dist is not modified for this function, if NULL its assumed zero | |
3700 */ | |
3701 void ED_view3d_from_m4(float mat[][4], float ofs[3], float quat[4], float *dist) | |
3702 { | |
3703 /* Offset */ | |
3704 if (ofs) | |
3705 negate_v3_v3(ofs, mat[3]); | |
3706 | |
3707 /* Quat */ | |
3708 if (quat) { | |
3709 float imat[4][4]; | |
3710 invert_m4_m4(imat, mat); | |
3711 mat4_to_quat(quat, imat); | |
3712 } | |
3713 | |
3714 if (dist) { | |
3715 float nmat[3][3]; | |
3716 float vec[3]; | |
3717 | |
3718 vec[0] = 0.0f; | |
3719 vec[1] = 0.0f; | |
3720 vec[2] = -(*dist); | |
3721 | |
3722 copy_m3_m4(nmat, mat); | |
3723 normalize_m3(nmat); | |
3724 | |
3725 mul_m3_v3(nmat, vec); | |
3726 sub_v3_v3(ofs, vec); | |
3727 } | |
3728 } | |
3729 | |
3730 void ED_view3d_to_m4(float mat[][4], const float ofs[3], const float quat[4], co
nst float dist) | |
3731 { | |
3732 float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]}; | |
3733 float dvec[3] = {0.0f, 0.0f, dist}; | |
3734 | |
3735 quat_to_mat4(mat, iviewquat); | |
3736 mul_mat3_m4_v3(mat, dvec); | |
3737 sub_v3_v3v3(mat[3], dvec, ofs); | |
3738 } | |
3739 | |
3740 | |
3741 /* object -> view */ | |
3742 void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist,
float *lens) | |
3743 { | |
3744 ED_view3d_from_m4(ob->obmat, ofs, quat, dist); | |
3745 | |
3746 if (lens) { | |
3747 CameraParams params; | |
3748 | |
3749 BKE_camera_params_init(¶ms); | |
3750 BKE_camera_params_from_object(¶ms, ob); | |
3751 *lens = params.lens; | |
3752 } | |
3753 } | |
3754 | |
3755 /* view -> object */ | |
3756 void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], co
nst float dist) | |
3757 { | |
3758 float mat[4][4]; | |
3759 ED_view3d_to_m4(mat, ofs, quat, dist); | |
3760 BKE_object_apply_mat4(ob, mat, TRUE, TRUE); | |
3761 } | |
3762 | |
3763 BGpic *ED_view3D_background_image_new(View3D *v3d) | |
3764 { | |
3765 BGpic *bgpic = MEM_callocN(sizeof(BGpic), "Background Image"); | |
3766 | |
3767 bgpic->size = 5.0; | |
3768 bgpic->blend = 0.5; | |
3769 bgpic->iuser.fie_ima = 2; | |
3770 bgpic->iuser.ok = 1; | |
3771 bgpic->view = 0; /* 0 for all */ | |
3772 bgpic->flag |= V3D_BGPIC_EXPANDED; | |
3773 | |
3774 BLI_addtail(&v3d->bgpicbase, bgpic); | |
3775 | |
3776 return bgpic; | |
3777 } | |
3778 | |
3779 void ED_view3D_background_image_remove(View3D *v3d, BGpic *bgpic) | |
3780 { | |
3781 BLI_remlink(&v3d->bgpicbase, bgpic); | |
3782 | |
3783 MEM_freeN(bgpic); | |
3784 } | |
3785 | |
3786 void ED_view3D_background_image_clear(View3D *v3d) | |
3787 { | |
3788 BGpic *bgpic = v3d->bgpicbase.first; | |
3789 | |
3790 while (bgpic) { | |
3791 BGpic *next_bgpic = bgpic->next; | |
3792 | |
3793 ED_view3D_background_image_remove(v3d, bgpic); | |
3794 | |
3795 bgpic = next_bgpic; | |
3796 } | |
3797 } | |
3798 | |
3799 void ED_view3D_lock_clear(View3D *v3d) | |
3800 { | |
3801 v3d->ob_centre = NULL; | |
3802 v3d->ob_centre_bone[0] = '\0'; | |
3803 v3d->ob_centre_cursor = FALSE; | |
3804 v3d->flag2 &= ~V3D_LOCK_CAMERA; | |
3805 } | |
LEFT | RIGHT |