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:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2013-03-18 04:48:59 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2013-03-18 04:48:59 +0400
commitc1ceab1281ccf061f03f8000bf190a082a5385d8 (patch)
tree01b9a9cfca80432d316bdad6c18c74eb025e9eb0 /source/blender/editors/space_view3d
parent0d9c98c4bbfbc8c70c4772086dd09a51d01921ef (diff)
parent66a35e089a64d27bfc09c2225a530069eca05875 (diff)
Merged changes in the trunk up to revision 55357.
Resolved conflicts: release/datafiles/startup.blend source/blender/editors/space_nla/nla_buttons.c Also updated source/blender/blenkernel/intern/linestyle.c as a follow-up of recent changes for the use of bool.
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/CMakeLists.txt1
-rw-r--r--source/blender/editors/space_view3d/drawmesh.c8
-rw-r--r--source/blender/editors/space_view3d/drawobject.c29
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c39
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c164
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c94
-rw-r--r--source/blender/editors/space_view3d/view3d_fly.c8
-rw-r--r--source/blender/editors/space_view3d/view3d_header.c18
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h3
-rw-r--r--source/blender/editors/space_view3d/view3d_ops.c1
-rw-r--r--source/blender/editors/space_view3d/view3d_project.c96
-rw-r--r--source/blender/editors/space_view3d/view3d_ruler.c939
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c50
-rw-r--r--source/blender/editors/space_view3d/view3d_toolbar.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c41
15 files changed, 1264 insertions, 229 deletions
diff --git a/source/blender/editors/space_view3d/CMakeLists.txt b/source/blender/editors/space_view3d/CMakeLists.txt
index 462619a7e8b..a04371a5ed9 100644
--- a/source/blender/editors/space_view3d/CMakeLists.txt
+++ b/source/blender/editors/space_view3d/CMakeLists.txt
@@ -54,6 +54,7 @@ set(SRC
view3d_iterators.c
view3d_ops.c
view3d_project.c
+ view3d_ruler.c
view3d_select.c
view3d_snap.c
view3d_toolbar.c
diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c
index 2cef10e1981..9000ccbf324 100644
--- a/source/blender/editors/space_view3d/drawmesh.c
+++ b/source/blender/editors/space_view3d/drawmesh.c
@@ -428,7 +428,9 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int
return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
}
else if (!has_mcol) {
- if (tface) glColor3f(1.0, 1.0, 1.0);
+ if (tface) {
+ glColor3f(1.0, 1.0, 1.0);
+ }
else {
if (ma) {
float col[3];
@@ -437,7 +439,9 @@ static DMDrawOption draw_tface__set_draw_legacy(MTFace *tface, int has_mcol, int
glColor3fv(col);
}
- else glColor3f(1.0, 1.0, 1.0);
+ else {
+ glColor3f(1.0, 1.0, 1.0);
+ }
}
return DM_DRAW_OPTION_NO_MCOL; /* Don't set color */
}
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 158b75c494a..743b53ce16c 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -615,7 +615,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char
glColor4fv(ob->col);
/* Draw the Image on the screen */
- glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, ibuf->rect);
+ glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
glDisable(GL_BLEND);
@@ -812,17 +812,6 @@ void view3d_cached_text_draw_end(View3D *v3d, ARegion *ar, int depth_write, floa
}
for (vos = strings->first; vos; vos = vos->next) {
- /* too slow, reading opengl info while drawing is very bad,
- * better to see if we can use the zbuffer while in pixel space - campbell */
-#if 0
- if (v3d->zbuf && (vos->flag & V3D_CACHE_TEXT_ZBUF)) {
- gluProject(vos->vec[0], vos->vec[1], vos->vec[2], mats.modelview, mats.projection, (GLint *)mats.viewport, &ux, &uy, &uz);
- glReadPixels(ar->winrct.xmin + vos->mval[0] + vos->xoffs, ar->winrct.ymin + vos->mval[1], 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &depth);
-
- if (uz > depth)
- continue;
- }
-#endif
if (vos->sco[0] != IS_CLIPPED) {
const char *str = (char *)(vos + 1);
@@ -3862,7 +3851,7 @@ static int drawDispList(Scene *scene, View3D *v3d, RegionView3D *rv3d, Base *bas
if (v3d->flag2 & V3D_BACKFACE_CULLING) {
/* not all displists use same in/out normal direction convention */
glEnable(GL_CULL_FACE);
- glCullFace((base->object->type == OB_MBALL) ? GL_BACK : GL_FRONT);
+ glCullFace((base->object->type == OB_MBALL || base->object->derivedFinal) ? GL_BACK : GL_FRONT);
}
retval = drawDispList_nobackface(scene, v3d, rv3d, base, dt, dflag, ob_wire_col);
@@ -3968,7 +3957,9 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
if (draw_as == PART_DRAW_AXIS) {
copy_v3_v3(vec2, state->co);
}
- else sub_v3_v3v3(vec2, state->co, vec);
+ else {
+ sub_v3_v3v3(vec2, state->co, vec);
+ }
add_v3_v3(vec, state->co);
copy_v3_v3(pdd->vd, vec); pdd->vd += 3;
@@ -3980,7 +3971,9 @@ static void draw_particle(ParticleKey *state, int draw_as, short draw, float pix
if (draw_as == PART_DRAW_AXIS) {
copy_v3_v3(vec2, state->co);
}
- else sub_v3_v3v3(vec2, state->co, vec);
+ else {
+ sub_v3_v3v3(vec2, state->co, vec);
+ }
add_v3_v3(vec, state->co);
@@ -6055,8 +6048,10 @@ static void drawtexspace(Object *ob)
copy_v3_v3(size, mb->size);
copy_v3_v3(loc, mb->loc);
}
- else return;
-
+ else {
+ return;
+ }
+
vec[0][0] = vec[1][0] = vec[2][0] = vec[3][0] = loc[0] - size[0];
vec[4][0] = vec[5][0] = vec[6][0] = vec[7][0] = loc[0] + size[0];
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 57755231240..d332fb9f8b3 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -48,10 +48,12 @@
#include "BKE_object.h"
#include "BKE_screen.h"
+#include "ED_render.h"
#include "ED_space_api.h"
#include "ED_screen.h"
#include "ED_object.h"
+#include "GPU_extensions.h"
#include "GPU_material.h"
#include "BIF_gl.h"
@@ -350,7 +352,7 @@ static void view3d_free(SpaceLink *sl)
/* spacetype; init callback */
-static void view3d_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
+static void view3d_init(wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa))
{
}
@@ -469,7 +471,22 @@ static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar)
}
-static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static void view3d_main_area_exit(wmWindowManager *UNUSED(wm), ARegion *ar)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->render_engine) {
+ RE_engine_free(rv3d->render_engine);
+ rv3d->render_engine = NULL;
+ }
+
+ if (rv3d->gpuoffscreen) {
+ GPU_offscreen_free(rv3d->gpuoffscreen);
+ rv3d->gpuoffscreen = NULL;
+ }
+}
+
+static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = (ID *)drag->poin;
@@ -479,7 +496,7 @@ static int view3d_ob_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSE
return 0;
}
-static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = (ID *)drag->poin;
@@ -489,7 +506,7 @@ static int view3d_group_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UN
return 0;
}
-static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = (ID *)drag->poin;
@@ -499,7 +516,7 @@ static int view3d_mat_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUS
return 0;
}
-static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event))
+static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, const wmEvent *UNUSED(event))
{
if (drag->type == WM_DRAG_ID) {
ID *id = (ID *)drag->poin;
@@ -513,7 +530,7 @@ static int view3d_ima_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUS
return 0;
}
-static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
if (event->ctrl)
return false;
@@ -524,7 +541,7 @@ static int view3d_ima_bg_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
return 0;
}
-static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
@@ -535,7 +552,7 @@ static int view3d_ima_empty_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
return 0;
}
-static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, wmEvent *event)
+static int view3d_ima_mesh_drop_poll(bContext *C, wmDrag *drag, const wmEvent *event)
{
Base *base = ED_view3d_give_base_under_cursor(C, event->mval);
@@ -615,6 +632,10 @@ static void view3d_main_area_free(ARegion *ar)
if (rv3d->sms) {
MEM_freeN(rv3d->sms);
}
+ if (rv3d->gpuoffscreen) {
+ GPU_offscreen_free(rv3d->gpuoffscreen);
+ }
+
MEM_freeN(rv3d);
ar->regiondata = NULL;
}
@@ -633,6 +654,7 @@ static void *view3d_main_area_duplicate(void *poin)
new->clipbb = MEM_dupallocN(rv3d->clipbb);
new->depths = NULL;
+ new->gpuoffscreen = NULL;
new->ri = NULL;
new->render_engine = NULL;
new->gpd = NULL;
@@ -1216,6 +1238,7 @@ void ED_spacetype_view3d(void)
art->keymapflag = ED_KEYMAP_GPENCIL;
art->draw = view3d_main_area_draw;
art->init = view3d_main_area_init;
+ art->exit = view3d_main_area_exit;
art->free = view3d_main_area_free;
art->duplicate = view3d_main_area_duplicate;
art->listener = view3d_main_area_listener;
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 4aaa3332252..8fdc9416513 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -219,15 +219,12 @@ void ED_view3d_clipping_enable(void)
}
}
-static int view3d_clipping_test(const float vec[3], float clip[6][4])
+static int view3d_clipping_test(const float co[3], float clip[6][4])
{
- float view[3];
- copy_v3_v3(view, vec);
-
- if (0.0f < clip[0][3] + dot_v3v3(view, clip[0]))
- if (0.0f < clip[1][3] + dot_v3v3(view, clip[1]))
- if (0.0f < clip[2][3] + dot_v3v3(view, clip[2]))
- if (0.0f < clip[3][3] + dot_v3v3(view, clip[3]))
+ if (0.0f < clip[0][3] + dot_v3v3(co, clip[0]))
+ if (0.0f < clip[1][3] + dot_v3v3(co, clip[1]))
+ if (0.0f < clip[2][3] + dot_v3v3(co, clip[2]))
+ if (0.0f < clip[3][3] + dot_v3v3(co, clip[3]))
return 0;
return 1;
@@ -235,9 +232,9 @@ static int view3d_clipping_test(const float vec[3], float clip[6][4])
/* for 'local' ED_view3d_clipping_local must run first
* then all comparisons can be done in localspace */
-int ED_view3d_clipping_test(RegionView3D *rv3d, const float vec[3], const int is_local)
+int ED_view3d_clipping_test(RegionView3D *rv3d, const float co[3], const bool is_local)
{
- return view3d_clipping_test(vec, is_local ? rv3d->clip_local : rv3d->clip);
+ return view3d_clipping_test(co, is_local ? rv3d->clip_local : rv3d->clip);
}
/* ********* end custom clipping *********** */
@@ -971,7 +968,7 @@ static void draw_selected_name(Scene *scene, Object *ob, rcti *rect)
}
static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d,
- rctf *viewborder_r, short no_shift, short no_zoom)
+ rctf *r_viewborder, const bool no_shift, const bool no_zoom)
{
CameraParams params;
rctf rect_view, rect_camera;
@@ -995,25 +992,25 @@ static void view3d_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionV
rect_camera = params.viewplane;
/* get camera border within viewport */
- viewborder_r->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
- viewborder_r->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
- viewborder_r->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
- viewborder_r->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
+ r_viewborder->xmin = ((rect_camera.xmin - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
+ r_viewborder->xmax = ((rect_camera.xmax - rect_view.xmin) / BLI_rctf_size_x(&rect_view)) * ar->winx;
+ r_viewborder->ymin = ((rect_camera.ymin - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
+ r_viewborder->ymax = ((rect_camera.ymax - rect_view.ymin) / BLI_rctf_size_y(&rect_view)) * ar->winy;
}
-void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float size_r[2])
+void ED_view3d_calc_camera_border_size(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d, float r_size[2])
{
rctf viewborder;
view3d_camera_border(scene, ar, v3d, rv3d, &viewborder, TRUE, TRUE);
- size_r[0] = BLI_rctf_size_x(&viewborder);
- size_r[1] = BLI_rctf_size_y(&viewborder);
+ r_size[0] = BLI_rctf_size_x(&viewborder);
+ r_size[1] = BLI_rctf_size_y(&viewborder);
}
void ED_view3d_calc_camera_border(Scene *scene, ARegion *ar, View3D *v3d, RegionView3D *rv3d,
- rctf *viewborder_r, short no_shift)
+ rctf *viewborder_r, const bool no_shift)
{
- view3d_camera_border(scene, ar, v3d, rv3d, viewborder_r, no_shift, FALSE);
+ view3d_camera_border(scene, ar, v3d, rv3d, viewborder_r, no_shift, false);
}
static void drawviewborder_grid3(float x1, float x2, float y1, float y2, float fac)
@@ -1316,11 +1313,6 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
{
/* do nothing */
}
- else if ((base && (base->object->mode & OB_MODE_TEXTURE_PAINT)) &&
- scene->toolsettings && (scene->toolsettings->imapaint.flag & IMAGEPAINT_PROJECT_DISABLE))
- {
- /* do nothing */
- }
else if ((base && (base->object->mode & OB_MODE_PARTICLE_EDIT)) &&
v3d->drawtype > OB_WIRE && (v3d->flag & V3D_ZBUF_SELECT))
{
@@ -1356,7 +1348,35 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
if (multisample_enabled)
glDisable(GL_MULTISAMPLE_ARB);
- glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
+ if (U.ogl_multisamples != USER_MULTISAMPLE_NONE) {
+ /* for multisample we use an offscreen FBO. multisample drawing can fail
+ * with color coded selection drawing, and reading back depths from such
+ * a buffer can also cause a few seconds freeze on OS X / NVidia. */
+ int w = BLI_rcti_size_x(&ar->winrct);
+ int h = BLI_rcti_size_y(&ar->winrct);
+ char error[256];
+
+ if (rv3d->gpuoffscreen) {
+ if (GPU_offscreen_width(rv3d->gpuoffscreen) != w ||
+ GPU_offscreen_height(rv3d->gpuoffscreen) != h)
+ {
+ GPU_offscreen_free(rv3d->gpuoffscreen);
+ rv3d->gpuoffscreen = NULL;
+ }
+ }
+
+ if (!rv3d->gpuoffscreen) {
+ rv3d->gpuoffscreen = GPU_offscreen_create(w, h, error);
+
+ if (!rv3d->gpuoffscreen)
+ fprintf(stderr, "Failed to create offscreen selection buffer for multisample: %s\n", error);
+ }
+ }
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_bind(rv3d->gpuoffscreen);
+ else
+ glScissor(ar->winrct.xmin, ar->winrct.ymin, BLI_rcti_size_x(&ar->winrct), BLI_rcti_size_y(&ar->winrct));
glClearColor(0.0, 0.0, 0.0, 0.0);
if (v3d->zbuf) {
@@ -1375,9 +1395,13 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
if (base && (base->lay & v3d->lay))
draw_object_backbufsel(scene, v3d, rv3d, base->object);
+
+ if (rv3d->gpuoffscreen)
+ GPU_offscreen_unbind(rv3d->gpuoffscreen);
+ else
+ ar->swap = 0; /* mark invalid backbuf for wm draw */
v3d->flag &= ~V3D_INVALID_BACKBUF;
- ar->swap = 0; /* mark invalid backbuf for wm draw */
G.f &= ~G_BACKBUFSEL;
v3d->zbuf = FALSE;
@@ -1394,6 +1418,21 @@ static void backdrawview3d(Scene *scene, ARegion *ar, View3D *v3d)
}
+void view3d_opengl_read_pixels(ARegion *ar, int x, int y, int w, int h, int format, int type, void *data)
+{
+ RegionView3D *rv3d = ar->regiondata;
+
+ if (rv3d->gpuoffscreen) {
+ GPU_offscreen_bind(rv3d->gpuoffscreen);
+ glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
+ glReadPixels(x, y, w, h, format, type, data);
+ GPU_offscreen_unbind(rv3d->gpuoffscreen);
+ }
+ else {
+ glReadPixels(ar->winrct.xmin + x, ar->winrct.ymin + y, w, h, format, type, data);
+ }
+}
+
void view3d_validate_backbuf(ViewContext *vc)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF)
@@ -1409,12 +1448,9 @@ unsigned int view3d_sample_backbuf(ViewContext *vc, int x, int y)
return 0;
}
- x += vc->ar->winrct.xmin;
- y += vc->ar->winrct.ymin;
-
view3d_validate_backbuf(vc);
- glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
+ view3d_opengl_read_pixels(vc->ar, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &col);
glReadBuffer(GL_BACK);
if (ENDIAN_ORDER == B_ENDIAN) {
@@ -1445,8 +1481,8 @@ ImBuf *view3d_read_backbuf(ViewContext *vc, short xmin, short ymin, short xmax,
view3d_validate_backbuf(vc);
- glReadPixels(vc->ar->winrct.xmin + xminc,
- vc->ar->winrct.ymin + yminc,
+ view3d_opengl_read_pixels(vc->ar,
+ xminc, yminc,
(xmaxc - xminc + 1),
(ymaxc - yminc + 1),
GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
@@ -1573,7 +1609,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
float fac, asp, zoomx, zoomy;
float x1, y1, x2, y2;
- ImBuf *ibuf = NULL, *freeibuf;
+ ImBuf *ibuf = NULL, *freeibuf, *releaseibuf;
Image *ima;
MovieClip *clip;
@@ -1583,6 +1619,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
continue;
freeibuf = NULL;
+ releaseibuf = NULL;
if (bgpic->source == V3D_BGPIC_IMAGE) {
ima = bgpic->ima;
if (ima == NULL)
@@ -1593,7 +1630,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
}
else {
ibuf = BKE_image_acquire_ibuf(ima, &bgpic->iuser, NULL);
- freeibuf = ibuf;
+ releaseibuf = ibuf;
}
image_aspect[0] = ima->aspx;
@@ -1608,7 +1645,9 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if (scene->camera)
clip = BKE_object_movieclip_get(scene, scene->camera, 1);
}
- else clip = bgpic->clip;
+ else {
+ clip = bgpic->clip;
+ }
if (clip == NULL)
continue;
@@ -1636,6 +1675,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if ((ibuf->rect == NULL && ibuf->rect_float == NULL) || ibuf->channels != 4) { /* invalid image format */
if (freeibuf)
IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, NULL);
continue;
}
@@ -1708,10 +1749,12 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
float tvec[3];
float sco[2];
const float mval_f[2] = {1.0f, 0.0f};
+ const float co_zero[3] = {0};
+ float zfac;
/* calc window coord */
- initgrabz(rv3d, 0.0, 0.0, 0.0);
- ED_view3d_win_to_delta(ar, mval_f, tvec);
+ zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
+ ED_view3d_win_to_delta(ar, mval_f, tvec, zfac);
fac = max_ff(fabsf(tvec[0]), max_ff(fabsf(tvec[1]), fabsf(tvec[2]))); /* largest abs axis */
fac = 1.0f / fac;
@@ -1731,6 +1774,8 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
if (x2 < 0 || y2 < 0 || x1 > ar->winx || y1 > ar->winy) {
if (freeibuf)
IMB_freeImBuf(freeibuf);
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, NULL);
continue;
}
@@ -1774,7 +1819,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
glPixelZoom(zoomx, zoomy);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f - bgpic->blend);
- glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
+ glaDrawPixelsAuto(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect);
glPixelZoom(1.0, 1.0);
glPixelTransferf(GL_ALPHA_SCALE, 1.0f);
@@ -1789,9 +1834,10 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d,
glDepthMask(1);
if (v3d->zbuf) glEnable(GL_DEPTH_TEST);
- if (freeibuf) {
+ if (freeibuf)
IMB_freeImBuf(freeibuf);
- }
+ if (releaseibuf)
+ BKE_image_release_ibuf(ima, releaseibuf, NULL);
}
}
}
@@ -2102,7 +2148,7 @@ void view3d_update_depths_rect(ARegion *ar, ViewDepths *d, rcti *rect)
}
if (d->damaged) {
- glReadPixels(ar->winrct.xmin + d->x, ar->winrct.ymin + d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
+ view3d_opengl_read_pixels(ar, d->x, d->y, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
d->damaged = FALSE;
}
@@ -2130,9 +2176,7 @@ void ED_view3d_depth_update(ARegion *ar)
}
if (d->damaged) {
- glReadPixels(ar->winrct.xmin, ar->winrct.ymin, d->w, d->h,
- GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
-
+ view3d_opengl_read_pixels(ar, 0, 0, d->w, d->h, GL_DEPTH_COMPONENT, GL_FLOAT, d->depths);
glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
d->damaged = 0;
@@ -2999,7 +3043,7 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
#define VIEWGRAD_RES_Y 16
GLubyte grid_col[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][4];
- static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][2];
+ static float grid_pos[VIEWGRAD_RES_X][VIEWGRAD_RES_Y][3];
static GLushort indices[VIEWGRAD_RES_X - 1][VIEWGRAD_RES_X - 1][4];
static char buf_calculated = FALSE;
@@ -3008,8 +3052,6 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
IMB_colormanagement_pixel_to_display_space_v3(col_zen, &scene->world->zenr, &scene->view_settings,
&scene->display_settings);
- glClear(GL_DEPTH_BUFFER_BIT);
-
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
@@ -3029,6 +3071,7 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
/* -1..1 range */
grid_pos[x][y][0] = (xf - 0.5f) * 2.0f;
grid_pos[x][y][1] = (yf - 0.5f) * 2.0f;
+ grid_pos[x][y][2] = 1.0;
}
}
@@ -3082,15 +3125,22 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
}
}
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
- glVertexPointer(2, GL_FLOAT, 0, grid_pos);
+ glVertexPointer(3, GL_FLOAT, 0, grid_pos);
glColorPointer(4, GL_UNSIGNED_BYTE, 0, grid_col);
glDrawElements(GL_QUADS, (VIEWGRAD_RES_X - 1) * (VIEWGRAD_RES_Y - 1) * 4, GL_UNSIGNED_SHORT, indices);
+
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
@@ -3112,9 +3162,6 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
}
else {
if (UI_GetThemeValue(TH_SHOW_BACK_GRAD)) {
- /* only clear depth buffer here */
- glClear(GL_DEPTH_BUFFER_BIT);
-
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
@@ -3122,17 +3169,22 @@ static void view3d_main_area_clear(Scene *scene, View3D *v3d, ARegion *ar)
glPushMatrix();
glLoadIdentity();
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
glShadeModel(GL_SMOOTH);
glBegin(GL_QUADS);
UI_ThemeColor(TH_LOW_GRAD);
- glVertex2f(-1.0, -1.0);
- glVertex2f(1.0, -1.0);
+ glVertex3f(-1.0, -1.0, 1.0);
+ glVertex3f(1.0, -1.0, 1.0);
UI_ThemeColor(TH_HIGH_GRAD);
- glVertex2f(1.0, 1.0);
- glVertex2f(-1.0, 1.0);
+ glVertex3f(1.0, 1.0, 1.0);
+ glVertex3f(-1.0, 1.0, 1.0);
glEnd();
glShadeModel(GL_FLAT);
+ glDepthFunc(GL_LEQUAL);
+ glDisable(GL_DEPTH_TEST);
+
glMatrixMode(GL_PROJECTION);
glPopMatrix();
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 5f54f0dcfc8..8c8332075a2 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -368,6 +368,7 @@ typedef struct ViewOpsData {
float reverse, dist0, camzoom0;
float grid, far;
short axis_snap; /* view rotate only */
+ float zfac;
/* use for orbit selection and auto-dist */
float ofs[3], dyn_ofs[3];
@@ -407,7 +408,7 @@ static void calctrackballvec(const rcti *rect, int mx, int my, float vec[3])
}
-static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event)
+static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *event)
{
static float lastofs[3] = {0, 0, 0};
RegionView3D *rv3d;
@@ -504,7 +505,11 @@ static void viewops_data_create(bContext *C, wmOperator *op, wmEvent *event)
calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec);
- initgrabz(rv3d, -rv3d->ofs[0], -rv3d->ofs[1], -rv3d->ofs[2]);
+ {
+ float tvec[3];
+ negate_v3_v3(tvec, rv3d->ofs);
+ vod->zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ }
vod->reverse = 1.0f;
if (rv3d->persmat[2][1] < 0.0f)
@@ -836,7 +841,7 @@ static void viewrotate_apply(ViewOpsData *vod, int x, int y)
ED_region_tag_redraw(vod->ar);
}
-static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int viewrotate_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
@@ -885,7 +890,7 @@ static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int viewrotate_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
RegionView3D *rv3d;
@@ -1092,7 +1097,7 @@ static void view3d_ndof_orbit(const struct wmNDOFMotionData *ndof, RegionView3D
* -- zooming
* -- panning in rotationally-locked views
*/
-static int ndof_orbit_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int ndof_orbit_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type != NDOF_MOTION)
@@ -1174,7 +1179,7 @@ void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot)
}
-static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int ndof_orbit_zoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type != NDOF_MOTION)
@@ -1272,7 +1277,7 @@ void VIEW3D_OT_ndof_orbit_zoom(struct wmOperatorType *ot)
/* -- "pan" navigation
* -- zoom or dolly?
*/
-static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
if (event->type != NDOF_MOTION)
return OPERATOR_CANCELLED;
@@ -1366,7 +1371,7 @@ void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot)
/*
* this is basically just the pan only code + the rotate only code crammed into one function that does both
*/
-static int ndof_all_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int ndof_all_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->type != NDOF_MOTION) {
return OPERATOR_CANCELLED;
@@ -1508,7 +1513,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
mval_f[0] = x - vod->oldx;
mval_f[1] = y - vod->oldy;
- ED_view3d_win_to_delta(vod->ar, mval_f, dvec);
+ ED_view3d_win_to_delta(vod->ar, mval_f, dvec, vod->zfac);
add_v3_v3(vod->rv3d->ofs, dvec);
@@ -1525,7 +1530,7 @@ static void viewmove_apply(ViewOpsData *vod, int x, int y)
}
-static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int viewmove_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
@@ -1568,7 +1573,7 @@ static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event)
return OPERATOR_RUNNING_MODAL;
}
-static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int viewmove_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
@@ -1665,15 +1670,16 @@ static void view_zoom_mouseloc(ARegion *ar, float dfac, int mx, int my)
float tpos[3];
float mval_f[2];
float new_dist;
+ float zfac;
negate_v3_v3(tpos, rv3d->ofs);
- /* Project cursor position into 3D space */
- initgrabz(rv3d, tpos[0], tpos[1], tpos[2]);
-
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;
- ED_view3d_win_to_delta(ar, mval_f, dvec);
+
+ /* Project cursor position into 3D space */
+ zfac = ED_view3d_calc_zfac(rv3d, tpos, NULL);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
/* Calculate view target position for dolly */
add_v3_v3v3(tvec, tpos, dvec);
@@ -1788,7 +1794,7 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho
}
-static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int viewzoom_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
@@ -1933,7 +1939,7 @@ void viewdolly_modal_keymap(wmKeyConfig *keyconf)
}
/* viewdolly_invoke() copied this function, changes here may apply there */
-static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int viewzoom_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
@@ -2053,7 +2059,7 @@ static void viewdolly_apply(ViewOpsData *vod, int x, int y, const short zoom_inv
}
-static int viewdolly_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int viewdolly_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod = op->customdata;
short event_code = VIEW_PASS;
@@ -2145,7 +2151,7 @@ static int viewdolly_exec(bContext *C, wmOperator *op)
}
/* copied from viewzoom_invoke(), changes here may apply there */
-static int viewdolly_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int viewdolly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
ViewOpsData *vod;
@@ -2957,14 +2963,20 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
}
else {
float mval_f[2];
+ float zfac;
+
/* We cant use the depth, fallback to the old way that dosnt set the center depth */
copy_v3_v3(new_ofs, rv3d->ofs);
- initgrabz(rv3d, -new_ofs[0], -new_ofs[1], -new_ofs[2]);
+ {
+ float tvec[3];
+ negate_v3_v3(tvec, new_ofs);
+ zfac = ED_view3d_calc_zfac(rv3d, tvec, NULL);
+ }
mval_f[0] = (rect.xmin + rect.xmax - vb[0]) / 2.0f;
mval_f[1] = (rect.ymin + rect.ymax - vb[1]) / 2.0f;
- ED_view3d_win_to_delta(ar, mval_f, dvec);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
/* center the view to the center of the rectangle */
sub_v3_v3(new_ofs, dvec);
}
@@ -2997,7 +3009,7 @@ static int view3d_zoom_border_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view3d_zoom_border_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -3415,16 +3427,19 @@ static int viewpan_exec(bContext *C, wmOperator *op)
ARegion *ar = CTX_wm_region(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float vec[3];
+ const float co_zero[3] = {0.0f};
float mval_f[2] = {0.0f, 0.0f};
+ float zfac;
int pandir;
pandir = RNA_enum_get(op->ptr, "type");
- initgrabz(rv3d, 0.0, 0.0, 0.0);
- if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); }
- else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; ED_view3d_win_to_delta(ar, mval_f, vec); }
- else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); }
- else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; ED_view3d_win_to_delta(ar, mval_f, vec); }
+ zfac = ED_view3d_calc_zfac(rv3d, co_zero, NULL);
+ if (pandir == V3D_VIEW_PANRIGHT) { mval_f[0] = -32.0f; }
+ else if (pandir == V3D_VIEW_PANLEFT) { mval_f[0] = 32.0f; }
+ else if (pandir == V3D_VIEW_PANUP) { mval_f[1] = -25.0f; }
+ else if (pandir == V3D_VIEW_PANDOWN) { mval_f[1] = 25.0f; }
+ ED_view3d_win_to_delta(ar, mval_f, vec, zfac);
add_v3_v3(rv3d->ofs, vec);
if (rv3d->viewlock & RV3D_BOXVIEW)
@@ -3506,7 +3521,7 @@ static int background_image_add_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_FINISHED;
}
-static int background_image_add_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int background_image_add_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
View3D *v3d = CTX_wm_view3d(C);
Image *ima = NULL;
@@ -3661,7 +3676,7 @@ static int view3d_clipping_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
-static int view3d_clipping_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view3d_clipping_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
ARegion *ar = CTX_wm_region(C);
@@ -3713,15 +3728,16 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
float mval_fl[2];
- int flip;
+ float zfac;
+ bool flip;
- flip = initgrabz(rv3d, fp[0], fp[1], fp[2]);
+ zfac = 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);
/* re initialize, no need to check flip again */
- /* flip = */ initgrabz(rv3d, fp[0], fp[1], fp[2]);
+ zfac = ED_view3d_calc_zfac(rv3d, fp, NULL /* &flip */ );
}
if (ED_view3d_project_float_global(ar, fp, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
@@ -3736,17 +3752,17 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
if (depth_used == FALSE) {
float dvec[3];
VECSUB2D(mval_fl, mval_fl, mval);
- ED_view3d_win_to_delta(ar, mval_fl, dvec);
+ ED_view3d_win_to_delta(ar, mval_fl, dvec, zfac);
sub_v3_v3(fp, dvec);
}
}
else {
- const float dx = ((float)(mval[0] - (ar->winx / 2))) * rv3d->zfac / (ar->winx / 2);
- const float dy = ((float)(mval[1] - (ar->winy / 2))) * rv3d->zfac / (ar->winy / 2);
+ const float dx = ((float)(mval[0] - (ar->winx / 2))) * zfac / (ar->winx / 2);
+ const float dy = ((float)(mval[1] - (ar->winy / 2))) * zfac / (ar->winy / 2);
const float fz = (rv3d->persmat[0][3] * fp[0] +
rv3d->persmat[1][3] * fp[1] +
rv3d->persmat[2][3] * fp[2] +
- rv3d->persmat[3][3]) / rv3d->zfac;
+ rv3d->persmat[3][3]) / zfac;
fp[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy + rv3d->persinv[2][0] * fz) - rv3d->ofs[0];
fp[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy + rv3d->persinv[2][1] * fz) - rv3d->ofs[1];
@@ -3755,7 +3771,7 @@ void ED_view3d_cursor3d_position(bContext *C, float fp[3], const int mval[2])
}
-static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int view3d_cursor3d_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
Scene *scene = CTX_data_scene(C);
View3D *v3d = CTX_wm_view3d(C);
@@ -3794,7 +3810,7 @@ void VIEW3D_OT_cursor3d(wmOperatorType *ot)
/* ***************** manipulator op ******************* */
-static int manipulator_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
@@ -3830,7 +3846,7 @@ void VIEW3D_OT_manipulator(wmOperatorType *ot)
Transform_Properties(ot, P_CONSTRAINT);
}
-static int enable_manipulator_invoke(bContext *C, wmOperator *op, wmEvent *UNUSED(event))
+static int enable_manipulator_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
{
View3D *v3d = CTX_wm_view3d(C);
diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c
index c2e75a1c5d9..700027d62a2 100644
--- a/source/blender/editors/space_view3d/view3d_fly.c
+++ b/source/blender/editors/space_view3d/view3d_fly.c
@@ -272,7 +272,7 @@ static void drawFlyPixel(const struct bContext *UNUSED(C), ARegion *UNUSED(ar),
#define FLY_CANCEL 1
#define FLY_CONFIRM 2
-static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *event)
+static int initFlyInfo(bContext *C, FlyInfo *fly, wmOperator *op, const wmEvent *event)
{
wmWindow *win = CTX_wm_window(C);
float upvec[3]; /* tmp */
@@ -486,7 +486,7 @@ static int flyEnd(bContext *C, FlyInfo *fly)
return OPERATOR_CANCELLED;
}
-static void flyEvent(FlyInfo *fly, wmEvent *event)
+static void flyEvent(FlyInfo *fly, const wmEvent *event)
{
if (event->type == TIMER && event->customdata == fly->timer) {
fly->redraw = 1;
@@ -1179,7 +1179,7 @@ static int flyApply_ndof(bContext *C, FlyInfo *fly)
return OPERATOR_FINISHED;
}
-static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int fly_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
RegionView3D *rv3d = CTX_wm_region_view3d(C);
FlyInfo *fly;
@@ -1214,7 +1214,7 @@ static int fly_cancel(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
-static int fly_modal(bContext *C, wmOperator *op, wmEvent *event)
+static int fly_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
int exit_code;
short do_draw = FALSE;
diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c
index e078fa8eda1..430ed8698d7 100644
--- a/source/blender/editors/space_view3d/view3d_header.c
+++ b/source/blender/editors/space_view3d/view3d_header.c
@@ -28,7 +28,6 @@
* \ingroup spview3d
*/
-
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
@@ -37,8 +36,6 @@
#include "DNA_object_types.h"
#include "DNA_mesh_types.h"
-#include "RNA_access.h"
-
#include "MEM_guardedalloc.h"
#include "BLI_math.h"
@@ -57,18 +54,19 @@
#include "BKE_screen.h"
#include "BKE_tessmesh.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
#include "ED_mesh.h"
#include "ED_util.h"
#include "ED_screen.h"
#include "ED_transform.h"
#include "ED_types.h"
-#include "WM_api.h"
-#include "WM_types.h"
-
-#include "RNA_define.h"
-#include "RNA_enum_types.h"
-
#include "UI_interface.h"
#include "UI_resources.h"
@@ -209,7 +207,7 @@ static int view3d_layers_exec(bContext *C, wmOperator *op)
/* applies shift and alt, lazy coding or ok? :) */
/* the local per-keymap-entry keymap will solve it */
-static int view3d_layers_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view3d_layers_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
if (event->ctrl || event->oskey)
return OPERATOR_PASS_THROUGH;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index d4cfa9076a6..26ed8e1885c 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -108,6 +108,9 @@ float ndof_to_axis_angle(const struct wmNDOFMotionData *ndof, float axis[3]);
void view3d_keymap(struct wmKeyConfig *keyconf);
void VIEW3D_OT_fly(struct wmOperatorType *ot);
+/* view3d_ruler.c */
+void VIEW3D_OT_ruler(struct wmOperatorType *ot);
+
/* drawanim.c */
void draw_motion_paths_init(View3D *v3d, struct ARegion *ar);
void draw_motion_path_instance(Scene *scene,
diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c
index bf1c5404c0e..e567ebda4b7 100644
--- a/source/blender/editors/space_view3d/view3d_ops.c
+++ b/source/blender/editors/space_view3d/view3d_ops.c
@@ -166,6 +166,7 @@ void view3d_operatortypes(void)
WM_operatortype_append(VIEW3D_OT_localview);
WM_operatortype_append(VIEW3D_OT_game_start);
WM_operatortype_append(VIEW3D_OT_fly);
+ WM_operatortype_append(VIEW3D_OT_ruler);
WM_operatortype_append(VIEW3D_OT_layers);
WM_operatortype_append(VIEW3D_OT_copybuffer);
WM_operatortype_append(VIEW3D_OT_pastebuffer);
diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c
index bc1656ff7c6..30a100283cc 100644
--- a/source/blender/editors/space_view3d/view3d_project.c
+++ b/source/blender/editors/space_view3d/view3d_project.c
@@ -73,7 +73,7 @@ void ED_view3d_project_float_v2_m4(const ARegion *ar, const float co[3], float r
/**
* \note use #ED_view3d_ob_project_mat_get to get projecting mat
*/
-void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3], float mat[4][4])
+void ED_view3d_project_float_v3_m4(const ARegion *ar, const float vec[3], float r_co[3], float mat[4][4])
{
float vec4[4];
@@ -97,7 +97,7 @@ void ED_view3d_project_float_v3_m4(ARegion *ar, const float vec[3], float r_co[3
/* Clipping Projection Functions
* ***************************** */
-eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base)
+eV3DProjStatus ED_view3d_project_base(const struct ARegion *ar, struct Base *base)
{
eV3DProjStatus ret = ED_view3d_project_short_global(ar, base->object->obmat[3], &base->sx, V3D_PROJ_TEST_CLIP_DEFAULT);
@@ -113,8 +113,8 @@ eV3DProjStatus ED_view3d_project_base(struct ARegion *ar, struct Base *base)
* - 'rv3d->perspmat', is_local == FALSE
* - 'rv3d->persmatob', is_local == TRUE
*/
-static eV3DProjStatus ed_view3d_project__internal(ARegion *ar,
- float perspmat[4][4], const int is_local, /* normally hidden */
+static eV3DProjStatus ed_view3d_project__internal(const ARegion *ar,
+ float perspmat[4][4], const bool is_local, /* normally hidden */
const float co[3], float r_co[2], const eV3DProjTest flag)
{
float vec4[4];
@@ -171,7 +171,7 @@ static eV3DProjStatus ed_view3d_project__internal(ARegion *ar,
return V3D_PROJ_RET_OK;
}
-eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], const int is_local,
+eV3DProjStatus ED_view3d_project_short_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
const float co[3], short r_co[2], const eV3DProjTest flag)
{
float tvec[2];
@@ -190,7 +190,7 @@ eV3DProjStatus ED_view3d_project_short_ex(ARegion *ar, float perspmat[4][4], con
return ret;
}
-eV3DProjStatus ED_view3d_project_int_ex(ARegion *ar, float perspmat[4][4], const int is_local,
+eV3DProjStatus ED_view3d_project_int_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
const float co[3], int r_co[2], const eV3DProjTest flag)
{
float tvec[2];
@@ -209,7 +209,7 @@ eV3DProjStatus ED_view3d_project_int_ex(ARegion *ar, float perspmat[4][4], const
return ret;
}
-eV3DProjStatus ED_view3d_project_float_ex(ARegion *ar, float perspmat[4][4], const int is_local,
+eV3DProjStatus ED_view3d_project_float_ex(const ARegion *ar, float perspmat[4][4], const bool is_local,
const float co[3], float r_co[2], const eV3DProjTest flag)
{
float tvec[2];
@@ -228,39 +228,39 @@ eV3DProjStatus ED_view3d_project_float_ex(ARegion *ar, float perspmat[4][4], con
}
/* --- short --- */
-eV3DProjStatus ED_view3d_project_short_global(ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_short_global(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
return ED_view3d_project_short_ex(ar, rv3d->persmat, FALSE, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_short_object(ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_short_object(const ARegion *ar, const float co[3], short r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
return ED_view3d_project_short_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag);
}
/* --- int --- */
-eV3DProjStatus ED_view3d_project_int_global(ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_int_global(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
return ED_view3d_project_int_ex(ar, rv3d->persmat, FALSE, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_int_object(ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_int_object(const ARegion *ar, const float co[3], int r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
return ED_view3d_project_int_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag);
}
/* --- float --- */
-eV3DProjStatus ED_view3d_project_float_global(ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_float_global(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
return ED_view3d_project_float_ex(ar, rv3d->persmat, FALSE, co, r_co, flag);
}
/* object space, use ED_view3d_init_mats_rv3d before calling */
-eV3DProjStatus ED_view3d_project_float_object(ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
+eV3DProjStatus ED_view3d_project_float_object(const ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag)
{
RegionView3D *rv3d = ar->regiondata;
return ED_view3d_project_float_ex(ar, rv3d->persmatob, TRUE, co, r_co, flag);
@@ -271,28 +271,30 @@ eV3DProjStatus ED_view3d_project_float_object(ARegion *ar, const float co[3], fl
/* More Generic Window/Ray/Vector projection functions
* *************************************************** */
-/* odd function, need to document better */
-int initgrabz(RegionView3D *rv3d, float x, float y, float z)
+/**
+ * Caculate a depth value from \a co, use with #ED_view3d_win_to_delta
+ */
+float ED_view3d_calc_zfac(const RegionView3D *rv3d, const float co[3], bool *r_flip)
{
- int flip = FALSE;
- if (rv3d == NULL) return flip;
- rv3d->zfac = rv3d->persmat[0][3] * x + rv3d->persmat[1][3] * y + rv3d->persmat[2][3] * z + rv3d->persmat[3][3];
- if (rv3d->zfac < 0.0f)
- flip = TRUE;
+ float zfac = mul_project_m4_v3_zfac((float (*)[4])rv3d->persmat, co);
+
+ if (r_flip) {
+ *r_flip = (zfac < 0.0f);
+ }
+
/* if x,y,z is exactly the viewport offset, zfac is 0 and we don't want that
- * (accounting for near zero values)
- */
- if (rv3d->zfac < 1.e-6f && rv3d->zfac > -1.e-6f) rv3d->zfac = 1.0f;
+ * (accounting for near zero values) */
+ if (zfac < 1.e-6f && zfac > -1.e-6f) {
+ zfac = 1.0f;
+ }
/* Negative zfac means x, y, z was behind the camera (in perspective).
- * This gives flipped directions, so revert back to ok default case.
- */
- /* NOTE: I've changed this to flip zfac to be positive again for now so that GPencil draws ok
- * Aligorith, 2009Aug31 */
- //if (rv3d->zfac < 0.0f) rv3d->zfac = 1.0f;
- if (rv3d->zfac < 0.0f) rv3d->zfac = -rv3d->zfac;
-
- return flip;
+ * This gives flipped directions, so revert back to ok default case. */
+ if (zfac < 0.0f) {
+ zfac = -zfac;
+ }
+
+ return zfac;
}
/**
@@ -306,7 +308,7 @@ int initgrabz(RegionView3D *rv3d, float x, float y, float z)
* \param ray_start The world-space starting point of the segment.
* \param ray_normal The normalized world-space direction of towards mval.
*/
-void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3])
+void ED_view3d_win_to_ray(const ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3])
{
float ray_end[3];
@@ -322,7 +324,7 @@ void ED_view3d_win_to_ray(ARegion *ar, View3D *v3d, const float mval[2], float r
* \param coord The world-space location.
* \param vec The resulting normalized vector.
*/
-void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float vec[3])
+void ED_view3d_global_to_vector(const RegionView3D *rv3d, const float coord[3], float vec[3])
{
if (rv3d->is_persp) {
float p1[4], p2[4];
@@ -331,11 +333,11 @@ void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float
p1[3] = 1.0f;
copy_v3_v3(p2, p1);
p2[3] = 1.0f;
- mul_m4_v4(rv3d->viewmat, p2);
+ mul_m4_v4((float (*)[4])rv3d->viewmat, p2);
mul_v3_fl(p2, 2.0f);
- mul_m4_v4(rv3d->viewinv, p2);
+ mul_m4_v4((float (*)[4])rv3d->viewinv, p2);
sub_v3_v3v3(vec, p1, p2);
}
@@ -352,7 +354,7 @@ void ED_view3d_global_to_vector(RegionView3D *rv3d, const float coord[3], float
* \param mval The area relative location (such as event->mval converted to floats).
* \param out The resulting world-space location.
*/
-void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[2], float out[3])
+void ED_view3d_win_to_3d(const ARegion *ar, const float depth_pt[3], const float mval[2], float out[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -384,19 +386,19 @@ void ED_view3d_win_to_3d(ARegion *ar, const float depth_pt[3], const float mval[
/**
* Calculate a 3d difference vector from 2d window offset.
- * note that initgrabz() must be called first to determine
+ * note that ED_view3d_calc_zfac() must be called first to determine
* the depth used to calculate the delta.
* \param ar The region (used for the window width and height).
* \param mval The area relative 2d difference (such as event->mval[0] - other_x).
* \param out The resulting world-space delta.
*/
-void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3])
+void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3], const float zfac)
{
RegionView3D *rv3d = ar->regiondata;
float dx, dy;
- dx = 2.0f * mval[0] * rv3d->zfac / ar->winx;
- dy = 2.0f * mval[1] * rv3d->zfac / ar->winy;
+ dx = 2.0f * mval[0] * zfac / ar->winx;
+ dy = 2.0f * mval[1] * zfac / ar->winy;
out[0] = (rv3d->persinv[0][0] * dx + rv3d->persinv[1][0] * dy);
out[1] = (rv3d->persinv[0][1] * dx + rv3d->persinv[1][1] * dy);
@@ -408,7 +410,7 @@ void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3])
* This direction vector starts and the view in the direction of the 2d window coordinates.
* In orthographic view all window coordinates yield the same vector.
*
- * \note doesn't rely on initgrabz
+ * \note doesn't rely on ED_view3d_calc_zfac
* for perspective view, get the vector direction to
* the mouse cursor as a normalized vector.
*
@@ -416,7 +418,7 @@ void ED_view3d_win_to_delta(ARegion *ar, const float mval[2], float out[3])
* \param mval The area relative 2d location (such as event->mval converted to floats).
* \param out The resulting normalized world-space direction vector.
*/
-void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3])
+void ED_view3d_win_to_vector(const ARegion *ar, const float mval[2], float out[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -433,7 +435,7 @@ void ED_view3d_win_to_vector(ARegion *ar, const float mval[2], float out[3])
normalize_v3(out);
}
-void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3])
+void ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3])
{
RegionView3D *rv3d = ar->regiondata;
@@ -472,7 +474,7 @@ void ED_view3d_win_to_segment(ARegion *ar, View3D *v3d, const float mval[2], flo
* \param ray_end The world-space end point of the segment.
* \return success, FALSE if the segment is totally clipped.
*/
-int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3])
+int ED_view3d_win_to_segment_clip(const ARegion *ar, View3D *v3d, const float mval[2], float ray_start[3], float ray_end[3])
{
RegionView3D *rv3d = ar->regiondata;
ED_view3d_win_to_segment(ar, v3d, mval, ray_start, ray_end);
@@ -503,12 +505,12 @@ int ED_view3d_win_to_segment_clip(ARegion *ar, View3D *v3d, const float mval[2],
/* Utility functions for projection
* ******************************** */
-void ED_view3d_ob_project_mat_get(RegionView3D *rv3d, Object *ob, float pmat[4][4])
+void ED_view3d_ob_project_mat_get(const RegionView3D *rv3d, Object *ob, float pmat[4][4])
{
float vmat[4][4];
- mult_m4_m4m4(vmat, rv3d->viewmat, ob->obmat);
- mult_m4_m4m4(pmat, rv3d->winmat, vmat);
+ mult_m4_m4m4(vmat, (float (*)[4])rv3d->viewmat, ob->obmat);
+ mult_m4_m4m4(pmat, (float (*)[4])rv3d->winmat, vmat);
}
/**
diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c
new file mode 100644
index 00000000000..410d20a1dc0
--- /dev/null
+++ b/source/blender/editors/space_view3d/view3d_ruler.c
@@ -0,0 +1,939 @@
+/*
+ * ***** 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.
+ *
+ * Contributor(s): Campbell Barton
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/editors/space_view3d/view3d_ruler.c
+ * \ingroup spview3d
+ */
+
+/* defines VIEW3D_OT_ruler modal operator */
+
+#include "DNA_scene_types.h"
+#include "DNA_gpencil_types.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_math.h"
+#include "BLI_blenlib.h"
+
+#include "BKE_context.h"
+#include "BKE_unit.h"
+#include "BKE_gpencil.h"
+
+#include "BIF_gl.h"
+
+#include "WM_api.h"
+#include "WM_types.h"
+
+#include "ED_screen.h"
+#include "ED_space_api.h"
+
+#include "BLF_api.h"
+#include "BIF_glutil.h"
+
+#include "UI_resources.h"
+#include "UI_interface.h"
+
+#include "view3d_intern.h" /* own include */
+
+
+/* -------------------------------------------------------------------- */
+/* Snapping (could be own function) */
+/* NOTE - this is not very nice use of transform snapping */
+#include "ED_transform.h"
+#include "../transform/transform.h"
+
+static bool ED_view3d_snap_co(bContext *C, float r_co[3], const float co_ss[2],
+ bool use_vert, bool use_edge, bool use_face)
+{
+ TransInfo t = {0};
+ int dist = 12; /* snap dist */
+ float r_no_dummy[3];
+ bool ret = false;
+ char backup_snap_mode;
+ Base *backup_baseact;
+
+ t.scene = CTX_data_scene(C);
+ t.view = CTX_wm_view3d(C);
+ t.ar = CTX_wm_region(C);
+ t.obedit = CTX_data_edit_object(C);
+
+ backup_snap_mode = t.scene->toolsettings->snap_mode;
+ backup_baseact = t.scene->basact;
+ t.scene->basact = NULL;
+
+ /* try snap edge, then face if it fails */
+ if (use_vert) {
+ t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_VERTEX;
+ ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ }
+ if (use_edge && (ret == false)) {
+ t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_EDGE;
+ ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ }
+ if (use_face && (ret == false)) {
+ t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_FACE;
+ ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL);
+ }
+
+ t.scene->toolsettings->snap_mode = backup_snap_mode;
+ t.scene->basact = backup_baseact;
+
+ return ret;
+}
+/* done snapping */
+
+
+/* -------------------------------------------------------------------- */
+/* Ruler Item (we can have many) */
+enum {
+ RULERITEM_USE_ANGLE = (1 << 0), /* use protractor */
+ RULERITEM_USE_RAYCAST = (1 << 1)
+};
+
+enum {
+ RULERITEM_DIRECTION_IN = 0,
+ RULERITEM_DIRECTION_OUT
+};
+
+#define RULER_PICK_DIST 75.0f
+#define RULER_PICK_DIST_SQ (RULER_PICK_DIST * RULER_PICK_DIST)
+
+typedef struct RulerItem {
+ struct RulerItem *next, *prev;
+
+ /* worldspace coords, middle being optional */
+ float co[3][3];
+
+ /* selected coord */
+ char co_index; /* 0 -> 2*/
+
+ int flag;
+ int raycast_dir; /* RULER_DIRECTION_* */
+} RulerItem;
+
+enum {
+ RULER_STATE_NORMAL = 0,
+ RULER_STATE_DRAG
+};
+
+
+/* -------------------------------------------------------------------- */
+/* Ruler Info (one per session) */
+
+typedef struct RulerInfo {
+ ListBase items;
+ int item_active;
+ int flag;
+ int snap_flag;
+ int state;
+
+ /* --- */
+ ARegion *ar;
+ void *draw_handle_pixel;
+} RulerInfo;
+
+/* -------------------------------------------------------------------- */
+/* local functions */
+static RulerItem *ruler_item_add(RulerInfo *ruler_info)
+{
+ RulerItem *ruler_item = MEM_callocN(sizeof(RulerItem), "RulerItem");
+ BLI_addtail(&ruler_info->items, ruler_item);
+ return ruler_item;
+}
+
+static void ruler_item_remove(RulerInfo *ruler_info, RulerItem *ruler_item)
+{
+ BLI_remlink(&ruler_info->items, ruler_item);
+ MEM_freeN(ruler_item);
+}
+
+static RulerItem *ruler_item_active_get(RulerInfo *ruler_info)
+{
+ return BLI_findlink(&ruler_info->items, ruler_info->item_active);
+}
+
+static void ruler_item_active_set(RulerInfo *ruler_info, RulerItem *ruler_item)
+{
+ ruler_info->item_active = BLI_findindex(&ruler_info->items, ruler_item);
+}
+
+static void ruler_item_as_string(RulerItem *ruler_item, UnitSettings *unit,
+ char *numstr, size_t numstr_size, int prec)
+{
+ const int do_split = unit->flag & USER_UNIT_OPT_SPLIT;
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ const float ruler_angle = angle_v3v3v3(ruler_item->co[0],
+ ruler_item->co[1],
+ ruler_item->co[2]);
+
+ if (unit->system == USER_UNIT_NONE) {
+ BLI_snprintf(numstr, numstr_size, "%.*f°", prec, RAD2DEGF(ruler_angle));
+ }
+ else {
+ bUnit_AsString(numstr, numstr_size,
+ (double)ruler_angle,
+ prec, unit->system, B_UNIT_ROTATION, do_split, false);
+ }
+ }
+ else {
+ const float ruler_len = len_v3v3(ruler_item->co[0],
+ ruler_item->co[2]);
+
+ if (unit->system == USER_UNIT_NONE) {
+ BLI_snprintf(numstr, numstr_size, "%.*f", prec, ruler_len);
+ }
+ else {
+ bUnit_AsString(numstr, numstr_size,
+ (double)(ruler_len * unit->scale_length),
+ prec, unit->system, B_UNIT_LENGTH, do_split, false);
+ }
+ }
+
+}
+
+static bool view3d_ruler_pick(RulerInfo *ruler_info, const float mval[2],
+ RulerItem **r_ruler_item, int *r_co_index)
+{
+ ARegion *ar = ruler_info->ar;
+ RulerItem *ruler_item;
+
+ float dist_best = RULER_PICK_DIST_SQ;
+ RulerItem *ruler_item_best = NULL;
+ int co_index_best = -1;
+
+ for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) {
+ float co_ss[3][2];
+ float dist;
+ int j;
+
+ /* should these be checked? - ok for now not to */
+ for (j = 0; j < 3; j++) {
+ ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ }
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ dist = min_ff(dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[1]),
+ dist_squared_to_line_segment_v2(mval, co_ss[1], co_ss[2]));
+ if (dist < dist_best) {
+ dist_best = dist;
+ ruler_item_best = ruler_item;
+
+ {
+ float dist_points[3] = {len_squared_v2v2(co_ss[0], mval),
+ len_squared_v2v2(co_ss[1], mval),
+ len_squared_v2v2(co_ss[2], mval)};
+ if (min_fff(UNPACK3(dist_points)) < RULER_PICK_DIST_SQ) {
+ co_index_best = min_axis_v3(dist_points);
+ }
+ else {
+ co_index_best = -1;
+ }
+ }
+ }
+ }
+ else {
+ dist = dist_squared_to_line_segment_v2(mval, co_ss[0], co_ss[2]);
+ if (dist < dist_best) {
+ dist_best = dist;
+ ruler_item_best = ruler_item;
+
+ {
+ float dist_points[2] = {len_squared_v2v2(co_ss[0], mval),
+ len_squared_v2v2(co_ss[2], mval)};
+ if (min_ff(UNPACK2(dist_points)) < RULER_PICK_DIST_SQ) {
+ co_index_best = (dist_points[0] < dist_points[1]) ? 0 : 2;
+ }
+ else {
+ co_index_best = -1;
+ }
+ }
+ }
+ }
+ }
+
+ if (ruler_item_best) {
+ *r_ruler_item = ruler_item_best;
+ *r_co_index = co_index_best;
+ return true;
+ }
+ else {
+ *r_ruler_item = NULL;
+ *r_co_index = -1;
+ return false;
+ }
+}
+
+#define RULER_ID "RulerData3D"
+static bool view3d_ruler_to_gpencil(bContext *C, RulerInfo *ruler_info)
+{
+ Scene *scene = CTX_data_scene(C);
+ bGPDlayer *gpl;
+ bGPDframe *gpf;
+ bGPDstroke *gps;
+ RulerItem *ruler_item;
+ const char *ruler_name = RULER_ID;
+ bool change = false;
+
+ if (scene->gpd == NULL) {
+ scene->gpd = gpencil_data_addnew("GPencil");
+ }
+
+ gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ if (gpl == NULL) {
+ gpl = gpencil_layer_addnew(scene->gpd, ruler_name, false);
+ gpl->thickness = 1;
+ gpl->flag |= GP_LAYER_HIDE;
+ }
+
+ gpf = gpencil_layer_getframe(gpl, CFRA, true);
+ free_gpencil_strokes(gpf);
+
+ for (ruler_item = ruler_info->items.first; ruler_item; ruler_item = ruler_item->next) {
+ bGPDspoint *pt;
+ int j;
+
+ /* allocate memory for a new stroke */
+ gps = MEM_callocN(sizeof(bGPDstroke), "gp_stroke");
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ gps->totpoints = 3;
+ pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ for (j = 0; j < 3; j++) {
+ copy_v3_v3(&pt->x, ruler_item->co[j]);
+ pt->pressure = 1.0f;
+ pt++;
+ }
+ }
+ else {
+ gps->totpoints = 2;
+ pt = gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points");
+ for (j = 0; j < 3; j += 2) {
+ copy_v3_v3(&pt->x, ruler_item->co[j]);
+ pt->pressure = 1.0f;
+ pt++;
+ }
+ }
+ gps->flag = GP_STROKE_3DSPACE;
+ BLI_addtail(&gpf->strokes, gps);
+ change = true;
+ }
+
+ return change;
+}
+
+static bool view3d_ruler_from_gpencil(bContext *C, RulerInfo *ruler_info)
+{
+ Scene *scene = CTX_data_scene(C);
+ bool change = false;
+
+ if (scene->gpd) {
+ bGPDlayer *gpl;
+ const char *ruler_name = RULER_ID;
+ gpl = BLI_findstring(&scene->gpd->layers, ruler_name, offsetof(bGPDlayer, info));
+ if (gpl) {
+ bGPDframe *gpf;
+ gpf = gpencil_layer_getframe(gpl, CFRA, false);
+ if (gpf) {
+ bGPDstroke *gps;
+ for (gps = gpf->strokes.first; gps; gps = gps->next) {
+ bGPDspoint *pt = gps->points;
+ int j;
+ if (gps->totpoints == 3) {
+ RulerItem *ruler_item = ruler_item_add(ruler_info);
+ for (j = 0; j < 3; j++) {
+ copy_v3_v3(ruler_item->co[j], &pt->x);
+ pt++;
+ }
+ ruler_item->flag |= RULERITEM_USE_ANGLE;
+ change = true;
+ }
+ else if (gps->totpoints == 2) {
+ RulerItem *ruler_item = ruler_item_add(ruler_info);
+ for (j = 0; j < 3; j += 2) {
+ copy_v3_v3(ruler_item->co[j], &pt->x);
+ pt++;
+ }
+ change = true;
+ }
+ }
+ }
+ }
+ }
+
+ return change;
+}
+
+/* -------------------------------------------------------------------- */
+/* local callbacks */
+
+static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *arg)
+{
+ Scene *scene = CTX_data_scene(C);
+ UnitSettings *unit = &scene->unit;
+ RulerItem *ruler_item;
+ RulerInfo *ruler_info = arg;
+ RegionView3D *rv3d = ruler_info->ar->regiondata;
+// ARegion *ar = ruler_info->ar;
+ const float cap_size = 4.0f;
+ const float bg_margin = 4.0f * U.pixelsize;
+ const float bg_radius = 4.0f * U.pixelsize;
+ const float arc_size = 64.0f * U.pixelsize;
+#define ARC_STEPS 24
+ const int arc_steps = ARC_STEPS;
+ int i;
+ //unsigned int color_act = 0x666600;
+ unsigned int color_act = 0xffffff;
+ unsigned int color_base = 0x0;
+ unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80};
+ unsigned char color_text[3];
+ unsigned char color_wire[3];
+
+ /* anti-aliased lines for more consistent appearance */
+ glEnable(GL_LINE_SMOOTH);
+
+ BLF_enable(blf_mono_font, BLF_ROTATION);
+ BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
+ BLF_rotation(blf_mono_font, 0.0f);
+
+ UI_GetThemeColor3ubv(TH_TEXT, color_text);
+ UI_GetThemeColor3ubv(TH_WIRE, color_wire);
+
+ for (ruler_item = ruler_info->items.first, i = 0; ruler_item; ruler_item = ruler_item->next, i++) {
+ const bool is_act = (i == ruler_info->item_active);
+ float dir_ruler[2];
+ float co_ss[3][2];
+ int j;
+
+ /* should these be checked? - ok for now not to */
+ for (j = 0; j < 3; j++) {
+ ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
+ }
+
+ glEnable(GL_BLEND);
+
+ cpack(is_act ? color_act : color_base);
+
+ if (ruler_item->flag & RULERITEM_USE_ANGLE) {
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < 3; j++) {
+ glVertex2fv(co_ss[j]);
+ }
+ glEnd();
+ cpack(0xaaaaaa);
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < 3; j++) {
+ glVertex2fv(co_ss[j]);
+ }
+ glEnd();
+ setlinestyle(0);
+
+ /* arc */
+ {
+ float dir_tmp[3];
+ float co_tmp[3];
+ float arc_ss_coords[ARC_STEPS + 1][2];
+
+ float dir_a[3];
+ float dir_b[3];
+ float quat[4];
+ float axis[3];
+ float angle;
+ const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) *
+ min_fff(arc_size,
+ len_v2v2(co_ss[0], co_ss[1]) / 2.0f,
+ len_v2v2(co_ss[2], co_ss[1]) / 2.0f));
+
+ sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]);
+ sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]);
+ normalize_v3(dir_a);
+ normalize_v3(dir_b);
+
+ cross_v3_v3v3(axis, dir_a, dir_b);
+ angle = angle_normalized_v3v3(dir_a, dir_b);
+
+ axis_angle_to_quat(quat, axis, angle / arc_steps);
+
+ copy_v3_v3(dir_tmp, dir_a);
+
+ glColor3ubv(color_wire);
+
+ for (j = 0; j <= arc_steps; j++) {
+ madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
+ ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP);
+ mul_qt_v3(quat, dir_tmp);
+ }
+
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords);
+ glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1);
+ glDisableClientState(GL_VERTEX_ARRAY);
+ }
+
+ /* text */
+ {
+ char numstr[256];
+ float numstr_size[2];
+ float pos[2];
+ const int prec = 2; /* XXX, todo, make optional */
+
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+
+ BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]);
+
+ pos[0] = co_ss[1][0] + (cap_size * 2.0f);
+ pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);
+
+ /* draw text (bg) */
+ glColor4ubv(color_back);
+ uiSetRoundBox(UI_CNR_ALL);
+ uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin,
+ pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
+ bg_radius);
+ /* draw text */
+ glColor3ubv(color_text);
+ BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
+ BLF_rotation(blf_mono_font, 0.0f);
+ BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ }
+
+ /* capping */
+ {
+ float rot_90_vec_a[2];
+ float rot_90_vec_b[2];
+ float cap[2];
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
+ rot_90_vec_a[0] = -dir_ruler[1];
+ rot_90_vec_a[1] = dir_ruler[0];
+ normalize_v2(rot_90_vec_a);
+
+ sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]);
+ rot_90_vec_b[0] = -dir_ruler[1];
+ rot_90_vec_b[1] = dir_ruler[0];
+ normalize_v2(rot_90_vec_b);
+
+ glEnable(GL_BLEND);
+
+ glColor3ubv(color_wire);
+
+ glBegin(GL_LINES);
+
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
+ glVertex2fv(cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
+ glVertex2fv(cap);
+
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
+ glVertex2fv(cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
+ glVertex2fv(cap);
+
+ /* angle vertex */
+ glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
+ glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
+ glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
+ glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
+ glEnd();
+
+ glDisable(GL_BLEND);
+ }
+ }
+ else {
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < 3; j += 2) {
+ glVertex2fv(co_ss[j]);
+ }
+ glEnd();
+ cpack(0xaaaaaa);
+ setlinestyle(3);
+ glBegin(GL_LINE_STRIP);
+ for (j = 0; j < 3; j += 2) {
+ glVertex2fv(co_ss[j]);
+ }
+ glEnd();
+ setlinestyle(0);
+
+ sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);
+
+ /* text */
+ {
+ char numstr[256];
+ float numstr_size[2];
+ const int prec = 6; /* XXX, todo, make optional */
+ float pos[2];
+
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+
+ BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]);
+
+ mid_v2_v2v2(pos, co_ss[0], co_ss[2]);
+
+ /* center text */
+ pos[0] -= numstr_size[0] / 2.0f;
+ pos[1] -= numstr_size[1] / 2.0f;
+
+ /* draw text (bg) */
+ glColor4ubv(color_back);
+ uiSetRoundBox(UI_CNR_ALL);
+ uiRoundBox(pos[0] - bg_margin, pos[1] - bg_margin,
+ pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
+ bg_radius);
+ /* draw text */
+ glColor3ubv(color_text);
+ BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
+ BLF_draw(blf_mono_font, numstr, sizeof(numstr));
+ }
+
+ /* capping */
+ {
+ float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
+ float cap[2];
+
+ normalize_v2(rot_90_vec);
+
+ glEnable(GL_BLEND);
+ glColor3ubv(color_wire);
+
+ glBegin(GL_LINES);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
+ glVertex2fv(cap);
+ madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
+ glVertex2fv(cap);
+
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
+ glVertex2fv(cap);
+ madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
+ glVertex2fv(cap);
+ glEnd();
+
+ glDisable(GL_BLEND);
+ }
+ }
+ }
+
+ glDisable(GL_LINE_SMOOTH);
+
+ BLF_disable(blf_mono_font, BLF_ROTATION);
+
+#undef ARC_STEPS
+}
+
+/* free, use for both cancel and finish */
+static void view3d_ruler_end(const struct bContext *UNUSED(C), RulerInfo *ruler_info)
+{
+ ED_region_draw_cb_exit(ruler_info->ar->type, ruler_info->draw_handle_pixel);
+}
+
+static void view3d_ruler_free(RulerInfo *ruler_info)
+{
+ BLI_freelistN(&ruler_info->items);
+ MEM_freeN(ruler_info);
+}
+
+static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3],
+ const int xy[2])
+{
+ view3d_get_view_aligned_coordinate(ruler_info->ar, r_co, xy, true);
+}
+
+/* use for mousemove events */
+static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, const int mval[2], const bool do_snap)
+{
+ RulerItem *ruler_item = ruler_item_active_get(ruler_info);
+
+ if (ruler_item) {
+ float *co = ruler_item->co[ruler_item->co_index];
+ view3d_ruler_item_project(ruler_info, co, mval);
+ if (do_snap) {
+ const float mval_fl[2] = {UNPACK2(mval)};
+ ED_view3d_snap_co(C, co, mval_fl, true, true, true);
+ }
+ return true;
+ }
+ else {
+ return false;
+ }
+}
+
+static void view3d_ruler_header_update(ScrArea *sa)
+{
+ const char *text = "Ctrl+LMB: Add, "
+ "Del: Remove, "
+ "Ctrl+Drag: Snap, "
+ "Ctrl+C: Copy Value, "
+ "Enter: Store, "
+ "Esc: Cancel";
+
+ ED_area_headerprint(sa, text);
+}
+
+/* -------------------------------------------------------------------- */
+/* Operator callbacks */
+
+static int view3d_ruler_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
+{
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+ ARegion *ar = CTX_wm_region(C);
+ RulerInfo *ruler_info;
+
+ ruler_info = MEM_callocN(sizeof(RulerInfo), "RulerInfo");
+
+ if (view3d_ruler_from_gpencil(C, ruler_info)) {
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ }
+
+ op->customdata = ruler_info;
+
+ ruler_info->ar = ar;
+ ruler_info->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ruler_info_draw_pixel,
+ ruler_info, REGION_DRAW_POST_PIXEL);
+
+ view3d_ruler_header_update(sa);
+
+ WM_cursor_modal(win, BC_CROSSCURSOR);
+ WM_event_add_modal_handler(C, op);
+
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int view3d_ruler_cancel(bContext *C, wmOperator *op)
+{
+ RulerInfo *ruler_info = op->customdata;
+
+ view3d_ruler_end(C, ruler_info);
+ view3d_ruler_free(ruler_info);
+ op->customdata = NULL;
+
+ return OPERATOR_CANCELLED;
+}
+
+static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ bool do_draw = false;
+ int exit_code = OPERATOR_RUNNING_MODAL;
+ RulerInfo *ruler_info = op->customdata;
+ ARegion *ar = ruler_info->ar;
+ RegionView3D *rv3d = ar->regiondata;
+
+ (void)C;
+
+ switch (event->type) {
+ case LEFTMOUSE:
+ if (event->val == KM_RELEASE) {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ /* rubber-band angle removal */
+ RulerItem *ruler_item = ruler_item_active_get(ruler_info);
+ if (ruler_item && (ruler_item->co_index == 1) && (ruler_item->flag & RULERITEM_USE_ANGLE)) {
+ if (!BLI_rcti_isect_pt_v(&ar->winrct, &event->x)) {
+ ruler_item->flag &= ~RULERITEM_USE_ANGLE;
+ do_draw = true;
+ }
+ }
+ ruler_info->state = RULER_STATE_NORMAL;
+ }
+ }
+ else {
+ if (ruler_info->state == RULER_STATE_NORMAL) {
+
+ if (event->ctrl ||
+ /* weak - but user friendly */
+ (ruler_info->items.first == NULL))
+ {
+ /* Create new line */
+ RulerItem *ruler_item;
+ /* check if we want to drag an existing point or add a new one */
+ ruler_info->state = RULER_STATE_DRAG;
+
+ ruler_item = ruler_item_add(ruler_info);
+ ruler_item_active_set(ruler_info, ruler_item);
+
+ negate_v3_v3(ruler_item->co[0], rv3d->ofs);
+ view3d_ruler_item_project(ruler_info, ruler_item->co[0], event->mval);
+
+ /* snap the first point added, not essential but handy */
+ {
+ ruler_item->co_index = 0;
+ view3d_ruler_item_mousemove(C, ruler_info, event->mval, true);
+ }
+
+ copy_v3_v3(ruler_item->co[2], ruler_item->co[0]);
+ ruler_item->co_index = 2;
+
+ do_draw = true;
+ }
+ else {
+ float mval_fl[2] = {UNPACK2(event->mval)};
+ RulerItem *ruler_item_pick;
+ int co_index;
+
+ /* select and drag */
+ if (view3d_ruler_pick(ruler_info, mval_fl, &ruler_item_pick, &co_index)) {
+ if (co_index == -1) {
+ if ((ruler_item_pick->flag & RULERITEM_USE_ANGLE) == 0) {
+ /* Add Center Point */
+ ruler_item_active_set(ruler_info, ruler_item_pick);
+ ruler_item_pick->flag |= RULERITEM_USE_ANGLE;
+ ruler_item_pick->co_index = 1;
+ ruler_info->state = RULER_STATE_DRAG;
+
+ /* find the factor */
+ {
+ float co_ss[2][2];
+ float fac;
+
+ ED_view3d_project_float_global(ar, ruler_item_pick->co[0], co_ss[0], V3D_PROJ_TEST_NOP);
+ ED_view3d_project_float_global(ar, ruler_item_pick->co[2], co_ss[1], V3D_PROJ_TEST_NOP);
+
+ fac = line_point_factor_v2(mval_fl, co_ss[0], co_ss[1]);
+ CLAMP(fac, 0.0f, 1.0f);
+
+ interp_v3_v3v3(ruler_item_pick->co[1],
+ ruler_item_pick->co[0],
+ ruler_item_pick->co[2], fac);
+ }
+
+ /* update the new location */
+ view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0);
+ do_draw = true;
+ }
+ }
+ else {
+ ruler_item_active_set(ruler_info, ruler_item_pick);
+ ruler_item_pick->co_index = co_index;
+ ruler_info->state = RULER_STATE_DRAG;
+ do_draw = true;
+ }
+ }
+ else {
+ exit_code = OPERATOR_PASS_THROUGH;
+ }
+
+ }
+ }
+ }
+ break;
+ case CKEY:
+ {
+ if (event->ctrl) {
+ RulerItem *ruler_item = ruler_item_active_get(ruler_info);
+ if (ruler_item) {
+ const int prec = 8;
+ char numstr[256];
+ Scene *scene = CTX_data_scene(C);
+ UnitSettings *unit = &scene->unit;
+
+ ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);
+ WM_clipboard_text_set((void *) numstr, false);
+ }
+ }
+ }
+ case RIGHTCTRLKEY:
+ case LEFTCTRLKEY:
+ {
+ WM_event_add_mousemove(C);
+ break;
+ }
+ case MOUSEMOVE:
+ {
+ if (ruler_info->state == RULER_STATE_DRAG) {
+ if (view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0)) {
+ do_draw = true;
+ }
+ }
+ break;
+ }
+ case ESCKEY:
+ {
+ do_draw = true;
+ exit_code = OPERATOR_CANCELLED;
+ break;
+ }
+ case RETKEY:
+ {
+ view3d_ruler_to_gpencil(C, ruler_info);
+ do_draw = true;
+ exit_code = OPERATOR_FINISHED;
+ break;
+ }
+ case DELKEY:
+ {
+ if (event->val == KM_PRESS) {
+ if (ruler_info->state == RULER_STATE_NORMAL) {
+ RulerItem *ruler_item = ruler_item_active_get(ruler_info);
+ if (ruler_item) {
+ ruler_item_remove(ruler_info, ruler_item);
+ ruler_info->item_active = -1;
+ do_draw = true;
+ }
+ }
+ }
+ break;
+ }
+ default:
+ exit_code = OPERATOR_PASS_THROUGH;
+ break;
+
+ }
+
+ if (do_draw) {
+ ScrArea *sa = CTX_wm_area(C);
+
+ view3d_ruler_header_update(sa);
+
+ /* all 3d views draw rulers */
+ WM_event_add_notifier(C, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ }
+
+ if (ELEM(exit_code, OPERATOR_FINISHED, OPERATOR_CANCELLED)) {
+ wmWindow *win = CTX_wm_window(C);
+ ScrArea *sa = CTX_wm_area(C);
+
+ WM_cursor_restore(win);
+
+ view3d_ruler_end(C, ruler_info);
+ view3d_ruler_free(ruler_info);
+ op->customdata = NULL;
+
+ ED_area_headerprint(sa, NULL);
+ }
+
+ return exit_code;
+}
+
+void VIEW3D_OT_ruler(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "3D Ruler & Protractor";
+ ot->description = "Interactive ruler";
+ ot->idname = "VIEW3D_OT_ruler";
+
+ /* api callbacks */
+ ot->invoke = view3d_ruler_invoke;
+ ot->cancel = view3d_ruler_cancel;
+ ot->modal = view3d_ruler_modal;
+ ot->poll = ED_operator_view3d_active;
+
+ /* flags */
+ ot->flag = 0;
+}
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 24260898066..b441e48f59d 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -108,23 +108,23 @@ void view3d_set_viewcontext(bContext *C, ViewContext *vc)
vc->obedit = CTX_data_edit_object(C);
}
-int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int mval[2], const short do_fallback)
+/**
+ * Re-project \a fp so it stays on the same view-plane but is under \a mval (normally the cursor location).
+ */
+bool view3d_get_view_aligned_coordinate(ARegion *ar, float fp[3], const int mval[2], const bool do_fallback)
{
+ RegionView3D *rv3d = ar->regiondata;
float dvec[3];
int mval_cpy[2];
eV3DProjStatus ret;
- mval_cpy[0] = mval[0];
- mval_cpy[1] = mval[1];
-
- ret = ED_view3d_project_int_global(vc->ar, fp, mval_cpy, V3D_PROJ_TEST_NOP);
-
- initgrabz(vc->rv3d, fp[0], fp[1], fp[2]);
+ ret = ED_view3d_project_int_global(ar, fp, mval_cpy, V3D_PROJ_TEST_NOP);
if (ret == V3D_PROJ_RET_OK) {
const float mval_f[2] = {(float)(mval_cpy[0] - mval[0]),
(float)(mval_cpy[1] - mval[1])};
- ED_view3d_win_to_delta(vc->ar, mval_f, dvec);
+ const float zfac = ED_view3d_calc_zfac(rv3d, fp, NULL);
+ ED_view3d_win_to_delta(ar, mval_f, dvec, zfac);
sub_v3_v3(fp, dvec);
return TRUE;
@@ -132,11 +132,11 @@ int view3d_get_view_aligned_coordinate(ViewContext *vc, float fp[3], const int m
else {
/* fallback to the view center */
if (do_fallback) {
- negate_v3_v3(fp, vc->rv3d->ofs);
- return view3d_get_view_aligned_coordinate(vc, fp, mval, FALSE);
+ negate_v3_v3(fp, rv3d->ofs);
+ return view3d_get_view_aligned_coordinate(ar, fp, mval, false);
}
else {
- return FALSE;
+ return false;
}
}
}
@@ -177,10 +177,9 @@ static void edbm_backbuf_check_and_select_verts(BMEditMesh *em, int select)
{
BMVert *eve;
BMIter iter;
- int index = bm_wireoffs;
+ unsigned int index = bm_wireoffs;
- eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL);
- for (; eve; eve = BM_iter_step(&iter), index++) {
+ for (eve = BM_iter_new(&iter, em->bm, BM_VERTS_OF_MESH, NULL); eve; eve = BM_iter_step(&iter), index++) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
if (EDBM_backbuf_check(index)) {
BM_vert_select_set(em->bm, eve, select);
@@ -209,7 +208,7 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, int select)
{
BMFace *efa;
BMIter iter;
- int index = 1;
+ unsigned int index = 1;
efa = BM_iter_new(&iter, em->bm, BM_FACES_OF_MESH, NULL);
for (; efa; efa = BM_iter_step(&iter), index++) {
@@ -226,11 +225,11 @@ static void edbm_backbuf_check_and_select_faces(BMEditMesh *em, int select)
static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select)
{
MVert *mv = me->mvert;
- int a;
+ unsigned int index;
if (mv) {
- for (a = 1; a <= me->totvert; a++, mv++) {
- if (EDBM_backbuf_check(a)) {
+ for (index = 1; index <= me->totvert; index++, mv++) {
+ if (EDBM_backbuf_check(index)) {
if (!(mv->flag & ME_HIDE)) {
mv->flag = select ? (mv->flag | SELECT) : (mv->flag & ~SELECT);
}
@@ -243,11 +242,11 @@ static void edbm_backbuf_check_and_select_verts_obmode(Mesh *me, int select)
static void edbm_backbuf_check_and_select_tfaces(Mesh *me, int select)
{
MPoly *mpoly = me->mpoly;
- int a;
+ unsigned int index;
if (mpoly) {
- for (a = 1; a <= me->totpoly; a++, mpoly++) {
- if (EDBM_backbuf_check(a)) {
+ for (index = 1; index <= me->totpoly; index++, mpoly++) {
+ if (EDBM_backbuf_check(index)) {
mpoly->flag = select ? (mpoly->flag | ME_FACE_SEL) : (mpoly->flag & ~ME_FACE_SEL);
}
}
@@ -733,7 +732,7 @@ static void do_lasso_select_meta(ViewContext *vc, const int mcords[][2], short m
MetaBall *mb = (MetaBall *)vc->obedit->data;
if (extend == 0 && select)
- BKE_mball_deselect_all(mb);
+ BKE_mball_deselect_all(mb);
BLI_lasso_boundbox(&rect, mcords, moves);
@@ -780,9 +779,6 @@ static void do_lasso_select_paintvert(ViewContext *vc, const int mcords[][2], sh
}
else {
LassoSelectUserData data;
- rcti rect;
-
- BLI_lasso_boundbox(&rect, mcords, moves);
view3d_userdata_lassoselect_init(&data, vc, &rect, mcords, moves, select);
@@ -1054,7 +1050,7 @@ static int object_select_menu_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Base *, base, selectable_bases)
{
/* this is a bit dodjy, there should only be ONE object with this name, but library objects can mess this up */
- if (strcmp(name, base->object->id.name + 2) == 0) {
+ if (STREQ(name, base->object->id.name + 2)) {
ED_base_object_activate(C, base);
ED_base_object_select(base, BA_SELECT);
changed = 1;
@@ -2230,7 +2226,7 @@ static int mouse_weight_paint_vertex_select(bContext *C, const int mval[2], shor
/* ****** Mouse Select ****** */
-static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
+static int view3d_select_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
Object *obedit = CTX_data_edit_object(C);
Object *obact = CTX_data_active_object(C);
diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c
index bb5b7aa6911..d3bf8a30792 100644
--- a/source/blender/editors/space_view3d/view3d_toolbar.c
+++ b/source/blender/editors/space_view3d/view3d_toolbar.c
@@ -156,7 +156,7 @@ static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), cons
{
GHashIterator *iter = WM_operatortype_iter();
- for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+ for (; BLI_ghashIterator_notDone(iter); BLI_ghashIterator_step(iter)) {
wmOperatorType *ot = BLI_ghashIterator_getValue(iter);
if (BLI_strcasestr(ot->name, str)) {
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index fba1ce328ba..b2e10fa8457 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -294,7 +294,7 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera
}
/* only meant for timer usage */
-static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event)
+static int view3d_smoothview_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
{
View3D *v3d = CTX_wm_view3d(C);
RegionView3D *rv3d = CTX_wm_region_view3d(C);
@@ -667,22 +667,29 @@ void ED_view3d_depth_tag_update(RegionView3D *rv3d)
}
/* copies logic of get_view3d_viewplane(), keep in sync */
-int ED_view3d_clip_range_get(View3D *v3d, RegionView3D *rv3d, float *clipsta, float *clipend)
+bool ED_view3d_clip_range_get(View3D *v3d, 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 (clipsta) *clipsta = params.clipsta;
- if (clipend) *clipend = params.clipend;
+ 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;
}
/* also exposed in previewrender.c */
-int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy,
- rctf *viewplane, float *clipsta, float *clipend)
+bool ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy,
+ rctf *r_viewplane, float *r_clipsta, float *r_clipend)
{
CameraParams params;
@@ -690,9 +697,9 @@ int ED_view3d_viewplane_get(View3D *v3d, RegionView3D *rv3d, int winx, int winy,
BKE_camera_params_from_view3d(&params, v3d, rv3d);
BKE_camera_params_compute_viewplane(&params, winx, winy, 1.0f, 1.0f);
- if (viewplane) *viewplane = params.viewplane;
- if (clipsta) *clipsta = params.clipsta;
- if (clipend) *clipend = params.clipend;
+ if (r_viewplane) *r_viewplane = params.viewplane;
+ if (r_clipsta) *r_clipsta = params.clipsta;
+ if (r_clipend) *r_clipend = params.clipend;
return params.is_ortho;
}
@@ -791,7 +798,7 @@ static void obmat_to_viewmat(View3D *v3d, RegionView3D *rv3d, Object *ob, short
#define QUATSET(a, b, c, d, e) { a[0] = b; a[1] = c; a[2] = d; a[3] = e; } (void)0
-int ED_view3d_lock(RegionView3D *rv3d)
+bool ED_view3d_lock(RegionView3D *rv3d)
{
switch (rv3d->view) {
case RV3D_VIEW_BOTTOM:
@@ -818,10 +825,10 @@ int ED_view3d_lock(RegionView3D *rv3d)
QUATSET(rv3d->viewquat, 0.5, -0.5, -0.5, -0.5);
break;
default:
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
/* don't set windows active in here, is used by renderwin too */
@@ -863,7 +870,9 @@ void setviewmatrixview3d(Scene *scene, View3D *v3d, RegionView3D *rv3d)
copy_v3_v3(vec, give_cursor(scene, v3d));
translate_m4(rv3d->viewmat, -vec[0], -vec[1], -vec[2]);
}
- else translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
+ else {
+ translate_m4(rv3d->viewmat, rv3d->ofs[0], rv3d->ofs[1], rv3d->ofs[2]);
+ }
}
}
@@ -1558,11 +1567,7 @@ static void UNUSED_FUNCTION(view3d_align_axis_to_vector)(View3D *v3d, RegionView
float ED_view3d_pixel_size(RegionView3D *rv3d, const float co[3])
{
- return (rv3d->persmat[3][3] + (
- rv3d->persmat[0][3] * co[0] +
- rv3d->persmat[1][3] * co[1] +
- rv3d->persmat[2][3] * co[2])
- ) * rv3d->pixsize * U.pixelsize;
+ return mul_project_m4_v3_zfac(rv3d->persmat, co) * rv3d->pixsize * U.pixelsize;
}
float ED_view3d_radius_to_persp_dist(const float angle, const float radius)