0025198: Draw Harness - add -noupdate option to vsetlocation command
authorkgv <kgv@opencascade.com>
Thu, 18 Sep 2014 11:16:45 +0000 (15:16 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 18 Sep 2014 11:17:44 +0000 (15:17 +0400)
Add sample for demonstrating display of multiple objects, evaluating viewer performance, and scene animation

cosmetics

samples/tcl/spheres.tcl [new file with mode: 0644]
src/ViewerTest/FILES
src/ViewerTest/ViewerTest.cxx
src/ViewerTest/ViewerTest_AutoUpdater.cxx [new file with mode: 0644]
src/ViewerTest/ViewerTest_AutoUpdater.hxx [new file with mode: 0644]
src/ViewerTest/ViewerTest_ObjectCommands.cxx

diff --git a/samples/tcl/spheres.tcl b/samples/tcl/spheres.tcl
new file mode 100644 (file)
index 0000000..fdf88ed
--- /dev/null
@@ -0,0 +1,142 @@
+# test performance of display of heavy scene involving multiple interactive
+# objects, on example of 1000 spheres
+
+pload MODELING
+pload VISUALIZATION
+
+vinit View1 w=1024 h=1024
+vclear
+
+# parameter NB defines number of spheres by each coordinate
+set NB 10
+puts "Creating [expr $NB * $NB * $NB] spheres..."
+set slist {}
+for {set i 0} {$i < $NB} {incr i} {
+  for {set j 0} {$j < $NB} {incr j} {
+    for {set k 0} {$k < $NB} {incr k} {
+      psphere s$i$j$k 1.
+      lappend slist s$i$j$k
+      ttranslate s$i$j$k 3.*$i 3.*$j 3.*$k
+    }
+  }
+}
+
+puts "Measuring FPS of display of spheres as separate objects..."
+vaxo
+vsetdispmode 1
+eval vdisplay $slist
+vfit
+
+# measure FPS
+puts [set fps_separate [vfps]]
+vclear
+
+puts "Measuring FPS of display of spheres as single object..."
+eval compound $slist c
+vdisplay c
+
+# measure FPS
+puts [set fps_compound [vfps]]
+vclear
+
+# redisplay individual spheres, trying to avoid unnecessary internal updates
+#vfrustumculling 0 ;# try to disable updates of frustum culling structures
+eval vdisplay -mutable $slist
+
+# auxiliary procedure to make random update of variable
+proc upd {theValueName theDeltaName theTime theToRand} {
+  upvar $theValueName aValue
+  upvar $theDeltaName aDelta
+
+  # set colors to corner spheres
+  if { $theToRand == 1 } {
+    set aValue [expr $aValue + $aDelta * $theTime / 100.0]
+    set aDelta [expr 0.5 * (rand() - 0.5)]
+    return $aValue
+  }
+
+  set aRes [expr $aValue + $aDelta * $theTime / 100.0]
+}
+
+# move corner spheres in cycle
+proc animateSpheres {{theDuration 10.0}} {
+  set nb [expr $::NB - 1]
+
+  # set colors to corner spheres
+  for {set i 0} {$i < $::NB} {incr i $nb} {
+    for {set j 0} {$j < $::NB} {incr j $nb} {
+      for {set k 0} {$k < $::NB} {incr k $nb} {
+#       vaspects -noupdate s$i$j$k -setcolor red -setmaterial plastic
+        vaspects -noupdate s$i$j$k -setcolor red
+        set x$i$j$k  0.0
+        set y$i$j$k  0.0
+        set z$i$j$k  0.0
+        set dx$i$j$k 0.0
+        set dy$i$j$k 0.0
+        set dz$i$j$k 0.0
+      }
+    }
+  }
+
+  set aDuration 0.0
+  set aPrevRand 0.0
+  set aTimeFrom [clock clicks -milliseconds]
+  uplevel #0 chrono anAnimTimer reset
+  uplevel #0 chrono anAnimTimer start
+  set toRand 1
+  for {set aFrameIter 1} { $aFrameIter > 0 } {incr aFrameIter} {
+    set aCurrTime [expr [clock clicks -milliseconds] - $aTimeFrom]
+    if { $aCurrTime >= [expr $theDuration * 1000.0] } {
+      puts "Nb Frames: $aFrameIter"
+      puts "Duration:  [expr $aCurrTime * 0.001] s"
+      set fps [expr ($aFrameIter - 1) / ($aDuration * 0.001) ]
+      puts "FPS:       $fps"
+      uplevel #0 chrono anAnimTimer stop
+      uplevel #0 chrono anAnimTimer show
+      return $fps
+    }
+
+    set aRandTime [expr $aCurrTime - $aPrevRand]
+    if { $aRandTime > 1000 } {
+      set toRand 1
+      set aPrevRand $aCurrTime
+    }
+
+    #puts "PTS: $aCurrTime ms"
+    for {set i 0} {$i < $::NB} {incr i $nb} {
+      for {set j 0} {$j < $::NB} {incr j $nb} {
+        for {set k 0} {$k < $::NB} {incr k $nb} {
+          uplevel #0 vsetlocation -noupdate s$i$j$k [upd x$i$j$k dx$i$j$k $aRandTime $toRand] [upd y$i$j$k dy$i$j$k $aRandTime $toRand] [upd z$i$j$k dz$i$j$k $aRandTime $toRand] 
+        }
+      }
+    }
+    uplevel #0 vrepaint
+    set aDuration [expr [clock clicks -milliseconds] - $aTimeFrom]
+    set toRand 0
+
+    # sleep 1 ms allowing the user to interact with the viewer
+    after 1 set waiter 1
+    vwait waiter
+  }
+}
+
+puts "Animating movements of corner spheres (10 sec)..."
+puts "(you can interact with the view during the process)"
+set fps_animation [animateSpheres 10.0]
+
+puts ""
+puts "Performance counters (FPS = \"Frames per second\"):"
+puts ""
+puts "Spheres as separate interactive objects:"
+puts "  Actual FPS: [lindex $fps_separate 1]"
+puts "  FPS estimate by CPU load: [expr 1000. / [lindex $fps_separate 3]]"
+puts ""
+puts "Spheres as one interactive object (compound):"
+puts "  Actual FPS: [lindex $fps_compound 1]"
+puts "  FPS estimate by CPU load: [expr 1000. / [lindex $fps_compound 3]]"
+puts ""
+puts "Animation FPS: $fps_animation"
+puts ""
+puts "Scene contains [lindex [trinfo c] 3] triangles"
+puts ""
+puts "Print 'animateSpheres 10.0' to restart animation"
\ No newline at end of file
index 066ac39..005c128 100755 (executable)
@@ -1,5 +1,7 @@
 EXTERNLIB
 ViewerTest_CMPLRS.edl
+ViewerTest_AutoUpdater.hxx
+ViewerTest_AutoUpdater.cxx
 ViewerTest_AviCommands.cxx
 ViewerTest_ViewerCommands.cxx
 ViewerTest_RelationCommands.cxx
index 1edd03e..210a3d0 100644 (file)
@@ -25,6 +25,7 @@
 #include <Standard_Stream.hxx>
 
 #include <ViewerTest.hxx>
+
 #include <TopLoc_Location.hxx>
 #include <TopTools_HArray1OfShape.hxx>
 #include <TColStd_HArray1OfTransient.hxx>
 #include <Prs3d_ShadingAspect.hxx>
 #include <Prs3d_IsoAspect.hxx>
 #include <TopTools_MapOfShape.hxx>
+#include <ViewerTest_AutoUpdater.hxx>
 
 #include <stdio.h>
 
 #include <Draw_Interpretor.hxx>
 #include <TCollection_AsciiString.hxx>
 #include <Draw_PluginMacro.hxx>
-#include <ViewerTest.hxx>
 
 // avoid warnings on 'extern "C"' functions returning C++ classes
 #ifdef WNT
@@ -84,34 +85,6 @@ extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
 #define DEFAULT_COLOR    Quantity_NOC_GOLDENROD
 #define DEFAULT_MATERIAL Graphic3d_NOM_BRASS
 
-enum ViewerTest_RedrawMode
-{
-  ViewerTest_RM_Auto = -1,
-  ViewerTest_RM_RedrawForce,
-  ViewerTest_RM_RedrawSuppress
-};
-
-//! Auxiliary method to parse redraw mode argument
-static Standard_Boolean parseRedrawMode (const TCollection_AsciiString& theArg,
-                                         ViewerTest_RedrawMode&         theMode)
-{
-  TCollection_AsciiString anArgCase (theArg);
-  anArgCase.LowerCase();
-  if (anArgCase == "-update"
-   || anArgCase == "-redraw")
-  {
-    theMode = ViewerTest_RM_RedrawForce;
-    return Standard_True;
-  }
-  else if (anArgCase == "-noupdate"
-        || anArgCase == "-noredraw")
-  {
-    theMode = ViewerTest_RM_RedrawSuppress;
-    return Standard_True;
-  }
-  return Standard_False;
-}
-
 //=======================================================================
 //function : GetColorFromName
 //purpose  : get the Quantity_NameOfColor from a string
@@ -1313,17 +1286,17 @@ static int VSetInteriorStyle (Draw_Interpretor& theDI,
                               const char**      theArgVec)
 {
   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx.IsNull())
   {
     std::cerr << "Error: no active view!\n";
     return 1;
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-  Standard_Integer      anArgIter = 1;
+  Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
-    if (!parseRedrawMode (theArgVec[anArgIter], aToUpdate))
+    if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
     {
       break;
     }
@@ -1397,15 +1370,6 @@ static int VSetInteriorStyle (Draw_Interpretor& theDI,
       aCtx->RecomputePrsOnly (anIO, Standard_False, Standard_True);
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
   return 0;
 }
 
@@ -1490,19 +1454,19 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
 {
   TCollection_AsciiString aCmdName (theArgVec[0]);
   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx.IsNull())
   {
     std::cerr << "Error: no active view!\n";
     return 1;
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-  Standard_Integer      anArgIter = 1;
+  Standard_Integer anArgIter = 1;
   NCollection_Sequence<TCollection_AsciiString> aNames;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
     TCollection_AsciiString anArg = theArgVec[anArgIter];
-    if (parseRedrawMode (anArg, aToUpdate))
+    if (anUpdateTool.parseRedrawMode (anArg))
     {
       continue;
     }
@@ -1885,15 +1849,6 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/,
       }
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
   return 0;
 }
 
@@ -1908,6 +1863,7 @@ static int VDonly2 (Draw_Interpretor& ,
                     const char**      theArgVec)
 {
   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx.IsNull())
   {
     std::cerr << "Error: no active view!\n";
@@ -1918,12 +1874,11 @@ static int VDonly2 (Draw_Interpretor& ,
   {
     aCtx->CloseLocalContext();
   }
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
 
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
-    if (!parseRedrawMode (theArgVec[anArgIter], aToUpdate))
+    if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
     {
       break;
     }
@@ -1986,16 +1941,6 @@ static int VDonly2 (Draw_Interpretor& ,
       TheNISContext()->Erase (aShape);
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2011,18 +1956,19 @@ int VRemove (Draw_Interpretor& theDI,
              Standard_Integer  theArgNb,
              const char**      theArgVec)
 {
-  if (a3DView().IsNull())
+  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
+  if (aCtx.IsNull())
   {
-    std::cout << "Error: wrong syntax!\n";
+    std::cout << "Error: no active view!\n";
     return 1;
   }
 
-  TheAISContext()->CloseAllContexts (Standard_False);
+  aCtx->CloseAllContexts (Standard_False);
 
-  ViewerTest_RedrawMode aToUpdate     = ViewerTest_RM_Auto;
-  Standard_Boolean      isContextOnly = Standard_False;
-  Standard_Boolean      toRemoveAll   = Standard_False;
-  Standard_Boolean      toPrintInfo   = Standard_True;
+  Standard_Boolean isContextOnly = Standard_False;
+  Standard_Boolean toRemoveAll   = Standard_False;
+  Standard_Boolean toPrintInfo   = Standard_True;
 
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
@@ -2041,7 +1987,7 @@ int VRemove (Draw_Interpretor& theDI,
     {
       toPrintInfo = Standard_False;
     }
-    else if (!parseRedrawMode (anArg, aToUpdate))
+    else if (!anUpdateTool.parseRedrawMode (anArg))
     {
       break;
     }
@@ -2078,7 +2024,7 @@ int VRemove (Draw_Interpretor& theDI,
       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (aTransientObj);
       if (!anIO.IsNull())
       {
-        if (anIO->GetContext() != TheAISContext())
+        if (anIO->GetContext() != aCtx)
         {
           theDI << aName.ToCString() << " was not displayed in current context.\n";
           theDI << "Please activate view with this object displayed and try again.\n";
@@ -2096,7 +2042,7 @@ int VRemove (Draw_Interpretor& theDI,
       }
     }
   }
-  else if (TheAISContext()->NbCurrents() > 0
+  else if (aCtx->NbCurrents() > 0
         || TheNISContext()->GetSelected().Extent() > 0)
   {
     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
@@ -2105,7 +2051,7 @@ int VRemove (Draw_Interpretor& theDI,
       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
       if (!anIO.IsNull())
       {
-        if (!TheAISContext()->IsCurrent (anIO))
+        if (!aCtx->IsCurrent (anIO))
         {
           continue;
         }
@@ -2134,7 +2080,7 @@ int VRemove (Draw_Interpretor& theDI,
     const Handle(AIS_InteractiveObject) anIO  = Handle(AIS_InteractiveObject)::DownCast (GetMapOfAIS().Find2 (anIter.Value()));
     if (!anIO.IsNull())
     {
-      TheAISContext()->Remove (anIO, Standard_False);
+      aCtx->Remove (anIO, Standard_False);
       if (toPrintInfo)
       {
         theDI << anIter.Value().ToCString() << " was removed\n";
@@ -2157,16 +2103,6 @@ int VRemove (Draw_Interpretor& theDI,
       GetMapOfAIS().UnBind2 (anIter.Value());
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2179,20 +2115,21 @@ int VErase (Draw_Interpretor& theDI,
             Standard_Integer  theArgNb,
             const char**      theArgVec)
 {
-  if (a3DView().IsNull())
+  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
+  if (aCtx.IsNull())
   {
     std::cout << "Error: no active view!\n";
     return 1;
   }
-  TheAISContext()->CloseAllContexts (Standard_False);
+  aCtx->CloseAllContexts (Standard_False);
 
-  ViewerTest_RedrawMode  aToUpdate  = ViewerTest_RM_Auto;
   const Standard_Boolean toEraseAll = TCollection_AsciiString (theArgNb > 0 ? theArgVec[0] : "") == "veraseall";
 
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
-    if (!parseRedrawMode (theArgVec[anArgIter], aToUpdate))
+    if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
     {
       break;
     }
@@ -2220,7 +2157,7 @@ int VErase (Draw_Interpretor& theDI,
       theDI << aName.ToCString() << " ";
       if (!anIO.IsNull())
       {
-        TheAISContext()->Erase (anIO, Standard_False);
+        aCtx->Erase (anIO, Standard_False);
       }
       else
       {
@@ -2233,7 +2170,7 @@ int VErase (Draw_Interpretor& theDI,
     }
   }
   else if (!toEraseAll
-        && TheAISContext()->NbCurrents() > 0)
+        && aCtx->NbCurrents() > 0)
   {
     // remove all currently selected objects
     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
@@ -2241,10 +2178,10 @@ int VErase (Draw_Interpretor& theDI,
     {
       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
       if (!anIO.IsNull()
-       && TheAISContext()->IsCurrent (anIO))
+       && aCtx->IsCurrent (anIO))
       {
         theDI << anIter.Key2().ToCString() << " ";
-        TheAISContext()->Erase (anIO, Standard_False);
+        aCtx->Erase (anIO, Standard_False);
       }
     }
   }
@@ -2257,7 +2194,7 @@ int VErase (Draw_Interpretor& theDI,
       const Handle(AIS_InteractiveObject) anIO = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
       if (!anIO.IsNull())
       {
-        TheAISContext()->Erase (anIO, Standard_False);
+        aCtx->Erase (anIO, Standard_False);
       }
       else
       {
@@ -2269,16 +2206,6 @@ int VErase (Draw_Interpretor& theDI,
       }
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2292,18 +2219,18 @@ static int VDisplayAll (Draw_Interpretor& ,
                         const char**      theArgVec)
 
 {
-  if (a3DView().IsNull())
+  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
+  if (aCtx.IsNull())
   {
     std::cout << "Error: no active view!\n";
     return 1;
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
   {
-    if (!parseRedrawMode (theArgVec[anArgIter], aToUpdate))
+    if (!anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
     {
       break;
     }
@@ -2314,9 +2241,9 @@ static int VDisplayAll (Draw_Interpretor& ,
     return 1;
   }
 
-  if (TheAISContext()->HasOpenedContext())
+  if (aCtx->HasOpenedContext())
   {
-    TheAISContext()->CloseLocalContext();
+    aCtx->CloseLocalContext();
   }
 
   for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (GetMapOfAIS());
@@ -2325,7 +2252,7 @@ static int VDisplayAll (Draw_Interpretor& ,
     if (anIter.Key1()->IsKind (STANDARD_TYPE(AIS_InteractiveObject)))
     {
       const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
-      TheAISContext()->Erase (aShape, Standard_False);
+      aCtx->Erase (aShape, Standard_False);
     }
     else if (anIter.Key1()->IsKind(STANDARD_TYPE(NIS_InteractiveObject)))
     {
@@ -2340,7 +2267,7 @@ static int VDisplayAll (Draw_Interpretor& ,
     if (anIter.Key1()->IsKind (STANDARD_TYPE(AIS_InteractiveObject)))
     {
       const Handle(AIS_InteractiveObject) aShape = Handle(AIS_InteractiveObject)::DownCast (anIter.Key1());
-      TheAISContext()->Display (aShape, Standard_False);
+      aCtx->Display (aShape, Standard_False);
     }
     else if (anIter.Key1()->IsKind (STANDARD_TYPE(NIS_InteractiveObject)))
     {
@@ -2348,16 +2275,6 @@ static int VDisplayAll (Draw_Interpretor& ,
       TheNISContext()->Display (aShape);
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2436,15 +2353,15 @@ int VBounding (Draw_Interpretor& theDI,
                const char**      theArgVec)
 {
   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx.IsNull())
   {
     std::cout << "Error: no active view!\n";
     return 1;
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-  ViewerTest_BndAction  anAction  = BndAction_Show;
-  Standard_Integer      aMode     = -1;
+  ViewerTest_BndAction anAction = BndAction_Show;
+  Standard_Integer     aMode    = -1;
 
   Standard_Integer anArgIter = 1;
   for (; anArgIter < theArgNb; ++anArgIter)
@@ -2472,7 +2389,7 @@ int VBounding (Draw_Interpretor& theDI,
       }
       aMode = Draw::Atoi (theArgVec[anArgIter]);
     }
-    else if (!parseRedrawMode (anArg, aToUpdate))
+    else if (!anUpdateTool.parseRedrawMode (anArg))
     {
       break;
     }
@@ -2500,7 +2417,7 @@ int VBounding (Draw_Interpretor& theDI,
       bndPresentation (theDI, aPrs, aName, anAction);
     }
   }
-  else if (TheAISContext()->NbCurrents() > 0)
+  else if (aCtx->NbCurrents() > 0)
   {
     // remove all currently selected objects
     for (aCtx->InitCurrent(); aCtx->MoreCurrent(); aCtx->NextCurrent())
@@ -2527,16 +2444,6 @@ int VBounding (Draw_Interpretor& theDI,
       }
     }
   }
-
-  // update the screen and redraw the view
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    TheAISContext()->UpdateCurrentViewer();
-  }
-
   return 0;
 }
 
@@ -2838,32 +2745,33 @@ static int VDisplay2 (Draw_Interpretor& theDI,
                       Standard_Integer  theArgNb,
                       const char**      theArgVec)
 {
+  Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
   if (theArgNb < 2)
   {
     std::cout << theArgVec[0] << "Error: wrong syntax!\n";
     return 1;
   }
-  else if (a3DView().IsNull())
+  else if (aCtx.IsNull())
   {
     ViewerTest::ViewerInit();
     std::cout << "Command vinit should be called before!\n";
     // return 1;
+    aCtx = ViewerTest::GetAISContext();
   }
 
-  const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aCtx, ViewerTest::CurrentView());
   if (aCtx->HasOpenedContext())
   {
     aCtx->CloseLocalContext();
   }
 
-  ViewerTest_RedrawMode aToUpdate = ViewerTest_RM_Auto;
-  Standard_Integer      isMutable = -1;
+  Standard_Integer isMutable = -1;
   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
   {
     const TCollection_AsciiString aName     = theArgVec[anArgIter];
     TCollection_AsciiString       aNameCase = aName;
     aNameCase.LowerCase();
-    if (parseRedrawMode (aName, aToUpdate))
+    if (anUpdateTool.parseRedrawMode (aName))
     {
       continue;
     }
@@ -2923,15 +2831,6 @@ static int VDisplay2 (Draw_Interpretor& theDI,
       TheNISContext()->Display (aShape);
     }
   }
-
-  const Standard_Boolean isAutoUpdate = a3DView()->SetImmediateUpdate (Standard_False);
-  a3DView()->SetImmediateUpdate (isAutoUpdate);
-  if ((isAutoUpdate && aToUpdate != ViewerTest_RM_RedrawSuppress)
-   || aToUpdate == ViewerTest_RM_RedrawForce)
-  {
-    // update the screen and redraw the view
-    aCtx->UpdateCurrentViewer();
-  }
   return 0;
 }
 
diff --git a/src/ViewerTest/ViewerTest_AutoUpdater.cxx b/src/ViewerTest/ViewerTest_AutoUpdater.cxx
new file mode 100644 (file)
index 0000000..2d6db65
--- /dev/null
@@ -0,0 +1,98 @@
+// Created on: 2014-04-24
+// Created by: Kirill Gavrilov
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <ViewerTest_AutoUpdater.hxx>
+
+//=======================================================================
+//function : ViewerTest_AutoUpdater
+//purpose  :
+//=======================================================================
+ViewerTest_AutoUpdater::ViewerTest_AutoUpdater (const Handle(AIS_InteractiveContext)& theContext,
+                                                const Handle(V3d_View)&               theView)
+: myContext       (theContext),
+  myView          (theView),
+  myToUpdate      (RedrawMode_Auto),
+  myWasAutoUpdate (Standard_False)
+{
+  if (!theView.IsNull())
+  {
+    myWasAutoUpdate = theView->SetImmediateUpdate (Standard_False);
+  }
+}
+
+//=======================================================================
+//function : ~ViewerTest_AutoUpdater
+//purpose  :
+//=======================================================================
+ViewerTest_AutoUpdater::~ViewerTest_AutoUpdater()
+{
+  Update();
+}
+
+//=======================================================================
+//function : parseRedrawMode
+//purpose  :
+//=======================================================================
+Standard_Boolean ViewerTest_AutoUpdater::parseRedrawMode (const TCollection_AsciiString& theArg)
+{
+  TCollection_AsciiString anArgCase (theArg);
+  anArgCase.LowerCase();
+  if (anArgCase == "-update"
+   || anArgCase == "-redraw")
+  {
+    myToUpdate = RedrawMode_Forced;
+    return Standard_True;
+  }
+  else if (anArgCase == "-noupdate"
+        || anArgCase == "-noredraw")
+  {
+    myToUpdate = RedrawMode_Suppressed;
+    return Standard_True;
+  }
+  return Standard_False;
+}
+
+//=======================================================================
+//function : Invalidate
+//purpose  :
+//=======================================================================
+void ViewerTest_AutoUpdater::Invalidate()
+{
+  myContext.Nullify();
+  if (myWasAutoUpdate)
+  {
+    myView->SetImmediateUpdate (myWasAutoUpdate);
+  }
+}
+
+//=======================================================================
+//function : Update
+//purpose  :
+//=======================================================================
+void ViewerTest_AutoUpdater::Update()
+{
+  if (myContext.IsNull())
+  {
+    return;
+  }
+
+  // update the screen and redraw the view
+  myView->SetImmediateUpdate (myWasAutoUpdate);
+  if ((myWasAutoUpdate && myToUpdate != ViewerTest_AutoUpdater::RedrawMode_Suppressed)
+    || myToUpdate == ViewerTest_AutoUpdater::RedrawMode_Forced)
+  {
+    myContext->UpdateCurrentViewer();
+  }
+}
diff --git a/src/ViewerTest/ViewerTest_AutoUpdater.hxx b/src/ViewerTest/ViewerTest_AutoUpdater.hxx
new file mode 100644 (file)
index 0000000..96a3c52
--- /dev/null
@@ -0,0 +1,64 @@
+// Created on: 2014-09-10
+// Created by: Kirill Gavrilov
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _ViewerTest_AutoUpdater_HeaderFile
+#define _ViewerTest_AutoUpdater_HeaderFile
+
+#include <AIS_InteractiveContext.hxx>
+#include <V3d_View.hxx>
+
+class TCollection_AsciiString;
+
+//! Auxiliary tool to control view updates.
+class ViewerTest_AutoUpdater
+{
+public:
+
+  //! Enumeration to control auto-update
+  enum RedrawMode
+  {
+    RedrawMode_Auto = -1,
+    RedrawMode_Forced,
+    RedrawMode_Suppressed
+  };
+
+public:
+
+  //! Constructor
+  Standard_EXPORT ViewerTest_AutoUpdater (const Handle(AIS_InteractiveContext)& theContext,
+                                          const Handle(V3d_View)&               theView);
+
+  //! Destructor to automatically update view
+  Standard_EXPORT ~ViewerTest_AutoUpdater();
+
+  //! Parse redraw mode argument
+  Standard_EXPORT Standard_Boolean parseRedrawMode (const TCollection_AsciiString& theArg);
+
+  //! Disable autoupdate
+  Standard_EXPORT void Invalidate();
+
+  //! Finally update view
+  Standard_EXPORT void Update();
+
+private:
+
+  Handle(AIS_InteractiveContext)     myContext;
+  Handle(V3d_View)                   myView;
+  ViewerTest_AutoUpdater::RedrawMode myToUpdate;
+  Standard_Boolean                   myWasAutoUpdate;
+
+};
+
+#endif // _ViewerTest_AutoUpdater_HeaderFile
index a05402d..009a941 100644 (file)
@@ -35,6 +35,7 @@
 #include <AIS_DisplayMode.hxx>
 #include <TColStd_MapOfInteger.hxx>
 #include <AIS_MapOfInteractive.hxx>
+#include <ViewerTest_AutoUpdater.hxx>
 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
 #include <ViewerTest_EventManager.hxx>
@@ -3481,53 +3482,72 @@ static int VDrawPArray (Draw_Interpretor& di, Standard_Integer argc, const char*
 //=======================================================================
 
 static Standard_Integer VSetLocation (Draw_Interpretor& /*di*/,
-                                      Standard_Integer argc,
-                                      const char ** argv)
+                                      Standard_Integer  theArgNb,
+                                      const char**      theArgVec)
 {
   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
+  ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
   if (aContext.IsNull())
   {
-    std::cout << argv[0] << "ERROR : use 'vinit' command before " << "\n";
+    std::cout << "Error: no active view!\n";
     return 1;
   }
 
-  if (argc != 5)
+  TCollection_AsciiString aName;
+  gp_Vec aLocVec;
+  Standard_Boolean isSetLoc = Standard_False;
+
+  Standard_Integer anArgIter = 1;
+  for (; anArgIter < theArgNb; ++anArgIter)
   {
-    std::cout << "ERROR : Usage : " << argv[0] << " name x y z; new location" << "\n";
-    return 1;
+    Standard_CString anArg = theArgVec[anArgIter];
+    if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
+    {
+      continue;
+    }
+    else if (aName.IsEmpty())
+    {
+      aName = anArg;
+    }
+    else if (!isSetLoc)
+    {
+      isSetLoc = Standard_True;
+      if (anArgIter + 1 >= theArgNb)
+      {
+        std::cout << "Error: syntax error at '" << anArg << "'\n";
+        return 1;
+      }
+      aLocVec.SetX (Draw::Atof (theArgVec[anArgIter++]));
+      aLocVec.SetY (Draw::Atof (theArgVec[anArgIter]));
+      if (anArgIter + 1 < theArgNb)
+      {
+        aLocVec.SetZ (Draw::Atof (theArgVec[++anArgIter]));
+      }
+    }
+    else
+    {
+      std::cout << "Error: unknown argument '" << anArg << "'\n";
+      return 1;
+    }
   }
 
-  TCollection_AsciiString aName (argv[1]);
-  Standard_Real aX = Draw::Atof (argv[2]);
-  Standard_Real aY = Draw::Atof (argv[3]);
-  Standard_Real aZ = Draw::Atof (argv[4]);
-
   // find object
-  ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
+  const ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
   Handle(AIS_InteractiveObject) anIObj;
-  if (!aMap.IsBound2 (aName))
+  if (aMap.IsBound2 (aName))
   {
-    std::cout << "Use 'vdisplay' before" << "\n";
-    return 1;
+    anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
   }
-  else
+  if (anIObj.IsNull())
   {
-    anIObj = Handle(AIS_InteractiveObject)::DownCast (aMap.Find2 (aName));
-
-    // not an AIS_InteractiveObject
-    if (anIObj.IsNull())
-    {
-      std::cout << argv[1] << " : Not an AIS interactive object" << "\n";
-      return 1;
-    }
-
-    gp_Trsf aTrsf;
-    aTrsf.SetTranslation (gp_Vec (aX, aY, aZ));
-    TopLoc_Location aLocation (aTrsf);
-    aContext->SetLocation (anIObj, aLocation);
-    aContext->UpdateCurrentViewer();
+    std::cout << "Error: object '" << aName << "' is not displayed!\n";
+    return 1;
   }
 
+  gp_Trsf aTrsf;
+  aTrsf.SetTranslation (aLocVec);
+  TopLoc_Location aLocation (aTrsf);
+  aContext->SetLocation (anIObj, aLocation);
   return 0;
 }
 
@@ -5429,7 +5449,8 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
     __FILE__,VDrawSphere,group);
 
   theCommands.Add ("vsetlocation",
-        "vsetlocation : name x y z; set new location for an interactive object",
+                   "vsetlocation [-noupdate|-update] name x y z"
+                   "\n\t\t: Set new location for an interactive object.",
         __FILE__, VSetLocation, group);
 
   theCommands.Add (