diff options
author | Joerg Mueller <nexyon@gmail.com> | 2011-08-02 16:16:06 +0400 |
---|---|---|
committer | Joerg Mueller <nexyon@gmail.com> | 2011-08-02 16:16:06 +0400 |
commit | 4e8e502c0267faa68ce686df51cfb061d73ae93e (patch) | |
tree | bf68517c1b537247b52b34d206cc640dc7280b31 /source/blender | |
parent | f5cff8ad37edbb46f155e768a07ff6785938f1b9 (diff) | |
parent | de0db6c8daaf4f6276b43bd4c78d623fdb0eafb9 (diff) |
Merging trunk up to r38932.
Diffstat (limited to 'source/blender')
47 files changed, 1446 insertions, 813 deletions
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 0491116d199..557ce417b14 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -115,5 +115,6 @@ int minmax_curve(struct Curve *cu, float min[3], float max[3]); int curve_center_median(struct Curve *cu, float cent[3]); int curve_center_bounds(struct Curve *cu, float cent[3]); void curve_translate(struct Curve *cu, float offset[3], int do_keys); +void curve_delete_material_index(struct Curve *cu, int index); #endif diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index d21b0428d76..17876c6ec9d 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -92,9 +92,6 @@ typedef struct Global { /* save the allowed windowstate of blender when using -W or -w */ int windowstate; - - /* ndof device found ? */ - int ndofdevice; } Global; /* **************** GLOBAL ********************* */ @@ -174,5 +171,3 @@ extern Global G; #endif #endif - - diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index c445408609c..88965d12e4a 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -78,7 +78,7 @@ int object_remove_material_slot(struct Object *ob); /* rna api */ void material_append_id(struct ID *id, struct Material *ma); -struct Material *material_pop_id(struct ID *id, int index); +struct Material *material_pop_id(struct ID *id, int index, int remove_material_slot); /* rendering */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index d9c98bc0200..62b8830de20 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1883,7 +1883,9 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos /* set the DerivedMesh to only copy needed data */ mask= (CustomDataMask)GET_INT_FROM_POINTER(curr->link); - DM_set_only_copy(dm, mask); + /* needMapping check here fixes bug [#28112], otherwise its + * possible that it wont be copied */ + DM_set_only_copy(dm, mask | (needMapping ? CD_MASK_ORIGINDEX : 0)); /* add cloth rest shape key if need */ if(mask & CD_MASK_CLOTH_ORCO) diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 202a3f28d9a..eb364af6ff8 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -580,46 +580,47 @@ void addNurbPointsBezier(Nurb *nu, int number) /* ~~~~~~~~~~~~~~~~~~~~Non Uniform Rational B Spline calculations ~~~~~~~~~~~ */ -static void calcknots(float *knots, short aantal, short order, short type) -/* knots: number of pnts NOT corrected for cyclic */ -/* type; 0: uniform, 1: endpoints, 2: bezier */ +static void calcknots(float *knots, const short pnts, const short order, const short flag) { + /* knots: number of pnts NOT corrected for cyclic */ + const int pnts_order= pnts + order; float k; - int a, t; - - t = aantal+order; - if(type==0) { + int a; - for(a=0;a<t;a++) { - knots[a]= (float)a; - } - } - else if(type==1) { + switch(flag & (CU_NURB_ENDPOINT|CU_NURB_BEZIER)) { + case CU_NURB_ENDPOINT: k= 0.0; - for(a=1;a<=t;a++) { + for(a=1; a <= pnts_order; a++) { knots[a-1]= k; - if(a>=order && a<=aantal) k+= 1.0f; + if(a >= order && a <= pnts) k+= 1.0f; } - } - else if(type==2) { - /* Warning, the order MUST be 2 or 4, if this is not enforced, the displist will be corrupt */ + break; + case CU_NURB_BEZIER: + /* Warning, the order MUST be 2 or 4, + * if this is not enforced, the displist will be corrupt */ if(order==4) { k= 0.34; - for(a=0;a<t;a++) { + for(a=0; a < pnts_order; a++) { knots[a]= floorf(k); k+= (1.0f/3.0f); } } else if(order==3) { k= 0.6f; - for(a=0;a<t;a++) { - if(a>=order && a<=aantal) k+= 0.5f; + for(a=0; a < pnts_order; a++) { + if(a >= order && a <= pnts) k+= 0.5f; knots[a]= floorf(k); } } else { printf("bez nurb curve order is not 3 or 4, should never happen\n"); } + break; + default: + for(a=0; a < pnts_order; a++) { + knots[a]= (float)a; + } + break; } } @@ -662,7 +663,7 @@ static void makeknots(Nurb *nu, short uv) calcknots(nu->knotsu, nu->pntsu, nu->orderu, 0); /* cyclic should be uniform */ makecyclicknots(nu->knotsu, nu->pntsu, nu->orderu); } else { - calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu>>1); + calcknots(nu->knotsu, nu->pntsu, nu->orderu, nu->flagu); } } else nu->knotsu= NULL; @@ -675,7 +676,7 @@ static void makeknots(Nurb *nu, short uv) calcknots(nu->knotsv, nu->pntsv, nu->orderv, 0); /* cyclic should be uniform */ makecyclicknots(nu->knotsv, nu->pntsv, nu->orderv); } else { - calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv>>1); + calcknots(nu->knotsv, nu->pntsv, nu->orderv, nu->flagv); } } else nu->knotsv= NULL; @@ -3259,3 +3260,28 @@ void curve_translate(Curve *cu, float offset[3], int do_keys) } } } + +void curve_delete_material_index(Curve *cu, int index) +{ + const int curvetype= curve_type(cu); + + if(curvetype == OB_FONT) { + struct CharInfo *info= cu->strinfo; + int i; + for(i= cu->len-1; i >= 0; i--, info++) { + if (info->mat_nr && info->mat_nr>=index) { + info->mat_nr--; + } + } + } + else { + Nurb *nu; + + for (nu= cu->nurb.first; nu; nu= nu->next) { + if(nu->mat_nr && nu->mat_nr>=index) { + nu->mat_nr--; + if (curvetype == OB_CURVE) nu->charidx--; + } + } + } +} diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 50c120a3ec1..2aef5b39c71 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -474,20 +474,20 @@ static int setkeys(float fac, ListBase *lb, KeyBlock *k[], float *t, int cycl) } -static void flerp(int aantal, float *in, float *f0, float *f1, float *f2, float *f3, float *t) +static void flerp(int tot, float *in, float *f0, float *f1, float *f2, float *f3, float *t) { int a; - for(a=0; a<aantal; a++) { + for(a=0; a<tot; a++) { in[a]= t[0]*f0[a]+t[1]*f1[a]+t[2]*f2[a]+t[3]*f3[a]; } } -static void rel_flerp(int aantal, float *in, float *ref, float *out, float fac) +static void rel_flerp(int tot, float *in, float *ref, float *out, float fac) { int a; - for(a=0; a<aantal; a++) { + for(a=0; a<tot; a++) { in[a]-= fac*(ref[a]-out[a]); } } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 3f01c55e935..9c455e84109 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -61,7 +61,7 @@ #include "BKE_material.h" #include "BKE_mesh.h" #include "BKE_node.h" - +#include "BKE_curve.h" #include "GPU_material.h" @@ -515,6 +515,21 @@ short *give_totcolp_id(ID *id) return NULL; } +void data_delete_material_index_id(ID *id, int index) +{ + switch(GS(id->name)) { + case ID_ME: + mesh_delete_material_index((Mesh *)id, index); + break; + case ID_CU: + curve_delete_material_index((Curve *)id, index); + break; + case ID_MB: + /* meta-elems dont have materials atm */ + break; + } +} + void material_append_id(ID *id, Material *ma) { Material ***matar; @@ -532,7 +547,7 @@ void material_append_id(ID *id, Material *ma) } } -Material *material_pop_id(ID *id, int index) +Material *material_pop_id(ID *id, int index, int remove_material_slot) { Material *ret= NULL; Material ***matar; @@ -540,27 +555,36 @@ Material *material_pop_id(ID *id, int index) short *totcol= give_totcolp_id(id); if(index >= 0 && index < (*totcol)) { ret= (*matar)[index]; - id_us_min((ID *)ret); - if(*totcol <= 1) { - *totcol= 0; - MEM_freeN(*matar); - *matar= NULL; - } - else { - Material **mat; - - if(index + 1 != (*totcol)) - memmove((*matar)+index, (*matar)+(index+1), sizeof(void *) * ((*totcol) - (index + 1))); + id_us_min((ID *)ret); - (*totcol)--; - - mat= MEM_callocN(sizeof(void *) * (*totcol), "newmatar"); - memcpy(mat, *matar, sizeof(void *) * (*totcol)); - MEM_freeN(*matar); + if (remove_material_slot) { + if(*totcol <= 1) { + *totcol= 0; + MEM_freeN(*matar); + *matar= NULL; + } + else { + Material **mat; + if(index + 1 != (*totcol)) + memmove((*matar)+index, (*matar)+(index+1), sizeof(void *) * ((*totcol) - (index + 1))); + + (*totcol)--; + + mat= MEM_callocN(sizeof(void *) * (*totcol), "newmatar"); + memcpy(mat, *matar, sizeof(void *) * (*totcol)); + MEM_freeN(*matar); + + *matar= mat; + test_object_materials(id); + } - *matar= mat; - test_object_materials(id); + /* decrease mat_nr index */ + data_delete_material_index_id(id, index); } + + /* don't remove material slot, only clear it*/ + else + (*matar)[index]= NULL; } } @@ -1025,8 +1049,6 @@ int object_remove_material_slot(Object *ob) { Material *mao, ***matarar; Object *obt; - Curve *cu; - Nurb *nu; short *totcolp; int a, actcol; @@ -1086,23 +1108,8 @@ int object_remove_material_slot(Object *ob) } /* check indices from mesh */ - - if(ob->type==OB_MESH) { - Mesh *me= get_mesh(ob); - mesh_delete_material_index(me, actcol-1); - freedisplist(&ob->disp); - } - else if ELEM(ob->type, OB_CURVE, OB_SURF) { - cu= ob->data; - nu= cu->nurb.first; - - while(nu) { - if(nu->mat_nr && nu->mat_nr>=actcol-1) { - nu->mat_nr--; - if (ob->type == OB_CURVE) nu->charidx--; - } - nu= nu->next; - } + if (ELEM4(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + data_delete_material_index_id((ID *)ob->data, actcol-1); freedisplist(&ob->disp); } diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 45a60b842a7..32819226361 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -1254,10 +1254,10 @@ void mesh_to_curve(Scene *scene, Object *ob) void mesh_delete_material_index(Mesh *me, int index) { + MFace *mf; int i; - for (i=0; i<me->totface; i++) { - MFace *mf = &((MFace*) me->mface)[i]; + for (i=0, mf=me->mface; i<me->totface; i++, mf++) { if (mf->mat_nr && mf->mat_nr>=index) mf->mat_nr--; } diff --git a/source/blender/blenlib/intern/BLI_args.c b/source/blender/blenlib/intern/BLI_args.c index 7bc93a3d3a0..5f31565d65b 100644 --- a/source/blender/blenlib/intern/BLI_args.c +++ b/source/blender/blenlib/intern/BLI_args.c @@ -290,8 +290,10 @@ void BLI_argsParse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void * } i += retval; } else if (retval == -1){ - if (a->key->pass != -1) - ba->passes[i] = pass; + if (a) { + if (a->key->pass != -1) + ba->passes[i] = pass; + } break; } } diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 85d79ae3b85..0613765b868 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -26,7 +26,6 @@ - #include "DNA_meshdata_types.h" #include "MEM_guardedalloc.h" @@ -85,25 +84,61 @@ struct PBVHNode { /* Opaque handle for drawing code */ void *draw_buffers; - int *vert_indices; - /* Voxel bounds */ BB vb; BB orig_vb; - /* For internal nodes */ + /* For internal nodes, the offset of the children in the PBVH + 'nodes' array. */ int children_offset; - /* Pointer into bvh prim_indices */ - int *prim_indices; - int *face_vert_indices; + /* Pointer into the PBVH prim_indices array and the number of + primitives used by this leaf node. + Used for leaf nodes in both mesh- and multires-based PBVHs. + */ + int *prim_indices; unsigned int totprim; + + /* Array of indices into the mesh's MVert array. Contains the + indices of all vertices used by faces that are within this + node's bounding box. + + Note that a vertex might be used by a multiple faces, and + these faces might be in different leaf nodes. Such a vertex + will appear in the vert_indices array of each of those leaf + nodes. + + In order to support cases where you want access to multiple + nodes' vertices without duplication, the vert_indices array + is ordered such that the first part of the array, up to + index 'uniq_verts', contains "unique" vertex indices. These + vertices might not be truly unique to this node, but if + they appear in another node's vert_indices array, they will + be above that node's 'uniq_verts' value. + + Used for leaf nodes in a mesh-based PBVH (not multires.) + */ + int *vert_indices; unsigned int uniq_verts, face_verts; - char flag; + /* An array mapping face corners into the vert_indices + array. The array is sized to match 'totprim', and each of + the face's corners gets an index into the vert_indices + array, in the same order as the corners in the original + MFace. The fourth value should not be used if the original + face is a triangle. + + Used for leaf nodes in a mesh-based PBVH (not multires.) + */ + int (*face_vert_indices)[4]; + + /* Indicates whether this node is a leaf or not; also used for + marking various updates that need to be applied. */ + PBVHNodeFlags flag : 8; - float tmin; // used for raycasting, is how close bb is to the ray point + /* Used for raycasting: how close bb is to the ray point. */ + float tmin; int proxy_count; PBVHProxyNode* proxies; @@ -339,15 +374,15 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) node->uniq_verts = node->face_verts = 0; totface= node->totprim; - node->face_vert_indices = MEM_callocN(sizeof(int) * - 4*totface, "bvh node face vert indices"); + node->face_vert_indices = MEM_callocN(sizeof(int) * 4*totface, + "bvh node face vert indices"); for(i = 0; i < totface; ++i) { MFace *f = bvh->faces + node->prim_indices[i]; int sides = f->v4 ? 4 : 3; for(j = 0; j < sides; ++j) { - node->face_vert_indices[i*4 + j]= + node->face_vert_indices[i][j]= map_insert_vert(bvh, map, &node->face_verts, &node->uniq_verts, (&f->v1)[j]); } @@ -373,9 +408,17 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node) BLI_ghashIterator_free(iter); - for(i = 0; i < totface*4; ++i) - if(node->face_vert_indices[i] < 0) - node->face_vert_indices[i]= -node->face_vert_indices[i] + node->uniq_verts - 1; + for(i = 0; i < totface; ++i) { + MFace *f = bvh->faces + node->prim_indices[i]; + int sides = f->v4 ? 4 : 3; + + for(j = 0; j < sides; ++j) { + if(node->face_vert_indices[i][j] < 0) + node->face_vert_indices[i][j]= + -node->face_vert_indices[i][j] + + node->uniq_verts - 1; + } + } if(!G.background) { node->draw_buffers = @@ -1340,20 +1383,20 @@ int BLI_pbvh_node_raycast(PBVH *bvh, PBVHNode *node, float (*origco)[3], if(bvh->faces) { MVert *vert = bvh->verts; int *faces= node->prim_indices; - int *face_verts= node->face_vert_indices; int totface= node->totprim; int i; for(i = 0; i < totface; ++i) { MFace *f = bvh->faces + faces[i]; + int *face_verts = node->face_vert_indices[i]; if(origco) { /* intersect with backuped original coordinates */ hit |= ray_face_intersection(ray_start, ray_normal, - origco[face_verts[i*4+0]], - origco[face_verts[i*4+1]], - origco[face_verts[i*4+2]], - f->v4? origco[face_verts[i*4+3]]: NULL, + origco[face_verts[0]], + origco[face_verts[1]], + origco[face_verts[2]], + f->v4? origco[face_verts[3]]: NULL, dist); } else { diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 18b461eb31d..1737b44a56f 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3163,7 +3163,7 @@ static void lib_link_particlesettings(FileData *fd, Main *main) if(part->effector_weights) part->effector_weights->group = newlibadr(fd, part->id.lib, part->effector_weights->group); - if(part->dupliweights.first) { + if(part->dupliweights.first && part->dup_group) { int index_ok = 0; /* check for old files without indices (all indexes 0) */ dw = part->dupliweights.first; @@ -3194,6 +3194,9 @@ static void lib_link_particlesettings(FileData *fd, Main *main) dw->ob = newlibadr(fd, part->id.lib, dw->ob); } } + else { + part->dupliweights.first = part->dupliweights.last = NULL; + } if(part->boids) { BoidState *state = part->boids->states.first; diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 06d88b16fa8..210f36ca074 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -3432,7 +3432,6 @@ static int convertspline(short type, Nurb *nu) nu->type = CU_NURBS; nu->orderu= 4; nu->flagu &= CU_NURB_CYCLIC; /* disable all flags except for cyclic */ - nu->flagu |= CU_NURB_BEZIER; nurbs_knot_calc_u(nu); a= nu->pntsu*nu->pntsv; bp= nu->bp; @@ -6544,12 +6543,15 @@ Nurb *add_nurbs_primitive(bContext *C, float mat[4][4], int type, int newob) BLI_assert(!"invalid nurbs type"); return NULL; } - - /* always do: */ - nu->flag |= CU_SMOOTH; - - test2DNurb(nu); - + + BLI_assert(nu != NULL); + + if(nu) { /* should always be set */ + nu->flag |= CU_SMOOTH; + + test2DNurb(nu); + } + return nu; } diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index f4da734473d..28a54b20277 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1617,6 +1617,18 @@ static int gpencil_draw_modal (bContext *C, wmOperator *op, wmEvent *event) tGPsdata *p= op->customdata; int estate = OPERATOR_PASS_THROUGH; /* default exit state - not handled, so let others have a share of the pie */ + // if (event->type == NDOF_MOTION) + // return OPERATOR_PASS_THROUGH; + // ------------------------------- + // [mce] Not quite what I was looking + // for, but a good start! GP continues to + // draw on the screen while the 3D mouse + // moves the viewpoint. Problem is that + // the stroke is converted to 3D only after + // it is finished. This approach should work + // better in tools that immediately apply + // in 3D space. + //printf("\tGP - handle modal event...\n"); /* exit painting mode (and/or end current stroke) */ diff --git a/source/blender/editors/interface/interface_anim.c b/source/blender/editors/interface/interface_anim.c index 2e172c496a3..1113f90a652 100644 --- a/source/blender/editors/interface/interface_anim.c +++ b/source/blender/editors/interface/interface_anim.c @@ -1,3 +1,27 @@ +/* + * $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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): + * + * ***** END GPL LICENSE BLOCK ***** + */ + /** \file blender/editors/interface/interface_anim.c * \ingroup edinterface */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index 1aa2fb391db..adabfe5f230 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -1,6 +1,3 @@ -/** \file blender/editors/interface/resources.c - * \ingroup edinterface - */ /* * $Id$ * @@ -33,6 +30,10 @@ * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ +/** \file blender/editors/interface/resources.c + * \ingroup edinterface + */ + #include <math.h> #include <stdlib.h> #include <string.h> @@ -1587,6 +1588,12 @@ void init_userdef_do_versions(void) if (U.anisotropic_filter <= 0) U.anisotropic_filter = 1; + if (U.ndof_sensitivity == 0.0f) { + U.ndof_sensitivity = 1.0f; + U.ndof_flag = NDOF_LOCK_HORIZON | + NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM | NDOF_SHOULD_ROTATE; + } + /* funny name, but it is GE stuff, moves userdef stuff to engine */ // XXX space_set_commmandline_options(); /* this timer uses U */ diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index ab9c69988fe..ce1f47c1b7b 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1097,7 +1097,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); View3D *v3d= CTX_wm_view3d(C); unsigned int lay, local; - int islamp= 0; + /* int islamp= 0; */ /* UNUSED */ lay= move_to_layer_init(C, op); lay &= 0xFFFFFF; @@ -1113,7 +1113,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) base->object->lay= lay; base->object->flag &= ~SELECT; base->flag &= ~SELECT; - if(base->object->type==OB_LAMP) islamp= 1; + /* if(base->object->type==OB_LAMP) islamp= 1; */ } CTX_DATA_END; } @@ -1125,7 +1125,7 @@ static int move_to_layer_exec(bContext *C, wmOperator *op) local= base->lay & 0xFF000000; base->lay= lay + local; base->object->lay= lay; - if(base->object->type==OB_LAMP) islamp= 1; + /* if(base->object->type==OB_LAMP) islamp= 1; */ } CTX_DATA_END; } diff --git a/source/blender/editors/screen/screen_ops.c b/source/blender/editors/screen/screen_ops.c index 68326edfb11..1410331700f 100644 --- a/source/blender/editors/screen/screen_ops.c +++ b/source/blender/editors/screen/screen_ops.c @@ -301,7 +301,7 @@ int ED_operator_object_active_editable(bContext *C) int ED_operator_object_active_editable_mesh(bContext *C) { Object *ob = ED_object_active_context(C); - return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && ob->type == OB_MESH); + return ((ob != NULL) && !(ob->id.lib) && !(ob->restrictflag & OB_RESTRICT_VIEW) && ob->type == OB_MESH && !(((ID *)ob->data)->lib)); } int ED_operator_object_active_editable_font(bContext *C) diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index c9a6aa87cd0..32004fd4525 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -2187,7 +2187,7 @@ static int IsectPoly2Df_twoside(const float pt[2], float uv[][2], const int tot) /* One of the most important function for projectiopn painting, since it selects the pixels to be added into each bucket. * initialize pixels from this face where it intersects with the bucket_index, optionally initialize pixels for removing seams */ -static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf) +static void project_paint_face_init(const ProjPaintState *ps, const int thread_index, const int bucket_index, const int face_index, const int image_index, rctf *bucket_bounds, const ImBuf *ibuf, const short clamp_u, const short clamp_v) { /* Projection vars, to get the 3D locations into screen space */ MemArena *arena = ps->arena_mt[thread_index]; @@ -2304,14 +2304,24 @@ static void project_paint_face_init(const ProjPaintState *ps, const int thread_i if (pixel_bounds_array(uv_clip, &bounds_px, ibuf->x, ibuf->y, uv_clip_tot)) { - + + if(clamp_u) { + CLAMP(bounds_px.xmin, 0, ibuf->x); + CLAMP(bounds_px.xmax, 0, ibuf->x); + } + + if(clamp_v) { + CLAMP(bounds_px.ymin, 0, ibuf->y); + CLAMP(bounds_px.ymax, 0, ibuf->y); + } + /* clip face and */ has_isect = 0; for (y = bounds_px.ymin; y < bounds_px.ymax; y++) { //uv[1] = (((float)y) + 0.5f) / (float)ibuf->y; uv[1] = (float)y / ibuf_yf; /* use pixel offset UV coords instead */ - + has_x_isect = 0; for (x = bounds_px.xmin; x < bounds_px.xmax; x++) { //uv[0] = (((float)x) + 0.5f) / ibuf->x; @@ -2630,6 +2640,7 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index LinkNode *node; int face_index, image_index=0; ImBuf *ibuf = NULL; + Image *ima = NULL; MTFace *tf; Image *tpage_last = NULL; @@ -2638,9 +2649,10 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index if (ps->image_tot==1) { /* Simple loop, no context switching */ ibuf = ps->projImages[0].ibuf; - + ima = ps->projImages[0].ima; + for (node = ps->bucketFaces[bucket_index]; node; node= node->next) { - project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf); + project_paint_face_init(ps, thread_index, bucket_index, GET_INT_FROM_POINTER(node->link), 0, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); } } else { @@ -2659,14 +2671,14 @@ static void project_bucket_init(const ProjPaintState *ps, const int thread_index for (image_index=0; image_index < ps->image_tot; image_index++) { if (ps->projImages[image_index].ima == tpage_last) { ibuf = ps->projImages[image_index].ibuf; + ima = ps->projImages[image_index].ima; break; } } } /* context switching done */ - project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf); - + project_paint_face_init(ps, thread_index, bucket_index, face_index, image_index, bucket_bounds, ibuf, ima->tpageflag & IMA_CLAMP_U, ima->tpageflag & IMA_CLAMP_V); } } diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 7ddf5dff000..09873566d4a 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -832,6 +832,13 @@ int paint_stroke_modal(bContext *C, wmOperator *op, wmEvent *event) float mouse[2]; int first= 0; + // let NDOF motion pass through to the 3D view so we can paint and rotate simultaneously! + // this isn't perfect... even when an extra MOUSEMOVE is spoofed, the stroke discards it + // since the 2D deltas are zero -- code in this file needs to be updated to use the + // post-NDOF_MOTION MOUSEMOVE + if (event->type == NDOF_MOTION) + return OPERATOR_PASS_THROUGH; + if(!stroke->stroke_started) { stroke->last_mouse_position[0] = event->x; stroke->last_mouse_position[1] = event->y; diff --git a/source/blender/editors/space_image/image_intern.h b/source/blender/editors/space_image/image_intern.h index e9e77ddf430..399157da85c 100644 --- a/source/blender/editors/space_image/image_intern.h +++ b/source/blender/editors/space_image/image_intern.h @@ -73,6 +73,7 @@ void IMAGE_OT_view_zoom(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_in(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_out(struct wmOperatorType *ot); void IMAGE_OT_view_zoom_ratio(struct wmOperatorType *ot); +void IMAGE_OT_view_ndof(struct wmOperatorType *ot); void IMAGE_OT_new(struct wmOperatorType *ot); void IMAGE_OT_open(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index d5515bd1cf8..6e84c1a7f0c 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -437,6 +437,60 @@ void IMAGE_OT_view_zoom(wmOperatorType *ot) "Factor", "Zoom factor, values higher than 1.0 zoom in, lower values zoom out.", -FLT_MAX, FLT_MAX); } +/********************** NDOF operator *********************/ + +/* Combined pan/zoom from a 3D mouse device. + * Z zooms, XY pans + * "view" (not "paper") control -- user moves the viewpoint, not the image being viewed + * that explains the negative signs in the code below + */ + +static int view_ndof_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +{ + SpaceImage *sima= CTX_wm_space_image(C); + ARegion *ar= CTX_wm_region(C); + + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + float dt = ndof->dt > 0.25f ? 0.0125f : ndof->dt; + /* this is probably the first event for this motion, so set dt to something reasonable + * TODO: replace such guesswork with a flag or field from the NDOF manager + */ + + /* tune these until it feels right */ + const float zoom_sensitivity = 0.5f; + const float pan_sensitivity = 300.f; + + float pan_x = pan_sensitivity * dt * ndof->tvec[0] / sima->zoom; + float pan_y = pan_sensitivity * dt * ndof->tvec[1] / sima->zoom; + + /* "mouse zoom" factor = 1 + (dx + dy) / 300 + * what about "ndof zoom" factor? should behave like this: + * at rest -> factor = 1 + * move forward -> factor > 1 + * move backward -> factor < 1 + */ + float zoom_factor = 1.f + zoom_sensitivity * dt * -ndof->tvec[2]; + + sima_zoom_set_factor(sima, ar, zoom_factor); + sima->xof += pan_x; + sima->yof += pan_y; + + ED_region_tag_redraw(ar); + + return OPERATOR_FINISHED; +} + +void IMAGE_OT_view_ndof(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "NDOF Pan/Zoom"; + ot->idname= "IMAGE_OT_view_ndof"; + + /* api callbacks */ + ot->invoke= view_ndof_invoke; +} + /********************** view all operator *********************/ /* Updates the fields of the View2D member of the SpaceImage struct. diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 2e9544f5d20..afab4ede229 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -469,6 +469,7 @@ static void image_operatortypes(void) WM_operatortype_append(IMAGE_OT_view_zoom_in); WM_operatortype_append(IMAGE_OT_view_zoom_out); WM_operatortype_append(IMAGE_OT_view_zoom_ratio); + WM_operatortype_append(IMAGE_OT_view_ndof); WM_operatortype_append(IMAGE_OT_new); WM_operatortype_append(IMAGE_OT_open); @@ -518,6 +519,9 @@ static void image_keymap(struct wmKeyConfig *keyconf) WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MIDDLEMOUSE, KM_PRESS, KM_SHIFT, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_pan", MOUSEPAN, 0, 0, 0); + WM_keymap_add_item(keymap, "IMAGE_OT_view_all", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); // or view selected? + WM_keymap_add_item(keymap, "IMAGE_OT_view_ndof", NDOF_MOTION, 0, 0, 0); + WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", WHEELINMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_out", WHEELOUTMOUSE, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "IMAGE_OT_view_zoom_in", PADPLUSKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index d2ff6eef097..6e3f6549ba3 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -675,6 +675,104 @@ static void draw_view_axis(RegionView3D *rv3d) glDisable(GL_BLEND); } +/* draw center and axis of rotation for ongoing 3D mouse navigation */ +static void draw_rotation_guide(RegionView3D *rv3d) +{ + float o[3]; // center of rotation + float end[3]; // endpoints for drawing + + float color[4] = {0.f ,0.4235f, 1.f, 1.f}; // bright blue so it matches device LEDs + + negate_v3_v3(o, rv3d->ofs); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glShadeModel(GL_SMOOTH); + glPointSize(5); + glEnable(GL_POINT_SMOOTH); + glDepthMask(0); // don't overwrite zbuf + + if (rv3d->rot_angle != 0.f) { + // -- draw rotation axis -- + float scaled_axis[3]; + const float scale = rv3d->dist; + mul_v3_v3fl(scaled_axis, rv3d->rot_axis, scale); + + glBegin(GL_LINE_STRIP); + color[3] = 0.f; // more transparent toward the ends + glColor4fv(color); + add_v3_v3v3(end, o, scaled_axis); + glVertex3fv(end); + + // color[3] = 0.2f + fabsf(rv3d->rot_angle); // modulate opacity with angle + // ^^ neat idea, but angle is frame-rate dependent, so it's usually close to 0.2 + + color[3] = 0.5f; // more opaque toward the center + glColor4fv(color); + glVertex3fv(o); + + color[3] = 0.f; + glColor4fv(color); + sub_v3_v3v3(end, o, scaled_axis); + glVertex3fv(end); + glEnd(); + + // -- draw ring around rotation center -- + { + #define ROT_AXIS_DETAIL 13 + const float s = 0.05f * scale; + const float step = 2.f * M_PI / ROT_AXIS_DETAIL; + float angle; + int i; + + float q[4]; // rotate ring so it's perpendicular to axis + const int upright = fabsf(rv3d->rot_axis[2]) >= 0.95f; + if (!upright) + { + const float up[3] = {0.f, 0.f, 1.f}; + float vis_angle, vis_axis[3]; + + cross_v3_v3v3(vis_axis, up, rv3d->rot_axis); + vis_angle = acosf(dot_v3v3(up, rv3d->rot_axis)); + axis_angle_to_quat(q, vis_axis, vis_angle); + } + + color[3] = 0.25f; // somewhat faint + glColor4fv(color); + glBegin(GL_LINE_LOOP); + for (i = 0, angle = 0.f; i < ROT_AXIS_DETAIL; ++i, angle += step) + { + float p[3] = { s * cosf(angle), s * sinf(angle), 0.f }; + + if (!upright) + mul_qt_v3(q, p); + + add_v3_v3(p, o); + glVertex3fv(p); + } + glEnd(); + } + + color[3] = 1.f; // solid dot + } + else + color[3] = 0.5f; // see-through dot + + // -- draw rotation center -- + glColor4fv(color); + glBegin(GL_POINTS); + glVertex3fv(o); + glEnd(); + + // find screen coordinates for rotation center, then draw pretty icon + // mul_m4_v3(rv3d->persinv, rot_center); + // UI_icon_draw(rot_center[0], rot_center[1], ICON_NDOF_TURN); + // ^^ just playing around, does not work + + glDisable(GL_BLEND); + glDisable(GL_POINT_SMOOTH); + glDepthMask(1); +} static void draw_view_icon(RegionView3D *rv3d) { @@ -2618,6 +2716,10 @@ void view3d_main_area_draw(const bContext *C, ARegion *ar) BDR_drawSketch(C); } + if ((U.ndof_flag & NDOF_SHOW_GUIDE) && (rv3d->viewlock != RV3D_LOCKED) && (rv3d->persp != RV3D_CAMOB)) + // TODO: draw something else (but not this) during fly mode + draw_rotation_guide(rv3d); + ED_region_pixelspace(ar); // retopo_paint_view_update(v3d); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index d563c07baf3..e6fd9e8867b 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -928,6 +928,244 @@ void VIEW3D_OT_rotate(wmOperatorType *ot) ot->flag= OPTYPE_BLOCKING|OPTYPE_GRAB_POINTER; } +// NDOF utility functions +// (should these functions live in this file?) +float ndof_to_axis_angle(struct wmNDOFMotionData* ndof, float axis[3]) +{ + return ndof->dt * normalize_v3_v3(axis, ndof->rvec); +} + +void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]) +{ + float axis[3]; + float angle; + + angle= ndof_to_axis_angle(ndof, axis); + axis_angle_to_quat(q, axis, angle); +} + +static int ndof_orbit_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +// -- "orbit" navigation (trackball/turntable) +// -- zooming +// -- panning in rotationally-locked views +{ + RegionView3D* rv3d = CTX_wm_region_view3d(C); + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + rv3d->rot_angle = 0.f; // off by default, until changed later this function + + if (ndof->progress != P_FINISHING) { + const float dt = ndof->dt; + + // tune these until everything feels right + const float rot_sensitivity = 1.f; + const float zoom_sensitivity = 1.f; + const float pan_sensitivity = 1.f; + + // rather have bool, but... + int has_rotation = rv3d->viewlock != RV3D_LOCKED && !is_zero_v3(ndof->rvec); + + float view_inv[4]; + invert_qt_qt(view_inv, rv3d->viewquat); + + //#define DEBUG_NDOF_MOTION + #ifdef DEBUG_NDOF_MOTION + printf("ndof: T=(%.2f,%.2f,%.2f) R=(%.2f,%.2f,%.2f) dt=%.3f delivered to 3D view\n", + ndof->tx, ndof->ty, ndof->tz, ndof->rx, ndof->ry, ndof->rz, ndof->dt); + #endif + + if (ndof->tvec[2]) { + // Zoom! + // velocity should be proportional to the linear velocity attained by rotational motion of same strength + // [got that?] + // proportional to arclength = radius * angle + + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tvec[2]; + rv3d->dist += zoom_distance; + } + + if (rv3d->viewlock == RV3D_LOCKED) { + /* rotation not allowed -- explore panning options instead */ + float pan_vec[3] = {ndof->tvec[0], ndof->tvec[1], 0.0f}; + mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); + + /* transform motion from view to world coordinates */ + invert_qt_qt(view_inv, rv3d->viewquat); + mul_qt_v3(view_inv, pan_vec); + + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, pan_vec); + } + + if (has_rotation) { + + const int invert = U.ndof_flag & NDOF_ORBIT_INVERT_AXES; + + rv3d->view = RV3D_VIEW_USER; + + if (U.flag & USER_TRACKBALL) { + float rot[4]; + #if 0 // -------------------------- Mike's nifty original version + float view_inv_conj[4]; + + ndof_to_quat(ndof, rot); + // mul_qt_fl(rot, rot_sensitivity); + // ^^ no apparent effect + + if (invert) + invert_qt(rot); + + copy_qt_qt(view_inv_conj, view_inv); + conjugate_qt(view_inv_conj); + + // transform rotation from view to world coordinates + mul_qt_qtqt(rot, view_inv, rot); + mul_qt_qtqt(rot, rot, view_inv_conj); + #else // ---------------------------------------- Mike's revised version + float axis[3]; + float angle = rot_sensitivity * ndof_to_axis_angle(ndof, axis); + + if (invert) + angle = -angle; + + // transform rotation axis from view to world coordinates + mul_qt_v3(view_inv, axis); + + // update the onscreen doo-dad + rv3d->rot_angle = angle; + copy_v3_v3(rv3d->rot_axis, axis); + + axis_angle_to_quat(rot, axis, angle); + #endif // -------------------------------------------- + // apply rotation + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + } else { + /* turntable view code by John Aughey, adapted for 3D mouse by [mce] */ + float angle, rot[4]; + float xvec[3] = {1,0,0}; + + /* Determine the direction of the x vector (for rotating up and down) */ + mul_qt_v3(view_inv, xvec); + + /* Perform the up/down rotation */ + angle = rot_sensitivity * dt * ndof->rvec[0]; + if (invert) + angle = -angle; + rot[0] = cos(angle); + mul_v3_v3fl(rot+1, xvec, sin(angle)); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + + /* Perform the orbital rotation */ + angle = rot_sensitivity * dt * ndof->rvec[1]; + if (invert) + angle = -angle; + + // update the onscreen doo-dad + rv3d->rot_angle = angle; + rv3d->rot_axis[0] = 0; + rv3d->rot_axis[1] = 0; + rv3d->rot_axis[2] = 1; + + rot[0] = cos(angle); + rot[1] = rot[2] = 0.0; + rot[3] = sin(angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rot); + } + } + } + + ED_region_tag_redraw(CTX_wm_region(C)); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "NDOF Orbit View"; + ot->description = "Explore every angle of an object using the 3D mouse."; + ot->idname = "VIEW3D_OT_ndof_orbit"; + + /* api callbacks */ + ot->invoke = ndof_orbit_invoke; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = 0; +} + +static int ndof_pan_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +// -- "pan" navigation +// -- zoom or dolly? +{ + RegionView3D* rv3d = CTX_wm_region_view3d(C); + wmNDOFMotionData* ndof = (wmNDOFMotionData*) event->customdata; + + rv3d->rot_angle = 0.f; // we're panning here! so erase any leftover rotation from other operators + + if (ndof->progress != P_FINISHING) { + const float dt = ndof->dt; + float view_inv[4]; +#if 0 // ------------------------------------------- zoom with Z + // tune these until everything feels right + const float zoom_sensitivity = 1.f; + const float pan_sensitivity = 1.f; + + float pan_vec[3] = { + ndof->tx, ndof->ty, 0 + }; + + // "zoom in" or "translate"? depends on zoom mode in user settings? + if (ndof->tz) { + float zoom_distance = zoom_sensitivity * rv3d->dist * dt * ndof->tz; + rv3d->dist += zoom_distance; + } + + mul_v3_fl(pan_vec, pan_sensitivity * rv3d->dist * dt); +#else // ------------------------------------------------------- dolly with Z + float speed = 10.f; // blender units per second + // ^^ this is ok for default cube scene, but should scale with.. something + + // tune these until everything feels right + const float forward_sensitivity = 1.f; + const float vertical_sensitivity = 0.4f; + const float lateral_sensitivity = 0.6f; + + float pan_vec[3] = {lateral_sensitivity * ndof->tvec[0], + vertical_sensitivity * ndof->tvec[1], + forward_sensitivity * ndof->tvec[2] + }; + + mul_v3_fl(pan_vec, speed * dt); +#endif + /* transform motion from view to world coordinates */ + invert_qt_qt(view_inv, rv3d->viewquat); + mul_qt_v3(view_inv, pan_vec); + + /* move center of view opposite of hand motion (this is camera mode, not object mode) */ + sub_v3_v3(rv3d->ofs, pan_vec); + } + + ED_region_tag_redraw(CTX_wm_region(C)); + + return OPERATOR_FINISHED; +} + +void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "NDOF Pan View"; + ot->description = "Position your viewpoint with the 3D mouse."; + ot->idname = "VIEW3D_OT_ndof_pan"; + + /* api callbacks */ + ot->invoke = ndof_pan_invoke; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = 0; +} + /* ************************ viewmove ******************************** */ @@ -3195,398 +3433,6 @@ int ED_view3d_autodist_depth_seg(struct ARegion *ar, const int mval_sta[2], cons return (*depth==FLT_MAX) ? 0: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. - -// Note: scaling in the plugin and ghostwinlay.c -// should be removed. With driver default setting, -// each axis returns approx. +-200 max deflection. - -// The values I selected are based on the older -// polling i/f. With event i/f, the sensistivity -// can be increased for improved response from -// small deflections of the device input. - - -// lukep notes : i disagree on the range. -// the normal 3Dconnection driver give +/-400 -// on defaut range in other applications -// and up to +/- 1000 if set to maximum -// because i remove the scaling by delta, -// which was a bad idea as it depend of the system -// speed and os, i changed the scaling values, but -// those are still not ok - -#if 0 -static float ndof_axis_scale[6] = { - +0.01, // Tx - +0.01, // Tz - +0.01, // Ty - +0.0015, // Rx - +0.0015, // Rz - +0.0015 // Ry -}; - -static void filterNDOFvalues(float *sbval) -{ - int i=0; - float max = 0.0; - - for (i =0; i<6;i++) - if (fabs(sbval[i]) > max) - max = fabs(sbval[i]); - for (i =0; i<6;i++) - if (fabs(sbval[i]) != max ) - sbval[i]=0.0; -} - -// statics for controlling rv3d->dist corrections. -// viewmoveNDOF zeros and adjusts rv3d->ofs. -// viewmove restores based on dz_flag state. - -int dz_flag = 0; -float m_dist; - -void viewmoveNDOFfly(ARegion *ar, View3D *v3d, int UNUSED(mode)) -{ - RegionView3D *rv3d= ar->regiondata; - int i; - float phi; - float dval[7]; - // static fval[6] for low pass filter; device input vector is dval[6] - static float fval[6]; - float tvec[3],rvec[3]; - float q1[4]; - float mat[3][3]; - float upvec[3]; - - - /*---------------------------------------------------- - * sometimes this routine is called from headerbuttons - * viewmove needs to refresh the screen - */ -// XXX areawinset(ar->win); - - - // fetch the current state of the ndof device -// XXX getndof(dval); - - if (v3d->ndoffilter) - filterNDOFvalues(fval); - - // Scale input values - -// if(dval[6] == 0) return; // guard against divide by zero - - for(i=0;i<6;i++) { - - // user scaling - dval[i] = dval[i] * ndof_axis_scale[i]; - } - - - // low pass filter with zero crossing reset - - for(i=0;i<6;i++) { - if((dval[i] * fval[i]) >= 0) - dval[i] = (fval[i] * 15 + dval[i]) / 16; - else - fval[i] = 0; - } - - - // force perspective mode. This is a hack and is - // incomplete. It doesn't actually effect the view - // until the first draw and doesn't update the menu - // to reflect persp mode. - - rv3d->persp = RV3D_PERSP; - - - // Correct the distance jump if rv3d->dist != 0 - - // This is due to a side effect of the original - // mouse view rotation code. The rotation point is - // set a distance in front of the viewport to - // make rotating with the mouse look better. - // The distance effect is written at a low level - // in the view management instead of the mouse - // view function. This means that all other view - // movement devices must subtract this from their - // view transformations. - - if(rv3d->dist != 0.0) { - dz_flag = 1; - m_dist = rv3d->dist; - upvec[0] = upvec[1] = 0; - upvec[2] = rv3d->dist; - copy_m3_m4(mat, rv3d->viewinv); - mul_m3_v3(mat, upvec); - sub_v3_v3(rv3d->ofs, upvec); - rv3d->dist = 0.0; - } - - - // Apply rotation - // Rotations feel relatively faster than translations only in fly mode, so - // we have no choice but to fix that here (not in the plugins) - rvec[0] = -0.5 * dval[3]; - rvec[1] = -0.5 * dval[4]; - rvec[2] = -0.5 * dval[5]; - - // rotate device x and y by view z - - copy_m3_m4(mat, rv3d->viewinv); - mat[2][2] = 0.0f; - mul_m3_v3(mat, rvec); - - // rotate the view - - phi = normalize_v3(rvec); - if(phi != 0) { - axis_angle_to_quat(q1,rvec,phi); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - } - - - // Apply translation - - tvec[0] = dval[0]; - tvec[1] = dval[1]; - tvec[2] = -dval[2]; - - // the next three lines rotate the x and y translation coordinates - // by the current z axis angle - - copy_m3_m4(mat, rv3d->viewinv); - mat[2][2] = 0.0f; - mul_m3_v3(mat, tvec); - - // translate the view - - sub_v3_v3(rv3d->ofs, tvec); - - - /*---------------------------------------------------- - * refresh the screen XXX - */ - - // update render preview window - -// XXX BIF_view3d_previewrender_signal(ar, PR_DBASE|PR_DISPRECT); -} - -void viewmoveNDOF(Scene *scene, ARegion *ar, View3D *v3d, int UNUSED(mode)) -{ - RegionView3D *rv3d= ar->regiondata; - float fval[7]; - float dvec[3]; - float sbadjust = 1.0f; - float len; - short use_sel = 0; - Object *ob = OBACT; - float m[3][3]; - float m_inv[3][3]; - float xvec[3] = {1,0,0}; - float yvec[3] = {0,-1,0}; - float zvec[3] = {0,0,1}; - float phi; - float q1[4]; - float obofs[3]; - float reverse; - //float diff[4]; - float d, curareaX, curareaY; - float mat[3][3]; - float upvec[3]; - - /* Sensitivity will control how fast the view rotates. The value was - * obtained experimentally by tweaking until the author didn't get dizzy watching. - * Perhaps this should be a configurable user parameter. - */ - float psens = 0.005f * (float) U.ndof_pan; /* pan sensitivity */ - float rsens = 0.005f * (float) U.ndof_rotate; /* rotate sensitivity */ - float zsens = 0.3f; /* zoom sensitivity */ - - const float minZoom = -30.0f; - const float maxZoom = 300.0f; - - //reset view type - rv3d->view = 0; -//printf("passing here \n"); -// - if (scene->obedit==NULL && ob && !(ob->mode & OB_MODE_POSE)) { - use_sel = 1; - } - - if((dz_flag)||rv3d->dist==0) { - dz_flag = 0; - rv3d->dist = m_dist; - upvec[0] = upvec[1] = 0; - upvec[2] = rv3d->dist; - copy_m3_m4(mat, rv3d->viewinv); - mul_m3_v3(mat, upvec); - add_v3_v3(rv3d->ofs, upvec); - } - - /*---------------------------------------------------- - * sometimes this routine is called from headerbuttons - * viewmove needs to refresh the screen - */ -// XXX areawinset(curarea->win); - - /*---------------------------------------------------- - * record how much time has passed. clamp at 10 Hz - * pretend the previous frame occurred at the clamped time - */ -// now = PIL_check_seconds_timer(); - // frametime = (now - prevTime); - // if (frametime > 0.1f){ /* if more than 1/10s */ - // frametime = 1.0f/60.0; /* clamp at 1/60s so no jumps when starting to move */ -// } -// prevTime = now; - // sbadjust *= 60 * frametime; /* normalize ndof device adjustments to 100Hz for framerate independence */ - - /* fetch the current state of the ndof device & enforce dominant mode if selected */ -// XXX getndof(fval); - if (v3d->ndoffilter) - filterNDOFvalues(fval); - - - // put scaling back here, was previously in ghostwinlay - fval[0] = fval[0] * (1.0f/600.0f); - fval[1] = fval[1] * (1.0f/600.0f); - fval[2] = fval[2] * (1.0f/1100.0f); - fval[3] = fval[3] * 0.00005f; - fval[4] =-fval[4] * 0.00005f; - fval[5] = fval[5] * 0.00005f; - fval[6] = fval[6] / 1000000.0f; - - // scale more if not in perspective mode - if (rv3d->persp == RV3D_ORTHO) { - fval[0] = fval[0] * 0.05f; - fval[1] = fval[1] * 0.05f; - fval[2] = fval[2] * 0.05f; - fval[3] = fval[3] * 0.9f; - fval[4] = fval[4] * 0.9f; - fval[5] = fval[5] * 0.9f; - zsens *= 8; - } - - /* set object offset */ - if (ob) { - obofs[0] = -ob->obmat[3][0]; - obofs[1] = -ob->obmat[3][1]; - obofs[2] = -ob->obmat[3][2]; - } - else { - copy_v3_v3(obofs, rv3d->ofs); - } - - /* calc an adjustment based on distance from camera - disabled per patch 14402 */ - d = 1.0f; - -/* if (ob) { - sub_v3_v3v3(diff, obofs, rv3d->ofs); - d = len_v3(diff); - } -*/ - - reverse = (rv3d->persmat[2][1] < 0.0f) ? -1.0f : 1.0f; - - /*---------------------------------------------------- - * ndof device pan - */ - psens *= 1.0f + d; - curareaX = sbadjust * psens * fval[0]; - curareaY = sbadjust * psens * fval[1]; - dvec[0] = curareaX * rv3d->persinv[0][0] + curareaY * rv3d->persinv[1][0]; - dvec[1] = curareaX * rv3d->persinv[0][1] + curareaY * rv3d->persinv[1][1]; - dvec[2] = curareaX * rv3d->persinv[0][2] + curareaY * rv3d->persinv[1][2]; - add_v3_v3(rv3d->ofs, dvec); - - /*---------------------------------------------------- - * ndof device dolly - */ - len = zsens * sbadjust * fval[2]; - - if (rv3d->persp==RV3D_CAMOB) { - if(rv3d->persp==RV3D_CAMOB) { /* This is stupid, please fix - TODO */ - rv3d->camzoom+= 10.0f * -len; - } - if (rv3d->camzoom < minZoom) rv3d->camzoom = minZoom; - else if (rv3d->camzoom > maxZoom) rv3d->camzoom = maxZoom; - } - else if ((rv3d->dist> 0.001*v3d->grid) && (rv3d->dist<10.0*v3d->far)) { - rv3d->dist*=(1.0 + len); - } - - - /*---------------------------------------------------- - * ndof device turntable - * derived from the turntable code in viewmove - */ - - /* Get the 3x3 matrix and its inverse from the quaternion */ - quat_to_mat3( m,rv3d->viewquat); - invert_m3_m3(m_inv,m); - - /* Determine the direction of the x vector (for rotating up and down) */ - /* This can likely be compuated directly from the quaternion. */ - mul_m3_v3(m_inv,xvec); - mul_m3_v3(m_inv,yvec); - mul_m3_v3(m_inv,zvec); - - /* Perform the up/down rotation */ - phi = sbadjust * rsens * /*0.5f * */ fval[3]; /* spin vertically half as fast as horizontally */ - q1[0] = cos(phi); - mul_v3_v3fl(q1+1, xvec, sin(phi)); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - - if (use_sel) { - conjugate_qt(q1); /* conj == inv for unit quat */ - sub_v3_v3(rv3d->ofs, obofs); - mul_qt_v3(q1, rv3d->ofs); - add_v3_v3(rv3d->ofs, obofs); - } - - /* Perform the orbital rotation */ - /* Perform the orbital rotation - If the seen Up axis is parallel to the zoom axis, rotation should be - achieved with a pure Roll motion (no Spin) on the device. When you start - to tilt, moving from Top to Side view, Spinning will increasingly become - more relevant while the Roll component will decrease. When a full - Side view is reached, rotations around the world's Up axis are achieved - with a pure Spin-only motion. In other words the control of the spinning - around the world's Up axis should move from the device's Spin axis to the - device's Roll axis depending on the orientation of the world's Up axis - relative to the screen. */ - //phi = sbadjust * rsens * reverse * fval[4]; /* spin the knob, y axis */ - phi = sbadjust * rsens * (yvec[2] * fval[4] + zvec[2] * fval[5]); - q1[0] = cos(phi); - q1[1] = q1[2] = 0.0; - q1[3] = sin(phi); - mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, q1); - - if (use_sel) { - conjugate_qt(q1); - sub_v3_v3(rv3d->ofs, obofs); - mul_qt_v3(q1, rv3d->ofs); - add_v3_v3(rv3d->ofs, obofs); - } - - /*---------------------------------------------------- - * refresh the screen - */ -// XXX scrarea_do_windraw(curarea); -} -#endif // if 0, unused NDof code - - /* Gets the view trasnformation from a camera * currently dosnt take camzoom into account * diff --git a/source/blender/editors/space_view3d/view3d_fly.c b/source/blender/editors/space_view3d/view3d_fly.c index ed1ed5b3881..046037a092f 100644 --- a/source/blender/editors/space_view3d/view3d_fly.c +++ b/source/blender/editors/space_view3d/view3d_fly.c @@ -29,6 +29,9 @@ /* defines VIEW3D_OT_fly modal operator */ +//#define NDOF_FLY_DEBUG +//#define NDOF_FLY_DRAW_TOOMUCH // is this needed for ndof? - commented so redraw doesnt thrash - campbell + #include "DNA_anim_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -106,7 +109,7 @@ void fly_modal_keymap(wmKeyConfig *keyconf) wmKeyMap *keymap= WM_modalkeymap_get(keyconf, "View3D Fly Modal"); /* this function is called for each spacetype, only needs to add map once */ - if(keymap) return; + if (keymap) return; keymap= WM_modalkeymap_add(keyconf, "View3D Fly Modal", modal_items); @@ -143,7 +146,6 @@ void fly_modal_keymap(wmKeyConfig *keyconf) /* assign map to operators */ WM_modalkeymap_assign(keymap, "VIEW3D_OT_fly"); - } typedef struct FlyInfo { @@ -158,7 +160,9 @@ typedef struct FlyInfo { short state; short use_precision; short redraw; - int mval[2]; + + int mval[2]; /* latest 2D mouse values */ + wmNDOFMotionData* ndof; /* latest 3D mouse values */ /* fly state state */ float speed; /* the speed the view is moving per redraw */ @@ -257,17 +261,21 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->ar = CTX_wm_region(C); fly->scene= CTX_data_scene(C); - if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) { +#ifdef NDOF_FLY_DEBUG + puts("\n-- fly begin --"); +#endif + + if (fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->id.lib) { BKE_report(op->reports, RPT_ERROR, "Cannot fly a camera from an external library"); return FALSE; } - if(fly->v3d->ob_centre) { + if (fly->v3d->ob_centre) { BKE_report(op->reports, RPT_ERROR, "Cannot fly when the view is locked to an object"); return FALSE; } - if(fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->constraints.first) { + if (fly->rv3d->persp==RV3D_CAMOB && fly->v3d->camera->constraints.first) { BKE_report(op->reports, RPT_ERROR, "Cannot fly an object with constraints"); return FALSE; } @@ -283,11 +291,15 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->grid= 1.0f; fly->use_precision= 0; +#ifdef NDOF_FLY_DRAW_TOOMUCH + fly->redraw= 1; +#endif fly->dvec_prev[0]= fly->dvec_prev[1]= fly->dvec_prev[2]= 0.0f; fly->timer= WM_event_add_timer(CTX_wm_manager(C), CTX_wm_window(C), TIMER, 0.01f); VECCOPY2D(fly->mval, event->mval) + fly->ndof = NULL; fly->time_lastdraw= fly->time_lastwheel= PIL_check_seconds_timer(); @@ -307,7 +319,7 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even fly->dist_backup= fly->rv3d->dist; if (fly->rv3d->persp==RV3D_CAMOB) { Object *ob_back; - if((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (fly->root_parent=fly->v3d->camera->parent)) { + if ((U.uiflag & USER_CAM_LOCK_NO_PARENT)==0 && (fly->root_parent=fly->v3d->camera->parent)) { while(fly->root_parent->parent) fly->root_parent= fly->root_parent->parent; ob_back= fly->root_parent; @@ -325,12 +337,22 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even negate_v3_v3(fly->rv3d->ofs, fly->v3d->camera->obmat[3]); fly->rv3d->dist=0.0; - } else { + } + else { /* perspective or ortho */ if (fly->rv3d->persp==RV3D_ORTHO) fly->rv3d->persp= RV3D_PERSP; /*if ortho projection, make perspective */ + copy_qt_qt(fly->rot_backup, fly->rv3d->viewquat); copy_v3_v3(fly->ofs_backup, fly->rv3d->ofs); + + /* the dist defines a vector that is infront of the offset + to rotate the view about. + this is no good for fly mode because we + want to rotate about the viewers center. + but to correct the dist removal we must + alter offset so the view doesn't jump. */ + fly->rv3d->dist= 0.0f; upvec[2]= fly->dist_backup; /*x and y are 0*/ @@ -338,7 +360,6 @@ static int initFlyInfo (bContext *C, FlyInfo *fly, wmOperator *op, wmEvent *even sub_v3_v3(fly->rv3d->ofs, upvec); /*Done with correcting for the dist*/ } - /* center the mouse, probably the UI mafia are against this but without its quite annoying */ WM_cursor_warp(CTX_wm_window(C), fly->ar->winrct.xmin + fly->ar->winx/2, fly->ar->winrct.ymin + fly->ar->winy/2); @@ -353,9 +374,13 @@ static int flyEnd(bContext *C, FlyInfo *fly) float upvec[3]; - if(fly->state == FLY_RUNNING) + if (fly->state == FLY_RUNNING) return OPERATOR_RUNNING_MODAL; +#ifdef NDOF_FLY_DEBUG + puts("\n-- fly end --"); +#endif + WM_event_remove_timer(CTX_wm_manager(C), CTX_wm_window(C), fly->timer); ED_region_draw_cb_exit(fly->ar->type, fly->draw_handle_pixel); @@ -366,14 +391,14 @@ static int flyEnd(bContext *C, FlyInfo *fly) /* Revert to original view? */ if (fly->persp_backup==RV3D_CAMOB) { /* a camera view */ Object *ob_back; - if(fly->root_parent)ob_back= fly->root_parent; - else ob_back= fly->v3d->camera; + ob_back= (fly->root_parent) ? fly->root_parent : fly->v3d->camera; /* store the original camera loc and rot */ object_tfm_restore(ob_back, fly->obtfm); DAG_id_tag_update(&ob_back->id, OB_RECALC_OB); - } else { + } + else { /* Non Camera we need to reset the view back to the original location bacause the user canceled*/ copy_qt_qt(rv3d->viewquat, fly->rot_backup); copy_v3_v3(rv3d->ofs, fly->ofs_backup); @@ -398,10 +423,13 @@ static int flyEnd(bContext *C, FlyInfo *fly) rv3d->rflag &= ~RV3D_NAVIGATING; //XXX2.5 BIF_view3d_previewrender_signal(fly->sa, PR_DBASE|PR_DISPRECT); /* not working at the moment not sure why */ - if(fly->obtfm) + if (fly->obtfm) MEM_freeN(fly->obtfm); - if(fly->state == FLY_CONFIRM) { + if (fly->ndof) + MEM_freeN(fly->ndof); + + if (fly->state == FLY_CONFIRM) { MEM_freeN(fly); return OPERATOR_FINISHED; } @@ -417,7 +445,52 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) } else if (event->type == MOUSEMOVE) { VECCOPY2D(fly->mval, event->mval); - } /* handle modal keymap first */ + } + else if (event->type == NDOF_MOTION) { + // do these automagically get delivered? yes. + // puts("ndof motion detected in fly mode!"); + // static const char* tag_name = "3D mouse position"; + + wmNDOFMotionData* incoming_ndof = (wmNDOFMotionData*) event->customdata; + switch (incoming_ndof->progress) { + case P_STARTING: + // start keeping track of 3D mouse position +#ifdef NDOF_FLY_DEBUG + puts("start keeping track of 3D mouse position"); +#endif + // fall through... + case P_IN_PROGRESS: + // update 3D mouse position +#ifdef NDOF_FLY_DEBUG + putchar('.'); fflush(stdout); +#endif + if (fly->ndof == NULL) { + // fly->ndof = MEM_mallocN(sizeof(wmNDOFMotionData), tag_name); + fly->ndof = MEM_dupallocN(incoming_ndof); + // fly->ndof = malloc(sizeof(wmNDOFMotionData)); + } + else { + memcpy(fly->ndof, incoming_ndof, sizeof(wmNDOFMotionData)); + } + break; + case P_FINISHING: + // stop keeping track of 3D mouse position +#ifdef NDOF_FLY_DEBUG + puts("stop keeping track of 3D mouse position"); +#endif + if (fly->ndof) { + MEM_freeN(fly->ndof); + // free(fly->ndof); + fly->ndof = NULL; + } + /* update the time else the view will jump when 2D mouse/timer resume */ + fly->time_lastdraw= PIL_check_seconds_timer(); + break; + default: + ; // should always be one of the above 3 + } + } + /* handle modal keymap first */ else if (event->type == EVT_MODAL_MAP) { switch (event->val) { case FLY_MODAL_CANCEL: @@ -439,7 +512,9 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) /*Mouse wheel delays range from 0.5==slow to 0.01==fast*/ time_wheel = 1.0f + (10.0f - (20.0f * MIN2(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ - if (fly->speed<0.0f) fly->speed= 0.0f; + if (fly->speed < 0.0f) { + fly->speed= 0.0f; + } else { if (event->shift) fly->speed += fly->grid*time_wheel * 0.1f; @@ -458,7 +533,9 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) fly->time_lastwheel = time_currwheel; time_wheel = 1.0f + (10.0f - (20.0f * MIN2(time_wheel, 0.5f))); /* 0-0.5 -> 0-5.0 */ - if (fly->speed>0) fly->speed=0; + if (fly->speed > 0.0f) { + fly->speed=0; + } else { if (event->shift) fly->speed-= fly->grid*time_wheel * 0.1f; @@ -528,14 +605,81 @@ static void flyEvent(FlyInfo *fly, wmEvent *event) case FLY_MODAL_PRECISION_DISABLE: fly->use_precision= FALSE; break; + } + } +} + +static void move_camera(bContext* C, RegionView3D* rv3d, FlyInfo* fly, int orientationChanged, int positionChanged) +{ + /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */ + + View3D* v3d = fly->v3d; + Scene *scene= fly->scene; + ID *id_key; + + /* transform the parent or the camera? */ + if (fly->root_parent) { + Object *ob_update; + + float view_mat[4][4]; + float prev_view_mat[4][4]; + float prev_view_imat[4][4]; + float diff_mat[4][4]; + float parent_mat[4][4]; + + ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist); + invert_m4_m4(prev_view_imat, prev_view_mat); + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + mul_m4_m4m4(diff_mat, prev_view_imat, view_mat); + mul_m4_m4m4(parent_mat, fly->root_parent->obmat, diff_mat); + object_apply_mat4(fly->root_parent, parent_mat, TRUE, FALSE); + + // where_is_object(scene, fly->root_parent); + + ob_update= v3d->camera->parent; + while(ob_update) { + DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); + ob_update= ob_update->parent; } + + id_key= &fly->root_parent->id; + } + else { + float view_mat[4][4]; + ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); + object_apply_mat4(v3d->camera, view_mat, TRUE, FALSE); + id_key= &v3d->camera->id; + } + + /* record the motion */ + if (autokeyframe_cfra_can_key(scene, id_key)) { + ListBase dsources = {NULL, NULL}; + + /* add datasource override for the camera object */ + ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL); + + /* insert keyframes + * 1) on the first frame + * 2) on each subsequent frame + * TODO: need to check in future that frame changed before doing this + */ + if (orientationChanged) { + KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation"); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); + } + if (positionChanged) { + KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location"); + ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); + } + + /* free temp data */ + BLI_freelistN(&dsources); } } static int flyApply(bContext *C, FlyInfo *fly) { - #define FLY_ROTATE_FAC 2.5f /* more is faster */ #define FLY_ZUP_CORRECT_FAC 0.1f /* amount to correct per step */ #define FLY_ZUP_CORRECT_ACCEL 0.05f /* increase upright momentum each step */ @@ -545,11 +689,7 @@ static int flyApply(bContext *C, FlyInfo *fly) a fly loop where the user can move move the view as if they are flying */ RegionView3D *rv3d= fly->rv3d; - View3D *v3d = fly->v3d; ARegion *ar = fly->ar; - Scene *scene= fly->scene; - - float prev_view_mat[4][4]; float mat[3][3], /* 3x3 copy of the view matrix so we can move allong the view axis */ dvec[3]={0,0,0}, /* this is the direction thast added to the view offset per redraw */ @@ -567,15 +707,11 @@ static int flyApply(bContext *C, FlyInfo *fly) unsigned char apply_rotation= 1; /* if the user presses shift they can look about without movinf the direction there looking*/ - if(fly->root_parent) - ED_view3d_to_m4(prev_view_mat, fly->rv3d->ofs, fly->rv3d->viewquat, fly->rv3d->dist); +#ifdef NDOF_FLY_DEBUG + static unsigned int iteration = 1; + printf("fly timer %d\n", iteration++); +#endif - /* the dist defines a vector that is infront of the offset - to rotate the view about. - this is no good for fly mode because we - want to rotate about the viewers center. - but to correct the dist removal we must - alter offset so the view doesn't jump. */ xmargin= ar->winx/20.0f; ymargin= ar->winy/20.0f; @@ -605,23 +741,25 @@ static int flyApply(bContext *C, FlyInfo *fly) * * the mouse moves isnt linear */ - if(moffset[0]) { + if (moffset[0]) { moffset[0] /= ar->winx - (xmargin*2); moffset[0] *= fabsf(moffset[0]); } - if(moffset[1]) { + if (moffset[1]) { moffset[1] /= ar->winy - (ymargin*2); moffset[1] *= fabsf(moffset[1]); } /* Should we redraw? */ - if(fly->speed != 0.0f || moffset[0] || moffset[1] || fly->zlock || fly->xlock || dvec[0] || dvec[1] || dvec[2] ) { + if (fly->speed != 0.0f || moffset[0] || moffset[1] || fly->zlock || fly->xlock || dvec[0] || dvec[1] || dvec[2] ) { float dvec_tmp[3]; double time_current; /*time how fast it takes for us to redraw, this is so simple scenes dont fly too fast */ float time_redraw; float time_redraw_clamped; - +#ifdef NDOF_FLY_DRAW_TOOMUCH + fly->redraw= 1; +#endif time_current= PIL_check_seconds_timer(); time_redraw= (float)(time_current - fly->time_lastdraw); time_redraw_clamped= MIN2(0.05f, time_redraw); /* clamt the redraw time to avoid jitter in roll correction */ @@ -648,8 +786,8 @@ static int flyApply(bContext *C, FlyInfo *fly) mul_m3_v3(mat, dvec_tmp); mul_v3_fl(dvec_tmp, time_redraw * 200.0f * fly->grid); - - } else { + } + else { float roll; /* similar to the angle between the camera's up and the Z-up, but its very rough so just roll*/ /* rotate about the X axis- look up/down */ @@ -670,27 +808,28 @@ static int flyApply(bContext *C, FlyInfo *fly) if (moffset[0]) { /* if we're upside down invert the moffset */ - upvec[0]=0; - upvec[1]=1; - upvec[2]=0; + upvec[0]= 0.0f; + upvec[1]= 1.0f; + upvec[2]= 0.0f; mul_m3_v3(mat, upvec); - if(upvec[2] < 0.0f) + if (upvec[2] < 0.0f) moffset[0]= -moffset[0]; /* make the lock vectors */ if (fly->zlock) { - upvec[0]=0; - upvec[1]=0; - upvec[2]=1; - } else { - upvec[0]=0; - upvec[1]=1; - upvec[2]=0; + upvec[0]= 0.0f; + upvec[1]= 0.0f; + upvec[2]= 1.0f; + } + else { + upvec[0]= 0.0f; + upvec[1]= 1.0f; + upvec[2]= 0.0f; mul_m3_v3(mat, upvec); } - axis_angle_to_quat( tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC); /* Rotate about the relative up vec */ + axis_angle_to_quat(tmp_quat, upvec, (float)moffset[0] * time_redraw * FLY_ROTATE_FAC); /* Rotate about the relative up vec */ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); if (fly->xlock) fly->xlock = 2;/*check for rotation*/ @@ -698,25 +837,26 @@ static int flyApply(bContext *C, FlyInfo *fly) } if (fly->zlock==2) { - upvec[0]=1; - upvec[1]=0; - upvec[2]=0; + upvec[0]= 1.0f; + upvec[1]= 0.0f; + upvec[2]= 0.0f; mul_m3_v3(mat, upvec); /*make sure we have some z rolling*/ if (fabsf(upvec[2]) > 0.00001f) { - roll= upvec[2]*5; - upvec[0]=0; /*rotate the view about this axis*/ - upvec[1]=0; - upvec[2]=1; + roll= upvec[2] * 5.0f; + upvec[0]= 0.0f; /*rotate the view about this axis*/ + upvec[1]= 0.0f; + upvec[2]= 1.0f; mul_m3_v3(mat, upvec); axis_angle_to_quat( tmp_quat, upvec, roll*time_redraw_clamped*fly->zlock_momentum * FLY_ZUP_CORRECT_FAC); /* Rotate about the relative up vec */ mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); fly->zlock_momentum += FLY_ZUP_CORRECT_ACCEL; - } else { - fly->zlock=1; /* dont check until the view rotates again */ + } + else { + fly->zlock= 1; /* dont check until the view rotates again */ fly->zlock_momentum= 0.0f; } } @@ -727,8 +867,8 @@ static int flyApply(bContext *C, FlyInfo *fly) upvec[2]=1; mul_m3_v3(mat, upvec); /*make sure we have some z rolling*/ - if (fabs(upvec[2]) > 0.00001) { - roll= upvec[2] * -5; + if (fabs(upvec[2]) > 0.00001f) { + roll= upvec[2] * -5.0f; upvec[0]= 1.0f; /*rotate the view about this axis*/ upvec[1]= 0.0f; @@ -740,7 +880,8 @@ static int flyApply(bContext *C, FlyInfo *fly) mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, tmp_quat); fly->xlock_momentum += 0.05f; - } else { + } + else { fly->xlock=1; /* see above */ fly->xlock_momentum= 0.0f; } @@ -784,96 +925,164 @@ static int flyApply(bContext *C, FlyInfo *fly) ED_area_headerprint(fly->ar, "FlyKeys Speed:(+/- | Wheel), Upright Axis:X off/Z off, Slow:Shift, Direction:WASDRF, Ok:LMB, Pan:MMB, Cancel:RMB"); #endif - /* we are in camera view so apply the view ofs and quat to the view matrix and set the camera to the view */ - if (rv3d->persp==RV3D_CAMOB) { - ID *id_key; - /* transform the parent or the camera? */ - if(fly->root_parent) { - Object *ob_update; - - float view_mat[4][4]; - float prev_view_imat[4][4]; - float diff_mat[4][4]; - float parent_mat[4][4]; - - invert_m4_m4(prev_view_imat, prev_view_mat); - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - mul_m4_m4m4(diff_mat, prev_view_imat, view_mat); - mul_m4_m4m4(parent_mat, fly->root_parent->obmat, diff_mat); - object_apply_mat4(fly->root_parent, parent_mat, TRUE, FALSE); - - // where_is_object(scene, fly->root_parent); - - ob_update= v3d->camera->parent; - while(ob_update) { - DAG_id_tag_update(&ob_update->id, OB_RECALC_OB); - ob_update= ob_update->parent; - } + if (rv3d->persp==RV3D_CAMOB) + move_camera(C, rv3d, fly, (fly->xlock || fly->zlock || moffset[0] || moffset[1]), fly->speed); - copy_m4_m4(prev_view_mat, view_mat); + } + else { + /* we're not redrawing but we need to update the time else the view will jump */ + fly->time_lastdraw= PIL_check_seconds_timer(); + } + /* end drawing */ + copy_v3_v3(fly->dvec_prev, dvec); + } - id_key= &fly->root_parent->id; + return OPERATOR_FINISHED; +} - } - else { - float view_mat[4][4]; - ED_view3d_to_m4(view_mat, rv3d->ofs, rv3d->viewquat, rv3d->dist); - object_apply_mat4(v3d->camera, view_mat, TRUE, FALSE); - id_key= &v3d->camera->id; - } +static int flyApply_ndof(bContext *C, FlyInfo *fly) +{ + /* shorthand for oft-used variables */ + wmNDOFMotionData* ndof = fly->ndof; + const float dt = ndof->dt; + RegionView3D* rv3d = fly->rv3d; + const int flag = U.ndof_flag; - /* record the motion */ - if (autokeyframe_cfra_can_key(scene, id_key)) { - ListBase dsources = {NULL, NULL}; - - /* add datasource override for the camera object */ - ANIM_relative_keyingset_add_source(&dsources, id_key, NULL, NULL); - - /* insert keyframes - * 1) on the first frame - * 2) on each subsequent frame - * TODO: need to check in future that frame changed before doing this - */ - if (fly->xlock || fly->zlock || moffset[0] || moffset[1]) { - KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation"); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); - } - if (fly->speed) { - KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Location"); - ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA); - } - - /* free temp data */ - BLI_freelistN(&dsources); - } +/* int shouldRotate = (flag & NDOF_SHOULD_ROTATE) && (fly->pan_view == FALSE), + shouldTranslate = (flag & (NDOF_SHOULD_PAN | NDOF_SHOULD_ZOOM)); */ + + int shouldRotate = (fly->pan_view == FALSE), + shouldTranslate = TRUE; + + float view_inv[4]; + invert_qt_qt(view_inv, rv3d->viewquat); + + rv3d->rot_angle = 0.f; // disable onscreen rotation doo-dad + + if (shouldTranslate) { + const float forward_sensitivity = 1.f; + const float vertical_sensitivity = 0.4f; + const float lateral_sensitivity = 0.6f; + + float speed = 10.f; /* blender units per second */ + /* ^^ this is ok for default cube scene, but should scale with.. something */ + + float trans[3] = { + lateral_sensitivity * ndof->tvec[0], + vertical_sensitivity * ndof->tvec[1], + forward_sensitivity * ndof->tvec[2] + }; + + if (fly->use_precision) + speed *= 0.2f; + + mul_v3_fl(trans, speed * dt); + + // transform motion from view to world coordinates + mul_qt_v3(view_inv, trans); + + if (flag & NDOF_FLY_HELICOPTER) { + /* replace world z component with device y (yes it makes sense) */ + trans[2] = speed * dt * vertical_sensitivity * ndof->tvec[1]; + } + + if (rv3d->persp==RV3D_CAMOB) { + // respect camera position locks + Object *lock_ob= fly->root_parent ? fly->root_parent : fly->v3d->camera; + if (lock_ob->protectflag & OB_LOCK_LOCX) trans[0] = 0.f; + if (lock_ob->protectflag & OB_LOCK_LOCY) trans[1] = 0.f; + if (lock_ob->protectflag & OB_LOCK_LOCZ) trans[2] = 0.f; + } + + if (!is_zero_v3(trans)) { + // move center of view opposite of hand motion (this is camera mode, not object mode) + sub_v3_v3(rv3d->ofs, trans); + shouldTranslate = TRUE; + } + else { + shouldTranslate = FALSE; + } + } + + if (shouldRotate) { + const float turn_sensitivity = 1.f; + + float rotation[4]; + float axis[3]; + float angle = turn_sensitivity * ndof_to_axis_angle(ndof, axis); + + if (fabsf(angle) > 0.0001f) { + shouldRotate = TRUE; + + if (fly->use_precision) + angle *= 0.2f; + + /* transform rotation axis from view to world coordinates */ + mul_qt_v3(view_inv, axis); + + // apply rotation to view + axis_angle_to_quat(rotation, axis, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); + + if (flag & NDOF_LOCK_HORIZON) { + /* force an upright viewpoint + * TODO: make this less... sudden */ + float view_horizon[3] = {1.f, 0.f, 0.f}; /* view +x */ + float view_direction[3] = {0.f, 0.f, -1.f}; /* view -z (into screen) */ + + /* find new inverse since viewquat has changed */ + invert_qt_qt(view_inv, rv3d->viewquat); + /* could apply reverse rotation to existing view_inv to save a few cycles */ + + /* transform view vectors to world coordinates */ + mul_qt_v3(view_inv, view_horizon); + mul_qt_v3(view_inv, view_direction); + + /* find difference between view & world horizons + * true horizon lives in world xy plane, so look only at difference in z */ + angle = -asinf(view_horizon[2]); + +#ifdef NDOF_FLY_DEBUG + printf("lock horizon: adjusting %.1f degrees\n\n", RAD2DEG(angle)); +#endif + + /* rotate view so view horizon = world horizon */ + axis_angle_to_quat(rotation, view_direction, angle); + mul_qt_qtqt(rv3d->viewquat, rv3d->viewquat, rotation); } - } else - /*were not redrawing but we need to update the time else the view will jump */ - fly->time_lastdraw= PIL_check_seconds_timer(); - /* end drawing */ - copy_v3_v3(fly->dvec_prev, dvec); + + rv3d->view = RV3D_VIEW_USER; + } + else { + shouldRotate = FALSE; + } } -/* moved to flyEnd() */ + if (shouldTranslate || shouldRotate) { + fly->redraw = TRUE; + + if (rv3d->persp==RV3D_CAMOB) { + move_camera(C, rv3d, fly, shouldRotate, shouldTranslate); + } + } return OPERATOR_FINISHED; } - static int fly_invoke(bContext *C, wmOperator *op, wmEvent *event) { RegionView3D *rv3d= CTX_wm_region_view3d(C); FlyInfo *fly; - if(rv3d->viewlock) + if (rv3d->viewlock) return OPERATOR_CANCELLED; fly= MEM_callocN(sizeof(FlyInfo), "FlyOperation"); op->customdata= fly; - if(initFlyInfo(C, fly, op, event)==FALSE) { + if (initFlyInfo(C, fly, op, event)==FALSE) { MEM_freeN(op->customdata); return OPERATOR_CANCELLED; } @@ -908,21 +1117,28 @@ static int fly_modal(bContext *C, wmOperator *op, wmEvent *event) flyEvent(fly, event); - if(event->type==TIMER && event->customdata == fly->timer) + if (fly->ndof) { /* 3D mouse overrules [2D mouse + timer] */ + if (event->type==NDOF_MOTION) { + flyApply_ndof(C, fly); + } + } + else if (event->type==TIMER && event->customdata == fly->timer) { flyApply(C, fly); + } do_draw |= fly->redraw; exit_code = flyEnd(C, fly); - if(exit_code!=OPERATOR_RUNNING_MODAL) + if (exit_code!=OPERATOR_RUNNING_MODAL) do_draw= TRUE; - if(do_draw) { - if(rv3d->persp==RV3D_CAMOB) { + if (do_draw) { + if (rv3d->persp==RV3D_CAMOB) { WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, fly_object); } + // puts("redraw!"); // too frequent, commented with NDOF_FLY_DRAW_TOOMUCH for now ED_region_tag_redraw(CTX_wm_region(C)); } diff --git a/source/blender/editors/space_view3d/view3d_header.c b/source/blender/editors/space_view3d/view3d_header.c index ae80a554e08..5b95ae63e56 100644 --- a/source/blender/editors/space_view3d/view3d_header.c +++ b/source/blender/editors/space_view3d/view3d_header.c @@ -280,7 +280,8 @@ static char *view3d_modeselect_pup(Scene *scene) str += sprintf(str, formatstr, "Object Mode", OB_MODE_OBJECT, ICON_OBJECT_DATA); - if(ob==NULL) return string; + if(ob==NULL || ob->data==NULL) return string; + if(ob->id.lib || ((ID *)ob->data)->lib) return string; /* if active object is editable */ if ( ((ob->type == OB_MESH) diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index d3886d48873..ab3ce37ff15 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -51,6 +51,7 @@ struct ARegionType; struct bPoseChannel; struct bAnimVizSettings; struct bMotionPath; +struct wmNDOFMotionData; #define BL_NEAR_CLIP 0.001 @@ -72,6 +73,8 @@ void VIEW3D_OT_dolly(struct wmOperatorType *ot); void VIEW3D_OT_zoom_camera_1_to_1(struct wmOperatorType *ot); void VIEW3D_OT_move(struct wmOperatorType *ot); void VIEW3D_OT_rotate(struct wmOperatorType *ot); +void VIEW3D_OT_ndof_orbit(struct wmOperatorType *ot); +void VIEW3D_OT_ndof_pan(struct wmOperatorType *ot); void VIEW3D_OT_view_all(struct wmOperatorType *ot); void VIEW3D_OT_viewnumpad(struct wmOperatorType *ot); void VIEW3D_OT_view_selected(struct wmOperatorType *ot); @@ -91,6 +94,8 @@ void VIEW3D_OT_zoom_border(struct wmOperatorType *ot); void VIEW3D_OT_drawtype(struct wmOperatorType *ot); void view3d_boxview_copy(ScrArea *sa, ARegion *ar); +void ndof_to_quat(struct wmNDOFMotionData* ndof, float q[4]); +float ndof_to_axis_angle(struct wmNDOFMotionData* ndof, float axis[3]); /* view3d_fly.c */ void view3d_keymap(struct wmKeyConfig *keyconf); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 05ef79a9f29..e47cb1db753 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -64,6 +64,8 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_zoom); WM_operatortype_append(VIEW3D_OT_zoom_camera_1_to_1); WM_operatortype_append(VIEW3D_OT_dolly); + WM_operatortype_append(VIEW3D_OT_ndof_orbit); + WM_operatortype_append(VIEW3D_OT_ndof_pan); WM_operatortype_append(VIEW3D_OT_view_all); WM_operatortype_append(VIEW3D_OT_viewnumpad); WM_operatortype_append(VIEW3D_OT_view_orbit); @@ -161,6 +163,17 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", HOMEKEY, KM_PRESS, 0, 0)->ptr, "center", 0); /* only without camera view */ RNA_boolean_set(WM_keymap_add_item(keymap, "VIEW3D_OT_view_all", CKEY, KM_PRESS, KM_SHIFT, 0)->ptr, "center", 1); + /* 3D mouse */ + WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_orbit", NDOF_MOTION, 0, 0, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_ndof_pan", NDOF_MOTION, 0, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "VIEW3D_OT_view_selected", NDOF_BUTTON_FIT, KM_PRESS, 0, 0); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BACK, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BACK); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_LEFT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_LEFT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_RIGHT); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_TOP); + RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_BOTTOM, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_BOTTOM); + /* numpad view hotkeys*/ RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD0, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_CAMERA); RNA_enum_set(WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", PAD1, KM_PRESS, 0, 0)->ptr, "type", RV3D_VIEW_FRONT); @@ -210,6 +223,17 @@ void view3d_keymap(wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_BOTTOM); RNA_boolean_set(kmi->ptr, "align_active", TRUE); + /* 3D mouse align */ + kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_FRONT, KM_PRESS, KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_FRONT); + RNA_boolean_set(kmi->ptr, "align_active", TRUE); + kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_RIGHT, KM_PRESS, KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_RIGHT); + RNA_boolean_set(kmi->ptr, "align_active", TRUE); + kmi= WM_keymap_add_item(keymap, "VIEW3D_OT_viewnumpad", NDOF_BUTTON_TOP, KM_PRESS, KM_SHIFT, 0); + RNA_enum_set(kmi->ptr, "type", RV3D_VIEW_TOP); + RNA_boolean_set(kmi->ptr, "align_active", TRUE); + WM_keymap_add_item(keymap, "VIEW3D_OT_localview", PADSLASHKEY, KM_PRESS, 0, 0); /* layers, shift + alt are properties set in invoke() */ diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 9290e1fc631..c6835b0cad3 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -889,14 +889,14 @@ static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo) { Base *base; unsigned int *bufmin,*bufmax; - int a,b,rc,tel,aantal,dirvec[4][2],maxob; + int a,b,rc,tel,len,dirvec[4][2],maxob; unsigned int retval=0; base= LASTBASE; if(base==0) return 0; maxob= base->selcol; - aantal= (size-1)/2; + len= (size-1)/2; rc= 0; dirvec[0][0]= 1; @@ -910,7 +910,7 @@ static unsigned int samplerect(unsigned int *buf, int size, unsigned int dontdo) bufmin= buf; bufmax= buf+ size*size; - buf+= aantal*size+ aantal; + buf+= len*size+ len; for(tel=1;tel<=size;tel++) { diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 65a0657d2f3..cb3b72468fe 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1006,9 +1006,11 @@ int transformEvent(TransInfo *t, wmEvent *event) else view_editmove(event->type); t->redraw= 1; break; -// case NDOFMOTION: -// viewmoveNDOF(1); - // break; +#if 0 + case NDOF_MOTION: + // should have been caught by tranform_modal + return OPERATOR_PASS_THROUGH; +#endif default: handled = 0; break; @@ -1017,43 +1019,6 @@ int transformEvent(TransInfo *t, wmEvent *event) // Numerical input events t->redraw |= handleNumInput(&(t->num), event); - // NDof input events - switch(handleNDofInput(&(t->ndof), event)) - { - case NDOF_CONFIRM: - if ((t->options & CTX_NDOF) == 0) - { - /* Confirm on normal transform only */ - t->state = TRANS_CONFIRM; - } - break; - case NDOF_CANCEL: - if (t->options & CTX_NDOF) - { - /* Cancel on pure NDOF transform */ - t->state = TRANS_CANCEL; - } - else - { - /* Otherwise, just redraw, NDof input was cancelled */ - t->redraw |= TREDRAW_HARD; - } - break; - case NDOF_NOMOVE: - if (t->options & CTX_NDOF) - { - /* Confirm on pure NDOF transform */ - t->state = TRANS_CONFIRM; - } - break; - case NDOF_REFRESH: - t->redraw |= TREDRAW_HARD; - break; - default: - handled = 0; - break; - } - // Snapping events t->redraw |= handleSnapping(t, event); @@ -2907,10 +2872,6 @@ void initRotation(TransInfo *t) setInputPostFct(&t->mouse, postInputRotation); initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - t->ndof.axis = 16; - /* Scale down and flip input for rotation */ - t->ndof.factor[0] = -0.2f; - t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; @@ -3182,8 +3143,6 @@ int Rotation(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0]; - applyNDofInput(&t->ndof, &final); - snapGrid(t, &final); if ((t->con.mode & CON_APPLY) && t->con.applyRot) { @@ -3237,11 +3196,6 @@ void initTrackball(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_TRACKBALL); - t->ndof.axis = 40; - /* Scale down input for rotation */ - t->ndof.factor[0] = 0.2f; - t->ndof.factor[1] = 0.2f; - t->idx_max = 1; t->num.idx_max = 1; t->snap[0] = 0.0f; @@ -3297,8 +3251,6 @@ int Trackball(TransInfo *t, const int UNUSED(mval[2])) phi[0] = t->values[0]; phi[1] = t->values[1]; - applyNDofInput(&t->ndof, phi); - snapGrid(t, phi); if (hasNumInput(&t->num)) { @@ -3352,8 +3304,6 @@ void initTranslation(TransInfo *t) t->num.flag = 0; t->num.idx_max = t->idx_max; - t->ndof.axis = (t->flag & T_2D_EDIT)? 1|2: 1|2|4; - if(t->spacetype == SPACE_VIEW3D) { RegionView3D *rv3d = t->ar->regiondata; @@ -3528,7 +3478,6 @@ int Translation(TransInfo *t, const int UNUSED(mval[2])) headerTranslation(t, pvec, str); } else { - applyNDofInput(&t->ndof, t->values); snapGrid(t, t->values); applyNumInput(&t->num, t->values); if (hasNumInput(&t->num)) { @@ -3637,10 +3586,6 @@ void initTilt(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_ANGLE); - t->ndof.axis = 16; - /* Scale down and flip input for rotation */ - t->ndof.factor[0] = -0.2f; - t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; @@ -3664,8 +3609,6 @@ int Tilt(TransInfo *t, const int UNUSED(mval[2])) final = t->values[0]; - applyNDofInput(&t->ndof, &final); - snapGrid(t, &final); if (hasNumInput(&t->num)) { @@ -3780,10 +3723,6 @@ void initPushPull(TransInfo *t) initMouseInputMode(t, &t->mouse, INPUT_VERTICAL_ABSOLUTE); - t->ndof.axis = 4; - /* Flip direction */ - t->ndof.factor[0] = -1.0f; - t->idx_max = 0; t->num.idx_max = 0; t->snap[0] = 0.0f; @@ -3804,8 +3743,6 @@ int PushPull(TransInfo *t, const int UNUSED(mval[2])) distance = t->values[0]; - applyNDofInput(&t->ndof, &distance); - snapGrid(t, &distance); applyNumInput(&t->num, &distance); @@ -4680,7 +4617,7 @@ static int createSlideVerts(TransInfo *t) #define EDGE_SLIDE_MIN 30 if (len_squared_v2v2(start, end) < (EDGE_SLIDE_MIN * EDGE_SLIDE_MIN)) { if(ABS(start[0]-end[0]) + ABS(start[1]-end[1]) < 4.0f) { - /* even more exceptional case, points are ontop of eachother */ + /* even more exceptional case, points are ontop of each other */ end[0]= start[0]; end[1]= start[1] + EDGE_SLIDE_MIN; } @@ -5330,8 +5267,6 @@ void initSeqSlide(TransInfo *t) t->num.flag = 0; t->num.idx_max = t->idx_max; - t->ndof.axis = 1|2; - t->snap[0] = 0.0f; t->snap[1] = floor(t->scene->r.frs_sec / t->scene->r.frs_sec_base); t->snap[2] = 10.0f; @@ -5386,7 +5321,6 @@ int SeqSlide(TransInfo *t, const int UNUSED(mval[2])) VECCOPY(t->values, tvec); } else { - applyNDofInput(&t->ndof, t->values); snapGrid(t, t->values); applyNumInput(&t->num, t->values); } @@ -5946,54 +5880,3 @@ void BIF_TransformSetUndo(char *UNUSED(str)) // TRANSFORM_FIX_ME //Trans.undostr= str; } - - -#if 0 // TRANSFORM_FIX_ME -static void NDofTransform(void) -{ - float fval[7]; - float maxval = 50.0f; // also serves as threshold - int axis = -1; - int mode = 0; - int i; - - getndof(fval); - - for(i = 0; i < 6; i++) - { - float val = fabs(fval[i]); - if (val > maxval) - { - axis = i; - maxval = val; - } - } - - switch(axis) - { - case -1: - /* No proper axis found */ - break; - case 0: - case 1: - case 2: - mode = TFM_TRANSLATION; - break; - case 4: - mode = TFM_ROTATION; - break; - case 3: - case 5: - mode = TFM_TRACKBALL; - break; - default: - printf("ndof: what we are doing here ?"); - } - - if (mode != 0) - { - initTransform(mode, CTX_NDOF); - Transform(); - } -} -#endif diff --git a/source/blender/editors/transform/transform_ops.c b/source/blender/editors/transform/transform_ops.c index 62a55e2b7c9..4765bc77bf1 100644 --- a/source/blender/editors/transform/transform_ops.c +++ b/source/blender/editors/transform/transform_ops.c @@ -360,6 +360,12 @@ static int transform_modal(bContext *C, wmOperator *op, wmEvent *event) TransInfo *t = op->customdata; + if (event->type == NDOF_MOTION) + { + /* puts("transform_modal: passing through NDOF_MOTION"); */ + return OPERATOR_PASS_THROUGH; + } + /* XXX insert keys are called here, and require context */ t->context= C; exit_code = transformEvent(t, event); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 4cf744a7878..b5a1a36e126 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -365,7 +365,6 @@ typedef struct UserDef { short recent_files; /* maximum number of recently used files to remember */ short smooth_viewtx; /* miliseconds to spend spinning the view */ short glreslimit; - short ndof_pan, ndof_rotate; short curssize; short color_picker_type; short ipo_new; /* interpolation mode for newly added F-Curves */ @@ -376,6 +375,10 @@ typedef struct UserDef { short widget_unit; /* defaults to 20 for 72 DPI setting */ short anisotropic_filter; + /*short pad[3]; */ + + float ndof_sensitivity; /* overall sensitivity of 3D mouse */ + int ndof_flag; /* flags for 3D mouse */ char versemaster[160]; char verseuser[160]; @@ -384,7 +387,7 @@ typedef struct UserDef { short autokey_mode; /* autokeying mode */ short autokey_flag; /* flags for autokeying */ - short text_render, pad9; /*options for text rendering*/ + short text_render, pad9[3]; /*options for text rendering*/ struct ColorBand coba_weight; /* from texture.h */ @@ -578,6 +581,28 @@ extern UserDef U; /* from blenkernel blender.c */ #define TH_OLDSKOOL 3 #define TH_SHADED 4 +/* ndof_flag (3D mouse options) */ +#define NDOF_SHOW_GUIDE (1 << 0) +#define NDOF_FLY_HELICOPTER (1 << 1) +#define NDOF_LOCK_HORIZON (1 << 2) +/* the following might not need to be saved between sessions, + but they do need to live somewhere accessible... */ +#define NDOF_SHOULD_PAN (1 << 3) +#define NDOF_SHOULD_ZOOM (1 << 4) +#define NDOF_SHOULD_ROTATE (1 << 5) +/* orbit navigation modes + only two options, so it's sort of a hyrbrid bool/enum + if ((U.ndof_flag & NDOF_ORBIT_MODE) == NDOF_OM_OBJECT)... */ +/* +#define NDOF_ORBIT_MODE (1 << 6) +#define NDOF_OM_TARGETCAMERA 0 +#define NDOF_OM_OBJECT NDOF_ORBIT_MODE +*/ +/* actually... users probably don't care about what the mode + is called, just that it feels right */ +#define NDOF_ORBIT_INVERT_AXES (1 << 6) + + #ifdef __cplusplus } #endif diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 7379493003d..89b8bad2806 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -130,7 +130,11 @@ typedef struct RegionView3D { float twangle[3]; - float padf; + /* active rotation from NDOF or elsewhere */ + float rot_angle; + float rot_axis[3]; + + char pad2[4]; } RegionView3D; @@ -190,11 +194,10 @@ typedef struct View3D { /* drawflags, denoting state */ short zbuf, transp, xray; - char ndofmode; /* mode of transform for 6DOF devices -1 not found, 0 normal, 1 fly, 2 ob transform */ - char ndoffilter; /* filter for 6DOF devices 0 normal, 1 dominant */ - + char pad3[2]; + void *properties_storage; /* Nkey panel stores stuff here (runtime only!) */ - + /* XXX depricated? */ struct bGPdata *gpd; /* Grease-Pencil Data (annotation layers) */ diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 48b5592dbfc..82217cdc3e4 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -35,6 +35,7 @@ #include "DNA_ID.h" #include "DNA_vfont_types.h" +#include "DNA_material_types.h" #include "DNA_object_types.h" #include "WM_types.h" @@ -419,8 +420,9 @@ static void rna_def_ID_materials(BlenderRNA *brna) func= RNA_def_function(srna, "pop", "material_pop_id"); RNA_def_function_ui_description(func, "Remove a material from the data block."); - parm= RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of material to remove.", 0, INT_MAX); + parm= RNA_def_int(func, "index", 0, 0, MAXMAT, "", "Index of material to remove.", 0, MAXMAT); RNA_def_property_flag(parm, PROP_REQUIRED); + RNA_def_boolean(func, "update_data", 0, "", "Update data by re-adjusting the material slots assigned."); parm= RNA_def_pointer(func, "material", "Material", "", "Material to remove."); RNA_def_function_return(func, parm); } diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index 31a9d57bc93..25c08a57889 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -191,8 +191,9 @@ static void rna_Action_active_pose_marker_index_range(PointerRNA *ptr, int *min, static void rna_Action_frame_range_get(PointerRNA *ptr,float *values) -{ - calc_action_range(ptr->id.data, values, values+1, 1); +{ /* don't include modifiers because they too easily can have very large + * ranges: MINAFRAMEF to MAXFRAMEF. */ + calc_action_range(ptr->id.data, values, values+1, FALSE); } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 36a6762074c..64cd7dc646f 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -2742,17 +2742,30 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_int_sdna(prop, NULL, "dragthreshold"); RNA_def_property_range(prop, 3, 40); RNA_def_property_ui_text(prop, "Drag Threshold", "Amount of pixels you have to drag before dragging UI items happens"); - - prop= RNA_def_property(srna, "ndof_pan_speed", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "ndof_pan"); - RNA_def_property_range(prop, 0, 200); - RNA_def_property_ui_text(prop, "NDof Pan Speed", "The overall panning speed of an NDOF device, as percent of standard"); - prop= RNA_def_property(srna, "ndof_rotate_speed", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "ndof_rotate"); - RNA_def_property_range(prop, 0, 200); - RNA_def_property_ui_text(prop, "NDof Rotation Speed", "The overall rotation speed of an NDOF device, as percent of standard"); - + /* 3D mouse settings */ + prop= RNA_def_property(srna, "ndof_sensitivity", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.25f, 4.0f); + RNA_def_property_ui_text(prop, "Sensitivity", "Overall sensitivity of the 3D Mouse"); + + prop= RNA_def_property(srna, "ndof_show_guide", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE); + RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation"); + /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ + + prop= RNA_def_property(srna, "ndof_orbit_invert_axes", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_ORBIT_INVERT_AXES); + RNA_def_property_ui_text(prop, "Invert Axes", "Toggle between moving the viewpoint or moving the scene being viewed"); + + prop= RNA_def_property(srna, "ndof_lock_horizon", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_LOCK_HORIZON); + RNA_def_property_ui_text(prop, "Lock Horizon", "Keep horizon level while flying with 3D Mouse"); + + prop= RNA_def_property(srna, "ndof_fly_helicopter", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_FLY_HELICOPTER); + RNA_def_property_ui_text(prop, "Helicopter Mode", "Device up/down directly controls your Z position"); + + prop= RNA_def_property(srna, "mouse_double_click_time", PROP_INT, PROP_NONE); RNA_def_property_int_sdna(prop, NULL, "dbl_click_time"); RNA_def_property_range(prop, 1, 1000); diff --git a/source/blender/makesrna/intern/rna_wm.c b/source/blender/makesrna/intern/rna_wm.c index 73221c47c90..a046be59ab5 100644 --- a/source/blender/makesrna/intern/rna_wm.c +++ b/source/blender/makesrna/intern/rna_wm.c @@ -106,6 +106,46 @@ EnumPropertyItem event_timer_type_items[]= { {TIMER2, "TIMER2", 0, "Timer 2", ""}, {0, NULL, 0, NULL, NULL}}; +EnumPropertyItem event_ndof_type_items[]= { + /* buttons on all 3dconnexion devices */ + {NDOF_BUTTON_MENU, "NDOF_BUTTON_MENU", 0, "Menu", ""}, + {NDOF_BUTTON_FIT, "NDOF_BUTTON_FIT", 0, "Fit", ""}, + /* view buttons */ + {NDOF_BUTTON_TOP, "NDOF_BUTTON_TOP", 0, "Top", ""}, + {NDOF_BUTTON_BOTTOM, "NDOF_BUTTON_BOTTOM", 0, "Bottom", ""}, + {NDOF_BUTTON_LEFT, "NDOF_BUTTON_LEFT", 0, "Left", ""}, + {NDOF_BUTTON_RIGHT, "NDOF_BUTTON_RIGHT", 0, "Right", ""}, + {NDOF_BUTTON_FRONT, "NDOF_BUTTON_FRONT", 0, "Front", ""}, + {NDOF_BUTTON_BACK, "NDOF_BUTTON_BACK", 0, "Back", ""}, + /* more views */ + {NDOF_BUTTON_ISO1, "NDOF_BUTTON_ISO1", 0, "ISO 1", ""}, + {NDOF_BUTTON_ISO2, "NDOF_BUTTON_ISO2", 0, "ISO 2", ""}, + /* 90 degree rotations */ + {NDOF_BUTTON_ROLL_CW, "NDOF_BUTTON_ROLL_CW", 0, "Roll CW", ""}, + {NDOF_BUTTON_ROLL_CCW, "NDOF_BUTTON_ROLL_CCW", 0, "Roll CCW", ""}, + {NDOF_BUTTON_SPIN_CW, "NDOF_BUTTON_SPIN_CW", 0, "Spin CW", ""}, + {NDOF_BUTTON_SPIN_CCW, "NDOF_BUTTON_SPIN_CCW", 0, "Spin CCW", ""}, + {NDOF_BUTTON_TILT_CW, "NDOF_BUTTON_TILT_CW", 0, "Tilt CW", ""}, + {NDOF_BUTTON_TILT_CCW, "NDOF_BUTTON_TILT_CCW", 0, "Tilt CCW", ""}, + /* device control */ + {NDOF_BUTTON_ROTATE, "NDOF_BUTTON_ROTATE", 0, "Rotate", ""}, + {NDOF_BUTTON_PANZOOM, "NDOF_BUTTON_PANZOOM", 0, "Pan/Zoom", ""}, + {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""}, + {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""}, + {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""}, + /* general-purpose buttons */ + {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""}, + {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""}, + {NDOF_BUTTON_3, "NDOF_BUTTON_3", 0, "Button 3", ""}, + {NDOF_BUTTON_4, "NDOF_BUTTON_4", 0, "Button 4", ""}, + {NDOF_BUTTON_5, "NDOF_BUTTON_5", 0, "Button 5", ""}, + {NDOF_BUTTON_6, "NDOF_BUTTON_6", 0, "Button 6", ""}, + {NDOF_BUTTON_7, "NDOF_BUTTON_7", 0, "Button 7", ""}, + {NDOF_BUTTON_8, "NDOF_BUTTON_8", 0, "Button 8", ""}, + {NDOF_BUTTON_9, "NDOF_BUTTON_9", 0, "Button 9", ""}, + {NDOF_BUTTON_10, "NDOF_BUTTON_10", 0, "Button 10", ""}, + {0, NULL, 0, NULL, NULL}}; + /* not returned: CAPSLOCKKEY, UNKNOWNKEY */ EnumPropertyItem event_type_items[] = { @@ -256,6 +296,44 @@ EnumPropertyItem event_type_items[] = { {TIMER0, "TIMER0", 0, "Timer 0", ""}, {TIMER1, "TIMER1", 0, "Timer 1", ""}, {TIMER2, "TIMER2", 0, "Timer 2", ""}, + {0, "", 0, NULL, NULL}, + /* buttons on all 3dconnexion devices */ + {NDOF_BUTTON_MENU, "NDOF_BUTTON_MENU", 0, "Menu", ""}, + {NDOF_BUTTON_FIT, "NDOF_BUTTON_FIT", 0, "Fit", ""}, + /* view buttons */ + {NDOF_BUTTON_TOP, "NDOF_BUTTON_TOP", 0, "Top", ""}, + {NDOF_BUTTON_BOTTOM, "NDOF_BUTTON_BOTTOM", 0, "Bottom", ""}, + {NDOF_BUTTON_LEFT, "NDOF_BUTTON_LEFT", 0, "Left", ""}, + {NDOF_BUTTON_RIGHT, "NDOF_BUTTON_RIGHT", 0, "Right", ""}, + {NDOF_BUTTON_FRONT, "NDOF_BUTTON_FRONT", 0, "Front", ""}, + {NDOF_BUTTON_BACK, "NDOF_BUTTON_BACK", 0, "Back", ""}, + /* more views */ + {NDOF_BUTTON_ISO1, "NDOF_BUTTON_ISO1", 0, "ISO 1", ""}, + {NDOF_BUTTON_ISO2, "NDOF_BUTTON_ISO2", 0, "ISO 2", ""}, + /* 90 degree rotations */ + {NDOF_BUTTON_ROLL_CW, "NDOF_BUTTON_ROLL_CW", 0, "Roll CW", ""}, + {NDOF_BUTTON_ROLL_CCW, "NDOF_BUTTON_ROLL_CCW", 0, "Roll CCW", ""}, + {NDOF_BUTTON_SPIN_CW, "NDOF_BUTTON_SPIN_CW", 0, "Spin CW", ""}, + {NDOF_BUTTON_SPIN_CCW, "NDOF_BUTTON_SPIN_CCW", 0, "Spin CCW", ""}, + {NDOF_BUTTON_TILT_CW, "NDOF_BUTTON_TILT_CW", 0, "Tilt CW", ""}, + {NDOF_BUTTON_TILT_CCW, "NDOF_BUTTON_TILT_CCW", 0, "Tilt CCW", ""}, + /* device control */ + {NDOF_BUTTON_ROTATE, "NDOF_BUTTON_ROTATE", 0, "Rotate", ""}, + {NDOF_BUTTON_PANZOOM, "NDOF_BUTTON_PANZOOM", 0, "Pan/Zoom", ""}, + {NDOF_BUTTON_DOMINANT, "NDOF_BUTTON_DOMINANT", 0, "Dominant", ""}, + {NDOF_BUTTON_PLUS, "NDOF_BUTTON_PLUS", 0, "Plus", ""}, + {NDOF_BUTTON_MINUS, "NDOF_BUTTON_MINUS", 0, "Minus", ""}, + /* general-purpose buttons */ + {NDOF_BUTTON_1, "NDOF_BUTTON_1", 0, "Button 1", ""}, + {NDOF_BUTTON_2, "NDOF_BUTTON_2", 0, "Button 2", ""}, + {NDOF_BUTTON_3, "NDOF_BUTTON_3", 0, "Button 3", ""}, + {NDOF_BUTTON_4, "NDOF_BUTTON_4", 0, "Button 4", ""}, + {NDOF_BUTTON_5, "NDOF_BUTTON_5", 0, "Button 5", ""}, + {NDOF_BUTTON_6, "NDOF_BUTTON_6", 0, "Button 6", ""}, + {NDOF_BUTTON_7, "NDOF_BUTTON_7", 0, "Button 7", ""}, + {NDOF_BUTTON_8, "NDOF_BUTTON_8", 0, "Button 8", ""}, + {NDOF_BUTTON_9, "NDOF_BUTTON_9", 0, "Button 9", ""}, + {NDOF_BUTTON_10, "NDOF_BUTTON_10", 0, "Button 10", ""}, {0, NULL, 0, NULL, NULL}}; EnumPropertyItem keymap_propvalue_items[] = { @@ -303,6 +381,7 @@ EnumPropertyItem wm_report_items[] = { #define KMI_TYPE_TWEAK 2 #define KMI_TYPE_TEXTINPUT 3 #define KMI_TYPE_TIMER 4 +#define KMI_TYPE_NDOF 5 #ifdef RNA_RUNTIME @@ -433,6 +512,7 @@ static int rna_wmKeyMapItem_map_type_get(PointerRNA *ptr) if(ISKEYBOARD(kmi->type)) return KMI_TYPE_KEYBOARD; if(ISTWEAK(kmi->type)) return KMI_TYPE_TWEAK; if(ISMOUSE(kmi->type)) return KMI_TYPE_MOUSE; + if(ISNDOF(kmi->type)) return KMI_TYPE_NDOF; if(kmi->type == KM_TEXTINPUT) return KMI_TYPE_TEXTINPUT; return KMI_TYPE_KEYBOARD; } @@ -464,6 +544,10 @@ static void rna_wmKeyMapItem_map_type_set(PointerRNA *ptr, int value) kmi->type= TIMER; kmi->val= KM_NOTHING; break; + case KMI_TYPE_NDOF: + kmi->type = NDOF_BUTTON_MENU; + kmi->val = KM_NOTHING; + break; } } } @@ -475,6 +559,7 @@ static EnumPropertyItem *rna_KeyMapItem_type_itemf(bContext *UNUSED(C), PointerR if(map_type == KMI_TYPE_MOUSE) return event_mouse_type_items; if(map_type == KMI_TYPE_TWEAK) return event_tweak_type_items; if(map_type == KMI_TYPE_TIMER) return event_timer_type_items; + if(map_type == KMI_TYPE_NDOF) return event_ndof_type_items; else return event_type_items; } @@ -482,7 +567,7 @@ static EnumPropertyItem *rna_KeyMapItem_value_itemf(bContext *UNUSED(C), Pointer { int map_type= rna_wmKeyMapItem_map_type_get(ptr); - if(map_type == KMI_TYPE_MOUSE || map_type == KMI_TYPE_KEYBOARD) return event_keymouse_value_items; + if(map_type == KMI_TYPE_MOUSE || map_type == KMI_TYPE_KEYBOARD || map_type == KMI_TYPE_NDOF) return event_keymouse_value_items; if(map_type == KMI_TYPE_TWEAK) return event_tweak_value_items; else return event_value_items; } @@ -1653,6 +1738,7 @@ static void rna_def_keyconfig(BlenderRNA *brna) {KMI_TYPE_KEYBOARD, "KEYBOARD", 0, "Keyboard", ""}, {KMI_TYPE_TWEAK, "TWEAK", 0, "Tweak", ""}, {KMI_TYPE_MOUSE, "MOUSE", 0, "Mouse", ""}, + {KMI_TYPE_NDOF, "NDOF", 0, "NDOF", ""}, {KMI_TYPE_TEXTINPUT, "TEXTINPUT", 0, "Text Input", ""}, {KMI_TYPE_TIMER, "TIMER", 0, "Timer", ""}, {0, NULL, 0, NULL, NULL}}; diff --git a/source/blender/makesrna/intern/rna_wm_api.c b/source/blender/makesrna/intern/rna_wm_api.c index e250cc84aa3..d44b68950f7 100644 --- a/source/blender/makesrna/intern/rna_wm_api.c +++ b/source/blender/makesrna/intern/rna_wm_api.c @@ -205,7 +205,7 @@ void RNA_api_operator(StructRNA *srna) /* check */ func= RNA_def_function(srna, "check", NULL); - RNA_def_function_ui_description(func, "Check the operator settings."); + RNA_def_function_ui_description(func, "Check the operator settings, return True to signal a change to redraw."); RNA_def_function_flag(func, FUNC_REGISTER_OPTIONAL); parm= RNA_def_pointer(func, "context", "Context", "", ""); RNA_def_property_flag(parm, PROP_REQUIRED|PROP_NEVER_NULL); diff --git a/source/blender/modifiers/intern/MOD_uvproject.c b/source/blender/modifiers/intern/MOD_uvproject.c index a5d2e0b38c7..922ae8c1e92 100644 --- a/source/blender/modifiers/intern/MOD_uvproject.c +++ b/source/blender/modifiers/intern/MOD_uvproject.c @@ -42,6 +42,7 @@ #include "DNA_object_types.h" #include "BLI_math.h" +#include "BLI_string.h" #include "BLI_uvproject.h" #include "BLI_utildefines.h" @@ -83,6 +84,7 @@ static void copyData(ModifierData *md, ModifierData *target) tumd->aspecty = umd->aspecty; tumd->scalex = umd->scalex; tumd->scaley = umd->scaley; + BLI_strncpy(tumd->uvlayer_name, umd->uvlayer_name, sizeof(umd->uvlayer_name)); } static CustomDataMask requiredDataMask(Object *UNUSED(ob), ModifierData *UNUSED(md)) diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index 0ba80bf0850..a0ad1ff7850 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -326,6 +326,11 @@ static int bpy_prop_callback_assign(struct PropertyRNA *prop, PyObject *update_c " :type description: string\n" \ +#define BPY_PROPDEF_UNIT_DOC \ +" :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', 'VELOCITY', 'ACCELERATION'].\n" \ +" :type unit: string\n" \ + + #define BPY_PROPDEF_UPDATE_DOC \ " :arg update: function to be called when this value is modified,\n" \ " This function must take 2 values (self, context) and return None.\n" \ @@ -639,8 +644,7 @@ BPY_PROPDEF_DESC_DOC " :type options: set\n" " :arg subtype: Enumerator in ['UNSIGNED', 'PERCENTAGE', 'FACTOR', 'ANGLE', 'TIME', 'DISTANCE', 'NONE'].\n" " :type subtype: string\n" -" :arg unit: Enumerator in ['NONE', 'LENGTH', 'AREA', 'VOLUME', 'ROTATION', 'TIME', 'VELOCITY', 'ACCELERATION'].\n" -" :type unit: string\n" +BPY_PROPDEF_UNIT_DOC BPY_PROPDEF_UPDATE_DOC ); static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) @@ -679,7 +683,7 @@ static PyObject *BPy_FloatProperty(PyObject *self, PyObject *args, PyObject *kw) BPY_PROPDEF_SUBTYPE_CHECK(FloatProperty, property_flag_items, property_subtype_number_items) if(pyunit && RNA_enum_value_from_id(property_unit_items, pyunit, &unit)==0) { - PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit"); + PyErr_Format(PyExc_TypeError, "FloatProperty(unit='%s'): invalid unit", pyunit); return NULL; } @@ -716,6 +720,7 @@ BPY_PROPDEF_DESC_DOC " :type options: set\n" " :arg subtype: Enumerator in ['COLOR', 'TRANSLATION', 'DIRECTION', 'VELOCITY', 'ACCELERATION', 'MATRIX', 'EULER', 'QUATERNION', 'AXISANGLE', 'XYZ', 'COLOR_GAMMA', 'LAYER', 'NONE'].\n" " :type subtype: string\n" +BPY_PROPDEF_UNIT_DOC " :arg size: Vector dimensions in [1, and " STRINGIFY(PYRNA_STACK_ARRAY) "].\n" " :type size: int\n" BPY_PROPDEF_UPDATE_DOC @@ -727,7 +732,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec BPY_PROPDEF_HEAD(FloatVectorProperty) if(srna) { - static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "size", "update", NULL}; + static const char *kwlist[]= {"attr", "name", "description", "default", "min", "max", "soft_min", "soft_max", "step", "precision", "options", "subtype", "unit", "size", "update", NULL}; const char *id=NULL, *name="", *description=""; int id_len; float min=-FLT_MAX, max=FLT_MAX, soft_min=-FLT_MAX, soft_max=FLT_MAX, step=3, def[PYRNA_STACK_ARRAY]={0.0f}; @@ -738,15 +743,17 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec int opts=0; char *pysubtype= NULL; int subtype= PROP_NONE; + char *pyunit= NULL; + int unit= PROP_UNIT_NONE; PyObject *update_cb= NULL; if (!PyArg_ParseTupleAndKeywords(args, kw, - "s#|ssOfffffiO!siO:FloatVectorProperty", + "s#|ssOfffffiO!ssiO:FloatVectorProperty", (char **)kwlist, &id, &id_len, &name, &description, &pydef, &min, &max, &soft_min, &soft_max, &step, &precision, &PySet_Type, - &pyopts, &pysubtype, &size, + &pyopts, &pysubtype, &pyunit, &size, &update_cb)) { return NULL; @@ -754,6 +761,11 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec BPY_PROPDEF_SUBTYPE_CHECK(FloatVectorProperty, property_flag_items, property_subtype_array_items) + if(pyunit && RNA_enum_value_from_id(property_unit_items, pyunit, &unit)==0) { + PyErr_Format(PyExc_TypeError, "FloatVectorProperty(unit='%s'): invalid unit", pyunit); + return NULL; + } + if(size < 1 || size > PYRNA_STACK_ARRAY) { PyErr_Format(PyExc_TypeError, "FloatVectorProperty(size=%d): size must be between 0 and " STRINGIFY(PYRNA_STACK_ARRAY), size); return NULL; @@ -766,7 +778,7 @@ static PyObject *BPy_FloatVectorProperty(PyObject *self, PyObject *args, PyObjec return NULL; } - prop= RNA_def_property(srna, id, PROP_FLOAT, subtype); + prop= RNA_def_property(srna, id, PROP_FLOAT, subtype | unit); RNA_def_property_array(prop, size); if(pydef) RNA_def_property_float_array_default(prop, def); RNA_def_property_range(prop, min, max); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 6e1b9c807f3..502b25842de 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -3262,11 +3262,15 @@ static PyObject *pyrna_prop_dir(BPy_PropertyRNA *self) * */ ret= PyList_New(0); - if (!BPy_PropertyRNA_CheckExact(self)) + if (!BPy_PropertyRNA_CheckExact(self)) { pyrna_dir_members_py(ret, (PyObject *)self); + } - if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) - pyrna_dir_members_rna(ret, &r_ptr); + if(RNA_property_type(self->prop) == PROP_COLLECTION) { + if(RNA_property_collection_type_get(&self->ptr, self->prop, &r_ptr)) { + pyrna_dir_members_rna(ret, &r_ptr); + } + } return ret; } @@ -6407,7 +6411,9 @@ PyDoc_STRVAR(pyrna_register_class_doc, " If the class has a *register* class method it will be called\n" " before registration.\n" "\n" -" .. note:: :exc:`ValueError` exception is raised if the class is not a\n" +" .. note::\n" +"\n" +" :exc:`ValueError` exception is raised if the class is not a\n" " subclass of a registerable blender class.\n" "\n" ); diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 49bd3ede37d..7fd52e89a5f 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -377,6 +377,26 @@ typedef struct wmTabletData { float Ytilt; /* as above */ } wmTabletData; +typedef enum { // motion progress, for modal handlers + P_NOT_STARTED, + P_STARTING, // <-- + P_IN_PROGRESS, // <-- only these are sent for NDOF motion + P_FINISHING, // <-- + P_FINISHED + } wmProgress; + +typedef struct wmNDOFMotionData { + /* awfully similar to GHOST_TEventNDOFMotionData... */ + // Each component normally ranges from -1 to +1, but can exceed that. + // These use blender standard view coordinates, with positive rotations being CCW about the axis. + float tvec[3]; // translation + float rvec[3]; // rotation: + // axis = (rx,ry,rz).normalized + // amount = (rx,ry,rz).magnitude [in revolutions, 1.0 = 360 deg] + float dt; // time since previous NDOF Motion event + wmProgress progress; // is this the first event, the last, or one of many in between? +} wmNDOFMotionData; + typedef struct wmTimer { struct wmTimer *next, *prev; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index ce3830b059c..0abae2e06b7 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1815,7 +1815,10 @@ void wm_event_do_handlers(bContext *C) /* for regions having custom cursors */ wm_paintcursor_test(C, event); } - + else if (event->type==NDOF_MOTION) { + win->addmousemove = TRUE; + } + for(sa= win->screen->areabase.first; sa; sa= sa->next) { if(wm_event_inside_i(event, &sa->totrct)) { CTX_wm_area_set(C, sa); @@ -1879,7 +1882,10 @@ void wm_event_do_handlers(bContext *C) if(doit && win->screen && win->screen->subwinactive != win->screen->mainwin) { win->eventstate->prevx= event->x; win->eventstate->prevy= event->y; + //printf("win->eventstate->prev = %d %d\n", event->x, event->y); } + else + ;//printf("not setting prev to %d %d\n", event->x, event->y); } /* store last event for this window */ @@ -1922,6 +1928,7 @@ void wm_event_do_handlers(bContext *C) /* only add mousemove when queue was read entirely */ if(win->addmousemove && win->eventstate) { wmEvent tevent= *(win->eventstate); + //printf("adding MOUSEMOVE %d %d\n", tevent.x, tevent.y); tevent.type= MOUSEMOVE; tevent.prevx= tevent.x; tevent.prevy= tevent.y; @@ -2309,6 +2316,30 @@ static void update_tablet_data(wmWindow *win, wmEvent *event) } } +/* adds customdata to event */ +static void attach_ndof_data(wmEvent* event, const GHOST_TEventNDOFMotionData* ghost) +{ + wmNDOFMotionData* data = MEM_mallocN(sizeof(wmNDOFMotionData), "customdata NDOF"); + + const float s = U.ndof_sensitivity; + + data->tvec[0]= s * ghost->tx; + data->tvec[1]= s * ghost->ty; + data->tvec[2]= s * ghost->tz; + + data->rvec[0]= s * ghost->rx; + data->rvec[1]= s * ghost->ry; + data->rvec[2]= s * ghost->rz; + + data->dt = ghost->dt; + + data->progress = (wmProgress) ghost->progress; + + event->custom = EVT_DATA_NDOF_MOTION; + event->customdata = data; + event->customdatafree = 1; +} + /* imperfect but probably usable... draw/enable drags to other windows */ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *evt) { @@ -2355,7 +2386,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U { wmWindow *owin; wmEvent event, *evt= win->eventstate; - + /* initialize and copy state (only mouse x y and modifiers) */ event= *evt; @@ -2384,6 +2415,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U update_tablet_data(win, &event); wm_event_add(win, &event); + + //printf("sending MOUSEMOVE %d %d\n", event.x, event.y); /* also add to other window if event is there, this makes overdraws disappear nicely */ /* it remaps mousecoord to other window in event */ @@ -2557,6 +2590,38 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U break; } + case GHOST_kEventNDOFMotion: { + event.type = NDOF_MOTION; + attach_ndof_data(&event, customdata); + wm_event_add(win, &event); + + //printf("sending NDOF_MOTION, prev = %d %d\n", event.x, event.y); + + break; + } + + case GHOST_kEventNDOFButton: { + GHOST_TEventNDOFButtonData* e = customdata; + + event.type = NDOF_BUTTON_NONE + e->button; + + switch (e->action) { + case GHOST_kPress: + event.val = KM_PRESS; + break; + case GHOST_kRelease: + event.val = KM_RELEASE; + break; + } + + event.custom = 0; + event.customdata = NULL; + + wm_event_add(win, &event); + + break; + } + case GHOST_kEventUnknown: case GHOST_kNumEventTypes: break; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 4c280fe4341..e22829577f4 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -183,8 +183,6 @@ void WM_init(bContext *C, int argc, const char **argv) ED_preview_init_dbase(); - G.ndofdevice = -1; /* XXX bad initializer, needs set otherwise buttons show! */ - WM_read_history(); /* allow a path of "", this is what happens when making a new file */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 29afdb570ea..a47dfacf358 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -3416,7 +3416,49 @@ static void WM_OT_memory_statistics(wmOperatorType *ot) } /* ******************************************************* */ - + +static int wm_ndof_sensitivity_exec(bContext *UNUSED(C), wmOperator *op) +{ + const float min = 0.25f, max = 4.f; // TODO: get these from RNA property + float change; + float sensitivity = U.ndof_sensitivity; + + if(RNA_boolean_get(op->ptr, "fast")) + change = 0.5f; // 50% change + else + change = 0.1f; // 10% + + if(RNA_boolean_get(op->ptr, "decrease")) { + sensitivity -= sensitivity * change; + if (sensitivity < min) + sensitivity = min; + } + else { + sensitivity += sensitivity * change; + if (sensitivity > max) + sensitivity = max; + } + + if (sensitivity != U.ndof_sensitivity) { + U.ndof_sensitivity = sensitivity; + } + + return OPERATOR_FINISHED; +} + +static void WM_OT_ndof_sensitivity_change(wmOperatorType *ot) +{ + ot->name= "Change NDOF sensitivity"; + ot->idname= "WM_OT_ndof_sensitivity_change"; + ot->description="Change NDOF sensitivity"; + + ot->exec= wm_ndof_sensitivity_exec; + + RNA_def_boolean(ot->srna, "decrease", 1, "Decrease NDOF sensitivity", "If true then action decreases NDOF sensitivity instead of increasing"); + RNA_def_boolean(ot->srna, "fast", 0, "Fast NDOF sensitivity change", "If true then sensitivity changes 50%, otherwise 10%"); +} + +/* ******************************************************* */ /* called on initialize WM_exit() */ void wm_operatortype_free(void) { @@ -3455,6 +3497,7 @@ void wm_operatortype_init(void) WM_operatortype_append(WM_OT_search_menu); WM_operatortype_append(WM_OT_call_menu); WM_operatortype_append(WM_OT_radial_control); + WM_operatortype_append(WM_OT_ndof_sensitivity_change); #if defined(WIN32) WM_operatortype_append(WM_OT_console_toggle); #endif @@ -3674,11 +3717,12 @@ void wm_window_keymap(wmKeyConfig *keyconf) /* debug/testing */ WM_keymap_verify_item(keymap, "WM_OT_redraw_timer", TKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); WM_keymap_verify_item(keymap, "WM_OT_debug_menu", DKEY, KM_PRESS, KM_ALT|KM_CTRL, 0); - WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); - - /* Space switching */ + /* menus that can be accessed anywhere in blender */ + WM_keymap_verify_item(keymap, "WM_OT_search_menu", SPACEKEY, KM_PRESS, 0, 0); + WM_keymap_add_menu(keymap, "VIEW3D_MT_ndof_settings", NDOF_BUTTON_MENU, KM_PRESS, 0, 0); + /* Space switching */ kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F2KEY, KM_PRESS, KM_SHIFT, 0); /* new in 2.5x, was DXF export */ RNA_string_set(kmi->ptr, "data_path", "area.type"); RNA_string_set(kmi->ptr, "value", "LOGIC_EDITOR"); @@ -3722,6 +3766,23 @@ void wm_window_keymap(wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "WM_OT_context_set_enum", F12KEY, KM_PRESS, KM_SHIFT, 0); RNA_string_set(kmi->ptr, "data_path", "area.type"); RNA_string_set(kmi->ptr, "value", "DOPESHEET_EDITOR"); + + /* ndof speed */ + kmi= WM_keymap_add_item(keymap, "WM_OT_ndof_sensitivity_change", NDOF_BUTTON_PLUS, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "decrease", FALSE); + RNA_boolean_set(kmi->ptr, "fast", FALSE); + + kmi= WM_keymap_add_item(keymap, "WM_OT_ndof_sensitivity_change", NDOF_BUTTON_MINUS, KM_PRESS, 0, 0); + RNA_boolean_set(kmi->ptr, "decrease", TRUE); + RNA_boolean_set(kmi->ptr, "fast", FALSE); + + kmi= WM_keymap_add_item(keymap, "WM_OT_ndof_sensitivity_change", NDOF_BUTTON_PLUS, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "decrease", FALSE); + RNA_boolean_set(kmi->ptr, "fast", TRUE); + + kmi= WM_keymap_add_item(keymap, "WM_OT_ndof_sensitivity_change", NDOF_BUTTON_MINUS, KM_PRESS, KM_SHIFT, 0); + RNA_boolean_set(kmi->ptr, "decrease", TRUE); + RNA_boolean_set(kmi->ptr, "fast", TRUE); gesture_circle_modal_keymap(keyconf); gesture_border_modal_keymap(keyconf); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 9b1695be67a..7d6010786d2 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -621,12 +621,12 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr private) if (!ghostwin) { // XXX - should be checked, why are we getting an event here, and // what is it? - + puts("<!> event has no window"); return 1; } else if (!GHOST_ValidWindow(g_system, ghostwin)) { // XXX - should be checked, why are we getting an event here, and // what is it? - + puts("<!> event has invalid window"); return 1; } else { win= GHOST_GetWindowUserData(ghostwin); diff --git a/source/blender/windowmanager/wm_event_types.h b/source/blender/windowmanager/wm_event_types.h index ee080e7c0aa..579f20ca605 100644 --- a/source/blender/windowmanager/wm_event_types.h +++ b/source/blender/windowmanager/wm_event_types.h @@ -45,6 +45,7 @@ #define EVT_DATA_GESTURE 2 #define EVT_DATA_TIMER 3 #define EVT_DATA_LISTBASE 4 +#define EVT_DATA_NDOF_MOTION 5 /* tablet active, matches GHOST_TTabletMode */ #define EVT_TABLET_NONE 0 @@ -78,6 +79,56 @@ #define INBETWEEN_MOUSEMOVE 17 +/* NDOF (from SpaceNavigator & friends) + These should be kept in sync with GHOST_NDOFManager.h + Ordering matters, exact values do not. */ + +#define NDOF_MOTION 400 + +enum { + // used internally, never sent + NDOF_BUTTON_NONE = NDOF_MOTION, + // these two are available from any 3Dconnexion device + NDOF_BUTTON_MENU, + NDOF_BUTTON_FIT, + // standard views + NDOF_BUTTON_TOP, + NDOF_BUTTON_BOTTOM, + NDOF_BUTTON_LEFT, + NDOF_BUTTON_RIGHT, + NDOF_BUTTON_FRONT, + NDOF_BUTTON_BACK, + // more views + NDOF_BUTTON_ISO1, + NDOF_BUTTON_ISO2, + // 90 degree rotations + NDOF_BUTTON_ROLL_CW, + NDOF_BUTTON_ROLL_CCW, + NDOF_BUTTON_SPIN_CW, + NDOF_BUTTON_SPIN_CCW, + NDOF_BUTTON_TILT_CW, + NDOF_BUTTON_TILT_CCW, + // device control + NDOF_BUTTON_ROTATE, + NDOF_BUTTON_PANZOOM, + NDOF_BUTTON_DOMINANT, + NDOF_BUTTON_PLUS, + NDOF_BUTTON_MINUS, + // general-purpose buttons + NDOF_BUTTON_1, + NDOF_BUTTON_2, + NDOF_BUTTON_3, + NDOF_BUTTON_4, + NDOF_BUTTON_5, + NDOF_BUTTON_6, + NDOF_BUTTON_7, + NDOF_BUTTON_8, + NDOF_BUTTON_9, + NDOF_BUTTON_10, + NDOF_LAST + }; + + /* SYSTEM : 0x01xx */ #define INPUTCHANGE 0x0103 /* input connected or disconnected */ #define WINDEACTIVATE 0x0104 /* window is deactivated, focus lost */ @@ -240,8 +291,11 @@ /* test whether the event is tweak event */ #define ISTWEAK(event) (event >= EVT_TWEAK_L && event <= EVT_GESTURE) + /* test whether the event is a NDOF event */ +#define ISNDOF(event) (event >= NDOF_MOTION && event < NDOF_LAST) + /* test whether event type is acceptable as hotkey, excluding modifiers */ -#define ISHOTKEY(event) ((ISKEYBOARD(event) || ISMOUSE(event)) && event!=ESCKEY && !(event>=LEFTCTRLKEY && event<=LEFTSHIFTKEY) && !(event>=UNKNOWNKEY && event<=GRLESSKEY)) +#define ISHOTKEY(event) ((ISKEYBOARD(event) || ISMOUSE(event) || ISNDOF(event)) && event!=ESCKEY && !(event>=LEFTCTRLKEY && event<=LEFTSHIFTKEY) && !(event>=UNKNOWNKEY && event<=GRLESSKEY)) /* **************** BLENDER GESTURE EVENTS (0x5000) **************** */ |