0031189: Draw Harness, ViewerTest - send messages to Message::DefaultMessenger()
[occt.git] / src / ViewerTest / ViewerTest.cxx
1 // Created on: 1997-07-23
2 // Created by: Henri JEANNIN
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <Standard_Stream.hxx>
18
19 #include <ViewerTest.hxx>
20 #include <ViewerTest_CmdParser.hxx>
21
22 #include <Draw.hxx>
23 #include <TopLoc_Location.hxx>
24 #include <TopTools_HArray1OfShape.hxx>
25 #include <TColStd_HArray1OfTransient.hxx>
26 #include <TColStd_SequenceOfAsciiString.hxx>
27 #include <TColStd_HSequenceOfAsciiString.hxx>
28 #include <TColStd_MapOfTransient.hxx>
29 #include <OSD_Timer.hxx>
30 #include <Geom_Axis2Placement.hxx>
31 #include <Geom_Axis1Placement.hxx>
32 #include <gp_Trsf.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <BRepAdaptor_Curve.hxx>
35 #include <StdSelect_ShapeTypeFilter.hxx>
36 #include <AIS_ColoredShape.hxx>
37 #include <AIS_InteractiveObject.hxx>
38 #include <AIS_Trihedron.hxx>
39 #include <AIS_Axis.hxx>
40 #include <PrsDim.hxx>
41 #include <PrsDim_Relation.hxx>
42 #include <AIS_TypeFilter.hxx>
43 #include <AIS_SignatureFilter.hxx>
44 #include <AIS_ListOfInteractive.hxx>
45 #include <AIS_ListIteratorOfListOfInteractive.hxx>
46 #include <Aspect_InteriorStyle.hxx>
47 #include <Aspect_Window.hxx>
48 #include <Graphic3d_AspectFillArea3d.hxx>
49 #include <Graphic3d_AspectLine3d.hxx>
50 #include <Graphic3d_CStructure.hxx>
51 #include <Graphic3d_Texture2Dmanual.hxx>
52 #include <Graphic3d_GraphicDriver.hxx>
53 #include <Graphic3d_MediaTextureSet.hxx>
54 #include <Image_AlienPixMap.hxx>
55 #include <Message.hxx>
56 #include <OSD_File.hxx>
57 #include <Prs3d_Drawer.hxx>
58 #include <Prs3d_ShadingAspect.hxx>
59 #include <Prs3d_IsoAspect.hxx>
60 #include <Prs3d_PointAspect.hxx>
61 #include <Select3D_SensitiveWire.hxx>
62 #include <Select3D_SensitivePrimitiveArray.hxx>
63 #include <SelectMgr_EntityOwner.hxx>
64 #include <StdSelect_BRepOwner.hxx>
65 #include <StdSelect_ViewerSelector3d.hxx>
66 #include <TopTools_MapOfShape.hxx>
67 #include <ViewerTest_AutoUpdater.hxx>
68
69 #include <stdio.h>
70
71 #include <Draw_Interpretor.hxx>
72 #include <TCollection_AsciiString.hxx>
73 #include <Draw_PluginMacro.hxx>
74
75 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
76
77 #include <Quantity_Color.hxx>
78 #include <Quantity_NameOfColor.hxx>
79
80 #include <Graphic3d_NameOfMaterial.hxx>
81
82 #define DEFAULT_COLOR              Quantity_NOC_GOLDENROD
83 #define DEFAULT_FREEBOUNDARY_COLOR Quantity_NOC_GREEN
84 #define DEFAULT_MATERIAL           Graphic3d_NOM_BRASS
85
86 namespace
87 {
88
89   const Standard_Integer THE_MAX_INTEGER_COLOR_COMPONENT = 255;
90
91   const Standard_ShortReal THE_MAX_REAL_COLOR_COMPONENT = 1.0f;
92
93   //! Parses string and get an integer color component (only values within range 0 .. 255 are allowed)
94   //! @param theColorComponentString the string representing the color component
95   //! @param theIntegerColorComponent an integer color component that is a result of parsing
96   //! @return true if parsing was successful, or false otherwise
97   static bool parseNumericalColorComponent (const Standard_CString theColorComponentString,
98                                             Standard_Integer&      theIntegerColorComponent)
99   {
100     Standard_Integer anIntegerColorComponent;
101     if (!Draw::ParseInteger (theColorComponentString, anIntegerColorComponent))
102     {
103       return false;
104     }
105     if ((anIntegerColorComponent < 0) || (anIntegerColorComponent > THE_MAX_INTEGER_COLOR_COMPONENT))
106     {
107       return false;
108     }
109     theIntegerColorComponent = anIntegerColorComponent;
110     return true;
111   }
112
113   //! Parses the string and gets a real color component from it (only values within range 0.0 .. 1.0 are allowed)
114   //! @param theColorComponentString the string representing the color component
115   //! @param theRealColorComponent a real color component that is a result of parsing
116   //! @return true if parsing was successful, or false otherwise
117   static bool parseNumericalColorComponent (const Standard_CString theColorComponentString,
118                                             Standard_ShortReal&    theRealColorComponent)
119   {
120     Standard_Real aRealColorComponent;
121     if (!Draw::ParseReal (theColorComponentString, aRealColorComponent))
122     {
123       return false;
124     }
125     const Standard_ShortReal aShortRealColorComponent = static_cast<Standard_ShortReal> (aRealColorComponent);
126     if ((aShortRealColorComponent < 0.0f) || (aShortRealColorComponent > THE_MAX_REAL_COLOR_COMPONENT))
127     {
128       return false;
129     }
130     theRealColorComponent = aShortRealColorComponent;
131     return true;
132   }
133
134   //! Parses the string and gets a real color component from it (integer values 2 .. 255 are scaled to the 0.0 .. 1.0
135   //! range, values 0 and 1 are leaved as they are)
136   //! @param theColorComponentString the string representing the color component
137   //! @param theColorComponent a color component that is a result of parsing
138   //! @return true if parsing was successful, or false otherwise
139   static bool parseColorComponent (const Standard_CString theColorComponentString,
140                                    Standard_ShortReal&    theColorComponent)
141   {
142     Standard_Integer anIntegerColorComponent;
143     if (parseNumericalColorComponent (theColorComponentString, anIntegerColorComponent))
144     {
145       if (anIntegerColorComponent == 1)
146       {
147         theColorComponent = THE_MAX_REAL_COLOR_COMPONENT;
148       }
149       else
150       {
151         theColorComponent = anIntegerColorComponent * 1.0f / THE_MAX_INTEGER_COLOR_COMPONENT;
152       }
153       return true;
154     }
155     return parseNumericalColorComponent (theColorComponentString, theColorComponent);
156   }
157
158   //! Parses the array of strings and gets an integer color (only values within range 0 .. 255 are allowed and at least
159   //! one of components must be greater than 1)
160   //! @tparam TheNumber the type of resulting color vector elements
161   //! @param theNumberOfColorComponents the number of color components
162   //! @param theColorComponentStrings the array of strings representing color components
163   //! @param theNumericalColor a 4-component vector that is a result of parsing
164   //! @return true if parsing was successful, or false otherwise
165   template <typename TheNumber>
166   static bool parseNumericalColor (Standard_Integer&            theNumberOfColorComponents,
167                                    const char* const* const     theColorComponentStrings,
168                                    NCollection_Vec4<TheNumber>& theNumericalColor)
169   {
170     for (Standard_Integer aColorComponentIndex = 0; aColorComponentIndex < theNumberOfColorComponents;
171          ++aColorComponentIndex)
172     {
173       const char* const aColorComponentString = theColorComponentStrings[aColorComponentIndex];
174       TheNumber         aNumericalColorComponent;
175       if (parseNumericalColorComponent (aColorComponentString, aNumericalColorComponent))
176       {
177         theNumericalColor[aColorComponentIndex] = aNumericalColorComponent;
178       }
179       else
180       {
181         if (aColorComponentIndex == 3)
182         {
183           theNumberOfColorComponents = 3;
184         }
185         else
186         {
187           return false;
188         }
189       }
190     }
191     return true;
192   }
193
194   //! Parses an array of strings and get an integer color (only values within range 0 .. 255 are allowed and at least
195   //! one of components must be greater than 1)
196   //! @param theNumberOfColorComponents the number of color components
197   //! @param theColorComponentStrings the array of strings representing color components
198   //! @param theColor a color that is a result of parsing
199   //! @return true if parsing was successful, or false otherwise
200   static bool parseIntegerColor (Standard_Integer&        theNumberOfColorComponents,
201                                  const char* const* const theColorComponentStrings,
202                                  Quantity_ColorRGBA&      theColor)
203   {
204     const Standard_Integer THE_COLOR_COMPONENT_NOT_PARSED = -1;
205     Graphic3d_Vec4i        anIntegerColor (THE_COLOR_COMPONENT_NOT_PARSED);
206     if (!parseNumericalColor (theNumberOfColorComponents, theColorComponentStrings, anIntegerColor)
207       || anIntegerColor.maxComp() <= 1)
208     {
209       return false;
210     }
211     if (anIntegerColor.a() == THE_COLOR_COMPONENT_NOT_PARSED)
212     {
213       anIntegerColor.a() = THE_MAX_INTEGER_COLOR_COMPONENT;
214     }
215
216     const Graphic3d_Vec4 aRealColor = Graphic3d_Vec4 (anIntegerColor) / static_cast<Standard_ShortReal> (THE_MAX_INTEGER_COLOR_COMPONENT);
217     theColor = Quantity_ColorRGBA (Quantity_ColorRGBA::Convert_sRGB_To_LinearRGB (aRealColor));
218     return true;
219   }
220
221   //! Parses an array of strings and get a real color (only values within range 0.0 .. 1.0 are allowed)
222   //! @param theNumberOfColorComponents the number of color components
223   //! @param theColorComponentStrings the array of strings representing color components
224   //! @param theColor a color that is a result of parsing
225   //! @return true if parsing was successful, or false otherwise
226   static bool parseRealColor (Standard_Integer&        theNumberOfColorComponents,
227                               const char* const* const theColorComponentStrings,
228                               Quantity_ColorRGBA&      theColor)
229   {
230     Graphic3d_Vec4 aRealColor (THE_MAX_REAL_COLOR_COMPONENT);
231     if (!parseNumericalColor (theNumberOfColorComponents, theColorComponentStrings, aRealColor))
232     {
233       return false;
234     }
235     theColor = Quantity_ColorRGBA (aRealColor);
236     return true;
237   }
238
239 } // namespace
240
241 //=======================================================================
242 // function : GetColorFromName
243 // purpose  : get the Quantity_NameOfColor from a string
244 //=======================================================================
245
246 Quantity_NameOfColor ViewerTest::GetColorFromName (const Standard_CString theName)
247 {
248   Quantity_NameOfColor aColor = DEFAULT_COLOR;
249   Quantity_Color::ColorFromName (theName, aColor);
250   return aColor;
251 }
252
253 //=======================================================================
254 // function : parseColor
255 // purpose  :
256 //=======================================================================
257 Standard_Integer ViewerTest::parseColor (const Standard_Integer   theArgNb,
258                                          const char* const* const theArgVec,
259                                          Quantity_ColorRGBA&      theColor,
260                                          const bool               theToParseAlpha)
261 {
262   if ((theArgNb >= 1) && Quantity_ColorRGBA::ColorFromHex (theArgVec[0], theColor, !theToParseAlpha))
263   {
264     return 1;
265   }
266   if (theArgNb >= 1 && Quantity_ColorRGBA::ColorFromName (theArgVec[0], theColor))
267   {
268     if (theArgNb >= 2 && theToParseAlpha)
269     {
270       const Standard_CString anAlphaStr = theArgVec[1];
271       Standard_ShortReal     anAlphaComponent;
272       if (parseColorComponent (anAlphaStr, anAlphaComponent))
273       {
274         theColor.SetAlpha (anAlphaComponent);
275         return 2;
276       }
277     }
278     return 1;
279   }
280   if (theArgNb >= 3)
281   {
282     const Standard_Integer aNumberOfColorComponentsToParse = Min (theArgNb, theToParseAlpha ? 4 : 3);
283     Standard_Integer aNumberOfColorComponentsParsed = aNumberOfColorComponentsToParse;
284     if (parseIntegerColor (aNumberOfColorComponentsParsed, theArgVec, theColor))
285     {
286       return aNumberOfColorComponentsParsed;
287     }
288     aNumberOfColorComponentsParsed = aNumberOfColorComponentsToParse;
289     if (parseRealColor (aNumberOfColorComponentsParsed, theArgVec, theColor))
290     {
291       return aNumberOfColorComponentsParsed;
292     }
293     return 0;
294   }
295   return 0;
296 }
297
298 //=======================================================================
299 //function : ParseOnOff
300 //purpose  :
301 //=======================================================================
302 Standard_Boolean ViewerTest::ParseOnOff (Standard_CString  theArg,
303                                          Standard_Boolean& theIsOn)
304 {
305   TCollection_AsciiString aFlag(theArg);
306   aFlag.LowerCase();
307   if (aFlag == "on"
308    || aFlag == "1")
309   {
310     theIsOn = Standard_True;
311     return Standard_True;
312   }
313   else if (aFlag == "off"
314         || aFlag == "0")
315   {
316     theIsOn = Standard_False;
317     return Standard_True;
318   }
319   return Standard_False;
320 }
321
322 //=======================================================================
323 //function : GetSelectedShapes
324 //purpose  :
325 //=======================================================================
326 void ViewerTest::GetSelectedShapes (TopTools_ListOfShape& theSelectedShapes)
327 {
328   for (GetAISContext()->InitSelected(); GetAISContext()->MoreSelected(); GetAISContext()->NextSelected())
329   {
330     TopoDS_Shape aShape = GetAISContext()->SelectedShape();
331     if (!aShape.IsNull())
332     {
333       theSelectedShapes.Append (aShape);
334     }
335   }
336 }
337
338 //=======================================================================
339 //function : ParseLineType
340 //purpose  :
341 //=======================================================================
342 Standard_Boolean ViewerTest::ParseLineType (Standard_CString theArg,
343                                             Aspect_TypeOfLine& theType,
344                                             uint16_t& thePattern)
345 {
346   TCollection_AsciiString aTypeStr (theArg);
347   aTypeStr.LowerCase();
348   if (aTypeStr == "empty"
349    || aTypeStr == "-1")
350   {
351     theType = Aspect_TOL_EMPTY;
352     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
353   }
354   else if (aTypeStr == "solid"
355         || aTypeStr == "0")
356   {
357     theType = Aspect_TOL_SOLID;
358     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
359   }
360   else if (aTypeStr == "dot"
361         || aTypeStr == "2")
362   {
363     theType = Aspect_TOL_DOT;
364     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
365   }
366   else if (aTypeStr == "dash"
367         || aTypeStr == "1")
368   {
369     theType = Aspect_TOL_DASH;
370     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
371   }
372   else if (aTypeStr == "dotdash"
373         || aTypeStr == "3")
374   {
375     theType = Aspect_TOL_DOTDASH;
376     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
377   }
378   else
379   {
380     if (aTypeStr.StartsWith ("0x"))
381     {
382       aTypeStr = aTypeStr.SubString (3, aTypeStr.Length());
383     }
384
385     if (aTypeStr.Length() != 4
386     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (1)))
387     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (2)))
388     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (3)))
389     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (4))))
390     {
391       return Standard_False;
392     }
393
394     std::stringstream aStream;
395     aStream << std::setbase (16) << aTypeStr.ToCString();
396     if (aStream.fail())
397     {
398       return Standard_False;
399     }
400
401     Standard_Integer aNumber = -1;
402     aStream >> aNumber;
403     if (aStream.fail())
404     {
405       return Standard_False;
406     }
407
408     thePattern = (uint16_t )aNumber;
409     theType = Graphic3d_Aspects::DefaultLineTypeForPattern (thePattern);
410   }
411   return Standard_True;
412 }
413
414 //=======================================================================
415 //function : ParseMarkerType
416 //purpose  :
417 //=======================================================================
418 Standard_Boolean ViewerTest::ParseMarkerType (Standard_CString theArg,
419                                               Aspect_TypeOfMarker& theType,
420                                               Handle(Image_PixMap)& theImage)
421 {
422   theImage.Nullify();
423   TCollection_AsciiString aTypeStr (theArg);
424   aTypeStr.LowerCase();
425   if (aTypeStr == "empty")
426   {
427     theType = Aspect_TOM_EMPTY;
428   }
429   else if (aTypeStr == "point"
430         || aTypeStr == "dot"
431         || aTypeStr == ".")
432   {
433     theType = Aspect_TOM_POINT;
434   }
435   else if (aTypeStr == "plus"
436         || aTypeStr == "+")
437   {
438     theType = Aspect_TOM_PLUS;
439   }
440   else if (aTypeStr == "star"
441         || aTypeStr == "*")
442   {
443     theType = Aspect_TOM_STAR;
444   }
445   else if (aTypeStr == "cross"
446         || aTypeStr == "x")
447   {
448     theType = Aspect_TOM_X;
449   }
450   else if (aTypeStr == "circle"
451         || aTypeStr == "o")
452   {
453     theType = Aspect_TOM_O;
454   }
455   else if (aTypeStr == "pointincircle")
456   {
457     theType = Aspect_TOM_O_POINT;
458   }
459   else if (aTypeStr == "plusincircle")
460   {
461     theType = Aspect_TOM_O_PLUS;
462   }
463   else if (aTypeStr == "starincircle")
464   {
465     theType = Aspect_TOM_O_STAR;
466   }
467   else if (aTypeStr == "crossincircle"
468         || aTypeStr == "xcircle")
469   {
470     theType = Aspect_TOM_O_X;
471   }
472   else if (aTypeStr == "ring1")
473   {
474     theType = Aspect_TOM_RING1;
475   }
476   else if (aTypeStr == "ring2")
477   {
478     theType = Aspect_TOM_RING2;
479   }
480   else if (aTypeStr == "ring"
481         || aTypeStr == "ring3")
482   {
483     theType = Aspect_TOM_RING3;
484   }
485   else if (aTypeStr == "ball")
486   {
487     theType = Aspect_TOM_BALL;
488   }
489   else if (aTypeStr.IsIntegerValue())
490   {
491     const int aTypeInt = aTypeStr.IntegerValue();
492     if (aTypeInt < -1 || aTypeInt >= Aspect_TOM_USERDEFINED)
493     {
494       return Standard_False;
495     }
496     theType = (Aspect_TypeOfMarker )aTypeInt;
497   }
498   else
499   {
500     theType = Aspect_TOM_USERDEFINED;
501     Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
502     if (!anImage->Load (theArg))
503     {
504       return Standard_False;
505     }
506     if (anImage->Format() == Image_Format_Gray)
507     {
508       anImage->SetFormat (Image_Format_Alpha);
509     }
510     else if (anImage->Format() == Image_Format_GrayF)
511     {
512       anImage->SetFormat (Image_Format_AlphaF);
513     }
514     theImage = anImage;
515   }
516   return Standard_True;
517 }
518
519 //=======================================================================
520 //function : ParseShadingModel
521 //purpose  :
522 //=======================================================================
523 Standard_Boolean ViewerTest::ParseShadingModel (Standard_CString              theArg,
524                                                 Graphic3d_TypeOfShadingModel& theModel)
525 {
526   TCollection_AsciiString aTypeStr (theArg);
527   aTypeStr.LowerCase();
528   if (aTypeStr == "unlit"
529    || aTypeStr == "color"
530    || aTypeStr == "none")
531   {
532     theModel = Graphic3d_TOSM_UNLIT;
533   }
534   else if (aTypeStr == "flat"
535         || aTypeStr == "facet")
536   {
537     theModel = Graphic3d_TOSM_FACET;
538   }
539   else if (aTypeStr == "gouraud"
540         || aTypeStr == "vertex"
541         || aTypeStr == "vert")
542   {
543     theModel = Graphic3d_TOSM_VERTEX;
544   }
545   else if (aTypeStr == "phong"
546         || aTypeStr == "fragment"
547         || aTypeStr == "frag"
548         || aTypeStr == "pixel")
549   {
550     theModel = Graphic3d_TOSM_FRAGMENT;
551   }
552   else if (aTypeStr == "pbr")
553   {
554     theModel = Graphic3d_TOSM_PBR;
555   }
556   else if (aTypeStr == "pbr_facet")
557   {
558     theModel = Graphic3d_TOSM_PBR_FACET;
559   }
560   else if (aTypeStr == "default"
561         || aTypeStr == "def")
562   {
563     theModel = Graphic3d_TOSM_DEFAULT;
564   }
565   else if (aTypeStr.IsIntegerValue())
566   {
567     const int aTypeInt = aTypeStr.IntegerValue();
568     if (aTypeInt <= Graphic3d_TOSM_DEFAULT || aTypeInt >= Graphic3d_TypeOfShadingModel_NB)
569     {
570       return Standard_False;
571     }
572     theModel = (Graphic3d_TypeOfShadingModel)aTypeInt;
573   }
574   else
575   {
576     return Standard_False;
577   }
578   return Standard_True;
579 }
580
581 //=======================================================================
582 //function : parseZLayer
583 //purpose  :
584 //=======================================================================
585 Standard_Boolean ViewerTest::parseZLayer (Standard_CString theArg,
586                                           Standard_Boolean theToAllowInteger,
587                                           Graphic3d_ZLayerId& theLayer)
588 {
589   TCollection_AsciiString aName (theArg);
590   aName.LowerCase();
591   if (aName == "default"
592    || aName == "def")
593   {
594     theLayer = Graphic3d_ZLayerId_Default;
595   }
596   else if (aName == "top")
597   {
598     theLayer = Graphic3d_ZLayerId_Top;
599   }
600   else if (aName == "topmost")
601   {
602     theLayer = Graphic3d_ZLayerId_Topmost;
603   }
604   else if (aName == "overlay"
605         || aName == "toposd")
606   {
607     theLayer = Graphic3d_ZLayerId_TopOSD;
608   }
609   else if (aName == "underlay"
610         || aName == "botosd")
611   {
612     theLayer = Graphic3d_ZLayerId_BotOSD;
613   }
614   else if (aName == "undefined")
615   {
616     theLayer = Graphic3d_ZLayerId_UNKNOWN;
617   }
618   else if (!GetAISContext().IsNull())
619   {
620     const Handle(V3d_Viewer)& aViewer = ViewerTest::GetAISContext()->CurrentViewer();
621     TColStd_SequenceOfInteger aLayers;
622     aViewer->GetAllZLayers (aLayers);
623     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
624     {
625       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
626       if (TCollection_AsciiString::IsSameString (aSettings.Name(), aName, Standard_False))
627       {
628         theLayer = aLayeriter.Value();
629         return true;
630       }
631     }
632
633     if (!theToAllowInteger
634      || !aName.IsIntegerValue())
635     {
636       return false;
637     }
638     Graphic3d_ZLayerId aLayer = aName.IntegerValue();
639     if (aLayer == Graphic3d_ZLayerId_UNKNOWN
640      || std::find (aLayers.begin(), aLayers.end(), aLayer) != aLayers.end())
641     {
642       theLayer = aLayer;
643       return true;
644     }
645     return false;
646   }
647   return true;
648 }
649
650 //=======================================================================
651 //function : GetTypeNames
652 //purpose  :
653 //=======================================================================
654 static const char** GetTypeNames()
655 {
656   static const char* names[14] = {"Point","Axis","Trihedron","PlaneTrihedron", "Line","Circle","Plane",
657                           "Shape","ConnectedShape","MultiConn.Shape",
658                           "ConnectedInter.","MultiConn.",
659                           "Constraint","Dimension"};
660   static const char** ThePointer = names;
661   return ThePointer;
662 }
663
664 //=======================================================================
665 //function : GetTypeAndSignfromString
666 //purpose  :
667 //=======================================================================
668 void GetTypeAndSignfromString (const char* name,AIS_KindOfInteractive& TheType,Standard_Integer& TheSign)
669 {
670   const char ** thefullnames = GetTypeNames();
671   Standard_Integer index(-1);
672
673   for(Standard_Integer i=0;i<=13 && index==-1;i++)
674     if(!strcasecmp(name,thefullnames[i]))
675       index = i;
676
677   if(index ==-1){
678     TheType = AIS_KOI_None;
679     TheSign = -1;
680     return;
681   }
682
683   if(index<=6){
684     TheType = AIS_KOI_Datum;
685     TheSign = index+1;
686   }
687   else if (index <=9){
688     TheType = AIS_KOI_Shape;
689     TheSign = index-7;
690   }
691   else if(index<=11){
692     TheType = AIS_KOI_Object;
693     TheSign = index-10;
694   }
695   else{
696     TheType = AIS_KOI_Relation;
697     TheSign = index-12;
698   }
699
700 }
701
702
703
704 #include <string.h>
705 #include <Draw_Interpretor.hxx>
706 #include <Draw.hxx>
707 #include <Draw_Appli.hxx>
708 #include <DBRep.hxx>
709
710
711 #include <TCollection_AsciiString.hxx>
712 #include <V3d_Viewer.hxx>
713 #include <V3d_View.hxx>
714 #include <V3d.hxx>
715
716 #include <AIS_InteractiveContext.hxx>
717 #include <AIS_Shape.hxx>
718 #include <AIS_DisplayMode.hxx>
719 #include <TColStd_MapOfInteger.hxx>
720 #include <AIS_MapOfInteractive.hxx>
721 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
722 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
723 #include <ViewerTest_EventManager.hxx>
724
725 #include <TopoDS_Solid.hxx>
726 #include <BRepTools.hxx>
727 #include <BRep_Builder.hxx>
728 #include <TopAbs_ShapeEnum.hxx>
729
730 #include <TopoDS.hxx>
731 #include <BRep_Tool.hxx>
732
733
734 #include <Draw_Window.hxx>
735 #include <AIS_ListIteratorOfListOfInteractive.hxx>
736 #include <AIS_ListOfInteractive.hxx>
737 #include <AIS_DisplayMode.hxx>
738 #include <TopTools_ListOfShape.hxx>
739 #include <BRepOffsetAPI_MakeThickSolid.hxx>
740
741 //==============================================================================
742 //  VIEWER OBJECT MANAGEMENT GLOBAL VARIABLES
743 //==============================================================================
744 Standard_EXPORT ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(){
745   static ViewerTest_DoubleMapOfInteractiveAndName TheMap;
746   return TheMap;
747 }
748
749 //=======================================================================
750 //function : Display
751 //purpose  :
752 //=======================================================================
753 Standard_Boolean ViewerTest::Display (const TCollection_AsciiString&       theName,
754                                       const Handle(AIS_InteractiveObject)& theObject,
755                                       const Standard_Boolean               theToUpdate,
756                                       const Standard_Boolean               theReplaceIfExists)
757 {
758   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
759   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
760   if (aCtx.IsNull())
761   {
762     Message::SendFail ("Error: AIS context is not available.");
763     return Standard_False;
764   }
765
766   if (aMap.IsBound2 (theName))
767   {
768     if (!theReplaceIfExists)
769     {
770       Message::SendFail() << "Error: other interactive object has been already registered with name: " << theName << ".\n"
771                           << "Please use another name.";
772       return Standard_False;
773     }
774
775     if (Handle(AIS_InteractiveObject) anOldObj = aMap.Find2 (theName))
776     {
777       aCtx->Remove (anOldObj, theObject.IsNull() && theToUpdate);
778     }
779     aMap.UnBind2 (theName);
780   }
781
782   if (theObject.IsNull())
783   {
784     // object with specified name has been already unbound
785     return Standard_True;
786   }
787
788   // unbind AIS object if it was bound with another name
789   aMap.UnBind1 (theObject);
790
791   // can be registered without rebinding
792   aMap.Bind (theObject, theName);
793   aCtx->Display (theObject, theToUpdate);
794   return Standard_True;
795 }
796
797 //! Alias for ViewerTest::Display(), compatibility with old code.
798 Standard_EXPORT Standard_Boolean VDisplayAISObject (const TCollection_AsciiString&       theName,
799                                                     const Handle(AIS_InteractiveObject)& theObject,
800                                                     Standard_Boolean theReplaceIfExists = Standard_True)
801 {
802   return ViewerTest::Display (theName, theObject, Standard_True, theReplaceIfExists);
803 }
804
805 static NCollection_List<Handle(ViewerTest_EventManager)> theEventMgrs;
806
807 static Handle(V3d_View)&  a3DView()
808 {
809   static Handle(V3d_View) Viou;
810   return Viou;
811 }
812
813
814 Standard_EXPORT Handle(AIS_InteractiveContext)& TheAISContext(){
815   static Handle(AIS_InteractiveContext) aContext;
816   return aContext;
817 }
818
819 const Handle(V3d_View)& ViewerTest::CurrentView()
820 {
821   return a3DView();
822 }
823 void ViewerTest::CurrentView(const Handle(V3d_View)& V)
824 {
825   a3DView() = V;
826 }
827
828 const Handle(AIS_InteractiveContext)& ViewerTest::GetAISContext()
829 {
830   return TheAISContext();
831 }
832
833 void ViewerTest::SetAISContext (const Handle(AIS_InteractiveContext)& aCtx)
834 {
835   TheAISContext() = aCtx;
836   ViewerTest::ResetEventManager();
837 }
838
839 Handle(V3d_Viewer) ViewerTest::GetViewerFromContext()
840 {
841   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
842 }
843
844 Handle(V3d_Viewer) ViewerTest::GetCollectorFromContext()
845 {
846   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
847 }
848
849
850 void ViewerTest::SetEventManager(const Handle(ViewerTest_EventManager)& EM){
851   theEventMgrs.Prepend(EM);
852 }
853
854 void ViewerTest::UnsetEventManager()
855 {
856   theEventMgrs.RemoveFirst();
857 }
858
859
860 void ViewerTest::ResetEventManager()
861 {
862   theEventMgrs.Clear();
863   theEventMgrs.Prepend (new ViewerTest_EventManager (ViewerTest::CurrentView(), ViewerTest::GetAISContext()));
864 }
865
866 Handle(ViewerTest_EventManager) ViewerTest::CurrentEventManager()
867 {
868   return !theEventMgrs.IsEmpty()
869         ? theEventMgrs.First()
870         : Handle(ViewerTest_EventManager)();
871 }
872
873 //=======================================================================
874 //function : Get Context and active view
875 //purpose  :
876 //=======================================================================
877 static Standard_Boolean getCtxAndView (Handle(AIS_InteractiveContext)& theCtx,
878                                        Handle(V3d_View)&               theView)
879 {
880   theCtx  = ViewerTest::GetAISContext();
881   theView = ViewerTest::CurrentView();
882   if (theCtx.IsNull()
883    || theView.IsNull())
884   {
885     Message::SendFail ("Error: cannot find an active view!");
886     return Standard_False;
887   }
888   return Standard_True;
889 }
890
891 //==============================================================================
892 //function : Clear
893 //purpose  : Remove all the object from the viewer
894 //==============================================================================
895 void ViewerTest::Clear()
896 {
897   if (a3DView().IsNull())
898   {
899     return;
900   }
901
902   NCollection_Sequence<Handle(AIS_InteractiveObject)> aListRemoved;
903   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS()); anObjIter.More(); anObjIter.Next())
904   {
905     const Handle(AIS_InteractiveObject) anObj = anObjIter.Key1();
906     if (anObj->GetContext() != TheAISContext())
907     {
908       continue;
909     }
910
911     Message::SendInfo() << "Remove " << anObjIter.Key2();
912     TheAISContext()->Remove (anObj, Standard_False);
913     aListRemoved.Append (anObj);
914   }
915
916   TheAISContext()->RebuildSelectionStructs();
917   TheAISContext()->UpdateCurrentViewer();
918   if (aListRemoved.Size() == GetMapOfAIS().Extent())
919   {
920     GetMapOfAIS().Clear();
921   }
922   else
923   {
924     for (NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator anObjIter (aListRemoved); anObjIter.More(); anObjIter.Next())
925     {
926       GetMapOfAIS().UnBind1 (anObjIter.Value());
927     }
928   }
929 }
930
931 //==============================================================================
932 //function : CopyIsoAspect
933 //purpose  : Returns copy Prs3d_IsoAspect with new number of isolines.
934 //==============================================================================
935 static Handle(Prs3d_IsoAspect) CopyIsoAspect
936       (const Handle(Prs3d_IsoAspect) &theIsoAspect,
937        const Standard_Integer theNbIsos)
938 {
939   Quantity_Color    aColor = theIsoAspect->Aspect()->Color();
940   Aspect_TypeOfLine aType  = theIsoAspect->Aspect()->Type();
941   Standard_Real     aWidth = theIsoAspect->Aspect()->Width();
942
943   Handle(Prs3d_IsoAspect) aResult =
944     new Prs3d_IsoAspect(aColor, aType, aWidth, theNbIsos);
945
946   return aResult;
947 }
948
949 //==============================================================================
950 //function : visos
951 //purpose  : Returns or sets the number of U- and V- isos and isIsoOnPlane flag
952 //Draw arg : [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]
953 //==============================================================================
954 static int visos (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
955 {
956   if (TheAISContext().IsNull()) {
957     di << argv[0] << " Call 'vinit' before!\n";
958     return 1;
959   }
960
961   if (argc <= 1) {
962     di << "Current number of isos : " <<
963       TheAISContext()->IsoNumber(AIS_TOI_IsoU) << " " <<
964       TheAISContext()->IsoNumber(AIS_TOI_IsoV) << "\n";
965     di << "IsoOnPlane mode is " <<
966       (TheAISContext()->IsoOnPlane() ? "ON" : "OFF") << "\n";
967     di << "IsoOnTriangulation mode is " <<
968       (TheAISContext()->IsoOnTriangulation() ? "ON" : "OFF") << "\n";
969     return 0;
970   }
971
972   Standard_Integer aLastInd = argc - 1;
973   Standard_Boolean isChanged = Standard_False;
974   Standard_Integer aNbUIsos = 0;
975   Standard_Integer aNbVIsos = 0;
976
977   if (aLastInd >= 3) {
978     Standard_Boolean isIsoOnPlane = Standard_False;
979
980     if (strcmp(argv[aLastInd], "1") == 0) {
981       isIsoOnPlane = Standard_True;
982       isChanged    = Standard_True;
983     } else if (strcmp(argv[aLastInd], "0") == 0) {
984       isIsoOnPlane = Standard_False;
985       isChanged    = Standard_True;
986     }
987
988     if (isChanged) {
989       aNbVIsos = Draw::Atoi(argv[aLastInd - 1]);
990       aNbUIsos = Draw::Atoi(argv[aLastInd - 2]);
991       aLastInd -= 3;
992
993       di << "New number of isos : " << aNbUIsos << " " << aNbVIsos << "\n";
994       di << "New IsoOnPlane mode is " << (isIsoOnPlane ? "ON" : "OFF") << "\n";
995
996       TheAISContext()->IsoOnPlane(isIsoOnPlane);
997
998       if (aLastInd == 0) {
999         // If there are no shapes provided set the default numbers.
1000         TheAISContext()->SetIsoNumber(aNbUIsos, AIS_TOI_IsoU);
1001         TheAISContext()->SetIsoNumber(aNbVIsos, AIS_TOI_IsoV);
1002       }
1003     }
1004   }
1005
1006   Standard_Integer i;
1007
1008   for (i = 1; i <= aLastInd; i++)
1009   {
1010     TCollection_AsciiString name(argv[i]);
1011     Handle(AIS_InteractiveObject) aShape;
1012     GetMapOfAIS().Find2(name, aShape);
1013     if (aShape.IsNull())
1014     {
1015       Message::SendFail() << "Syntax error: object '" << name << "' is not found";
1016       return 1;
1017     }
1018
1019     Handle(Prs3d_Drawer) CurDrawer = aShape->Attributes();
1020     Handle(Prs3d_IsoAspect) aUIso = CurDrawer->UIsoAspect();
1021     Handle(Prs3d_IsoAspect) aVIso = CurDrawer->VIsoAspect();
1022     if (isChanged)
1023     {
1024       CurDrawer->SetUIsoAspect(CopyIsoAspect(aUIso, aNbUIsos));
1025       CurDrawer->SetVIsoAspect(CopyIsoAspect(aVIso, aNbVIsos));
1026       TheAISContext()->SetLocalAttributes (aShape, CurDrawer, Standard_False);
1027       TheAISContext()->Redisplay (aShape, Standard_False);
1028     }
1029     else
1030     {
1031       di << "Number of isos for " << argv[i] << " : "
1032           << aUIso->Number() << " " << aVIso->Number() << "\n";
1033     }
1034   }
1035
1036   if (isChanged) {
1037     TheAISContext()->UpdateCurrentViewer();
1038   }
1039
1040   return 0;
1041 }
1042
1043 static Standard_Integer VDispSensi (Draw_Interpretor& ,
1044                                     Standard_Integer  theArgNb,
1045                                     Standard_CString* )
1046 {
1047   if (theArgNb > 1)
1048   {
1049     Message::SendFail ("Error: wrong syntax!");
1050     return 1;
1051   }
1052
1053   Handle(AIS_InteractiveContext) aCtx;
1054   Handle(V3d_View)               aView;
1055   if (!getCtxAndView (aCtx, aView))
1056   {
1057     return 1;
1058   }
1059
1060   aCtx->DisplayActiveSensitive (aView);
1061   return 0;
1062
1063 }
1064
1065 static Standard_Integer VClearSensi (Draw_Interpretor& ,
1066                                      Standard_Integer  theArgNb,
1067                                      Standard_CString* )
1068 {
1069   if (theArgNb > 1)
1070   {
1071     Message::SendFail ("Error: wrong syntax!");
1072     return 1;
1073   }
1074
1075   Handle(AIS_InteractiveContext) aCtx;
1076   Handle(V3d_View)               aView;
1077   if (!getCtxAndView (aCtx, aView))
1078   {
1079     return 1;
1080   }
1081   aCtx->ClearActiveSensitive (aView);
1082   return 0;
1083 }
1084
1085 //==============================================================================
1086 //function : VDir
1087 //purpose  : To list the displayed object with their attributes
1088 //==============================================================================
1089 static int VDir (Draw_Interpretor& theDI,
1090                  Standard_Integer theNbArgs,
1091                  const char** theArgVec)
1092 {
1093   TCollection_AsciiString aMatch;
1094   Standard_Boolean toFormat = Standard_False;
1095   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
1096   {
1097     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
1098     anArgCase.LowerCase();
1099     if (anArgCase == "-list"
1100      || anArgCase == "-format")
1101     {
1102       toFormat = Standard_True;
1103     }
1104     else if (aMatch.IsEmpty())
1105     {
1106       aMatch = theArgVec[anArgIter];
1107     }
1108     else
1109     {
1110       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
1111       return 1;
1112     }
1113   }
1114
1115   TCollection_AsciiString aRes;
1116   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
1117   {
1118     if (!aMatch.IsEmpty())
1119     {
1120       const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aMatch + "' '" + anIter.Key2() + "'";
1121       if (theDI.Eval (aCheck.ToCString()) == 0
1122       && *theDI.Result() != '1')
1123       {
1124         continue;
1125       }
1126     }
1127
1128     if (toFormat)
1129     {
1130       aRes += TCollection_AsciiString("\t") + anIter.Key2() + "\n";
1131     }
1132     else
1133     {
1134       aRes += anIter.Key2() + " ";
1135     }
1136   }
1137   theDI.Reset();
1138   theDI << aRes;
1139   return 0;
1140 }
1141
1142 //! Auxiliary enumeration
1143 enum ViewerTest_StereoPair
1144 {
1145   ViewerTest_SP_Single,
1146   ViewerTest_SP_SideBySide,
1147   ViewerTest_SP_OverUnder
1148 };
1149
1150 //==============================================================================
1151 //function : VDump
1152 //purpose  : To dump the active view snapshot to image file
1153 //==============================================================================
1154 static Standard_Integer VDump (Draw_Interpretor& theDI,
1155                                Standard_Integer  theArgNb,
1156                                Standard_CString* theArgVec)
1157 {
1158   if (theArgNb < 2)
1159   {
1160     Message::SendFail ("Error: wrong number of arguments! Image file name should be specified at least.");
1161     return 1;
1162   }
1163
1164   Standard_Integer      anArgIter   = 1;
1165   Standard_CString      aFilePath   = theArgVec[anArgIter++];
1166   ViewerTest_StereoPair aStereoPair = ViewerTest_SP_Single;
1167   V3d_ImageDumpOptions  aParams;
1168   aParams.BufferType    = Graphic3d_BT_RGB;
1169   aParams.StereoOptions = V3d_SDO_MONO;
1170   for (; anArgIter < theArgNb; ++anArgIter)
1171   {
1172     TCollection_AsciiString anArg (theArgVec[anArgIter]);
1173     anArg.LowerCase();
1174     if (anArg == "-buffer")
1175     {
1176       if (++anArgIter >= theArgNb)
1177       {
1178         Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
1179         return 1;
1180       }
1181
1182       TCollection_AsciiString aBufArg (theArgVec[anArgIter]);
1183       aBufArg.LowerCase();
1184       if (aBufArg == "rgba")
1185       {
1186         aParams.BufferType = Graphic3d_BT_RGBA;
1187       }
1188       else if (aBufArg == "rgb")
1189       {
1190         aParams.BufferType = Graphic3d_BT_RGB;
1191       }
1192       else if (aBufArg == "red")
1193       {
1194         aParams.BufferType = Graphic3d_BT_Red;
1195       }
1196       else if (aBufArg == "depth")
1197       {
1198         aParams.BufferType = Graphic3d_BT_Depth;
1199       }
1200       else
1201       {
1202         Message::SendFail() << "Error: unknown buffer '" << aBufArg << "'";
1203         return 1;
1204       }
1205     }
1206     else if (anArg == "-stereo")
1207     {
1208       if (++anArgIter >= theArgNb)
1209       {
1210         Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
1211         return 1;
1212       }
1213
1214       TCollection_AsciiString aStereoArg (theArgVec[anArgIter]);
1215       aStereoArg.LowerCase();
1216       if (aStereoArg == "l"
1217        || aStereoArg == "left")
1218       {
1219         aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1220       }
1221       else if (aStereoArg == "r"
1222             || aStereoArg == "right")
1223       {
1224         aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1225       }
1226       else if (aStereoArg == "mono")
1227       {
1228         aParams.StereoOptions = V3d_SDO_MONO;
1229       }
1230       else if (aStereoArg == "blended"
1231             || aStereoArg == "blend"
1232             || aStereoArg == "stereo")
1233       {
1234         aParams.StereoOptions = V3d_SDO_BLENDED;
1235       }
1236       else if (aStereoArg == "sbs"
1237             || aStereoArg == "sidebyside")
1238       {
1239         aStereoPair = ViewerTest_SP_SideBySide;
1240       }
1241       else if (aStereoArg == "ou"
1242             || aStereoArg == "overunder")
1243       {
1244         aStereoPair = ViewerTest_SP_OverUnder;
1245       }
1246       else
1247       {
1248         Message::SendFail() << "Error: unknown stereo format '" << aStereoArg << "'";
1249         return 1;
1250       }
1251     }
1252     else if (anArg == "-rgba"
1253           || anArg ==  "rgba")
1254     {
1255       aParams.BufferType = Graphic3d_BT_RGBA;
1256     }
1257     else if (anArg == "-rgb"
1258           || anArg ==  "rgb")
1259     {
1260       aParams.BufferType = Graphic3d_BT_RGB;
1261     }
1262     else if (anArg == "-red"
1263           || anArg ==  "red")
1264     {
1265       aParams.BufferType = Graphic3d_BT_Red;
1266     }
1267     else if (anArg == "-depth"
1268           || anArg ==  "depth")
1269     {
1270       aParams.BufferType = Graphic3d_BT_Depth;
1271     }
1272     else if (anArg == "-width"
1273           || anArg ==  "width"
1274           || anArg ==  "sizex")
1275     {
1276       if (aParams.Width != 0)
1277       {
1278         Message::SendFail() << "Error: wrong syntax at " << theArgVec[anArgIter];
1279         return 1;
1280       }
1281       else if (++anArgIter >= theArgNb)
1282       {
1283         Message::SendFail() << "Error: integer value is expected right after 'width'";
1284         return 1;
1285       }
1286       aParams.Width = Draw::Atoi (theArgVec[anArgIter]);
1287     }
1288     else if (anArg == "-height"
1289           || anArg ==  "height"
1290           || anArg ==  "-sizey")
1291     {
1292       if (aParams.Height != 0)
1293       {
1294         Message::SendFail() << "Error: wrong syntax at " << theArgVec[anArgIter];
1295         return 1;
1296       }
1297       else if (++anArgIter >= theArgNb)
1298       {
1299         Message::SendFail() << "Error: integer value is expected right after 'height'";
1300         return 1;
1301       }
1302       aParams.Height = Draw::Atoi (theArgVec[anArgIter]);
1303     }
1304     else if (anArg == "-tile"
1305           || anArg == "-tilesize")
1306     {
1307       if (++anArgIter >= theArgNb)
1308       {
1309         Message::SendFail() << "Error: integer value is expected right after 'tileSize'";
1310         return 1;
1311       }
1312       aParams.TileSize = Draw::Atoi (theArgVec[anArgIter]);
1313     }
1314     else
1315     {
1316       Message::SendFail() << "Error: unknown argument '" << theArgVec[anArgIter] << "'";
1317       return 1;
1318     }
1319   }
1320   if ((aParams.Width <= 0 && aParams.Height >  0)
1321    || (aParams.Width >  0 && aParams.Height <= 0))
1322   {
1323     Message::SendFail() << "Error: dimensions " << aParams.Width << "x" << aParams.Height << " are incorrect";
1324     return 1;
1325   }
1326
1327   Handle(V3d_View) aView = ViewerTest::CurrentView();
1328   if (aView.IsNull())
1329   {
1330     Message::SendFail() << "Error: cannot find an active view!";
1331     return 1;
1332   }
1333
1334   if (aParams.Width <= 0 || aParams.Height <= 0)
1335   {
1336     aView->Window()->Size (aParams.Width, aParams.Height);
1337   }
1338
1339   Image_AlienPixMap aPixMap;
1340   Image_Format aFormat = Image_Format_UNKNOWN;
1341   switch (aParams.BufferType)
1342   {
1343     case Graphic3d_BT_RGB:                 aFormat = Image_Format_RGB;   break;
1344     case Graphic3d_BT_RGBA:                aFormat = Image_Format_RGBA;  break;
1345     case Graphic3d_BT_Depth:               aFormat = Image_Format_GrayF; break;
1346     case Graphic3d_BT_RGB_RayTraceHdrLeft: aFormat = Image_Format_RGBF;  break;
1347     case Graphic3d_BT_Red:                 aFormat = Image_Format_Gray;  break;
1348   }
1349
1350   switch (aStereoPair)
1351   {
1352     case ViewerTest_SP_Single:
1353     {
1354       if (!aView->ToPixMap (aPixMap, aParams))
1355       {
1356         theDI << "Fail: view dump failed!\n";
1357         return 0;
1358       }
1359       else if (aPixMap.SizeX() != Standard_Size(aParams.Width)
1360             || aPixMap.SizeY() != Standard_Size(aParams.Height))
1361       {
1362         theDI << "Fail: dumped dimensions "    << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY()
1363               << " are lesser than requested " << aParams.Width << "x" << aParams.Height << "\n";
1364       }
1365       break;
1366     }
1367     case ViewerTest_SP_SideBySide:
1368     {
1369       if (!aPixMap.InitZero (aFormat, aParams.Width * 2, aParams.Height))
1370       {
1371         theDI << "Fail: not enough memory for image allocation!\n";
1372         return 0;
1373       }
1374
1375       Image_PixMap aPixMapL, aPixMapR;
1376       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
1377                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1378       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizePixelBytes() * aParams.Width,
1379                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1380
1381       aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1382       Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams);
1383       aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1384       isOk          = isOk && aView->ToPixMap (aPixMapR, aParams);
1385       if (!isOk)
1386       {
1387         theDI << "Fail: view dump failed!\n";
1388         return 0;
1389       }
1390       break;
1391     }
1392     case ViewerTest_SP_OverUnder:
1393     {
1394       if (!aPixMap.InitZero (aFormat, aParams.Width, aParams.Height * 2))
1395       {
1396         theDI << "Fail: not enough memory for image allocation!\n";
1397         return 0;
1398       }
1399
1400       Image_PixMap aPixMapL, aPixMapR;
1401       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
1402                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1403       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizeRowBytes() * aParams.Height,
1404                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1405
1406       aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1407       Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams);
1408       aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1409       isOk          = isOk && aView->ToPixMap (aPixMapR, aParams);
1410       if (!isOk)
1411       {
1412         theDI << "Fail: view dump failed!\n";
1413         return 0;
1414       }
1415       break;
1416     }
1417   }
1418
1419   if (!aPixMap.Save (aFilePath))
1420   {
1421     theDI << "Fail: image can not be saved!\n";
1422   }
1423   return 0;
1424 }
1425
1426 enum TypeOfDispOperation
1427 {
1428   TypeOfDispOperation_SetDispMode,
1429   TypeOfDispOperation_UnsetDispMode
1430 };
1431
1432 //! Displays,Erase...
1433 static void VwrTst_DispErase (const Handle(AIS_InteractiveObject)& thePrs,
1434                                                 const Standard_Integer theMode,
1435                                                 const TypeOfDispOperation theType,
1436                                                 const Standard_Boolean theToUpdate)
1437 {
1438   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1439   switch (theType)
1440   {
1441     case TypeOfDispOperation_SetDispMode:
1442     {
1443       if (!thePrs.IsNull())
1444       {
1445         aCtx->SetDisplayMode (thePrs, theMode, theToUpdate);
1446       }
1447       else
1448       {
1449         aCtx->SetDisplayMode ((AIS_DisplayMode )theMode, theToUpdate);
1450       }
1451       break;
1452     }
1453     case TypeOfDispOperation_UnsetDispMode:
1454     {
1455       if (!thePrs.IsNull())
1456       {
1457         aCtx->UnsetDisplayMode (thePrs, theToUpdate);
1458       }
1459       else
1460       {
1461         aCtx->SetDisplayMode (AIS_WireFrame, theToUpdate);
1462       }
1463       break;
1464     }
1465   }
1466 }
1467
1468 //=======================================================================
1469 //function :
1470 //purpose  :
1471 //=======================================================================
1472 static int VDispMode (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1473 {
1474   if (argc < 1
1475    || argc > 3)
1476   {
1477     Message::SendFail() << "Syntax error: wrong number of arguments";
1478     return 1;
1479   }
1480
1481   TypeOfDispOperation aType = TCollection_AsciiString (argv[0]) == "vunsetdispmode"
1482                             ? TypeOfDispOperation_UnsetDispMode
1483                             : TypeOfDispOperation_SetDispMode;
1484   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1485   if (aType == TypeOfDispOperation_UnsetDispMode)
1486   {
1487     if (argc == 1)
1488     {
1489       if (aCtx->NbSelected() == 0)
1490       {
1491         VwrTst_DispErase (Handle(AIS_InteractiveObject)(), -1, TypeOfDispOperation_UnsetDispMode, Standard_False);
1492       }
1493       else
1494       {
1495         for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
1496         {
1497           VwrTst_DispErase (aCtx->SelectedInteractive(), -1, TypeOfDispOperation_UnsetDispMode, Standard_False);
1498         }
1499       }
1500       aCtx->UpdateCurrentViewer();
1501     }
1502     else
1503     {
1504       TCollection_AsciiString aName = argv[1];
1505       Handle(AIS_InteractiveObject) aPrs;
1506       if (GetMapOfAIS().Find2 (aName, aPrs)
1507       && !aPrs.IsNull())
1508       {
1509         VwrTst_DispErase (aPrs, -1, TypeOfDispOperation_UnsetDispMode, Standard_True);
1510       }
1511     }
1512   }
1513   else if (argc == 2)
1514   {
1515     Standard_Integer aDispMode = Draw::Atoi (argv[1]);
1516     if (aCtx->NbSelected() == 0
1517      && aType == TypeOfDispOperation_SetDispMode)
1518     {
1519       VwrTst_DispErase (Handle(AIS_InteractiveObject)(), aDispMode, TypeOfDispOperation_SetDispMode, Standard_True);
1520     }
1521     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
1522     {
1523       VwrTst_DispErase (aCtx->SelectedInteractive(), aDispMode, aType, Standard_False);
1524     }
1525     aCtx->UpdateCurrentViewer();
1526   }
1527   else
1528   {
1529     Handle(AIS_InteractiveObject) aPrs;
1530     TCollection_AsciiString aName (argv[1]);
1531     if (GetMapOfAIS().Find2 (aName, aPrs)
1532      && !aPrs.IsNull())
1533     {
1534       VwrTst_DispErase (aPrs, Draw::Atoi(argv[2]), aType, Standard_True);
1535     }
1536   }
1537   return 0;
1538 }
1539
1540
1541 //=======================================================================
1542 //function :
1543 //purpose  :
1544 //=======================================================================
1545 static int VSubInt(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1546 {
1547   if(argc==1) return 1;
1548   Standard_Integer On = Draw::Atoi(argv[1]);
1549   const Handle(AIS_InteractiveContext)& Ctx = ViewerTest::GetAISContext();
1550
1551   if(argc==2)
1552   {
1553     TCollection_AsciiString isOnOff = On == 1 ? "on" : "off";
1554     di << "Sub intensite is turned " << isOnOff << " for " << Ctx->NbSelected() << "objects\n";
1555     for (Ctx->InitSelected(); Ctx->MoreSelected(); Ctx->NextSelected())
1556     {
1557       if(On==1)
1558       {
1559         Ctx->SubIntensityOn (Ctx->SelectedInteractive(), Standard_False);
1560       }
1561       else
1562       {
1563         Ctx->SubIntensityOff (Ctx->SelectedInteractive(), Standard_False);
1564       }
1565     }
1566
1567     Ctx->UpdateCurrentViewer();
1568   }
1569   else {
1570     Handle(AIS_InteractiveObject) IO;
1571     TCollection_AsciiString name = argv[2];
1572     if (GetMapOfAIS().Find2 (name, IO)
1573     && !IO.IsNull())
1574     {
1575       if(On==1)
1576         Ctx->SubIntensityOn(IO, Standard_True);
1577       else
1578         Ctx->SubIntensityOff(IO, Standard_True);
1579     }
1580     else return 1;
1581   }
1582   return 0;
1583 }
1584
1585 //! Auxiliary class to iterate presentations from different collections.
1586 class ViewTest_PrsIter
1587 {
1588 public:
1589
1590   //! Create and initialize iterator object.
1591   ViewTest_PrsIter (const TCollection_AsciiString& theName)
1592   : mySource (IterSource_All)
1593   {
1594     NCollection_Sequence<TCollection_AsciiString> aNames;
1595     if (!theName.IsEmpty())
1596     aNames.Append (theName);
1597     Init (aNames);
1598   }
1599
1600   //! Create and initialize iterator object.
1601   ViewTest_PrsIter (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1602   : mySource (IterSource_All)
1603   {
1604     Init (theNames);
1605   }
1606
1607   //! Initialize the iterator.
1608   void Init (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1609   {
1610     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1611     mySeq = theNames;
1612     mySelIter.Nullify();
1613     myCurrent.Nullify();
1614     myCurrentTrs.Nullify();
1615     if (!mySeq.IsEmpty())
1616     {
1617       mySource = IterSource_List;
1618       mySeqIter = NCollection_Sequence<TCollection_AsciiString>::Iterator (mySeq);
1619     }
1620     else if (aCtx->NbSelected() > 0)
1621     {
1622       mySource  = IterSource_Selected;
1623       mySelIter = aCtx;
1624       mySelIter->InitSelected();
1625     }
1626     else
1627     {
1628       mySource = IterSource_All;
1629       myMapIter.Initialize (GetMapOfAIS());
1630     }
1631     initCurrent();
1632   }
1633
1634   const TCollection_AsciiString& CurrentName() const
1635   {
1636     return myCurrentName;
1637   }
1638
1639   const Handle(AIS_InteractiveObject)& Current() const
1640   {
1641     return myCurrent;
1642   }
1643
1644   const Handle(Standard_Transient)& CurrentTrs() const
1645   {
1646     return myCurrentTrs;
1647   }
1648
1649   //! @return true if iterator points to valid object within collection
1650   Standard_Boolean More() const
1651   {
1652     switch (mySource)
1653     {
1654       case IterSource_All:      return myMapIter.More();
1655       case IterSource_List:     return mySeqIter.More();
1656       case IterSource_Selected: return mySelIter->MoreSelected();
1657     }
1658     return Standard_False;
1659   }
1660
1661   //! Go to the next item.
1662   void Next()
1663   {
1664     myCurrentName.Clear();
1665     myCurrentTrs.Nullify();
1666     myCurrent.Nullify();
1667     switch (mySource)
1668     {
1669       case IterSource_All:
1670       {
1671         myMapIter.Next();
1672         break;
1673       }
1674       case IterSource_List:
1675       {
1676         mySeqIter.Next();
1677         break;
1678       }
1679       case IterSource_Selected:
1680       {
1681         mySelIter->NextSelected();
1682         break;
1683       }
1684     }
1685     initCurrent();
1686   }
1687
1688 private:
1689
1690   void initCurrent()
1691   {
1692     switch (mySource)
1693     {
1694       case IterSource_All:
1695       {
1696         if (myMapIter.More())
1697         {
1698           myCurrentName = myMapIter.Key2();
1699           myCurrentTrs  = myMapIter.Key1();
1700           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1701         }
1702         break;
1703       }
1704       case IterSource_List:
1705       {
1706         if (mySeqIter.More())
1707         {
1708           if (!GetMapOfAIS().IsBound2 (mySeqIter.Value()))
1709           {
1710             Message::SendFail() << "Error: object " << mySeqIter.Value() << " is not displayed!";
1711             return;
1712           }
1713           myCurrentName = mySeqIter.Value();
1714           myCurrentTrs  = GetMapOfAIS().Find2 (mySeqIter.Value());
1715           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1716         }
1717         break;
1718       }
1719       case IterSource_Selected:
1720       {
1721         if (mySelIter->MoreSelected())
1722         {
1723           myCurrentName = GetMapOfAIS().Find1 (mySelIter->SelectedInteractive());
1724           myCurrent     = mySelIter->SelectedInteractive();
1725         }
1726         break;
1727       }
1728     }
1729   }
1730
1731 private:
1732
1733   enum IterSource
1734   {
1735     IterSource_All,
1736     IterSource_List,
1737     IterSource_Selected
1738   };
1739
1740 private:
1741
1742   Handle(AIS_InteractiveContext) mySelIter;    //!< iterator for current (selected) objects (IterSource_Selected)
1743   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName myMapIter; //!< iterator for map of all objects (IterSource_All)
1744   NCollection_Sequence<TCollection_AsciiString>           mySeq;
1745   NCollection_Sequence<TCollection_AsciiString>::Iterator mySeqIter;
1746
1747   TCollection_AsciiString        myCurrentName;//!< current item name
1748   Handle(Standard_Transient)     myCurrentTrs; //!< current item (as transient object)
1749   Handle(AIS_InteractiveObject)  myCurrent;    //!< current item
1750
1751   IterSource                     mySource;     //!< iterated collection
1752
1753 };
1754
1755 //! Parse interior style name.
1756 static bool parseInteriorStyle (const TCollection_AsciiString& theArg,
1757                                 Aspect_InteriorStyle& theStyle)
1758 {
1759   TCollection_AsciiString anArg (theArg);
1760   anArg.LowerCase();
1761   if (anArg == "empty")
1762   {
1763     theStyle = Aspect_IS_EMPTY;
1764   }
1765   else if (anArg == "hollow")
1766   {
1767     theStyle = Aspect_IS_HOLLOW;
1768   }
1769   else if (anArg == "solid")
1770   {
1771     theStyle = Aspect_IS_SOLID;
1772   }
1773   else if (anArg == "hatch")
1774   {
1775     theStyle = Aspect_IS_HATCH;
1776   }
1777   else if (anArg == "hiddenline"
1778         || anArg == "hidden-line"
1779         || anArg == "hidden_line")
1780   {
1781     theStyle = Aspect_IS_HIDDENLINE;
1782   }
1783   else if (anArg == "point")
1784   {
1785     theStyle = Aspect_IS_POINT;
1786   }
1787   else if (theArg.IsIntegerValue())
1788   {
1789     const Standard_Integer anIntStyle = theArg.IntegerValue();
1790     if (anIntStyle < Aspect_IS_EMPTY || anIntStyle > Aspect_IS_POINT)
1791     {
1792       return false;
1793     }
1794     theStyle = (Aspect_InteriorStyle)anIntStyle;
1795   }
1796   else
1797   {
1798     return false;
1799   }
1800   return true;
1801 }
1802
1803 //! Auxiliary structure for VAspects
1804 struct ViewerTest_AspectsChangeSet
1805 {
1806   Standard_Integer             ToSetVisibility;
1807   Standard_Integer             Visibility;
1808
1809   Standard_Integer             ToSetColor;
1810   Quantity_Color               Color;
1811   Standard_Integer             ToSetBackFaceColor;
1812   Quantity_Color               BackFaceColor;
1813
1814   Standard_Integer             ToSetLineWidth;
1815   Standard_Real                LineWidth;
1816
1817   Standard_Integer             ToSetTypeOfLine;
1818   uint16_t                     StippleLinePattern;
1819
1820   Standard_Integer             ToSetTypeOfMarker;
1821   Aspect_TypeOfMarker          TypeOfMarker;
1822   Handle(Image_PixMap)         MarkerImage;
1823
1824   Standard_Integer             ToSetMarkerSize;
1825   Standard_Real                MarkerSize;
1826
1827   Standard_Integer             ToSetTransparency;
1828   Standard_Real                Transparency;
1829
1830   Standard_Integer             ToSetAlphaMode;
1831   Graphic3d_AlphaMode          AlphaMode;
1832   Standard_ShortReal           AlphaCutoff;
1833
1834   Standard_Integer             ToSetMaterial;
1835   Graphic3d_NameOfMaterial     Material;
1836   TCollection_AsciiString      MatName;
1837
1838   NCollection_Sequence<TopoDS_Shape> SubShapes;
1839
1840   Standard_Integer             ToSetShowFreeBoundary;
1841   Standard_Integer             ToSetFreeBoundaryWidth;
1842   Standard_Real                FreeBoundaryWidth;
1843   Standard_Integer             ToSetFreeBoundaryColor;
1844   Quantity_Color               FreeBoundaryColor;
1845
1846   Standard_Integer             ToEnableIsoOnTriangulation;
1847
1848   Standard_Integer             ToSetFaceBoundaryDraw;
1849   Standard_Integer             ToSetFaceBoundaryUpperContinuity;
1850   GeomAbs_Shape                FaceBoundaryUpperContinuity;
1851
1852   Standard_Integer             ToSetFaceBoundaryColor;
1853   Quantity_Color               FaceBoundaryColor;
1854
1855   Standard_Integer             ToSetFaceBoundaryWidth;
1856   Standard_Real                FaceBoundaryWidth;
1857
1858   Standard_Integer             ToSetTypeOfFaceBoundaryLine;
1859   Aspect_TypeOfLine            TypeOfFaceBoundaryLine;
1860
1861   Standard_Integer             ToSetMaxParamValue;
1862   Standard_Real                MaxParamValue;
1863
1864   Standard_Integer             ToSetSensitivity;
1865   Standard_Integer             SelectionMode;
1866   Standard_Integer             Sensitivity;
1867
1868   Standard_Integer             ToSetHatch;
1869   Standard_Integer             StdHatchStyle;
1870   TCollection_AsciiString      PathToHatchPattern;
1871
1872   Standard_Integer             ToSetShadingModel;
1873   Graphic3d_TypeOfShadingModel ShadingModel;
1874   TCollection_AsciiString      ShadingModelName;
1875
1876   Standard_Integer             ToSetInterior;
1877   Aspect_InteriorStyle         InteriorStyle;
1878
1879   Standard_Integer             ToSetDrawSilhouette;
1880
1881   Standard_Integer             ToSetDrawEdges;
1882   Standard_Integer             ToSetQuadEdges;
1883
1884   Standard_Integer             ToSetEdgeColor;
1885   Quantity_ColorRGBA           EdgeColor;
1886
1887   Standard_Integer             ToSetEdgeWidth;
1888   Standard_Real                EdgeWidth;
1889
1890   Standard_Integer             ToSetTypeOfEdge;
1891   Aspect_TypeOfLine            TypeOfEdge;
1892
1893   //! Empty constructor
1894   ViewerTest_AspectsChangeSet()
1895   : ToSetVisibility   (0),
1896     Visibility        (1),
1897     ToSetColor        (0),
1898     Color             (DEFAULT_COLOR),
1899     ToSetBackFaceColor(0),
1900     BackFaceColor     (DEFAULT_COLOR),
1901     ToSetLineWidth    (0),
1902     LineWidth         (1.0),
1903     ToSetTypeOfLine   (0),
1904     StippleLinePattern(0xFFFF),
1905     ToSetTypeOfMarker (0),
1906     TypeOfMarker      (Aspect_TOM_PLUS),
1907     ToSetMarkerSize   (0),
1908     MarkerSize        (1.0),
1909     ToSetTransparency (0),
1910     Transparency      (0.0),
1911     ToSetAlphaMode    (0),
1912     AlphaMode         (Graphic3d_AlphaMode_BlendAuto),
1913     AlphaCutoff       (0.5f),
1914     ToSetMaterial     (0),
1915     Material          (Graphic3d_NOM_DEFAULT),
1916     ToSetShowFreeBoundary      (0),
1917     ToSetFreeBoundaryWidth     (0),
1918     FreeBoundaryWidth          (1.0),
1919     ToSetFreeBoundaryColor     (0),
1920     FreeBoundaryColor          (DEFAULT_FREEBOUNDARY_COLOR),
1921     ToEnableIsoOnTriangulation (0),
1922     //
1923     ToSetFaceBoundaryDraw      (0),
1924     ToSetFaceBoundaryUpperContinuity (0),
1925     FaceBoundaryUpperContinuity(GeomAbs_CN),
1926     ToSetFaceBoundaryColor     (0),
1927     FaceBoundaryColor          (Quantity_NOC_BLACK),
1928     ToSetFaceBoundaryWidth     (0),
1929     FaceBoundaryWidth          (1.0f),
1930     ToSetTypeOfFaceBoundaryLine(0),
1931     TypeOfFaceBoundaryLine     (Aspect_TOL_SOLID),
1932     //
1933     ToSetMaxParamValue         (0),
1934     MaxParamValue              (500000),
1935     ToSetSensitivity           (0),
1936     SelectionMode              (-1),
1937     Sensitivity                (-1),
1938     ToSetHatch                 (0),
1939     StdHatchStyle              (-1),
1940     ToSetShadingModel          (0),
1941     ShadingModel               (Graphic3d_TOSM_DEFAULT),
1942     ToSetInterior              (0),
1943     InteriorStyle              (Aspect_IS_SOLID),
1944     ToSetDrawSilhouette (0),
1945     ToSetDrawEdges    (0),
1946     ToSetQuadEdges    (0),
1947     ToSetEdgeColor    (0),
1948     ToSetEdgeWidth    (0),
1949     EdgeWidth         (1.0),
1950     ToSetTypeOfEdge   (0),
1951     TypeOfEdge        (Aspect_TOL_SOLID)
1952     {}
1953
1954   //! @return true if no changes have been requested
1955   Standard_Boolean IsEmpty() const
1956   {
1957     return ToSetVisibility        == 0
1958         && ToSetLineWidth         == 0
1959         && ToSetTransparency      == 0
1960         && ToSetAlphaMode         == 0
1961         && ToSetColor             == 0
1962         && ToSetBackFaceColor     == 0
1963         && ToSetMaterial          == 0
1964         && ToSetShowFreeBoundary  == 0
1965         && ToSetFreeBoundaryColor == 0
1966         && ToSetFreeBoundaryWidth == 0
1967         && ToEnableIsoOnTriangulation == 0
1968         && ToSetFaceBoundaryDraw == 0
1969         && ToSetFaceBoundaryUpperContinuity == 0
1970         && ToSetFaceBoundaryColor == 0
1971         && ToSetFaceBoundaryWidth == 0
1972         && ToSetTypeOfFaceBoundaryLine == 0
1973         && ToSetMaxParamValue     == 0
1974         && ToSetSensitivity       == 0
1975         && ToSetHatch             == 0
1976         && ToSetShadingModel      == 0
1977         && ToSetInterior          == 0
1978         && ToSetDrawSilhouette    == 0
1979         && ToSetDrawEdges         == 0
1980         && ToSetQuadEdges         == 0
1981         && ToSetEdgeColor         == 0
1982         && ToSetEdgeWidth         == 0
1983         && ToSetTypeOfEdge        == 0;
1984   }
1985
1986   //! @return true if properties are valid
1987   Standard_Boolean Validate() const
1988   {
1989     Standard_Boolean isOk = Standard_True;
1990     if (Visibility != 0 && Visibility != 1)
1991     {
1992       Message::SendFail() << "Error: the visibility should be equal to 0 or 1 (0 - invisible; 1 - visible) (specified " << Visibility << ")";
1993       isOk = Standard_False;
1994     }
1995     if (LineWidth <= 0.0
1996      || LineWidth >  10.0)
1997     {
1998       Message::SendFail() << "Error: the width should be within [1; 10] range (specified " << LineWidth << ")";
1999       isOk = Standard_False;
2000     }
2001     if (Transparency < 0.0
2002      || Transparency > 1.0)
2003     {
2004       Message::SendFail() << "Error: the transparency should be within [0; 1] range (specified " << Transparency << ")";
2005       isOk = Standard_False;
2006     }
2007     if (ToSetAlphaMode == 1
2008      && (AlphaCutoff <= 0.0f || AlphaCutoff >= 1.0f))
2009     {
2010       Message::SendFail() << "Error: alpha cutoff value should be within (0; 1) range (specified " << AlphaCutoff << ")";
2011       isOk = Standard_False;
2012     }
2013     if (FreeBoundaryWidth <= 0.0
2014      || FreeBoundaryWidth >  10.0)
2015     {
2016       Message::SendFail() << "Error: the free boundary width should be within [1; 10] range (specified " << FreeBoundaryWidth << ")";
2017       isOk = Standard_False;
2018     }
2019     if (MaxParamValue < 0.0)
2020     {
2021       Message::SendFail() << "Error: the max parameter value should be greater than zero (specified " << MaxParamValue << ")";
2022       isOk = Standard_False;
2023     }
2024     if (Sensitivity <= 0 && ToSetSensitivity)
2025     {
2026       Message::SendFail() << "Error: sensitivity parameter value should be positive (specified " << Sensitivity << ")";
2027       isOk = Standard_False;
2028     }
2029     if (ToSetHatch == 1 && StdHatchStyle < 0 && PathToHatchPattern == "")
2030     {
2031       Message::SendFail ("Error: hatch style must be specified");
2032       isOk = Standard_False;
2033     }
2034     if (ToSetShadingModel == 1
2035     && (ShadingModel < Graphic3d_TOSM_DEFAULT || ShadingModel > Graphic3d_TOSM_PBR_FACET))
2036     {
2037       Message::SendFail() << "Error: unknown shading model " << ShadingModelName << ".";
2038       isOk = Standard_False;
2039     }
2040     return isOk;
2041   }
2042
2043   //! Apply aspects to specified drawer.
2044   bool Apply (const Handle(Prs3d_Drawer)& theDrawer)
2045   {
2046     bool toRecompute = false;
2047     const Handle(Prs3d_Drawer)& aDefDrawer = ViewerTest::GetAISContext()->DefaultDrawer();
2048     if (ToSetShowFreeBoundary != 0)
2049     {
2050       theDrawer->SetFreeBoundaryDraw (ToSetShowFreeBoundary == 1);
2051       toRecompute = true;
2052     }
2053     if (ToSetFreeBoundaryWidth != 0)
2054     {
2055       if (ToSetFreeBoundaryWidth != -1
2056        || theDrawer->HasOwnFreeBoundaryAspect())
2057       {
2058         if (!theDrawer->HasOwnFreeBoundaryAspect())
2059         {
2060           Handle(Prs3d_LineAspect) aBoundaryAspect = new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2061           *aBoundaryAspect->Aspect() = *theDrawer->FreeBoundaryAspect()->Aspect();
2062           theDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2063           toRecompute = true;
2064         }
2065         theDrawer->FreeBoundaryAspect()->SetWidth (FreeBoundaryWidth);
2066       }
2067     }
2068     if (ToSetFreeBoundaryColor != 0)
2069     {
2070       Handle(Prs3d_LineAspect) aBoundaryAspect = new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2071       *aBoundaryAspect->Aspect() = *theDrawer->FreeBoundaryAspect()->Aspect();
2072       aBoundaryAspect->SetColor (FreeBoundaryColor);
2073       theDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2074       toRecompute = true;
2075     }
2076     if (ToSetTypeOfLine != 0)
2077     {
2078       if (ToSetTypeOfLine != -1
2079        || theDrawer->HasOwnLineAspect()
2080        || theDrawer->HasOwnWireAspect()
2081        || theDrawer->HasOwnFreeBoundaryAspect()
2082        || theDrawer->HasOwnUnFreeBoundaryAspect()
2083        || theDrawer->HasOwnSeenLineAspect())
2084       {
2085         toRecompute = theDrawer->SetOwnLineAspects() || toRecompute;
2086         theDrawer->LineAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2087         theDrawer->WireAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2088         theDrawer->FreeBoundaryAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2089         theDrawer->UnFreeBoundaryAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2090         theDrawer->SeenLineAspect()->Aspect()->SetLinePattern (StippleLinePattern);
2091       }
2092     }
2093     if (ToSetTypeOfMarker != 0)
2094     {
2095       if (ToSetTypeOfMarker != -1
2096        || theDrawer->HasOwnPointAspect())
2097       {
2098         toRecompute = theDrawer->SetupOwnPointAspect (aDefDrawer) || toRecompute;
2099         theDrawer->PointAspect()->SetTypeOfMarker (TypeOfMarker);
2100         theDrawer->PointAspect()->Aspect()->SetMarkerImage (MarkerImage.IsNull() ? Handle(Graphic3d_MarkerImage)() : new Graphic3d_MarkerImage (MarkerImage));
2101       }
2102     }
2103     if (ToSetMarkerSize != 0)
2104     {
2105       if (ToSetMarkerSize != -1
2106        || theDrawer->HasOwnPointAspect())
2107       {
2108         toRecompute = theDrawer->SetupOwnPointAspect (aDefDrawer) || toRecompute;
2109         theDrawer->PointAspect()->SetScale (MarkerSize);
2110         toRecompute = true;
2111       }
2112     }
2113     if (ToSetMaxParamValue != 0)
2114     {
2115       if (ToSetMaxParamValue != -1
2116        || theDrawer->HasOwnMaximalParameterValue())
2117       {
2118         theDrawer->SetMaximalParameterValue (MaxParamValue);
2119         toRecompute = true;
2120       }
2121     }
2122     if (ToSetFaceBoundaryDraw != 0)
2123     {
2124       if (ToSetFaceBoundaryDraw != -1
2125        || theDrawer->HasOwnFaceBoundaryDraw())
2126       {
2127         toRecompute = true;
2128         theDrawer->SetFaceBoundaryDraw (ToSetFaceBoundaryDraw == 1);
2129       }
2130     }
2131     if (ToSetFaceBoundaryUpperContinuity != 0)
2132     {
2133       if (ToSetFaceBoundaryUpperContinuity != -1
2134        || theDrawer->HasOwnFaceBoundaryUpperContinuity())
2135       {
2136         toRecompute = true;
2137         if (ToSetFaceBoundaryUpperContinuity == -1)
2138         {
2139           theDrawer->UnsetFaceBoundaryUpperContinuity();
2140         }
2141         else
2142         {
2143           theDrawer->SetFaceBoundaryUpperContinuity (FaceBoundaryUpperContinuity);
2144         }
2145       }
2146     }
2147     if (ToSetFaceBoundaryColor != 0)
2148     {
2149       if (ToSetFaceBoundaryColor != -1
2150        || theDrawer->HasOwnFaceBoundaryAspect())
2151       {
2152         if (ToSetFaceBoundaryColor == -1)
2153         {
2154           toRecompute = true;
2155           theDrawer->SetFaceBoundaryAspect (Handle(Prs3d_LineAspect)());
2156         }
2157         else
2158         {
2159           toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2160           theDrawer->FaceBoundaryAspect()->SetColor (FaceBoundaryColor);
2161         }
2162       }
2163     }
2164     if (ToSetFaceBoundaryWidth != 0)
2165     {
2166       if (ToSetFaceBoundaryWidth != -1
2167        || theDrawer->HasOwnFaceBoundaryAspect())
2168       {
2169         toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2170         theDrawer->FaceBoundaryAspect()->SetWidth (FaceBoundaryWidth);
2171       }
2172     }
2173     if (ToSetTypeOfFaceBoundaryLine != 0)
2174     {
2175       if (ToSetTypeOfFaceBoundaryLine != -1
2176        || theDrawer->HasOwnFaceBoundaryAspect())
2177       {
2178         toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2179         theDrawer->FaceBoundaryAspect()->SetTypeOfLine (TypeOfFaceBoundaryLine);
2180       }
2181     }
2182     if (ToSetShadingModel != 0)
2183     {
2184       if (ToSetShadingModel != -1
2185        || theDrawer->HasOwnShadingAspect())
2186       {
2187         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2188         theDrawer->ShadingAspect()->Aspect()->SetShadingModel (ShadingModel);
2189       }
2190     }
2191     if (ToSetBackFaceColor != 0)
2192     {
2193       if (ToSetBackFaceColor != -1
2194        || theDrawer->HasOwnShadingAspect())
2195       {
2196         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2197         theDrawer->ShadingAspect()->SetColor (BackFaceColor, Aspect_TOFM_BACK_SIDE);
2198       }
2199     }
2200     if (ToSetAlphaMode != 0)
2201     {
2202       if (ToSetAlphaMode != -1
2203        || theDrawer->HasOwnShadingAspect())
2204       {
2205         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2206         theDrawer->ShadingAspect()->Aspect()->SetAlphaMode (AlphaMode, AlphaCutoff);
2207       }
2208     }
2209     if (ToSetHatch != 0)
2210     {
2211       if (ToSetHatch != -1
2212       ||  theDrawer->HasOwnShadingAspect())
2213       {
2214         theDrawer->SetupOwnShadingAspect (aDefDrawer);
2215         Handle(Graphic3d_AspectFillArea3d) anAsp = theDrawer->ShadingAspect()->Aspect();
2216         if (ToSetHatch == -1)
2217         {
2218           anAsp->SetInteriorStyle (Aspect_IS_SOLID);
2219         }
2220         else
2221         {
2222           anAsp->SetInteriorStyle (Aspect_IS_HATCH);
2223           if (!PathToHatchPattern.IsEmpty())
2224           {
2225             Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
2226             if (anImage->Load (TCollection_AsciiString (PathToHatchPattern.ToCString())))
2227             {
2228               anAsp->SetHatchStyle (new Graphic3d_HatchStyle (anImage));
2229             }
2230             else
2231             {
2232               Message::SendFail() << "Error: cannot load the following image: " << PathToHatchPattern;
2233             }
2234           }
2235           else if (StdHatchStyle != -1)
2236           {
2237             anAsp->SetHatchStyle (new Graphic3d_HatchStyle ((Aspect_HatchStyle)StdHatchStyle));
2238           }
2239         }
2240         toRecompute = true;
2241       }
2242     }
2243     if (ToSetInterior != 0)
2244     {
2245       if (ToSetInterior != -1
2246        || theDrawer->HasOwnShadingAspect())
2247       {
2248         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2249         theDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (InteriorStyle);
2250         if (InteriorStyle == Aspect_IS_HATCH
2251          && theDrawer->ShadingAspect()->Aspect()->HatchStyle().IsNull())
2252         {
2253           theDrawer->ShadingAspect()->Aspect()->SetHatchStyle (Aspect_HS_VERTICAL);
2254         }
2255       }
2256     }
2257     if (ToSetDrawSilhouette != 0)
2258     {
2259       if (ToSetDrawSilhouette != -1
2260        || theDrawer->HasOwnShadingAspect())
2261       {
2262         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2263         theDrawer->ShadingAspect()->Aspect()->SetDrawSilhouette (ToSetDrawSilhouette == 1);
2264       }
2265     }
2266     if (ToSetDrawEdges != 0)
2267     {
2268       if (ToSetDrawEdges != -1
2269        || theDrawer->HasOwnShadingAspect())
2270       {
2271         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2272         theDrawer->ShadingAspect()->Aspect()->SetDrawEdges (ToSetDrawEdges == 1);
2273       }
2274     }
2275     if (ToSetQuadEdges != 0)
2276     {
2277       if (ToSetQuadEdges != -1
2278           || theDrawer->HasOwnShadingAspect())
2279       {
2280         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2281         theDrawer->ShadingAspect()->Aspect()->SetSkipFirstEdge (ToSetQuadEdges == 1);
2282       }
2283     }
2284     if (ToSetEdgeWidth != 0)
2285     {
2286       if (ToSetEdgeWidth != -1
2287        || theDrawer->HasOwnShadingAspect())
2288       {
2289         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2290         theDrawer->ShadingAspect()->Aspect()->SetEdgeWidth (EdgeWidth);
2291       }
2292     }
2293     if (ToSetTypeOfEdge != 0)
2294     {
2295       if (ToSetTypeOfEdge != -1
2296        || theDrawer->HasOwnShadingAspect())
2297       {
2298         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2299         theDrawer->ShadingAspect()->Aspect()->SetEdgeLineType (TypeOfEdge);
2300         if (ToSetInterior == 0)
2301         {
2302           theDrawer->ShadingAspect()->Aspect()->SetDrawEdges (ToSetTypeOfEdge == 1
2303                                                            && TypeOfEdge != Aspect_TOL_EMPTY);
2304         }
2305       }
2306     }
2307     if (ToSetEdgeColor != 0)
2308     {
2309       if (ToSetEdgeColor != -1
2310        || theDrawer->HasOwnShadingAspect())
2311       {
2312         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2313         if (ToSetEdgeColor == -1)
2314         {
2315           theDrawer->ShadingAspect()->Aspect()->SetEdgeColor (theDrawer->ShadingAspect()->Aspect()->InteriorColor());
2316         }
2317         else
2318         {
2319           theDrawer->ShadingAspect()->Aspect()->SetEdgeColor (EdgeColor);
2320         }
2321       }
2322     }
2323     return toRecompute;
2324   }
2325 };
2326
2327 //==============================================================================
2328 //function : VAspects
2329 //purpose  :
2330 //==============================================================================
2331 static Standard_Integer VAspects (Draw_Interpretor& theDI,
2332                                   Standard_Integer  theArgNb,
2333                                   const char**      theArgVec)
2334 {
2335   TCollection_AsciiString aCmdName (theArgVec[0]);
2336   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2337   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2338   if (aCtx.IsNull())
2339   {
2340     Message::SendFail ("Error: no active view!");
2341     return 1;
2342   }
2343
2344   Standard_Integer anArgIter = 1;
2345   Standard_Boolean isDefaults = Standard_False;
2346   NCollection_Sequence<TCollection_AsciiString> aNames;
2347   for (; anArgIter < theArgNb; ++anArgIter)
2348   {
2349     TCollection_AsciiString anArg = theArgVec[anArgIter];
2350     if (anUpdateTool.parseRedrawMode (anArg))
2351     {
2352       continue;
2353     }
2354     else if (!anArg.IsEmpty()
2355            && anArg.Value (1) != '-')
2356     {
2357       aNames.Append (anArg);
2358     }
2359     else
2360     {
2361       if (anArg == "-defaults")
2362       {
2363         isDefaults = Standard_True;
2364         ++anArgIter;
2365       }
2366       break;
2367     }
2368   }
2369
2370   if (!aNames.IsEmpty() && isDefaults)
2371   {
2372     Message::SendFail ("Error: wrong syntax. If -defaults is used there should not be any objects' names!");
2373     return 1;
2374   }
2375
2376   NCollection_Sequence<ViewerTest_AspectsChangeSet> aChanges;
2377   aChanges.Append (ViewerTest_AspectsChangeSet());
2378   ViewerTest_AspectsChangeSet* aChangeSet = &aChanges.ChangeLast();
2379
2380   // parse syntax of legacy commands
2381   bool toParseAliasArgs = false;
2382   Standard_Boolean toDump = 0;
2383   Standard_Boolean toCompactDump = 0;
2384   Standard_Integer aDumpDepth = -1;
2385   if (aCmdName == "vsetwidth")
2386   {
2387     if (aNames.IsEmpty()
2388     || !aNames.Last().IsRealValue())
2389     {
2390       Message::SendFail ("Error: not enough arguments!");
2391       return 1;
2392     }
2393     aChangeSet->ToSetLineWidth = 1;
2394     aChangeSet->LineWidth = aNames.Last().RealValue();
2395     aNames.Remove (aNames.Length());
2396   }
2397   else if (aCmdName == "vunsetwidth")
2398   {
2399     aChangeSet->ToSetLineWidth = -1;
2400   }
2401   else if (aCmdName == "vsetcolor")
2402   {
2403     if (aNames.IsEmpty())
2404     {
2405       Message::SendFail ("Error: not enough arguments!");
2406       return 1;
2407     }
2408     aChangeSet->ToSetColor = 1;
2409
2410     Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
2411     Standard_Boolean     isOk   = Standard_False;
2412     if (Quantity_Color::ColorFromName (aNames.Last().ToCString(), aColor))
2413     {
2414       aChangeSet->Color = aColor;
2415       aNames.Remove (aNames.Length());
2416       isOk = Standard_True;
2417     }
2418     else if (Quantity_Color::ColorFromHex (aNames.Last().ToCString(), aChangeSet->Color))
2419     {
2420       aNames.Remove (aNames.Length());
2421       isOk = Standard_True;
2422     }
2423     else if (aNames.Length() >= 3)
2424     {
2425       const char* anArgVec[3] =
2426       {
2427         aNames.Value (aNames.Upper() - 2).ToCString(),
2428         aNames.Value (aNames.Upper() - 1).ToCString(),
2429         aNames.Value (aNames.Upper() - 0).ToCString(),
2430       };
2431
2432       Standard_Integer aNbParsed = ViewerTest::ParseColor (3, anArgVec, aChangeSet->Color);
2433       isOk = aNbParsed == 3;
2434       aNames.Remove (aNames.Length());
2435       aNames.Remove (aNames.Length());
2436       aNames.Remove (aNames.Length());
2437     }
2438     if (!isOk)
2439     {
2440       Message::SendFail ("Error: not enough arguments!");
2441       return 1;
2442     }
2443   }
2444   else if (aCmdName == "vunsetcolor")
2445   {
2446     aChangeSet->ToSetColor = -1;
2447   }
2448   else if (aCmdName == "vsettransparency")
2449   {
2450     if (aNames.IsEmpty()
2451     || !aNames.Last().IsRealValue())
2452     {
2453       Message::SendFail ("Error: not enough arguments!");
2454       return 1;
2455     }
2456     aChangeSet->ToSetTransparency = 1;
2457     aChangeSet->Transparency  = aNames.Last().RealValue();
2458     aNames.Remove (aNames.Length());
2459   }
2460   else if (aCmdName == "vunsettransparency")
2461   {
2462     aChangeSet->ToSetTransparency = -1;
2463   }
2464   else if (aCmdName == "vsetmaterial")
2465   {
2466     if (aNames.IsEmpty())
2467     {
2468       Message::SendFail ("Error: not enough arguments!");
2469       return 1;
2470     }
2471     aChangeSet->ToSetMaterial = 1;
2472     aChangeSet->MatName = aNames.Last();
2473     aNames.Remove (aNames.Length());
2474     if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString(), aChangeSet->Material))
2475     {
2476       Message::SendFail() << "Syntax error: unknown material '" << aChangeSet->MatName << "'.";
2477       return 1;
2478     }
2479   }
2480   else if (aCmdName == "vunsetmaterial")
2481   {
2482     aChangeSet->ToSetMaterial = -1;
2483   }
2484   else if (aCmdName == "vsetinteriorstyle")
2485   {
2486     if (aNames.IsEmpty()
2487     || !aNames.Last().IsRealValue())
2488     {
2489       Message::SendFail ("Error: not enough arguments!");
2490       return 1;
2491     }
2492     aChangeSet->ToSetInterior = 1;
2493     if (!parseInteriorStyle (aNames.Last(), aChangeSet->InteriorStyle))
2494     {
2495       Message::SendFail() << "Error: wrong syntax at " << aNames.Last();
2496       return 1;
2497     }
2498     aNames.Remove (aNames.Length());
2499   }
2500   else if (aCmdName == "vsetedgetype")
2501   {
2502     aChangeSet->ToSetDrawEdges = 1;
2503     toParseAliasArgs = true;
2504   }
2505   else if (aCmdName == "vunsetedgetype")
2506   {
2507     aChangeSet->ToSetDrawEdges  = -1;
2508     aChangeSet->ToSetEdgeColor  = -1;
2509     aChangeSet->ToSetTypeOfEdge = -1;
2510     aChangeSet->TypeOfEdge = Aspect_TOL_SOLID;
2511   }
2512   else if (aCmdName == "vshowfaceboundary")
2513   {
2514     aChangeSet->ToSetFaceBoundaryDraw = 1;
2515     toParseAliasArgs = true;
2516     if (aNames.Size() >= 2
2517      && aNames.Value (2).IsIntegerValue())
2518     {
2519       if (aNames.Size() == 7)
2520       {
2521         if (ViewerTest::ParseLineType (aNames.Value (7).ToCString(), aChangeSet->TypeOfFaceBoundaryLine))
2522         {
2523           aChangeSet->ToSetTypeOfFaceBoundaryLine = 1;
2524           aNames.Remove (7);
2525         }
2526       }
2527       if (aNames.Size() == 6
2528        && aNames.Value (6).IsRealValue())
2529       {
2530         aChangeSet->ToSetFaceBoundaryWidth = 1;
2531         aChangeSet->FaceBoundaryWidth = aNames.Value (6).RealValue();
2532         aNames.Remove (6);
2533       }
2534       if (aNames.Size() == 5
2535        && aNames.Value (3).IsIntegerValue()
2536        && aNames.Value (4).IsIntegerValue()
2537        && aNames.Value (5).IsIntegerValue())
2538       {
2539         aChangeSet->ToSetFaceBoundaryColor = 1;
2540         aChangeSet->FaceBoundaryColor = Quantity_Color (aNames.Value (3).IntegerValue() / 255.0,
2541                                                         aNames.Value (4).IntegerValue() / 255.0,
2542                                                         aNames.Value (5).IntegerValue() / 255.0,
2543                                                         Quantity_TOC_sRGB);
2544         aNames.Remove (5);
2545         aNames.Remove (4);
2546         aNames.Remove (3);
2547       }
2548       if (aNames.Size() == 2)
2549       {
2550         toParseAliasArgs = false;
2551         aChangeSet->ToSetFaceBoundaryDraw = aNames.Value (2).IntegerValue() == 1 ? 1 : -1;
2552         aNames.Remove (2);
2553       }
2554     }
2555   }
2556   else if (anArgIter >= theArgNb)
2557   {
2558     Message::SendFail ("Error: not enough arguments!");
2559     return 1;
2560   }
2561
2562   if (!aChangeSet->IsEmpty()
2563    && !toParseAliasArgs)
2564   {
2565     anArgIter = theArgNb;
2566   }
2567   for (; anArgIter < theArgNb; ++anArgIter)
2568   {
2569     TCollection_AsciiString anArg = theArgVec[anArgIter];
2570     anArg.LowerCase();
2571     if (anArg == "-setwidth"
2572      || anArg == "-width"
2573      || anArg == "-setlinewidth"
2574      || anArg == "-linewidth"
2575      || anArg == "-setedgewidth"
2576      || anArg == "-setedgeswidth"
2577      || anArg == "-edgewidth"
2578      || anArg == "-edgeswidth"
2579      || anArg == "-setfaceboundarywidth"
2580      || anArg == "-setboundarywidth"
2581      || anArg == "-faceboundarywidth"
2582      || anArg == "-boundarywidth")
2583     {
2584       if (++anArgIter >= theArgNb)
2585       {
2586         Message::SendFail() << "Error: wrong syntax at " << anArg;
2587         return 1;
2588       }
2589
2590       const Standard_Real aWidth = Draw::Atof (theArgVec[anArgIter]);
2591       if (anArg == "-setedgewidth"
2592        || anArg == "-setedgeswidth"
2593        || anArg == "-edgewidth"
2594        || anArg == "-edgeswidth"
2595        || aCmdName == "vsetedgetype")
2596       {
2597         aChangeSet->ToSetEdgeWidth = 1;
2598         aChangeSet->EdgeWidth = aWidth;
2599       }
2600       else if (anArg == "-setfaceboundarywidth"
2601             || anArg == "-setboundarywidth"
2602             || anArg == "-faceboundarywidth"
2603             || anArg == "-boundarywidth"
2604             || aCmdName == "vshowfaceboundary")
2605       {
2606         aChangeSet->ToSetFaceBoundaryWidth = 1;
2607         aChangeSet->FaceBoundaryWidth = aWidth;
2608       }
2609       else
2610       {
2611         aChangeSet->ToSetLineWidth = 1;
2612         aChangeSet->LineWidth = aWidth;
2613       }
2614     }
2615     else if (anArg == "-unsetwidth"
2616           || anArg == "-unsetlinewidth"
2617           || anArg == "-unsetedgewidth")
2618     {
2619       if (anArg == "-unsetedgewidth")
2620       {
2621         aChangeSet->ToSetEdgeWidth = -1;
2622         aChangeSet->EdgeWidth = 1.0;
2623       }
2624       else
2625       {
2626         aChangeSet->ToSetLineWidth = -1;
2627         aChangeSet->LineWidth = 1.0;
2628       }
2629     }
2630     else if (anArg == "-settransp"
2631           || anArg == "-settransparency"
2632           || anArg == "-transparency"
2633           || anArg == "-transp")
2634     {
2635       if (++anArgIter >= theArgNb)
2636       {
2637         Message::SendFail() << "Error: wrong syntax at " << anArg;
2638         return 1;
2639       }
2640       aChangeSet->ToSetTransparency = 1;
2641       aChangeSet->Transparency = Draw::Atof (theArgVec[anArgIter]);
2642       if (aChangeSet->Transparency >= 0.0
2643        && aChangeSet->Transparency <= Precision::Confusion())
2644       {
2645         aChangeSet->ToSetTransparency = -1;
2646         aChangeSet->Transparency = 0.0;
2647       }
2648     }
2649     else if (anArg == "-setalphamode"
2650           || anArg == "-alphamode")
2651     {
2652       if (++anArgIter >= theArgNb)
2653       {
2654         Message::SendFail() << "Error: wrong syntax at " << anArg;
2655         return 1;
2656       }
2657       aChangeSet->ToSetAlphaMode = 1;
2658       aChangeSet->AlphaCutoff = 0.5f;
2659       {
2660         TCollection_AsciiString aParam (theArgVec[anArgIter]);
2661         aParam.LowerCase();
2662         if (aParam == "opaque")
2663         {
2664           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Opaque;
2665         }
2666         else if (aParam == "mask")
2667         {
2668           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Mask;
2669         }
2670         else if (aParam == "blend")
2671         {
2672           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Blend;
2673         }
2674         else if (aParam == "blendauto"
2675               || aParam == "auto")
2676         {
2677           aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
2678         }
2679         else
2680         {
2681           Message::SendFail() << "Error: wrong syntax at " << aParam;
2682           return 1;
2683         }
2684       }
2685
2686       if (anArgIter + 1 < theArgNb
2687        && theArgVec[anArgIter + 1][0] != '-')
2688       {
2689         TCollection_AsciiString aParam2 (theArgVec[anArgIter + 1]);
2690         if (aParam2.IsRealValue())
2691         {
2692           aChangeSet->AlphaCutoff = (float )aParam2.RealValue();
2693           ++anArgIter;
2694         }
2695       }
2696     }
2697     else if (anArg == "-setvis"
2698           || anArg == "-setvisibility"
2699           || anArg == "-visibility")
2700     {
2701       if (++anArgIter >= theArgNb)
2702       {
2703         Message::SendFail() << "Error: wrong syntax at " << anArg;
2704         return 1;
2705       }
2706
2707       aChangeSet->ToSetVisibility = 1;
2708       aChangeSet->Visibility = Draw::Atoi (theArgVec[anArgIter]);
2709     }
2710     else if (anArg == "-setalpha"
2711           || anArg == "-alpha")
2712     {
2713       if (++anArgIter >= theArgNb)
2714       {
2715         Message::SendFail() << "Error: wrong syntax at " << anArg;
2716         return 1;
2717       }
2718       aChangeSet->ToSetTransparency = 1;
2719       aChangeSet->Transparency  = Draw::Atof (theArgVec[anArgIter]);
2720       if (aChangeSet->Transparency < 0.0
2721        || aChangeSet->Transparency > 1.0)
2722       {
2723         Message::SendFail() << "Error: the transparency should be within [0; 1] range (specified " << aChangeSet->Transparency << ")";
2724         return 1;
2725       }
2726       aChangeSet->Transparency = 1.0 - aChangeSet->Transparency;
2727       if (aChangeSet->Transparency >= 0.0
2728        && aChangeSet->Transparency <= Precision::Confusion())
2729       {
2730         aChangeSet->ToSetTransparency = -1;
2731         aChangeSet->Transparency = 0.0;
2732       }
2733     }
2734     else if (anArg == "-unsettransp"
2735           || anArg == "-unsettransparency"
2736           || anArg == "-unsetalpha"
2737           || anArg == "-opaque")
2738     {
2739       aChangeSet->ToSetTransparency = -1;
2740       aChangeSet->Transparency = 0.0;
2741     }
2742     else if (anArg == "-setcolor"
2743           || anArg == "-color"
2744           || anArg == "-setbackfacecolor"
2745           || anArg == "-backfacecolor"
2746           || anArg == "-setbackcolor"
2747           || anArg == "-backcolor"
2748           || anArg == "-setfaceboundarycolor"
2749           || anArg == "-setboundarycolor"
2750           || anArg == "-faceboundarycolor"
2751           || anArg == "-boundarycolor")
2752     {
2753       Quantity_Color aColor;
2754       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
2755                                                            theArgVec + anArgIter + 1,
2756                                                            aColor);
2757       if (aNbParsed == 0)
2758       {
2759         Message::SendFail() << "Syntax error at '" << anArg << "'";
2760         return 1;
2761       }
2762       anArgIter += aNbParsed;
2763       if (aCmdName == "vsetedgetype")
2764       {
2765         aChangeSet->ToSetEdgeColor = 1;
2766         aChangeSet->EdgeColor = Quantity_ColorRGBA (aColor);
2767       }
2768       else if (aCmdName == "vshowfaceboundary"
2769             || anArg == "-setfaceboundarycolor"
2770             || anArg == "-setboundarycolor"
2771             || anArg == "-faceboundarycolor"
2772             || anArg == "-boundarycolor")
2773       {
2774         aChangeSet->ToSetFaceBoundaryColor = 1;
2775         aChangeSet->FaceBoundaryColor = aColor;
2776       }
2777       else if (anArg == "-setbackfacecolor"
2778             || anArg == "-backfacecolor"
2779             || anArg == "-setbackcolor"
2780             || anArg == "-backcolor")
2781       {
2782         aChangeSet->ToSetBackFaceColor = 1;
2783         aChangeSet->BackFaceColor = aColor;
2784       }
2785       else
2786       {
2787         aChangeSet->ToSetColor = 1;
2788         aChangeSet->Color = aColor;
2789       }
2790     }
2791     else if (anArg == "-setlinetype"
2792           || anArg == "-linetype"
2793           || anArg == "-setedgetype"
2794           || anArg == "-setedgestype"
2795           || anArg == "-edgetype"
2796           || anArg == "-edgestype"
2797           || anArg == "-setfaceboundarystyle"
2798           || anArg == "-faceboundarystyle"
2799           || anArg == "-boundarystyle"
2800           || anArg == "-setfaceboundarytype"
2801           || anArg == "-faceboundarytype"
2802           || anArg == "-setboundarytype"
2803           || anArg == "-boundarytype"
2804           || anArg == "-type")
2805     {
2806       if (++anArgIter >= theArgNb)
2807       {
2808         Message::SendFail() << "Error: wrong syntax at " << anArg;
2809         return 1;
2810       }
2811       Aspect_TypeOfLine aLineType = Aspect_TOL_EMPTY;
2812       uint16_t aLinePattern = 0xFFFF;
2813       if (!ViewerTest::ParseLineType (theArgVec[anArgIter], aLineType, aLinePattern))
2814       {
2815         Message::SendFail() << "Error: wrong syntax at " << anArg;
2816         return 1;
2817       }
2818
2819       if (anArg == "-setedgetype"
2820        || anArg == "-setedgestype"
2821        || anArg == "-edgetype"
2822        || anArg == "-edgestype"
2823        || aCmdName == "vsetedgetype")
2824       {
2825         aChangeSet->TypeOfEdge = Graphic3d_Aspects::DefaultLineTypeForPattern (aLinePattern);
2826         aChangeSet->ToSetTypeOfEdge = 1;
2827       }
2828       else if (anArg == "-setfaceboundarystyle"
2829             || anArg == "-faceboundarystyle"
2830             || anArg == "-boundarystyle"
2831             || anArg == "-setfaceboundarytype"
2832             || anArg == "-faceboundarytype"
2833             || anArg == "-setboundarytype"
2834             || anArg == "-boundarytype"
2835             || aCmdName == "vshowfaceboundary")
2836       {
2837         aChangeSet->TypeOfFaceBoundaryLine = Graphic3d_Aspects::DefaultLineTypeForPattern (aLinePattern);
2838         aChangeSet->ToSetTypeOfFaceBoundaryLine = 1;
2839       }
2840       else
2841       {
2842         aChangeSet->StippleLinePattern = aLinePattern;
2843         aChangeSet->ToSetTypeOfLine = 1;
2844       }
2845     }
2846     else if (anArg == "-unsetlinetype"
2847           || anArg == "-unsetedgetype"
2848           || anArg == "-unsetedgestype")
2849     {
2850       if (anArg == "-unsetedgetype"
2851        || anArg == "-unsetedgestype")
2852       {
2853         aChangeSet->ToSetTypeOfEdge = -1;
2854       }
2855       else
2856       {
2857         aChangeSet->ToSetTypeOfLine = -1;
2858       }
2859     }
2860     else if (anArg == "-setmarkertype"
2861           || anArg == "-markertype"
2862           || anArg == "-setpointtype"
2863           || anArg == "-pointtype")
2864     {
2865       if (++anArgIter >= theArgNb)
2866       {
2867         Message::SendFail() << "Error: wrong syntax at " << anArg;
2868         return 1;
2869       }
2870       if (!ViewerTest::ParseMarkerType (theArgVec[anArgIter], aChangeSet->TypeOfMarker, aChangeSet->MarkerImage))
2871       {
2872         Message::SendFail() << "Error: wrong syntax at " << anArg;
2873         return 1;
2874       }
2875
2876       aChangeSet->ToSetTypeOfMarker = 1;
2877     }
2878     else if (anArg == "-unsetmarkertype"
2879           || anArg == "-unsetpointtype")
2880     {
2881       aChangeSet->ToSetTypeOfMarker = -1;
2882     }
2883     else if (anArg == "-setmarkersize"
2884           || anArg == "-markersize"
2885           || anArg == "-setpointsize"
2886           || anArg == "-pointsize")
2887     {
2888       if (++anArgIter >= theArgNb)
2889       {
2890         Message::SendFail() << "Error: wrong syntax at " << anArg;
2891         return 1;
2892       }
2893       aChangeSet->ToSetMarkerSize = 1;
2894       aChangeSet->MarkerSize = Draw::Atof (theArgVec[anArgIter]);
2895     }
2896     else if (anArg == "-unsetmarkersize"
2897           || anArg == "-unsetpointsize")
2898     {
2899       aChangeSet->ToSetMarkerSize = -1;
2900       aChangeSet->MarkerSize = 1.0;
2901     }
2902     else if (anArg == "-unsetcolor")
2903     {
2904       aChangeSet->ToSetColor = -1;
2905       aChangeSet->Color = DEFAULT_COLOR;
2906     }
2907     else if (anArg == "-setmat"
2908           || anArg == "-mat"
2909           || anArg == "-setmaterial"
2910           || anArg == "-material")
2911     {
2912       if (++anArgIter >= theArgNb)
2913       {
2914         Message::SendFail() << "Error: wrong syntax at " << anArg;
2915         return 1;
2916       }
2917       aChangeSet->ToSetMaterial = 1;
2918       aChangeSet->MatName = theArgVec[anArgIter];
2919       if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString(), aChangeSet->Material))
2920       {
2921         Message::SendFail() << "Syntax error: unknown material '" << aChangeSet->MatName << "'.";
2922         return 1;
2923       }
2924     }
2925     else if (anArg == "-unsetmat"
2926           || anArg == "-unsetmaterial")
2927     {
2928       aChangeSet->ToSetMaterial = -1;
2929       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
2930     }
2931     else if (anArg == "-subshape"
2932           || anArg == "-subshapes")
2933     {
2934       if (isDefaults)
2935       {
2936         Message::SendFail() << "Error: wrong syntax. -subshapes can not be used together with -defaults call!";
2937         return 1;
2938       }
2939
2940       if (aNames.IsEmpty())
2941       {
2942         Message::SendFail() << "Error: main objects should specified explicitly when -subshapes is used!";
2943         return 1;
2944       }
2945
2946       aChanges.Append (ViewerTest_AspectsChangeSet());
2947       aChangeSet = &aChanges.ChangeLast();
2948
2949       for (++anArgIter; anArgIter < theArgNb; ++anArgIter)
2950       {
2951         Standard_CString aSubShapeName = theArgVec[anArgIter];
2952         if (*aSubShapeName == '-')
2953         {
2954           --anArgIter;
2955           break;
2956         }
2957
2958         TopoDS_Shape aSubShape = DBRep::Get (aSubShapeName);
2959         if (aSubShape.IsNull())
2960         {
2961           Message::SendFail() << "Error: shape " << aSubShapeName << " doesn't found!";
2962           return 1;
2963         }
2964         aChangeSet->SubShapes.Append (aSubShape);
2965       }
2966
2967       if (aChangeSet->SubShapes.IsEmpty())
2968       {
2969         Message::SendFail() << "Error: empty list is specified after -subshapes!";
2970         return 1;
2971       }
2972     }
2973     else if (anArg == "-setfreeboundary"
2974           || anArg == "-freeboundary"
2975           || anArg == "-setfb"
2976           || anArg == "-fb")
2977     {
2978       bool toEnable = true;
2979       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
2980       {
2981         Message::SendFail() << "Error: wrong syntax at " << anArg;
2982         return 1;
2983       }
2984       ++anArgIter;
2985       aChangeSet->ToSetShowFreeBoundary = toEnable ? 1 : -1;
2986     }
2987     else if (anArg == "-setfreeboundarywidth"
2988           || anArg == "-freeboundarywidth"
2989           || anArg == "-setfbwidth"
2990           || anArg == "-fbwidth")
2991     {
2992       if (++anArgIter >= theArgNb)
2993       {
2994         Message::SendFail() << "Error: wrong syntax at " << anArg;
2995         return 1;
2996       }
2997       aChangeSet->ToSetFreeBoundaryWidth = 1;
2998       aChangeSet->FreeBoundaryWidth = Draw::Atof (theArgVec[anArgIter]);
2999     }
3000     else if (anArg == "-unsetfreeboundarywidth"
3001           || anArg == "-unsetfbwidth")
3002     {
3003       aChangeSet->ToSetFreeBoundaryWidth = -1;
3004       aChangeSet->FreeBoundaryWidth = 1.0;
3005     }
3006     else if (anArg == "-setfreeboundarycolor"
3007           || anArg == "-freeboundarycolor"
3008           || anArg == "-setfbcolor"
3009           || anArg == "-fbcolor")
3010     {
3011       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3012                                                            theArgVec + anArgIter + 1,
3013                                                            aChangeSet->FreeBoundaryColor);
3014       if (aNbParsed == 0)
3015       {
3016         Message::SendFail() << "Syntax error at '" << anArg << "'";
3017         return 1;
3018       }
3019       anArgIter += aNbParsed;
3020       aChangeSet->ToSetFreeBoundaryColor = 1;
3021     }
3022     else if (anArg == "-unsetfreeboundarycolor"
3023           || anArg == "-unsetfbcolor")
3024     {
3025       aChangeSet->ToSetFreeBoundaryColor = -1;
3026       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
3027     }
3028     else if (anArg == "-setisoontriangulation"
3029           || anArg == "-isoontriangulation"
3030           || anArg == "-setisoontriang"
3031           || anArg == "-isoontriang")
3032     {
3033       bool toEnable = true;
3034       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
3035       {
3036         Message::SendFail() << "Error: wrong syntax at " << anArg;
3037         return 1;
3038       }
3039       ++anArgIter;
3040       aChangeSet->ToEnableIsoOnTriangulation = toEnable ? 1 : -1;
3041     }
3042     else if (anArg == "-setfaceboundarydraw"
3043           || anArg == "-setdrawfaceboundary"
3044           || anArg == "-setdrawfaceboundaries"
3045           || anArg == "-setshowfaceboundary"
3046           || anArg == "-setshowfaceboundaries"
3047           || anArg == "-setdrawfaceedges"
3048           || anArg == "-faceboundarydraw"
3049           || anArg == "-drawfaceboundary"
3050           || anArg == "-drawfaceboundaries"
3051           || anArg == "-showfaceboundary"
3052           || anArg == "-showfaceboundaries"
3053           || anArg == "-drawfaceedges"
3054           || anArg == "-faceboundary"
3055           || anArg == "-faceboundaries"
3056           || anArg == "-faceedges")
3057     {
3058       bool toEnable = true;
3059       if (!ViewerTest::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
3060       {
3061         Message::SendFail() << "Error: wrong syntax at " << anArg;
3062         return 1;
3063       }
3064       ++anArgIter;
3065       aChangeSet->ToSetFaceBoundaryDraw = toEnable ? 1 : -1;
3066     }
3067     else if (anArg == "-unsetfaceboundary"
3068           || anArg == "-unsetboundary")
3069     {
3070       aChangeSet->ToSetFaceBoundaryDraw  = -1;
3071       aChangeSet->ToSetFaceBoundaryColor = -1;
3072     }
3073     else if (anArg == "-setmostcontinuity"
3074           || anArg == "-mostcontinuity")
3075     {
3076       TCollection_AsciiString aClassArg (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "");
3077       aClassArg.LowerCase();
3078       GeomAbs_Shape aClass = GeomAbs_CN;
3079       if (aClassArg == "c0"
3080        || aClassArg == "0")
3081       {
3082         aClass = GeomAbs_C0;
3083       }
3084       else if (aClassArg == "c1"
3085             || aClassArg == "1")
3086       {
3087         aClass = GeomAbs_C1;
3088       }
3089       else if (aClassArg == "c2"
3090             || aClassArg == "2")
3091       {
3092         aClass = GeomAbs_C2;
3093       }
3094       else if (aClassArg == "c3"
3095             || aClassArg == "3")
3096       {
3097         aClass = GeomAbs_C3;
3098       }
3099       else if (aClassArg == "cn"
3100             || aClassArg == "n")
3101       {
3102         aClass = GeomAbs_CN;
3103       }
3104       else
3105       {
3106         Message::SendFail() << "Syntax error at '" << anArg << "'";
3107         return 1;
3108       }
3109
3110       ++anArgIter;
3111       aChangeSet->ToSetFaceBoundaryUpperContinuity = 1;
3112       aChangeSet->FaceBoundaryUpperContinuity = aClass;
3113     }
3114     else if (anArg == "-setmaxparamvalue"
3115           || anArg == "-maxparamvalue")
3116     {
3117       if (++anArgIter >= theArgNb)
3118       {
3119         Message::SendFail() << "Error: wrong syntax at " << anArg;
3120         return 1;
3121       }
3122       aChangeSet->ToSetMaxParamValue = 1;
3123       aChangeSet->MaxParamValue = Draw::Atof (theArgVec[anArgIter]);
3124     }
3125     else if (anArg == "-setsensitivity"
3126           || anArg == "-sensitivity")
3127     {
3128       if (isDefaults)
3129       {
3130         Message::SendFail() << "Error: wrong syntax. -setSensitivity can not be used together with -defaults call!";
3131         return 1;
3132       }
3133
3134       if (aNames.IsEmpty())
3135       {
3136         Message::SendFail() << "Error: object and selection mode should specified explicitly when -setSensitivity is used!";
3137         return 1;
3138       }
3139
3140       if (anArgIter + 2 >= theArgNb)
3141       {
3142         Message::SendFail() << "Error: wrong syntax at " << anArg;
3143         return 1;
3144       }
3145       aChangeSet->ToSetSensitivity = 1;
3146       aChangeSet->SelectionMode = Draw::Atoi (theArgVec[++anArgIter]);
3147       aChangeSet->Sensitivity = Draw::Atoi (theArgVec[++anArgIter]);
3148     }
3149     else if (anArg == "-sethatch"
3150           || anArg == "-hatch")
3151     {
3152       if (isDefaults)
3153       {
3154         Message::SendFail() << "Error: wrong syntax. -setHatch can not be used together with -defaults call!";
3155         return 1;
3156       }
3157
3158       if (aNames.IsEmpty())
3159       {
3160         Message::SendFail() << "Error: object should be specified explicitly when -setHatch is used!";
3161         return 1;
3162       }
3163
3164       aChangeSet->ToSetHatch = 1;
3165       TCollection_AsciiString anArgHatch (theArgVec[++anArgIter]);
3166       if (anArgHatch.Length() <= 2)
3167       {
3168         const Standard_Integer anIntStyle = Draw::Atoi (anArgHatch.ToCString());
3169         if (anIntStyle < 0
3170          || anIntStyle >= Aspect_HS_NB)
3171         {
3172           Message::SendFail() << "Error: hatch style is out of range [0, " << (Aspect_HS_NB - 1) << "]!";
3173           return 1;
3174         }
3175         aChangeSet->StdHatchStyle = anIntStyle;
3176       }
3177       else
3178       {
3179         aChangeSet->PathToHatchPattern = anArgHatch;
3180       }
3181     }
3182     else if (anArg == "-setshadingmodel"
3183           || anArg == "-setshading"
3184           || anArg == "-shadingmodel"
3185           || anArg == "-shading")
3186     {
3187       if (++anArgIter >= theArgNb)
3188       {
3189         Message::SendFail() << "Error: wrong syntax at " << anArg;
3190         return 1;
3191       }
3192       aChangeSet->ToSetShadingModel = 1;
3193       aChangeSet->ShadingModelName  = theArgVec[anArgIter];
3194       if (!ViewerTest::ParseShadingModel (theArgVec[anArgIter], aChangeSet->ShadingModel))
3195       {
3196         Message::SendFail() << "Error: wrong syntax at " << anArg;
3197         return 1;
3198       }
3199     }
3200     else if (anArg == "-unsetshadingmodel")
3201     {
3202       aChangeSet->ToSetShadingModel = -1;
3203       aChangeSet->ShadingModel = Graphic3d_TOSM_DEFAULT;
3204     }
3205     else if (anArg == "-setinterior"
3206           || anArg == "-setinteriorstyle"
3207           || anArg == "-interior"
3208           || anArg == "-interiorstyle")
3209     {
3210       if (++anArgIter >= theArgNb)
3211       {
3212         Message::SendFail() << "Error: wrong syntax at " << anArg;
3213         return 1;
3214       }
3215       aChangeSet->ToSetInterior = 1;
3216       if (!parseInteriorStyle (theArgVec[anArgIter], aChangeSet->InteriorStyle))
3217       {
3218         Message::SendFail() << "Error: wrong syntax at " << anArg;
3219         return 1;
3220       }
3221     }
3222     else if (anArg == "-unsetinterior")
3223     {
3224       aChangeSet->ToSetInterior = -1;
3225       aChangeSet->InteriorStyle = Aspect_IS_SOLID;
3226     }
3227     else if (anArg == "-setdrawoutline"
3228           || anArg == "-setdrawsilhouette"
3229           || anArg == "-setoutline"
3230           || anArg == "-setsilhouette"
3231           || anArg == "-outline"
3232           || anArg == "-outlined"
3233           || anArg == "-silhouette")
3234     {
3235       bool toDrawOutline = true;
3236       if (anArgIter + 1 < theArgNb
3237        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toDrawOutline))
3238       {
3239         ++anArgIter;
3240       }
3241       aChangeSet->ToSetDrawSilhouette = toDrawOutline ? 1 : -1;
3242     }
3243     else if (anArg == "-setdrawedges"
3244           || anArg == "-setdrawedge"
3245           || anArg == "-drawedges"
3246           || anArg == "-drawedge"
3247           || anArg == "-edges")
3248     {
3249       bool toDrawEdges = true;
3250       if (anArgIter + 1 < theArgNb
3251        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toDrawEdges))
3252       {
3253         ++anArgIter;
3254       }
3255       aChangeSet->ToSetDrawEdges = toDrawEdges ? 1 : -1;
3256     }
3257     else if (anArg == "-setquadedges"
3258           || anArg == "-setquads"
3259           || anArg == "-quads"
3260           || anArg == "-skipfirstedge")
3261     {
3262       bool isQuadMode = true;
3263       if (anArgIter + 1 < theArgNb
3264        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isQuadMode))
3265       {
3266         ++anArgIter;
3267       }
3268       aChangeSet->ToSetQuadEdges = isQuadMode ? 1 : -1;
3269     }
3270     else if (anArg == "-setedgecolor"
3271           || anArg == "-setedgescolor"
3272           || anArg == "-edgecolor"
3273           || anArg == "-edgescolor")
3274     {
3275       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3276                                                            theArgVec + anArgIter + 1,
3277                                                            aChangeSet->EdgeColor);
3278       if (aNbParsed == 0)
3279       {
3280         Message::SendFail() << "Syntax error at '" << anArg << "'";
3281         return 1;
3282       }
3283       anArgIter += aNbParsed;
3284       aChangeSet->ToSetEdgeColor = 1;
3285     }
3286     else if (anArg == "-unset")
3287     {
3288       aChangeSet->ToSetVisibility = 1;
3289       aChangeSet->Visibility = 1;
3290       aChangeSet->ToSetLineWidth = -1;
3291       aChangeSet->LineWidth = 1.0;
3292       aChangeSet->ToSetTypeOfLine = -1;
3293       aChangeSet->StippleLinePattern = 0xFFFF;
3294       aChangeSet->ToSetTypeOfMarker = -1;
3295       aChangeSet->TypeOfMarker = Aspect_TOM_PLUS;
3296       aChangeSet->ToSetMarkerSize = -1;
3297       aChangeSet->MarkerSize = 1.0;
3298       aChangeSet->ToSetTransparency = -1;
3299       aChangeSet->Transparency = 0.0;
3300       aChangeSet->ToSetAlphaMode = -1;
3301       aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
3302       aChangeSet->AlphaCutoff = 0.5f;
3303       aChangeSet->ToSetColor = -1;
3304       aChangeSet->Color = DEFAULT_COLOR;
3305       //aChangeSet->ToSetBackFaceColor = -1; // should be reset by ToSetColor
3306       //aChangeSet->BackFaceColor = DEFAULT_COLOR;
3307       aChangeSet->ToSetMaterial = -1;
3308       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
3309       aChangeSet->ToSetShowFreeBoundary = -1;
3310       aChangeSet->ToSetFreeBoundaryColor = -1;
3311       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
3312       aChangeSet->ToSetFreeBoundaryWidth = -1;
3313       aChangeSet->FreeBoundaryWidth = 1.0;
3314       aChangeSet->ToEnableIsoOnTriangulation = -1;
3315       //
3316       aChangeSet->ToSetFaceBoundaryDraw = -1;
3317       aChangeSet->ToSetFaceBoundaryUpperContinuity = -1;
3318       aChangeSet->FaceBoundaryUpperContinuity = GeomAbs_CN;
3319       aChangeSet->ToSetFaceBoundaryColor = -1;
3320       aChangeSet->FaceBoundaryColor = Quantity_NOC_BLACK;
3321       aChangeSet->ToSetFaceBoundaryWidth = -1;
3322       aChangeSet->FaceBoundaryWidth = 1.0f;
3323       aChangeSet->ToSetTypeOfFaceBoundaryLine = -1;
3324       aChangeSet->TypeOfFaceBoundaryLine = Aspect_TOL_SOLID;
3325       //
3326       aChangeSet->ToSetHatch = -1;
3327       aChangeSet->StdHatchStyle = -1;
3328       aChangeSet->PathToHatchPattern.Clear();
3329       aChangeSet->ToSetShadingModel = -1;
3330       aChangeSet->ShadingModel = Graphic3d_TOSM_DEFAULT;
3331       aChangeSet->ToSetInterior = -1;
3332       aChangeSet->InteriorStyle = Aspect_IS_SOLID;
3333       aChangeSet->ToSetDrawSilhouette = -1;
3334       aChangeSet->ToSetDrawEdges = -1;
3335       aChangeSet->ToSetQuadEdges = -1;
3336       aChangeSet->ToSetEdgeColor = -1;
3337       aChangeSet->EdgeColor = Quantity_ColorRGBA (DEFAULT_COLOR);
3338       aChangeSet->ToSetEdgeWidth = -1;
3339       aChangeSet->EdgeWidth = 1.0;
3340       aChangeSet->ToSetTypeOfEdge = -1;
3341       aChangeSet->TypeOfEdge = Aspect_TOL_SOLID;
3342     }
3343     else if (anArg == "-dumpjson")
3344     {
3345       toDump = Standard_True;
3346     }
3347     else if (anArg == "-dumpcompact")
3348     {
3349       toCompactDump = Standard_False;
3350       if (++anArgIter >= theArgNb && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toCompactDump))
3351         ++anArgIter;
3352     }
3353     else if (anArg == "-dumpdepth")
3354     {
3355       if (++anArgIter >= theArgNb)
3356       {
3357         Message::SendFail() << "Error: wrong syntax at " << anArg;
3358         return 1;
3359       }
3360       aDumpDepth = Draw::Atoi (theArgVec[anArgIter]);
3361     }
3362     else
3363     {
3364       Message::SendFail() << "Error: wrong syntax at " << anArg;
3365       return 1;
3366     }
3367   }
3368
3369   for (NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
3370        aChangesIter.More(); aChangesIter.Next())
3371   {
3372     if (!aChangesIter.Value().Validate())
3373     {
3374       return 1;
3375     }
3376   }
3377
3378   // special case for -defaults parameter.
3379   // all changed values will be set to DefaultDrawer.
3380   if (isDefaults)
3381   {
3382     const Handle(Prs3d_Drawer)& aDrawer = aCtx->DefaultDrawer();
3383     aChangeSet->Apply (aDrawer);
3384     if (aChangeSet->ToSetLineWidth != 0)
3385     {
3386       aDrawer->LineAspect()->SetWidth (aChangeSet->LineWidth);
3387       aDrawer->WireAspect()->SetWidth (aChangeSet->LineWidth);
3388       aDrawer->UnFreeBoundaryAspect()->SetWidth (aChangeSet->LineWidth);
3389       aDrawer->SeenLineAspect()->SetWidth (aChangeSet->LineWidth);
3390     }
3391     if (aChangeSet->ToSetColor != 0)
3392     {
3393       aDrawer->ShadingAspect()->SetColor        (aChangeSet->Color);
3394       aDrawer->LineAspect()->SetColor           (aChangeSet->Color);
3395       aDrawer->UnFreeBoundaryAspect()->SetColor (aChangeSet->Color);
3396       aDrawer->SeenLineAspect()->SetColor       (aChangeSet->Color);
3397       aDrawer->WireAspect()->SetColor           (aChangeSet->Color);
3398       aDrawer->PointAspect()->SetColor          (aChangeSet->Color);
3399     }
3400     if (aChangeSet->ToSetTransparency != 0)
3401     {
3402       aDrawer->ShadingAspect()->SetTransparency (aChangeSet->Transparency);
3403     }
3404     if (aChangeSet->ToSetMaterial != 0)
3405     {
3406       aDrawer->ShadingAspect()->SetMaterial (aChangeSet->Material);
3407     }
3408     if (aChangeSet->ToEnableIsoOnTriangulation != 0)
3409     {
3410       aDrawer->SetIsoOnTriangulation (aChangeSet->ToEnableIsoOnTriangulation == 1);
3411     }
3412
3413     // redisplay all objects in context
3414     for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
3415     {
3416       Handle(AIS_InteractiveObject)  aPrs = aPrsIter.Current();
3417       if (!aPrs.IsNull())
3418       {
3419         aCtx->Redisplay (aPrs, Standard_False);
3420       }
3421     }
3422     if (toDump)
3423     {
3424       Standard_SStream aStream;
3425       aDrawer->DumpJson (aStream, aDumpDepth);
3426
3427       if (toCompactDump)
3428         theDI << Standard_Dump::Text (aStream);
3429       else
3430         theDI << Standard_Dump::FormatJson (aStream);
3431     }
3432     return 0;
3433   }
3434
3435   for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
3436   {
3437     const TCollection_AsciiString& aName = aPrsIter.CurrentName();
3438     Handle(AIS_InteractiveObject)  aPrs  = aPrsIter.Current();
3439     if (aPrs.IsNull())
3440     {
3441       return 1;
3442     }
3443
3444     Handle(Prs3d_Drawer)           aDrawer = aPrs->Attributes();
3445     Handle(AIS_ColoredShape) aColoredPrs;
3446     Standard_Boolean toDisplay = Standard_False;
3447     Standard_Boolean toRedisplay = Standard_False;
3448     if (aChanges.Length() > 1 || aChangeSet->ToSetVisibility == 1)
3449     {
3450       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aPrs);
3451       if (aShapePrs.IsNull())
3452       {
3453         Message::SendFail() << "Error: an object " << aName << " is not an AIS_Shape presentation!";
3454         return 1;
3455       }
3456       aColoredPrs = Handle(AIS_ColoredShape)::DownCast (aShapePrs);
3457       if (aColoredPrs.IsNull())
3458       {
3459         aColoredPrs = new AIS_ColoredShape (aShapePrs);
3460         if (aShapePrs->HasDisplayMode())
3461         {
3462           aColoredPrs->SetDisplayMode (aShapePrs->DisplayMode());
3463         }
3464         aColoredPrs->SetLocalTransformation (aShapePrs->LocalTransformation());
3465         aCtx->Remove (aShapePrs, Standard_False);
3466         GetMapOfAIS().UnBind2 (aName);
3467         GetMapOfAIS().Bind (aColoredPrs, aName);
3468         toDisplay = Standard_True;
3469         aShapePrs = aColoredPrs;
3470         aPrs      = aColoredPrs;
3471       }
3472     }
3473
3474     if (!aPrs.IsNull())
3475     {
3476       NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
3477       aChangeSet = &aChangesIter.ChangeValue();
3478       if (aChangeSet->ToSetVisibility == 1)
3479       {
3480         Handle(AIS_ColoredDrawer) aColDrawer = aColoredPrs->CustomAspects (aColoredPrs->Shape());
3481         aColDrawer->SetHidden (aChangeSet->Visibility == 0);
3482       }
3483       else if (aChangeSet->ToSetMaterial == 1)
3484       {
3485         aCtx->SetMaterial (aPrs, aChangeSet->Material, Standard_False);
3486       }
3487       else if (aChangeSet->ToSetMaterial == -1)
3488       {
3489         aCtx->UnsetMaterial (aPrs, Standard_False);
3490       }
3491       if (aChangeSet->ToSetColor == 1)
3492       {
3493         aCtx->SetColor (aPrs, aChangeSet->Color, Standard_False);
3494       }
3495       else if (aChangeSet->ToSetColor == -1)
3496       {
3497         aCtx->UnsetColor (aPrs, Standard_False);
3498       }
3499       if (aChangeSet->ToSetTransparency == 1)
3500       {
3501         aCtx->SetTransparency (aPrs, aChangeSet->Transparency, Standard_False);
3502       }
3503       else if (aChangeSet->ToSetTransparency == -1)
3504       {
3505         aCtx->UnsetTransparency (aPrs, Standard_False);
3506       }
3507       if (aChangeSet->ToSetLineWidth == 1)
3508       {
3509         aCtx->SetWidth (aPrs, aChangeSet->LineWidth, Standard_False);
3510       }
3511       else if (aChangeSet->ToSetLineWidth == -1)
3512       {
3513         aCtx->UnsetWidth (aPrs, Standard_False);
3514       }
3515       else if (aChangeSet->ToEnableIsoOnTriangulation != 0)
3516       {
3517         aCtx->IsoOnTriangulation (aChangeSet->ToEnableIsoOnTriangulation == 1, aPrs);
3518         toRedisplay = Standard_True;
3519       }
3520       else if (aChangeSet->ToSetSensitivity != 0)
3521       {
3522         aCtx->SetSelectionSensitivity (aPrs, aChangeSet->SelectionMode, aChangeSet->Sensitivity);
3523       }
3524       if (!aDrawer.IsNull())
3525       {
3526         toRedisplay = aChangeSet->Apply (aDrawer) || toRedisplay;
3527       }
3528
3529       for (aChangesIter.Next(); aChangesIter.More(); aChangesIter.Next())
3530       {
3531         aChangeSet = &aChangesIter.ChangeValue();
3532         for (NCollection_Sequence<TopoDS_Shape>::Iterator aSubShapeIter (aChangeSet->SubShapes);
3533              aSubShapeIter.More(); aSubShapeIter.Next())
3534         {
3535           const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
3536           if (!aChangeSet->IsEmpty())
3537           {
3538             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
3539             aChangeSet->Apply (aCurColDrawer);
3540           }
3541           if (aChangeSet->ToSetVisibility == 1)
3542           {
3543             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
3544             aCurColDrawer->SetHidden (aChangeSet->Visibility == 0);
3545           }
3546           if (aChangeSet->ToSetColor == 1)
3547           {
3548             aColoredPrs->SetCustomColor (aSubShape, aChangeSet->Color);
3549           }
3550           if (aChangeSet->ToSetTransparency == 1)
3551           {
3552             aColoredPrs->SetCustomTransparency (aSubShape, aChangeSet->Transparency);
3553           }
3554           if (aChangeSet->ToSetLineWidth == 1)
3555           {
3556             aColoredPrs->SetCustomWidth (aSubShape, aChangeSet->LineWidth);
3557           }
3558           if (aChangeSet->ToSetColor     == -1
3559            || aChangeSet->ToSetLineWidth == -1)
3560           {
3561             aColoredPrs->UnsetCustomAspects (aSubShape, Standard_True);
3562           }
3563           if (aChangeSet->ToSetSensitivity != 0)
3564           {
3565             aCtx->SetSelectionSensitivity (aPrs, aChangeSet->SelectionMode, aChangeSet->Sensitivity);
3566           }
3567         }
3568       }
3569       if (toDisplay)
3570       {
3571         aCtx->Display (aPrs, Standard_False);
3572       }
3573       if (toRedisplay)
3574       {
3575         aCtx->Redisplay (aPrs, Standard_False);
3576       }
3577       else if (!aColoredPrs.IsNull())
3578       {
3579         aCtx->Redisplay (aColoredPrs, Standard_False);
3580       }
3581       else
3582       {
3583         aPrs->SynchronizeAspects();
3584       }
3585
3586       if (toDump)
3587       {
3588         Standard_SStream aStream;
3589         aDrawer->DumpJson (aStream);
3590
3591         theDI << aName << ": \n";
3592         theDI << Standard_Dump::FormatJson (aStream);
3593         theDI << "\n";
3594       }
3595     }
3596   }
3597   return 0;
3598 }