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