diff options
author | Ton Roosendaal <ton@blender.org> | 2008-12-19 20:14:02 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2008-12-19 20:14:02 +0300 |
commit | 663612c70c0e41be59f918a45eaa93164626f0a5 (patch) | |
tree | cb6c3844d30f8f9577b18de66f5e9d9385e7c558 /source/blender/editors/space_view3d | |
parent | 92b1d3f9461e6d122d6523955cc8124559e5f36e (diff) |
2.5
View3d: middle mouse rotate, translate, zoom.
(using default mouse map)
Diffstat (limited to 'source/blender/editors/space_view3d')
-rw-r--r-- | source/blender/editors/space_view3d/Makefile | 1 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/SConscript | 2 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/drawobject.c | 76 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/space_view3d.c | 20 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_edit.c | 1174 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_intern.h | 10 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_ops.c | 77 |
7 files changed, 730 insertions, 630 deletions
diff --git a/source/blender/editors/space_view3d/Makefile b/source/blender/editors/space_view3d/Makefile index 7a5f609a187..442ab502e65 100644 --- a/source/blender/editors/space_view3d/Makefile +++ b/source/blender/editors/space_view3d/Makefile @@ -49,6 +49,7 @@ CPPFLAGS += -I../../makesdna CPPFLAGS += -I../../imbuf CPPFLAGS += -I../../python CPPFLAGS += -I../../gpu +CPPFLAGS += -I../../makesrna CPPFLAGS += -I../../render/extern/include CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include diff --git a/source/blender/editors/space_view3d/SConscript b/source/blender/editors/space_view3d/SConscript index 77cf03820ed..fac4cd65ee2 100644 --- a/source/blender/editors/space_view3d/SConscript +++ b/source/blender/editors/space_view3d/SConscript @@ -6,6 +6,6 @@ sources = env.Glob('*.c') incs = '../include ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' incs += ' ../../render/extern/include #/intern/guardedalloc #intern/bmfont' -incs += ' ../../gpu' +incs += ' ../../gpu ../../makesrna' env.BlenderLib ( 'bf_editors_space_view3d', sources, Split(incs), [], libtype=['core','intern'], priority=[35, 40] ) diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 4c621c6ec63..01bdc1ba941 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -1202,30 +1202,30 @@ static void drawlattice(View3D *v3d, Object *ob) static void mesh_foreachScreenVert__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { - struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; - ARegion *ar= NULL; // XXX - View3D *v3d= NULL; // XXX + struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; EditVert *eve = EM_get_vert_for_index(index); short s[2]; if (eve->h==0) { if (data->clipVerts) { - view3d_project_short_clip(ar, v3d, co, s, data->pmat, data->vmat); + view3d_project_short_clip(data->ar, data->v3d, co, s, data->pmat, data->vmat); } else { - view3d_project_short_noclip(ar, co, s, data->pmat); + view3d_project_short_noclip(data->ar, co, s, data->pmat); } data->func(data->userData, eve, s[0], s[1], index); } } -void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts) + +void mesh_foreachScreenVert(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditVert *eve, int x, int y, int index), void *userData, int clipVerts) { - struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data; - View3D *v3d= NULL; // XXX + struct { void (*func)(void *userData, EditVert *eve, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } data; DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); data.func = func; data.userData = userData; + data.ar= ar; + data.v3d= v3d; data.clipVerts = clipVerts; view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat); @@ -1239,23 +1239,21 @@ void mesh_foreachScreenVert(void (*func)(void *userData, EditVert *eve, int x, i static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0co, float *v1co) { - struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; - ARegion *ar= NULL; // XXX - View3D *v3d= NULL; // XXX + struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } *data = userData; EditEdge *eed = EM_get_edge_for_index(index); short s[2][2]; if (eed->h==0) { if (data->clipVerts==1) { - view3d_project_short_clip(ar, v3d, v0co, s[0], data->pmat, data->vmat); - view3d_project_short_clip(ar, v3d, v1co, s[1], data->pmat, data->vmat); + view3d_project_short_clip(data->ar, data->v3d, v0co, s[0], data->pmat, data->vmat); + view3d_project_short_clip(data->ar, data->v3d, v1co, s[1], data->pmat, data->vmat); } else { - view3d_project_short_noclip(ar, v0co, s[0], data->pmat); - view3d_project_short_noclip(ar, v1co, s[1], data->pmat); + view3d_project_short_noclip(data->ar, v0co, s[0], data->pmat); + view3d_project_short_noclip(data->ar, v1co, s[1], data->pmat); if (data->clipVerts==2) { - if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<ar->winx && s[0][1]<ar->winy)) - if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<ar->winx && s[1][1]<ar->winy)) + if (!(s[0][0]>=0 && s[0][1]>= 0 && s[0][0]<data->ar->winx && s[0][1]<data->ar->winy)) + if (!(s[1][0]>=0 && s[1][1]>= 0 && s[1][0]<data->ar->winx && s[1][1]<data->ar->winy)) return; } } @@ -1263,13 +1261,14 @@ static void mesh_foreachScreenEdge__mapFunc(void *userData, int index, float *v0 data->func(data->userData, eed, s[0][0], s[0][1], s[1][0], s[1][1], index); } } -void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts) +void mesh_foreachScreenEdge(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index), void *userData, int clipVerts) { - struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; int clipVerts; float pmat[4][4], vmat[4][4]; } data; - View3D *v3d= NULL; // XXX + struct { void (*func)(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index); void *userData; ARegion *ar; View3D *v3d; int clipVerts; float pmat[4][4], vmat[4][4]; } data; DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); data.func = func; + data.ar= ar; + data.v3d= v3d; data.userData = userData; data.clipVerts = clipVerts; @@ -1284,25 +1283,24 @@ void mesh_foreachScreenEdge(void (*func)(void *userData, EditEdge *eed, int x0, static void mesh_foreachScreenFace__mapFunc(void *userData, int index, float *cent, float *no) { - struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } *data = userData; - ARegion *ar= NULL; // XXX - View3D *v3d= NULL; // XXX + struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; float pmat[4][4], vmat[4][4]; } *data = userData; EditFace *efa = EM_get_face_for_index(index); short s[2]; if (efa && efa->h==0 && efa->fgonf!=EM_FGON) { - view3d_project_short_clip(ar, v3d, cent, s, data->pmat, data->vmat); + view3d_project_short_clip(data->ar, data->v3d, cent, s, data->pmat, data->vmat); data->func(data->userData, efa, s[0], s[1], index); } } -void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData) +void mesh_foreachScreenFace(ARegion *ar, View3D *v3d, void (*func)(void *userData, EditFace *efa, int x, int y, int index), void *userData) { - struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; float pmat[4][4], vmat[4][4]; } data; + struct { void (*func)(void *userData, EditFace *efa, int x, int y, int index); void *userData; ARegion *ar; View3D *v3d; float pmat[4][4], vmat[4][4]; } data; DerivedMesh *dm = editmesh_get_derived_cage(CD_MASK_BAREMESH); - View3D *v3d= NULL; // XXX data.func = func; + data.ar= ar; + data.v3d= v3d; data.userData = userData; view3d_get_object_project_mat(v3d, G.obedit, data.pmat, data.vmat); @@ -1314,10 +1312,8 @@ void mesh_foreachScreenFace(void (*func)(void *userData, EditFace *efa, int x, i dm->release(dm); } -void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData) +void nurbs_foreachScreenVert(ARegion *ar, View3D *v3d, void (*func)(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y), void *userData) { - ARegion *ar= NULL; // XXX - View3D *v3d= NULL; // XXX float pmat[4][4], vmat[4][4]; short s[2]; Nurb *nu; @@ -1375,7 +1371,7 @@ void nurbs_foreachScreenVert(void (*func)(void *userData, Nurb *nu, BPoint *bp, static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent, float *no) { - Scene *scene= NULL; // XXX + Scene *scene= (Scene *)userData; EditFace *efa = EM_get_face_for_index(index); if (efa->h==0 && efa->fgonf!=EM_FGON) { @@ -1385,9 +1381,10 @@ static void draw_dm_face_normals__mapFunc(void *userData, int index, float *cent cent[2] + no[2]*scene->editbutsize); } } -static void draw_dm_face_normals(DerivedMesh *dm) { +static void draw_dm_face_normals(Scene *scene, DerivedMesh *dm) +{ glBegin(GL_LINES); - dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, 0); + dm->foreachMappedFaceCenter(dm, draw_dm_face_normals__mapFunc, scene); glEnd(); } @@ -1409,7 +1406,7 @@ static void draw_dm_face_centers(DerivedMesh *dm, int sel) static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, float *no_f, short *no_s) { - Scene *scene= NULL; // XXX + Scene *scene= (Scene *)userData; EditVert *eve = EM_get_vert_for_index(index); if (eve->h==0) { @@ -1426,9 +1423,10 @@ static void draw_dm_vert_normals__mapFunc(void *userData, int index, float *co, } } } -static void draw_dm_vert_normals(DerivedMesh *dm) { +static void draw_dm_vert_normals(Scene *scene, DerivedMesh *dm) +{ glBegin(GL_LINES); - dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, NULL); + dm->foreachMappedVert(dm, draw_dm_vert_normals__mapFunc, scene); glEnd(); } @@ -2106,11 +2104,11 @@ static void draw_em_fancy(Scene *scene, View3D *v3d, Object *ob, EditMesh *em, D if(G.f & G_DRAWNORMALS) { UI_ThemeColor(TH_NORMAL); - draw_dm_face_normals(cageDM); + draw_dm_face_normals(scene, cageDM); } if(G.f & G_DRAW_VNORMALS) { UI_ThemeColor(TH_NORMAL); - draw_dm_vert_normals(cageDM); + draw_dm_vert_normals(scene, cageDM); } if(G.f & (G_DRAW_EDGELEN|G_DRAW_FACEAREA|G_DRAW_EDGEANG)) @@ -2978,7 +2976,7 @@ static void draw_new_particle_system(View3D *v3d, Base *base, ParticleSystem *ps break; case PART_DRAW_BB: if(v3d->camera==0 && part->bb_ob==0){ -// XXX error("Billboards need an active camera or a target object!"); + printf("Billboards need an active camera or a target object!\n"); draw_as=part->draw_as=PART_DRAW_DOT; diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index b279e888bea..e20490c0c07 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -178,14 +178,6 @@ static SpaceLink *view3d_duplicate(SpaceLink *sl) return (SpaceLink *)v3dn; } -void view3d_operatortypes(void) -{ -} - -void view3d_keymap(struct wmWindowManager *wm) -{ -} - static void view3d_main_area_draw(const bContext *C, ARegion *ar) { /* draw entirely, view changes should be handled here */ @@ -195,6 +187,17 @@ static void view3d_main_area_draw(const bContext *C, ARegion *ar) drawview3dspace(CTX_data_scene(C), ar, v3d); } +/* add handlers, stuff you only do once or on area/region changes */ +static void view3d_main_area_init(wmWindowManager *wm, ARegion *ar) +{ + ListBase *keymap; + + /* own keymap */ + keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0); /* XXX weak? */ + WM_event_add_keymap_handler_bb(&ar->handlers, keymap,NULL, NULL); + +} + /* add handlers, stuff you only do once or on area/region changes */ static void view3d_header_area_init(wmWindowManager *wm, ARegion *ar) @@ -244,6 +247,7 @@ void ED_spacetype_view3d(void) art= MEM_callocN(sizeof(ARegionType), "spacetype time region"); art->regionid = RGN_TYPE_WINDOW; art->draw= view3d_main_area_draw; + art->init= view3d_main_area_init; BLI_addhead(&st->regiontypes, art); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index aa2f58ba4a2..2cca530ce86 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -49,6 +49,7 @@ #include "BLI_rand.h" #include "BKE_action.h" +#include "BKE_context.h" #include "BKE_object.h" #include "BKE_global.h" #include "BKE_scene.h" @@ -61,39 +62,49 @@ #include "BIF_retopo.h" #include "WM_api.h" +#include "WM_types.h" #include "ED_screen.h" +#include "ED_types.h" #include "UI_interface.h" #include "UI_resources.h" #include "UI_view2d.h" -#include "ED_types.h" - #include "PIL_time.h" /* smoothview */ #include "view3d_intern.h" // own include /* ********************** view3d_edit: view manipulations ********************* */ -#define TRACKBALLSIZE (1.1) +/* ************************** init for view ops **********************************/ -/* the central math in this function was copied from trackball.cpp, sample code from the - Developers Toolbox series by SGI. */ +typedef struct ViewOpsData { + ARegion *ar; + View3D *v3d; + + float oldquat[4]; + float trackvec[3]; + float ofs[3], obofs[3]; + float reverse, dist0; + + int origx, origy, oldx, oldy; + +} ViewOpsData; -/* trackball: better one than a full spherical solution */ +#define TRACKBALLSIZE (1.1) -void calctrackballvecfirst(rcti *area, short *mval, float *vec) +static void calctrackballvec(rcti *rect, int mx, int my, float *vec) { float x, y, radius, d, z, t; radius= TRACKBALLSIZE; /* normalize x and y */ - x= (area->xmax + area->xmin)/2 -mval[0]; - x/= (float)((area->xmax - area->xmin)/2); - y= (area->ymax + area->ymin)/2 -mval[1]; - y/= (float)((area->ymax - area->ymin)/2); + x= (rect->xmax + rect->xmin)/2 - mx; + x/= (float)((rect->xmax - rect->xmin)/4); + y= (rect->ymax + rect->ymin)/2 - my; + y/= (float)((rect->ymax - rect->ymin)/2); d = sqrt(x*x + y*y); if (d < radius*M_SQRT1_2) /* Inside sphere */ @@ -107,52 +118,592 @@ void calctrackballvecfirst(rcti *area, short *mval, float *vec) vec[0]= x; vec[1]= y; vec[2]= -z; /* yah yah! */ +} + - if( fabs(vec[2])>fabs(vec[1]) && fabs(vec[2])>fabs(vec[0]) ) { - vec[0]= 0.0; - vec[1]= 0.0; - if(vec[2]>0.0) vec[2]= 1.0; else vec[2]= -1.0; +static void viewops_data(bContext *C, wmOperator *op, wmEvent *event) +{ + ScrArea *sa= CTX_wm_area(C); + View3D *v3d= sa->spacedata.first; + ViewOpsData *vod= MEM_callocN(sizeof(ViewOpsData), "viewops data"); + + /* store data */ + op->customdata= vod; + vod->ar= CTX_wm_region(C); + vod->v3d= v3d; + vod->dist0= v3d->dist; + QUATCOPY(vod->oldquat, v3d->viewquat); + vod->origx= vod->oldx= event->x; + vod->origy= vod->oldy= event->y; + + calctrackballvec(&vod->ar->winrct, event->x, event->y, vod->trackvec); + + initgrabz(v3d, -v3d->ofs[0], -v3d->ofs[1], -v3d->ofs[2]); + + vod->reverse= 1.0f; + if (v3d->persmat[2][1] < 0.0f) + vod->reverse= -1.0f; + +} + +/* ************************** viewrotate **********************************/ + +static const float thres = 0.93f; //cos(20 deg); + +#define COS45 0.70710678118654746 +#define SIN45 COS45 + +static float snapquats[39][6] = { + /*{q0, q1, q3, q4, view, oposite_direction}*/ +{COS45, -SIN45, 0.0, 0.0, 1, 0}, //front +{0.0, 0.0, -SIN45, -SIN45, 1, 1}, //back +{1.0, 0.0, 0.0, 0.0, 7, 0}, //top +{0.0, -1.0, 0.0, 0.0, 7, 1}, //bottom +{0.5, -0.5, -0.5, -0.5, 3, 0}, //left +{0.5, -0.5, 0.5, 0.5, 3, 1}, //right + + /* some more 45 deg snaps */ +{0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0}, +{0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0, 0}, +{0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0, 0}, +{0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0, 0}, +{0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0, 0}, +{0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0, 0}, +{0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0, 0}, +{0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0, 0}, +{0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0, 0}, +{0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0, 0}, +{0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0, 0}, +{0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0, 0}, +{0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0, 0}, +{0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0, 0}, +{-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0, 0}, +{-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0, 0}, +{-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0, 0}, +{0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0, 0}, +{-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0, 0}, +{-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0, 0}, +{-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0, 0}, +{-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0, 0}, +{-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0, 0}, +{-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0, 0}, +{-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0, 0}, +{0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0, 0}, +{-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0, 0}, +{-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0, 0}, +{-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0, 0}, +{-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0, 0}, +{-COS45, 0.0, 0.0, SIN45, 0, 0}, +{COS45, 0.0, 0.0, SIN45, 0, 0}, +{0.0, 0.0, 0.0, 1.0, 0, 0} +}; + + +static void viewrotate_apply(ViewOpsData *vod, int x, int y, int ctrl) +{ + View3D *v3d= vod->v3d; + int use_sel= 0; /* XXX */ + + v3d->view= 0; /* need to reset everytime because of view snapping */ + + if (U.flag & USER_TRACKBALL) { + float phi, si, q1[4], dvec[3], newvec[3]; + + calctrackballvec(&vod->ar->winrct, x, y, newvec); + + VecSubf(dvec, newvec, vod->trackvec); + + si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]); + si/= (2.0*TRACKBALLSIZE); + + Crossf(q1+1, vod->trackvec, newvec); + Normalize(q1+1); + + /* Allow for rotation beyond the interval + * [-pi, pi] */ + while (si > 1.0) + si -= 2.0; + + /* This relation is used instead of + * phi = asin(si) so that the angle + * of rotation is linearly proportional + * to the distance that the mouse is + * dragged. */ + phi = si * M_PI / 2.0; + + si= sin(phi); + q1[0]= cos(phi); + q1[1]*= si; + q1[2]*= si; + q1[3]*= si; + QuatMul(v3d->viewquat, q1, vod->oldquat); + + if (use_sel) { + /* compute the post multiplication quat, to rotate the offset correctly */ + QUATCOPY(q1, vod->oldquat); + QuatConj(q1); + QuatMul(q1, q1, v3d->viewquat); + + QuatConj(q1); /* conj == inv for unit quat */ + VECCOPY(v3d->ofs, vod->ofs); + VecSubf(v3d->ofs, v3d->ofs, vod->obofs); + QuatMulVecf(q1, v3d->ofs); + VecAddf(v3d->ofs, v3d->ofs, vod->obofs); + } + } + else { + /* New turntable view code by John Aughey */ + float si, phi, q1[4]; + float m[3][3]; + float m_inv[3][3]; + float xvec[3] = {1,0,0}; + /* Sensitivity will control how fast the viewport rotates. 0.0035 was + obtained experimentally by looking at viewport rotation sensitivities + on other modeling programs. */ + /* Perhaps this should be a configurable user parameter. */ + const float sensitivity = 0.0035; + + /* Get the 3x3 matrix and its inverse from the quaternion */ + QuatToMat3(v3d->viewquat, m); + Mat3Inv(m_inv,m); + + /* Determine the direction of the x vector (for rotating up and down) */ + /* This can likely be compuated directly from the quaternion. */ + Mat3MulVecfl(m_inv,xvec); + + /* Perform the up/down rotation */ + phi = sensitivity * -(y - vod->oldy); + si = sin(phi); + q1[0] = cos(phi); + q1[1] = si * xvec[0]; + q1[2] = si * xvec[1]; + q1[3] = si * xvec[2]; + QuatMul(v3d->viewquat, v3d->viewquat, q1); + + if (use_sel) { + QuatConj(q1); /* conj == inv for unit quat */ + VecSubf(v3d->ofs, v3d->ofs, vod->obofs); + QuatMulVecf(q1, v3d->ofs); + VecAddf(v3d->ofs, v3d->ofs, vod->obofs); + } + + /* Perform the orbital rotation */ + phi = sensitivity * vod->reverse * (x - vod->oldx); + q1[0] = cos(phi); + q1[1] = q1[2] = 0.0; + q1[3] = sin(phi); + QuatMul(v3d->viewquat, v3d->viewquat, q1); + + if (use_sel) { + QuatConj(q1); + VecSubf(v3d->ofs, v3d->ofs, vod->obofs); + QuatMulVecf(q1, v3d->ofs); + VecAddf(v3d->ofs, v3d->ofs, vod->obofs); + } + } + + /* check for view snap */ + if (ctrl){ + int i; + float viewmat[3][3]; + + + QuatToMat3(v3d->viewquat, viewmat); + + for (i = 0 ; i < 39; i++){ + float snapmat[3][3]; + float view = (int)snapquats[i][4]; + float oposite_dir = (int)snapquats[i][5]; + + QuatToMat3(snapquats[i], snapmat); + + if ((Inpf(snapmat[0], viewmat[0]) > thres) && + (Inpf(snapmat[1], viewmat[1]) > thres) && + (Inpf(snapmat[2], viewmat[2]) > thres)){ + + QUATCOPY(v3d->viewquat, snapquats[i]); + + v3d->view = view; + if (view){ + if (oposite_dir){ + v3d->flag2 |= V3D_OPP_DIRECTION_NAME; + }else{ + v3d->flag2 &= ~V3D_OPP_DIRECTION_NAME; + } + } + + break; + } + } } - else if( fabs(vec[1])>fabs(vec[0]) && fabs(vec[1])>fabs(vec[2]) ) { - vec[0]= 0.0; - vec[2]= 0.0; - if(vec[1]>0.0) vec[1]= 1.0; else vec[1]= -1.0; + vod->oldx= x; + vod->oldy= y; + + ED_region_tag_redraw(vod->ar); +} + +static int viewrotate_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + + /* execute the events */ + switch(event->type) { + case MOUSEMOVE: + viewrotate_apply(op->customdata, event->x, event->y, event->ctrl); + break; + + case MIDDLEMOUSE: + if(event->val==0) { + + MEM_freeN(op->customdata); + op->customdata= NULL; + + return OPERATOR_FINISHED; + } + break; } - else { - vec[1]= 0.0; - vec[2]= 0.0; - if(vec[0]>0.0) vec[0]= 1.0; else vec[0]= -1.0; + + return OPERATOR_RUNNING_MODAL; +} + +static int viewrotate_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + ViewOpsData *vod; + + /* makes op->customdata */ + viewops_data(C, op, event); + vod= op->customdata; + + /* switch from camera view when: */ + if(vod->v3d->persp != V3D_PERSP) { + + if (U.uiflag & USER_AUTOPERSP) + vod->v3d->persp= V3D_PERSP; + else if(vod->v3d->persp==V3D_CAMOB) + vod->v3d->persp= V3D_PERSP; + ED_region_tag_redraw(vod->ar); } + + /* add temp handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + + return OPERATOR_RUNNING_MODAL; } -void calctrackballvec(rcti *area, short *mval, float *vec) + +void ED_VIEW3D_OT_viewrotate(wmOperatorType *ot) { - float x, y, radius, d, z, t; - radius= TRACKBALLSIZE; + /* identifiers */ + ot->name= "Rotate view"; + ot->idname= "ED_VIEW3D_OT_viewrotate"; + + /* api callbacks */ + ot->invoke= viewrotate_invoke; + ot->modal= viewrotate_modal; +} + +/* ************************ viewmove ******************************** */ + +static void viewmove_apply(ViewOpsData *vod, int x, int y) +{ + if(vod->v3d->persp==V3D_CAMOB) { + float max= (float)MAX2(vod->ar->winx, vod->ar->winy); + + vod->v3d->camdx += (vod->oldx - x)/(max); + vod->v3d->camdy += (vod->oldy - y)/(max); + CLAMP(vod->v3d->camdx, -1.0f, 1.0f); + CLAMP(vod->v3d->camdy, -1.0f, 1.0f); +// XXX preview3d_event= 0; + } + else { + float dvec[3]; + + window_to_3d(vod->ar, vod->v3d, dvec, x-vod->oldx, y-vod->oldy); + VecAddf(vod->v3d->ofs, vod->v3d->ofs, dvec); + } - /* x en y normalizeren */ - x= (area->xmax + area->xmin)/2 -mval[0]; - x/= (float)((area->xmax - area->xmin)/4); - y= (area->ymax + area->ymin)/2 -mval[1]; - y/= (float)((area->ymax - area->ymin)/2); + vod->oldx= x; + vod->oldy= y; - d = sqrt(x*x + y*y); - if (d < radius*M_SQRT1_2) /* Inside sphere */ - z = sqrt(radius*radius - d*d); - else - { /* On hyperbola */ - t = radius / M_SQRT2; - z = t*t / d; + ED_region_tag_redraw(vod->ar); +} + + +static int viewmove_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + /* execute the events */ + switch(event->type) { + case MOUSEMOVE: + viewmove_apply(op->customdata, event->x, event->y); + break; + + case MIDDLEMOUSE: + if(event->val==0) { + + MEM_freeN(op->customdata); + op->customdata= NULL; + + return OPERATOR_FINISHED; + } + break; } + + return OPERATOR_RUNNING_MODAL; +} - vec[0]= x; - vec[1]= y; - vec[2]= -z; /* yah yah! */ +static int viewmove_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + /* makes op->customdata */ + viewops_data(C, op, event); + + /* add temp handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + + return OPERATOR_RUNNING_MODAL; +} + + +void ED_VIEW3D_OT_viewmove(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Rotate view"; + ot->idname= "ED_VIEW3D_OT_viewmove"; + + /* api callbacks */ + ot->invoke= viewmove_invoke; + ot->modal= viewmove_modal; +} + +/* ************************ viewzoom ******************************** */ + +static void view_zoom_mouseloc(ARegion *ar, View3D *v3d, float dfac, int mx, int my) +{ + if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) { + float dvec[3]; + float tvec[3]; + float tpos[3]; + float new_dist; + short vb[2], mouseloc[2]; + + mouseloc[0]= mx - ar->winrct.xmin; + mouseloc[1]= my - ar->winrct.ymin; + + /* find the current window width and height */ + vb[0] = ar->winx; + vb[1] = ar->winy; + + tpos[0] = -v3d->ofs[0]; + tpos[1] = -v3d->ofs[1]; + tpos[2] = -v3d->ofs[2]; + + /* Project cursor position into 3D space */ + initgrabz(v3d, tpos[0], tpos[1], tpos[2]); + window_to_3d(ar, v3d, dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2); + + /* Calculate view target position for dolly */ + tvec[0] = -(tpos[0] + dvec[0]); + tvec[1] = -(tpos[1] + dvec[1]); + tvec[2] = -(tpos[2] + dvec[2]); + + /* Offset to target position and dolly */ + new_dist = v3d->dist * dfac; + + VECCOPY(v3d->ofs, tvec); + v3d->dist = new_dist; + + /* Calculate final offset */ + dvec[0] = tvec[0] + dvec[0] * dfac; + dvec[1] = tvec[1] + dvec[1] * dfac; + dvec[2] = tvec[2] + dvec[2] * dfac; + + VECCOPY(v3d->ofs, dvec); + } else { + v3d->dist *= dfac; + } +} + + +static void viewzoom_apply(ViewOpsData *vod, int x, int y) +{ + float zfac=1.0; + + if(U.viewzoom==USER_ZOOM_CONT) { + // oldstyle zoom + zfac = 1.0+(float)(vod->origx - x + vod->origy - y)/1000.0; + } + else if(U.viewzoom==USER_ZOOM_SCALE) { + int ctr[2], len1, len2; + // method which zooms based on how far you move the mouse + + ctr[0] = (vod->ar->winrct.xmax + vod->ar->winrct.xmin)/2; + ctr[1] = (vod->ar->winrct.ymax + vod->ar->winrct.ymin)/2; + + len1 = (int)sqrt((ctr[0] - x)*(ctr[0] - x) + (ctr[1] - y)*(ctr[1] - y)) + 5; + len2 = (int)sqrt((ctr[0] - vod->origx)*(ctr[0] - vod->origx) + (ctr[1] - vod->origy)*(ctr[1] - vod->origy)) + 5; + + zfac = vod->dist0 * ((float)len2/len1) / vod->v3d->dist; + } + else { /* USER_ZOOM_DOLLY */ + float len1 = (vod->ar->winrct.ymax - y) + 5; + float len2 = (vod->ar->winrct.ymax - vod->origy) + 5; + zfac = vod->dist0 * (2.0*((len2/len1)-1.0) + 1.0) / vod->v3d->dist; + } + + if(zfac != 1.0 && zfac*vod->v3d->dist > 0.001*vod->v3d->grid && + zfac*vod->v3d->dist < 10.0*vod->v3d->far) + view_zoom_mouseloc(vod->ar, vod->v3d, zfac, vod->oldx, vod->oldy); + + + if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (vod->v3d->persp==V3D_PERSP)) { + float upvec[3], mat[3][3]; + + /* Secret apricot feature, translate the view when in continues mode */ + upvec[0] = upvec[1] = 0.0f; + upvec[2] = (vod->dist0 - vod->v3d->dist) * vod->v3d->grid; + vod->v3d->dist = vod->dist0; + Mat3CpyMat4(mat, vod->v3d->viewinv); + Mat3MulVecfl(mat, upvec); + VecAddf(vod->v3d->ofs, vod->v3d->ofs, upvec); + } else { + /* these limits are in toets.c too */ + if(vod->v3d->dist<0.001*vod->v3d->grid) vod->v3d->dist= 0.001*vod->v3d->grid; + if(vod->v3d->dist>10.0*vod->v3d->far) vod->v3d->dist=10.0*vod->v3d->far; + } + +// XXX if(vod->v3d->persp==V3D_ORTHO || vod->v3d->persp==V3D_CAMOB) preview3d_event= 0; + + ED_region_tag_redraw(vod->ar); +} + + +static int viewzoom_modal(bContext *C, wmOperator *op, wmEvent *event) +{ + /* execute the events */ + switch(event->type) { + case MOUSEMOVE: + viewzoom_apply(op->customdata, event->x, event->y); + break; + + case MIDDLEMOUSE: + if(event->val==0) { + + MEM_freeN(op->customdata); + op->customdata= NULL; + + return OPERATOR_FINISHED; + } + break; + } + + return OPERATOR_RUNNING_MODAL; +} +static int viewzoom_invoke(bContext *C, wmOperator *op, wmEvent *event) +{ + /* makes op->customdata */ + viewops_data(C, op, event); + + /* add temp handler */ + WM_event_add_modal_handler(C, &CTX_wm_window(C)->handlers, op); + + return OPERATOR_RUNNING_MODAL; +} + + +void ED_VIEW3D_OT_viewzoom(wmOperatorType *ot) +{ + + /* identifiers */ + ot->name= "Rotate view"; + ot->idname= "ED_VIEW3D_OT_viewzoom"; + + /* api callbacks */ + ot->invoke= viewzoom_invoke; + ot->modal= viewzoom_modal; +} + +/* ************************* below the line! *********************** */ + + +/* XXX todo Zooms in on a border drawn by the user */ +int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist ) +{ + rcti rect; + /* ZBuffer depth vars */ + bglMats mats; + float depth, depth_close= MAXFLOAT; + int had_depth = 0; + double cent[2], p[3]; + int xs, ys; + + // XXX getmouseco_areawin(mval); + + // XXX persp(PERSP_VIEW); + + rect.xmax = mval[0] + 4; + rect.ymax = mval[1] + 4; + + rect.xmin = mval[0] - 4; + rect.ymin = mval[1] - 4; + + /* Get Z Depths, needed for perspective, nice for ortho */ + bgl_get_mats(&mats); + draw_depth(scene, ar, v3d, NULL); + + /* force updating */ + if (v3d->depths) { + had_depth = 1; + v3d->depths->damaged = 1; + } + + view3d_update_depths(ar, v3d); + + /* Constrain rect to depth bounds */ + if (rect.xmin < 0) rect.xmin = 0; + if (rect.ymin < 0) rect.ymin = 0; + if (rect.xmax >= v3d->depths->w) rect.xmax = v3d->depths->w-1; + if (rect.ymax >= v3d->depths->h) rect.ymax = v3d->depths->h-1; + + /* Find the closest Z pixel */ + for (xs=rect.xmin; xs < rect.xmax; xs++) { + for (ys=rect.ymin; ys < rect.ymax; ys++) { + depth= v3d->depths->depths[ys*v3d->depths->w+xs]; + if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) { + if (depth_close > depth) { + depth_close = depth; + } + } + } + } + + if (depth_close==MAXFLOAT) + return 0; + + if (had_depth==0) { + MEM_freeN(v3d->depths->depths); + v3d->depths->depths = NULL; + } + v3d->depths->damaged = 1; + + cent[0] = (double)mval[0]; + cent[1] = (double)mval[1]; + + if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) + return 0; + + mouse_worldloc[0] = (float)p[0]; + mouse_worldloc[1] = (float)p[1]; + mouse_worldloc[2] = (float)p[2]; + return 1; } + +/* ********************* NDOF ************************ */ +/* note: this code is confusing and unclear... (ton) */ +/* **************************************************** */ + // ndof scaling will be moved to user setting. // In the mean time this is just a place holder. @@ -333,547 +884,6 @@ void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int mode) // XXX BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT); } -/* Zooms in on a border drawn by the user */ -static int view_autodist(Scene *scene, ARegion *ar, View3D *v3d, short *mval, float mouse_worldloc[3] ) //, float *autodist ) -{ - rcti rect; - /* ZBuffer depth vars */ - bglMats mats; - float depth, depth_close= MAXFLOAT; - int had_depth = 0; - double cent[2], p[3]; - int xs, ys; - -// XXX getmouseco_areawin(mval); - -// XXX persp(PERSP_VIEW); - - rect.xmax = mval[0] + 4; - rect.ymax = mval[1] + 4; - - rect.xmin = mval[0] - 4; - rect.ymin = mval[1] - 4; - - /* Get Z Depths, needed for perspective, nice for ortho */ - bgl_get_mats(&mats); - draw_depth(scene, ar, v3d, NULL); - - /* force updating */ - if (v3d->depths) { - had_depth = 1; - v3d->depths->damaged = 1; - } - - view3d_update_depths(ar, v3d); - - /* Constrain rect to depth bounds */ - if (rect.xmin < 0) rect.xmin = 0; - if (rect.ymin < 0) rect.ymin = 0; - if (rect.xmax >= v3d->depths->w) rect.xmax = v3d->depths->w-1; - if (rect.ymax >= v3d->depths->h) rect.ymax = v3d->depths->h-1; - - /* Find the closest Z pixel */ - for (xs=rect.xmin; xs < rect.xmax; xs++) { - for (ys=rect.ymin; ys < rect.ymax; ys++) { - depth= v3d->depths->depths[ys*v3d->depths->w+xs]; - if(depth < v3d->depths->depth_range[1] && depth > v3d->depths->depth_range[0]) { - if (depth_close > depth) { - depth_close = depth; - } - } - } - } - - if (depth_close==MAXFLOAT) - return 0; - - if (had_depth==0) { - MEM_freeN(v3d->depths->depths); - v3d->depths->depths = NULL; - } - v3d->depths->damaged = 1; - - cent[0] = (double)mval[0]; - cent[1] = (double)mval[1]; - - if (!gluUnProject(cent[0], cent[1], depth_close, mats.modelview, mats.projection, (GLint *)mats.viewport, &p[0], &p[1], &p[2])) - return 0; - - mouse_worldloc[0] = (float)p[0]; - mouse_worldloc[1] = (float)p[1]; - mouse_worldloc[2] = (float)p[2]; - return 1; -} - -static void view_zoom_mouseloc(ARegion *ar, View3D *v3d, float dfac, short *mouseloc) -{ - if(U.uiflag & USER_ZOOM_TO_MOUSEPOS) { - short vb[2]; - float dvec[3]; - float tvec[3]; - float tpos[3]; - float new_dist; - - /* find the current window width and height */ - vb[0] = ar->winx; - vb[1] = ar->winy; - - tpos[0] = -v3d->ofs[0]; - tpos[1] = -v3d->ofs[1]; - tpos[2] = -v3d->ofs[2]; - - /* Project cursor position into 3D space */ - initgrabz(v3d, tpos[0], tpos[1], tpos[2]); - window_to_3d(ar, v3d, dvec, mouseloc[0]-vb[0]/2, mouseloc[1]-vb[1]/2); - - /* Calculate view target position for dolly */ - tvec[0] = -(tpos[0] + dvec[0]); - tvec[1] = -(tpos[1] + dvec[1]); - tvec[2] = -(tpos[2] + dvec[2]); - - /* Offset to target position and dolly */ - new_dist = v3d->dist * dfac; - - VECCOPY(v3d->ofs, tvec); - v3d->dist = new_dist; - - /* Calculate final offset */ - dvec[0] = tvec[0] + dvec[0] * dfac; - dvec[1] = tvec[1] + dvec[1] * dfac; - dvec[2] = tvec[2] + dvec[2] * dfac; - - VECCOPY(v3d->ofs, dvec); - } else { - v3d->dist *= dfac; - } -} - - -#define COS45 0.70710678118654746 -#define SIN45 COS45 - -void viewmove(Scene *scene, ARegion *ar, View3D *v3d, int mode) -{ - static float lastofs[3] = {0,0,0}; - Object *ob = OBACT; - float firstvec[3], newvec[3], dvec[3]; - float reverse, oldquat[4], q1[4], si, phi, dist0; - float ofs[3], obofs[3]= {0.0f, 0.0f, 0.0f}; - int firsttime=1; - short mvalball[2], mval[2], mvalo[2], mval_area[2], mvali[2]; - short use_sel = 0; - short preview3d_event= 1; - - // locals for dist correction - float mat[3][3]; - float upvec[3]; - - /* 3D window may not be defined */ - if( !v3d ) { - fprintf( stderr, "v3d == NULL in viewmove()\n" ); - return; - } - - // dist correction from other movement devices - if((dz_flag)||v3d->dist==0) { - dz_flag = 0; - v3d->dist = m_dist; - upvec[0] = upvec[1] = 0; - upvec[2] = v3d->dist; - Mat3CpyMat4(mat, v3d->viewinv); - Mat3MulVecfl(mat, upvec); - VecAddf(v3d->ofs, v3d->ofs, upvec); - } - - /* sometimes this routine is called from headerbuttons */ - -// XXX areawinset(ar->win); - - QUATCOPY(oldquat, v3d->viewquat); - -// XXX getmouseco_areawin(mval_area); /* for zoom to mouse loc */ -// XXX getmouseco_sc(mvali); /* work with screen coordinates because of trackball function */ - mvalball[0]= mvalo[0] = mvali[0]; /* needed for turntable to work */ - mvalball[1]= mvalo[1] = mvali[1]; - dist0= v3d->dist; - - calctrackballvec(&ar->winrct, mvalo, firstvec); - - /* cumultime(0); */ - - if(!G.obedit && (G.f & G_SCULPTMODE) && ob && v3d->pivot_last) { - use_sel= 1; - VecCopyf(ofs, v3d->ofs); - -// XXX VecCopyf(obofs, sculpt_data()->pivot); - Mat4MulVecfl(ob->obmat, obofs); - obofs[0]= -obofs[0]; - obofs[1]= -obofs[1]; - obofs[2]= -obofs[2]; - } - else if (U.uiflag & USER_ORBIT_SELECTION) { - use_sel = 1; - - VECCOPY(ofs, v3d->ofs); - - /* If there's no selection, lastofs is unmodified and last value since static */ -// XXX calculateTransformCenter(V3D_CENTROID, lastofs); - - VECCOPY(obofs, lastofs); - VecMulf(obofs, -1.0f); - } - else if (U.uiflag & USER_ORBIT_ZBUF) { - if ((use_sel= view_autodist(scene, ar, v3d, mval, obofs))) { - if (v3d->persp==V3D_PERSP) { - float my_origin[3]; /* original v3d->ofs */ - float my_pivot[3]; /* view */ - - VECCOPY(my_origin, v3d->ofs); - VecMulf(my_origin, -1.0f); /* ofs is flipped */ - - /* Set the dist value to be the distance from this 3d point */ - /* this means youll always be able to zoom into it and panning wont go bad when dist was zero */ - - /* remove dist value */ - upvec[0] = upvec[1] = 0; - upvec[2] = v3d->dist; - Mat3CpyMat4(mat, v3d->viewinv); - Mat3MulVecfl(mat, upvec); - VecSubf(my_pivot, v3d->ofs, upvec); - VecMulf(my_pivot, -1.0f); /* ofs is flipped */ - - /* find a new ofs value that is allong the view axis (rather then the mouse location) */ - lambda_cp_line_ex(obofs, my_pivot, my_origin, dvec); - dist0 = v3d->dist = VecLenf(my_pivot, dvec); - - VecMulf(dvec, -1.0f); - VECCOPY(v3d->ofs, dvec); - } - VecMulf(obofs, -1.0f); - VECCOPY(ofs, v3d->ofs); - } else { - ofs[0] = ofs[1] = ofs[2] = 0.0f; - } - } - else - ofs[0] = ofs[1] = ofs[2] = 0.0f; - - initgrabz(v3d, -v3d->ofs[0], -v3d->ofs[1], -v3d->ofs[2]); - - reverse= 1.0f; - if (v3d->persmat[2][1] < 0.0f) - reverse= -1.0f; - - while(TRUE) { -// XXX getmouseco_sc(mval); - - if( (mode==2 && U.viewzoom==USER_ZOOM_CONT) || /* continues zoom always update */ - mval[0]!=mvalo[0] || mval[1]!=mvalo[1]) { /* mouse moved, so update */ - - if(firsttime) { - - firsttime= 0; - /* are we translating, rotating or zooming? */ - if(mode==0) { -// XXX if(v3d->view!=0) scrarea_queue_headredraw(ar); /*for button */ - } - if(v3d->persp==V3D_CAMOB && mode!=1 && v3d->camera) { - v3d->persp= V3D_PERSP; -// XXX scrarea_do_windraw(ar); -// XXX scrarea_queue_headredraw(ar); - } - } - - if(mode==0) { /* view rotate */ - v3d->view= 0; /* need to reset everytime because of view snapping */ - - if (U.uiflag & USER_AUTOPERSP) v3d->persp= V3D_PERSP; - - if (U.flag & USER_TRACKBALL) mvalball[0]= mval[0]; - mvalball[1]= mval[1]; - - calctrackballvec(&ar->winrct, mvalball, newvec); - - VecSubf(dvec, newvec, firstvec); - - si= sqrt(dvec[0]*dvec[0]+ dvec[1]*dvec[1]+ dvec[2]*dvec[2]); - si/= (2.0*TRACKBALLSIZE); - - if (U.flag & USER_TRACKBALL) { - Crossf(q1+1, firstvec, newvec); - - Normalize(q1+1); - - /* Allow for rotation beyond the interval - * [-pi, pi] */ - while (si > 1.0) - si -= 2.0; - - /* This relation is used instead of - * phi = asin(si) so that the angle - * of rotation is linearly proportional - * to the distance that the mouse is - * dragged. */ - phi = si * M_PI / 2.0; - - si= sin(phi); - q1[0]= cos(phi); - q1[1]*= si; - q1[2]*= si; - q1[3]*= si; - QuatMul(v3d->viewquat, q1, oldquat); - - if (use_sel) { - /* compute the post multiplication quat, to rotate the offset correctly */ - QUATCOPY(q1, oldquat); - QuatConj(q1); - QuatMul(q1, q1, v3d->viewquat); - - QuatConj(q1); /* conj == inv for unit quat */ - VECCOPY(v3d->ofs, ofs); - VecSubf(v3d->ofs, v3d->ofs, obofs); - QuatMulVecf(q1, v3d->ofs); - VecAddf(v3d->ofs, v3d->ofs, obofs); - } - } else { - /* New turntable view code by John Aughey */ - - float m[3][3]; - float m_inv[3][3]; - float xvec[3] = {1,0,0}; - /* Sensitivity will control how fast the viewport rotates. 0.0035 was - obtained experimentally by looking at viewport rotation sensitivities - on other modeling programs. */ - /* Perhaps this should be a configurable user parameter. */ - const float sensitivity = 0.0035; - - /* Get the 3x3 matrix and its inverse from the quaternion */ - QuatToMat3(v3d->viewquat, m); - Mat3Inv(m_inv,m); - - /* Determine the direction of the x vector (for rotating up and down) */ - /* This can likely be compuated directly from the quaternion. */ - Mat3MulVecfl(m_inv,xvec); - - /* Perform the up/down rotation */ - phi = sensitivity * -(mval[1] - mvalo[1]); - si = sin(phi); - q1[0] = cos(phi); - q1[1] = si * xvec[0]; - q1[2] = si * xvec[1]; - q1[3] = si * xvec[2]; - QuatMul(v3d->viewquat, v3d->viewquat, q1); - - if (use_sel) { - QuatConj(q1); /* conj == inv for unit quat */ - VecSubf(v3d->ofs, v3d->ofs, obofs); - QuatMulVecf(q1, v3d->ofs); - VecAddf(v3d->ofs, v3d->ofs, obofs); - } - - /* Perform the orbital rotation */ - phi = sensitivity * reverse * (mval[0] - mvalo[0]); - q1[0] = cos(phi); - q1[1] = q1[2] = 0.0; - q1[3] = sin(phi); - QuatMul(v3d->viewquat, v3d->viewquat, q1); - - if (use_sel) { - QuatConj(q1); - VecSubf(v3d->ofs, v3d->ofs, obofs); - QuatMulVecf(q1, v3d->ofs); - VecAddf(v3d->ofs, v3d->ofs, obofs); - } - } - - /* check for view snap */ - if (G.qual==LR_CTRLKEY){ - int i; - float viewmat[3][3]; - - static const float thres = 0.93f; //cos(20 deg); - - static float snapquats[39][6] = { - /*{q0, q1, q3, q4, view, oposite_direction}*/ - {COS45, -SIN45, 0.0, 0.0, 1, 0}, //front - {0.0, 0.0, -SIN45, -SIN45, 1, 1}, //back - {1.0, 0.0, 0.0, 0.0, 7, 0}, //top - {0.0, -1.0, 0.0, 0.0, 7, 1}, //bottom - {0.5, -0.5, -0.5, -0.5, 3, 0}, //left - {0.5, -0.5, 0.5, 0.5, 3, 1}, //right - - /* some more 45 deg snaps */ - {0.65328145027160645, -0.65328145027160645, 0.27059805393218994, 0.27059805393218994, 0, 0}, - {0.92387950420379639, 0.0, 0.0, 0.38268342614173889, 0, 0}, - {0.0, -0.92387950420379639, 0.38268342614173889, 0.0, 0, 0}, - {0.35355335474014282, -0.85355335474014282, 0.35355338454246521, 0.14644660055637360, 0, 0}, - {0.85355335474014282, -0.35355335474014282, 0.14644660055637360, 0.35355338454246521, 0, 0}, - {0.49999994039535522, -0.49999994039535522, 0.49999997019767761, 0.49999997019767761, 0, 0}, - {0.27059802412986755, -0.65328145027160645, 0.65328145027160645, 0.27059802412986755, 0, 0}, - {0.65328145027160645, -0.27059802412986755, 0.27059802412986755, 0.65328145027160645, 0, 0}, - {0.27059799432754517, -0.27059799432754517, 0.65328139066696167, 0.65328139066696167, 0, 0}, - {0.38268336653709412, 0.0, 0.0, 0.92387944459915161, 0, 0}, - {0.0, -0.38268336653709412, 0.92387944459915161, 0.0, 0, 0}, - {0.14644658565521240, -0.35355335474014282, 0.85355335474014282, 0.35355335474014282, 0, 0}, - {0.35355335474014282, -0.14644658565521240, 0.35355335474014282, 0.85355335474014282, 0, 0}, - {0.0, 0.0, 0.92387944459915161, 0.38268336653709412, 0, 0}, - {-0.0, 0.0, 0.38268336653709412, 0.92387944459915161, 0, 0}, - {-0.27059802412986755, 0.27059802412986755, 0.65328133106231689, 0.65328133106231689, 0, 0}, - {-0.38268339633941650, 0.0, 0.0, 0.92387938499450684, 0, 0}, - {0.0, 0.38268339633941650, 0.92387938499450684, 0.0, 0, 0}, - {-0.14644658565521240, 0.35355338454246521, 0.85355329513549805, 0.35355332493782043, 0, 0}, - {-0.35355338454246521, 0.14644658565521240, 0.35355332493782043, 0.85355329513549805, 0, 0}, - {-0.49999991059303284, 0.49999991059303284, 0.49999985098838806, 0.49999985098838806, 0, 0}, - {-0.27059799432754517, 0.65328145027160645, 0.65328139066696167, 0.27059799432754517, 0, 0}, - {-0.65328145027160645, 0.27059799432754517, 0.27059799432754517, 0.65328139066696167, 0, 0}, - {-0.65328133106231689, 0.65328133106231689, 0.27059793472290039, 0.27059793472290039, 0, 0}, - {-0.92387932538986206, 0.0, 0.0, 0.38268333673477173, 0, 0}, - {0.0, 0.92387932538986206, 0.38268333673477173, 0.0, 0, 0}, - {-0.35355329513549805, 0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0, 0}, - {-0.85355329513549805, 0.35355329513549805, 0.14644657075405121, 0.35355329513549805, 0, 0}, - {-0.38268330693244934, 0.92387938499450684, 0.0, 0.0, 0, 0}, - {-0.92387938499450684, 0.38268330693244934, 0.0, 0.0, 0, 0}, - {-COS45, 0.0, 0.0, SIN45, 0, 0}, - {COS45, 0.0, 0.0, SIN45, 0, 0}, - {0.0, 0.0, 0.0, 1.0, 0, 0} - }; - - QuatToMat3(v3d->viewquat, viewmat); - - for (i = 0 ; i < 39; i++){ - float snapmat[3][3]; - float view = (int)snapquats[i][4]; - float oposite_dir = (int)snapquats[i][5]; - - QuatToMat3(snapquats[i], snapmat); - - if ((Inpf(snapmat[0], viewmat[0]) > thres) && - (Inpf(snapmat[1], viewmat[1]) > thres) && - (Inpf(snapmat[2], viewmat[2]) > thres)){ - - QUATCOPY(v3d->viewquat, snapquats[i]); - - v3d->view = view; - if (view){ - if (oposite_dir){ - v3d->flag2 |= V3D_OPP_DIRECTION_NAME; - }else{ - v3d->flag2 &= ~V3D_OPP_DIRECTION_NAME; - } - } - - break; - } - } - } - } - else if(mode==1) { /* translate */ - if(v3d->persp==V3D_CAMOB) { - float max= (float)MAX2(ar->winx, ar->winy); - - v3d->camdx += (mvalo[0]-mval[0])/(max); - v3d->camdy += (mvalo[1]-mval[1])/(max); - CLAMP(v3d->camdx, -1.0f, 1.0f); - CLAMP(v3d->camdy, -1.0f, 1.0f); - preview3d_event= 0; - } - else { - window_to_3d(ar, v3d, dvec, mval[0]-mvalo[0], mval[1]-mvalo[1]); - VecAddf(v3d->ofs, v3d->ofs, dvec); - } - } - else if(mode==2) { - float zfac=1.0; - - /* use initial value (do not use mvalo (that is used to detect mouse moviments)) */ - mvalo[0] = mvali[0]; - mvalo[1] = mvali[1]; - - if(U.viewzoom==USER_ZOOM_CONT) { - // oldstyle zoom - zfac = 1.0+(float)(mvalo[0]-mval[0]+mvalo[1]-mval[1])/1000.0; - } - else if(U.viewzoom==USER_ZOOM_SCALE) { - int ctr[2], len1, len2; - // method which zooms based on how far you move the mouse - - ctr[0] = (ar->winrct.xmax + ar->winrct.xmin)/2; - ctr[1] = (ar->winrct.ymax + ar->winrct.ymin)/2; - - len1 = (int)sqrt((ctr[0] - mval[0])*(ctr[0] - mval[0]) + (ctr[1] - mval[1])*(ctr[1] - mval[1])) + 5; - len2 = (int)sqrt((ctr[0] - mvalo[0])*(ctr[0] - mvalo[0]) + (ctr[1] - mvalo[1])*(ctr[1] - mvalo[1])) + 5; - - zfac = dist0 * ((float)len2/len1) / v3d->dist; - } - else { /* USER_ZOOM_DOLLY */ - float len1 = (ar->winrct.ymax - mval[1]) + 5; - float len2 = (ar->winrct.ymax - mvalo[1]) + 5; - zfac = dist0 * (2.0*((len2/len1)-1.0) + 1.0) / v3d->dist; - } - - if(zfac != 1.0 && zfac*v3d->dist > 0.001*v3d->grid && - zfac*v3d->dist < 10.0*v3d->far) - view_zoom_mouseloc(ar, v3d, zfac, mval_area); - - - if ((U.uiflag & USER_ORBIT_ZBUF) && (U.viewzoom==USER_ZOOM_CONT) && (v3d->persp==V3D_PERSP)) { - /* Secret apricot feature, translate the view when in continues mode */ - upvec[0] = upvec[1] = 0; - upvec[2] = (dist0 - v3d->dist) * v3d->grid; - v3d->dist = dist0; - Mat3CpyMat4(mat, v3d->viewinv); - Mat3MulVecfl(mat, upvec); - VecAddf(v3d->ofs, v3d->ofs, upvec); - } else { - /* these limits are in toets.c too */ - if(v3d->dist<0.001*v3d->grid) v3d->dist= 0.001*v3d->grid; - if(v3d->dist>10.0*v3d->far) v3d->dist=10.0*v3d->far; - } - - if(v3d->persp==V3D_ORTHO || v3d->persp==V3D_CAMOB) preview3d_event= 0; - } - - - - mvalo[0]= mval[0]; - mvalo[1]= mval[1]; - -// XXX if(G.f & G_PLAYANIM) inner_play_anim_loop(0, 0); - - /* If in retopo paint mode, update lines */ - if(retopo_mesh_paint_check() && v3d->retopo_view_data) { - v3d->retopo_view_data->queue_matrix_update= 1; - retopo_paint_view_update(v3d); - } - -// XXX scrarea_do_windraw(ar); -// XXX screen_swapbuffers(); - } - else { -// short val; -// unsigned short event; - /* we need to empty the queue... when you do this very long it overflows */ -// XX while(qtest()) event= extern_qread(&val); - -// XXX BIF_wait_for_statechange(); - } - - /* this in the end, otherwise get_mbut does not work on a PC... */ -// XXX if( !(get_mbut() & (L_MOUSE|M_MOUSE))) break; - } - - if(v3d->depths) v3d->depths->damaged= 1; -// XXX retopo_queue_updates(v3d); -// XXX allqueue(REDRAWVIEW3D, 0); - -// XXX if(preview3d_event) -// BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT); -// else -// BIF_view3d_previewrender_signal(ar, PR_PROJECTED); - -} - - void viewmoveNDOF(Scene *scene, View3D *v3d, int mode) { float fval[7]; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 6c0a978f088..4067fb2bc4c 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -33,6 +33,7 @@ struct BoundBox; struct Object; struct DerivedMesh; +struct wmOperatorType; typedef struct ViewDepths { unsigned short w, h; @@ -56,6 +57,15 @@ typedef struct ViewDepths { /* view3d_header.c */ void view3d_header_buttons(const struct bContext *C, ARegion *ar); +/* view3d_ops.c */ +void view3d_operatortypes(void); +void view3d_keymap(struct wmWindowManager *wm); + +/* view3d_edit.c */ +void ED_VIEW3D_OT_viewzoom(struct wmOperatorType *ot); +void ED_VIEW3D_OT_viewmove(struct wmOperatorType *ot); +void ED_VIEW3D_OT_viewrotate(struct wmOperatorType *ot); + /* drawobject.c */ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, int flag); int draw_glsl_material(Scene *scene, Object *ob, View3D *v3d, int dt); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c new file mode 100644 index 00000000000..31b7fe33ea7 --- /dev/null +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -0,0 +1,77 @@ +/** + * $Id: + * + * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include <stdlib.h> +#include <math.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_space_types.h" +#include "DNA_userdef_types.h" +#include "DNA_view3d_types.h" +#include "DNA_windowmanager_types.h" + +#include "BLI_arithb.h" +#include "BLI_blenlib.h" + +#include "BKE_context.h" +#include "BKE_global.h" +#include "BKE_utildefines.h" + +#include "RNA_access.h" +#include "RNA_define.h" + +#include "WM_api.h" +#include "WM_types.h" + +#include "ED_screen.h" + +#include "view3d_intern.h" + + +/* ************************** registration **********************************/ + +void view3d_operatortypes(void) +{ + WM_operatortype_append(ED_VIEW3D_OT_viewrotate); + WM_operatortype_append(ED_VIEW3D_OT_viewmove); + WM_operatortype_append(ED_VIEW3D_OT_viewzoom); +} + +void view3d_keymap(wmWindowManager *wm) +{ + ListBase *keymap= WM_keymap_listbase(wm, "View3D", SPACE_VIEW3D, 0); + + WM_keymap_verify_item(keymap, "ED_VIEW3D_OT_viewrotate", MIDDLEMOUSE, KM_PRESS, 0, 0); + WM_keymap_verify_item(keymap, "ED_VIEW3D_OT_viewmove", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); + WM_keymap_verify_item(keymap, "ED_VIEW3D_OT_viewzoom", MIDDLEMOUSE, KM_PRESS, KM_CTRL, 0); +} + |