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