0024023: Revamp the OCCT Handle - gcc and clang
[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 // Modified by  Eric Gouthiere [sep-oct 98] -> add commands for display...
18 // Modified by  Robert Coublanc [nov 16-17-18 1998]
19 //             -split ViewerTest.cxx into 3 files : ViewerTest.cxx,
20 //                                                  ViewerTest_ObjectCommands.cxx
21 //                                                  ViewerTest_RelationCommands.cxx
22 //             -add Functions and commands for interactive selection of shapes and objects
23 //              in AIS Viewers. (PickShape(s), PickObject(s),
24
25 #include <Standard_Stream.hxx>
26
27 #include <ViewerTest.hxx>
28 #include <ViewerTest_CmdParser.hxx>
29
30 #include <TopLoc_Location.hxx>
31 #include <TopTools_HArray1OfShape.hxx>
32 #include <TColStd_HArray1OfTransient.hxx>
33 #include <TColStd_SequenceOfAsciiString.hxx>
34 #include <TColStd_HSequenceOfAsciiString.hxx>
35 #include <TColStd_MapOfTransient.hxx>
36 #include <OSD_Timer.hxx>
37 #include <Geom_Axis2Placement.hxx>
38 #include <Geom_Axis1Placement.hxx>
39 #include <gp_Trsf.hxx>
40 #include <TopExp_Explorer.hxx>
41 #include <BRepAdaptor_Curve.hxx>
42 #include <StdSelect_ShapeTypeFilter.hxx>
43 #include <AIS.hxx>
44 #include <AIS_ColoredShape.hxx>
45 #include <AIS_InteractiveObject.hxx>
46 #include <AIS_Trihedron.hxx>
47 #include <AIS_Axis.hxx>
48 #include <AIS_Relation.hxx>
49 #include <AIS_TypeFilter.hxx>
50 #include <AIS_SignatureFilter.hxx>
51 #include <AIS_LocalContext.hxx>
52 #include <AIS_ListOfInteractive.hxx>
53 #include <AIS_ListIteratorOfListOfInteractive.hxx>
54 #include <Aspect_InteriorStyle.hxx>
55 #include <Aspect_Window.hxx>
56 #include <Graphic3d_AspectFillArea3d.hxx>
57 #include <Graphic3d_AspectLine3d.hxx>
58 #include <Graphic3d_CStructure.hxx>
59 #include <Graphic3d_TextureRoot.hxx>
60 #include <Image_AlienPixMap.hxx>
61 #include <Prs3d_Drawer.hxx>
62 #include <Prs3d_ShadingAspect.hxx>
63 #include <Prs3d_IsoAspect.hxx>
64 #include <Prs3d_PointAspect.hxx>
65 #include <Select3D_SensitiveWire.hxx>
66 #include <SelectMgr_EntityOwner.hxx>
67 #include <StdSelect_BRepOwner.hxx>
68 #include <StdSelect_ViewerSelector3d.hxx>
69 #include <TopTools_MapOfShape.hxx>
70 #include <ViewerTest_AutoUpdater.hxx>
71
72 #include <stdio.h>
73
74 #include <Draw_Interpretor.hxx>
75 #include <TCollection_AsciiString.hxx>
76 #include <Draw_PluginMacro.hxx>
77
78 // avoid warnings on 'extern "C"' functions returning C++ classes
79 #ifdef WNT
80 #define _CRT_SECURE_NO_DEPRECATE
81 #pragma warning(4:4190)
82 #pragma warning (disable:4996)
83 #endif
84
85 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
86
87 #include <Quantity_Color.hxx>
88 #include <Quantity_NameOfColor.hxx>
89
90 #include <Graphic3d_NameOfMaterial.hxx>
91
92 #define DEFAULT_COLOR              Quantity_NOC_GOLDENROD
93 #define DEFAULT_FREEBOUNDARY_COLOR Quantity_NOC_GREEN
94 #define DEFAULT_MATERIAL           Graphic3d_NOM_BRASS
95
96 //=======================================================================
97 //function : GetColorFromName
98 //purpose  : get the Quantity_NameOfColor from a string
99 //=======================================================================
100
101 Quantity_NameOfColor ViewerTest::GetColorFromName (const Standard_CString theName)
102 {
103   Quantity_NameOfColor aColor = DEFAULT_COLOR;
104   Quantity_Color::ColorFromName (theName, aColor);
105   return aColor;
106 }
107
108 //=======================================================================
109 //function : ParseColor
110 //purpose  :
111 //=======================================================================
112
113 Standard_Integer ViewerTest::ParseColor (Standard_Integer  theArgNb,
114                                          const char**      theArgVec,
115                                          Quantity_Color&   theColor)
116 {
117   Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
118   if (theArgNb >= 1
119    && Quantity_Color::ColorFromName (theArgVec[0], aColor))
120   {
121     theColor = aColor;
122     return 1;
123   }
124   else if (theArgNb >= 3)
125   {
126     const TCollection_AsciiString anRgbStr[3] =
127     {
128       theArgVec[0],
129       theArgVec[1],
130       theArgVec[2]
131     };
132     if (!anRgbStr[0].IsRealValue()
133      || !anRgbStr[1].IsRealValue()
134      || !anRgbStr[2].IsRealValue())
135     {
136       return 0;
137     }
138
139     Graphic3d_Vec4d anRgb;
140     anRgb.x() = anRgbStr[0].RealValue();
141     anRgb.y() = anRgbStr[1].RealValue();
142     anRgb.z() = anRgbStr[2].RealValue();
143     if (anRgb.x() < 0.0 || anRgb.x() > 1.0
144      || anRgb.y() < 0.0 || anRgb.y() > 1.0
145      || anRgb.z() < 0.0 || anRgb.z() > 1.0)
146     {
147       std::cout << "Error: RGB color values should be within range 0..1!\n";
148       return 0;
149     }
150
151     theColor.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
152     return 3;
153   }
154
155   return 0;
156 }
157
158 //=======================================================================
159 //function : GetTypeNames
160 //purpose  :
161 //=======================================================================
162 static const char** GetTypeNames()
163 {
164   static const char* names[14] = {"Point","Axis","Trihedron","PlaneTrihedron", "Line","Circle","Plane",
165                           "Shape","ConnectedShape","MultiConn.Shape",
166                           "ConnectedInter.","MultiConn.",
167                           "Constraint","Dimension"};
168   static const char** ThePointer = names;
169   return ThePointer;
170 }
171
172 //=======================================================================
173 //function : GetTypeAndSignfromString
174 //purpose  :
175 //=======================================================================
176 void GetTypeAndSignfromString (const char* name,AIS_KindOfInteractive& TheType,Standard_Integer& TheSign)
177 {
178   const char ** thefullnames = GetTypeNames();
179   Standard_Integer index(-1);
180
181   for(Standard_Integer i=0;i<=13 && index==-1;i++)
182     if(!strcasecmp(name,thefullnames[i]))
183       index = i;
184
185   if(index ==-1){
186     TheType = AIS_KOI_None;
187     TheSign = -1;
188     return;
189   }
190
191   if(index<=6){
192     TheType = AIS_KOI_Datum;
193     TheSign = index+1;
194   }
195   else if (index <=9){
196     TheType = AIS_KOI_Shape;
197     TheSign = index-7;
198   }
199   else if(index<=11){
200     TheType = AIS_KOI_Object;
201     TheSign = index-10;
202   }
203   else{
204     TheType = AIS_KOI_Relation;
205     TheSign = index-12;
206   }
207
208 }
209
210
211
212 #include <string.h>
213 #include <Draw_Interpretor.hxx>
214 #include <Draw.hxx>
215 #include <Draw_Appli.hxx>
216 #include <DBRep.hxx>
217
218
219 #include <TCollection_AsciiString.hxx>
220 #include <V3d_Viewer.hxx>
221 #include <V3d_View.hxx>
222 #include <V3d.hxx>
223
224 #include <AIS_InteractiveContext.hxx>
225 #include <AIS_Shape.hxx>
226 #include <AIS_TexturedShape.hxx>
227 #include <AIS_DisplayMode.hxx>
228 #include <TColStd_MapOfInteger.hxx>
229 #include <AIS_MapOfInteractive.hxx>
230 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
231 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
232 #include <ViewerTest_EventManager.hxx>
233
234 #include <TopoDS_Solid.hxx>
235 #include <BRepTools.hxx>
236 #include <BRep_Builder.hxx>
237 #include <TopAbs_ShapeEnum.hxx>
238
239 #include <TopoDS.hxx>
240 #include <BRep_Tool.hxx>
241
242
243 #include <Draw_Window.hxx>
244 #include <AIS_ListIteratorOfListOfInteractive.hxx>
245 #include <AIS_ListOfInteractive.hxx>
246 #include <AIS_DisplayMode.hxx>
247 #include <TopTools_ListOfShape.hxx>
248 #include <BRepOffsetAPI_MakeThickSolid.hxx>
249 #include <BRepOffset.hxx>
250
251 //==============================================================================
252 //  VIEWER OBJECT MANAGEMENT GLOBAL VARIABLES
253 //==============================================================================
254 Standard_EXPORT ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS(){
255   static ViewerTest_DoubleMapOfInteractiveAndName TheMap;
256   return TheMap;
257 }
258
259 //=======================================================================
260 //function : Display
261 //purpose  :
262 //=======================================================================
263 Standard_Boolean ViewerTest::Display (const TCollection_AsciiString&       theName,
264                                       const Handle(AIS_InteractiveObject)& theObject,
265                                       const Standard_Boolean               theToUpdate,
266                                       const Standard_Boolean               theReplaceIfExists)
267 {
268   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
269   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
270   if (aCtx.IsNull())
271   {
272     std::cout << "Error: AIS context is not available.\n";
273     return Standard_False;
274   }
275
276   if (aMap.IsBound2 (theName))
277   {
278     if (!theReplaceIfExists)
279     {
280       std::cout << "Error: other interactive object has been already registered with name: " << theName << ".\n"
281                 << "Please use another name.\n";
282       return Standard_False;
283     }
284
285     Handle(AIS_InteractiveObject) anOldObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (theName));
286     if (!anOldObj.IsNull())
287     {
288       aCtx->Remove (anOldObj, Standard_True);
289     }
290     aMap.UnBind2 (theName);
291   }
292
293   if (theObject.IsNull())
294   {
295     // object with specified name has been already unbound
296     return Standard_True;
297   }
298
299   // unbind AIS object if it was bound with another name
300   aMap.UnBind1 (theObject);
301
302   // can be registered without rebinding
303   aMap.Bind (theObject, theName);
304   aCtx->Display (theObject, theToUpdate);
305   return Standard_True;
306 }
307
308 //! Alias for ViewerTest::Display(), compatibility with old code.
309 Standard_EXPORT Standard_Boolean VDisplayAISObject (const TCollection_AsciiString&       theName,
310                                                     const Handle(AIS_InteractiveObject)& theObject,
311                                                     Standard_Boolean theReplaceIfExists = Standard_True)
312 {
313   return ViewerTest::Display (theName, theObject, Standard_True, theReplaceIfExists);
314 }
315
316 static TColStd_MapOfInteger theactivatedmodes(8);
317 static TColStd_ListOfTransient theEventMgrs;
318
319 static void VwrTst_InitEventMgr(const Handle(V3d_View)& aView,
320                                 const Handle(AIS_InteractiveContext)& Ctx)
321 {
322   theEventMgrs.Clear();
323   theEventMgrs.Prepend(new ViewerTest_EventManager(aView, Ctx));
324 }
325
326 static Handle(V3d_View)&  a3DView()
327 {
328   static Handle(V3d_View) Viou;
329   return Viou;
330 }
331
332
333 Standard_EXPORT Handle(AIS_InteractiveContext)& TheAISContext(){
334   static Handle(AIS_InteractiveContext) aContext;
335   return aContext;
336 }
337
338 const Handle(V3d_View)& ViewerTest::CurrentView()
339 {
340   return a3DView();
341 }
342 void ViewerTest::CurrentView(const Handle(V3d_View)& V)
343 {
344   a3DView() = V;
345 }
346
347 const Handle(AIS_InteractiveContext)& ViewerTest::GetAISContext()
348 {
349   return TheAISContext();
350 }
351
352 void ViewerTest::SetAISContext (const Handle(AIS_InteractiveContext)& aCtx)
353 {
354   TheAISContext() = aCtx;
355   ViewerTest::ResetEventManager();
356 }
357
358 Handle(V3d_Viewer) ViewerTest::GetViewerFromContext()
359 {
360   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
361 }
362
363 Handle(V3d_Viewer) ViewerTest::GetCollectorFromContext()
364 {
365   return !TheAISContext().IsNull() ? TheAISContext()->CurrentViewer() : Handle(V3d_Viewer)();
366 }
367
368
369 void ViewerTest::SetEventManager(const Handle(ViewerTest_EventManager)& EM){
370   theEventMgrs.Prepend(EM);
371 }
372
373 void ViewerTest::UnsetEventManager()
374 {
375   theEventMgrs.RemoveFirst();
376 }
377
378
379 void ViewerTest::ResetEventManager()
380 {
381   const Handle(V3d_View) aView = ViewerTest::CurrentView();
382   VwrTst_InitEventMgr(aView, ViewerTest::GetAISContext());
383 }
384
385 Handle(ViewerTest_EventManager) ViewerTest::CurrentEventManager()
386 {
387   Handle(ViewerTest_EventManager) EM;
388   if(theEventMgrs.IsEmpty()) return EM;
389   Handle(Standard_Transient) Tr =  theEventMgrs.First();
390   EM = Handle(ViewerTest_EventManager)::DownCast (Tr);
391   return EM;
392 }
393
394 //=======================================================================
395 //function : Get Context and active view
396 //purpose  :
397 //=======================================================================
398 static Standard_Boolean getCtxAndView (Handle(AIS_InteractiveContext)& theCtx,
399                                        Handle(V3d_View)&               theView)
400 {
401   theCtx  = ViewerTest::GetAISContext();
402   theView = ViewerTest::CurrentView();
403   if (theCtx.IsNull()
404    || theView.IsNull())
405   {
406     std::cout << "Error: cannot find an active view!\n";
407     return Standard_False;
408   }
409   return Standard_True;
410 }
411
412 //==============================================================================
413 //function : GetShapeFromName
414 //purpose  : Compute an Shape from a draw variable or a file name
415 //==============================================================================
416
417 static TopoDS_Shape GetShapeFromName(const char* name)
418 {
419   TopoDS_Shape S = DBRep::Get(name);
420
421   if ( S.IsNull() ) {
422         BRep_Builder aBuilder;
423         BRepTools::Read( S, name, aBuilder);
424   }
425
426   return S;
427 }
428
429 //==============================================================================
430 //function : GetAISShapeFromName
431 //purpose  : Compute an AIS_Shape from a draw variable or a file name
432 //==============================================================================
433 Handle(AIS_Shape) GetAISShapeFromName(const char* name)
434 {
435   Handle(AIS_Shape) retsh;
436
437   if(GetMapOfAIS().IsBound2(name)){
438     const Handle(AIS_InteractiveObject) IO =
439       Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(name));
440     if (!IO.IsNull()) {
441       if(IO->Type()==AIS_KOI_Shape) {
442         if(IO->Signature()==0){
443           retsh = Handle(AIS_Shape)::DownCast (IO);
444         }
445         else
446           cout << "an Object which is not an AIS_Shape "
447             "already has this name!!!"<<endl;
448       }
449     }
450     return retsh;
451   }
452
453
454   TopoDS_Shape S = GetShapeFromName(name);
455   if ( !S.IsNull() ) {
456     retsh = new AIS_Shape(S);
457   }
458   return retsh;
459 }
460
461
462 //==============================================================================
463 //function : Clear
464 //purpose  : Remove all the object from the viewer
465 //==============================================================================
466 void ViewerTest::Clear()
467 {
468   if ( !a3DView().IsNull() ) {
469     if (TheAISContext()->HasOpenedContext())
470       TheAISContext()->CloseLocalContext();
471     ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName it(GetMapOfAIS());
472     while ( it.More() ) {
473       cout << "Remove " << it.Key2() << endl;
474       const Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast (it.Key1());
475       TheAISContext()->Remove(anObj,Standard_False);
476       it.Next();
477     }
478     TheAISContext()->RebuildSelectionStructs();
479     TheAISContext()->UpdateCurrentViewer();
480     GetMapOfAIS().Clear();
481   }
482 }
483
484 //==============================================================================
485 //function : StandardModesActivation
486 //purpose  : Activate a selection mode, vertex, edge, wire ..., in a local
487 //           Context
488 //==============================================================================
489 void ViewerTest::StandardModeActivation(const Standard_Integer mode )
490 {
491   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
492   if(mode==0) {
493     if (TheAISContext()->HasOpenedContext())
494       aContext->CloseLocalContext();
495   } else {
496
497     if(!aContext->HasOpenedContext()) {
498       // To unhilight the preselected object
499       aContext->UnhilightCurrents(Standard_False);
500       // Open a local Context in order to be able to select subshape from
501       // the selected shape if any or for all if there is no selection
502       if (!aContext->FirstCurrentObject().IsNull()){
503         aContext->OpenLocalContext(Standard_False);
504
505         for(aContext->InitCurrent();aContext->MoreCurrent();aContext->NextCurrent()){
506           aContext->Load(       aContext->Current(),-1,Standard_True);
507         }
508       }
509       else
510         aContext->OpenLocalContext();
511     }
512
513     const char *cmode="???";
514
515     switch (mode) {
516     case 0: cmode = "Shape"; break;
517     case 1: cmode = "Vertex"; break;
518     case 2: cmode = "Edge"; break;
519     case 3: cmode = "Wire"; break;
520     case 4: cmode = "Face"; break;
521     case 5: cmode = "Shell"; break;
522     case 6: cmode = "Solid"; break;
523     case 7: cmode = "Compsolid"; break;
524     case 8: cmode = "Compound"; break;
525     }
526
527     if(theactivatedmodes.Contains(mode))
528       { // Desactivate
529         aContext->DeactivateStandardMode(AIS_Shape::SelectionType(mode));
530         theactivatedmodes.Remove(mode);
531         cout<<"Mode "<< cmode <<" OFF"<<endl;
532       }
533     else
534       { // Activate
535         aContext->ActivateStandardMode(AIS_Shape::SelectionType(mode));
536         theactivatedmodes.Add(mode);
537         cout<<"Mode "<< cmode << " ON" << endl;
538       }
539   }
540 }
541
542 //==============================================================================
543 //function : CopyIsoAspect
544 //purpose  : Returns copy Prs3d_IsoAspect with new number of isolines.
545 //==============================================================================
546 static Handle(Prs3d_IsoAspect) CopyIsoAspect
547       (const Handle(Prs3d_IsoAspect) &theIsoAspect,
548        const Standard_Integer theNbIsos)
549 {
550   Quantity_Color    aColor;
551   Aspect_TypeOfLine aType;
552   Standard_Real     aWidth;
553
554   theIsoAspect->Aspect()->Values(aColor, aType, aWidth);
555
556   Handle(Prs3d_IsoAspect) aResult =
557     new Prs3d_IsoAspect(aColor, aType, aWidth, theNbIsos);
558
559   return aResult;
560 }
561
562 //==============================================================================
563 //function : visos
564 //purpose  : Returns or sets the number of U- and V- isos and isIsoOnPlane flag
565 //Draw arg : [name1 ...] [nbUIsos nbVIsos IsoOnPlane(0|1)]
566 //==============================================================================
567 static int visos (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
568 {
569   if (TheAISContext().IsNull()) {
570     di << argv[0] << " Call 'vinit' before!\n";
571     return 1;
572   }
573
574   if (argc <= 1) {
575     di << "Current number of isos : " <<
576       TheAISContext()->IsoNumber(AIS_TOI_IsoU) << " " <<
577       TheAISContext()->IsoNumber(AIS_TOI_IsoV) << "\n";
578     di << "IsoOnPlane mode is " <<
579       (TheAISContext()->IsoOnPlane() ? "ON" : "OFF") << "\n";
580
581     return 0;
582   }
583
584   Standard_Integer aLastInd = argc - 1;
585   Standard_Boolean isChanged = Standard_False;
586   Standard_Integer aNbUIsos = 0;
587   Standard_Integer aNbVIsos = 0;
588
589   if (aLastInd >= 3) {
590     Standard_Boolean isIsoOnPlane = Standard_False;
591
592     if (strcmp(argv[aLastInd], "1") == 0) {
593       isIsoOnPlane = Standard_True;
594       isChanged    = Standard_True;
595     } else if (strcmp(argv[aLastInd], "0") == 0) {
596       isIsoOnPlane = Standard_False;
597       isChanged    = Standard_True;
598     }
599
600     if (isChanged) {
601       aNbVIsos = Draw::Atoi(argv[aLastInd - 1]);
602       aNbUIsos = Draw::Atoi(argv[aLastInd - 2]);
603       aLastInd -= 3;
604
605       di << "New number of isos : " << aNbUIsos << " " << aNbVIsos << "\n";
606       di << "New IsoOnPlane mode is " << (isIsoOnPlane ? "ON" : "OFF") << "\n";
607
608       TheAISContext()->IsoOnPlane(isIsoOnPlane);
609
610       if (aLastInd == 0) {
611         // If there are no shapes provided set the default numbers.
612         TheAISContext()->SetIsoNumber(aNbUIsos, AIS_TOI_IsoU);
613         TheAISContext()->SetIsoNumber(aNbVIsos, AIS_TOI_IsoV);
614       }
615     }
616   }
617
618   Standard_Integer i;
619
620   for (i = 1; i <= aLastInd; i++) {
621     TCollection_AsciiString name(argv[i]);
622     Standard_Boolean IsBound = GetMapOfAIS().IsBound2(name);
623
624     if (IsBound) {
625       const Handle(Standard_Transient) anObj = GetMapOfAIS().Find2(name);
626       if (anObj->IsKind(STANDARD_TYPE(AIS_InteractiveObject))) {
627         const Handle(AIS_InteractiveObject) aShape =
628         Handle(AIS_InteractiveObject)::DownCast (anObj);
629         Handle(Prs3d_Drawer) CurDrawer = aShape->Attributes();
630         Handle(Prs3d_IsoAspect) aUIso = CurDrawer->UIsoAspect();
631         Handle(Prs3d_IsoAspect) aVIso = CurDrawer->VIsoAspect();
632
633         if (isChanged) {
634           CurDrawer->SetUIsoAspect(CopyIsoAspect(aUIso, aNbUIsos));
635           CurDrawer->SetVIsoAspect(CopyIsoAspect(aVIso, aNbVIsos));
636           TheAISContext()->SetLocalAttributes
637                   (aShape, CurDrawer, Standard_False);
638           TheAISContext()->Redisplay(aShape);
639         } else {
640           di << "Number of isos for " << argv[i] << " : "
641              << aUIso->Number() << " " << aVIso->Number() << "\n";
642         }
643       } else {
644         di << argv[i] << ": Not an AIS interactive object!\n";
645       }
646     } else {
647       di << argv[i] << ": Use 'vdisplay' before\n";
648     }
649   }
650
651   if (isChanged) {
652     TheAISContext()->UpdateCurrentViewer();
653   }
654
655   return 0;
656 }
657
658 static Standard_Integer VDispSensi (Draw_Interpretor& ,
659                                     Standard_Integer  theArgNb,
660                                     Standard_CString* )
661 {
662   if (theArgNb > 1)
663   {
664     std::cout << "Error: wrong syntax!\n";
665     return 1;
666   }
667
668   Handle(AIS_InteractiveContext) aCtx;
669   Handle(V3d_View)               aView;
670   if (!getCtxAndView (aCtx, aView))
671   {
672     return 1;
673   }
674
675   aCtx->DisplayActiveSensitive (aView);
676   return 0;
677
678 }
679
680 static Standard_Integer VClearSensi (Draw_Interpretor& ,
681                                      Standard_Integer  theArgNb,
682                                      Standard_CString* )
683 {
684   if (theArgNb > 1)
685   {
686     std::cout << "Error: wrong syntax!\n";
687     return 1;
688   }
689
690   Handle(AIS_InteractiveContext) aCtx;
691   Handle(V3d_View)               aView;
692   if (!getCtxAndView (aCtx, aView))
693   {
694     return 1;
695   }
696   aCtx->ClearActiveSensitive (aView);
697   return 0;
698 }
699
700 //==============================================================================
701 //function : VDir
702 //purpose  : To list the displayed object with their attributes
703 //==============================================================================
704 static int VDir (Draw_Interpretor& theDI,
705                  Standard_Integer ,
706                  const char** )
707 {
708   if (!a3DView().IsNull())
709   {
710     return 0;
711   }
712
713   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
714        anIter.More(); anIter.Next())
715   {
716     theDI << "\t" << anIter.Key2().ToCString() << "\n";
717   }
718   return 0;
719 }
720
721 //==============================================================================
722 //function : VSelPrecision
723 //purpose  : To set the selection tolerance value
724 //Draw arg : Selection tolerance value (real value determining the width and
725 //           height of selecting frustum bases). Without arguments the function
726 //           just prints current tolerance.
727 //==============================================================================
728 static int VSelPrecision(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
729 {
730   if( argc > 2 )
731   {
732     di << "Wrong parameters! Must be: " << argv[0] << " [-unset] [tolerance]\n";
733     return 1;
734   }
735
736   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
737   if( aContext.IsNull() )
738     return 1;
739
740   if( argc == 1 )
741   {
742     Standard_Real aPixelTolerance = aContext->PixelTolerance();
743     di << "Pixel tolerance : " << aPixelTolerance << "\n";
744   }
745   else if (argc == 2)
746   {
747     TCollection_AsciiString anArg = TCollection_AsciiString (argv[1]);
748     anArg.LowerCase();
749     if (anArg == "-unset")
750     {
751       aContext->SetPixelTolerance (-1.0);
752     }
753     else
754     {
755       aContext->SetPixelTolerance (anArg.RealValue());
756     }
757   }
758
759   return 0;
760 }
761
762 //! Auxiliary enumeration
763 enum ViewerTest_StereoPair
764 {
765   ViewerTest_SP_Single,
766   ViewerTest_SP_SideBySide,
767   ViewerTest_SP_OverUnder
768 };
769
770 //==============================================================================
771 //function : VDump
772 //purpose  : To dump the active view snapshot to image file
773 //==============================================================================
774 static Standard_Integer VDump (Draw_Interpretor& theDI,
775                                Standard_Integer  theArgNb,
776                                Standard_CString* theArgVec)
777 {
778   if (theArgNb < 2)
779   {
780     std::cout << "Error: wrong number of arguments! Image file name should be specified at least.\n";
781     return 1;
782   }
783
784   Standard_Integer      anArgIter   = 1;
785   Standard_CString      aFilePath   = theArgVec[anArgIter++];
786   Graphic3d_BufferType  aBufferType = Graphic3d_BT_RGB;
787   V3d_StereoDumpOptions aStereoOpts = V3d_SDO_MONO;
788   ViewerTest_StereoPair aStereoPair = ViewerTest_SP_Single;
789   Standard_Integer      aWidth      = 0;
790   Standard_Integer      aHeight     = 0;
791   for (; anArgIter < theArgNb; ++anArgIter)
792   {
793     TCollection_AsciiString anArg (theArgVec[anArgIter]);
794     anArg.LowerCase();
795     if (anArg == "-buffer")
796     {
797       if (++anArgIter >= theArgNb)
798       {
799         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
800         return 1;
801       }
802
803       TCollection_AsciiString aBufArg (theArgVec[anArgIter]);
804       aBufArg.LowerCase();
805       if (aBufArg == "rgba")
806       {
807         aBufferType = Graphic3d_BT_RGBA;
808       }
809       else if (aBufArg == "rgb")
810       {
811         aBufferType = Graphic3d_BT_RGB;
812       }
813       else if (aBufArg == "depth")
814       {
815         aBufferType = Graphic3d_BT_Depth;
816       }
817       else
818       {
819         std::cout << "Error: unknown buffer '" << aBufArg << "'\n";
820         return 1;
821       }
822     }
823     else if (anArg == "-stereo")
824     {
825       if (++anArgIter >= theArgNb)
826       {
827         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
828         return 1;
829       }
830
831       TCollection_AsciiString aStereoArg (theArgVec[anArgIter]);
832       aStereoArg.LowerCase();
833       if (aStereoArg == "l"
834        || aStereoArg == "left")
835       {
836         aStereoOpts = V3d_SDO_LEFT_EYE;
837       }
838       else if (aStereoArg == "r"
839             || aStereoArg == "right")
840       {
841         aStereoOpts = V3d_SDO_RIGHT_EYE;
842       }
843       else if (aStereoArg == "mono")
844       {
845         aStereoOpts = V3d_SDO_MONO;
846       }
847       else if (aStereoArg == "blended"
848             || aStereoArg == "blend"
849             || aStereoArg == "stereo")
850       {
851         aStereoOpts = V3d_SDO_BLENDED;
852       }
853       else if (aStereoArg == "sbs"
854             || aStereoArg == "sidebyside")
855       {
856         aStereoPair = ViewerTest_SP_SideBySide;
857       }
858       else if (aStereoArg == "ou"
859             || aStereoArg == "overunder")
860       {
861         aStereoPair = ViewerTest_SP_OverUnder;
862       }
863       else
864       {
865         std::cout << "Error: unknown stereo format '" << aStereoArg << "'\n";
866         return 1;
867       }
868     }
869     else if (anArg == "-rgba"
870           || anArg ==  "rgba")
871     {
872       aBufferType = Graphic3d_BT_RGBA;
873     }
874     else if (anArg == "-rgb"
875           || anArg ==  "rgb")
876     {
877       aBufferType = Graphic3d_BT_RGB;
878     }
879     else if (anArg == "-depth"
880           || anArg ==  "depth")
881     {
882       aBufferType = Graphic3d_BT_Depth;
883     }
884
885     else if (anArg == "-width"
886           || anArg ==  "width"
887           || anArg ==  "sizex")
888     {
889       if (aWidth != 0)
890       {
891         std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n";
892         return 1;
893       }
894       else if (++anArgIter >= theArgNb)
895       {
896         std::cout << "Error: integer value is expected right after 'width'\n";
897         return 1;
898       }
899       aWidth = Draw::Atoi (theArgVec[anArgIter]);
900     }
901     else if (anArg == "-height"
902           || anArg ==  "height"
903           || anArg ==  "-sizey")
904     {
905       if (aHeight != 0)
906       {
907         std::cout << "Error: wrong syntax at " << theArgVec[anArgIter] << "\n";
908         return 1;
909       }
910       else if (++anArgIter >= theArgNb)
911       {
912         std::cout << "Error: integer value is expected right after 'height'\n";
913         return 1;
914       }
915       aHeight = Draw::Atoi (theArgVec[anArgIter]);
916     }
917     else
918     {
919       std::cout << "Error: unknown argument '" << theArgVec[anArgIter] << "'\n";
920       return 1;
921     }
922   }
923   if ((aWidth <= 0 && aHeight >  0)
924    || (aWidth >  0 && aHeight <= 0))
925   {
926     std::cout << "Error: dimensions " << aWidth << "x" << aHeight << " are incorrect\n";
927     return 1;
928   }
929
930   Handle(V3d_View) aView = ViewerTest::CurrentView();
931   if (aView.IsNull())
932   {
933     std::cout << "Error: cannot find an active view!\n";
934     return 1;
935   }
936
937   if (aWidth <= 0 || aHeight <= 0)
938   {
939     aView->Window()->Size (aWidth, aHeight);
940   }
941
942   Image_AlienPixMap aPixMap;
943
944   bool isBigEndian = Image_PixMap::IsBigEndianHost();
945   Image_PixMap::ImgFormat aFormat = Image_PixMap::ImgUNKNOWN;
946   switch (aBufferType)
947   {
948     case Graphic3d_BT_RGB:   aFormat = isBigEndian ? Image_PixMap::ImgRGB  : Image_PixMap::ImgBGR;  break;
949     case Graphic3d_BT_RGBA:  aFormat = isBigEndian ? Image_PixMap::ImgRGBA : Image_PixMap::ImgBGRA; break;
950     case Graphic3d_BT_Depth: aFormat = Image_PixMap::ImgGrayF; break;
951   }
952
953   switch (aStereoPair)
954   {
955     case ViewerTest_SP_Single:
956     {
957       if (!aView->ToPixMap (aPixMap, aWidth, aHeight, aBufferType, Standard_True, aStereoOpts))
958       {
959         theDI << "Fail: view dump failed!\n";
960         return 0;
961       }
962       else if (aPixMap.SizeX() != Standard_Size(aWidth)
963             || aPixMap.SizeY() != Standard_Size(aHeight))
964       {
965         theDI << "Fail: dumped dimensions "    << (Standard_Integer )aPixMap.SizeX() << "x" << (Standard_Integer )aPixMap.SizeY()
966               << " are lesser than requested " << aWidth << "x" << aHeight << "\n";
967       }
968       break;
969     }
970     case ViewerTest_SP_SideBySide:
971     {
972       if (!aPixMap.InitZero (aFormat, aWidth * 2, aHeight))
973       {
974         theDI << "Fail: not enough memory for image allocation!\n";
975         return 0;
976       }
977
978       Image_PixMap aPixMapL, aPixMapR;
979       aPixMapL.InitWrapper (aPixMap.Format(), aPixMap.ChangeData(),
980                             aWidth, aHeight, aPixMap.SizeRowBytes());
981       aPixMapR.InitWrapper (aPixMap.Format(), aPixMap.ChangeData() + aPixMap.SizePixelBytes() * aWidth,
982                             aWidth, aHeight, aPixMap.SizeRowBytes());
983       if (!aView->ToPixMap (aPixMapL, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_LEFT_EYE)
984        || !aView->ToPixMap (aPixMapR, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_RIGHT_EYE)
985        )
986       {
987         theDI << "Fail: view dump failed!\n";
988         return 0;
989       }
990       break;
991     }
992     case ViewerTest_SP_OverUnder:
993     {
994       if (!aPixMap.InitZero (aFormat, aWidth, aHeight * 2))
995       {
996         theDI << "Fail: not enough memory for image allocation!\n";
997         return 0;
998       }
999
1000       Image_PixMap aPixMapL, aPixMapR;
1001       aPixMapL.InitWrapper (aFormat, aPixMap.ChangeData(),
1002                             aWidth, aHeight, aPixMap.SizeRowBytes());
1003       aPixMapR.InitWrapper (aFormat, aPixMap.ChangeData() + aPixMap.SizeRowBytes() * aHeight,
1004                             aWidth, aHeight, aPixMap.SizeRowBytes());
1005       if (!aView->ToPixMap (aPixMapL, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_LEFT_EYE)
1006        || !aView->ToPixMap (aPixMapR, aWidth, aHeight, aBufferType, Standard_True, V3d_SDO_RIGHT_EYE))
1007       {
1008         theDI << "Fail: view dump failed!\n";
1009         return 0;
1010       }
1011       break;
1012     }
1013   }
1014
1015   if (!aPixMap.Save (aFilePath))
1016   {
1017     theDI << "Fail: image can not be saved!\n";
1018   }
1019   return 0;
1020 }
1021
1022 //==============================================================================
1023 //function : Displays,Erase...
1024 //purpose  :
1025 //Draw arg :
1026 //==============================================================================
1027 static int VwrTst_DispErase(const Handle(AIS_InteractiveObject)& IO,
1028                             const Standard_Integer Mode,
1029                             const Standard_Integer TypeOfOperation,
1030                             const Standard_Boolean Upd)
1031 {
1032   Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1033
1034   switch(TypeOfOperation){
1035   case 1:
1036     Ctx->Display(IO,Mode,Upd);
1037     break;
1038   case 2:{
1039     Ctx->Erase(IO,Upd);
1040     break;
1041   }
1042   case 3:{
1043     if(IO.IsNull())
1044       Ctx->SetDisplayMode((AIS_DisplayMode)Mode,Upd);
1045     else
1046       Ctx->SetDisplayMode(IO,Mode,Upd);
1047     break;
1048   }
1049   case 4:{
1050     if(IO.IsNull())
1051       Ctx->SetDisplayMode(0,Upd);
1052     else
1053       Ctx->UnsetDisplayMode(IO,Upd);
1054     break;
1055   }
1056   }
1057   return 0;
1058 }
1059
1060 //=======================================================================
1061 //function :
1062 //purpose  :
1063 //=======================================================================
1064 static int VDispMode (Draw_Interpretor& , Standard_Integer argc, const char** argv)
1065 {
1066
1067   TCollection_AsciiString name;
1068   if(argc>3)
1069     return 1;
1070   // display others presentations
1071   Standard_Integer TypeOfOperation = (strcasecmp(argv[0],"vdispmode")==0)? 1:
1072     (strcasecmp(argv[0],"verasemode")==0) ? 2 :
1073       (strcasecmp(argv[0],"vsetdispmode")==0) ? 3 :
1074         (strcasecmp(argv[0],"vunsetdispmode")==0) ? 4 : -1;
1075
1076   Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1077
1078   //unset displaymode.. comportement particulier...
1079   if(TypeOfOperation==4){
1080     if(argc==1){
1081       if(Ctx->NbCurrents()==0 ||
1082          Ctx->NbSelected()==0){
1083         Handle(AIS_InteractiveObject) IO;
1084         VwrTst_DispErase(IO,-1,4,Standard_False);
1085       }
1086       else if(!Ctx->HasOpenedContext()){
1087         for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent())
1088           VwrTst_DispErase(Ctx->Current(),-1,4,Standard_False);
1089       }
1090       else{
1091         for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1092           VwrTst_DispErase(Ctx->Interactive(),-1,4,Standard_False);}
1093       Ctx->UpdateCurrentViewer();
1094     }
1095     else{
1096       Handle(AIS_InteractiveObject) IO;
1097       name = argv[1];
1098       if(GetMapOfAIS().IsBound2(name)){
1099         IO = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(name));
1100         if (!IO.IsNull())
1101           VwrTst_DispErase(IO,-1,4,Standard_True);
1102       }
1103     }
1104   }
1105   else if(argc==2){
1106     Standard_Integer Dmode = Draw::Atoi(argv[1]);
1107     if(Ctx->NbCurrents()==0 && TypeOfOperation==3){
1108       Handle(AIS_InteractiveObject) IO;
1109       VwrTst_DispErase(IO,Dmode,TypeOfOperation,Standard_True);
1110     }
1111     if(!Ctx->HasOpenedContext()){
1112       // set/unset display mode sur le Contexte...
1113       for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent()){
1114         VwrTst_DispErase(Ctx->Current(),Dmode,TypeOfOperation,Standard_False);
1115       }
1116       Ctx->UpdateCurrentViewer();
1117     }
1118     else{
1119       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1120         Ctx->Display(Ctx->Interactive(),Dmode);
1121     }
1122   }
1123   else{
1124     Handle(AIS_InteractiveObject) IO;
1125     name = argv[1];
1126     if(GetMapOfAIS().IsBound2(name))
1127       IO = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(name));
1128     if (!IO.IsNull())
1129       VwrTst_DispErase(IO,Draw::Atoi(argv[2]),TypeOfOperation,Standard_True);
1130   }
1131   return 0;
1132 }
1133
1134
1135 //=======================================================================
1136 //function :
1137 //purpose  :
1138 //=======================================================================
1139 static int VSubInt(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1140 {
1141   if(argc==1) return 1;
1142   Standard_Integer On = Draw::Atoi(argv[1]);
1143   const Handle(AIS_InteractiveContext)& Ctx = ViewerTest::GetAISContext();
1144
1145   if(argc==2){
1146
1147     if(!Ctx->HasOpenedContext()){
1148       di<<"sub intensite ";
1149       if(On==1) di<<"On";
1150       else di<<"Off";
1151       di<<" pour "<<Ctx->NbCurrents()<<"  objets"<<"\n";
1152       for(Ctx->InitCurrent();Ctx->MoreCurrent();Ctx->NextCurrent()){
1153         if(On==1){
1154           Ctx->SubIntensityOn(Ctx->Current(),Standard_False);}
1155         else{
1156           di <<"passage dans off"<<"\n";
1157           Ctx->SubIntensityOff(Ctx->Current(),Standard_False);
1158         }
1159       }
1160     }
1161     else{
1162       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected()){
1163         if(On==1){
1164           Ctx->SubIntensityOn(Ctx->Interactive(),Standard_False);}
1165         else{
1166           Ctx->SubIntensityOff(Ctx->Interactive(),Standard_False);}
1167       }
1168     }
1169     Ctx->UpdateCurrentViewer();
1170   }
1171   else {
1172     Handle(AIS_InteractiveObject) IO;
1173     TCollection_AsciiString name = argv[2];
1174     if(GetMapOfAIS().IsBound2(name)){
1175       IO = Handle(AIS_InteractiveObject)::DownCast(GetMapOfAIS().Find2(name));
1176       if (!IO.IsNull()) {
1177         if(On==1)
1178           Ctx->SubIntensityOn(IO);
1179         else
1180           Ctx->SubIntensityOff(IO);
1181       }
1182     }
1183     else return 1;
1184   }
1185   return 0;
1186 }
1187
1188 //! Auxiliary class to iterate presentations from different collections.
1189 class ViewTest_PrsIter
1190 {
1191 public:
1192
1193   //! Create and initialize iterator object.
1194   ViewTest_PrsIter (const TCollection_AsciiString& theName)
1195   : mySource (IterSource_All)
1196   {
1197     NCollection_Sequence<TCollection_AsciiString> aNames;
1198     if (!theName.IsEmpty())
1199     aNames.Append (theName);
1200     Init (aNames);
1201   }
1202
1203   //! Create and initialize iterator object.
1204   ViewTest_PrsIter (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1205   : mySource (IterSource_All)
1206   {
1207     Init (theNames);
1208   }
1209
1210   //! Initialize the iterator.
1211   void Init (const NCollection_Sequence<TCollection_AsciiString>& theNames)
1212   {
1213     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1214     mySeq = theNames;
1215     mySelIter.Nullify();
1216     myCurrent.Nullify();
1217     myCurrentTrs.Nullify();
1218     if (!mySeq.IsEmpty())
1219     {
1220       mySource = IterSource_List;
1221       mySeqIter = NCollection_Sequence<TCollection_AsciiString>::Iterator (mySeq);
1222     }
1223     else if (aCtx->NbCurrents() > 0)
1224     {
1225       mySource  = IterSource_Selected;
1226       mySelIter = aCtx;
1227       mySelIter->InitCurrent();
1228     }
1229     else
1230     {
1231       mySource = IterSource_All;
1232       myMapIter.Initialize (GetMapOfAIS());
1233     }
1234     initCurrent();
1235   }
1236
1237   const TCollection_AsciiString& CurrentName() const
1238   {
1239     return myCurrentName;
1240   }
1241
1242   const Handle(AIS_InteractiveObject)& Current() const
1243   {
1244     return myCurrent;
1245   }
1246
1247   const Handle(Standard_Transient)& CurrentTrs() const
1248   {
1249     return myCurrentTrs;
1250   }
1251
1252   //! @return true if iterator points to valid object within collection
1253   Standard_Boolean More() const
1254   {
1255     switch (mySource)
1256     {
1257       case IterSource_All:      return myMapIter.More();
1258       case IterSource_List:     return mySeqIter.More();
1259       case IterSource_Selected: return mySelIter->MoreCurrent();
1260     }
1261     return Standard_False;
1262   }
1263
1264   //! Go to the next item.
1265   void Next()
1266   {
1267     myCurrentName.Clear();
1268     myCurrentTrs.Nullify();
1269     myCurrent.Nullify();
1270     switch (mySource)
1271     {
1272       case IterSource_All:
1273       {
1274         myMapIter.Next();
1275         break;
1276       }
1277       case IterSource_List:
1278       {
1279         mySeqIter.Next();
1280         break;
1281       }
1282       case IterSource_Selected:
1283       {
1284         mySelIter->NextCurrent();
1285         break;
1286       }
1287     }
1288     initCurrent();
1289   }
1290
1291 private:
1292
1293   void initCurrent()
1294   {
1295     switch (mySource)
1296     {
1297       case IterSource_All:
1298       {
1299         if (myMapIter.More())
1300         {
1301           myCurrentName = myMapIter.Key2();
1302           myCurrentTrs  = myMapIter.Key1();
1303           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1304         }
1305         break;
1306       }
1307       case IterSource_List:
1308       {
1309         if (mySeqIter.More())
1310         {
1311           if (!GetMapOfAIS().IsBound2 (mySeqIter.Value()))
1312           {
1313             std::cout << "Error: object " << mySeqIter.Value() << " is not displayed!\n";
1314             return;
1315           }
1316           myCurrentName = mySeqIter.Value();
1317           myCurrentTrs  = GetMapOfAIS().Find2 (mySeqIter.Value());
1318           myCurrent     = Handle(AIS_InteractiveObject)::DownCast (myCurrentTrs);
1319         }
1320         break;
1321       }
1322       case IterSource_Selected:
1323       {
1324         if (mySelIter->MoreCurrent())
1325         {
1326           myCurrentName = GetMapOfAIS().Find1 (mySelIter->Current());
1327           myCurrent     = mySelIter->Current();
1328         }
1329         break;
1330       }
1331     }
1332   }
1333
1334 private:
1335
1336   enum IterSource
1337   {
1338     IterSource_All,
1339     IterSource_List,
1340     IterSource_Selected
1341   };
1342
1343 private:
1344
1345   Handle(AIS_InteractiveContext) mySelIter;    //!< iterator for current (selected) objects (IterSource_Selected)
1346   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName myMapIter; //!< iterator for map of all objects (IterSource_All)
1347   NCollection_Sequence<TCollection_AsciiString>           mySeq;
1348   NCollection_Sequence<TCollection_AsciiString>::Iterator mySeqIter;
1349
1350   TCollection_AsciiString        myCurrentName;//!< current item name
1351   Handle(Standard_Transient)     myCurrentTrs; //!< current item (as transient object)
1352   Handle(AIS_InteractiveObject)  myCurrent;    //!< current item
1353
1354   IterSource                     mySource;     //!< iterated collection
1355
1356 };
1357
1358 //==============================================================================
1359 //function : VInteriorStyle
1360 //purpose  : sets interior style of the a selected or named or displayed shape
1361 //==============================================================================
1362 static int VSetInteriorStyle (Draw_Interpretor& theDI,
1363                               Standard_Integer  theArgNb,
1364                               const char**      theArgVec)
1365 {
1366   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
1367   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
1368   if (aCtx.IsNull())
1369   {
1370     std::cerr << "Error: no active view!\n";
1371     return 1;
1372   }
1373
1374   Standard_Integer anArgIter = 1;
1375   for (; anArgIter < theArgNb; ++anArgIter)
1376   {
1377     if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
1378     {
1379       break;
1380     }
1381   }
1382   TCollection_AsciiString aName;
1383   if (theArgNb - anArgIter == 2)
1384   {
1385     aName = theArgVec[anArgIter++];
1386   }
1387   else if (theArgNb - anArgIter != 1)
1388   {
1389     std::cout << "Error: wrong number of arguments! See usage:\n";
1390     theDI.PrintHelp (theArgVec[0]);
1391     return 1;
1392   }
1393   Standard_Integer        anInterStyle = Aspect_IS_SOLID;
1394   TCollection_AsciiString aStyleArg (theArgVec[anArgIter++]);
1395   aStyleArg.LowerCase();
1396   if (aStyleArg == "empty")
1397   {
1398     anInterStyle = 0;
1399   }
1400   else if (aStyleArg == "hollow")
1401   {
1402     anInterStyle = 1;
1403   }
1404   else if (aStyleArg == "hatch")
1405   {
1406     anInterStyle = 2;
1407   }
1408   else if (aStyleArg == "solid")
1409   {
1410     anInterStyle = 3;
1411   }
1412   else if (aStyleArg == "hiddenline")
1413   {
1414     anInterStyle = 4;
1415   }
1416   else
1417   {
1418     anInterStyle = aStyleArg.IntegerValue();
1419   }
1420   if (anInterStyle < Aspect_IS_EMPTY
1421    || anInterStyle > Aspect_IS_HIDDENLINE)
1422   {
1423     std::cout << "Error: style must be within a range [0 (Aspect_IS_EMPTY), "
1424               << Aspect_IS_HIDDENLINE << " (Aspect_IS_HIDDENLINE)]\n";
1425     return 1;
1426   }
1427
1428   if (!aName.IsEmpty()
1429    && !GetMapOfAIS().IsBound2 (aName))
1430   {
1431     std::cout << "Error: object " << aName << " is not displayed!\n";
1432     return 1;
1433   }
1434
1435   if (aCtx->HasOpenedContext())
1436   {
1437     aCtx->CloseLocalContext();
1438   }
1439   for (ViewTest_PrsIter anIter (aName); anIter.More(); anIter.Next())
1440   {
1441     const Handle(AIS_InteractiveObject)& anIO = anIter.Current();
1442     if (!anIO.IsNull())
1443     {
1444       const Handle(Prs3d_Drawer)& aDrawer        = anIO->Attributes();
1445       Handle(Prs3d_ShadingAspect) aShadingAspect = aDrawer->ShadingAspect();
1446       Handle(Graphic3d_AspectFillArea3d) aFillAspect = aShadingAspect->Aspect();
1447       aFillAspect->SetInteriorStyle ((Aspect_InteriorStyle )anInterStyle);
1448       aCtx->RecomputePrsOnly (anIO, Standard_False, Standard_True);
1449     }
1450   }
1451   return 0;
1452 }
1453
1454 //! Auxiliary structure for VAspects
1455 struct ViewerTest_AspectsChangeSet
1456 {
1457   Standard_Integer         ToSetVisibility;
1458   Standard_Integer         Visibility;
1459
1460   Standard_Integer         ToSetColor;
1461   Quantity_Color           Color;
1462
1463   Standard_Integer         ToSetLineWidth;
1464   Standard_Real            LineWidth;
1465
1466   Standard_Integer         ToSetTypeOfLine;
1467   Aspect_TypeOfLine        TypeOfLine;
1468
1469   Standard_Integer         ToSetTransparency;
1470   Standard_Real            Transparency;
1471
1472   Standard_Integer         ToSetMaterial;
1473   Graphic3d_NameOfMaterial Material;
1474   TCollection_AsciiString  MatName;
1475
1476   NCollection_Sequence<TopoDS_Shape> SubShapes;
1477
1478   Standard_Integer         ToSetShowFreeBoundary;
1479   Standard_Integer         ToSetFreeBoundaryWidth;
1480   Standard_Real            FreeBoundaryWidth;
1481   Standard_Integer         ToSetFreeBoundaryColor;
1482   Quantity_Color           FreeBoundaryColor;
1483
1484   //! Empty constructor
1485   ViewerTest_AspectsChangeSet()
1486   : ToSetVisibility   (0),
1487     Visibility        (1),
1488     ToSetColor        (0),
1489     Color             (DEFAULT_COLOR),
1490     ToSetLineWidth    (0),
1491     LineWidth         (1.0),
1492     ToSetTypeOfLine   (0),
1493     TypeOfLine        (Aspect_TOL_SOLID),
1494     ToSetTransparency (0),
1495     Transparency      (0.0),
1496     ToSetMaterial     (0),
1497     Material          (Graphic3d_NOM_DEFAULT),
1498     ToSetShowFreeBoundary  (0),
1499     ToSetFreeBoundaryWidth (0),
1500     FreeBoundaryWidth      (1.0),
1501     ToSetFreeBoundaryColor (0),
1502     FreeBoundaryColor      (DEFAULT_FREEBOUNDARY_COLOR) {}
1503
1504   //! @return true if no changes have been requested
1505   Standard_Boolean IsEmpty() const
1506   {
1507     return ToSetVisibility        == 0
1508         && ToSetLineWidth         == 0
1509         && ToSetTransparency      == 0
1510         && ToSetColor             == 0
1511         && ToSetMaterial          == 0
1512         && ToSetShowFreeBoundary  == 0
1513         && ToSetFreeBoundaryColor == 0
1514         && ToSetFreeBoundaryWidth == 0;
1515   }
1516
1517   //! @return true if properties are valid
1518   Standard_Boolean Validate (const Standard_Boolean theIsSubPart) const
1519   {
1520     Standard_Boolean isOk = Standard_True;
1521     if (Visibility != 0 && Visibility != 1)
1522     {
1523       std::cout << "Error: the visibility should be equal to 0 or 1 (0 - invisible; 1 - visible) (specified " << Visibility << ")\n";
1524       isOk = Standard_False;
1525     }
1526     if (LineWidth <= 0.0
1527      || LineWidth >  10.0)
1528     {
1529       std::cout << "Error: the width should be within [1; 10] range (specified " << LineWidth << ")\n";
1530       isOk = Standard_False;
1531     }
1532     if (Transparency < 0.0
1533      || Transparency > 1.0)
1534     {
1535       std::cout << "Error: the transparency should be within [0; 1] range (specified " << Transparency << ")\n";
1536       isOk = Standard_False;
1537     }
1538     if (theIsSubPart
1539      && ToSetTransparency)
1540     {
1541       std::cout << "Error: the transparency can not be defined for sub-part of object!\n";
1542       isOk = Standard_False;
1543     }
1544     if (ToSetMaterial == 1
1545      && Material == Graphic3d_NOM_DEFAULT)
1546     {
1547       std::cout << "Error: unknown material " << MatName << ".\n";
1548       isOk = Standard_False;
1549     }
1550     if (FreeBoundaryWidth <= 0.0
1551      || FreeBoundaryWidth >  10.0)
1552     {
1553       std::cout << "Error: the free boundary width should be within [1; 10] range (specified " << FreeBoundaryWidth << ")\n";
1554       isOk = Standard_False;
1555     }
1556     return isOk;
1557   }
1558
1559 };
1560
1561 //==============================================================================
1562 //function : VAspects
1563 //purpose  :
1564 //==============================================================================
1565 static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
1566                                   Standard_Integer  theArgNb,
1567                                   const char**      theArgVec)
1568 {
1569   TCollection_AsciiString aCmdName (theArgVec[0]);
1570   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
1571   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
1572   if (aCtx.IsNull())
1573   {
1574     std::cerr << "Error: no active view!\n";
1575     return 1;
1576   }
1577
1578   Standard_Integer anArgIter = 1;
1579   Standard_Boolean isDefaults = Standard_False;
1580   NCollection_Sequence<TCollection_AsciiString> aNames;
1581   for (; anArgIter < theArgNb; ++anArgIter)
1582   {
1583     TCollection_AsciiString anArg = theArgVec[anArgIter];
1584     if (anUpdateTool.parseRedrawMode (anArg))
1585     {
1586       continue;
1587     }
1588     else if (!anArg.IsEmpty()
1589            && anArg.Value (1) != '-')
1590     {
1591       aNames.Append (anArg);
1592     }
1593     else
1594     {
1595       if (anArg == "-defaults")
1596       {
1597         isDefaults = Standard_True;
1598         ++anArgIter;
1599       }
1600       break;
1601     }
1602   }
1603
1604   if (!aNames.IsEmpty() && isDefaults)
1605   {
1606     std::cout << "Error: wrong syntax. If -defaults is used there should not be any objects' names!\n";
1607     return 1;
1608   }
1609
1610   NCollection_Sequence<ViewerTest_AspectsChangeSet> aChanges;
1611   aChanges.Append (ViewerTest_AspectsChangeSet());
1612   ViewerTest_AspectsChangeSet* aChangeSet = &aChanges.ChangeLast();
1613
1614   // parse syntax of legacy commands
1615   if (aCmdName == "vsetwidth")
1616   {
1617     if (aNames.IsEmpty()
1618     || !aNames.Last().IsRealValue())
1619     {
1620       std::cout << "Error: not enough arguments!\n";
1621       return 1;
1622     }
1623     aChangeSet->ToSetLineWidth = 1;
1624     aChangeSet->LineWidth = aNames.Last().RealValue();
1625     aNames.Remove (aNames.Length());
1626   }
1627   else if (aCmdName == "vunsetwidth")
1628   {
1629     aChangeSet->ToSetLineWidth = -1;
1630   }
1631   else if (aCmdName == "vsetcolor")
1632   {
1633     if (aNames.IsEmpty())
1634     {
1635       std::cout << "Error: not enough arguments!\n";
1636       return 1;
1637     }
1638     aChangeSet->ToSetColor = 1;
1639
1640     Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
1641     Standard_Boolean     isOk   = Standard_False;
1642     if (Quantity_Color::ColorFromName (aNames.Last().ToCString(), aColor))
1643     {
1644       aChangeSet->Color = aColor;
1645       aNames.Remove (aNames.Length());
1646       isOk = Standard_True;
1647     }
1648     else if (aNames.Length() >= 3)
1649     {
1650       const TCollection_AsciiString anRgbStr[3] =
1651       {
1652         aNames.Value (aNames.Upper() - 2),
1653         aNames.Value (aNames.Upper() - 1),
1654         aNames.Value (aNames.Upper() - 0)
1655       };
1656       isOk = anRgbStr[0].IsRealValue()
1657           && anRgbStr[1].IsRealValue()
1658           && anRgbStr[2].IsRealValue();
1659       if (isOk)
1660       {
1661         Graphic3d_Vec4d anRgb;
1662         anRgb.x() = anRgbStr[0].RealValue();
1663         anRgb.y() = anRgbStr[1].RealValue();
1664         anRgb.z() = anRgbStr[2].RealValue();
1665         if (anRgb.x() < 0.0 || anRgb.x() > 1.0
1666          || anRgb.y() < 0.0 || anRgb.y() > 1.0
1667          || anRgb.z() < 0.0 || anRgb.z() > 1.0)
1668         {
1669           std::cout << "Error: RGB color values should be within range 0..1!\n";
1670           return 1;
1671         }
1672         aChangeSet->Color.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
1673         aNames.Remove (aNames.Length());
1674         aNames.Remove (aNames.Length());
1675         aNames.Remove (aNames.Length());
1676       }
1677     }
1678     if (!isOk)
1679     {
1680       std::cout << "Error: not enough arguments!\n";
1681       return 1;
1682     }
1683   }
1684   else if (aCmdName == "vunsetcolor")
1685   {
1686     aChangeSet->ToSetColor = -1;
1687   }
1688   else if (aCmdName == "vsettransparency")
1689   {
1690     if (aNames.IsEmpty()
1691     || !aNames.Last().IsRealValue())
1692     {
1693       std::cout << "Error: not enough arguments!\n";
1694       return 1;
1695     }
1696     aChangeSet->ToSetTransparency = 1;
1697     aChangeSet->Transparency  = aNames.Last().RealValue();
1698     aNames.Remove (aNames.Length());
1699   }
1700   else if (aCmdName == "vunsettransparency")
1701   {
1702     aChangeSet->ToSetTransparency = -1;
1703   }
1704   else if (aCmdName == "vsetmaterial")
1705   {
1706     if (aNames.IsEmpty())
1707     {
1708       std::cout << "Error: not enough arguments!\n";
1709       return 1;
1710     }
1711     aChangeSet->ToSetMaterial = 1;
1712     aChangeSet->MatName  = aNames.Last();
1713     aChangeSet->Material = Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString());
1714     aNames.Remove (aNames.Length());
1715   }
1716   else if (aCmdName == "vunsetmaterial")
1717   {
1718     aChangeSet->ToSetMaterial = -1;
1719   }
1720   else if (anArgIter >= theArgNb)
1721   {
1722     std::cout << "Error: not enough arguments!\n";
1723     return 1;
1724   }
1725
1726   if (!aChangeSet->IsEmpty())
1727   {
1728     anArgIter = theArgNb;
1729   }
1730   for (; anArgIter < theArgNb; ++anArgIter)
1731   {
1732     TCollection_AsciiString anArg = theArgVec[anArgIter];
1733     anArg.LowerCase();
1734     if (anArg == "-setwidth"
1735      || anArg == "-setlinewidth")
1736     {
1737       if (++anArgIter >= theArgNb)
1738       {
1739         std::cout << "Error: wrong syntax at " << anArg << "\n";
1740         return 1;
1741       }
1742       aChangeSet->ToSetLineWidth = 1;
1743       aChangeSet->LineWidth = Draw::Atof (theArgVec[anArgIter]);
1744     }
1745     else if (anArg == "-unsetwidth"
1746           || anArg == "-unsetlinewidth")
1747     {
1748       aChangeSet->ToSetLineWidth = -1;
1749       aChangeSet->LineWidth = 1.0;
1750     }
1751     else if (anArg == "-settransp"
1752           || anArg == "-settransparency")
1753     {
1754       if (++anArgIter >= theArgNb)
1755       {
1756         std::cout << "Error: wrong syntax at " << anArg << "\n";
1757         return 1;
1758       }
1759       aChangeSet->ToSetTransparency = 1;
1760       aChangeSet->Transparency = Draw::Atof (theArgVec[anArgIter]);
1761       if (aChangeSet->Transparency >= 0.0
1762        && aChangeSet->Transparency <= Precision::Confusion())
1763       {
1764         aChangeSet->ToSetTransparency = -1;
1765         aChangeSet->Transparency = 0.0;
1766       }
1767     }
1768     else if (anArg == "-setvis"
1769           || anArg == "-setvisibility")
1770     {
1771       if (++anArgIter >= theArgNb)
1772       {
1773         std::cout << "Error: wrong syntax at " << anArg << "\n";
1774         return 1;
1775       }
1776
1777       aChangeSet->ToSetVisibility = 1;
1778       aChangeSet->Visibility = Draw::Atoi (theArgVec[anArgIter]);
1779     }
1780     else if (anArg == "-setalpha")
1781     {
1782       if (++anArgIter >= theArgNb)
1783       {
1784         std::cout << "Error: wrong syntax at " << anArg << "\n";
1785         return 1;
1786       }
1787       aChangeSet->ToSetTransparency = 1;
1788       aChangeSet->Transparency  = Draw::Atof (theArgVec[anArgIter]);
1789       if (aChangeSet->Transparency < 0.0
1790        || aChangeSet->Transparency > 1.0)
1791       {
1792         std::cout << "Error: the transparency should be within [0; 1] range (specified " << aChangeSet->Transparency << ")\n";
1793         return 1;
1794       }
1795       aChangeSet->Transparency = 1.0 - aChangeSet->Transparency;
1796       if (aChangeSet->Transparency >= 0.0
1797        && aChangeSet->Transparency <= Precision::Confusion())
1798       {
1799         aChangeSet->ToSetTransparency = -1;
1800         aChangeSet->Transparency = 0.0;
1801       }
1802     }
1803     else if (anArg == "-unsettransp"
1804           || anArg == "-unsettransparency"
1805           || anArg == "-unsetalpha"
1806           || anArg == "-opaque")
1807     {
1808       aChangeSet->ToSetTransparency = -1;
1809       aChangeSet->Transparency = 0.0;
1810     }
1811     else if (anArg == "-setcolor")
1812     {
1813       Standard_Integer aNbComps  = 0;
1814       Standard_Integer aCompIter = anArgIter + 1;
1815       for (; aCompIter < theArgNb; ++aCompIter, ++aNbComps)
1816       {
1817         if (theArgVec[aCompIter][0] == '-')
1818         {
1819           break;
1820         }
1821       }
1822       switch (aNbComps)
1823       {
1824         case 1:
1825         {
1826           Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
1827           Standard_CString     aName  = theArgVec[anArgIter + 1];
1828           if (!Quantity_Color::ColorFromName (aName, aColor))
1829           {
1830             std::cout << "Error: unknown color name '" << aName << "'\n";
1831             return 1;
1832           }
1833           aChangeSet->Color = aColor;
1834           break;
1835         }
1836         case 3:
1837         {
1838           Graphic3d_Vec3d anRgb;
1839           anRgb.x() = Draw::Atof (theArgVec[anArgIter + 1]);
1840           anRgb.y() = Draw::Atof (theArgVec[anArgIter + 2]);
1841           anRgb.z() = Draw::Atof (theArgVec[anArgIter + 3]);
1842           if (anRgb.x() < 0.0 || anRgb.x() > 1.0
1843            || anRgb.y() < 0.0 || anRgb.y() > 1.0
1844            || anRgb.z() < 0.0 || anRgb.z() > 1.0)
1845           {
1846             std::cout << "Error: RGB color values should be within range 0..1!\n";
1847             return 1;
1848           }
1849           aChangeSet->Color.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
1850           break;
1851         }
1852         default:
1853         {
1854           std::cout << "Error: wrong syntax at " << anArg << "\n";
1855           return 1;
1856         }
1857       }
1858       aChangeSet->ToSetColor = 1;
1859       anArgIter += aNbComps;
1860     }
1861     else if (anArg == "-setlinetype")
1862     {
1863       if (++anArgIter >= theArgNb)
1864       {
1865         std::cout << "Error: wrong syntax at " << anArg << "\n";
1866         return 1;
1867       }
1868
1869       TCollection_AsciiString aValue (theArgVec[anArgIter]);
1870       aValue.LowerCase();
1871
1872       if (aValue.IsEqual ("solid"))
1873       {
1874         aChangeSet->TypeOfLine = Aspect_TOL_SOLID;
1875       }
1876       else if (aValue.IsEqual ("dot"))
1877       {
1878         aChangeSet->TypeOfLine = Aspect_TOL_DOT;
1879       }
1880       else if (aValue.IsEqual ("dash"))
1881       {
1882         aChangeSet->TypeOfLine = Aspect_TOL_DASH;
1883       }
1884       else if (aValue.IsEqual ("dotdash"))
1885       {
1886         aChangeSet->TypeOfLine = Aspect_TOL_DOTDASH;
1887       }
1888       else
1889       {
1890         std::cout << "Error: wrong syntax at " << anArg << "\n";
1891         return 1;
1892       }
1893
1894       aChangeSet->ToSetTypeOfLine = 1;
1895     }
1896     else if (anArg == "-unsetlinetype")
1897     {
1898       aChangeSet->ToSetTypeOfLine = -1;
1899     }
1900     else if (anArg == "-unsetcolor")
1901     {
1902       aChangeSet->ToSetColor = -1;
1903       aChangeSet->Color = DEFAULT_COLOR;
1904     }
1905     else if (anArg == "-setmat"
1906           || anArg == "-setmaterial")
1907     {
1908       if (++anArgIter >= theArgNb)
1909       {
1910         std::cout << "Error: wrong syntax at " << anArg << "\n";
1911         return 1;
1912       }
1913       aChangeSet->ToSetMaterial = 1;
1914       aChangeSet->MatName  = theArgVec[anArgIter];
1915       aChangeSet->Material = Graphic3d_MaterialAspect::MaterialFromName (aChangeSet->MatName.ToCString());
1916     }
1917     else if (anArg == "-unsetmat"
1918           || anArg == "-unsetmaterial")
1919     {
1920       aChangeSet->ToSetMaterial = -1;
1921       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
1922     }
1923     else if (anArg == "-subshape"
1924           || anArg == "-subshapes")
1925     {
1926       if (isDefaults)
1927       {
1928         std::cout << "Error: wrong syntax. -subshapes can not be used together with -defaults call!\n";
1929         return 1;
1930       }
1931
1932       if (aNames.IsEmpty())
1933       {
1934         std::cout << "Error: main objects should specified explicitly when -subshapes is used!\n";
1935         return 1;
1936       }
1937
1938       aChanges.Append (ViewerTest_AspectsChangeSet());
1939       aChangeSet = &aChanges.ChangeLast();
1940
1941       for (++anArgIter; anArgIter < theArgNb; ++anArgIter)
1942       {
1943         Standard_CString aSubShapeName = theArgVec[anArgIter];
1944         if (*aSubShapeName == '-')
1945         {
1946           --anArgIter;
1947           break;
1948         }
1949
1950         TopoDS_Shape aSubShape = DBRep::Get (aSubShapeName);
1951         if (aSubShape.IsNull())
1952         {
1953           std::cerr << "Error: shape " << aSubShapeName << " doesn't found!\n";
1954           return 1;
1955         }
1956         aChangeSet->SubShapes.Append (aSubShape);
1957       }
1958
1959       if (aChangeSet->SubShapes.IsEmpty())
1960       {
1961         std::cerr << "Error: empty list is specified after -subshapes!\n";
1962         return 1;
1963       }
1964     }
1965     else if (anArg == "-freeboundary"
1966           || anArg == "-fb")
1967     {
1968       if (++anArgIter >= theArgNb)
1969       {
1970         std::cout << "Error: wrong syntax at " << anArg << "\n";
1971         return 1;
1972       }
1973       TCollection_AsciiString aValue (theArgVec[anArgIter]);
1974       aValue.LowerCase();
1975       if (aValue == "on"
1976        || aValue == "1")
1977       {
1978         aChangeSet->ToSetShowFreeBoundary = 1;
1979       }
1980       else if (aValue == "off"
1981             || aValue == "0")
1982       {
1983         aChangeSet->ToSetShowFreeBoundary = -1;
1984       }
1985       else
1986       {
1987         std::cout << "Error: wrong syntax at " << anArg << "\n";
1988         return 1;
1989       }
1990     }
1991     else if (anArg == "-setfreeboundarywidth"
1992           || anArg == "-setfbwidth")
1993     {
1994       if (++anArgIter >= theArgNb)
1995       {
1996         std::cout << "Error: wrong syntax at " << anArg << "\n";
1997         return 1;
1998       }
1999       aChangeSet->ToSetFreeBoundaryWidth = 1;
2000       aChangeSet->FreeBoundaryWidth = Draw::Atof (theArgVec[anArgIter]);
2001     }
2002     else if (anArg == "-unsetfreeboundarywidth"
2003           || anArg == "-unsetfbwidth")
2004     {
2005       aChangeSet->ToSetFreeBoundaryWidth = -1;
2006       aChangeSet->FreeBoundaryWidth = 1.0;
2007     }
2008     else if (anArg == "-setfreeboundarycolor"
2009           || anArg == "-setfbcolor")
2010     {
2011       Standard_Integer aNbComps  = 0;
2012       Standard_Integer aCompIter = anArgIter + 1;
2013       for (; aCompIter < theArgNb; ++aCompIter, ++aNbComps)
2014       {
2015         if (theArgVec[aCompIter][0] == '-')
2016         {
2017           break;
2018         }
2019       }
2020       switch (aNbComps)
2021       {
2022         case 1:
2023         {
2024           Quantity_NameOfColor aColor = Quantity_NOC_BLACK;
2025           Standard_CString     aName  = theArgVec[anArgIter + 1];
2026           if (!Quantity_Color::ColorFromName (aName, aColor))
2027           {
2028             std::cout << "Error: unknown free boundary color name '" << aName << "'\n";
2029             return 1;
2030           }
2031           aChangeSet->FreeBoundaryColor = aColor;
2032           break;
2033         }
2034         case 3:
2035         {
2036           Graphic3d_Vec3d anRgb;
2037           anRgb.x() = Draw::Atof (theArgVec[anArgIter + 1]);
2038           anRgb.y() = Draw::Atof (theArgVec[anArgIter + 2]);
2039           anRgb.z() = Draw::Atof (theArgVec[anArgIter + 3]);
2040           if (anRgb.x() < 0.0 || anRgb.x() > 1.0
2041            || anRgb.y() < 0.0 || anRgb.y() > 1.0
2042            || anRgb.z() < 0.0 || anRgb.z() > 1.0)
2043           {
2044             std::cout << "Error: free boundary RGB color values should be within range 0..1!\n";
2045             return 1;
2046           }
2047           aChangeSet->FreeBoundaryColor.SetValues (anRgb.x(), anRgb.y(), anRgb.z(), Quantity_TOC_RGB);
2048           break;
2049         }
2050         default:
2051         {
2052           std::cout << "Error: wrong syntax at " << anArg << "\n";
2053           return 1;
2054         }
2055       }
2056       aChangeSet->ToSetFreeBoundaryColor = 1;
2057       anArgIter += aNbComps;
2058     }
2059     else if (anArg == "-unsetfreeboundarycolor"
2060           || anArg == "-unsetfbcolor")
2061     {
2062       aChangeSet->ToSetFreeBoundaryColor = -1;
2063       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
2064     }
2065     else if (anArg == "-unset")
2066     {
2067       aChangeSet->ToSetVisibility = 1;
2068       aChangeSet->Visibility = 1;
2069       aChangeSet->ToSetLineWidth = -1;
2070       aChangeSet->LineWidth = 1.0;
2071       aChangeSet->ToSetTypeOfLine = -1;
2072       aChangeSet->TypeOfLine = Aspect_TOL_SOLID;
2073       aChangeSet->ToSetTransparency = -1;
2074       aChangeSet->Transparency = 0.0;
2075       aChangeSet->ToSetColor = -1;
2076       aChangeSet->Color = DEFAULT_COLOR;
2077       aChangeSet->ToSetMaterial = -1;
2078       aChangeSet->Material = Graphic3d_NOM_DEFAULT;
2079       aChangeSet->ToSetShowFreeBoundary = -1;
2080       aChangeSet->ToSetFreeBoundaryColor = -1;
2081       aChangeSet->FreeBoundaryColor = DEFAULT_FREEBOUNDARY_COLOR;
2082       aChangeSet->ToSetFreeBoundaryWidth = -1;
2083       aChangeSet->FreeBoundaryWidth = 1.0;
2084     }
2085     else
2086     {
2087       std::cout << "Error: wrong syntax at " << anArg << "\n";
2088       return 1;
2089     }
2090   }
2091
2092   Standard_Boolean isFirst = Standard_True;
2093   for (NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
2094        aChangesIter.More(); aChangesIter.Next())
2095   {
2096     if (!aChangesIter.Value().Validate (!isFirst))
2097     {
2098       return 1;
2099     }
2100     isFirst = Standard_False;
2101   }
2102
2103   if (aCtx->HasOpenedContext())
2104   {
2105     aCtx->CloseLocalContext();
2106   }
2107
2108   // special case for -defaults parameter.
2109   // all changed values will be set to DefaultDrawer.
2110   if (isDefaults)
2111   {
2112     const Handle(Prs3d_Drawer)& aDrawer = aCtx->DefaultDrawer();
2113
2114     if (aChangeSet->ToSetLineWidth != 0)
2115     {
2116       aDrawer->LineAspect()->SetWidth (aChangeSet->LineWidth);
2117       aDrawer->WireAspect()->SetWidth (aChangeSet->LineWidth);
2118       aDrawer->UnFreeBoundaryAspect()->SetWidth (aChangeSet->LineWidth);
2119       aDrawer->SeenLineAspect()->SetWidth (aChangeSet->LineWidth);
2120     }
2121     if (aChangeSet->ToSetColor != 0)
2122     {
2123       aDrawer->ShadingAspect()->SetColor        (aChangeSet->Color);
2124       aDrawer->LineAspect()->SetColor           (aChangeSet->Color);
2125       aDrawer->UnFreeBoundaryAspect()->SetColor (aChangeSet->Color);
2126       aDrawer->SeenLineAspect()->SetColor       (aChangeSet->Color);
2127       aDrawer->WireAspect()->SetColor           (aChangeSet->Color);
2128       aDrawer->PointAspect()->SetColor          (aChangeSet->Color);
2129     }
2130     if (aChangeSet->ToSetTypeOfLine != 0)
2131     {
2132       aDrawer->LineAspect()->SetTypeOfLine           (aChangeSet->TypeOfLine);
2133       aDrawer->WireAspect()->SetTypeOfLine           (aChangeSet->TypeOfLine);
2134       aDrawer->FreeBoundaryAspect()->SetTypeOfLine   (aChangeSet->TypeOfLine);
2135       aDrawer->UnFreeBoundaryAspect()->SetTypeOfLine (aChangeSet->TypeOfLine);
2136       aDrawer->SeenLineAspect()->SetTypeOfLine       (aChangeSet->TypeOfLine);
2137     }
2138     if (aChangeSet->ToSetTransparency != 0)
2139     {
2140       aDrawer->ShadingAspect()->SetTransparency (aChangeSet->Transparency);
2141     }
2142     if (aChangeSet->ToSetMaterial != 0)
2143     {
2144       aDrawer->ShadingAspect()->SetMaterial (aChangeSet->Material);
2145     }
2146     if (aChangeSet->ToSetShowFreeBoundary == 1)
2147     {
2148       aDrawer->SetFreeBoundaryDraw (Standard_True);
2149     }
2150     else if (aChangeSet->ToSetShowFreeBoundary == -1)
2151     {
2152       aDrawer->SetFreeBoundaryDraw (Standard_False);
2153     }
2154     if (aChangeSet->ToSetFreeBoundaryWidth != 0)
2155     {
2156       aDrawer->FreeBoundaryAspect()->SetWidth (aChangeSet->FreeBoundaryWidth);
2157     }
2158     if (aChangeSet->ToSetFreeBoundaryColor != 0)
2159     {
2160       aDrawer->FreeBoundaryAspect()->SetColor (aChangeSet->FreeBoundaryColor);
2161     }
2162
2163     // redisplay all objects in context
2164     for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
2165     {
2166       Handle(AIS_InteractiveObject)  aPrs = aPrsIter.Current();
2167       if (!aPrs.IsNull())
2168       {
2169         aCtx->Redisplay (aPrs, Standard_False);
2170       }
2171     }
2172     return 0;
2173   }
2174
2175   for (ViewTest_PrsIter aPrsIter (aNames); aPrsIter.More(); aPrsIter.Next())
2176   {
2177     const TCollection_AsciiString& aName   = aPrsIter.CurrentName();
2178     Handle(AIS_InteractiveObject)  aPrs    = aPrsIter.Current();
2179     Handle(Prs3d_Drawer)           aDrawer = aPrs->Attributes();
2180     Handle(AIS_ColoredShape) aColoredPrs;
2181     Standard_Boolean toDisplay = Standard_False;
2182     Standard_Boolean toRedisplay = Standard_False;
2183     if (aChanges.Length() > 1 || aChangeSet->ToSetVisibility == 1)
2184     {
2185       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aPrs);
2186       if (aShapePrs.IsNull())
2187       {
2188         std::cout << "Error: an object " << aName << " is not an AIS_Shape presentation!\n";
2189         return 1;
2190       }
2191       aColoredPrs = Handle(AIS_ColoredShape)::DownCast (aShapePrs);
2192       if (aColoredPrs.IsNull())
2193       {
2194         aColoredPrs = new AIS_ColoredShape (aShapePrs);
2195         aCtx->Remove (aShapePrs, Standard_False);
2196         GetMapOfAIS().UnBind2 (aName);
2197         GetMapOfAIS().Bind (aColoredPrs, aName);
2198         toDisplay = Standard_True;
2199         aShapePrs = aColoredPrs;
2200         aPrs      = aColoredPrs;
2201       }
2202     }
2203
2204     if (!aPrs.IsNull())
2205     {
2206       NCollection_Sequence<ViewerTest_AspectsChangeSet>::Iterator aChangesIter (aChanges);
2207       aChangeSet = &aChangesIter.ChangeValue();
2208       if (aChangeSet->ToSetVisibility == 1)
2209       {
2210         Handle(AIS_ColoredDrawer) aColDrawer = aColoredPrs->CustomAspects (aColoredPrs->Shape());
2211         aColDrawer->SetHidden (aChangeSet->Visibility == 0);
2212       }
2213       else if (aChangeSet->ToSetMaterial == 1)
2214       {
2215         aCtx->SetMaterial (aPrs, aChangeSet->Material, Standard_False);
2216       }
2217       else if (aChangeSet->ToSetMaterial == -1)
2218       {
2219         aCtx->UnsetMaterial (aPrs, Standard_False);
2220       }
2221       if (aChangeSet->ToSetColor == 1)
2222       {
2223         aCtx->SetColor (aPrs, aChangeSet->Color, Standard_False);
2224       }
2225       else if (aChangeSet->ToSetColor == -1)
2226       {
2227         aCtx->UnsetColor (aPrs, Standard_False);
2228       }
2229       if (aChangeSet->ToSetTransparency == 1)
2230       {
2231         aCtx->SetTransparency (aPrs, aChangeSet->Transparency, Standard_False);
2232       }
2233       else if (aChangeSet->ToSetTransparency == -1)
2234       {
2235         aCtx->UnsetTransparency (aPrs, Standard_False);
2236       }
2237       if (aChangeSet->ToSetLineWidth == 1)
2238       {
2239         aCtx->SetWidth (aPrs, aChangeSet->LineWidth, Standard_False);
2240       }
2241       else if (aChangeSet->ToSetLineWidth == -1)
2242       {
2243         aCtx->UnsetWidth (aPrs, Standard_False);
2244       }
2245       if (!aDrawer.IsNull())
2246       {
2247         if (aChangeSet->ToSetShowFreeBoundary == 1)
2248         {
2249           aDrawer->SetFreeBoundaryDraw (Standard_True);
2250           toRedisplay = Standard_True;
2251         }
2252         else if (aChangeSet->ToSetShowFreeBoundary == -1)
2253         {
2254           aDrawer->SetFreeBoundaryDraw (Standard_False);
2255           toRedisplay = Standard_True;
2256         }
2257         if (aChangeSet->ToSetFreeBoundaryWidth != 0)
2258         {
2259           Handle(Prs3d_LineAspect) aBoundaryAspect =
2260               new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2261           *aBoundaryAspect->Aspect() = *aDrawer->FreeBoundaryAspect()->Aspect();
2262           aBoundaryAspect->SetWidth (aChangeSet->FreeBoundaryWidth);
2263           aDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2264           toRedisplay = Standard_True;
2265         }
2266         if (aChangeSet->ToSetFreeBoundaryColor != 0)
2267         {
2268           Handle(Prs3d_LineAspect) aBoundaryAspect =
2269               new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0);
2270           *aBoundaryAspect->Aspect() = *aDrawer->FreeBoundaryAspect()->Aspect();
2271           aBoundaryAspect->SetColor (aChangeSet->FreeBoundaryColor);
2272           aDrawer->SetFreeBoundaryAspect (aBoundaryAspect);
2273           toRedisplay = Standard_True;
2274         }
2275         if (aChangeSet->ToSetTypeOfLine != 0)
2276         {
2277           aDrawer->LineAspect()->SetTypeOfLine           (aChangeSet->TypeOfLine);
2278           aDrawer->WireAspect()->SetTypeOfLine           (aChangeSet->TypeOfLine);
2279           aDrawer->FreeBoundaryAspect()->SetTypeOfLine   (aChangeSet->TypeOfLine);
2280           aDrawer->UnFreeBoundaryAspect()->SetTypeOfLine (aChangeSet->TypeOfLine);
2281           aDrawer->SeenLineAspect()->SetTypeOfLine       (aChangeSet->TypeOfLine);
2282           toRedisplay = Standard_True;
2283         }
2284       }
2285
2286       for (aChangesIter.Next(); aChangesIter.More(); aChangesIter.Next())
2287       {
2288         aChangeSet = &aChangesIter.ChangeValue();
2289         for (NCollection_Sequence<TopoDS_Shape>::Iterator aSubShapeIter (aChangeSet->SubShapes);
2290              aSubShapeIter.More(); aSubShapeIter.Next())
2291         {
2292           const TopoDS_Shape& aSubShape = aSubShapeIter.Value();
2293           if (aChangeSet->ToSetVisibility == 1)
2294           {
2295             Handle(AIS_ColoredDrawer) aCurColDrawer = aColoredPrs->CustomAspects (aSubShape);
2296             aCurColDrawer->SetHidden (aChangeSet->Visibility == 0);
2297           }
2298           if (aChangeSet->ToSetColor == 1)
2299           {
2300             aColoredPrs->SetCustomColor (aSubShape, aChangeSet->Color);
2301           }
2302           if (aChangeSet->ToSetLineWidth == 1)
2303           {
2304             aColoredPrs->SetCustomWidth (aSubShape, aChangeSet->LineWidth);
2305           }
2306           if (aChangeSet->ToSetColor     == -1
2307            || aChangeSet->ToSetLineWidth == -1)
2308           {
2309             aColoredPrs->UnsetCustomAspects (aSubShape, Standard_True);
2310           }
2311         }
2312       }
2313       if (toDisplay)
2314       {
2315         aCtx->Display (aPrs, Standard_False);
2316       }
2317       if (toRedisplay)
2318       {
2319         aCtx->Redisplay (aPrs, Standard_False);
2320       }
2321       else if (!aColoredPrs.IsNull())
2322       {
2323         aCtx->Redisplay (aColoredPrs, Standard_False);
2324       }
2325     }
2326   }
2327   return 0;
2328 }
2329
2330 //==============================================================================
2331 //function : VDonly2
2332 //author   : ege
2333 //purpose  : Display only a selected or named  object
2334 //           if there is no selected or named object s, nothing is done
2335 //==============================================================================
2336 static int VDonly2 (Draw_Interpretor& ,
2337                     Standard_Integer  theArgNb,
2338                     const char**      theArgVec)
2339 {
2340   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2341   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2342   if (aCtx.IsNull())
2343   {
2344     std::cerr << "Error: no active view!\n";
2345     return 1;
2346   }
2347
2348   if (aCtx->HasOpenedContext())
2349   {
2350     aCtx->CloseLocalContext();
2351   }
2352
2353   Standard_Integer anArgIter = 1;
2354   for (; anArgIter < theArgNb; ++anArgIter)
2355   {
2356     if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
2357     {
2358       break;
2359     }
2360   }
2361
2362   NCollection_Map<Handle(Standard_Transient)> aDispSet;
2363   if (anArgIter >= theArgNb)
2364   {
2365     // display only selected objects
2366     if (aCtx->NbCurrents() < 1)
2367     {
2368       return 0;
2369     }
2370
2371     for (aCtx->InitCurrent(); aCtx->MoreCurrent(); aCtx->NextCurrent())
2372     {
2373       aDispSet.Add (aCtx->Current());
2374     }
2375   }
2376   else
2377   {
2378     // display only specified objects
2379     for (; anArgIter < theArgNb; ++anArgIter)
2380     {
2381       TCollection_AsciiString aName = theArgVec[anArgIter];
2382       if (GetMapOfAIS().IsBound2 (aName))
2383       {
2384         const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
2385         if (!aShape.IsNull())
2386         {
2387           aCtx->Display (aShape, Standard_False);
2388           aDispSet.Add (aShape);
2389         }
2390       }
2391     }
2392   }
2393
2394   // weed out other objects
2395   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS()); anIter.More(); anIter.Next())
2396   {
2397     if (aDispSet.Contains (anIter.Key1()))
2398     {
2399       continue;
2400     }
2401
2402     const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2403     if (aShape.IsNull())
2404     {
2405       aCtx->Erase (aShape, Standard_False);
2406     }
2407   }
2408   return 0;
2409 }
2410
2411 //==============================================================================
2412 //function : VRemove
2413 //purpose  : Removes selected or named objects.
2414 //           If there is no selected or named objects,
2415 //           all objects in the viewer can be removed with argument -all.
2416 //           If -context is in arguments, the object is not deleted from the map of
2417 //           objects (deleted only from the current context).
2418 //==============================================================================
2419 int VRemove (Draw_Interpretor& theDI,
2420              Standard_Integer  theArgNb,
2421              const char**      theArgVec)
2422 {
2423   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2424   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2425   if (aCtx.IsNull())
2426   {
2427     std::cerr << "Error: no active view!\n";
2428     return 1;
2429   }
2430
2431   Standard_Boolean isContextOnly = Standard_False;
2432   Standard_Boolean toRemoveAll   = Standard_False;
2433   Standard_Boolean toPrintInfo   = Standard_True;
2434   Standard_Boolean toRemoveLocal = Standard_False;
2435
2436   Standard_Integer anArgIter = 1;
2437   for (; anArgIter < theArgNb; ++anArgIter)
2438   {
2439     TCollection_AsciiString anArg = theArgVec[anArgIter];
2440     anArg.LowerCase();
2441     if (anArg == "-context")
2442     {
2443       isContextOnly = Standard_True;
2444     }
2445     else if (anArg == "-all")
2446     {
2447       toRemoveAll = Standard_True;
2448     }
2449     else if (anArg == "-noinfo")
2450     {
2451       toPrintInfo = Standard_False;
2452     }
2453     else if (anArg == "-local")
2454     {
2455       toRemoveLocal = Standard_True;
2456     }
2457     else if (anUpdateTool.parseRedrawMode (anArg))
2458     {
2459       continue;
2460     }
2461     else
2462     {
2463       break;
2464     }
2465   }
2466   if (toRemoveAll
2467    && anArgIter < theArgNb)
2468   {
2469     std::cerr << "Error: wrong syntax!\n";
2470     return 1;
2471   }
2472
2473   if (toRemoveLocal && !aCtx->HasOpenedContext())
2474   {
2475     std::cerr << "Error: local selection context is not open.\n";
2476     return 1;
2477   }
2478   else if (!toRemoveLocal && aCtx->HasOpenedContext())
2479   {
2480     aCtx->CloseAllContexts (Standard_False);
2481   }
2482
2483   NCollection_List<TCollection_AsciiString> anIONameList;
2484   if (toRemoveAll)
2485   {
2486     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2487          anIter.More(); anIter.Next())
2488     {
2489       anIONameList.Append (anIter.Key2());
2490     }
2491   }
2492   else if (anArgIter < theArgNb) // removed objects names are in argument list
2493   {
2494     for (; anArgIter < theArgNb; ++anArgIter)
2495     {
2496       TCollection_AsciiString aName = theArgVec[anArgIter];
2497       if (!GetMapOfAIS().IsBound2 (aName))
2498       {
2499         theDI << aName.ToCString() << " was not bound to some object.\n";
2500         continue;
2501       }
2502
2503       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
2504       if (anIO->GetContext() != aCtx)
2505       {
2506         theDI << aName.ToCString() << " was not displayed in current context.\n";
2507         theDI << "Please activate view with this object displayed and try again.\n";
2508         continue;
2509       }
2510
2511       anIONameList.Append (aName);
2512       continue;
2513     }
2514   }
2515   else if (aCtx->NbCurrents() > 0)
2516   {
2517     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2518          anIter.More(); anIter.Next())
2519     {
2520       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2521       if (!aCtx->IsCurrent (anIO))
2522       {
2523         continue;
2524       }
2525
2526       anIONameList.Append (anIter.Key2());
2527       continue;
2528     }
2529   }
2530
2531   // Unbind all removed objects from the map of displayed IO.
2532   for (NCollection_List<TCollection_AsciiString>::Iterator anIter (anIONameList);
2533        anIter.More(); anIter.Next())
2534   {
2535     const Handle(AIS_InteractiveObject) anIO  = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anIter.Value()));
2536     aCtx->Remove (anIO, Standard_False);
2537     if (toPrintInfo)
2538     {
2539       theDI << anIter.Value().ToCString() << " was removed\n";
2540     }
2541     if (!isContextOnly)
2542     {
2543       GetMapOfAIS().UnBind2 (anIter.Value());
2544     }
2545   }
2546
2547   // Close local context if it is empty
2548   TColStd_MapOfTransient aLocalIO;
2549   if (aCtx->HasOpenedContext()
2550    && !aCtx->LocalContext()->DisplayedObjects (aLocalIO))
2551   {
2552     aCtx->CloseAllContexts (Standard_False);
2553   }
2554
2555   return 0;
2556 }
2557
2558 //==============================================================================
2559 //function : VErase
2560 //purpose  : Erase some selected or named objects
2561 //           if there is no selected or named objects, the whole viewer is erased
2562 //==============================================================================
2563 int VErase (Draw_Interpretor& theDI,
2564             Standard_Integer  theArgNb,
2565             const char**      theArgVec)
2566 {
2567   const Handle(AIS_InteractiveContext)& aCtx  = ViewerTest::GetAISContext();
2568   const Handle(V3d_View)&               aView = ViewerTest::CurrentView();
2569   ViewerTest_AutoUpdater anUpdateTool (aCtx, aView);
2570   if (aCtx.IsNull())
2571   {
2572     std::cerr << "Error: no active view!\n";
2573     return 1;
2574   }
2575
2576   const Standard_Boolean toEraseAll = TCollection_AsciiString (theArgNb > 0 ? theArgVec[0] : "") == "veraseall";
2577
2578   Standard_Integer anArgIter = 1;
2579   Standard_Boolean toEraseLocal  = Standard_False;
2580   Standard_Boolean toEraseInView = Standard_False;
2581   TColStd_SequenceOfAsciiString aNamesOfEraseIO;
2582   for (; anArgIter < theArgNb; ++anArgIter)
2583   {
2584     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2585     anArgCase.LowerCase();
2586     if (anUpdateTool.parseRedrawMode (anArgCase))
2587     {
2588       continue;
2589     }
2590     else if (anArgCase == "-local")
2591     {
2592       toEraseLocal = Standard_True;
2593     }
2594     else if (anArgCase == "-view"
2595           || anArgCase == "-inview")
2596     {
2597       toEraseInView = Standard_True;
2598     }
2599     else
2600     {
2601       aNamesOfEraseIO.Append (theArgVec[anArgIter]);
2602     }
2603   }
2604
2605   if (!aNamesOfEraseIO.IsEmpty() && toEraseAll)
2606   {
2607     std::cerr << "Error: wrong syntax, " << theArgVec[0] << " too much arguments.\n";
2608     return 1;
2609   }
2610
2611   if (toEraseLocal && !aCtx->HasOpenedContext())
2612   {
2613     std::cerr << "Error: local selection context is not open.\n";
2614     return 1;
2615   }
2616   else if (!toEraseLocal && aCtx->HasOpenedContext())
2617   {
2618     aCtx->CloseAllContexts (Standard_False);
2619   }
2620
2621   if (!aNamesOfEraseIO.IsEmpty())
2622   {
2623     // Erase named objects
2624     for (Standard_Integer anIter = 1; anIter <= aNamesOfEraseIO.Length(); ++anIter)
2625     {
2626       TCollection_AsciiString aName = aNamesOfEraseIO.Value (anIter);
2627       if (!GetMapOfAIS().IsBound2 (aName))
2628       {
2629         continue;
2630       }
2631
2632       const Handle(Standard_Transient)    anObj = GetMapOfAIS().Find2 (aName);
2633       const Handle(AIS_InteractiveObject) anIO  = Handle(AIS_InteractiveObject)::DownCast (anObj);
2634       theDI << aName.ToCString() << " ";
2635       if (!anIO.IsNull())
2636       {
2637         if (toEraseInView)
2638         {
2639           aCtx->SetViewAffinity (anIO, aView, Standard_False);
2640         }
2641         else
2642         {
2643           aCtx->Erase (anIO, Standard_False);
2644         }
2645       }
2646     }
2647   }
2648   else if (!toEraseAll && aCtx->NbCurrents() > 0)
2649   {
2650     // Erase selected objects
2651     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2652          anIter.More(); anIter.Next())
2653     {
2654       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2655       if (!anIO.IsNull()
2656        && aCtx->IsCurrent (anIO))
2657       {
2658         theDI << anIter.Key2().ToCString() << " ";
2659         if (toEraseInView)
2660         {
2661           aCtx->SetViewAffinity (anIO, aView, Standard_False);
2662         }
2663         else
2664         {
2665           aCtx->Erase (anIO, Standard_False);
2666         }
2667       }
2668     }
2669   }
2670   else
2671   {
2672     // Erase all objects
2673     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2674          anIter.More(); anIter.Next())
2675     {
2676       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2677       if (!anIO.IsNull())
2678       {
2679         if (toEraseInView)
2680         {
2681           aCtx->SetViewAffinity (anIO, aView, Standard_False);
2682         }
2683         else
2684         {
2685           aCtx->Erase (anIO, Standard_False);
2686         }
2687       }
2688     }
2689   }
2690
2691   return 0;
2692 }
2693
2694 //==============================================================================
2695 //function : VDisplayAll
2696 //author   : ege
2697 //purpose  : Display all the objects of the Map
2698 //==============================================================================
2699 static int VDisplayAll (Draw_Interpretor& ,
2700                         Standard_Integer  theArgNb,
2701                         const char**      theArgVec)
2702
2703 {
2704   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
2705   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2706   if (aCtx.IsNull())
2707   {
2708     std::cerr << "Error: no active view!\n";
2709     return 1;
2710   }
2711
2712   Standard_Integer anArgIter = 1;
2713   Standard_Boolean toDisplayLocal = Standard_False;
2714   for (; anArgIter < theArgNb; ++anArgIter)
2715   {
2716     TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2717     anArgCase.LowerCase();
2718     if (anArgCase == "-local")
2719     {
2720       toDisplayLocal = Standard_True;
2721     }
2722     else if (anUpdateTool.parseRedrawMode (anArgCase))
2723     {
2724       continue;
2725     }
2726     else
2727     {
2728       break;
2729     }
2730   }
2731   if (anArgIter < theArgNb)
2732   {
2733     std::cout << theArgVec[0] << "Error: wrong syntax\n";
2734     return 1;
2735   }
2736
2737   if (toDisplayLocal && !aCtx->HasOpenedContext())
2738   {
2739     std::cerr << "Error: local selection context is not open.\n";
2740     return 1;
2741   }
2742   else if (!toDisplayLocal && aCtx->HasOpenedContext())
2743   {
2744     aCtx->CloseLocalContext (Standard_False);
2745   }
2746
2747   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2748        anIter.More(); anIter.Next())
2749   {
2750     const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2751     aCtx->Erase (aShape, Standard_False);
2752   }
2753
2754   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2755        anIter.More(); anIter.Next())
2756   {
2757     const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2758     aCtx->Display (aShape, Standard_False);
2759   }
2760   return 0;
2761 }
2762
2763 //! Auxiliary method to find presentation
2764 inline Handle(PrsMgr_Presentation) findPresentation (const Handle(AIS_InteractiveContext)& theCtx,
2765                                                      const Handle(AIS_InteractiveObject)&  theIO,
2766                                                      const Standard_Integer                theMode)
2767 {
2768   if (theIO.IsNull())
2769   {
2770     return Handle(PrsMgr_Presentation)();
2771   }
2772
2773   if (theMode != -1)
2774   {
2775     if (theCtx->MainPrsMgr()->HasPresentation (theIO, theMode))
2776     {
2777       return theCtx->MainPrsMgr()->Presentation (theIO, theMode);
2778     }
2779   }
2780   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theIO->DisplayMode()))
2781   {
2782     return theCtx->MainPrsMgr()->Presentation (theIO, theIO->DisplayMode());
2783   }
2784   else if (theCtx->MainPrsMgr()->HasPresentation (theIO, theCtx->DisplayMode()))
2785   {
2786     return theCtx->MainPrsMgr()->Presentation (theIO, theCtx->DisplayMode());
2787   }
2788   return Handle(PrsMgr_Presentation)();
2789 }
2790
2791 enum ViewerTest_BndAction
2792 {
2793   BndAction_Hide,
2794   BndAction_Show,
2795   BndAction_Print
2796 };
2797
2798 //! Auxiliary method to print bounding box of presentation
2799 inline void bndPresentation (Draw_Interpretor&                  theDI,
2800                              const Handle(PrsMgr_Presentation)& thePrs,
2801                              const TCollection_AsciiString&     theName,
2802                              const ViewerTest_BndAction         theAction)
2803 {
2804   switch (theAction)
2805   {
2806     case BndAction_Hide:
2807     {
2808       thePrs->Presentation()->GraphicUnHighlight();
2809       break;
2810     }
2811     case BndAction_Show:
2812     {
2813       Handle(Graphic3d_Structure) aPrs (thePrs->Presentation());
2814       aPrs->CStructure()->HighlightColor.r = 0.988235f;
2815       aPrs->CStructure()->HighlightColor.g = 0.988235f;
2816       aPrs->CStructure()->HighlightColor.b = 0.988235f;
2817       aPrs->CStructure()->HighlightWithBndBox (aPrs, Standard_True);
2818       break;
2819     }
2820     case BndAction_Print:
2821     {
2822       Bnd_Box aBox = thePrs->Presentation()->MinMaxValues();
2823       gp_Pnt aMin = aBox.CornerMin();
2824       gp_Pnt aMax = aBox.CornerMax();
2825       theDI << theName  << "\n"
2826             << aMin.X() << " " << aMin.Y() << " " << aMin.Z() << " "
2827             << aMax.X() << " " << aMax.Y() << " " << aMax.Z() << "\n";
2828       break;
2829     }
2830   }
2831 }
2832
2833 //==============================================================================
2834 //function : VBounding
2835 //purpose  :
2836 //==============================================================================
2837 int VBounding (Draw_Interpretor& theDI,
2838                Standard_Integer  theArgNb,
2839                const char**      theArgVec)
2840 {
2841   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2842   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
2843   if (aCtx.IsNull())
2844   {
2845     std::cout << "Error: no active view!\n";
2846     return 1;
2847   }
2848
2849   ViewerTest_BndAction anAction = BndAction_Show;
2850   Standard_Integer     aMode    = -1;
2851
2852   Standard_Integer anArgIter = 1;
2853   for (; anArgIter < theArgNb; ++anArgIter)
2854   {
2855     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2856     anArg.LowerCase();
2857     if (anArg == "-print")
2858     {
2859       anAction = BndAction_Print;
2860     }
2861     else if (anArg == "-show")
2862     {
2863       anAction = BndAction_Show;
2864     }
2865     else if (anArg == "-hide")
2866     {
2867       anAction = BndAction_Hide;
2868     }
2869     else if (anArg == "-mode")
2870     {
2871       if (++anArgIter >= theArgNb)
2872       {
2873         std::cout << "Error: wrong syntax at " << anArg << "\n";
2874         return 1;
2875       }
2876       aMode = Draw::Atoi (theArgVec[anArgIter]);
2877     }
2878     else if (!anUpdateTool.parseRedrawMode (anArg))
2879     {
2880       break;
2881     }
2882   }
2883
2884   if (anArgIter < theArgNb)
2885   {
2886     // has a list of names
2887     for (; anArgIter < theArgNb; ++anArgIter)
2888     {
2889       TCollection_AsciiString aName = theArgVec[anArgIter];
2890       if (!GetMapOfAIS().IsBound2 (aName))
2891       {
2892         std::cout << "Error: presentation " << aName << " does not exist\n";
2893         return 1;
2894       }
2895
2896       Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
2897       Handle(PrsMgr_Presentation)   aPrs = findPresentation (aCtx, anIO, aMode);
2898       if (aPrs.IsNull())
2899       {
2900         std::cout << "Error: presentation " << aName << " does not exist\n";
2901         return 1;
2902       }
2903       bndPresentation (theDI, aPrs, aName, anAction);
2904     }
2905   }
2906   else if (aCtx->NbCurrents() > 0)
2907   {
2908     // remove all currently selected objects
2909     for (aCtx->InitCurrent(); aCtx->MoreCurrent(); aCtx->NextCurrent())
2910     {
2911       Handle(AIS_InteractiveObject) anIO = aCtx->Current();
2912       Handle(PrsMgr_Presentation)   aPrs = findPresentation (aCtx, anIO, aMode);
2913       if (!aPrs.IsNull())
2914       {
2915         bndPresentation (theDI, aPrs, GetMapOfAIS().IsBound1 (anIO) ? GetMapOfAIS().Find1 (anIO) : "", anAction);
2916       }
2917     }
2918   }
2919   else
2920   {
2921     // all objects
2922     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
2923          anIter.More(); anIter.Next())
2924     {
2925       Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
2926       Handle(PrsMgr_Presentation)   aPrs = findPresentation (aCtx, anIO, aMode);
2927       if (!aPrs.IsNull())
2928       {
2929         bndPresentation (theDI, aPrs, anIter.Key2(), anAction);
2930       }
2931     }
2932   }
2933   return 0;
2934 }
2935
2936 //==============================================================================
2937 //function : VTexture
2938 //purpose  :
2939 //==============================================================================
2940 Standard_Integer VTexture (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgv)
2941 {
2942   TCollection_AsciiString aCommandName (theArgv[0]);
2943
2944   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
2945   if (aCommandName == "vtexture")
2946   {
2947     if (theArgsNb < 2)
2948     {
2949       std::cout << theArgv[0] << ": " << " invalid arguments.\n";
2950       std::cout << "Type help for more information.\n";
2951       return 1;
2952     }
2953
2954     // look for options of vtexture command
2955     TCollection_AsciiString aParseKey;
2956     for (Standard_Integer anArgIt = 2; anArgIt < theArgsNb; ++anArgIt)
2957     {
2958       TCollection_AsciiString anArg (theArgv [anArgIt]);
2959
2960       anArg.UpperCase();
2961       if (anArg.Value (1) == '-' && !anArg.IsRealValue())
2962       {
2963         aParseKey = anArg;
2964         aParseKey.Remove (1);
2965         aParseKey.UpperCase();
2966         aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
2967         continue;
2968       }
2969
2970       if (aParseKey.IsEmpty())
2971       {
2972         continue;
2973       }
2974
2975       aMapOfArgs(aParseKey)->Append (anArg);
2976     }
2977   }
2978   else if (aCommandName == "vtexscale"
2979         || aCommandName == "vtexorigin"
2980         || aCommandName == "vtexrepeat")
2981   {
2982     // scan for parameters of vtexscale, vtexorigin, vtexrepeat commands
2983     // equal to -scale, -origin, -repeat options of vtexture command
2984     if (theArgsNb < 2 || theArgsNb > 4)
2985     {
2986       std::cout << theArgv[0] << ": " << " invalid arguments.\n";
2987       std::cout << "Type help for more information.\n";
2988       return 1;
2989     }
2990
2991     Handle(TColStd_HSequenceOfAsciiString) anArgs = new TColStd_HSequenceOfAsciiString;
2992     if (theArgsNb == 2)
2993     {
2994       anArgs->Append ("OFF");
2995     }
2996     else if (theArgsNb == 4)
2997     {
2998       anArgs->Append (TCollection_AsciiString (theArgv[2]));
2999       anArgs->Append (TCollection_AsciiString (theArgv[3]));
3000     }
3001
3002     TCollection_AsciiString anArgKey;
3003     if (aCommandName == "vtexscale")
3004     {
3005       anArgKey = "SCALE";
3006     }
3007     else if (aCommandName == "vtexorigin")
3008     {
3009       anArgKey = "ORIGIN";
3010     }
3011     else
3012     {
3013       anArgKey = "REPEAT";
3014     }
3015
3016     aMapOfArgs.Bind (anArgKey, anArgs);
3017   }
3018   else if (aCommandName == "vtexdefault")
3019   {
3020     // scan for parameters of vtexdefault command
3021     // equal to -default option of vtexture command
3022     aMapOfArgs.Bind ("DEFAULT", new TColStd_HSequenceOfAsciiString);
3023   }
3024
3025   // Check arguments for validity
3026   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
3027   for (; aMapIt.More(); aMapIt.Next())
3028   {
3029     const TCollection_AsciiString& aKey = aMapIt.Key();
3030     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
3031
3032     // -scale, -origin, -repeat: one argument "off", or two real values
3033     if ((aKey.IsEqual ("SCALE") || aKey.IsEqual ("ORIGIN") || aKey.IsEqual ("REPEAT"))
3034       && ((anArgs->Length() == 1 && anArgs->Value(1) == "OFF")
3035        || (anArgs->Length() == 2 && anArgs->Value(1).IsRealValue() && anArgs->Value(2).IsRealValue())))
3036     {
3037       continue;
3038     }
3039
3040     // -modulate: single argument "on" / "off"
3041     if (aKey.IsEqual ("MODULATE") && anArgs->Length() == 1 && (anArgs->Value(1) == "OFF" || anArgs->Value(1) == "ON"))
3042     {
3043       continue;
3044     }
3045
3046     // -default: no arguments
3047     if (aKey.IsEqual ("DEFAULT") && anArgs->IsEmpty())
3048     {
3049       continue;
3050     }
3051
3052     TCollection_AsciiString aLowerKey;
3053     aLowerKey  = "-";
3054     aLowerKey += aKey;
3055     aLowerKey.LowerCase();
3056     std::cout << theArgv[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
3057     std::cout << "Type help for more information.\n";
3058     return 1;
3059   }
3060
3061   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
3062   if (anAISContext.IsNull())
3063   {
3064     std::cout << aCommandName << ": " << " please use 'vinit' command to initialize view.\n";
3065     return 1;
3066   }
3067
3068   Standard_Integer aPreviousMode = 0;
3069
3070   ViewerTest::CurrentView()->SetSurfaceDetail (V3d_TEX_ALL);
3071
3072   TCollection_AsciiString aShapeName (theArgv[1]);
3073   Handle(AIS_InteractiveObject) anIO;
3074
3075   const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfIO = GetMapOfAIS();
3076   if (aMapOfIO.IsBound2 (aShapeName))
3077   {
3078     anIO = Handle(AIS_InteractiveObject)::DownCast (aMapOfIO.Find2 (aShapeName));
3079   }
3080
3081   if (anIO.IsNull())
3082   {
3083     std::cout << aCommandName << ": shape " << aShapeName << " does not exists.\n";
3084     return 1;
3085   }
3086
3087   Handle(AIS_TexturedShape) aTexturedIO;
3088   if (anIO->IsKind (STANDARD_TYPE (AIS_TexturedShape)))
3089   {
3090     aTexturedIO = Handle(AIS_TexturedShape)::DownCast (anIO);
3091     aPreviousMode = aTexturedIO->DisplayMode();
3092   }
3093   else
3094   {
3095     anAISContext->Remove (anIO, Standard_False);
3096     aTexturedIO = new AIS_TexturedShape (DBRep::Get (theArgv[1]));
3097     GetMapOfAIS().UnBind1 (anIO);
3098     GetMapOfAIS().UnBind2 (aShapeName);
3099     GetMapOfAIS().Bind (aTexturedIO, aShapeName);
3100   }
3101
3102   // -------------------------------------------
3103   //  Turn texturing on/off - only for vtexture
3104   // -------------------------------------------
3105
3106   if (aCommandName == "vtexture")
3107   {
3108     TCollection_AsciiString aTextureArg (theArgsNb > 2 ? theArgv[2] : "");
3109
3110     if (aTextureArg.IsEmpty())
3111     {
3112       std::cout << aCommandName << ": " << " Texture mapping disabled.\n";
3113       std::cout << "To enable it, use 'vtexture NameOfShape NameOfTexture'\n" << "\n";
3114
3115       anAISContext->SetDisplayMode (aTexturedIO, AIS_Shaded, Standard_False);
3116       if (aPreviousMode == 3)
3117       {
3118         anAISContext->RecomputePrsOnly (aTexturedIO);
3119       }
3120
3121       anAISContext->Display (aTexturedIO, Standard_True);
3122       return 0;
3123     }
3124     else if (aTextureArg.Value(1) != '-') // "-option" on place of texture argument
3125     {
3126       if (aTextureArg == "?")
3127       {
3128         TCollection_AsciiString aTextureFolder = Graphic3d_TextureRoot::TexturesFolder();
3129
3130         theDi << "\n Files in current directory : \n" << "\n";
3131         theDi.Eval ("glob -nocomplain *");
3132
3133         TCollection_AsciiString aCmnd ("glob -nocomplain ");
3134         aCmnd += aTextureFolder;
3135         aCmnd += "/* ";
3136
3137         theDi << "Files in " << aTextureFolder.ToCString() << " : \n" << "\n";
3138         theDi.Eval (aCmnd.ToCString());
3139         return 0;
3140       }
3141       else
3142       {
3143         aTexturedIO->SetTextureFileName (aTextureArg);
3144       }
3145     }
3146   }
3147
3148   // ------------------------------------
3149   //  Process other options and commands
3150   // ------------------------------------
3151
3152   Handle(TColStd_HSequenceOfAsciiString) aValues;
3153   if (aMapOfArgs.Find ("DEFAULT", aValues))
3154   {
3155     aTexturedIO->SetTextureRepeat (Standard_False);
3156     aTexturedIO->SetTextureOrigin (Standard_False);
3157     aTexturedIO->SetTextureScale  (Standard_False);
3158     aTexturedIO->EnableTextureModulate();
3159   }
3160   else
3161   {
3162     if (aMapOfArgs.Find ("SCALE", aValues))
3163     {
3164       if (aValues->Value(1) != "OFF")
3165       {
3166         aTexturedIO->SetTextureScale (Standard_True, aValues->Value(1).RealValue(), aValues->Value(2).RealValue());
3167       }
3168       else
3169       {
3170         aTexturedIO->SetTextureScale (Standard_False);
3171       }
3172     }
3173
3174     if (aMapOfArgs.Find ("ORIGIN", aValues))
3175     {
3176       if (aValues->Value(1) != "OFF")
3177       {
3178         aTexturedIO->SetTextureOrigin (Standard_True, aValues->Value(1).RealValue(), aValues->Value(2).RealValue());
3179       }
3180       else
3181       {
3182         aTexturedIO->SetTextureOrigin (Standard_False);
3183       }
3184     }
3185
3186     if (aMapOfArgs.Find ("REPEAT", aValues))
3187     {
3188       if (aValues->Value(1) != "OFF")
3189       {
3190         aTexturedIO->SetTextureRepeat (Standard_True, aValues->Value(1).RealValue(), aValues->Value(2).RealValue());
3191       }
3192       else
3193       {
3194         aTexturedIO->SetTextureRepeat (Standard_False);
3195       }
3196     }
3197
3198     if (aMapOfArgs.Find ("MODULATE", aValues))
3199     {
3200       if (aValues->Value(1) == "ON")
3201       {
3202         aTexturedIO->EnableTextureModulate();
3203       }
3204       else
3205       {
3206         aTexturedIO->DisableTextureModulate();
3207       }
3208     }
3209   }
3210
3211   if (aTexturedIO->DisplayMode() == 3 || aPreviousMode == 3)
3212   {
3213     anAISContext->RecomputePrsOnly (aTexturedIO);
3214   }
3215   else
3216   {
3217     anAISContext->SetDisplayMode (aTexturedIO, 3, Standard_False);
3218     anAISContext->Display (aTexturedIO, Standard_True);
3219     anAISContext->Update (aTexturedIO,Standard_True);
3220   }
3221
3222   return 0;
3223 }
3224
3225 //! Auxiliary method to parse transformation persistence flags
3226 inline Standard_Boolean parseTrsfPersFlag (const TCollection_AsciiString& theFlagString,
3227                                            Standard_Integer&              theFlags)
3228 {
3229   if (theFlagString == "pan")
3230   {
3231     theFlags |= Graphic3d_TMF_PanPers;
3232   }
3233   else if (theFlagString == "zoom")
3234   {
3235     theFlags |= Graphic3d_TMF_ZoomPers;
3236   }
3237   else if (theFlagString == "rotate")
3238   {
3239     theFlags |= Graphic3d_TMF_RotatePers;
3240   }
3241   else if (theFlagString == "trihedron")
3242   {
3243     theFlags = Graphic3d_TMF_TriedronPers;
3244   }
3245   else if (theFlagString == "full")
3246   {
3247     theFlags = Graphic3d_TMF_FullPers;
3248   }
3249   else if (theFlagString == "none")
3250   {
3251     theFlags = Graphic3d_TMF_None;
3252   }
3253   else
3254   {
3255     return Standard_False;
3256   }
3257
3258   return Standard_True;
3259 }
3260
3261 //==============================================================================
3262 //function : VDisplay2
3263 //author   : ege
3264 //purpose  : Display an object from its name
3265 //==============================================================================
3266 static int VDisplay2 (Draw_Interpretor& theDI,
3267                       Standard_Integer  theArgNb,
3268                       const char**      theArgVec)
3269 {
3270   if (theArgNb < 2)
3271   {
3272     std::cerr << theArgVec[0] << "Error: wrong number of arguments.\n";
3273     return 1;
3274   }
3275
3276   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
3277   if (aCtx.IsNull())
3278   {
3279     ViewerTest::ViewerInit();
3280     aCtx = ViewerTest::GetAISContext();
3281   }
3282
3283   // Parse input arguments
3284   ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
3285   Standard_Integer   isMutable      = -1;
3286   Graphic3d_ZLayerId aZLayer        = Graphic3d_ZLayerId_UNKNOWN;
3287   Standard_Boolean   toDisplayLocal = Standard_False;
3288   Standard_Boolean   toReDisplay    = Standard_False;
3289   Standard_Integer   isSelectable   = -1;
3290   Standard_Integer   anObjDispMode  = -2;
3291   Standard_Integer   anObjHighMode  = -2;
3292   Standard_Boolean   toSetTrsfPers  = Standard_False;
3293   Graphic3d_TransModeFlags aTrsfPersFlags = Graphic3d_TMF_None;
3294   gp_Pnt aTPPosition;
3295   TColStd_SequenceOfAsciiString aNamesOfDisplayIO;
3296   AIS_DisplayStatus aDispStatus = AIS_DS_None;
3297   Standard_Integer toDisplayInView = Standard_False;
3298   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3299   {
3300     const TCollection_AsciiString aName     = theArgVec[anArgIter];
3301     TCollection_AsciiString       aNameCase = aName;
3302     aNameCase.LowerCase();
3303     if (anUpdateTool.parseRedrawMode (aName))
3304     {
3305       continue;
3306     }
3307     else if (aNameCase == "-mutable")
3308     {
3309       isMutable = 1;
3310     }
3311     else if (aNameCase == "-neutral")
3312     {
3313       aDispStatus = AIS_DS_Displayed;
3314     }
3315     else if (aNameCase == "-immediate"
3316           || aNameCase == "-top")
3317     {
3318       aZLayer = Graphic3d_ZLayerId_Top;
3319     }
3320     else if (aNameCase == "-topmost")
3321     {
3322       aZLayer = Graphic3d_ZLayerId_Topmost;
3323     }
3324     else if (aNameCase == "-osd"
3325           || aNameCase == "-toposd"
3326           || aNameCase == "-overlay")
3327     {
3328       aZLayer = Graphic3d_ZLayerId_TopOSD;
3329     }
3330     else if (aNameCase == "-botosd"
3331           || aNameCase == "-underlay")
3332     {
3333       aZLayer = Graphic3d_ZLayerId_BotOSD;
3334     }
3335     else if (aNameCase == "-select"
3336           || aNameCase == "-selectable")
3337     {
3338       isSelectable = 1;
3339     }
3340     else if (aNameCase == "-noselect"
3341           || aNameCase == "-noselection")
3342     {
3343       isSelectable = 0;
3344     }
3345     else if (aNameCase == "-dispmode"
3346           || aNameCase == "-displaymode")
3347     {
3348       if (++anArgIter >= theArgNb)
3349       {
3350         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3351         return 1;
3352       }
3353
3354       anObjDispMode = Draw::Atoi (theArgVec [anArgIter]);
3355     }
3356     else if (aNameCase == "-highmode"
3357           || aNameCase == "-highlightmode")
3358     {
3359       if (++anArgIter >= theArgNb)
3360       {
3361         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3362         return 1;
3363       }
3364
3365       anObjHighMode = Draw::Atoi (theArgVec [anArgIter]);
3366     }
3367     else if (aNameCase == "-3d")
3368     {
3369       toSetTrsfPers  = Standard_True;
3370       aTrsfPersFlags = Graphic3d_TMF_None;
3371     }
3372     else if (aNameCase == "-2d")
3373     {
3374       toSetTrsfPers  = Standard_True;
3375       aTrsfPersFlags = Graphic3d_TMF_2d;
3376     }
3377     else if (aNameCase == "-2dtopdown")
3378     {
3379       toSetTrsfPers  = Standard_True;
3380       aTrsfPersFlags = Graphic3d_TMF_2d | Graphic3d_TMF_2d_IsTopDown;
3381     }
3382     else if (aNameCase == "-trsfpers"
3383           || aNameCase == "-pers")
3384     {
3385       if (++anArgIter >= theArgNb)
3386       {
3387         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3388         return 1;
3389       }
3390
3391       toSetTrsfPers  = Standard_True;
3392       aTrsfPersFlags = Graphic3d_TMF_None;
3393       TCollection_AsciiString aPersFlags (theArgVec [anArgIter]);
3394       aPersFlags.LowerCase();
3395       for (Standard_Integer aParserPos = aPersFlags.Search ("|");; aParserPos = aPersFlags.Search ("|"))
3396       {
3397         if (aParserPos == -1)
3398         {
3399           if (!parseTrsfPersFlag (aPersFlags, aTrsfPersFlags))
3400           {
3401             std::cerr << "Error: wrong transform persistence flags " << theArgVec [anArgIter] << ".\n";
3402             return 1;
3403           }
3404           break;
3405         }
3406
3407         TCollection_AsciiString anOtherFlags = aPersFlags.Split (aParserPos - 1);
3408         if (!parseTrsfPersFlag (aPersFlags, aTrsfPersFlags))
3409         {
3410           std::cerr << "Error: wrong transform persistence flags " << theArgVec [anArgIter] << ".\n";
3411           return 1;
3412         }
3413         aPersFlags = anOtherFlags;
3414       }
3415     }
3416     else if (aNameCase == "-trsfperspos"
3417           || aNameCase == "-perspos")
3418     {
3419       if (anArgIter + 2 >= theArgNb)
3420       {
3421         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3422         return 1;
3423       }
3424
3425       TCollection_AsciiString aX (theArgVec[++anArgIter]);
3426       TCollection_AsciiString aY (theArgVec[++anArgIter]);
3427       TCollection_AsciiString aZ = "0";
3428       if (!aX.IsIntegerValue()
3429        || !aY.IsIntegerValue())
3430       {
3431         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3432         return 1;
3433       }
3434       if (anArgIter + 1 < theArgNb)
3435       {
3436         TCollection_AsciiString aTemp = theArgVec[anArgIter + 1];
3437         if (aTemp.IsIntegerValue())
3438         {
3439           aZ = aTemp;
3440           ++anArgIter;
3441         }
3442       }
3443       aTPPosition.SetCoord (aX.IntegerValue(), aY.IntegerValue(), aZ.IntegerValue());
3444     }
3445     else if (aNameCase == "-layer")
3446     {
3447       if (++anArgIter >= theArgNb)
3448       {
3449         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3450         return 1;
3451       }
3452
3453       TCollection_AsciiString aValue (theArgVec[anArgIter]);
3454       if (!aValue.IsIntegerValue())
3455       {
3456         std::cerr << "Error: wrong syntax at " << aName << ".\n";
3457         return 1;
3458       }
3459
3460       aZLayer = aValue.IntegerValue();
3461     }
3462     else if (aNameCase == "-view"
3463           || aNameCase == "-inview")
3464     {
3465       toDisplayInView = Standard_True;
3466     }
3467     else if (aNameCase == "-local")
3468     {
3469       aDispStatus = AIS_DS_Temporary;
3470       toDisplayLocal = Standard_True;
3471     }
3472     else if (aNameCase == "-redisplay")
3473     {
3474       toReDisplay = Standard_True;
3475     }
3476     else
3477     {
3478       aNamesOfDisplayIO.Append (aName);
3479     }
3480   }
3481
3482   if (aNamesOfDisplayIO.IsEmpty())
3483   {
3484     std::cerr << theArgVec[0] << "Error: wrong number of arguments.\n";
3485     return 1;
3486   }
3487
3488   // Prepare context for display
3489   if (toDisplayLocal && !aCtx->HasOpenedContext())
3490   {
3491     aCtx->OpenLocalContext (Standard_False);
3492   }
3493   else if (!toDisplayLocal && aCtx->HasOpenedContext())
3494   {
3495     aCtx->CloseAllContexts (Standard_False);
3496   }
3497
3498   // Display interactive objects
3499   for (Standard_Integer anIter = 1; anIter <= aNamesOfDisplayIO.Length(); ++anIter)
3500   {
3501     const TCollection_AsciiString& aName = aNamesOfDisplayIO.Value(anIter);
3502
3503     if (!GetMapOfAIS().IsBound2 (aName))
3504     {
3505       // create the AIS_Shape from a name
3506       const Handle(AIS_InteractiveObject) aShape = GetAISShapeFromName (aName.ToCString());
3507       if (!aShape.IsNull())
3508       {
3509         if (isMutable != -1)
3510         {
3511           aShape->SetMutable (isMutable == 1);
3512         }
3513         if (aZLayer != Graphic3d_ZLayerId_UNKNOWN)
3514         {
3515           aShape->SetZLayer (aZLayer);
3516         }
3517         if (toSetTrsfPers)
3518         {
3519           aShape->SetTransformPersistence (aTrsfPersFlags, aTPPosition);
3520         }
3521         if (anObjDispMode != -2)
3522         {
3523           aShape->SetDisplayMode (anObjDispMode);
3524         }
3525         if (anObjHighMode != -2)
3526         {
3527           aShape->SetHilightMode (anObjHighMode);
3528         }
3529         if (!toDisplayLocal)
3530           GetMapOfAIS().Bind (aShape, aName);
3531
3532         Standard_Integer aDispMode = aShape->HasDisplayMode()
3533                                    ? aShape->DisplayMode()
3534                                    : (aShape->AcceptDisplayMode (aCtx->DisplayMode())
3535                                     ? aCtx->DisplayMode()
3536                                     : 0);
3537         Standard_Integer aSelMode = -1;
3538         if ( isSelectable ==  1
3539          || (isSelectable == -1
3540           && aCtx->GetAutoActivateSelection()
3541           && aShape->GetTransformPersistenceMode() == 0))
3542         {
3543           aSelMode = aShape->HasSelectionMode() ? aShape->SelectionMode() : -1;
3544         }
3545
3546         aCtx->Display (aShape, aDispMode, aSelMode,
3547                        Standard_False, aShape->AcceptShapeDecomposition(),
3548                        aDispStatus);
3549         if (toDisplayInView)
3550         {
3551           for (aCtx->CurrentViewer()->InitDefinedViews(); aCtx->CurrentViewer()->MoreDefinedViews(); aCtx->CurrentViewer()->NextDefinedViews())
3552           {
3553             aCtx->SetViewAffinity (aShape, aCtx->CurrentViewer()->DefinedView(), Standard_False);
3554           }
3555           aCtx->SetViewAffinity (aShape, ViewerTest::CurrentView(), Standard_True);
3556         }
3557       }
3558       else
3559       {
3560         std::cerr << "Error: object with name '" << aName << "' does not exist!\n";
3561       }
3562       continue;
3563     }
3564
3565     Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (aName));
3566     if (isMutable != -1)
3567     {
3568       aShape->SetMutable (isMutable == 1);
3569     }
3570     if (aZLayer != Graphic3d_ZLayerId_UNKNOWN)
3571     {
3572       aShape->SetZLayer (aZLayer);
3573     }
3574     if (toSetTrsfPers)
3575     {
3576       aShape->SetTransformPersistence (aTrsfPersFlags, aTPPosition);
3577     }
3578     if (anObjDispMode != -2)
3579     {
3580       aShape->SetDisplayMode (anObjDispMode);
3581     }
3582     if (anObjHighMode != -2)
3583     {
3584       aShape->SetHilightMode (anObjHighMode);
3585     }
3586     Standard_Integer aDispMode = aShape->HasDisplayMode()
3587                                 ? aShape->DisplayMode()
3588                                 : (aShape->AcceptDisplayMode (aCtx->DisplayMode())
3589                                 ? aCtx->DisplayMode()
3590                                 : 0);
3591     Standard_Integer aSelMode = -1;
3592     if ( isSelectable ==  1
3593      || (isSelectable == -1
3594       && aCtx->GetAutoActivateSelection()
3595       && aShape->GetTransformPersistenceMode() == 0))
3596     {
3597       aSelMode = aShape->HasSelectionMode() ? aShape->SelectionMode() : -1;
3598     }
3599
3600     if (aShape->Type() == AIS_KOI_Datum)
3601     {
3602       aCtx->Display (aShape, Standard_False);
3603     }
3604     else
3605     {
3606       theDI << "Display " << aName.ToCString() << "\n";
3607
3608       // update the Shape in the AIS_Shape
3609       TopoDS_Shape      aNewShape = GetShapeFromName (aName.ToCString());
3610       Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast(aShape);
3611       if (!aShapePrs.IsNull())
3612       {
3613         if (!aShapePrs->Shape().IsEqual (aNewShape))
3614         {
3615           toReDisplay = Standard_True;
3616         }
3617         aShapePrs->Set (aNewShape);
3618       }
3619       if (toReDisplay)
3620       {
3621         aCtx->Redisplay (aShape, Standard_False);
3622       }
3623
3624       if (aSelMode == -1)
3625       {
3626         aCtx->Erase (aShape);
3627       }
3628       aCtx->Display (aShape, aDispMode, aSelMode,
3629                      Standard_False, aShape->AcceptShapeDecomposition(),
3630                      aDispStatus);
3631       if (toDisplayInView)
3632       {
3633         aCtx->SetViewAffinity (aShape, ViewerTest::CurrentView(), Standard_True);
3634       }
3635     }
3636   }
3637
3638   return 0;
3639 }
3640
3641 //===============================================================================================
3642 //function : VUpdate
3643 //purpose  :
3644 //===============================================================================================
3645 static int VUpdate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
3646 {
3647   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
3648   if (aContextAIS.IsNull())
3649   {
3650     std::cout << theArgVec[0] << "AIS context is not available.\n";
3651     return 1;
3652   }
3653
3654   if (theArgsNb < 2)
3655   {
3656     std::cout << theArgVec[0] << ": insufficient arguments. Type help for more information.\n";
3657     return 1;
3658   }
3659
3660   const ViewerTest_DoubleMapOfInteractiveAndName& anAISMap = GetMapOfAIS();
3661
3662   AIS_ListOfInteractive aListOfIO;
3663
3664   for (int anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
3665   {
3666     TCollection_AsciiString aName = TCollection_AsciiString (theArgVec[anArgIt]);
3667
3668     Handle(AIS_InteractiveObject) anAISObj;
3669     if (anAISMap.IsBound2 (aName))
3670