Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2018-01-30 00:53:32 +0300
committerJulian Eisel <eiseljulian@gmail.com>2018-01-30 01:24:11 +0300
commit3f0871dfcfbb1dda15c176dba92d36639305385a (patch)
treede7ffeeef7a99fc6103d413ebfa564596811087d /source/blender/editors/space_view3d
parent53d94dafc474380651fc529f9c03f84ce7142b13 (diff)
parent1fe2b4bf608b22ae4513051e01cf45e5012c2409 (diff)
Merge branch 'blender2.8' into topbar
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt3
-rw-r--r--source/blender/editors/space_view3d/drawanimviz.c18
-rw-r--r--source/blender/editors/space_view3d/drawobject.c64
-rw-r--r--source/blender/editors/space_view3d/drawvolume.c4
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_camera_control.c7
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c111
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c59
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c1830
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c14
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h25
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_camera.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate.c359
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c307
-rw-r--r--source/blender/editors/space_view3d/view3d_manipulator_ruler.c27
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c19
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c1436
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c714
-rw-r--r--source/blender/editors/space_view3d/view3d_walk.c13
19 files changed, 3112 insertions, 1908 deletions
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index de8380aa8bb..d148ef3c6fe 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -64,6 +64,8 @@ set(SRC
view3d_manipulator_empty.c
view3d_manipulator_forcefield.c
view3d_manipulator_lamp.c
+ view3d_manipulator_navigate.c
+ view3d_manipulator_navigate_type.c
view3d_manipulator_ruler.c
view3d_ops.c
view3d_project.c
@@ -71,6 +73,7 @@ set(SRC
view3d_select.c
view3d_snap.c
view3d_toolbar.c
+ view3d_utils.c
view3d_view.c
view3d_intern.h
diff --git a/source/blender/editors/space_view3d/drawanimviz.c b/source/blender/editors/space_view3d/drawanimviz.c
index 66355a50478..9fa85b55362 100644
--- a/source/blender/editors/space_view3d/drawanimviz.c
+++ b/source/blender/editors/space_view3d/drawanimviz.c
@@ -77,15 +77,15 @@ void draw_motion_paths_init(View3D *v3d, ARegion *ar)
}
/* set color
-* - more intense for active/selected bones, less intense for unselected bones
-* - black for before current frame, green for current frame, blue for after current frame
-* - intensity decreases as distance from current frame increases
-*
-* If the user select custom color, the color is replaced for the color selected in UI panel
-* - 75% Darker color is used for previous frames
-* - 50% Darker color for current frame
-* - User selected color for next frames
-*/
+ * - more intense for active/selected bones, less intense for unselected bones
+ * - black for before current frame, green for current frame, blue for after current frame
+ * - intensity decreases as distance from current frame increases
+ *
+ * If the user select custom color, the color is replaced for the color selected in UI panel
+ * - 75% Darker color is used for previous frames
+ * - 50% Darker color for current frame
+ * - User selected color for next frames
+ */
static void set_motion_path_color(Scene *scene, bMotionPath *mpath, int i, short sel, int sfra, int efra,
float prev_color[3], float frame_color[3], float next_color[3], unsigned color)
{
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 08ef9cc21cb..51dc56bafaf 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -980,14 +980,12 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, bool depth_write)
col_pack_prev = vos->col.pack;
}
- ((vos->flag & V3D_CACHE_TEXT_ASCII) ?
- BLF_draw_default_ascii :
- BLF_draw_default
- )((float)(vos->sco[0] + vos->xoffs),
- (float)(vos->sco[1]),
- (depth_write) ? 0.0f : 2.0f,
- vos->str,
- vos->str_len);
+ ((vos->flag & V3D_CACHE_TEXT_ASCII) ? BLF_draw_default_ascii : BLF_draw_default)(
+ (float)(vos->sco[0] + vos->xoffs),
+ (float)(vos->sco[1]),
+ (depth_write) ? 0.0f : 2.0f,
+ vos->str,
+ vos->str_len);
}
}
@@ -1036,7 +1034,7 @@ static void drawcube_size(float size, unsigned pos)
{ size, size, size}
};
- const GLubyte indices[24] = {0,1,1,3,3,2,2,0,0,4,4,5,5,7,7,6,6,4,1,5,3,7,2,6};
+ const GLubyte indices[24] = {0, 1, 1, 3, 3, 2, 2, 0, 0, 4, 4, 5, 5, 7, 7, 6, 6, 4, 1, 5, 3, 7, 2, 6};
#if 0
glEnableClientState(GL_VERTEX_ARRAY);
@@ -6098,46 +6096,46 @@ static void draw_new_particle_system(
/* 4. */
if (draw_as && ELEM(draw_as, PART_DRAW_PATH, PART_DRAW_CIRC) == 0) {
- int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
+ int partsize = 3 * sizeof(float);
int create_ndata = 0;
if (!pdd)
pdd = psys->pdd = MEM_callocN(sizeof(ParticleDrawData), "ParticleDrawData");
if (part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
- tot_vec_size *= part->trail_count;
+ partsize *= part->trail_count;
psys_make_temp_pointcache(ob, psys);
}
switch (draw_as) {
case PART_DRAW_AXIS:
case PART_DRAW_CROSS:
- tot_vec_size *= 6;
+ partsize *= 6;
if (draw_as != PART_DRAW_CROSS)
create_cdata = 1;
break;
case PART_DRAW_LINE:
- tot_vec_size *= 2;
+ partsize *= 2;
break;
case PART_DRAW_BB:
- tot_vec_size *= 6; /* New OGL only understands tris, no choice here. */
+ partsize *= 6; /* New OGL only understands tris, no choice here. */
create_ndata = 1;
break;
}
- if (pdd->tot_vec_size != tot_vec_size)
+ if (pdd->totpart != totpart + totchild || pdd->partsize != partsize)
psys_free_pdd(psys);
if (!pdd->vdata)
- pdd->vdata = MEM_callocN(tot_vec_size, "particle_vdata");
+ pdd->vdata = MEM_calloc_arrayN(totpart + totchild, partsize, "particle_vdata");
if (create_cdata && !pdd->cdata)
- pdd->cdata = MEM_callocN(tot_vec_size, "particle_cdata");
+ pdd->cdata = MEM_calloc_arrayN(totpart + totchild, partsize, "particle_cdata");
if (create_ndata && !pdd->ndata)
- pdd->ndata = MEM_callocN(tot_vec_size, "particle_ndata");
+ pdd->ndata = MEM_calloc_arrayN(totpart + totchild, partsize, "particle_ndata");
if (part->draw & PART_DRAW_VEL && draw_as != PART_DRAW_LINE) {
if (!pdd->vedata)
- pdd->vedata = MEM_callocN(2 * (totpart + totchild) * 3 * sizeof(float), "particle_vedata");
+ pdd->vedata = MEM_calloc_arrayN(totpart + totchild, 2 * 3 * sizeof(float), "particle_vedata");
need_v = 1;
}
@@ -6151,7 +6149,8 @@ static void draw_new_particle_system(
pdd->ved = pdd->vedata;
pdd->cd = pdd->cdata;
pdd->nd = pdd->ndata;
- pdd->tot_vec_size = tot_vec_size;
+ pdd->totpart = totpart + totchild;
+ pdd->partsize = partsize;
}
else if (psys->pdd) {
psys_free_pdd(psys);
@@ -6630,7 +6629,7 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
const int totkeys = (*edit->pathcache)->segments + 1;
glEnable(GL_BLEND);
- float *pathcol = MEM_callocN(totkeys * 4 * sizeof(float), "particle path color data");
+ float *pathcol = MEM_calloc_arrayN(totkeys, 4 * sizeof(float), "particle path color data");
if (pset->brushtype == PE_BRUSH_WEIGHT)
glLineWidth(2.0f);
@@ -6707,8 +6706,8 @@ static void draw_ptcache_edit(Scene *scene, View3D *v3d, PTCacheEdit *edit)
if (totkeys_visible) {
if (edit->points && !(edit->points->keys->flag & PEK_USE_WCO))
- pd = pdata = MEM_callocN(totkeys_visible * 3 * sizeof(float), "particle edit point data");
- cd = cdata = MEM_callocN(totkeys_visible * (timed ? 4 : 3) * sizeof(float), "particle edit color data");
+ pd = pdata = MEM_calloc_arrayN(totkeys_visible, 3 * sizeof(float), "particle edit point data");
+ cd = cdata = MEM_calloc_arrayN(totkeys_visible, (timed ? 4 : 3) * sizeof(float), "particle edit color data");
}
for (i = 0, point = edit->points; i < totpoint; i++, point++) {
@@ -7405,7 +7404,7 @@ static void draw_editnurb(
}
#else
/* Same as loop above */
- count += 4 * max_ii((nr + max_ii(skip - 1, 0)) / (skip + 1), 0);
+ count += 4 * ((nr / (skip + 1)) + ((nr % (skip + 1)) != 0));
#endif
}
@@ -8066,7 +8065,7 @@ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
if (solid) {
/* Adpated from "Optimizing Triangle Strips for Fast Rendering" by F. Evans, S. Skiena and A. Varshney
* (http://www.cs.umd.edu/gvil/papers/av_ts.pdf). */
- static const GLubyte tris_strip_indices[14] = {0,1,3,2,6,1,5,0,4,3,7,6,4,5};
+ static const GLubyte tris_strip_indices[14] = {0, 1, 3, 2, 6, 1, 5, 0, 4, 3, 7, 6, 4, 5};
immBegin(GWN_PRIM_TRI_STRIP, 14);
for (int i = 0; i < 14; ++i) {
immVertex3fv(pos, vec[tris_strip_indices[i]]);
@@ -8074,7 +8073,8 @@ static void imm_draw_box(const float vec[8][3], bool solid, unsigned pos)
immEnd();
}
else {
- static const GLubyte line_indices[24] = {0,1,1,2,2,3,3,0,0,4,4,5,5,6,6,7,7,4,1,5,2,6,3,7};
+ static const GLubyte line_indices[24] =
+ {0, 1, 1, 2, 2, 3, 3, 0, 0, 4, 4, 5, 5, 6, 6, 7, 7, 4, 1, 5, 2, 6, 3, 7};
immBegin(GWN_PRIM_LINES, 24);
for (int i = 0; i < 24; ++i) {
immVertex3fv(pos, vec[line_indices[i]]);
@@ -9217,7 +9217,10 @@ afterdraw:
/* help lines and so */
if (ob != scene->obedit && ob->parent) {
- if (BKE_object_is_visible(ob->parent)) {
+ const eObjectVisibilityCheck mode = eval_ctx->mode != DAG_EVAL_VIEWPORT ?
+ OB_VISIBILITY_CHECK_FOR_RENDER :
+ OB_VISIBILITY_CHECK_FOR_VIEWPORT;
+ if (BKE_object_is_visible(ob->parent, mode)) {
setlinestyle(3);
immBegin(GWN_PRIM_LINES, 2);
immVertex3fv(pos, ob->obmat[3]);
@@ -9769,8 +9772,9 @@ void draw_object_backbufsel(
bbs_mesh_solid_EM(em, scene, v3d, ob, dm, (ts->selectmode & SCE_SELECT_FACE) != 0);
if (ts->selectmode & SCE_SELECT_FACE)
bm_solidoffs = 1 + em->bm->totface;
- else
+ else {
bm_solidoffs = 1;
+ }
ED_view3d_polygon_offset(rv3d, 1.0);
@@ -9779,6 +9783,10 @@ void draw_object_backbufsel(
bbs_mesh_wire(em, dm, bm_solidoffs);
bm_wireoffs = bm_solidoffs + em->bm->totedge;
}
+ else {
+ /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */
+ bm_wireoffs = bm_solidoffs;
+ }
/* we draw verts if vert select mode. */
if (ts->selectmode & SCE_SELECT_VERTEX) {
diff --git a/source/blender/editors/space_view3d/drawvolume.c b/source/blender/editors/space_view3d/drawvolume.c
index 3a80624acd9..d39f3937a9d 100644
--- a/source/blender/editors/space_view3d/drawvolume.c
+++ b/source/blender/editors/space_view3d/drawvolume.c
@@ -41,7 +41,7 @@
#include "BLI_math.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_texture.h"
+#include "BKE_colorband.h"
#include "BKE_particle.h"
#include "smoke_API.h"
@@ -111,7 +111,7 @@ static void create_flame_spectrum_texture(float *data)
static void create_color_ramp(const ColorBand *coba, float *data)
{
for (int i = 0; i < TFUNC_WIDTH; i++) {
- do_colorband(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
+ BKE_colorband_evaluate(coba, (float)i / TFUNC_WIDTH, &data[i * 4]);
}
}
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 7cf1573de43..6540a1fb234 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -711,6 +711,9 @@ static void view3d_widgets(void)
WM_manipulatorgrouptype_append(VIEW3D_WGT_ruler);
WM_manipulatortype_append(VIEW3D_WT_ruler_item);
+
+ WM_manipulatorgrouptype_append_and_link(mmap_type, VIEW3D_WGT_navigate);
+ WM_manipulatortype_append(VIEW3D_WT_navigate_rotate);
}
@@ -1055,6 +1058,8 @@ static void view3d_main_region_message_subscribe(
/* Only subscribe to types. */
StructRNA *type_array[] = {
+ &RNA_Window,
+
/* These object have properties that impact drawing. */
&RNA_AreaLamp,
&RNA_Camera,
@@ -1102,10 +1107,12 @@ static void view3d_main_region_message_subscribe(
extern StructRNA RNA_ViewLayerEngineSettingsEevee;
WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw);
}
+#ifdef WITH_CLAY_ENGINE
else if (STREQ(view_render->engine_id, RE_engine_id_BLENDER_CLAY)) {
extern StructRNA RNA_ViewLayerEngineSettingsClay;
WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw);
}
+#endif
}
/* concept is to retrieve cursor type context-less */
diff --git a/source/blender/editors/space_view3d/view3d_camera_control.c b/source/blender/editors/space_view3d/view3d_camera_control.c
index 9b07593e576..c39057431c2 100644
--- a/source/blender/editors/space_view3d/view3d_camera_control.c
+++ b/source/blender/editors/space_view3d/view3d_camera_control.c
@@ -138,13 +138,10 @@ Object *ED_view3d_cameracontrol_object_get(View3DCameraControl *vctrl)
* the view for first-person style navigation.
*/
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- const bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root)
{
View3DCameraControl *vctrl;
- EvaluationContext eval_ctx;
-
- CTX_data_eval_ctx(C, &eval_ctx);
vctrl = MEM_callocN(sizeof(View3DCameraControl), __func__);
@@ -181,7 +178,7 @@ struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
/* store the original camera loc and rot */
vctrl->obtfm = BKE_object_tfm_backup(ob_back);
- BKE_object_where_is_calc(&eval_ctx, scene, v3d->camera);
+ BKE_object_where_is_calc(eval_ctx, scene, v3d->camera);
negate_v3_v3(rv3d->ofs, v3d->camera->obmat[3]);
rv3d->dist = 0.0;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 6ea2ff10af2..f734bb085d0 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -123,21 +123,28 @@ void ED_view3d_update_viewmat(
const EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar,
float viewmat[4][4], float winmat[4][4], const rcti *rect)
{
+ const Depsgraph *depsgraph = eval_ctx->depsgraph;
RegionView3D *rv3d = ar->regiondata;
-
/* setup window matrices */
if (winmat)
copy_m4_m4(rv3d->winmat, winmat);
else
- view3d_winmatrix_set(ar, v3d, rect);
+ view3d_winmatrix_set(depsgraph, ar, v3d, rect);
/* setup view matrix */
- if (viewmat)
+ if (viewmat) {
copy_m4_m4(rv3d->viewmat, viewmat);
- else
- view3d_viewmatrix_set(eval_ctx, scene, v3d, rv3d); /* note: calls BKE_object_where_is_calc for camera... */
-
+ }
+ else {
+ float rect_scale[2];
+ if (rect) {
+ rect_scale[0] = (float)BLI_rcti_size_x(rect) / (float)ar->winx;
+ rect_scale[1] = (float)BLI_rcti_size_y(rect) / (float)ar->winy;
+ }
+ /* note: calls BKE_object_where_is_calc for camera... */
+ view3d_viewmatrix_set(eval_ctx, scene, v3d, rv3d, rect ? rect_scale : NULL);
+ }
/* update utility matrices */
mul_m4_m4m4(rv3d->persmat, rv3d->winmat, rv3d->viewmat);
invert_m4_m4(rv3d->persinv, rv3d->persmat);
@@ -148,7 +155,7 @@ void ED_view3d_update_viewmat(
/* store window coordinates scaling/offset */
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
rctf cameraborder;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &cameraborder, false);
+ ED_view3d_calc_camera_border(scene, eval_ctx->depsgraph, ar, v3d, rv3d, &cameraborder, false);
rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
rv3d->viewcamtexcofac[1] = (float)ar->winy / BLI_rctf_size_y(&cameraborder);
@@ -307,7 +314,8 @@ void ED_view3d_draw_setup_view(
/* ******************** view border ***************** */
static void view3d_camera_border(
- const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
+ const Scene *scene, const struct Depsgraph *depsgraph,
+ const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
rctf *r_viewborder, const bool no_shift, const bool no_zoom)
{
CameraParams params;
@@ -315,7 +323,7 @@ static void view3d_camera_border(
/* get viewport viewplane */
BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, v3d, rv3d);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
if (no_zoom)
params.zoom = 1.0f;
BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
@@ -342,21 +350,23 @@ static void view3d_camera_border(
}
void ED_view3d_calc_camera_border_size(
- const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
+ const Scene *scene, const Depsgraph *depsgraph,
+ const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
float r_size[2])
{
rctf viewborder;
- view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, true, true);
+ view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, true, true);
r_size[0] = BLI_rctf_size_x(&viewborder);
r_size[1] = BLI_rctf_size_y(&viewborder);
}
void ED_view3d_calc_camera_border(
- const Scene *scene, const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
+ const Scene *scene, const Depsgraph *depsgraph,
+ const ARegion *ar, const View3D *v3d, const RegionView3D *rv3d,
rctf *r_viewborder, const bool no_shift)
{
- view3d_camera_border(scene, ar, v3d, rv3d, r_viewborder, no_shift, false);
+ view3d_camera_border(scene, depsgraph, ar, v3d, rv3d, r_viewborder, no_shift, false);
}
static void drawviewborder_grid3(uint shdr_pos, float x1, float x2, float y1, float y2, float fac)
@@ -435,7 +445,7 @@ static void drawviewborder_triangle(
immEnd();
}
-static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
+static void drawviewborder(Scene *scene, const Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
{
float x1, x2, y1, y2;
float x1i, x2i, y1i, y2i;
@@ -449,7 +459,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
if (v3d->camera->type == OB_CAMERA)
ca = v3d->camera->data;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
/* the offsets */
x1 = viewborder.xmin;
y1 = viewborder.ymin;
@@ -1318,6 +1328,10 @@ float ED_view3d_grid_scale(Scene *scene, View3D *v3d, const char **grid_unit)
static bool is_cursor_visible(Scene *scene, ViewLayer *view_layer)
{
+ if (U.app_flag & USER_APP_VIEW3D_HIDE_CURSOR) {
+ return false;
+ }
+
Object *ob = OBACT(view_layer);
/* don't draw cursor in paint modes, but with a few exceptions */
@@ -1594,11 +1608,12 @@ static void UNUSED_FUNCTION(draw_rotation_guide)(RegionView3D *rv3d)
static void view3d_draw_border(const bContext *C, ARegion *ar)
{
Scene *scene = CTX_data_scene(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
RegionView3D *rv3d = ar->regiondata;
View3D *v3d = CTX_wm_view3d(C);
if (rv3d->persp == RV3D_CAMOB) {
- drawviewborder(scene, ar, v3d);
+ drawviewborder(scene, depsgraph, ar, v3d);
}
else if (v3d->flag2 & V3D_RENDER_BORDER) {
drawrenderborder(ar, v3d);
@@ -1966,7 +1981,7 @@ void ED_view3d_draw_offscreen(
float viewmat[4][4], float winmat[4][4],
bool do_bgpic, bool do_sky, bool is_persp, const char *viewname,
GPUFX *fx, GPUFXSettings *fx_settings,
- GPUOffScreen *ofs)
+ GPUOffScreen *ofs, GPUViewport *viewport)
{
bool do_compositing = false;
RegionView3D *rv3d = ar->regiondata;
@@ -2015,6 +2030,10 @@ void ED_view3d_draw_offscreen(
else
view3d_main_region_setup_view(eval_ctx, scene, v3d, ar, viewmat, winmat, NULL);
+ /* XXX, should take depsgraph as arg */
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
+ BLI_assert(depsgraph != NULL);
+
/* main drawing call */
RenderEngineType *engine_type = eval_ctx->engine_type;
if (engine_type->flag & RE_USE_LEGACY_PIPELINE) {
@@ -2049,7 +2068,7 @@ void ED_view3d_draw_offscreen(
if (v3d->flag2 & V3D_SHOW_GPENCIL) {
/* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
- ED_gpencil_draw_view3d(NULL, scene, view_layer, v3d, ar, false);
+ ED_gpencil_draw_view3d(NULL, scene, view_layer, depsgraph, v3d, ar, false);
}
/* freeing the images again here could be done after the operator runs, leaving for now */
@@ -2057,10 +2076,7 @@ void ED_view3d_draw_offscreen(
}
}
else {
- /* XXX, should take depsgraph as arg */
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false);
- BLI_assert(depsgraph != NULL);
- DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine_type, ar, v3d, ofs);
+ DRW_draw_render_loop_offscreen(depsgraph, eval_ctx->engine_type, ar, v3d, do_sky, ofs, viewport);
}
/* restore size */
@@ -2090,6 +2106,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
/* output vars */
GPUFX *fx, GPUOffScreen *ofs, char err_out[256])
{
+ const Depsgraph *depsgraph = eval_ctx->depsgraph;
RegionView3D *rv3d = ar->regiondata;
const bool draw_sky = (alpha_mode == R_ADDSKY);
const bool draw_background = (draw_flags & V3D_OFSDRAW_USE_BACKGROUND);
@@ -2109,7 +2126,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
if (own_ofs) {
/* bind */
- ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, false, err_out);
if (ofs == NULL) {
return NULL;
}
@@ -2145,7 +2162,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
rctf viewplane;
float clipsta, clipend;
- is_ortho = ED_view3d_viewplane_get(v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
+ is_ortho = ED_view3d_viewplane_get(depsgraph, v3d, rv3d, sizex, sizey, &viewplane, &clipsta, &clipend, NULL);
if (is_ortho) {
orthographic_m4(winmat, viewplane.xmin, viewplane.xmax, viewplane.ymin, viewplane.ymax, -clipend, clipend);
}
@@ -2159,7 +2176,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
ED_view3d_draw_offscreen(
eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat,
draw_background, draw_sky, !is_ortho, viewname,
- fx, &fx_settings, ofs);
+ fx, &fx_settings, ofs, NULL);
if (ibuf->rect_float) {
GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
@@ -2173,9 +2190,9 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
* Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
static float jit_ofs[32][2];
float winmat_jitter[4][4];
- /* use imbuf as temp storage, before writing into it from accumulation buffer */
- unsigned char *rect_temp = ibuf->rect ? (void *)ibuf->rect : (void *)ibuf->rect_float;
- unsigned int *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(int[4]), "accum1");
+ float *rect_temp = (ibuf->rect_float) ? ibuf->rect_float : MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp");
+ float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer");
+ GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs);
BLI_jitter_init(jit_ofs, samples);
@@ -2183,13 +2200,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
ED_view3d_draw_offscreen(
eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat,
draw_background, draw_sky, !is_ortho, viewname,
- fx, &fx_settings, ofs);
- GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
-
- unsigned i = sizex * sizey * 4;
- while (i--) {
- accum_buffer[i] = rect_temp[i];
- }
+ fx, &fx_settings, ofs, viewport);
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer);
/* skip the first sample */
for (int j = 1; j < samples; j++) {
@@ -2202,27 +2214,38 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(
ED_view3d_draw_offscreen(
eval_ctx, scene, view_layer, v3d, ar, sizex, sizey, NULL, winmat_jitter,
draw_background, draw_sky, !is_ortho, viewname,
- fx, &fx_settings, ofs);
- GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, rect_temp);
+ fx, &fx_settings, ofs, viewport);
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp);
- i = sizex * sizey * 4;
+ unsigned int i = sizex * sizey * 4;
while (i--) {
accum_buffer[i] += rect_temp[i];
}
}
+ {
+ /* don't free data owned by 'ofs' */
+ GPU_viewport_clear_from_offscreen(viewport);
+ GPU_viewport_free(viewport);
+ MEM_freeN(viewport);
+ }
+
+ if (ibuf->rect_float == NULL) {
+ MEM_freeN(rect_temp);
+ }
+
if (ibuf->rect_float) {
float *rect_float = ibuf->rect_float;
- i = sizex * sizey * 4;
+ unsigned int i = sizex * sizey * 4;
while (i--) {
- rect_float[i] = (float)(accum_buffer[i] / samples) * (1.0f / 255.0f);
+ rect_float[i] = accum_buffer[i] / samples;
}
}
else {
unsigned char *rect_ub = (unsigned char *)ibuf->rect;
- i = sizex * sizey * 4;
+ unsigned int i = sizex * sizey * 4;
while (i--) {
- rect_ub[i] = accum_buffer[i] / samples;
+ rect_ub[i] = (unsigned char)(255.0f * accum_buffer[i] / samples);
}
}
@@ -2383,9 +2406,9 @@ bool VP_legacy_use_depth(Scene *scene, View3D *v3d)
return use_depth_doit(scene, v3d);
}
-void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d)
+void VP_drawviewborder(Scene *scene, const struct Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
{
- drawviewborder(scene, ar, v3d);
+ drawviewborder(scene, depsgraph, ar, v3d);
}
void VP_drawrenderborder(ARegion *ar, View3D *v3d)
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index 84f0f96fe0b..7cb362ffb92 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -284,7 +284,7 @@ static void backdrawview3d(const struct EvaluationContext *eval_ctx, Scene *scen
}
if (!rv3d->gpuoffscreen) {
- rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, error);
+ rv3d->gpuoffscreen = GPU_offscreen_create(w, h, 0, false, error);
if (!rv3d->gpuoffscreen)
fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
@@ -530,7 +530,8 @@ static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, Ima
}
}
-static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
+static void view3d_draw_bgpic(Scene *scene, const Depsgraph *depsgraph,
+ ARegion *ar, View3D *v3d,
const bool do_foreground, const bool do_camera_frame)
{
RegionView3D *rv3d = ar->regiondata;
@@ -629,7 +630,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
{
if (do_camera_frame) {
rctf vb;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
x1 = vb.xmin;
y1 = vb.ymin;
x2 = vb.xmax;
@@ -773,8 +774,10 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
}
}
-void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame)
+void ED_view3d_draw_bgpic_test(
+ Scene *scene, const Depsgraph *depsgraph,
+ ARegion *ar, View3D *v3d,
+ const bool do_foreground, const bool do_camera_frame)
{
RegionView3D *rv3d = ar->regiondata;
@@ -797,11 +800,11 @@ void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
if ((rv3d->view == RV3D_VIEW_USER) || (rv3d->persp != RV3D_ORTHO)) {
if (rv3d->persp == RV3D_CAMOB) {
- view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
+ view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
}
}
else {
- view3d_draw_bgpic(scene, ar, v3d, do_foreground, do_camera_frame);
+ view3d_draw_bgpic(scene, depsgraph, ar, v3d, do_foreground, do_camera_frame);
}
}
@@ -1182,7 +1185,7 @@ void ED_view3d_draw_depth_gpencil(
glEnable(GL_DEPTH_TEST);
if (v3d->flag2 & V3D_SHOW_GPENCIL) {
- ED_gpencil_draw_view3d(NULL, scene, eval_ctx->view_layer, v3d, ar, true);
+ ED_gpencil_draw_view3d(NULL, scene, eval_ctx->view_layer, eval_ctx->depsgraph, v3d, ar, true);
}
v3d->zbuf = zbuf;
@@ -1423,7 +1426,7 @@ static void gpu_update_lamps_shadows_world(const EvaluationContext *eval_ctx, Sc
ED_view3d_draw_offscreen(
eval_ctx, scene, eval_ctx->view_layer, v3d, &ar, winsize, winsize, viewmat, winmat,
false, false, true,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL, NULL);
GPU_lamp_shadow_buffer_unbind(shadow->lamp);
v3d->drawtype = drawtype;
@@ -1500,6 +1503,7 @@ static void view3d_draw_objects(
const bool do_bgpic, const bool draw_offscreen, GPUFX *fx)
{
ViewLayer *view_layer = C ? CTX_data_view_layer(C) : BKE_view_layer_from_scene_get(scene);
+ Depsgraph *depsgraph = CTX_data_depsgraph(C);
RegionView3D *rv3d = ar->regiondata;
Base *base;
const bool do_camera_frame = !draw_offscreen;
@@ -1544,7 +1548,7 @@ static void view3d_draw_objects(
/* important to do before clipping */
if (do_bgpic) {
- view3d_draw_bgpic_test(scene, ar, v3d, false, do_camera_frame);
+ ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, false, do_camera_frame);
}
if (rv3d->rflag & RV3D_CLIPPING) {
@@ -1625,7 +1629,7 @@ static void view3d_draw_objects(
/* must be before xray draw which clears the depth buffer */
if (v3d->zbuf) glDisable(GL_DEPTH_TEST);
- ED_gpencil_draw_view3d(wm, scene, view_layer, v3d, ar, true);
+ ED_gpencil_draw_view3d(wm, scene, view_layer, depsgraph, v3d, ar, true);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
}
@@ -1654,7 +1658,7 @@ static void view3d_draw_objects(
/* important to do after clipping */
if (do_bgpic) {
- view3d_draw_bgpic_test(scene, ar, v3d, true, do_camera_frame);
+ ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, true, do_camera_frame);
}
/* cleanup */
@@ -1773,7 +1777,7 @@ static bool view3d_main_region_do_render_draw(const Scene *scene)
return (type && type->view_update && type->render_to_view);
}
-bool ED_view3d_calc_render_border(const Scene *scene, View3D *v3d, ARegion *ar, rcti *rect)
+bool ED_view3d_calc_render_border(const Scene *scene, const Depsgraph *depsgraph, View3D *v3d, ARegion *ar, rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
bool use_border;
@@ -1794,7 +1798,7 @@ bool ED_view3d_calc_render_border(const Scene *scene, View3D *v3d, ARegion *ar,
/* compute border */
if (rv3d->persp == RV3D_CAMOB) {
rctf viewborder;
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewborder, false);
rect->xmin = viewborder.xmin + scene->r.border.xmin * BLI_rctf_size_x(&viewborder);
rect->ymin = viewborder.ymin + scene->r.border.ymin * BLI_rctf_size_y(&viewborder);
@@ -1823,11 +1827,11 @@ static bool view3d_main_region_draw_engine(
ARegion *ar, View3D *v3d,
bool clip_border, const rcti *border_rect)
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
RegionView3D *rv3d = ar->regiondata;
RenderEngineType *type;
GLint scissor[4];
-
/* create render engine */
if (!rv3d->render_engine) {
RenderEngine *engine;
@@ -1872,7 +1876,7 @@ static bool view3d_main_region_draw_engine(
Camera *cam = ED_view3d_camera_data_get(v3d, rv3d);
if (cam->flag & CAM_SHOW_BG_IMAGE) {
show_image = true;
- view3d_draw_bgpic_test(scene, ar, v3d, false, true);
+ ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, false, true);
}
else {
imm_draw_box_checker_2d(0, 0, ar->winx, ar->winy);
@@ -1880,7 +1884,7 @@ static bool view3d_main_region_draw_engine(
}
if (show_image) {
- view3d_draw_bgpic_test(scene, ar, v3d, false, true);
+ ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, false, true);
}
else {
imm_draw_box_checker_2d(0, 0, ar->winx, ar->winy);
@@ -1891,7 +1895,7 @@ static bool view3d_main_region_draw_engine(
type->render_to_view(rv3d->render_engine, C);
if (show_image) {
- view3d_draw_bgpic_test(scene, ar, v3d, true, true);
+ ED_view3d_draw_bgpic_test(scene, depsgraph, ar, v3d, true, true);
}
if (clip_border) {
@@ -2007,11 +2011,6 @@ static void view3d_main_region_draw_objects(const bContext *C, Scene *scene, Vie
/* main drawing call */
view3d_draw_objects(C, &eval_ctx, scene, v3d, ar, grid_unit, true, false, do_compositing ? rv3d->compositor : NULL);
- /* draw depth culled manipulators - manipulators need to be updated *after* view matrix was set up */
- /* TODO depth culling manipulators is not yet supported, just drawing _3D here, should
- * later become _IN_SCENE (and draw _3D separate) */
- WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D);
-
/* post process */
if (do_compositing) {
GPU_fx_do_composite_pass(rv3d->compositor, rv3d->winmat, rv3d->is_persp, scene, NULL);
@@ -2038,6 +2037,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
ARegion *ar, View3D *v3d,
const char *grid_unit, bool render_border)
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
wmWindowManager *wm = CTX_wm_manager(C);
RegionView3D *rv3d = ar->regiondata;
@@ -2047,7 +2047,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
ED_region_visible_rect(ar, &rect);
if (rv3d->persp == RV3D_CAMOB) {
- VP_drawviewborder(scene, ar, v3d);
+ VP_drawviewborder(scene, CTX_data_depsgraph(C), ar, v3d);
}
else if (v3d->flag2 & V3D_RENDER_BORDER) {
VP_drawrenderborder(ar, v3d);
@@ -2055,7 +2055,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
if (v3d->flag2 & V3D_SHOW_GPENCIL) {
/* draw grease-pencil stuff - needed to get paint-buffer shown too (since it's 2D) */
- ED_gpencil_draw_view3d(wm, scene, view_layer, v3d, ar, false);
+ ED_gpencil_draw_view3d(wm, scene, view_layer, depsgraph, v3d, ar, false);
}
if ((v3d->flag2 & V3D_RENDER_OVERRIDE) == 0) {
@@ -2102,6 +2102,7 @@ static void view3d_main_region_draw_info(const bContext *C, Scene *scene,
void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar)
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
EvaluationContext eval_ctx;
Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
@@ -2111,7 +2112,7 @@ void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar)
/* if we only redraw render border area, skip opengl draw and also
* don't do scissor because it's already set */
- bool render_border = ED_view3d_calc_render_border(scene, v3d, ar, &border_rect);
+ bool render_border = ED_view3d_calc_render_border(scene, depsgraph, v3d, ar, &border_rect);
bool clip_border = (render_border && !BLI_rcti_compare(&ar->drawrct, &border_rect));
gpuPushProjectionMatrix();
@@ -2141,12 +2142,14 @@ void view3d_main_region_draw_legacy(const bContext *C, ARegion *ar)
VP_legacy_view3d_main_region_setup_view(&eval_ctx, scene, v3d, ar, NULL, NULL);
glClear(GL_DEPTH_BUFFER_BIT);
- ED_region_pixelspace(ar);
+ WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_3D);
- WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D);
+ ED_region_pixelspace(ar);
view3d_main_region_draw_info(C, scene, ar, v3d, grid_unit, render_border);
+ WM_manipulatormap_draw(ar->manipulator_map, C, WM_MANIPULATORMAP_DRAWSTEP_2D);
+
gpuPopProjectionMatrix();
gpuPopMatrix();
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 0dba87bef25..2457a890f71 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -26,6 +26,8 @@
/** \file blender/editors/space_view3d/view3d_edit.c
* \ingroup spview3d
+ *
+ * 3D view manipulation/operators.
*/
#include <string.h>
@@ -42,9 +44,7 @@
#include "MEM_guardedalloc.h"
-#include "BLI_bitmap_draw_2d.h"
#include "BLI_blenlib.h"
-#include "BLI_kdopbvh.h"
#include "BLI_math.h"
#include "BLI_utildefines.h"
@@ -63,7 +63,6 @@
#include "DEG_depsgraph.h"
-#include "BIF_gl.h"
#include "WM_api.h"
#include "WM_types.h"
@@ -73,499 +72,129 @@
#include "ED_armature.h"
#include "ED_particle.h"
-#include "ED_keyframing.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_mesh.h"
#include "ED_gpencil.h"
#include "ED_view3d.h"
-#include "DEG_depsgraph_query.h"
-
#include "UI_resources.h"
-#include "PIL_time.h" /* smoothview */
+#include "PIL_time.h"
#include "view3d_intern.h" /* own include */
-static bool view3d_ensure_persp(struct View3D *v3d, ARegion *ar);
-
-bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
-{
- return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
-}
-
-/* ********************** view3d_edit: view manipulations ********************* */
-
-/**
- * \return true when the view-port is locked to its camera.
- */
-bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
-{
- return ((v3d->camera) &&
- (!ID_IS_LINKED(v3d->camera)) &&
- (v3d->flag2 & V3D_LOCK_CAMERA) &&
- (rv3d->persp == RV3D_CAMOB));
-}
-
-/**
- * Apply the camera object transformation to the view-port.
- * (needed so we can use regular view-port manipulation operators, that sync back to the camera).
- */
-void ED_view3d_camera_lock_init_ex(View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
-{
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- if (calc_dist) {
- /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
- rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- }
- ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
- }
-}
-
-void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
-{
- ED_view3d_camera_lock_init_ex(v3d, rv3d, true);
-}
-
-/**
- * Apply the view-port transformation back to the camera object.
- *
- * \return true if the camera is moved.
- */
-bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
-{
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- ObjectTfmProtectedChannels obtfm;
- Object *root_parent;
-
- if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
- Object *ob_update;
- float tmat[4][4];
- float imat[4][4];
- float view_mat[4][4];
- float diff_mat[4][4];
- float parent_mat[4][4];
-
- while (root_parent->parent) {
- root_parent = root_parent->parent;
- }
-
- ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
-
- normalize_m4_m4(tmat, v3d->camera->obmat);
-
- invert_m4_m4(imat, tmat);
- mul_m4_m4m4(diff_mat, view_mat, imat);
-
- mul_m4_m4m4(parent_mat, diff_mat, root_parent->obmat);
-
- BKE_object_tfm_protected_backup(root_parent, &obtfm);
- BKE_object_apply_mat4(root_parent, parent_mat, true, false);
- BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag);
-
- ob_update = v3d->camera;
- while (ob_update) {
- DEG_id_tag_update(&ob_update->id, OB_RECALC_OB);
- WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update);
- ob_update = ob_update->parent;
- }
- }
- else {
- /* always maintain the same scale */
- const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ);
- BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
- ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
- BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all);
-
- DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
- WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
- }
-
- return true;
- }
- else {
- return false;
- }
-}
-
-bool ED_view3d_camera_autokey(
- Scene *scene, ID *id_key,
- struct bContext *C, const bool do_rotate, const bool do_translate)
-{
- if (autokeyframe_cfra_can_key(scene, id_key)) {
- const float cfra = (float)CFRA;
- ListBase dsources = {NULL, NULL};
-
- /* add data-source override for the camera object */
- ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
-
- /* insert keyframes
- * 1) on the first frame
- * 2) on each subsequent frame
- * TODO: need to check in future that frame changed before doing this
- */
- if (do_rotate) {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
- if (do_translate) {
- struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
- ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
- }
-
- /* free temp data */
- BLI_freelistN(&dsources);
-
- return true;
- }
- else {
- return false;
- }
-}
-
-/**
- * Call after modifying a locked view.
- *
- * \note Not every view edit currently auto-keys (numpad for eg),
- * this is complicated because of smoothview.
- */
-bool ED_view3d_camera_lock_autokey(
- View3D *v3d, RegionView3D *rv3d,
- struct bContext *C, const bool do_rotate, const bool do_translate)
-{
- /* similar to ED_view3d_cameracontrol_update */
- if (ED_view3d_camera_lock_check(v3d, rv3d)) {
- Scene *scene = CTX_data_scene(C);
- ID *id_key;
- Object *root_parent;
- if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
- while (root_parent->parent) {
- root_parent = root_parent->parent;
- }
- id_key = &root_parent->id;
- }
- else {
- id_key = &v3d->camera->id;
- }
-
- return ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate);
- }
- else {
- return false;
- }
-}
-
-/**
- * For viewport operators that exit camera persp.
- *
- * \note This differs from simply setting ``rv3d->persp = persp`` because it
- * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera,
- * otherwise switching out of camera view may jump to a different part of the scene.
- */
-static void view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp)
-{
- BLI_assert(rv3d->persp == RV3D_CAMOB);
- BLI_assert(persp != RV3D_CAMOB);
-
- if (v3d->camera) {
- rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
- ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
- }
-
- if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
- rv3d->persp = persp;
- }
-}
-
-/* ********************* box view support ***************** */
-
-static void view3d_boxview_clip(ScrArea *sa)
-{
- ARegion *ar;
- BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb");
- float clip[6][4];
- float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f};
- int val;
-
- /* create bounding box */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d->viewlock & RV3D_BOXCLIP) {
- if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
- if (ar->winx > ar->winy) x1 = rv3d->dist;
- else x1 = ar->winx * rv3d->dist / ar->winy;
-
- if (ar->winx > ar->winy) y1 = ar->winy * rv3d->dist / ar->winx;
- else y1 = rv3d->dist;
- copy_v2_v2(ofs, rv3d->ofs);
- }
- else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
- ofs[2] = rv3d->ofs[2];
-
- if (ar->winx > ar->winy) z1 = ar->winy * rv3d->dist / ar->winx;
- else z1 = rv3d->dist;
- }
- }
- }
- }
-
- for (val = 0; val < 8; val++) {
- if (ELEM(val, 0, 3, 4, 7))
- bb->vec[val][0] = -x1 - ofs[0];
- else
- bb->vec[val][0] = x1 - ofs[0];
-
- if (ELEM(val, 0, 1, 4, 5))
- bb->vec[val][1] = -y1 - ofs[1];
- else
- bb->vec[val][1] = y1 - ofs[1];
-
- if (val > 3)
- bb->vec[val][2] = -z1 - ofs[2];
- else
- bb->vec[val][2] = z1 - ofs[2];
- }
-
- /* normals for plane equations */
- normal_tri_v3(clip[0], bb->vec[0], bb->vec[1], bb->vec[4]);
- normal_tri_v3(clip[1], bb->vec[1], bb->vec[2], bb->vec[5]);
- normal_tri_v3(clip[2], bb->vec[2], bb->vec[3], bb->vec[6]);
- normal_tri_v3(clip[3], bb->vec[3], bb->vec[0], bb->vec[7]);
- normal_tri_v3(clip[4], bb->vec[4], bb->vec[5], bb->vec[6]);
- normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]);
-
- /* then plane equations */
- for (val = 0; val < 6; val++) {
- clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]);
- }
-
- /* create bounding box */
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3d = ar->regiondata;
-
- if (rv3d->viewlock & RV3D_BOXCLIP) {
- rv3d->rflag |= RV3D_CLIPPING;
- memcpy(rv3d->clip, clip, sizeof(clip));
- if (rv3d->clipbb) MEM_freeN(rv3d->clipbb);
- rv3d->clipbb = MEM_dupallocN(bb);
- }
- }
- }
- MEM_freeN(bb);
-}
-
-/**
- * Find which axis values are shared between both views and copy to \a rv3d_dst
- * taking axis flipping into account.
- */
-static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_src)
-{
- /* absolute axis values above this are considered to be set (will be ~1.0f) */
- const float axis_eps = 0.5f;
- float viewinv[4];
-
- /* use the view rotation to identify which axis to sync on */
- float view_axis_all[4][3] = {
- {1.0f, 0.0f, 0.0f},
- {0.0f, 1.0f, 0.0f},
- {1.0f, 0.0f, 0.0f},
- {0.0f, 1.0f, 0.0f}};
-
- float *view_src_x = &view_axis_all[0][0];
- float *view_src_y = &view_axis_all[1][0];
-
- float *view_dst_x = &view_axis_all[2][0];
- float *view_dst_y = &view_axis_all[3][0];
- int i;
-
-
- /* we could use rv3d->viewinv, but better not depend on view matrix being updated */
- if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) {
- return;
- }
- invert_qt_normalized(viewinv);
- mul_qt_v3(viewinv, view_src_x);
- mul_qt_v3(viewinv, view_src_y);
-
- if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) {
- return;
- }
- invert_qt_normalized(viewinv);
- mul_qt_v3(viewinv, view_dst_x);
- mul_qt_v3(viewinv, view_dst_y);
+/* -------------------------------------------------------------------- */
+/** \name Generic View Operator Properties
+ * \{ */
- /* check source and dest have a matching axis */
- for (i = 0; i < 3; i++) {
- if (((fabsf(view_src_x[i]) > axis_eps) || (fabsf(view_src_y[i]) > axis_eps)) &&
- ((fabsf(view_dst_x[i]) > axis_eps) || (fabsf(view_dst_y[i]) > axis_eps)))
- {
- rv3d_dst->ofs[i] = rv3d_src->ofs[i];
- }
- }
-}
+enum eV3D_OpPropFlag {
+ V3D_OP_PROP_MOUSE_CO = (1 << 0),
+ V3D_OP_PROP_DELTA = (1 << 1),
+ V3D_OP_PROP_USE_ALL_REGIONS = (1 << 2),
+ V3D_OP_PROP_USE_MOUSE_INIT = (1 << 3),
+};
-/* sync center/zoom view of region to others, for view transforms */
-static void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
+static void view3d_operator_properties_common(wmOperatorType *ot, const enum eV3D_OpPropFlag flag)
{
- ARegion *artest;
- RegionView3D *rv3d = ar->regiondata;
- short clip = 0;
-
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
- if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3dtest = artest->regiondata;
-
- if (rv3dtest->viewlock & RV3D_LOCKED) {
- rv3dtest->dist = rv3d->dist;
- view3d_boxview_sync_axis(rv3dtest, rv3d);
- clip |= rv3dtest->viewlock & RV3D_BOXCLIP;
-
- ED_region_tag_redraw(artest);
- }
- }
+ if (flag & V3D_OP_PROP_MOUSE_CO) {
+ PropertyRNA *prop;
+ prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Region Position X", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
+ prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Region Position Y", "", 0, INT_MAX);
+ RNA_def_property_flag(prop, PROP_HIDDEN);
}
-
- if (clip) {
- view3d_boxview_clip(sa);
+ if (flag & V3D_OP_PROP_DELTA) {
+ RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
}
-}
-
-/* for home, center etc */
-void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
-{
- ARegion *artest;
- RegionView3D *rv3d = ar->regiondata;
- bool clip = false;
-
- for (artest = sa->regionbase.first; artest; artest = artest->next) {
- if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
- RegionView3D *rv3dtest = artest->regiondata;
-
- if (rv3dtest->viewlock) {
- rv3dtest->dist = rv3d->dist;
- copy_v3_v3(rv3dtest->ofs, rv3d->ofs);
- ED_region_tag_redraw(artest);
-
- clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0);
- }
- }
+ if (flag & V3D_OP_PROP_USE_ALL_REGIONS) {
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-
- if (clip) {
- view3d_boxview_clip(sa);
+ if (flag & V3D_OP_PROP_USE_MOUSE_INIT) {
+ /* Disable when view operators are initialized from buttons. */
+ PropertyRNA *prop;
+ prop = RNA_def_boolean(ot->srna, "use_mouse_init", true, "Mouse Init", "Use initial mouse position");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE | PROP_HIDDEN);
}
}
-/* 'clip' is used to know if our clip setting has changed */
-void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
-{
- ARegion *ar_sync = NULL;
- RegionView3D *rv3d = ar->regiondata;
- short viewlock;
- /* this function copies flags from the first of the 3 other quadview
- * regions to the 2 other, so it assumes this is the region whose
- * properties are always being edited, weak */
- viewlock = rv3d->viewlock;
-
- if ((viewlock & RV3D_LOCKED) == 0) {
- do_clip = (viewlock & RV3D_BOXCLIP) != 0;
- viewlock = 0;
- }
- else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) {
- do_clip = true;
- viewlock &= ~RV3D_BOXCLIP;
- }
-
- for (; ar; ar = ar->prev) {
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- rv3d = ar->regiondata;
- rv3d->viewlock = viewlock;
-
- if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) {
- rv3d->rflag &= ~RV3D_BOXCLIP;
- }
-
- /* use ar_sync so we sync with one of the aligned views below
- * else the view jumps on changing view settings like 'clip'
- * since it copies from the perspective view */
- ar_sync = ar;
- }
- }
-
- if (rv3d->viewlock & RV3D_BOXVIEW) {
- view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
- }
-
- /* ensure locked regions have an axis, locked user views don't make much sense */
- if (viewlock & RV3D_LOCKED) {
- int index_qsplit = 0;
- for (ar = sa->regionbase.first; ar; ar = ar->next) {
- if (ar->alignment == RGN_ALIGN_QSPLIT) {
- rv3d = ar->regiondata;
- if (rv3d->viewlock) {
- if (!RV3D_VIEW_IS_AXIS(rv3d->view)) {
- rv3d->view = ED_view3d_lock_view_from_index(index_qsplit);
- rv3d->persp = RV3D_ORTHO;
- ED_view3d_lock(rv3d);
- }
- }
- index_qsplit++;
- }
- }
- }
-
- ED_area_tag_redraw(sa);
-}
+/** \} */
-/* ************************** init for view ops **********************************/
+/* -------------------------------------------------------------------- */
+/** \name Generic View Operator Custom-Data
+ * \{ */
typedef struct ViewOpsData {
- /* context pointers (assigned by viewops_data_alloc) */
+ /** Context pointers (assigned by #viewops_data_alloc). */
Scene *scene;
ScrArea *sa;
ARegion *ar;
View3D *v3d;
RegionView3D *rv3d;
+ Depsgraph *depsgraph;
- /* needed for continuous zoom */
+ /** Needed for continuous zoom. */
wmTimer *timer;
- double timer_lastdraw;
- float oldquat[4];
- float viewquat[4]; /* working copy of rv3d->viewquat */
- float trackvec[3];
- float mousevec[3]; /* dolly only */
+ /** Viewport state on initialization, don't change afterwards. */
+ struct {
+ float dist;
+ float camzoom;
+ float quat[4];
+ /** #wmEvent.x, y. */
+ int event_xy[2];
+ /** Offset to use when #VIEWOPS_FLAG_USE_MOUSE_INIT is not set.
+ * so we can simulate pressing in the middle of the screen. */
+ int event_xy_offset[2];
+ /** #wmEvent.type that triggered the operator. */
+ int event_type;
+ float ofs[3];
+ /** Initial distance to 'ofs'. */
+ float zfac;
+
+ /** Trackball rotation only. */
+ float trackvec[3];
+ /** Dolly only. */
+ float mousevec[3];
+ } init;
+
+ /** Previous state (previous modal event handled). */
+ struct {
+ int event_xy[2];
+ /** For operators that use time-steps (continuous zoom). */
+ double time;
+ } prev;
+
+ /** Current state. */
+ struct {
+ /** Working copy of #RegionView3D.viewquat, needed for rotation calculation
+ * so we can apply snap to the view-port while keeping the unsnapped rotation
+ * here to use when snap is disabled and for continued calculation. */
+ float viewquat[4];
+ } curr;
+
float reverse;
- float dist_prev, camzoom_prev;
- float grid, far;
bool axis_snap; /* view rotate only */
- float zfac;
- /* use for orbit selection and auto-dist */
- float ofs[3], dyn_ofs[3];
+ /** Use for orbit selection and auto-dist. */
+ float dyn_ofs[3];
bool use_dyn_ofs;
-
- int origx, origy, oldx, oldy;
- int origkey; /* the key that triggered the operator */
-
} ViewOpsData;
#define TRACKBALLSIZE (1.1f)
-static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
+static void calctrackballvec(const rcti *rect, const int event_xy[2], float vec[3])
{
const float radius = TRACKBALLSIZE;
const float t = radius / (float)M_SQRT2;
float x, y, z, d;
/* normalize x and y */
- x = BLI_rcti_cent_x(rect) - mx;
+ x = BLI_rcti_cent_x(rect) - event_xy[0];
x /= (float)(BLI_rcti_size_x(rect) / 4);
- y = BLI_rcti_cent_y(rect) - my;
+ y = BLI_rcti_cent_y(rect) - event_xy[1];
y /= (float)(BLI_rcti_size_y(rect) / 2);
d = sqrtf(x * x + y * y);
if (d < t) { /* Inside sphere */
@@ -580,13 +209,6 @@ static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
vec[2] = -z; /* yah yah! */
}
-
-/* -------------------------------------------------------------------- */
-/* ViewOpsData */
-
-/** \name Generic View Operator Custom-Data.
- * \{ */
-
/**
* Allocate and fill in context pointers for #ViewOpsData
*/
@@ -596,6 +218,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
/* store data */
op->customdata = vod;
+ vod->depsgraph = CTX_data_depsgraph(C);
vod->scene = CTX_data_scene(C);
vod->sa = CTX_wm_area(C);
vod->ar = CTX_wm_region(C);
@@ -604,7 +227,7 @@ static void viewops_data_alloc(bContext *C, wmOperator *op)
}
void view3d_orbit_apply_dyn_ofs(
- float r_ofs[3], const float ofs_old[3], const float viewquat_old[4],
+ float r_ofs[3], const float ofs_init[3], const float viewquat_old[4],
const float viewquat_new[4], const float dyn_ofs[3])
{
float q[4];
@@ -613,7 +236,7 @@ void view3d_orbit_apply_dyn_ofs(
invert_qt_normalized(q);
- sub_v3_v3v3(r_ofs, ofs_old, dyn_ofs);
+ sub_v3_v3v3(r_ofs, ofs_init, dyn_ofs);
mul_qt_v3(q, r_ofs);
add_v3_v3(r_ofs, dyn_ofs);
}
@@ -702,48 +325,58 @@ static bool view3d_orbit_calc_center(bContext *C, float r_dyn_ofs[3])
return is_set;
}
-enum eViewOpsOrbit {
- VIEWOPS_ORBIT_SELECT = (1 << 0),
- VIEWOPS_ORBIT_DEPTH = (1 << 1),
+enum eViewOpsFlag {
+ /** When enabled, rotate around the selection. */
+ VIEWOPS_FLAG_ORBIT_SELECT = (1 << 0),
+ /** When enabled, use the depth under the cursor for navigation. */
+ VIEWOPS_FLAG_DEPTH_NAVIGATE = (1 << 1),
+ /**
+ * When enabled run #ED_view3d_persp_ensure this may switch out of
+ * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
+ * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
+ * so we don't want it to trigger auto-perspective). */
+ VIEWOPS_FLAG_PERSP_ENSURE = (1 << 2),
+ /** When set, ignore any options that depend on initial cursor location. */
+ VIEWOPS_FLAG_USE_MOUSE_INIT = (1 << 3),
};
-static enum eViewOpsOrbit viewops_orbit_mode_ex(bool use_select, bool use_depth)
+static enum eViewOpsFlag viewops_flag_from_args(bool use_select, bool use_depth)
{
- enum eViewOpsOrbit flag = 0;
+ enum eViewOpsFlag flag = 0;
if (use_select) {
- flag |= VIEWOPS_ORBIT_SELECT;
+ flag |= VIEWOPS_FLAG_ORBIT_SELECT;
}
if (use_depth) {
- flag |= VIEWOPS_ORBIT_DEPTH;
+ flag |= VIEWOPS_FLAG_DEPTH_NAVIGATE;
}
return flag;
}
-static enum eViewOpsOrbit viewops_orbit_mode(void)
+static enum eViewOpsFlag viewops_flag_from_prefs(void)
{
- return viewops_orbit_mode_ex(
+ return viewops_flag_from_args(
(U.uiflag & USER_ORBIT_SELECTION) != 0,
- (U.uiflag & USER_ZBUF_ORBIT) != 0);
+ (U.uiflag & USER_DEPTH_NAVIGATE) != 0);
}
/**
* Calculate the values for #ViewOpsData
- *
- * \param use_ensure_persp: When enabled run #view3d_ensure_persp this may switch out of
- * camera view when orbiting or switch from ortho to perspective when auto-persp is enabled.
- * Some operations don't require this (view zoom/pan or ndof where subtle rotation is common
- * so we don't want it to trigger auto-perspective).
*/
-static void viewops_data_create_ex(
+static void viewops_data_create(
bContext *C, wmOperator *op, const wmEvent *event,
- bool use_ensure_persp, enum eViewOpsOrbit orbit_mode)
+ enum eViewOpsFlag viewops_flag)
{
ViewOpsData *vod = op->customdata;
RegionView3D *rv3d = vod->rv3d;
+ /* Could do this more nicely. */
+ if ((viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) == 0) {
+ viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
+ }
+
/* we need the depth info before changing any viewport options */
- if (orbit_mode & VIEWOPS_ORBIT_DEPTH) {
+ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
EvaluationContext eval_ctx;
struct Depsgraph *graph = CTX_data_depsgraph(C);
float fallback_depth_pt[3];
@@ -762,8 +395,8 @@ static void viewops_data_create_ex(
vod->use_dyn_ofs = false;
}
- if (use_ensure_persp) {
- if (view3d_ensure_persp(vod->v3d, vod->ar)) {
+ if (viewops_flag & VIEWOPS_FLAG_PERSP_ENSURE) {
+ if (ED_view3d_persp_ensure(vod->v3d, vod->ar)) {
/* If we're switching from camera view to the perspective one,
* need to tag viewport update, so camera vuew and borders
* are properly updated.
@@ -776,25 +409,37 @@ static void viewops_data_create_ex(
* we may want to make this optional but for now its needed always */
ED_view3d_camera_lock_init(vod->v3d, vod->rv3d);
- vod->dist_prev = rv3d->dist;
- vod->camzoom_prev = rv3d->camzoom;
- copy_qt_qt(vod->viewquat, rv3d->viewquat);
- copy_qt_qt(vod->oldquat, rv3d->viewquat);
- vod->origx = vod->oldx = event->x;
- vod->origy = vod->oldy = event->y;
- vod->origkey = event->type; /* the key that triggered the operator. */
- copy_v3_v3(vod->ofs, rv3d->ofs);
+ vod->init.dist = rv3d->dist;
+ vod->init.camzoom = rv3d->camzoom;
+ copy_qt_qt(vod->init.quat, rv3d->viewquat);
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = event->y;
+
+ if (viewops_flag & VIEWOPS_FLAG_USE_MOUSE_INIT) {
+ vod->init.event_xy_offset[0] = 0;
+ vod->init.event_xy_offset[1] = 0;
+ }
+ else {
+ /* Simulate the event starting in the middle of the region. */
+ vod->init.event_xy_offset[0] = BLI_rcti_cent_x(&vod->ar->winrct) - event->x;
+ vod->init.event_xy_offset[1] = BLI_rcti_cent_y(&vod->ar->winrct) - event->y;
+ }
- if (orbit_mode & VIEWOPS_ORBIT_SELECT) {
+ vod->init.event_type = event->type;
+ copy_v3_v3(vod->init.ofs, rv3d->ofs);
+
+ copy_qt_qt(vod->curr.viewquat, rv3d->viewquat);
+
+ if (viewops_flag & VIEWOPS_FLAG_ORBIT_SELECT) {
float ofs[3];
if (view3d_orbit_calc_center(C, ofs) || (vod->use_dyn_ofs == false)) {
vod->use_dyn_ofs = true;
negate_v3_v3(vod->dyn_ofs, ofs);
- orbit_mode &= ~VIEWOPS_ORBIT_DEPTH;
+ viewops_flag &= ~VIEWOPS_FLAG_DEPTH_NAVIGATE;
}
}
- if (orbit_mode & VIEWOPS_ORBIT_DEPTH) {
+ if (viewops_flag & VIEWOPS_FLAG_DEPTH_NAVIGATE) {
if (vod->use_dyn_ofs) {
if (rv3d->is_persp) {
float my_origin[3]; /* original G.vd->ofs */
@@ -821,7 +466,7 @@ static void viewops_data_create_ex(
/* find a new ofs value that is along the view axis (rather than the mouse location) */
closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin);
- vod->dist_prev = rv3d->dist = len_v3v3(my_pivot, dvec);
+ vod->init.dist = rv3d->dist = len_v3v3(my_pivot, dvec);
negate_v3_v3(rv3d->ofs, dvec);
}
@@ -834,27 +479,26 @@ static void viewops_data_create_ex(
negate_v3(rv3d->ofs);
}
negate_v3(vod->dyn_ofs);
- copy_v3_v3(vod->ofs, rv3d->ofs);
+ copy_v3_v3(vod->init.ofs, rv3d->ofs);
}
}
+ /* For dolly */
+ ED_view3d_win_to_vector(vod->ar, (const float[2]){UNPACK2(event->mval)}, vod->init.mousevec);
+
{
- /* for dolly */
- const float mval_f[2] = {(float)event->mval[0],
- (float)event->mval[1]};
- ED_view3d_win_to_vector(vod->ar, mval_f, vod->mousevec);
+ const int event_xy_offset[2] = {
+ event->x + vod->init.event_xy_offset[0],
+ event->y + vod->init.event_xy_offset[1],
+ };
+ /* For rotation with trackball rotation. */
+ calctrackballvec(&vod->ar->winrct, event_xy_offset, vod->init.trackvec);
}
- /* lookup, we don't pass on v3d to prevent confusement */
- vod->grid = vod->v3d->grid;
- vod->far = vod->v3d->far;
-
- calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec);
-
{
float tvec[3];
negate_v3_v3(tvec, rv3d->ofs);
- vod->zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ vod->init.zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
}
vod->reverse = 1.0f;
@@ -864,12 +508,6 @@ static void viewops_data_create_ex(
rv3d->rflag |= RV3D_NAVIGATING;
}
-static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event, bool use_ensure_persp)
-{
- enum eViewOpsOrbit orbit_mode = viewops_orbit_mode();
- viewops_data_create_ex(C, op, event, use_ensure_persp, orbit_mode);
-}
-
static void viewops_data_free(bContext *C, wmOperator *op)
{
ARegion *ar;
@@ -896,10 +534,12 @@ static void viewops_data_free(bContext *C, wmOperator *op)
#endif
ED_region_tag_redraw(ar);
}
-/** \} */
+/** \} */
-/* ************************** viewrotate **********************************/
+/* -------------------------------------------------------------------- */
+/** \name View Rotate Operator
+ * \{ */
enum {
VIEW_PASS = 0,
@@ -908,12 +548,14 @@ enum {
};
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
-#define VIEW_MODAL_CONFIRM 1 /* used for all view operations */
-#define VIEWROT_MODAL_AXIS_SNAP_ENABLE 2
-#define VIEWROT_MODAL_AXIS_SNAP_DISABLE 3
-#define VIEWROT_MODAL_SWITCH_ZOOM 4
-#define VIEWROT_MODAL_SWITCH_MOVE 5
-#define VIEWROT_MODAL_SWITCH_ROTATE 6
+enum {
+ VIEW_MODAL_CONFIRM = 1, /* used for all view operations */
+ VIEWROT_MODAL_AXIS_SNAP_ENABLE = 2,
+ VIEWROT_MODAL_AXIS_SNAP_DISABLE = 3,
+ VIEWROT_MODAL_SWITCH_ZOOM = 4,
+ VIEWROT_MODAL_SWITCH_MOVE = 5,
+ VIEWROT_MODAL_SWITCH_ROTATE = 6,
+};
/* called in transform_ops.c, on each regeneration of keymaps */
void viewrotate_modal_keymap(wmKeyConfig *keyconf)
@@ -923,7 +565,7 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf)
{VIEWROT_MODAL_AXIS_SNAP_ENABLE, "AXIS_SNAP_ENABLE", 0, "Enable Axis Snap", ""},
{VIEWROT_MODAL_AXIS_SNAP_DISABLE, "AXIS_SNAP_DISABLE", 0, "Disable Axis Snap", ""},
-
+
{VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
{VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
@@ -950,17 +592,16 @@ void viewrotate_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
#endif
-
+
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_rotate");
-
}
static void viewrotate_apply_dyn_ofs(ViewOpsData *vod, const float viewquat_new[4])
{
if (vod->use_dyn_ofs) {
RegionView3D *rv3d = vod->rv3d;
- view3d_orbit_apply_dyn_ofs(rv3d->ofs, vod->ofs, vod->oldquat, viewquat_new, vod->dyn_ofs);
+ view3d_orbit_apply_dyn_ofs(rv3d->ofs, vod->init.ofs, vod->init.quat, viewquat_new, vod->dyn_ofs);
}
}
@@ -976,7 +617,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
int x, y, z;
bool found = false;
- invert_qt_qt_normalized(viewquat_inv, vod->viewquat);
+ invert_qt_qt_normalized(viewquat_inv, vod->curr.viewquat);
mul_qt_v3(viewquat_inv, zaxis);
normalize_v3(zaxis);
@@ -1012,7 +653,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
* for testing roll */
rotation_between_vecs_to_quat(viewquat_align, zaxis_best, zaxis);
normalize_qt(viewquat_align);
- mul_qt_qtqt(viewquat_align, vod->viewquat, viewquat_align);
+ mul_qt_qtqt(viewquat_align, vod->curr.viewquat, viewquat_align);
normalize_qt(viewquat_align);
invert_qt_qt_normalized(viewquat_align_inv, viewquat_align);
@@ -1066,7 +707,7 @@ static void viewrotate_apply_snap(ViewOpsData *vod)
}
}
-static void viewrotate_apply(ViewOpsData *vod, int x, int y)
+static void viewrotate_apply(ViewOpsData *vod, const int event_xy[2])
{
RegionView3D *rv3d = vod->rv3d;
@@ -1076,9 +717,15 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
float axis[3], q1[4], dvec[3], newvec[3];
float angle;
- calctrackballvec(&vod->ar->winrct, x, y, newvec);
+ {
+ const int event_xy_offset[2] = {
+ event_xy[0] + vod->init.event_xy_offset[0],
+ event_xy[1] + vod->init.event_xy_offset[1],
+ };
+ calctrackballvec(&vod->ar->winrct, event_xy_offset, newvec);
+ }
- sub_v3_v3v3(dvec, newvec, vod->trackvec);
+ sub_v3_v3v3(dvec, newvec, vod->init.trackvec);
angle = (len_v3(dvec) / (2.0f * TRACKBALLSIZE)) * (float)M_PI;
@@ -1089,12 +736,12 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
* so that the angle of rotation is linearly proportional to
* the distance that the mouse is dragged. */
- cross_v3_v3v3(axis, vod->trackvec, newvec);
+ cross_v3_v3v3(axis, vod->init.trackvec, newvec);
axis_angle_to_quat(q1, axis, angle);
- mul_qt_qtqt(vod->viewquat, q1, vod->oldquat);
+ mul_qt_qtqt(vod->curr.viewquat, q1, vod->init.quat);
- viewrotate_apply_dyn_ofs(vod, vod->viewquat);
+ viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
}
else {
/* New turntable view code by John Aughey */
@@ -1111,7 +758,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
const float sensitivity = 0.007f;
/* Get the 3x3 matrix and its inverse from the quaternion */
- quat_to_mat3(m, vod->viewquat);
+ quat_to_mat3(m, vod->curr.viewquat);
invert_m3_m3(m_inv, m);
/* avoid gimble lock */
@@ -1138,30 +785,30 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
/* This can likely be computed directly from the quaternion. */
/* Perform the up/down rotation */
- axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(y - vod->oldy));
- mul_qt_qtqt(quat_local_x, vod->viewquat, quat_local_x);
+ axis_angle_to_quat(quat_local_x, xaxis, sensitivity * -(event_xy[1] - vod->prev.event_xy[1]));
+ mul_qt_qtqt(quat_local_x, vod->curr.viewquat, quat_local_x);
/* Perform the orbital rotation */
- axis_angle_to_quat_single(quat_global_z, 'Z', sensitivity * vod->reverse * (x - vod->oldx));
- mul_qt_qtqt(vod->viewquat, quat_local_x, quat_global_z);
+ axis_angle_to_quat_single(quat_global_z, 'Z', sensitivity * vod->reverse * (event_xy[0] - vod->prev.event_xy[0]));
+ mul_qt_qtqt(vod->curr.viewquat, quat_local_x, quat_global_z);
- viewrotate_apply_dyn_ofs(vod, vod->viewquat);
+ viewrotate_apply_dyn_ofs(vod, vod->curr.viewquat);
}
/* avoid precision loss over time */
- normalize_qt(vod->viewquat);
+ normalize_qt(vod->curr.viewquat);
/* use a working copy so view rotation locking doesnt overwrite the locked
* rotation back into the view we calculate with */
- copy_qt_qt(rv3d->viewquat, vod->viewquat);
+ copy_qt_qt(rv3d->viewquat, vod->curr.viewquat);
/* check for view snap,
* note: don't apply snap to vod->viewquat so the view wont jam up */
if (vod->axis_snap) {
viewrotate_apply_snap(vod);
}
- vod->oldx = x;
- vod->oldy = y;
+ vod->prev.event_xy[0] = event_xy[0];
+ vod->prev.event_xy[1] = event_xy[1];
ED_view3d_camera_lock_sync(vod->v3d, rv3d);
@@ -1202,12 +849,12 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
- viewrotate_apply(vod, event->x, event->y);
+ viewrotate_apply(vod, &event->x);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
@@ -1229,41 +876,12 @@ static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
return ret;
}
-/**
- * Action to take when rotating the view,
- * handle auto-persp and logic for switching out of views.
- *
- * shared with NDOF.
- */
-static bool view3d_ensure_persp(struct View3D *v3d, ARegion *ar)
-{
- RegionView3D *rv3d = ar->regiondata;
- const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
-
- BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
-
- if (ED_view3d_camera_lock_check(v3d, rv3d))
- return false;
-
- if (rv3d->persp != RV3D_PERSP) {
- if (rv3d->persp == RV3D_CAMOB) {
- /* If autopersp and previous view was an axis one, switch back to PERSP mode, else reuse previous mode. */
- char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp;
- view3d_persp_switch_from_camera(v3d, rv3d, persp);
- }
- else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
- rv3d->persp = RV3D_PERSP;
- }
- return true;
- }
-
- return false;
-}
-
static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
/* makes op->customdata */
viewops_data_alloc(C, op);
vod = op->customdata;
@@ -1276,29 +894,33 @@ static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
- viewops_data_create(C, op, event, true);
+ viewops_data_create(
+ C, op, event,
+ viewops_flag_from_prefs() |
+ VIEWOPS_FLAG_PERSP_ENSURE |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
if (ELEM(event->type, MOUSEPAN, MOUSEROTATE)) {
/* Rotate direction we keep always same */
- int x, y;
+ int event_xy[2];
if (event->type == MOUSEPAN) {
if (U.uiflag2 & USER_TRACKPAD_NATURAL) {
- x = 2 * event->x - event->prevx;
- y = 2 * event->y - event->prevy;
+ event_xy[0] = 2 * event->x - event->prevx;
+ event_xy[1] = 2 * event->y - event->prevy;
}
else {
- x = event->prevx;
- y = event->prevy;
+ event_xy[0] = event->prevx;
+ event_xy[1] = event->prevy;
}
}
else {
/* MOUSEROTATE performs orbital rotation, so y axis delta is set to 0 */
- x = event->prevx;
- y = event->y;
+ event_xy[0] = event->prevx;
+ event_xy[1] = event->y;
}
- viewrotate_apply(vod, x, y);
+ viewrotate_apply(vod, event_xy);
ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -1361,13 +983,17 @@ void VIEW3D_OT_rotate(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
}
-#ifdef WITH_INPUT_NDOF
+/** \} */
+/* -------------------------------------------------------------------- */
/** \name NDOF Utility Functions
* \{ */
+#ifdef WITH_INPUT_NDOF
#define NDOF_HAS_TRANSLATE ((!ED_view3d_offset_lock_check(v3d, rv3d)) && !is_zero_v3(ndof->tvec))
#define NDOF_HAS_ROTATE (((rv3d->viewlock & RV3D_LOCKED) == 0) && !is_zero_v3(ndof->rvec))
@@ -1417,8 +1043,9 @@ static float view3d_ndof_pan_speed_calc(RegionView3D *rv3d)
*
* \param has_zoom zoom, otherwise dolly, often `!rv3d->is_persp` since it doesnt make sense to dolly in ortho.
*/
-static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
- const bool has_translate, const bool has_zoom)
+static void view3d_ndof_pan_zoom(
+ const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
+ const bool has_translate, const bool has_zoom)
{
RegionView3D *rv3d = ar->regiondata;
float view_inv[4];
@@ -1479,9 +1106,10 @@ static void view3d_ndof_pan_zoom(const struct wmNDOFMotionData *ndof, ScrArea *s
}
-static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
- /* optional, can be NULL*/
- ViewOpsData *vod)
+static void view3d_ndof_orbit(
+ const struct wmNDOFMotionData *ndof, ScrArea *sa, ARegion *ar,
+ /* optional, can be NULL*/
+ ViewOpsData *vod)
{
View3D *v3d = sa->spacedata.first;
RegionView3D *rv3d = ar->regiondata;
@@ -1490,7 +1118,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa,
BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
- view3d_ensure_persp(v3d, ar);
+ ED_view3d_persp_ensure(v3d, ar);
rv3d->view = RV3D_VIEW_USER;
@@ -1525,7 +1153,6 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, ScrArea *sa,
axis_angle_to_quat_single(quat, 'Z', angle);
mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, quat);
-
}
else {
float quat[4];
@@ -1666,14 +1293,16 @@ void view3d_ndof_fly(
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name NDOF Operators
+ *
+ * - "orbit" navigation (trackball/turntable)
+ * - zooming
+ * - panning in rotationally-locked views
+ * \{ */
-/* -- "orbit" navigation (trackball/turntable)
- * -- zooming
- * -- panning in rotationally-locked views
- */
static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
-
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
@@ -1685,9 +1314,9 @@ static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
const wmNDOFMotionData *ndof = event->customdata;
viewops_data_alloc(C, op);
- viewops_data_create_ex(
+ viewops_data_create(
C, op, event,
- false, viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
+ viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -1742,7 +1371,6 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
-
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
}
@@ -1754,9 +1382,9 @@ static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *ev
const wmNDOFMotionData *ndof = event->customdata;
viewops_data_alloc(C, op);
- viewops_data_create_ex(
+ viewops_data_create(
C, op, event,
- false, viewops_orbit_mode_ex((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
+ viewops_flag_from_args((U.uiflag & USER_ORBIT_SELECTION) != 0, false));
vod = op->customdata;
@@ -1934,8 +1562,11 @@ void VIEW3D_OT_ndof_all(struct wmOperatorType *ot)
#endif /* WITH_INPUT_NDOF */
-/* ************************ viewmove ******************************** */
+/** \} */
+/* -------------------------------------------------------------------- */
+/** \name View Move (Pan) Operator
+ * \{ */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
@@ -1944,7 +1575,7 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
{
static const EnumPropertyItem modal_items[] = {
{VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
+
{VIEWROT_MODAL_SWITCH_ZOOM, "SWITCH_TO_ZOOM", 0, "Switch to Zoom"},
{VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
@@ -1968,7 +1599,7 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ZOOM);
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
#endif
-
+
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_move");
}
@@ -1977,13 +1608,13 @@ void viewmove_modal_keymap(wmKeyConfig *keyconf)
static void viewmove_apply(ViewOpsData *vod, int x, int y)
{
if (ED_view3d_offset_lock_check(vod->v3d, vod->rv3d)) {
- vod->rv3d->ofs_lock[0] -= ((vod->oldx - x) * 2.0f) / (float)vod->ar->winx;
- vod->rv3d->ofs_lock[1] -= ((vod->oldy - y) * 2.0f) / (float)vod->ar->winy;
+ vod->rv3d->ofs_lock[0] -= ((vod->prev.event_xy[0] - x) * 2.0f) / (float)vod->ar->winx;
+ vod->rv3d->ofs_lock[1] -= ((vod->prev.event_xy[1] - y) * 2.0f) / (float)vod->ar->winy;
}
else if ((vod->rv3d->persp == RV3D_CAMOB) && !ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) {
const float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
- vod->rv3d->camdx += (vod->oldx - x) / (vod->ar->winx * zoomfac);
- vod->rv3d->camdy += (vod->oldy - y) / (vod->ar->winy * zoomfac);
+ vod->rv3d->camdx += (vod->prev.event_xy[0] - x) / (vod->ar->winx * zoomfac);
+ vod->rv3d->camdy += (vod->prev.event_xy[1] - y) / (vod->ar->winy * zoomfac);
CLAMP(vod->rv3d->camdx, -1.0f, 1.0f);
CLAMP(vod->rv3d->camdy, -1.0f, 1.0f);
}
@@ -1991,18 +1622,19 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
float dvec[3];
float mval_f[2];
- mval_f[0] = x - vod->oldx;
- mval_f[1] = y - vod->oldy;
- ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->zfac);
+ mval_f[0] = x - vod->prev.event_xy[0];
+ mval_f[1] = y - vod->prev.event_xy[1];
+ ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->init.zfac);
add_v3_v3(vod->rv3d->ofs, dvec);
- if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
+ }
}
- vod->oldx = x;
- vod->oldy = y;
+ vod->prev.event_xy[0] = x;
+ vod->prev.event_xy[1] = y;
ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
@@ -2037,7 +1669,7 @@ static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
@@ -2068,9 +1700,14 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, false);
+ viewops_data_create(
+ C, op, event,
+ viewops_flag_from_prefs() |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -2079,9 +1716,9 @@ static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
/* invert it, trackpad scroll follows same principle as 2d windows this way */
viewmove_apply(vod, 2 * event->x - event->prevx, 2 * event->y - event->prevy);
ED_view3d_depth_tag_update(vod->rv3d);
-
+
viewops_data_free(C, op);
-
+
return OPERATOR_FINISHED;
}
else {
@@ -2113,9 +1750,16 @@ void VIEW3D_OT_move(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
+
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_MOUSE_INIT);
}
-/* ************************ viewzoom ******************************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Zoom Operator
+ * \{ */
/* viewdolly_modal_keymap has an exact copy of this, apply fixes to both */
/* called in transform_ops.c, on each regeneration of keymaps */
@@ -2123,7 +1767,7 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
{
static const EnumPropertyItem modal_items[] = {
{VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
+
{VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
{VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
@@ -2147,14 +1791,17 @@ void viewzoom_modal_keymap(wmKeyConfig *keyconf)
WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
#endif
-
+
/* assign map to operators */
WM_modalkeymap_assign(keymap, "VIEW3D_OT_zoom");
}
-static void view_zoom_mouseloc_camera(
- Scene *scene, View3D *v3d,
- ARegion *ar, float dfac, int mx, int my)
+/**
+ * \param zoom_xy: Optionally zoom to window location (coords compatible w/ #wmEvent.x, y). Use when not NULL.
+ */
+static void view_zoom_to_window_xy_camera(
+ Scene *scene, const Depsgraph *depsgraph, View3D *v3d,
+ ARegion *ar, float dfac, const int zoom_xy[2])
{
RegionView3D *rv3d = ar->regiondata;
const float zoomfac = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom);
@@ -2162,22 +1809,22 @@ static void view_zoom_mouseloc_camera(
const float camzoom_new = BKE_screen_view3d_zoom_from_fac(zoomfac_new);
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ if (zoom_xy != NULL) {
float zoomfac_px;
rctf camera_frame_old;
rctf camera_frame_new;
- const float pt_src[2] = {mx, my};
+ const float pt_src[2] = {zoom_xy[0], zoom_xy[1]};
float pt_dst[2];
float delta_px[2];
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_old, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_old, false);
BLI_rctf_translate(&camera_frame_old, ar->winrct.xmin, ar->winrct.ymin);
rv3d->camzoom = camzoom_new;
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &camera_frame_new, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &camera_frame_new, false);
BLI_rctf_translate(&camera_frame_new, ar->winrct.xmin, ar->winrct.ymin);
BLI_rctf_transform_pt_v(&camera_frame_new, &camera_frame_old, pt_dst, pt_src);
@@ -2198,12 +1845,15 @@ static void view_zoom_mouseloc_camera(
}
}
-static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my)
+/**
+ * \param zoom_xy: Optionally zoom to window location (coords compatible w/ #wmEvent.x, y). Use when not NULL.
+ */
+static void view_zoom_to_window_xy_3d(ARegion *ar, float dfac, const int zoom_xy[2])
{
RegionView3D *rv3d = ar->regiondata;
const float dist_new = rv3d->dist * dfac;
- if (U.uiflag & USER_ZOOM_TO_MOUSEPOS) {
+ if (zoom_xy != NULL) {
float dvec[3];
float tvec[3];
float tpos[3];
@@ -2213,8 +1863,8 @@ static void view_zoom_mouseloc_3d(ARegion *ar, float dfac, int mx, int my)
negate_v3_v3(tpos, rv3d->ofs);
- mval_f[0] = (float)(((mx - ar->winrct.xmin) * 2) - ar->winx) / 2.0f;
- mval_f[1] = (float)(((my - ar->winrct.ymin) * 2) - ar->winy) / 2.0f;
+ mval_f[0] = (float)(((zoom_xy[0] - ar->winrct.xmin) * 2) - ar->winx) / 2.0f;
+ mval_f[1] = (float)(((zoom_xy[1] - ar->winrct.ymin) * 2) - ar->winy) / 2.0f;
/* Project cursor position into 3D space */
zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
@@ -2240,7 +1890,7 @@ static float viewzoom_scale_value(
const rcti *winrct,
const short viewzoom,
const bool zoom_invert, const bool zoom_invert_force,
- const int xy[2], const int xy_orig[2],
+ const int xy_curr[2], const int xy_init[2],
const float val, const float val_orig,
double *r_timer_lastdraw)
{
@@ -2252,10 +1902,10 @@ static float viewzoom_scale_value(
float fac;
if (U.uiflag & USER_ZOOM_HORIZ) {
- fac = (float)(xy_orig[0] - xy[0]);
+ fac = (float)(xy_init[0] - xy_curr[0]);
}
else {
- fac = (float)(xy_orig[1] - xy[1]);
+ fac = (float)(xy_init[1] - xy_curr[1]);
}
if (zoom_invert != zoom_invert_force) {
@@ -2273,8 +1923,8 @@ static float viewzoom_scale_value(
BLI_rcti_cent_x(winrct),
BLI_rcti_cent_y(winrct),
};
- float len_new = 5 + len_v2v2_int(ctr, xy);
- float len_old = 5 + len_v2v2_int(ctr, xy_orig);
+ float len_new = 5 + len_v2v2_int(ctr, xy_curr);
+ float len_old = 5 + len_v2v2_int(ctr, xy_init);
/* intentionally ignore 'zoom_invert' for scale */
if (zoom_invert_force) {
@@ -2288,12 +1938,12 @@ static float viewzoom_scale_value(
float len_old = 5;
if (U.uiflag & USER_ZOOM_HORIZ) {
- len_new += (winrct->xmax - xy[0]);
- len_old += (winrct->xmax - xy_orig[0]);
+ len_new += (winrct->xmax - (xy_curr[0]));
+ len_old += (winrct->xmax - (xy_init[0]));
}
else {
- len_new += (winrct->ymax - xy[1]);
- len_old += (winrct->ymax - xy_orig[1]);
+ len_new += (winrct->ymax - (xy_curr[1]));
+ len_old += (winrct->ymax - (xy_init[1]));
}
if (zoom_invert != zoom_invert_force) {
@@ -2307,25 +1957,48 @@ static float viewzoom_scale_value(
return zfac;
}
+static float viewzoom_scale_value_offset(
+ const rcti *winrct,
+ const short viewzoom,
+ const bool zoom_invert, const bool zoom_invert_force,
+ const int xy_curr[2], const int xy_init[2], const int xy_offset[2],
+ const float val, const float val_orig,
+ double *r_timer_lastdraw)
+{
+ const int xy_curr_offset[2] = {
+ xy_curr[0] + xy_offset[0],
+ xy_curr[1] + xy_offset[1],
+ };
+ const int xy_init_offset[2] = {
+ xy_init[0] + xy_offset[0],
+ xy_init[1] + xy_offset[1],
+ };
+ return viewzoom_scale_value(
+ winrct, viewzoom, zoom_invert, zoom_invert_force,
+ xy_curr_offset, xy_init_offset,
+ val, val_orig, r_timer_lastdraw);
+}
+
static void viewzoom_apply_camera(
ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert)
+ const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
{
float zfac;
- float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->camzoom_prev) * 2.0f;
+ float zoomfac_prev = BKE_screen_view3d_zoom_to_fac(vod->init.camzoom) * 2.0f;
float zoomfac = BKE_screen_view3d_zoom_to_fac(vod->rv3d->camzoom) * 2.0f;
- zfac = viewzoom_scale_value(
- &vod->ar->winrct, viewzoom, zoom_invert, true, xy, &vod->origx,
+ zfac = viewzoom_scale_value_offset(
+ &vod->ar->winrct, viewzoom, zoom_invert, true,
+ xy, vod->init.event_xy, vod->init.event_xy_offset,
zoomfac, zoomfac_prev,
- &vod->timer_lastdraw);
+ &vod->prev.time);
if (zfac != 1.0f && zfac != 0.0f) {
/* calculate inverted, then invert again (needed because of camera zoom scaling) */
zfac = 1.0f / zfac;
- view_zoom_mouseloc_camera(
- vod->scene, vod->v3d,
- vod->ar, zfac, vod->oldx, vod->oldy);
+ view_zoom_to_window_xy_camera(
+ vod->scene, vod->depsgraph, vod->v3d,
+ vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
}
ED_region_tag_redraw(vod->ar);
@@ -2333,32 +2006,34 @@ static void viewzoom_apply_camera(
static void viewzoom_apply_3d(
ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert)
+ const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
{
float zfac;
float dist_range[2];
ED_view3d_dist_range_get(vod->v3d, dist_range);
- zfac = viewzoom_scale_value(
- &vod->ar->winrct, viewzoom, zoom_invert, false, xy, &vod->origx,
- vod->rv3d->dist, vod->dist_prev,
- &vod->timer_lastdraw);
+ zfac = viewzoom_scale_value_offset(
+ &vod->ar->winrct, viewzoom, zoom_invert, false,
+ xy, vod->init.event_xy, vod->init.event_xy_offset,
+ vod->rv3d->dist, vod->init.dist,
+ &vod->prev.time);
if (zfac != 1.0f) {
const float zfac_min = dist_range[0] / vod->rv3d->dist;
const float zfac_max = dist_range[1] / vod->rv3d->dist;
CLAMP(zfac, zfac_min, zfac_max);
- view_zoom_mouseloc_3d(
- vod->ar, zfac, vod->oldx, vod->oldy);
+ view_zoom_to_window_xy_3d(
+ vod->ar, zfac, zoom_to_pos ? vod->prev.event_xy : NULL);
}
/* these limits were in old code too */
CLAMP(vod->rv3d->dist, dist_range[0], dist_range[1]);
- if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
+ }
ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
@@ -2367,15 +2042,15 @@ static void viewzoom_apply_3d(
static void viewzoom_apply(
ViewOpsData *vod, const int xy[2],
- const short viewzoom, const bool zoom_invert)
+ const short viewzoom, const bool zoom_invert, const bool zoom_to_pos)
{
if ((vod->rv3d->persp == RV3D_CAMOB) &&
(vod->rv3d->is_persp && ED_view3d_camera_lock_check(vod->v3d, vod->rv3d)) == 0)
{
- viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert);
+ viewzoom_apply_camera(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
}
else {
- viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert);
+ viewzoom_apply_3d(vod, xy, viewzoom, zoom_invert, zoom_to_pos);
}
}
@@ -2409,12 +2084,16 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
- viewzoom_apply(vod, &event->x, U.viewzoom, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+ viewzoom_apply(
+ vod, &event->x, U.viewzoom,
+ (U.uiflag & USER_ZOOM_INVERT) != 0,
+ (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) ? vod->prev.event_xy : NULL);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
@@ -2438,6 +2117,7 @@ static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
static int viewzoom_exec(bContext *C, wmOperator *op)
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d;
RegionView3D *rv3d;
@@ -2447,7 +2127,7 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
float dist_range[2];
const int delta = RNA_int_get(op->ptr, "delta");
- int mx, my;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
if (op->customdata) {
ViewOpsData *vod = op->customdata;
@@ -2463,39 +2143,46 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
v3d = sa->spacedata.first;
rv3d = ar->regiondata;
- mx = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : ar->winx / 2;
- my = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2;
use_cam_zoom = (rv3d->persp == RV3D_CAMOB) && !(rv3d->is_persp && ED_view3d_camera_lock_check(v3d, rv3d));
+ int zoom_xy_buf[2];
+ const int *zoom_xy = NULL;
+ if (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) {
+ zoom_xy_buf[0] = RNA_struct_property_is_set(op->ptr, "mx") ? RNA_int_get(op->ptr, "mx") : ar->winx / 2;
+ zoom_xy_buf[1] = RNA_struct_property_is_set(op->ptr, "my") ? RNA_int_get(op->ptr, "my") : ar->winy / 2;
+ zoom_xy = zoom_xy_buf;
+ }
+
ED_view3d_dist_range_get(v3d, dist_range);
if (delta < 0) {
const float step = 1.2f;
/* this min and max is also in viewmove() */
if (use_cam_zoom) {
- view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my);
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
}
else {
if (rv3d->dist < dist_range[1]) {
- view_zoom_mouseloc_3d(ar, step, mx, my);
+ view_zoom_to_window_xy_3d(ar, step, zoom_xy);
}
}
}
else {
const float step = 1.0f / 1.2f;
if (use_cam_zoom) {
- view_zoom_mouseloc_camera(scene, v3d, ar, step, mx, my);
+ view_zoom_to_window_xy_camera(scene, depsgraph, v3d, ar, step, zoom_xy);
}
else {
if (rv3d->dist > dist_range[0]) {
- view_zoom_mouseloc_3d(ar, step, mx, my);
+ view_zoom_to_window_xy_3d(ar, step, zoom_xy);
}
}
}
- if (rv3d->viewlock & RV3D_BOXVIEW)
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(sa, ar);
+ }
ED_view3d_depth_tag_update(rv3d);
@@ -2509,49 +2196,19 @@ static int viewzoom_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-/* this is an exact copy of viewzoom_modal_keymap */
-/* called in transform_ops.c, on each regeneration of keymaps */
-void viewdolly_modal_keymap(wmKeyConfig *keyconf)
-{
- static const EnumPropertyItem modal_items[] = {
- {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
-
- {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
- {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
-
- {0, NULL, 0, NULL, NULL}
- };
-
- wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal");
-
- /* this function is called for each spacetype, only needs to add map once */
- if (keymap && keymap->modal_items) return;
-
- keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items);
-
- /* items for modal map */
- WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
- WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
-
- /* disabled mode switching for now, can re-implement better, later on */
-#if 0
- WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
- WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
-#endif
-
- /* assign map to operators */
- WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
-}
-
/* viewdolly_invoke() copied this function, changes here may apply there */
static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, false);
+ viewops_data_create(
+ C, op, event,
+ viewops_flag_from_prefs() |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
@@ -2569,14 +2226,16 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (event->type == MOUSEZOOM || event->type == MOUSEPAN) {
if (U.uiflag & USER_ZOOM_HORIZ) {
- vod->origx = vod->oldx = event->x;
- viewzoom_apply(vod, &event->prevx, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
}
else {
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
- vod->origy = vod->oldy = vod->origy + event->x - event->prevx;
- viewzoom_apply(vod, &event->prevx, USER_ZOOM_DOLLY, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - event->prevx;
}
+ viewzoom_apply(
+ vod, &event->prevx, USER_ZOOM_DOLLY,
+ (U.uiflag & USER_ZOOM_INVERT) != 0,
+ (use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)));
ED_view3d_camera_lock_autokey(vod->v3d, vod->rv3d, C, false, true);
ED_view3d_depth_tag_update(vod->rv3d);
@@ -2588,7 +2247,7 @@ static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (U.viewzoom == USER_ZOOM_CONT) {
/* needs a timer to continue redrawing */
vod->timer = WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f);
- vod->timer_lastdraw = PIL_check_seconds_timer();
+ vod->prev.time = PIL_check_seconds_timer();
}
/* add temp handler */
@@ -2607,8 +2266,6 @@ static void viewzoom_cancel(bContext *C, wmOperator *op)
void VIEW3D_OT_zoom(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "Zoom View";
ot->description = "Zoom in/out in the view";
@@ -2624,15 +2281,56 @@ void VIEW3D_OT_zoom(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
- prop = RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
- prop = RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
+ /* properties */
+ view3d_operator_properties_common(
+ ot,
+ V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Dolly Operator
+ *
+ * Like zoom but translates the view offset along the view direction
+ * which avoids #RegionView3D.dist approaching zero.
+ * \{ */
+
+/* this is an exact copy of viewzoom_modal_keymap */
+/* called in transform_ops.c, on each regeneration of keymaps */
+void viewdolly_modal_keymap(wmKeyConfig *keyconf)
+{
+ static const EnumPropertyItem modal_items[] = {
+ {VIEW_MODAL_CONFIRM, "CONFIRM", 0, "Confirm", ""},
+
+ {VIEWROT_MODAL_SWITCH_ROTATE, "SWITCH_TO_ROTATE", 0, "Switch to Rotate"},
+ {VIEWROT_MODAL_SWITCH_MOVE, "SWITCH_TO_MOVE", 0, "Switch to Move"},
+
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ wmKeyMap *keymap = WM_modalkeymap_get(keyconf, "View3D Dolly Modal");
+
+ /* this function is called for each spacetype, only needs to add map once */
+ if (keymap && keymap->modal_items) return;
+
+ keymap = WM_modalkeymap_add(keyconf, "View3D Dolly Modal", modal_items);
+
+ /* items for modal map */
+ WM_modalkeymap_add_item(keymap, MIDDLEMOUSE, KM_RELEASE, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+ WM_modalkeymap_add_item(keymap, ESCKEY, KM_PRESS, KM_ANY, 0, VIEW_MODAL_CONFIRM);
+
+ /* disabled mode switching for now, can re-implement better, later on */
+#if 0
+ WM_modalkeymap_add_item(keymap, LEFTMOUSE, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTCTRLKEY, KM_RELEASE, KM_ANY, 0, VIEWROT_MODAL_SWITCH_ROTATE);
+ WM_modalkeymap_add_item(keymap, LEFTSHIFTKEY, KM_PRESS, KM_ANY, 0, VIEWROT_MODAL_SWITCH_MOVE);
+#endif
+
+ /* assign map to operators */
+ WM_modalkeymap_assign(keymap, "VIEW3D_OT_dolly");
+}
-/* ************************ viewdolly ******************************** */
static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
@@ -2646,13 +2344,13 @@ static bool viewdolly_offset_lock_check(bContext *C, wmOperator *op)
}
}
-static void view_dolly_mouseloc(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
+static void view_dolly_to_vector_3d(ARegion *ar, float orig_ofs[3], float dvec[3], float dfac)
{
RegionView3D *rv3d = ar->regiondata;
madd_v3_v3v3fl(rv3d->ofs, orig_ofs, dvec, -(1.0f - dfac));
}
-static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_invert)
+static void viewdolly_apply(ViewOpsData *vod, const int xy[2], const short zoom_invert)
{
float zfac = 1.0;
@@ -2660,24 +2358,27 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv
float len1, len2;
if (U.uiflag & USER_ZOOM_HORIZ) {
- len1 = (vod->ar->winrct.xmax - x) + 5;
- len2 = (vod->ar->winrct.xmax - vod->origx) + 5;
+ len1 = (vod->ar->winrct.xmax - xy[0]) + 5;
+ len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) + 5;
}
else {
- len1 = (vod->ar->winrct.ymax - y) + 5;
- len2 = (vod->ar->winrct.ymax - vod->origy) + 5;
+ len1 = (vod->ar->winrct.ymax - xy[1]) + 5;
+ len2 = (vod->ar->winrct.ymax - vod->init.event_xy[1]) + 5;
}
- if (zoom_invert)
+ if (zoom_invert) {
SWAP(float, len1, len2);
+ }
zfac = 1.0f + ((len1 - len2) * 0.01f * vod->rv3d->dist);
}
- if (zfac != 1.0f)
- view_dolly_mouseloc(vod->ar, vod->ofs, vod->mousevec, zfac);
+ if (zfac != 1.0f) {
+ view_dolly_to_vector_3d(vod->ar, vod->init.ofs, vod->init.mousevec, zfac);
+ }
- if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
+ }
ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
@@ -2711,12 +2412,12 @@ static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
if (event_code == VIEW_APPLY) {
- viewdolly_apply(vod, event->x, event->y, (U.uiflag & USER_ZOOM_INVERT) != 0);
+ viewdolly_apply(vod, &event->x, (U.uiflag & USER_ZOOM_INVERT) != 0);
if (ED_screen_animation_playing(CTX_wm_manager(C))) {
use_autokey = true;
}
@@ -2753,7 +2454,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
sa = vod->sa;
ar = vod->ar;
- copy_v3_v3(mousevec, vod->mousevec);
+ copy_v3_v3(mousevec, vod->init.mousevec);
}
else {
sa = CTX_wm_area(C);
@@ -2765,20 +2466,18 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
v3d = sa->spacedata.first;
rv3d = ar->regiondata;
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
/* overwrite the mouse vector with the view direction (zoom into the center) */
- if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) {
+ if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
normalize_v3_v3(mousevec, rv3d->viewinv[2]);
}
- if (delta < 0) {
- view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 0.2f);
- }
- else {
- view_dolly_mouseloc(ar, rv3d->ofs, mousevec, 1.8f);
- }
+ view_dolly_to_vector_3d(ar, rv3d->ofs, mousevec, delta < 0 ? 0.2f : 1.8f);
- if (rv3d->viewlock & RV3D_BOXVIEW)
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(sa, ar);
+ }
ED_view3d_depth_tag_update(rv3d);
@@ -2816,7 +2515,7 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
if (vod->rv3d->persp != RV3D_PERSP) {
if (vod->rv3d->persp == RV3D_CAMOB) {
/* ignore rv3d->lpersp because dolly only makes sense in perspective mode */
- view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
+ ED_view3d_persp_switch_from_camera(vod->v3d, vod->rv3d, RV3D_PERSP);
}
else {
vod->rv3d->persp = RV3D_PERSP;
@@ -2824,7 +2523,12 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
ED_region_tag_redraw(vod->ar);
}
- viewops_data_create(C, op, event, false);
+ const bool use_mouse_init = RNA_boolean_get(op->ptr, "use_mouse_init");
+
+ viewops_data_create(
+ C, op, event,
+ viewops_flag_from_prefs() |
+ (use_mouse_init ? VIEWOPS_FLAG_USE_MOUSE_INIT : 0));
/* if one or the other zoom position aren't set, set from event */
@@ -2838,24 +2542,22 @@ static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
}
else {
/* overwrite the mouse vector with the view direction (zoom into the center) */
- if ((U.uiflag & USER_ZOOM_TO_MOUSEPOS) == 0) {
- negate_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]);
- normalize_v3(vod->mousevec);
+ if ((use_mouse_init && (U.uiflag & USER_ZOOM_TO_MOUSEPOS)) == 0) {
+ negate_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
+ normalize_v3(vod->init.mousevec);
}
if (event->type == MOUSEZOOM) {
/* Bypass Zoom invert flag for track pads (pass false always) */
if (U.uiflag & USER_ZOOM_HORIZ) {
- vod->origx = vod->oldx = event->x;
- viewdolly_apply(vod, event->prevx, event->prevy, (U.uiflag & USER_ZOOM_INVERT) == 0);
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
}
else {
-
/* Set y move = x move as MOUSEZOOM uses only x axis to pass magnification value */
- vod->origy = vod->oldy = vod->origy + event->x - event->prevx;
- viewdolly_apply(vod, event->prevx, event->prevy, (U.uiflag & USER_ZOOM_INVERT) == 0);
+ vod->init.event_xy[1] = vod->prev.event_xy[1] = vod->init.event_xy[1] + event->x - event->prevx;
}
+ viewdolly_apply(vod, &event->prevx, (U.uiflag & USER_ZOOM_INVERT) == 0);
ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -2893,14 +2595,23 @@ void VIEW3D_OT_dolly(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_BLOCKING | OPTYPE_GRAB_CURSOR;
- RNA_def_int(ot->srna, "delta", 0, INT_MIN, INT_MAX, "Delta", "", INT_MIN, INT_MAX);
- RNA_def_int(ot->srna, "mx", 0, 0, INT_MAX, "Zoom Position X", "", 0, INT_MAX);
- RNA_def_int(ot->srna, "my", 0, 0, INT_MAX, "Zoom Position Y", "", 0, INT_MAX);
+ /* properties */
+ view3d_operator_properties_common(
+ ot, V3D_OP_PROP_DELTA | V3D_OP_PROP_MOUSE_CO | V3D_OP_PROP_USE_MOUSE_INIT);
}
-static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
- const float min[3], const float max[3],
- bool ok_dist, const int smooth_viewtx)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View All Operator
+ *
+ * Move & Zoom the view to fit all of it's contents.
+ * \{ */
+
+static void view3d_from_minmax(
+ bContext *C, View3D *v3d, ARegion *ar,
+ const float min[3], const float max[3],
+ bool ok_dist, const int smooth_viewtx)
{
RegionView3D *rv3d = ar->regiondata;
float afm[3];
@@ -2966,10 +2677,13 @@ static void view3d_from_minmax(bContext *C, View3D *v3d, ARegion *ar,
/* smooth view does viewlock RV3D_BOXVIEW copy */
}
-/* same as view3d_from_minmax but for all regions (except cameras) */
-static void view3d_from_minmax_multi(bContext *C, View3D *v3d,
- const float min[3], const float max[3],
- const bool ok_dist, const int smooth_viewtx)
+/**
+ * Same as #view3d_from_minmax but for all regions (except cameras).
+ */
+static void view3d_from_minmax_multi(
+ bContext *C, View3D *v3d,
+ const float min[3], const float max[3],
+ const bool ok_dist, const int smooth_viewtx)
{
ScrArea *sa = CTX_wm_area(C);
ARegion *ar;
@@ -2985,7 +2699,7 @@ static void view3d_from_minmax_multi(bContext *C, View3D *v3d,
}
}
-static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in 2.4x */
+static int view3d_all_exec(bContext *C, wmOperator *op)
{
ARegion *ar = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -3050,8 +2764,6 @@ static int view3d_all_exec(bContext *C, wmOperator *op) /* was view3d_home() in
void VIEW3D_OT_view_all(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "View All";
ot->description = "View all objects in scene";
@@ -3064,11 +2776,19 @@ void VIEW3D_OT_view_all(wmOperatorType *ot)
/* flags */
ot->flag = 0;
- prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
RNA_def_boolean(ot->srna, "center", 0, "Center", "");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Selected Operator
+ *
+ * Move & Zoom the view to fit selected contents.
+ * \{ */
+
/* like a localview without local!, was centerview() in 2.4x */
static int viewselected_exec(bContext *C, wmOperator *op)
{
@@ -3180,8 +2900,6 @@ static int viewselected_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_view_selected(wmOperatorType *ot)
{
- PropertyRNA *prop;
-
/* identifiers */
ot->name = "View Selected";
ot->description = "Move the view to the selection center";
@@ -3194,17 +2912,22 @@ void VIEW3D_OT_view_selected(wmOperatorType *ot)
/* flags */
ot->flag = 0;
- /* rna later */
- prop = RNA_def_boolean(ot->srna, "use_all_regions", 0, "All Regions", "View selected for all regions");
- RNA_def_property_flag(prop, PROP_SKIP_SAVE);
+ /* properties */
+ view3d_operator_properties_common(ot, V3D_OP_PROP_USE_ALL_REGIONS);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Lock Clear Operator
+ * \{ */
+
static int view_lock_clear_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d = CTX_wm_view3d(C);
if (v3d) {
- ED_view3D_lock_clear(v3d);
+ ED_view3d_lock_clear(v3d);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
@@ -3231,6 +2954,12 @@ void VIEW3D_OT_view_lock_clear(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Lock to Active Operator
+ * \{ */
+
static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d = CTX_wm_view3d(C);
@@ -3238,7 +2967,7 @@ static int view_lock_to_active_exec(bContext *C, wmOperator *UNUSED(op))
if (v3d) {
- ED_view3D_lock_clear(v3d);
+ ED_view3d_lock_clear(v3d);
v3d->ob_centre = obact; /* can be NULL */
@@ -3282,12 +3011,18 @@ void VIEW3D_OT_view_lock_to_active(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Center Cursor Operator
+ * \{ */
+
static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
Scene *scene = CTX_data_scene(C);
-
+
if (rv3d) {
ARegion *ar = CTX_wm_region(C);
const int smooth_viewtx = WM_operator_smooth_viewtx_get(op);
@@ -3303,7 +3038,7 @@ static int viewcenter_cursor_exec(bContext *C, wmOperator *op)
/* smooth view does viewlock RV3D_BOXVIEW copy */
}
-
+
return OPERATOR_FINISHED;
}
@@ -3313,15 +3048,21 @@ void VIEW3D_OT_view_center_cursor(wmOperatorType *ot)
ot->name = "Center View to Cursor";
ot->description = "Center the view so that the cursor is in the middle of the view";
ot->idname = "VIEW3D_OT_view_center_cursor";
-
+
/* api callbacks */
ot->exec = viewcenter_cursor_exec;
ot->poll = ED_operator_view3d_active;
-
+
/* flags */
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Center Pick Operator
+ * \{ */
+
static int viewcenter_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
@@ -3372,8 +3113,15 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Camera Center Operator
+ * \{ */
+
static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
float xfac, yfac;
float size[2];
@@ -3388,7 +3136,7 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op)) /* was
rv3d->camdx = rv3d->camdy = 0.0f;
- ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size);
+ ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
/* 4px is just a little room from the edge of the area */
xfac = (float)ar->winx / (float)(size[0] + 4);
@@ -3417,6 +3165,12 @@ void VIEW3D_OT_view_center_camera(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Lock Center Operator
+ * \{ */
+
static int view3d_center_lock_exec(bContext *C, wmOperator *UNUSED(op)) /* was view3d_home() in 2.4x */
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -3443,10 +3197,15 @@ void VIEW3D_OT_view_center_lock(wmOperatorType *ot)
ot->flag = 0;
}
-/* ********************* Set render border operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Render Border Operator
+ * \{ */
static int render_border_exec(bContext *C, wmOperator *op)
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = ED_view3d_context_rv3d(C);
@@ -3467,7 +3226,7 @@ static int render_border_exec(bContext *C, wmOperator *op)
/* calculate range */
if (rv3d->persp == RV3D_CAMOB) {
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &vb, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &vb, false);
}
else {
vb.xmin = 0;
@@ -3513,7 +3272,6 @@ static int render_border_exec(bContext *C, wmOperator *op)
}
return OPERATOR_FINISHED;
-
}
void VIEW3D_OT_render_border(wmOperatorType *ot)
@@ -3536,7 +3294,7 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
- /* rna */
+ /* properties */
WM_operator_properties_border(ot);
prop = RNA_def_boolean(ot->srna, "camera_only", false, "Camera Only",
@@ -3544,7 +3302,11 @@ void VIEW3D_OT_render_border(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_HIDDEN);
}
-/* ********************* Clear render border operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Clear Render Border Operator
+ * \{ */
static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -3573,7 +3335,6 @@ static int clear_render_border_exec(bContext *C, wmOperator *UNUSED(op))
border->ymax = 1.0f;
return OPERATOR_FINISHED;
-
}
void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
@@ -3591,7 +3352,11 @@ void VIEW3D_OT_clear_render_border(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************* Border Zoom operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Border Zoom Operator
+ * \{ */
static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
{
@@ -3612,7 +3377,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* ZBuffer depth vars */
float depth_close = FLT_MAX;
- float p[3];
+ float cent[2], p[3];
/* note; otherwise opengl won't work */
view3d_operator_needs_opengl(C);
@@ -3629,22 +3394,22 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
/* Get Z Depths, needed for perspective, nice for ortho */
ED_view3d_draw_depth(&eval_ctx, CTX_data_depsgraph(C), ar, v3d, true);
-
+
{
/* avoid allocating the whole depth buffer */
ViewDepths depth_temp = {0};
/* avoid view3d_update_depths() for speed. */
view3d_update_depths_rect(ar, &depth_temp, &rect);
-
+
/* find the closest Z pixel */
depth_close = view3d_depth_near(&depth_temp);
-
+
MEM_SAFE_FREE(depth_temp.depths);
}
- float centx = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
- float centy = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
+ cent[0] = (((float)rect.xmin) + ((float)rect.xmax)) / 2;
+ cent[1] = (((float)rect.ymin) + ((float)rect.ymax)) / 2;
if (rv3d->is_persp) {
float p_corner[3];
@@ -3655,7 +3420,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
/* convert border to 3d coordinates */
- if ((!ED_view3d_unproject(ar, centx, centy, depth_close, p)) ||
+ if ((!ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) ||
(!ED_view3d_unproject(ar, rect.xmin, rect.ymin, depth_close, p_corner)))
{
return OPERATOR_CANCELLED;
@@ -3677,7 +3442,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
new_dist = rv3d->dist;
/* convert the drawn rectangle into 3d space */
- if (depth_close != FLT_MAX && ED_view3d_unproject(ar, centx, centy, depth_close, p)) {
+ if (depth_close != FLT_MAX && ED_view3d_unproject(ar, cent[0], cent[1], depth_close, p)) {
negate_v3_v3(new_ofs, p);
}
else {
@@ -3719,8 +3484,9 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
C, v3d, ar, smooth_viewtx,
&(const V3D_SmoothParams) {.ofs = new_ofs, .dist = &new_dist});
- if (rv3d->viewlock & RV3D_BOXVIEW)
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(CTX_wm_area(C), ar);
+ }
return OPERATOR_FINISHED;
}
@@ -3755,18 +3521,25 @@ void VIEW3D_OT_zoom_border(wmOperatorType *ot)
/* flags */
ot->flag = 0;
- /* rna */
+ /* properties */
WM_operator_properties_gesture_border_zoom(ot);
}
-/* sets the view to 1:1 camera/render-pixel */
-static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar, View3D *v3d)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Camera Zoom 1:1 Operator
+ *
+ * Sets the view to 1:1 camera/render-pixel.
+ * \{ */
+
+static void view3d_set_1_to_1_viewborder(Scene *scene, const Depsgraph *depsgraph, ARegion *ar, View3D *v3d)
{
RegionView3D *rv3d = ar->regiondata;
float size[2];
int im_width = (scene->r.size * scene->r.xsch) / 100;
-
- ED_view3d_calc_camera_border_size(scene, ar, v3d, rv3d, size);
+
+ ED_view3d_calc_camera_border_size(scene, depsgraph, ar, v3d, rv3d, size);
rv3d->camzoom = BKE_screen_view3d_zoom_from_fac((float)im_width / size[0]);
CLAMP(rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX);
@@ -3774,6 +3547,7 @@ static void view3d_set_1_to_1_viewborder(Scene *scene, ARegion *ar, View3D *v3d)
static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op))
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
View3D *v3d;
@@ -3782,7 +3556,7 @@ static int view3d_zoom_1_to_1_camera_exec(bContext *C, wmOperator *UNUSED(op))
/* no NULL check is needed, poll checks */
ED_view3d_context_user_region(C, &v3d, &ar);
- view3d_set_1_to_1_viewborder(scene, ar, v3d);
+ view3d_set_1_to_1_viewborder(scene, depsgraph, ar, v3d);
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
@@ -3804,7 +3578,11 @@ void VIEW3D_OT_zoom_camera_1_to_1(wmOperatorType *ot)
ot->flag = 0;
}
-/* ********************* Changing view operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Axis/Type Operator
+ * \{ */
static const EnumPropertyItem prop_view_items[] = {
{RV3D_VIEW_LEFT, "LEFT", ICON_TRIA_LEFT, "Left", "View From the Left"},
@@ -3820,10 +3598,11 @@ static const EnumPropertyItem prop_view_items[] = {
/* would like to make this a generic function - outside of transform */
-static void axis_set_view(bContext *C, View3D *v3d, ARegion *ar,
- const float quat_[4],
- short view, int perspo, bool align_active,
- const int smooth_viewtx)
+static void axis_set_view(
+ bContext *C, View3D *v3d, ARegion *ar,
+ const float quat_[4],
+ short view, int perspo, bool align_active,
+ const int smooth_viewtx)
{
RegionView3D *rv3d = ar->regiondata; /* no NULL check is needed, poll checks */
float quat[4];
@@ -4002,7 +3781,6 @@ static int viewnumpad_exec(bContext *C, wmOperator *op)
&(const V3D_SmoothParams) {
.camera = v3d->camera, .ofs = rv3d->ofs, .quat = rv3d->viewquat,
.dist = &rv3d->dist, .lens = &v3d->lens});
-
}
else {
/* return to settings of last view */
@@ -4043,6 +3821,14 @@ void VIEW3D_OT_viewnumpad(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Orbit Operator
+ *
+ * Rotate (orbit) in incremental steps. For interactive orbit see #VIEW3D_OT_rotate.
+ * \{ */
+
static const EnumPropertyItem prop_view_orbit_items[] = {
{V3D_VIEW_STEPLEFT, "ORBITLEFT", 0, "Orbit Left", "Orbit the view around to the Left"},
{V3D_VIEW_STEPRIGHT, "ORBITRIGHT", 0, "Orbit Right", "Orbit the view around to the Right"},
@@ -4086,7 +3872,7 @@ static int vieworbit_exec(bContext *C, wmOperator *op)
float quat_new[4];
if (view_opposite == RV3D_VIEW_USER) {
- view3d_ensure_persp(v3d, ar);
+ ED_view3d_persp_ensure(v3d, ar);
}
if (ELEM(orbitdir, V3D_VIEW_STEPLEFT, V3D_VIEW_STEPRIGHT)) {
@@ -4157,17 +3943,19 @@ void VIEW3D_OT_view_orbit(wmOperatorType *ot)
/* flags */
ot->flag = 0;
-
+
/* properties */
prop = RNA_def_float(ot->srna, "angle", 0, -FLT_MAX, FLT_MAX, "Roll", "", -FLT_MAX, FLT_MAX);
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
ot->prop = RNA_def_enum(ot->srna, "type", prop_view_orbit_items, 0, "Orbit", "Direction of View Orbit");
-
}
+/** \} */
-/* ************************ viewroll ******************************** */
+/* -------------------------------------------------------------------- */
+/** \name View Roll Operator
+ * \{ */
static void view_roll_angle(ARegion *ar, float quat[4], const float orig_quat[4], const float dvec[3], float angle)
{
@@ -4194,19 +3982,20 @@ static void viewroll_apply(ViewOpsData *vod, int x, int UNUSED(y))
tot = vod->ar->winrct.xmax - vod->ar->winrct.xmin;
len1 = (vod->ar->winrct.xmax - x) / tot;
- len2 = (vod->ar->winrct.xmax - vod->origx) / tot;
+ len2 = (vod->ar->winrct.xmax - vod->init.event_xy[0]) / tot;
angle = (len1 - len2) * (float)M_PI * 4.0f;
}
if (angle != 0.0f)
- view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->oldquat, vod->mousevec, angle);
+ view_roll_angle(vod->ar, vod->rv3d->viewquat, vod->init.quat, vod->init.mousevec, angle);
if (vod->use_dyn_ofs) {
- view3d_orbit_apply_dyn_ofs(vod->rv3d->ofs, vod->ofs, vod->oldquat, vod->rv3d->viewquat, vod->dyn_ofs);
+ view3d_orbit_apply_dyn_ofs(vod->rv3d->ofs, vod->init.ofs, vod->init.quat, vod->rv3d->viewquat, vod->dyn_ofs);
}
- if (vod->rv3d->viewlock & RV3D_BOXVIEW)
+ if (vod->rv3d->viewlock & RV3D_BOXVIEW) {
view3d_boxview_sync(vod->sa, vod->ar);
+ }
ED_view3d_camera_lock_sync(vod->v3d, vod->rv3d);
@@ -4239,7 +4028,7 @@ static int viewroll_modal(bContext *C, wmOperator *op, const wmEvent *event)
break;
}
}
- else if (event->type == vod->origkey && event->val == KM_RELEASE) {
+ else if (event->type == vod->init.event_type && event->val == KM_RELEASE) {
event_code = VIEW_CONFIRM;
}
@@ -4343,17 +4132,17 @@ static int viewroll_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else {
/* makes op->customdata */
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, false);
+ viewops_data_create(C, op, event, viewops_flag_from_prefs());
vod = op->customdata;
ED_view3d_smooth_view_force_finish(C, vod->v3d, vod->ar);
/* overwrite the mouse vector with the view direction */
- normalize_v3_v3(vod->mousevec, vod->rv3d->viewinv[2]);
- negate_v3(vod->mousevec);
+ normalize_v3_v3(vod->init.mousevec, vod->rv3d->viewinv[2]);
+ negate_v3(vod->init.mousevec);
if (event->type == MOUSEROTATE) {
- vod->origx = vod->oldx = event->x;
+ vod->init.event_xy[0] = vod->prev.event_xy[0] = event->x;
viewroll_apply(vod, event->prevx, event->prevy);
ED_view3d_depth_tag_update(vod->rv3d);
@@ -4409,6 +4198,14 @@ static const EnumPropertyItem prop_view_pan_items[] = {
{0, NULL, 0, NULL, NULL}
};
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Pan Operator
+ *
+ * Move (pan) in incremental steps. For interactive pan see #VIEW3D_OT_move.
+ * \{ */
+
static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
int x = 0, y = 0;
@@ -4420,10 +4217,10 @@ static int viewpan_invoke(bContext *C, wmOperator *op, const wmEvent *event)
else if (pandir == V3D_VIEW_PANDOWN) { y = 25; }
viewops_data_alloc(C, op);
- viewops_data_create(C, op, event, false);
+ viewops_data_create(C, op, event, viewops_flag_from_prefs());
ViewOpsData *vod = op->customdata;
- viewmove_apply(vod, vod->oldx + x, vod->oldy + y);
+ viewmove_apply(vod, vod->prev.event_xy[0] + x, vod->prev.event_xy[1] + y);
ED_view3d_depth_tag_update(vod->rv3d);
viewops_data_free(C, op);
@@ -4444,11 +4241,17 @@ void VIEW3D_OT_view_pan(wmOperatorType *ot)
/* flags */
ot->flag = 0;
-
+
/* Properties */
ot->prop = RNA_def_enum(ot->srna, "type", prop_view_pan_items, 0, "Pan", "Direction of View Pan");
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Toggle Perspective/Orthographic Operator
+ * \{ */
+
static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op))
{
View3D *v3d_dummy;
@@ -4467,7 +4270,6 @@ static int viewpersportho_exec(bContext *C, wmOperator *UNUSED(op))
}
return OPERATOR_FINISHED;
-
}
void VIEW3D_OT_view_persportho(wmOperatorType *ot)
@@ -4485,6 +4287,14 @@ void VIEW3D_OT_view_persportho(wmOperatorType *ot)
ot->flag = 0;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Navigate Operator
+ *
+ * Wraps walk/fly modes.
+ * \{ */
+
static int view3d_navigate_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
{
eViewNavigation_Method mode = U.navigation_mode;
@@ -4514,8 +4324,11 @@ void VIEW3D_OT_navigate(wmOperatorType *ot)
ot->poll = ED_operator_view3d_active;
}
+/** \} */
-/* ******************** add background image operator **************** */
+/* -------------------------------------------------------------------- */
+/** \name Background Image Add Operator
+ * \{ */
static CameraBGImage *background_image_add(bContext *C)
{
@@ -4536,7 +4349,7 @@ static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEven
Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
Image *ima;
CameraBGImage *bgpic;
-
+
ima = (Image *)WM_operator_drop_load_path(C, op, ID_IM);
/* may be NULL, continue anyway */
@@ -4566,7 +4379,7 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_UNDO;
-
+
/* properties */
RNA_def_string(ot->srna, "name", "Image", MAX_ID_NAME - 2, "Name", "Image name to assign");
WM_operator_properties_filesel(
@@ -4574,8 +4387,12 @@ void VIEW3D_OT_background_image_add(wmOperatorType *ot)
WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA);
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Background Image Remove Operator
+ * \{ */
-/* ***** remove image operator ******* */
static int background_image_remove_exec(bContext *C, wmOperator *op)
{
Camera *cam = CTX_data_pointer_get_type(C, "camera", &RNA_Camera).data;
@@ -4593,13 +4410,11 @@ static int background_image_remove_exec(bContext *C, wmOperator *op)
BKE_camera_background_image_remove(cam, bgpic_rem);
WM_event_add_notifier(C, NC_CAMERA | ND_DRAW_RENDER_VIEWPORT, cam);
-
return OPERATOR_FINISHED;
}
else {
return OPERATOR_CANCELLED;
}
-
}
void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
@@ -4615,12 +4430,18 @@ void VIEW3D_OT_background_image_remove(wmOperatorType *ot)
/* flags */
ot->flag = 0;
-
+
/* properties */
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "Background image index to remove", 0, INT_MAX);
}
-/* ********************* set clipping operator ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Clipping Planes Operator
+ *
+ * Draw border or toggle off.
+ * \{ */
static void calc_local_clipping(float clip_local[6][4], BoundBox *clipbb, float mat[4][4])
{
@@ -4677,7 +4498,6 @@ static int view3d_clipping_invoke(bContext *C, wmOperator *op, const wmEvent *ev
}
}
-/* toggles */
void VIEW3D_OT_clip_border(wmOperatorType *ot)
{
@@ -4697,11 +4517,15 @@ void VIEW3D_OT_clip_border(wmOperatorType *ot)
/* flags */
ot->flag = 0;
- /* rna */
+ /* properties */
WM_operator_properties_border(ot);
}
-/* ***************** 3d cursor cursor op ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Set Cursor Operator
+ * \{ */
/* cursor position in vec, result in vec, mval in region coords */
/* note: cannot use event->mval here (called by object_add() */
@@ -4712,14 +4536,14 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
RegionView3D *rv3d = ar->regiondata;
bool flip;
bool depth_used = false;
-
+
/* normally the caller should ensure this,
* but this is called from areas that aren't already dealing with the viewport */
if (rv3d == NULL)
return;
ED_view3d_calc_zfac(rv3d, fp, &flip);
-
+
/* reset the depth based on the view offset (we _know_ the offset is infront of us) */
if (flip) {
negate_v3_v3(fp, rv3d->ofs);
@@ -4727,7 +4551,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
ED_view3d_calc_zfac(rv3d, fp, NULL /* &flip */ );
}
- if (U.uiflag & USER_ZBUF_CURSOR) { /* maybe this should be accessed some other way */
+ if (U.uiflag & USER_DEPTH_CURSOR) { /* maybe this should be accessed some other way */
EvaluationContext eval_ctx;
struct Depsgraph *graph = CTX_data_depsgraph(C);
@@ -4808,26 +4632,27 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* flags */
// ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
-
- /* rna later */
-
}
-/* ***************** manipulator op ******************* */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Enable Transform Manipulator Operator
+ * \{ */
static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
View3D *v3d = CTX_wm_view3d(C);
v3d->twtype = 0;
-
+
if (RNA_boolean_get(op->ptr, "translate"))
v3d->twtype |= V3D_MANIP_TRANSLATE;
if (RNA_boolean_get(op->ptr, "rotate"))
v3d->twtype |= V3D_MANIP_ROTATE;
if (RNA_boolean_get(op->ptr, "scale"))
v3d->twtype |= V3D_MANIP_SCALE;
-
+
WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, v3d);
return OPERATOR_FINISHED;
@@ -4841,12 +4666,12 @@ void VIEW3D_OT_enable_manipulator(wmOperatorType *ot)
ot->name = "Enable 3D Manipulator";
ot->description = "Enable the transform manipulator for use";
ot->idname = "VIEW3D_OT_enable_manipulator";
-
+
/* api callbacks */
ot->invoke = enable_manipulator_invoke;
ot->poll = ED_operator_view3d_active;
-
- /* rna later */
+
+ /* properties */
prop = RNA_def_boolean(ot->srna, "translate", 0, "Translate", "Enable the translate manipulator");
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
prop = RNA_def_boolean(ot->srna, "rotate", 0, "Rotate", "Enable the rotate manipulator");
@@ -4855,7 +4680,11 @@ void VIEW3D_OT_enable_manipulator(wmOperatorType *ot)
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
-/* ************************* Toggle rendered shading *********************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Toggle Render Shading Operator
+ * \{ */
static int toggle_render_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -4884,315 +4713,4 @@ void VIEW3D_OT_toggle_render(wmOperatorType *ot)
ot->poll = ED_operator_view3d_active;
}
-/* ************************* below the line! *********************** */
-
-
-static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin)
-{
- ViewDepths depth_temp = {0};
- rcti rect;
- float depth_close;
-
- if (margin == 0) {
- /* Get Z Depths, needed for perspective, nice for ortho */
- rect.xmin = mval[0];
- rect.ymin = mval[1];
- rect.xmax = mval[0] + 1;
- rect.ymax = mval[1] + 1;
- }
- else {
- BLI_rcti_init_pt_radius(&rect, mval, margin);
- }
-
- view3d_update_depths_rect(ar, &depth_temp, &rect);
- depth_close = view3d_depth_near(&depth_temp);
- MEM_SAFE_FREE(depth_temp.depths);
- return depth_close;
-}
-
-/**
- * Get the world-space 3d location from a screen-space 2d point.
- *
- * \param mval: Input screen-space pixel location.
- * \param mouse_worldloc: Output world-space location.
- * \param fallback_depth_pt: Use this points depth when no depth can be found.
- */
-bool ED_view3d_autodist(
- const EvaluationContext *eval_ctx, struct Depsgraph *graph, ARegion *ar, View3D *v3d,
- const int mval[2], float mouse_worldloc[3],
- const bool alphaoverride, const float fallback_depth_pt[3])
-{
- float depth_close;
- int margin_arr[] = {0, 2, 4};
- int i;
- bool depth_ok = false;
-
- /* Get Z Depths, needed for perspective, nice for ortho */
- ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, alphaoverride);
-
- /* Attempt with low margin's first */
- i = 0;
- do {
- depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize);
- depth_ok = (depth_close != FLT_MAX);
- } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
-
- if (depth_ok) {
- float centx = (float)mval[0] + 0.5f;
- float centy = (float)mval[1] + 0.5f;
-
- if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) {
- return true;
- }
- }
-
- if (fallback_depth_pt) {
- ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc);
- return true;
- }
- else {
- return false;
- }
-}
-
-void ED_view3d_autodist_init(
- const EvaluationContext *eval_ctx, struct Depsgraph *graph,
- ARegion *ar, View3D *v3d, int mode)
-{
- /* Get Z Depths, needed for perspective, nice for ortho */
- switch (mode) {
- case 0:
- ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true);
- break;
- case 1:
- {
- Scene *scene = DEG_get_evaluated_scene(graph);
- ED_view3d_draw_depth_gpencil(eval_ctx, scene, ar, v3d);
- break;
- }
- }
-}
-
-/* no 4x4 sampling, run #ED_view3d_autodist_init first */
-bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
- int margin, float *force_depth)
-{
- float depth;
-
- /* Get Z Depths, needed for perspective, nice for ortho */
- if (force_depth)
- depth = *force_depth;
- else
- depth = view_autodist_depth_margin(ar, mval, margin);
-
- if (depth == FLT_MAX)
- return false;
-
- float centx = (float)mval[0] + 0.5f;
- float centy = (float)mval[1] + 0.5f;
- return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
-}
-
-bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
-{
- *depth = view_autodist_depth_margin(ar, mval, margin);
-
- return (*depth != FLT_MAX);
-}
-
-static bool depth_segment_cb(int x, int y, void *userData)
-{
- struct { ARegion *ar; int margin; float depth; } *data = userData;
- int mval[2];
- float depth;
-
- mval[0] = x;
- mval[1] = y;
-
- depth = view_autodist_depth_margin(data->ar, mval, data->margin);
-
- if (depth != FLT_MAX) {
- data->depth = depth;
- return 0;
- }
- else {
- return 1;
- }
-}
-
-bool ED_view3d_autodist_depth_seg(ARegion *ar, const int mval_sta[2], const int mval_end[2],
- int margin, float *depth)
-{
- struct { ARegion *ar; int margin; float depth; } data = {NULL};
- int p1[2];
- int p2[2];
-
- data.ar = ar;
- data.margin = margin;
- data.depth = FLT_MAX;
-
- copy_v2_v2_int(p1, mval_sta);
- copy_v2_v2_int(p2, mval_end);
-
- BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data);
-
- *depth = data.depth;
-
- return (*depth != FLT_MAX);
-}
-
-/* problem - ofs[3] can be on same location as camera itself.
- * Blender needs proper dist value for zoom.
- * use fallback_dist to override small values
- */
-float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float fallback_dist)
-{
- float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f};
- float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f};
- float dist;
-
- mul_m4_v4(mat, pos);
- add_v3_v3(pos, ofs);
- mul_m4_v4(mat, dir);
- normalize_v3(dir);
-
- dist = dot_v3v3(pos, dir);
-
- if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) {
- dist = fallback_dist;
- }
-
- return dist;
-}
-
-/**
- * Set the dist without moving the view (compensate with #RegionView3D.ofs)
- *
- * \note take care that viewinv is up to date, #ED_view3d_update_viewmat first.
- */
-void ED_view3d_distance_set(RegionView3D *rv3d, const float dist)
-{
- float viewinv[4];
- float tvec[3];
-
- BLI_assert(dist >= 0.0f);
-
- copy_v3_fl3(tvec, 0.0f, 0.0f, rv3d->dist - dist);
- /* rv3d->viewinv isn't always valid */
-#if 0
- mul_mat3_m4_v3(rv3d->viewinv, tvec);
-#else
- invert_qt_qt_normalized(viewinv, rv3d->viewquat);
- mul_qt_v3(viewinv, tvec);
-#endif
- sub_v3_v3(rv3d->ofs, tvec);
-
- rv3d->dist = dist;
-}
-
-/**
- * Set the view transformation from a 4x4 matrix.
- *
- * \param mat The view 4x4 transformation matrix to assign.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
-void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist)
-{
- float nmat[3][3];
-
- /* dist depends on offset */
- BLI_assert(dist == NULL || ofs != NULL);
-
- copy_m3_m4(nmat, mat);
- normalize_m3(nmat);
-
- /* Offset */
- if (ofs)
- negate_v3_v3(ofs, mat[3]);
-
- /* Quat */
- if (quat) {
- mat3_normalized_to_quat(quat, nmat);
- invert_qt_normalized(quat);
- }
-
- if (ofs && dist) {
- madd_v3_v3fl(ofs, nmat[2], *dist);
- }
-}
-
-/**
- * Calculate the view transformation matrix from RegionView3D input.
- * The resulting matrix is equivalent to RegionView3D.viewinv
- * \param mat The view 4x4 transformation matrix to calculate.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
-void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist)
-{
- float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]};
- float dvec[3] = {0.0f, 0.0f, dist};
-
- quat_to_mat4(mat, iviewquat);
- mul_mat3_m4_v3(mat, dvec);
- sub_v3_v3v3(mat[3], dvec, ofs);
-}
-
-/**
- * Set the RegionView3D members from an objects transformation and optionally lens.
- * \param ob The object to set the view to.
- * \param ofs The view offset to be set, normally from RegionView3D.ofs.
- * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
- * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
- */
-void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
-{
- ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
-
- if (lens) {
- CameraParams params;
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_object(&params, ob);
- *lens = params.lens;
- }
-}
-
-/**
- * Set the object transformation from RegionView3D members.
- * \param ob The object which has the transformation assigned.
- * \param ofs The view offset, normally from RegionView3D.ofs.
- * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
- * \param dist The view distance from ofs, normally from RegionView3D.dist.
- */
-void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist)
-{
- float mat[4][4];
-
- ED_view3d_to_m4(mat, ofs, quat, dist);
- BKE_object_apply_mat4(ob, mat, true, true);
-}
-
-/**
- * Use to store the last view, before entering camera view.
- */
-void ED_view3d_lastview_store(RegionView3D *rv3d)
-{
- copy_qt_qt(rv3d->lviewquat, rv3d->viewquat);
- rv3d->lview = rv3d->view;
- if (rv3d->persp != RV3D_CAMOB) {
- rv3d->lpersp = rv3d->persp;
- }
-}
-
-void ED_view3D_lock_clear(View3D *v3d)
-{
- v3d->ob_centre = NULL;
- v3d->ob_centre_bone[0] = '\0';
- v3d->ob_centre_cursor = false;
- v3d->flag2 &= ~V3D_LOCK_CAMERA;
-}
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index 5e7eddb1c22..d2aa19509d7 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -58,6 +58,8 @@
#include "GPU_immediate.h"
+#include "DEG_depsgraph.h"
+
#include "view3d_intern.h" /* own include */
/* NOTE: these defines are saved in keymap files, do not change values but just add new ones */
@@ -193,6 +195,7 @@ typedef struct FlyInfo {
RegionView3D *rv3d;
View3D *v3d;
ARegion *ar;
+ const struct Depsgraph *depsgraph;
Scene *scene;
wmTimer *timer; /* needed for redraws */
@@ -242,7 +245,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
float x1, x2, y1, y2;
if (fly->scene->camera) {
- ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
xoff = viewborder.xmin;
yoff = viewborder.ymin;
}
@@ -343,6 +346,10 @@ enum {
static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
+
rctf viewborder;
float upvec[3]; /* tmp */
@@ -351,6 +358,7 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
fly->rv3d = CTX_wm_region_view3d(C);
fly->v3d = CTX_wm_view3d(C);
fly->ar = CTX_wm_region(C);
+ fly->depsgraph = CTX_data_depsgraph(C);
fly->scene = CTX_data_scene(C);
#ifdef NDOF_FLY_DEBUG
@@ -417,12 +425,12 @@ static bool initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent
}
fly->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- C, fly->scene, fly->v3d, fly->rv3d,
+ &eval_ctx, fly->scene, fly->v3d, fly->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* calculate center */
if (fly->scene->camera) {
- ED_view3d_calc_camera_border(fly->scene, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(fly->scene, fly->depsgraph, fly->ar, fly->v3d, fly->rv3d, &viewborder, false);
fly->width = BLI_rctf_size_x(&viewborder);
fly->height = BLI_rctf_size_y(&viewborder);
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index f86f6423f93..d1968166904 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -111,6 +111,7 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot);
void VIEW3D_OT_toggle_render(struct wmOperatorType *ot);
void view3d_boxview_copy(ScrArea *sa, ARegion *ar);
+void view3d_boxview_sync(ScrArea *sa, ARegion *ar);
void view3d_orbit_apply_dyn_ofs(
float r_ofs[3], const float ofs_old[3], const float viewquat_old[4],
@@ -153,7 +154,7 @@ void draw_object_select(
const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, struct ARegion *ar, View3D *v3d,
Base *base, const short dflag);
-void draw_mesh_object_outline(View3D *v3d, Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]);
+void draw_mesh_object_outline(View3D *v3d, struct Object *ob, struct DerivedMesh *dm, const unsigned char ob_wire_col[4]);
bool draw_glsl_material(Scene *scene, struct ViewLayer *view_layer, struct Object *ob, View3D *v3d, const char dt);
void draw_object_instance(const struct EvaluationContext *eval_ctx, Scene *scene, struct ViewLayer *view_layer, View3D *v3d, RegionView3D *rv3d, struct Object *ob, const char dt, int outline, const float wire_col[4]);
@@ -233,9 +234,6 @@ void ED_view3d_draw_select_loop(
void ED_view3d_draw_depth_loop(
const struct EvaluationContext *eval_ctx, Scene *scene, ARegion *ar, View3D *v3d);
-void view3d_draw_bgpic_test(Scene *scene, ARegion *ar, View3D *v3d,
- const bool do_foreground, const bool do_camera_frame);
-
void ED_view3d_after_add(ListBase *lb, Base *base, const short dflag);
void view3d_update_depths_rect(struct ARegion *ar, struct ViewDepths *d, struct rcti *rect);
@@ -279,8 +277,12 @@ void ED_view3d_smooth_view_force_finish(
struct bContext *C,
struct View3D *v3d, struct ARegion *ar);
-void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect);
-void view3d_viewmatrix_set(const struct EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d);
+void view3d_winmatrix_set(
+ const struct Depsgraph *depsgraph,
+ ARegion *ar, const View3D *v3d, const rcti *rect);
+void view3d_viewmatrix_set(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2]);
void fly_modal_keymap(struct wmKeyConfig *keyconf);
void walk_modal_keymap(struct wmKeyConfig *keyconf);
@@ -295,7 +297,7 @@ void view3d_buttons_register(struct ARegionType *art);
/* view3d_camera_control.c */
struct View3DCameraControl *ED_view3d_cameracontrol_acquire(
- const struct bContext *C, Scene *scene, View3D *v3d, RegionView3D *rv3d,
+ const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, RegionView3D *rv3d,
const bool use_parent_root);
void ED_view3d_cameracontrol_update(
struct View3DCameraControl *vctrl,
@@ -304,7 +306,7 @@ void ED_view3d_cameracontrol_update(
void ED_view3d_cameracontrol_release(
struct View3DCameraControl *vctrl,
const bool restore);
-Object *ED_view3d_cameracontrol_object_get(
+struct Object *ED_view3d_cameracontrol_object_get(
struct View3DCameraControl *vctrl);
/* view3d_toolbar.c */
@@ -337,11 +339,14 @@ void VIEW3D_WGT_camera_view(struct wmManipulatorGroupType *wgt);
void VIEW3D_WGT_force_field(struct wmManipulatorGroupType *wgt);
void VIEW3D_WGT_empty_image(struct wmManipulatorGroupType *wgt);
void VIEW3D_WGT_armature_spline(struct wmManipulatorGroupType *wgt);
+void VIEW3D_WGT_navigate(struct wmManipulatorGroupType *wgt);
void VIEW3D_WGT_ruler(struct wmManipulatorGroupType *wgt);
void VIEW3D_WT_ruler_item(struct wmManipulatorType *wt);
void VIEW3D_OT_ruler_add(struct wmOperatorType *ot);
+void VIEW3D_WT_navigate_rotate(struct wmManipulatorType *wt);
+
/* draw_volume.c */
void draw_smoke_volume(struct SmokeDomainSettings *sds, struct Object *ob,
const float min[3], const float max[3],
@@ -364,7 +369,7 @@ extern bool view3d_camera_border_hack_test;
void VP_legacy_drawcursor(Scene *scene, struct ViewLayer *view_layer, ARegion *ar, View3D *v3d);
void VP_legacy_draw_view_axis(RegionView3D *rv3d, rcti *rect);
void VP_legacy_draw_viewport_name(ARegion *ar, View3D *v3d, rcti *rect);
-void VP_legacy_draw_selected_name(Scene *scene, Object *ob, rcti *rect);
+void VP_legacy_draw_selected_name(Scene *scene, struct Object *ob, rcti *rect);
void VP_legacy_drawgrid(UnitSettings *unit, ARegion *ar, View3D *v3d, const char **grid_unit);
void VP_legacy_drawfloor(Scene *scene, View3D *v3d, const char **grid_unit, bool write_depth);
void VP_legacy_view3d_main_region_setup_view(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar, float viewmat[4][4], float winmat[4][4]);
@@ -372,7 +377,7 @@ bool VP_legacy_view3d_stereo3d_active(struct wmWindow *win, Scene *scene, View3D
void VP_legacy_view3d_stereo3d_setup(const struct EvaluationContext *eval_ctx, Scene *scene, View3D *v3d, ARegion *ar);
void draw_dupli_objects(const struct EvaluationContext *eval_ctx, Scene *scene, ViewLayer *view_layer, ARegion *ar, View3D *v3d, Base *base);
bool VP_legacy_use_depth(Scene *scene, View3D *v3d);
-void VP_drawviewborder(Scene *scene, ARegion *ar, View3D *v3d);
+void VP_drawviewborder(Scene *scene, const struct Depsgraph *depsgraph, ARegion *ar, View3D *v3d);
void VP_drawrenderborder(ARegion *ar, View3D *v3d);
void VP_view3d_draw_background_none(void);
void VP_view3d_draw_background_world(Scene *scene, RegionView3D *rv3d);
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_camera.c b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
index d020571930a..6a45ec5095f 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_camera.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_camera.c
@@ -378,11 +378,12 @@ static void WIDGETGROUP_camera_view_draw_prepare(const bContext *C, wmManipulato
struct CameraViewWidgetGroup *viewgroup = mgroup->customdata;
ARegion *ar = CTX_wm_region(C);
+ struct Depsgraph *depsgraph = CTX_data_depsgraph(C);
RegionView3D *rv3d = ar->regiondata;
if (rv3d->persp == RV3D_CAMOB) {
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
- ED_view3d_calc_camera_border(scene, ar, v3d, rv3d, &viewgroup->state.view_border, false);
+ ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &viewgroup->state.view_border, false);
}
else {
viewgroup->state.view_border = (rctf){.xmin = 0, .ymin = 0, .xmax = ar->winx, .ymax = ar->winy};
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
new file mode 100644
index 00000000000..6a5d63b180f
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate.c
@@ -0,0 +1,359 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_manipulator_navigate.c
+ * \ingroup spview3d
+ */
+
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_context.h"
+#include "BKE_object.h"
+
+#include "DNA_object_types.h"
+
+#include "ED_screen.h"
+#include "ED_manipulator_library.h"
+
+#include "UI_resources.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_access.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "view3d_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View3D Navigation Manipulator Group
+ * \{ */
+
+/* Offset from screen edge. */
+#define MANIPULATOR_OFFSET_FAC 2.5
+/* Size of main icon. */
+#define MANIPULATOR_SIZE 64
+/* Factor for size of smaller button. */
+#define MANIPULATOR_MINI_FAC 0.5
+/* How much mini buttons offset from the primary. */
+#define MANIPULATOR_MINI_OFFSET_FAC 0.6666f
+
+
+enum {
+ MPR_MOVE = 0,
+ MPR_ROTATE = 1,
+ MPR_ZOOM = 2,
+
+ /* just buttons */
+ /* overlaps MPR_ORTHO (switch between) */
+ MPR_PERSP = 3,
+ MPR_ORTHO = 4,
+ MPR_CAMERA = 5,
+
+ MPR_TOTAL = 6,
+};
+
+/* Vector icons compatible with 'GPU_batch_from_poly_2d_encoded' */
+static const uchar shape_camera[] = {
+ 0xa3, 0x19, 0x78, 0x55, 0x4d, 0x19, 0x4f, 0x0a, 0x7f, 0x00, 0xb0, 0x0a, 0xa9, 0x19,
+ 0xa9, 0x19, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f, 0x0a, 0x4f, 0x25, 0x25, 0x4f, 0x0a,
+ 0x4d, 0x19, 0x47, 0x19, 0x65, 0x55, 0x41, 0x55, 0x41, 0x9e, 0x43, 0xa8, 0x38, 0xb3,
+ 0x34, 0xc3, 0x38, 0xd2, 0x43, 0xdd, 0x53, 0xe1, 0x62, 0xdd, 0x6d, 0xd2, 0x72, 0xc3,
+ 0x78, 0xc3, 0x7c, 0xd2, 0x87, 0xdd, 0x96, 0xe1, 0xa6, 0xdd, 0xb1, 0xd2, 0xb5, 0xc3,
+ 0xb1, 0xb3, 0xa6, 0xa8, 0xa9, 0x9e, 0xa9, 0x8c, 0xbb, 0x8c, 0xbb, 0x86, 0xc7, 0x86,
+ 0xe0, 0x9e, 0xe0, 0x55, 0xc7, 0x6d, 0xbb, 0x6d, 0xbb, 0x67, 0xa9, 0x67, 0xa9, 0x55,
+ 0x8a, 0x55, 0xa9, 0x19, 0xb0, 0x0a, 0xda, 0x25, 0xf5, 0x4f, 0xff, 0x80, 0xf5, 0xb0,
+ 0xda, 0xda, 0xb0, 0xf5, 0x80, 0xff, 0x4f, 0xf5, 0x4f, 0xf5, 0x7c, 0xb3, 0x78, 0xc3,
+ 0x72, 0xc3, 0x6d, 0xb3, 0x62, 0xa8, 0x53, 0xa4, 0x43, 0xa8, 0x41, 0x9e, 0xa9, 0x9e,
+ 0xa6, 0xa8, 0x96, 0xa4, 0x87, 0xa8, 0x87, 0xa8,
+};
+static const uchar shape_ortho[] = {
+ 0x85, 0x15, 0x85, 0x7c, 0xde, 0xb3, 0xde, 0xb8, 0xd9, 0xba, 0x80, 0x85, 0x27, 0xba,
+ 0x22, 0xb8, 0x22, 0xb3, 0x7b, 0x7c, 0x7b, 0x15, 0x80, 0x12, 0x80, 0x12, 0x1d, 0xba,
+ 0x80, 0xf2, 0x80, 0xff, 0x4f, 0xf5, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f, 0x0a, 0x4f,
+ 0x25, 0x25, 0x4f, 0x0a, 0x7f, 0x00, 0x80, 0x0d, 0x1d, 0x45, 0x1d, 0x45, 0xb0, 0x0a,
+ 0xda, 0x25, 0xf5, 0x4f, 0xff, 0x80, 0xf5, 0xb0, 0xda, 0xda, 0xb0, 0xf5, 0x80, 0xff,
+ 0x80, 0xf2, 0xe3, 0xba, 0xe3, 0x45, 0x80, 0x0d, 0x7f, 0x00, 0x7f, 0x00,
+};
+static const uchar shape_pan[] = {
+ 0xbf, 0x4c, 0xbf, 0x66, 0x99, 0x66, 0x99, 0x40, 0xb2, 0x40, 0x7f, 0x0d, 0x7f, 0x00,
+ 0xb0, 0x0a, 0xda, 0x25, 0xf5, 0x4f, 0xff, 0x80, 0xf5, 0xb0, 0xda, 0xda, 0xb0, 0xf5,
+ 0x80, 0xff, 0x80, 0xf2, 0xb3, 0xbf, 0x99, 0xbf, 0x99, 0x99, 0xbf, 0x99, 0xbf, 0xb2,
+ 0xf2, 0x7f, 0xf2, 0x7f, 0x40, 0xb3, 0x40, 0x99, 0x66, 0x99, 0x66, 0xbf, 0x4d, 0xbf,
+ 0x80, 0xf2, 0x80, 0xff, 0x4f, 0xf5, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f, 0x0a, 0x4f,
+ 0x25, 0x25, 0x4f, 0x0a, 0x7f, 0x00, 0x7f, 0x0d, 0x4c, 0x40, 0x66, 0x40, 0x66, 0x66,
+ 0x40, 0x66, 0x40, 0x4d, 0x0d, 0x80, 0x0d, 0x80,
+};
+static const uchar shape_persp[] = {
+ 0xda, 0xda, 0xb0, 0xf5, 0x80, 0xff, 0x4f, 0xf5, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f,
+ 0x0a, 0x4f, 0x25, 0x25, 0x4f, 0x0a, 0x7f, 0x00, 0x80, 0x07, 0x30, 0x50, 0x18, 0xbd,
+ 0x80, 0xdb, 0xe8, 0xbd, 0xf5, 0xb0, 0xf5, 0xb0, 0x83, 0x0f, 0x87, 0x7b, 0xe2, 0xb7,
+ 0xe3, 0xba, 0xe0, 0xbb, 0x80, 0x87, 0x20, 0xbb, 0x1d, 0xba, 0x1d, 0xb7, 0x78, 0x7b,
+ 0x7d, 0x0f, 0x80, 0x0c, 0x80, 0x0c, 0xd0, 0x50, 0x80, 0x07, 0x7f, 0x00, 0xb0, 0x0a,
+ 0xda, 0x25, 0xf5, 0x4f, 0xff, 0x80, 0xf5, 0xb0, 0xe8, 0xbd, 0xe8, 0xbd,
+};
+static const uchar shape_zoom[] = {
+ 0xad, 0x7f, 0xf1, 0x7f, 0xff, 0x80, 0xf5, 0xb0, 0xda, 0xda, 0xb0, 0xf5, 0x80, 0xff,
+ 0x4f, 0xf5, 0x25, 0xda, 0x0a, 0xb0, 0x00, 0x7f, 0x0d, 0x7f, 0x52, 0x7f, 0x69, 0xb7,
+ 0x48, 0xb7, 0x80, 0xd8, 0xb8, 0xb7, 0x96, 0xb7, 0x96, 0xb7, 0x7f, 0x2f, 0x0d, 0x7f,
+ 0x00, 0x7f, 0x0a, 0x4f, 0x25, 0x25, 0x4f, 0x0a, 0x7f, 0x00, 0xb0, 0x0a, 0xda, 0x25,
+ 0xf5, 0x4f, 0xff, 0x80, 0xf1, 0x7f, 0xf1, 0x7f,
+};
+
+
+struct NavigateManipulatorInfo {
+ const char *opname;
+ const char *manipulator;
+ const unsigned char *shape;
+ uint shape_size;
+};
+
+#define SHAPE_VARS(shape_id) shape = shape_id, .shape_size = ARRAY_SIZE(shape_id)
+
+struct NavigateManipulatorInfo g_navigate_params[MPR_TOTAL] = {
+ {
+ .opname = "VIEW3D_OT_move",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_pan),
+ }, {
+ .opname = "VIEW3D_OT_rotate",
+ .manipulator = "VIEW3D_WT_navigate_rotate",
+ .shape = NULL,
+ .shape_size = 0,
+ }, {
+ .opname = "VIEW3D_OT_zoom",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_zoom),
+ }, {
+ .opname = "VIEW3D_OT_view_persportho",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_persp),
+ }, {
+ .opname = "VIEW3D_OT_view_persportho",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_ortho),
+ }, {
+ .opname = "VIEW3D_OT_viewnumpad",
+ .manipulator = "MANIPULATOR_WT_button_2d",
+ .SHAPE_VARS(shape_camera),
+ },
+};
+
+#undef SHAPE_VARS
+
+struct NavigateWidgetGroup {
+ wmManipulator *mpr_array[MPR_TOTAL];
+ /* Store the view state to check for changes. */
+ struct {
+ struct {
+ short winx, winy;
+ } ar;
+ struct {
+ char is_persp;
+ char viewlock;
+ } rv3d;
+ } state;
+ int region_size[2];
+ bool is_persp;
+};
+
+static bool WIDGETGROUP_navigate_poll(const bContext *UNUSED(C), wmManipulatorGroupType *UNUSED(wgt))
+{
+ if (U.manipulator_flag & USER_MANIPULATOR_DRAW_NAVIGATE) {
+ return true;
+ }
+ return false;
+
+}
+
+static void WIDGETGROUP_navigate_setup(const bContext *UNUSED(C), wmManipulatorGroup *mgroup)
+{
+ struct NavigateWidgetGroup *navgroup = MEM_callocN(sizeof(struct NavigateWidgetGroup), __func__);
+
+ navgroup->region_size[0] = -1;
+ navgroup->region_size[1] = -1;
+
+ wmOperatorType *ot_viewnumpad = WM_operatortype_find("VIEW3D_OT_viewnumpad", true);
+
+ for (int i = 0; i < MPR_TOTAL; i++) {
+ const struct NavigateManipulatorInfo *info = &g_navigate_params[i];
+ navgroup->mpr_array[i] = WM_manipulator_new(info->manipulator, mgroup, NULL);
+ wmManipulator *mpr = navgroup->mpr_array[i];
+ mpr->flag |= WM_MANIPULATOR_GRAB_CURSOR | WM_MANIPULATOR_DRAW_MODAL;
+ mpr->color[3] = 0.2f;
+ mpr->color_hi[3] = 0.4f;
+
+ /* may be overwritten later */
+ mpr->scale_basis = (MANIPULATOR_SIZE * MANIPULATOR_MINI_FAC) / 2;
+ if (info->shape != NULL) {
+ PropertyRNA *prop = RNA_struct_find_property(mpr->ptr, "shape");
+ RNA_property_string_set_bytes(
+ mpr->ptr, prop,
+ (const char *)info->shape, info->shape_size);
+ }
+
+ wmOperatorType *ot = WM_operatortype_find(info->opname, true);
+ WM_manipulator_operator_set(mpr, 0, ot, NULL);
+ }
+
+ {
+ wmManipulator *mpr = navgroup->mpr_array[MPR_CAMERA];
+ PointerRNA *ptr = WM_manipulator_operator_set(mpr, 0, ot_viewnumpad, NULL);
+ RNA_enum_set(ptr, "type", RV3D_VIEW_CAMERA);
+ }
+
+ /* Click only buttons (not modal). */
+ {
+ int mpr_ids[] = {MPR_PERSP, MPR_ORTHO, MPR_CAMERA};
+ for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) {
+ wmManipulator *mpr = navgroup->mpr_array[mpr_ids[i]];
+ RNA_boolean_set(mpr->ptr, "show_drag", false);
+ }
+ }
+
+ /* Modal operators, don't use initial mouse location since we're clicking on a button. */
+ {
+ int mpr_ids[] = {MPR_MOVE, MPR_ROTATE, MPR_ZOOM};
+ for (int i = 0; i < ARRAY_SIZE(mpr_ids); i++) {
+ wmManipulator *mpr = navgroup->mpr_array[mpr_ids[i]];
+ wmManipulatorOpElem *mpop = WM_manipulator_operator_get(mpr, 0);
+ RNA_boolean_set(&mpop->ptr, "use_mouse_init", false);
+ }
+ }
+
+ {
+ wmManipulator *mpr = navgroup->mpr_array[MPR_ROTATE];
+ mpr->scale_basis = MANIPULATOR_SIZE / 2;
+ char mapping[6] = {
+ RV3D_VIEW_LEFT,
+ RV3D_VIEW_RIGHT,
+ RV3D_VIEW_FRONT,
+ RV3D_VIEW_BACK,
+ RV3D_VIEW_BOTTOM,
+ RV3D_VIEW_TOP,
+ };
+
+ for (int part_index = 0; part_index < 6; part_index += 1) {
+ PointerRNA *ptr = WM_manipulator_operator_set(mpr, part_index + 1, ot_viewnumpad, NULL);
+ RNA_enum_set(ptr, "type", mapping[part_index]);
+ }
+
+ /* When dragging an axis, use this instead. */
+ mpr->drag_part = 0;
+ }
+
+ mgroup->customdata = navgroup;
+}
+
+static void WIDGETGROUP_navigate_draw_prepare(const bContext *C, wmManipulatorGroup *mgroup)
+{
+ struct NavigateWidgetGroup *navgroup = mgroup->customdata;
+ ARegion *ar = CTX_wm_region(C);
+ const RegionView3D *rv3d = ar->regiondata;
+
+ for (int i = 0; i < 3; i++) {
+ copy_v3_v3(navgroup->mpr_array[MPR_ROTATE]->matrix_offset[i], rv3d->viewmat[i]);
+ }
+
+ if ((navgroup->state.ar.winx == ar->winx) &&
+ (navgroup->state.ar.winy == ar->winy) &&
+ (navgroup->state.rv3d.is_persp == rv3d->is_persp) &&
+ (navgroup->state.rv3d.viewlock == rv3d->viewlock))
+ {
+ return;
+ }
+
+
+ navgroup->state.ar.winx = ar->winx;
+ navgroup->state.ar.winy = ar->winy;
+ navgroup->state.rv3d.is_persp = rv3d->is_persp;
+ navgroup->state.rv3d.viewlock = rv3d->viewlock;
+
+
+ const float icon_size = MANIPULATOR_SIZE;
+ const float icon_offset = (icon_size / 2.0) * MANIPULATOR_OFFSET_FAC * U.ui_scale;
+ const float icon_offset_mini = icon_size * MANIPULATOR_MINI_OFFSET_FAC * U.ui_scale;
+ const float co[2] = {ar->winx - icon_offset, ar->winy - icon_offset};
+
+ wmManipulator *mpr;
+
+ for (uint i = 0; i < ARRAY_SIZE(navgroup->mpr_array); i++) {
+ mpr = navgroup->mpr_array[i];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, true);
+ }
+
+ if ((rv3d->viewlock & RV3D_LOCKED) == 0) {
+ mpr = navgroup->mpr_array[MPR_ROTATE];
+ mpr->matrix_basis[3][0] = co[0];
+ mpr->matrix_basis[3][1] = co[1];
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[MPR_MOVE];
+ mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[MPR_ZOOM];
+ mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] - icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[rv3d->is_persp ? MPR_ORTHO : MPR_PERSP];
+ mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[MPR_CAMERA];
+ mpr->matrix_basis[3][0] = co[0] - icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ }
+ else {
+ /* RV3D_LOCKED: only show supported buttons. */
+ mpr = navgroup->mpr_array[MPR_MOVE];
+ mpr->matrix_basis[3][0] = co[0] + icon_offset_mini;
+ mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+
+ mpr = navgroup->mpr_array[MPR_ZOOM];
+ mpr->matrix_basis[3][0] = co[0];
+ mpr->matrix_basis[3][1] = co[1] + icon_offset_mini;
+ WM_manipulator_set_flag(mpr, WM_MANIPULATOR_HIDDEN, false);
+ }
+}
+
+void VIEW3D_WGT_navigate(wmManipulatorGroupType *wgt)
+{
+ wgt->name = "View3D Navigate";
+ wgt->idname = "VIEW3D_WGT_navigate";
+
+ wgt->flag |= (WM_MANIPULATORGROUPTYPE_PERSISTENT |
+ WM_MANIPULATORGROUPTYPE_SCALE |
+ WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL);
+
+ wgt->poll = WIDGETGROUP_navigate_poll;
+ wgt->setup = WIDGETGROUP_navigate_setup;
+ wgt->draw_prepare = WIDGETGROUP_navigate_draw_prepare;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
new file mode 100644
index 00000000000..424b5dae402
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_manipulator_navigate_type.c
@@ -0,0 +1,307 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file view3d_manipulator_navigate_type.c
+ * \ingroup wm
+ *
+ * \name Custom Orientation/Navigation Manipulator for the 3D View
+ *
+ * \brief Simple manipulator to axis and translate.
+ *
+ * - scale_basis: used for the size.
+ * - matrix_basis: used for the location.
+ * - matrix_offset: used to store the orientation.
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_sort_utils.h"
+
+#include "BKE_context.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+#include "GPU_matrix.h"
+
+#include "RNA_access.h"
+#include "RNA_define.h"
+
+#include "UI_resources.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+
+#include "view3d_intern.h"
+
+#define DIAL_RESOLUTION 32
+
+#define HANDLE_SIZE 0.33
+
+static void axis_geom_draw(
+ const wmManipulator *mpr, const float color[4], const bool UNUSED(select))
+{
+ glLineWidth(mpr->line_width);
+
+ Gwn_VertFormat *format = immVertexFormat();
+ const uint pos_id = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+ /* flip z for reverse */
+ const float cone_coords[5][3] = {
+ {-1, -1, 4},
+ {-1, +1, 4},
+ {+1, +1, 4},
+ {+1, -1, 4},
+ {0, 0, 2},
+ };
+
+ struct {
+ float depth;
+ char index;
+ char axis;
+ char is_pos;
+ } axis_order[6] = {
+ {-mpr->matrix_offset[0][2], 0, 0, false},
+ {+mpr->matrix_offset[0][2], 1, 0, true},
+ {-mpr->matrix_offset[1][2], 2, 1, false},
+ {+mpr->matrix_offset[1][2], 3, 1, true},
+ {-mpr->matrix_offset[2][2], 4, 2, false},
+ {+mpr->matrix_offset[2][2], 5, 2, true},
+ };
+ qsort(&axis_order, ARRAY_SIZE(axis_order), sizeof(axis_order[0]), BLI_sortutil_cmp_float);
+
+ const float scale_axis = 0.25f;
+ static const float axis_highlight[4] = {1, 1, 1, 1};
+ static const float axis_nop[4] = {1, 1, 1, 0};
+ static const float axis_black[4] = {0, 0, 0, 1};
+ static float axis_color[3][4];
+ gpuPushMatrix();
+ gpuMultMatrix(mpr->matrix_offset);
+
+ bool draw_center_done = false;
+
+ for (int axis_index = 0; axis_index < ARRAY_SIZE(axis_order); axis_index++) {
+ const int index = axis_order[axis_index].index;
+ const int axis = axis_order[axis_index].axis;
+ const bool is_pos = axis_order[axis_index].is_pos;
+
+ /* Draw slightly before, so axis aligned arrows draw ontop. */
+ if ((draw_center_done == false) && (axis_order[axis_index].depth > -0.01f)) {
+
+ /* Circle defining active area (revert back to 2D space). */
+ {
+ gpuPopMatrix();
+ immUniformColor4fv(color);
+ imm_draw_circle_fill_3d(pos_id, 0, 0, 1.0f, DIAL_RESOLUTION);
+ gpuPushMatrix();
+ gpuMultMatrix(mpr->matrix_offset);
+ }
+
+ /* Center cube. */
+ {
+ float center[3], size[3];
+
+ zero_v3(center);
+ copy_v3_fl(size, HANDLE_SIZE);
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthMask(GL_TRUE);
+ glDepthFunc(GL_LEQUAL);
+ glBlendFunc(GL_ONE, GL_ZERO);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_LINE_SMOOTH);
+ glEnable(GL_BLEND);
+ glLineWidth(1.0f);
+ /* Just draw depth values. */
+ immUniformColor4fv(axis_nop);
+ imm_draw_cube_fill_3d(pos_id, center, size);
+ immUniformColor4fv(axis_black);
+ madd_v3_v3fl(
+ center,
+ (float [3]){
+ mpr->matrix_offset[0][2],
+ mpr->matrix_offset[1][2],
+ mpr->matrix_offset[2][2]},
+ 0.08f);
+ imm_draw_cube_wire_3d(pos_id, center, size);
+ glDisable(GL_BLEND);
+ glDisable(GL_LINE_SMOOTH);
+ glDisable(GL_DEPTH_TEST);
+ }
+
+ draw_center_done = true;
+ }
+ UI_GetThemeColor3fv(TH_AXIS_X + axis, axis_color[axis]);
+ axis_color[axis][3] = 1.0f;
+
+ const int index_z = axis;
+ const int index_y = (axis + 1) % 3;
+ const int index_x = (axis + 2) % 3;
+
+#define ROTATED_VERT(v_orig) \
+ { \
+ float v[3]; \
+ copy_v3_v3(v, v_orig); \
+ if (is_pos == 0) { \
+ v[2] *= -1.0f; \
+ } \
+ immVertex3f(pos_id, v[index_x] * scale_axis, v[index_y] * scale_axis, v[index_z] * scale_axis); \
+ } ((void)0)
+
+ bool ok = true;
+
+ /* skip view align axis */
+ if (len_squared_v2(mpr->matrix_offset[axis]) < 1e-6f && (mpr->matrix_offset[axis][2] > 0.0f) == is_pos) {
+ ok = false;
+ }
+ if (ok) {
+ immUniformColor4fv(index + 1 == mpr->highlight_part ? axis_highlight : axis_color[axis]);
+ immBegin(GWN_PRIM_TRI_FAN, 6);
+ ROTATED_VERT(cone_coords[4]);
+ for (int j = 0; j <= 4; j++) {
+ ROTATED_VERT(cone_coords[j % 4]);
+ }
+ immEnd();
+ }
+
+#undef ROTATED_VERT
+ }
+
+ gpuPopMatrix();
+ immUnbindProgram();
+}
+
+static void axis3d_draw_intern(
+ const bContext *UNUSED(C), wmManipulator *mpr,
+ const bool select, const bool highlight)
+{
+ const float *color = highlight ? mpr->color_hi : mpr->color;
+ float matrix_final[4][4];
+ float matrix_unit[4][4];
+
+ unit_m4(matrix_unit);
+
+ WM_manipulator_calc_matrix_final_params(
+ mpr,
+ &((struct WM_ManipulatorMatrixParams) {
+ .matrix_offset = matrix_unit,
+ }), matrix_final);
+
+ gpuPushMatrix();
+ gpuMultMatrix(matrix_final);
+
+ glEnable(GL_BLEND);
+ axis_geom_draw(mpr, color, select);
+ glDisable(GL_BLEND);
+ gpuPopMatrix();
+}
+
+static void manipulator_axis_draw(const bContext *C, wmManipulator *mpr)
+{
+ const bool is_modal = mpr->state & WM_MANIPULATOR_STATE_MODAL;
+ const bool is_highlight = (mpr->state & WM_MANIPULATOR_STATE_HIGHLIGHT) != 0;
+
+ (void)is_modal;
+
+ glEnable(GL_BLEND);
+ axis3d_draw_intern(C, mpr, false, is_highlight);
+ glDisable(GL_BLEND);
+}
+
+static int manipulator_axis_test_select(
+ bContext *UNUSED(C), wmManipulator *mpr, const wmEvent *event)
+{
+ float point_local[2] = {UNPACK2(event->mval)};
+ sub_v2_v2(point_local, mpr->matrix_basis[3]);
+ mul_v2_fl(point_local, 1.0f / (mpr->scale_basis * U.ui_scale));
+
+ const float len_sq = len_squared_v2(point_local);
+ if (len_sq > 1.0) {
+ return -1;
+ }
+
+ int part_best = -1;
+ int part_index = 1;
+ /* Use 'SQUARE(HANDLE_SIZE)' if we want to be able to _not_ focus on one of the axis. */
+ float i_best_len_sq = FLT_MAX;
+ for (int i = 0; i < 3; i++) {
+ for (int is_pos = 0; is_pos < 2; is_pos++) {
+ float co[2] = {
+ mpr->matrix_offset[i][0] * (is_pos ? 1 : -1),
+ mpr->matrix_offset[i][1] * (is_pos ? 1 : -1),
+ };
+
+ bool ok = true;
+
+ /* Check if we're viewing on an axis, there is no point to clicking on the current axis so show the reverse. */
+ if (len_squared_v2(co) < 1e-6f && (mpr->matrix_offset[i][2] > 0.0f) == is_pos) {
+ ok = false;
+ }
+
+ if (ok) {
+ const float len_axis_sq = len_squared_v2v2(co, point_local);
+ if (len_axis_sq < i_best_len_sq) {
+ part_best = part_index;
+ i_best_len_sq = len_axis_sq;
+ }
+ }
+ part_index += 1;
+ }
+ }
+
+ if (part_best != -1) {
+ return part_best;
+ }
+
+ /* The 'mpr->scale_final' is already applied when projecting. */
+ if (len_sq < 1.0f) {
+ return 0;
+ }
+
+ return -1;
+}
+
+static int manipulator_axis_cursor_get(wmManipulator *mpr)
+{
+ if (mpr->highlight_part > 0) {
+ return CURSOR_EDIT;
+ }
+ return BC_NSEW_SCROLLCURSOR;
+}
+
+void VIEW3D_WT_navigate_rotate(wmManipulatorType *wt)
+{
+ /* identifiers */
+ wt->idname = "VIEW3D_WT_navigate_rotate";
+
+ /* api callbacks */
+ wt->draw = manipulator_axis_draw;
+ wt->test_select = manipulator_axis_test_select;
+ wt->cursor_get = manipulator_axis_cursor_get;
+
+ wt->struct_size = sizeof(wmManipulator);
+}
diff --git a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
index 230b4f44c16..e8d540bcc9d 100644
--- a/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
+++ b/source/blender/editors/space_view3d/view3d_manipulator_ruler.c
@@ -148,6 +148,11 @@ static RulerItem *ruler_item_add(wmManipulatorGroup *mgroup)
return ruler_item;
}
+static void ruler_item_remove(bContext *C, wmManipulatorGroup *mgroup, RulerItem *ruler_item)
+{
+ WM_manipulator_unlink(&mgroup->manipulators, mgroup->parent_mmap, &ruler_item->mpr, C);
+}
+
static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
char *numstr, size_t numstr_size, int prec)
{
@@ -908,16 +913,24 @@ static void manipulator_ruler_exit(bContext *C, wmManipulator *mpr, const bool c
{
wmManipulatorGroup *mgroup = mpr->parent_mgroup;
RulerInfo *ruler_info = mgroup->customdata;
- RulerItem *ruler_item = (RulerItem *)mpr;
- RulerInteraction *inter = mpr->interaction_data;
if (!cancel) {
if (ruler_info->state == RULER_STATE_DRAG) {
+ RulerItem *ruler_item = (RulerItem *)mpr;
+ RulerInteraction *inter = mpr->interaction_data;
/* rubber-band angle removal */
- if (ruler_item && (inter->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
- if (!inter->inside_region) {
+ if (!inter->inside_region) {
+ if ((inter->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
ruler_item->flag &= ~RULERITEM_USE_ANGLE;
}
+ else {
+ /* Not ideal, since the ruler isn't a mode and we don't want to override delete key
+ * use dragging out of the view for removal. */
+ ruler_item_remove(C, mgroup, ruler_item);
+ ruler_item = NULL;
+ mpr = NULL;
+ inter = NULL;
+ }
}
if (ruler_info->snap_flag & RULER_SNAP_OK) {
ruler_info->snap_flag &= ~RULER_SNAP_OK;
@@ -928,7 +941,9 @@ static void manipulator_ruler_exit(bContext *C, wmManipulator *mpr, const bool c
view3d_ruler_to_gpencil(C, mgroup);
}
- MEM_SAFE_FREE(mpr->interaction_data);
+ if (mpr) {
+ MEM_SAFE_FREE(mpr->interaction_data);
+ }
ruler_state_set(C, ruler_info, RULER_STATE_NORMAL);
}
@@ -996,7 +1011,7 @@ void VIEW3D_WGT_ruler(wmManipulatorGroupType *wgt)
wgt->name = "Ruler Widgets";
wgt->idname = view3d_wgt_ruler_id;
- wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE;
+ wgt->flag |= WM_MANIPULATORGROUPTYPE_SCALE | WM_MANIPULATORGROUPTYPE_DRAW_MODAL_ALL;
wgt->mmap_params.spaceid = SPACE_VIEW3D;
wgt->mmap_params.regionid = RGN_TYPE_WINDOW;
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index f8b02f0b405..ba3e78b25b9 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -277,6 +277,11 @@ eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, const float co[
/* More Generic Window/Ray/Vector projection functions
* *************************************************** */
+float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
+{
+ return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
+}
+
/**
* Calculate a depth value from \a co, use with #ED_view3d_win_to_delta
*/
@@ -304,6 +309,7 @@ float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_f
}
static void view3d_win_to_ray_segment(
+ const struct Depsgraph *depsgraph,
const ARegion *ar, const View3D *v3d, const float mval[2],
float r_ray_co[3], float r_ray_dir[3], float r_ray_start[3], float r_ray_end[3])
{
@@ -321,7 +327,7 @@ static void view3d_win_to_ray_segment(
start_offset = -end_offset;
}
else {
- ED_view3d_clip_range_get(v3d, rv3d, &start_offset, &end_offset, false);
+ ED_view3d_clip_range_get(depsgraph, v3d, rv3d, &start_offset, &end_offset, false);
}
if (r_ray_start) {
@@ -360,12 +366,13 @@ bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float
* \return success, false if the ray is totally clipped.
*/
bool ED_view3d_win_to_ray_ex(
+ const struct Depsgraph *depsgraph,
const ARegion *ar, const View3D *v3d, const float mval[2],
float r_ray_co[3], float r_ray_normal[3], float r_ray_start[3], bool do_clip)
{
float ray_end[3];
- view3d_win_to_ray_segment(ar, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end);
+ view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, r_ray_co, r_ray_normal, r_ray_start, ray_end);
/* bounds clipping */
if (do_clip) {
@@ -389,10 +396,11 @@ bool ED_view3d_win_to_ray_ex(
* \return success, false if the ray is totally clipped.
*/
bool ED_view3d_win_to_ray(
+ const struct Depsgraph *depsgraph,
const ARegion *ar, const View3D *v3d, const float mval[2],
float r_ray_start[3], float r_ray_normal[3], const bool do_clip)
{
- return ED_view3d_win_to_ray_ex(ar, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip);
+ return ED_view3d_win_to_ray_ex(depsgraph,ar, v3d, mval, NULL, r_ray_normal, r_ray_start, do_clip);
}
/**
@@ -622,10 +630,11 @@ void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3
* \param do_clip Optionally clip the ray by the view clipping planes.
* \return success, false if the segment is totally clipped.
*/
-bool ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2],
+bool ED_view3d_win_to_segment(const struct Depsgraph *depsgraph,
+ const ARegion *ar, View3D *v3d, const float mval[2],
float r_ray_start[3], float r_ray_end[3], const bool do_clip)
{
- view3d_win_to_ray_segment(ar, v3d, mval, NULL, NULL, r_ray_start, r_ray_end);
+ view3d_win_to_ray_segment(depsgraph, ar, v3d, mval, NULL, NULL, r_ray_start, r_ray_end);
/* bounds clipping */
if (do_clip) {
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
new file mode 100644
index 00000000000..7bb3f443ac6
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -0,0 +1,1436 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_utils.c
+ * \ingroup spview3d
+ *
+ * 3D View checks and manipulation (no operators).
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <float.h>
+
+#include "DNA_camera_types.h"
+#include "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_bitmap_draw_2d.h"
+#include "BLI_blenlib.h"
+#include "BLI_math.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_camera.h"
+#include "BKE_context.h"
+#include "BKE_object.h"
+#include "BKE_screen.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "BIF_gl.h"
+#include "BIF_glutil.h"
+
+#include "GPU_matrix.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_keyframing.h"
+#include "ED_screen.h"
+#include "ED_view3d.h"
+
+#include "view3d_intern.h" /* own include */
+
+/* -------------------------------------------------------------------- */
+/** \name View Data Access Utilities
+ *
+ * \{ */
+
+float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d)
+{
+ if (v3d && v3d->localvd) return v3d->cursor;
+ else return scene->cursor;
+}
+
+Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
+{
+ /* establish the camera object, so we can default to view mapping if anything is wrong with it */
+ if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
+ return v3d->camera->data;
+ }
+ else {
+ return NULL;
+ }
+}
+
+void ED_view3d_dist_range_get(
+ const View3D *v3d,
+ float r_dist_range[2])
+{
+ r_dist_range[0] = v3d->grid * 0.001f;
+ r_dist_range[1] = v3d->far * 10.0f;
+}
+
+/**
+ * \note copies logic of #ED_view3d_viewplane_get(), keep in sync.
+ */
+bool ED_view3d_clip_range_get(
+ const Depsgraph *depsgraph,
+ const View3D *v3d, const RegionView3D *rv3d,
+ float *r_clipsta, float *r_clipend,
+ const bool use_ortho_factor)
+{
+ CameraParams params;
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
+
+ if (use_ortho_factor && params.is_ortho) {
+ const float fac = 2.0f / (params.clipend - params.clipsta);
+ params.clipsta *= fac;
+ params.clipend *= fac;
+ }
+
+ if (r_clipsta) *r_clipsta = params.clipsta;
+ if (r_clipend) *r_clipend = params.clipend;
+
+ return params.is_ortho;
+}
+
+bool ED_view3d_viewplane_get(
+ const Depsgraph *depsgraph,
+ const View3D *v3d, const RegionView3D *rv3d, int winx, int winy,
+ rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
+{
+ CameraParams params;
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_view3d(&params, depsgraph, v3d, rv3d);
+ BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
+
+ if (r_viewplane) *r_viewplane = params.viewplane;
+ if (r_clipsta) *r_clipsta = params.clipsta;
+ if (r_clipend) *r_clipend = params.clipend;
+ if (r_pixsize) *r_pixsize = params.viewdx;
+
+ return params.is_ortho;
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+/** \name View State/Context Utilities
+ *
+ * \{ */
+
+/**
+ * Use this call when executing an operator,
+ * event system doesn't set for each event the OpenGL drawing context.
+ */
+void view3d_operator_needs_opengl(const bContext *C)
+{
+ wmWindow *win = CTX_wm_window(C);
+ ARegion *ar = CTX_wm_region(C);
+
+ view3d_region_operator_needs_opengl(win, ar);
+}
+
+void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
+{
+ /* for debugging purpose, context should always be OK */
+ if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
+ printf("view3d_region_operator_needs_opengl error, wrong region\n");
+ }
+ else {
+ RegionView3D *rv3d = ar->regiondata;
+
+ wmSubWindowSet(win, ar->swinid);
+ gpuLoadProjectionMatrix(rv3d->winmat);
+ gpuLoadMatrix(rv3d->viewmat);
+ }
+}
+
+/**
+ * Use instead of: ``bglPolygonOffset(rv3d->dist, ...)`` see bug [#37727]
+ */
+void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
+{
+ float viewdist;
+
+ if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) {
+ return;
+ }
+
+ viewdist = rv3d->dist;
+
+ /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
+ if (dist != 0.0f) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ if (rv3d->is_persp == false) {
+ viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
+ }
+ }
+ }
+
+ bglPolygonOffset(viewdist, dist);
+}
+
+bool ED_view3d_context_activate(bContext *C)
+{
+ bScreen *sc = CTX_wm_screen(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar;
+
+ /* sa can be NULL when called from python */
+ if (sa == NULL || sa->spacetype != SPACE_VIEW3D) {
+ sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0);
+ }
+
+ if (sa == NULL) {
+ return false;
+ }
+
+ ar = BKE_area_find_region_active_win(sa);
+ if (ar == NULL) {
+ return false;
+ }
+
+ /* bad context switch .. */
+ CTX_wm_area_set(C, sa);
+ CTX_wm_region_set(C, ar);
+
+ return true;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Clipping Utilities
+ *
+ * \{ */
+
+void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
+{
+ int val;
+
+ for (val = 0; val < 4; val++) {
+ normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
+ if (UNLIKELY(is_flip)) {
+ negate_v3(clip[val]);
+ }
+
+ clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]);
+ }
+}
+
+void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
+{
+ /* init in case unproject fails */
+ memset(bb->vec, 0, sizeof(bb->vec));
+
+ /* four clipping planes and bounding volume */
+ /* first do the bounding volume */
+ for (int val = 0; val < 4; val++) {
+ float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
+ float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
+
+ ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]);
+ ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]);
+ }
+
+ /* optionally transform to object space */
+ if (ob) {
+ float imat[4][4];
+ invert_m4_m4(imat, ob->obmat);
+
+ for (int val = 0; val < 8; val++) {
+ mul_m4_v3(imat, bb->vec[val]);
+ }
+ }
+
+ /* verify if we have negative scale. doing the transform before cross
+ * product flips the sign of the vector compared to doing cross product
+ * before transform then, so we correct for that. */
+ int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
+
+ ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Bound-Box Utilities
+ *
+ * \{ */
+
+static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4])
+{
+ int a, flag = -1, fl;
+
+ for (a = 0; a < 8; a++) {
+ float vec[4], min, max;
+ copy_v3_v3(vec, bb->vec[a]);
+ vec[3] = 1.0;
+ mul_m4_v4(persmatob, vec);
+ max = vec[3];
+ min = -vec[3];
+
+ fl = 0;
+ if (vec[0] < min) fl += 1;
+ if (vec[0] > max) fl += 2;
+ if (vec[1] < min) fl += 4;
+ if (vec[1] > max) fl += 8;
+ if (vec[2] < min) fl += 16;
+ if (vec[2] > max) fl += 32;
+
+ flag &= fl;
+ if (flag == 0) return true;
+ }
+
+ return false;
+}
+
+bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4])
+{
+ /* return 1: draw */
+
+ float persmatob[4][4];
+
+ if (bb == NULL) return true;
+ if (bb->flag & BOUNDBOX_DISABLED) return true;
+
+ mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat);
+
+ return view3d_boundbox_clip_m4(bb, persmatob);
+}
+
+bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
+{
+ if (bb == NULL) return true;
+ if (bb->flag & BOUNDBOX_DISABLED) return true;
+
+ return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Perspective & Mode Switching
+ *
+ * Misc view utility functions.
+ * \{ */
+
+bool ED_view3d_offset_lock_check(const View3D *v3d, const RegionView3D *rv3d)
+{
+ return (rv3d->persp != RV3D_CAMOB) && (v3d->ob_centre_cursor || v3d->ob_centre);
+}
+
+/**
+ * Use to store the last view, before entering camera view.
+ */
+void ED_view3d_lastview_store(RegionView3D *rv3d)
+{
+ copy_qt_qt(rv3d->lviewquat, rv3d->viewquat);
+ rv3d->lview = rv3d->view;
+ if (rv3d->persp != RV3D_CAMOB) {
+ rv3d->lpersp = rv3d->persp;
+ }
+}
+
+void ED_view3d_lock_clear(View3D *v3d)
+{
+ v3d->ob_centre = NULL;
+ v3d->ob_centre_bone[0] = '\0';
+ v3d->ob_centre_cursor = false;
+ v3d->flag2 &= ~V3D_LOCK_CAMERA;
+}
+
+/**
+ * For viewport operators that exit camera perspective.
+ *
+ * \note This differs from simply setting ``rv3d->persp = persp`` because it
+ * sets the ``ofs`` and ``dist`` values of the viewport so it matches the camera,
+ * otherwise switching out of camera view may jump to a different part of the scene.
+ */
+void ED_view3d_persp_switch_from_camera(View3D *v3d, RegionView3D *rv3d, const char persp)
+{
+ BLI_assert(rv3d->persp == RV3D_CAMOB);
+ BLI_assert(persp != RV3D_CAMOB);
+
+ if (v3d->camera) {
+ rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ }
+
+ if (!ED_view3d_camera_lock_check(v3d, rv3d)) {
+ rv3d->persp = persp;
+ }
+}
+/**
+ * Action to take when rotating the view,
+ * handle auto-persp and logic for switching out of views.
+ *
+ * shared with NDOF.
+ */
+bool ED_view3d_persp_ensure(struct View3D *v3d, ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+ const bool autopersp = (U.uiflag & USER_AUTOPERSP) != 0;
+
+ BLI_assert((rv3d->viewlock & RV3D_LOCKED) == 0);
+
+ if (ED_view3d_camera_lock_check(v3d, rv3d))
+ return false;
+
+ if (rv3d->persp != RV3D_PERSP) {
+ if (rv3d->persp == RV3D_CAMOB) {
+ /* If autopersp and previous view was an axis one, switch back to PERSP mode, else reuse previous mode. */
+ char persp = (autopersp && RV3D_VIEW_IS_AXIS(rv3d->lview)) ? RV3D_PERSP : rv3d->lpersp;
+ ED_view3d_persp_switch_from_camera(v3d, rv3d, persp);
+ }
+ else if (autopersp && RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ rv3d->persp = RV3D_PERSP;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Camera Lock API
+ *
+ * Lock the camera to the view-port, allowing view manipulation to transform the camera.
+ * \{ */
+
+/**
+ * \return true when the view-port is locked to its camera.
+ */
+bool ED_view3d_camera_lock_check(const View3D *v3d, const RegionView3D *rv3d)
+{
+ return ((v3d->camera) &&
+ (!ID_IS_LINKED(v3d->camera)) &&
+ (v3d->flag2 & V3D_LOCK_CAMERA) &&
+ (rv3d->persp == RV3D_CAMOB));
+}
+
+/**
+ * Apply the camera object transformation to the view-port.
+ * (needed so we can use regular view-port manipulation operators, that sync back to the camera).
+ */
+void ED_view3d_camera_lock_init_ex(View3D *v3d, RegionView3D *rv3d, const bool calc_dist)
+{
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ if (calc_dist) {
+ /* using a fallback dist is OK here since ED_view3d_from_object() compensates for it */
+ rv3d->dist = ED_view3d_offset_distance(v3d->camera->obmat, rv3d->ofs, VIEW3D_DIST_FALLBACK);
+ }
+ ED_view3d_from_object(v3d->camera, rv3d->ofs, rv3d->viewquat, &rv3d->dist, NULL);
+ }
+}
+
+void ED_view3d_camera_lock_init(View3D *v3d, RegionView3D *rv3d)
+{
+ ED_view3d_camera_lock_init_ex(v3d, rv3d, true);
+}
+
+/**
+ * Apply the view-port transformation back to the camera object.
+ *
+ * \return true if the camera is moved.
+ */
+bool ED_view3d_camera_lock_sync(View3D *v3d, RegionView3D *rv3d)
+{
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ ObjectTfmProtectedChannels obtfm;
+ Object *root_parent;
+
+ if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
+ Object *ob_update;
+ float tmat[4][4];
+ float imat[4][4];
+ float view_mat[4][4];
+ float diff_mat[4][4];
+ float parent_mat[4][4];
+
+ while (root_parent->parent) {
+ root_parent = root_parent->parent;
+ }
+
+ ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+
+ normalize_m4_m4(tmat, v3d->camera->obmat);
+
+ invert_m4_m4(imat, tmat);
+ mul_m4_m4m4(diff_mat, view_mat, imat);
+
+ mul_m4_m4m4(parent_mat, diff_mat, root_parent->obmat);
+
+ BKE_object_tfm_protected_backup(root_parent, &obtfm);
+ BKE_object_apply_mat4(root_parent, parent_mat, true, false);
+ BKE_object_tfm_protected_restore(root_parent, &obtfm, root_parent->protectflag);
+
+ ob_update = v3d->camera;
+ while (ob_update) {
+ DEG_id_tag_update(&ob_update->id, OB_RECALC_OB);
+ WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, ob_update);
+ ob_update = ob_update->parent;
+ }
+ }
+ else {
+ /* always maintain the same scale */
+ const short protect_scale_all = (OB_LOCK_SCALEX | OB_LOCK_SCALEY | OB_LOCK_SCALEZ);
+ BKE_object_tfm_protected_backup(v3d->camera, &obtfm);
+ ED_view3d_to_object(v3d->camera, rv3d->ofs, rv3d->viewquat, rv3d->dist);
+ BKE_object_tfm_protected_restore(v3d->camera, &obtfm, v3d->camera->protectflag | protect_scale_all);
+
+ DEG_id_tag_update(&v3d->camera->id, OB_RECALC_OB);
+ WM_main_add_notifier(NC_OBJECT | ND_TRANSFORM, v3d->camera);
+ }
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool ED_view3d_camera_autokey(
+ Scene *scene, ID *id_key,
+ struct bContext *C, const bool do_rotate, const bool do_translate)
+{
+ if (autokeyframe_cfra_can_key(scene, id_key)) {
+ const float cfra = (float)CFRA;
+ ListBase dsources = {NULL, NULL};
+
+ /* add data-source override for the camera object */
+ ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL);
+
+ /* insert keyframes
+ * 1) on the first frame
+ * 2) on each subsequent frame
+ * TODO: need to check in future that frame changed before doing this
+ */
+ if (do_rotate) {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_ROTATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+ if (do_translate) {
+ struct KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, ANIM_KS_LOCATION_ID);
+ ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, cfra);
+ }
+
+ /* free temp data */
+ BLI_freelistN(&dsources);
+
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+/**
+ * Call after modifying a locked view.
+ *
+ * \note Not every view edit currently auto-keys (numpad for eg),
+ * this is complicated because of smoothview.
+ */
+bool ED_view3d_camera_lock_autokey(
+ View3D *v3d, RegionView3D *rv3d,
+ struct bContext *C, const bool do_rotate, const bool do_translate)
+{
+ /* similar to ED_view3d_cameracontrol_update */
+ if (ED_view3d_camera_lock_check(v3d, rv3d)) {
+ Scene *scene = CTX_data_scene(C);
+ ID *id_key;
+ Object *root_parent;
+ if ((U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0 && (root_parent = v3d->camera->parent)) {
+ while (root_parent->parent) {
+ root_parent = root_parent->parent;
+ }
+ id_key = &root_parent->id;
+ }
+ else {
+ id_key = &v3d->camera->id;
+ }
+
+ return ED_view3d_camera_autokey(scene, id_key, C, do_rotate, do_translate);
+ }
+ else {
+ return false;
+ }
+}
+
+/** \} */
+
+
+
+/* -------------------------------------------------------------------- */
+/** \name Box View Support
+ *
+ * Use with quad-split so each view is clipped by the bounds of each view axis.
+ * \{ */
+
+static void view3d_boxview_clip(ScrArea *sa)
+{
+ ARegion *ar;
+ BoundBox *bb = MEM_callocN(sizeof(BoundBox), "clipbb");
+ float clip[6][4];
+ float x1 = 0.0f, y1 = 0.0f, z1 = 0.0f, ofs[3] = {0.0f, 0.0f, 0.0f};
+ int val;
+
+ /* create bounding box */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->viewlock & RV3D_BOXCLIP) {
+ if (ELEM(rv3d->view, RV3D_VIEW_TOP, RV3D_VIEW_BOTTOM)) {
+ if (ar->winx > ar->winy) x1 = rv3d->dist;
+ else x1 = ar->winx * rv3d->dist / ar->winy;
+
+ if (ar->winx > ar->winy) y1 = ar->winy * rv3d->dist / ar->winx;
+ else y1 = rv3d->dist;
+ copy_v2_v2(ofs, rv3d->ofs);
+ }
+ else if (ELEM(rv3d->view, RV3D_VIEW_FRONT, RV3D_VIEW_BACK)) {
+ ofs[2] = rv3d->ofs[2];
+
+ if (ar->winx > ar->winy) z1 = ar->winy * rv3d->dist / ar->winx;
+ else z1 = rv3d->dist;
+ }
+ }
+ }
+ }
+
+ for (val = 0; val < 8; val++) {
+ if (ELEM(val, 0, 3, 4, 7))
+ bb->vec[val][0] = -x1 - ofs[0];
+ else
+ bb->vec[val][0] = x1 - ofs[0];
+
+ if (ELEM(val, 0, 1, 4, 5))
+ bb->vec[val][1] = -y1 - ofs[1];
+ else
+ bb->vec[val][1] = y1 - ofs[1];
+
+ if (val > 3)
+ bb->vec[val][2] = -z1 - ofs[2];
+ else
+ bb->vec[val][2] = z1 - ofs[2];
+ }
+
+ /* normals for plane equations */
+ normal_tri_v3(clip[0], bb->vec[0], bb->vec[1], bb->vec[4]);
+ normal_tri_v3(clip[1], bb->vec[1], bb->vec[2], bb->vec[5]);
+ normal_tri_v3(clip[2], bb->vec[2], bb->vec[3], bb->vec[6]);
+ normal_tri_v3(clip[3], bb->vec[3], bb->vec[0], bb->vec[7]);
+ normal_tri_v3(clip[4], bb->vec[4], bb->vec[5], bb->vec[6]);
+ normal_tri_v3(clip[5], bb->vec[0], bb->vec[2], bb->vec[1]);
+
+ /* then plane equations */
+ for (val = 0; val < 6; val++) {
+ clip[val][3] = -dot_v3v3(clip[val], bb->vec[val % 5]);
+ }
+
+ /* create bounding box */
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->viewlock & RV3D_BOXCLIP) {
+ rv3d->rflag |= RV3D_CLIPPING;
+ memcpy(rv3d->clip, clip, sizeof(clip));
+ if (rv3d->clipbb) MEM_freeN(rv3d->clipbb);
+ rv3d->clipbb = MEM_dupallocN(bb);
+ }
+ }
+ }
+ MEM_freeN(bb);
+}
+
+/**
+ * Find which axis values are shared between both views and copy to \a rv3d_dst
+ * taking axis flipping into account.
+ */
+static void view3d_boxview_sync_axis(RegionView3D *rv3d_dst, RegionView3D *rv3d_src)
+{
+ /* absolute axis values above this are considered to be set (will be ~1.0f) */
+ const float axis_eps = 0.5f;
+ float viewinv[4];
+
+ /* use the view rotation to identify which axis to sync on */
+ float view_axis_all[4][3] = {
+ {1.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f},
+ {1.0f, 0.0f, 0.0f},
+ {0.0f, 1.0f, 0.0f}};
+
+ float *view_src_x = &view_axis_all[0][0];
+ float *view_src_y = &view_axis_all[1][0];
+
+ float *view_dst_x = &view_axis_all[2][0];
+ float *view_dst_y = &view_axis_all[3][0];
+ int i;
+
+
+ /* we could use rv3d->viewinv, but better not depend on view matrix being updated */
+ if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_src->view, viewinv) == false)) {
+ return;
+ }
+ invert_qt_normalized(viewinv);
+ mul_qt_v3(viewinv, view_src_x);
+ mul_qt_v3(viewinv, view_src_y);
+
+ if (UNLIKELY(ED_view3d_quat_from_axis_view(rv3d_dst->view, viewinv) == false)) {
+ return;
+ }
+ invert_qt_normalized(viewinv);
+ mul_qt_v3(viewinv, view_dst_x);
+ mul_qt_v3(viewinv, view_dst_y);
+
+ /* check source and dest have a matching axis */
+ for (i = 0; i < 3; i++) {
+ if (((fabsf(view_src_x[i]) > axis_eps) || (fabsf(view_src_y[i]) > axis_eps)) &&
+ ((fabsf(view_dst_x[i]) > axis_eps) || (fabsf(view_dst_y[i]) > axis_eps)))
+ {
+ rv3d_dst->ofs[i] = rv3d_src->ofs[i];
+ }
+ }
+}
+
+/* sync center/zoom view of region to others, for view transforms */
+void view3d_boxview_sync(ScrArea *sa, ARegion *ar)
+{
+ ARegion *artest;
+ RegionView3D *rv3d = ar->regiondata;
+ short clip = 0;
+
+ for (artest = sa->regionbase.first; artest; artest = artest->next) {
+ if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3dtest = artest->regiondata;
+
+ if (rv3dtest->viewlock & RV3D_LOCKED) {
+ rv3dtest->dist = rv3d->dist;
+ view3d_boxview_sync_axis(rv3dtest, rv3d);
+ clip |= rv3dtest->viewlock & RV3D_BOXCLIP;
+
+ ED_region_tag_redraw(artest);
+ }
+ }
+ }
+
+ if (clip) {
+ view3d_boxview_clip(sa);
+ }
+}
+
+/* for home, center etc */
+void view3d_boxview_copy(ScrArea *sa, ARegion *ar)
+{
+ ARegion *artest;
+ RegionView3D *rv3d = ar->regiondata;
+ bool clip = false;
+
+ for (artest = sa->regionbase.first; artest; artest = artest->next) {
+ if (artest != ar && artest->regiontype == RGN_TYPE_WINDOW) {
+ RegionView3D *rv3dtest = artest->regiondata;
+
+ if (rv3dtest->viewlock) {
+ rv3dtest->dist = rv3d->dist;
+ copy_v3_v3(rv3dtest->ofs, rv3d->ofs);
+ ED_region_tag_redraw(artest);
+
+ clip |= ((rv3dtest->viewlock & RV3D_BOXCLIP) != 0);
+ }
+ }
+ }
+
+ if (clip) {
+ view3d_boxview_clip(sa);
+ }
+}
+
+/* 'clip' is used to know if our clip setting has changed */
+void ED_view3d_quadview_update(ScrArea *sa, ARegion *ar, bool do_clip)
+{
+ ARegion *ar_sync = NULL;
+ RegionView3D *rv3d = ar->regiondata;
+ short viewlock;
+ /* this function copies flags from the first of the 3 other quadview
+ * regions to the 2 other, so it assumes this is the region whose
+ * properties are always being edited, weak */
+ viewlock = rv3d->viewlock;
+
+ if ((viewlock & RV3D_LOCKED) == 0) {
+ do_clip = (viewlock & RV3D_BOXCLIP) != 0;
+ viewlock = 0;
+ }
+ else if ((viewlock & RV3D_BOXVIEW) == 0 && (viewlock & RV3D_BOXCLIP) != 0) {
+ do_clip = true;
+ viewlock &= ~RV3D_BOXCLIP;
+ }
+
+ for (; ar; ar = ar->prev) {
+ if (ar->alignment == RGN_ALIGN_QSPLIT) {
+ rv3d = ar->regiondata;
+ rv3d->viewlock = viewlock;
+
+ if (do_clip && (viewlock & RV3D_BOXCLIP) == 0) {
+ rv3d->rflag &= ~RV3D_BOXCLIP;
+ }
+
+ /* use ar_sync so we sync with one of the aligned views below
+ * else the view jumps on changing view settings like 'clip'
+ * since it copies from the perspective view */
+ ar_sync = ar;
+ }
+ }
+
+ if (rv3d->viewlock & RV3D_BOXVIEW) {
+ view3d_boxview_sync(sa, ar_sync ? ar_sync : sa->regionbase.last);
+ }
+
+ /* ensure locked regions have an axis, locked user views don't make much sense */
+ if (viewlock & RV3D_LOCKED) {
+ int index_qsplit = 0;
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->alignment == RGN_ALIGN_QSPLIT) {
+ rv3d = ar->regiondata;
+ if (rv3d->viewlock) {
+ if (!RV3D_VIEW_IS_AXIS(rv3d->view)) {
+ rv3d->view = ED_view3d_lock_view_from_index(index_qsplit);
+ rv3d->persp = RV3D_ORTHO;
+ ED_view3d_lock(rv3d);
+ }
+ }
+ index_qsplit++;
+ }
+ }
+ }
+
+ ED_area_tag_redraw(sa);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Auto-Depth Utilities
+ * \{ */
+
+static float view_autodist_depth_margin(ARegion *ar, const int mval[2], int margin)
+{
+ ViewDepths depth_temp = {0};
+ rcti rect;
+ float depth_close;
+
+ if (margin == 0) {
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ rect.xmin = mval[0];
+ rect.ymin = mval[1];
+ rect.xmax = mval[0] + 1;
+ rect.ymax = mval[1] + 1;
+ }
+ else {
+ BLI_rcti_init_pt_radius(&rect, mval, margin);
+ }
+
+ view3d_update_depths_rect(ar, &depth_temp, &rect);
+ depth_close = view3d_depth_near(&depth_temp);
+ MEM_SAFE_FREE(depth_temp.depths);
+ return depth_close;
+}
+
+/**
+ * Get the world-space 3d location from a screen-space 2d point.
+ *
+ * \param mval: Input screen-space pixel location.
+ * \param mouse_worldloc: Output world-space location.
+ * \param fallback_depth_pt: Use this points depth when no depth can be found.
+ */
+bool ED_view3d_autodist(
+ const EvaluationContext *eval_ctx, struct Depsgraph *graph, ARegion *ar, View3D *v3d,
+ const int mval[2], float mouse_worldloc[3],
+ const bool alphaoverride, const float fallback_depth_pt[3])
+{
+ float depth_close;
+ int margin_arr[] = {0, 2, 4};
+ int i;
+ bool depth_ok = false;
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, alphaoverride);
+
+ /* Attempt with low margin's first */
+ i = 0;
+ do {
+ depth_close = view_autodist_depth_margin(ar, mval, margin_arr[i++] * U.pixelsize);
+ depth_ok = (depth_close != FLT_MAX);
+ } while ((depth_ok == false) && (i < ARRAY_SIZE(margin_arr)));
+
+ if (depth_ok) {
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+
+ if (ED_view3d_unproject(ar, centx, centy, depth_close, mouse_worldloc)) {
+ return true;
+ }
+ }
+
+ if (fallback_depth_pt) {
+ ED_view3d_win_to_3d_int(v3d, ar, fallback_depth_pt, mval, mouse_worldloc);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+void ED_view3d_autodist_init(
+ const EvaluationContext *eval_ctx, struct Depsgraph *graph,
+ ARegion *ar, View3D *v3d, int mode)
+{
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ switch (mode) {
+ case 0:
+ ED_view3d_draw_depth(eval_ctx, graph, ar, v3d, true);
+ break;
+ case 1:
+ {
+ Scene *scene = DEG_get_evaluated_scene(graph);
+ ED_view3d_draw_depth_gpencil(eval_ctx, scene, ar, v3d);
+ break;
+ }
+ }
+}
+
+/* no 4x4 sampling, run #ED_view3d_autodist_init first */
+bool ED_view3d_autodist_simple(ARegion *ar, const int mval[2], float mouse_worldloc[3],
+ int margin, float *force_depth)
+{
+ float depth;
+
+ /* Get Z Depths, needed for perspective, nice for ortho */
+ if (force_depth)
+ depth = *force_depth;
+ else
+ depth = view_autodist_depth_margin(ar, mval, margin);
+
+ if (depth == FLT_MAX)
+ return false;
+
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, mouse_worldloc);
+}
+
+bool ED_view3d_autodist_depth(ARegion *ar, const int mval[2], int margin, float *depth)
+{
+ *depth = view_autodist_depth_margin(ar, mval, margin);
+
+ return (*depth != FLT_MAX);
+}
+
+static bool depth_segment_cb(int x, int y, void *userData)
+{
+ struct { ARegion *ar; int margin; float depth; } *data = userData;
+ int mval[2];
+ float depth;
+
+ mval[0] = x;
+ mval[1] = y;
+
+ depth = view_autodist_depth_margin(data->ar, mval, data->margin);
+
+ if (depth != FLT_MAX) {
+ data->depth = depth;
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+bool ED_view3d_autodist_depth_seg(
+ ARegion *ar, const int mval_sta[2], const int mval_end[2],
+ int margin, float *depth)
+{
+ struct { ARegion *ar; int margin; float depth; } data = {NULL};
+ int p1[2];
+ int p2[2];
+
+ data.ar = ar;
+ data.margin = margin;
+ data.depth = FLT_MAX;
+
+ copy_v2_v2_int(p1, mval_sta);
+ copy_v2_v2_int(p2, mval_end);
+
+ BLI_bitmap_draw_2d_line_v2v2i(p1, p2, depth_segment_cb, &data);
+
+ *depth = data.depth;
+
+ return (*depth != FLT_MAX);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Radius/Distance Utilities
+ *
+ * Use to calculate a distance to a point based on it's radius.
+ * \{ */
+
+float ED_view3d_radius_to_dist_persp(const float angle, const float radius)
+{
+ return radius * (1.0f / tanf(angle / 2.0f));
+}
+
+float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
+{
+ return radius / (DEFAULT_SENSOR_WIDTH / lens);
+}
+
+/**
+ * Return a new RegionView3D.dist value to fit the \a radius.
+ *
+ * \note Depth isn't taken into account, this will fit a flat plane exactly,
+ * but points towards the view (with a perspective projection),
+ * may be within the radius but outside the view. eg:
+ *
+ * <pre>
+ * +
+ * pt --> + /^ radius
+ * / |
+ * / |
+ * view + +
+ * \ |
+ * \ |
+ * \|
+ * +
+ * </pre>
+ *
+ * \param ar Can be NULL if \a use_aspect is false.
+ * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera)
+ * \param use_aspect Increase the distance to account for non 1:1 view aspect.
+ * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN).
+ */
+float ED_view3d_radius_to_dist(
+ const View3D *v3d, const ARegion *ar,
+ const char persp, const bool use_aspect,
+ const float radius)
+{
+ float dist;
+
+ BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB));
+ BLI_assert((persp != RV3D_CAMOB) || v3d->camera);
+
+ if (persp == RV3D_ORTHO) {
+ dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius);
+ }
+ else {
+ float lens, sensor_size, zoom;
+ float angle;
+
+ if (persp == RV3D_CAMOB) {
+ CameraParams params;
+ BKE_camera_params_init(&params);
+ params.clipsta = v3d->near;
+ params.clipend = v3d->far;
+ BKE_camera_params_from_object(&params, v3d->camera);
+
+ lens = params.lens;
+ sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
+
+ /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */
+ zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
+ }
+ else {
+ lens = v3d->lens;
+ sensor_size = DEFAULT_SENSOR_WIDTH;
+ zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
+ }
+
+ angle = focallength_to_fov(lens, sensor_size);
+
+ /* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */
+ angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f;
+
+ dist = ED_view3d_radius_to_dist_persp(angle, radius);
+ }
+
+ if (use_aspect) {
+ const RegionView3D *rv3d = ar->regiondata;
+
+ float winx, winy;
+
+ if (persp == RV3D_CAMOB) {
+ /* camera frame x/y in pixels */
+ winx = ar->winx / rv3d->viewcamtexcofac[0];
+ winy = ar->winy / rv3d->viewcamtexcofac[1];
+ }
+ else {
+ winx = ar->winx;
+ winy = ar->winy;
+ }
+
+ if (winx && winy) {
+ float aspect = winx / winy;
+ if (aspect < 1.0f) {
+ aspect = 1.0f / aspect;
+ }
+ dist *= aspect;
+ }
+ }
+
+ return dist;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Distance Utilities
+ * \{ */
+
+/* problem - ofs[3] can be on same location as camera itself.
+ * Blender needs proper dist value for zoom.
+ * use fallback_dist to override small values
+ */
+float ED_view3d_offset_distance(float mat[4][4], const float ofs[3], const float fallback_dist)
+{
+ float pos[4] = {0.0f, 0.0f, 0.0f, 1.0f};
+ float dir[4] = {0.0f, 0.0f, 1.0f, 0.0f};
+ float dist;
+
+ mul_m4_v4(mat, pos);
+ add_v3_v3(pos, ofs);
+ mul_m4_v4(mat, dir);
+ normalize_v3(dir);
+
+ dist = dot_v3v3(pos, dir);
+
+ if ((dist < FLT_EPSILON) && (fallback_dist != 0.0f)) {
+ dist = fallback_dist;
+ }
+
+ return dist;
+}
+
+/**
+ * Set the dist without moving the view (compensate with #RegionView3D.ofs)
+ *
+ * \note take care that viewinv is up to date, #ED_view3d_update_viewmat first.
+ */
+void ED_view3d_distance_set(RegionView3D *rv3d, const float dist)
+{
+ float viewinv[4];
+ float tvec[3];
+
+ BLI_assert(dist >= 0.0f);
+
+ copy_v3_fl3(tvec, 0.0f, 0.0f, rv3d->dist - dist);
+ /* rv3d->viewinv isn't always valid */
+#if 0
+ mul_mat3_m4_v3(rv3d->viewinv, tvec);
+#else
+ invert_qt_qt_normalized(viewinv, rv3d->viewquat);
+ mul_qt_v3(viewinv, tvec);
+#endif
+ sub_v3_v3(rv3d->ofs, tvec);
+
+ rv3d->dist = dist;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Axis Utilities
+ * \{ */
+static float view3d_quat_axis[6][4] = {
+ {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */
+ {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */
+ {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */
+ {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */
+ {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */
+ {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */
+};
+
+
+bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
+{
+ if (RV3D_VIEW_IS_AXIS(view)) {
+ copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]);
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon)
+{
+ /* quat values are all unit length */
+
+ char view;
+
+ for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
+ if (fabsf(angle_signed_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT])) < epsilon) {
+ return view;
+ }
+ }
+
+ return RV3D_VIEW_USER;
+}
+
+char ED_view3d_lock_view_from_index(int index)
+{
+ switch (index) {
+ case 0: return RV3D_VIEW_FRONT;
+ case 1: return RV3D_VIEW_TOP;
+ case 2: return RV3D_VIEW_RIGHT;
+ default: return RV3D_VIEW_USER;
+ }
+
+}
+
+char ED_view3d_axis_view_opposite(char view)
+{
+ switch (view) {
+ case RV3D_VIEW_FRONT: return RV3D_VIEW_BACK;
+ case RV3D_VIEW_BACK: return RV3D_VIEW_FRONT;
+ case RV3D_VIEW_LEFT: return RV3D_VIEW_RIGHT;
+ case RV3D_VIEW_RIGHT: return RV3D_VIEW_LEFT;
+ case RV3D_VIEW_TOP: return RV3D_VIEW_BOTTOM;
+ case RV3D_VIEW_BOTTOM: return RV3D_VIEW_TOP;
+ }
+
+ return RV3D_VIEW_USER;
+}
+
+
+bool ED_view3d_lock(RegionView3D *rv3d)
+{
+ return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Transform Utilities
+ * \{ */
+
+/**
+ * Set the view transformation from a 4x4 matrix.
+ *
+ * \param mat The view 4x4 transformation matrix to assign.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
+ */
+void ED_view3d_from_m4(float mat[4][4], float ofs[3], float quat[4], float *dist)
+{
+ float nmat[3][3];
+
+ /* dist depends on offset */
+ BLI_assert(dist == NULL || ofs != NULL);
+
+ copy_m3_m4(nmat, mat);
+ normalize_m3(nmat);
+
+ /* Offset */
+ if (ofs)
+ negate_v3_v3(ofs, mat[3]);
+
+ /* Quat */
+ if (quat) {
+ mat3_normalized_to_quat(quat, nmat);
+ invert_qt_normalized(quat);
+ }
+
+ if (ofs && dist) {
+ madd_v3_v3fl(ofs, nmat[2], *dist);
+ }
+}
+
+/**
+ * Calculate the view transformation matrix from RegionView3D input.
+ * The resulting matrix is equivalent to RegionView3D.viewinv
+ * \param mat The view 4x4 transformation matrix to calculate.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
+ */
+void ED_view3d_to_m4(float mat[4][4], const float ofs[3], const float quat[4], const float dist)
+{
+ float iviewquat[4] = {-quat[0], quat[1], quat[2], quat[3]};
+ float dvec[3] = {0.0f, 0.0f, dist};
+
+ quat_to_mat4(mat, iviewquat);
+ mul_mat3_m4_v3(mat, dvec);
+ sub_v3_v3v3(mat[3], dvec, ofs);
+}
+
+/**
+ * Set the RegionView3D members from an objects transformation and optionally lens.
+ * \param ob The object to set the view to.
+ * \param ofs The view offset to be set, normally from RegionView3D.ofs.
+ * \param quat The view rotation to be set, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs to be set, normally from RegionView3D.dist.
+ * \param lens The view lens angle set for cameras and lamps, normally from View3D.lens.
+ */
+void ED_view3d_from_object(Object *ob, float ofs[3], float quat[4], float *dist, float *lens)
+{
+ ED_view3d_from_m4(ob->obmat, ofs, quat, dist);
+
+ if (lens) {
+ CameraParams params;
+
+ BKE_camera_params_init(&params);
+ BKE_camera_params_from_object(&params, ob);
+ *lens = params.lens;
+ }
+}
+
+/**
+ * Set the object transformation from RegionView3D members.
+ * \param ob The object which has the transformation assigned.
+ * \param ofs The view offset, normally from RegionView3D.ofs.
+ * \param quat The view rotation, quaternion normally from RegionView3D.viewquat.
+ * \param dist The view distance from ofs, normally from RegionView3D.dist.
+ */
+void ED_view3d_to_object(Object *ob, const float ofs[3], const float quat[4], const float dist)
+{
+ float mat[4][4];
+ ED_view3d_to_m4(mat, ofs, quat, dist);
+ BKE_object_apply_mat4(ob, mat, true, true);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Depth Buffer Utilities
+ * \{ */
+
+float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2])
+{
+ ViewDepths *vd = vc->rv3d->depths;
+
+ int x = mval[0];
+ int y = mval[1];
+
+ if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) {
+ return vd->depths[y * vd->w + x];
+ }
+ else {
+ BLI_assert(1.0 <= vd->depth_range[1]);
+ return 1.0f;
+ }
+}
+
+bool ED_view3d_depth_read_cached_normal(
+ const ViewContext *vc, const int mval[2],
+ float r_normal[3])
+{
+ /* Note: we could support passing in a radius.
+ * For now just read 9 pixels. */
+
+ /* pixels surrounding */
+ bool depths_valid[9] = {false};
+ float coords[9][3] = {{0}};
+
+ ARegion *ar = vc->ar;
+ const ViewDepths *depths = vc->rv3d->depths;
+
+ for (int x = 0, i = 0; x < 2; x++) {
+ for (int y = 0; y < 2; y++) {
+ const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
+
+ const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
+ if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
+ if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) {
+ depths_valid[i] = true;
+ }
+ }
+ i++;
+ }
+ }
+
+ const int edges[2][6][2] = {
+ /* x edges */
+ {{0, 1}, {1, 2},
+ {3, 4}, {4, 5},
+ {6, 7}, {7, 8}},
+ /* y edges */
+ {{0, 3}, {3, 6},
+ {1, 4}, {4, 7},
+ {2, 5}, {5, 8}},
+ };
+
+ float cross[2][3] = {{0.0f}};
+
+ for (int i = 0; i < 6; i++) {
+ for (int axis = 0; axis < 2; axis++) {
+ if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) {
+ float delta[3];
+ sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]);
+ add_v3_v3(cross[axis], delta);
+ }
+ }
+ }
+
+ cross_v3_v3v3(r_normal, cross[0], cross[1]);
+
+ if (normalize_v3(r_normal) != 0.0f) {
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+bool ED_view3d_depth_unproject(
+ const ARegion *ar,
+ const int mval[2], const double depth,
+ float r_location_world[3])
+{
+ float centx = (float)mval[0] + 0.5f;
+ float centy = (float)mval[1] + 0.5f;
+ return ED_view3d_unproject(ar, centx, centy, depth, r_location_world);
+}
+
+void ED_view3d_depth_tag_update(RegionView3D *rv3d)
+{
+ if (rv3d->depths)
+ rv3d->depths->damaged = true;
+}
+
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 882f0ec0bc0..0597f2806b3 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -28,7 +28,6 @@
* \ingroup spview3d
*/
-
#include "DNA_camera_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -39,7 +38,6 @@
#include "BLI_rect.h"
#include "BLI_utildefines.h"
-#include "BKE_anim.h"
#include "BKE_action.h"
#include "BKE_camera.h"
#include "BKE_context.h"
@@ -48,12 +46,9 @@
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
-#include "BKE_screen.h"
#include "DEG_depsgraph.h"
-#include "BIF_glutil.h"
-
#include "UI_resources.h"
#include "GPU_glew.h"
@@ -64,10 +59,10 @@
#include "WM_types.h"
#include "ED_screen.h"
-#include "ED_armature.h"
#include "DRW_engine.h"
+#include "DEG_depsgraph_query.h"
#ifdef WITH_GAMEENGINE
# include "BLI_listbase.h"
@@ -78,53 +73,14 @@
# include "BL_System.h"
#endif
-
#include "view3d_intern.h" /* own include */
-/* use this call when executing an operator,
- * event system doesn't set for each event the
- * opengl drawing context */
-void view3d_operator_needs_opengl(const bContext *C)
-{
- wmWindow *win = CTX_wm_window(C);
- ARegion *ar = CTX_wm_region(C);
-
- view3d_region_operator_needs_opengl(win, ar);
-}
-
-void view3d_region_operator_needs_opengl(wmWindow *win, ARegion *ar)
-{
- /* for debugging purpose, context should always be OK */
- if ((ar == NULL) || (ar->regiontype != RGN_TYPE_WINDOW)) {
- printf("view3d_region_operator_needs_opengl error, wrong region\n");
- }
- else {
- RegionView3D *rv3d = ar->regiondata;
-
- wmSubWindowSet(win, ar->swinid);
- gpuLoadProjectionMatrix(rv3d->winmat);
- gpuLoadMatrix(rv3d->viewmat);
- }
-}
-
-float *ED_view3d_cursor3d_get(Scene *scene, View3D *v3d)
-{
- if (v3d && v3d->localvd) return v3d->cursor;
- else return scene->cursor;
-}
-
-Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
-{
- /* establish the camera object, so we can default to view mapping if anything is wrong with it */
- if ((rv3d->persp == RV3D_CAMOB) && v3d->camera && (v3d->camera->type == OB_CAMERA)) {
- return v3d->camera->data;
- }
- else {
- return NULL;
- }
-}
+/* -------------------------------------------------------------------- */
+/** \name Smooth View Operator & Utilities
+ *
+ * Use for view transitions to have smooth (animated) transitions.
+ * \{ */
-/* ****************** smooth view operator ****************** */
/* This operator is one of the 'timer refresh' ones like animation playback */
struct SmoothView3DState {
@@ -273,7 +229,7 @@ void ED_view3d_smooth_view_ex(
* this means small rotations wont lag */
if (sview->quat && !sview->ofs && !sview->dist) {
/* scale the time allowed by the rotation */
- sms.time_allowed *= (double)angle_normalized_qtqt(sms.dst.quat, sms.src.quat) / M_PI; /* 180deg == 1.0 */
+ sms.time_allowed *= (double)fabsf(angle_signed_normalized_qtqt(sms.dst.quat, sms.src.quat)) / M_PI; /* 180deg == 1.0 */
}
/* ensure it shows correct */
@@ -401,6 +357,8 @@ static void view3d_smoothview_apply(bContext *C, View3D *v3d, ARegion *ar, bool
ED_view3d_camera_lock_autokey(v3d, rv3d, C, true, true);
}
+ /* Event handling won't know if a UI item has been moved under the pointer. */
+ WM_event_add_mousemove(C);
}
if (sync_boxview && (rv3d->viewlock & RV3D_BOXVIEW)) {
@@ -462,22 +420,25 @@ void ED_view3d_smooth_view_force_finish(
void VIEW3D_OT_smoothview(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Smooth View";
ot->description = "";
ot->idname = "VIEW3D_OT_smoothview";
-
+
/* api callbacks */
ot->invoke = view3d_smoothview_invoke;
-
+
/* flags */
ot->flag = OPTYPE_INTERNAL;
ot->poll = ED_operator_view3d_active;
}
-/* ****************** change view operators ****************** */
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Camera to View Operator
+ * \{ */
static int view3d_camera_to_view_exec(bContext *C, wmOperator *UNUSED(op))
{
@@ -541,6 +502,12 @@ void VIEW3D_OT_camera_to_view(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Camera Fit Frame to Selected Operator
+ * \{ */
+
/* unlike VIEW3D_OT_view_selected this is for framing a render and not
* meant to take into account vertex/bone selection for eg. */
static int view3d_camera_to_view_selected_exec(bContext *C, wmOperator *op)
@@ -600,6 +567,12 @@ void VIEW3D_OT_camera_to_view_selected(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Object as Camera Operator
+ * \{ */
+
static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob, const int smooth_viewtx)
{
Main *bmain = CTX_data_main(C);
@@ -650,7 +623,7 @@ static void sync_viewport_camera_smoothview(bContext *C, View3D *v3d, Object *ob
}
static int view3d_setobjectascamera_exec(bContext *C, wmOperator *op)
-{
+{
View3D *v3d;
ARegion *ar;
RegionView3D *rv3d;
@@ -703,7 +676,6 @@ int ED_operator_rv3d_user_region_poll(bContext *C)
void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Set Active Object as Camera";
ot->description = "Set the active object as the active camera for this view or scene";
@@ -717,289 +689,23 @@ void VIEW3D_OT_object_as_camera(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
-/* ********************************** */
-
-void ED_view3d_clipping_calc_from_boundbox(float clip[4][4], const BoundBox *bb, const bool is_flip)
-{
- int val;
-
- for (val = 0; val < 4; val++) {
- normal_tri_v3(clip[val], bb->vec[val], bb->vec[val == 3 ? 0 : val + 1], bb->vec[val + 4]);
- if (UNLIKELY(is_flip)) {
- negate_v3(clip[val]);
- }
-
- clip[val][3] = -dot_v3v3(clip[val], bb->vec[val]);
- }
-}
-
-void ED_view3d_clipping_calc(BoundBox *bb, float planes[4][4], const ARegion *ar, const Object *ob, const rcti *rect)
-{
- /* init in case unproject fails */
- memset(bb->vec, 0, sizeof(bb->vec));
-
- /* four clipping planes and bounding volume */
- /* first do the bounding volume */
- for (int val = 0; val < 4; val++) {
- float xs = (val == 0 || val == 3) ? rect->xmin : rect->xmax;
- float ys = (val == 0 || val == 1) ? rect->ymin : rect->ymax;
-
- ED_view3d_unproject(ar, xs, ys, 0.0, bb->vec[val]);
- ED_view3d_unproject(ar, xs, ys, 1.0, bb->vec[4 + val]);
- }
-
- /* optionally transform to object space */
- if (ob) {
- float imat[4][4];
- invert_m4_m4(imat, ob->obmat);
-
- for (int val = 0; val < 8; val++) {
- mul_m4_v3(imat, bb->vec[val]);
- }
- }
-
- /* verify if we have negative scale. doing the transform before cross
- * product flips the sign of the vector compared to doing cross product
- * before transform then, so we correct for that. */
- int flip_sign = (ob) ? is_negative_m4(ob->obmat) : false;
-
- ED_view3d_clipping_calc_from_boundbox(planes, bb, flip_sign);
-}
-
-static bool view3d_boundbox_clip_m4(const BoundBox *bb, float persmatob[4][4])
-{
- int a, flag = -1, fl;
-
- for (a = 0; a < 8; a++) {
- float vec[4], min, max;
- copy_v3_v3(vec, bb->vec[a]);
- vec[3] = 1.0;
- mul_m4_v4(persmatob, vec);
- max = vec[3];
- min = -vec[3];
-
- fl = 0;
- if (vec[0] < min) fl += 1;
- if (vec[0] > max) fl += 2;
- if (vec[1] < min) fl += 4;
- if (vec[1] > max) fl += 8;
- if (vec[2] < min) fl += 16;
- if (vec[2] > max) fl += 32;
-
- flag &= fl;
- if (flag == 0) return true;
- }
-
- return false;
-}
-
-bool ED_view3d_boundbox_clip_ex(const RegionView3D *rv3d, const BoundBox *bb, float obmat[4][4])
-{
- /* return 1: draw */
-
- float persmatob[4][4];
-
- if (bb == NULL) return true;
- if (bb->flag & BOUNDBOX_DISABLED) return true;
-
- mul_m4_m4m4(persmatob, (float(*)[4])rv3d->persmat, obmat);
-
- return view3d_boundbox_clip_m4(bb, persmatob);
-}
-
-bool ED_view3d_boundbox_clip(RegionView3D *rv3d, const BoundBox *bb)
-{
- if (bb == NULL) return true;
- if (bb->flag & BOUNDBOX_DISABLED) return true;
-
- return view3d_boundbox_clip_m4(bb, rv3d->persmatob);
-}
+/** \} */
/* -------------------------------------------------------------------- */
-
-/** \name Depth Utilities
+/** \name Window and View Matrix Calculation
* \{ */
-float ED_view3d_depth_read_cached(const ViewContext *vc, const int mval[2])
-{
- ViewDepths *vd = vc->rv3d->depths;
-
- int x = mval[0];
- int y = mval[1];
-
- if (vd && vd->depths && x > 0 && y > 0 && x < vd->w && y < vd->h) {
- return vd->depths[y * vd->w + x];
- }
- else {
- BLI_assert(1.0 <= vd->depth_range[1]);
- return 1.0f;
- }
-}
-
-bool ED_view3d_depth_read_cached_normal(
- const ViewContext *vc, const int mval[2],
- float r_normal[3])
-{
- /* Note: we could support passing in a radius.
- * For now just read 9 pixels. */
-
- /* pixels surrounding */
- bool depths_valid[9] = {false};
- float coords[9][3] = {{0}};
-
- ARegion *ar = vc->ar;
- const ViewDepths *depths = vc->rv3d->depths;
-
- for (int x = 0, i = 0; x < 2; x++) {
- for (int y = 0; y < 2; y++) {
- const int mval_ofs[2] = {mval[0] + (x - 1), mval[1] + (y - 1)};
-
- const double depth = (double)ED_view3d_depth_read_cached(vc, mval_ofs);
- if ((depth > depths->depth_range[0]) && (depth < depths->depth_range[1])) {
- if (ED_view3d_depth_unproject(ar, mval_ofs, depth, coords[i])) {
- depths_valid[i] = true;
- }
- }
- i++;
- }
- }
-
- const int edges[2][6][2] = {
- /* x edges */
- {{0, 1}, {1, 2},
- {3, 4}, {4, 5},
- {6, 7}, {7, 8}},
- /* y edges */
- {{0, 3}, {3, 6},
- {1, 4}, {4, 7},
- {2, 5}, {5, 8}},
- };
-
- float cross[2][3] = {{0.0f}};
-
- for (int i = 0; i < 6; i++) {
- for (int axis = 0; axis < 2; axis++) {
- if (depths_valid[edges[axis][i][0]] && depths_valid[edges[axis][i][1]]) {
- float delta[3];
- sub_v3_v3v3(delta, coords[edges[axis][i][0]], coords[edges[axis][i][1]]);
- add_v3_v3(cross[axis], delta);
- }
- }
- }
-
- cross_v3_v3v3(r_normal, cross[0], cross[1]);
-
- if (normalize_v3(r_normal) != 0.0f) {
- return true;
- }
- else {
- return false;
- }
-}
-
-bool ED_view3d_depth_unproject(
- const ARegion *ar,
- const int mval[2], const double depth,
- float r_location_world[3])
-{
- float centx = (float)mval[0] + 0.5f;
- float centy = (float)mval[1] + 0.5f;
- return ED_view3d_unproject(ar, centx, centy, depth, r_location_world);
-}
-
-/** \} */
-
-void ED_view3d_depth_tag_update(RegionView3D *rv3d)
-{
- if (rv3d->depths)
- rv3d->depths->damaged = true;
-}
-
-void ED_view3d_dist_range_get(
- const View3D *v3d,
- float r_dist_range[2])
-{
- r_dist_range[0] = v3d->grid * 0.001f;
- r_dist_range[1] = v3d->far * 10.0f;
-}
-
-/* copies logic of get_view3d_viewplane(), keep in sync */
-bool ED_view3d_clip_range_get(
- const View3D *v3d, const RegionView3D *rv3d,
- float *r_clipsta, float *r_clipend,
- const bool use_ortho_factor)
-{
- CameraParams params;
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, v3d, rv3d);
-
- if (use_ortho_factor && params.is_ortho) {
- const float fac = 2.0f / (params.clipend - params.clipsta);
- params.clipsta *= fac;
- params.clipend *= fac;
- }
-
- if (r_clipsta) *r_clipsta = params.clipsta;
- if (r_clipend) *r_clipend = params.clipend;
-
- return params.is_ortho;
-}
-
-bool ED_view3d_viewplane_get(
- const View3D *v3d, const RegionView3D *rv3d, int winx, int winy,
- rctf *r_viewplane, float *r_clipsta, float *r_clipend, float *r_pixsize)
-{
- CameraParams params;
-
- BKE_camera_params_init(&params);
- BKE_camera_params_from_view3d(&params, v3d, rv3d);
- BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
-
- if (r_viewplane) *r_viewplane = params.viewplane;
- if (r_clipsta) *r_clipsta = params.clipsta;
- if (r_clipend) *r_clipend = params.clipend;
- if (r_pixsize) *r_pixsize = params.viewdx;
-
- return params.is_ortho;
-}
-
-/**
- * Use instead of: ``bglPolygonOffset(rv3d->dist, ...)`` see bug [#37727]
- */
-void ED_view3d_polygon_offset(const RegionView3D *rv3d, const float dist)
-{
- float viewdist;
-
- if (rv3d->rflag & RV3D_ZOFFSET_DISABLED) {
- return;
- }
-
- viewdist = rv3d->dist;
-
- /* special exception for ortho camera (viewdist isnt used for perspective cameras) */
- if (dist != 0.0f) {
- if (rv3d->persp == RV3D_CAMOB) {
- if (rv3d->is_persp == false) {
- viewdist = 1.0f / max_ff(fabsf(rv3d->winmat[0][0]), fabsf(rv3d->winmat[1][1]));
- }
- }
- }
-
- bglPolygonOffset(viewdist, dist);
-}
-
/**
* \param rect optional for picking (can be NULL).
*/
-void view3d_winmatrix_set(ARegion *ar, const View3D *v3d, const rcti *rect)
+void view3d_winmatrix_set(const Depsgraph *depsgraph, ARegion *ar, const View3D *v3d, const rcti *rect)
{
RegionView3D *rv3d = ar->regiondata;
rctf viewplane;
float clipsta, clipend;
bool is_ortho;
- is_ortho = ED_view3d_viewplane_get(v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
+ is_ortho = ED_view3d_viewplane_get(depsgraph, v3d, rv3d, ar->winx, ar->winy, &viewplane, &clipsta, &clipend, NULL);
rv3d->is_persp = !is_ortho;
#if 0
@@ -1041,80 +747,28 @@ static void obmat_to_viewmat(RegionView3D *rv3d, Object *ob)
mat4_normalized_to_quat(rv3d->viewquat, rv3d->viewmat);
}
-static float view3d_quat_axis[6][4] = {
- {M_SQRT1_2, -M_SQRT1_2, 0.0f, 0.0f}, /* RV3D_VIEW_FRONT */
- {0.0f, 0.0f, -M_SQRT1_2, -M_SQRT1_2}, /* RV3D_VIEW_BACK */
- {0.5f, -0.5f, 0.5f, 0.5f}, /* RV3D_VIEW_LEFT */
- {0.5f, -0.5f, -0.5f, -0.5f}, /* RV3D_VIEW_RIGHT */
- {1.0f, 0.0f, 0.0f, 0.0f}, /* RV3D_VIEW_TOP */
- {0.0f, -1.0f, 0.0f, 0.0f}, /* RV3D_VIEW_BOTTOM */
-};
-
-
-bool ED_view3d_quat_from_axis_view(const char view, float quat[4])
-{
- if (RV3D_VIEW_IS_AXIS(view)) {
- copy_qt_qt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]);
- return true;
- }
- else {
- return false;
- }
-}
-
-char ED_view3d_quat_to_axis_view(const float quat[4], const float epsilon)
-{
- /* quat values are all unit length */
-
- char view;
-
- for (view = RV3D_VIEW_FRONT; view <= RV3D_VIEW_BOTTOM; view++) {
- if (angle_qtqt(quat, view3d_quat_axis[view - RV3D_VIEW_FRONT]) < epsilon) {
- return view;
- }
- }
-
- return RV3D_VIEW_USER;
-}
-
-char ED_view3d_lock_view_from_index(int index)
-{
- switch (index) {
- case 0: return RV3D_VIEW_FRONT;
- case 1: return RV3D_VIEW_TOP;
- case 2: return RV3D_VIEW_RIGHT;
- default: return RV3D_VIEW_USER;
- }
-
-}
-
-char ED_view3d_axis_view_opposite(char view)
-{
- switch (view) {
- case RV3D_VIEW_FRONT: return RV3D_VIEW_BACK;
- case RV3D_VIEW_BACK: return RV3D_VIEW_FRONT;
- case RV3D_VIEW_LEFT: return RV3D_VIEW_RIGHT;
- case RV3D_VIEW_RIGHT: return RV3D_VIEW_LEFT;
- case RV3D_VIEW_TOP: return RV3D_VIEW_BOTTOM;
- case RV3D_VIEW_BOTTOM: return RV3D_VIEW_TOP;
- }
-
- return RV3D_VIEW_USER;
-}
-
-
-bool ED_view3d_lock(RegionView3D *rv3d)
-{
- return ED_view3d_quat_from_axis_view(rv3d->view, rv3d->viewquat);
-}
-
-/* don't set windows active in here, is used by renderwin too */
-void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, const View3D *v3d, RegionView3D *rv3d)
+/**
+ * Sets #RegionView3D.viewmat
+ *
+ * \param eval_ctx: Context.
+ * \param scene: Scene for camera and cursor location.
+ * \param v3d: View 3D space data.
+ * \param rv3d: 3D region which stores the final matrices.
+ * \param rect_scale: Optional 2D scale argument,
+ * Use when displaying a sub-region, eg: when #view3d_winmatrix_set takes a 'rect' argument.
+ *
+ * \note don't set windows active in here, is used by renderwin too.
+ */
+void view3d_viewmatrix_set(
+ const EvaluationContext *eval_ctx, Scene *scene,
+ const View3D *v3d, RegionView3D *rv3d, const float rect_scale[2])
{
if (rv3d->persp == RV3D_CAMOB) { /* obs/camera */
if (v3d->camera) {
- BKE_object_where_is_calc(eval_ctx, scene, v3d->camera);
- obmat_to_viewmat(rv3d, v3d->camera);
+ const Depsgraph *depsgraph = eval_ctx->depsgraph;
+ Object *camera_object = DEG_get_evaluated_object(depsgraph, v3d->camera);
+ BKE_object_where_is_calc(eval_ctx, scene, camera_object);
+ obmat_to_viewmat(rv3d, camera_object);
}
else {
quat_to_mat4(rv3d->viewmat, rv3d->viewquat);
@@ -1168,6 +822,17 @@ void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, cons
mul_v2_v2fl(vec, rv3d->ofs_lock, rv3d->is_persp ? rv3d->dist : 1.0f);
vec[2] = 0.0f;
+
+ if (rect_scale) {
+ /* Since 'RegionView3D.winmat' has been calculated and this function doesn't take the 'ARegion'
+ * we don't know about the region size.
+ * Use 'rect_scale' when drawing a sub-region to apply 2D offset,
+ * scaled by the difference between the sub-region and the region size.
+ */
+ vec[0] /= rect_scale[0];
+ vec[1] /= rect_scale[1];
+ }
+
mul_mat3_m4_v3(persinv, vec);
translate_m4(rv3d->viewmat, vec[0], vec[1], vec[2]);
}
@@ -1175,6 +840,12 @@ void view3d_viewmatrix_set(const EvaluationContext *eval_ctx, Scene *scene, cons
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name OpenGL Select Utilities
+ * \{ */
+
/**
* Optionally cache data for multiple calls to #view3d_opengl_select
*
@@ -1326,6 +997,12 @@ finally:
return hits;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name View Layer Utilities
+ * \{ */
+
int ED_view3d_view_layer_set(int lay, const int *values, int *active)
{
int i, tot = 0;
@@ -1364,43 +1041,43 @@ int ED_view3d_view_layer_set(int lay, const int *values, int *active)
return lay;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Game Engine Operator
+ *
+ * Start the game engine (handles context switching).
+ * \{ */
+
#ifdef WITH_GAMEENGINE
static ListBase queue_back;
-static void SaveState(bContext *C, wmWindow *win)
+static void game_engine_save_state(bContext *C, wmWindow *win)
{
Object *obact = CTX_data_active_object(C);
-
+
glPushAttrib(GL_ALL_ATTRIB_BITS);
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
GPU_paint_set_mipmap(1);
-
+
queue_back = win->queue;
-
+
BLI_listbase_clear(&win->queue);
-
- //XXX waitcursor(1);
}
-static void RestoreState(bContext *C, wmWindow *win)
+static void game_engine_restore_state(bContext *C, wmWindow *win)
{
Object *obact = CTX_data_active_object(C);
-
+
if (obact && obact->mode & OB_MODE_TEXTURE_PAINT)
GPU_paint_set_mipmap(0);
- //XXX curarea->win_swap = 0;
- //XXX curarea->head_swap = 0;
- //XXX allqueue(REDRAWVIEW3D, 1);
- //XXX allqueue(REDRAWBUTSALL, 0);
- //XXX reset_slowparents();
- //XXX waitcursor(0);
- //XXX G.qual = 0;
-
- if (win) /* check because closing win can set to NULL */
+ /* check because closing win can set to NULL */
+ if (win) {
win->queue = queue_back;
-
+ }
+
GPU_state_init();
glPopAttrib();
@@ -1471,33 +1148,6 @@ static int game_engine_poll(bContext *C)
return 1;
}
-bool ED_view3d_context_activate(bContext *C)
-{
- bScreen *sc = CTX_wm_screen(C);
- ScrArea *sa = CTX_wm_area(C);
- ARegion *ar;
-
- /* sa can be NULL when called from python */
- if (sa == NULL || sa->spacetype != SPACE_VIEW3D) {
- sa = BKE_screen_find_big_area(sc, SPACE_VIEW3D, 0);
- }
-
- if (sa == NULL) {
- return false;
- }
-
- ar = BKE_area_find_region_active_win(sa);
- if (ar == NULL) {
- return false;
- }
-
- /* bad context switch .. */
- CTX_wm_area_set(C, sa);
- CTX_wm_region_set(C, ar);
-
- return true;
-}
-
static int game_engine_exec(bContext *C, wmOperator *op)
{
#ifdef WITH_GAMEENGINE
@@ -1509,12 +1159,12 @@ static int game_engine_exec(bContext *C, wmOperator *op)
RegionView3D *rv3d;
rcti cam_frame;
- (void)op; /* unused */
-
+ UNUSED_VARS(op);
+
/* bad context switch .. */
if (!ED_view3d_context_activate(C))
return OPERATOR_CANCELLED;
-
+
/* redraw to hide any menus/popups, we don't go back to
* the window manager until after this operator exits */
WM_redraw_windows(C);
@@ -1526,16 +1176,17 @@ static int game_engine_exec(bContext *C, wmOperator *op)
ar = CTX_wm_region(C);
view3d_operator_needs_opengl(C);
-
+
game_set_commmandline_options(&startscene->gm);
if ((rv3d->persp == RV3D_CAMOB) &&
(startscene->gm.framing.type == SCE_GAMEFRAMING_BARS) &&
(startscene->gm.stereoflag != STEREO_DOME))
{
+ const Depsgraph *depsgraph = CTX_data_depsgraph(C);
/* Letterbox */
rctf cam_framef;
- ED_view3d_calc_camera_border(startscene, ar, CTX_wm_view3d(C), rv3d, &cam_framef, false);
+ ED_view3d_calc_camera_border(startscene, depsgraph, ar, CTX_wm_view3d(C), rv3d, &cam_framef, false);
cam_frame.xmin = cam_framef.xmin + ar->winrct.xmin;
cam_frame.xmax = cam_framef.xmax + ar->winrct.xmin;
cam_frame.ymin = cam_framef.ymin + ar->winrct.ymin;
@@ -1550,7 +1201,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
}
- SaveState(C, prevwin);
+ game_engine_save_state(C, prevwin);
StartKetsjiShell(C, ar, &cam_frame, 1);
@@ -1559,7 +1210,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
prevwin = NULL;
CTX_wm_window_set(C, NULL);
}
-
+
ED_area_tag_redraw(CTX_wm_area(C));
if (prevwin) {
@@ -1570,7 +1221,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
CTX_wm_area_set(C, prevsa);
}
- RestoreState(C, prevwin);
+ game_engine_restore_state(C, prevwin);
//XXX restore_all_scene_cfra(scene_cfra_store);
BKE_scene_set_background(CTX_data_main(C), startscene);
@@ -1580,7 +1231,7 @@ static int game_engine_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
#else
- (void)C; /* unused */
+ UNUSED_VARS(C);
BKE_report(op->reports, RPT_ERROR, "Game engine is disabled in this build");
return OPERATOR_CANCELLED;
#endif
@@ -1588,168 +1239,15 @@ static int game_engine_exec(bContext *C, wmOperator *op)
void VIEW3D_OT_game_start(wmOperatorType *ot)
{
-
/* identifiers */
ot->name = "Start Game Engine";
ot->description = "Start game engine";
ot->idname = "VIEW3D_OT_game_start";
-
+
/* api callbacks */
ot->exec = game_engine_exec;
-
- ot->poll = game_engine_poll;
-}
-
-/* ************************************** */
-
-float ED_view3d_pixel_size(const RegionView3D *rv3d, const float co[3])
-{
- return mul_project_m4_v3_zfac((float(*)[4])rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
-}
-
-float ED_view3d_radius_to_dist_persp(const float angle, const float radius)
-{
- return radius * (1.0f / tanf(angle / 2.0f));
-}
-
-float ED_view3d_radius_to_dist_ortho(const float lens, const float radius)
-{
- return radius / (DEFAULT_SENSOR_WIDTH / lens);
-}
-
-/**
- * Return a new RegionView3D.dist value to fit the \a radius.
- *
- * \note Depth isn't taken into account, this will fit a flat plane exactly,
- * but points towards the view (with a perspective projection),
- * may be within the radius but outside the view. eg:
- *
- * <pre>
- * +
- * pt --> + /^ radius
- * / |
- * / |
- * view + +
- * \ |
- * \ |
- * \|
- * +
- * </pre>
- *
- * \param ar Can be NULL if \a use_aspect is false.
- * \param persp Allow the caller to tell what kind of perspective to use (ortho/view/camera)
- * \param use_aspect Increase the distance to account for non 1:1 view aspect.
- * \param radius The radius will be fitted exactly, typically pre-scaled by a margin (#VIEW3D_MARGIN).
- */
-float ED_view3d_radius_to_dist(
- const View3D *v3d, const ARegion *ar,
- const char persp, const bool use_aspect,
- const float radius)
-{
- float dist;
-
- BLI_assert(ELEM(persp, RV3D_ORTHO, RV3D_PERSP, RV3D_CAMOB));
- BLI_assert((persp != RV3D_CAMOB) || v3d->camera);
-
- if (persp == RV3D_ORTHO) {
- dist = ED_view3d_radius_to_dist_ortho(v3d->lens, radius);
- }
- else {
- float lens, sensor_size, zoom;
- float angle;
-
- if (persp == RV3D_CAMOB) {
- CameraParams params;
- BKE_camera_params_init(&params);
- params.clipsta = v3d->near;
- params.clipend = v3d->far;
- BKE_camera_params_from_object(&params, v3d->camera);
-
- lens = params.lens;
- sensor_size = BKE_camera_sensor_size(params.sensor_fit, params.sensor_x, params.sensor_y);
- /* ignore 'rv3d->camzoom' because we want to fit to the cameras frame */
- zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB;
- }
- else {
- lens = v3d->lens;
- sensor_size = DEFAULT_SENSOR_WIDTH;
- zoom = CAMERA_PARAM_ZOOM_INIT_PERSP;
- }
-
- angle = focallength_to_fov(lens, sensor_size);
-
- /* zoom influences lens, correct this by scaling the angle as a distance (by the zoom-level) */
- angle = atanf(tanf(angle / 2.0f) * zoom) * 2.0f;
-
- dist = ED_view3d_radius_to_dist_persp(angle, radius);
- }
-
- if (use_aspect) {
- const RegionView3D *rv3d = ar->regiondata;
-
- float winx, winy;
-
- if (persp == RV3D_CAMOB) {
- /* camera frame x/y in pixels */
- winx = ar->winx / rv3d->viewcamtexcofac[0];
- winy = ar->winy / rv3d->viewcamtexcofac[1];
- }
- else {
- winx = ar->winx;
- winy = ar->winy;
- }
-
- if (winx && winy) {
- float aspect = winx / winy;
- if (aspect < 1.0f) {
- aspect = 1.0f / aspect;
- }
- dist *= aspect;
- }
- }
-
- return dist;
-}
-
-/* view matrix properties utilities */
-
-/* unused */
-#if 0
-void ED_view3d_operator_properties_viewmat(wmOperatorType *ot)
-{
- PropertyRNA *prop;
-
- prop = RNA_def_int(ot->srna, "region_width", 0, 0, INT_MAX, "Region Width", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- prop = RNA_def_int(ot->srna, "region_height", 0, 0, INT_MAX, "Region height", "", 0, INT_MAX);
- RNA_def_property_flag(prop, PROP_HIDDEN);
-
- prop = RNA_def_float_matrix(ot->srna, "perspective_matrix", 4, 4, NULL, 0.0f, 0.0f, "", "Perspective Matrix", 0.0f, 0.0f);
- RNA_def_property_flag(prop, PROP_HIDDEN);
-}
-
-void ED_view3d_operator_properties_viewmat_set(bContext *C, wmOperator *op)
-{
- ARegion *ar = CTX_wm_region(C);
- RegionView3D *rv3d = ED_view3d_context_rv3d(C);
-
- if (!RNA_struct_property_is_set(op->ptr, "region_width"))
- RNA_int_set(op->ptr, "region_width", ar->winx);
-
- if (!RNA_struct_property_is_set(op->ptr, "region_height"))
- RNA_int_set(op->ptr, "region_height", ar->winy);
-
- if (!RNA_struct_property_is_set(op->ptr, "perspective_matrix"))
- RNA_float_set_array(op->ptr, "perspective_matrix", (float *)rv3d->persmat);
+ ot->poll = game_engine_poll;
}
-void ED_view3d_operator_properties_viewmat_get(wmOperator *op, int *winx, int *winy, float persmat[4][4])
-{
- *winx = RNA_int_get(op->ptr, "region_width");
- *winy = RNA_int_get(op->ptr, "region_height");
-
- RNA_float_get_array(op->ptr, "perspective_matrix", (float *)persmat);
-}
-#endif
+/** \} */
diff --git a/source/blender/editors/space_view3d/view3d_walk.c b/source/blender/editors/space_view3d/view3d_walk.c
index 76da1faf530..e65f9abae27 100644
--- a/source/blender/editors/space_view3d/view3d_walk.c
+++ b/source/blender/editors/space_view3d/view3d_walk.c
@@ -60,6 +60,8 @@
#include "RE_engine.h"
+#include "DEG_depsgraph.h"
+
#include "view3d_intern.h" /* own include */
#ifdef WITH_INPUT_NDOF
@@ -249,6 +251,7 @@ typedef struct WalkInfo {
RegionView3D *rv3d;
View3D *v3d;
ARegion *ar;
+ const struct Depsgraph *depsgraph;
Scene *scene;
ViewLayer *view_layer;
RenderEngineType *engine_type;
@@ -334,7 +337,7 @@ static void drawWalkPixel(const struct bContext *UNUSED(C), ARegion *ar, void *a
rctf viewborder;
if (walk->scene->camera) {
- ED_view3d_calc_camera_border(walk->scene, ar, walk->v3d, walk->rv3d, &viewborder, false);
+ ED_view3d_calc_camera_border(walk->scene, walk->depsgraph, ar, walk->v3d, walk->rv3d, &viewborder, false);
xoff = viewborder.xmin + BLI_rctf_size_x(&viewborder) * 0.5f;
yoff = viewborder.ymin + BLI_rctf_size_y(&viewborder) * 0.5f;
}
@@ -509,10 +512,14 @@ static float userdef_speed = -1.f;
static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
{
wmWindow *win = CTX_wm_window(C);
+ EvaluationContext eval_ctx;
+
+ CTX_data_eval_ctx(C, &eval_ctx);
walk->rv3d = CTX_wm_region_view3d(C);
walk->v3d = CTX_wm_view3d(C);
walk->ar = CTX_wm_region(C);
+ walk->depsgraph = CTX_data_depsgraph(C);
walk->scene = CTX_data_scene(C);
walk->view_layer = CTX_data_view_layer(C);
walk->engine_type = CTX_data_engine_type(C);
@@ -608,7 +615,7 @@ static bool initWalkInfo(bContext *C, WalkInfo *walk, wmOperator *op)
walk->ar, walk->v3d);
walk->v3d_camera_control = ED_view3d_cameracontrol_acquire(
- C, walk->scene, walk->v3d, walk->rv3d,
+ &eval_ctx, walk->scene, walk->v3d, walk->rv3d,
(U.uiflag & USER_CAM_LOCK_NO_PARENT) == 0);
/* center the mouse */
@@ -716,7 +723,7 @@ static void walkEvent(bContext *C, wmOperator *op, WalkInfo *walk, const wmEvent
return;
}
- if ((walk->is_cursor_absolute == false) && WM_event_is_absolute(event)) {
+ if ((walk->is_cursor_absolute == false) && event->is_motion_absolute) {
walk->is_cursor_absolute = true;
copy_v2_v2_int(walk->prev_mval, event->mval);
copy_v2_v2_int(walk->center_mval, event->mval);