Salome HOME
c8cefc3d9273c40df663a57c84a4f3fce86d3a8d
[modules/hydro.git] / src / HYDROGUI / HYDROGUI_Shape.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 #include <HYDROGUI_Shape.h>
24 #include <HYDROGUI_Tool.h>
25 #include <HYDROData_Channel.h>
26 #include <HYDROData_Document.h>
27 #include <HYDROData_DummyObject3D.h>
28 #include <HYDROData_ImmersibleZone.h>
29 #include <HYDROData_Obstacle.h>
30 #include <HYDROData_PolylineXY.h>
31 #include <HYDROData_Polyline3D.h>
32 #include <HYDROData_Profile.h>
33 #include <HYDROData_ShapesGroup.h>
34 #include <HYDROData_Stream.h>
35 #include <HYDROData_Zone.h>
36 #include <HYDROGUI_Polyline.h>
37
38 #include <AIS_Shape.hxx>
39 #include <BRep_Builder.hxx>
40 #include <BRepBuilderAPI_MakeFace.hxx>
41 #include <Graphic3d_AspectFillArea3d.hxx>
42 #include <Prs3d_IsoAspect.hxx>
43 #include <Prs3d_ShadingAspect.hxx>
44 #include <TopoDS.hxx>
45 #include <TopoDS_Face.hxx>
46 #include <TopoDS_Wire.hxx>
47 #include <TopExp_Explorer.hxx>
48
49 HYDROGUI_Shape::HYDROGUI_Shape( const Handle(AIS_InteractiveContext)& theContext,
50                                 const Handle(HYDROData_Entity)&       theObject,
51                                 const int                             theZLayer )
52 : myContext( theContext ),
53   myObject( theObject ),
54   myZLayer( theZLayer ),
55   myIsHighlight( false ),
56   myFillingColor( Qt::transparent ),
57   myBorderColor( Qt::black ),
58   myHighlightColor( Qt::white ),
59   myIsToUpdate( false ),
60   myIsVisible( true ),
61   myDisplayMode( AIS_Shaded )
62 {
63 }
64
65 HYDROGUI_Shape::~HYDROGUI_Shape()
66 {
67   erase( false );
68
69   if ( !myShape.IsNull() )
70     myShape.Nullify();
71 }
72
73 Handle(AIS_InteractiveContext) HYDROGUI_Shape::getContext() const
74 {
75   return myContext;
76 }
77
78 Handle(HYDROData_Entity) HYDROGUI_Shape::getObject() const
79 {
80   return myObject;
81 }
82
83 TopoDS_Shape HYDROGUI_Shape::getTopoShape() const
84 {
85   return myTopoShape;
86 }
87
88 bool HYDROGUI_Shape::getIsToUpdate() const
89 {
90   return myIsToUpdate;
91 }
92
93 void HYDROGUI_Shape::setIsToUpdate( bool theState )
94 {
95   myIsToUpdate = theState;
96 }
97
98 bool HYDROGUI_Shape::isVisible() const
99 {
100   return myIsVisible;
101 }
102
103 Handle(AIS_InteractiveObject) HYDROGUI_Shape::getAISObject() const
104 {
105   return myShape;
106 }
107
108 void HYDROGUI_Shape::display( const bool theIsUpdateViewer )
109 {
110   if ( myContext.IsNull() || myShape.IsNull() || !isVisible() )
111     return;
112
113   displayShape( theIsUpdateViewer );
114 }
115
116 void HYDROGUI_Shape::erase( const bool theIsUpdateViewer )
117 {
118   if ( myContext.IsNull() || myShape.IsNull() )
119     return;
120
121   myContext->Erase( myShape, theIsUpdateViewer );
122 }
123
124 void HYDROGUI_Shape::update( bool isUpdateViewer,
125                              bool isDeactivateSelection )
126
127 {
128   setIsToUpdate( false );
129
130   if ( myContext.IsNull() )
131     return;
132
133   // Try to retrieve information from object
134   if ( !myObject.IsNull() )
135   {
136     Handle(HYDROData_Document) aDocument = HYDROData_Document::Document( myObject->Label() );
137   
138     if ( myObject->IsKind( STANDARD_TYPE(HYDROData_ImmersibleZone) ) )
139     {
140       Handle(HYDROData_ImmersibleZone) aZoneObj =
141         Handle(HYDROData_ImmersibleZone)::DownCast( myObject );
142
143       TopoDS_Shape aZoneShape = aZoneObj->GetTopShape();
144       if ( !aZoneShape.IsNull() ) {
145         if ( aZoneShape.ShapeType() == TopAbs_FACE ) {
146           TopoDS_Face aZoneFace = TopoDS::Face( aZoneShape );
147           setFace( aZoneFace, false, false, "" );
148         } else {
149           myTopoShape = aZoneShape;
150           //TODO: myDisplayMode = myTextureFileName.isEmpty() ? AIS_Shaded : AIS_Shaded+2;
151           myDisplayMode = AIS_Shaded;
152
153           buildShape();
154           updateShape( false, false );
155         }
156       }
157
158       QColor aFillingColor = aZoneObj->GetFillingColor();
159       QColor aBorderColor = aZoneObj->GetBorderColor();
160
161       setFillingColor( aFillingColor, false, false );
162       setBorderColor( aBorderColor, false, false );
163     }
164     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_PolylineXY) ) )
165     {
166       Handle(HYDROData_PolylineXY) aPolyline =
167         Handle(HYDROData_PolylineXY)::DownCast( myObject );
168
169       TopoDS_Shape aPolylineShape = aPolyline->GetShape();
170
171       if ( !aPolylineShape.IsNull() ) {
172         if ( aPolylineShape.ShapeType() == TopAbs_WIRE ) {
173           TopoDS_Wire aPolylineWire = TopoDS::Wire( aPolylineShape );
174           setWire( aPolylineWire, false, false );  
175         } else {
176           myTopoShape = aPolylineShape;
177           // Set shading mode to avoid that hilight presentation is equal to "normal" object presentation.
178           // Note that hilight presentation is always to be on top ( i.e. in the top Z layer ).
179           myDisplayMode = AIS_Shaded;
180
181           buildShape();
182           updateShape( false, false );
183         }
184       }
185
186       QColor aWireColor = aPolyline->GetWireColor();
187       setBorderColor( aWireColor, false, false );
188     }
189     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_Polyline3D) ) )
190     {
191       Handle(HYDROData_Polyline3D) aPolyline =
192         Handle(HYDROData_Polyline3D)::DownCast( myObject );
193
194       TopoDS_Shape aPolylineShape = aPolyline->GetShape3D();
195
196       if ( !aPolylineShape.IsNull() ) {
197         if ( aPolylineShape.ShapeType() == TopAbs_WIRE ) {
198           TopoDS_Wire aPolylineWire = TopoDS::Wire( aPolylineShape );
199           setWire( aPolylineWire, false, false );  
200         } else {
201           myTopoShape = aPolylineShape;
202           // Set shading mode to avoid that hilight presentation is equal to "normal" object presentation.
203           // Note that hilight presentation is always to be on top ( i.e. in the top Z layer ).
204           myDisplayMode = AIS_Shaded;
205
206           buildShape();
207           updateShape( false, false );
208         }
209       }
210
211       QColor aWireColor = aPolyline->GetBorderColor();
212       setBorderColor( aWireColor, false, false );
213     }
214     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_Zone) ) )
215     {
216       Handle(HYDROData_Zone) aZone =
217         Handle(HYDROData_Zone)::DownCast( myObject );
218
219       TopoDS_Face aZoneFace = TopoDS::Face( aZone->GetShape() );
220
221       setFace( aZoneFace, false, false, "" );
222       if (aZone->IsMergingNeed() && aZone->GetMergeType() == HYDROData_Zone::Merge_UNKNOWN )
223       {
224         // Red color for a zone with bathymetry conflict
225         setFillingColor( Qt::red );
226       }
227       else
228       {
229                 // Set the filling color for zone
230                 setFillingColor( aZone->GetColor(HYDROData_ImmersibleZone::DefaultFillingColor()) );
231       }
232     }
233     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_Profile) ) )
234     {
235       Handle(HYDROData_Profile) aProfile =
236         Handle(HYDROData_Profile)::DownCast( myObject );
237
238       TopoDS_Wire aProfileWire;
239
240       if ( aProfile->IsValid() ) {
241         TopoDS_Shape aProfileShape = aProfile->GetShape3D();
242
243         if ( !aProfileShape.IsNull() && 
244              aProfileShape.ShapeType() == TopAbs_WIRE ) {
245           aProfileWire = TopoDS::Wire( aProfileShape );
246         }
247       }
248
249       setWire( aProfileWire, false, false );  
250
251       QColor aWireColor = aProfile->GetBorderColor();
252       setBorderColor( aWireColor, false, false );
253     }
254     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_Stream) ) ||
255               myObject->IsKind( STANDARD_TYPE(HYDROData_Channel) ) ||
256               myObject->IsKind( STANDARD_TYPE(HYDROData_Obstacle) ) )
257     {
258       Handle(HYDROData_Object) aGeomObject =
259         Handle(HYDROData_Object)::DownCast( myObject );
260
261       TopoDS_Shape anObjShape = aGeomObject->GetTopShape();
262
263       setShape( anObjShape, false, false );
264
265       QColor aFillingColor = aGeomObject->GetFillingColor();
266       QColor aBorderColor = aGeomObject->GetBorderColor();
267
268       setFillingColor( aFillingColor, false, false );
269       setBorderColor( aBorderColor, false, false );
270     }
271     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_DummyObject3D) ) )
272     {
273       Handle(HYDROData_DummyObject3D) anObject3D =
274         Handle(HYDROData_DummyObject3D)::DownCast( myObject );
275       TopoDS_Shape aShape3D = anObject3D->GetShape();
276
277       setShape( aShape3D, false, false );
278
279       QColor aFillingColor = anObject3D->GetFillingColor();
280       QColor aBorderColor = anObject3D->GetBorderColor();
281
282       setFillingColor( aFillingColor, false, false );
283       setBorderColor( aBorderColor, false, false );
284     }
285     else if ( myObject->IsKind( STANDARD_TYPE(HYDROData_ShapesGroup) ) )
286     {
287       Handle(HYDROData_ShapesGroup) aShapesGroup =
288         Handle(HYDROData_ShapesGroup)::DownCast( myObject );
289
290       TopTools_SequenceOfShape aShapes;
291       aShapesGroup->GetShapes( aShapes );
292
293       TopoDS_Compound aCompound;
294       BRep_Builder aCompoundBuilder;
295       aCompoundBuilder.MakeCompound( aCompound );
296
297       for ( int i = 1, n = aShapes.Length(); i <= n; ++i )
298       {
299         const TopoDS_Shape& aShape = aShapes.Value( i );
300         aCompoundBuilder.Add( aCompound, aShape );
301       }
302
303       setShape( aCompound, false, false );  
304     }
305   }
306  
307   if ( myShape.IsNull() || !isVisible() )
308     return;
309
310   displayShape( isUpdateViewer );
311
312   if (isDeactivateSelection)
313     myContext->Deactivate(myShape);
314 }
315
316 void HYDROGUI_Shape::setVisible( const bool theState,
317                                  const bool theIsUpdateViewer )
318 {
319   myIsVisible = theState;
320
321   if ( myShape.IsNull() )
322     return;
323
324   if ( ( myIsVisible && myContext->IsDisplayed( myShape ) ) ||
325        ( !myIsVisible && !myContext->IsDisplayed( myShape ) ) )
326     return;
327
328   if ( myIsVisible ) {
329     displayShape( theIsUpdateViewer );
330   }
331   else
332     myContext->Erase( myShape, theIsUpdateViewer );
333 }
334
335 void HYDROGUI_Shape::highlight( bool theIsHighlight, bool isUpdateViewer )
336 {
337   if ( myIsHighlight == theIsHighlight )
338     return;
339
340   myIsHighlight = theIsHighlight;
341
342   if ( myContext.IsNull() || myShape.IsNull() )
343     return;
344
345   colorShapeBorder( getActiveColor() );
346   displayShape( isUpdateViewer );
347 }
348
349 bool HYDROGUI_Shape::isHighlighted() const
350 {
351   return myIsHighlight;
352 }
353
354 void HYDROGUI_Shape::setWire( const TopoDS_Wire& theWire,
355                               const bool         theToDisplay,
356                               const bool         theIsUpdateViewer )
357 {
358   myTopoShape = theWire;
359   // To avoid that hilight presentation is equal to "normal" object presentation.
360   // Note that hilight presentation is always to be on top ( i.e. in the top Z layer ).
361   myDisplayMode = AIS_Shaded;
362
363   buildShape();
364   updateShape( theToDisplay, theIsUpdateViewer );
365 }
366
367 void HYDROGUI_Shape::setFaces( const TopoDS_Compound& theWires,
368                                const bool             theToDisplay,
369                                const bool             theIsUpdateViewer )
370 {
371   TopExp_Explorer anExp( theWires, TopAbs_WIRE );
372   TopoDS_Compound aCompound;
373   BRep_Builder aBuilder;
374     aBuilder.MakeCompound( aCompound );
375
376   for ( ; anExp.More(); anExp.Next() ) {
377     TopoDS_Wire aWire = TopoDS::Wire( anExp.Current() );
378     if ( aWire.IsNull() ) {
379       continue;
380     }
381
382     BRepBuilderAPI_MakeFace aMakeFace( aWire, Standard_True );
383     aMakeFace.Build();
384     if( aMakeFace.IsDone() ) {
385       aBuilder.Add( aCompound, aMakeFace.Face() );
386     }
387   }
388
389   myTopoShape = aCompound;
390   myDisplayMode = AIS_Shaded;
391
392   buildShape();
393   updateShape( theToDisplay, theIsUpdateViewer );
394 }
395
396 void HYDROGUI_Shape::setFace( const TopoDS_Wire& theWire,
397                               const bool         theToDisplay,
398                               const bool         theIsUpdateViewer,
399                               const QString&     theTextureFileName )
400 {
401   BRepBuilderAPI_MakeFace aFaceBuilder( theWire, Standard_True );
402   aFaceBuilder.Build();
403   if( aFaceBuilder.IsDone() )
404   {
405     TopoDS_Face aFace = aFaceBuilder.Face();
406     setFace( aFace, theToDisplay, theIsUpdateViewer, theTextureFileName );
407   }
408 }
409
410 void HYDROGUI_Shape::setFace( const TopoDS_Face& theFace,
411                               const bool         theToDisplay,
412                               const bool         theIsUpdateViewer,
413                               const QString&     theTextureFileName )
414 {
415   myTopoShape = theFace;
416   myDisplayMode = theTextureFileName.isEmpty() ? AIS_Shaded : AIS_Shaded+2;
417   //Note: AIS_Shaded+2 is the same as AIS_ExactHLR
418   //TODO: it would be more suitable to use TexturedShape mode from GEOM_AISShape
419
420   buildShape();
421   updateShape( theToDisplay, theIsUpdateViewer );
422 }
423
424 void HYDROGUI_Shape::setShape( const TopoDS_Shape& theShape,
425                                const bool          theToDisplay,
426                                const bool          theIsUpdateViewer )
427 {
428   myTopoShape = theShape;
429   myDisplayMode = AIS_Shaded;
430
431   buildShape();
432   updateShape( theToDisplay, theIsUpdateViewer );
433 }
434
435 void HYDROGUI_Shape::setFillingColor( const QColor& theColor,
436                                       const bool    theToDisplay,
437                                       const bool    theIsUpdateViewer )
438 {
439   myFillingColor = theColor;
440   updateShape( theToDisplay, theIsUpdateViewer );
441 }
442
443 QColor HYDROGUI_Shape::getFillingColor() const
444 {
445   return myFillingColor;
446 }
447
448 void HYDROGUI_Shape::setBorderColor( const QColor& theColor,
449                                      const bool    theToDisplay,
450                                      const bool    theIsUpdateViewer )
451 {
452   myBorderColor = theColor;
453   updateShape( theToDisplay, theIsUpdateViewer );
454 }
455
456 QColor HYDROGUI_Shape::getBorderColor() const
457 {
458   return myBorderColor;
459 }
460
461 void HYDROGUI_Shape::setHighlightColor( const QColor& theColor )
462 {
463   myHighlightColor = theColor;
464 }
465
466 QColor HYDROGUI_Shape::getHighlightColor() const
467 {
468   return myHighlightColor;
469 }
470
471 void HYDROGUI_Shape::setZLayer( const int theZLayer )
472 {
473   if ( myZLayer == theZLayer )
474     return;
475
476   myZLayer = theZLayer;
477   if ( !myShape.IsNull() && isVisible() && !myContext.IsNull() && myZLayer >= 0 )
478     myContext->SetZLayer( myShape, myZLayer );
479 }
480
481 Handle_AIS_InteractiveObject HYDROGUI_Shape::createShape() const
482 {
483   if( myTopoShape.IsNull() )
484     return Handle_AIS_InteractiveObject();
485   else
486     if ( myObject->IsKind( STANDARD_TYPE(HYDROData_PolylineXY) ) ||
487         myObject->IsKind( STANDARD_TYPE(HYDROData_Polyline3D)) ||
488         myObject->IsKind( STANDARD_TYPE(HYDROData_Profile) ))
489       return new HYDROGUI_Polyline(myTopoShape);
490     else
491       return new AIS_Shape( myTopoShape );
492 }
493
494 void HYDROGUI_Shape::buildShape()
495 {
496   // Erase previously created shape
497   erase();
498
499   myShape = createShape();
500   if( myShape.IsNull() )
501     return;
502
503   Handle_AIS_Shape anAISShape = Handle_AIS_Shape::DownCast( myShape );
504   if( !anAISShape.IsNull() )
505     anAISShape ->SetHLRAngleAndDeviation( 0.001 );
506
507   if ( !myObject.IsNull() )
508     myShape->SetOwner( myObject );
509
510   myShape->SetTransparency( 0 );
511   myShape->SetDisplayMode( (AIS_DisplayMode)myDisplayMode );
512
513     // Init default params for shape
514   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
515   if ( !anAttributes.IsNull() )
516   {
517     Handle(Prs3d_IsoAspect) anIsoAspect = anAttributes->UIsoAspect();
518     if ( !anIsoAspect.IsNull() ) {
519       anIsoAspect->SetNumber( 0 );
520       anAttributes->SetUIsoAspect( anIsoAspect );
521     }
522       
523     anIsoAspect = anAttributes->VIsoAspect();
524     if ( !anIsoAspect.IsNull() ) {
525       anIsoAspect->SetNumber( 0 );
526       anAttributes->SetVIsoAspect( anIsoAspect );
527     }
528
529     if ( myDisplayMode == AIS_Shaded )
530     {
531       Handle(Prs3d_ShadingAspect) aShadingAspect = anAttributes->ShadingAspect();
532       if ( !aShadingAspect.IsNull() )
533       {
534         Graphic3d_MaterialAspect aMatAspect( Graphic3d_NOM_PLASTIC );
535         //aMatAspect.SetAmbient( 1 );
536         //aMatAspect.SetDiffuse( 0 );
537
538         aShadingAspect->Aspect()->SetFrontMaterial( aMatAspect );
539         aShadingAspect->Aspect()->SetBackMaterial( aMatAspect );
540       }
541     }
542     else if ( myDisplayMode == AIS_WireFrame )
543     {
544       anAttributes->SetWireDraw( true );
545     }
546   }
547 }
548
549 void HYDROGUI_Shape::updateShape( const bool theToDisplay,
550                                   const bool theIsUpdateViewer )
551 {
552   if ( myShape.IsNull() )
553     return;
554
555   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
556   if ( !anAttributes.IsNull() )
557   {
558     if ( myDisplayMode == AIS_Shaded )
559     {
560       // Coloring face filling
561       Handle(Prs3d_ShadingAspect) aShadingAspect = anAttributes->ShadingAspect();
562       if ( !aShadingAspect.IsNull() )
563       {
564         Quantity_Color aFillingColor( getQuantityColorVal( myFillingColor.red() ), 
565                                       getQuantityColorVal( myFillingColor.green() ),
566                                       getQuantityColorVal( myFillingColor.blue() ),
567                                       Quantity_TOC_RGB );
568
569         aShadingAspect->SetColor( aFillingColor );
570         aShadingAspect->SetTransparency( 1 - getQuantityColorVal( myFillingColor.alpha() ) );
571       }
572     }
573     else if ( myDisplayMode == AIS_WireFrame )
574     {
575     }
576
577     // Coloring borders
578     colorShapeBorder( getActiveColor() );
579   }
580
581   if ( !theToDisplay || !isVisible() || myContext.IsNull() )
582     return;
583   
584   displayShape( theIsUpdateViewer );
585 }
586
587 void HYDROGUI_Shape::displayShape( const bool theIsUpdateViewer )
588 {
589   myContext->Display( myShape, Standard_False );
590
591   if ( myZLayer >= 0 )
592     myContext->SetZLayer( myShape, myZLayer );
593
594   myContext->UpdateCurrentViewer();
595 }
596
597 QColor HYDROGUI_Shape::getActiveColor() const
598 {
599   return isHighlighted() ? myHighlightColor : myBorderColor;
600 }
601
602 double HYDROGUI_Shape::getQuantityColorVal( const int theColorVal )
603 {
604   return theColorVal == 0 ? 0 : ( (double)theColorVal / 255 );
605 }
606
607 void HYDROGUI_Shape::colorShapeBorder( const QColor& theColor )
608 {
609   if ( myShape.IsNull() )
610     return;
611
612   const Handle(AIS_Drawer)& anAttributes = myShape->Attributes();
613   if ( anAttributes.IsNull() )
614     return;
615
616   Quantity_Color aBorderColor( getQuantityColorVal( theColor.red() ), 
617                                getQuantityColorVal( theColor.green() ),
618                                getQuantityColorVal( theColor.blue() ),
619                                Quantity_TOC_RGB );
620   
621   if( !myTopoShape.IsNull() )
622   {
623     if ( myTopoShape.ShapeType() == TopAbs_WIRE ) // Note that we display polylines in shaded mode
624     {
625       myShape->SetColor( aBorderColor );
626     }
627     else if ( myDisplayMode == AIS_Shaded )
628     {
629       if ( theColor.alpha() == 0 )
630       {
631         anAttributes->SetFaceBoundaryDraw( false );
632       }
633       else
634       {
635         anAttributes->SetFaceBoundaryDraw( true );
636   
637         Handle(Prs3d_LineAspect) aBoundaryAspect = anAttributes->FaceBoundaryAspect();
638         if ( !aBoundaryAspect.IsNull() )
639         {
640           aBoundaryAspect->SetColor( aBorderColor );
641           anAttributes->SetFaceBoundaryAspect( aBoundaryAspect );
642         }
643         Handle(Prs3d_LineAspect) aWireAspect = anAttributes->WireAspect();
644         if ( !aWireAspect.IsNull() )
645         {
646           aWireAspect->SetColor( aBorderColor );
647           anAttributes->SetWireAspect( aWireAspect );
648         }
649       }
650     }
651     else if ( myDisplayMode == AIS_WireFrame )
652     {
653       myShape->SetColor( aBorderColor );
654     }
655   }
656 }
657
658 void HYDROGUI_Shape::setDisplayMode( int theDisplayMode )
659 {
660   myDisplayMode = theDisplayMode;
661 }