2008-12-20 18:43:21 +00:00
|
|
|
/**
|
|
|
|
* $Id:
|
|
|
|
*
|
|
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2008 Blender Foundation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Contributor(s): Blender Foundation
|
|
|
|
*
|
|
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <float.h>
|
|
|
|
|
|
|
|
#include "DNA_action_types.h"
|
|
|
|
#include "DNA_armature_types.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
|
|
#include "DNA_camera_types.h"
|
|
|
|
#include "DNA_lamp_types.h"
|
|
|
|
#include "DNA_meta_types.h"
|
|
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "DNA_meshdata_types.h"
|
|
|
|
#include "DNA_object_types.h"
|
|
|
|
#include "DNA_space_types.h"
|
|
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "DNA_screen_types.h"
|
|
|
|
#include "DNA_userdef_types.h"
|
|
|
|
#include "DNA_view3d_types.h"
|
|
|
|
#include "DNA_world_types.h"
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
|
|
|
#include "BLI_arithb.h"
|
|
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BLI_editVert.h"
|
|
|
|
#include "BLI_rand.h"
|
2009-09-16 01:15:30 +00:00
|
|
|
#include "BLI_linklist.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
#include "BKE_action.h"
|
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_depsgraph.h"
|
|
|
|
#include "BKE_object.h"
|
|
|
|
#include "BKE_global.h"
|
2009-08-15 19:48:50 +00:00
|
|
|
#include "BKE_paint.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
#include "BKE_scene.h"
|
|
|
|
#include "BKE_screen.h"
|
|
|
|
#include "BKE_utildefines.h"
|
|
|
|
|
|
|
|
#include "RE_pipeline.h" // make_stars
|
|
|
|
|
|
|
|
#include "BIF_gl.h"
|
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
|
|
|
#include "RNA_access.h"
|
|
|
|
#include "RNA_define.h"
|
|
|
|
|
2009-01-05 15:19:31 +00:00
|
|
|
#include "ED_armature.h"
|
2009-01-14 12:26:45 +00:00
|
|
|
#include "ED_curve.h"
|
2009-02-20 20:39:27 +00:00
|
|
|
#include "ED_particle.h"
|
2008-12-30 13:16:14 +00:00
|
|
|
#include "ED_mesh.h"
|
2008-12-29 12:15:42 +00:00
|
|
|
#include "ED_object.h"
|
2009-07-08 16:17:47 +00:00
|
|
|
#include "ED_retopo.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
#include "ED_screen.h"
|
|
|
|
#include "ED_types.h"
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
#include "ED_util.h"
|
2009-07-29 12:35:09 +00:00
|
|
|
#include "ED_mball.h"
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
#include "UI_interface.h"
|
|
|
|
#include "UI_resources.h"
|
|
|
|
#include "UI_view2d.h"
|
|
|
|
|
|
|
|
#include "PIL_time.h" /* smoothview */
|
|
|
|
|
|
|
|
#include "view3d_intern.h" // own include
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
|
2.5
Vertex Paint back!
Added WM level "paint cursor" system, which manages a custom painting
cursor for tools or modes.
- Activate it with WM_paint_cursor_activate(). That function wants two
callbacks, a poll(C) to check whether there's a cursor in given context
and ARegion, and a draw(C, x, y) which gets called when appropriate.
- While paintcursor is active, the WM handles necessary redrawing events
for all regions, also to nicely clear the cursor on region exit.
- WM_paint_cursor_activate returns a handle, which you have to use to
end the paint cursor. This handle also means you can register as many
custom cursors as you want.
At the moment, vertex paint mode registers only a mousemove handler,
all other events are still normally handled. This is stuff for the
future todo.
2009-01-09 13:55:45 +00:00
|
|
|
void view3d_set_viewcontext(bContext *C, ViewContext *vc)
|
2009-01-02 14:11:18 +00:00
|
|
|
{
|
|
|
|
memset(vc, 0, sizeof(ViewContext));
|
|
|
|
vc->ar= CTX_wm_region(C);
|
|
|
|
vc->scene= CTX_data_scene(C);
|
2009-01-17 18:35:33 +00:00
|
|
|
vc->v3d= CTX_wm_view3d(C);
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
vc->rv3d= vc->ar->regiondata;
|
2009-01-02 14:11:18 +00:00
|
|
|
vc->obact= CTX_data_active_object(C);
|
|
|
|
vc->obedit= CTX_data_edit_object(C);
|
|
|
|
}
|
|
|
|
|
2009-02-13 17:37:01 +00:00
|
|
|
void view3d_get_view_aligned_coordinate(ViewContext *vc, float *fp, short mval[2])
|
|
|
|
{
|
|
|
|
float dvec[3];
|
|
|
|
short mx, my;
|
|
|
|
|
|
|
|
mx= mval[0];
|
|
|
|
my= mval[1];
|
|
|
|
|
|
|
|
project_short_noclip(vc->ar, fp, mval);
|
|
|
|
|
|
|
|
initgrabz(vc->rv3d, fp[0], fp[1], fp[2]);
|
|
|
|
|
|
|
|
if(mval[0]!=IS_CLIPPED) {
|
|
|
|
window_to_3d_delta(vc->ar, dvec, mval[0]-mx, mval[1]-my);
|
|
|
|
VecSubf(fp, fp, dvec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-20 20:39:27 +00:00
|
|
|
void view3d_get_transformation(ViewContext *vc, Object *ob, bglMats *mats)
|
|
|
|
{
|
|
|
|
float cpy[4][4];
|
|
|
|
int i, j;
|
|
|
|
|
2009-07-30 22:24:05 +00:00
|
|
|
Mat4MulMat4(cpy, ob->obmat, vc->rv3d->viewmat);
|
2009-02-20 20:39:27 +00:00
|
|
|
|
|
|
|
for(i = 0; i < 4; ++i) {
|
|
|
|
for(j = 0; j < 4; ++j) {
|
|
|
|
mats->projection[i*4+j] = vc->rv3d->winmat[i][j];
|
|
|
|
mats->modelview[i*4+j] = cpy[i][j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mats->viewport[0] = vc->ar->winrct.xmin;
|
|
|
|
mats->viewport[1] = vc->ar->winrct.ymin;
|
|
|
|
mats->viewport[2] = vc->ar->winx;
|
|
|
|
mats->viewport[3] = vc->ar->winy;
|
|
|
|
}
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* ********************** view3d_select: selection manipulations ********************* */
|
|
|
|
|
|
|
|
/* XXX to solve *************** */
|
|
|
|
static void BIF_undo_push() {}
|
|
|
|
/* XXX end ********************* */
|
|
|
|
|
|
|
|
/* local prototypes */
|
|
|
|
|
|
|
|
void EM_backbuf_checkAndSelectVerts(EditMesh *em, int select)
|
|
|
|
{
|
|
|
|
EditVert *eve;
|
|
|
|
int index= em_wireoffs;
|
|
|
|
|
|
|
|
for(eve= em->verts.first; eve; eve= eve->next, index++) {
|
|
|
|
if(eve->h==0) {
|
|
|
|
if(EM_check_backbuf(index)) {
|
|
|
|
eve->f = select?(eve->f|1):(eve->f&~1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EM_backbuf_checkAndSelectEdges(EditMesh *em, int select)
|
|
|
|
{
|
|
|
|
EditEdge *eed;
|
|
|
|
int index= em_solidoffs;
|
|
|
|
|
|
|
|
for(eed= em->edges.first; eed; eed= eed->next, index++) {
|
|
|
|
if(eed->h==0) {
|
|
|
|
if(EM_check_backbuf(index)) {
|
|
|
|
EM_select_edge(eed, select);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EM_backbuf_checkAndSelectFaces(EditMesh *em, int select)
|
|
|
|
{
|
|
|
|
EditFace *efa;
|
|
|
|
int index= 1;
|
|
|
|
|
|
|
|
for(efa= em->faces.first; efa; efa= efa->next, index++) {
|
|
|
|
if(efa->h==0) {
|
|
|
|
if(EM_check_backbuf(index)) {
|
2008-12-30 13:16:14 +00:00
|
|
|
EM_select_face_fgon(em, efa, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EM_backbuf_checkAndSelectTFaces(Mesh *me, int select)
|
|
|
|
{
|
|
|
|
MFace *mface = me->mface;
|
|
|
|
int a;
|
|
|
|
|
|
|
|
if (mface) {
|
|
|
|
for(a=1; a<=me->totface; a++, mface++) {
|
|
|
|
if(EM_check_backbuf(a)) {
|
|
|
|
mface->flag = select?(mface->flag|ME_FACE_SEL):(mface->flag&~ME_FACE_SEL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void arrows_move_cursor(unsigned short event)
|
|
|
|
{
|
|
|
|
#if 0
|
|
|
|
short mval[2];
|
|
|
|
|
|
|
|
getmouseco_sc(mval);
|
|
|
|
|
|
|
|
if(event==UPARROWKEY) {
|
|
|
|
warp_pointer(mval[0], mval[1]+1);
|
|
|
|
} else if(event==DOWNARROWKEY) {
|
|
|
|
warp_pointer(mval[0], mval[1]-1);
|
|
|
|
} else if(event==LEFTARROWKEY) {
|
|
|
|
warp_pointer(mval[0]-1, mval[1]);
|
|
|
|
} else if(event==RIGHTARROWKEY) {
|
|
|
|
warp_pointer(mval[0]+1, mval[1]);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* *********************** GESTURE AND LASSO ******************* */
|
|
|
|
|
|
|
|
/* helper also for borderselect */
|
|
|
|
static int edge_fully_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
|
|
|
|
{
|
|
|
|
return BLI_in_rcti(rect, x1, y1) && BLI_in_rcti(rect, x2, y2);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int edge_inside_rect(rcti *rect, short x1, short y1, short x2, short y2)
|
|
|
|
{
|
|
|
|
int d1, d2, d3, d4;
|
|
|
|
|
|
|
|
/* check points in rect */
|
|
|
|
if(edge_fully_inside_rect(rect, x1, y1, x2, y2)) return 1;
|
|
|
|
|
|
|
|
/* check points completely out rect */
|
|
|
|
if(x1<rect->xmin && x2<rect->xmin) return 0;
|
|
|
|
if(x1>rect->xmax && x2>rect->xmax) return 0;
|
|
|
|
if(y1<rect->ymin && y2<rect->ymin) return 0;
|
|
|
|
if(y1>rect->ymax && y2>rect->ymax) return 0;
|
|
|
|
|
|
|
|
/* simple check lines intersecting. */
|
|
|
|
d1= (y1-y2)*(x1- rect->xmin ) + (x2-x1)*(y1- rect->ymin );
|
|
|
|
d2= (y1-y2)*(x1- rect->xmin ) + (x2-x1)*(y1- rect->ymax );
|
|
|
|
d3= (y1-y2)*(x1- rect->xmax ) + (x2-x1)*(y1- rect->ymax );
|
|
|
|
d4= (y1-y2)*(x1- rect->xmax ) + (x2-x1)*(y1- rect->ymin );
|
|
|
|
|
|
|
|
if(d1<0 && d2<0 && d3<0 && d4<0) return 0;
|
|
|
|
if(d1>0 && d2>0 && d3>0 && d4>0) return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#define MOVES_GESTURE 50
|
|
|
|
#define MOVES_LASSO 500
|
|
|
|
|
|
|
|
int lasso_inside(short mcords[][2], short moves, short sx, short sy)
|
|
|
|
{
|
|
|
|
/* we do the angle rule, define that all added angles should be about zero or 2*PI */
|
|
|
|
float angletot=0.0, len, dot, ang, cross, fp1[2], fp2[2];
|
|
|
|
int a;
|
|
|
|
short *p1, *p2;
|
|
|
|
|
|
|
|
if(sx==IS_CLIPPED)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
p1= mcords[moves-1];
|
|
|
|
p2= mcords[0];
|
|
|
|
|
|
|
|
/* first vector */
|
|
|
|
fp1[0]= (float)(p1[0]-sx);
|
|
|
|
fp1[1]= (float)(p1[1]-sy);
|
|
|
|
len= sqrt(fp1[0]*fp1[0] + fp1[1]*fp1[1]);
|
|
|
|
fp1[0]/= len;
|
|
|
|
fp1[1]/= len;
|
|
|
|
|
|
|
|
for(a=0; a<moves; a++) {
|
|
|
|
/* second vector */
|
|
|
|
fp2[0]= (float)(p2[0]-sx);
|
|
|
|
fp2[1]= (float)(p2[1]-sy);
|
|
|
|
len= sqrt(fp2[0]*fp2[0] + fp2[1]*fp2[1]);
|
|
|
|
fp2[0]/= len;
|
|
|
|
fp2[1]/= len;
|
|
|
|
|
|
|
|
/* dot and angle and cross */
|
|
|
|
dot= fp1[0]*fp2[0] + fp1[1]*fp2[1];
|
|
|
|
ang= fabs(saacos(dot));
|
|
|
|
|
|
|
|
cross= (float)((p1[1]-p2[1])*(p1[0]-sx) + (p2[0]-p1[0])*(p1[1]-sy));
|
|
|
|
|
|
|
|
if(cross<0.0) angletot-= ang;
|
|
|
|
else angletot+= ang;
|
|
|
|
|
|
|
|
/* circulate */
|
|
|
|
fp1[0]= fp2[0]; fp1[1]= fp2[1];
|
|
|
|
p1= p2;
|
|
|
|
p2= mcords[a+1];
|
|
|
|
}
|
|
|
|
|
|
|
|
if( fabs(angletot) > 4.0 ) return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* edge version for lasso select. we assume boundbox check was done */
|
|
|
|
int lasso_inside_edge(short mcords[][2], short moves, int x0, int y0, int x1, int y1)
|
|
|
|
{
|
|
|
|
short v1[2], v2[2];
|
|
|
|
int a;
|
|
|
|
|
|
|
|
if(x0==IS_CLIPPED || x1==IS_CLIPPED)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
v1[0] = x0, v1[1] = y0;
|
|
|
|
v2[0] = x1, v2[1] = y1;
|
|
|
|
|
|
|
|
/* check points in lasso */
|
|
|
|
if(lasso_inside(mcords, moves, v1[0], v1[1])) return 1;
|
|
|
|
if(lasso_inside(mcords, moves, v2[0], v2[1])) return 1;
|
|
|
|
|
|
|
|
/* no points in lasso, so we have to intersect with lasso edge */
|
|
|
|
|
|
|
|
if( IsectLL2Ds(mcords[0], mcords[moves-1], v1, v2) > 0) return 1;
|
|
|
|
for(a=0; a<moves-1; a++) {
|
|
|
|
if( IsectLL2Ds(mcords[a], mcords[a+1], v1, v2) > 0) return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* warning; lasso select with backbuffer-check draws in backbuf with persp(PERSP_WIN)
|
|
|
|
and returns with persp(PERSP_VIEW). After lasso select backbuf is not OK
|
|
|
|
*/
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_lasso_select_pose(ViewContext *vc, short mcords[][2], short moves, short select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
Object *ob= vc->obact;
|
2008-12-20 18:43:21 +00:00
|
|
|
bPoseChannel *pchan;
|
|
|
|
float vec[3];
|
|
|
|
short sco1[2], sco2[2];
|
|
|
|
|
|
|
|
if(ob->type!=OB_ARMATURE || ob->pose==NULL) return;
|
|
|
|
|
|
|
|
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
|
|
|
VECCOPY(vec, pchan->pose_head);
|
|
|
|
Mat4MulVecfl(ob->obmat, vec);
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
project_short(vc->ar, vec, sco1);
|
2008-12-20 18:43:21 +00:00
|
|
|
VECCOPY(vec, pchan->pose_tail);
|
|
|
|
Mat4MulVecfl(ob->obmat, vec);
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
project_short(vc->ar, vec, sco2);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if(lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) {
|
|
|
|
if(select) pchan->bone->flag |= BONE_SELECTED;
|
|
|
|
else pchan->bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_lasso_select_objects(ViewContext *vc, short mcords[][2], short moves, short select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
for(base= vc->scene->base.first; base; base= base->next) {
|
|
|
|
if(base->lay & vc->v3d->lay) {
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
project_short(vc->ar, base->object->obmat[3], &base->sx);
|
2008-12-20 18:43:21 +00:00
|
|
|
if(lasso_inside(mcords, moves, base->sx, base->sy)) {
|
|
|
|
|
2008-12-29 12:15:42 +00:00
|
|
|
if(select) ED_base_object_select(base, BA_SELECT);
|
|
|
|
else ED_base_object_select(base, BA_DESELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
base->object->flag= base->flag;
|
|
|
|
}
|
2009-08-16 03:24:23 +00:00
|
|
|
if(base->object->mode & OB_MODE_POSE) {
|
2008-12-30 16:03:29 +00:00
|
|
|
do_lasso_select_pose(vc, mcords, moves, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void lasso_select_boundbox(rcti *rect, short mcords[][2], short moves)
|
|
|
|
{
|
|
|
|
short a;
|
|
|
|
|
|
|
|
rect->xmin= rect->xmax= mcords[0][0];
|
|
|
|
rect->ymin= rect->ymax= mcords[0][1];
|
|
|
|
|
|
|
|
for(a=1; a<moves; a++) {
|
|
|
|
if(mcords[a][0]<rect->xmin) rect->xmin= mcords[a][0];
|
|
|
|
else if(mcords[a][0]>rect->xmax) rect->xmax= mcords[a][0];
|
|
|
|
if(mcords[a][1]<rect->ymin) rect->ymin= mcords[a][1];
|
|
|
|
else if(mcords[a][1]>rect->ymax) rect->ymax= mcords[a][1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_lasso_select_mesh__doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
|
|
|
|
eve->f = data->select?(eve->f|1):(eve->f&~1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void do_lasso_select_mesh__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (EM_check_backbuf(em_solidoffs+index)) {
|
|
|
|
if (data->pass==0) {
|
|
|
|
if ( edge_fully_inside_rect(data->rect, x0, y0, x1, y1) &&
|
|
|
|
lasso_inside(data->mcords, data->moves, x0, y0) &&
|
|
|
|
lasso_inside(data->mcords, data->moves, x1, y1)) {
|
|
|
|
EM_select_edge(eed, data->select);
|
|
|
|
data->done = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (lasso_inside_edge(data->mcords, data->moves, x0, y0, x1, y1)) {
|
|
|
|
EM_select_edge(eed, data->select);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void do_lasso_select_mesh__doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (BLI_in_rcti(data->rect, x, y) && lasso_inside(data->mcords, data->moves, x, y)) {
|
2008-12-30 16:03:29 +00:00
|
|
|
EM_select_face_fgon(data->vc.em, efa, data->select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_lasso_select_mesh(ViewContext *vc, short mcords[][2], short moves, short select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; short (*mcords)[2], moves, select, pass, done; } data;
|
2009-06-23 00:41:55 +00:00
|
|
|
ToolSettings *ts= vc->scene->toolsettings;
|
2008-12-20 18:43:21 +00:00
|
|
|
rcti rect;
|
|
|
|
int bbsel;
|
|
|
|
|
|
|
|
lasso_select_boundbox(&rect, mcords, moves);
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/* set editmesh */
|
|
|
|
vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
data.vc= *vc;
|
2008-12-20 18:43:21 +00:00
|
|
|
data.rect = ▭
|
|
|
|
data.mcords = mcords;
|
|
|
|
data.moves = moves;
|
|
|
|
data.select = select;
|
|
|
|
data.done = 0;
|
|
|
|
data.pass = 0;
|
|
|
|
|
2009-01-01 19:18:03 +00:00
|
|
|
bbsel= EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_VERTEX) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if (bbsel) {
|
2008-12-30 16:03:29 +00:00
|
|
|
EM_backbuf_checkAndSelectVerts(vc->em, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
} else {
|
2008-12-30 16:03:29 +00:00
|
|
|
mesh_foreachScreenVert(vc, do_lasso_select_mesh__doSelectVert, &data, 1);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_EDGE) {
|
2008-12-20 18:43:21 +00:00
|
|
|
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
|
|
|
|
|
|
|
|
data.pass = 0;
|
2008-12-30 16:03:29 +00:00
|
|
|
mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, 0);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (data.done==0) {
|
|
|
|
data.pass = 1;
|
2008-12-30 16:03:29 +00:00
|
|
|
mesh_foreachScreenEdge(vc, do_lasso_select_mesh__doSelectEdge, &data, 0);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_FACE) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if (bbsel) {
|
2008-12-30 16:03:29 +00:00
|
|
|
EM_backbuf_checkAndSelectFaces(vc->em, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
} else {
|
2008-12-30 16:03:29 +00:00
|
|
|
mesh_foreachScreenFace(vc, do_lasso_select_mesh__doSelectFace, &data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EM_free_backbuf();
|
2008-12-30 16:03:29 +00:00
|
|
|
EM_selectmode_flush(vc->em);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
/* this is an exception in that its the only lasso that dosnt use the 3d view (uses space image view) */
|
|
|
|
static void do_lasso_select_mesh_uv(short mcords[][2], short moves, short select)
|
|
|
|
{
|
|
|
|
EditFace *efa;
|
|
|
|
MTFace *tf;
|
|
|
|
int screenUV[2], nverts, i, ok = 1;
|
|
|
|
rcti rect;
|
|
|
|
|
|
|
|
lasso_select_boundbox(&rect, mcords, moves);
|
|
|
|
|
|
|
|
if (draw_uvs_face_check()) { /* Face Center Sel */
|
|
|
|
float cent[2];
|
|
|
|
ok = 0;
|
|
|
|
for (efa= em->faces.first; efa; efa= efa->next) {
|
|
|
|
/* assume not touched */
|
|
|
|
efa->tmp.l = 0;
|
|
|
|
tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
|
|
|
|
if ((select) != (simaFaceSel_Check(efa, tf))) {
|
|
|
|
uv_center(tf->uv, cent, (void *)efa->v4);
|
|
|
|
uvco_to_areaco_noclip(cent, screenUV);
|
|
|
|
if (BLI_in_rcti(&rect, screenUV[0], screenUV[1]) && lasso_inside(mcords, moves, screenUV[0], screenUV[1])) {
|
|
|
|
efa->tmp.l = ok = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* (de)selects all tagged faces and deals with sticky modes */
|
|
|
|
if (ok)
|
|
|
|
uvface_setsel__internal(select);
|
|
|
|
|
|
|
|
} else { /* Vert Sel*/
|
|
|
|
for (efa= em->faces.first; efa; efa= efa->next) {
|
|
|
|
tf = CustomData_em_get(&em->fdata, efa->data, CD_MTFACE);
|
|
|
|
if (simaFaceDraw_Check(efa, tf)) {
|
|
|
|
nverts= efa->v4? 4: 3;
|
|
|
|
for(i=0; i<nverts; i++) {
|
|
|
|
if ((select) != (simaUVSel_Check(efa, tf, i))) {
|
|
|
|
uvco_to_areaco_noclip(tf->uv[i], screenUV);
|
|
|
|
if (BLI_in_rcti(&rect, screenUV[0], screenUV[1]) && lasso_inside(mcords, moves, screenUV[0], screenUV[1])) {
|
|
|
|
if (select) {
|
|
|
|
simaUVSel_Set(efa, tf, i);
|
|
|
|
} else {
|
|
|
|
simaUVSel_UnSet(efa, tf, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ok && G.sima->flag & SI_SYNC_UVSEL) {
|
2008-12-30 16:03:29 +00:00
|
|
|
if (select) EM_select_flush(vc->em);
|
|
|
|
else EM_deselect_flush(vc->em);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void do_lasso_select_curve__doSelect(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
|
|
|
|
{
|
2009-09-08 07:35:07 +00:00
|
|
|
struct { ViewContext vc; short (*mcords)[2]; short moves; short select; } *data = userData;
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
if (lasso_inside(data->mcords, data->moves, x, y)) {
|
|
|
|
if (bp) {
|
|
|
|
bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
|
|
|
|
} else {
|
2009-09-08 07:35:07 +00:00
|
|
|
Curve *cu= data->vc.obedit->data;
|
|
|
|
|
|
|
|
if (cu->drawflag & CU_HIDE_HANDLES) {
|
2008-12-20 18:43:21 +00:00
|
|
|
/* can only be beztindex==0 here since handles are hidden */
|
|
|
|
bezt->f1 = bezt->f2 = bezt->f3 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
|
|
|
|
} else {
|
|
|
|
if (beztindex==0) {
|
|
|
|
bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT);
|
|
|
|
} else if (beztindex==1) {
|
|
|
|
bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
|
|
|
|
} else {
|
|
|
|
bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_lasso_select_curve(ViewContext *vc, short mcords[][2], short moves, short select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-09-08 07:35:07 +00:00
|
|
|
struct { ViewContext vc; short (*mcords)[2]; short moves; short select; } data;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/* set vc->editnurb */
|
2009-09-08 07:35:07 +00:00
|
|
|
data.vc = *vc;
|
2008-12-20 18:43:21 +00:00
|
|
|
data.mcords = mcords;
|
|
|
|
data.moves = moves;
|
|
|
|
data.select = select;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
nurbs_foreachScreenVert(vc, do_lasso_select_curve__doSelect, &data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void do_lasso_select_lattice__doSelect(void *userData, BPoint *bp, int x, int y)
|
|
|
|
{
|
|
|
|
struct { short (*mcords)[2]; short moves; short select; } *data = userData;
|
|
|
|
|
|
|
|
if (lasso_inside(data->mcords, data->moves, x, y)) {
|
|
|
|
bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
|
|
|
|
}
|
|
|
|
}
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_lasso_select_lattice(ViewContext *vc, short mcords[][2], short moves, short select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
struct { short (*mcords)[2]; short moves; short select; } data;
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/* set editdata in vc */
|
2008-12-20 18:43:21 +00:00
|
|
|
data.mcords = mcords;
|
|
|
|
data.moves = moves;
|
|
|
|
data.select = select;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
lattice_foreachScreenVert(vc, do_lasso_select_lattice__doSelect, &data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_lasso_select_armature(ViewContext *vc, short mcords[][2], short moves, short select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-04 14:14:06 +00:00
|
|
|
bArmature *arm= vc->obedit->data;
|
2008-12-20 18:43:21 +00:00
|
|
|
EditBone *ebone;
|
|
|
|
float vec[3];
|
|
|
|
short sco1[2], sco2[2], didpoint;
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/* set editdata in vc */
|
|
|
|
|
2009-01-04 14:14:06 +00:00
|
|
|
for (ebone= arm->edbo->first; ebone; ebone=ebone->next) {
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
VECCOPY(vec, ebone->head);
|
2009-01-02 19:10:35 +00:00
|
|
|
Mat4MulVecfl(vc->obedit->obmat, vec);
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
project_short(vc->ar, vec, sco1);
|
2008-12-20 18:43:21 +00:00
|
|
|
VECCOPY(vec, ebone->tail);
|
2009-01-02 19:10:35 +00:00
|
|
|
Mat4MulVecfl(vc->obedit->obmat, vec);
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
project_short(vc->ar, vec, sco2);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
didpoint= 0;
|
|
|
|
if(lasso_inside(mcords, moves, sco1[0], sco1[1])) {
|
|
|
|
if(select) ebone->flag |= BONE_ROOTSEL;
|
|
|
|
else ebone->flag &= ~BONE_ROOTSEL;
|
|
|
|
didpoint= 1;
|
|
|
|
}
|
|
|
|
if(lasso_inside(mcords, moves, sco2[0], sco2[1])) {
|
|
|
|
if(select) ebone->flag |= BONE_TIPSEL;
|
|
|
|
else ebone->flag &= ~BONE_TIPSEL;
|
|
|
|
didpoint= 1;
|
|
|
|
}
|
|
|
|
/* if one of points selected, we skip the bone itself */
|
|
|
|
if(didpoint==0 && lasso_inside_edge(mcords, moves, sco1[0], sco1[1], sco2[0], sco2[1])) {
|
|
|
|
if(select) ebone->flag |= BONE_TIPSEL|BONE_ROOTSEL|BONE_SELECTED;
|
|
|
|
else ebone->flag &= ~(BONE_ACTIVE|BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_lasso_select_facemode(ViewContext *vc, short mcords[][2], short moves, short select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
Object *ob= vc->obact;
|
2008-12-20 18:43:21 +00:00
|
|
|
Mesh *me= ob?ob->data:NULL;
|
|
|
|
rcti rect;
|
|
|
|
|
|
|
|
if(me==NULL || me->mtface==NULL) return;
|
|
|
|
if(me->totface==0) return;
|
|
|
|
|
|
|
|
em_vertoffs= me->totface+1; /* max index array */
|
|
|
|
|
|
|
|
lasso_select_boundbox(&rect, mcords, moves);
|
2009-01-01 19:18:03 +00:00
|
|
|
EM_mask_init_backbuf_border(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
EM_backbuf_checkAndSelectTFaces(me, select);
|
|
|
|
|
|
|
|
EM_free_backbuf();
|
|
|
|
|
|
|
|
// XXX object_tface_flags_changed(ob, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
static void do_lasso_select_node(short mcords[][2], short moves, short select)
|
|
|
|
{
|
|
|
|
SpaceNode *snode = sa->spacedata.first;
|
|
|
|
|
|
|
|
bNode *node;
|
|
|
|
rcti rect;
|
|
|
|
short node_cent[2];
|
|
|
|
float node_centf[2];
|
|
|
|
|
|
|
|
lasso_select_boundbox(&rect, mcords, moves);
|
|
|
|
|
|
|
|
/* store selection in temp test flag */
|
|
|
|
for(node= snode->edittree->nodes.first; node; node= node->next) {
|
|
|
|
|
|
|
|
node_centf[0] = (node->totr.xmin+node->totr.xmax)/2;
|
|
|
|
node_centf[1] = (node->totr.ymin+node->totr.ymax)/2;
|
|
|
|
|
|
|
|
ipoco_to_areaco_noclip(G.v2d, node_centf, node_cent);
|
|
|
|
if (BLI_in_rcti(&rect, node_cent[0], node_cent[1]) && lasso_inside(mcords, moves, node_cent[0], node_cent[1])) {
|
|
|
|
if (select) {
|
|
|
|
node->flag |= SELECT;
|
|
|
|
} else {
|
|
|
|
node->flag &= ~SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BIF_undo_push("Lasso select nodes");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-02-25 19:29:58 +00:00
|
|
|
void view3d_lasso_select(bContext *C, ViewContext *vc, short mcords[][2], short moves, short select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-08-15 20:36:15 +00:00
|
|
|
Object *ob = CTX_data_active_object(C);
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(vc->obedit==NULL) {
|
2009-08-15 20:36:15 +00:00
|
|
|
if(paint_facesel_test(ob))
|
2008-12-30 16:03:29 +00:00
|
|
|
do_lasso_select_facemode(vc, mcords, moves, select);
|
2009-08-16 01:25:53 +00:00
|
|
|
else if(ob && ob->mode & (OB_MODE_VERTEX_PAINT|OB_MODE_WEIGHT_PAINT|OB_MODE_TEXTURE_PAINT))
|
2008-12-20 18:43:21 +00:00
|
|
|
;
|
2009-08-16 02:35:44 +00:00
|
|
|
else if(ob && ob->mode & OB_MODE_PARTICLE_EDIT)
|
2009-02-25 19:29:58 +00:00
|
|
|
PE_lasso_select(C, mcords, moves, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
else
|
2008-12-30 16:03:29 +00:00
|
|
|
do_lasso_select_objects(vc, mcords, moves, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(vc->obedit->type==OB_MESH) {
|
2008-12-30 16:03:29 +00:00
|
|
|
do_lasso_select_mesh(vc, mcords, moves, select);
|
2009-01-02 19:10:35 +00:00
|
|
|
} else if(vc->obedit->type==OB_CURVE || vc->obedit->type==OB_SURF)
|
2008-12-30 16:03:29 +00:00
|
|
|
do_lasso_select_curve(vc, mcords, moves, select);
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(vc->obedit->type==OB_LATTICE)
|
2008-12-30 16:03:29 +00:00
|
|
|
do_lasso_select_lattice(vc, mcords, moves, select);
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(vc->obedit->type==OB_ARMATURE)
|
2008-12-30 16:03:29 +00:00
|
|
|
do_lasso_select_armature(vc, mcords, moves, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
BIF_undo_push("Lasso select");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
|
|
|
|
/* lasso operator gives properties, but since old code works
|
|
|
|
with short array we convert */
|
|
|
|
static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
|
|
|
ViewContext vc;
|
|
|
|
int select, i= 0;
|
|
|
|
short mcords[1024][2];
|
|
|
|
|
|
|
|
RNA_BEGIN(op->ptr, itemptr, "path") {
|
|
|
|
float loc[2];
|
|
|
|
|
|
|
|
RNA_float_get_array(&itemptr, "loc", loc);
|
|
|
|
mcords[i][0]= (short)loc[0];
|
|
|
|
mcords[i][1]= (short)loc[1];
|
|
|
|
i++;
|
|
|
|
if(i>=1024) break;
|
|
|
|
}
|
|
|
|
RNA_END;
|
|
|
|
|
2.5
- Edit mesh: Add ctrl+click add vertex or extrude.
I've made it not move the 3d cursor in that case.
Also found out tweak events conflicted with existing
keymap definitions; on tweak failure (= no mousemove)
it now passes on the mouse event as 'mouse down' for
the remaining keymaps to check.
These then actually respond to mouse-up instead of down...
The location in the keymaps where tweaks get generated
remains important. Examples:
1 - 'select' mouse-handler, operator return pass-through
2 - tweak handler checks, and makes tweak event
3 - grabber responds to tweak event
1 - ctrl+mouse tweak handler checks, makes tweak event,
or passes event on
2 - if tweak event, it runs lasso
3 - else when passed on, ctrl+click extrude happens
In the first case, select works on mouse-down, immediate.
In the second case, extrude happens on mouse-release, even
though the keymap defined mouse-press.
This will make designing nice balanced keymaps still not
simple; especially because you can't tell operators to
pass on the key... although we can add the convention that
select-mouse operators always pass on to enable tweaks.
Still a good reason to wait with custom keymaps
when this is fully settled!
2009-01-30 18:18:41 +00:00
|
|
|
if(i>1) {
|
2.5
Sanitized the 'tweak' event.
Original idea was to have WM event system generating it
automatically. However, I first tested it via a handler
and operator, to check what kind of configurations would
be useful. It appeared to not work nice, also because
that inserting a tweak operator in a keymap is confusing.
Now 'tweaks' are generated automatically, and can be
catched by keymaps as any event. The current definition
of tweak is:
- if Left/Middle/Rightmouse pressed
if event wasn't handled by window queue (modal handlers)
start checking mousepositions
- while mousepositions are checked
- escape on any event other than mouse
- on mouse events:
- add tweak event if mousemove > 10 pixels
- stop checking for tweak if mousebutton released
- Tweak events have a define indicating mousebutton used
EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R
- In keymap definitions you can use _S or _A to map to
action or select mouse userdef.
- Event value in keymap should be KM_ANY for all tweaks,
or use one of the eight directions:
EVT_GESTURE_E, _SE, _S, _SW, _W, _NW, _N, _NE
- And of course you can add modifier checks in keymaps for it.
- Because tweaks are a result of mouse events, the handlers get
both to evaluate. That means that RMB-select + tweak will work
correctly.
In case you don't want both to be handled, for example the
CTRL+LMB 'extrude' and CTRL+LMB-tweak 'lasso select', you will
need to set the first acting on a EVT_RELEASE, this event only
gets passed on when tweak fails.
The current system allows all options, configurable, we had in 2.48,
and many more! A diagram of what's possible is on the todo. :)
Also in this commit: lasso select editmesh failed with 'zbuffer
occluded select'. Also circle-select failed.
2009-02-02 14:13:14 +00:00
|
|
|
view3d_operator_needs_opengl(C);
|
|
|
|
|
2.5
- Edit mesh: Add ctrl+click add vertex or extrude.
I've made it not move the 3d cursor in that case.
Also found out tweak events conflicted with existing
keymap definitions; on tweak failure (= no mousemove)
it now passes on the mouse event as 'mouse down' for
the remaining keymaps to check.
These then actually respond to mouse-up instead of down...
The location in the keymaps where tweaks get generated
remains important. Examples:
1 - 'select' mouse-handler, operator return pass-through
2 - tweak handler checks, and makes tweak event
3 - grabber responds to tweak event
1 - ctrl+mouse tweak handler checks, makes tweak event,
or passes event on
2 - if tweak event, it runs lasso
3 - else when passed on, ctrl+click extrude happens
In the first case, select works on mouse-down, immediate.
In the second case, extrude happens on mouse-release, even
though the keymap defined mouse-press.
This will make designing nice balanced keymaps still not
simple; especially because you can't tell operators to
pass on the key... although we can add the convention that
select-mouse operators always pass on to enable tweaks.
Still a good reason to wait with custom keymaps
when this is fully settled!
2009-01-30 18:18:41 +00:00
|
|
|
/* setup view context for argument to callbacks */
|
|
|
|
view3d_set_viewcontext(C, &vc);
|
|
|
|
|
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
|
|
|
select= !RNA_boolean_get(op->ptr, "deselect");
|
2009-02-25 19:29:58 +00:00
|
|
|
view3d_lasso_select(C, &vc, mcords, i, select);
|
2.5
- Edit mesh: Add ctrl+click add vertex or extrude.
I've made it not move the 3d cursor in that case.
Also found out tweak events conflicted with existing
keymap definitions; on tweak failure (= no mousemove)
it now passes on the mouse event as 'mouse down' for
the remaining keymaps to check.
These then actually respond to mouse-up instead of down...
The location in the keymaps where tweaks get generated
remains important. Examples:
1 - 'select' mouse-handler, operator return pass-through
2 - tweak handler checks, and makes tweak event
3 - grabber responds to tweak event
1 - ctrl+mouse tweak handler checks, makes tweak event,
or passes event on
2 - if tweak event, it runs lasso
3 - else when passed on, ctrl+click extrude happens
In the first case, select works on mouse-down, immediate.
In the second case, extrude happens on mouse-release, even
though the keymap defined mouse-press.
This will make designing nice balanced keymaps still not
simple; especially because you can't tell operators to
pass on the key... although we can add the convention that
select-mouse operators always pass on to enable tweaks.
Still a good reason to wait with custom keymaps
when this is fully settled!
2009-01-30 18:18:41 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
return OPERATOR_PASS_THROUGH;
|
2009-01-02 14:11:18 +00:00
|
|
|
}
|
|
|
|
|
2009-03-29 02:15:13 +00:00
|
|
|
void VIEW3D_OT_select_lasso(wmOperatorType *ot)
|
2009-01-02 14:11:18 +00:00
|
|
|
{
|
|
|
|
ot->name= "Lasso Select";
|
2009-09-07 04:52:42 +00:00
|
|
|
ot->description= "Select items using lasso selection.";
|
2009-03-29 02:15:13 +00:00
|
|
|
ot->idname= "VIEW3D_OT_select_lasso";
|
2009-01-02 14:11:18 +00:00
|
|
|
|
|
|
|
ot->invoke= WM_gesture_lasso_invoke;
|
|
|
|
ot->modal= WM_gesture_lasso_modal;
|
|
|
|
ot->exec= view3d_lasso_select_exec;
|
|
|
|
ot->poll= WM_operator_winactive;
|
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
2.5
Summary of ain features:
- Themes and Styles are now editable.
- CTRL+U "Save user defaults" now goes to new .B25.blend, so you
can use 2.4x and 2.5x next to each other. If B25 doesn't exist, it
reads the regular .B.blend
- Press Tkey in 3d window for (unfinished) toolbar WIP. It now only
shows the last operator, if appropriate.
Nkey properties moved to the other side.
A lot of work was done on removing old themes for good and properly
getting it work with the 2.5 region system. Here's some notes;
- Buttons now all have a complete set of colors, based on button classifications
(See outliner -> user prefs -> Interface
- Theme colors have been extended with basic colors for region types.
Currently colors are defined for Window, Header, List/Channels and
for Button/Tool views.
The screen manager handles this btw, so a TH_BACK will always pick the
right backdrop color.
- Menu backdrops are in in Button theme colors. Floating Panels will be in
the per-space type Themes.
- Styles were added in RNA too, but only for the font settings now.
Only Panel font, widget font and widget-label work now. The 'group label'
will be for templates mostly.
Style settings will be expanded with spacing defaults, label conventions,
etc.
- Label text colors are stored in per-space Theme too, to make sure they fit.
Same goes for Panel title color.
Note that 'shadow' for fonts can conflict with text colors; shadow color is
currently stored in Style... shadow code needs a bit of work still.
2009-04-27 13:44:11 +00:00
|
|
|
ot->flag= OPTYPE_UNDO;
|
2009-01-31 19:40:40 +00:00
|
|
|
|
2009-01-16 23:53:11 +00:00
|
|
|
RNA_def_collection_runtime(ot->srna, "path", &RNA_OperatorMousePath, "Path", "");
|
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
|
|
|
RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "Deselect rather than select items.");
|
2009-01-02 14:11:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ************************************************* */
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
#if 0
|
|
|
|
/* smart function to sample a rect spiralling outside, nice for backbuf selection */
|
|
|
|
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;
|
|
|
|
unsigned int retval=0;
|
|
|
|
|
|
|
|
base= LASTBASE;
|
|
|
|
if(base==0) return 0;
|
|
|
|
maxob= base->selcol;
|
|
|
|
|
|
|
|
aantal= (size-1)/2;
|
|
|
|
rc= 0;
|
|
|
|
|
|
|
|
dirvec[0][0]= 1;
|
|
|
|
dirvec[0][1]= 0;
|
|
|
|
dirvec[1][0]= 0;
|
|
|
|
dirvec[1][1]= -size;
|
|
|
|
dirvec[2][0]= -1;
|
|
|
|
dirvec[2][1]= 0;
|
|
|
|
dirvec[3][0]= 0;
|
|
|
|
dirvec[3][1]= size;
|
|
|
|
|
|
|
|
bufmin= buf;
|
|
|
|
bufmax= buf+ size*size;
|
|
|
|
buf+= aantal*size+ aantal;
|
|
|
|
|
|
|
|
for(tel=1;tel<=size;tel++) {
|
|
|
|
|
|
|
|
for(a=0;a<2;a++) {
|
|
|
|
for(b=0;b<tel;b++) {
|
|
|
|
|
|
|
|
if(*buf && *buf<=maxob && *buf!=dontdo) return *buf;
|
|
|
|
if( *buf==dontdo ) retval= dontdo; /* if only color dontdo is available, still return dontdo */
|
|
|
|
|
|
|
|
buf+= (dirvec[rc][0]+dirvec[rc][1]);
|
|
|
|
|
|
|
|
if(buf<bufmin || buf>=bufmax) return retval;
|
|
|
|
}
|
|
|
|
rc++;
|
|
|
|
rc &= 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* ************************** mouse select ************************* */
|
|
|
|
|
|
|
|
|
|
|
|
/* The max number of menu items in an object select menu */
|
|
|
|
#define SEL_MENU_SIZE 22
|
|
|
|
|
|
|
|
static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */
|
|
|
|
{
|
|
|
|
Base *base;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if (base->flag & SELECT) {
|
|
|
|
if(b!=base) {
|
2008-12-29 12:15:42 +00:00
|
|
|
ED_base_object_select(base, BA_DESELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-09-16 01:15:30 +00:00
|
|
|
static Base *mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, short *mval, short extend)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
short baseCount = 0;
|
2009-09-16 01:15:30 +00:00
|
|
|
short ok;
|
|
|
|
LinkNode *linklist= NULL;
|
|
|
|
|
|
|
|
CTX_DATA_BEGIN(C, Base*, base, selectable_bases) {
|
|
|
|
ok= FALSE;
|
|
|
|
|
|
|
|
/* two selection methods, the CTRL select uses max dist of 15 */
|
|
|
|
if(buffer) {
|
|
|
|
int a;
|
|
|
|
for(a=0; a<hits; a++) {
|
|
|
|
/* index was converted */
|
|
|
|
if(base->selcol==buffer[ (4 * a) + 3 ])
|
|
|
|
ok= TRUE;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-09-16 01:15:30 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
int temp, dist=15;
|
|
|
|
|
|
|
|
project_short(vc->ar, base->object->obmat[3], &base->sx);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-09-16 01:15:30 +00:00
|
|
|
temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]);
|
|
|
|
if(temp < dist)
|
|
|
|
ok= TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(ok) {
|
|
|
|
baseCount++;
|
|
|
|
BLI_linklist_prepend(&linklist, base);
|
|
|
|
|
|
|
|
if (baseCount==SEL_MENU_SIZE)
|
|
|
|
break;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2009-09-16 01:15:30 +00:00
|
|
|
CTX_DATA_END;
|
|
|
|
|
|
|
|
if(baseCount)
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-09-16 01:15:30 +00:00
|
|
|
if(baseCount==0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if(baseCount == 1) {
|
|
|
|
Base *base= (Base *)linklist->link;
|
|
|
|
BLI_linklist_free(linklist, NULL);
|
|
|
|
return base;
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
else {
|
2009-09-16 01:15:30 +00:00
|
|
|
/* UI */
|
|
|
|
uiPopupMenu *pup= uiPupMenuBegin(C, "Select Object", 0);
|
|
|
|
uiLayout *layout= uiPupMenuLayout(pup);
|
|
|
|
uiLayout *split= uiLayoutSplit(layout, 0);
|
|
|
|
uiLayout *column= uiLayoutColumn(split, 0);
|
|
|
|
LinkNode *node;
|
|
|
|
|
|
|
|
node= linklist;
|
|
|
|
while(node) {
|
|
|
|
Base *base=node->link;
|
|
|
|
Object *ob= base->object;
|
|
|
|
char *name= ob->id.name+2;
|
|
|
|
/* annoying!, since we need to set 2 props cant use this. */
|
|
|
|
/* uiItemStringO(column, name, 0, "OBJECT_OT_select_name", "name", name); */
|
|
|
|
|
|
|
|
{
|
|
|
|
PointerRNA ptr;
|
|
|
|
|
|
|
|
WM_operator_properties_create(&ptr, "OBJECT_OT_select_name");
|
|
|
|
RNA_string_set(&ptr, "name", name);
|
|
|
|
RNA_boolean_set(&ptr, "extend", extend);
|
|
|
|
uiItemFullO(column, name, uiIconFromID((ID *)ob), "OBJECT_OT_select_name", ptr.data, WM_OP_EXEC_DEFAULT, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
node= node->next;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-09-16 01:15:30 +00:00
|
|
|
|
|
|
|
uiPupMenuEnd(C, pup);
|
|
|
|
|
|
|
|
BLI_linklist_free(linklist, NULL);
|
|
|
|
return NULL;
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we want a select buffer with bones, if there are... */
|
|
|
|
/* so check three selection levels and compare */
|
2008-12-30 16:03:29 +00:00
|
|
|
static short mixed_bones_object_selectbuffer(ViewContext *vc, unsigned int *buffer, short *mval)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
rcti rect;
|
|
|
|
int offs;
|
|
|
|
short a, hits15, hits9=0, hits5=0;
|
|
|
|
short has_bones15=0, has_bones9=0, has_bones5=0;
|
|
|
|
|
|
|
|
BLI_init_rcti(&rect, mval[0]-14, mval[0]+14, mval[1]-14, mval[1]+14);
|
2008-12-30 16:03:29 +00:00
|
|
|
hits15= view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect);
|
2008-12-20 18:43:21 +00:00
|
|
|
if(hits15>0) {
|
|
|
|
for(a=0; a<hits15; a++) if(buffer[4*a+3] & 0xFFFF0000) has_bones15= 1;
|
|
|
|
|
|
|
|
offs= 4*hits15;
|
|
|
|
BLI_init_rcti(&rect, mval[0]-9, mval[0]+9, mval[1]-9, mval[1]+9);
|
2008-12-30 16:03:29 +00:00
|
|
|
hits9= view3d_opengl_select(vc, buffer+offs, MAXPICKBUF-offs, &rect);
|
2008-12-20 18:43:21 +00:00
|
|
|
if(hits9>0) {
|
|
|
|
for(a=0; a<hits9; a++) if(buffer[offs+4*a+3] & 0xFFFF0000) has_bones9= 1;
|
|
|
|
|
|
|
|
offs+= 4*hits9;
|
|
|
|
BLI_init_rcti(&rect, mval[0]-5, mval[0]+5, mval[1]-5, mval[1]+5);
|
2008-12-30 16:03:29 +00:00
|
|
|
hits5= view3d_opengl_select(vc, buffer+offs, MAXPICKBUF-offs, &rect);
|
2008-12-20 18:43:21 +00:00
|
|
|
if(hits5>0) {
|
|
|
|
for(a=0; a<hits5; a++) if(buffer[offs+4*a+3] & 0xFFFF0000) has_bones5= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(has_bones5) {
|
|
|
|
offs= 4*hits15 + 4*hits9;
|
|
|
|
memcpy(buffer, buffer+offs, 4*offs);
|
|
|
|
return hits5;
|
|
|
|
}
|
|
|
|
if(has_bones9) {
|
|
|
|
offs= 4*hits15;
|
|
|
|
memcpy(buffer, buffer+offs, 4*offs);
|
|
|
|
return hits9;
|
|
|
|
}
|
|
|
|
if(has_bones15) {
|
|
|
|
return hits15;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(hits5>0) {
|
|
|
|
offs= 4*hits15 + 4*hits9;
|
|
|
|
memcpy(buffer, buffer+offs, 4*offs);
|
|
|
|
return hits5;
|
|
|
|
}
|
|
|
|
if(hits9>0) {
|
|
|
|
offs= 4*hits15;
|
|
|
|
memcpy(buffer, buffer+offs, 4*offs);
|
|
|
|
return hits9;
|
|
|
|
}
|
|
|
|
return hits15;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-12-31 17:50:00 +00:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* mval is region coords */
|
2009-09-16 01:15:30 +00:00
|
|
|
static void mouse_select(bContext *C, short *mval, short extend, short obcenter, short enumerate)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
ViewContext vc;
|
2008-12-29 12:15:42 +00:00
|
|
|
ARegion *ar= CTX_wm_region(C);
|
2009-01-17 18:35:33 +00:00
|
|
|
View3D *v3d= CTX_wm_view3d(C);
|
2008-12-29 12:15:42 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2008-12-20 18:43:21 +00:00
|
|
|
Base *base, *startbase=NULL, *basact=NULL, *oldbasact=NULL;
|
|
|
|
int temp, a, dist=100;
|
|
|
|
short hits;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
/* setup view context for argument to callbacks */
|
2009-01-02 14:11:18 +00:00
|
|
|
view3d_set_viewcontext(C, &vc);
|
2008-12-30 16:03:29 +00:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* always start list from basact in wire mode */
|
|
|
|
startbase= FIRSTBASE;
|
|
|
|
if(BASACT && BASACT->next) startbase= BASACT->next;
|
|
|
|
|
|
|
|
/* This block uses the control key to make the object selected by its center point rather then its contents */
|
2008-12-31 17:50:00 +00:00
|
|
|
/* XXX later on, in editmode do not activate */
|
2009-01-02 19:10:35 +00:00
|
|
|
if(vc.obedit==NULL && obcenter) {
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
/* note; shift+alt goes to group-flush-selecting */
|
2009-09-16 01:15:30 +00:00
|
|
|
if(enumerate) {
|
|
|
|
basact= mouse_select_menu(C, &vc, NULL, 0, mval, extend);
|
|
|
|
} else {
|
2008-12-20 18:43:21 +00:00
|
|
|
base= startbase;
|
|
|
|
while(base) {
|
|
|
|
if (BASE_SELECTABLE(v3d, base)) {
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
project_short(ar, base->object->obmat[3], &base->sx);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
temp= abs(base->sx -mval[0]) + abs(base->sy -mval[1]);
|
|
|
|
if(base==BASACT) temp+=10;
|
|
|
|
if(temp<dist ) {
|
|
|
|
|
|
|
|
dist= temp;
|
|
|
|
basact= base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
base= base->next;
|
|
|
|
|
|
|
|
if(base==0) base= FIRSTBASE;
|
|
|
|
if(base==startbase) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2009-09-16 01:15:30 +00:00
|
|
|
unsigned int buffer[4*MAXPICKBUF];
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* if objects have posemode set, the bones are in the same selection buffer */
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
hits= mixed_bones_object_selectbuffer(&vc, buffer, mval);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if(hits>0) {
|
|
|
|
int has_bones= 0;
|
|
|
|
|
|
|
|
for(a=0; a<hits; a++) if(buffer[4*a+3] & 0xFFFF0000) has_bones= 1;
|
|
|
|
|
|
|
|
/* note; shift+alt goes to group-flush-selecting */
|
2009-09-16 01:15:30 +00:00
|
|
|
if(has_bones==0 && enumerate) {
|
|
|
|
basact= mouse_select_menu(C, &vc, buffer, hits, mval, extend);
|
|
|
|
} else {
|
2008-12-20 18:43:21 +00:00
|
|
|
static short lastmval[2]={-100, -100};
|
|
|
|
int donearest= 0;
|
|
|
|
|
|
|
|
/* define if we use solid nearest select or not */
|
|
|
|
if(v3d->drawtype>OB_WIRE) {
|
|
|
|
donearest= 1;
|
|
|
|
if( ABS(mval[0]-lastmval[0])<3 && ABS(mval[1]-lastmval[1])<3) {
|
|
|
|
if(!has_bones) /* hrms, if theres bones we always do nearest */
|
|
|
|
donearest= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lastmval[0]= mval[0]; lastmval[1]= mval[1];
|
|
|
|
|
|
|
|
if(donearest) {
|
|
|
|
unsigned int min= 0xFFFFFFFF;
|
|
|
|
int selcol= 0, notcol=0;
|
|
|
|
|
|
|
|
|
|
|
|
if(has_bones) {
|
|
|
|
/* we skip non-bone hits */
|
|
|
|
for(a=0; a<hits; a++) {
|
|
|
|
if( min > buffer[4*a+1] && (buffer[4*a+3] & 0xFFFF0000) ) {
|
|
|
|
min= buffer[4*a+1];
|
|
|
|
selcol= buffer[4*a+3] & 0xFFFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* only exclude active object when it is selected... */
|
|
|
|
if(BASACT && (BASACT->flag & SELECT) && hits>1) notcol= BASACT->selcol;
|
|
|
|
|
|
|
|
for(a=0; a<hits; a++) {
|
|
|
|
if( min > buffer[4*a+1] && notcol!=(buffer[4*a+3] & 0xFFFF)) {
|
|
|
|
min= buffer[4*a+1];
|
|
|
|
selcol= buffer[4*a+3] & 0xFFFF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
base= FIRSTBASE;
|
|
|
|
while(base) {
|
|
|
|
if(base->lay & v3d->lay) {
|
|
|
|
if(base->selcol==selcol) break;
|
|
|
|
}
|
|
|
|
base= base->next;
|
|
|
|
}
|
|
|
|
if(base) basact= base;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
base= startbase;
|
|
|
|
while(base) {
|
|
|
|
/* skip objects with select restriction, to prevent prematurely ending this loop
|
|
|
|
* with an un-selectable choice */
|
|
|
|
if (base->object->restrictflag & OB_RESTRICT_SELECT) {
|
|
|
|
base=base->next;
|
|
|
|
if(base==NULL) base= FIRSTBASE;
|
|
|
|
if(base==startbase) break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(base->lay & v3d->lay) {
|
|
|
|
for(a=0; a<hits; a++) {
|
|
|
|
if(has_bones) {
|
|
|
|
/* skip non-bone objects */
|
|
|
|
if((buffer[4*a+3] & 0xFFFF0000)) {
|
|
|
|
if(base->selcol== (buffer[(4*a)+3] & 0xFFFF))
|
|
|
|
basact= base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(base->selcol== (buffer[(4*a)+3] & 0xFFFF))
|
|
|
|
basact= base;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(basact) break;
|
|
|
|
|
|
|
|
base= base->next;
|
|
|
|
if(base==NULL) base= FIRSTBASE;
|
|
|
|
if(base==startbase) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(has_bones && basact) {
|
2009-01-05 19:32:04 +00:00
|
|
|
if(ED_do_pose_selectbuffer(scene, basact, buffer, hits, extend) ) { /* then bone is found */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
/* we make the armature selected:
|
|
|
|
not-selected active object in posemode won't work well for tools */
|
|
|
|
basact->flag|= SELECT;
|
|
|
|
basact->object->flag= basact->flag;
|
|
|
|
|
2009-01-10 14:19:14 +00:00
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, basact->object);
|
|
|
|
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_ACTIVE, basact->object);
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* in weightpaint, we use selected bone to select vertexgroup, so no switch to new active object */
|
2009-08-15 21:46:25 +00:00
|
|
|
if(basact->object->mode & OB_MODE_WEIGHT_PAINT) {
|
2008-12-20 18:43:21 +00:00
|
|
|
/* prevent activating */
|
|
|
|
basact= NULL;
|
|
|
|
}
|
2008-12-29 12:15:42 +00:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
/* prevent bone selecting to pass on to object selecting */
|
|
|
|
if(basact==BASACT)
|
|
|
|
basact= NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* so, do we have something selected? */
|
|
|
|
if(basact) {
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(vc.obedit) {
|
2008-12-20 18:43:21 +00:00
|
|
|
/* only do select */
|
|
|
|
deselectall_except(scene, basact);
|
2008-12-29 12:15:42 +00:00
|
|
|
ED_base_object_select(basact, BA_SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
/* also prevent making it active on mouse selection */
|
|
|
|
else if (BASE_SELECTABLE(v3d, basact)) {
|
|
|
|
|
|
|
|
oldbasact= BASACT;
|
|
|
|
|
2008-12-31 17:50:00 +00:00
|
|
|
if(!extend) {
|
2008-12-20 18:43:21 +00:00
|
|
|
deselectall_except(scene, basact);
|
2008-12-29 12:15:42 +00:00
|
|
|
ED_base_object_select(basact, BA_SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2008-12-31 17:50:00 +00:00
|
|
|
else if(0) {
|
2008-12-20 18:43:21 +00:00
|
|
|
// XXX select_all_from_groups(basact);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(basact->flag & SELECT) {
|
|
|
|
if(basact==oldbasact)
|
2008-12-29 12:15:42 +00:00
|
|
|
ED_base_object_select(basact, BA_DESELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2008-12-29 12:15:42 +00:00
|
|
|
else ED_base_object_select(basact, BA_SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(oldbasact != basact) {
|
2008-12-29 12:15:42 +00:00
|
|
|
ED_base_object_activate(C, basact); /* adds notifier */
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2008-12-29 12:15:42 +00:00
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ******************** border and circle ************************************** */
|
|
|
|
|
|
|
|
|
|
|
|
int edge_inside_circle(short centx, short centy, short rad, short x1, short y1, short x2, short y2)
|
|
|
|
{
|
|
|
|
int radsq= rad*rad;
|
|
|
|
float v1[2], v2[2], v3[2];
|
|
|
|
|
|
|
|
/* check points in circle itself */
|
|
|
|
if( (x1-centx)*(x1-centx) + (y1-centy)*(y1-centy) <= radsq ) return 1;
|
|
|
|
if( (x2-centx)*(x2-centx) + (y2-centy)*(y2-centy) <= radsq ) return 1;
|
|
|
|
|
|
|
|
/* pointdistline */
|
|
|
|
v3[0]= centx;
|
|
|
|
v3[1]= centy;
|
|
|
|
v1[0]= x1;
|
|
|
|
v1[1]= y1;
|
|
|
|
v2[0]= x2;
|
|
|
|
v2[1]= y2;
|
|
|
|
|
|
|
|
if( PdistVL2Dfl(v3, v1, v2) < (float)rad ) return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_nurbs_box_select__doSelect(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; int select; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (BLI_in_rcti(data->rect, x, y)) {
|
|
|
|
if (bp) {
|
|
|
|
bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
|
|
|
|
} else {
|
2009-09-08 07:35:07 +00:00
|
|
|
Curve *cu= data->vc.obedit->data;
|
|
|
|
|
|
|
|
if (cu->drawflag & CU_HIDE_HANDLES) {
|
2008-12-20 18:43:21 +00:00
|
|
|
/* can only be beztindex==0 here since handles are hidden */
|
|
|
|
bezt->f1 = bezt->f2 = bezt->f3 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
|
|
|
|
} else {
|
|
|
|
if (beztindex==0) {
|
|
|
|
bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT);
|
|
|
|
} else if (beztindex==1) {
|
|
|
|
bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
|
|
|
|
} else {
|
|
|
|
bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_nurbs_box_select(ViewContext *vc, rcti *rect, int select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; int select; } data;
|
|
|
|
|
2009-09-08 07:35:07 +00:00
|
|
|
data.vc = *vc;
|
2008-12-20 18:43:21 +00:00
|
|
|
data.rect = rect;
|
|
|
|
data.select = select;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
nurbs_foreachScreenVert(vc, do_nurbs_box_select__doSelect, &data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void do_lattice_box_select__doSelect(void *userData, BPoint *bp, int x, int y)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; int select; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (BLI_in_rcti(data->rect, x, y)) {
|
|
|
|
bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
|
|
|
|
}
|
|
|
|
}
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_lattice_box_select(ViewContext *vc, rcti *rect, int select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; int select, pass, done; } data;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
data.vc= *vc;
|
2008-12-20 18:43:21 +00:00
|
|
|
data.rect = rect;
|
|
|
|
data.select = select;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
lattice_foreachScreenVert(vc, do_lattice_box_select__doSelect, &data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void do_mesh_box_select__doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (BLI_in_rcti(data->rect, x, y)) {
|
|
|
|
eve->f = data->select?(eve->f|1):(eve->f&~1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void do_mesh_box_select__doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if(EM_check_backbuf(em_solidoffs+index)) {
|
|
|
|
if (data->pass==0) {
|
|
|
|
if (edge_fully_inside_rect(data->rect, x0, y0, x1, y1)) {
|
|
|
|
EM_select_edge(eed, data->select);
|
|
|
|
data->done = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (edge_inside_rect(data->rect, x0, y0, x1, y1)) {
|
|
|
|
EM_select_edge(eed, data->select);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static void do_mesh_box_select__doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; short select, pass, done; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (BLI_in_rcti(data->rect, x, y)) {
|
2008-12-30 16:03:29 +00:00
|
|
|
EM_select_face_fgon(data->vc.em, efa, data->select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2008-12-30 16:03:29 +00:00
|
|
|
static void do_mesh_box_select(ViewContext *vc, rcti *rect, int select)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
struct { ViewContext vc; rcti *rect; short select, pass, done; } data;
|
2009-06-23 00:41:55 +00:00
|
|
|
ToolSettings *ts= vc->scene->toolsettings;
|
2008-12-20 18:43:21 +00:00
|
|
|
int bbsel;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
data.vc= *vc;
|
2008-12-20 18:43:21 +00:00
|
|
|
data.rect = rect;
|
|
|
|
data.select = select;
|
|
|
|
data.pass = 0;
|
|
|
|
data.done = 0;
|
|
|
|
|
2009-01-01 19:18:03 +00:00
|
|
|
bbsel= EM_init_backbuf_border(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_VERTEX) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if (bbsel) {
|
2008-12-30 16:03:29 +00:00
|
|
|
EM_backbuf_checkAndSelectVerts(vc->em, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
} else {
|
2008-12-30 16:03:29 +00:00
|
|
|
mesh_foreachScreenVert(vc, do_mesh_box_select__doSelectVert, &data, 1);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_EDGE) {
|
2008-12-20 18:43:21 +00:00
|
|
|
/* Does both bbsel and non-bbsel versions (need screen cos for both) */
|
|
|
|
|
|
|
|
data.pass = 0;
|
2008-12-30 16:03:29 +00:00
|
|
|
mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, 0);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (data.done==0) {
|
|
|
|
data.pass = 1;
|
2008-12-30 16:03:29 +00:00
|
|
|
mesh_foreachScreenEdge(vc, do_mesh_box_select__doSelectEdge, &data, 0);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_FACE) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if(bbsel) {
|
2008-12-30 16:03:29 +00:00
|
|
|
EM_backbuf_checkAndSelectFaces(vc->em, select);
|
2008-12-20 18:43:21 +00:00
|
|
|
} else {
|
2008-12-30 16:03:29 +00:00
|
|
|
mesh_foreachScreenFace(vc, do_mesh_box_select__doSelectFace, &data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
EM_free_backbuf();
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
EM_selectmode_flush(vc->em);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int view3d_borderselect_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2008-12-30 16:03:29 +00:00
|
|
|
ViewContext vc;
|
2008-12-20 18:43:21 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
|
|
|
ScrArea *sa= CTX_wm_area(C);
|
|
|
|
View3D *v3d= sa->spacedata.first;
|
2009-01-02 19:10:35 +00:00
|
|
|
Object *obedit= CTX_data_edit_object(C);
|
2009-08-16 02:35:44 +00:00
|
|
|
Object *obact= CTX_data_active_object(C);
|
2008-12-20 18:43:21 +00:00
|
|
|
rcti rect;
|
|
|
|
Base *base;
|
|
|
|
MetaElem *ml;
|
|
|
|
unsigned int buffer[4*MAXPICKBUF];
|
|
|
|
int a, index;
|
|
|
|
short hits, val;
|
|
|
|
|
2009-01-01 19:18:03 +00:00
|
|
|
view3d_operator_needs_opengl(C);
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
/* setup view context for argument to callbacks */
|
2009-01-02 14:11:18 +00:00
|
|
|
view3d_set_viewcontext(C, &vc);
|
2008-12-30 16:03:29 +00:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
val= RNA_int_get(op->ptr, "event_type");
|
|
|
|
rect.xmin= RNA_int_get(op->ptr, "xmin");
|
|
|
|
rect.ymin= RNA_int_get(op->ptr, "ymin");
|
|
|
|
rect.xmax= RNA_int_get(op->ptr, "xmax");
|
|
|
|
rect.ymax= RNA_int_get(op->ptr, "ymax");
|
|
|
|
|
2009-08-15 19:48:50 +00:00
|
|
|
if(obedit==NULL && (paint_facesel_test(OBACT))) {
|
2008-12-20 18:43:21 +00:00
|
|
|
// XXX face_borderselect();
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
2009-08-16 02:35:44 +00:00
|
|
|
else if(obedit==NULL && (obact && obact->mode & OB_MODE_PARTICLE_EDIT)) {
|
2009-02-25 19:29:58 +00:00
|
|
|
return PE_border_select(C, &rect, (val==LEFTMOUSE));
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2009-01-02 19:10:35 +00:00
|
|
|
if(obedit) {
|
|
|
|
if(obedit->type==OB_MESH) {
|
|
|
|
Mesh *me= obedit->data;
|
2009-01-01 13:15:35 +00:00
|
|
|
vc.em= me->edit_mesh;
|
2008-12-30 16:03:29 +00:00
|
|
|
do_mesh_box_select(&vc, &rect, (val==LEFTMOUSE));
|
2008-12-20 18:43:21 +00:00
|
|
|
// if (EM_texFaceCheck())
|
2.5
Notifiers
---------
Various fixes for wrong use of notifiers, and some new notifiers
to make things a bit more clear and consistent, with two notable
changes:
* Geometry changes are now done with NC_GEOM, rather than
NC_OBJECT|ND_GEOM_, so an object does need to be available.
* Space data now use NC_SPACE|ND_SPACE_*, instead of data
notifiers or even NC_WINDOW in some cases. Note that NC_SPACE
should only be used for notifying about changes in space data,
we don't want to go back to allqueue(REDRAW..).
Depsgraph
---------
The dependency graph now has a different flush call:
DAG_object_flush_update(scene, ob, flag)
is replaced by:
DAG_id_flush_update(id, flag)
It still works basically the same, one difference is that it now
also accepts object data (e.g. Mesh), again to avoid requiring an
Object to be available. Other ID types will simply do nothing at
the moment.
Docs
----
I made some guidelines for how/when to do which kinds of updates
and notifiers. I can't specify totally exact how to make these
decisions, but these are basically the guidelines I use. So, new
and updated docs are here:
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/NotifiersUpdates
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/DataNotifiers
2009-09-04 20:51:09 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obedit->data);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(ELEM(obedit->type, OB_CURVE, OB_SURF)) {
|
2008-12-30 16:03:29 +00:00
|
|
|
do_nurbs_box_select(&vc, &rect, val==LEFTMOUSE);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_MBALL) {
|
2009-07-29 12:35:09 +00:00
|
|
|
MetaBall *mb = (MetaBall*)obedit->data;
|
2008-12-30 16:03:29 +00:00
|
|
|
hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-07-29 12:35:09 +00:00
|
|
|
ml= mb->editelems->first;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
while(ml) {
|
|
|
|
for(a=0; a<hits; a++) {
|
|
|
|
if(ml->selcol1==buffer[ (4 * a) + 3 ]) {
|
|
|
|
ml->flag |= MB_SCALE_RAD;
|
|
|
|
if(val==LEFTMOUSE) ml->flag |= SELECT;
|
|
|
|
else ml->flag &= ~SELECT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if(ml->selcol2==buffer[ (4 * a) + 3 ]) {
|
|
|
|
ml->flag &= ~MB_SCALE_RAD;
|
|
|
|
if(val==LEFTMOUSE) ml->flag |= SELECT;
|
|
|
|
else ml->flag &= ~SELECT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ml= ml->next;
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_ARMATURE) {
|
2009-01-04 14:14:06 +00:00
|
|
|
bArmature *arm= obedit->data;
|
2008-12-20 18:43:21 +00:00
|
|
|
EditBone *ebone;
|
|
|
|
|
|
|
|
/* clear flag we use to detect point was affected */
|
2009-01-04 14:14:06 +00:00
|
|
|
for(ebone= arm->edbo->first; ebone; ebone= ebone->next)
|
2008-12-20 18:43:21 +00:00
|
|
|
ebone->flag &= ~BONE_DONE;
|
|
|
|
|
2008-12-30 16:03:29 +00:00
|
|
|
hits= view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect);
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
/* first we only check points inside the border */
|
|
|
|
for (a=0; a<hits; a++){
|
|
|
|
index = buffer[(4*a)+3];
|
|
|
|
if (index!=-1) {
|
2009-01-04 14:14:06 +00:00
|
|
|
ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
|
2008-12-20 18:43:21 +00:00
|
|
|
if (index & BONESEL_TIP) {
|
|
|
|
ebone->flag |= BONE_DONE;
|
|
|
|
if (val==LEFTMOUSE) ebone->flag |= BONE_TIPSEL;
|
|
|
|
else ebone->flag &= ~BONE_TIPSEL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (index & BONESEL_ROOT) {
|
|
|
|
ebone->flag |= BONE_DONE;
|
|
|
|
if (val==LEFTMOUSE) ebone->flag |= BONE_ROOTSEL;
|
|
|
|
else ebone->flag &= ~BONE_ROOTSEL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now we have to flush tag from parents... */
|
2009-01-04 14:14:06 +00:00
|
|
|
for(ebone= arm->edbo->first; ebone; ebone= ebone->next) {
|
2008-12-20 18:43:21 +00:00
|
|
|
if(ebone->parent && (ebone->flag & BONE_CONNECTED)) {
|
|
|
|
if(ebone->parent->flag & BONE_DONE)
|
|
|
|
ebone->flag |= BONE_DONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* only select/deselect entire bones when no points where in the rect */
|
|
|
|
for (a=0; a<hits; a++){
|
|
|
|
index = buffer[(4*a)+3];
|
|
|
|
if (index!=-1) {
|
2009-01-04 14:14:06 +00:00
|
|
|
ebone = BLI_findlink(arm->edbo, index & ~(BONESEL_ANY));
|
2008-12-20 18:43:21 +00:00
|
|
|
if (index & BONESEL_BONE) {
|
|
|
|
if(!(ebone->flag & BONE_DONE)) {
|
|
|
|
if (val==LEFTMOUSE)
|
|
|
|
ebone->flag |= (BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
|
|
|
|
else
|
|
|
|
ebone->flag &= ~(BONE_ROOTSEL|BONE_TIPSEL|BONE_SELECTED);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-08 15:34:41 +00:00
|
|
|
ED_armature_sync_selection(arm->edbo);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-01-02 19:10:35 +00:00
|
|
|
else if(obedit->type==OB_LATTICE) {
|
2008-12-30 16:03:29 +00:00
|
|
|
do_lattice_box_select(&vc, &rect, val==LEFTMOUSE);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else { /* no editmode, unified for bones and objects */
|
|
|
|
Bone *bone;
|
2009-01-15 15:01:39 +00:00
|
|
|
Object *ob= OBACT;
|
2008-12-20 18:43:21 +00:00
|
|
|
unsigned int *vbuffer=NULL; /* selection buffer */
|
|
|
|
unsigned int *col; /* color in buffer */
|
|
|
|
short selecting = 0;
|
|
|
|
int bone_only;
|
2009-01-15 15:01:39 +00:00
|
|
|
int totobj= MAXPICKBUF; // XXX solve later
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-08-16 03:24:23 +00:00
|
|
|
if((ob) && (ob->mode & OB_MODE_POSE))
|
2008-12-20 18:43:21 +00:00
|
|
|
bone_only= 1;
|
|
|
|
else
|
|
|
|
bone_only= 0;
|
|
|
|
|
|
|
|
if (val==LEFTMOUSE)
|
|
|
|
selecting = 1;
|
|
|
|
|
|
|
|
/* selection buffer now has bones potentially too, so we add MAXPICKBUF */
|
2009-01-15 15:01:39 +00:00
|
|
|
vbuffer = MEM_mallocN(4 * (totobj+MAXPICKBUF) * sizeof(unsigned int), "selection buffer");
|
|
|
|
hits= view3d_opengl_select(&vc, vbuffer, 4*(totobj+MAXPICKBUF), &rect);
|
2008-12-20 18:43:21 +00:00
|
|
|
/*
|
|
|
|
LOGIC NOTES (theeth):
|
|
|
|
The buffer and ListBase have the same relative order, which makes the selection
|
|
|
|
very simple. Loop through both data sets at the same time, if the color
|
|
|
|
is the same as the object, we have a hit and can move to the next color
|
|
|
|
and object pair, if not, just move to the next object,
|
|
|
|
keeping the same color until we have a hit.
|
|
|
|
|
|
|
|
The buffer order is defined by OGL standard, hopefully no stupid GFX card
|
|
|
|
does it incorrectly.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (hits>0) { /* no need to loop if there's no hit */
|
|
|
|
base= FIRSTBASE;
|
|
|
|
col = vbuffer + 3;
|
2008-12-29 12:15:42 +00:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
while(base && hits) {
|
|
|
|
Base *next = base->next;
|
|
|
|
if(base->lay & v3d->lay) {
|
|
|
|
while (base->selcol == (*col & 0xFFFF)) { /* we got an object */
|
|
|
|
|
|
|
|
if(*col & 0xFFFF0000) { /* we got a bone */
|
2009-01-10 14:19:14 +00:00
|
|
|
bone = get_indexed_bone(base->object, *col & ~(BONESEL_ANY));
|
2008-12-20 18:43:21 +00:00
|
|
|
if(bone) {
|
|
|
|
if(selecting) {
|
|
|
|
bone->flag |= BONE_SELECTED;
|
|
|
|
// XXX select_actionchannel_by_name(base->object->action, bone->name, 1);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bone->flag &= ~(BONE_ACTIVE|BONE_SELECTED);
|
|
|
|
// XXX select_actionchannel_by_name(base->object->action, bone->name, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if(!bone_only) {
|
|
|
|
if (selecting)
|
2008-12-29 12:15:42 +00:00
|
|
|
ED_base_object_select(base, BA_SELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
else
|
2008-12-29 12:15:42 +00:00
|
|
|
ED_base_object_select(base, BA_DESELECT);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
col+=4; /* next color */
|
|
|
|
hits--;
|
|
|
|
if(hits==0) break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
base= next;
|
|
|
|
}
|
2008-12-29 12:15:42 +00:00
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, scene);
|
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
MEM_freeN(vbuffer);
|
|
|
|
}
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-28 01:28:31 +00:00
|
|
|
/* *****************Selection Operators******************* */
|
|
|
|
|
|
|
|
/* ****** Border Select ****** */
|
2009-03-29 02:15:13 +00:00
|
|
|
void VIEW3D_OT_select_border(wmOperatorType *ot)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Border Select";
|
2009-09-07 04:52:42 +00:00
|
|
|
ot->description= "Select items using border selection.";
|
2009-03-29 02:15:13 +00:00
|
|
|
ot->idname= "VIEW3D_OT_select_border";
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= WM_border_select_invoke;
|
|
|
|
ot->exec= view3d_borderselect_exec;
|
|
|
|
ot->modal= WM_border_select_modal;
|
|
|
|
|
2008-12-26 19:07:31 +00:00
|
|
|
ot->poll= ED_operator_view3d_active;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
2.5
Summary of ain features:
- Themes and Styles are now editable.
- CTRL+U "Save user defaults" now goes to new .B25.blend, so you
can use 2.4x and 2.5x next to each other. If B25 doesn't exist, it
reads the regular .B.blend
- Press Tkey in 3d window for (unfinished) toolbar WIP. It now only
shows the last operator, if appropriate.
Nkey properties moved to the other side.
A lot of work was done on removing old themes for good and properly
getting it work with the 2.5 region system. Here's some notes;
- Buttons now all have a complete set of colors, based on button classifications
(See outliner -> user prefs -> Interface
- Theme colors have been extended with basic colors for region types.
Currently colors are defined for Window, Header, List/Channels and
for Button/Tool views.
The screen manager handles this btw, so a TH_BACK will always pick the
right backdrop color.
- Menu backdrops are in in Button theme colors. Floating Panels will be in
the per-space type Themes.
- Styles were added in RNA too, but only for the font settings now.
Only Panel font, widget font and widget-label work now. The 'group label'
will be for templates mostly.
Style settings will be expanded with spacing defaults, label conventions,
etc.
- Label text colors are stored in per-space Theme too, to make sure they fit.
Same goes for Panel title color.
Note that 'shadow' for fonts can conflict with text colors; shadow color is
currently stored in Style... shadow code needs a bit of work still.
2009-04-27 13:44:11 +00:00
|
|
|
ot->flag= OPTYPE_UNDO;
|
2009-01-31 19:40:40 +00:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
/* rna */
|
2009-01-16 23:53:11 +00:00
|
|
|
RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
|
|
|
|
RNA_def_int(ot->srna, "xmin", 0, INT_MIN, INT_MAX, "X Min", "", INT_MIN, INT_MAX);
|
|
|
|
RNA_def_int(ot->srna, "xmax", 0, INT_MIN, INT_MAX, "X Max", "", INT_MIN, INT_MAX);
|
|
|
|
RNA_def_int(ot->srna, "ymin", 0, INT_MIN, INT_MAX, "Y Min", "", INT_MIN, INT_MAX);
|
|
|
|
RNA_def_int(ot->srna, "ymax", 0, INT_MIN, INT_MAX, "Y Max", "", INT_MIN, INT_MAX);
|
|
|
|
|
2009-09-16 10:09:57 +00:00
|
|
|
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first.");
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2008-12-28 01:28:31 +00:00
|
|
|
/* ****** Mouse Select ****** */
|
2008-12-29 00:45:00 +00:00
|
|
|
|
2008-12-31 17:50:00 +00:00
|
|
|
|
2008-12-28 01:28:31 +00:00
|
|
|
static int view3d_select_invoke(bContext *C, wmOperator *op, wmEvent *event)
|
|
|
|
{
|
2008-12-31 17:11:42 +00:00
|
|
|
Object *obedit= CTX_data_edit_object(C);
|
2009-08-16 02:35:44 +00:00
|
|
|
Object *obact= CTX_data_active_object(C);
|
RNA
* Enums can now be dynamically created in the _itemf callback,
using RNA_enum_item(s)_add, RNA_enum_item_end. All places asking
for enum items now need to potentially free the items.
* This callback now also gets context, this was added specifically
for operators. This doesn't fit design well at all, needed to do
some ugly hacks, but can't find a good solution at the moment.
* All enums must have a default list of items too, even with an
_itemf callback, for docs and fallback in case there is no context.
* Used by MESH_OT_merge, MESH_OT_select_similar, TFM_OT_select_orientation.
* Also changes some operator properties that were enums to booleas
(unselected, deselect), to make them consistent with other ops.
2009-07-10 19:56:13 +00:00
|
|
|
short extend= RNA_boolean_get(op->ptr, "extend");
|
2009-09-16 01:15:30 +00:00
|
|
|
short center= RNA_boolean_get(op->ptr, "center");
|
|
|
|
short enumerate= RNA_boolean_get(op->ptr, "enumerate");
|
2008-12-28 01:28:31 +00:00
|
|
|
|
|
|
|
view3d_operator_needs_opengl(C);
|
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
if(obedit) {
|
|
|
|
if(obedit->type==OB_MESH)
|
2009-02-19 19:03:53 +00:00
|
|
|
mouse_mesh(C, event->mval, extend);
|
2009-01-05 19:32:04 +00:00
|
|
|
else if(obedit->type==OB_ARMATURE)
|
2009-02-19 19:03:53 +00:00
|
|
|
mouse_armature(C, event->mval, extend);
|
2009-01-13 15:18:41 +00:00
|
|
|
else if(obedit->type==OB_LATTICE)
|
2009-02-19 19:03:53 +00:00
|
|
|
mouse_lattice(C, event->mval, extend);
|
2009-01-14 12:26:45 +00:00
|
|
|
else if(ELEM(obedit->type, OB_CURVE, OB_SURF))
|
2009-02-19 19:03:53 +00:00
|
|
|
mouse_nurb(C, event->mval, extend);
|
2009-07-29 12:35:09 +00:00
|
|
|
else if(obedit->type==OB_MBALL)
|
|
|
|
mouse_mball(C, event->mval, extend);
|
2009-01-05 19:32:04 +00:00
|
|
|
|
2008-12-31 17:11:42 +00:00
|
|
|
}
|
2009-08-16 02:35:44 +00:00
|
|
|
else if(obact && obact->mode & OB_MODE_PARTICLE_EDIT)
|
2009-02-25 19:29:58 +00:00
|
|
|
PE_mouse_particles(C, event->mval, extend);
|
2008-12-31 17:11:42 +00:00
|
|
|
else
|
2009-09-16 01:15:30 +00:00
|
|
|
mouse_select(C, event->mval, extend, center, enumerate);
|
2009-01-31 19:40:40 +00:00
|
|
|
|
2009-01-01 18:05:12 +00:00
|
|
|
/* allowing tweaks */
|
2009-01-31 19:40:40 +00:00
|
|
|
return OPERATOR_PASS_THROUGH|OPERATOR_FINISHED;
|
2008-12-28 01:28:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VIEW3D_OT_select(wmOperatorType *ot)
|
|
|
|
{
|
|
|
|
/* identifiers */
|
|
|
|
ot->name= "Activate/Select";
|
2009-09-07 04:52:42 +00:00
|
|
|
ot->description= "Activate/select item(s).";
|
2008-12-28 01:28:31 +00:00
|
|
|
ot->idname= "VIEW3D_OT_select";
|
|
|
|
|
|
|
|
/* api callbacks */
|
|
|
|
ot->invoke= view3d_select_invoke;
|
|
|
|
ot->poll= ED_operator_view3d_active;
|
2009-01-31 19:40:40 +00:00
|
|
|
|
|
|
|
/* flags */
|
2.5
Summary of ain features:
- Themes and Styles are now editable.
- CTRL+U "Save user defaults" now goes to new .B25.blend, so you
can use 2.4x and 2.5x next to each other. If B25 doesn't exist, it
reads the regular .B.blend
- Press Tkey in 3d window for (unfinished) toolbar WIP. It now only
shows the last operator, if appropriate.
Nkey properties moved to the other side.
A lot of work was done on removing old themes for good and properly
getting it work with the 2.5 region system. Here's some notes;
- Buttons now all have a complete set of colors, based on button classifications
(See outliner -> user prefs -> Interface
- Theme colors have been extended with basic colors for region types.
Currently colors are defined for Window, Header, List/Channels and
for Button/Tool views.
The screen manager handles this btw, so a TH_BACK will always pick the
right backdrop color.
- Menu backdrops are in in Button theme colors. Floating Panels will be in
the per-space type Themes.
- Styles were added in RNA too, but only for the font settings now.
Only Panel font, widget font and widget-label work now. The 'group label'
will be for templates mostly.
Style settings will be expanded with spacing defaults, label conventions,
etc.
- Label text colors are stored in per-space Theme too, to make sure they fit.
Same goes for Panel title color.
Note that 'shadow' for fonts can conflict with text colors; shadow color is
currently stored in Style... shadow code needs a bit of work still.
2009-04-27 13:44:11 +00:00
|
|
|
ot->flag= OPTYPE_UNDO;
|
2009-01-31 19:40:40 +00:00
|
|
|
|
2009-01-16 23:53:11 +00:00
|
|
|
/* properties */
|
2009-09-16 01:15:30 +00:00
|
|
|
RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first.");
|
|
|
|
RNA_def_boolean(ot->srna, "center", 0, "Center", "Use the object center when selecting (object mode only).");
|
|
|
|
RNA_def_boolean(ot->srna, "enumerate", 0, "Enumerate", "List objects under the mouse (object mode only).");
|
2008-12-28 01:28:31 +00:00
|
|
|
}
|
2008-12-29 00:45:00 +00:00
|
|
|
|
2008-12-28 01:28:31 +00:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/* -------------------- circle select --------------------------------------------- */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
static void mesh_circle_doSelectVert(void *userData, EditVert *eve, int x, int y, int index)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-24 13:45:24 +00:00
|
|
|
struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
int mx = x - data->mval[0], my = y - data->mval[1];
|
|
|
|
float r = sqrt(mx*mx + my*my);
|
|
|
|
|
|
|
|
if (r<=data->radius) {
|
|
|
|
eve->f = data->select?(eve->f|1):(eve->f&~1);
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
static void mesh_circle_doSelectEdge(void *userData, EditEdge *eed, int x0, int y0, int x1, int y1, int index)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-24 13:45:24 +00:00
|
|
|
struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
|
|
|
if (edge_inside_circle(data->mval[0], data->mval[1], (short) data->radius, x0, y0, x1, y1)) {
|
|
|
|
EM_select_edge(eed, data->select);
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
static void mesh_circle_doSelectFace(void *userData, EditFace *efa, int x, int y, int index)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-24 13:45:24 +00:00
|
|
|
struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
int mx = x - data->mval[0], my = y - data->mval[1];
|
|
|
|
float r = sqrt(mx*mx + my*my);
|
2008-12-30 13:16:14 +00:00
|
|
|
|
2008-12-20 18:43:21 +00:00
|
|
|
if (r<=data->radius) {
|
2009-01-24 13:45:24 +00:00
|
|
|
EM_select_face_fgon(data->vc->em, efa, data->select);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
static void mesh_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-06-23 00:41:55 +00:00
|
|
|
ToolSettings *ts= vc->scene->toolsettings;
|
2008-12-20 18:43:21 +00:00
|
|
|
int bbsel;
|
2009-08-15 19:48:50 +00:00
|
|
|
Object *ob= vc->obact;
|
2009-01-02 14:11:18 +00:00
|
|
|
|
2009-08-15 19:48:50 +00:00
|
|
|
if(vc->obedit==NULL && paint_facesel_test(ob)) {
|
2008-12-20 18:43:21 +00:00
|
|
|
Mesh *me = ob?ob->data:NULL;
|
|
|
|
|
|
|
|
if (me) {
|
|
|
|
em_vertoffs= me->totface+1; /* max index array */
|
|
|
|
|
2009-01-01 19:18:03 +00:00
|
|
|
bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
|
2008-12-20 18:43:21 +00:00
|
|
|
EM_backbuf_checkAndSelectTFaces(me, selecting==LEFTMOUSE);
|
|
|
|
EM_free_backbuf();
|
|
|
|
|
|
|
|
// XXX object_tface_flags_changed(OBACT, 0);
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
else {
|
2009-01-24 13:45:24 +00:00
|
|
|
struct {ViewContext *vc; short select, mval[2]; float radius; } data;
|
2009-01-02 14:11:18 +00:00
|
|
|
|
|
|
|
bbsel= EM_init_backbuf_circle(vc, mval[0], mval[1], (short)(rad+1.0));
|
|
|
|
vc->em= ((Mesh *)vc->obedit->data)->edit_mesh;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
data.select = selecting;
|
|
|
|
data.mval[0] = mval[0];
|
|
|
|
data.mval[1] = mval[1];
|
|
|
|
data.radius = rad;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_VERTEX) {
|
2009-01-02 14:11:18 +00:00
|
|
|
if(bbsel) {
|
|
|
|
EM_backbuf_checkAndSelectVerts(vc->em, selecting==LEFTMOUSE);
|
|
|
|
} else {
|
|
|
|
mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, 1);
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_EDGE) {
|
2009-01-02 14:11:18 +00:00
|
|
|
if (bbsel) {
|
|
|
|
EM_backbuf_checkAndSelectEdges(vc->em, selecting==LEFTMOUSE);
|
|
|
|
} else {
|
|
|
|
mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, 0);
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
|
2009-06-23 00:41:55 +00:00
|
|
|
if(ts->selectmode & SCE_SELECT_FACE) {
|
2009-01-02 14:11:18 +00:00
|
|
|
if(bbsel) {
|
|
|
|
EM_backbuf_checkAndSelectFaces(vc->em, selecting==LEFTMOUSE);
|
|
|
|
} else {
|
|
|
|
mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data);
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
EM_free_backbuf();
|
|
|
|
EM_selectmode_flush(vc->em);
|
|
|
|
}
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
static void nurbscurve_circle_doSelect(void *userData, Nurb *nu, BPoint *bp, BezTriple *bezt, int beztindex, int x, int y)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-24 13:45:24 +00:00
|
|
|
struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
int mx = x - data->mval[0], my = y - data->mval[1];
|
|
|
|
float r = sqrt(mx*mx + my*my);
|
|
|
|
|
|
|
|
if (r<=data->radius) {
|
|
|
|
if (bp) {
|
|
|
|
bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
|
|
|
|
} else {
|
|
|
|
if (beztindex==0) {
|
|
|
|
bezt->f1 = data->select?(bezt->f1|SELECT):(bezt->f1&~SELECT);
|
|
|
|
} else if (beztindex==1) {
|
|
|
|
bezt->f2 = data->select?(bezt->f2|SELECT):(bezt->f2&~SELECT);
|
|
|
|
} else {
|
|
|
|
bezt->f3 = data->select?(bezt->f3|SELECT):(bezt->f3&~SELECT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
static void nurbscurve_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-24 13:45:24 +00:00
|
|
|
struct {ViewContext *vc; short select, mval[2]; float radius; } data;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/* set vc-> edit data */
|
|
|
|
|
|
|
|
data.select = selecting;
|
2008-12-20 18:43:21 +00:00
|
|
|
data.mval[0] = mval[0];
|
|
|
|
data.mval[1] = mval[1];
|
|
|
|
data.radius = rad;
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
nurbs_foreachScreenVert(vc, nurbscurve_circle_doSelect, &data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
static void latticecurve_circle_doSelect(void *userData, BPoint *bp, int x, int y)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-24 13:45:24 +00:00
|
|
|
struct {ViewContext *vc; short select, mval[2]; float radius; } *data = userData;
|
2008-12-20 18:43:21 +00:00
|
|
|
int mx = x - data->mval[0], my = y - data->mval[1];
|
|
|
|
float r = sqrt(mx*mx + my*my);
|
|
|
|
|
|
|
|
if (r<=data->radius) {
|
|
|
|
bp->f1 = data->select?(bp->f1|SELECT):(bp->f1&~SELECT);
|
|
|
|
}
|
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
static void lattice_circle_select(ViewContext *vc, int selecting, short *mval, float rad)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-24 13:45:24 +00:00
|
|
|
struct {ViewContext *vc; short select, mval[2]; float radius; } data;
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/* set vc-> edit data */
|
|
|
|
|
|
|
|
data.select = selecting;
|
2008-12-20 18:43:21 +00:00
|
|
|
data.mval[0] = mval[0];
|
|
|
|
data.mval[1] = mval[1];
|
|
|
|
data.radius = rad;
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
lattice_foreachScreenVert(vc, latticecurve_circle_doSelect, &data);
|
2008-12-20 18:43:21 +00:00
|
|
|
}
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
/** Callbacks for circle selection in Editmode */
|
2008-12-20 18:43:21 +00:00
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
static void obedit_circle_select(ViewContext *vc, short selecting, short *mval, float rad)
|
2008-12-20 18:43:21 +00:00
|
|
|
{
|
2009-01-02 14:11:18 +00:00
|
|
|
switch(vc->obedit->type) {
|
2008-12-20 18:43:21 +00:00
|
|
|
case OB_MESH:
|
2009-01-02 14:11:18 +00:00
|
|
|
mesh_circle_select(vc, selecting, mval, rad);
|
2008-12-20 18:43:21 +00:00
|
|
|
break;
|
|
|
|
case OB_CURVE:
|
|
|
|
case OB_SURF:
|
2009-01-02 14:11:18 +00:00
|
|
|
nurbscurve_circle_select(vc, selecting, mval, rad);
|
2008-12-20 18:43:21 +00:00
|
|
|
break;
|
|
|
|
case OB_LATTICE:
|
2009-01-02 14:11:18 +00:00
|
|
|
lattice_circle_select(vc, selecting, mval, rad);
|
2008-12-20 18:43:21 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-12-29 12:15:42 +00:00
|
|
|
/* not a real operator, only for circle test */
|
2009-01-02 14:11:18 +00:00
|
|
|
static int view3d_circle_select_exec(bContext *C, wmOperator *op)
|
2008-12-21 16:24:19 +00:00
|
|
|
{
|
|
|
|
ScrArea *sa= CTX_wm_area(C);
|
|
|
|
ARegion *ar= CTX_wm_region(C);
|
2008-12-22 09:43:29 +00:00
|
|
|
Scene *scene= CTX_data_scene(C);
|
2009-08-16 02:35:44 +00:00
|
|
|
Object *obact= CTX_data_active_object(C);
|
2008-12-21 16:24:19 +00:00
|
|
|
View3D *v3d= sa->spacedata.first;
|
|
|
|
int x= RNA_int_get(op->ptr, "x");
|
|
|
|
int y= RNA_int_get(op->ptr, "y");
|
|
|
|
int radius= RNA_int_get(op->ptr, "radius");
|
|
|
|
|
2009-08-16 02:35:44 +00:00
|
|
|
if(CTX_data_edit_object(C) || (obact && obact->mode & OB_MODE_PARTICLE_EDIT)) {
|
2009-01-02 14:11:18 +00:00
|
|
|
ViewContext vc;
|
|
|
|
short mval[2], selecting;
|
|
|
|
|
2.5
Sanitized the 'tweak' event.
Original idea was to have WM event system generating it
automatically. However, I first tested it via a handler
and operator, to check what kind of configurations would
be useful. It appeared to not work nice, also because
that inserting a tweak operator in a keymap is confusing.
Now 'tweaks' are generated automatically, and can be
catched by keymaps as any event. The current definition
of tweak is:
- if Left/Middle/Rightmouse pressed
if event wasn't handled by window queue (modal handlers)
start checking mousepositions
- while mousepositions are checked
- escape on any event other than mouse
- on mouse events:
- add tweak event if mousemove > 10 pixels
- stop checking for tweak if mousebutton released
- Tweak events have a define indicating mousebutton used
EVT_TWEAK_L, EVT_TWEAK_M, EVT_TWEAK_R
- In keymap definitions you can use _S or _A to map to
action or select mouse userdef.
- Event value in keymap should be KM_ANY for all tweaks,
or use one of the eight directions:
EVT_GESTURE_E, _SE, _S, _SW, _W, _NW, _N, _NE
- And of course you can add modifier checks in keymaps for it.
- Because tweaks are a result of mouse events, the handlers get
both to evaluate. That means that RMB-select + tweak will work
correctly.
In case you don't want both to be handled, for example the
CTRL+LMB 'extrude' and CTRL+LMB-tweak 'lasso select', you will
need to set the first acting on a EVT_RELEASE, this event only
gets passed on when tweak fails.
The current system allows all options, configurable, we had in 2.48,
and many more! A diagram of what's possible is on the todo. :)
Also in this commit: lasso select editmesh failed with 'zbuffer
occluded select'. Also circle-select failed.
2009-02-02 14:13:14 +00:00
|
|
|
view3d_operator_needs_opengl(C);
|
|
|
|
|
2009-01-02 14:11:18 +00:00
|
|
|
view3d_set_viewcontext(C, &vc);
|
|
|
|
mval[0]= x;
|
|
|
|
mval[1]= y;
|
|
|
|
selecting= LEFTMOUSE==RNA_int_get(op->ptr, "event_type"); // XXX solve
|
2009-02-20 20:39:27 +00:00
|
|
|
|
2009-08-16 18:25:22 +00:00
|
|
|
if(CTX_data_edit_object(C)) {
|
2009-02-20 20:39:27 +00:00
|
|
|
obedit_circle_select(&vc, selecting, mval, (float)radius);
|
2.5
Notifiers
---------
Various fixes for wrong use of notifiers, and some new notifiers
to make things a bit more clear and consistent, with two notable
changes:
* Geometry changes are now done with NC_GEOM, rather than
NC_OBJECT|ND_GEOM_, so an object does need to be available.
* Space data now use NC_SPACE|ND_SPACE_*, instead of data
notifiers or even NC_WINDOW in some cases. Note that NC_SPACE
should only be used for notifying about changes in space data,
we don't want to go back to allqueue(REDRAW..).
Depsgraph
---------
The dependency graph now has a different flush call:
DAG_object_flush_update(scene, ob, flag)
is replaced by:
DAG_id_flush_update(id, flag)
It still works basically the same, one difference is that it now
also accepts object data (e.g. Mesh), again to avoid requiring an
Object to be available. Other ID types will simply do nothing at
the moment.
Docs
----
I made some guidelines for how/when to do which kinds of updates
and notifiers. I can't specify totally exact how to make these
decisions, but these are basically the guidelines I use. So, new
and updated docs are here:
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/NotifiersUpdates
http://wiki.blender.org/index.php/BlenderDev/Blender2.5/DataNotifiers
2009-09-04 20:51:09 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM|ND_SELECT, obact->data);
|
2009-08-16 18:25:22 +00:00
|
|
|
}
|
2009-02-20 20:39:27 +00:00
|
|
|
else
|
2009-02-25 19:29:58 +00:00
|
|
|
return PE_circle_select(C, selecting, mval, (float)radius);
|
2009-01-02 14:11:18 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
Base *base;
|
|
|
|
|
|
|
|
for(base= FIRSTBASE; base; base= base->next) {
|
|
|
|
if(base->lay & v3d->lay) {
|
2.5
View3D has been split now in a local part (RegionView3D) and a
per-area part (old View3D). Currently local is:
- view transform
- camera zoom/offset
- gpencil (todo)
- custom clipping planes
Rest is in Area still, like active camera, draw type, layers,
localview, custom centers, around-settings, transform widget,
gridlines, and so on (mostly stuff as available in header).
To see it work; also added new feature for region split,
press SHIFT+ALT+CTRL+S for four-split.
The idea is to make a preset 4-split, configured to stick
to top/right/front views for three views.
Another cool idea to explore is to then box-clip all drawing
based on these 3 views.
Note about the code:
- currently view3d still stores some depricated settings, to
convert from older files. Not all settings are copied over
though, like custom clip planes or the 'lock view to object'.
- since some view3d ops are now on area level, the operators
for it should keep track of that.
Bugfix in transform: quat initialize in operator-invoke missed
one zero.
Als brought back GE to compile for missing Ipos and channels.
2009-01-19 16:54:41 +00:00
|
|
|
project_short(ar, base->object->obmat[3], &base->sx);
|
2009-01-02 14:11:18 +00:00
|
|
|
if(base->sx!=IS_CLIPPED) {
|
|
|
|
int dx= base->sx-x;
|
|
|
|
int dy= base->sy-y;
|
|
|
|
if( dx*dx + dy*dy < radius*radius)
|
|
|
|
ED_base_object_select(base, BA_SELECT);
|
|
|
|
}
|
2008-12-21 16:24:19 +00:00
|
|
|
}
|
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
|
|
|
|
WM_event_add_notifier(C, NC_SCENE|ND_OB_SELECT, CTX_data_scene(C));
|
2008-12-21 16:24:19 +00:00
|
|
|
}
|
2009-01-02 14:11:18 +00:00
|
|
|
|
|
|
|
return OPERATOR_FINISHED;
|
2008-12-21 16:24:19 +00:00
|
|
|
}
|
|
|
|
|
2009-03-29 02:15:13 +00:00
|
|
|
void VIEW3D_OT_select_circle(wmOperatorType *ot)
|
2008-12-21 16:24:19 +00:00
|
|
|
{
|
|
|
|
ot->name= "Circle Select";
|
2009-09-07 04:52:42 +00:00
|
|
|
ot->description= "Select items using circle selection.";
|
2009-03-29 02:15:13 +00:00
|
|
|
ot->idname= "VIEW3D_OT_select_circle";
|
2008-12-21 16:24:19 +00:00
|
|
|
|
|
|
|
ot->invoke= WM_gesture_circle_invoke;
|
|
|
|
ot->modal= WM_gesture_circle_modal;
|
2009-01-02 14:11:18 +00:00
|
|
|
ot->exec= view3d_circle_select_exec;
|
2008-12-26 19:07:31 +00:00
|
|
|
ot->poll= ED_operator_view3d_active;
|
2008-12-21 16:24:19 +00:00
|
|
|
|
2009-01-31 19:40:40 +00:00
|
|
|
/* flags */
|
2.5
Summary of ain features:
- Themes and Styles are now editable.
- CTRL+U "Save user defaults" now goes to new .B25.blend, so you
can use 2.4x and 2.5x next to each other. If B25 doesn't exist, it
reads the regular .B.blend
- Press Tkey in 3d window for (unfinished) toolbar WIP. It now only
shows the last operator, if appropriate.
Nkey properties moved to the other side.
A lot of work was done on removing old themes for good and properly
getting it work with the 2.5 region system. Here's some notes;
- Buttons now all have a complete set of colors, based on button classifications
(See outliner -> user prefs -> Interface
- Theme colors have been extended with basic colors for region types.
Currently colors are defined for Window, Header, List/Channels and
for Button/Tool views.
The screen manager handles this btw, so a TH_BACK will always pick the
right backdrop color.
- Menu backdrops are in in Button theme colors. Floating Panels will be in
the per-space type Themes.
- Styles were added in RNA too, but only for the font settings now.
Only Panel font, widget font and widget-label work now. The 'group label'
will be for templates mostly.
Style settings will be expanded with spacing defaults, label conventions,
etc.
- Label text colors are stored in per-space Theme too, to make sure they fit.
Same goes for Panel title color.
Note that 'shadow' for fonts can conflict with text colors; shadow color is
currently stored in Style... shadow code needs a bit of work still.
2009-04-27 13:44:11 +00:00
|
|
|
ot->flag= OPTYPE_UNDO;
|
2009-01-31 19:40:40 +00:00
|
|
|
|
2009-01-16 23:53:11 +00:00
|
|
|
RNA_def_int(ot->srna, "x", 0, INT_MIN, INT_MAX, "X", "", INT_MIN, INT_MAX);
|
|
|
|
RNA_def_int(ot->srna, "y", 0, INT_MIN, INT_MAX, "Y", "", INT_MIN, INT_MAX);
|
|
|
|
RNA_def_int(ot->srna, "radius", 0, INT_MIN, INT_MAX, "Radius", "", INT_MIN, INT_MAX);
|
|
|
|
RNA_def_int(ot->srna, "event_type", 0, INT_MIN, INT_MAX, "Event Type", "", INT_MIN, INT_MAX);
|
2008-12-21 16:24:19 +00:00
|
|
|
}
|