Salome HOME
*** empty log message ***
[modules/gui.git] / src / GLViewer / GLViewer_Context.cxx
1 // File:      GLViewer_Context.cxx
2 // Created:   November, 2004
3 // Author:    OCC team
4 // Copyright (C) CEA 2004
5
6 /****************************************************************************
7 **  Class:   GLViewer_Context 
8 **  Descr:   OpenGL Context
9 **  Module:  GLViewer
10 **  Created: UI team, 20.09.02
11 *****************************************************************************/
12
13 #include "GLViewer_Context.h"
14
15 #include "GLViewer_Object.h"
16 #include "GLViewer_Viewer2d.h"
17 #include "GLViewer_ViewPort2d.h"
18
19 #include <TColStd_SequenceOfInteger.hxx>
20
21 #define TOLERANCE  12
22
23 GLViewer_Context::GLViewer_Context( GLViewer_Viewer2d* v ) :
24        myGLViewer2d( v ),
25        myHighlightColor( Quantity_NOC_CYAN1 ),
26        mySelectionColor( Quantity_NOC_RED ),
27        myTolerance( TOLERANCE ),
28        myNumber( 0 )
29 {
30   myLastPicked = NULL;
31   isLastPickedChanged = false;
32   myHFlag = GL_TRUE;
33   mySFlag = GL_TRUE;
34   mySelCurIndex = 0;
35 }
36
37 GLViewer_Context::~GLViewer_Context()
38 {
39 }
40
41 int GLViewer_Context::MoveTo( int xi, int yi, bool byCircle )
42 {
43   GLfloat x = (GLfloat)xi;
44   GLfloat y = (GLfloat)yi;
45   myGLViewer2d->transPoint( x, y );
46   //cout << "GLViewer_Context::MoveTo " << x << " " << y << endl;
47
48   QValueList<GLViewer_Object*> anUpdatedObjects;
49   
50   ObjectMap::Iterator it;
51   
52   myXhigh = x;
53   myYhigh = y;  
54   
55   //if( !myHFlag )
56   //  return 1;
57
58   GLfloat aXScale;
59   GLfloat aYScale;
60   GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )myGLViewer2d->getActiveView()->getViewPort();
61   vp->getScale( aXScale, aYScale );
62
63   //bool onlyUpdate = true;
64   GLboolean update = GL_FALSE;
65   GLboolean isHigh = GL_FALSE;
66   GLboolean onObject = GL_FALSE;
67   
68   GLViewer_Object* aPrevLastPicked = myLastPicked;
69   GLViewer_Object* lastPicked = NULL;
70   QRect* rect;
71   QRegion obj;
72   QRegion intersection;
73   QRect region;
74
75   region.setLeft( (int)(x - myTolerance) );
76   region.setRight( (int)(x + myTolerance) );
77   region.setTop( (int)(y - myTolerance) );
78   region.setBottom( (int)(y + myTolerance) );
79
80   for( it = myObjects.begin(); it != myObjects.end(); ++it )
81   {
82     it.key()->setScale( aXScale, aYScale );
83     rect = it.key()->getUpdateRect()->toQRect();
84     obj = QRegion( *rect );
85
86     if( !byCircle && rect->intersects( region ) )
87     {
88       //      cout << "object : " << it.data() << endl;
89       update = it.key()->highlight( x, y, myTolerance, GL_FALSE );
90       isHigh = it.key()->isHighlighted();
91       onObject = GL_TRUE;
92       //if( update )
93       //    cout << "update" << endl;
94       //if( isHigh )
95       //    cout << "highlight" << endl;
96     }
97
98     if( byCircle )
99     {
100       QRegion circle( (int)(x - myTolerance), (int)(y - myTolerance),
101                       (int)(2 * myTolerance), (int)(2 * myTolerance), QRegion::Ellipse );
102       intersection = obj.intersect( circle );
103       if( !intersection.isEmpty() )
104       {
105         update = it.key()->highlight( x, y, myTolerance, GL_TRUE );
106         isHigh = it.key()->isHighlighted();
107         onObject = GL_TRUE;
108       }
109     }
110
111     if( isHigh )
112     {
113       lastPicked = it.key();
114       break;
115     }
116   }
117
118   if( !myHFlag )
119   {
120     myLastPicked = lastPicked; //we need this information everytime
121     return -1;
122   }
123   
124   if ( !onObject )
125   {
126     for( it = myObjects.begin(); it != myObjects.end(); ++it )
127       if( it.key()->unhighlight() )
128         anUpdatedObjects.append( it.key() );
129     
130     myLastPicked = NULL;
131     isLastPickedChanged = aPrevLastPicked != myLastPicked;
132     
133     if( isLastPickedChanged )
134       myGLViewer2d->updateAll();  
135     
136     return 0;
137   }
138   
139   if( !myLastPicked && isHigh )
140   {
141     //cout << "1" << endl;
142     myLastPicked = lastPicked;
143     myHNumber = myObjects[ lastPicked ];
144     anUpdatedObjects.append( myLastPicked );
145   }
146   else if( myLastPicked && !isHigh )
147   {
148     //cout << "2" << endl;
149     //onlyUpdate = 
150     myLastPicked->unhighlight();
151     anUpdatedObjects.append( myLastPicked );
152     //eraseObject( myLastPicked, true );
153     myLastPicked = NULL;
154     myHNumber = -1;
155   }
156   else if( myLastPicked && isHigh )
157   {
158     //cout << "3" << endl;
159     //cout << "HNumber" << myHNumber << endl;
160
161     myLastPicked->highlight( x, y, myTolerance, byCircle );
162     if( !myLastPicked->isHighlighted() )
163     {
164       myLastPicked->unhighlight();
165       anUpdatedObjects.append( myLastPicked );
166       myLastPicked = lastPicked;
167       myHNumber = myObjects[ lastPicked ];
168     }
169     anUpdatedObjects.append( myLastPicked );
170   }
171
172   isLastPickedChanged = ( aPrevLastPicked != myLastPicked );
173
174   if( isLastPickedChanged/*!onlyUpdate*/ )
175     {
176       myGLViewer2d->updateAll();
177       //myGLViewer2d->activateAllDrawers( true );
178     }
179   else
180     myGLViewer2d->activateDrawers( anUpdatedObjects, TRUE, TRUE );
181
182   return 0;
183 }
184
185 int GLViewer_Context::Select( bool Append, bool byCircle )
186 {
187   //cout << "GLViewer_Context::Select " << (int)Append << endl;
188   QValueList<int>::Iterator it;
189   ObjectMap::Iterator oit;
190   SelectionStatus status = SS_Invalid;
191
192   bool onlyUpdate = false;
193
194   QValueList<GLViewer_Object*> aList;
195
196   if ( !mySFlag )
197     return status;//invalid
198   
199   if( myHFlag && myLastPicked )
200   {
201     if( mySelNumbers.count() == 1 && mySelNumbers.first() == myHNumber )
202       status = SS_LocalChanged;
203     
204     if ( !Append )
205     {
206       for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
207         for( oit = myObjects.begin(); oit != myObjects.end(); ++oit )
208           if( *it == myObjects[ oit.key() ] )
209             if ( myLastPicked != oit.key() )
210             {
211                 onlyUpdate = oit.key()->unselect();
212                 aList.append( oit.key() );
213             }
214
215       if( onlyUpdate )
216         myGLViewer2d->updateAll();
217       else
218         myGLViewer2d->activateDrawers( aList, TRUE, TRUE );
219
220       if( mySelNumbers.count() != 0 && status == SS_Invalid )
221         status = SS_GlobalChanged;
222       mySelNumbers.clear();
223     } 
224
225     if ( myLastPicked->select( myXhigh, myYhigh, myTolerance, GLViewer_Rect(), false, byCircle, Append )
226       && mySelNumbers.findIndex( myHNumber ) == -1 )
227       /*if ( myLastPicked->select( myXhigh, myYhigh, myTolerance, byCircle, Append ) )
228       //&&( mySelNumbers.findIndex( myHNumber ) == -1 ) )*/
229     {
230       mySelNumbers.append( myHNumber );
231       //cout << "context::select object #" << myHNumber << endl;
232       myGLViewer2d->activateDrawer( myLastPicked, TRUE, TRUE );
233       
234       if( status == SS_Invalid )
235         status = SS_GlobalChanged;
236 //      else
237 //        status = SS_GlobalChanged;
238     }
239     else if( status == SS_LocalChanged )
240       status = SS_GlobalChanged;
241     
242     return status;
243   }
244   
245   if( myHFlag && !myLastPicked )
246   {
247     if ( !Append )
248     {
249       for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
250         for( oit = myObjects.begin(); oit != myObjects.end(); ++oit )
251           if( *it == myObjects[ oit.key() ] )
252           {
253             onlyUpdate = oit.key()->unselect();
254             //list.Append( *it );
255             aList.append( oit.key() );
256           } 
257      
258       if( onlyUpdate )
259           myGLViewer2d->updateAll();
260       else
261         myGLViewer2d->activateDrawers( aList, TRUE, TRUE );
262
263       if( mySelNumbers.count() != 0 )
264         status = SS_GlobalChanged;
265       
266       mySelNumbers.clear();
267       //cout << " myHFlag && !myLastPicked  " << endl;
268     }
269     return status;
270   }
271
272 //   if( !myHFlag )
273 //   {
274 //     GLViewer_Object* lastPicked = NULL;
275 //     GLboolean update = FALSE;
276 //     GLboolean isSel = GL_FALSE;
277 //     list = new int[2];
278 //     number = 0;
279 //     float xa, xb, ya, yb;
280 //     QRect* rect;
281
282 //     ObjectMap::Iterator it;
283 //     for( it = myObjects.begin(); it != myObjects.end(); ++it )
284 //     {
285 //       rect = it.key()->getRect();
286 //       xa = rect->left();
287 //       xb = rect->right();
288 //       ya = rect->top();
289 //       yb = rect->bottom();      
290       
291 //       if( myXhigh >= xa && myXhigh <= xb && myYhigh >= ya && myYhigh <= yb )
292 //       {
293 //  update = it.key()->select( myXhigh, myYhigh, myTolerance, byCircle, Append );
294 //  isSel = it.key()->isSelected();
295 //  if( isSel )
296 //  {
297 //    myLastPicked = it.key();
298 //    number = myObjects[ lastPicked ];
299 //  }
300 //       }
301 //     }
302
303 //     if ( !Append )
304 //     {
305 //       for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
306 //  for( it1 = myObjects.begin(); it1 != myObjects.end(); ++it1 )
307 //    if( *it == myObjects[ it1.key() ] )
308 //    {
309 //      it1.key()->unselect();
310 //      myGLViewer2d->initDrawer( it1.key(), it.data() );
311 //      list.Append( *it );
312 //    }      
313 //       myGLViewer2d->activateDrawers( list, TRUE );
314 //       mySelNumbers.clear();
315 //     }
316 //     if ( mySelNumbers.findIndex( myObjects[lastPicked] ) == -1)
317 //       mySelNumbers.append( myObjects[lastPicked] );
318
319 //     number = mySelNumbers.count();
320 //     list = new int[number + 1];
321 //     list[0] = number;
322     
323 //     for( it = mySelNumbers.begin(), i = 1; it != mySelNumbers.end(); ++it, i++ )
324 //       list[i] = *it;
325
326 //     myGLViewer2d->initDrawer( myLastPicked, myHNumber );
327 //     myGLViewer2d->activateDrawers( list, TRUE );
328 //   }
329
330   if( !myHFlag )
331   {
332     bool isSel = false;
333     GLfloat aXScale;
334     GLfloat aYScale;
335     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )myGLViewer2d->getActiveView()->getViewPort();
336     vp->getScale( aXScale, aYScale );
337     
338     QRect* rect;
339     QRect region;
340     QRegion obj;
341     
342     region.setLeft( ( int )( myXhigh - myTolerance ) );
343     region.setRight( ( int )( myXhigh + myTolerance ) );
344     region.setTop( ( int )( myYhigh - myTolerance ) );
345     region.setBottom( ( int )( myYhigh + myTolerance ) );
346     
347     QRegion circle( ( int )( myXhigh - myTolerance ), ( int )( myYhigh - myTolerance ),
348                     2 * myTolerance, 2 * myTolerance, QRegion::Ellipse );
349     
350     if ( !Append )
351     {
352       for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
353         for( oit = myObjects.begin(); oit != myObjects.end(); ++oit )
354           if( *it == myObjects[ oit.key() ] )
355           {
356             onlyUpdate |= (bool)oit.key()->unselect();
357             aList.append( oit.key() );
358           }
359       
360       if( onlyUpdate )
361         myGLViewer2d->updateAll();
362       else
363         myGLViewer2d->activateDrawers( aList, TRUE, TRUE );
364       
365       if( mySelNumbers.count() != 0 )
366         status = SS_GlobalChanged;
367
368       mySelNumbers.clear();
369     }        
370
371     for( oit = myObjects.begin(); oit != myObjects.end(); ++oit )
372     {
373       oit.key()->setScale( aXScale, aYScale );
374       rect = oit.key()->getUpdateRect()->toQRect();
375       obj = QRegion( *rect );
376       
377       if( !byCircle && rect->intersects( region ) )
378       {
379         oit.key()->select( myXhigh, myYhigh, myTolerance, GLViewer_Rect(), false, byCircle, Append );
380         isSel = oit.key()->isSelected();
381       }
382       
383       if( byCircle && !obj.intersect( circle ).isEmpty() )
384       {
385         oit.key()->select( myXhigh, myYhigh, myTolerance, GLViewer_Rect(), false, byCircle, Append );
386         isSel = oit.key()->isSelected();
387       }
388       if( isSel )
389       {
390         myLastPicked = oit.key();
391         mySelNumbers.append( myObjects[ myLastPicked ] );
392         myGLViewer2d->activateDrawer( myLastPicked, TRUE, TRUE );
393         status = SS_GlobalChanged;
394         return status;
395       }
396     }
397   }
398         
399   return SS_NoChanged;
400 }
401
402 int GLViewer_Context::SelectByRect( const QRect& theRect, bool Append )
403 {
404     GLfloat aXScale;
405     GLfloat aYScale;
406     GLViewer_ViewPort2d* vp = ( GLViewer_ViewPort2d* )myGLViewer2d->getActiveView()->getViewPort();
407     vp->getScale( aXScale, aYScale );
408
409     SelectionStatus status = SS_NoChanged;
410
411     QValueList<int>::Iterator it;
412     ObjectMap::Iterator oit;
413
414     QValueList<GLViewer_Object*> aList;
415
416     if ( !mySFlag || myObjList.empty() )
417         return SS_Invalid;
418
419     bool updateAll = false;
420     if( !Append )
421     {
422         if( mySelNumbers.count() != 0 )
423             status = SS_GlobalChanged;
424
425         for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
426             for( oit = myObjects.begin(); oit != myObjects.end(); ++oit )
427                 if( *it == myObjects[ oit.key() ] )
428                 {
429                     updateAll |= (bool)oit.key()->unselect();
430                     aList.append( oit.key() );
431                 }
432         mySelNumbers.clear();
433     }
434
435     for( oit = myObjects.begin(); oit != myObjects.end(); ++oit )
436     {
437         bool isSel = false;
438         oit.key()->setScale( aXScale, aYScale );
439         QRect rect = //myGLViewer2d->getWinObjectRect( oit.key() ); //->getUpdateRect()->toQRect();
440           myGLViewer2d->getQRect( *(oit.key()->getRect()) );
441
442         if( rect.intersects( theRect ) )
443         {
444             GLViewer_Rect aRect = myGLViewer2d->getGLVRect( theRect );
445             oit.key()->select( myXhigh, myYhigh, myTolerance, aRect, false, false, Append );
446             isSel = oit.key()->isSelected();
447         }
448
449         if( isSel && mySelNumbers.findIndex( oit.data() ) == -1 )
450         {
451             aList.append( oit.key() );
452             mySelNumbers.append( oit.data() );
453             status = SS_GlobalChanged;
454         }
455     }
456
457     if( updateAll ) //i.e only update
458     {
459         //cout << "Unhilight.ALL" << endl;
460         myGLViewer2d->updateAll();
461     }
462     else
463         myGLViewer2d->activateDrawers( aList, TRUE, TRUE );
464
465     return status;
466 }
467
468 void GLViewer_Context::SetHighlightColor( Quantity_NameOfColor aCol )
469 {
470   myHighlightColor = aCol;
471   
472   Quantity_Color colorH( aCol );
473   int redH = 255 * (int)colorH.Red();
474   int greenH = 255 * (int)colorH.Green();
475   int blueH = 255 * (int)colorH.Blue();
476   QColor colH = QColor( redH, greenH, blueH );
477
478   Quantity_Color colorS( mySelectionColor );
479   int redS = 255 * (int)colorS.Red();
480   int greenS = 255 * (int)colorS.Green();
481   int blueS = 255 * (int)colorS.Blue();
482   QColor colS = QColor( redS, greenS, blueS );
483
484   myGLViewer2d->updateColors( colH, colS);
485 }
486
487 void GLViewer_Context::SetSelectionColor( Quantity_NameOfColor aCol )
488 {
489   mySelectionColor = aCol;
490   
491   Quantity_Color colorH( myHighlightColor );
492   int redH = 255 * (int)colorH.Red();
493   int greenH = 255 * (int)colorH.Green();
494   int blueH = 255 * (int)colorH.Blue();
495   QColor colH = QColor( redH, greenH, blueH );
496
497   Quantity_Color colorS( aCol );
498   int redS = 255 * (int)colorS.Red();
499   int greenS = 255 * (int)colorS.Green();
500   int blueS = 255 * (int)colorS.Blue();
501   QColor colS = QColor( redS, greenS, blueS );
502
503   myGLViewer2d->updateColors( colH, colS);
504 }
505
506 int GLViewer_Context::NbSelected()
507 {
508   return mySelNumbers.count();
509 }
510
511 void GLViewer_Context::InitSelected()
512 {
513   mySelCurIndex = 0;
514 }
515
516 bool GLViewer_Context::MoreSelected()
517 {
518   return ( mySelCurIndex < NbSelected() );
519 }
520
521 bool GLViewer_Context::NextSelected()
522 {
523   if ( mySelCurIndex >= 0 && mySelCurIndex < NbSelected() )
524   {
525     mySelCurIndex++;
526     return TRUE;
527   }
528
529   return FALSE;
530 }
531
532 GLViewer_Object* GLViewer_Context::SelectedObject()
533 {
534     ObjectMap::Iterator it;
535     for( it = myObjects.begin(); it != myObjects.end(); ++it )
536         if( mySelNumbers[mySelCurIndex] == it.data() )
537             return it.key();
538
539     return NULL;
540 }
541
542 bool  GLViewer_Context::isSelected( GLViewer_Object* theObj )
543 {
544   for( InitSelected(); MoreSelected(); NextSelected() )
545     if( SelectedObject() == theObj )
546       return true;
547
548   return false;
549 }
550
551 int GLViewer_Context::insertObject( GLViewer_Object* object, bool display )
552 {
553 //  cout << "GLViewer_Context::insertObject" << endl;
554   
555     myObjects.insert( object, myNumber++ );
556     myObjList.append( object );
557
558     if( display )
559     {
560         //QRect* rect = object->getRect()->toQRect();
561         //myGLViewer2d->updateBorders( *rect );
562         myGLViewer2d->activateDrawer( object, FALSE );
563     }
564
565     return myNumber - 1;
566 }
567
568 bool GLViewer_Context::replaceObject( GLViewer_Object* oldObject, GLViewer_Object* newObject )
569 {
570   if( myObjects.contains( oldObject ) )
571   {
572     int index = myObjects[ oldObject ];
573     myObjects.remove( oldObject );
574     myObjects.insert( newObject, index );
575     return GL_TRUE;
576   }
577
578   return GL_FALSE;
579 }
580
581 void GLViewer_Context::updateScales( GLfloat scX, GLfloat scY )
582 {
583   if( scX && scY )
584     for ( ObjectMap::Iterator it = myObjects.begin(); it != myObjects.end(); ++it )
585       it.key()->setScale( scX, scY );
586 }
587
588 void GLViewer_Context::clearSelected( bool updateViewer )
589 {
590   QValueList<int>::Iterator it;
591   ObjectMap::Iterator oit;
592
593   TColStd_SequenceOfInteger list;
594
595   if( !mySFlag )
596     return ;
597
598   for( it = mySelNumbers.begin(); it != mySelNumbers.end(); ++it )
599     for( oit = myObjects.begin(); oit != myObjects.end(); ++oit )
600       if( *it == myObjects[ oit.key() ] )
601       {         
602         oit.key()->unselect();
603         //myGLViewer2d->initDrawer( oit.key(), oit.data() );
604         ///myGLViewer2d->initDrawer( oit.key() );
605         list.Append( *it );
606       }          
607         
608   if( updateViewer )
609     myGLViewer2d->activateDrawers( list, TRUE );
610   mySelNumbers.clear();    
611 }
612
613 void GLViewer_Context::setSelected( GLViewer_Object* object, bool updateViewer )
614 {
615   int index = -1;
616   if ( myObjects.contains( object ) )
617     index = myObjects[object];
618
619   if( index == -1 || mySelNumbers.findIndex( index ) != -1 )
620     return;
621
622   mySelNumbers.append( index );
623   object->setSelected( TRUE );
624
625   if( updateViewer )
626     myGLViewer2d->activateDrawer( object, TRUE, TRUE );
627 }
628
629 void GLViewer_Context::remSelected( GLViewer_Object* object, bool updateViewer )
630 {
631   int index = -1;
632   if ( myObjects.contains( object ) )
633     index = myObjects[object];
634
635   if( index == -1 || mySelNumbers.findIndex( index ) == -1 )
636     return;
637   
638   mySelNumbers.remove( index );
639   object->unselect();
640
641   if( updateViewer )
642     myGLViewer2d->activateDrawer( object, TRUE, TRUE );
643 }
644
645 void GLViewer_Context::eraseObject( GLViewer_Object* theObject, bool theUpdateViewer )
646 {
647     if( !theObject )
648         return;
649
650     theObject->unhighlight();
651     theObject->unselect();
652     theObject->setVisible( false );
653
654     if( theUpdateViewer )
655         myGLViewer2d->updateAll();
656         //myGLViewer2d->activateAllDrawers( true );
657 }
658
659 void GLViewer_Context::deleteObject( GLViewer_Object* theObject, bool updateViewer )
660 {
661     if( !theObject || !myObjects.contains(theObject) )
662         return;
663
664     int anIndex = myObjects[theObject];
665     myObjects.remove( theObject );
666     myObjList.remove( theObject );
667
668     if( myLastPicked == theObject )
669     {
670         myLastPicked = NULL;
671         myHNumber = -1;
672     }
673
674     QValueList<int>::Iterator anIt= mySelNumbers.find( anIndex );
675     if( anIt != mySelNumbers.end() )
676         mySelNumbers.remove( anIt );
677
678     if( mySelCurIndex == anIndex )
679         mySelCurIndex = 0;
680
681     if ( updateViewer )
682       myGLViewer2d->updateAll();
683 }