0033041: Coding - get rid of unused headers [TopTools to Xw]
[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 #include <ViewerTest_AutoUpdater.hxx>
22
23 #include <Draw.hxx>
24 #include <TopTools_HArray1OfShape.hxx>
25 #include <TColStd_HSequenceOfAsciiString.hxx>
26 #include <TColStd_MapOfTransient.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <BRepAdaptor_Curve.hxx>
29 #include <StdSelect_ShapeTypeFilter.hxx>
30 #include <AIS_ColoredShape.hxx>
31 #include <AIS_InteractiveObject.hxx>
32 #include <AIS_Trihedron.hxx>
33 #include <AIS_Axis.hxx>
34 #include <AIS_SignatureFilter.hxx>
35 #include <AIS_ListOfInteractive.hxx>
36 #include <Aspect_InteriorStyle.hxx>
37 #include <Aspect_Window.hxx>
38 #include <Aspect_XRSession.hxx>
39 #include <Graphic3d_AspectFillArea3d.hxx>
40 #include <Graphic3d_AspectLine3d.hxx>
41 #include <Graphic3d_CStructure.hxx>
42 #include <Graphic3d_Texture2D.hxx>
43 #include <Graphic3d_Texture3D.hxx>
44 #include <Graphic3d_GraphicDriver.hxx>
45 #include <Graphic3d_MediaTextureSet.hxx>
46 #include <Image_AlienPixMap.hxx>
47 #include <Message.hxx>
48 #include <OSD_File.hxx>
49 #include <Prs3d_Drawer.hxx>
50 #include <Prs3d_ShadingAspect.hxx>
51 #include <Prs3d_IsoAspect.hxx>
52 #include <Prs3d_PointAspect.hxx>
53 #include <PrsDim_Relation.hxx>
54 #include <Select3D_SensitiveWire.hxx>
55 #include <Select3D_SensitivePrimitiveArray.hxx>
56 #include <Select3D_SensitiveTriangulation.hxx>
57 #include <SelectMgr_EntityOwner.hxx>
58 #include <StdSelect_BRepOwner.hxx>
59 #include <StdSelect_ViewerSelector3d.hxx>
60 #include <TopTools_MapOfShape.hxx>
61 #include <V3d_Viewer.hxx>
62
63 #include <stdio.h>
64
65 #include <Draw_Interpretor.hxx>
66 #include <TCollection_AsciiString.hxx>
67 #include <Draw_PluginMacro.hxx>
68
69 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
70
71 #include <Quantity_Color.hxx>
72 #include <Quantity_NameOfColor.hxx>
73
74 #include <Graphic3d_NameOfMaterial.hxx>
75
76 #define DEFAULT_COLOR              Quantity_NOC_GOLDENROD
77 #define DEFAULT_FREEBOUNDARY_COLOR Quantity_NOC_GREEN
78 #define DEFAULT_MATERIAL           Graphic3d_NameOfMaterial_Brass
79
80 //=======================================================================
81 // function : GetColorFromName
82 // purpose  : get the Quantity_NameOfColor from a string
83 //=======================================================================
84
85 Quantity_NameOfColor ViewerTest::GetColorFromName (const Standard_CString theName)
86 {
87   Quantity_NameOfColor aColor = DEFAULT_COLOR;
88   Quantity_Color::ColorFromName (theName, aColor);
89   return aColor;
90 }
91
92 //=======================================================================
93 // function : ParseColor
94 // purpose  :
95 //=======================================================================
96 Standard_Integer ViewerTest::ParseColor (const Standard_Integer   theArgNb,
97                                          const char* const* const theArgVec,
98                                          Quantity_ColorRGBA&      theColor)
99 {
100   return Draw::ParseColor (theArgNb, theArgVec, theColor);
101 }
102
103 //=======================================================================
104 // function : ParseColor
105 // purpose  :
106 //=======================================================================
107 Standard_Integer ViewerTest::ParseColor (const Standard_Integer   theArgNb,
108                                          const char* const* const theArgVec,
109                                          Quantity_Color&          theColor)
110 {
111   return Draw::ParseColor (theArgNb, theArgVec, theColor);
112 }
113
114 //=======================================================================
115 //function : ParseOnOff
116 //purpose  :
117 //=======================================================================
118 Standard_Boolean ViewerTest::ParseOnOff (Standard_CString  theArg,
119                                          Standard_Boolean& theIsOn)
120 {
121   return Draw::ParseOnOff (theArg, theIsOn);
122 }
123
124 //=======================================================================
125 //function : GetSelectedShapes
126 //purpose  :
127 //=======================================================================
128 void ViewerTest::GetSelectedShapes (TopTools_ListOfShape& theSelectedShapes)
129 {
130   for (GetAISContext()->InitSelected(); GetAISContext()->MoreSelected(); GetAISContext()->NextSelected())
131   {
132     TopoDS_Shape aShape = GetAISContext()->SelectedShape();
133     if (!aShape.IsNull())
134     {
135       theSelectedShapes.Append (aShape);
136     }
137   }
138 }
139
140 //=======================================================================
141 //function : ParseLineType
142 //purpose  :
143 //=======================================================================
144 Standard_Boolean ViewerTest::ParseLineType (Standard_CString theArg,
145                                             Aspect_TypeOfLine& theType,
146                                             uint16_t& thePattern)
147 {
148   TCollection_AsciiString aTypeStr (theArg);
149   aTypeStr.LowerCase();
150   if (aTypeStr == "empty"
151    || aTypeStr == "-1")
152   {
153     theType = Aspect_TOL_EMPTY;
154     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
155   }
156   else if (aTypeStr == "solid"
157         || aTypeStr == "0")
158   {
159     theType = Aspect_TOL_SOLID;
160     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
161   }
162   else if (aTypeStr == "dot"
163         || aTypeStr == "2")
164   {
165     theType = Aspect_TOL_DOT;
166     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
167   }
168   else if (aTypeStr == "dash"
169         || aTypeStr == "1")
170   {
171     theType = Aspect_TOL_DASH;
172     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
173   }
174   else if (aTypeStr == "dotdash"
175         || aTypeStr == "3")
176   {
177     theType = Aspect_TOL_DOTDASH;
178     thePattern = Graphic3d_Aspects::DefaultLinePatternForType (theType);
179   }
180   else
181   {
182     if (aTypeStr.StartsWith ("0x"))
183     {
184       aTypeStr = aTypeStr.SubString (3, aTypeStr.Length());
185     }
186
187     if (aTypeStr.Length() != 4
188     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (1)))
189     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (2)))
190     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (3)))
191     || !std::isxdigit (static_cast<unsigned char> (aTypeStr.Value (4))))
192     {
193       return Standard_False;
194     }
195
196     std::stringstream aStream;
197     aStream << std::setbase (16) << aTypeStr.ToCString();
198     if (aStream.fail())
199     {
200       return Standard_False;
201     }
202
203     Standard_Integer aNumber = -1;
204     aStream >> aNumber;
205     if (aStream.fail())
206     {
207       return Standard_False;
208     }
209
210     thePattern = (uint16_t )aNumber;
211     theType = Graphic3d_Aspects::DefaultLineTypeForPattern (thePattern);
212   }
213   return Standard_True;
214 }
215
216 //=======================================================================
217 //function : ParseMarkerType
218 //purpose  :
219 //=======================================================================
220 Standard_Boolean ViewerTest::ParseMarkerType (Standard_CString theArg,
221                                               Aspect_TypeOfMarker& theType,
222                                               Handle(Image_PixMap)& theImage)
223 {
224   theImage.Nullify();
225   TCollection_AsciiString aTypeStr (theArg);
226   aTypeStr.LowerCase();
227   if (aTypeStr == "empty")
228   {
229     theType = Aspect_TOM_EMPTY;
230   }
231   else if (aTypeStr == "point"
232         || aTypeStr == "dot"
233         || aTypeStr == ".")
234   {
235     theType = Aspect_TOM_POINT;
236   }
237   else if (aTypeStr == "plus"
238         || aTypeStr == "+")
239   {
240     theType = Aspect_TOM_PLUS;
241   }
242   else if (aTypeStr == "star"
243         || aTypeStr == "*")
244   {
245     theType = Aspect_TOM_STAR;
246   }
247   else if (aTypeStr == "cross"
248         || aTypeStr == "x")
249   {
250     theType = Aspect_TOM_X;
251   }
252   else if (aTypeStr == "circle"
253         || aTypeStr == "o")
254   {
255     theType = Aspect_TOM_O;
256   }
257   else if (aTypeStr == "pointincircle")
258   {
259     theType = Aspect_TOM_O_POINT;
260   }
261   else if (aTypeStr == "plusincircle")
262   {
263     theType = Aspect_TOM_O_PLUS;
264   }
265   else if (aTypeStr == "starincircle")
266   {
267     theType = Aspect_TOM_O_STAR;
268   }
269   else if (aTypeStr == "crossincircle"
270         || aTypeStr == "xcircle")
271   {
272     theType = Aspect_TOM_O_X;
273   }
274   else if (aTypeStr == "ring1")
275   {
276     theType = Aspect_TOM_RING1;
277   }
278   else if (aTypeStr == "ring2")
279   {
280     theType = Aspect_TOM_RING2;
281   }
282   else if (aTypeStr == "ring"
283         || aTypeStr == "ring3")
284   {
285     theType = Aspect_TOM_RING3;
286   }
287   else if (aTypeStr == "ball")
288   {
289     theType = Aspect_TOM_BALL;
290   }
291   else if (aTypeStr.IsIntegerValue())
292   {
293     const int aTypeInt = aTypeStr.IntegerValue();
294     if (aTypeInt < -1 || aTypeInt >= Aspect_TOM_USERDEFINED)
295     {
296       return Standard_False;
297     }
298     theType = (Aspect_TypeOfMarker )aTypeInt;
299   }
300   else
301   {
302     theType = Aspect_TOM_USERDEFINED;
303     Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
304     if (!anImage->Load (theArg))
305     {
306       return Standard_False;
307     }
308     if (anImage->Format() == Image_Format_Gray)
309     {
310       anImage->SetFormat (Image_Format_Alpha);
311     }
312     else if (anImage->Format() == Image_Format_GrayF)
313     {
314       anImage->SetFormat (Image_Format_AlphaF);
315     }
316     theImage = anImage;
317   }
318   return Standard_True;
319 }
320
321 //=======================================================================
322 //function : ParseShadingModel
323 //purpose  :
324 //=======================================================================
325 Standard_Boolean ViewerTest::ParseShadingModel (Standard_CString              theArg,
326                                                 Graphic3d_TypeOfShadingModel& theModel)
327 {
328   TCollection_AsciiString aTypeStr (theArg);
329   aTypeStr.LowerCase();
330   if (aTypeStr == "unlit"
331    || aTypeStr == "color"
332    || aTypeStr == "none")
333   {
334     theModel = Graphic3d_TypeOfShadingModel_Unlit;
335   }
336   else if (aTypeStr == "flat"
337         || aTypeStr == "facet")
338   {
339     theModel = Graphic3d_TypeOfShadingModel_PhongFacet;
340   }
341   else if (aTypeStr == "gouraud"
342         || aTypeStr == "vertex"
343         || aTypeStr == "vert")
344   {
345     theModel = Graphic3d_TypeOfShadingModel_Gouraud;
346   }
347   else if (aTypeStr == "phong"
348         || aTypeStr == "fragment"
349         || aTypeStr == "frag"
350         || aTypeStr == "pixel")
351   {
352     theModel = Graphic3d_TypeOfShadingModel_Phong;
353   }
354   else if (aTypeStr == "pbr")
355   {
356     theModel = Graphic3d_TypeOfShadingModel_Pbr;
357   }
358   else if (aTypeStr == "pbr_facet")
359   {
360     theModel = Graphic3d_TypeOfShadingModel_PbrFacet;
361   }
362   else if (aTypeStr == "default"
363         || aTypeStr == "def")
364   {
365     theModel = Graphic3d_TypeOfShadingModel_DEFAULT;
366   }
367   else if (aTypeStr.IsIntegerValue())
368   {
369     const int aTypeInt = aTypeStr.IntegerValue();
370     if (aTypeInt <= Graphic3d_TypeOfShadingModel_DEFAULT || aTypeInt >= Graphic3d_TypeOfShadingModel_NB)
371     {
372       return Standard_False;
373     }
374     theModel = (Graphic3d_TypeOfShadingModel)aTypeInt;
375   }
376   else
377   {
378     return Standard_False;
379   }
380   return Standard_True;
381 }
382
383 //=======================================================================
384 //function : parseZLayer
385 //purpose  :
386 //=======================================================================
387 Standard_Boolean ViewerTest::parseZLayer (Standard_CString theArg,
388                                           Standard_Boolean theToAllowInteger,
389                                           Graphic3d_ZLayerId& theLayer)
390 {
391   TCollection_AsciiString aName (theArg);
392   aName.LowerCase();
393   if (aName == "default"
394    || aName == "def")
395   {
396     theLayer = Graphic3d_ZLayerId_Default;
397   }
398   else if (aName == "top")
399   {
400     theLayer = Graphic3d_ZLayerId_Top;
401   }
402   else if (aName == "topmost")
403   {
404     theLayer = Graphic3d_ZLayerId_Topmost;
405   }
406   else if (aName == "overlay"
407         || aName == "toposd")
408   {
409     theLayer = Graphic3d_ZLayerId_TopOSD;
410   }
411   else if (aName == "underlay"
412         || aName == "botosd")
413   {
414     theLayer = Graphic3d_ZLayerId_BotOSD;
415   }
416   else if (aName == "undefined")
417   {
418     theLayer = Graphic3d_ZLayerId_UNKNOWN;
419   }
420   else if (!GetAISContext().IsNull())
421   {
422     const Handle(V3d_Viewer)& aViewer = ViewerTest::GetAISContext()->CurrentViewer();
423     TColStd_SequenceOfInteger aLayers;
424     aViewer->GetAllZLayers (aLayers);
425     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
426     {
427       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
428       if (TCollection_AsciiString::IsSameString (aSettings.Name(), aName, Standard_False))
429       {
430         theLayer = aLayeriter.Value();
431         return true;
432       }
433     }
434
435     if (!theToAllowInteger
436      || !aName.IsIntegerValue())
437     {
438       return false;
439     }
440     Graphic3d_ZLayerId aLayer = aName.IntegerValue();
441     if (aLayer == Graphic3d_ZLayerId_UNKNOWN
442      || std::find (aLayers.begin(), aLayers.end(), aLayer) != aLayers.end())
443     {
444       theLayer = aLayer;
445       return true;
446     }
447     return false;
448   }
449   return true;
450 }
451
452 //=======================================================================
453 //function : GetTypeNames
454 //purpose  :
455 //=======================================================================
456 static const char** GetTypeNames()
457 {
458   static const char* names[14] = {"Point","Axis","Trihedron","PlaneTrihedron", "Line","Circle","Plane",
459                           "Shape","ConnectedShape","MultiConn.Shape",
460                           "ConnectedInter.","MultiConn.",
461                           "Constraint","Dimension"};
462   static const char** ThePointer = names;
463   return ThePointer;
464 }
465
466 //=======================================================================
467 //function : GetTypeAndSignfromString
468 //purpose  :
469 //=======================================================================
470 static void GetTypeAndSignfromString (const char* theName,
471                                       AIS_KindOfInteractive& theType,
472                                       Standard_Integer& theSign)
473 {
474   const char** aFullNames = GetTypeNames();
475   Standard_Integer anIndex = -1;
476   for (Standard_Integer i = 0; i <= 13 && anIndex == -1; ++i)
477   {
478     if (strcasecmp (theName, aFullNames[i]) == 0)
479     {
480       anIndex = i;
481     }
482   }
483
484   if (anIndex ==-1)
485   {
486     theType = AIS_KindOfInteractive_None;
487     theSign = -1;
488     return;
489   }
490
491   if (anIndex <= 6)
492   {
493     theType = AIS_KindOfInteractive_Datum;
494     theSign = anIndex+1;
495   }
496   else if (anIndex <= 9)
497   {
498     theType = AIS_KindOfInteractive_Shape;
499     theSign = anIndex - 7;
500   }
501   else if (anIndex <= 11)
502   {
503     theType = AIS_KindOfInteractive_Object;
504     theSign = anIndex - 10;
505   }
506   else
507   {
508     theType = AIS_KindOfInteractive_Relation;
509     theSign = anIndex - 12;
510   }
511 }
512
513 #include <string.h>
514 #include <Draw_Appli.hxx>
515 #include <DBRep.hxx>
516
517
518 #include <V3d_View.hxx>
519
520 #include <AIS_InteractiveContext.hxx>
521 #include <AIS_Shape.hxx>
522 #include <AIS_DisplayMode.hxx>
523 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
524 #include <ViewerTest_EventManager.hxx>
525
526 #include <BRep_Builder.hxx>
527 #include <TopAbs_ShapeEnum.hxx>
528
529 #include <BRep_Tool.hxx>
530
531
532 #include <Draw_Window.hxx>
533 #include <TopTools_ListOfShape.hxx>
534
535 //==============================================================================
536 //  VIEWER OBJECT MANAGEMENT GLOBAL VARIABLES
537 //==============================================================================
538 Standard_EXPORT ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(){
539   static ViewerTest_DoubleMapOfInteractiveAndName TheMap;
540   return TheMap;
541 }
542
543 //=======================================================================
544 //function : Display
545 //purpose  :
546 //=======================================================================
547 Standard_Boolean ViewerTest::Display (const TCollection_AsciiString&       theName,
548                                       const Handle(AIS_InteractiveObject)& theObject,
549                                       const Standard_Boolean               theToUpdate,
550                                       const Standard_Boolean               theReplaceIfExists)
551 {
552   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
553   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
554   if (aCtx.IsNull())
555   {
556     Message::SendFail ("Error: AIS context is not available.");
557     return Standard_False;
558   }
559
560   if (aMap.IsBound2 (theName))
561   {
562     if (!theReplaceIfExists)
563     {
564       Message::SendFail() << "Error: other interactive object has been already registered with name: " << theName << ".\n"
565                           << "Please use another name.";
566       return Standard_False;
567     }
568
569     if (Handle(AIS_InteractiveObject) anOldObj = aMap.Find2 (theName))
570     {
571       aCtx->Remove (anOldObj, theObject.IsNull() && theToUpdate);
572     }
573     aMap.UnBind2 (theName);
574   }
575
576   if (theObject.IsNull())
577   {
578     // object with specified name has been already unbound
579     return Standard_True;
580   }
581
582   // unbind AIS object if it was bound with another name
583   aMap.UnBind1 (theObject);
584
585   // can be registered without rebinding
586   aMap.Bind (theObject, theName);
587   aCtx->Display (theObject, theToUpdate);
588   return Standard_True;
589 }
590
591 //! Alias for ViewerTest::Display(), compatibility with old code.
592 Standard_EXPORT Standard_Boolean VDisplayAISObject (const TCollection_AsciiString&       theName,
593                                                     const Handle(AIS_InteractiveObject)& theObject,
594                                                     Standard_Boolean theReplaceIfExists = Standard_True)
595 {
596   return ViewerTest::Display (theName, theObject, Standard_True, theReplaceIfExists);
597 }
598
599 static NCollection_List<Handle(ViewerTest_EventManager)> theEventMgrs;
600
601 static Handle(V3d_View)&  a3DView()
602 {
603   static Handle(V3d_View) Viou;
604   return Viou;
605 }
606
607
608 Standard_EXPORT Handle(AIS_InteractiveContext)& TheAISContext(){
609   static Handle(AIS_InteractiveContext) aContext;
610   return aContext;
611 }
612
613 const Handle(V3d_View)& ViewerTest::CurrentView()
614 {
615   return a3DView();
616 }
617 void ViewerTest::CurrentView(const Handle(V3d_View)& V)
618 {
619   a3DView() = V;
620 }
621
622 const Handle(AIS_InteractiveContext)& ViewerTest::GetAISContext()
623 {
624   return TheAISContext();
625 }
626
627 void ViewerTest::SetAISContext (const Handle(AIS_InteractiveContext)& aCtx)
628 {
629   TheAISContext() = aCtx;
630   ViewerTest::ResetEventManager();
631 }
632
633 Handle(V3d_Viewer) ViewerTest::GetViewerFromContext()
634 {
635   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
636 }
637
638 Handle(V3d_Viewer) ViewerTest::GetCollectorFromContext()
639 {
640   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
641 }
642
643
644 void ViewerTest::SetEventManager(const Handle(ViewerTest_EventManager)& EM){
645   theEventMgrs.Prepend(EM);
646 }
647
648 void ViewerTest::UnsetEventManager()
649 {
650   theEventMgrs.RemoveFirst();
651 }
652
653
654 void ViewerTest::ResetEventManager()
655 {
656   theEventMgrs.Clear();
657   theEventMgrs.Prepend (new ViewerTest_EventManager (ViewerTest::CurrentView(), ViewerTest::GetAISContext()));
658 }
659
660 Handle(ViewerTest_EventManager) ViewerTest::CurrentEventManager()
661 {
662   return !theEventMgrs.IsEmpty()
663         ? theEventMgrs.First()
664         : Handle(ViewerTest_EventManager)();
665 }
666
667 //=======================================================================
668 //function : Get Context and active view
669 //purpose  :
670 //=======================================================================
671 static Standard_Boolean getCtxAndView (Handle(AIS_InteractiveContext)& theCtx,
672                                        Handle(V3d_View)&               theView)
673 {
674   theCtx  = ViewerTest::GetAISContext();
675   theView = ViewerTest::CurrentView();
676   if (theCtx.IsNull()
677    || theView.IsNull())
678   {
679     Message::SendFail ("Error: cannot find an active view!");
680     return Standard_False;
681   }
682   return Standard_True;
683 }
684
685 //==============================================================================
686 //function : Clear
687 //purpose  : Remove all the object from the viewer
688 //==============================================================================
689 void ViewerTest::Clear()
690 {
691   if (a3DView().IsNull())
692   {
693     return;
694   }
695
696   NCollection_Sequence<Handle(AIS_InteractiveObject)> aListRemoved;
697   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS()); anObjIter.More(); anObjIter.Next())
698   {
699     const Handle(AIS_InteractiveObject) anObj = anObjIter.Key1();
700     if (anObj->GetContext() != TheAISContext())
701     {
702       continue;
703     }
704
705     Message::SendInfo() << "Remove " << anObjIter.Key2();
706     TheAISContext()->Remove (anObj, Standard_False);
707     aListRemoved.Append (anObj);
708   }
709
710   TheAISContext()->RebuildSelectionStructs();
711   TheAISContext()->UpdateCurrentViewer();
712   if (aListRemoved.Size() == GetMapOfAIS().Extent())
713   {
714     GetMapOfAIS().Clear();
715   }
716   else
717   {
718     for (NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator anObjIter (aListRemoved); anObjIter.More(); anObjIter.Next())
719     {
720       GetMapOfAIS().UnBind1 (anObjIter.Value());
721     }
722   }
723 }
724
725 //==============================================================================
726 //function : CopyIsoAspect
727 //purpose  : Returns copy Prs3d_IsoAspect with new number of isolines.
728 //==============================================================================
729 static Handle(Prs3d_IsoAspect) CopyIsoAspect
730       (const Handle(Prs3d_IsoAspect) &theIsoAspect,
731        const Standard_Integer theNbIsos)
732 {
733   Quantity_Color    aColor = theIsoAspect->Aspect()->Color();
734   Aspect_TypeOfLine aType  = theIsoAspect->Aspect()->Type();
735   Standard_Real     aWidth = theIsoAspect->Aspect()->Width();
736
737   Handle(Prs3d_IsoAspect) aResult =
738     new Prs3d_IsoAspect(aColor, aType, aWidth, theNbIsos);
739
740   return aResult;
741 }
742
743 //==============================================================================
744 //function : visos
745 //purpose  : Returns or sets the number of U- and V- isos and isIsoOnPlane flag
746 //Draw arg : [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]
747 //==============================================================================
748 static int visos (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
749 {
750   if (TheAISContext().IsNull()) {
751     di << argv[0] << " Call 'vinit' before!\n";
752     return 1;
753   }
754
755   if (argc <= 1) {
756     di << "Current number of isos : " <<
757       TheAISContext()->IsoNumber(AIS_TOI_IsoU) << " " <<
758       TheAISContext()->IsoNumber(AIS_TOI_IsoV) << "\n";
759     di << "IsoOnPlane mode is " <<
760       (TheAISContext()->IsoOnPlane() ? "ON" : "OFF") << "\n";
761     di << "IsoOnTriangulation mode is " <<
762       (TheAISContext()->IsoOnTriangulation() ? "ON" : "OFF") << "\n";
763     return 0;
764   }
765
766   Standard_Integer aLastInd = argc - 1;
767   Standard_Boolean isChanged = Standard_False;
768   Standard_Integer aNbUIsos = 0;
769   Standard_Integer aNbVIsos = 0;
770
771   if (aLastInd >= 3) {
772     Standard_Boolean isIsoOnPlane = Standard_False;
773
774     if (strcmp(argv[aLastInd], "1") == 0) {
775       isIsoOnPlane = Standard_True;
776       isChanged    = Standard_True;
777     } else if (strcmp(argv[aLastInd], "0") == 0) {
778       isIsoOnPlane = Standard_False;
779       isChanged    = Standard_True;
780     }
781
782     if (isChanged) {
783       aNbVIsos = Draw::Atoi(argv[aLastInd - 1]);
784       aNbUIsos = Draw::Atoi(argv[aLastInd - 2]);
785       aLastInd -= 3;
786
787       di << "New number of isos : " << aNbUIsos << " " << aNbVIsos << "\n";
788       di << "New IsoOnPlane mode is " << (isIsoOnPlane ? "ON" : "OFF") << "\n";
789
790       TheAISContext()->IsoOnPlane(isIsoOnPlane);
791
792       if (aLastInd == 0) {
793         // If there are no shapes provided set the default numbers.
794         TheAISContext()->SetIsoNumber(aNbUIsos, AIS_TOI_IsoU);
795         TheAISContext()->SetIsoNumber(aNbVIsos, AIS_TOI_IsoV);
796       }
797     }
798   }
799
800   Standard_Integer i;
801
802   for (i = 1; i <= aLastInd; i++)
803   {
804     TCollection_AsciiString name(argv[i]);
805     Handle(AIS_InteractiveObject) aShape;
806     GetMapOfAIS().Find2(name, aShape);
807     if (aShape.IsNull())
808     {
809       Message::SendFail() << "Syntax error: object '" << name << "' is not found";
810       return 1;
811     }
812
813     Handle(Prs3d_Drawer) CurDrawer = aShape->Attributes();
814     Handle(Prs3d_IsoAspect) aUIso = CurDrawer->UIsoAspect();
815     Handle(Prs3d_IsoAspect) aVIso = CurDrawer->VIsoAspect();
816     if (isChanged)
817     {
818       CurDrawer->SetUIsoAspect(CopyIsoAspect(aUIso, aNbUIsos));
819       CurDrawer->SetVIsoAspect(CopyIsoAspect(aVIso, aNbVIsos));
820       TheAISContext()->SetLocalAttributes (aShape, CurDrawer, Standard_False);
821       TheAISContext()->Redisplay (aShape, Standard_False);
822     }
823     else
824     {
825       di << "Number of isos for " << argv[i] << " : "
826           << aUIso->Number() << " " << aVIso->Number() << "\n";
827     }
828   }
829
830   if (isChanged) {
831     TheAISContext()->UpdateCurrentViewer();
832   }
833
834   return 0;
835 }
836
837 static Standard_Integer VDispSensi (Draw_Interpretor& ,
838                                     Standard_Integer  theArgNb,
839                                     Standard_CString* )
840 {
841   if (theArgNb > 1)
842   {
843     Message::SendFail ("Error: wrong syntax!");
844     return 1;
845   }
846
847   Handle(AIS_InteractiveContext) aCtx;
848   Handle(V3d_View)               aView;
849   if (!getCtxAndView (aCtx, aView))
850   {
851     return 1;
852   }
853
854   aCtx->DisplayActiveSensitive (aView);
855   return 0;
856
857 }
858
859 static Standard_Integer VClearSensi (Draw_Interpretor& ,
860                                      Standard_Integer  theArgNb,
861                                      Standard_CString* )
862 {
863   if (theArgNb > 1)
864   {
865     Message::SendFail ("Error: wrong syntax!");
866     return 1;
867   }
868
869   Handle(AIS_InteractiveContext) aCtx;
870   Handle(V3d_View)               aView;
871   if (!getCtxAndView (aCtx, aView))
872   {
873     return 1;
874   }
875   aCtx->ClearActiveSensitive (aView);
876   return 0;
877 }
878
879 //==============================================================================
880 //function : VDir
881 //purpose  : To list the displayed object with their attributes
882 //==============================================================================
883 static int VDir (Draw_Interpretor& theDI,
884                  Standard_Integer theNbArgs,
885                  const char** theArgVec)
886 {
887   TCollection_AsciiString aMatch;
888   Standard_Boolean toFormat = Standard_False;
889   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
890   {
891     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
892     anArgCase.LowerCase();
893     if (anArgCase == "-list"
894      || anArgCase == "-format")
895     {
896       toFormat = Standard_True;
897     }
898     else if (aMatch.IsEmpty())
899     {
900       aMatch = theArgVec[anArgIter];
901     }
902     else
903     {
904       Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
905       return 1;
906     }
907   }
908
909   TCollection_AsciiString aRes;
910   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
911   {
912     if (!aMatch.IsEmpty())
913     {
914       const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aMatch + "' '" + anIter.Key2() + "'";
915       if (theDI.Eval (aCheck.ToCString()) == 0
916       && *theDI.Result() != '1')
917       {
918         continue;
919       }
920     }
921
922     if (toFormat)
923     {
924       aRes += TCollection_AsciiString("\t") + anIter.Key2() + "\n";
925     }
926     else
927     {
928       aRes += anIter.Key2() + " ";
929     }
930   }
931   theDI.Reset();
932   theDI << aRes;
933   return 0;
934 }
935
936 //! Auxiliary enumeration
937 enum ViewerTest_StereoPair
938 {
939   ViewerTest_SP_Single,
940   ViewerTest_SP_SideBySide,
941   ViewerTest_SP_OverUnder
942 };
943
944 //==============================================================================
945 //function : VDump
946 //purpose  : To dump the active view snapshot to image file
947 //==============================================================================
948 static Standard_Integer VDump (Draw_Interpretor& theDI,
949                                Standard_Integer  theArgNb,
950                                Standard_CString* theArgVec)
951 {
952   Handle(V3d_View) aView = ViewerTest::CurrentView();
953   if (theArgNb < 2)
954   {
955     Message::SendFail ("Error: wrong number of arguments! Image file name should be specified at least.");
956     return 1;
957   }
958   if (aView.IsNull())
959   {
960     Message::SendFail() << "Error: cannot find an active view!";
961     return 1;
962   }
963
964   Standard_Integer      anArgIter   = 1;
965   Standard_CString      aFilePath   = theArgVec[anArgIter++];
966   ViewerTest_StereoPair aStereoPair = ViewerTest_SP_Single;
967   V3d_ImageDumpOptions  aParams;
968   Handle(Graphic3d_Camera) aCustomCam;
969   aParams.BufferType    = Graphic3d_BT_RGB;
970   aParams.StereoOptions = V3d_SDO_MONO;
971   for (; anArgIter < theArgNb; ++anArgIter)
972   {
973     TCollection_AsciiString anArg (theArgVec[anArgIter]);
974     anArg.LowerCase();
975     if (anArg == "-buffer")
976     {
977       if (++anArgIter >= theArgNb)
978       {
979         Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
980         return 1;
981       }
982
983       TCollection_AsciiString aBufArg (theArgVec[anArgIter]);
984       aBufArg.LowerCase();
985       if (aBufArg == "rgba")
986       {
987         aParams.BufferType = Graphic3d_BT_RGBA;
988       }
989       else if (aBufArg == "rgb")
990       {
991         aParams.BufferType = Graphic3d_BT_RGB;
992       }
993       else if (aBufArg == "red")
994       {
995         aParams.BufferType = Graphic3d_BT_Red;
996       }
997       else if (aBufArg == "depth")
998       {
999         aParams.BufferType = Graphic3d_BT_Depth;
1000       }
1001       else
1002       {
1003         Message::SendFail() << "Error: unknown buffer '" << aBufArg << "'";
1004         return 1;
1005       }
1006     }
1007     else if (anArgIter + 1 < theArgNb
1008           && anArg == "-xrpose")
1009     {
1010       TCollection_AsciiString anXRArg (theArgVec[++anArgIter]);
1011       anXRArg.LowerCase();
1012       if (anXRArg == "base")
1013       {
1014         aCustomCam = aView->View()->BaseXRCamera();
1015       }
1016       else if (anXRArg == "head")
1017       {
1018         aCustomCam = aView->View()->PosedXRCamera();
1019       }
1020       else if (anXRArg == "handleft"
1021             || anXRArg == "handright")
1022       {
1023         if (aView->View()->IsActiveXR())
1024         {
1025           aCustomCam = new Graphic3d_Camera();
1026           aView->View()->ComputeXRPosedCameraFromBase (*aCustomCam, anXRArg == "handleft"
1027                                                      ? aView->View()->XRSession()->LeftHandPose()
1028                                                      : aView->View()->XRSession()->RightHandPose());
1029         }
1030       }
1031       else
1032       {
1033         Message::SendFail() << "Syntax error: unknown XR pose '" << anXRArg << "'";
1034         return 1;
1035       }
1036       if (aCustomCam.IsNull())
1037       {
1038         Message::SendFail() << "Error: undefined XR pose";
1039         return 0;
1040       }
1041     }
1042     else if (anArg == "-stereo")
1043     {
1044       if (++anArgIter >= theArgNb)
1045       {
1046         Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
1047         return 1;
1048       }
1049
1050       TCollection_AsciiString aStereoArg (theArgVec[anArgIter]);
1051       aStereoArg.LowerCase();
1052       if (aStereoArg == "l"
1053        || aStereoArg == "left")
1054       {
1055         aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1056       }
1057       else if (aStereoArg == "r"
1058             || aStereoArg == "right")
1059       {
1060         aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1061       }
1062       else if (aStereoArg == "mono")
1063       {
1064         aParams.StereoOptions = V3d_SDO_MONO;
1065       }
1066       else if (aStereoArg == "blended"
1067             || aStereoArg == "blend"
1068             || aStereoArg == "stereo")
1069       {
1070         aParams.StereoOptions = V3d_SDO_BLENDED;
1071       }
1072       else if (aStereoArg == "sbs"
1073             || aStereoArg == "sidebyside")
1074       {
1075         aStereoPair = ViewerTest_SP_SideBySide;
1076       }
1077       else if (aStereoArg == "ou"
1078             || aStereoArg == "overunder")
1079       {
1080         aStereoPair = ViewerTest_SP_OverUnder;
1081       }
1082       else
1083       {
1084         Message::SendFail() << "Error: unknown stereo format '" << aStereoArg << "'";
1085         return 1;
1086       }
1087     }
1088     else if (anArg == "-rgba"
1089           || anArg ==  "rgba")
1090     {
1091       aParams.BufferType = Graphic3d_BT_RGBA;
1092     }
1093     else if (anArg == "-rgb"
1094           || anArg ==  "rgb")
1095     {
1096       aParams.BufferType = Graphic3d_BT_RGB;
1097     }
1098     else if (anArg == "-red"
1099           || anArg ==  "red")
1100     {
1101       aParams.BufferType = Graphic3d_BT_Red;
1102     }
1103     else if (anArg == "-depth"
1104           || anArg ==  "depth")
1105     {
1106       aParams.BufferType = Graphic3d_BT_Depth;
1107     }
1108     else if (anArg == "-width"
1109           || anArg ==  "width"
1110           || anArg ==  "sizex")
1111     {
1112       if (aParams.Width != 0)
1113       {
1114         Message::SendFail() << "Error: wrong syntax at " << theArgVec[anArgIter];
1115         return 1;
1116       }
1117       else if (++anArgIter >= theArgNb)
1118       {
1119         Message::SendFail() << "Error: integer value is expected right after 'width'";
1120         return 1;
1121       }
1122       aParams.Width = Draw::Atoi (theArgVec[anArgIter]);
1123     }
1124     else if (anArg == "-height"
1125           || anArg ==  "height"
1126           || anArg ==  "-sizey")
1127     {
1128       if (aParams.Height != 0)
1129       {
1130         Message::SendFail() << "Error: wrong syntax at " << theArgVec[anArgIter];
1131         return 1;
1132       }
1133       else if (++anArgIter >= theArgNb)
1134       {
1135         Message::SendFail() << "Error: integer value is expected right after 'height'";
1136         return 1;
1137       }
1138       aParams.Height = Draw::Atoi (theArgVec[anArgIter]);
1139     }
1140     else if (anArg == "-tile"
1141           || anArg == "-tilesize")
1142     {
1143       if (++anArgIter >= theArgNb)
1144       {
1145         Message::SendFail() << "Error: integer value is expected right after 'tileSize'";
1146         return 1;
1147       }
1148       aParams.TileSize = Draw::Atoi (theArgVec[anArgIter]);
1149     }
1150     else
1151     {
1152       Message::SendFail() << "Error: unknown argument '" << theArgVec[anArgIter] << "'";
1153       return 1;
1154     }
1155   }
1156   if ((aParams.Width <= 0 && aParams.Height >  0)
1157    || (aParams.Width >  0 && aParams.Height <= 0))
1158   {
1159     Message::SendFail() << "Error: dimensions " << aParams.Width << "x" << aParams.Height << " are incorrect";
1160     return 1;
1161   }
1162
1163   if (aParams.Width <= 0 || aParams.Height <= 0)
1164   {
1165     aView->Window()->Size (aParams.Width, aParams.Height);
1166   }
1167
1168   Image_AlienPixMap aPixMap;
1169   Image_Format aFormat = Image_Format_UNKNOWN;
1170   switch (aParams.BufferType)
1171   {
1172     case Graphic3d_BT_RGB:                 aFormat = Image_Format_RGB;   break;
1173     case Graphic3d_BT_RGBA:                aFormat = Image_Format_RGBA;  break;
1174     case Graphic3d_BT_Depth:               aFormat = Image_Format_GrayF; break;
1175     case Graphic3d_BT_RGB_RayTraceHdrLeft: aFormat = Image_Format_RGBF;  break;
1176     case Graphic3d_BT_Red:                 aFormat = Image_Format_Gray;  break;
1177   }
1178
1179   const bool wasImmUpdate = aView->SetImmediateUpdate (false);
1180   Handle(Graphic3d_Camera) aCamBack = aView->Camera();
1181   if (!aCustomCam.IsNull())
1182   {
1183     aView->SetCamera (aCustomCam);
1184   }
1185   switch (aStereoPair)
1186   {
1187     case ViewerTest_SP_Single:
1188     {
1189       if (!aView->ToPixMap (aPixMap, aParams))
1190       {
1191         theDI << "Fail: view dump failed!\n";
1192         return 0;
1193       }
1194       else if (aPixMap.SizeX() != Standard_Size(aParams.Width)
1195             || aPixMap.SizeY() != Standard_Size(aParams.Height))
1196       {
1197         theDI << "Fail: dumped dimensions "    << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY()
1198               << " are lesser than requested " << aParams.Width << "x" << aParams.Height << "\n";
1199       }
1200       break;
1201     }
1202     case ViewerTest_SP_SideBySide:
1203     {
1204       if (!aPixMap.InitZero (aFormat, aParams.Width * 2, aParams.Height))
1205       {
1206         theDI << "Fail: not enough memory for image allocation!\n";
1207         return 0;
1208       }
1209
1210       Image_PixMap aPixMapL, aPixMapR;
1211       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
1212                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1213       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizePixelBytes() * aParams.Width,
1214                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1215
1216       aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1217       Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams);
1218       aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1219       isOk          = isOk && aView->ToPixMap (aPixMapR, aParams);
1220       if (!isOk)
1221       {
1222         theDI << "Fail: view dump failed!\n";
1223         return 0;
1224       }
1225       break;
1226     }
1227     case ViewerTest_SP_OverUnder:
1228     {
1229       if (!aPixMap.InitZero (aFormat, aParams.Width, aParams.Height * 2))
1230       {
1231         theDI << "Fail: not enough memory for image allocation!\n";
1232         return 0;
1233       }
1234
1235       Image_PixMap aPixMapL, aPixMapR;
1236       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
1237                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1238       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizeRowBytes() * aParams.Height,
1239                             aParams.Width, aParams.Height, aPixMap.SizeRowBytes());
1240
1241       aParams.StereoOptions = V3d_SDO_LEFT_EYE;
1242       Standard_Boolean isOk = aView->ToPixMap (aPixMapL, aParams);
1243       aParams.StereoOptions = V3d_SDO_RIGHT_EYE;
1244       isOk          = isOk && aView->ToPixMap (aPixMapR, aParams);
1245       if (!isOk)
1246       {
1247         theDI << "Fail: view dump failed!\n";
1248         return 0;
1249       }
1250       break;
1251     }
1252   }
1253   if (!aCustomCam.IsNull())
1254   {
1255     aView->SetCamera (aCamBack);
1256   }
1257   aView->SetImmediateUpdate (wasImmUpdate);
1258
1259   if (!aPixMap.Save (aFilePath))
1260   {
1261     theDI << "Fail: image can not be saved!\n";
1262   }
1263   return 0;
1264 }
1265
1266 enum TypeOfDispOperation
1267 {
1268   TypeOfDispOperation_SetDispMode,
1269   TypeOfDispOperation_UnsetDispMode
1270 };
1271
1272 //! Displays,Erase...
1273 static void VwrTst_DispErase (const Handle(AIS_InteractiveObject)& thePrs,
1274                                                 const Standard_Integer theMode,
1275                                                 const TypeOfDispOperation theType,
1276                                                 const Standard_Boolean theToUpdate)
1277 {
1278   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1279   switch (theType)
1280   {
1281     case TypeOfDispOperation_SetDispMode:
1282     {
1283       if (!thePrs.IsNull())
1284       {
1285         aCtx->SetDisplayMode (thePrs, theMode, theToUpdate);
1286       }
1287       else
1288       {
1289         aCtx->SetDisplayMode ((AIS_DisplayMode )theMode, theToUpdate);
1290       }
1291       break;
1292     }
1293     case TypeOfDispOperation_UnsetDispMode:
1294     {
1295       if (!thePrs.IsNull())
1296       {
1297         aCtx->UnsetDisplayMode (thePrs, theToUpdate);
1298       }
1299       else
1300       {
1301         aCtx->SetDisplayMode (AIS_WireFrame, theToUpdate);
1302       }
1303       break;
1304     }
1305   }
1306 }
1307
1308 //=======================================================================
1309 //function :
1310 //purpose  :
1311 //=======================================================================
1312 static int VDispMode (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1313 {
1314   if (argc < 1
1315    || argc > 3)
1316   {
1317     Message::SendFail() << "Syntax error: wrong number of arguments";
1318     return 1;
1319   }
1320
1321   TypeOfDispOperation aType = TCollection_AsciiString (argv[0]) == "vunsetdispmode"
1322                             ? TypeOfDispOperation_UnsetDispMode
1323                             : TypeOfDispOperation_SetDispMode;
1324   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1325   if (aCtx.IsNull())
1326   {
1327     Message::SendFail ("Error: no active viewer");
1328     return 1;
1329   }
1330
1331   if (aType == TypeOfDispOperation_UnsetDispMode)
1332   {
1333     if (argc == 1)
1334     {
1335       if (aCtx->NbSelected() == 0)
1336       {
1337         VwrTst_DispErase (Handle(AIS_InteractiveObject)(), -1, TypeOfDispOperation_UnsetDispMode, Standard_False);
1338       }
1339       else
1340       {
1341         for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
1342         {
1343           VwrTst_DispErase (aCtx->SelectedInteractive(), -1, TypeOfDispOperation_UnsetDispMode, Standard_False);
1344         }
1345       }
1346       aCtx->UpdateCurrentViewer();
1347     }
1348     else
1349     {
1350       TCollection_AsciiString aName = argv[1];
1351       Handle(AIS_InteractiveObject) aPrs;
1352       if (GetMapOfAIS().Find2 (aName, aPrs)
1353       && !aPrs.IsNull())
1354       {
1355         VwrTst_DispErase (aPrs, -1, TypeOfDispOperation_UnsetDispMode, Standard_True);
1356       }
1357     }
1358   }
1359   else if (argc == 2)
1360   {
1361     Standard_Integer aDispMode = Draw::Atoi (argv[1]);
1362     if (aCtx->NbSelected() == 0
1363      && aType == TypeOfDispOperation_SetDispMode)
1364     {
1365       VwrTst_DispErase (Handle(AIS_InteractiveObject)(), aDispMode, TypeOfDispOperation_SetDispMode, Standard_True);
1366     }
1367     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
1368     {
1369       VwrTst_DispErase (aCtx->SelectedInteractive(), aDispMode, aType, Standard_False);
1370     }
1371     aCtx->UpdateCurrentViewer();
1372   }
1373   else
1374   {
1375     Handle(AIS_InteractiveObject) aPrs;
1376     TCollection_AsciiString aName (argv[1]);
1377     if (GetMapOfAIS().Find2 (aName, aPrs)
1378      && !aPrs.IsNull())
1379     {
1380       VwrTst_DispErase (aPrs, Draw::Atoi(argv[2]), aType, Standard_True);
1381     }
1382   }
1383   return 0;
1384 }
1385
1386
1387 //=======================================================================
1388 //function :
1389 //purpose  :
1390 //=======================================================================
1391 static int VSubInt(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1392 {
1393   if(argc==1) return 1;
1394   Standard_Integer On = Draw::Atoi(argv[1]);
1395   const Handle(AIS_InteractiveContext)& Ctx = ViewerTest::GetAISContext();
1396   if (Ctx.IsNull())
1397   {
1398     Message::SendFail ("Error: no active viewer");
1399     return 1;
1400   }
1401
1402   if(argc==2)
1403   {
1404     TCollection_AsciiString isOnOff = On == 1 ? "on" : "off";
1405     di << "Sub intensite is turned " << isOnOff << " for " << Ctx->NbSelected() << "objects\n";
1406     for (Ctx->InitSelected(); Ctx->MoreSelected(); Ctx->NextSelected())
1407     {
1408       if(On==1)
1409       {
1410         Ctx->SubIntensityOn (Ctx->SelectedInteractive(), Standard_False);
1411       }
1412       else
1413       {
1414         Ctx->SubIntensityOff (Ctx->SelectedInteractive(), Standard_False);
1415       }
1416     }
1417
1418     Ctx->UpdateCurrentViewer();
1419   }
1420   else {
1421     Handle(AIS_InteractiveObject) IO;
1422     TCollection_AsciiString name = argv[2];
1423     if (GetMapOfAIS().Find2 (name, IO)
1424     && !IO.IsNull())
1425     {
1426       if(On==1)
1427         Ctx->SubIntensityOn(IO, Standard_True);
1428       else
1429         Ctx->SubIntensityOff(IO, Standard_True);
1430     }
1431     else return 1;
1432   }
1433   return 0;
1434 }
1435
1436 //! Auxiliary class to iterate presentations from different collections.
1437 class ViewTest_PrsIter
1438 {
1439 public:
1440
1441   //! Create and initialize iterator object.
1442   ViewTest_PrsIter (const TCollection_AsciiString& theName)
1443   : mySource (IterSource_All)
1444   {
1445     NCollection_Sequence<TCollection_AsciiString> aNames;
1446     if (!theName.IsEmpty())
1447     aNames.Append (theName);
1448     Init (aNames);
1449   }
1450
1451   //! Create and initialize iterator object.
1452   ViewTest_PrsIter (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1453   : mySource (IterSource_All)
1454   {
1455     Init (theNames);
1456   }
1457
1458   //! Initialize the iterator.
1459   void Init (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1460   {
1461     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1462     mySeq = theNames;
1463     mySelIter.Nullify();
1464     myCurrent.Nullify();
1465     myCurrentTrs.Nullify();
1466     if (!mySeq.IsEmpty())
1467     {
1468       mySource = IterSource_List;
1469       mySeqIter = NCollection_Sequence<TCollection_AsciiString>::Iterator (mySeq);
1470     }
1471     else if (aCtx->NbSelected() > 0)
1472     {
1473       mySource  = IterSource_Selected;
1474       mySelIter = aCtx;
1475       mySelIter->InitSelected();
1476     }
1477     else
1478     {
1479       mySource = IterSource_All;
1480       myMapIter.Initialize (GetMapOfAIS());
1481     }
1482     initCurrent();
1483   }
1484
1485   const TCollection_AsciiString& CurrentName() const
1486   {
1487     return myCurrentName;
1488   }
1489
1490   const Handle(AIS_InteractiveObject)& Current() const
1491   {
1492     return myCurrent;
1493   }
1494
1495   const Handle(Standard_Transient)& CurrentTrs() const
1496   {
1497     return myCurrentTrs;
1498   }
1499
1500   //! @return true if iterator points to valid object within collection
1501   Standard_Boolean More() const
1502   {
1503     switch (mySource)
1504     {
1505       case IterSource_All:      return myMapIter.More();
1506       case IterSource_List:     return mySeqIter.More();
1507       case IterSource_Selected: return mySelIter->MoreSelected();
1508     }
1509     return Standard_False;
1510   }
1511
1512   //! Go to the next item.
1513   void Next()
1514   {
1515     myCurrentName.Clear();
1516     myCurrentTrs.Nullify();
1517     myCurrent.Nullify();
1518     switch (mySource)
1519     {
1520       case IterSource_All:
1521       {
1522         myMapIter.Next();
1523         break;
1524       }
1525       case IterSource_List:
1526       {
1527         mySeqIter.Next();
1528         break;
1529       }
1530       case IterSource_Selected:
1531       {
1532         mySelIter->NextSelected();
1533         break;
1534       }
1535     }
1536     initCurrent();
1537   }
1538
1539 private:
1540
1541   void initCurrent()
1542   {
1543     switch (mySource)
1544     {
1545       case IterSource_All:
1546       {
1547         if (myMapIter.More())
1548         {
1549           myCurrentName = myMapIter.Key2();
1550           myCurrentTrs  = myMapIter.Key1();
1551           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1552         }
1553         break;
1554       }
1555       case IterSource_List:
1556       {
1557         if (mySeqIter.More())
1558         {
1559           if (!GetMapOfAIS().IsBound2 (mySeqIter.Value()))
1560           {
1561             Message::SendFail() << "Error: object " << mySeqIter.Value() << " is not displayed!";
1562             return;
1563           }
1564           myCurrentName = mySeqIter.Value();
1565           myCurrentTrs  = GetMapOfAIS().Find2 (mySeqIter.Value());
1566           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1567         }
1568         break;
1569       }
1570       case IterSource_Selected:
1571       {
1572         if (mySelIter->MoreSelected())
1573         {
1574           myCurrentName = GetMapOfAIS().Find1 (mySelIter->SelectedInteractive());
1575           myCurrent     = mySelIter->SelectedInteractive();
1576         }
1577         break;
1578       }
1579     }
1580   }
1581
1582 private:
1583
1584   enum IterSource
1585   {
1586     IterSource_All,
1587     IterSource_List,
1588     IterSource_Selected
1589   };
1590
1591 private:
1592
1593   Handle(AIS_InteractiveContext) mySelIter;    //!< iterator for current (selected) objects (IterSource_Selected)
1594   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName myMapIter; //!< iterator for map of all objects (IterSource_All)
1595   NCollection_Sequence<TCollection_AsciiString>           mySeq;
1596   NCollection_Sequence<TCollection_AsciiString>::Iterator mySeqIter;
1597
1598   TCollection_AsciiString        myCurrentName;//!< current item name
1599   Handle(Standard_Transient)     myCurrentTrs; //!< current item (as transient object)
1600   Handle(AIS_InteractiveObject)  myCurrent;    //!< current item
1601
1602   IterSource                     mySource;     //!< iterated collection
1603
1604 };
1605
1606 //! Parse interior style name.
1607 static bool parseInteriorStyle (const TCollection_AsciiString& theArg,
1608                                 Aspect_InteriorStyle& theStyle)
1609 {
1610   TCollection_AsciiString anArg (theArg);
1611   anArg.LowerCase();
1612   if (anArg == "empty")
1613   {
1614     theStyle = Aspect_IS_EMPTY;
1615   }
1616   else if (anArg == "hollow")
1617   {
1618     theStyle = Aspect_IS_HOLLOW;
1619   }
1620   else if (anArg == "solid")
1621   {
1622     theStyle = Aspect_IS_SOLID;
1623   }
1624   else if (anArg == "hatch")
1625   {
1626     theStyle = Aspect_IS_HATCH;
1627   }
1628   else if (anArg == "hiddenline"
1629         || anArg == "hidden-line"
1630         || anArg == "hidden_line")
1631   {
1632     theStyle = Aspect_IS_HIDDENLINE;
1633   }
1634   else if (anArg == "point")
1635   {
1636     theStyle = Aspect_IS_POINT;
1637   }
1638   else if (theArg.IsIntegerValue())
1639   {
1640     const Standard_Integer anIntStyle = theArg.IntegerValue();
1641     if (anIntStyle < Aspect_IS_EMPTY || anIntStyle > Aspect_IS_POINT)
1642     {
1643       return false;
1644     }
1645     theStyle = (Aspect_InteriorStyle)anIntStyle;
1646   }
1647   else
1648   {
1649     return false;
1650   }
1651   return true;
1652 }
1653
1654 //! Auxiliary structure for VAspects
1655 struct ViewerTest_AspectsChangeSet
1656 {
1657   Standard_Integer             ToSetVisibility;
1658   Standard_Integer             Visibility;
1659
1660   Standard_Integer             ToSetColor;
1661   Quantity_Color               Color;
1662   Standard_Integer             ToSetBackFaceColor;
1663   Quantity_Color               BackFaceColor;
1664
1665   Standard_Integer             ToSetLineWidth;
1666   Standard_Real                LineWidth;
1667
1668   Standard_Integer             ToSetTypeOfLine;
1669   uint16_t                     StippleLinePattern;
1670   uint16_t                     StippleLineFactor;
1671
1672   Standard_Integer             ToSetTypeOfMarker;
1673   Aspect_TypeOfMarker          TypeOfMarker;
1674   Handle(Image_PixMap)         MarkerImage;
1675
1676   Standard_Integer             ToSetMarkerSize;
1677   Standard_Real                MarkerSize;
1678
1679   Standard_Integer             ToSetTransparency;
1680   Standard_Real                Transparency;
1681
1682   Standard_Integer             ToSetAlphaMode;
1683   Graphic3d_AlphaMode          AlphaMode;
1684   Standard_ShortReal           AlphaCutoff;
1685
1686   Standard_Integer             ToSetMaterial;
1687   Graphic3d_NameOfMaterial     Material;
1688   TCollection_AsciiString      MatName;
1689
1690   NCollection_Sequence<TopoDS_Shape> SubShapes;
1691
1692   Standard_Integer             ToSetShowFreeBoundary;
1693   Standard_Integer             ToSetFreeBoundaryWidth;
1694   Standard_Real                FreeBoundaryWidth;
1695   Standard_Integer             ToSetFreeBoundaryColor;
1696   Quantity_Color               FreeBoundaryColor;
1697
1698   Standard_Integer             ToEnableIsoOnTriangulation;
1699
1700   Standard_Integer             ToSetFaceBoundaryDraw;
1701   Standard_Integer             ToSetFaceBoundaryUpperContinuity;
1702   GeomAbs_Shape                FaceBoundaryUpperContinuity;
1703
1704   Standard_Integer             ToSetFaceBoundaryColor;
1705   Quantity_Color               FaceBoundaryColor;
1706
1707   Standard_Integer             ToSetFaceBoundaryWidth;
1708   Standard_Real                FaceBoundaryWidth;
1709
1710   Standard_Integer             ToSetTypeOfFaceBoundaryLine;
1711   Aspect_TypeOfLine            TypeOfFaceBoundaryLine;
1712
1713   Standard_Integer             ToSetMaxParamValue;
1714   Standard_Real                MaxParamValue;
1715
1716   Standard_Integer             ToSetSensitivity;
1717   Standard_Integer             SelectionMode;
1718   Standard_Integer             Sensitivity;
1719
1720   Standard_Integer             ToSetHatch;
1721   Standard_Integer             StdHatchStyle;
1722   TCollection_AsciiString      PathToHatchPattern;
1723
1724   Standard_Integer             ToSetShadingModel;
1725   Graphic3d_TypeOfShadingModel ShadingModel;
1726   TCollection_AsciiString      ShadingModelName;
1727
1728   Standard_Integer             ToSetInterior;
1729   Aspect_InteriorStyle         InteriorStyle;
1730
1731   Standard_Integer             ToSetDrawSilhouette;
1732
1733   Standard_Integer             ToSetDrawEdges;
1734   Standard_Integer             ToSetQuadEdges;
1735
1736   Standard_Integer             ToSetEdgeColor;
1737   Quantity_ColorRGBA           EdgeColor;
1738
1739   Standard_Integer             ToSetEdgeWidth;
1740   Standard_Real                EdgeWidth;
1741
1742   Standard_Integer             ToSetTypeOfEdge;
1743   Aspect_TypeOfLine            TypeOfEdge;
1744
1745   //! Empty constructor
1746   ViewerTest_AspectsChangeSet()
1747   : ToSetVisibility   (0),
1748     Visibility        (1),
1749     ToSetColor        (0),
1750     Color             (DEFAULT_COLOR),
1751     ToSetBackFaceColor(0),
1752     BackFaceColor     (DEFAULT_COLOR),
1753     ToSetLineWidth    (0),
1754     LineWidth         (1.0),
1755     ToSetTypeOfLine   (0),
1756     StippleLinePattern(0xFFFF),
1757     StippleLineFactor (1),
1758     ToSetTypeOfMarker (0),
1759     TypeOfMarker      (Aspect_TOM_PLUS),
1760     ToSetMarkerSize   (0),
1761     MarkerSize        (1.0),
1762     ToSetTransparency (0),
1763     Transparency      (0.0),
1764     ToSetAlphaMode    (0),
1765     AlphaMode         (Graphic3d_AlphaMode_BlendAuto),
1766     AlphaCutoff       (0.5f),
1767     ToSetMaterial     (0),
1768     Material          (Graphic3d_NameOfMaterial_DEFAULT),
1769     ToSetShowFreeBoundary      (0),
1770     ToSetFreeBoundaryWidth     (0),
1771     FreeBoundaryWidth          (1.0),
1772     ToSetFreeBoundaryColor     (0),
1773     FreeBoundaryColor          (DEFAULT_FREEBOUNDARY_COLOR),
1774     ToEnableIsoOnTriangulation (0),
1775     //
1776     ToSetFaceBoundaryDraw      (0),
1777     ToSetFaceBoundaryUpperContinuity (0),
1778     FaceBoundaryUpperContinuity(GeomAbs_CN),
1779     ToSetFaceBoundaryColor     (0),
1780     FaceBoundaryColor          (Quantity_NOC_BLACK),
1781     ToSetFaceBoundaryWidth     (0),
1782     FaceBoundaryWidth          (1.0f),
1783     ToSetTypeOfFaceBoundaryLine(0),
1784     TypeOfFaceBoundaryLine     (Aspect_TOL_SOLID),
1785     //
1786     ToSetMaxParamValue         (0),
1787     MaxParamValue              (500000),
1788     ToSetSensitivity           (0),
1789     SelectionMode              (-1),
1790     Sensitivity                (-1),
1791     ToSetHatch                 (0),
1792     StdHatchStyle              (-1),
1793     ToSetShadingModel          (0),
1794     ShadingModel               (Graphic3d_TypeOfShadingModel_DEFAULT),
1795     ToSetInterior              (0),
1796     InteriorStyle              (Aspect_IS_SOLID),
1797     ToSetDrawSilhouette (0),
1798     ToSetDrawEdges    (0),
1799     ToSetQuadEdges    (0),
1800     ToSetEdgeColor    (0),
1801     ToSetEdgeWidth    (0),
1802     EdgeWidth         (1.0),
1803     ToSetTypeOfEdge   (0),
1804     TypeOfEdge        (Aspect_TOL_SOLID)
1805     {}
1806
1807   //! @return true if no changes have been requested
1808   Standard_Boolean IsEmpty() const
1809   {
1810     return ToSetVisibility        == 0
1811         && ToSetLineWidth         == 0
1812         && ToSetTransparency      == 0
1813         && ToSetAlphaMode         == 0
1814         && ToSetColor             == 0
1815         && ToSetBackFaceColor     == 0
1816         && ToSetMaterial          == 0
1817         && ToSetShowFreeBoundary  == 0
1818         && ToSetFreeBoundaryColor == 0
1819         && ToSetFreeBoundaryWidth == 0
1820         && ToEnableIsoOnTriangulation == 0
1821         && ToSetFaceBoundaryDraw == 0
1822         && ToSetFaceBoundaryUpperContinuity == 0
1823         && ToSetFaceBoundaryColor == 0
1824         && ToSetFaceBoundaryWidth == 0
1825         && ToSetTypeOfFaceBoundaryLine == 0
1826         && ToSetMaxParamValue     == 0
1827         && ToSetSensitivity       == 0
1828         && ToSetHatch             == 0
1829         && ToSetShadingModel      == 0
1830         && ToSetInterior          == 0
1831         && ToSetDrawSilhouette    == 0
1832         && ToSetDrawEdges         == 0
1833         && ToSetQuadEdges         == 0
1834         && ToSetEdgeColor         == 0
1835         && ToSetEdgeWidth         == 0
1836         && ToSetTypeOfEdge        == 0;
1837   }
1838
1839   //! @return true if properties are valid
1840   Standard_Boolean Validate() const
1841   {
1842     Standard_Boolean isOk = Standard_True;
1843     if (Visibility != 0 && Visibility != 1)
1844     {
1845       Message::SendFail() << "Error: the visibility should be equal to 0 or 1 (0 - invisible; 1 - visible) (specified " << Visibility << ")";
1846       isOk = Standard_False;
1847     }
1848     if (LineWidth <= 0.0
1849      || LineWidth >  10.0)
1850     {
1851       Message::SendFail() << "Error: the width should be within [1; 10] range (specified " << LineWidth << ")";
1852       isOk = Standard_False;
1853     }
1854     if (Transparency < 0.0
1855      || Transparency > 1.0)
1856     {
1857       Message::SendFail() << "Error: the transparency should be within [0; 1] range (specified " << Transparency << ")";
1858       isOk = Standard_False;
1859     }
1860     if (ToSetAlphaMode == 1
1861      && (AlphaCutoff <= 0.0f || AlphaCutoff >= 1.0f))
1862     {
1863       Message::SendFail() << "Error: alpha cutoff value should be within (0; 1) range (specified " << AlphaCutoff << ")";
1864       isOk = Standard_False;
1865     }
1866     if (FreeBoundaryWidth <= 0.0
1867      || FreeBoundaryWidth >  10.0)
1868     {
1869       Message::SendFail() << "Error: the free boundary width should be within [1; 10] range (specified " << FreeBoundaryWidth << ")";
1870       isOk = Standard_False;
1871     }
1872     if (MaxParamValue < 0.0)
1873     {
1874       Message::SendFail() << "Error: the max parameter value should be greater than zero (specified " << MaxParamValue << ")";
1875       isOk = Standard_False;
1876     }
1877     if (Sensitivity < 0 && ToSetSensitivity)
1878     {
1879       Message::SendFail() << "Error: sensitivity parameter value should not be negative (specified " << Sensitivity << ")";
1880       isOk = Standard_False;
1881     }
1882     if (ToSetHatch == 1 && StdHatchStyle < 0 && PathToHatchPattern == "")
1883     {
1884       Message::SendFail ("Error: hatch style must be specified");
1885       isOk = Standard_False;
1886     }
1887     if (ToSetShadingModel == 1
1888     && (ShadingModel < Graphic3d_TypeOfShadingModel_DEFAULT || ShadingModel > Graphic3d_TypeOfShadingModel_PbrFacet))
1889     {
1890       Message::SendFail() << "Error: unknown shading model " << ShadingModelName << ".";
1891       isOk = Standard_False;
1892     }
1893     return isOk;
1894   }
1895
1896   //! Apply aspects to specified drawer.
1897   bool Apply (const Handle(Prs3d_Drawer)& theDrawer)
1898   {
1899     bool toRecompute = false;
1900     const Handle(Prs3d_Drawer)& aDefDrawer = ViewerTest::GetAISContext()->DefaultDrawer();
1901     if (ToSetShowFreeBoundary != 0)
1902     {
1903       theDrawer->SetFreeBoundaryDraw (ToSetShowFreeBoundary == 1);
1904       toRecompute = true;
1905     }
1906     if (ToSetFreeBoundaryWidth != 0)
1907     {
1908       if (ToSetFreeBoundaryWidth != -1
1909        || theDrawer->HasOwnFreeBoundaryAspect())
1910       {
1911         if (!theDrawer->HasOwnFreeBoundaryAspect())
1912         {
1913           Handle(Prs3d_LineAspect) aBoundaryAspect = new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
1914           *aBoundaryAspect->Aspect() = *theDrawer->FreeBoundaryAspect()->Aspect();
1915           theDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
1916           toRecompute = true;
1917         }
1918         theDrawer->FreeBoundaryAspect()->SetWidth (FreeBoundaryWidth);
1919       }
1920     }
1921     if (ToSetFreeBoundaryColor != 0)
1922     {
1923       Handle(Prs3d_LineAspect) aBoundaryAspect = new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
1924       *aBoundaryAspect->Aspect() = *theDrawer->FreeBoundaryAspect()->Aspect();
1925       aBoundaryAspect->SetColor (FreeBoundaryColor);
1926       theDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
1927       toRecompute = true;
1928     }
1929     if (ToSetTypeOfLine != 0)
1930     {
1931       if (ToSetTypeOfLine != -1
1932        || theDrawer->HasOwnLineAspect()
1933        || theDrawer->HasOwnWireAspect()
1934        || theDrawer->HasOwnFreeBoundaryAspect()
1935        || theDrawer->HasOwnUnFreeBoundaryAspect()
1936        || theDrawer->HasOwnSeenLineAspect())
1937       {
1938         toRecompute = theDrawer->SetOwnLineAspects() || toRecompute;
1939         theDrawer->LineAspect()->Aspect()->SetLinePattern (StippleLinePattern);
1940         theDrawer->LineAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
1941         theDrawer->WireAspect()->Aspect()->SetLinePattern (StippleLinePattern);
1942         theDrawer->WireAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
1943         theDrawer->FreeBoundaryAspect()->Aspect()->SetLinePattern (StippleLinePattern);
1944         theDrawer->FreeBoundaryAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
1945         theDrawer->UnFreeBoundaryAspect()->Aspect()->SetLinePattern (StippleLinePattern);
1946         theDrawer->UnFreeBoundaryAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
1947         theDrawer->SeenLineAspect()->Aspect()->SetLinePattern (StippleLinePattern);
1948         theDrawer->SeenLineAspect()->Aspect()->SetLineStippleFactor (StippleLineFactor);
1949       }
1950     }
1951     if (ToSetTypeOfMarker != 0)
1952     {
1953       if (ToSetTypeOfMarker != -1
1954        || theDrawer->HasOwnPointAspect())
1955       {
1956         toRecompute = theDrawer->SetupOwnPointAspect (aDefDrawer) || toRecompute;
1957         theDrawer->PointAspect()->SetTypeOfMarker (TypeOfMarker);
1958         theDrawer->PointAspect()->Aspect()->SetMarkerImage (MarkerImage.IsNull() ? Handle(Graphic3d_MarkerImage)() : new Graphic3d_MarkerImage (MarkerImage));
1959       }
1960     }
1961     if (ToSetMarkerSize != 0)
1962     {
1963       if (ToSetMarkerSize != -1
1964        || theDrawer->HasOwnPointAspect())
1965       {
1966         toRecompute = theDrawer->SetupOwnPointAspect (aDefDrawer) || toRecompute;
1967         theDrawer->PointAspect()->SetScale (MarkerSize);
1968         toRecompute = true;
1969       }
1970     }
1971     if (ToSetMaxParamValue != 0)
1972     {
1973       if (ToSetMaxParamValue != -1
1974        || theDrawer->HasOwnMaximalParameterValue())
1975       {
1976         theDrawer->SetMaximalParameterValue (MaxParamValue);
1977         toRecompute = true;
1978       }
1979     }
1980     if (ToSetFaceBoundaryDraw != 0)
1981     {
1982       if (ToSetFaceBoundaryDraw != -1
1983        || theDrawer->HasOwnFaceBoundaryDraw())
1984       {
1985         toRecompute = true;
1986         theDrawer->SetFaceBoundaryDraw (ToSetFaceBoundaryDraw == 1);
1987       }
1988     }
1989     if (ToSetFaceBoundaryUpperContinuity != 0)
1990     {
1991       if (ToSetFaceBoundaryUpperContinuity != -1
1992        || theDrawer->HasOwnFaceBoundaryUpperContinuity())
1993       {
1994         toRecompute = true;
1995         if (ToSetFaceBoundaryUpperContinuity == -1)
1996         {
1997           theDrawer->UnsetFaceBoundaryUpperContinuity();
1998         }
1999         else
2000         {
2001           theDrawer->SetFaceBoundaryUpperContinuity (FaceBoundaryUpperContinuity);
2002         }
2003       }
2004     }
2005     if (ToSetFaceBoundaryColor != 0)
2006     {
2007       if (ToSetFaceBoundaryColor != -1
2008        || theDrawer->HasOwnFaceBoundaryAspect())
2009       {
2010         if (ToSetFaceBoundaryColor == -1)
2011         {
2012           toRecompute = true;
2013           theDrawer->SetFaceBoundaryAspect (Handle(Prs3d_LineAspect)());
2014         }
2015         else
2016         {
2017           toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2018           theDrawer->FaceBoundaryAspect()->SetColor (FaceBoundaryColor);
2019         }
2020       }
2021     }
2022     if (ToSetFaceBoundaryWidth != 0)
2023     {
2024       if (ToSetFaceBoundaryWidth != -1
2025        || theDrawer->HasOwnFaceBoundaryAspect())
2026       {
2027         toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2028         theDrawer->FaceBoundaryAspect()->SetWidth (FaceBoundaryWidth);
2029       }
2030     }
2031     if (ToSetTypeOfFaceBoundaryLine != 0)
2032     {
2033       if (ToSetTypeOfFaceBoundaryLine != -1
2034        || theDrawer->HasOwnFaceBoundaryAspect())
2035       {
2036         toRecompute = theDrawer->SetupOwnFaceBoundaryAspect (aDefDrawer) || toRecompute;
2037         theDrawer->FaceBoundaryAspect()->SetTypeOfLine (TypeOfFaceBoundaryLine);
2038       }
2039     }
2040     if (ToSetShadingModel != 0)
2041     {
2042       if (ToSetShadingModel != -1
2043        || theDrawer->HasOwnShadingAspect())
2044       {
2045         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2046         theDrawer->ShadingAspect()->Aspect()->SetShadingModel (ShadingModel);
2047       }
2048     }
2049     if (ToSetBackFaceColor != 0)
2050     {
2051       if (ToSetBackFaceColor != -1
2052        || theDrawer->HasOwnShadingAspect())
2053       {
2054         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2055         theDrawer->ShadingAspect()->SetColor (BackFaceColor, Aspect_TOFM_BACK_SIDE);
2056       }
2057     }
2058     if (ToSetAlphaMode != 0)
2059     {
2060       if (ToSetAlphaMode != -1
2061        || theDrawer->HasOwnShadingAspect())
2062       {
2063         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2064         theDrawer->ShadingAspect()->Aspect()->SetAlphaMode (AlphaMode, AlphaCutoff);
2065       }
2066     }
2067     if (ToSetHatch != 0)
2068     {
2069       if (ToSetHatch != -1
2070       ||  theDrawer->HasOwnShadingAspect())
2071       {
2072         theDrawer->SetupOwnShadingAspect (aDefDrawer);
2073         Handle(Graphic3d_AspectFillArea3d) anAsp = theDrawer->ShadingAspect()->Aspect();
2074         if (ToSetHatch == -1)
2075         {
2076           anAsp->SetInteriorStyle (Aspect_IS_SOLID);
2077         }
2078         else
2079         {
2080           anAsp->SetInteriorStyle (Aspect_IS_HATCH);
2081           if (!PathToHatchPattern.IsEmpty())
2082           {
2083             Handle(Image_AlienPixMap) anImage = new Image_AlienPixMap();
2084             if (anImage->Load (TCollection_AsciiString (PathToHatchPattern.ToCString())))
2085             {
2086               anAsp->SetHatchStyle (new Graphic3d_HatchStyle (anImage));
2087             }
2088             else
2089             {
2090               Message::SendFail() << "Error: cannot load the following image: " << PathToHatchPattern;
2091             }
2092           }
2093           else if (StdHatchStyle != -1)
2094           {
2095             anAsp->SetHatchStyle (new Graphic3d_HatchStyle ((Aspect_HatchStyle)StdHatchStyle));
2096           }
2097         }
2098         toRecompute = true;
2099       }
2100     }
2101     if (ToSetInterior != 0)
2102     {
2103       if (ToSetInterior != -1
2104        || theDrawer->HasOwnShadingAspect())
2105       {
2106         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2107         theDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (InteriorStyle);
2108         if (InteriorStyle == Aspect_IS_HATCH
2109          && theDrawer->ShadingAspect()->Aspect()->HatchStyle().IsNull())
2110         {
2111           theDrawer->ShadingAspect()->Aspect()->SetHatchStyle (Aspect_HS_VERTICAL);
2112         }
2113       }
2114     }
2115     if (ToSetDrawSilhouette != 0)
2116     {
2117       if (ToSetDrawSilhouette != -1
2118        || theDrawer->HasOwnShadingAspect())
2119       {
2120         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2121         theDrawer->ShadingAspect()->Aspect()->SetDrawSilhouette (ToSetDrawSilhouette == 1);
2122       }
2123     }
2124     if (ToSetDrawEdges != 0)
2125     {
2126       if (ToSetDrawEdges != -1
2127        || theDrawer->HasOwnShadingAspect())
2128       {
2129         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2130         theDrawer->ShadingAspect()->Aspect()->SetDrawEdges (ToSetDrawEdges == 1);
2131       }
2132     }
2133     if (ToSetQuadEdges != 0)
2134     {
2135       if (ToSetQuadEdges != -1
2136           || theDrawer->HasOwnShadingAspect())
2137       {
2138         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2139         theDrawer->ShadingAspect()->Aspect()->SetSkipFirstEdge (ToSetQuadEdges == 1);
2140       }
2141     }
2142     if (ToSetEdgeWidth != 0)
2143     {
2144       if (ToSetEdgeWidth != -1
2145        || theDrawer->HasOwnShadingAspect())
2146       {
2147         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2148         theDrawer->ShadingAspect()->Aspect()->SetEdgeWidth (EdgeWidth);
2149       }
2150     }
2151     if (ToSetTypeOfEdge != 0)
2152     {
2153       if (ToSetTypeOfEdge != -1
2154        || theDrawer->HasOwnShadingAspect())
2155       {
2156         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2157         theDrawer->ShadingAspect()->Aspect()->SetEdgeLineType (TypeOfEdge);
2158         if (ToSetInterior == 0)
2159         {
2160           theDrawer->ShadingAspect()->Aspect()->SetDrawEdges (ToSetTypeOfEdge == 1
2161                                                            && TypeOfEdge != Aspect_TOL_EMPTY);
2162         }
2163       }
2164     }
2165     if (ToSetEdgeColor != 0)
2166     {
2167       if (ToSetEdgeColor != -1
2168        || theDrawer->HasOwnShadingAspect())
2169       {
2170         toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute;
2171         if (ToSetEdgeColor == -1)
2172         {
2173           theDrawer->ShadingAspect()->Aspect()->SetEdgeColor (theDrawer->ShadingAspect()->Aspect()->InteriorColor());
2174         }
2175         else
2176         {
2177           theDrawer->ShadingAspect()->Aspect()->SetEdgeColor (EdgeColor);
2178         }
2179       }
2180     }
2181     return toRecompute;
2182   }
2183 };
2184
2185 //==============================================================================
2186 //function : VAspects
2187 //purpose  :
2188 //==============================================================================
2189 static Standard_Integer VAspects (Draw_Interpretor& theDI,
2190                                   Standard_Integer  theArgNb,
2191                                   const char**      theArgVec)
2192 {
2193   TCollection_AsciiString aCmdName (theArgVec[0]);
2194   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2195   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2196   if (aCtx.IsNull())
2197   {
2198     Message::SendFail ("Error: no active view!");
2199     return 1;
2200   }
2201
2202   Standard_Integer anArgIter = 1;
2203   Standard_Boolean isDefaults = Standard_False;
2204   NCollection_Sequence<TCollection_AsciiString> aNames;
2205   for (; anArgIter < theArgNb; ++anArgIter)
2206   {
2207     TCollection_AsciiString anArg = theArgVec[anArgIter];
2208     if (anUpdateTool.parseRedrawMode (anArg))
2209     {
2210       continue;
2211     }
2212     else if (!anArg.IsEmpty()
2213            && anArg.Value (1) != '-')
2214     {
2215       aNames.Append (anArg);
2216     }
2217     else
2218     {
2219       if (anArg == "-defaults")
2220       {
2221         isDefaults = Standard_True;
2222         ++anArgIter;
2223       }
2224       break;
2225     }
2226   }
2227
2228   if (!aNames.IsEmpty() && isDefaults)
2229   {
2230     Message::SendFail ("Error: wrong syntax. If -defaults is used there should not be any objects' names!");
2231     return 1;
2232   }
2233
2234   NCollection_Sequence<ViewerTest_AspectsChangeSet> aChanges;
2235   aChanges.Append (ViewerTest_AspectsChangeSet());
2236   ViewerTest_AspectsChangeSet* aChangeSet = &aChanges.ChangeLast();
2237
2238   // parse syntax of legacy commands
2239   bool toParseAliasArgs = false;
2240   Standard_Boolean toDump = 0;
2241   Standard_Boolean toCompactDump = 0;
2242   Standard_Integer aDumpDepth = -1;
2243   if (aCmdName == "vsetwidth")
2244   {
2245     if (aNames.IsEmpty()
2246     || !aNames.Last().IsRealValue (Standard_True))
2247     {
2248       Message::SendFail ("Error: not enough arguments!");
2249       return 1;
2250     }
2251     aChangeSet->ToSetLineWidth = 1;
2252     aChangeSet->LineWidth = aNames.Last().RealValue();
2253     aNames.Remove (aNames.Length());
2254   }
2255   else if (aCmdName == "vunsetwidth")
2256   {
2257     aChangeSet->ToSetLineWidth = -1;
2258   }
2259   else if (aCmdName == "vsetcolor")
2260   {
2261     if (aNames.IsEmpty())
2262     {
2263       Message::SendFail ("Error: not enough arguments!");
2264       return 1;
2265     }
2266     aChangeSet->ToSetColor = 1;
2267
2268     Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
2269     Standard_Boolean     isOk   = Standard_False;
2270     if (Quantity_Color::ColorFromName (aNames.Last().ToCString(), aColor))
2271     {
2272       aChangeSet->Color = aColor;
2273       aNames.Remove (aNames.Length());
2274       isOk = Standard_True;
2275     }
2276     else if (Quantity_Color::ColorFromHex (aNames.Last().ToCString(), aChangeSet->Color))
2277     {
2278       aNames.Remove (aNames.Length());
2279       isOk = Standard_True;
2280     }
2281     else if (aNames.Length() >= 3)
2282     {
2283       const char* anArgVec[3] =
2284       {
2285         aNames.Value (aNames.Upper() - 2).ToCString(),
2286         aNames.Value (aNames.Upper() - 1).ToCString(),
2287         aNames.Value (aNames.Upper() - 0).ToCString(),
2288       };
2289
2290       Standard_Integer aNbParsed = Draw::ParseColor (3, anArgVec, aChangeSet->Color);
2291       isOk = aNbParsed == 3;
2292       aNames.Remove (aNames.Length());
2293       aNames.Remove (aNames.Length());
2294       aNames.Remove (aNames.Length());
2295     }
2296     if (!isOk)
2297     {
2298       Message::SendFail ("Error: not enough arguments!");
2299       return 1;
2300     }
2301   }
2302   else if (aCmdName == "vunsetcolor")
2303   {
2304     aChangeSet->ToSetColor = -1;
2305   }
2306   else if (aCmdName == "vsettransparency")
2307   {
2308     if (aNames.IsEmpty()
2309     || !aNames.Last().IsRealValue (Standard_True))
2310     {
2311       Message::SendFail ("Error: not enough arguments!");
2312       return 1;
2313     }
2314     aChangeSet->ToSetTransparency = 1;
2315     aChangeSet->Transparency  = aNames.Last().RealValue();
2316     aNames.Remove (aNames.Length());
2317   }
2318   else if (aCmdName == "vunsettransparency")
2319   {
2320     aChangeSet->ToSetTransparency = -1;
2321   }
2322   else if (aCmdName == "vsetmaterial")
2323   {
2324     if (aNames.IsEmpty())
2325     {
2326       Message::SendFail ("Error: not enough arguments!");
2327       return 1;
2328     }
2329     aChangeSet->ToSetMaterial = 1;
2330     aChangeSet->MatName = aNames.Last();
2331     aNames.Remove (aNames.Length());
2332     if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString(), aChangeSet->Material))
2333     {
2334       Message::SendFail() << "Syntax error: unknown material '" << aChangeSet->MatName << "'.";
2335       return 1;
2336     }
2337   }
2338   else if (aCmdName == "vunsetmaterial")
2339   {
2340     aChangeSet->ToSetMaterial = -1;
2341   }
2342   else if (aCmdName == "vsetinteriorstyle")
2343   {
2344     if (aNames.IsEmpty()
2345     || !aNames.Last().IsRealValue (Standard_True))
2346     {
2347       Message::SendFail ("Error: not enough arguments!");
2348       return 1;
2349     }
2350     aChangeSet->ToSetInterior = 1;
2351     if (!parseInteriorStyle (aNames.Last(), aChangeSet->InteriorStyle))
2352     {
2353       Message::SendFail() << "Error: wrong syntax at " << aNames.Last();
2354       return 1;
2355     }
2356     aNames.Remove (aNames.Length());
2357   }
2358   else if (aCmdName == "vsetedgetype")
2359   {
2360     aChangeSet->ToSetDrawEdges = 1;
2361     toParseAliasArgs = true;
2362   }
2363   else if (aCmdName == "vunsetedgetype")
2364   {
2365     aChangeSet->ToSetDrawEdges  = -1;
2366     aChangeSet->ToSetEdgeColor  = -1;
2367     aChangeSet->ToSetTypeOfEdge = -1;
2368     aChangeSet->TypeOfEdge = Aspect_TOL_SOLID;
2369   }
2370   else if (aCmdName == "vshowfaceboundary")
2371   {
2372     aChangeSet->ToSetFaceBoundaryDraw = 1;
2373     toParseAliasArgs = true;
2374     if (aNames.Size() >= 2
2375      && aNames.Value (2).IsIntegerValue())
2376     {
2377       if (aNames.Size() == 7)
2378       {
2379         if (ViewerTest::ParseLineType (aNames.Value (7).ToCString(), aChangeSet->TypeOfFaceBoundaryLine))
2380         {
2381           aChangeSet->ToSetTypeOfFaceBoundaryLine = 1;
2382           aNames.Remove (7);
2383         }
2384       }
2385       if (aNames.Size() == 6
2386        && aNames.Value (6).IsRealValue (Standard_True))
2387       {
2388         aChangeSet->ToSetFaceBoundaryWidth = 1;
2389         aChangeSet->FaceBoundaryWidth = aNames.Value (6).RealValue();
2390         aNames.Remove (6);
2391       }
2392       if (aNames.Size() == 5
2393        && aNames.Value (3).IsIntegerValue()
2394        && aNames.Value (4).IsIntegerValue()
2395        && aNames.Value (5).IsIntegerValue())
2396       {
2397         aChangeSet->ToSetFaceBoundaryColor = 1;
2398         aChangeSet->FaceBoundaryColor = Quantity_Color (aNames.Value (3).IntegerValue() / 255.0,
2399                                                         aNames.Value (4).IntegerValue() / 255.0,
2400                                                         aNames.Value (5).IntegerValue() / 255.0,
2401                                                         Quantity_TOC_sRGB);
2402         aNames.Remove (5);
2403         aNames.Remove (4);
2404         aNames.Remove (3);
2405       }
2406       if (aNames.Size() == 2)
2407       {
2408         toParseAliasArgs = false;
2409         aChangeSet->ToSetFaceBoundaryDraw = aNames.Value (2).IntegerValue() == 1 ? 1 : -1;
2410         aNames.Remove (2);
2411       }
2412     }
2413   }
2414   else if (anArgIter >= theArgNb)
2415   {
2416     Message::SendFail ("Error: not enough arguments!");
2417     return 1;
2418   }
2419
2420   if (!aChangeSet->IsEmpty()
2421    && !toParseAliasArgs)
2422   {
2423     anArgIter = theArgNb;
2424   }
2425   for (; anArgIter < theArgNb; ++anArgIter)
2426   {
2427     TCollection_AsciiString anArg = theArgVec[anArgIter];
2428     anArg.LowerCase();
2429     if (anArg == "-setwidth"
2430      || anArg == "-width"
2431      || anArg == "-setlinewidth"
2432      || anArg == "-linewidth"
2433      || anArg == "-setedgewidth"
2434      || anArg == "-setedgeswidth"
2435      || anArg == "-edgewidth"
2436      || anArg == "-edgeswidth"
2437      || anArg == "-setfaceboundarywidth"
2438      || anArg == "-setboundarywidth"
2439      || anArg == "-faceboundarywidth"
2440      || anArg == "-boundarywidth")
2441     {
2442       if (++anArgIter >= theArgNb)
2443       {
2444         Message::SendFail() << "Error: wrong syntax at " << anArg;
2445         return 1;
2446       }
2447
2448       const Standard_Real aWidth = Draw::Atof (theArgVec[anArgIter]);
2449       if (anArg == "-setedgewidth"
2450        || anArg == "-setedgeswidth"
2451        || anArg == "-edgewidth"
2452        || anArg == "-edgeswidth"
2453        || aCmdName == "vsetedgetype")
2454       {
2455         aChangeSet->ToSetEdgeWidth = 1;
2456         aChangeSet->EdgeWidth = aWidth;
2457       }
2458       else if (anArg == "-setfaceboundarywidth"
2459             || anArg == "-setboundarywidth"
2460             || anArg == "-faceboundarywidth"
2461             || anArg == "-boundarywidth"
2462             || aCmdName == "vshowfaceboundary")
2463       {
2464         aChangeSet->ToSetFaceBoundaryWidth = 1;
2465         aChangeSet->FaceBoundaryWidth = aWidth;
2466       }
2467       else
2468       {
2469         aChangeSet->ToSetLineWidth = 1;
2470         aChangeSet->LineWidth = aWidth;
2471       }
2472     }
2473     else if (anArg == "-unsetwidth"
2474           || anArg == "-unsetlinewidth"
2475           || anArg == "-unsetedgewidth")
2476     {
2477       if (anArg == "-unsetedgewidth")
2478       {
2479         aChangeSet->ToSetEdgeWidth = -1;
2480         aChangeSet->EdgeWidth = 1.0;
2481       }
2482       else
2483       {
2484         aChangeSet->ToSetLineWidth = -1;
2485         aChangeSet->LineWidth = 1.0;
2486       }
2487     }
2488     else if (anArg == "-settransp"
2489           || anArg == "-settransparency"
2490           || anArg == "-transparency"
2491           || anArg == "-transp")
2492     {
2493       if (++anArgIter >= theArgNb)
2494       {
2495         Message::SendFail() << "Error: wrong syntax at " << anArg;
2496         return 1;
2497       }
2498       aChangeSet->ToSetTransparency = 1;
2499       aChangeSet->Transparency = Draw::Atof (theArgVec[anArgIter]);
2500       if (aChangeSet->Transparency >= 0.0
2501        && aChangeSet->Transparency <= Precision::Confusion())
2502       {
2503         aChangeSet->ToSetTransparency = -1;
2504         aChangeSet->Transparency = 0.0;
2505       }
2506     }
2507     else if (anArg == "-setalphamode"
2508           || anArg == "-alphamode")
2509     {
2510       if (++anArgIter >= theArgNb)
2511       {
2512         Message::SendFail() << "Error: wrong syntax at " << anArg;
2513         return 1;
2514       }
2515       aChangeSet->ToSetAlphaMode = 1;
2516       aChangeSet->AlphaCutoff = 0.5f;
2517       {
2518         TCollection_AsciiString aParam (theArgVec[anArgIter]);
2519         aParam.LowerCase();
2520         if (aParam == "opaque")
2521         {
2522           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Opaque;
2523         }
2524         else if (aParam == "mask")
2525         {
2526           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Mask;
2527         }
2528         else if (aParam == "blend")
2529         {
2530           aChangeSet->AlphaMode = Graphic3d_AlphaMode_Blend;
2531         }
2532         else if (aParam == "maskblend"
2533               || aParam == "blendmask")
2534         {
2535           aChangeSet->AlphaMode = Graphic3d_AlphaMode_MaskBlend;
2536         }
2537         else if (aParam == "blendauto"
2538               || aParam == "auto")
2539         {
2540           aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
2541         }
2542         else
2543         {
2544           Message::SendFail() << "Error: wrong syntax at " << aParam;
2545           return 1;
2546         }
2547       }
2548
2549       if (anArgIter + 1 < theArgNb
2550        && theArgVec[anArgIter + 1][0] != '-')
2551       {
2552         TCollection_AsciiString aParam2 (theArgVec[anArgIter + 1]);
2553         if (aParam2.IsRealValue (Standard_True))
2554         {
2555           aChangeSet->AlphaCutoff = (float )aParam2.RealValue();
2556           ++anArgIter;
2557         }
2558       }
2559     }
2560     else if (anArg == "-setvis"
2561           || anArg == "-setvisibility"
2562           || anArg == "-visibility")
2563     {
2564       if (++anArgIter >= theArgNb)
2565       {
2566         Message::SendFail() << "Error: wrong syntax at " << anArg;
2567         return 1;
2568       }
2569
2570       aChangeSet->ToSetVisibility = 1;
2571       aChangeSet->Visibility = Draw::Atoi (theArgVec[anArgIter]);
2572     }
2573     else if (anArg == "-setalpha"
2574           || anArg == "-alpha")
2575     {
2576       if (++anArgIter >= theArgNb)
2577       {
2578         Message::SendFail() << "Error: wrong syntax at " << anArg;
2579         return 1;
2580       }
2581       aChangeSet->ToSetTransparency = 1;
2582       aChangeSet->Transparency  = Draw::Atof (theArgVec[anArgIter]);
2583       if (aChangeSet->Transparency < 0.0
2584        || aChangeSet->Transparency > 1.0)
2585       {
2586         Message::SendFail() << "Error: the transparency should be within [0; 1] range (specified " << aChangeSet->Transparency << ")";
2587         return 1;
2588       }
2589       aChangeSet->Transparency = 1.0 - aChangeSet->Transparency;
2590       if (aChangeSet->Transparency >= 0.0
2591        && aChangeSet->Transparency <= Precision::Confusion())
2592       {
2593         aChangeSet->ToSetTransparency = -1;
2594         aChangeSet->Transparency = 0.0;
2595       }
2596     }
2597     else if (anArg == "-unsettransp"
2598           || anArg == "-unsettransparency"
2599           || anArg == "-unsetalpha"
2600           || anArg == "-opaque")
2601     {
2602       aChangeSet->ToSetTransparency = -1;
2603       aChangeSet->Transparency = 0.0;
2604     }
2605     else if (anArg == "-setcolor"
2606           || anArg == "-color"
2607           || anArg == "-setbackfacecolor"
2608           || anArg == "-backfacecolor"
2609           || anArg == "-setbackcolor"
2610           || anArg == "-backcolor"
2611           || anArg == "-setfaceboundarycolor"
2612           || anArg == "-setboundarycolor"
2613           || anArg == "-faceboundarycolor"
2614           || anArg == "-boundarycolor")
2615     {
2616       Quantity_Color aColor;
2617       Standard_Integer aNbParsed = Draw::ParseColor (theArgNb  - anArgIter - 1,
2618                                                      theArgVec + anArgIter + 1,
2619                                                      aColor);
2620       if (aNbParsed == 0)
2621       {
2622         Message::SendFail() << "Syntax error at '" << anArg << "'";
2623         return 1;
2624       }
2625       anArgIter += aNbParsed;
2626       if (aCmdName == "vsetedgetype")
2627       {
2628         aChangeSet->ToSetEdgeColor = 1;
2629         aChangeSet->EdgeColor = Quantity_ColorRGBA (aColor);
2630       }
2631       else if (aCmdName == "vshowfaceboundary"
2632             || anArg == "-setfaceboundarycolor"
2633             || anArg == "-setboundarycolor"
2634             || anArg == "-faceboundarycolor"
2635             || anArg == "-boundarycolor")
2636       {
2637         aChangeSet->ToSetFaceBoundaryColor = 1;
2638         aChangeSet->FaceBoundaryColor = aColor;
2639       }
2640       else if (anArg == "-setbackfacecolor"
2641             || anArg == "-backfacecolor"
2642             || anArg == "-setbackcolor"
2643             || anArg == "-backcolor")
2644       {
2645         aChangeSet->ToSetBackFaceColor = 1;
2646         aChangeSet->BackFaceColor = aColor;
2647       }
2648       else
2649       {
2650         aChangeSet->ToSetColor = 1;
2651         aChangeSet->Color = aColor;
2652       }
2653     }
2654     else if (anArg == "-setlinetype"
2655           || anArg == "-linetype"
2656           || anArg == "-setedgetype"
2657           || anArg == "-setedgestype"
2658           || anArg == "-edgetype"
2659           || anArg == "-edgestype"
2660           || anArg == "-setfaceboundarystyle"
2661           || anArg == "-faceboundarystyle"
2662           || anArg == "-boundarystyle"
2663           || anArg == "-setfaceboundarytype"
2664           || anArg == "-faceboundarytype"
2665           || anArg == "-setboundarytype"
2666           || anArg == "-boundarytype"
2667           || anArg == "-type")
2668     {
2669       if (++anArgIter >= theArgNb)
2670       {
2671         Message::SendFail() << "Error: wrong syntax at " << anArg;
2672         return 1;
2673       }
2674       Aspect_TypeOfLine aLineType = Aspect_TOL_EMPTY;
2675       uint16_t aLinePattern = 0xFFFF;
2676       if (!ViewerTest::ParseLineType (theArgVec[anArgIter], aLineType, aLinePattern))
2677       {
2678         Message::SendFail() << "Error: wrong syntax at " << anArg;
2679         return 1;
2680       }
2681
2682       if (anArg == "-setedgetype"
2683        || anArg == "-setedgestype"
2684        || anArg == "-edgetype"
2685        || anArg == "-edgestype"
2686        || aCmdName == "vsetedgetype")
2687       {
2688         aChangeSet->TypeOfEdge = Graphic3d_Aspects::DefaultLineTypeForPattern (aLinePattern);
2689         aChangeSet->ToSetTypeOfEdge = 1;
2690       }
2691       else if (anArg == "-setfaceboundarystyle"
2692             || anArg == "-faceboundarystyle"
2693             || anArg == "-boundarystyle"
2694             || anArg == "-setfaceboundarytype"
2695             || anArg == "-faceboundarytype"
2696             || anArg == "-setboundarytype"
2697             || anArg == "-boundarytype"
2698             || aCmdName == "vshowfaceboundary")
2699       {
2700         aChangeSet->TypeOfFaceBoundaryLine = Graphic3d_Aspects::DefaultLineTypeForPattern (aLinePattern);
2701         aChangeSet->ToSetTypeOfFaceBoundaryLine = 1;
2702       }
2703       else
2704       {
2705         aChangeSet->StippleLinePattern = aLinePattern;
2706         aChangeSet->ToSetTypeOfLine = 1;
2707       }
2708     }
2709     else if (anArg == "-unsetlinetype"
2710           || anArg == "-unsetedgetype"
2711           || anArg == "-unsetedgestype")
2712     {
2713       if (anArg == "-unsetedgetype"
2714        || anArg == "-unsetedgestype")
2715       {
2716         aChangeSet->ToSetTypeOfEdge = -1;
2717       }
2718       else
2719       {
2720         aChangeSet->ToSetTypeOfLine = -1;
2721       }
2722     }
2723     else if (anArg == "-setstipplelinefactor"
2724           || anArg == "-setstipplefactor"
2725           || anArg == "-setlinefactor"
2726           || anArg == "-stipplelinefactor"
2727           || anArg == "-stipplefactor"
2728           || anArg == "-linefactor")
2729     {
2730       if (aChangeSet->ToSetTypeOfLine == -1)
2731       {
2732         Message::SendFail() << "Error: -setStippleLineFactor requires -setLineType";
2733         return 1;
2734       }
2735       if (++anArgIter >= theArgNb)
2736       {
2737         Message::SendFail() << "Error: wrong syntax at " << anArg;
2738         return 1;
2739       }
2740       aChangeSet->StippleLineFactor = (uint16_t )Draw::Atoi (theArgVec[anArgIter]);
2741     }
2742     else if (anArg == "-setmarkertype"
2743           || anArg == "-markertype"
2744           || anArg == "-setpointtype"
2745           || anArg == "-pointtype")
2746     {
2747       if (++anArgIter >= theArgNb)
2748       {
2749         Message::SendFail() << "Error: wrong syntax at " << anArg;
2750         return 1;
2751       }
2752       if (!ViewerTest::ParseMarkerType (theArgVec[anArgIter], aChangeSet->TypeOfMarker, aChangeSet->MarkerImage))
2753       {
2754         Message::SendFail() << "Error: wrong syntax at " << anArg;
2755         return 1;
2756       }
2757
2758       aChangeSet->ToSetTypeOfMarker = 1;
2759     }
2760     else if (anArg == "-unsetmarkertype"
2761           || anArg == "-unsetpointtype")
2762     {
2763       aChangeSet->ToSetTypeOfMarker = -1;
2764     }
2765     else if (anArg == "-setmarkersize"
2766           || anArg == "-markersize"
2767           || anArg == "-setpointsize"
2768           || anArg == "-pointsize")
2769     {
2770       if (++anArgIter >= theArgNb)
2771       {
2772         Message::SendFail() << "Error: wrong syntax at " << anArg;
2773         return 1;
2774       }
2775       aChangeSet->ToSetMarkerSize = 1;
2776       aChangeSet->MarkerSize = Draw::Atof (theArgVec[anArgIter]);
2777     }
2778     else if (anArg == "-unsetmarkersize"
2779           || anArg == "-unsetpointsize")
2780     {
2781       aChangeSet->ToSetMarkerSize = -1;
2782       aChangeSet->MarkerSize = 1.0;
2783     }
2784     else if (anArg == "-unsetcolor")
2785     {
2786       aChangeSet->ToSetColor = -1;
2787       aChangeSet->Color = DEFAULT_COLOR;
2788     }
2789     else if (anArg == "-setmat"
2790           || anArg == "-mat"
2791           || anArg == "-setmaterial"
2792           || anArg == "-material")
2793     {
2794       if (++anArgIter >= theArgNb)
2795       {
2796         Message::SendFail() << "Error: wrong syntax at " << anArg;
2797         return 1;
2798       }
2799       aChangeSet->ToSetMaterial = 1;
2800       aChangeSet->MatName = theArgVec[anArgIter];
2801       if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString(), aChangeSet->Material))
2802       {
2803         Message::SendFail() << "Syntax error: unknown material '" << aChangeSet->MatName << "'.";
2804         return 1;
2805       }
2806     }
2807     else if (anArg == "-unsetmat"
2808           || anArg == "-unsetmaterial")
2809     {
2810       aChangeSet->ToSetMaterial = -1;
2811       aChangeSet->Material = Graphic3d_NameOfMaterial_DEFAULT;
2812     }
2813     else if (anArg == "-subshape"
2814           || anArg == "-subshapes")
2815     {
2816       if (isDefaults)
2817       {
2818         Message::SendFail() << "Error: wrong syntax. -subshapes can not be used together with -defaults call!";
2819         return 1;
2820       }
2821
2822       if (aNames.IsEmpty())
2823       {
2824         Message::SendFail() << "Error: main objects should specified explicitly when -subshapes is used!";
2825         return 1;
2826       }
2827
2828       aChanges.Append (ViewerTest_AspectsChangeSet());
2829       aChangeSet = &aChanges.ChangeLast();
2830
2831       for (++anArgIter; anArgIter < theArgNb; ++anArgIter)
2832       {
2833         Standard_CString aSubShapeName = theArgVec[anArgIter];
2834         if (*aSubShapeName == '-')
2835         {
2836           --anArgIter;
2837           break;
2838         }
2839
2840         TopoDS_Shape aSubShape = DBRep::Get (aSubShapeName);
2841         if (aSubShape.IsNull())
2842         {
2843           Message::SendFail() << "Error: shape " << aSubShapeName << " doesn't found!";
2844           return 1;
2845         }
2846         aChangeSet->SubShapes.Append (aSubShape);
2847       }
2848
2849       if (aChangeSet->SubShapes.IsEmpty())
2850       {
2851         Message::SendFail() << "Error: empty list is specified after -subshapes!";
2852         return 1;
2853       }
2854     }
2855     else if (anArg == "-setfreeboundary"
2856           || anArg == "-freeboundary"
2857           || anArg == "-setfb"
2858           || anArg == "-fb")
2859     {
2860       bool toEnable = true;
2861       if (!Draw::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
2862       {
2863         Message::SendFail() << "Error: wrong syntax at " << anArg;
2864         return 1;
2865       }
2866       ++anArgIter;
2867       aChangeSet->ToSetShowFreeBoundary = toEnable ? 1 : -1;
2868     }
2869     else if (anArg == "-setfreeboundarywidth"
2870           || anArg == "-freeboundarywidth"
2871           || anArg == "-setfbwidth"
2872           || anArg == "-fbwidth")
2873     {
2874       if (++anArgIter >= theArgNb)
2875       {
2876         Message::SendFail() << "Error: wrong syntax at " << anArg;
2877         return 1;
2878       }
2879       aChangeSet->ToSetFreeBoundaryWidth = 1;
2880       aChangeSet->FreeBoundaryWidth = Draw::Atof (theArgVec[anArgIter]);
2881     }
2882     else if (anArg == "-unsetfreeboundarywidth"
2883           || anArg == "-unsetfbwidth")
2884     {
2885       aChangeSet->ToSetFreeBoundaryWidth = -1;
2886       aChangeSet->FreeBoundaryWidth = 1.0;
2887     }
2888     else if (anArg == "-setfreeboundarycolor"
2889           || anArg == "-freeboundarycolor"
2890           || anArg == "-setfbcolor"
2891           || anArg == "-fbcolor")
2892     {
2893       Standard_Integer aNbParsed = Draw::ParseColor (theArgNb  - anArgIter - 1,
2894                                                      theArgVec + anArgIter + 1,
2895                                                      aChangeSet->FreeBoundaryColor);
2896       if (aNbParsed == 0)
2897       {
2898         Message::SendFail() << "Syntax error at '" << anArg << "'";
2899         return 1;
2900       }
2901       anArgIter += aNbParsed;
2902       aChangeSet->ToSetFreeBoundaryColor = 1;
2903     }
2904     else if (anArg == "-unsetfreeboundarycolor"
2905           || anArg == "-unsetfbcolor")
2906     {
2907       aChangeSet->ToSetFreeBoundaryColor = -1;
2908       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
2909     }
2910     else if (anArg == "-setisoontriangulation"
2911           || anArg == "-isoontriangulation"
2912           || anArg == "-setisoontriang"
2913           || anArg == "-isoontriang")
2914     {
2915       bool toEnable = true;
2916       if (!Draw::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
2917       {
2918         Message::SendFail() << "Error: wrong syntax at " << anArg;
2919         return 1;
2920       }
2921       ++anArgIter;
2922       aChangeSet->ToEnableIsoOnTriangulation = toEnable ? 1 : -1;
2923     }
2924     else if (anArg == "-setfaceboundarydraw"
2925           || anArg == "-setdrawfaceboundary"
2926           || anArg == "-setdrawfaceboundaries"
2927           || anArg == "-setshowfaceboundary"
2928           || anArg == "-setshowfaceboundaries"
2929           || anArg == "-setdrawfaceedges"
2930           || anArg == "-faceboundarydraw"
2931           || anArg == "-drawfaceboundary"
2932           || anArg == "-drawfaceboundaries"
2933           || anArg == "-showfaceboundary"
2934           || anArg == "-showfaceboundaries"
2935           || anArg == "-drawfaceedges"
2936           || anArg == "-faceboundary"
2937           || anArg == "-faceboundaries"
2938           || anArg == "-faceedges")
2939     {
2940       bool toEnable = true;
2941       if (!Draw::ParseOnOff (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "", toEnable))
2942       {
2943         Message::SendFail() << "Error: wrong syntax at " << anArg;
2944         return 1;
2945       }
2946       ++anArgIter;
2947       aChangeSet->ToSetFaceBoundaryDraw = toEnable ? 1 : -1;
2948     }
2949     else if (anArg == "-unsetfaceboundary"
2950           || anArg == "-unsetboundary")
2951     {
2952       aChangeSet->ToSetFaceBoundaryDraw  = -1;
2953       aChangeSet->ToSetFaceBoundaryColor = -1;
2954     }
2955     else if (anArg == "-setmostcontinuity"
2956           || anArg == "-mostcontinuity")
2957     {
2958       TCollection_AsciiString aClassArg (anArgIter + 1 < theArgNb ? theArgVec[anArgIter + 1] : "");
2959       aClassArg.LowerCase();
2960       GeomAbs_Shape aClass = GeomAbs_CN;
2961       if (aClassArg == "c0"
2962        || aClassArg == "0")
2963       {
2964         aClass = GeomAbs_C0;
2965       }
2966       else if (aClassArg == "g1")
2967       {
2968         aClass = GeomAbs_G1;
2969       }
2970       else if (aClassArg == "c1"
2971             || aClassArg == "1")
2972       {
2973         aClass = GeomAbs_C1;
2974       }
2975       else if (aClassArg == "g2")
2976       {
2977         aClass = GeomAbs_G2;
2978       }
2979       else if (aClassArg == "c2"
2980             || aClassArg == "2")
2981       {
2982         aClass = GeomAbs_C2;
2983       }
2984       else if (aClassArg == "c3"
2985             || aClassArg == "3")
2986       {
2987         aClass = GeomAbs_C3;
2988       }
2989       else if (aClassArg == "cn"
2990             || aClassArg == "n")
2991       {
2992         aClass = GeomAbs_CN;
2993       }
2994       else
2995       {
2996         Message::SendFail() << "Syntax error at '" << anArg << "'";
2997         return 1;
2998       }
2999
3000       ++anArgIter;
3001       aChangeSet->ToSetFaceBoundaryUpperContinuity = 1;
3002       aChangeSet->FaceBoundaryUpperContinuity = aClass;
3003     }
3004     else if (anArg == "-setmaxparamvalue"
3005           || anArg == "-maxparamvalue")
3006     {
3007       if (++anArgIter >= theArgNb)
3008       {
3009         Message::SendFail() << "Error: wrong syntax at " << anArg;
3010         return 1;
3011       }
3012       aChangeSet->ToSetMaxParamValue = 1;
3013       aChangeSet->MaxParamValue = Draw::Atof (theArgVec[anArgIter]);
3014     }
3015     else if (anArg == "-setsensitivity"
3016           || anArg == "-sensitivity")
3017     {
3018       if (isDefaults)
3019       {
3020         Message::SendFail() << "Error: wrong syntax. -setSensitivity can not be used together with -defaults call!";
3021         return 1;
3022       }
3023
3024       if (aNames.IsEmpty())
3025       {
3026         Message::SendFail() << "Error: object and selection mode should specified explicitly when -setSensitivity is used!";
3027         return 1;
3028       }
3029
3030       if (anArgIter + 2 >= theArgNb)
3031       {
3032         Message::SendFail() << "Error: wrong syntax at " << anArg;
3033         return 1;
3034       }
3035       aChangeSet->ToSetSensitivity = 1;
3036       aChangeSet->SelectionMode = Draw::Atoi (theArgVec[++anArgIter]);
3037       aChangeSet->Sensitivity = Draw::Atoi (theArgVec[++anArgIter]);
3038     }
3039     else if (anArg == "-sethatch"
3040           || anArg == "-hatch")
3041     {
3042       if (isDefaults)
3043       {
3044         Message::SendFail() << "Error: wrong syntax. -setHatch can not be used together with -defaults call!";
3045         return 1;
3046       }
3047
3048       if (aNames.IsEmpty())
3049       {
3050         Message::SendFail() << "Error: object should be specified explicitly when -setHatch is used!";
3051         return 1;
3052       }
3053
3054       aChangeSet->ToSetHatch = 1;
3055       TCollection_AsciiString anArgHatch (theArgVec[++anArgIter]);
3056       if (anArgHatch.Length() <= 2)
3057       {
3058         const Standard_Integer anIntStyle = Draw::Atoi (anArgHatch.ToCString());
3059         if (anIntStyle < 0
3060          || anIntStyle >= Aspect_HS_NB)
3061         {
3062           Message::SendFail() << "Error: hatch style is out of range [0, " << (Aspect_HS_NB - 1) << "]!";
3063           return 1;
3064         }
3065         aChangeSet->StdHatchStyle = anIntStyle;
3066       }
3067       else
3068       {
3069         aChangeSet->PathToHatchPattern = anArgHatch;
3070       }
3071     }
3072     else if (anArg == "-setshadingmodel"
3073           || anArg == "-setshading"
3074           || anArg == "-shadingmodel"
3075           || anArg == "-shading")
3076     {
3077       if (++anArgIter >= theArgNb)
3078       {
3079         Message::SendFail() << "Error: wrong syntax at " << anArg;
3080         return 1;
3081       }
3082       aChangeSet->ToSetShadingModel = 1;
3083       aChangeSet->ShadingModelName  = theArgVec[anArgIter];
3084       if (!ViewerTest::ParseShadingModel (theArgVec[anArgIter], aChangeSet->ShadingModel))
3085       {
3086         Message::SendFail() << "Error: wrong syntax at " << anArg;
3087         return 1;
3088       }
3089     }
3090     else if (anArg == "-unsetshadingmodel")
3091     {
3092       aChangeSet->ToSetShadingModel = -1;
3093       aChangeSet->ShadingModel = Graphic3d_TypeOfShadingModel_DEFAULT;
3094     }
3095     else if (anArg == "-setinterior"
3096           || anArg == "-setinteriorstyle"
3097           || anArg == "-interior"
3098           || anArg == "-interiorstyle")
3099     {
3100       if (++anArgIter >= theArgNb)
3101       {
3102         Message::SendFail() << "Error: wrong syntax at " << anArg;
3103         return 1;
3104       }
3105       aChangeSet->ToSetInterior = 1;
3106       if (!parseInteriorStyle (theArgVec[anArgIter], aChangeSet->InteriorStyle))
3107       {
3108         Message::SendFail() << "Error: wrong syntax at " << anArg;
3109         return 1;
3110       }
3111     }
3112     else if (anArg == "-unsetinterior")
3113     {
3114       aChangeSet->ToSetInterior = -1;
3115       aChangeSet->InteriorStyle = Aspect_IS_SOLID;
3116     }
3117     else if (anArg == "-setdrawoutline"
3118           || anArg == "-setdrawsilhouette"
3119           || anArg == "-setoutline"
3120           || anArg == "-setsilhouette"
3121           || anArg == "-outline"
3122           || anArg == "-outlined"
3123           || anArg == "-drawsilhouette"
3124           || anArg == "-silhouette")
3125     {
3126       bool toDrawOutline = true;
3127       if (anArgIter + 1 < theArgNb
3128        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toDrawOutline))
3129       {
3130         ++anArgIter;
3131       }
3132       aChangeSet->ToSetDrawSilhouette = toDrawOutline ? 1 : -1;
3133     }
3134     else if (anArg == "-setdrawedges"
3135           || anArg == "-setdrawedge"
3136           || anArg == "-drawedges"
3137           || anArg == "-drawedge"
3138           || anArg == "-edges")
3139     {
3140       bool toDrawEdges = true;
3141       if (anArgIter + 1 < theArgNb
3142        && Draw::ParseOnOff (theArgVec[anArgIter + 1], toDrawEdges))
3143       {
3144         ++anArgIter;
3145       }
3146       aChangeSet->ToSetDrawEdges = toDrawEdges ? 1 : -1;
3147     }
3148     else if (anArg == "-setquadedges"
3149           || anArg == "-setquads"
3150           || anArg == "-quads"
3151           || anArg == "-skipfirstedge")
3152     {
3153       bool isQuadMode = true;
3154       if (anArgIter + 1 < theArgNb
3155        && Draw::ParseOnOff (theArgVec[anArgIter + 1], isQuadMode))
3156       {
3157         ++anArgIter;
3158       }
3159       aChangeSet->ToSetQuadEdges = isQuadMode ? 1 : -1;
3160     }
3161     else if (anArg == "-setedgecolor"
3162           || anArg == "-setedgescolor"
3163           || anArg == "-edgecolor"
3164           || anArg == "-edgescolor")
3165     {
3166       Standard_Integer aNbParsed = Draw::ParseColor (theArgNb  - anArgIter - 1,
3167                                                      theArgVec + anArgIter + 1,
3168                                                      aChangeSet->EdgeColor);
3169       if (aNbParsed == 0)
3170       {
3171         Message::SendFail() << "Syntax error at '" << anArg << "'";
3172         return 1;
3173       }
3174       anArgIter += aNbParsed;
3175       aChangeSet->ToSetEdgeColor = 1;
3176     }
3177     else if (anArg == "-unset")
3178     {
3179       aChangeSet->ToSetVisibility = 1;
3180       aChangeSet->Visibility = 1;
3181       aChangeSet->ToSetLineWidth = -1;
3182       aChangeSet->LineWidth = 1.0;
3183       aChangeSet->ToSetTypeOfLine = -1;
3184       aChangeSet->StippleLinePattern = 0xFFFF;
3185       aChangeSet->StippleLineFactor = 1;
3186       aChangeSet->ToSetTypeOfMarker = -1;
3187       aChangeSet->TypeOfMarker = Aspect_TOM_PLUS;
3188       aChangeSet->ToSetMarkerSize = -1;
3189       aChangeSet->MarkerSize = 1.0;
3190       aChangeSet->ToSetTransparency = -1;
3191       aChangeSet->Transparency = 0.0;
3192       aChangeSet->ToSetAlphaMode = -1;
3193       aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto;
3194       aChangeSet->AlphaCutoff = 0.5f;
3195       aChangeSet->ToSetColor = -1;
3196       aChangeSet->Color = DEFAULT_COLOR;
3197       //aChangeSet->ToSetBackFaceColor = -1; // should be reset by ToSetColor
3198       //aChangeSet->BackFaceColor = DEFAULT_COLOR;
3199       aChangeSet->ToSetMaterial = -1;
3200       aChangeSet->Material = Graphic3d_NameOfMaterial_DEFAULT;
3201       aChangeSet->ToSetShowFreeBoundary = -1;
3202       aChangeSet->ToSetFreeBoundaryColor = -1;
3203       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
3204       aChangeSet->ToSetFreeBoundaryWidth = -1;
3205       aChangeSet->FreeBoundaryWidth = 1.0;
3206       aChangeSet->ToEnableIsoOnTriangulation = -1;
3207       //
3208       aChangeSet->ToSetFaceBoundaryDraw = -1;
3209       aChangeSet->ToSetFaceBoundaryUpperContinuity = -1;
3210       aChangeSet->FaceBoundaryUpperContinuity = GeomAbs_CN;
3211       aChangeSet->ToSetFaceBoundaryColor = -1;
3212       aChangeSet->FaceBoundaryColor = Quantity_NOC_BLACK;
3213       aChangeSet->ToSetFaceBoundaryWidth = -1;
3214       aChangeSet->FaceBoundaryWidth = 1.0f;
3215       aChangeSet->ToSetTypeOfFaceBoundaryLine = -1;
3216       aChangeSet->TypeOfFaceBoundaryLine = Aspect_TOL_SOLID;
3217       //
3218       aChangeSet->ToSetHatch = -1;
3219       aChangeSet->StdHatchStyle = -1;
3220       aChangeSet->PathToHatchPattern.Clear();
3221       aChangeSet->ToSetShadingModel = -1;
3222       aChangeSet->ShadingModel = Graphic3d_TypeOfShadingModel_DEFAULT;
3223       aChangeSet->ToSetInterior = -1;
3224       aChangeSet->InteriorStyle = Aspect_IS_SOLID;
3225       aChangeSet->ToSetDrawSilhouette = -1;
3226       aChangeSet->ToSetDrawEdges = -1;
3227       aChangeSet->ToSetQuadEdges = -1;
3228       aChangeSet->ToSetEdgeColor = -1;
3229       aChangeSet->EdgeColor = Quantity_ColorRGBA (DEFAULT_COLOR);
3230       aChangeSet->ToSetEdgeWidth = -1;
3231       aChangeSet->EdgeWidth = 1.0;
3232       aChangeSet->ToSetTypeOfEdge = -1;
3233       aChangeSet->TypeOfEdge = Aspect_TOL_SOLID;
3234     }
3235     else if (anArg == "-dumpjson")
3236     {
3237       toDump = Standard_True;
3238     }
3239     else if (anArg == "-dumpcompact")
3240     {
3241       toCompactDump = Standard_False;
3242       if (++anArgIter >= theArgNb && Draw::ParseOnOff (theArgVec[anArgIter + 1], toCompactDump))
3243         ++anArgIter;
3244     }
3245     else if (anArg == "-dumpdepth")
3246     {
3247       if (++anArgIter >= theArgNb)
3248       {
3249         Message::SendFail() << "Error: wrong syntax at " << anArg;
3250         return 1;
3251       }
3252       aDumpDepth = Draw::Atoi (theArgVec[anArgIter]);
3253     }
3254     else
3255     {
3256       Message::SendFail() << "Error: wrong syntax at " << anArg;
3257       return 1;
3258     }
3259   }
3260
3261   for (NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
3262        aChangesIter.More(); aChangesIter.Next())
3263   {
3264     if (!aChangesIter.Value().Validate())
3265     {
3266       return 1;
3267     }
3268   }
3269
3270   // special case for -defaults parameter.
3271   // all changed values will be set to DefaultDrawer.
3272   if (isDefaults)
3273   {
3274     const Handle(Prs3d_Drawer)& aDrawer = aCtx->DefaultDrawer();
3275     aChangeSet->Apply (aDrawer);
3276     if (aChangeSet->ToSetLineWidth != 0)
3277     {
3278       aDrawer->LineAspect()->SetWidth (aChangeSet->LineWidth);
3279       aDrawer->WireAspect()->SetWidth (aChangeSet->LineWidth);
3280       aDrawer->UnFreeBoundaryAspect()->SetWidth (aChangeSet->LineWidth);
3281       aDrawer->SeenLineAspect()->SetWidth (aChangeSet->LineWidth);
3282     }
3283     if (aChangeSet->ToSetColor != 0)
3284     {
3285       aDrawer->ShadingAspect()->SetColor        (aChangeSet->Color);
3286       aDrawer->LineAspect()->SetColor           (aChangeSet->Color);
3287       aDrawer->UnFreeBoundaryAspect()->SetColor (aChangeSet->Color);
3288       aDrawer->SeenLineAspect()->SetColor       (aChangeSet->Color);
3289       aDrawer->WireAspect()->SetColor           (aChangeSet->Color);
3290       aDrawer->PointAspect()->SetColor          (aChangeSet->Color);
3291     }
3292     if (aChangeSet->ToSetTransparency != 0)
3293     {
3294       aDrawer->ShadingAspect()->SetTransparency (aChangeSet->Transparency);
3295     }
3296     if (aChangeSet->ToSetMaterial != 0)
3297     {
3298       aDrawer->ShadingAspect()->SetMaterial (aChangeSet->Material);
3299     }
3300     if (aChangeSet->ToEnableIsoOnTriangulation != 0)
3301     {
3302       aDrawer->SetIsoOnTriangulation (aChangeSet->ToEnableIsoOnTriangulation == 1);
3303     }
3304
3305     // redisplay all objects in context
3306     for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
3307     {
3308       Handle(AIS_InteractiveObject)  aPrs = aPrsIter.Current();
3309       if (!aPrs.IsNull())
3310       {
3311         aCtx->Redisplay (aPrs, Standard_False);
3312       }
3313     }
3314     if (toDump)
3315     {
3316       Standard_SStream aStream;
3317       aDrawer->DumpJson (aStream, aDumpDepth);
3318
3319       if (toCompactDump)
3320         theDI << Standard_Dump::Text (aStream);
3321       else
3322         theDI << Standard_Dump::FormatJson (aStream);
3323     }
3324     return 0;
3325   }
3326
3327   for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
3328   {
3329     const TCollection_AsciiString& aName = aPrsIter.CurrentName();
3330     Handle(AIS_InteractiveObject)  aPrs  = aPrsIter.Current();
3331     if (aPrs.IsNull())
3332     {
3333       return 1;
3334     }
3335
3336     Handle(Prs3d_Drawer)           aDrawer = aPrs->Attributes();
3337     Handle(AIS_ColoredShape) aColoredPrs;
3338     Standard_Boolean toDisplay = Standard_False;
3339     Standard_Boolean toRedisplay = Standard_False;
3340     if (aChanges.Length() > 1 || aChangeSet->ToSetVisibility == 1)
3341     {
3342       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aPrs);
3343       if (aShapePrs.IsNull())
3344       {
3345         Message::SendFail() << "Error: an object " << aName << " is not an AIS_Shape presentation!";
3346         return 1;
3347       }
3348       aColoredPrs = Handle(AIS_ColoredShape)::DownCast (aShapePrs);
3349       if (aColoredPrs.IsNull())
3350       {
3351         aColoredPrs = new AIS_ColoredShape (aShapePrs);
3352         if (aShapePrs->HasDisplayMode())
3353         {
3354           aColoredPrs->SetDisplayMode (aShapePrs->DisplayMode());
3355         }
3356         aColoredPrs->SetLocalTransformation (aShapePrs->LocalTransformation());
3357         aCtx->Remove (aShapePrs, Standard_False);
3358         GetMapOfAIS().UnBind2 (aName);
3359         GetMapOfAIS().Bind (aColoredPrs, aName);
3360         toDisplay = Standard_True;
3361         aShapePrs = aColoredPrs;
3362         aPrs      = aColoredPrs;
3363       }
3364     }
3365
3366     if (!aPrs.IsNull())
3367     {
3368       NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
3369       aChangeSet = &aChangesIter.ChangeValue();
3370       if (aChangeSet->ToSetVisibility == 1)
3371       {
3372         Handle(AIS_ColoredDrawer) aColDrawer = aColoredPrs->CustomAspects (aColoredPrs->Shape());
3373         aColDrawer->SetHidden (aChangeSet->Visibility == 0);
3374       }
3375       else if (aChangeSet->ToSetMaterial == 1)
3376       {
3377         aCtx->SetMaterial (aPrs, aChangeSet->Material, Standard_False);
3378       }
3379       else if (aChangeSet->ToSetMaterial == -1)
3380       {
3381         aCtx->UnsetMaterial (aPrs, Standard_False);
3382       }
3383       if (aChangeSet->ToSetColor == 1)
3384       {
3385         aCtx->SetColor (aPrs, aChangeSet->Color, Standard_False);
3386       }
3387       else if (aChangeSet->ToSetColor == -1)
3388       {
3389         aCtx->UnsetColor (aPrs, Standard_False);
3390       }
3391       if (aChangeSet->ToSetTransparency == 1)
3392       {
3393         aCtx->SetTransparency (aPrs, aChangeSet->Transparency, Standard_False);
3394       }
3395       else if (aChangeSet->ToSetTransparency == -1)
3396       {
3397         aCtx->UnsetTransparency (aPrs, Standard_False);
3398       }
3399       if (aChangeSet->ToSetLineWidth == 1)
3400       {
3401         aCtx->SetWidth (aPrs, aChangeSet->LineWidth, Standard_False);
3402       }
3403       else if (aChangeSet->ToSetLineWidth == -1)
3404       {
3405         aCtx->UnsetWidth (aPrs, Standard_False);
3406       }
3407       else if (aChangeSet->ToEnableIsoOnTriangulation != 0)
3408       {
3409         aCtx->IsoOnTriangulation (aChangeSet->ToEnableIsoOnTriangulation == 1, aPrs);
3410         toRedisplay = Standard_True;
3411       }
3412       else if (aChangeSet->ToSetSensitivity != 0)
3413       {
3414         aCtx->SetSelectionSensitivity (aPrs, aChangeSet->SelectionMode, aChangeSet->Sensitivity);
3415       }
3416       if (!aDrawer.IsNull())
3417       {
3418         toRedisplay = aChangeSet->Apply (aDrawer) || toRedisplay;
3419       }
3420
3421       for (aChangesIter.Next(); aChangesIter.More(); aChangesIter.Next())
3422       {
3423         aChangeSet = &aChangesIter.ChangeValue();
3424         for (NCollection_Sequence<TopoDS_Shape>::Iterator aSubShapeIter (aChangeSet->SubShapes);
3425              aSubShapeIter.More(); aSubShapeIter.Next())
3426         {
3427           const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
3428           if (!aChangeSet->IsEmpty())
3429           {
3430             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
3431             aChangeSet->Apply (aCurColDrawer);
3432           }
3433           if (aChangeSet->ToSetVisibility == 1)
3434           {
3435             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
3436             aCurColDrawer->SetHidden (aChangeSet->Visibility == 0);
3437           }
3438           if (aChangeSet->ToSetColor == 1)
3439           {
3440             aColoredPrs->SetCustomColor (aSubShape, aChangeSet->Color);
3441           }
3442           if (aChangeSet->ToSetTransparency == 1)
3443           {
3444             aColoredPrs->SetCustomTransparency (aSubShape, aChangeSet->Transparency);
3445           }
3446           if (aChangeSet->ToSetLineWidth == 1)
3447           {
3448             aColoredPrs->SetCustomWidth (aSubShape, aChangeSet->LineWidth);
3449           }
3450           if (aChangeSet->ToSetColor     == -1
3451            || aChangeSet->ToSetLineWidth == -1)
3452           {
3453             aColoredPrs->UnsetCustomAspects (aSubShape, Standard_True);
3454           }
3455           if (aChangeSet->ToSetSensitivity != 0)
3456           {
3457             aCtx->SetSelectionSensitivity (aPrs, aChangeSet->SelectionMode, aChangeSet->Sensitivity);
3458           }
3459         }
3460       }
3461       if (toDisplay)
3462       {
3463         aCtx->Display (aPrs, Standard_False);
3464       }
3465       if (toRedisplay)
3466       {
3467         aCtx->Redisplay (aPrs, Standard_False);
3468       }
3469       else if (!aColoredPrs.IsNull())
3470       {
3471         aCtx->Redisplay (aColoredPrs, Standard_False);
3472       }
3473       else
3474       {
3475         aPrs->SynchronizeAspects();
3476       }
3477
3478       if (toDump)
3479       {
3480         Standard_SStream aStream;
3481         aDrawer->DumpJson (aStream);
3482
3483         theDI << aName << ": \n";
3484         theDI << Standard_Dump::FormatJson (aStream);
3485         theDI << "\n";
3486       }
3487     }
3488   }
3489   return 0;
3490 }
3491
3492 //==============================================================================
3493 //function : VDonly2
3494 //author   : ege
3495 //purpose  : Display only a selected or named  object
3496 //           if there is no selected or named object s, nothing is done
3497 //==============================================================================
3498 static int VDonly2 (Draw_Interpretor& ,
3499                     Standard_Integer  theArgNb,
3500                     const char**      theArgVec)
3501 {
3502   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
3503   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3504   if (aCtx.IsNull())
3505   {
3506     Message::SendFail ("Error: no active view!");
3507     return 1;
3508   }
3509
3510   Standard_Integer anArgIter = 1;
3511   for (; anArgIter < theArgNb; ++anArgIter)
3512   {
3513     if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
3514     {
3515       break;
3516     }
3517   }
3518
3519   NCollection_Map<Handle(Standard_Transient)> aDispSet;
3520   if (anArgIter >= theArgNb)
3521   {
3522     // display only selected objects
3523     if (aCtx->NbSelected() < 1)
3524     {
3525       return 0;
3526     }
3527
3528     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
3529     {
3530       aDispSet.Add (aCtx->SelectedInteractive());
3531     }
3532   }
3533   else
3534   {
3535     // display only specified objects
3536     for (; anArgIter < theArgNb; ++anArgIter)
3537     {
3538       TCollection_AsciiString aName = theArgVec[anArgIter];
3539       Handle(AIS_InteractiveObject) aShape;
3540       if (GetMapOfAIS().Find2 (aName, aShape)
3541       && !aShape.IsNull())
3542       {
3543         aCtx->Display (aShape, Standard_False);
3544         aDispSet.Add (aShape);
3545       }
3546     }
3547   }
3548
3549   // weed out other objects
3550   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
3551   {
3552     if (aDispSet.Contains (anIter.Key1()))
3553     {
3554       continue;
3555     }
3556
3557     if (Handle(AIS_InteractiveObject) aShape = anIter.Key1())
3558     {
3559       aCtx->Erase (aShape, Standard_False);
3560     }
3561   }
3562   return 0;
3563 }
3564
3565 //==============================================================================
3566 //function : VRemove
3567 //purpose  : Removes selected or named objects.
3568 //           If there is no selected or named objects,
3569 //           all objects in the viewer can be removed with argument -all.
3570 //           If -context is in arguments, the object is not deleted from the map of
3571 //           objects (deleted only from the current context).
3572 //==============================================================================
3573 int VRemove (Draw_Interpretor& theDI,
3574              Standard_Integer  theArgNb,
3575              const char**      theArgVec)
3576 {
3577   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
3578   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3579   if (aCtx.IsNull())
3580   {
3581     Message::SendFail ("Error: no active view!");
3582     return 1;
3583   }
3584
3585   Standard_Boolean isContextOnly = Standard_False;
3586   Standard_Boolean toRemoveAll   = Standard_False;
3587   Standard_Boolean toPrintInfo   = Standard_True;
3588   Standard_Boolean toFailOnError = Standard_True;
3589
3590   Standard_Integer anArgIter = 1;
3591   for (; anArgIter < theArgNb; ++anArgIter)
3592   {
3593     TCollection_AsciiString anArg = theArgVec[anArgIter];
3594     anArg.LowerCase();
3595     if (anArg == "-context")
3596     {
3597       isContextOnly = Standard_True;
3598     }
3599     else if (anArg == "-all")
3600     {
3601       toRemoveAll = Standard_True;
3602     }
3603     else if (anArg == "-noinfo")
3604     {
3605       toPrintInfo = Standard_False;
3606     }
3607     else if (anArg == "-noerror"
3608           || anArg == "-nofail")
3609     {
3610       toFailOnError = Standard_False;
3611     }
3612     else if (anUpdateTool.parseRedrawMode (anArg))
3613     {
3614       continue;
3615     }
3616     else
3617     {
3618       break;
3619     }
3620   }
3621   if (toRemoveAll
3622    && anArgIter < theArgNb)
3623   {
3624     Message::SendFail ("Error: wrong syntax!");
3625     return 1;
3626   }
3627
3628   NCollection_List<TCollection_AsciiString> anIONameList;
3629   if (toRemoveAll)
3630   {
3631     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3632          anIter.More(); anIter.Next())
3633     {
3634       anIONameList.Append (anIter.Key2());
3635     }
3636   }
3637   else if (anArgIter < theArgNb) // removed objects names are in argument list
3638   {
3639     for (; anArgIter < theArgNb; ++anArgIter)
3640     {
3641       const TCollection_AsciiString aName (theArgVec[anArgIter]);
3642       if (aName.Search ("*") != -1)
3643       {
3644         for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aPrsIter (GetMapOfAIS()); aPrsIter.More(); aPrsIter.Next())
3645         {
3646           if (aPrsIter.Key1()->GetContext() != aCtx)
3647           {
3648             continue;
3649           }
3650           const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aName + "' '" + aPrsIter.Key2() + "'";
3651           if (theDI.Eval (aCheck.ToCString()) == 0
3652           && *theDI.Result() == '1')
3653           {
3654             anIONameList.Append (aPrsIter.Key2());
3655           }
3656         }
3657         theDI.Reset();
3658         continue;
3659       }
3660
3661       Handle(AIS_InteractiveObject) anIO;
3662       if (!GetMapOfAIS().Find2 (aName, anIO))
3663       {
3664         if (toFailOnError)
3665         {
3666           Message::SendFail() << "Syntax error: '" << aName << "' was not bound to some object.";
3667           return 1;
3668         }
3669       }
3670       else if (anIO->GetContext() != aCtx)
3671       {
3672         if (toFailOnError)
3673         {
3674           Message::SendFail() << "Syntax error: '" << aName << "' was not displayed in current context.\n"
3675                               << "Please activate view with this object displayed and try again.";
3676           return 1;
3677         }
3678       }
3679       else
3680       {
3681         anIONameList.Append (aName);
3682       }
3683     }
3684   }
3685   else if (aCtx->NbSelected() > 0)
3686   {
3687     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3688          anIter.More(); anIter.Next())
3689     {
3690       if (!aCtx->IsSelected (anIter.Key1()))
3691       {
3692         continue;
3693       }
3694
3695       anIONameList.Append (anIter.Key2());
3696       continue;
3697     }
3698   }
3699
3700   // Unbind all removed objects from the map of displayed IO.
3701   for (NCollection_List<TCollection_AsciiString>::Iterator anIter (anIONameList);
3702        anIter.More(); anIter.Next())
3703   {
3704     const Handle(AIS_InteractiveObject) anIO = GetMapOfAIS().Find2 (anIter.Value());
3705     aCtx->Remove (anIO, Standard_False);
3706     if (toPrintInfo)
3707     {
3708       theDI << anIter.Value() << " ";
3709     }
3710     if (!isContextOnly)
3711     {
3712       GetMapOfAIS().UnBind2 (anIter.Value());
3713     }
3714   }
3715   return 0;
3716 }
3717
3718 //==============================================================================
3719 //function : VErase
3720 //purpose  : Erase some selected or named objects
3721 //           if there is no selected or named objects, the whole viewer is erased
3722 //==============================================================================
3723 int VErase (Draw_Interpretor& theDI,
3724             Standard_Integer  theArgNb,
3725             const char**      theArgVec)
3726 {
3727   const Handle(AIS_InteractiveContext)& aCtx  = ViewerTest::GetAISContext();
3728   const Handle(V3d_View)&               aView = ViewerTest::CurrentView();
3729   ViewerTest_AutoUpdater anUpdateTool (aCtx, aView);
3730   if (aCtx.IsNull())
3731   {
3732     Message::SendFail ("Error: no active view!");
3733     return 1;
3734   }
3735
3736   const Standard_Boolean toEraseAll = TCollection_AsciiString (theArgNb > 0 ? theArgVec[0] : "") == "veraseall";
3737
3738   Standard_Integer anArgIter = 1;
3739   Standard_Boolean toEraseInView = Standard_False;
3740   Standard_Boolean toFailOnError = Standard_True;
3741   TColStd_SequenceOfAsciiString aNamesOfEraseIO;
3742   for (; anArgIter < theArgNb; ++anArgIter)
3743   {
3744     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
3745     anArgCase.LowerCase();
3746     if (anUpdateTool.parseRedrawMode (anArgCase))
3747     {
3748       continue;
3749     }
3750     else if (anArgCase == "-view"
3751           || anArgCase == "-inview")
3752     {
3753       toEraseInView = Standard_True;
3754     }
3755     else if (anArgCase == "-noerror"
3756           || anArgCase == "-nofail")
3757     {
3758       toFailOnError = Standard_False;
3759     }
3760     else
3761     {
3762       aNamesOfEraseIO.Append (theArgVec[anArgIter]);
3763     }
3764   }
3765
3766   if (!aNamesOfEraseIO.IsEmpty() && toEraseAll)
3767   {
3768     Message::SendFail() << "Error: wrong syntax, " << theArgVec[0] << " too much arguments.";
3769     return 1;
3770   }
3771
3772   if (!aNamesOfEraseIO.IsEmpty())
3773   {
3774     // Erase named objects
3775     NCollection_IndexedDataMap<Handle(AIS_InteractiveObject), TCollection_AsciiString> aPrsList;
3776     for (TColStd_SequenceOfAsciiString::Iterator anIter (aNamesOfEraseIO); anIter.More(); anIter.Next())
3777     {
3778       const TCollection_AsciiString& aName = anIter.Value();
3779       if (aName.Search ("*") != -1)
3780       {
3781         for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aPrsIter (GetMapOfAIS()); aPrsIter.More(); aPrsIter.Next())
3782         {
3783           const TCollection_AsciiString aCheck = TCollection_AsciiString ("string match '") + aName + "' '" + aPrsIter.Key2() + "'";
3784           if (theDI.Eval (aCheck.ToCString()) == 0
3785           && *theDI.Result() == '1')
3786           {
3787             aPrsList.Add (aPrsIter.Key1(), aPrsIter.Key2());
3788           }
3789         }
3790         theDI.Reset();
3791       }
3792       else
3793       {
3794         Handle(AIS_InteractiveObject) anIO;
3795         if (!GetMapOfAIS().Find2 (aName, anIO))
3796         {
3797           if (toFailOnError)
3798           {
3799             Message::SendFail() << "Syntax error: '" << aName << "' is not found";
3800             return 1;
3801           }
3802         }
3803         else
3804         {
3805           aPrsList.Add (anIO, aName);
3806         }
3807       }
3808     }
3809
3810     for (NCollection_IndexedDataMap<Handle(AIS_InteractiveObject), TCollection_AsciiString>::Iterator anIter (aPrsList); anIter.More(); anIter.Next())
3811     {
3812       theDI << anIter.Value() << " ";
3813       if (toEraseInView)
3814       {
3815         aCtx->SetViewAffinity (anIter.Key(), aView, Standard_False);
3816       }
3817       else
3818       {
3819         aCtx->Erase (anIter.Key(), Standard_False);
3820       }
3821     }
3822   }
3823   else if (!toEraseAll && aCtx->NbSelected() > 0)
3824   {
3825     // Erase selected objects
3826     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3827          anIter.More(); anIter.Next())
3828     {
3829       const Handle(AIS_InteractiveObject) anIO = anIter.Key1();
3830       if (!anIO.IsNull()
3831        && aCtx->IsSelected (anIO))
3832       {
3833         theDI << anIter.Key2() << " ";
3834         if (toEraseInView)
3835         {
3836           aCtx->SetViewAffinity (anIO, aView, Standard_False);
3837         }
3838       }
3839     }
3840
3841     if (!toEraseInView)
3842     {
3843       aCtx->EraseSelected (Standard_False);
3844     }
3845   }
3846   else
3847   {
3848     // Erase all objects
3849     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3850          anIter.More(); anIter.Next())
3851     {
3852       Handle(AIS_InteractiveObject) anIO = anIter.Key1();
3853       if (!anIO.IsNull())
3854       {
3855         if (toEraseInView)
3856         {
3857           aCtx->SetViewAffinity (anIO, aView, Standard_False);
3858         }
3859         else
3860         {
3861           aCtx->Erase (anIO, Standard_False);
3862         }
3863       }
3864     }
3865   }
3866
3867   return 0;
3868 }
3869
3870 //==============================================================================
3871 //function : VDisplayAll
3872 //purpose  : Display all the objects of the Map
3873 //==============================================================================
3874 static int VDisplayAll (Draw_Interpretor& ,
3875                         Standard_Integer  theArgNb,
3876                         const char**      theArgVec)
3877
3878 {
3879   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
3880   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3881   if (aCtx.IsNull())
3882   {
3883     Message::SendFail ("Error: no active view!");
3884     return 1;
3885   }
3886
3887   Standard_Integer anArgIter = 1;
3888   for (; anArgIter < theArgNb; ++anArgIter)
3889   {
3890     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
3891     anArgCase.LowerCase();
3892     if (anUpdateTool.parseRedrawMode (anArgCase))
3893     {
3894       continue;
3895     }
3896     else
3897     {
3898       break;
3899     }
3900   }
3901   if (anArgIter < theArgNb)
3902   {
3903     Message::SendFail() << theArgVec[0] << "Error: wrong syntax";
3904     return 1;
3905   }
3906
3907   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3908        anIter.More(); anIter.Next())
3909   {
3910     aCtx->Erase (anIter.Key1(), Standard_False);
3911   }
3912
3913   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
3914        anIter.More(); anIter.Next())
3915   {
3916     aCtx->Display (anIter.Key1(), Standard_False);
3917   }
3918   return 0;
3919 }
3920
3921 //! Auxiliary method to check if presentation exists
3922 inline Standard_Integer checkMode (const Handle(AIS_InteractiveContext)& theCtx,
3923                                    const Handle(AIS_InteractiveObject)&  theIO,
3924                                    const Standard_Integer                theMode)
3925 {
3926   if (theIO.IsNull() || theCtx.IsNull())
3927   {
3928     return -1;
3929   }
3930
3931   if (theMode != -1)
3932   {
3933     if (theCtx->MainPrsMgr()->HasPresentation (theIO, theMode))
3934     {
3935       return theMode;
3936     }
3937   }
3938   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theIO->DisplayMode()))
3939   {
3940     return theIO->DisplayMode();
3941   }
3942   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theCtx->DisplayMode()))
3943   {
3944     return theCtx->DisplayMode();
3945   }
3946
3947   return -1;
3948 }
3949
3950 enum ViewerTest_BndAction
3951 {
3952   BndAction_Hide,
3953   BndAction_Show,
3954   BndAction_Print
3955 };
3956
3957 //! Auxiliary method to print bounding box of presentation
3958 inline void bndPresentation (Draw_Interpretor&                         theDI,
3959                              const Handle(PrsMgr_PresentationManager)& theMgr,
3960                              const Handle(AIS_InteractiveObject)&      theObj,
3961                              const Standard_Integer                    theDispMode,
3962                              const TCollection_AsciiString&            theName,
3963                              const ViewerTest_BndAction                theAction,
3964                              const Handle(Prs3d_Drawer)&               theStyle)
3965 {
3966   switch (theAction)
3967   {
3968     case BndAction_Hide:
3969     {
3970       theMgr->Unhighlight (theObj);
3971       break;
3972     }
3973     case BndAction_Show:
3974     {
3975       theMgr->Color (theObj, theStyle, theDispMode);
3976       break;
3977     }
3978     case BndAction_Print:
3979     {
3980       Bnd_Box aBox;
3981       for (PrsMgr_Presentations::Iterator aPrsIter (theObj->Presentations()); aPrsIter.More(); aPrsIter.Next())
3982       {
3983         if (aPrsIter.Value()->Mode() != theDispMode)
3984           continue;
3985
3986         aBox = aPrsIter.Value()->MinMaxValues();
3987       }
3988       gp_Pnt aMin = aBox.CornerMin();
3989       gp_Pnt aMax = aBox.CornerMax();
3990       theDI << theName  << "\n"
3991             << aMin.X() << " " << aMin.Y() << " " << aMin.Z() << " "
3992             << aMax.X() << " " << aMax.Y() << " " << aMax.Z() << "\n";
3993       break;
3994     }
3995   }
3996 }
3997
3998 //==============================================================================
3999 //function : VBounding
4000 //purpose  :
4001 //==============================================================================
4002 int VBounding (Draw_Interpretor& theDI,
4003                Standard_Integer  theArgNb,
4004                const char**      theArgVec)
4005 {
4006   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
4007   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4008   if (aCtx.IsNull())
4009   {
4010     Message::SendFail ("Error: no active view!");
4011     return 1;
4012   }
4013
4014   ViewerTest_BndAction anAction = BndAction_Show;
4015   Standard_Integer     aMode    = -1;
4016
4017   Handle(Prs3d_Drawer) aStyle;
4018
4019   Standard_Integer anArgIter = 1;
4020   for (; anArgIter < theArgNb; ++anArgIter)
4021   {
4022     TCollection_AsciiString anArg (theArgVec[anArgIter]);
4023     anArg.LowerCase();
4024     if (anArg == "-print")
4025     {
4026       anAction = BndAction_Print;
4027     }
4028     else if (anArg == "-show")
4029     {
4030       anAction = BndAction_Show;
4031     }
4032     else if (anArg == "-hide")
4033     {
4034       anAction = BndAction_Hide;
4035     }
4036     else if (anArg == "-mode")
4037     {
4038       if (++anArgIter >= theArgNb)
4039       {
4040         Message::SendFail() << "Error: wrong syntax at " << anArg;
4041         return 1;
4042       }
4043       aMode = Draw::Atoi (theArgVec[anArgIter]);
4044     }
4045     else if (!anUpdateTool.parseRedrawMode (anArg))
4046     {
4047       break;
4048     }
4049   }
4050
4051   if (anAction == BndAction_Show)
4052   {
4053     aStyle = new Prs3d_Drawer();
4054     aStyle->SetMethod (Aspect_TOHM_BOUNDBOX);
4055     aStyle->SetColor  (Quantity_NOC_GRAY99);
4056   }
4057
4058   Standard_Integer aHighlightedMode = -1;
4059   if (anArgIter < theArgNb)
4060   {
4061     // has a list of names
4062     for (; anArgIter < theArgNb; ++anArgIter)
4063     {
4064       TCollection_AsciiString aName = theArgVec[anArgIter];
4065       Handle(AIS_InteractiveObject) anIO;
4066       if (!GetMapOfAIS().Find2 (aName, anIO))
4067       {
4068         Message::SendFail() << "Error: presentation " << aName << " does not exist";
4069         return 1;
4070       }
4071
4072       aHighlightedMode = checkMode (aCtx, anIO, aMode);
4073       if (aHighlightedMode == -1)
4074       {
4075         Message::SendFail() << "Error: object " << aName << " has no presentation with mode " << aMode;
4076         return 1;
4077       }
4078       bndPresentation (theDI, aCtx->MainPrsMgr(), anIO, aHighlightedMode, aName, anAction, aStyle);
4079     }
4080   }
4081   else if (aCtx->NbSelected() > 0)
4082   {
4083     // remove all currently selected objects
4084     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
4085     {
4086       Handle(AIS_InteractiveObject) anIO = aCtx->SelectedInteractive();
4087       aHighlightedMode = checkMode (aCtx, anIO, aMode);
4088       if (aHighlightedMode != -1)
4089       {
4090         bndPresentation (theDI, aCtx->MainPrsMgr(), anIO, aHighlightedMode,
4091           GetMapOfAIS().IsBound1 (anIO) ? GetMapOfAIS().Find1 (anIO) : "", anAction, aStyle);
4092       }
4093     }
4094   }
4095   else
4096   {
4097     // all objects
4098     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
4099          anIter.More(); anIter.Next())
4100     {
4101       Handle(AIS_InteractiveObject) anIO = anIter.Key1();
4102       aHighlightedMode = checkMode (aCtx, anIO, aMode);
4103       if (aHighlightedMode != -1)
4104       {
4105         bndPresentation (theDI, aCtx->MainPrsMgr(), anIO, aHighlightedMode, anIter.Key2(), anAction, aStyle);
4106       }
4107     }
4108   }
4109   return 0;
4110 }
4111
4112 //==============================================================================
4113 //function : VTexture
4114 //purpose  :
4115 //==============================================================================
4116 Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
4117 {
4118   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
4119   if (aCtx.IsNull())
4120   {
4121     Message::SendFail() << "Error: no active view!";
4122     return 1;
4123   }
4124
4125   int toModulate = -1, toSetSRgb = -1;
4126   bool toSetFilter = false, toSetAniso = false, toSetTrsfAngle = false, toSetTrsfTrans = false, toSetTrsfScale = false;
4127   Standard_ShortReal aTrsfRotAngle = 0.0f;
4128   Graphic3d_Vec2 aTrsfTrans (0.0f, 0.0f);
4129   Graphic3d_Vec2 aTrsfScale (1.0f, 1.0f);
4130   Graphic3d_TypeOfTextureFilter      aFilter       = Graphic3d_TOTF_NEAREST;
4131   Graphic3d_LevelOfTextureAnisotropy anAnisoFilter = Graphic3d_LOTA_OFF;
4132
4133   Handle(AIS_InteractiveObject) aTexturedIO;
4134   Handle(AIS_Shape) aTexturedShape;
4135   Handle(Graphic3d_TextureSet) aTextureSetOld;
4136   NCollection_Vector<Handle(Graphic3d_TextureMap)> aTextureVecNew;
4137   bool toSetGenRepeat = false, toSetGenScale = false, toSetGenOrigin = false, toSetImage = false, toComputeUV = false;
4138
4139   const TCollection_AsciiString aCommandName (theArgVec[0]);
4140   bool toSetDefaults = aCommandName == "vtexdefault";
4141
4142   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4143   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
4144   {
4145     const TCollection_AsciiString aName     = theArgVec[anArgIter];
4146     TCollection_AsciiString       aNameCase = aName;
4147     aNameCase.LowerCase();
4148     if (anUpdateTool.parseRedrawMode (aName))
4149     {
4150       continue;
4151     }
4152     else if (aTexturedIO.IsNull())
4153     {
4154       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfIO = GetMapOfAIS();
4155       if (aMapOfIO.IsBound2 (aName))
4156       {
4157         aTexturedIO = aMapOfIO.Find2 (aName);
4158         aTexturedShape = Handle(AIS_Shape)::DownCast (aTexturedIO);
4159       }
4160       if (aTexturedIO.IsNull())
4161       {
4162         Message::SendFail() << "Syntax error: shape " << aName << " does not exists in the viewer.";
4163         return 1;
4164       }
4165
4166       if (aTexturedIO->Attributes()->HasOwnShadingAspect())
4167       {
4168         aTextureSetOld = aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureSet();
4169       }
4170     }
4171     else if (!aTexturedShape.IsNull()
4172           && (aNameCase == "-scale"
4173            || aNameCase == "-setscale"
4174            || aCommandName == "vtexscale"))
4175     {
4176       if (aCommandName != "vtexscale")
4177       {
4178         ++anArgIter;
4179       }
4180       if (anArgIter < theArgsNb)
4181       {
4182         TCollection_AsciiString aValU (theArgVec[anArgIter]);
4183         TCollection_AsciiString aValUCase = aValU;
4184         aValUCase.LowerCase();
4185         toSetGenScale = true;
4186         if (aValUCase == "off")
4187         {
4188           aTexturedShape->SetTextureScaleUV (gp_Pnt2d (1.0, 1.0));
4189           continue;
4190         }
4191         else if (anArgIter + 1 < theArgsNb)
4192         {
4193           TCollection_AsciiString aValV (theArgVec[anArgIter + 1]);
4194           if (aValU.IsRealValue (Standard_True)
4195            && aValV.IsRealValue (Standard_True))
4196           {
4197             aTexturedShape->SetTextureScaleUV (gp_Pnt2d (aValU.RealValue(), aValV.RealValue()));
4198             ++anArgIter;
4199             continue;
4200           }
4201         }
4202       }
4203       Message::SendFail() << "Syntax error: unexpected argument '" << aName << "'";
4204       return 1;
4205     }
4206     else if (!aTexturedShape.IsNull()
4207           && (aNameCase == "-origin"
4208            || aNameCase == "-setorigin"
4209            || aCommandName == "vtexorigin"))
4210     {
4211       if (aCommandName != "vtexorigin")
4212       {
4213         ++anArgIter;
4214       }
4215       if (anArgIter < theArgsNb)
4216       {
4217         TCollection_AsciiString aValU (theArgVec[anArgIter]);
4218         TCollection_AsciiString aValUCase = aValU;
4219         aValUCase.LowerCase();
4220         toSetGenOrigin = true;
4221         if (aValUCase == "off")
4222         {
4223           aTexturedShape->SetTextureOriginUV (gp_Pnt2d (0.0, 0.0));
4224           continue;
4225         }
4226         else if (anArgIter + 1 < theArgsNb)
4227         {
4228           TCollection_AsciiString aValV (theArgVec[anArgIter + 1]);
4229           if (aValU.IsRealValue (Standard_True)
4230            && aValV.IsRealValue (Standard_True))
4231           {
4232             aTexturedShape->SetTextureOriginUV (gp_Pnt2d (aValU.RealValue(), aValV.RealValue()));
4233             ++anArgIter;
4234             continue;
4235           }
4236         }
4237       }
4238       Message::SendFail() << "Syntax error: unexpected argument '" << aName << "'";
4239       return 1;
4240     }
4241     else if (!aTexturedShape.IsNull()
4242           && (aNameCase == "-repeat"
4243            || aNameCase == "-setrepeat"
4244            || aCommandName == "vtexrepeat"))
4245     {
4246       if (aCommandName != "vtexrepeat")
4247       {
4248         ++anArgIter;
4249       }
4250       if (anArgIter < theArgsNb)
4251       {
4252         TCollection_AsciiString aValU (theArgVec[anArgIter]);
4253         TCollection_AsciiString aValUCase = aValU;
4254         aValUCase.LowerCase();
4255         toSetGenRepeat = true;
4256         if (aValUCase == "off")
4257         {
4258           aTexturedShape->SetTextureRepeatUV (gp_Pnt2d (1.0, 1.0));
4259           continue;
4260         }
4261         else if (anArgIter + 1 < theArgsNb)
4262         {
4263           TCollection_AsciiString aValV (theArgVec[anArgIter + 1]);
4264           if (aValU.IsRealValue (Standard_True)
4265            && aValV.IsRealValue (Standard_True))
4266           {
4267             aTexturedShape->SetTextureRepeatUV (gp_Pnt2d (aValU.RealValue(), aValV.RealValue()));
4268             ++anArgIter;
4269             continue;
4270           }
4271         }
4272       }
4273       Message::SendFail() << "Syntax error: unexpected argument '" << aName << "'";
4274       return 1;
4275     }
4276     else if (aNameCase == "-modulate"
4277           || aNameCase == "-nomodulate")
4278     {
4279       toModulate = Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0;
4280     }
4281     else if (aNameCase == "-srgb"
4282           || aNameCase == "-nosrgb")
4283     {
4284       toSetSRgb = Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0;
4285     }
4286     else if ((aNameCase == "-setfilter"
4287            || aNameCase == "-filter")
4288            && anArgIter + 1 < theArgsNb)
4289     {
4290       TCollection_AsciiString aValue (theArgVec[anArgIter + 1]);
4291       aValue.LowerCase();
4292       ++anArgIter;
4293       toSetFilter = true;
4294       if (aValue == "nearest")
4295       {
4296         aFilter = Graphic3d_TOTF_NEAREST;
4297       }
4298       else if (aValue == "bilinear")
4299       {
4300         aFilter = Graphic3d_TOTF_BILINEAR;
4301       }
4302       else if (aValue == "trilinear")
4303       {
4304         aFilter = Graphic3d_TOTF_TRILINEAR;
4305       }
4306       else
4307       {
4308         Message::SendFail() << "Syntax error: unexpected argument '" << aValue << "'";
4309         return 1;
4310       }
4311     }
4312     else if ((aNameCase == "-setaniso"
4313            || aNameCase == "-setanisofilter"
4314            || aNameCase == "-aniso"
4315            || aNameCase == "-anisofilter")
4316            && anArgIter + 1 < theArgsNb)
4317     {
4318       TCollection_AsciiString aValue (theArgVec[anArgIter + 1]);
4319       aValue.LowerCase();
4320       ++anArgIter;
4321       toSetAniso = true;
4322       if (aValue == "off")
4323       {
4324         anAnisoFilter = Graphic3d_LOTA_OFF;
4325       }
4326       else if (aValue == "fast")
4327       {
4328         anAnisoFilter = Graphic3d_LOTA_FAST;
4329       }
4330       else if (aValue == "middle")
4331       {
4332         anAnisoFilter = Graphic3d_LOTA_MIDDLE;
4333       }
4334       else if (aValue == "quality"
4335             || aValue == "high")
4336       {
4337         anAnisoFilter =  Graphic3d_LOTA_QUALITY;
4338       }
4339       else
4340       {
4341         Message::SendFail() << "Syntax error: unexpected argument '" << aValue << "'";
4342         return 1;
4343       }
4344     }
4345     else if ((aNameCase == "-rotateangle"
4346            || aNameCase == "-rotangle"
4347            || aNameCase == "-rotate"
4348            || aNameCase == "-angle"
4349            || aNameCase == "-trsfangle")
4350            && anArgIter + 1 < theArgsNb)
4351     {
4352       aTrsfRotAngle  = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 1]));
4353       toSetTrsfAngle = true;
4354       ++anArgIter;
4355     }
4356     else if ((aNameCase == "-trsftrans"
4357            || aNameCase == "-trsftranslate"
4358            || aNameCase == "-translate"
4359            || aNameCase == "-translation")
4360            && anArgIter + 2 < theArgsNb)
4361     {
4362       aTrsfTrans.x() = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 1]));
4363       aTrsfTrans.y() = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 2]));
4364       toSetTrsfTrans = true;
4365       anArgIter += 2;
4366     }
4367     else if ((aNameCase == "-trsfscale")
4368            && anArgIter + 2 < theArgsNb)
4369     {
4370       aTrsfScale.x() = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 1]));
4371       aTrsfScale.y() = Standard_ShortReal (Draw::Atof (theArgVec[anArgIter + 2]));
4372       toSetTrsfScale = true;
4373       anArgIter += 2;
4374     }
4375     else if (aNameCase == "-default"
4376           || aNameCase == "-defaults")
4377     {
4378       toSetDefaults = true;
4379     }
4380     else if ((aNameCase == "-video")
4381            && anArgIter + 1 < theArgsNb)
4382     {
4383       const TCollection_AsciiString anInput (theArgVec[++anArgIter]);
4384       Handle(Graphic3d_MediaTextureSet) aMedia = Handle(Graphic3d_MediaTextureSet)::DownCast (aTextureSetOld);
4385       if (aMedia.IsNull())
4386       {
4387         aMedia = new Graphic3d_MediaTextureSet();
4388       }
4389       if (aMedia->Input() != anInput)
4390       {
4391         aMedia->OpenInput (anInput, false);
4392       }
4393       else
4394       {
4395         if (aMedia->SwapFrames()
4396         && !aCtx->CurrentViewer()->ZLayerSettings (aTexturedIO->ZLayer()).IsImmediate())
4397         {
4398           ViewerTest::CurrentView()->Invalidate();
4399         }
4400       }
4401       if (aTexturedIO->Attributes()->SetupOwnShadingAspect (aCtx->DefaultDrawer())
4402        && aTexturedShape.IsNull())
4403       {
4404         aTexturedIO->SetToUpdate();
4405       }
4406
4407       toComputeUV = aTextureSetOld.IsNull();
4408       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOn (true);
4409       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureSet (aMedia);
4410       aTextureSetOld.Nullify();
4411     }
4412     else if (aCommandName == "vtexture"
4413           && aTextureVecNew.IsEmpty()
4414           && aNameCase == "-3d")
4415     {
4416       TColStd_SequenceOfAsciiString aSlicesSeq;
4417       for (; anArgIter + 1 < theArgsNb; ++anArgIter)
4418       {
4419         TCollection_AsciiString aSlicePath (theArgVec[anArgIter + 1]);
4420         if (aSlicePath.StartsWith ("-"))
4421         {
4422           break;
4423         }
4424
4425         aSlicesSeq.Append (aSlicePath);
4426       }
4427
4428       if (aSlicesSeq.Size() < 2)
4429       {
4430         Message::SendFail() << "Syntax error at '" << aNameCase << "'";
4431         return 1;
4432       }
4433       NCollection_Array1<TCollection_AsciiString> aSlices;
4434       aSlices.Resize (0, aSlicesSeq.Size() - 1, false);
4435       Standard_Integer aSliceIndex = 0;
4436       for (const TCollection_AsciiString& aSliceIter : aSlicesSeq)
4437       {
4438         aSlices[aSliceIndex++] = aSliceIter;
4439       }
4440
4441       toSetImage = true;
4442       aTextureVecNew.SetValue (0, new Graphic3d_Texture3D (aSlices));
4443     }
4444     else if (aCommandName == "vtexture"
4445           && (aTextureVecNew.IsEmpty()
4446            || aNameCase.StartsWith ("-tex")))
4447     {
4448       Standard_Integer aTexIndex = 0;
4449       TCollection_AsciiString aTexName = aName;
4450       if (aNameCase.StartsWith ("-tex"))
4451       {
4452         if (anArgIter + 1 >= theArgsNb
4453          || aNameCase.Length() < 5)
4454         {
4455           Message::SendFail() << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'";
4456           return 1;
4457         }
4458
4459         TCollection_AsciiString aTexIndexStr = aNameCase.SubString (5, aNameCase.Length());
4460         if (!aTexIndexStr.IsIntegerValue())
4461         {
4462           Message::SendFail() << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'";
4463           return 1;
4464         }
4465
4466         aTexIndex = aTexIndexStr.IntegerValue();
4467         aTexName  = theArgVec[anArgIter + 1];
4468         ++anArgIter;
4469       }
4470       if (aTexIndex >= Graphic3d_TextureUnit_NB
4471        || aTexIndex >= aCtx->CurrentViewer()->Driver()->InquireLimit (Graphic3d_TypeOfLimit_MaxCombinedTextureUnits))
4472       {
4473         Message::SendFail ("Error: too many textures specified");
4474         return 1;
4475       }
4476
4477       toSetImage = true;
4478       if (aTexName.IsIntegerValue())
4479       {
4480         const Standard_Integer aValue = aTexName.IntegerValue();
4481         if (aValue < 0 || aValue >= Graphic3d_Texture2D::NumberOfTextures())
4482         {
4483           Message::SendFail() << "Syntax error: texture with ID " << aValue << " is undefined!";
4484           return 1;
4485         }
4486         aTextureVecNew.SetValue (aTexIndex, new Graphic3d_Texture2D (Graphic3d_NameOfTexture2D (aValue)));
4487       }
4488       else if (aTexName == "?")
4489       {
4490         const TCollection_AsciiString aTextureFolder = Graphic3d_TextureRoot::TexturesFolder();
4491
4492         theDi << "\n Files in current directory : \n\n";
4493         theDi.Eval ("glob -nocomplain *");
4494
4495         TCollection_AsciiString aCmnd ("glob -nocomplain ");
4496         aCmnd += aTextureFolder;
4497         aCmnd += "/* ";
4498
4499         theDi << "Files in " << aTextureFolder << " : \n\n";
4500         theDi.Eval (aCmnd.ToCString());
4501         return 0;
4502       }
4503       else if (aTexName != "off")
4504       {
4505         if (!OSD_File (aTexName).Exists())
4506         {
4507           Message::SendFail() << "Syntax error: non-existing image file has been specified '" << aTexName << "'.";
4508           return 1;
4509         }
4510         aTextureVecNew.SetValue (aTexIndex, new Graphic3d_Texture2D (aTexName));
4511       }
4512       else
4513       {
4514         aTextureVecNew.SetValue (aTexIndex, Handle(Graphic3d_TextureMap)());
4515       }
4516
4517       if (aTextureVecNew.Value (aTexIndex))
4518       {
4519         aTextureVecNew.ChangeValue(aTexIndex)->GetParams()->SetTextureUnit((Graphic3d_TextureUnit)aTexIndex);
4520       }
4521     }
4522     else
4523     {
4524       Message::SendFail() << "Syntax error: invalid argument '" << theArgVec[anArgIter] << "'";
4525       return 1;
4526     }
4527   }
4528
4529   if (toSetImage)
4530   {
4531     // check if new image set is equal to already set one
4532     Standard_Integer aNbChanged = 0;
4533     Handle(Graphic3d_TextureSet) aTextureSetNew;
4534     if (!aTextureVecNew.IsEmpty())
4535     {
4536       aNbChanged = aTextureVecNew.Size();
4537       aTextureSetNew = new Graphic3d_TextureSet (aTextureVecNew.Size());
4538       for (Standard_Integer aTexIter = 0; aTexIter < aTextureSetNew->Size(); ++aTexIter)
4539       {
4540         Handle(Graphic3d_TextureMap)& aTextureNew = aTextureVecNew.ChangeValue (aTexIter);
4541         Handle(Graphic3d_TextureRoot) aTextureOld;
4542         if (!aTextureSetOld.IsNull()
4543           && aTexIter < aTextureSetOld->Size())
4544         {
4545           aTextureOld = aTextureSetOld->Value (aTexIter);
4546         }
4547
4548         if (!aTextureOld.IsNull()
4549          && !aTextureNew.IsNull())
4550         {
4551           *aTextureNew->GetParams() = *aTextureOld->GetParams();
4552
4553           Handle(Graphic3d_Texture2D) aTex2dNew = Handle(Graphic3d_Texture2D)::DownCast (aTextureNew);
4554           Handle(Graphic3d_Texture2D) aTex2dOld = Handle(Graphic3d_Texture2D)::DownCast (aTextureOld);
4555           if (!aTex2dOld.IsNull()
4556            && !aTex2dNew.IsNull())
4557           {
4558             TCollection_AsciiString aFilePathOld, aFilePathNew;
4559             aTextureOld->Path().SystemName (aFilePathOld);
4560             aTextureNew->Path().SystemName (aFilePathNew);
4561             if (aTex2dNew->Name() == aTex2dOld->Name()
4562              && aFilePathOld == aFilePathNew
4563              && (!aFilePathNew.IsEmpty() || aTex2dNew->Name() != Graphic3d_NOT_2D_UNKNOWN))
4564             {
4565               --aNbChanged;
4566               aTextureNew = aTex2dOld;
4567             }
4568           }
4569         }
4570         aTextureSetNew->SetValue (aTexIter, aTextureNew);
4571       }
4572     }
4573     if (aNbChanged == 0
4574      && ((aTextureSetOld.IsNull() && aTextureSetNew.IsNull())
4575       || (aTextureSetOld->Size() == aTextureSetNew->Size())))
4576     {
4577       aTextureSetNew = aTextureSetOld;
4578     }
4579
4580     if (aTexturedIO->Attributes()->SetupOwnShadingAspect (aCtx->DefaultDrawer())
4581      && aTexturedShape.IsNull())
4582     {
4583       aTexturedIO->SetToUpdate();
4584     }
4585
4586     toComputeUV = !aTextureSetNew.IsNull() && aTextureSetOld.IsNull();
4587     aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOn (!aTextureSetNew.IsNull());
4588     aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureSet (aTextureSetNew);
4589     aTextureSetOld.Nullify();
4590   }
4591
4592   if (toSetDefaults)
4593   {
4594     if (toModulate != -1)
4595     {
4596       toModulate = 1;
4597     }
4598     if (!toSetFilter)
4599     {
4600       toSetFilter = true;
4601       aFilter     = Graphic3d_TOTF_BILINEAR;
4602     }
4603     if (!toSetAniso)
4604     {
4605       toSetAniso    = true;
4606       anAnisoFilter = Graphic3d_LOTA_OFF;
4607     }
4608     if (!toSetTrsfAngle)
4609     {
4610       toSetTrsfAngle = true;
4611       aTrsfRotAngle  = 0.0f;
4612     }
4613     if (!toSetTrsfTrans)
4614     {
4615       toSetTrsfTrans = true;
4616       aTrsfTrans = Graphic3d_Vec2 (0.0f, 0.0f);
4617     }
4618     if (!toSetTrsfScale)
4619     {
4620       toSetTrsfScale = true;
4621       aTrsfScale = Graphic3d_Vec2 (1.0f, 1.0f);
4622     }
4623   }
4624
4625   if (aCommandName == "vtexture"
4626    && theArgsNb == 2)
4627   {
4628     if (!aTextureSetOld.IsNull())
4629     {
4630       //toComputeUV = true; // we can keep UV vertex attributes
4631       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureMapOff();
4632       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->SetTextureSet (Handle(Graphic3d_TextureSet)());
4633       aTextureSetOld.Nullify();
4634     }
4635   }
4636
4637   if (aTexturedIO->Attributes()->HasOwnShadingAspect()
4638   && !aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap().IsNull())
4639   {
4640     if (toModulate != -1)
4641     {
4642       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetModulate (toModulate == 1);
4643     }
4644     if (toSetSRgb != -1)
4645     {
4646       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->SetColorMap (toSetSRgb == 1);
4647     }
4648     if (toSetTrsfAngle)
4649     {
4650       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetRotation (aTrsfRotAngle); // takes degrees
4651     }
4652     if (toSetTrsfTrans)
4653     {
4654       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetTranslation (aTrsfTrans);
4655     }
4656     if (toSetTrsfScale)
4657     {
4658       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetScale (aTrsfScale);
4659     }
4660     if (toSetFilter)
4661     {
4662       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetFilter (aFilter);
4663     }
4664     if (toSetAniso)
4665     {
4666       aTexturedIO->Attributes()->ShadingAspect()->Aspect()->TextureMap()->GetParams()->SetAnisoFilter (anAnisoFilter);
4667     }
4668   }
4669
4670   // set default values if requested
4671   if (!toSetGenRepeat
4672    && (aCommandName == "vtexrepeat"
4673     || toSetDefaults))
4674   {
4675     if (!aTexturedShape.IsNull())
4676     {
4677       aTexturedShape->SetTextureRepeatUV (gp_Pnt2d (1.0, 1.0));
4678     }
4679     toSetGenRepeat = true;
4680   }
4681   if (!toSetGenOrigin
4682    && (aCommandName == "vtexorigin"
4683     || toSetDefaults))
4684   {
4685     if (!aTexturedShape.IsNull())
4686     {
4687       aTexturedShape->SetTextureOriginUV (gp_Pnt2d (0.0, 0.0));
4688     }
4689     toSetGenOrigin = true;
4690   }
4691   if (!toSetGenScale
4692    && (aCommandName == "vtexscale"
4693     || toSetDefaults))
4694   {
4695     if (!aTexturedShape.IsNull())
4696     {
4697       aTexturedShape->SetTextureScaleUV  (gp_Pnt2d (1.0, 1.0));
4698     }
4699     toSetGenScale = true;
4700   }
4701
4702   if (toSetGenRepeat || toSetGenOrigin || toSetGenScale || toComputeUV)
4703   {
4704     if (!aTexturedShape.IsNull())
4705     {
4706       aTexturedShape->SetToUpdate (AIS_Shaded);
4707       if (toSetImage)
4708       {
4709         if ((aTexturedIO->HasDisplayMode() && aTexturedIO->DisplayMode() != AIS_Shaded)
4710          || aCtx->DisplayMode() != AIS_Shaded)
4711         {
4712           aCtx->SetDisplayMode (aTexturedIO, AIS_Shaded, false);
4713         }
4714       }
4715     }
4716   }
4717   aCtx->Display (aTexturedIO, false);
4718   aTexturedIO->SynchronizeAspects();
4719   return 0;
4720 }
4721
4722 //! Auxiliary method to parse transformation persistence flags
4723 inline Standard_Boolean parseTrsfPersFlag (const TCollection_AsciiString& theFlagString,
4724                                            Graphic3d_TransModeFlags&      theFlags)
4725 {
4726   if (theFlagString == "zoom")
4727   {
4728     theFlags = Graphic3d_TMF_ZoomPers;
4729   }
4730   else if (theFlagString == "rotate")
4731   {
4732     theFlags = Graphic3d_TMF_RotatePers;
4733   }
4734   else if (theFlagString == "zoomrotate")
4735   {
4736     theFlags = Graphic3d_TMF_ZoomRotatePers;
4737   }
4738   else if (theFlagString == "trihedron"
4739         || theFlagString == "triedron")
4740   {
4741     theFlags = Graphic3d_TMF_TriedronPers;
4742   }
4743   else if (theFlagString == "none")
4744   {
4745     theFlags = Graphic3d_TMF_None;
4746   }
4747   else
4748   {
4749     return Standard_False;
4750   }
4751
4752   return Standard_True;
4753 }
4754
4755 // =============================================================================
4756 // function : ParseCorner
4757 // purpose  :
4758 // =============================================================================
4759 Standard_Boolean ViewerTest::ParseCorner (Standard_CString theArg,
4760                                           Aspect_TypeOfTriedronPosition& theCorner)
4761 {
4762   TCollection_AsciiString aString (theArg);
4763   aString.LowerCase();
4764   if (aString == "center")
4765   {
4766     theCorner = Aspect_TOTP_CENTER;
4767   }
4768   else if (aString == "top"
4769         || aString == "upper")
4770   {
4771     theCorner = Aspect_TOTP_TOP;
4772   }
4773   else if (aString == "bottom"
4774         || aString == "lower")
4775   {
4776     theCorner = Aspect_TOTP_BOTTOM;
4777   }
4778   else if (aString == "left")
4779   {
4780     theCorner = Aspect_TOTP_LEFT;
4781   }
4782   else if (aString == "right")
4783   {
4784     theCorner = Aspect_TOTP_RIGHT;
4785   }
4786   else if (aString == "topleft"
4787         || aString == "leftupper"
4788         || aString == "upperleft"
4789         || aString == "left_upper"
4790         || aString == "upper_left")
4791   {
4792     theCorner = Aspect_TOTP_LEFT_UPPER;
4793   }
4794   else if (aString == "bottomleft"
4795         || aString == "leftlower"
4796         || aString == "lowerleft"
4797         || aString == "left_lower"
4798         || aString == "lower_left")
4799   {
4800     theCorner = Aspect_TOTP_LEFT_LOWER;
4801   }
4802   else if (aString == "topright"
4803         || aString == "rightupper"
4804         || aString == "upperright"
4805         || aString == "right_upper"
4806         || aString == "upper_right")
4807   {
4808     theCorner = Aspect_TOTP_RIGHT_UPPER;
4809   }
4810   else if (aString == "bottomright"
4811         || aString == "lowerright"
4812         || aString == "rightlower"
4813         || aString == "right_lower"
4814         || aString == "lower_right")
4815   {
4816     theCorner = Aspect_TOTP_RIGHT_LOWER;
4817   }
4818   else
4819   {
4820     return Standard_False;
4821   }
4822
4823   return Standard_True;
4824 }
4825
4826 //==============================================================================
4827 //function : VDisplay2
4828 //author   : ege
4829 //purpose  : Display an object from its name
4830 //==============================================================================
4831 static int VDisplay2 (Draw_Interpretor& theDI,
4832                       Standard_Integer  theArgNb,
4833                       const char**      theArgVec)
4834 {
4835   if (theArgNb < 2)
4836   {
4837     Message::SendFail ("Syntax error: wrong number of arguments.");
4838     return 1;
4839   }
4840   if (theArgNb == 2
4841    && TCollection_AsciiString (theArgVec[1]) == "*")
4842   {
4843     // alias
4844     return VDisplayAll (theDI, 1, theArgVec);
4845   }
4846
4847   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
4848   if (aCtx.IsNull())
4849   {
4850     ViewerTest::ViewerInit();
4851     aCtx = ViewerTest::GetAISContext();
4852   }
4853
4854   // Parse input arguments
4855   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
4856   Standard_Integer   isMutable      = -1;
4857   Graphic3d_ZLayerId aZLayer        = Graphic3d_ZLayerId_UNKNOWN;
4858   Standard_Boolean   toReDisplay    = Standard_False;
4859   Standard_Integer   isSelectable   = -1;
4860   Standard_Integer   anObjDispMode  = -2;
4861   Standard_Integer   anObjHighMode  = -2;
4862   Standard_Boolean   toSetTrsfPers  = Standard_False;
4863   Standard_Boolean   toEcho         = Standard_True;
4864   Standard_Integer   isAutoTriang   = -1;
4865   Handle(Graphic3d_TransformPers) aTrsfPers;
4866   TColStd_SequenceOfAsciiString aNamesOfDisplayIO;
4867   AIS_DisplayStatus aDispStatus = AIS_DS_None;
4868   Standard_Integer toDisplayInView = Standard_False;
4869   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4870   {
4871     const TCollection_AsciiString aName     = theArgVec[anArgIter];
4872     TCollection_AsciiString       aNameCase = aName;
4873     aNameCase.LowerCase();
4874     if (anUpdateTool.parseRedrawMode (aName))
4875     {
4876       continue;
4877     }
4878     else if (aNameCase == "-mutable")
4879     {
4880       isMutable = 1;
4881     }
4882     else if (aNameCase == "-neutral")
4883     {
4884       aDispStatus = AIS_DS_Displayed;
4885     }
4886     else if (aNameCase == "-immediate"
4887           || aNameCase == "-top")
4888     {
4889       aZLayer = Graphic3d_ZLayerId_Top;
4890     }
4891     else if (aNameCase == "-topmost")
4892     {
4893       aZLayer = Graphic3d_ZLayerId_Topmost;
4894     }
4895     else if (aNameCase == "-osd"
4896           || aNameCase == "-toposd"
4897           || aNameCase == "-overlay")
4898     {
4899       aZLayer = Graphic3d_ZLayerId_TopOSD;
4900     }
4901     else if (aNameCase == "-botosd"
4902           || aNameCase == "-underlay")
4903     {
4904       aZLayer = Graphic3d_ZLayerId_BotOSD;
4905     }
4906     else if (aNameCase == "-select"
4907           || aNameCase == "-selectable")
4908     {
4909       isSelectable = 1;
4910     }
4911     else if (aNameCase == "-noselect"
4912           || aNameCase == "-noselection")
4913     {
4914       isSelectable = 0;
4915     }
4916     else if (aNameCase == "-dispmode"
4917           || aNameCase == "-displaymode")
4918     {
4919       if (++anArgIter >= theArgNb)
4920       {
4921         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
4922         return 1;
4923       }
4924
4925       anObjDispMode = Draw::Atoi (theArgVec [anArgIter]);
4926     }
4927     else if (aNameCase == "-himode"
4928           || aNameCase == "-highmode"
4929           || aNameCase == "-highlightmode")
4930     {
4931       if (++anArgIter >= theArgNb)
4932       {
4933         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
4934         return 1;
4935       }
4936
4937       anObjHighMode = Draw::Atoi (theArgVec [anArgIter]);
4938     }
4939     else if (aNameCase == "-3d")
4940     {
4941       toSetTrsfPers  = Standard_True;
4942       aTrsfPers.Nullify();
4943     }
4944     else if (aNameCase == "-2d"
4945           || aNameCase == "-trihedron"
4946           || aNameCase == "-triedron")
4947     {
4948       toSetTrsfPers  = Standard_True;
4949       aTrsfPers = new Graphic3d_TransformPers (aNameCase == "-2d" ? Graphic3d_TMF_2d : Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER);
4950
4951       if (anArgIter + 1 < theArgNb)
4952       {
4953         Aspect_TypeOfTriedronPosition aCorner = Aspect_TOTP_CENTER;
4954         if (ViewerTest::ParseCorner (theArgVec[anArgIter + 1], aCorner))
4955         {
4956           ++anArgIter;
4957           aTrsfPers->SetCorner2d (aCorner);
4958
4959           if (anArgIter + 2 < theArgNb)
4960           {
4961             TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
4962             TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
4963             if (anX.IsIntegerValue()
4964              && anY.IsIntegerValue())
4965             {
4966               anArgIter += 2;
4967               aTrsfPers->SetOffset2d (Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue()));
4968             }
4969           }
4970         }
4971       }
4972     }
4973     else if (aNameCase == "-trsfpers"
4974           || aNameCase == "-pers")
4975     {
4976       if (++anArgIter >= theArgNb
4977        || !aTrsfPers.IsNull())
4978       {
4979         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
4980         return 1;
4981       }
4982
4983       toSetTrsfPers  = Standard_True;
4984       Graphic3d_TransModeFlags aTrsfPersFlags = Graphic3d_TMF_None;
4985       TCollection_AsciiString aPersFlags (theArgVec [anArgIter]);
4986       aPersFlags.LowerCase();
4987       if (!parseTrsfPersFlag (aPersFlags, aTrsfPersFlags))
4988       {
4989         Message::SendFail() << "Error: wrong transform persistence flags " << theArgVec [anArgIter] << ".";
4990         return 1;
4991       }
4992
4993       if (aTrsfPersFlags == Graphic3d_TMF_TriedronPers)
4994       {
4995         aTrsfPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers, Aspect_TOTP_LEFT_LOWER);
4996       }
4997       else if (aTrsfPersFlags != Graphic3d_TMF_None)
4998       {
4999         aTrsfPers = new Graphic3d_TransformPers (aTrsfPersFlags, gp_Pnt());
5000       }
5001     }
5002     else if (aNameCase == "-trsfperspos"
5003           || aNameCase == "-perspos")
5004     {
5005       if (anArgIter + 2 >= theArgNb
5006        || aTrsfPers.IsNull())
5007       {
5008         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5009         return 1;
5010       }
5011
5012       TCollection_AsciiString aX (theArgVec[++anArgIter]);
5013       TCollection_AsciiString aY (theArgVec[++anArgIter]);
5014       TCollection_AsciiString aZ = "0";
5015       if (!aX.IsRealValue (Standard_True)
5016        || !aY.IsRealValue (Standard_True))
5017       {
5018         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5019         return 1;
5020       }
5021       if (anArgIter + 1 < theArgNb)
5022       {
5023         TCollection_AsciiString aTemp = theArgVec[anArgIter + 1];
5024         if (aTemp.IsRealValue (Standard_True))
5025         {
5026           aZ = aTemp;
5027           ++anArgIter;
5028         }
5029       }
5030
5031       if (aTrsfPers->IsZoomOrRotate())
5032       {
5033         aTrsfPers->SetAnchorPoint (gp_Pnt (aX.RealValue(), aY.RealValue(), aZ.RealValue()));
5034       }
5035       else if (aTrsfPers->IsTrihedronOr2d())
5036       {
5037         Standard_Integer aCorner = Aspect_TOTP_CENTER;
5038         if      (aX.RealValue() > 0.0) { aCorner |= Aspect_TOTP_RIGHT; }
5039         else if (aX.RealValue() < 0.0) { aCorner |= Aspect_TOTP_LEFT; }
5040         if      (aY.RealValue() > 0.0) { aCorner |= Aspect_TOTP_TOP; }
5041         else if (aY.RealValue() < 0.0) { aCorner |= Aspect_TOTP_BOTTOM; }
5042         aTrsfPers = new Graphic3d_TransformPers (aTrsfPers->Mode(), Aspect_TypeOfTriedronPosition (aCorner), Graphic3d_Vec2i (aZ.IntegerValue()));
5043       }
5044     }
5045     else if (aNameCase == "-layer"
5046           || aNameCase == "-zlayer")
5047     {
5048       ++anArgIter;
5049       if (anArgIter >= theArgNb
5050       || !ViewerTest::ParseZLayer (theArgVec[anArgIter], aZLayer)
5051       ||  aZLayer == Graphic3d_ZLayerId_UNKNOWN)
5052       {
5053         Message::SendFail() << "Error: wrong syntax at " << aName << ".";
5054         return 1;
5055       }
5056     }
5057     else if (aNameCase == "-view"
5058           || aNameCase == "-inview")
5059     {
5060       toDisplayInView = Standard_True;
5061     }
5062     else if (aNameCase == "-redisplay")
5063     {
5064       toReDisplay = Standard_True;
5065     }
5066     else if (aNameCase == "-autotr"
5067           || aNameCase == "-autotrian"
5068           || aNameCase == "-autotriang"
5069           || aNameCase == "-autotriangulation"
5070           || aNameCase == "-noautotr"
5071           || aNameCase == "-noautotrian"
5072           || aNameCase == "-noautotriang"
5073           || aNameCase == "-noautotriangulation")
5074     {
5075       isAutoTriang = Draw::ParseOnOffNoIterator (theArgNb, theArgVec, anArgIter) ? 1 : 0;
5076     }
5077     else if (aNameCase == "-erased"
5078           || aNameCase == "-load")
5079     {
5080       aDispStatus = AIS_DS_Erased;
5081     }
5082     else if (aNameCase == "-noecho")
5083     {
5084       toEcho = false;
5085     }
5086     else
5087     {
5088       aNamesOfDisplayIO.Append (aName);
5089     }
5090   }
5091
5092   if (aNamesOfDisplayIO.IsEmpty())
5093   {
5094     Message::SendFail ("Syntax error: wrong number of arguments.");
5095     return 1;
5096   }
5097
5098   // Display interactive objects
5099   for (Standard_Integer anIter = 1; anIter <= aNamesOfDisplayIO.Length(); ++anIter)
5100   {
5101     const TCollection_AsciiString& aName = aNamesOfDisplayIO.Value (anIter);
5102     Handle(AIS_InteractiveObject) aShape;
5103     if (!GetMapOfAIS().Find2 (aName, aShape))
5104     {
5105       // create the AIS_Shape from a name
5106       TopoDS_Shape aDrawShape = DBRep::GetExisting (aName);
5107       if (!aDrawShape.IsNull())
5108       {
5109         aShape = new AIS_Shape (aDrawShape);
5110         if (isMutable != -1)
5111         {
5112           aShape->SetMutable (isMutable == 1);
5113         }
5114         if (aZLayer != Graphic3d_ZLayerId_UNKNOWN)
5115         {
5116           aShape->SetZLayer (aZLayer);
5117         }
5118         if (isAutoTriang != -1)
5119         {
5120           aShape->Attributes()->SetAutoTriangulation (isAutoTriang == 1);
5121         }
5122         if (toSetTrsfPers)
5123         {
5124           aCtx->SetTransformPersistence (aShape, aTrsfPers);
5125         }
5126         if (anObjDispMode != -2)
5127         {
5128           if (anObjDispMode == -1)
5129           {
5130             aShape->UnsetDisplayMode();
5131           }
5132           if (!aShape->AcceptDisplayMode (anObjDispMode))
5133           {
5134             Message::SendFail() << "Syntax error: " << aShape->DynamicType()->Name() << " rejects " << anObjDispMode << " display mode";
5135             return 1;
5136           }
5137           else
5138           {
5139             aShape->SetDisplayMode (anObjDispMode);
5140           }
5141         }
5142         if (anObjHighMode != -2)
5143         {
5144           if (anObjHighMode != -1
5145           && !aShape->AcceptDisplayMode (anObjHighMode))
5146           {
5147             Message::SendFail() << "Syntax error: " << aShape->DynamicType()->Name() << " rejects " << anObjHighMode << " display mode";
5148             return 1;
5149           }
5150           aShape->SetHilightMode (anObjHighMode);
5151         }
5152
5153         GetMapOfAIS().Bind (aShape, aName);
5154         Standard_Integer aDispMode = aShape->HasDisplayMode()
5155                                    ? aShape->DisplayMode()
5156                                    : (aShape->AcceptDisplayMode (aCtx->DisplayMode())
5157                                     ? aCtx->DisplayMode()
5158                                     : 0);
5159         Standard_Integer aSelMode = -1;
5160         if (isSelectable ==  1 || (isSelectable == -1 && aCtx->GetAutoActivateSelection()))
5161         {
5162           aSelMode = aShape->GlobalSelectionMode();
5163         }
5164
5165         aCtx->Display (aShape, aDispMode, aSelMode, Standard_False, aDispStatus);
5166         if (toDisplayInView)
5167         {
5168           for (V3d_ListOfViewIterator aViewIter (aCtx->CurrentViewer()->DefinedViewIterator()); aViewIter.More(); aViewIter.Next())
5169           {
5170             aCtx->SetViewAffinity (aShape, aViewIter.Value(), Standard_False);
5171           }
5172           aCtx->SetViewAffinity (aShape, ViewerTest::CurrentView(), Standard_True);
5173         }
5174       }
5175       else
5176       {
5177         Message::SendFail() << "Error: object with name '" << aName << "' does not exist!";
5178       }
5179       continue;
5180     }
5181
5182     if (isMutable != -1)
5183     {
5184       aShape->SetMutable (isMutable == 1);
5185     }
5186     if (aZLayer != Graphic3d_ZLayerId_UNKNOWN)
5187     {
5188       aShape->SetZLayer (aZLayer);
5189     }
5190     if (isAutoTriang != -1)
5191     {
5192       aShape->Attributes()->SetAutoTriangulation (isAutoTriang == 1);
5193     }
5194     if (toSetTrsfPers)
5195     {
5196       aCtx->SetTransformPersistence (aShape, aTrsfPers);
5197     }
5198     if (anObjDispMode != -2)
5199     {
5200       aShape->SetDisplayMode (anObjDispMode);
5201     }
5202     if (anObjHighMode != -2)
5203     {
5204       aShape->SetHilightMode (anObjHighMode);
5205     }
5206     Standard_Integer aDispMode = aShape->HasDisplayMode()
5207                                 ? aShape->DisplayMode()
5208                                 : (aShape->AcceptDisplayMode (aCtx->DisplayMode())
5209                                 ? aCtx->DisplayMode()
5210                                 : 0);
5211     Standard_Integer aSelMode = -1;
5212     if (isSelectable ==  1 || (isSelectable == -1 && aCtx->GetAutoActivateSelection()))
5213     {
5214       aSelMode = aShape->GlobalSelectionMode();
5215     }
5216
5217     if (aShape->Type() == AIS_KindOfInteractive_Datum)
5218     {
5219       aCtx->Display (aShape, Standard_False);
5220     }
5221     else
5222     {
5223       if (toEcho)
5224       {
5225         theDI << "Display " << aName << "\n";
5226       }
5227
5228       // update the Shape in the AIS_Shape
5229       TopoDS_Shape      aNewShape = DBRep::GetExisting (aName);
5230       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(aShape);
5231       if (!aShapePrs.IsNull())
5232       {
5233         if (!aShapePrs->Shape().IsEqual (aNewShape))
5234         {
5235           toReDisplay = Standard_True;
5236         }
5237         aShapePrs->Set (aNewShape);
5238       }
5239       if (toReDisplay)
5240       {
5241         aCtx->Redisplay (aShape, Standard_False);
5242       }
5243
5244       if (aSelMode == -1)
5245       {
5246         aCtx->Erase (aShape, Standard_False);
5247       }
5248       aCtx->Display (aShape, aDispMode, aSelMode, Standard_False, aDispStatus);
5249       if (toDisplayInView)
5250       {
5251         aCtx->SetViewAffinity (aShape, ViewerTest::CurrentView(), Standard_True);
5252       }
5253     }
5254   }
5255
5256   return 0;
5257 }
5258
5259 //=======================================================================
5260 //function : VNbDisplayed
5261 //purpose  : Returns number of displayed objects
5262 //=======================================================================
5263 static Standard_Integer VNbDisplayed (Draw_Interpretor& theDi,
5264                                       Standard_Integer theArgsNb,
5265                                       const char** theArgVec)
5266 {
5267   if(theArgsNb != 1)
5268   {
5269     theDi << "Usage : " << theArgVec[0] << "\n";
5270     return 1;
5271   }
5272
5273   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5274   if (aContextAIS.IsNull())
5275   {
5276     Message::SendFail ("Syntax error: AIS context is not available.");
5277     return 1;
5278   }
5279
5280   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5281   if(aContext.IsNull())
5282   {
5283     theDi << "use 'vinit' command before " << theArgVec[0] << "\n";
5284     return 1;
5285   }
5286
5287   AIS_ListOfInteractive aListOfIO;
5288   aContextAIS->DisplayedObjects (aListOfIO);
5289
5290   theDi << aListOfIO.Extent() << "\n";
5291   return 0;
5292 }
5293
5294 //===============================================================================================
5295 //function : VUpdate
5296 //purpose  :
5297 //===============================================================================================
5298 static int VUpdate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
5299 {
5300   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5301   if (aContextAIS.IsNull())
5302   {
5303     Message::SendFail ("Syntax error: AIS context is not available.");
5304     return 1;
5305   }
5306
5307   if (theArgsNb < 2)
5308   {
5309     Message::SendFail ("Syntax error: insufficient arguments. Type help for more information.");
5310     return 1;
5311   }
5312
5313   AIS_ListOfInteractive aListOfIO;
5314   for (int anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
5315   {
5316     TCollection_AsciiString aName = TCollection_AsciiString (theArgVec[anArgIt]);
5317
5318     Handle(AIS_InteractiveObject) anAISObj;
5319     GetMapOfAIS().Find2 (aName, anAISObj);
5320     if (anAISObj.IsNull())
5321     {
5322       Message::SendFail() << theArgVec[0] << ": no AIS interactive object named \"" << aName << "\".";
5323       return 1;
5324     }
5325
5326     aListOfIO.Append (anAISObj);
5327   }
5328
5329   AIS_ListIteratorOfListOfInteractive anIOIt (aListOfIO);
5330   for (; anIOIt.More(); anIOIt.Next())
5331   {
5332     aContextAIS->Update (anIOIt.Value(), Standard_False);
5333   }
5334
5335   aContextAIS->UpdateCurrentViewer();
5336
5337   return 0;
5338 }
5339
5340 //==============================================================================
5341 //function : VShading
5342 //purpose  : Sharpen or roughten the quality of the shading
5343 //Draw arg : vshading ShapeName 0.1->0.00001  1 deg-> 30 deg
5344 //==============================================================================
5345 static int VShading(Draw_Interpretor& ,Standard_Integer argc, const char** argv)
5346 {
5347   Standard_Real    myDevCoef;
5348   Handle(AIS_InteractiveObject) TheAisIO;
5349
5350   // Verifications
5351   const Standard_Boolean HaveToSet = (strcasecmp(argv[0],"vsetshading") == 0);
5352   if (argc < 3) {
5353     myDevCoef  = 0.0008;
5354   } else {
5355     myDevCoef  =Draw::Atof(argv[2]);
5356   }
5357
5358   TCollection_AsciiString name=argv[1];
5359   GetMapOfAIS().Find2(name, TheAisIO);
5360   if (TheAisIO.IsNull())
5361   {
5362     TopoDS_Shape aDrawShape = DBRep::GetExisting (name);
5363     if (!aDrawShape.IsNull())
5364     {
5365       TheAisIO = new AIS_Shape (aDrawShape);
5366     }
5367   }
5368
5369   if (HaveToSet)
5370     TheAISContext()->SetDeviationCoefficient(TheAisIO,myDevCoef,Standard_True);
5371   else
5372     TheAISContext()->SetDeviationCoefficient(TheAisIO,0.0008,Standard_True);
5373
5374   TheAISContext()->Redisplay (TheAisIO, Standard_True);
5375   return 0;
5376 }
5377
5378 //! Auxiliary method to print Interactive Object information
5379 static void objInfo (const NCollection_Map<Handle(AIS_InteractiveObject)>& theDetected,
5380                      const Handle(AIS_InteractiveObject)&                  theObj,
5381                      Draw_Interpretor&                                     theDI)
5382 {
5383   if (theObj.IsNull())
5384   {
5385     theDI << "NULL presentation\n";
5386     return;
5387   }
5388
5389   theDI << (TheAISContext()->IsDisplayed (theObj) ? "Displayed"  : "Hidden   ")
5390         << (TheAISContext()->IsSelected  (theObj) ? " Selected" : "         ")
5391         << (theDetected.Contains (theObj)         ? " Detected" : "         ")
5392         << " Type: ";
5393   if (theObj->Type() == AIS_KindOfInteractive_Datum)
5394   {
5395     // AIS_Datum
5396     if      (theObj->Signature() == 3) { theDI << " AIS_Trihedron"; }
5397     else if (theObj->Signature() == 2) { theDI << " AIS_Axis"; }
5398     else if (theObj->Signature() == 6) { theDI << " AIS_Circle"; }
5399     else if (theObj->Signature() == 5) { theDI << " AIS_Line"; }
5400     else if (theObj->Signature() == 7) { theDI << " AIS_Plane"; }
5401     else if (theObj->Signature() == 1) { theDI << " AIS_Point"; }
5402     else if (theObj->Signature() == 4) { theDI << " AIS_PlaneTrihedron"; }
5403   }
5404   // AIS_Shape
5405   else if (theObj->Type()      == AIS_KindOfInteractive_Shape
5406         && theObj->Signature() == 0)
5407   {
5408     theDI << " AIS_Shape";
5409   }
5410   else if (theObj->Type() == AIS_KindOfInteractive_Relation)
5411   {
5412     // PrsDim_Dimension and AIS_Relation
5413     Handle(PrsDim_Relation) aRelation = Handle(PrsDim_Relation)::DownCast (theObj);
5414     switch (aRelation->KindOfDimension())
5415     {
5416       case PrsDim_KOD_PLANEANGLE:     theDI << " PrsDim_AngleDimension"; break;
5417       case PrsDim_KOD_LENGTH:         theDI << " PrsDim_Chamf2/3dDimension/PrsDim_LengthDimension"; break;
5418       case PrsDim_KOD_DIAMETER:       theDI << " PrsDim_DiameterDimension"; break;
5419       case PrsDim_KOD_ELLIPSERADIUS:  theDI << " PrsDim_EllipseRadiusDimension"; break;
5420       //case PrsDim_KOD_FILLETRADIUS:   theDI << " PrsDim_FilletRadiusDimension "; break;
5421       case PrsDim_KOD_OFFSET:         theDI << " PrsDim_OffsetDimension"; break;
5422       case PrsDim_KOD_RADIUS:         theDI << " PrsDim_RadiusDimension"; break;
5423       default:                     theDI << " UNKNOWN dimension"; break;
5424     }
5425   }
5426   else
5427   {
5428     theDI << " UserPrs";
5429   }
5430   theDI << " (" << theObj->DynamicType()->Name() << ")";
5431 }
5432
5433 //! Print information about locally selected sub-shapes
5434 template <typename T>
5435 static void printLocalSelectionInfo (const T& theContext, Draw_Interpretor& theDI)
5436 {
5437   const Standard_Boolean isGlobalCtx = (theContext->DynamicType() == STANDARD_TYPE(AIS_InteractiveContext));
5438   TCollection_AsciiString aPrevName;
5439   for (theContext->InitSelected(); theContext->MoreSelected(); theContext->NextSelected())
5440   {
5441     const Handle(AIS_Shape) aShapeIO = Handle(AIS_Shape)::DownCast (theContext->SelectedInteractive());
5442     const Handle(SelectMgr_EntityOwner) anOwner = theContext->SelectedOwner();
5443     if (aShapeIO.IsNull() || anOwner.IsNull())
5444       continue;
5445     if (isGlobalCtx)
5446     {
5447       if (anOwner == aShapeIO->GlobalSelOwner())
5448         continue;
5449     }
5450     const TopoDS_Shape      aSubShape = theContext->SelectedShape();
5451     if (aSubShape.IsNull()
5452       || aShapeIO.IsNull()
5453       || !GetMapOfAIS().IsBound1 (aShapeIO))
5454     {
5455       continue;
5456     }
5457
5458     const TCollection_AsciiString aParentName = GetMapOfAIS().Find1 (aShapeIO);
5459     TopTools_MapOfShape aFilter;
5460     Standard_Integer    aNumber = 0;
5461     const TopoDS_Shape  aShape  = aShapeIO->Shape();
5462     for (TopExp_Explorer anIter (aShape, aSubShape.ShapeType());
5463          anIter.More(); anIter.Next())
5464     {
5465       if (!aFilter.Add (anIter.Current()))
5466       {
5467         continue; // filter duplicates
5468       }
5469
5470       ++aNumber;
5471       if (!anIter.Current().IsSame (aSubShape))
5472       {
5473         continue;
5474       }
5475
5476       Standard_CString aShapeName = NULL;
5477       switch (aSubShape.ShapeType())
5478       {
5479         case TopAbs_COMPOUND:  aShapeName = " Compound"; break;
5480         case TopAbs_COMPSOLID: aShapeName = "CompSolid"; break;
5481         case TopAbs_SOLID:     aShapeName = "    Solid"; break;
5482         case TopAbs_SHELL:     aShapeName = "    Shell"; break;
5483         case TopAbs_FACE:      aShapeName = "     Face"; break;
5484         case TopAbs_WIRE:      aShapeName = "     Wire"; break;
5485         case TopAbs_EDGE:      aShapeName = "     Edge"; break;
5486         case TopAbs_VERTEX:    aShapeName = "   Vertex"; break;
5487         default:
5488         case TopAbs_SHAPE:     aShapeName = "    Shape"; break;
5489       }
5490
5491       if (aParentName != aPrevName)
5492       {
5493         theDI << "Locally selected sub-shapes within " << aParentName << ":\n";
5494         aPrevName = aParentName;
5495       }
5496       theDI << "  " << aShapeName << " #" << aNumber << "\n";
5497       break;
5498     }
5499   }
5500 }
5501
5502 //==============================================================================
5503 //function : VState
5504 //purpose  :
5505 //==============================================================================
5506 static Standard_Integer VState (Draw_Interpretor& theDI,
5507                                 Standard_Integer  theArgNb,
5508                                 Standard_CString* theArgVec)
5509 {
5510   Handle(AIS_InteractiveContext) aCtx = TheAISContext();
5511   if (aCtx.IsNull())
5512   {
5513     Message::SendFail ("Error: No opened viewer!");
5514     return 1;
5515   }
5516
5517   Standard_Boolean toPrintEntities = Standard_False;
5518   Standard_Boolean toCheckSelected = Standard_False;
5519
5520   for (Standard_Integer anArgIdx = 1; anArgIdx < theArgNb; ++anArgIdx)
5521   {
5522     TCollection_AsciiString anOption (theArgVec[anArgIdx]);
5523     anOption.LowerCase();
5524     if (anOption == "-detectedentities"
5525       || anOption == "-entities")
5526     {
5527       toPrintEntities = Standard_True;
5528     }
5529     else if (anOption == "-hasselected")
5530     {
5531       toCheckSelected = Standard_True;
5532     }
5533   }
5534
5535   if (toCheckSelected)
5536   {
5537     aCtx->InitSelected();
5538     TCollection_AsciiString hasSelected (static_cast<Standard_Integer> (aCtx->HasSelectedShape()));
5539     theDI << "Check if context has selected shape: " << hasSelected << "\n";
5540
5541     return 0;
5542   }
5543
5544   if (toPrintEntities)
5545   {
5546     theDI << "Detected entities:\n";
5547     Handle(StdSelect_ViewerSelector3d) aSelector = aCtx->MainSelector();
5548
5549     SelectMgr_SelectingVolumeManager aMgr = aSelector->GetManager();
5550     for (Standard_Integer aPickIter = 1; aPickIter <= aSelector->NbPicked(); ++aPickIter)
5551     {
5552       const SelectMgr_SortCriterion&         aPickData = aSelector->PickedData (aPickIter);
5553       const Handle(Select3D_SensitiveEntity)& anEntity = aSelector->PickedEntity (aPickIter);
5554       const Handle(SelectMgr_EntityOwner)& anOwner = anEntity->OwnerId();
5555       Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
5556
5557       TCollection_AsciiString aName;
5558       GetMapOfAIS().Find1 (anObj, aName);
5559       aName.LeftJustify (20, ' ');
5560       char anInfoStr[512];
5561       if (aPickData.Normal.SquareModulus() > ShortRealEpsilon())
5562       {
5563         Sprintf (anInfoStr,
5564                  " Depth: %g Distance: %g Point: %g %g %g Normal: %g %g %g",
5565                  aPickData.Depth,
5566                  aPickData.MinDist,
5567                  aPickData.Point.X(), aPickData.Point.Y(), aPickData.Point.Z(),
5568                  aPickData.Normal.x(), aPickData.Normal.y(), aPickData.Normal.z());
5569       }
5570       else
5571       {
5572         Sprintf (anInfoStr,
5573                  " Depth: %g Distance: %g Point: %g %g %g",
5574                  aPickData.Depth,
5575                  aPickData.MinDist,
5576                  aPickData.Point.X(), aPickData.Point.Y(), aPickData.Point.Z());
5577       }
5578       theDI << "  " << aName
5579             << anInfoStr
5580             << " (" << anEntity->DynamicType()->Name() << ")"
5581             << "\n";
5582
5583       if (Handle(StdSelect_BRepOwner) aBRepOwner = Handle(StdSelect_BRepOwner)::DownCast (anOwner))
5584       {
5585         theDI << "                       Detected Shape: "
5586               << aBRepOwner->Shape().TShape()->DynamicType()->Name()
5587               << "\n";
5588       }
5589
5590       if (Handle(Select3D_SensitiveWire) aWire = Handle(Select3D_SensitiveWire)::DownCast (anEntity))
5591       {
5592         Handle(Select3D_SensitiveEntity) aSen = aWire->GetLastDetected();
5593         theDI << "                       Detected Child: "
5594               << aSen->DynamicType()->Name()
5595               << "\n";
5596       }
5597       else if (Handle(Select3D_SensitivePrimitiveArray) aPrimArr = Handle(Select3D_SensitivePrimitiveArray)::DownCast (anEntity))
5598       {
5599         theDI << "                       Detected Element: "
5600               << aPrimArr->LastDetectedElement()
5601               << "\n";
5602       }
5603       else if (Handle(Select3D_SensitiveTriangulation) aTriSens = Handle(Select3D_SensitiveTriangulation)::DownCast (anEntity))
5604       {
5605         theDI << "                       Detected Triangle: "
5606               << aTriSens->LastDetectedTriangleIndex()
5607               << "\n";
5608       }
5609     }
5610     return 0;
5611   }
5612
5613   NCollection_Map<Handle(AIS_InteractiveObject)> aDetected;
5614   for (aCtx->InitDetected(); aCtx->MoreDetected(); aCtx->NextDetected())
5615   {
5616     aDetected.Add (Handle(AIS_InteractiveObject)::DownCast (aCtx->DetectedCurrentOwner()->Selectable()));
5617   }
5618
5619   const Standard_Boolean toShowAll = (theArgNb >= 2 && *theArgVec[1] == '*');
5620   if (theArgNb >= 2
5621    && !toShowAll)
5622   {
5623     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5624     {
5625       const TCollection_AsciiString anObjName = theArgVec[anArgIter];
5626       Handle(AIS_InteractiveObject) anObj;
5627       if (!GetMapOfAIS().Find2 (anObjName, anObj))
5628       {
5629         theDI << anObjName << " doesn't exist!\n";
5630         continue;
5631       }
5632
5633       TCollection_AsciiString aName = anObjName;
5634       aName.LeftJustify (20, ' ');
5635       theDI << "  " << aName << " ";
5636       objInfo (aDetected, anObj, theDI);
5637       theDI << "\n";
5638     }
5639     return 0;
5640   }
5641
5642   if (aCtx->NbSelected() > 0 && !toShowAll)
5643   {
5644     NCollection_DataMap<Handle(SelectMgr_EntityOwner), TopoDS_Shape> anOwnerShapeMap;
5645     for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected())
5646     {
5647       const Handle(SelectMgr_EntityOwner) anOwner = aCtx->SelectedOwner();
5648       const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (anOwner->Selectable());
5649       // handle whole object selection
5650       if (anOwner == anObj->GlobalSelOwner())
5651       {
5652         TCollection_AsciiString aName;
5653         GetMapOfAIS().Find1 (anObj, aName);
5654         aName.LeftJustify (20, ' ');
5655         theDI << aName << " ";
5656         objInfo (aDetected, anObj, theDI);
5657         theDI << "\n";
5658       }
5659     }
5660
5661     // process selected sub-shapes
5662     printLocalSelectionInfo (aCtx, theDI);
5663
5664     return 0;
5665   }
5666
5667   theDI << "Neutral-point state:\n";
5668   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5669        anObjIter.More(); anObjIter.Next())
5670   {
5671     if (anObjIter.Key1().IsNull())
5672     {
5673       continue;
5674     }
5675
5676     TCollection_AsciiString aName = anObjIter.Key2();
5677     aName.LeftJustify (20, ' ');
5678     theDI << "  " << aName << " ";
5679     objInfo (aDetected, anObjIter.Key1(), theDI);
5680     theDI << "\n";
5681   }
5682   printLocalSelectionInfo (aCtx, theDI);
5683   return 0;
5684 }
5685
5686 //=======================================================================
5687 //function : PickShape
5688 //purpose  : First Activate the rightmode + Put Filters to be able to
5689 //           pick objets that are of type <TheType>...
5690 //=======================================================================
5691
5692 TopoDS_Shape ViewerTest::PickShape (const TopAbs_ShapeEnum theShapeType,
5693                                     const Standard_Integer theMaxPick)
5694 {
5695   Handle(TopTools_HArray1OfShape) aResArray = new TopTools_HArray1OfShape (1, 1);
5696   PickShapes (theShapeType, aResArray, theMaxPick);
5697   return aResArray->First();
5698 }
5699
5700 //=======================================================================
5701 //function : PickShapes
5702 //purpose  :
5703 //=======================================================================
5704 Standard_Boolean ViewerTest::PickShapes (const TopAbs_ShapeEnum theShapeType,
5705                                          Handle(TopTools_HArray1OfShape)& theResArray,
5706                                          const Standard_Integer theMaxPick)
5707 {
5708   const Standard_Integer aNbToReach = theResArray->Length();
5709   if (aNbToReach > 1)
5710   {
5711     Message::SendWarning ("WARNING : Pick with Shift+ MB1 for Selection of more than 1 object");
5712   }
5713
5714   // step 1: prepare the data
5715   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
5716   if (aCtx.IsNull())
5717   {
5718     Message::SendFail ("Error: no active viewer");
5719     return Standard_False;
5720   }
5721
5722   aCtx->RemoveFilters();
5723   AIS_ListOfInteractive aDispObjects;
5724   aCtx->DisplayedObjects (aDispObjects);
5725   if (theShapeType == TopAbs_SHAPE)
5726   {
5727     aCtx->AddFilter (new AIS_TypeFilter (AIS_KindOfInteractive_Shape));
5728   }
5729   else
5730   {
5731     aCtx->AddFilter (new StdSelect_ShapeTypeFilter (theShapeType));
5732   }
5733
5734   const Standard_Integer aSelMode = AIS_Shape::SelectionMode (theShapeType);
5735   for (AIS_ListOfInteractive::Iterator anObjIter (aDispObjects); anObjIter.More(); anObjIter.Next())
5736   {
5737     if (Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (anObjIter.Value()))
5738     {
5739       aCtx->SetSelectionModeActive (aShapePrs, aSelMode, true, AIS_SelectionModesConcurrency_Single);
5740     }
5741   }
5742
5743   // step 2 : wait for the selection...
5744   Standard_Integer aNbPickGood = 0, aNbPickFail = 0;
5745   Standard_Integer argccc = 5;
5746   const char *bufff[] = { "A", "B", "C", "D", "E" };
5747   const char **argvvv = (const char** )bufff;
5748   for (; aNbPickGood < aNbToReach && aNbPickFail <= theMaxPick; )
5749   {
5750     while (ViewerMainLoop (argccc, argvvv)) {}
5751     Standard_Integer aNbStored = aCtx->NbSelected();
5752     if (aNbStored != aNbPickGood)
5753     {
5754       aNbPickGood = aNbStored;
5755     }
5756     else
5757     {
5758       ++aNbPickFail;
5759     }
5760     Message::SendInfo() << "NbPicked =  " << aNbPickGood << " |  Nb Pick Fail :" << aNbPickFail;
5761   }
5762
5763   // step3 get result.
5764   if (aNbPickFail >= aNbToReach)
5765   {
5766     return Standard_False;
5767   }
5768
5769   Standard_Integer anIndex = theResArray->Lower();
5770   for (aCtx->InitSelected(); aCtx->MoreSelected(); aCtx->NextSelected(), ++anIndex)
5771   {
5772     if (aCtx->HasSelectedShape())
5773     {
5774       theResArray->SetValue (anIndex, aCtx->SelectedShape());
5775     }
5776     else
5777     {
5778       Handle(AIS_InteractiveObject) IO = aCtx->SelectedInteractive();
5779       theResArray->SetValue (anIndex, Handle(AIS_Shape)::DownCast (IO)->Shape());
5780     }
5781   }
5782
5783   aCtx->RemoveFilters();
5784   if (theShapeType != TopAbs_SHAPE)
5785   {
5786     for (AIS_ListOfInteractive::Iterator anObjIter (aDispObjects); anObjIter.More(); anObjIter.Next())
5787     {
5788       if (Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (anObjIter.Value()))
5789       {
5790         aCtx->SetSelectionModeActive (aShapePrs, aSelMode, true, AIS_SelectionModesConcurrency_Single);
5791       }
5792     }
5793   }
5794   return Standard_True;
5795 }
5796
5797 //=======================================================================
5798 //function : VPickShape
5799 //purpose  :
5800 //=======================================================================
5801 static int VPickShape( Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5802 {
5803   TopAbs_ShapeEnum aShapeType = TopAbs_SHAPE;
5804   if (argc != 1)
5805   {
5806     TCollection_AsciiString aShapeArg (argv[1]);
5807     aShapeArg.LowerCase();
5808     aShapeType = TopAbs_COMPOUND;
5809     if      (aShapeArg == "v"
5810           || aShapeArg == "vertex") aShapeType = TopAbs_VERTEX;
5811     else if (aShapeArg == "e"
5812           || aShapeArg == "edge")   aShapeType = TopAbs_EDGE;
5813     else if (aShapeArg == "w"
5814           || aShapeArg == "wire")   aShapeType = TopAbs_WIRE;
5815     else if (aShapeArg == "f"
5816           || aShapeArg == "face")   aShapeType = TopAbs_FACE;
5817     else if (aShapeArg == "shape")  aShapeType = TopAbs_SHAPE;
5818     else if (aShapeArg == "shell")  aShapeType = TopAbs_SHELL;
5819     else if (aShapeArg == "solid")  aShapeType = TopAbs_SOLID;
5820     else
5821     {
5822       Message::SendFail() << "Syntax error at '" << argv[1] << "'";
5823       return 1;
5824     }
5825   }
5826
5827   static Standard_Integer THE_NB_SHAPES_OF_TYPE[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
5828   static const TCollection_AsciiString THE_NAME_TYPE[8] = {"COMPS","SOL","SHE","F","W","E","V","SHAP"};
5829
5830   const Standard_Integer aNbToPick = argc > 2 ? argc - 2 : 1;
5831   if (aNbToPick == 1)
5832   {
5833     TopoDS_Shape aPickedShape = ViewerTest::PickShape (aShapeType);
5834     if (aPickedShape.IsNull())
5835     {
5836       return 1;
5837     }
5838
5839     TCollection_AsciiString aName;
5840     if (argc > 2)
5841     {
5842       aName = argv[2];
5843     }
5844     else
5845     {
5846       const int aShapeIndex = ++THE_NB_SHAPES_OF_TYPE[Standard_Integer(aShapeType)];
5847       aName = TCollection_AsciiString ("Picked_") + THE_NAME_TYPE[Standard_Integer(aShapeType)] + "_" + aShapeIndex;
5848     }
5849
5850     DBRep::Set (aName.ToCString(), aPickedShape);
5851     Handle(AIS_Shape) aShapePrs = new AIS_Shape (aPickedShape);
5852     ViewerTest::Display (aName, aShapePrs, false, true);
5853     di << "Name of picked shape: " << aName <<"\n";
5854   }
5855   else
5856   {
5857     TCollection_AsciiString aName (argv[2]);
5858     aName.LowerCase();
5859     const Standard_Boolean isAutoNaming = aName == ".";
5860     Handle(TopTools_HArray1OfShape) aPickedArray = new TopTools_HArray1OfShape (1, aNbToPick);
5861     if (ViewerTest::PickShapes (aShapeType, aPickedArray))
5862     {
5863       for (Standard_Integer aPickedIter = aPickedArray->Lower(); aPickedIter <= aPickedArray->Upper(); ++aPickedIter)
5864       {
5865         TopoDS_Shape aPickedShape = aPickedArray->Value (aPickedIter);
5866         aName.Clear();
5867         if (!aPickedShape.IsNull()
5868          && isAutoNaming)
5869         {
5870           const int aShapeIndex = ++THE_NB_SHAPES_OF_TYPE[Standard_Integer(aShapeType)];
5871           aName = TCollection_AsciiString ("Picked_") + THE_NAME_TYPE[Standard_Integer(aShapeType)] + "_" + aShapeIndex;
5872         }
5873         else
5874         {
5875           aName = argv[1 + aPickedIter];
5876         }
5877
5878         DBRep::Set (aName.ToCString(), aPickedShape);
5879         Handle(AIS_Shape) aShapePrs = new AIS_Shape (aPickedShape);
5880         di << "Display of picked shape #" << aPickedIter << " - name: " << aName <<"\n";
5881         ViewerTest::Display (aName, aShapePrs, false, true);
5882       }
5883     }
5884   }
5885   TheAISContext()->UpdateCurrentViewer();
5886   return 0;
5887 }
5888
5889 //=======================================================================
5890 //function : VSelFilter
5891 //purpose  :
5892 //=======================================================================
5893 static int VSelFilter(Draw_Interpretor& , Standard_Integer theArgc,
5894                       const char** theArgv)
5895 {
5896   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5897   if (aContext.IsNull())
5898   {
5899     Message::SendFail ("Error: AIS context is not available.");
5900     return 1;
5901   }
5902
5903   for (Standard_Integer anArgIter = 1; anArgIter < theArgc; ++anArgIter)
5904   {
5905     TCollection_AsciiString anArg (theArgv[anArgIter]);
5906     anArg.LowerCase();
5907     if (anArg == "-clear")
5908     {
5909       aContext->RemoveFilters();
5910     }
5911     else if (anArg == "-contextfilter" && anArgIter + 1 < theArgc)
5912     {
5913       TCollection_AsciiString aVal (theArgv[++anArgIter]);
5914       aVal.LowerCase();
5915       if (aVal == "and")
5916       {
5917         aContext->SetFilterType (SelectMgr_FilterType_AND);
5918       }
5919       else if (aVal == "or")
5920       {
5921         aContext->SetFilterType (SelectMgr_FilterType_OR);
5922       }
5923       else
5924       {
5925         Message::SendFail() << "Syntax error: wrong command attribute value '" << aVal << "'";
5926         return 1;
5927       }
5928     }
5929     else if (anArg == "-type"
5930           && anArgIter + 1 < theArgc)
5931     {
5932       TCollection_AsciiString aVal (theArgv[++anArgIter]);
5933       TopAbs_ShapeEnum aShapeType = TopAbs_COMPOUND;
5934       if (!TopAbs::ShapeTypeFromString (aVal.ToCString(), aShapeType))
5935       {
5936         Message::SendFail() << "Syntax error: wrong command attribute value '" << aVal << "'";
5937         return 1;
5938       }
5939
5940       Handle(SelectMgr_Filter) aFilter;
5941       if (aShapeType == TopAbs_SHAPE)
5942       {
5943         aFilter = new AIS_TypeFilter (AIS_KindOfInteractive_Shape);
5944       }
5945       else
5946       {
5947         aFilter = new StdSelect_ShapeTypeFilter (aShapeType);
5948       }
5949       aContext->AddFilter (aFilter);
5950     }
5951     else if (anArg == "-secondtype"
5952           && anArgIter + 1 < theArgc)
5953     {
5954       TCollection_AsciiString aVal (theArgv[++anArgIter]);
5955       TopAbs_ShapeEnum aShapeType = TopAbs_COMPOUND;
5956       if (!TopAbs::ShapeTypeFromString (aVal.ToCString(), aShapeType))
5957       {
5958         Message::SendFail() << "Syntax error: wrong command attribute value '" << aVal << "'";
5959         return 1;
5960       }
5961
5962       Handle(SelectMgr_Filter) aFilter;
5963       if (aShapeType == TopAbs_SHAPE)
5964       {
5965         aFilter = new AIS_TypeFilter (AIS_KindOfInteractive_Shape);
5966       }
5967       else
5968       {
5969         aFilter = new StdSelect_ShapeTypeFilter (aShapeType);
5970       }
5971       aContext->AddFilter (aFilter);
5972     }
5973     else
5974     {
5975       Message::SendFail() << "Syntax error: unknown argument '" << theArgv[anArgIter] << "'";
5976       return 1;
5977     }
5978   }
5979   return 0;
5980 }
5981
5982 //=======================================================================
5983 //function : VPickSelected
5984 //purpose  :
5985 //=======================================================================
5986 static int VPickSelected (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgs)
5987 {
5988   static Standard_Integer aCount = 0;
5989   TCollection_AsciiString aName = "PickedShape_";
5990
5991   if (theArgNb > 1)
5992   {
5993     aName = theArgs[1];
5994   }
5995   else
5996   {
5997     aName = aName + aCount++ + "_";
5998   }
5999
6000   Standard_Integer anIdx = 0;
6001   for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected(), ++anIdx)
6002   {
6003     TopoDS_Shape aShape;
6004     if (TheAISContext()->HasSelectedShape())
6005     {
6006       aShape = TheAISContext()->SelectedShape();
6007     }
6008     else
6009     {
6010       Handle(AIS_InteractiveObject) IO = TheAISContext()->SelectedInteractive();
6011       aShape = Handle(AIS_Shape)::DownCast (IO)->Shape();
6012     }
6013
6014     TCollection_AsciiString aCurrentName = aName;
6015     if (anIdx > 0)
6016     {
6017       aCurrentName += anIdx;
6018     }
6019
6020     DBRep::Set ((aCurrentName).ToCString(), aShape);
6021
6022     Handle(AIS_Shape) aNewShape = new AIS_Shape (aShape);
6023     GetMapOfAIS().Bind (aNewShape, aCurrentName);
6024     TheAISContext()->Display (aNewShape, Standard_False);
6025   }
6026
6027   TheAISContext()->UpdateCurrentViewer();
6028
6029   return 0;
6030 }
6031
6032 //=======================================================================
6033 //function : list of known objects
6034 //purpose  :
6035 //=======================================================================
6036 static int VIOTypes( Draw_Interpretor& di, Standard_Integer , const char** )
6037 {
6038   //                             1234567890         12345678901234567         123456789
6039   TCollection_AsciiString Colum [3]={"Standard Types","Type Of Object","Signature"};
6040   TCollection_AsciiString BlankLine(64,'_');
6041   Standard_Integer i ;
6042
6043   di<<"/n"<<BlankLine.ToCString()<<"\n";
6044
6045   for( i =0;i<=2;i++)
6046     Colum[i].Center(20,' ');
6047   for(i=0;i<=2;i++)
6048     di<<"|"<<Colum[i].ToCString();
6049   di<<"|\n";
6050
6051   di<<BlankLine.ToCString()<<"\n";
6052
6053   //  TCollection_AsciiString thetypes[5]={"Datum","Shape","Object","Relation","None"};
6054   const char ** names = GetTypeNames();
6055
6056   TCollection_AsciiString curstring;
6057   TCollection_AsciiString curcolum[3];
6058
6059
6060   // les objets de type Datum..
6061   curcolum[1]+="Datum";
6062   for(i =0;i<=6;i++){
6063     curcolum[0].Clear();
6064     curcolum[0] += names[i];
6065
6066     curcolum[2].Clear();
6067     curcolum[2]+=TCollection_AsciiString(i+1);
6068
6069     for(Standard_Integer j =0;j<=2;j++){
6070       curcolum[j].Center(20,' ');
6071       di<<"|"<<curcolum[j].ToCString();
6072     }
6073     di<<"|\n";
6074   }
6075   di<<BlankLine.ToCString()<<"\n";
6076
6077   // les objets de type shape
6078   curcolum[1].Clear();
6079   curcolum[1]+="Shape";
6080   curcolum[1].Center(20,' ');
6081
6082   for(i=0;i<=2;i++){
6083     curcolum[0].Clear();
6084     curcolum[0] += names[7+i];
6085     curcolum[2].Clear();
6086     curcolum[2]+=TCollection_AsciiString(i);
6087
6088     for(Standard_Integer j =0;j<=2;j++){
6089       curcolum[j].Center(20,' ');
6090       di<<"|"<<curcolum[j].ToCString();
6091     }
6092     di<<"|\n";
6093   }
6094   di<<BlankLine.ToCString()<<"\n";
6095   // les IO de type objet...
6096   curcolum[1].Clear();
6097   curcolum[1]+="Object";
6098   curcolum[1].Center(20,' ');
6099   for(i=0;i<=1;i++){
6100     curcolum[0].Clear();
6101     curcolum[0] += names[10+i];
6102     curcolum[2].Clear();
6103     curcolum[2]+=TCollection_AsciiString(i);
6104
6105     for(Standard_Integer j =0;j<=2;j++){
6106       curcolum[j].Center(20,' ');
6107       di<<"|"<<curcolum[j].ToCString();
6108     }
6109     di<<"|\n";
6110   }
6111   di<<BlankLine.ToCString()<<"\n";
6112   // les contraintes et dimensions.
6113   // pour l'instant on separe juste contraintes et dimensions...
6114   // plus tard, on detaillera toutes les sortes...
6115   curcolum[1].Clear();
6116   curcolum[1]+="Relation";
6117   curcolum[1].Center(20,' ');
6118   for(i=0;i<=1;i++){
6119     curcolum[0].Clear();
6120     curcolum[0] += names[12+i];
6121     curcolum[2].Clear();
6122     curcolum[2]+=TCollection_AsciiString(i);
6123
6124     for(Standard_Integer j =0;j<=2;j++){
6125       curcolum[j].Center(20,' ');
6126       di<<"|"<<curcolum[j].ToCString();
6127     }
6128     di<<"|\n";
6129   }
6130   di<<BlankLine.ToCString()<<"\n";
6131
6132
6133   return 0;
6134 }
6135
6136
6137 static int VEraseType( Draw_Interpretor& , Standard_Integer argc, const char** argv)
6138 {
6139   if(argc!=2) return 1;
6140
6141   AIS_KindOfInteractive TheType;
6142   Standard_Integer TheSign(-1);
6143   GetTypeAndSignfromString(argv[1],TheType,TheSign);
6144
6145
6146   AIS_ListOfInteractive LIO;
6147
6148   // en attendant l'amelioration ais pour les dimensions...
6149   //
6150   Standard_Integer dimension_status(-1);
6151   if (TheType==AIS_KindOfInteractive_Relation)
6152   {
6153     dimension_status = TheSign == 1 ? 1 : 0;
6154     TheSign = -1;
6155   }
6156
6157   TheAISContext()->DisplayedObjects(TheType,TheSign,LIO);
6158   Handle(AIS_InteractiveObject) curio;
6159   for(AIS_ListIteratorOfListOfInteractive it(LIO);it.More();it.Next()){
6160     curio  = it.Value();
6161
6162     if(dimension_status == -1)
6163       TheAISContext()->Erase(curio,Standard_False);
6164     else {
6165       PrsDim_KindOfDimension KOD = Handle(PrsDim_Relation)::DownCast (curio)->KindOfDimension();
6166       if ((dimension_status==0 && KOD == PrsDim_KOD_NONE)||
6167           (dimension_status==1 && KOD != PrsDim_KOD_NONE))
6168         TheAISContext()->Erase(curio,Standard_False);
6169     }
6170   }
6171   TheAISContext()->UpdateCurrentViewer();
6172   return 0;
6173 }
6174 static int VDisplayType(Draw_Interpretor& , Standard_Integer argc, const char** argv)
6175 {
6176   if(argc!=2) return 1;
6177
6178   AIS_KindOfInteractive TheType;
6179   Standard_Integer TheSign(-1);
6180   GetTypeAndSignfromString(argv[1],TheType,TheSign);
6181
6182   // en attendant l'amelioration ais pour les dimensions...
6183   //
6184   Standard_Integer dimension_status(-1);
6185   if (TheType==AIS_KindOfInteractive_Relation)
6186   {
6187     dimension_status = TheSign == 1 ? 1 : 0;
6188     TheSign = -1;
6189   }
6190
6191   AIS_ListOfInteractive LIO;
6192   TheAISContext()->ObjectsInside(LIO,TheType,TheSign);
6193   Handle(AIS_InteractiveObject) curio;
6194   for(AIS_ListIteratorOfListOfInteractive it(LIO);it.More();it.Next()){
6195     curio  = it.Value();
6196     if(dimension_status == -1)
6197       TheAISContext()->Display(curio,Standard_False);
6198     else {
6199       PrsDim_KindOfDimension KOD = Handle(PrsDim_Relation)::DownCast (curio)->KindOfDimension();
6200       if ((dimension_status==0 && KOD == PrsDim_KOD_NONE)||
6201           (dimension_status==1 && KOD != PrsDim_KOD_NONE))
6202         TheAISContext()->Display(curio,Standard_False);
6203     }
6204
6205   }
6206
6207   TheAISContext()->UpdateCurrentViewer();
6208   return 0;
6209 }
6210
6211 //===============================================================================================
6212 //function : VBsdf
6213 //purpose  :
6214 //===============================================================================================
6215 static int VBsdf (Draw_Interpretor& theDI,
6216                   Standard_Integer  theArgsNb,
6217                   const char**      theArgVec)
6218 {
6219   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
6220   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6221   if (aView.IsNull()
6222    || aViewer.IsNull())
6223   {
6224     Message::SendFail ("Error: No active viewer!");
6225     return 1;
6226   }
6227
6228   ViewerTest_CmdParser aCmd;
6229
6230   aCmd.SetDescription ("Adjusts parameters of material BSDF:");
6231
6232   aCmd.AddOption ("print|echo|p", "Prints BSDF");
6233
6234   aCmd.AddOption ("noupdate|update", "Suppresses viewer redraw call");
6235
6236   aCmd.AddOption ("kc", "Weight of coat specular/glossy BRDF");
6237   aCmd.AddOption ("kd", "Weight of base diffuse BRDF");
6238   aCmd.AddOption ("ks", "Weight of base specular/glossy BRDF");
6239   aCmd.AddOption ("kt", "Weight of base specular/glossy BTDF");
6240   aCmd.AddOption ("le", "Radiance emitted by surface");
6241
6242   aCmd.AddOption ("coatFresnel|cf", "Fresnel reflectance of coat layer. Allowed formats: Constant R, Schlick R G B, Dielectric N, Conductor N K");
6243   aCmd.AddOption ("baseFresnel|bf", "Fresnel reflectance of base layer. Allowed formats: Constant R, Schlick R G B, Dielectric N, Conductor N K");
6244
6245   aCmd.AddOption ("coatRoughness|cr", "Roughness of coat glossy BRDF");
6246   aCmd.AddOption ("baseRoughness|br", "Roughness of base glossy BRDF");
6247
6248   aCmd.AddOption ("absorpCoeff|af", "Absorption coeff of base transmission BTDF");
6249   aCmd.AddOption ("absorpColor|ac", "Absorption color of base transmission BTDF");
6250
6251   aCmd.AddOption ("normalize|n", "Normalizes BSDF to ensure energy conservation");
6252
6253   aCmd.Parse (theArgsNb, theArgVec);
6254
6255   if (aCmd.HasOption ("help"))
6256   {
6257     theDI.PrintHelp (theArgVec[0]);
6258     return 0;
6259   }
6260
6261   // check viewer update mode
6262   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
6263   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
6264   {
6265     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
6266     {
6267       break;
6268     }
6269   }
6270
6271   // find object
6272   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
6273   Handle(AIS_InteractiveObject) anIObj;
6274   if (!GetMapOfAIS().Find2 (aName, anIObj))
6275   {
6276     Message::SendFail ("Error: no active viewer");
6277     return 1;
6278   }
6279
6280   Graphic3d_MaterialAspect aMaterial = anIObj->Attributes()->ShadingAspect()->Material();
6281   Graphic3d_BSDF aBSDF = aMaterial.BSDF();
6282
6283   if (aCmd.HasOption ("print"))
6284   {
6285     theDI << "\n"
6286       << "Kc:               " << aBSDF.Kc.r() << ", " << aBSDF.Kc.g() << ", " << aBSDF.Kc.b() << "\n"
6287       << "Kd:               " << aBSDF.Kd.r() << ", " << aBSDF.Kd.g() << ", " << aBSDF.Kd.b() << "\n"
6288       << "Ks:               " << aBSDF.Ks.r() << ", " << aBSDF.Ks.g() << ", " << aBSDF.Ks.b() << "\n"
6289       << "Kt:               " << aBSDF.Kt.r() << ", " << aBSDF.Kt.g() << ", " << aBSDF.Kt.b() << "\n"
6290       << "Le:               " << aBSDF.Le.r() << ", " << aBSDF.Le.g() << ", " << aBSDF.Le.b() << "\n";
6291
6292     for (int aLayerID = 0; aLayerID < 2; ++aLayerID)
6293     {
6294       const Graphic3d_Vec4 aFresnel = aLayerID < 1 ? aBSDF.FresnelCoat.Serialize()
6295                                                    : aBSDF.FresnelBase.Serialize();
6296
6297       theDI << (aLayerID < 1 ? "Coat Fresnel:     "
6298                              : "Base Fresnel:     ");
6299
6300       if (aFresnel.x() >= 0.f)
6301       {
6302         theDI << "Schlick " << "R = " << aFresnel.r() << ", "
6303                             << "G = " << aFresnel.g() << ", "
6304                             << "B = " << aFresnel.b() << "\n";
6305       }
6306       else if (aFresnel.x() >= -1.5f)
6307       {
6308         theDI << "Constant " << aFresnel.z() << "\n";
6309       }
6310       else if (aFresnel.x() >= -2.5f)
6311       {
6312         theDI << "Conductor " << "N = " << aFresnel.y() << ", "
6313                               << "K = " << aFresnel.z() << "\n";
6314       }
6315       else
6316       {
6317         theDI << "Dielectric " << "N = " << aFresnel.y() << "\n";
6318       }
6319     }
6320
6321     theDI << "Coat roughness:   " << aBSDF.Kc.w() << "\n"
6322           << "Base roughness:   " << aBSDF.Ks.w() << "\n"
6323           << "Absorption coeff: " << aBSDF.Absorption.w() << "\n"
6324           << "Absorption color: " << aBSDF.Absorption.r() << ", "
6325                                   << aBSDF.Absorption.g() << ", "
6326                                   << aBSDF.Absorption.b() << "\n";
6327
6328     return 0;
6329   }
6330
6331   if (aCmd.HasOption ("coatRoughness", 1, Standard_True))
6332   {
6333     aBSDF.Kc.w() = aCmd.ArgFloat ("coatRoughness");
6334   }
6335
6336   if (aCmd.HasOption ("baseRoughness", 1, Standard_True))
6337   {
6338     aBSDF.Ks.w () = aCmd.ArgFloat ("baseRoughness");
6339   }
6340
6341   if (aCmd.HasOption ("absorpCoeff", 1, Standard_True))
6342   {
6343     aBSDF.Absorption.w() = aCmd.ArgFloat ("absorpCoeff");
6344   }
6345
6346   if (aCmd.HasOption ("absorpColor", 3, Standard_True))
6347   {
6348     const Graphic3d_Vec3 aRGB = aCmd.ArgVec3f ("absorpColor");
6349
6350     aBSDF.Absorption.r() = aRGB.r();
6351     aBSDF.Absorption.g() = aRGB.g();
6352     aBSDF.Absorption.b() = aRGB.b();
6353   }
6354
6355   if (aCmd.HasOption ("kc", 3) || aCmd.HasOption ("kc", 1, Standard_True))
6356   {
6357     Graphic3d_Vec3 aKc;
6358
6359     if (aCmd.HasOption ("kc", 3))
6360     {
6361       aKc = aCmd.ArgVec3f ("kc");
6362     }
6363     else
6364     {
6365       aKc = Graphic3d_Vec3 (aCmd.ArgFloat ("kc"));
6366     }
6367
6368     aBSDF.Kc.r() = aKc.r();
6369     aBSDF.Kc.g() = aKc.g();
6370     aBSDF.Kc.b() = aKc.b();
6371   }
6372
6373   if (aCmd.HasOption ("kd", 3))
6374   {
6375     aBSDF.Kd = aCmd.ArgVec3f ("kd");
6376   }
6377   else if (aCmd.HasOption ("kd", 1, Standard_True))
6378   {
6379     aBSDF.Kd = Graphic3d_Vec3 (aCmd.ArgFloat ("kd"));
6380   }
6381
6382   if (aCmd.HasOption ("ks", 3) || aCmd.HasOption ("ks", 1, Standard_True))
6383   {
6384     Graphic3d_Vec3 aKs;
6385
6386     if (aCmd.HasOption ("ks", 3))
6387     {
6388       aKs = aCmd.ArgVec3f ("ks");
6389     }
6390     else
6391     {
6392       aKs = Graphic3d_Vec3 (aCmd.ArgFloat ("ks"));
6393     }
6394
6395     aBSDF.Ks.r() = aKs.r();
6396     aBSDF.Ks.g() = aKs.g();
6397     aBSDF.Ks.b() = aKs.b();
6398   }
6399
6400   if (aCmd.HasOption ("kt", 3))
6401   {
6402     aBSDF.Kt = aCmd.ArgVec3f ("kt");
6403   }
6404   else if (aCmd.HasOption ("kt", 1, Standard_True))
6405   {
6406     aBSDF.Kt = Graphic3d_Vec3 (aCmd.ArgFloat ("kt"));
6407   }
6408
6409   if (aCmd.HasOption ("le", 3))
6410   {
6411     aBSDF.Le = aCmd.ArgVec3f ("le");
6412   }
6413   else if (aCmd.HasOption ("le", 1, Standard_True))
6414   {
6415     aBSDF.Le = Graphic3d_Vec3 (aCmd.ArgFloat ("le"));
6416   }
6417
6418   const std::string aFresnelErrorMessage =
6419     "Error! Wrong Fresnel type. Allowed types are: Constant F, Schlick R G B, Dielectric N, Conductor N K\n";
6420
6421   for (int aLayerID = 0; aLayerID < 2; ++aLayerID)
6422   {
6423     const std::string aFresnel = aLayerID < 1 ? "baseFresnel"
6424                                               : "coatFresnel";
6425
6426     if (aCmd.HasOption (aFresnel, 4)) // Schlick: type R G B
6427     {
6428       std::string aFresnelType = aCmd.Arg (aFresnel, 0);
6429       std::transform (aFresnelType.begin (), aFresnelType.end (), aFresnelType.begin (), ::LowerCase);
6430
6431       if (aFresnelType == "schlick")
6432       {
6433         Graphic3d_Vec3 aRGB (static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 1).c_str())),
6434                              static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 2).c_str())),
6435                              static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 3).c_str())));
6436
6437         aRGB.r() = std::min (std::max (aRGB.r(), 0.f), 1.f);
6438         aRGB.g() = std::min (std::max (aRGB.g(), 0.f), 1.f);
6439         aRGB.b() = std::min (std::max (aRGB.b(), 0.f), 1.f);
6440
6441         (aLayerID < 1 ? aBSDF.FresnelBase : aBSDF.FresnelCoat) = Graphic3d_Fresnel::CreateSchlick (aRGB);
6442       }
6443       else
6444       {
6445         theDI << aFresnelErrorMessage.c_str() << "\n";
6446       }
6447     }
6448     else if (aCmd.HasOption (aFresnel, 3)) // Conductor: type N K
6449     {
6450       std::string aFresnelType = aCmd.Arg (aFresnel, 0);
6451       std::transform (aFresnelType.begin (), aFresnelType.end (), aFresnelType.begin (), ::LowerCase);
6452
6453       if (aFresnelType == "conductor")
6454       {
6455         const float aN = static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 1).c_str()));
6456         const float aK = static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 2).c_str()));
6457
6458         (aLayerID < 1 ? aBSDF.FresnelBase : aBSDF.FresnelCoat) = Graphic3d_Fresnel::CreateConductor (aN, aK);
6459       }
6460       else
6461       {
6462         theDI << aFresnelErrorMessage.c_str() << "\n";
6463       }
6464     }
6465     else if (aCmd.HasOption (aFresnel, 2)) // Dielectric or Constant: type N|C
6466     {
6467       std::string aFresnelType = aCmd.Arg (aFresnel, 0);
6468       std::transform (aFresnelType.begin (), aFresnelType.end (), aFresnelType.begin (), ::LowerCase);
6469
6470       if (aFresnelType == "constant")
6471       {
6472         const float aR = static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 1).c_str()));
6473
6474         (aLayerID < 1 ? aBSDF.FresnelBase : aBSDF.FresnelCoat) = Graphic3d_Fresnel::CreateConstant (aR);
6475       }
6476       else if (aFresnelType == "dielectric")
6477       {
6478         const float aN = static_cast<float> (Draw::Atof (aCmd.Arg (aFresnel, 1).c_str()));
6479
6480         (aLayerID < 1 ? aBSDF.FresnelBase : aBSDF.FresnelCoat) = Graphic3d_Fresnel::CreateDielectric (aN);
6481       }
6482       else
6483       {
6484         theDI << aFresnelErrorMessage.c_str() << "\n";
6485       }
6486     }
6487   }
6488
6489   if (aCmd.HasOption ("normalize"))
6490   {
6491     aBSDF.Normalize();
6492   }
6493
6494   aMaterial.SetBSDF (aBSDF);
6495   anIObj->SetMaterial (aMaterial);
6496
6497   return 0;
6498 }
6499
6500 //==============================================================================
6501 //function : VLoadSelection
6502 //purpose  : Adds given objects to map of AIS and loads selection primitives for them
6503 //==============================================================================
6504 static Standard_Integer VLoadSelection (Draw_Interpretor& /*theDi*/,
6505                                         Standard_Integer theArgNb,
6506                                         const char** theArgVec)
6507 {
6508   if (theArgNb < 2)
6509   {
6510     Message::SendFail ("Syntax error: wrong number of arguments.");
6511     return 1;
6512   }
6513
6514   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
6515   if (aCtx.IsNull())
6516   {
6517     ViewerTest::ViewerInit();
6518     aCtx = ViewerTest::GetAISContext();
6519   }
6520
6521   // Parse input arguments
6522   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6523   {
6524     const TCollection_AsciiString aName = theArgVec[anArgIter];
6525     Handle(AIS_InteractiveObject) aShape;
6526     if (!GetMapOfAIS().Find2 (aName, aShape))
6527     {
6528       TopoDS_Shape aDrawShape = DBRep::GetExisting (aName);
6529       if (!aDrawShape.IsNull())
6530       {
6531         aShape = new AIS_Shape (aDrawShape);
6532         GetMapOfAIS().Bind (aShape, aName);
6533       }
6534     }
6535     if (aShape.IsNull())
6536     {
6537       Message::SendFail() << "Syntax error: presentation '" << aName << "' not found";
6538       return 1;
6539     }
6540
6541     aCtx->Load (aShape, -1);
6542     aCtx->Activate (aShape, aShape->GlobalSelectionMode(), Standard_True);
6543   }
6544   return 0;
6545 }
6546
6547 //==============================================================================
6548 //function : ViewerTest::Commands
6549 //purpose  : Add all the viewer command in the Draw_Interpretor
6550 //==============================================================================
6551
6552 void ViewerTest::Commands(Draw_Interpretor& theCommands)
6553 {
6554   ViewerTest::ViewerCommands(theCommands);
6555   ViewerTest::RelationCommands(theCommands);
6556   ViewerTest::ObjectCommands(theCommands);
6557   ViewerTest::FilletCommands(theCommands);
6558   ViewerTest::OpenGlCommands(theCommands);
6559
6560   const char* aGroup = "AIS Viewer";
6561   const char* aFileName = __FILE__;
6562   auto addCmd = [&](const char* theName, Draw_Interpretor::CommandFunction theFunc, const char* theHelp)
6563   {
6564     theCommands.Add (theName, theHelp, aFileName, theFunc, aGroup);
6565   };
6566
6567   // display
6568   addCmd ("visos", visos, /* [visos] */ R"(
6569 visos [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]
6570 If last 3 optional parameters are not set prints numbers of U-, V- isolines and IsoOnPlane.
6571 )" /* [visos] */);
6572
6573   addCmd ("vdisplay", VDisplay2, /* [vdisplay] */ R"(
6574 vdisplay [-noupdate|-update] [-mutable] [-neutral]
6575          [-trsfPers {zoom|rotate|zoomRotate|none}=none]
6576             [-trsfPersPos X Y [Z]] [-3d]
6577             [-2d|-trihedron [{top|bottom|left|right|topLeft
6578                             |topRight|bottomLeft|bottomRight}
6579               [offsetX offsetY]]]
6580          [-dispMode mode] [-highMode mode]
6581          [-layer index] [-top|-topmost|-overlay|-underlay]
6582          [-redisplay] [-erased]
6583          [-noecho] [-autoTriangulation {0|1}]
6584          name1 [name2] ... [name n]
6585 Displays named objects.
6586  -noupdate    Suppresses viewer redraw call.
6587  -mutable     Enables optimizations for mutable objects.
6588  -neutral     Draws objects in main viewer.
6589  -erased      Loads the object into context, but does not display it.
6590  -layer       Sets z-layer for objects.
6591               Alternatively -overlay|-underlay|-top|-topmost
6592               options can be used for the default z-layers.
6593  -top         Draws object on top of main presentations
6594               but below topmost.
6595  -topmost     Draws in overlay for 3D presentations.
6596               with independent Depth.
6597  -overlay     Draws objects in overlay for 2D presentations.
6598               (On-Screen-Display)
6599  -underlay    Draws objects in underlay for 2D presentations.
6600               (On-Screen-Display)
6601  -selectable|-noselect Controls selection of objects.
6602  -trsfPers    Sets a transform persistence flags.
6603  -trsfPersPos Sets an anchor point for transform persistence.
6604  -2d          Displays object in screen coordinates.
6605               (DY looks up)
6606  -dispmode    Sets display mode for objects.
6607  -highmode    Sets hilight mode for objects.
6608  -redisplay   Recomputes presentation of objects.
6609  -noecho      Avoid printing of command results.
6610  -autoTriang  Enable/disable auto-triangulation for displayed shape.
6611 )" /* [vdisplay] */);
6612
6613   addCmd ("vnbdisplayed", VNbDisplayed, /* [vnbdisplayed] */ R"(
6614 vnbdisplayed : Returns number of displayed objects
6615 )" /* [vnbdisplayed] */);
6616
6617   addCmd ("vupdate", VUpdate, /* [vupdate] */ R"(
6618 vupdate name1 [name2] ... [name n]
6619 Updates named objects in interactive context
6620 )" /* [vupdate] */);
6621
6622   addCmd ("verase", VErase, /* [verase] */ R"(
6623 verase [-noupdate|-update] [name1] ...  [name n] [-noerror]
6624 Erases selected or named objects.
6625 If there are no selected or named objects the whole viewer is erased.
6626 Option -noerror prevents exception on non-existing objects.
6627 )" /* [verase] */);
6628
6629   addCmd ("vremove", VRemove, /* [vremove] */ R"(
6630 vremove [-noupdate|-update] [-context] [-all] [-noinfo] [name1] ...  [name n] [-noerror]
6631 or vremove [-context] -all to remove all objects
6632 Removes selected or named objects.
6633  -context  do not delete object from the map of objects and names;
6634  -noupdate suppresses viewer redraw call;
6635  -noinfo   suppresses displaying the list of removed objects;
6636  -noerror  prevents exception on non-existing objects.
6637 )" /* [vremove] */);
6638
6639   addCmd ("vdonly", VDonly2, /* [vdonly] */ R"(
6640 vdonly [-noupdate|-update] [name1] ...  [name n]
6641 Displays only selected or named objects.
6642 )" /* [vdonly] */);
6643
6644   addCmd ("vdisplayall", VDisplayAll, /* [vdisplayall] */ R"(
6645 vdisplayall : Displays all erased interactive objects (see vdir and vstate).
6646 )" /* [vdisplayall] */);
6647
6648   addCmd ("veraseall", VErase, /* [veraseall] */ R"(
6649 veraseall : Erases all objects displayed in the viewer.
6650 )" /* [veraseall] */);
6651
6652   addCmd ("verasetype", VEraseType, /* [verasetype] */ R"(
6653 verasetype <Type>
6654 Erase all the displayed objects of one given kind (see vtypes).
6655 The following types are possible:
6656   Point, Axis, Trihedron, PlaneTrihedron, Line, Circle, Plane, Shape,
6657   ConnectedShape, MultiConn.Shape, ConnectedInter., MultiConn., Constraint and Dimension.
6658 )" /* [verasetype] */);
6659
6660   addCmd ("vbounding", VBounding, /* [vbounding] */ R"(
6661 vbounding [-noupdate|-update] [-mode] name1 [name2 [...]]
6662           [-print] [-hide]
6663 Temporarily display bounding box of specified Interactive Objects,
6664 or print it to console if -print is specified.
6665 Already displayed box might be hidden by -hide option.
6666 )" /* [vbounding] */);
6667
6668   addCmd ("vdisplaytype", VDisplayType, /* [vdisplaytype] */ R"(
6669 vdisplaytype <Type> <Signature>
6670 Display all the objects of one given kind (see vtypes) which are stored the interactive context.
6671 The following types are possible:
6672   Point, Axis, Trihedron, PlaneTrihedron, Line, Circle, Plane, Shape,
6673   ConnectedShape, MultiConn.Shape, ConnectedInter., MultiConn., Constraint and Dimension.
6674 )" /* [vdisplaytype] */);
6675
6676   addCmd ("vsetdispmode", VDispMode, /* [vsetdispmode] */ R"(
6677 vsetdispmode [name] mode(1,2,..)
6678 Sets display mode for all, selected or named objects.
6679 In case of a shape presentation, 0 defines WireFrame, and 1 defines Shading display modes.
6680 )" /* [vsetdispmode] */);
6681
6682   addCmd ("vunsetdispmode", VDispMode, /* [vunsetdispmode] */ R"(
6683 vunsetdispmode [name]
6684 Unsets custom display mode for selected or named objects.
6685 )" /* [vunsetdispmode] */);
6686
6687   addCmd ("vdir", VDir, /* [vdir] */ R"(
6688 vdir [mask] [-list]
6689 Lists all objects displayed in 3D viewer
6690   mask - name filter like prefix*
6691  -list - format list with new-line per name; OFF by default
6692 )" /* [vdir] */);
6693
6694   addCmd ("vdump", VDump, /* [vdump] */ R"(
6695 vdump <filename>.png [-width Width -height Height]
6696       [-buffer rgb|rgba|depth=rgb]
6697       [-stereo mono|left|right|blend|sideBySide|overUnder=mono]
6698       [-xrPose base|head|handLeft|handRight=base]
6699       [-tileSize Size=0]
6700 Dumps content of the active view into image file.
6701 )" /* [vdump] */);
6702
6703   addCmd ("vsub", VSubInt, /* [vsub] */ R"(
6704 vsub 0/1 (off/on) [obj] : Subintensity(on/off) of selected objects
6705 )" /* [vsub] */);
6706
6707   addCmd ("vaspects", VAspects, /* [vaspects] */ R"(
6708 vaspects [-noupdate|-update] [name1 [name2 [...]] | -defaults] [-subshapes subname1 [subname2 [...]]]
6709          [-visibility {0|1}]
6710          [-color {ColorName | R G B}] [-unsetColor]
6711          [-backfaceColor Color]
6712          [-material MatName] [-unsetMaterial]
6713          [-transparency Transp] [-unsetTransparency]
6714          [-width LineWidth] [-unsetWidth]
6715          [-lineType {solid|dash|dot|dotDash|0xHexPattern} [-stippleFactor factor]]
6716            [-unsetLineType]
6717          [-markerType {.|+|x|O|xcircle|pointcircle|ring1|ring2|ring3|ball|ImagePath}]
6718            [-unsetMarkerType]
6719          [-markerSize Scale] [-unsetMarkerSize]
6720          [-freeBoundary {0|1}]
6721            [-freeBoundaryWidth Width] [-unsetFreeBoundaryWidth]
6722            [-freeBoundaryColor {ColorName | R G B}] [-unsetFreeBoundaryColor]
6723          [-isoOnTriangulation 0|1]
6724          [-maxParamValue {value}]
6725          [-sensitivity {selection_mode} {value}]
6726          [-shadingModel {unlit|flat|gouraud|phong|pbr|pbr_facet}]
6727            [-unsetShadingModel]
6728          [-interior {solid|hatch|hidenline|point}] [-setHatch HatchStyle]
6729            [-unsetInterior]
6730          [-faceBoundaryDraw {0|1}] [-mostContinuity {c0|g1|c1|g2|c2|c3|cn}]
6731          [-faceBoundaryWidth LineWidth] [-faceBoundaryColor R G B] [-faceBoundaryType LineType]
6732          [-drawEdges {0|1}] [-edgeType LineType] [-edgeColor R G B] [-quadEdges {0|1}]
6733          [-drawSilhouette {0|1}]
6734          [-alphaMode {opaque|mask|blend|maskblend|blendauto} [alphaCutOff=0.5]]
6735          [-dumpJson] [-dumpCompact {0|1}] [-dumpDepth depth]
6736 Manage presentation properties of all, selected or named objects.
6737 When -subshapes is specified than following properties will be assigned to specified sub-shapes.
6738 When -defaults is specified than presentation properties will be
6739 assigned to all objects that have not their own specified properties
6740 and to all objects to be displayed in the future.
6741 If -defaults is used there should not be any objects' names nor -subshapes specifier.
6742 See also vlistcolors and vlistmaterials to list named colors and materials
6743 accepted by arguments -material and -color
6744 )" /* [vaspects] */);
6745
6746   addCmd ("vsetcolor", VAspects, /* [vsetcolor] */ R"(
6747 vsetcolor [-noupdate|-update] [name] ColorName
6748 Sets color for all, selected or named objects.
6749 Alias for vaspects -setcolor [name] ColorName.
6750 )" /* [vsetcolor] */);
6751
6752   addCmd ("vunsetcolor", VAspects, /* [vunsetcolor] */ R"(
6753 vunsetcolor [-noupdate|-update] [name]
6754 Resets color for all, selected or named objects.
6755 Alias for vaspects -unsetcolor [name].
6756 )" /* [vunsetcolor] */);
6757
6758   addCmd ("vsettransparency", VAspects, /* [vsettransparency] */ R"(
6759 vsettransparency [-noupdate|-update] [name] Coefficient
6760 Sets transparency for all, selected or named objects.
6761 The Coefficient may be between 0.0 (opaque) and 1.0 (fully transparent).
6762 Alias for vaspects -settransp [name] Coefficient.
6763 )" /* [vsettransparency] */);
6764
6765   addCmd ("vunsettransparency", VAspects, /* [vunsettransparency] */ R"(
6766 vunsettransparency [-noupdate|-update] [name]
6767 Resets transparency for all, selected or named objects.
6768 Alias for vaspects -unsettransp [name].
6769 )" /* [vunsettransparency] */);
6770
6771   addCmd ("vsetmaterial", VAspects, /* [vsetmaterial] */ R"(
6772 vsetmaterial [-noupdate|-update] [name] MaterialName
6773 n\t\t: Alias for vaspects -setmaterial [name] MaterialName.
6774 )" /* [vsetmaterial] */);
6775
6776   addCmd ("vunsetmaterial", VAspects, /* [vunsetmaterial] */ R"(
6777 vunsetmaterial [-noupdate|-update] [name]
6778 Alias for vaspects -unsetmaterial [name].
6779 )" /* [vunsetmaterial] */);
6780
6781   addCmd ("vsetwidth", VAspects, /* [vsetwidth] */ R"(
6782 vsetwidth [-noupdate|-update] [name] width(0->10)
6783 Alias for vaspects -setwidth [name] width.
6784 )" /* [vsetwidth] */);
6785
6786   addCmd ("vunsetwidth", VAspects, /* [vunsetwidth] */ R"(
6787 vunsetwidth [-noupdate|-update] [name]
6788 Alias for vaspects -unsetwidth [name].
6789 )" /* [vunsetwidth] */);
6790
6791   addCmd ("vsetinteriorstyle", VAspects, /* [vsetinteriorstyle] */ R"(
6792 vsetinteriorstyle [-noupdate|-update] [name] Style
6793 Alias for vaspects -setInterior [name] Style.
6794 )" /* [vsetinteriorstyle] */);
6795
6796   addCmd ("vsetedgetype", VAspects, /* [vsetedgetype] */ R"(
6797 vsetedgetype [name] [-type {solid, dash, dot}] [-color R G B] [-width value]
6798 Alias for vaspects [name] -setEdgeType Type.
6799 )" /* [vsetedgetype] */);
6800
6801   addCmd ("vunsetedgetype", VAspects, /* [vunsetedgetype] */ R"(
6802 vunsetedgetype [name] : Alias for vaspects [name] -unsetEdgeType.
6803 )" /* [vunsetedgetype] */);
6804
6805   addCmd ("vshowfaceboundary", VAspects, /* [vshowfaceboundary] */ R"(
6806 vshowfaceboundary [name]: Alias for vaspects [name] -setFaceBoundaryDraw on.
6807 )" /* [vshowfaceboundary] */);
6808
6809   addCmd ("vsensdis", VDispSensi, /* [vsensdis] */ R"(
6810 vsensdis : Display active entities
6811 (sensitive entities of one of the standard types corresponding to active selection modes).
6812 Standard entity types are those defined in Select3D package:
6813  - sensitive box, face, curve, segment, circle, point, triangulation, triangle.
6814 Custom (application-defined) sensitive entity types are not processed by this command.
6815 )" /* [vsensdis] */);
6816
6817   addCmd ("vsensera", VClearSensi, /* [vsensera] */ R"(
6818 vsensera : erase active entities
6819 )" /* [vsensera] */);
6820
6821   addCmd ("vsetshading", VShading, /* [vsetshading] */ R"(
6822 vsetshading name Quality(default=0.0008)
6823 Sets deflection coefficient that defines the quality of the shape representation in the shading mode.
6824 )" /* [vsetshading] */);
6825
6826   addCmd ("vunsetshading", VShading, /* [vunsetshading] */ R"(
6827 vunsetshading name
6828 Sets default deflection coefficient (0.0008) that defines the quality of the shape representation in the shading mode.
6829 )" /* [vunsetshading] */);
6830
6831   addCmd ("vtexture", VTexture, /* [vtexture] */ R"(
6832 vtexture [-noupdate|-update] name [ImageFile|IdOfTexture|off]
6833          [-tex0 Image0] [-tex1 Image1] [...]
6834          [-3d Image0 Image1 ... ImageN]
6835          [-origin {u v|off}] [-scale {u v|off}] [-repeat {u v|off}]
6836          [-trsfTrans du dv] [-trsfScale su sv] [-trsfAngle Angle]
6837          [-modulate {on|off}] [-srgb {on|off}]=on
6838          [-setFilter {nearest|bilinear|trilinear}]
6839          [-setAnisoFilter {off|low|middle|quality}]
6840          [-default]
6841 The texture can be specified by filepath
6842 or as ID (0<=IdOfTexture<=20) specifying one of the predefined textures.
6843 The options are:
6844  -scale     Setup texture scaling for generating coordinates; (1, 1) by default
6845  -origin    Setup texture origin  for generating coordinates; (0, 0) by default
6846  -repeat    Setup texture repeat  for generating coordinates; (1, 1) by default
6847  -modulate  Enable or disable texture color modulation
6848  -srgb      Prefer sRGB texture format when applicable; TRUE by default
6849  -trsfAngle Setup dynamic texture coordinates transformation - rotation angle
6850  -trsfTrans Setup dynamic texture coordinates transformation - translation vector
6851  -trsfScale Setup dynamic texture coordinates transformation - scale vector
6852  -setFilter Setup texture filter
6853  -setAnisoFilter Setup anisotropic filter for texture with mip-levels
6854  -default   Sets texture mapping default parameters
6855  -3d        Load 3D texture from the list of 2D image files
6856 )" /* [vtexture] */);
6857
6858   addCmd ("vtexscale", VTexture, /* [vtexscale] */ R"(
6859 vtexscale name ScaleU ScaleV
6860 Alias for vtexture name -setScale ScaleU ScaleV.
6861 )" /* [vtexscale] */);
6862
6863   addCmd ("vtexorigin", VTexture, /* [vtexorigin] */ R"(
6864 vtexorigin name OriginU OriginV
6865 Alias for vtexture name -setOrigin OriginU OriginV.
6866 )" /* [vtexorigin] */);
6867
6868   addCmd ("vtexrepeat", VTexture, /* [vtexrepeat] */ R"(
6869 vtexrepeat name RepeatU RepeatV
6870 Alias for vtexture name -setRepeat RepeatU RepeatV.
6871 )" /* [vtexrepeat] */);
6872
6873   addCmd ("vtexdefault", VTexture, /* [vtexdefault] */ R"(
6874 vtexdefault name : Alias for vtexture name -default.
6875 )" /* [vtexdefault] */);
6876
6877   addCmd ("vstate", VState, /* [vstate] */ R"(
6878 vstate [-entities] [-hasSelected] [name1] ... [nameN]
6879 Reports show/hidden state for selected or named objects.
6880  -entities    prints low-level information about detected entities;
6881  -hasSelected prints 1 if context has selected shape and 0 otherwise.
6882 )" /* [vstate] */);
6883
6884   addCmd ("vpickshapes", VPickShape, /* [vpickshapes] */ R"(
6885 vpickshape subtype(VERTEX,EDGE,WIRE,FACE,SHELL,SOLID) [name1 or .] [name2 or .] [name n or .]
6886 Hold Ctrl and pick object by clicking Left mouse button.
6887 Hold also Shift for multiple selection.
6888 )" /* [vpickshapes] */);
6889
6890   addCmd ("vtypes", VIOTypes, /* [vtypes] */ R"(
6891 vtypes : list of known types and signatures in AIS.
6892 To be Used in vpickobject command for selection with filters.
6893 )" /* [vtypes] */);
6894
6895   addCmd ("vselfilter", VSelFilter, /* [vselfilter] */ R"(
6896 vselfilter [-contextfilter {AND|OR}]
6897            [-type {VERTEX|EDGE|WIRE|FACE|SHAPE|SHELL|SOLID}]
6898            [-secondtype {VERTEX|EDGE|WIRE|FACE|SHAPE|SHELL|SOLID}]
6899            [-clear]
6900 Sets selection shape type filter in context or remove all filters.
6901  -contextfilter to define a selection filter for two or more types of entity,
6902                 use value AND (OR by default).
6903  -type  set type of selection filter; filters are applied with Or combination.
6904  -clear remove all filters in context.
6905 )" /* [vselfilter] */);
6906
6907   addCmd ("vpickselected", VPickSelected, /* [vpickselected] */ R"(
6908 vpickselected [name]: extract selected shape.
6909 )" /* [vpickselected] */);
6910
6911   addCmd ("vloadselection", VLoadSelection, /* [vloadselection] */ R"(
6912 vloadselection [-context] [name1] ... [nameN]
6913 Allows to load selection primitives for the shapes with names given without displaying them.
6914 )" /* [vloadselection] */);
6915
6916   addCmd ("vbsdf", VBsdf, /* [vbsdf] */ R"(
6917 vbsdf [name] [options]
6918 nAdjusts parameters of material BSDF:
6919  -help    shows this message
6920  -print   print BSDF
6921  -kd      weight of the Lambertian BRDF
6922  -kr      weight of the reflection BRDF
6923  -kt      weight of the transmission BTDF
6924  -ks      weight of the glossy Blinn BRDF
6925  -le      self-emitted radiance
6926  -fresnel Fresnel coefficients; Allowed fresnel formats are: Constant x,
6927           Schlick x y z, Dielectric x, Conductor x y
6928  -roughness   roughness of material (Blinn's exponent)
6929  -absorpcoeff absorption coefficient (only for transparent material)
6930  -absorpcolor absorption color (only for transparent material)
6931  -normalize   normalize BSDF coefficients
6932 )" /* [vbsdf] */);
6933 }
6934
6935 //==============================================================================
6936 //function : splitParameter
6937 //purpose  : Split parameter string to parameter name and parameter value
6938 //==============================================================================
6939 Standard_Boolean ViewerTest::SplitParameter (const TCollection_AsciiString& theString,
6940                                              TCollection_AsciiString&       theName,
6941                                              TCollection_AsciiString&       theValue)
6942 {
6943   Standard_Integer aParamNameEnd = theString.FirstLocationInSet ("=", 1, theString.Length());
6944
6945   if (aParamNameEnd == 0)
6946   {
6947     return Standard_False;
6948   }
6949
6950   TCollection_AsciiString aString (theString);
6951   if (aParamNameEnd != 0)
6952   {
6953     theValue = aString.Split (aParamNameEnd);
6954     aString.Split (aString.Length() - 1);
6955     theName = aString;
6956   }
6957
6958   return Standard_True;
6959 }
6960
6961 //==============================================================================
6962 // ViewerTest::Factory
6963 //==============================================================================
6964 void ViewerTest::Factory(Draw_Interpretor& theDI)
6965 {
6966   // definition of Viewer Command
6967   ViewerTest::Commands(theDI);
6968
6969 #ifdef OCCT_DEBUG
6970       theDI << "Draw Plugin : OCC V2d & V3d commands are loaded\n";
6971 #endif
6972 }
6973
6974 // Declare entry point PLUGINFACTORY
6975 DPLUGIN(ViewerTest)