1 /****************************************************************************
2  * MeshLab                                                           o o     *
3  * A versatile mesh processing toolbox                             o     o   *
4  *                                                                _   O  _   *
5  * Copyright(C) 2005                                                \/)\/    *
6  * Visual Computing Lab                                            /\/|      *
7  * ISTI - Italian National Research Council                           |      *
8  *                                                                    \      *
9  * All rights reserved.                                                      *
10  *                                                                           *
11  * This program is free software; you can redistribute it and/or modify      *
12  * it under the terms of the GNU General Public License as published by      *
13  * the Free Software Foundation; either version 2 of the License, or         *
14  * (at your option) any later version.                                       *
15  *                                                                           *
16  * This program is distributed in the hope that it will be useful,           *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19  * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20  * for more details.                                                         *
21  *                                                                           *
22  ****************************************************************************/
23 
24 #include "edit_select.h"
25 #include <common/GLExtensionsManager.h>
26 #include <wrap/gl/pick.h>
27 #include <wrap/qt/device_to_logical.h>
28 #include <meshlab/glarea.h>
29 #include <vcg/space/intersection2.h>
30 
31 
32 using namespace std;
33 using namespace vcg;
34 
EditSelectPlugin(int ConnectedMode)35 EditSelectPlugin::EditSelectPlugin(int ConnectedMode) :selectionMode(ConnectedMode) {
36 	isDragging = false;
37 }
38 
Info()39 QString EditSelectPlugin::Info()
40 {
41 	return tr("Interactive selection inside a dragged rectangle in screen space");
42 }
43 
suggestedRenderingData(MeshModel &,MLRenderingData & dt)44 void EditSelectPlugin::suggestedRenderingData(MeshModel & /*m*/, MLRenderingData & dt)
45 {
46 	MLPerViewGLOptions opts;
47 	dt.get(opts);
48 	opts._sel_enabled = true;
49 
50 	if ((selectionMode == SELECT_FACE_MODE) || (selectionMode == SELECT_CONN_MODE))
51 		opts._face_sel = true;
52 
53 	if (selectionMode == SELECT_VERT_MODE)
54 		opts._vertex_sel = true;
55 
56 	if (selectionMode == SELECT_AREA_MODE)
57 	{
58 		opts._face_sel = true;
59 		opts._vertex_sel = true;
60 	}
61 
62 	dt.set(opts);
63 }
64 
keyReleaseEvent(QKeyEvent * e,MeshModel & m,GLArea * gla)65 void EditSelectPlugin::keyReleaseEvent(QKeyEvent *e, MeshModel &m, GLArea *gla)
66 {
67 	// global "all" commands
68 	if (e->key() == Qt::Key_A) // select all
69 	{
70 		if (areaMode == 0){ // vertices
71           tri::UpdateSelection<CMeshO>::VertexAll(m.cm);
72 			gla->updateSelection(m.id(), true, false);
73 		}
74 		else if (areaMode == 1){ //faces
75           tri::UpdateSelection<CMeshO>::FaceAll(m.cm);
76 			gla->updateSelection(m.id(), false, true);
77 		}
78 		gla->update();
79         e->accept();
80 	}
81 
82 	if (e->key() == Qt::Key_D) // deselect all
83 	{
84 		if (areaMode == 0){ // vertices
85           tri::UpdateSelection<CMeshO>::VertexClear(m.cm);
86 			gla->updateSelection(m.id(), true, false);
87 		}
88 		else if (areaMode == 1){ //faces
89           tri::UpdateSelection<CMeshO>::FaceClear(m.cm);
90 			gla->updateSelection(m.id(), false, true);
91 		}
92 		gla->update();
93         e->accept();
94 	}
95 
96 	if (e->key() == Qt::Key_I) // invert all
97 	{
98 		if (areaMode == 0){ // vertices
99           tri::UpdateSelection<CMeshO>::VertexInvert(m.cm);
100 			gla->updateSelection(m.id(), true, false);
101 		}
102 		else if (areaMode == 1){ //faces
103           tri::UpdateSelection<CMeshO>::FaceInvert(m.cm);
104 			gla->updateSelection(m.id(), false, true);
105 		}
106 		gla->update();
107         e->accept();
108 	}
109 
110 
111 	if (selectionMode == SELECT_AREA_MODE)
112 	{
113 		if (e->key() == Qt::Key_T) // toggle pick mode
114 		{
115 			areaMode = (areaMode + 1) % 2;
116 			gla->update();
117             e->accept();
118 		}
119 
120 		if (e->key() == Qt::Key_C) // clear Polyline
121 		{
122 			selPolyLine.clear();
123 			gla->update();
124             e->accept();
125 		}
126 
127 		if (e->key() == Qt::Key_Backspace) // remove last point Polyline
128 		{
129 			if (selPolyLine.size() > 0)
130 				selPolyLine.pop_back();
131 			gla->update();
132             e->accept();
133 		}
134 
135 		if (e->key() == Qt::Key_Q) // add to selection
136 		{
137 			doSelection(m, gla, 0);
138 			gla->update();
139             e->accept();
140 		}
141 
142 		if (e->key() == Qt::Key_W) // sub from selection
143 		{
144 			doSelection(m, gla, 1);
145 			gla->update();
146             e->accept();
147 		}
148 
149 		if (e->key() == Qt::Key_E) // invert selection
150 		{
151 			doSelection(m, gla, 2);
152 			gla->update();
153             e->accept();
154 		}
155         gla->setCursor(QCursor(QPixmap(":/images/sel_area.png"), 1, 1));
156 	}
157     else
158     {
159         gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"), 1, 1));
160         Qt::KeyboardModifiers mod = QApplication::queryKeyboardModifiers();
161         if(selectionMode == SELECT_VERT_MODE)
162         {
163             if (mod & Qt::ControlModifier)
164                 gla->setCursor(QCursor(QPixmap(":/images/sel_rect_plus.png"), 1, 1));
165             else if (mod & Qt::ShiftModifier)
166                 gla->setCursor(QCursor(QPixmap(":/images/sel_rect_minus.png"), 1, 1));
167         }
168         else
169         {
170             if (mod & Qt::AltModifier)
171             {
172                 if (mod & Qt::ControlModifier)
173                     gla->setCursor(QCursor(QPixmap(":/images/sel_rect_plus_eye.png"), 1, 1));
174                 else if (mod & Qt::ShiftModifier)
175                     gla->setCursor(QCursor(QPixmap(":/images/sel_rect_minus_eye.png"), 1, 1));
176                 else
177                     gla->setCursor(QCursor(QPixmap(":/images/sel_rect_eye.png"), 1, 1));
178             }
179             else
180             {
181                 if (mod & Qt::ControlModifier)
182                     gla->setCursor(QCursor(QPixmap(":/images/sel_rect_plus.png"), 1, 1));
183                 else if (mod & Qt::ShiftModifier)
184                     gla->setCursor(QCursor(QPixmap(":/images/sel_rect_minus.png"), 1, 1));
185             }
186         }
187     }
188 
189 }
190 
doSelection(MeshModel & m,GLArea * gla,int mode)191 void EditSelectPlugin::doSelection(MeshModel &m, GLArea *gla, int mode)
192 {
193   QImage bufQImg(this->viewpSize[2],this->viewpSize[3],QImage::Format_RGB32);
194   bufQImg.fill(Qt::white);
195   QPainter bufQPainter(&bufQImg);
196   vector<QPointF> qpoints;
197   for(size_t i=0;i<selPolyLine.size();++i)
198     qpoints.push_back(QPointF(selPolyLine[i][0],selPolyLine[i][1]));
199   bufQPainter.setBrush(QBrush(Qt::black));
200   bufQPainter.drawPolygon(&qpoints[0],qpoints.size(), Qt::WindingFill);
201   QRgb blk=QColor(Qt::black).rgb();
202 
203 
204   static Eigen::Matrix<Scalarm,4,4> LastSelMatrix;
205   static vector<Point3m> projVec;
206   static MeshModel *lastMeshModel=0;
207   if((LastSelMatrix != SelMatrix) || lastMeshModel != &m)
208   {
209     GLPickTri<CMeshO>::FillProjectedVector(m.cm,projVec,this->SelMatrix,this->SelViewport);
210     LastSelMatrix=this->SelMatrix;
211     lastMeshModel=&m;
212   }
213 
214     if (areaMode == 0) // vertices
215     {
216       for (size_t vi = 0; vi<m.cm.vert.size(); ++vi) if (!m.cm.vert[vi].IsD())
217       {
218         bool res=false;
219         if ((projVec[vi][2] <= -1.0) || (projVec[vi][2] >= 1.0) ||
220             (projVec[vi][0] <= 0) || (projVec[vi][0] >= this->viewpSize[2]) ||
221             (projVec[vi][1] <= 0) || (projVec[vi][1] >= this->viewpSize[3]))
222           res = false;
223         else
224         {
225           res = (bufQImg.pixel( projVec[vi][0],projVec[vi][1]) == blk);
226         }
227         if (res)
228           switch(mode){
229           case 0: m.cm.vert[vi].SetS(); break;
230           case 1: m.cm.vert[vi].ClearS(); break;
231           case 2: m.cm.vert[vi].IsS() ? m.cm.vert[vi].ClearS() : m.cm.vert[vi].SetS();
232           }
233       }
234       gla->updateSelection(m.id(), true, false);
235     }
236     else if (areaMode == 1) //faces
237 	{
238       for (size_t fi = 0; fi < m.cm.face.size(); ++fi) if (!m.cm.face[fi].IsD())
239       {
240         bool res=false;
241         for (int vi = 0; vi < 3 && !res ; vi++)
242         {
243           int vInd=tri::Index(m.cm,m.cm.face[fi].V(vi));
244           if ((projVec[vInd][2] <= -1.0) || (projVec[vInd][2] >= 1.0) ||
245               (projVec[vInd][0] <= 0) || (projVec[vInd][0] >= this->viewpSize[2]) ||
246               (projVec[vInd][1] <= 0) || (projVec[vInd][1] >= this->viewpSize[3]))
247             res = false;
248           else
249             res = (bufQImg.pixel( projVec[vInd][0],projVec[vInd][1]) == blk);
250         }
251 
252         if (res) // do the actual selection
253         {
254           switch(mode){
255           case 0: m.cm.face[fi].SetS(); break;
256           case 1: m.cm.face[fi].ClearS(); break;
257           case 2: m.cm.face[fi].IsS() ? m.cm.face[fi].ClearS() : m.cm.face[fi].SetS();
258           }
259         }
260       }
261       gla->updateSelection(m.id(), false, true);
262     }
263 
264 }
265 
keyPressEvent(QKeyEvent *,MeshModel &,GLArea * gla)266 void EditSelectPlugin::keyPressEvent(QKeyEvent * /*event*/, MeshModel & /*m*/, GLArea *gla)
267 {
268 	if (selectionMode == SELECT_AREA_MODE)
269 		return;
270 
271     gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"), 1, 1));
272 	Qt::KeyboardModifiers mod = QApplication::queryKeyboardModifiers();
273     if(selectionMode == SELECT_VERT_MODE)
274     {
275         if (mod & Qt::ControlModifier)
276             gla->setCursor(QCursor(QPixmap(":/images/sel_rect_plus.png"), 1, 1));
277         else if (mod & Qt::ShiftModifier)
278             gla->setCursor(QCursor(QPixmap(":/images/sel_rect_minus.png"), 1, 1));
279     }
280     else
281     {
282         if (mod & Qt::AltModifier)
283         {
284             if (mod & Qt::ControlModifier)
285                 gla->setCursor(QCursor(QPixmap(":/images/sel_rect_plus_eye.png"), 1, 1));
286             else if (mod & Qt::ShiftModifier)
287                 gla->setCursor(QCursor(QPixmap(":/images/sel_rect_minus_eye.png"), 1, 1));
288             else
289                 gla->setCursor(QCursor(QPixmap(":/images/sel_rect_eye.png"), 1, 1));
290         }
291         else
292         {
293             if (mod & Qt::ControlModifier)
294                 gla->setCursor(QCursor(QPixmap(":/images/sel_rect_plus.png"), 1, 1));
295             else if (mod & Qt::ShiftModifier)
296                 gla->setCursor(QCursor(QPixmap(":/images/sel_rect_minus.png"), 1, 1));
297         }
298     }
299 }
300 
mousePressEvent(QMouseEvent * event,MeshModel & m,GLArea * gla)301 void EditSelectPlugin::mousePressEvent(QMouseEvent * event, MeshModel &m, GLArea *gla)
302 {
303 	if (selectionMode == SELECT_AREA_MODE)
304 	{
305 		selPolyLine.push_back(QTLogicalToOpenGL(gla, event->pos()));
306 		return;
307 	}
308 
309 	LastSelVert.clear();
310 	LastSelFace.clear();
311 
312 	if ((event->modifiers() & Qt::ControlModifier) ||
313 		(event->modifiers() & Qt::ShiftModifier))
314 	{
315 		CMeshO::FaceIterator fi;
316 		for (fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
317 			if (!(*fi).IsD() && (*fi).IsS())
318 				LastSelFace.push_back(&*fi);
319 
320 		CMeshO::VertexIterator vi;
321 		for (vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
322 			if (!(*vi).IsD() && (*vi).IsS())
323 				LastSelVert.push_back(&*vi);
324 	}
325 
326 	composingSelMode = SMClear;
327     if (event->modifiers() & Qt::ControlModifier)
328 		composingSelMode = SMAdd;
329     else if (event->modifiers() & Qt::ShiftModifier)
330 		composingSelMode = SMSub;
331 
332 	if (event->modifiers() & Qt::AltModifier)
333 		selectFrontFlag = true;
334 	else
335 		selectFrontFlag = false;
336 
337 	start = QTLogicalToOpenGL(gla, event->pos());
338 	cur = start;
339 	return;
340 }
341 
mouseMoveEvent(QMouseEvent * event,MeshModel &,GLArea * gla)342 void EditSelectPlugin::mouseMoveEvent(QMouseEvent * event, MeshModel & /*m*/, GLArea * gla)
343 {
344 	if (selectionMode == SELECT_AREA_MODE)
345 	{
346 		selPolyLine.back() = QTLogicalToOpenGL(gla, event->pos());
347 	}
348 	else
349 	{
350 		prev = cur;
351 		cur = QTLogicalToOpenGL(gla, event->pos());
352 		isDragging = true;
353 	}
354 	gla->update();
355 
356 	//    // to avoid too frequent rendering
357 	//    if(gla->lastRenderingTime() < 200 )
358 	//    {
359 	//    }
360 	//    else{
361 	//      gla->makeCurrent();
362 	//      glDrawBuffer(GL_FRONT);
363 	//      DrawXORRect(gla,true);
364 	//      glDrawBuffer(GL_BACK);
365 	//      glFlush();
366 	//    }
367 }
368 
mouseReleaseEvent(QMouseEvent * event,MeshModel &,GLArea * gla)369 void EditSelectPlugin::mouseReleaseEvent(QMouseEvent * event, MeshModel &/*m*/, GLArea * gla)
370 {
371 	//gla->update();
372 	if (gla == NULL)
373 		return;
374 
375 	gla->updateAllSiblingsGLAreas();
376 
377 	if (selectionMode == SELECT_AREA_MODE)
378 	{
379 		selPolyLine.back() = QTLogicalToOpenGL(gla, event->pos());
380 		return;
381 	}
382 
383 	prev = cur;
384 	cur = QTLogicalToOpenGL(gla, event->pos());
385 	isDragging = false;
386 }
387 
DrawXORPolyLine(GLArea * gla)388 void EditSelectPlugin::DrawXORPolyLine(GLArea * gla)
389 {
390 	if (selPolyLine.size() == 0)
391 		return;
392 
393 	glMatrixMode(GL_PROJECTION);
394 	glPushMatrix();
395 	glLoadIdentity();
396 	glOrtho(0, QTDeviceWidth(gla), 0, QTDeviceHeight(gla), -1, 1);
397 	glMatrixMode(GL_MODELVIEW);
398 	glPushMatrix();
399 	glLoadIdentity();
400 	glPushAttrib(GL_ENABLE_BIT);
401 	glDisable(GL_DEPTH_TEST);
402 	glDisable(GL_LIGHTING);
403 	glDisable(GL_TEXTURE_2D);
404 	glEnable(GL_COLOR_LOGIC_OP);
405 	glLogicOp(GL_XOR);
406 	glColor3f(1, 1, 1);
407 	glLineStipple(1, 0xAAAA);
408 	glEnable(GL_LINE_STIPPLE);
409     glLineWidth(QTLogicalToDevice(gla,1));
410 	//draw PolyLine
411 	if (selPolyLine.size() == 1)
412 	{
413 		glBegin(GL_POINTS);
414 		glVertex(selPolyLine[0]);
415 	}
416 	else if (selPolyLine.size() == 2)
417 	{
418 		glBegin(GL_LINES);
419 		glVertex(selPolyLine[0]);
420 		glVertex(selPolyLine[1]);
421 	}
422 	else
423 	{
424 		glBegin(GL_LINE_LOOP);
425 		for (size_t ii = 0; ii < selPolyLine.size(); ii++)
426 			glVertex(selPolyLine[ii]);
427 	}
428 	glEnd();
429 
430 	glDisable(GL_LOGIC_OP);
431 	// Closing 2D
432 	glPopAttrib();
433 	glPopMatrix(); // restore modelview
434 	glMatrixMode(GL_PROJECTION);
435 	glPopMatrix();
436 	glMatrixMode(GL_MODELVIEW);
437 }
438 
DrawXORRect(GLArea * gla,bool doubleDraw)439 void EditSelectPlugin::DrawXORRect(GLArea * gla, bool doubleDraw)
440 {
441 	glMatrixMode(GL_PROJECTION);
442 	glPushMatrix();
443 	glLoadIdentity();
444 	glOrtho(0, QTDeviceWidth(gla), 0, QTDeviceHeight(gla), -1, 1);
445 	glMatrixMode(GL_MODELVIEW);
446 	glPushMatrix();
447 	glLoadIdentity();
448 	glPushAttrib(GL_ENABLE_BIT);
449 	glDisable(GL_DEPTH_TEST);
450 	glDisable(GL_LIGHTING);
451 	glDisable(GL_TEXTURE_2D);
452 	glEnable(GL_COLOR_LOGIC_OP);
453 	glLogicOp(GL_XOR);
454 	glColor3f(1, 1, 1);
455 	if (doubleDraw)
456 	{
457 		glBegin(GL_LINE_LOOP);
458 		glVertex(start);
459 		glVertex2f(prev.X(), start.Y());
460 		glVertex(prev);
461 		glVertex2f(start.X(), prev.Y());
462 		glEnd();
463 	}
464 	glBegin(GL_LINE_LOOP);
465 	glVertex(start);
466 	glVertex2f(cur.X(), start.Y());
467 	glVertex(cur);
468 	glVertex2f(start.X(), cur.Y());
469 	glEnd();
470 	glDisable(GL_LOGIC_OP);
471 
472 	// Closing 2D
473 	glPopAttrib();
474 	glPopMatrix(); // restore modelview
475 	glMatrixMode(GL_PROJECTION);
476 	glPopMatrix();
477 	glMatrixMode(GL_MODELVIEW);
478 
479 }
480 
Decorate(MeshModel & m,GLArea * gla)481 void EditSelectPlugin::Decorate(MeshModel &m, GLArea * gla)
482 {
483 	if (selectionMode == SELECT_AREA_MODE)
484 	{
485 		// get proj data of last rendering
486 		glPushMatrix();
487 		glMultMatrix(m.cm.Tr);
488         GLPickTri<CMeshO>::glGetMatrixAndViewport(this->SelMatrix, this->SelViewport);
489 		glGetDoublev(GL_MODELVIEW_MATRIX, mvMatrix_f);
490 		glGetDoublev(GL_PROJECTION_MATRIX, prMatrix_f);
491 		glGetIntegerv(GL_VIEWPORT, viewpSize);
492 		glPopMatrix();
493 
494 		// draw current poly
495 		DrawXORPolyLine(gla);
496 
497 		// then, the status
498 		QString line1 = "";
499 		QString line2 = "";
500 		QString line3 = "";
501 		QString line4 = "";
502 
503 		if (areaMode == 0)
504 			line1 = "Vertices Selection - T for faces";
505 		else if (areaMode == 1)
506 			line1 = "Faces Selection - T for vertices";
507 
508 		line2 = "C to clear polyline, BACKSPACE to remove last point";
509 
510 		if (selPolyLine.size() < 3)
511 			line3 = "cannot select - more points needed";
512 		else
513 			line3 = "Q to add, W to subtract, E to invert";
514 
515 		line4 = "<br>A select all, D de-select all, I invert all";
516 
517 		this->RealTimeLog("Selection from Area", m.shortName(),
518 			"%s<br>%s<br>%s<br>%s", line1.toStdString().c_str(), line2.toStdString().c_str(), line3.toStdString().c_str(), line4.toStdString().c_str());
519 
520 		return;
521 	}
522 	else
523 	{
524 		QString line1, line2, line3;
525 
526 		line1 = "Drag to select";
527 		if ((selectionMode == SELECT_FACE_MODE) || (selectionMode == SELECT_CONN_MODE))
528 			line2 = "you may hold:<br>- CTRL to add<br>- SHIFT to subtract<br>- ALT to select only visible";
529 		else
530 			line2 = "you may hold:<br>- CTRL to add<br>- SHIFT to subtract";
531 		line3 = "<br>A select all, D de-select all, I invert all";
532 
533 		this->RealTimeLog("Interactive Selection", m.shortName(), "%s<br>%s<br>%s", line1.toStdString().c_str(), line2.toStdString().c_str(), line3.toStdString().c_str());
534 	}
535 
536 	if (isDragging)
537 	{
538 		DrawXORRect(gla, false);
539 		vector<CMeshO::FacePointer>::iterator fpi;
540 		// Starting Sel
541 		vector<CMeshO::FacePointer> NewSelFace;
542 		Point2f mid = (start + cur) / 2;
543 		Point2f wid = vcg::Abs(start - cur);
544 
545 		glPushMatrix();
546 		glMultMatrix(m.cm.Tr);
547 		if (selectionMode == SELECT_VERT_MODE)
548 		{
549 			//m.cm.selvert.clear();
550 			vector<CMeshO::VertexPointer> NewSelVert;
551 			vector<CMeshO::VertexPointer>::iterator vpi;
552 
553 			GLPickTri<CMeshO>::PickVert(mid[0], mid[1], m.cm, NewSelVert, wid[0], wid[1]);
554 			glPopMatrix();
555 			tri::UpdateSelection<CMeshO>::VertexClear(m.cm);
556 
557 			switch (composingSelMode)
558 			{
559 			case SMSub:  // Subtract mode : The faces in the rect must be de-selected
560 				for (vpi = LastSelVert.begin(); vpi != LastSelVert.end(); ++vpi)
561 					(*vpi)->SetS();
562 				for (vpi = NewSelVert.begin(); vpi != NewSelVert.end(); ++vpi)
563 					(*vpi)->ClearS();
564 				break;
565 			case SMAdd:  // Subtract mode : The faces in the rect must be de-selected
566 				for (vpi = LastSelVert.begin(); vpi != LastSelVert.end(); ++vpi)
567 					(*vpi)->SetS();
568 			case SMClear:  // Subtract mode : The faces in the rect must be de-selected
569 				for (vpi = NewSelVert.begin(); vpi != NewSelVert.end(); ++vpi)
570 					(*vpi)->SetS();
571 				break;
572 			}
573 			//for (unsigned int ii = 0; ii < m.cm.VN(); ++ii)
574 			//{
575 			//	CVertexO& vv = m.cm.vert[ii];
576 			//	if (!vv.IsD() && vv.IsS())
577 			//	{
578 			//		m.cm.selvert.push_back(Point3m::Construct(vv.cP()));
579 			//		++m.cm.svn;
580 			//	}
581 			//}
582 			gla->updateSelection(m.id(), true,false);
583 		}
584 		else
585 		{
586 			//m.cm.selface.clear();
587 			if (selectFrontFlag)	GLPickTri<CMeshO>::PickVisibleFace(mid[0], mid[1], m.cm, NewSelFace, wid[0], wid[1]);
588 			else                GLPickTri<CMeshO>::PickFace(mid[0], mid[1], m.cm, NewSelFace, wid[0], wid[1]);
589 
590 			//    qDebug("Pickface: rect %i %i - %i %i",mid.x(),mid.y(),wid.x(),wid.y());
591 			//    qDebug("Pickface: Got  %i on %i",int(NewSelFace.size()),int(m.cm.face.size()));
592 			glPopMatrix();
593 			tri::UpdateSelection<CMeshO>::FaceClear(m.cm);
594 			switch (composingSelMode)
595 			{
596 			case SMSub:  // Subtract mode : The faces in the rect must be de-selected
597 				if (selectionMode == SELECT_CONN_MODE)
598 				{
599 					for (fpi = NewSelFace.begin(); fpi != NewSelFace.end(); ++fpi)
600 						(*fpi)->SetS();
601 					tri::UpdateSelection<CMeshO>::FaceConnectedFF(m.cm);
602 					NewSelFace.clear();
603 					for (CMeshO::FaceIterator fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)
604 						if (!(*fi).IsD() && (*fi).IsS()) NewSelFace.push_back(&*fi);
605 				}
606 				// Normal case: simply deselect what has been selected.
607 				for (fpi = LastSelFace.begin(); fpi != LastSelFace.end(); ++fpi)
608 					(*fpi)->SetS();
609 				for (fpi = NewSelFace.begin(); fpi != NewSelFace.end(); ++fpi)
610 					(*fpi)->ClearS();
611 				break;
612 			case SMAdd:
613 				for (fpi = LastSelFace.begin(); fpi != LastSelFace.end(); ++fpi)
614 					(*fpi)->SetS();
615 			case SMClear:
616 				for (fpi = NewSelFace.begin(); fpi != NewSelFace.end(); ++fpi)
617 					(*fpi)->SetS();
618 				if (selectionMode == SELECT_CONN_MODE)
619 					tri::UpdateSelection<CMeshO>::FaceConnectedFF(m.cm);
620 				break;
621 			}
622 			gla->updateSelection(m.id(), false, true);
623 			isDragging = false;
624 		}
625 
626 	}
627 }
628 
StartEdit(MeshModel & m,GLArea * gla,MLSceneGLSharedDataContext *)629 bool EditSelectPlugin::StartEdit(MeshModel & m, GLArea * gla, MLSceneGLSharedDataContext* /*cont*/)
630 {
631 	if (gla == NULL)
632 		return false;
633 	if (!GLExtensionsManager::initializeGLextensions_notThrowing())
634 		return false;
635 	gla->setCursor(QCursor(QPixmap(":/images/sel_rect.png"), 1, 1));
636 
637 	if (selectionMode == SELECT_AREA_MODE)
638 	{
639 		if (m.cm.fn > 0)
640 			areaMode = 1;
641 		else
642 			areaMode = 0;
643 
644 		selPolyLine.clear();
645         gla->setCursor(QCursor(QPixmap(":/images/sel_area.png"), 1, 1));
646 	}
647 
648 	if (selectionMode == SELECT_VERT_MODE)
649 		areaMode = 0;
650 
651 	if ((selectionMode == SELECT_FACE_MODE) || (selectionMode == SELECT_CONN_MODE))
652 		areaMode = 1;
653 
654 	if (selectionMode == SELECT_CONN_MODE)
655 		m.updateDataMask(MeshModel::MM_FACEFACETOPO);
656 	return true;
657 }
658