0033661: Data Exchange, Step Import - Tessellated GDTs are not imported
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
CommitLineData
b311480e 1// Created on: 1998-09-01
2// Created by: Robert COUBLANC
3// Copyright (c) 1998-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
b8db9379 17#if defined(_WIN32)
18 #include <windows.h>
19#endif
20
49582f9d 21#include <ViewerTest.hxx>
1beb58d7 22
53eae1a9 23#include <AIS_AnimationAxisRotation.hxx>
1beb58d7 24#include <AIS_AnimationCamera.hxx>
25#include <AIS_AnimationObject.hxx>
0461e7fd 26#include <AIS_Axis.hxx>
30a1b24e 27#include <AIS_CameraFrustum.hxx>
7a324550 28#include <AIS_ColorScale.hxx>
49582f9d 29#include <AIS_InteractiveContext.hxx>
2daa5d95 30#include <AIS_LightSource.hxx>
0a768f56 31#include <AIS_ListOfInteractive.hxx>
49582f9d 32#include <AIS_Manipulator.hxx>
2108d9a2 33#include <AIS_ViewCube.hxx>
49582f9d 34#include <AIS_Shape.hxx>
0461e7fd 35#include <AIS_Point.hxx>
49582f9d 36#include <Aspect_DisplayConnection.hxx>
8a590580 37#include <Aspect_Grid.hxx>
49582f9d 38#include <Aspect_TypeOfLine.hxx>
49582f9d 39#include <Draw_Appli.hxx>
40#include <Draw_Interpretor.hxx>
08f8a185 41#include <Draw_ProgressIndicator.hxx>
49582f9d 42#include <gp_Dir.hxx>
43#include <gp_Pln.hxx>
44#include <gp_Pnt.hxx>
0461e7fd 45#include <Geom_Axis2Placement.hxx>
46#include <Geom_CartesianPoint.hxx>
61b0191c 47#include <Graphic3d_ArrayOfPolylines.hxx>
49582f9d 48#include <Graphic3d_AspectFillArea3d.hxx>
49582f9d 49#include <Graphic3d_ClipPlane.hxx>
077a220c 50#include <Graphic3d_CubeMapPacked.hxx>
51#include <Graphic3d_CubeMapSeparate.hxx>
a79f67f8 52#include <Graphic3d_GraduatedTrihedron.hxx>
b8db9379 53#include <Graphic3d_GraphicDriver.hxx>
54#include <Graphic3d_GraphicDriverFactory.hxx>
49582f9d 55#include <Graphic3d_NameOfTextureEnv.hxx>
633084b8 56#include <Graphic3d_Texture2D.hxx>
269294d6 57#include <Graphic3d_TextureEnv.hxx>
58#include <Graphic3d_TextureParams.hxx>
59#include <Graphic3d_TypeOfTextureFilter.hxx>
49582f9d 60#include <Image_AlienPixMap.hxx>
61#include <Image_Diff.hxx>
62#include <Image_VideoRecorder.hxx>
b8db9379 63#include <Message.hxx>
7e785937 64#include <Message_ProgressScope.hxx>
49582f9d 65#include <NCollection_DataMap.hxx>
18d715bd 66#include <NCollection_List.hxx>
d6fbb2ab 67#include <NCollection_LocalArray.hxx>
6a2fb7a1 68#include <OSD_Parallel.hxx>
208e6839 69#include <OSD_Timer.hxx>
4269bd1b 70#include <Prs3d_ShadingAspect.hxx>
0aeb8984 71#include <Prs3d_DatumAspect.hxx>
6262338c 72#include <Prs3d_Drawer.hxx>
61b0191c 73#include <Prs3d_LineAspect.hxx>
fd3f6bd0 74#include <Prs3d_Text.hxx>
75#include <Select3D_SensitivePrimitiveArray.hxx>
49582f9d 76#include <TColStd_HSequenceOfAsciiString.hxx>
77#include <TColStd_SequenceOfInteger.hxx>
78#include <TColStd_HSequenceOfReal.hxx>
49582f9d 79#include <ViewerTest_AutoUpdater.hxx>
08b7a39f 80#include <ViewerTest_ContinuousRedrawer.hxx>
49582f9d 81#include <ViewerTest_EventManager.hxx>
49582f9d 82#include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
83#include <ViewerTest_CmdParser.hxx>
84#include <ViewerTest_V3dView.hxx>
85#include <V3d_AmbientLight.hxx>
86#include <V3d_DirectionalLight.hxx>
87#include <V3d_PositionalLight.hxx>
88#include <V3d_SpotLight.hxx>
0aeb8984 89#include <V3d_Trihedron.hxx>
1a96d253 90#include <V3d_Viewer.hxx>
0461e7fd 91#include <UnitsAPI.hxx>
7fd59977 92
293211ae 93#include <tcl.h>
94
58655684 95#if defined(_WIN32)
4fe56619 96 #include <WNT_WClass.hxx>
97 #include <WNT_Window.hxx>
b69e576a 98#elif defined(HAVE_XLIB)
4fe56619 99 #include <Xw_Window.hxx>
b69e576a 100 #include <X11/Xlib.h>
4fe56619 101 #include <X11/Xutil.h>
b69e576a 102#elif defined(__APPLE__)
103 #include <Cocoa_Window.hxx>
f9ab9f7f 104#elif defined(__EMSCRIPTEN__)
105 #include <Wasm_Window.hxx>
106 #include <emscripten/emscripten.h>
b69e576a 107#else
108 #include <Aspect_NeutralWindow.hxx>
7fd59977 109#endif
110
7fd59977 111//==============================================================================
112// VIEWER GLOBAL VARIABLES
113//==============================================================================
114
115Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
b514beda 116Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
7fd59977 117
118Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
4754e164 119extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
7fd59977 120
58655684 121#if defined(_WIN32)
b69e576a 122typedef WNT_Window ViewerTest_Window;
123#elif defined(HAVE_XLIB)
124typedef Xw_Window ViewerTest_Window;
125static void VProcessEvents(ClientData,int);
126#elif defined(__APPLE__)
127typedef Cocoa_Window ViewerTest_Window;
4fe56619 128extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
18d715bd 129extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
f9ab9f7f 130#elif defined(__EMSCRIPTEN__)
131typedef Wasm_Window ViewerTest_Window;
7fd59977 132#else
b69e576a 133typedef Aspect_NeutralWindow ViewerTest_Window;
7fd59977 134#endif
135
f9ab9f7f 136#if defined(__EMSCRIPTEN__)
137//! Return DOM id of default WebGL canvas from Module.canvas.
138EM_JS(char*, occJSModuleCanvasId, (), {
139 const aCanvasId = Module.canvas.id;
140 const aNbBytes = lengthBytesUTF8 (aCanvasId) + 1;
141 const aStrPtr = Module._malloc (aNbBytes);
142 stringToUTF8 (aCanvasId, aStrPtr, aNbBytes);
143 return aStrPtr;
144});
145
146//! Return DOM id of default WebGL canvas from Module.canvas.
147static TCollection_AsciiString getModuleCanvasId()
148{
149 char* aRawId = occJSModuleCanvasId();
150 TCollection_AsciiString anId (aRawId != NULL ? aRawId : "");
151 free (aRawId);
152 return anId;
153}
154#endif
155
1103eb60 156namespace
b69e576a 157{
1103eb60 158 static Handle(ViewerTest_Window)& VT_GetWindow()
159 {
160 static Handle(ViewerTest_Window) aWindow;
161 return aWindow;
162 }
b69e576a 163
1103eb60 164 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
165 {
166 static Handle(Aspect_DisplayConnection) aDisplayConnection;
167 return aDisplayConnection;
168 }
18d715bd 169
1103eb60 170 using ViewerTest_ViewerCommandsViewMap = NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>;
171 using ViewerTest_ViewerCommandsInteractiveContextMap = NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>;
172 using ViewerTest_ViewerCommandsGraphicDriverMap = NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>;
18d715bd 173
1103eb60 174 static void SetDisplayConnection(const Handle(Aspect_DisplayConnection)& theDisplayConnection)
175 {
176 GetDisplayConnection() = theDisplayConnection;
177 }
178
1103eb60 179 static ViewerTest_ViewerCommandsInteractiveContextMap ViewerTest_myContexts;
180 static ViewerTest_ViewerCommandsGraphicDriverMap ViewerTest_myDrivers;
181}
18d715bd 182
656b0d21 183ViewerTest_ViewerCommandsViewMap ViewerTest_myViews;
184
f42753ed 185static struct
186{
187 Quantity_Color FlatColor;
188 Quantity_Color GradientColor1;
189 Quantity_Color GradientColor2;
190 Aspect_GradientFillMethod FillMethod;
293211ae 191
c585f731 192 //! Sets the gradient filling for a background in a default viewer.
193 void SetDefaultGradient()
194 {
1103eb60 195 for (ViewerTest_ViewerCommandsInteractiveContextMap::Iterator aCtxIter (ViewerTest_myContexts);
c585f731 196 aCtxIter.More(); aCtxIter.Next())
293211ae 197 {
1103eb60 198 const Handle (V3d_Viewer)& aViewer = aCtxIter.Key2()->CurrentViewer();
c585f731 199 aViewer->SetDefaultBgGradientColors (GradientColor1, GradientColor2, FillMethod);
293211ae 200 }
c585f731 201 }
293211ae 202
c585f731 203 //! Sets the color used for filling a background in a default viewer.
204 void SetDefaultColor()
205 {
1103eb60 206 for (ViewerTest_ViewerCommandsInteractiveContextMap::Iterator aCtxIter (ViewerTest_myContexts);
c585f731 207 aCtxIter.More(); aCtxIter.Next())
293211ae 208 {
1103eb60 209 const Handle (V3d_Viewer)& aViewer = aCtxIter.Key2()->CurrentViewer();
c585f731 210 aViewer->SetDefaultBackgroundColor (FlatColor);
293211ae 211 }
c585f731 212 }
293211ae 213
9af0d66b 214} ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GradientFillMethod_None };
b12e1c7b 215
c585f731 216//==============================================================================
217// EVENT GLOBAL VARIABLES
7fd59977 218//==============================================================================
219
57c28b61 220#ifdef _WIN32
e8e157df 221static LRESULT WINAPI AdvViewerWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
7fd59977 222#endif
223
7fd59977 224//==============================================================================
225//function : WClass
226//purpose :
227//==============================================================================
228
1bd04b5a 229const Handle(WNT_WClass)& ViewerTest::WClass()
7fd59977 230{
1bd04b5a 231 static Handle(WNT_WClass) theWClass;
58655684 232#if defined(_WIN32)
4fe56619 233 if (theWClass.IsNull())
234 {
7c65581d 235 theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
ad03c234 236 CS_VREDRAW | CS_HREDRAW, 0, 0,
c85a994a 237 ::LoadCursor (NULL, IDC_ARROW));
7fd59977 238 }
239#endif
240 return theWClass;
241}
242
18d715bd 243//==============================================================================
244//function : CreateName
245//purpose : Create numerical name for new object in theMap
246//==============================================================================
247template <typename ObjectType>
248TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
249 const TCollection_AsciiString& theDefaultString)
250{
251 if (theObjectMap.IsEmpty())
252 return theDefaultString + TCollection_AsciiString(1);
253
254 Standard_Integer aNextKey = 1;
255 Standard_Boolean isFound = Standard_False;
256 while (!isFound)
257 {
258 TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
259 // Look for objects with default names
260 if (theObjectMap.IsBound1(aStringKey))
261 {
262 aNextKey++;
263 }
264 else
265 isFound = Standard_True;
266 }
267
268 return theDefaultString + TCollection_AsciiString(aNextKey);
269}
270
271//==============================================================================
272//structure : ViewerTest_Names
273//purpose : Allow to operate with full view name: driverName/viewerName/viewName
274//==============================================================================
275struct ViewerTest_Names
276{
277private:
278 TCollection_AsciiString myDriverName;
279 TCollection_AsciiString myViewerName;
280 TCollection_AsciiString myViewName;
281
282public:
283
284 const TCollection_AsciiString& GetDriverName () const
285 {
286 return myDriverName;
287 }
288 void SetDriverName (const TCollection_AsciiString& theDriverName)
289 {
290 myDriverName = theDriverName;
291 }
292 const TCollection_AsciiString& GetViewerName () const
293 {
294 return myViewerName;
295 }
296 void SetViewerName (const TCollection_AsciiString& theViewerName)
297 {
298 myViewerName = theViewerName;
299 }
300 const TCollection_AsciiString& GetViewName () const
301 {
302 return myViewName;
303 }
304 void SetViewName (const TCollection_AsciiString& theViewName)
305 {
306 myViewName = theViewName;
307 }
308
309 //===========================================================================
310 //function : Constructor for ViewerTest_Names
311 //purpose : Get view, viewer, driver names from custom string
312 //===========================================================================
313
314 ViewerTest_Names (const TCollection_AsciiString& theInputString)
315 {
316 TCollection_AsciiString aName(theInputString);
317 if (theInputString.IsEmpty())
318 {
319 // Get current configuration
320 if (ViewerTest_myDrivers.IsEmpty())
321 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
322 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
323 else
324 myDriverName = ViewerTest_myDrivers.Find2
325 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
326
327 if(ViewerTest_myContexts.IsEmpty())
328 {
329 myViewerName = CreateName <Handle(AIS_InteractiveContext)>
330 (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
331 }
332 else
c48e2889 333 {
18d715bd 334 myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
c48e2889 335 }
18d715bd 336
c48e2889 337 myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
18d715bd 338 }
339 else
340 {
341 // There is at least view name
342 Standard_Integer aParserNumber = 0;
343 for (Standard_Integer i = 0; i < 3; ++i)
344 {
345 Standard_Integer aParserPos = aName.SearchFromEnd("/");
346 if(aParserPos != -1)
347 {
348 aParserNumber++;
349 aName.Split(aParserPos-1);
350 }
351 else
352 break;
353 }
354 if (aParserNumber == 0)
355 {
356 // Only view name
357 if (!ViewerTest::GetAISContext().IsNull())
358 {
359 myDriverName = ViewerTest_myDrivers.Find2
360 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
361 myViewerName = ViewerTest_myContexts.Find2
362 (ViewerTest::GetAISContext());
363 }
364 else
365 {
366 // There is no opened contexts here, need to create names for viewer and driver
367 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
368 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
369
370 myViewerName = CreateName <Handle(AIS_InteractiveContext)>
371 (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
372 }
373 myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
374 }
375 else if (aParserNumber == 1)
376 {
377 // Here is viewerName/viewName
378 if (!ViewerTest::GetAISContext().IsNull())
379 myDriverName = ViewerTest_myDrivers.Find2
380 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
381 else
382 {
383 // There is no opened contexts here, need to create name for driver
384 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
385 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
386 }
387 myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
388
389 myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
390 }
391 else
392 {
393 //Here is driverName/viewerName/viewName
394 myDriverName = TCollection_AsciiString(aName);
395
396 TCollection_AsciiString aViewerName(theInputString);
397 aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
398 myViewerName = TCollection_AsciiString(aViewerName);
399
400 myViewName = TCollection_AsciiString(theInputString);
401 }
402 }
403 }
404};
405
406//==============================================================================
407//function : FindContextByView
408//purpose : Find AIS_InteractiveContext by View
409//==============================================================================
410
411Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
412{
413 Handle(AIS_InteractiveContext) anAISContext;
414
1103eb60 415 for (ViewerTest_ViewerCommandsInteractiveContextMap::Iterator
18d715bd 416 anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
417 {
1103eb60 418 if (anIter.Key2()->CurrentViewer() == theView->Viewer())
18d715bd 419 return anIter.Key2();
420 }
421 return anAISContext;
422}
423
18d715bd 424//==============================================================================
425//function : IsWindowOverlapped
426//purpose : Check if theWindow overlapp another view
427//==============================================================================
428
429Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
430 const Standard_Integer thePxTop,
431 const Standard_Integer thePxRight,
432 const Standard_Integer thePxBottom,
433 TCollection_AsciiString& theViewId)
434{
1103eb60 435 for(ViewerTest_ViewerCommandsViewMap::Iterator
18d715bd 436 anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
437 {
438 Standard_Integer aTop = 0,
439 aLeft = 0,
440 aRight = 0,
441 aBottom = 0;
1103eb60 442 anIter.Key2()->Window()->Position(aLeft, aTop, aRight, aBottom);
18d715bd 443 if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
444 (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
445 (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
446 (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
447 {
448 theViewId = anIter.Key1();
449 return Standard_True;
450 }
451 }
452 return Standard_False;
453}
454
455// Workaround: to create and delete non-orthographic views outside ViewerTest
456void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
457{
458 ViewerTest_myViews.UnBind1 (theName);
459}
460
461void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
462 const Handle(V3d_View)& theView)
463{
464 ViewerTest_myViews.Bind (theName, theView);
465}
466
467TCollection_AsciiString ViewerTest::GetCurrentViewName ()
468{
469 return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
470}
8693dfd0 471
7fd59977 472//==============================================================================
473//function : ViewerInit
474//purpose : Create the window viewer and initialize all the global variable
475//==============================================================================
476
879768fb 477TCollection_AsciiString ViewerTest::ViewerInit (const ViewerTest_VinitParams& theParams)
7fd59977 478{
8c3c9904 479 // Default position and dimension of the viewer window.
4fe56619 480 // Note that left top corner is set to be sufficiently small to have
8c3c9904 481 // window fit in the small screens (actual for remote desktops, see #23003).
4fe56619 482 // The position corresponds to the window's client area, thus some
8c3c9904 483 // gap is added for window frame to be visible.
879768fb 484 Graphic3d_Vec2d aPxTopLeft (20, 40);
485 Graphic3d_Vec2d aPxSize (409, 409);
f9ab9f7f 486 Standard_Boolean isDefViewSize = Standard_True;
18d715bd 487 Standard_Boolean toCreateViewer = Standard_False;
879768fb 488 const Standard_Boolean isVirtual = Draw_VirtualWindows || theParams.IsVirtual;
489 if (!theParams.ViewToClone.IsNull())
9e04ccdc 490 {
879768fb 491 Graphic3d_Vec2i aCloneSize;
492 theParams.ViewToClone->Window()->Size (aCloneSize.x(), aCloneSize.y());
493 aPxSize = Graphic3d_Vec2d (aCloneSize);
f9ab9f7f 494 isDefViewSize = Standard_False;
495 #if !defined(__EMSCRIPTEN__)
496 (void )isDefViewSize;
497 #endif
9e04ccdc 498 }
18d715bd 499
b8db9379 500 Handle(Graphic3d_GraphicDriverFactory) aFactory = Graphic3d_GraphicDriverFactory::DefaultDriverFactory();
501 if (aFactory.IsNull())
502 {
503 Draw::GetInterpretor().Eval ("pload OPENGL");
504 aFactory = Graphic3d_GraphicDriverFactory::DefaultDriverFactory();
505 if (aFactory.IsNull())
506 {
b8ef513c 507 Draw::GetInterpretor().Eval ("pload GLES");
508 aFactory = Graphic3d_GraphicDriverFactory::DefaultDriverFactory();
509 if (aFactory.IsNull())
510 {
511 throw Standard_ProgramError("Error: no graphic driver factory found");
512 }
b8db9379 513 }
514 }
515
516 Handle(Graphic3d_GraphicDriver) aGraphicDriver;
879768fb 517 ViewerTest_Names aViewNames (theParams.ViewName);
f9ab9f7f 518 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
519 {
18d715bd 520 aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
f9ab9f7f 521 }
18d715bd 522
18d715bd 523 // Get graphic driver (create it or get from another view)
8693dfd0 524 const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
525 if (isNewDriver)
18d715bd 526 {
527 // Get connection string
b69e576a 528 #if defined(HAVE_XLIB)
879768fb 529 if (!theParams.DisplayName.IsEmpty())
8693dfd0 530 {
879768fb 531 SetDisplayConnection (new Aspect_DisplayConnection (theParams.DisplayName));
8693dfd0 532 }
18d715bd 533 else
8693dfd0 534 {
b69e576a 535 Aspect_XDisplay* aDispX = NULL;
8693dfd0 536 // create dedicated display connection instead of reusing Tk connection
b69e576a 537 // so that to proceed events independently through VProcessEvents()/ViewerMainLoop() callbacks
8693dfd0 538 /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
539 Tcl_Interp* aTclInterp = aCommands.Interp();
540 Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
541 aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
542 SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
543 }
18d715bd 544 #else
545 SetDisplayConnection (new Aspect_DisplayConnection ());
546 #endif
14cb22a1 547
b8db9379 548 aGraphicDriver = aFactory->CreateDriver (GetDisplayConnection());
72ed0644 549 if (isVirtual)
14cb22a1 550 {
551 // don't waste the time waiting for VSync when window is not displayed on the screen
b8db9379 552 aGraphicDriver->SetVerticalSync (false);
14cb22a1 553 }
14cb22a1 554
18d715bd 555 ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
556 toCreateViewer = Standard_True;
557 }
558 else
559 {
b8db9379 560 aGraphicDriver = ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName());
7fd59977 561 }
562
879768fb 563 // Get screen resolution
564 Graphic3d_Vec2i aScreenSize;
b69e576a 565#if defined(_WIN32)
879768fb 566 RECT aWindowSize;
567 GetClientRect(GetDesktopWindow(), &aWindowSize);
568 aScreenSize.SetValues (aWindowSize.right, aWindowSize.bottom);
b69e576a 569#elif defined(HAVE_XLIB)
879768fb 570 ::Display* aDispX = (::Display* )GetDisplayConnection()->GetDisplayAspect();
571 Screen* aScreen = DefaultScreenOfDisplay(aDispX);
572 aScreenSize.x() = WidthOfScreen(aScreen);
573 aScreenSize.y() = HeightOfScreen(aScreen);
b69e576a 574#elif defined(__APPLE__)
879768fb 575 GetCocoaScreenResolution (aScreenSize.x(), aScreenSize.y());
18d715bd 576#else
879768fb 577 // not implemented
18d715bd 578#endif
579
879768fb 580 if (!theParams.ParentView.IsNull())
581 {
582 aPxTopLeft.SetValues (0, 0);
583 }
584 if (theParams.Offset.x() != 0)
585 {
586 aPxTopLeft.x() = theParams.Offset.x();
587 }
588 if (theParams.Offset.y() != 0)
589 {
590 aPxTopLeft.y() = theParams.Offset.y();
591 }
592 if (theParams.Size.x() != 0)
593 {
594 isDefViewSize = Standard_False;
595 aPxSize.x() = theParams.Size.x();
596 if (aPxSize.x() <= 1.0
597 && aScreenSize.x() > 0
598 && theParams.ParentView.IsNull())
599 {
600 aPxSize.x() = aPxSize.x() * double(aScreenSize.x());
601 }
602 }
603 if (theParams.Size.y() != 0)
604 {
605 isDefViewSize = Standard_False;
606 aPxSize.y() = theParams.Size.y();
607 if (aPxSize.y() <= 1.0
608 && aScreenSize.y() > 0
609 && theParams.ParentView.IsNull())
610 {
611 aPxSize.y() = aPxSize.y() * double(aScreenSize.y());
612 }
613 }
773f53f1 614
879768fb 615 //Dispose the window if input parameters are default
616 if (!ViewerTest_myViews.IsEmpty()
617 && theParams.ParentView.IsNull()
618 && theParams.Offset.x() == 0
619 && theParams.Offset.y() == 0)
620 {
621 Standard_Integer aTop = 0, aLeft = 0, aRight = 0, aBottom = 0;
622 TCollection_AsciiString anOverlappedViewId("");
623 while (IsWindowOverlapped ((int )aPxTopLeft.x(), (int )aPxTopLeft.y(),
624 (int )aPxTopLeft.x() + (int )aPxSize.x(),
625 (int )aPxTopLeft.y() + (int )aPxSize.y(), anOverlappedViewId))
dc3fe572 626 {
18d715bd 627 ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
628
879768fb 629 if (IsWindowOverlapped (aRight + 20, (int )aPxTopLeft.y(), aRight + 20 + (int )aPxSize.x(),
630 (int )aPxTopLeft.y() + (int )aPxSize.y(), anOverlappedViewId)
631 && aRight + 2 * aPxSize.x() + 40 > aScreenSize.x())
18d715bd 632 {
879768fb 633 if (aBottom + aPxSize.y() + 40 > aScreenSize.y())
18d715bd 634 {
879768fb 635 aPxTopLeft.x() = 20;
636 aPxTopLeft.y() = 40;
18d715bd 637 break;
638 }
879768fb 639 aPxTopLeft.x() = 20;
640 aPxTopLeft.y() = aBottom + 40;
18d715bd 641 }
642 else
879768fb 643 {
644 aPxTopLeft.x() = aRight + 20;
645 }
dc3fe572 646 }
18d715bd 647 }
648
649 // Get viewer name
650 TCollection_AsciiString aTitle("3D View - ");
651 aTitle = aTitle + aViewNames.GetViewName() + "(*)";
652
653 // Change name of current active window
49582f9d 654 if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
18d715bd 655 {
49582f9d 656 aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
18d715bd 657 }
658
659 // Create viewer
eb4320f2 660 Handle(V3d_Viewer) a3DViewer;
18d715bd 661 // If it's the single view, we first look for empty context
662 if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
663 {
1103eb60 664 ViewerTest_ViewerCommandsInteractiveContextMap::Iterator
18d715bd 665 anIter(ViewerTest_myContexts);
666 if (anIter.More())
1103eb60 667 ViewerTest::SetAISContext (anIter.Key2());
18d715bd 668 a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
18d715bd 669 }
670 else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
671 {
672 ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
673 a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
18d715bd 674 }
eb4320f2 675 else if (a3DViewer.IsNull())
18d715bd 676 {
677 toCreateViewer = Standard_True;
6a24c6de 678 a3DViewer = new V3d_Viewer(aGraphicDriver);
f42753ed 679 a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
680 a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
681 ViewerTest_DefaultBackground.GradientColor2,
682 ViewerTest_DefaultBackground.FillMethod);
18d715bd 683 }
684
685 // AIS context setup
686 if (ViewerTest::GetAISContext().IsNull() ||
687 !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
688 {
e79a94b9 689 Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
18d715bd 690 ViewerTest::SetAISContext (aContext);
691 ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
692 }
693 else
e79a94b9 694 {
18d715bd 695 ViewerTest::ResetEventManager();
e79a94b9 696 }
18d715bd 697
698 // Create window
879768fb 699 if (!theParams.ParentView.IsNull())
f9ab9f7f 700 {
879768fb 701 VT_GetWindow() = Handle(ViewerTest_Window)::DownCast (theParams.ParentView->Window());
f9ab9f7f 702 }
879768fb 703 else
f9ab9f7f 704 {
879768fb 705 #if defined(_WIN32)
706 VT_GetWindow() = new WNT_Window (aTitle.ToCString(), WClass(),
707 isVirtual ? WS_POPUP : WS_OVERLAPPEDWINDOW,
708 (int )aPxTopLeft.x(), (int )aPxTopLeft.y(),
709 (int )aPxSize.x(), (int )aPxSize.y(),
710 Quantity_NOC_BLACK);
711 VT_GetWindow()->RegisterRawInputDevices (WNT_Window::RawInputMask_SpaceMouse);
712 #elif defined(HAVE_XLIB)
713 VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
714 aTitle.ToCString(),
715 (int )aPxTopLeft.x(), (int )aPxTopLeft.y(),
716 (int )aPxSize.x(), (int )aPxSize.y());
717 #elif defined(__APPLE__)
718 VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
719 (int )aPxTopLeft.x(), (int )aPxTopLeft.y(),
720 (int )aPxSize.x(), (int )aPxSize.y());
721 ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
722 #elif defined(__EMSCRIPTEN__)
723 // current EGL implementation in Emscripten supports only one global WebGL canvas returned by Module.canvas property;
724 // the code should be revised for handling multiple canvas elements (which is technically also possible)
725 TCollection_AsciiString aCanvasId = getModuleCanvasId();
726 if (!aCanvasId.IsEmpty())
727 {
728 aCanvasId = TCollection_AsciiString("#") + aCanvasId;
729 }
730
731 VT_GetWindow() = new Wasm_Window (aCanvasId);
732 Graphic3d_Vec2i aRealSize;
733 VT_GetWindow()->Size (aRealSize.x(), aRealSize.y());
734 if (!isDefViewSize || (aRealSize.x() <= 0 && aRealSize.y() <= 0))
735 {
736 // Wasm_Window wraps an existing HTML element without creating a new one.
737 // Keep size defined on a web page instead of defaulting to 409x409 (as in case of other platform),
738 // but resize canvas if vinit has been called with explicitly specified dimensions.
739 VT_GetWindow()->SetSizeLogical (Graphic3d_Vec2d (aPxSize));
740 }
741 #else
742 // not implemented
743 VT_GetWindow() = new Aspect_NeutralWindow();
744 VT_GetWindow()->SetSize ((int )aPxSize.x(), (int )aPxSize.y());
745 #endif
746 VT_GetWindow()->SetVirtual (isVirtual);
f9ab9f7f 747 }
7fd59977 748
d09dda09 749 // View setup
9e04ccdc 750 Handle(V3d_View) aView;
879768fb 751 if (!theParams.ViewToClone.IsNull())
9e04ccdc 752 {
879768fb 753 aView = new ViewerTest_V3dView (a3DViewer, theParams.ViewToClone);
9e04ccdc 754 }
755 else
756 {
2e93433e 757 aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
9e04ccdc 758 }
759
879768fb 760 aView->View()->SetSubviewComposer (theParams.IsComposer);
761 if (!theParams.ParentView.IsNull())
762 {
763 aView->SetWindow (theParams.ParentView, aPxSize, theParams.Corner, aPxTopLeft, theParams.SubviewMargins);
764 }
765 else
766 {
767 aView->SetWindow (VT_GetWindow());
768 }
c3282ec1 769 ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
4269bd1b 770
18d715bd 771 ViewerTest::CurrentView(aView);
772 ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
7fd59977 773
18d715bd 774 // Setup for X11 or NT
f9ab9f7f 775 SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
776 ViewerTest_EventManager::SetupWindowCallbacks (VT_GetWindow());
7fd59977 777
18d715bd 778 // Set parameters for V3d_View and V3d_Viewer
779 const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
780 aV3dView->SetComputedMode(Standard_False);
7fd59977 781
18d715bd 782 a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
783 if (toCreateViewer)
784 {
7fd59977 785 a3DViewer->SetDefaultLights();
786 a3DViewer->SetLightOn();
18d715bd 787 }
7fd59977 788
b69e576a 789#if defined(HAVE_XLIB)
8693dfd0 790 if (isNewDriver)
791 {
b69e576a 792 ::Display* aDispX = (::Display* )GetDisplayConnection()->GetDisplayAspect();
8693dfd0 793 Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
794 }
795#endif
7fd59977 796
7fd59977 797 VT_GetWindow()->Map();
4269bd1b 798
18d715bd 799 // Set the handle of created view in the event manager
800 ViewerTest::ResetEventManager();
801
4fe56619 802 ViewerTest::CurrentView()->Redraw();
18d715bd 803
804 aView.Nullify();
805 a3DViewer.Nullify();
18d715bd 806
807 return aViewNames.GetViewName();
808}
809
4269bd1b 810//==============================================================================
811//function : RedrawAllViews
812//purpose : Redraw all created views
813//==============================================================================
814void ViewerTest::RedrawAllViews()
815{
1103eb60 816 ViewerTest_ViewerCommandsViewMap::Iterator aViewIt(ViewerTest_myViews);
4269bd1b 817 for (; aViewIt.More(); aViewIt.Next())
818 {
819 const Handle(V3d_View)& aView = aViewIt.Key2();
820 aView->Redraw();
821 }
822}
823
b8db9379 824//==============================================================================
825//function : VDriver
826//purpose :
827//==============================================================================
828static int VDriver (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
829{
830 if (theArgsNb == 1)
831 {
832 theDi << "Registered: ";
833 for (Graphic3d_GraphicDriverFactoryList::Iterator aFactoryIter (Graphic3d_GraphicDriverFactory::DriverFactories());
834 aFactoryIter.More(); aFactoryIter.Next())
835 {
836 const Handle(Graphic3d_GraphicDriverFactory)& aFactory = aFactoryIter.Value();
837 theDi << aFactory->Name() << " ";
838 }
839
840 theDi << "\n";
841 theDi << "Default: ";
842 if (Handle(Graphic3d_GraphicDriverFactory) aFactory = Graphic3d_GraphicDriverFactory::DefaultDriverFactory())
843 {
844 theDi << aFactory->Name();
845 }
846 else
847 {
848 theDi << "NONE";
849 }
850 return 0;
851 }
852
853 TCollection_AsciiString aNewActive;
854 bool toLoad = false;
855 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
856 {
857 TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
858 anArgCase.LowerCase();
859 if (anArgCase == "-list")
860 {
861 for (Graphic3d_GraphicDriverFactoryList::Iterator aFactoryIter (Graphic3d_GraphicDriverFactory::DriverFactories());
862 aFactoryIter.More(); aFactoryIter.Next())
863 {
864 const Handle(Graphic3d_GraphicDriverFactory)& aFactory = aFactoryIter.Value();
865 theDi << aFactory->Name() << " ";
866 }
867 }
868 else if ((anArgCase == "-default"
869 || anArgCase == "-load")
870 && aNewActive.IsEmpty())
871 {
872 toLoad = (anArgCase == "-load");
873 if (anArgIter + 1 < theArgsNb)
874 {
875 aNewActive = theArgVec[++anArgIter];
876 }
877 else if (toLoad)
878 {
879 theDi << "Syntax error at '" << theArgVec[anArgIter] << "'";
880 return 1;
881 }
882 else
883 {
884 if (Handle(Graphic3d_GraphicDriverFactory) aFactory = Graphic3d_GraphicDriverFactory::DefaultDriverFactory())
885 {
886 theDi << aFactory->Name();
887 }
888 else
889 {
890 theDi << "NONE";
891 }
892 }
893 }
894 else if (aNewActive.IsEmpty())
895 {
896 aNewActive = theArgVec[anArgIter];
897 }
898 else
899 {
900 theDi << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
901 return 1;
902 }
903 }
904
905 if (!aNewActive.IsEmpty())
906 {
907 const TCollection_AsciiString aNameCopy = aNewActive;
908 if (TCollection_AsciiString::IsSameString (aNewActive, "gl", false)
909 || TCollection_AsciiString::IsSameString (aNewActive, "opengl", false)
910 || TCollection_AsciiString::IsSameString (aNewActive, "tkopengl", false))
911 {
912 aNewActive = "tkopengl";
913 }
b8ef513c 914 else if (TCollection_AsciiString::IsSameString (aNewActive, "gles", false)
915 || TCollection_AsciiString::IsSameString (aNewActive, "opengles", false)
916 || TCollection_AsciiString::IsSameString (aNewActive, "tkopengles", false))
917 {
918 aNewActive = "tkopengles";
919 }
b8db9379 920 else if (TCollection_AsciiString::IsSameString (aNewActive, "d3d", false)
921 || TCollection_AsciiString::IsSameString (aNewActive, "d3dhost", false)
922 || TCollection_AsciiString::IsSameString (aNewActive, "tkd3dhost", false))
923 {
924 aNewActive = "tkd3dhost";
925 }
926
927 if (toLoad)
928 {
929 if (aNewActive == "tkopengl")
930 {
931 Draw::GetInterpretor().Eval ("pload OPENGL");
932 }
b8ef513c 933 else if (aNewActive == "tkopengles")
934 {
935 Draw::GetInterpretor().Eval ("pload GLES");
936 }
b8db9379 937 else if (aNewActive == "tkd3dhost")
938 {
939 Draw::GetInterpretor().Eval ("pload D3DHOST");
940 }
941 else
942 {
943 theDi << "Syntax error: unable to load plugin for unknown driver factory '" << aNameCopy << "'";
944 return 1;
945 }
946 }
947
948 bool isFound = false;
949 for (Graphic3d_GraphicDriverFactoryList::Iterator aFactoryIter (Graphic3d_GraphicDriverFactory::DriverFactories());
950 aFactoryIter.More(); aFactoryIter.Next())
951 {
952 Handle(Graphic3d_GraphicDriverFactory) aFactory = aFactoryIter.Value();
953 if (TCollection_AsciiString::IsSameString (aFactory->Name(), aNewActive, false))
954 {
955 Graphic3d_GraphicDriverFactory::RegisterFactory (aFactory, true);
956 isFound = true;
957 break;
958 }
959 }
960
961 if (!isFound)
962 {
963 theDi << "Syntax error: driver factory '" << aNameCopy << "' not found";
964 return 1;
965 }
966 }
967
968 return 0;
969}
970
7fd59977 971//==============================================================================
972//function : Vinit
973//purpose : Create the window viewer and initialize all the global variable
87b68a0f 974// Use Tcl_CreateFileHandler on UNIX to catch the X11 Viewer event
7fd59977 975//==============================================================================
18d715bd 976static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7fd59977 977{
879768fb 978 ViewerTest_VinitParams aParams;
e79a94b9 979 TCollection_AsciiString aName, aValue;
2275caec 980 int is2dMode = -1, aDpiAware = -1;
e79a94b9 981 for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
18d715bd 982 {
e79a94b9 983 const TCollection_AsciiString anArg = theArgVec[anArgIt];
984 TCollection_AsciiString anArgCase = anArg;
fd3f6bd0 985 anArgCase.LowerCase();
986 if (anArgIt + 1 < theArgsNb
987 && anArgCase == "-name")
988 {
879768fb 989 aParams.ViewName = theArgVec[++anArgIt];
fd3f6bd0 990 }
991 else if (anArgIt + 1 < theArgsNb
992 && (anArgCase == "-left"
879768fb 993 || anArgCase == "-l")
994 && Draw::ParseReal (theArgVec[anArgIt + 1], aParams.Offset.x()))
fd3f6bd0 995 {
879768fb 996 ++anArgIt;
fd3f6bd0 997 }
998 else if (anArgIt + 1 < theArgsNb
999 && (anArgCase == "-top"
879768fb 1000 || anArgCase == "-t")
1001 && Draw::ParseReal (theArgVec[anArgIt + 1], aParams.Offset.y()))
fd3f6bd0 1002 {
879768fb 1003 ++anArgIt;
fd3f6bd0 1004 }
1005 else if (anArgIt + 1 < theArgsNb
1006 && (anArgCase == "-width"
879768fb 1007 || anArgCase == "-w")
1008 && Draw::ParseReal (theArgVec[anArgIt + 1], aParams.Size.x()))
fd3f6bd0 1009 {
879768fb 1010 ++anArgIt;
fd3f6bd0 1011 }
1012 else if (anArgIt + 1 < theArgsNb
1013 && (anArgCase == "-height"
879768fb 1014 || anArgCase == "-h")
1015 && Draw::ParseReal (theArgVec[anArgIt + 1], aParams.Size.y()))
18d715bd 1016 {
879768fb 1017 ++anArgIt;
1018 }
1019 else if (anArgIt + 1 < theArgsNb
1020 && (anArgCase == "-pos"
1021 || anArgCase == "-position"
1022 || anArgCase == "-corner")
1023 && ViewerTest::ParseCorner (theArgVec[anArgIt + 1], aParams.Corner))
1024 {
1025 ++anArgIt;
1026 }
1027 else if (anArgIt + 2 < theArgsNb
1028 && anArgCase == "-margins"
1029 && Draw::ParseInteger (theArgVec[anArgIt + 1], aParams.SubviewMargins.x())
1030 && Draw::ParseInteger (theArgVec[anArgIt + 2], aParams.SubviewMargins.y()))
1031 {
1032 anArgIt += 2;
fd3f6bd0 1033 }
72ed0644 1034 else if (anArgCase == "-virtual"
1035 || anArgCase == "-offscreen")
1036 {
879768fb 1037 aParams.IsVirtual = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
1038 }
1039 else if (anArgCase == "-composer")
1040 {
1041 aParams.IsComposer = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
72ed0644 1042 }
fd3f6bd0 1043 else if (anArgCase == "-exitonclose")
1044 {
879768fb 1045 ViewerTest_EventManager::ToExitOnCloseView() = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
fd3f6bd0 1046 }
1047 else if (anArgCase == "-closeonescape"
1048 || anArgCase == "-closeonesc")
1049 {
879768fb 1050 ViewerTest_EventManager::ToCloseViewOnEscape() = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
fd3f6bd0 1051 }
2e93433e 1052 else if (anArgCase == "-2d_mode"
1053 || anArgCase == "-2dmode"
1054 || anArgCase == "-2d")
1055 {
879768fb 1056 bool toEnable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
2e93433e 1057 is2dMode = toEnable ? 1 : 0;
1058 }
fd3f6bd0 1059 else if (anArgIt + 1 < theArgsNb
1060 && (anArgCase == "-disp"
1061 || anArgCase == "-display"))
1062 {
879768fb 1063 aParams.DisplayName = theArgVec[++anArgIt];
fd3f6bd0 1064 }
2275caec 1065 else if (anArgCase == "-dpiaware")
1066 {
1067 aDpiAware = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt) ? 1 : 0;
1068 }
9e04ccdc 1069 else if (!ViewerTest::CurrentView().IsNull()
879768fb 1070 && aParams.ViewToClone.IsNull()
9e04ccdc 1071 && (anArgCase == "-copy"
1072 || anArgCase == "-clone"
1073 || anArgCase == "-cloneactive"
1074 || anArgCase == "-cloneactiveview"))
1075 {
879768fb 1076 aParams.ViewToClone = ViewerTest::CurrentView();
1077 }
1078 else if (!ViewerTest::CurrentView().IsNull()
1079 && aParams.ParentView.IsNull()
1080 && anArgCase == "-subview")
1081 {
1082 aParams.ParentView = ViewerTest::CurrentView();
1083 if (aParams.ParentView.IsNull())
1084 {
1085 Message::SendFail() << "Syntax error: cannot create of subview without parent";
1086 return 1;
1087 }
1088 if (aParams.ParentView->IsSubview())
1089 {
1090 aParams.ParentView = aParams.ParentView->ParentView();
1091 }
1092 }
1093 else if (!ViewerTest::CurrentView().IsNull()
1094 && aParams.ParentView.IsNull()
1095 && anArgCase == "-parent"
1096 && anArgIt + 1 < theArgsNb)
1097 {
1098 TCollection_AsciiString aParentStr (theArgVec[++anArgIt]);
1099 ViewerTest_Names aViewNames (aParentStr);
1100 if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
1101 {
1102 Message::SendFail() << "Syntax error: parent view '" << aParentStr << "' not found";
1103 return 1;
1104 }
1105
1106 aParams.ParentView = ViewerTest_myViews.Find1(aViewNames.GetViewName());
1107 if (aParams.ParentView->IsSubview())
1108 {
1109 aParams.ParentView = aParams.ParentView->ParentView();
1110 }
9e04ccdc 1111 }
fd3f6bd0 1112 // old syntax
1113 else if (ViewerTest::SplitParameter (anArg, aName, aValue))
1114 {
1115 aName.LowerCase();
1116 if (aName == "name")
18d715bd 1117 {
879768fb 1118 aParams.ViewName = aValue;
18d715bd 1119 }
fd3f6bd0 1120 else if (aName == "l"
1121 || aName == "left")
e79a94b9 1122 {
879768fb 1123 aParams.Offset.x() = (float)aValue.RealValue();
e79a94b9 1124 }
fd3f6bd0 1125 else if (aName == "t"
1126 || aName == "top")
e79a94b9 1127 {
879768fb 1128 aParams.Offset.y() = (float)aValue.RealValue();
e79a94b9 1129 }
fd3f6bd0 1130 else if (aName == "disp"
1131 || aName == "display")
e79a94b9 1132 {
879768fb 1133 aParams.DisplayName = aValue;
e79a94b9 1134 }
fd3f6bd0 1135 else if (aName == "w"
1136 || aName == "width")
e79a94b9 1137 {
879768fb 1138 aParams.Size.x() = (float )aValue.RealValue();
e79a94b9 1139 }
fd3f6bd0 1140 else if (aName == "h"
1141 || aName == "height")
e79a94b9 1142 {
879768fb 1143 aParams.Size.y() = (float)aValue.RealValue();
e79a94b9 1144 }
18d715bd 1145 else
1146 {
23fe70ec 1147 Message::SendFail() << "Syntax error: unknown argument " << anArg;
fd3f6bd0 1148 return 1;
18d715bd 1149 }
1150 }
879768fb 1151 else if (aParams.ViewName.IsEmpty())
e79a94b9 1152 {
879768fb 1153 aParams.ViewName = anArg;
e79a94b9 1154 }
1155 else
1156 {
23fe70ec 1157 Message::SendFail() << "Syntax error: unknown argument " << anArg;
fd3f6bd0 1158 return 1;
e79a94b9 1159 }
18d715bd 1160 }
1161
2275caec 1162#if defined(_WIN32)
1163 if (aDpiAware != -1)
1164 {
1165 typedef void* (WINAPI *SetThreadDpiAwarenessContext_t)(void*);
1166 if (HMODULE aUser32Module = GetModuleHandleW (L"User32"))
1167 {
1168 SetThreadDpiAwarenessContext_t aSetDpiAware = (SetThreadDpiAwarenessContext_t )GetProcAddress (aUser32Module, "SetThreadDpiAwarenessContext");
1169 if (aDpiAware == 1)
1170 {
1171 // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2
1172 if (aSetDpiAware ((void* )-4) == NULL)
1173 {
1174 // DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE for older systems
1175 if (aSetDpiAware ((void* )-3) == NULL)
1176 {
1177 Message::SendFail() << "Error: unable to enable DPI awareness";
1178 }
1179 }
1180 }
1181 else
1182 {
1183 // DPI_AWARENESS_CONTEXT_UNAWARE
1184 if (aSetDpiAware ((void* )-1) == NULL)
1185 {
1186 Message::SendFail() << "Error: unable to disable DPI awareness";
1187 }
1188 }
1189 }
1190 }
1191#else
1192 (void )aDpiAware;
b69e576a 1193#if !defined(HAVE_XLIB)
879768fb 1194 if (!aParams.DisplayName.IsEmpty())
fd3f6bd0 1195 {
879768fb 1196 aParams.DisplayName.Clear();
23fe70ec 1197 Message::SendWarning() << "Warning: display parameter will be ignored.\n";
fd3f6bd0 1198 }
2275caec 1199#endif
fd3f6bd0 1200#endif
1201
879768fb 1202 ViewerTest_Names aViewNames (aParams.ViewName);
e79a94b9 1203 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
18d715bd 1204 {
e79a94b9 1205 TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
1206 theDi.Eval (aCommand.ToCString());
2e93433e 1207 if (is2dMode != -1)
1208 {
1209 ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
1210 }
18d715bd 1211 return 0;
1212 }
1213
879768fb 1214 TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aParams);
2e93433e 1215 if (is2dMode != -1)
1216 {
1217 ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
1218 }
e79a94b9 1219 theDi << aViewId;
7fd59977 1220 return 0;
1221}
1222
1eeef710 1223//! Parse HLR algo type.
1224static Standard_Boolean parseHlrAlgoType (const char* theName,
1225 Prs3d_TypeOfHLR& theType)
1226{
1227 TCollection_AsciiString aName (theName);
1228 aName.LowerCase();
1229 if (aName == "polyalgo")
1230 {
1231 theType = Prs3d_TOH_PolyAlgo;
1232 }
1233 else if (aName == "algo")
1234 {
1235 theType = Prs3d_TOH_Algo;
1236 }
1237 else
1238 {
1239 return Standard_False;
1240 }
1241 return Standard_True;
1242}
1243
0a768f56 1244//==============================================================================
1245//function : VHLR
1246//purpose : hidden lines removal algorithm
1247//==============================================================================
1248
1249static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
1250{
1eeef710 1251 const Handle(V3d_View) aView = ViewerTest::CurrentView();
1252 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1253 if (aView.IsNull())
0a768f56 1254 {
23fe70ec 1255 Message::SendFail ("Error: no active viewer");
0a768f56 1256 return 1;
1257 }
1258
1eeef710 1259 Standard_Boolean hasHlrOnArg = Standard_False;
1260 Standard_Boolean hasShowHiddenArg = Standard_False;
1261 Standard_Boolean isHLROn = Standard_False;
1262 Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
1263 Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1264 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1265 for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
0a768f56 1266 {
1eeef710 1267 TCollection_AsciiString anArg (argv[anArgIter]);
1268 anArg.LowerCase();
1269 if (anUpdateTool.parseRedrawMode (anArg))
1270 {
1271 continue;
1272 }
1273 else if (anArg == "-showhidden"
1274 && anArgIter + 1 < argc
dae2a922 1275 && Draw::ParseOnOff (argv[anArgIter + 1], toShowHidden))
1eeef710 1276 {
1277 ++anArgIter;
1278 hasShowHiddenArg = Standard_True;
1279 continue;
1280 }
1281 else if ((anArg == "-type"
1282 || anArg == "-algo"
1283 || anArg == "-algotype")
1284 && anArgIter + 1 < argc
1285 && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1286 {
1287 ++anArgIter;
1288 continue;
1289 }
1290 else if (!hasHlrOnArg
dae2a922 1291 && Draw::ParseOnOff (argv[anArgIter], isHLROn))
1eeef710 1292 {
1293 hasHlrOnArg = Standard_True;
1294 continue;
1295 }
1296 // old syntax
1297 else if (!hasShowHiddenArg
dae2a922 1298 && Draw::ParseOnOff(argv[anArgIter], toShowHidden))
1eeef710 1299 {
1300 hasShowHiddenArg = Standard_True;
1301 continue;
1302 }
1303 else
1304 {
23fe70ec 1305 Message::SendFail() << "Syntax error at '" << argv[anArgIter] << "'";
1eeef710 1306 return 1;
1307 }
0a768f56 1308 }
1eeef710 1309 if (!hasHlrOnArg)
0a768f56 1310 {
1eeef710 1311 di << "HLR: " << aView->ComputedMode() << "\n";
1312 di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
1313 di << "HlrAlgo: ";
1314 switch (aCtx->DefaultDrawer()->TypeOfHLR())
1315 {
1316 case Prs3d_TOH_NotSet: di << "NotSet\n"; break;
1317 case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
1318 case Prs3d_TOH_Algo: di << "Algo\n"; break;
1319 }
1320 anUpdateTool.Invalidate();
1321 return 0;
0a768f56 1322 }
1323
1eeef710 1324 Standard_Boolean toRecompute = Standard_False;
1325 if (aTypeOfHLR != Prs3d_TOH_NotSet
1326 && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
e9224045 1327 {
1eeef710 1328 toRecompute = Standard_True;
1329 aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
1330 }
1331 if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
1332 {
1333 toRecompute = Standard_True;
1334 if (toShowHidden)
e9224045 1335 {
1eeef710 1336 aCtx->DefaultDrawer()->EnableDrawHiddenLine();
e9224045 1337 }
1338 else
1339 {
1eeef710 1340 aCtx->DefaultDrawer()->DisableDrawHiddenLine();
e9224045 1341 }
1eeef710 1342 }
e9224045 1343
1eeef710 1344 // redisplay shapes
1345 if (aView->ComputedMode() && isHLROn && toRecompute)
1346 {
1347 AIS_ListOfInteractive aListOfShapes;
1348 aCtx->DisplayedObjects (aListOfShapes);
1349 for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
e9224045 1350 {
1eeef710 1351 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
e9224045 1352 {
1eeef710 1353 aCtx->Redisplay (aShape, Standard_False);
e9224045 1354 }
1355 }
1356 }
0a768f56 1357
1eeef710 1358 aView->SetComputedMode (isHLROn);
0a768f56 1359 return 0;
1360}
1361
1362//==============================================================================
1363//function : VHLRType
1364//purpose : change type of using HLR algorithm
1365//==============================================================================
1366
1eeef710 1367static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
0a768f56 1368{
1eeef710 1369 const Handle(V3d_View) aView = ViewerTest::CurrentView();
1370 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1371 if (aView.IsNull())
0a768f56 1372 {
23fe70ec 1373 Message::SendFail ("Error: no active viewer");
0a768f56 1374 return 1;
1375 }
1376
1eeef710 1377 Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
1378 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
1379 AIS_ListOfInteractive aListOfShapes;
1380 for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
0a768f56 1381 {
1eeef710 1382 TCollection_AsciiString anArg (argv[anArgIter]);
1383 anArg.LowerCase();
1384 if (anUpdateTool.parseRedrawMode (anArg))
0a768f56 1385 {
1eeef710 1386 continue;
0a768f56 1387 }
1eeef710 1388 else if ((anArg == "-type"
1389 || anArg == "-algo"
1390 || anArg == "-algotype")
1391 && anArgIter + 1 < argc
1392 && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
1393 {
1394 ++anArgIter;
1395 continue;
1396 }
1397 // old syntax
1398 else if (aTypeOfHLR == Prs3d_TOH_NotSet
1399 && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
1400 {
1401 continue;
1402 }
1403 else
0a768f56 1404 {
1405 ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1eeef710 1406 TCollection_AsciiString aName (argv[anArgIter]);
0a768f56 1407 if (!aMap.IsBound2 (aName))
1408 {
23fe70ec 1409 Message::SendFail() << "Syntax error: Wrong shape name '" << aName << "'";
1eeef710 1410 return 1;
0a768f56 1411 }
1eeef710 1412
1413 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
1414 if (aShape.IsNull())
1415 {
23fe70ec 1416 Message::SendFail() << "Syntax error: '" << aName << "' is not a shape presentation";
1eeef710 1417 return 1;
1418 }
1419 aListOfShapes.Append (aShape);
1420 continue;
0a768f56 1421 }
1eeef710 1422 }
1423 if (aTypeOfHLR == Prs3d_TOH_NotSet)
1424 {
23fe70ec 1425 Message::SendFail ("Syntax error: wrong number of arguments");
1eeef710 1426 return 1;
1427 }
1428
1429 const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
1430 if (isGlobal)
1431 {
1432 aCtx->DisplayedObjects (aListOfShapes);
1433 aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
0a768f56 1434 }
1435
1eeef710 1436 for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
1437 {
1438 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1439 if (aShape.IsNull())
1440 {
1441 continue;
1442 }
1443
1444 const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
1445 && aView->ComputedMode();
1446 if (!isGlobal
1447 || aShape->TypeOfHLR() != aTypeOfHLR)
1448 {
1449 aShape->SetTypeOfHLR (aTypeOfHLR);
1450 }
1451 if (toUpdateShape)
1452 {
1453 aCtx->Redisplay (aShape, Standard_False);
1454 }
1455 }
0a768f56 1456 return 0;
1457}
1458
18d715bd 1459//==============================================================================
1460//function : FindViewIdByWindowHandle
1461//purpose : Find theView Id in the map of views by window handle
1462//==============================================================================
b69e576a 1463#if defined(_WIN32) || defined(HAVE_XLIB)
1464static TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWindowHandle)
18d715bd 1465{
1103eb60 1466 for (ViewerTest_ViewerCommandsViewMap::Iterator
18d715bd 1467 anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1468 {
1103eb60 1469 Aspect_Drawable aWindowHandle = anIter.Key2()->Window()->NativeHandle();
18d715bd 1470 if (aWindowHandle == theWindowHandle)
1471 return anIter.Key1();
1472 }
1473 return TCollection_AsciiString("");
1474}
1475#endif
1476
e084dbbc 1477//! Make the view active
1478void ActivateView (const TCollection_AsciiString& theViewName,
1479 Standard_Boolean theToUpdate = Standard_True)
18d715bd 1480{
b2fedee6 1481 if (const Handle(V3d_View)& aView = ViewerTest_myViews.Find1(theViewName))
879768fb 1482 {
1483 ViewerTest::ActivateView (aView, theToUpdate);
1484 }
1485}
1486
1487//==============================================================================
1488//function : ActivateView
1489//purpose :
1490//==============================================================================
1491void ViewerTest::ActivateView (const Handle(V3d_View)& theView,
1492 Standard_Boolean theToUpdate)
1493{
b2fedee6 1494 const Handle(V3d_View)& aView = theView;
879768fb 1495 const TCollection_AsciiString* aViewName = ViewerTest_myViews.Seek2 (aView);
1496 if (aViewName == nullptr)
18d715bd 1497 {
e084dbbc 1498 return;
1499 }
18d715bd 1500
e084dbbc 1501 Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
879768fb 1502 if (anAISContext.IsNull())
1503 {
1504 return;
1505 }
1506
1507 if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
e084dbbc 1508 {
879768fb 1509 if (!aCurrentView->Window().IsNull())
e084dbbc 1510 {
49582f9d 1511 aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
e084dbbc 1512 }
879768fb 1513 }
e084dbbc 1514
879768fb 1515 ViewerTest::CurrentView (aView);
1516 ViewerTest::SetAISContext (anAISContext);
1517 if (aView->IsSubview())
1518 {
1519 aView->ParentView()->Window()->SetTitle (TCollection_AsciiString("3D View - ") + *aViewName + "(*)");
1520 VT_GetWindow() = Handle(ViewerTest_Window)::DownCast(aView->View()->ParentView()->Window());
1521 }
1522 else
1523 {
1524 VT_GetWindow() = Handle(ViewerTest_Window)::DownCast(aView->Window());
1525 }
1526 if (!VT_GetWindow().IsNull())
1527 {
1528 VT_GetWindow()->SetTitle (TCollection_AsciiString("3D View - ") + *aViewName + "(*)");
1529 }
1530 SetDisplayConnection(aView->Viewer()->Driver()->GetDisplayConnection());
1531 if (theToUpdate)
1532 {
1533 aView->Redraw();
18d715bd 1534 }
1535}
1536
0e93d9e5 1537//==============================================================================
1538//function : RemoveView
1539//purpose :
1540//==============================================================================
1541void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1542 const Standard_Boolean theToRemoveContext)
1543{
1544 if (!ViewerTest_myViews.IsBound2 (theView))
1545 {
1546 return;
1547 }
1548
b2fedee6 1549 const TCollection_AsciiString& aViewName = ViewerTest_myViews.Find2 (theView);
0e93d9e5 1550 RemoveView (aViewName, theToRemoveContext);
1551}
1552
18d715bd 1553//==============================================================================
1554//function : RemoveView
4551e1be 1555//purpose : Close and remove view from display, clear maps if necessary
18d715bd 1556//==============================================================================
1557void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1558{
1559 if (!ViewerTest_myViews.IsBound1(theViewName))
1560 {
23fe70ec 1561 Message::SendFail() << "Wrong view name";
18d715bd 1562 return;
1563 }
1564
879768fb 1565 Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1566 Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1567 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
1568 aRedrawer.Stop (aView);
1569 if (!aView->Subviews().IsEmpty())
1570 {
1571 NCollection_Sequence<Handle(V3d_View)> aSubviews = aView->Subviews();
1572 for (const Handle(V3d_View)& aSubviewIter : aSubviews)
1573 {
1574 RemoveView (aSubviewIter, isContextRemoved);
1575 }
1576 }
1577
18d715bd 1578 // Activate another view if it's active now
1579 if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1580 {
1581 if (ViewerTest_myViews.Extent() > 1)
1582 {
1103eb60 1583 for (ViewerTest_ViewerCommandsViewMap::Iterator anIter (ViewerTest_myViews);
c48e2889 1584 anIter.More(); anIter.Next())
1585 {
18d715bd 1586 if (anIter.Key1() != theViewName)
1587 {
1103eb60 1588 ActivateView (anIter.Key2(), true);
18d715bd 1589 break;
1590 }
c48e2889 1591 }
18d715bd 1592 }
1593 else
1594 {
e084dbbc 1595 VT_GetWindow().Nullify();
1596 ViewerTest::CurrentView (Handle(V3d_View)());
18d715bd 1597 if (isContextRemoved)
1598 {
1599 Handle(AIS_InteractiveContext) anEmptyContext;
1600 ViewerTest::SetAISContext(anEmptyContext);
1601 }
1602 }
1603 }
1604
1103eb60 1605 // Delete view, name will be removed too
1606 const TCollection_AsciiString aCopyString(theViewName);
18d715bd 1607 ViewerTest_myViews.UnBind1(theViewName);
879768fb 1608 if (!aView->Window().IsNull())
1609 {
1610 aView->Window()->Unmap();
1611 }
18d715bd 1612 aView->Remove();
1613
b69e576a 1614#if defined(HAVE_XLIB)
1615 XFlush ((::Display* )GetDisplayConnection()->GetDisplayAspect());
18d715bd 1616#endif
1617
1618 // Keep context opened only if the closed view is last to avoid
1619 // unused empty contexts
1620 if (!aCurrentContext.IsNull())
1621 {
f227f3dc 1622 // Check if there are more defined views in the viewer
f7fc0c03 1623 if ((isContextRemoved || ViewerTest_myContexts.Size() != 1)
1624 && aCurrentContext->CurrentViewer()->DefinedViews().IsEmpty())
18d715bd 1625 {
1626 // Remove driver if there is no viewers that use it
1627 Standard_Boolean isRemoveDriver = Standard_True;
1103eb60 1628 for(ViewerTest_ViewerCommandsInteractiveContextMap::Iterator
18d715bd 1629 anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1630 {
1631 if (aCurrentContext != anIter.Key2() &&
1103eb60 1632 aCurrentContext->CurrentViewer()->Driver() == anIter.Key2()->CurrentViewer()->Driver())
18d715bd 1633 {
1634 isRemoveDriver = Standard_False;
1635 break;
1636 }
1637 }
2ec85268 1638
1639 aCurrentContext->RemoveAll (Standard_False);
18d715bd 1640 if(isRemoveDriver)
1641 {
1642 ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
b69e576a 1643 #if defined(HAVE_XLIB)
1644 Tcl_DeleteFileHandler (XConnectionNumber ((::Display* )aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplayAspect()));
18d715bd 1645 #endif
1646 }
1647
1648 ViewerTest_myContexts.UnBind2(aCurrentContext);
1649 }
1650 }
1103eb60 1651 Message::SendInfo() << "3D View - " << aCopyString << " was deleted.\n";
49582f9d 1652 if (ViewerTest_EventManager::ToExitOnCloseView())
fd3f6bd0 1653 {
1654 Draw_Interprete ("exit");
1655 }
18d715bd 1656}
1657
1658//==============================================================================
1659//function : VClose
1660//purpose : Remove the view defined by its name
1661//==============================================================================
1662
d0cc1cb7 1663static int VClose (Draw_Interpretor& /*theDi*/,
1664 Standard_Integer theArgsNb,
1665 const char** theArgVec)
18d715bd 1666{
18d715bd 1667 NCollection_List<TCollection_AsciiString> aViewList;
d0cc1cb7 1668 if (theArgsNb > 1)
18d715bd 1669 {
d0cc1cb7 1670 TCollection_AsciiString anArg (theArgVec[1]);
1671 anArg.UpperCase();
1672 if (anArg.IsEqual ("ALL")
1673 || anArg.IsEqual ("*"))
1674 {
1103eb60 1675 for (ViewerTest_ViewerCommandsViewMap::Iterator anIter (ViewerTest_myViews);
d0cc1cb7 1676 anIter.More(); anIter.Next())
1677 {
1678 aViewList.Append (anIter.Key1());
1679 }
1680 if (aViewList.IsEmpty())
1681 {
1682 std::cout << "No view to close\n";
1683 return 0;
1684 }
1685 }
1686 else
18d715bd 1687 {
d0cc1cb7 1688 ViewerTest_Names aViewName (theArgVec[1]);
1689 if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1690 {
23fe70ec 1691 Message::SendFail() << "Error: the view with name '" << theArgVec[1] << "' does not exist";
d0cc1cb7 1692 return 1;
1693 }
1694 aViewList.Append (aViewName.GetViewName());
18d715bd 1695 }
1696 }
1697 else
1698 {
d0cc1cb7 1699 // close active view
1700 if (ViewerTest::CurrentView().IsNull())
1701 {
23fe70ec 1702 Message::SendFail ("Error: no active view");
d0cc1cb7 1703 return 1;
1704 }
1705 aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
18d715bd 1706 }
1707
d0cc1cb7 1708 Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
18d715bd 1709 for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1710 anIter.More(); anIter.Next())
1711 {
d0cc1cb7 1712 ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
18d715bd 1713 }
1714
1715 return 0;
1716}
1717
1718//==============================================================================
1719//function : VActivate
1720//purpose : Activate the view defined by its ID
1721//==============================================================================
1722
1723static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1724{
e084dbbc 1725 if (theArgsNb == 1)
18d715bd 1726 {
1727 theDi.Eval("vviewlist");
1728 return 0;
1729 }
1730
e084dbbc 1731 TCollection_AsciiString aNameString;
1732 Standard_Boolean toUpdate = Standard_True;
1733 Standard_Boolean toActivate = Standard_True;
1734 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
18d715bd 1735 {
e084dbbc 1736 TCollection_AsciiString anArg (theArgVec[anArgIter]);
1737 anArg.LowerCase();
1738 if (toUpdate
1739 && anArg == "-noupdate")
1740 {
1741 toUpdate = Standard_False;
1742 }
1743 else if (toActivate
1744 && aNameString.IsEmpty()
1745 && anArg == "none")
1746 {
49582f9d 1747 ViewerTest::CurrentView()->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
e084dbbc 1748 VT_GetWindow().Nullify();
1749 ViewerTest::CurrentView (Handle(V3d_View)());
1750 ViewerTest::ResetEventManager();
1751 theDi << theArgVec[0] << ": all views are inactive\n";
1752 toActivate = Standard_False;
1753 }
1754 else if (toActivate
1755 && aNameString.IsEmpty())
1756 {
1757 aNameString = theArgVec[anArgIter];
1758 }
1759 else
1760 {
23fe70ec 1761 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
e084dbbc 1762 return 1;
1763 }
18d715bd 1764 }
1765
e084dbbc 1766 if (!toActivate)
1767 {
1768 return 0;
1769 }
1770 else if (aNameString.IsEmpty())
1771 {
23fe70ec 1772 Message::SendFail ("Syntax error: wrong number of arguments");
e084dbbc 1773 return 1;
1774 }
18d715bd 1775
1776 // Check if this view exists in the viewer with the driver
e084dbbc 1777 ViewerTest_Names aViewNames (aNameString);
18d715bd 1778 if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1779 {
e084dbbc 1780 theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
18d715bd 1781 return 1;
1782 }
1783
1784 // Check if it is active already
1785 if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1786 {
1787 theDi << theArgVec[0] << ": the view is active already\n";
1788 return 0;
1789 }
1790
e084dbbc 1791 ActivateView (aViewNames.GetViewName(), toUpdate);
18d715bd 1792 return 0;
1793}
1794
1795//==============================================================================
1796//function : VViewList
1797//purpose : Print current list of views per viewer and graphic driver ID
1798// shared between viewers
1799//==============================================================================
1800
1801static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1802{
1803 if (theArgsNb > 2)
1804 {
1805 theDi << theArgVec[0] << ": Wrong number of command arguments\n"
29cb310a 1806 << "Usage: " << theArgVec[0] << " name";
18d715bd 1807 return 1;
1808 }
1809 if (ViewerTest_myContexts.Size() < 1)
1810 return 0;
1811
18d715bd 1812 Standard_Boolean isTreeView =
29cb310a 1813 (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
18d715bd 1814
1815 if (isTreeView)
c48e2889 1816 {
18d715bd 1817 theDi << theArgVec[0] <<":\n";
c48e2889 1818 }
18d715bd 1819
1103eb60 1820 for (ViewerTest_ViewerCommandsGraphicDriverMap::Iterator aDriverIter (ViewerTest_myDrivers);
c48e2889 1821 aDriverIter.More(); aDriverIter.Next())
1822 {
1823 if (isTreeView)
1824 theDi << aDriverIter.Key1() << ":\n";
18d715bd 1825
1103eb60 1826 for (ViewerTest_ViewerCommandsInteractiveContextMap::Iterator
c48e2889 1827 aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1828 {
1829 if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
18d715bd 1830 {
c48e2889 1831 if (isTreeView)
18d715bd 1832 {
c48e2889 1833 TCollection_AsciiString aContextName(aContextIter.Key1());
1834 theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1835 }
18d715bd 1836
1103eb60 1837 for (ViewerTest_ViewerCommandsViewMap::Iterator aViewIter (ViewerTest_myViews);
c48e2889 1838 aViewIter.More(); aViewIter.Next())
1839 {
1840 if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
18d715bd 1841 {
c48e2889 1842 TCollection_AsciiString aViewName(aViewIter.Key1());
1843 if (isTreeView)
18d715bd 1844 {
1103eb60 1845 if (aViewIter.Key2() == ViewerTest::CurrentView())
c48e2889 1846 theDi << " " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
18d715bd 1847 else
c48e2889 1848 theDi << " " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1849 }
1850 else
1851 {
1852 theDi << aViewName << " ";
18d715bd 1853 }
1854 }
1855 }
1856 }
1857 }
c48e2889 1858 }
18d715bd 1859 return 0;
1860}
1861
7fd59977 1862//==============================================================================
49582f9d 1863//function : GetMousePosition
1864//purpose :
7fd59977 1865//==============================================================================
49582f9d 1866void ViewerTest::GetMousePosition (Standard_Integer& theX,
1867 Standard_Integer& theY)
7fd59977 1868{
49582f9d 1869 if (Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager())
4fe56619 1870 {
49582f9d 1871 theX = aViewCtrl->LastMousePosition().x();
1872 theY = aViewCtrl->LastMousePosition().y();
4fe56619 1873 }
7fd59977 1874}
1875
44b8f2d6 1876//==============================================================================
fc552d84 1877//function : VViewProj
1878//purpose : Switch view projection
44b8f2d6 1879//==============================================================================
fc552d84 1880static int VViewProj (Draw_Interpretor& ,
1881 Standard_Integer theNbArgs,
1882 const char** theArgVec)
44b8f2d6 1883{
fc552d84 1884 static Standard_Boolean isYup = Standard_False;
1885 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
1886 if (aView.IsNull())
44b8f2d6 1887 {
23fe70ec 1888 Message::SendFail ("Error: no active viewer");
44b8f2d6 1889 return 1;
1890 }
1891
fc552d84 1892 TCollection_AsciiString aCmdName (theArgVec[0]);
1893 Standard_Boolean isGeneralCmd = Standard_False;
1894 if (aCmdName == "vfront")
1895 {
1896 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
1897 }
1898 else if (aCmdName == "vback")
1899 {
1900 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
1901 }
1902 else if (aCmdName == "vtop")
1903 {
1904 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
1905 }
1906 else if (aCmdName == "vbottom")
1907 {
1908 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
1909 }
1910 else if (aCmdName == "vleft")
1911 {
1912 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
1913 }
1914 else if (aCmdName == "vright")
1915 {
1916 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
1917 }
1918 else if (aCmdName == "vaxo")
1919 {
1920 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
1921 }
1922 else
1923 {
1924 isGeneralCmd = Standard_True;
1925 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
1926 {
1927 TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
1928 anArgCase.LowerCase();
1929 if (anArgCase == "-zup")
1930 {
1931 isYup = Standard_False;
1932 }
1933 else if (anArgCase == "-yup")
1934 {
1935 isYup = Standard_True;
1936 }
1937 else if (anArgCase == "-front"
1938 || anArgCase == "front"
1939 || anArgCase == "-f"
1940 || anArgCase == "f")
1941 {
1942 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
1943 }
1944 else if (anArgCase == "-back"
1945 || anArgCase == "back"
1946 || anArgCase == "-b"
1947 || anArgCase == "b")
1948 {
1949 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
1950 }
1951 else if (anArgCase == "-top"
1952 || anArgCase == "top"
1953 || anArgCase == "-t"
1954 || anArgCase == "t")
1955 {
1956 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
1957 }
1958 else if (anArgCase == "-bottom"
1959 || anArgCase == "bottom"
1960 || anArgCase == "-bot"
1961 || anArgCase == "bot"
1962 || anArgCase == "-b"
1963 || anArgCase == "b")
1964 {
1965 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
1966 }
1967 else if (anArgCase == "-left"
1968 || anArgCase == "left"
1969 || anArgCase == "-l"
1970 || anArgCase == "l")
1971 {
1972 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
1973 }
1974 else if (anArgCase == "-right"
1975 || anArgCase == "right"
1976 || anArgCase == "-r"
1977 || anArgCase == "r")
1978 {
1979 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
1980 }
1981 else if (anArgCase == "-axoleft"
1982 || anArgCase == "-leftaxo"
1983 || anArgCase == "axoleft"
1984 || anArgCase == "leftaxo")
1985 {
1986 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
1987 }
1988 else if (anArgCase == "-axo"
1989 || anArgCase == "axo"
1990 || anArgCase == "-a"
1991 || anArgCase == "a"
1992 || anArgCase == "-axoright"
1993 || anArgCase == "-rightaxo"
1994 || anArgCase == "axoright"
1995 || anArgCase == "rightaxo")
1996 {
1997 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
1998 }
1999 else if (anArgCase == "+x")
2000 {
2001 aView->SetProj (V3d_Xpos, isYup);
2002 }
2003 else if (anArgCase == "-x")
2004 {
2005 aView->SetProj (V3d_Xneg, isYup);
2006 }
2007 else if (anArgCase == "+y")
2008 {
2009 aView->SetProj (V3d_Ypos, isYup);
2010 }
2011 else if (anArgCase == "-y")
2012 {
2013 aView->SetProj (V3d_Yneg, isYup);
2014 }
2015 else if (anArgCase == "+z")
2016 {
2017 aView->SetProj (V3d_Zpos, isYup);
2018 }
2019 else if (anArgCase == "-z")
2020 {
2021 aView->SetProj (V3d_Zneg, isYup);
2022 }
2023 else if (anArgCase == "+x+y+z")
2024 {
2025 aView->SetProj (V3d_XposYposZpos, isYup);
2026 }
2027 else if (anArgCase == "+x+y-z")
2028 {
2029 aView->SetProj (V3d_XposYposZneg, isYup);
2030 }
2031 else if (anArgCase == "+x-y+z")
2032 {
2033 aView->SetProj (V3d_XposYnegZpos, isYup);
2034 }
2035 else if (anArgCase == "+x-y-z")
2036 {
2037 aView->SetProj (V3d_XposYnegZneg, isYup);
2038 }
2039 else if (anArgCase == "-x+y+z")
2040 {
2041 aView->SetProj (V3d_XnegYposZpos, isYup);
2042 }
2043 else if (anArgCase == "-x+y-z")
2044 {
2045 aView->SetProj (V3d_XnegYposZneg, isYup);
2046 }
2047 else if (anArgCase == "-x-y+z")
2048 {
2049 aView->SetProj (V3d_XnegYnegZpos, isYup);
2050 }
2051 else if (anArgCase == "-x-y-z")
2052 {
2053 aView->SetProj (V3d_XnegYnegZneg, isYup);
2054 }
2055 else if (anArgCase == "+x+y")
2056 {
2057 aView->SetProj (V3d_XposYpos, isYup);
2058 }
2059 else if (anArgCase == "+x-y")
2060 {
2061 aView->SetProj (V3d_XposYneg, isYup);
2062 }
2063 else if (anArgCase == "-x+y")
2064 {
2065 aView->SetProj (V3d_XnegYpos, isYup);
2066 }
2067 else if (anArgCase == "-x-y")
2068 {
2069 aView->SetProj (V3d_XnegYneg, isYup);
2070 }
2071 else if (anArgCase == "+x+z")
2072 {
2073 aView->SetProj (V3d_XposZpos, isYup);
2074 }
2075 else if (anArgCase == "+x-z")
2076 {
2077 aView->SetProj (V3d_XposZneg, isYup);
2078 }
2079 else if (anArgCase == "-x+z")
2080 {
2081 aView->SetProj (V3d_XnegZpos, isYup);
2082 }
2083 else if (anArgCase == "-x-z")
2084 {
2085 aView->SetProj (V3d_XnegZneg, isYup);
2086 }
2087 else if (anArgCase == "+y+z")
2088 {
2089 aView->SetProj (V3d_YposZpos, isYup);
2090 }
2091 else if (anArgCase == "+y-z")
2092 {
2093 aView->SetProj (V3d_YposZneg, isYup);
2094 }
2095 else if (anArgCase == "-y+z")
2096 {
2097 aView->SetProj (V3d_YnegZpos, isYup);
2098 }
2099 else if (anArgCase == "-y-z")
2100 {
2101 aView->SetProj (V3d_YnegZneg, isYup);
2102 }
2103 else if (anArgIter + 1 < theNbArgs
2104 && anArgCase == "-frame"
2105 && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
2106 {
2107 TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
2108 aFrameDef.LowerCase();
2109 gp_Dir aRight, anUp;
2110 if (aFrameDef.Value (2) == aFrameDef.Value (4))
2111 {
23fe70ec 2112 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
fc552d84 2113 return 1;
2114 }
44b8f2d6 2115
fc552d84 2116 if (aFrameDef.Value (2) == 'x')
2117 {
2118 aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
2119 }
2120 else if (aFrameDef.Value (2) == 'y')
2121 {
2122 aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
2123 }
2124 else if (aFrameDef.Value (2) == 'z')
2125 {
2126 aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
2127 }
2128 else
2129 {
23fe70ec 2130 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
fc552d84 2131 return 1;
2132 }
7fd59977 2133
fc552d84 2134 if (aFrameDef.Value (4) == 'x')
2135 {
2136 anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
2137 }
2138 else if (aFrameDef.Value (4) == 'y')
2139 {
2140 anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
2141 }
2142 else if (aFrameDef.Value (4) == 'z')
2143 {
2144 anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
2145 }
2146 else
2147 {
23fe70ec 2148 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
fc552d84 2149 return 1;
2150 }
44b8f2d6 2151
fc552d84 2152 const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
2153 const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
2154 const gp_Dir aDir = anUp.Crossed (aRight);
2155 aCamera->SetCenter (gp_Pnt (0, 0, 0));
2156 aCamera->SetDirection (aDir);
2157 aCamera->SetUp (anUp);
2158 aCamera->OrthogonalizeUp();
44b8f2d6 2159
fc552d84 2160 aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
2161 aView->Update();
2162 }
2163 else
2164 {
23fe70ec 2165 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
fc552d84 2166 return 1;
2167 }
2168 }
2169 }
44b8f2d6 2170
fc552d84 2171 if (!isGeneralCmd
2172 && theNbArgs != 1)
2173 {
23fe70ec 2174 Message::SendFail ("Syntax error: wrong number of arguments");
fc552d84 2175 return 1;
2176 }
2177 return 0;
7fd59977 2178}
2179
2180//==============================================================================
2181//function : VHelp
2182//purpose : Dsiplay help on viewer Keyboead and mouse commands
2183//Draw arg : No args
2184//==============================================================================
2185
2186static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
2187{
586db386 2188 di << "=========================\n";
2189 di << "F : FitAll\n";
2190 di << "T : TopView\n";
2191 di << "B : BottomView\n";
2192 di << "R : RightView\n";
2193 di << "L : LeftView\n";
d22962e4 2194 di << "Backspace : AxonometricView\n";
586db386 2195
2196 di << "=========================\n";
d22962e4 2197 di << "W, S : Fly forward/backward\n";
2198 di << "A, D : Slide left/right\n";
2199 di << "Q, E : Bank left/right\n";
2200 di << "-, + : Change flying speed\n";
2201 di << "Arrows : look left/right/up/down\n";
2202 di << "Arrows+Shift : slide left/right/up/down\n";
2203
2204 di << "=========================\n";
2205 di << "S + Ctrl : Shading\n";
2206 di << "W + Ctrl : Wireframe\n";
49582f9d 2207 di << "H : HiddenLineRemoval\n";
586db386 2208 di << "U : Unset display mode\n";
2209 di << "Delete : Remove selection from viewer\n";
2210
2211 di << "=========================\n";
2212 di << "Selection mode \n";
2213 di << "0 : Shape\n";
2214 di << "1 : Vertex\n";
2215 di << "2 : Edge\n";
2216 di << "3 : Wire\n";
2217 di << "4 : Face\n";
2218 di << "5 : Shell\n";
2219 di << "6 : Solid\n";
2220 di << "7 : Compound\n";
2221
2222 di << "=========================\n";
49582f9d 2223 di << "< : Hilight next detected\n";
2224 di << "> : Hilight previous detected\n";
7fd59977 2225
2226 return 0;
2227}
2228
57c28b61 2229#ifdef _WIN32
7fd59977 2230
49582f9d 2231static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
2232 UINT theMsg,
2233 WPARAM wParam,
2234 LPARAM lParam )
7fd59977 2235{
49582f9d 2236 if (ViewerTest_myViews.IsEmpty())
2237 {
e8e157df 2238 return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
49582f9d 2239 }
7fd59977 2240
49582f9d 2241 switch (theMsg)
2242 {
18d715bd 2243 case WM_CLOSE:
49582f9d 2244 {
2245 // Delete view from map of views
2246 ViewerTest::RemoveView (FindViewIdByWindowHandle (theWinHandle));
2247 return 0;
2248 }
18d715bd 2249 case WM_ACTIVATE:
49582f9d 2250 {
2251 if (LOWORD(wParam) == WA_CLICKACTIVE
2252 || LOWORD(wParam) == WA_ACTIVE
2253 || ViewerTest::CurrentView().IsNull())
18d715bd 2254 {
2255 // Activate inactive window
49582f9d 2256 if (VT_GetWindow().IsNull()
2257 || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
625e1958 2258 {
49582f9d 2259 ActivateView (FindViewIdByWindowHandle (theWinHandle));
625e1958 2260 }
7fd59977 2261 }
e8e157df 2262 return 0;
49582f9d 2263 }
e8e157df 2264 default:
49582f9d 2265 {
e8e157df 2266 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2267 if (!aView.IsNull()
2268 && !VT_GetWindow().IsNull())
49582f9d 2269 {
e8e157df 2270 MSG aMsg = {};
2271 aMsg.hwnd = theWinHandle;
2272 aMsg.message = theMsg;
2273 aMsg.wParam = wParam;
2274 aMsg.lParam = lParam;
2275 if (VT_GetWindow()->ProcessMessage (*ViewerTest::CurrentEventManager(), aMsg))
49582f9d 2276 {
e8e157df 2277 return 0;
49582f9d 2278 }
2279 }
7fd59977 2280 }
49582f9d 2281 }
e8e157df 2282 return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
7fd59977 2283}
2284
7fd59977 2285//==============================================================================
2286//function : ViewerMainLoop
2287//purpose : Get a Event on the view and dispatch it
2288//==============================================================================
2289
49582f9d 2290int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
7fd59977 2291{
49582f9d 2292 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
2293 if (aViewCtrl.IsNull()
2294 || theNbArgs < 4)
2295 {
2296 return 0;
2297 }
7fd59977 2298
49582f9d 2299 aViewCtrl->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
7fd59977 2300
49582f9d 2301 std::cout << "Start picking\n";
7fd59977 2302
49582f9d 2303 MSG aMsg;
2304 aMsg.wParam = 1;
2305 while (aViewCtrl->ToPickPoint())
2306 {
2307 // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2308 if (GetMessageW (&aMsg, NULL, 0, 0))
2309 {
2310 TranslateMessage (&aMsg);
2311 DispatchMessageW (&aMsg);
7fd59977 2312 }
7fd59977 2313 }
2314
49582f9d 2315 std::cout << "Picking done\n";
2316 return 0;
7fd59977 2317}
2318
b69e576a 2319#elif defined(HAVE_XLIB)
7fd59977 2320
49582f9d 2321int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
4269bd1b 2322{
18d715bd 2323 static XEvent aReport;
49582f9d 2324 const Standard_Boolean toPick = theNbArgs > 0;
2325 if (theNbArgs > 0)
2326 {
2327 if (ViewerTest::CurrentEventManager().IsNull())
2328 {
2329 return 0;
2330 }
2331 ViewerTest::CurrentEventManager()->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
2332 }
2333
b69e576a 2334 Display* aDisplay = (Display* )GetDisplayConnection()->GetDisplayAspect();
18d715bd 2335 XNextEvent (aDisplay, &aReport);
7fd59977 2336
18d715bd 2337 // Handle event for the chosen display connection
8693dfd0 2338 switch (aReport.type)
2339 {
2340 case ClientMessage:
2341 {
2342 if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2343 {
2344 // Close the window
2345 ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2346 return toPick ? 0 : 1;
2347 }
2348 break;
2349 }
2350 case FocusIn:
2351 {
2352 // Activate inactive view
49582f9d 2353 Window aWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
8693dfd0 2354 if (aWindow != aReport.xfocus.window)
2355 {
2356 ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2357 }
2358 break;
2359 }
e8e157df 2360 default:
8693dfd0 2361 {
e8e157df 2362 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2363 if (!aView.IsNull()
2364 && !VT_GetWindow().IsNull())
8693dfd0 2365 {
e8e157df 2366 VT_GetWindow()->ProcessMessage (*ViewerTest::CurrentEventManager(), aReport);
49582f9d 2367 }
8693dfd0 2368 break;
2369 }
2370 }
49582f9d 2371 return (!toPick || ViewerTest::CurrentEventManager()->ToPickPoint()) ? 1 : 0;
7fd59977 2372}
2373
2374//==============================================================================
2375//function : VProcessEvents
8693dfd0 2376//purpose : manage the event in the Viewer window (see Tcl_CreateFileHandler())
7fd59977 2377//==============================================================================
8693dfd0 2378static void VProcessEvents (ClientData theDispX, int)
7fd59977 2379{
8693dfd0 2380 Display* aDispX = (Display* )theDispX;
2381 Handle(Aspect_DisplayConnection) aDispConn;
1103eb60 2382 for (ViewerTest_ViewerCommandsGraphicDriverMap::Iterator
8693dfd0 2383 aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
18d715bd 2384 {
8693dfd0 2385 const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
b69e576a 2386 if ((Display* )aDispConnTmp->GetDisplayAspect() == aDispX)
8693dfd0 2387 {
2388 aDispConn = aDispConnTmp;
2389 break;
2390 }
2391 }
2392 if (aDispConn.IsNull())
2393 {
23fe70ec 2394 Message::SendFail ("Error: ViewerTest is unable processing messages for unknown X Display");
8693dfd0 2395 return;
4269bd1b 2396 }
8693dfd0 2397
2398 // process new events in queue
2399 SetDisplayConnection (aDispConn);
2400 int aNbRemain = 0;
2401 for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
18d715bd 2402 {
8693dfd0 2403 const int anEventResult = ViewerMainLoop (0, NULL);
2404 if (anEventResult == 0)
18d715bd 2405 {
8693dfd0 2406 return;
2407 }
2408
2409 aNbRemain = XPending (aDispX);
2410 if (++anEventIter >= aNbEventsMax
2411 || aNbRemain <= 0)
2412 {
2413 break;
18d715bd 2414 }
7fd59977 2415 }
4269bd1b 2416
8693dfd0 2417 // Listening X events through Tcl_CreateFileHandler() callback is fragile,
2418 // it is possible that new events will arrive to queue before the end of this callback
2419 // so that either this callback should go into an infinite loop (blocking processing of other events)
2420 // or to keep unprocessed events till the next queue update (which can arrive not soon).
2421 // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
2422 if (aNbRemain != 0)
2423 {
2424 XEvent aDummyEvent;
2425 memset (&aDummyEvent, 0, sizeof(aDummyEvent));
2426 aDummyEvent.type = ClientMessage;
2427 aDummyEvent.xclient.format = 32;
2428 XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
2429 XFlush (aDispX);
2430 }
4269bd1b 2431
8693dfd0 2432 if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
2433 {
2434 SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
2435 }
7fd59977 2436}
b69e576a 2437#elif !defined(__APPLE__)
2438// =======================================================================
2439// function : ViewerMainLoop
2440// purpose :
2441// =======================================================================
2442int ViewerMainLoop (Standard_Integer , const char** )
2443{
2444 // unused
2445 return 0;
2446}
7fd59977 2447#endif
2448
7fd59977 2449//==============================================================================
2450//function : VFit
1beb58d7 2451//purpose :
7fd59977 2452//==============================================================================
2453
1beb58d7 2454static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
7fd59977 2455{
1beb58d7 2456 const Handle(V3d_View) aView = ViewerTest::CurrentView();
2457 if (aView.IsNull())
b586500b 2458 {
23fe70ec 2459 Message::SendFail ("Error: no active viewer");
1beb58d7 2460 return 1;
b586500b 2461 }
2462
1beb58d7 2463 Standard_Boolean toFit = Standard_True;
2464 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2465 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
b586500b 2466 {
1beb58d7 2467 TCollection_AsciiString anArg (theArgv[anArgIter]);
b586500b 2468 anArg.LowerCase();
1beb58d7 2469 if (anUpdateTool.parseRedrawMode (anArg))
b586500b 2470 {
1beb58d7 2471 continue;
2472 }
2473 else if (anArg == "-selected")
2474 {
2475 ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
2476 toFit = Standard_False;
2477 }
2478 else
2479 {
23fe70ec 2480 Message::SendFail() << "Syntax error at '" << anArg << "'";
b586500b 2481 }
2482 }
2483
1beb58d7 2484 if (toFit)
2485 {
2486 aView->FitAll (0.01, Standard_False);
7fd59977 2487 }
2488 return 0;
2489}
2490
6262a303 2491//=======================================================================
2492//function : VFitArea
2493//purpose : Fit view to show area located between two points
2494// : given in world 2D or 3D coordinates.
2495//=======================================================================
2496static int VFitArea (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2497{
2498 Handle(V3d_View) aView = ViewerTest::CurrentView();
2499 if (aView.IsNull())
2500 {
23fe70ec 2501 Message::SendFail ("Error: No active viewer");
6262a303 2502 return 1;
2503 }
2504
2505 // Parse arguments.
2506 gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2507 gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2508
2509 if (theArgNb == 5)
2510 {
2511 aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2512 aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2513 aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2514 aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2515 }
2516 else if (theArgNb == 7)
2517 {
2518 aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2519 aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2520 aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2521 aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2522 aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2523 aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2524 }
2525 else
2526 {
23fe70ec 2527 Message::SendFail ("Syntax error: Invalid number of arguments");
6262a303 2528 theDI.PrintHelp(theArgVec[0]);
2529 return 1;
2530 }
2531
2532 // Convert model coordinates to view space
2533 Handle(Graphic3d_Camera) aCamera = aView->Camera();
2534 gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2535 gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2536
2537 // Determine fit area
2538 gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2539 gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2540
2541 Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2542
2543 if (aDiagonal < Precision::Confusion())
2544 {
23fe70ec 2545 Message::SendFail ("Error: view area is too small");
6262a303 2546 return 1;
2547 }
2548
2549 aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2550 return 0;
2551}
2552
7fd59977 2553//==============================================================================
2554//function : VZFit
2555//purpose : ZFitall, no DRAW arguments
2556//Draw arg : No args
2557//==============================================================================
197ac94e 2558static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
7fd59977 2559{
197ac94e 2560 const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2561
2562 if (aCurrentView.IsNull())
2563 {
23fe70ec 2564 Message::SendFail ("Error: no active viewer");
197ac94e 2565 return 1;
2566 }
2567
2568 if (theArgsNb == 1)
2569 {
c357e426 2570 aCurrentView->ZFitAll();
197ac94e 2571 aCurrentView->Redraw();
2572 return 0;
2573 }
2574
2575 Standard_Real aScale = 1.0;
2576
2577 if (theArgsNb >= 2)
2578 {
2579 aScale = Draw::Atoi (theArgVec[1]);
2580 }
2581
c357e426 2582 aCurrentView->ZFitAll (aScale);
197ac94e 2583 aCurrentView->Redraw();
7fd59977 2584
197ac94e 2585 return 0;
2586}
7fd59977 2587
197ac94e 2588//==============================================================================
2589//function : VRepaint
2590//purpose :
2591//==============================================================================
56689b27 2592static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
7fd59977 2593{
56689b27 2594 Handle(V3d_View) aView = ViewerTest::CurrentView();
2595 if (aView.IsNull())
2596 {
23fe70ec 2597 Message::SendFail ("Error: no active viewer");
56689b27 2598 return 1;
2599 }
2600
2601 Standard_Boolean isImmediateUpdate = Standard_False;
2602 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2603 {
2604 TCollection_AsciiString anArg (theArgVec[anArgIter]);
2605 anArg.LowerCase();
8693dfd0 2606 if (anArg == "-immediate"
2607 || anArg == "-imm")
56689b27 2608 {
2609 isImmediateUpdate = Standard_True;
2610 if (anArgIter + 1 < theArgNb
dae2a922 2611 && Draw::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
56689b27 2612 {
2613 ++anArgIter;
2614 }
2615 }
8693dfd0 2616 else if (anArg == "-continuous"
2617 || anArg == "-cont"
2618 || anArg == "-fps"
2619 || anArg == "-framerate")
2620 {
2621 Standard_Real aFps = -1.0;
2622 if (anArgIter + 1 < theArgNb
d45edf24 2623 && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue (Standard_True))
8693dfd0 2624 {
2625 aFps = Draw::Atof (theArgVec[++anArgIter]);
2626 }
2627
2628 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
f227f3dc 2629 ViewerTest::CurrentEventManager()->SetContinuousRedraw (false);
2630 if (aFps >= 1.0)
8693dfd0 2631 {
f227f3dc 2632 aRedrawer.Start (aView, aFps);
2633 }
2634 else if (aFps < 0.0)
2635 {
2636 if (ViewerTest::GetViewerFromContext()->ActiveViews().Extent() == 1)
2637 {
2638 aRedrawer.Stop();
2639 ViewerTest::CurrentEventManager()->SetContinuousRedraw (true);
2640 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
2641 continue;
2642 }
2643 aRedrawer.Start (aView, aFps);
8693dfd0 2644 }
2645 else
2646 {
2647 aRedrawer.Stop();
2648 }
2649 }
56689b27 2650 else
2651 {
23fe70ec 2652 Message::SendFail() << "Syntax error at '" << anArg << "'";
8693dfd0 2653 return 1;
56689b27 2654 }
2655 }
2656
2657 if (isImmediateUpdate)
2658 {
2659 aView->RedrawImmediate();
2660 }
2661 else
2662 {
2663 aView->Redraw();
2664 }
2665 return 0;
7fd59977 2666}
2667
7fd59977 2668//==============================================================================
2669//function : VClear
2670//purpose : Remove all the object from the viewer
2671//Draw arg : No args
2672//==============================================================================
2673
2674static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2675{
2676 Handle(V3d_View) V = ViewerTest::CurrentView();
2677 if(!V.IsNull())
2678 ViewerTest::Clear();
2679 return 0;
2680}
2681
2682//==============================================================================
2683//function : VPick
2684//purpose :
2685//==============================================================================
2686
49582f9d 2687static int VPick (Draw_Interpretor& ,
2688 Standard_Integer theNbArgs,
2689 const char** theArgVec)
2690{
2691 if (ViewerTest::CurrentView().IsNull())
2692 {
2693 return 1;
2694 }
7fd59977 2695
49582f9d 2696 if (theNbArgs < 4)
2697 {
23fe70ec 2698 Message::SendFail ("Syntax error: wrong number of arguments");
49582f9d 2699 return 1;
2700 }
7fd59977 2701
49582f9d 2702 while (ViewerMainLoop (theNbArgs, theArgVec))
2703 {
2704 //
2705 }
7fd59977 2706
49582f9d 2707 return 0;
7fd59977 2708}
2709
c585f731 2710//! Parse image fill method.
2711static bool parseImageMode (const TCollection_AsciiString& theName,
2712 Aspect_FillMethod& theMode)
2713{
2714 TCollection_AsciiString aName = theName;
2715 aName.LowerCase();
2716 if (aName == "none")
2717 {
2718 theMode = Aspect_FM_NONE;
2719 }
2720 else if (aName == "centered")
2721 {
2722 theMode = Aspect_FM_CENTERED;
2723 }
2724 else if (aName == "tiled")
2725 {
2726 theMode = Aspect_FM_TILED;
2727 }
2728 else if (aName == "stretch")
2729 {
2730 theMode = Aspect_FM_STRETCH;
2731 }
2732 else
2733 {
2734 return false;
2735 }
2736 return true;
2737}
2738
2739//! Parse gradient fill method.
2740static bool parseGradientMode (const TCollection_AsciiString& theName,
2741 Aspect_GradientFillMethod& theMode)
2742{
2743 TCollection_AsciiString aName = theName;
2744 aName.LowerCase();
2745 if (aName == "none")
2746 {
9af0d66b 2747 theMode = Aspect_GradientFillMethod_None;
c585f731 2748 }
2749 else if (aName == "hor"
2750 || aName == "horizontal")
2751 {
9af0d66b 2752 theMode = Aspect_GradientFillMethod_Horizontal;
c585f731 2753 }
2754 else if (aName == "ver"
2755 || aName == "vert"
2756 || aName == "vertical")
2757 {
9af0d66b 2758 theMode = Aspect_GradientFillMethod_Vertical;
c585f731 2759 }
2760 else if (aName == "diag"
2761 || aName == "diagonal"
2762 || aName == "diag1"
2763 || aName == "diagonal1")
2764 {
9af0d66b 2765 theMode = Aspect_GradientFillMethod_Diagonal1;
c585f731 2766 }
2767 else if (aName == "diag2"
2768 || aName == "diagonal2")
2769 {
9af0d66b 2770 theMode = Aspect_GradientFillMethod_Diagonal2;
c585f731 2771 }
2772 else if (aName == "corner1")
2773 {
9af0d66b 2774 theMode = Aspect_GradientFillMethod_Corner1;
c585f731 2775 }
2776 else if (aName == "corner2")
2777 {
9af0d66b 2778 theMode = Aspect_GradientFillMethod_Corner2;
c585f731 2779 }
2780 else if (aName == "corner3")
2781 {
9af0d66b 2782 theMode = Aspect_GradientFillMethod_Corner3;
c585f731 2783 }
2784 else if (aName == "corner4")
2785 {
9af0d66b 2786 theMode = Aspect_GradientFillMethod_Corner4;
2787 }
2788 else if (aName == "ellip"
2789 || aName == "elliptical")
2790 {
2791 theMode = Aspect_GradientFillMethod_Elliptical;
c585f731 2792 }
2793 else
2794 {
2795 return false;
2796 }
2797 return true;
2798}
2799
2800//==============================================================================
2801//function : VBackground
2802//purpose :
2803//==============================================================================
2804static int VBackground (Draw_Interpretor& theDI,
2805 Standard_Integer theNbArgs,
2806 const char** theArgVec)
7fd59977 2807{
c585f731 2808 if (theNbArgs < 2)
2809 {
2810 theDI << "Syntax error: wrong number of arguments";
2811 return 1;
2812 }
2813
2814 const TCollection_AsciiString aCmdName (theArgVec[0]);
2815 bool isDefault = aCmdName == "vsetdefaultbg";
2816 Standard_Integer aNbColors = 0;
2817 Quantity_ColorRGBA aColors[2];
2818
9af0d66b 2819 Aspect_GradientFillMethod aGradientMode = Aspect_GradientFillMethod_None;
c585f731 2820 bool hasGradientMode = false;
2821
2822 TCollection_AsciiString anImagePath;
2823 Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
2824 bool hasImageMode = false;
2825
16a263dc 2826 bool isSkydomeBg = false;
2827 Aspect_SkydomeBackground aSkydomeAspect;
2828
c585f731 2829 NCollection_Sequence<TCollection_AsciiString> aCubeMapSeq;
2830 Graphic3d_CubeMapOrder aCubeOrder = Graphic3d_CubeMapOrder::Default();
3e9cb806 2831 bool isCubeZInverted = false;
c585f731 2832 bool isSRgb = true;
2833
3e9cb806 2834 int toUseIBL = 1;
2835
c585f731 2836 Handle(V3d_View) aView = ViewerTest::CurrentView();
2837 ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2838 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2839 {
2840 TCollection_AsciiString anArg (theArgVec[anArgIter]);
2841 anArg.LowerCase();
2842 if (anUpdateTool.parseRedrawMode (anArg))
2843 {
2844 continue;
2845 }
2846 else if (anArg == "-default"
2847 || anArg == "-def")
2848 {
2849 isDefault = true;
2850 }
2851 else if (anArgIter + 1 < theNbArgs
2852 && (anArg == "-imagefile"
2853 || anArg == "-imgfile"
2854 || anArg == "-image"
2855 || anArg == "-img"))
2856 {
2857 anImagePath = theArgVec[++anArgIter];
2858 }
16a263dc 2859 else if (anArg == "-skydome"
2860 || anArg == "-sky")
2861 {
2862 isSkydomeBg = true;
2863 }
2864 else if (anArgIter + 3 < theNbArgs
2865 && isSkydomeBg
2866 && anArg == "-sundir")
2867 {
2868 float aX = (float) Draw::Atof (theArgVec[++anArgIter]);
2869 float aY = (float) Draw::Atof (theArgVec[++anArgIter]);
2870 float aZ = (float) Draw::Atof (theArgVec[++anArgIter]);
2871 aSkydomeAspect.SetSunDirection (gp_Dir(aX, aY, aZ));
2872 }
2873 else if (anArgIter + 1 < theNbArgs
2874 && isSkydomeBg
2875 && anArg == "-cloud")
2876 {
2877 float aCloudy = (float) Draw::Atof (theArgVec[++anArgIter]);
2878 aSkydomeAspect.SetCloudiness (aCloudy);
2879 }
2880 else if (anArgIter + 1 < theNbArgs
2881 && isSkydomeBg
2882 && anArg == "-time")
2883 {
2884 float aTime = (float) Draw::Atof (theArgVec[++anArgIter]);
2885 aSkydomeAspect.SetTimeParameter (aTime);
2886 }
2887 else if (anArgIter + 1 < theNbArgs
2888 && isSkydomeBg
2889 && anArg == "-fog")
2890 {
2891 float aFoggy = (float) Draw::Atof (theArgVec[++anArgIter]);
2892 aSkydomeAspect.SetFogginess (aFoggy);
2893 }
2894 else if (anArgIter + 1 < theNbArgs
2895 && isSkydomeBg
2896 && anArg == "-size")
2897 {
2898 Standard_Integer aSize = Draw::Atoi (theArgVec[++anArgIter]);
2899 aSkydomeAspect.SetSize (aSize);
2900 }
c585f731 2901 else if (anArgIter + 1 < theNbArgs
2902 && aCubeMapSeq.IsEmpty()
2903 && (anArg == "-cubemap"
2904 || anArg == "-cmap"
2905 || anArg == "-cm"))
2906 {
2907 aCubeMapSeq.Append (theArgVec[++anArgIter]);
2908 for (Standard_Integer aCubeSideIter = 1; anArgIter + aCubeSideIter < theNbArgs; ++aCubeSideIter)
2909 {
2910 TCollection_AsciiString aSideArg (theArgVec[anArgIter + aCubeSideIter]);
2911 if (!aSideArg.IsEmpty()
2912 && aSideArg.Value (1) == '-')
2913 {
2914 break;
2915 }
2916
2917 aCubeMapSeq.Append (aSideArg);
2918 if (aCubeMapSeq.Size() == 6)
2919 {
2920 anArgIter += 5;
2921 break;
2922 }
2923 }
2924
2925 if (aCubeMapSeq.Size() > 1
2926 && aCubeMapSeq.Size() < 6)
2927 {
2928 aCubeMapSeq.Remove (2, aCubeMapSeq.Size());
2929 }
2930 }
2931 else if (anArgIter + 6 < theNbArgs
2932 && anArg == "-order")
2933 {
2934 for (Standard_Integer aCubeSideIter = 0; aCubeSideIter < 6; ++aCubeSideIter)
2935 {
2936 Standard_Integer aSideArg = 0;
2937 if (!Draw::ParseInteger (theArgVec[anArgIter + aCubeSideIter + 1], aSideArg)
2938 || aSideArg < 0
2939 || aSideArg > 5)
2940 {
2941 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
2942 return 1;
2943 }
2944 aCubeOrder.Set ((Graphic3d_CubeMapSide )aCubeSideIter, (unsigned char )aSideArg);
2945 }
2946 if (!aCubeOrder.IsValid())
2947 {
2948 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
2949 return 1;
2950 }
2951 anArgIter += 6;
2952 }
2953 else if (anArg == "-invertedz"
2954 || anArg == "-noinvertedz"
2955 || anArg == "-invz"
2956 || anArg == "-noinvz")
2957 {
2958 isCubeZInverted = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
2959 }
2960 else if (anArg == "-pbrenv"
3e9cb806 2961 || anArg == "-nopbrenv"
2962 || anArg == "-ibl"
2963 || anArg == "-noibl")
c585f731 2964 {
3e9cb806 2965 toUseIBL = !anArg.StartsWith ("-no") ? 1 : 0;
2966 if (anArgIter + 1 < theNbArgs)
2967 {
2968 TCollection_AsciiString anIblArg (theArgVec[anArgIter + 1]);
2969 anIblArg.LowerCase();
2970 if (anIblArg == "keep"
2971 || anIblArg == "-1")
2972 {
2973 toUseIBL = -1;
2974 ++anArgIter;
2975 }
2976 else if (anIblArg == "ibl"
2977 || anIblArg == "1"
2978 || anIblArg == "on")
2979 {
2980 toUseIBL = !anArg.StartsWith ("-no") ? 1 : 0;
2981 ++anArgIter;
2982 }
2983 else if (anIblArg == "noibl"
2984 || anIblArg == "0"
2985 || anIblArg == "off")
2986 {
2987 toUseIBL = !anArg.StartsWith ("-no") ? 0 : 1;
2988 ++anArgIter;
2989 }
2990 }
c585f731 2991 }
2992 else if (anArg == "-srgb"
2993 || anArg == "-nosrgb")
2994 {
2995 isSRgb = Draw::ParseOnOffNoIterator (theNbArgs, theArgVec, anArgIter);
2996 }
2997 else if (aNbColors < 2
2998 && (anArg == "-color"
2999 || anArg == "-col"))
3000 {
3001 Standard_Integer aNbParsed = Draw::ParseColor (theNbArgs - (anArgIter + 1),
3002 theArgVec + (anArgIter + 1),
3003 aColors[aNbColors].ChangeRGB());
3004 if (aNbParsed == 0)
3005 {
3006 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
3007 return 1;
3008 }
3009 anArgIter += aNbParsed;
3010 ++aNbColors;
3011 }
3012 else if (anArgIter + 1 < theNbArgs
3013 && (anArg == "-gradientmode"
3014 || anArg == "-gradmode"
3015 || anArg == "-gradmd"
3016 || anArg == "-grmode"
3017 || anArg == "-grmd")
3018 && parseGradientMode (theArgVec[anArgIter + 1], aGradientMode))
3019 {
3020 ++anArgIter;
3021 hasGradientMode = true;
3022 }
3023 else if (anArgIter + 1 < theNbArgs
3024 && (anArg == "-imagemode"
3025 || anArg == "-imgmode"
3026 || anArg == "-imagemd"
3027 || anArg == "-imgmd")
3028 && parseImageMode (theArgVec[anArgIter + 1], anImageMode))
3029 {
3030 ++anArgIter;
3031 hasImageMode = true;
3032 }
3033 else if (aNbColors == 0
3034 && anArgIter + 2 < theNbArgs
3035 && (anArg == "-gradient"
3036 || anArg == "-grad"
3037 || anArg == "-gr"))
3038 {
3039 Standard_Integer aNbParsed1 = Draw::ParseColor (theNbArgs - (anArgIter + 1),
3040 theArgVec + (anArgIter + 1),
3041 aColors[aNbColors].ChangeRGB());
3042 anArgIter += aNbParsed1;
3043 ++aNbColors;
3044 if (aNbParsed1 == 0)
3045 {
3046 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
3047 return 1;
3048 }
3049 Standard_Integer aNbParsed2 = Draw::ParseColor (theNbArgs - (anArgIter + 1),
3050 theArgVec + (anArgIter + 1),
3051 aColors[aNbColors].ChangeRGB());
3052 anArgIter += aNbParsed2;
3053 ++aNbColors;
3054 if (aNbParsed2 == 0)
3055 {
3056 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
3057 return 1;
3058 }
3059 }
3060 else if (parseGradientMode (theArgVec[anArgIter], aGradientMode))
3061 {
3062 hasGradientMode = true;
3063 }
3064 else if (aNbColors < 2
3065 && (Quantity_ColorRGBA::ColorFromName(theArgVec[anArgIter], aColors[aNbColors])
3066 || Quantity_ColorRGBA::ColorFromHex (theArgVec[anArgIter], aColors[aNbColors])))
3067 {
3068 ++aNbColors;
3069 }
3070 else if (anImagePath.IsEmpty()
3071 && aNbColors == 0
3072 && !hasGradientMode
3073 && aCubeMapSeq.IsEmpty())
3074 {
3075 anImagePath = theArgVec[anArgIter];
3076 }
3077 else
3078 {
3079 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
3080 return 1;
3081 }
3082 }
3083
3084 if (!isDefault
3085 && aView.IsNull())
3086 {
3087 theDI << "Error: no active viewer";
3088 return 1;
3089 }
3090 else if (isDefault
3091 && aNbColors == 0
3092 && !hasGradientMode)
3093 {
3094 theDI << "Syntax error at '-default'";
3095 return 1;
3096 }
3097
3098 if (aNbColors == 1)
3099 {
3100 if (isDefault)
3101 {
3102 ViewerTest_DefaultBackground.GradientColor1 = Quantity_Color();
3103 ViewerTest_DefaultBackground.GradientColor2 = Quantity_Color();
9af0d66b 3104 ViewerTest_DefaultBackground.FillMethod = Aspect_GradientFillMethod_None;
c585f731 3105 ViewerTest_DefaultBackground.FlatColor = aColors[0].GetRGB();
3106 ViewerTest_DefaultBackground.SetDefaultGradient();
3107 ViewerTest_DefaultBackground.SetDefaultColor();
3108 }
3109 else
3110 {
9af0d66b 3111 aView->SetBgGradientStyle (hasGradientMode ? aGradientMode : Aspect_GradientFillMethod_None);
c585f731 3112 aView->SetBackgroundColor (aColors[0].GetRGB());
3e9cb806 3113 if (toUseIBL != -1)
3114 {
3115 aView->SetBackgroundCubeMap (Handle(Graphic3d_CubeMap)(), true);
3116 }
c585f731 3117 }
3118 }
3119 else if (aNbColors == 2)
3120 {
3121 if (isDefault)
3122 {
3123 ViewerTest_DefaultBackground.GradientColor1 = aColors[0].GetRGB();
3124 ViewerTest_DefaultBackground.GradientColor2 = aColors[1].GetRGB();
3125 if (hasGradientMode)
3126 {
3127 ViewerTest_DefaultBackground.FillMethod = aGradientMode;
3128 }
9af0d66b 3129 else if (ViewerTest_DefaultBackground.FillMethod == Aspect_GradientFillMethod_None)
c585f731 3130 {
9af0d66b 3131 ViewerTest_DefaultBackground.FillMethod = Aspect_GradientFillMethod_Vertical;
c585f731 3132 }
3133 ViewerTest_DefaultBackground.SetDefaultGradient();
3134 }
3135 else
3136 {
3137 if (!hasGradientMode)
3138 {
3139 aGradientMode = aView->GradientBackground().BgGradientFillMethod();
9af0d66b 3140 if (aGradientMode == Aspect_GradientFillMethod_None)
c585f731 3141 {
9af0d66b 3142 aGradientMode = Aspect_GradientFillMethod_Vertical;
c585f731 3143 }
3144 }
3145 aView->SetBgGradientColors (aColors[0].GetRGB(), aColors[1].GetRGB(), aGradientMode);
3e9cb806 3146 if (toUseIBL != -1)
3147 {
3148 aView->SetBackgroundCubeMap (Handle(Graphic3d_CubeMap)(), true);
3149 }
c585f731 3150 }
3151 }
3152 else if (hasGradientMode)
3153 {
3154 if (isDefault)
3155 {
3156 ViewerTest_DefaultBackground.FillMethod = aGradientMode;
3157 ViewerTest_DefaultBackground.SetDefaultGradient();
3158 }
3159 else
3160 {
3161 aView->SetBgGradientStyle (aGradientMode);
3162 }
3163 }
7fd59977 3164
c585f731 3165 if (!anImagePath.IsEmpty())
7fd59977 3166 {
633084b8 3167 Handle(Graphic3d_Texture2D) aTextureMap = new Graphic3d_Texture2D (anImagePath);
c585f731 3168 aTextureMap->DisableModulate();
3169 aTextureMap->SetColorMap (isSRgb);
3170 if (!aTextureMap->IsDone())
7fd59977 3171 {
c585f731 3172 theDI << "Syntax error at '" << anImagePath << "'";
3173 return 1;
3174 }
3175 aView->SetBackgroundImage (aTextureMap, anImageMode);
3176 }
3177 else if (hasImageMode)
3178 {
3179 aView->SetBgImageStyle (anImageMode);
3180 }
3181
16a263dc 3182 if (isSkydomeBg)
3183 {
3184 aView->SetBackgroundSkydome (aSkydomeAspect, toUseIBL != -1);
3185 }
3186
c585f731 3187 if (!aCubeMapSeq.IsEmpty())
3188 {
3189 Handle(Graphic3d_CubeMap) aCubeMap;
3190 if (aCubeMapSeq.Size() == 1)
3191 {
3192 aCubeMap = new Graphic3d_CubeMapPacked (aCubeMapSeq.First(), aCubeOrder.Validated());
7fd59977 3193 }
c585f731 3194 else
f8b2ed36 3195 {
c585f731 3196 NCollection_Array1<TCollection_AsciiString> aCubeMapArr (0, 5);
3197 Standard_Integer aCubeSide = 0;
3198 for (NCollection_Sequence<TCollection_AsciiString>::Iterator aFileIter (aCubeMapSeq); aFileIter.More(); aFileIter.Next(), ++aCubeSide)
3199 {
3200 aCubeMapArr[aCubeSide] = aFileIter.Value();
3201 }
3202 aCubeMap = new Graphic3d_CubeMapSeparate (aCubeMapArr);
f8b2ed36 3203 }
c585f731 3204
3205 aCubeMap->SetZInversion (isCubeZInverted);
3206 aCubeMap->SetColorMap (isSRgb);
3207
3208 aCubeMap->GetParams()->SetFilter (Graphic3d_TOTF_BILINEAR);
3209 aCubeMap->GetParams()->SetRepeat (false);
3210 aCubeMap->GetParams()->SetTextureUnit (Graphic3d_TextureUnit_EnvMap);
3211
3e9cb806 3212 aView->SetBackgroundCubeMap (aCubeMap, toUseIBL != -1);
3213 }
3214 if (toUseIBL != -1
3215 && !aView.IsNull())
3216 {
3217 aView->SetImageBasedLighting (toUseIBL == 1);
f8b2ed36 3218 }
3219
c585f731 3220 return 0;
3221}
f42753ed 3222
7fd59977 3223//==============================================================================
3224//function : VScale
3225//purpose : View Scaling
3226//==============================================================================
3227
3228static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3229{
3230 Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3231 if ( V3dView.IsNull() ) return 1;
3232
3233 if ( argc != 4 ) {
586db386 3234 di << argv[0] << "Invalid number of arguments\n";
7fd59977 3235 return 1;
3236 }
91322f44 3237 V3dView->SetAxialScale( Draw::Atof(argv[1]), Draw::Atof(argv[2]), Draw::Atof(argv[3]) );
7fd59977 3238 return 0;
3239}
3240//==============================================================================
536d98e2 3241//function : VZBuffTrihedron
3242//purpose :
7fd59977 3243//==============================================================================
3244
536d98e2 3245static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3246 Standard_Integer theArgNb,
3247 const char** theArgVec)
7fd59977 3248{
536d98e2 3249 Handle(V3d_View) aView = ViewerTest::CurrentView();
3250 if (aView.IsNull())
3251 {
23fe70ec 3252 Message::SendFail ("Error: no active viewer");
536d98e2 3253 return 1;
3254 }
7fd59977 3255
536d98e2 3256 ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7c8a8fcc 3257
536d98e2 3258 Aspect_TypeOfTriedronPosition aPosition = Aspect_TOTP_LEFT_LOWER;
3259 V3d_TypeOfVisualization aVisType = V3d_ZBUFFER;
0aeb8984 3260 Quantity_Color aLabelsColorX = Quantity_NOC_WHITE;
3261 Quantity_Color aLabelsColorY = Quantity_NOC_WHITE;
3262 Quantity_Color aLabelsColorZ = Quantity_NOC_WHITE;
536d98e2 3263 Quantity_Color anArrowColorX = Quantity_NOC_RED;
3264 Quantity_Color anArrowColorY = Quantity_NOC_GREEN;
3265 Quantity_Color anArrowColorZ = Quantity_NOC_BLUE1;
3266 Standard_Real aScale = 0.1;
3267 Standard_Real aSizeRatio = 0.8;
3268 Standard_Real anArrowDiam = 0.05;
3269 Standard_Integer aNbFacets = 12;
3270 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
7c8a8fcc 3271 {
536d98e2 3272 Standard_CString anArg = theArgVec[anArgIter];
3273 TCollection_AsciiString aFlag (anArg);
3274 aFlag.LowerCase();
3275 if (anUpdateTool.parseRedrawMode (aFlag))
7c8a8fcc 3276 {
536d98e2 3277 continue;
3278 }
3279 else if (aFlag == "-on")
7c8a8fcc 3280 {
536d98e2 3281 continue;
3282 }
3283 else if (aFlag == "-off")
7c8a8fcc 3284 {
536d98e2 3285 aView->TriedronErase();
3286 return 0;
3287 }
3288 else if (aFlag == "-pos"
3289 || aFlag == "-position"
3290 || aFlag == "-corner")
7c8a8fcc 3291 {
536d98e2 3292 if (++anArgIter >= theArgNb)
3293 {
879768fb 3294 Message::SendFail() << "Syntax error at '" << anArg << "'";
536d98e2 3295 return 1;
3296 }
3297
879768fb 3298 if (!ViewerTest::ParseCorner (theArgVec[anArgIter], aPosition))
536d98e2 3299 {
879768fb 3300 Message::SendFail() << "Syntax error at '" << anArg << "' - unknown position '" << theArgVec[anArgIter] << "'";
536d98e2 3301 return 1;
3302 }
3303 }
3304 else if (aFlag == "-type")
7c8a8fcc 3305 {
536d98e2 3306 if (++anArgIter >= theArgNb)
3307 {
23fe70ec 3308 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
536d98e2 3309 return 1;
3310 }
3311
3312 TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3313 aTypeName.LowerCase();
3314 if (aTypeName == "wireframe"
3315 || aTypeName == "wire")
3316 {
3317 aVisType = V3d_WIREFRAME;
3318 }
3319 else if (aTypeName == "zbuffer"
3320 || aTypeName == "shaded")
3321 {
3322 aVisType = V3d_ZBUFFER;
3323 }
3324 else
3325 {
23fe70ec 3326 Message::SendFail() << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'";
536d98e2 3327 }
3328 }
3329 else if (aFlag == "-scale")
7c8a8fcc 3330 {
536d98e2 3331 if (++anArgIter >= theArgNb)
3332 {
23fe70ec 3333 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
536d98e2 3334 return 1;
3335 }
3336
3337 aScale = Draw::Atof (theArgVec[anArgIter]);
7c8a8fcc 3338 }
536d98e2 3339 else if (aFlag == "-size"
3340 || aFlag == "-sizeratio")
3341 {
3342 if (++anArgIter >= theArgNb)
3343 {
23fe70ec 3344 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
536d98e2 3345 return 1;
3346 }
7c8a8fcc 3347
536d98e2 3348 aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3349 }
3350 else if (aFlag == "-arrowdiam"
3351 || aFlag == "-arrowdiameter")
3352 {
3353 if (++anArgIter >= theArgNb)
3354 {
23fe70ec 3355 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
536d98e2 3356 return 1;
3357 }
7c8a8fcc 3358
536d98e2 3359 anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3360 }
3361 else if (aFlag == "-nbfacets")
3362 {
3363 if (++anArgIter >= theArgNb)
3364 {
23fe70ec 3365 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
536d98e2 3366 return 1;
3367 }
7c8a8fcc 3368
536d98e2 3369 aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3370 }
3371 else if (aFlag == "-colorlabel"
0aeb8984 3372 || aFlag == "-colorlabels"
3373 || aFlag == "-colorlabelx"
3374 || aFlag == "-colorlabely"
3375 || aFlag == "-colorlabelz"
3376 || aFlag == "-colorarrowx"
3377 || aFlag == "-colorarrowy"
3378 || aFlag == "-colorarrowz")
7c8a8fcc 3379 {
0aeb8984 3380 Quantity_Color aColor;
dae2a922 3381 Standard_Integer aNbParsed = Draw::ParseColor (theArgNb - anArgIter - 1,
3382 theArgVec + anArgIter + 1,
0aeb8984 3383 aColor);
536d98e2 3384 if (aNbParsed == 0)
3385 {
23fe70ec 3386 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
536d98e2 3387 return 1;
3388 }
0aeb8984 3389
3390 if (aFlag == "-colorarrowx")
536d98e2 3391 {
0aeb8984 3392 anArrowColorX = aColor;
536d98e2 3393 }
0aeb8984 3394 else if (aFlag == "-colorarrowy")
536d98e2 3395 {
0aeb8984 3396 anArrowColorY = aColor;
536d98e2 3397 }
0aeb8984 3398 else if (aFlag == "-colorarrowz")
536d98e2 3399 {
0aeb8984 3400 anArrowColorZ = aColor;
3401 }
3402 else if (aFlag == "-colorlabelx")
3403 {
3404 aLabelsColorX = aColor;
3405 }
3406 else if (aFlag == "-colorlabely")
3407 {
3408 aLabelsColorY = aColor;
3409 }
3410 else if (aFlag == "-colorlabelz")
3411 {
3412 aLabelsColorZ = aColor;
3413 }
3414 else
3415 {
3416 aLabelsColorZ = aLabelsColorY = aLabelsColorX = aColor;
536d98e2 3417 }
3418 anArgIter += aNbParsed;
3419 }
3420 else
3421 {
23fe70ec 3422 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
7c8a8fcc 3423 return 1;
3424 }
7c8a8fcc 3425 }
3426
0aeb8984 3427 const Handle(V3d_Trihedron)& aTrihedron = aView->Trihedron();
3428 aTrihedron->SetArrowsColor (anArrowColorX, anArrowColorY, anArrowColorZ);
3429 aTrihedron->SetLabelsColor (aLabelsColorX, aLabelsColorY, aLabelsColorZ);
3430 aTrihedron->SetSizeRatio (aSizeRatio);
3431 aTrihedron->SetNbFacets (aNbFacets);
3432 aTrihedron->SetArrowDiameter(anArrowDiam);
3433 aTrihedron->SetScale (aScale);
3434 aTrihedron->SetPosition (aPosition);
3435 aTrihedron->SetWireframe (aVisType == V3d_WIREFRAME);
3436 aTrihedron->Display (aView);
3437
c357e426 3438 aView->ZFitAll();
7fd59977 3439 return 0;
3440}
3441
3442//==============================================================================
3443//function : VRotate
3444//purpose : Camera Rotating
3445//==============================================================================
3446
4af098ba 3447static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3448{
3449 Handle(V3d_View) aView = ViewerTest::CurrentView();
3450 if (aView.IsNull())
3451 {
23fe70ec 3452 Message::SendFail ("Error: no active viewer");
7fd59977 3453 return 1;
3454 }
3455
4af098ba 3456 Standard_Boolean hasFlags = Standard_False;
3457 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3458 {
3459 Standard_CString anArg (theArgVec[anArgIter]);
3460 TCollection_AsciiString aFlag (anArg);
3461 aFlag.LowerCase();
3462 if (aFlag == "-mousestart"
3463 || aFlag == "-mousefrom")
3464 {
3465 hasFlags = Standard_True;
3466 if (anArgIter + 2 >= theArgNb)
3467 {
23fe70ec 3468 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
4af098ba 3469 return 1;
3470 }
3471
3472 Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3473 Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3474 aView->StartRotation (anX, anY);
3475 }
3476 else if (aFlag == "-mousemove")
3477 {
3478 hasFlags = Standard_True;
3479 if (anArgIter + 2 >= theArgNb)
3480 {
23fe70ec 3481 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
4af098ba 3482 return 1;
3483 }
3484
3485 Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3486 Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3487 aView->Rotation (anX, anY);
3488 }
3489 else if (theArgNb != 4
3490 && theArgNb != 7)
3491 {
23fe70ec 3492 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
4af098ba 3493 return 1;
3494 }
3495 }
3496
3497 if (hasFlags)
3498 {
7fd59977 3499 return 0;
4af098ba 3500 }
3501 else if (theArgNb == 4)
3502 {
3503 Standard_Real anAX = Draw::Atof (theArgVec[1]);
3504 Standard_Real anAY = Draw::Atof (theArgVec[2]);
3505 Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3506 aView->Rotate (anAX, anAY, anAZ);
3507 return 0;
3508 }
3509 else if (theArgNb == 7)
3510 {
3511 Standard_Real anAX = Draw::Atof (theArgVec[1]);
3512 Standard_Real anAY = Draw::Atof (theArgVec[2]);
3513 Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3514
3515 Standard_Real anX = Draw::Atof (theArgVec[4]);
3516 Standard_Real anY = Draw::Atof (theArgVec[5]);
3517 Standard_Real anZ = Draw::Atof (theArgVec[6]);
3518
3519 aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
7fd59977 3520 return 0;
7fd59977 3521 }
4af098ba 3522
23fe70ec 3523 Message::SendFail ("Error: Invalid number of arguments");
4af098ba 3524 return 1;
7fd59977 3525}
3526
3527//==============================================================================
3528//function : VZoom
3529//purpose : View zoom in / out (relative to current zoom)
3530//==============================================================================
3531
3532static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3533 Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3534 if ( V3dView.IsNull() ) {
3535 return 1;
3536 }
3537
3538 if ( argc == 2 ) {
91322f44 3539 Standard_Real coef = Draw::Atof(argv[1]);
7fd59977 3540 if ( coef <= 0.0 ) {
586db386 3541 di << argv[1] << "Invalid value\n";
7fd59977 3542 return 1;
3543 }
91322f44 3544 V3dView->SetZoom( Draw::Atof(argv[1]) );
7fd59977 3545 return 0;
3546 } else {
586db386 3547 di << argv[0] << " Invalid number of arguments\n";
7fd59977 3548 return 1;
3549 }
3550}
3551
3552//==============================================================================
3553//function : VPan
3554//purpose : View panning (in pixels)
3555//==============================================================================
3556
3557static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3558 Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3559 if ( V3dView.IsNull() ) return 1;
3560
3561 if ( argc == 3 ) {
91322f44 3562 V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
7fd59977 3563 return 0;
3564 } else {
586db386 3565 di << argv[0] << " Invalid number of arguments\n";
7fd59977 3566 return 1;
3567 }
3568}
3569
49e1a5c7 3570//==============================================================================
3571//function : VPlace
3572//purpose : Place the point (in pixels) at the center of the window
3573//==============================================================================
3574static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3575{
3576 Handle(V3d_View) aView = ViewerTest::CurrentView();
3577 if (aView.IsNull())
3578 {
23fe70ec 3579 Message::SendFail ("Error: no active viewer");
49e1a5c7 3580 return 1;
3581 }
3582
3583 if (theArgNb != 3)
3584 {
23fe70ec 3585 Message::SendFail ("Syntax error: wrong number of arguments");
49e1a5c7 3586 return 1;
3587 }
3588
3589 aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3590
3591 return 0;
3592}
7fd59977 3593
71215351 3594static int VColorScale (Draw_Interpretor& theDI,
3595 Standard_Integer theArgNb,
3596 const char** theArgVec)
3597{
7fd59977 3598 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
71215351 3599 Handle(V3d_View) aView = ViewerTest::CurrentView();
3600 if (aContext.IsNull())
3601 {
23fe70ec 3602 Message::SendFail ("Error: no active viewer");
71215351 3603 return 1;
7fd59977 3604 }
24a88697 3605 if (theArgNb <= 1)
3606 {
23fe70ec 3607 Message::SendFail() << "Error: wrong syntax at command '" << theArgVec[0] << "'";
24a88697 3608 return 1;
3609 }
7fd59977 3610
4b3d6eb1 3611 Handle(AIS_ColorScale) aColorScale;
7a324550 3612 if (GetMapOfAIS().IsBound2 (theArgVec[1]))
71215351 3613 {
4b3d6eb1 3614 // find existing object
3615 aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
3616 if (aColorScale.IsNull())
7a324550 3617 {
23fe70ec 3618 Message::SendFail() << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale";
7a324550 3619 return 1;
3620 }
3621 }
71215351 3622
7a324550 3623 if (theArgNb <= 2)
3624 {
4b3d6eb1 3625 if (aColorScale.IsNull())
3626 {
23fe70ec 3627 Message::SendFail() << "Syntax error: colorscale with a given name does not exist";
4b3d6eb1 3628 return 1;
3629 }
3630
7a324550 3631 theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
4b3d6eb1 3632 << "Min range: " << aColorScale->GetMin() << "\n"
3633 << "Max range: " << aColorScale->GetMax() << "\n"
3634 << "Number of intervals: " << aColorScale->GetNumberOfIntervals() << "\n"
3635 << "Text height: " << aColorScale->GetTextHeight() << "\n"
3636 << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
3637 << "Color scale title: " << aColorScale->GetTitle() << "\n"
71215351 3638 << "Label position: ";
4b3d6eb1 3639 switch (aColorScale->GetLabelPosition())
71215351 3640 {
3641 case Aspect_TOCSP_NONE:
3642 theDI << "None\n";
3643 break;
3644 case Aspect_TOCSP_LEFT:
3645 theDI << "Left\n";
3646 break;
3647 case Aspect_TOCSP_RIGHT:
3648 theDI << "Right\n";
3649 break;
3650 case Aspect_TOCSP_CENTER:
3651 theDI << "Center\n";
3652 break;
3653 }
3654 return 0;
3655 }
71215351 3656
4b3d6eb1 3657 if (aColorScale.IsNull())
3658 {
3659 aColorScale = new AIS_ColorScale();
3660 aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
3661 aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
3662 }
3663
3664 ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
7a324550 3665 for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
71215351 3666 {
3667 Standard_CString anArg = theArgVec[anArgIter];
3668 TCollection_AsciiString aFlag (anArg);
3669 aFlag.LowerCase();
3670 if (anUpdateTool.parseRedrawMode (aFlag))
3671 {
3672 continue;
3673 }
3674 else if (aFlag == "-range")
3675 {
3676 if (anArgIter + 3 >= theArgNb)
3677 {
23fe70ec 3678 Message::SendFail() << "Error: wrong syntax at argument '" << anArg << "'";
71215351 3679 return 1;
3680 }
3681
4b3d6eb1 3682 const TCollection_AsciiString aRangeMin (theArgVec[++anArgIter]);
3683 const TCollection_AsciiString aRangeMax (theArgVec[++anArgIter]);
3684 const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
d45edf24 3685 if (!aRangeMin.IsRealValue (Standard_True)
3686 || !aRangeMax.IsRealValue (Standard_True))
71215351 3687 {
23fe70ec 3688 Message::SendFail ("Syntax error: the range values should be real");
71215351 3689 return 1;
3690 }
4b3d6eb1 3691 else if (!aNbIntervals.IsIntegerValue())
71215351 3692 {
23fe70ec 3693 Message::SendFail ("Syntax error: the number of intervals should be integer");
71215351 3694 return 1;
3695 }
3696
4b3d6eb1 3697 aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
3698 aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
71215351 3699 }
3700 else if (aFlag == "-font")
3701 {
3702 if (anArgIter + 1 >= theArgNb)
3703 {
23fe70ec 3704 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
71215351 3705 return 1;
3706 }
51740958 3707 TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
3708 if (!aFontArg.IsIntegerValue())
71215351 3709 {
23fe70ec 3710 Message::SendFail ("Syntax error: HeightFont value should be integer");
71215351 3711 return 1;
3712 }
3713
4b3d6eb1 3714 aColorScale->SetTextHeight (aFontArg.IntegerValue());
71215351 3715 anArgIter += 1;
3716 }
3717 else if (aFlag == "-textpos")
3718 {
3719 if (anArgIter + 1 >= theArgNb)
3720 {
23fe70ec 3721 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
71215351 3722 return 1;
3723 }
4b3d6eb1 3724
51740958 3725 TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
3726 aTextPosArg.LowerCase();
4b3d6eb1 3727 Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
51740958 3728 if (aTextPosArg == "none")
71215351 3729 {
3730 aLabPosition = Aspect_TOCSP_NONE;
3731 }
51740958 3732 else if (aTextPosArg == "left")
71215351 3733 {
3734 aLabPosition = Aspect_TOCSP_LEFT;
3735 }
51740958 3736 else if (aTextPosArg == "right")
71215351 3737 {
3738 aLabPosition = Aspect_TOCSP_RIGHT;
3739 }
51740958 3740 else if (aTextPosArg == "center")
71215351 3741 {
3742 aLabPosition = Aspect_TOCSP_CENTER;
3743 }
3744 else
3745 {
23fe70ec 3746 Message::SendFail() << "Syntax error: unknown position '" << aTextPosArg << "'";
71215351 3747 return 1;
3748 }
4b3d6eb1 3749 aColorScale->SetLabelPosition (aLabPosition);
71215351 3750 }
24a88697 3751 else if (aFlag == "-logarithmic"
3752 || aFlag == "-log")
3753 {
3754 if (anArgIter + 1 >= theArgNb)
3755 {
23fe70ec 3756 Message::SendFail() << "Synta error at argument '" << anArg << "'";
24a88697 3757 return 1;
3758 }
4b3d6eb1 3759
24a88697 3760 Standard_Boolean IsLog;
dae2a922 3761 if (!Draw::ParseOnOff(theArgVec[++anArgIter], IsLog))
24a88697 3762 {
23fe70ec 3763 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
24a88697 3764 return 1;
3765 }
4b3d6eb1 3766 aColorScale->SetLogarithmic (IsLog);
3767 }
3768 else if (aFlag == "-huerange"
3769 || aFlag == "-hue")
3770 {
3771 if (anArgIter + 2 >= theArgNb)
3772 {
23fe70ec 3773 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
4b3d6eb1 3774 return 1;
3775 }
3776
3777 const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
3778 const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
3779 aColorScale->SetHueRange (aHueMin, aHueMax);
3780 }
3781 else if (aFlag == "-colorrange")
3782 {
3783 Quantity_Color aColorMin, aColorMax;
dae2a922 3784 Standard_Integer aNbParsed1 = Draw::ParseColor (theArgNb - (anArgIter + 1),
3785 theArgVec + (anArgIter + 1),
3786 aColorMin);
4b3d6eb1 3787 anArgIter += aNbParsed1;
dae2a922 3788 Standard_Integer aNbParsed2 = Draw::ParseColor (theArgNb - (anArgIter + 1),
3789 theArgVec + (anArgIter + 1),
3790 aColorMax);
4b3d6eb1 3791 anArgIter += aNbParsed2;
3792 if (aNbParsed1 == 0
3793 || aNbParsed2 == 0)
3794 {
23fe70ec 3795 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
4b3d6eb1 3796 return 1;
3797 }
3798
3799 aColorScale->SetColorRange (aColorMin, aColorMax);
3800 }
3801 else if (aFlag == "-reversed"
3802 || aFlag == "-inverted"
3803 || aFlag == "-topdown"
3804 || aFlag == "-bottomup")
3805 {
3806 Standard_Boolean toEnable = Standard_True;
3807 if (anArgIter + 1 < theArgNb
dae2a922 3808 && Draw::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
4b3d6eb1 3809 {
3810 ++anArgIter;
3811 }
3812 aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
3813 }
3814 else if (aFlag == "-smooth"
3815 || aFlag == "-smoothtransition")
3816 {
3817 Standard_Boolean toEnable = Standard_True;
3818 if (anArgIter + 1 < theArgNb
dae2a922 3819 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4b3d6eb1 3820 {
3821 ++anArgIter;
3822 }
3823 aColorScale->SetSmoothTransition (toEnable);
24a88697 3824 }
71215351 3825 else if (aFlag == "-xy")
3826 {
3827 if (anArgIter + 2 >= theArgNb)
3828 {
23fe70ec 3829 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
71215351 3830 return 1;
3831 }
3832
4b3d6eb1 3833 const TCollection_AsciiString anX (theArgVec[++anArgIter]);
3834 const TCollection_AsciiString anY (theArgVec[++anArgIter]);
3835 if (!anX.IsIntegerValue()
3836 || !anY.IsIntegerValue())
71215351 3837 {
23fe70ec 3838 Message::SendFail ("Syntax error: coordinates should be integer values");
71215351 3839 return 1;
3840 }
3841
4b3d6eb1 3842 aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
b4b2ecca 3843 }
3844 else if (aFlag == "-width"
4b3d6eb1 3845 || aFlag == "-w"
3846 || aFlag == "-breadth")
b4b2ecca 3847 {
3848 if (anArgIter + 1 >= theArgNb)
3849 {
23fe70ec 3850 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
b4b2ecca 3851 return 1;
3852 }
3853
4b3d6eb1 3854 const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
3855 if (!aBreadth.IsIntegerValue())
b4b2ecca 3856 {
23fe70ec 3857 Message::SendFail ("Syntax error: a width should be an integer value");
b4b2ecca 3858 return 1;
3859 }
4b3d6eb1 3860 aColorScale->SetBreadth (aBreadth.IntegerValue());
b4b2ecca 3861 }
3862 else if (aFlag == "-height"
3863 || aFlag == "-h")
3864 {
3865 if (anArgIter + 1 >= theArgNb)
3866 {
23fe70ec 3867 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
b4b2ecca 3868 return 1;
3869 }
3870
4b3d6eb1 3871 const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
3872 if (!aHeight.IsIntegerValue())
b4b2ecca 3873 {
23fe70ec 3874 Message::SendFail ("Syntax error: a width should be an integer value");
b4b2ecca 3875 return 1;
3876 }
4b3d6eb1 3877 aColorScale->SetHeight (aHeight.IntegerValue());
71215351 3878 }
3879 else if (aFlag == "-color")
3880 {
4b3d6eb1 3881 if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
71215351 3882 {
23fe70ec 3883 Message::SendFail ("Syntax error: wrong color type. Call -colors before to set user-specified colors");
71215351 3884 return 1;
3885 }
4b3d6eb1 3886 else if (anArgIter + 2 >= theArgNb)
71215351 3887 {
23fe70ec 3888 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
4b3d6eb1 3889 return 1;
71215351 3890 }
3891
4b3d6eb1 3892 const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
71215351 3893 if (!anInd.IsIntegerValue())
3894 {
23fe70ec 3895 Message::SendFail ("Syntax error: Index value should be integer");
71215351 3896 return 1;
3897 }
4b3d6eb1 3898 const Standard_Integer anIndex = anInd.IntegerValue();
3899 if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
71215351 3900 {
23fe70ec 3901 Message::SendFail() << "Syntax error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals();
71215351 3902 return 1;
3903 }
3904
4b3d6eb1 3905 Quantity_Color aColor;
dae2a922 3906 Standard_Integer aNbParsed = Draw::ParseColor (theArgNb - (anArgIter + 1),
3907 theArgVec + (anArgIter + 1),
3908 aColor);
4b3d6eb1 3909 if (aNbParsed == 0)
71215351 3910 {
23fe70ec 3911 Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
71215351 3912 return 1;
3913 }
4b3d6eb1 3914 aColorScale->SetIntervalColor (aColor, anIndex);
3915 aColorScale->SetColorType (Aspect_TOCSD_USER);
3916 anArgIter += aNbParsed;
71215351 3917 }
3918 else if (aFlag == "-label")
3919 {
4b3d6eb1 3920 if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
71215351 3921 {
23fe70ec 3922 Message::SendFail ("Syntax error: wrong label type. Call -labels before to set user-specified labels");
71215351 3923 return 1;
3924 }
3925 else if (anArgIter + 2 >= theArgNb)
3926 {
23fe70ec 3927 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
71215351 3928 return 1;
3929 }
3930
3931 Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4b3d6eb1 3932 if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
71215351 3933 {
23fe70ec 3934 Message::SendFail() << "Syntax error: Index value should be within range 1.." << (aColorScale->GetNumberOfIntervals() + 1);
71215351 3935 return 1;
3936 }
3937
94f16a89 3938 TCollection_ExtendedString aText (theArgVec[anArgIter + 2], Standard_True);
4b3d6eb1 3939 aColorScale->SetLabel (aText, anIndex);
3940 aColorScale->SetLabelType (Aspect_TOCSD_USER);
71215351 3941 anArgIter += 2;
3942 }
4b3d6eb1 3943 else if (aFlag == "-labelat"
3944 || aFlag == "-labat"
3945 || aFlag == "-labelatborder"
3946 || aFlag == "-labatborder"
3947 || aFlag == "-labelatcenter"
3948 || aFlag == "-labatcenter")
71215351 3949 {
4b3d6eb1 3950 Standard_Boolean toEnable = Standard_True;
3951 if (aFlag == "-labelat"
3952 || aFlag == "-labat")
71215351 3953 {
4b3d6eb1 3954 Standard_Integer aLabAtBorder = -1;
3955 if (++anArgIter >= theArgNb)
71215351 3956 {
4b3d6eb1 3957 TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
3958 anAtBorder.LowerCase();
3959 if (anAtBorder == "border")
71215351 3960 {
4b3d6eb1 3961 aLabAtBorder = 1;
71215351 3962 }
4b3d6eb1 3963 else if (anAtBorder == "center")
71215351 3964 {
4b3d6eb1 3965 aLabAtBorder = 0;
71215351 3966 }
71215351 3967 }
4b3d6eb1 3968 if (aLabAtBorder == -1)
3969 {
23fe70ec 3970 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
4b3d6eb1 3971 return 1;
3972 }
3973 toEnable = (aLabAtBorder == 1);
3974 }
3975 else if (anArgIter + 1 < theArgNb
dae2a922 3976 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4b3d6eb1 3977 {
3978 ++anArgIter;
71215351 3979 }
4b3d6eb1 3980 aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
3981 || aFlag == "-labatcenter"
3982 ? !toEnable
3983 : toEnable);
3984 }
3985 else if (aFlag == "-colors")
3986 {
3987 Aspect_SequenceOfColor aSeq;
3988 for (;;)
3989 {
3990 Quantity_Color aColor;
dae2a922 3991 Standard_Integer aNbParsed = Draw::ParseColor (theArgNb - (anArgIter + 1),
3992 theArgVec + (anArgIter + 1),
3993 aColor);
4b3d6eb1 3994 if (aNbParsed == 0)
3995 {
3996 break;
3997 }
3998 anArgIter += aNbParsed;
3999 aSeq.Append (aColor);
4000 }
4001 if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
71215351 4002 {
23fe70ec 4003 Message::SendFail() << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4004 << aColorScale->GetNumberOfIntervals() << " intervals";
71215351 4005 return 1;
4006 }
4007
4b3d6eb1 4008 aColorScale->SetColors (aSeq);
4009 aColorScale->SetColorType (Aspect_TOCSD_USER);
71215351 4010 }
14b741b0 4011 else if (aFlag == "-uniform")
4012 {
4013 const Standard_Real aLightness = Draw::Atof (theArgVec[++anArgIter]);
4014 const Standard_Real aHueStart = Draw::Atof (theArgVec[++anArgIter]);
4015 const Standard_Real aHueEnd = Draw::Atof (theArgVec[++anArgIter]);
4016 aColorScale->SetUniformColors (aLightness, aHueStart, aHueEnd);
4017 aColorScale->SetColorType (Aspect_TOCSD_USER);
4018 }
4b3d6eb1 4019 else if (aFlag == "-labels"
4020 || aFlag == "-freelabels")
71215351 4021 {
4b3d6eb1 4022 if (anArgIter + 1 >= theArgNb)
4023 {
23fe70ec 4024 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
4b3d6eb1 4025 return 1;
4026 }
4027
4028 Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4029 ? aColorScale->GetNumberOfIntervals() + 1
4030 : aColorScale->GetNumberOfIntervals();
4031 if (aFlag == "-freelabels")
4032 {
4033 ++anArgIter;
4034 aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4035 }
4036 if (anArgIter + aNbLabels >= theArgNb)
71215351 4037 {
23fe70ec 4038 Message::SendFail() << "Syntax error: not enough arguments. " << aNbLabels << " text labels are expected";
71215351 4039 return 1;
4040 }
4041
4042 TColStd_SequenceOfExtendedString aSeq;
4b3d6eb1 4043 for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
71215351 4044 {
94f16a89 4045 aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter], Standard_True));
71215351 4046 }
4b3d6eb1 4047 aColorScale->SetLabels (aSeq);
4048 aColorScale->SetLabelType (Aspect_TOCSD_USER);
71215351 4049 }
4050 else if (aFlag == "-title")
4051 {
4052 if (anArgIter + 1 >= theArgNb)
4053 {
23fe70ec 4054 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
71215351 4055 return 1;
4056 }
4057
4058 Standard_Boolean isTwoArgs = Standard_False;
4059 if (anArgIter + 2 < theArgNb)
4060 {
4061 TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4062 aSecondArg.LowerCase();
4b3d6eb1 4063 Standard_DISABLE_DEPRECATION_WARNINGS
71215351 4064 if (aSecondArg == "none")
4065 {
4b3d6eb1 4066 aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
71215351 4067 isTwoArgs = Standard_True;
4068 }
4069 else if (aSecondArg == "left")
4070 {
4b3d6eb1 4071 aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
71215351 4072 isTwoArgs = Standard_True;
4073 }
4074 else if (aSecondArg == "right")
4075 {
4b3d6eb1 4076 aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
71215351 4077 isTwoArgs = Standard_True;
4078 }
4079 else if (aSecondArg == "center")
4080 {
4b3d6eb1 4081 aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
71215351 4082 isTwoArgs = Standard_True;
4083 }
4b3d6eb1 4084 Standard_ENABLE_DEPRECATION_WARNINGS
71215351 4085 }
4086
94f16a89 4087 TCollection_ExtendedString aTitle(theArgVec[anArgIter + 1], Standard_True);
4088 aColorScale->SetTitle (aTitle);
71215351 4089 if (isTwoArgs)
4090 {
4091 anArgIter += 1;
4092 }
4093 anArgIter += 1;
4094 }
4095 else if (aFlag == "-demoversion"
4096 || aFlag == "-demo")
4097 {
4b3d6eb1 4098 aColorScale->SetPosition (0, 0);
4099 aColorScale->SetTextHeight (16);
4100 aColorScale->SetRange (0.0, 100.0);
4101 aColorScale->SetNumberOfIntervals (10);
4102 aColorScale->SetBreadth (0);
4103 aColorScale->SetHeight (0);
4104 aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4105 aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4106 aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
71215351 4107 }
d5514578 4108 else if (aFlag == "-findcolor")
4109 {
4110 if (anArgIter + 1 >= theArgNb)
4111 {
23fe70ec 4112 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
d5514578 4113 return 1;
4114 }
4115
4116 TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4117
d45edf24 4118 if (!anArg1.IsRealValue (Standard_True))
d5514578 4119 {
23fe70ec 4120 Message::SendFail ("Syntax error: the value should be real");
d5514578 4121 return 1;
4122 }
4123
4124 Quantity_Color aColor;
4b3d6eb1 4125 aColorScale->FindColor (anArg1.RealValue(), aColor);
d5514578 4126 theDI << Quantity_Color::StringName (aColor.Name());
4127 return 0;
4128 }
71215351 4129 else
4130 {
23fe70ec 4131 Message::SendFail() << "Syntax error at " << anArg << " - unknown argument";
71215351 4132 return 1;
4133 }
4134 }
4b3d6eb1 4135
4136 Standard_Integer aWinWidth = 0, aWinHeight = 0;
4137 aView->Window()->Size (aWinWidth, aWinHeight);
4138 if (aColorScale->GetBreadth() == 0)
b4b2ecca 4139 {
4b3d6eb1 4140 aColorScale->SetBreadth (aWinWidth);
b4b2ecca 4141 }
4b3d6eb1 4142 if (aColorScale->GetHeight() == 0)
4143 {
4144 aColorScale->SetHeight (aWinHeight);
4145 }
4146 aColorScale->SetToUpdate();
4147 ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
7fd59977 4148 return 0;
4149}
4150
4151//==============================================================================
4152//function : VGraduatedTrihedron
a79f67f8 4153//purpose : Displays or hides a graduated trihedron
7fd59977 4154//==============================================================================
a79f67f8 4155static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4156 Quantity_Color& theColor)
13a22457 4157{
a79f67f8 4158 Quantity_NameOfColor aColorName;
4159 TCollection_AsciiString aVal = theValue;
4160 aVal.UpperCase();
4161 if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
13a22457 4162 {
a79f67f8 4163 return Standard_False;
13a22457 4164 }
a79f67f8 4165 theColor = Quantity_Color (aColorName);
4166 return Standard_True;
13a22457
S
4167}
4168
a79f67f8 4169static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
7fd59977 4170{
a79f67f8 4171 if (theArgNum < 2)
13a22457 4172 {
23fe70ec 4173 Message::SendFail() << "Syntax error: wrong number of parameters. Type 'help"
4174 << theArgs[0] <<"' for more information";
4175 return 1;
13a22457 4176 }
7fd59977 4177
a79f67f8 4178 NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4179 TCollection_AsciiString aParseKey;
4180 for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4181 {
4182 TCollection_AsciiString anArg (theArgs [anArgIt]);
4183
d45edf24 4184 if (anArg.Value (1) == '-' && !anArg.IsRealValue (Standard_True))
a79f67f8 4185 {
4186 aParseKey = anArg;
4187 aParseKey.Remove (1);
4188 aParseKey.LowerCase();
4189 aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4190 continue;
4191 }
13a22457 4192
a79f67f8 4193 if (aParseKey.IsEmpty())
4194 {
4195 continue;
4196 }
4197
4198 aMapOfArgs(aParseKey)->Append (anArg);
4199 }
4200
4201 // Check parameters
4202 for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4203 aMapIt.More(); aMapIt.Next())
7fd59977 4204 {
a79f67f8 4205 const TCollection_AsciiString& aKey = aMapIt.Key();
4206 const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4207
4208 // Bool key, without arguments
4209 if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4210 && anArgs->IsEmpty())
4211 {
4212 continue;
4213 }
4214
4215 // One argument
4216 if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4217 && anArgs->Length() == 1)
4218 {
4219 continue;
4220 }
4221
4222 // On/off arguments
4223 if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4224 || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
536d98e2 4225 || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4226 || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
a79f67f8 4227 && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4228 {
4229 continue;
4230 }
4231
4232 // One string argument
4233 if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4234 || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
d45edf24 4235 && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue (Standard_True))
a79f67f8 4236 {
4237 continue;
4238 }
4239
4240 // One integer argument
4241 if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4242 || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4243 || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4244 || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4245 && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4246 {
4247 continue;
4248 }
4249
4250 // One real argument
4251 if ( aKey.IsEqual ("arrowlength")
d45edf24 4252 && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue (Standard_True)))
a79f67f8 4253 {
4254 continue;
4255 }
4256
4257 // Two string arguments
4258 if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
d45edf24 4259 && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue (Standard_True))
13a22457 4260 {
a79f67f8 4261 continue;
13a22457 4262 }
a79f67f8 4263
4264 TCollection_AsciiString aLowerKey;
4265 aLowerKey = "-";
4266 aLowerKey += aKey;
4267 aLowerKey.LowerCase();
23fe70ec 4268 Message::SendFail() << "Syntax error: " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n"
4269 << "Type help for more information";
a79f67f8 4270 return 1;
7fd59977 4271 }
4272
a79f67f8 4273 Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4274 if (anAISContext.IsNull())
4275 {
23fe70ec 4276 Message::SendFail ("Error: no active viewer");
a79f67f8 4277 return 1;
4278 }
7fd59977 4279
a79f67f8 4280 Standard_Boolean toDisplay = Standard_True;
4281 Quantity_Color aColor;
4282 Graphic3d_GraduatedTrihedron aTrihedronData;
4283 // Process parameters
4284 Handle(TColStd_HSequenceOfAsciiString) aValues;
4285 if (aMapOfArgs.Find ("off", aValues))
7fd59977 4286 {
a79f67f8 4287 toDisplay = Standard_False;
4288 }
13a22457 4289
a79f67f8 4290 // AXES NAMES
4291 if (aMapOfArgs.Find ("xname", aValues))
4292 {
4293 aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4294 }
4295 if (aMapOfArgs.Find ("yname", aValues))
4296 {
4297 aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4298 }
4299 if (aMapOfArgs.Find ("zname", aValues))
4300 {
4301 aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4302 }
4303 if (aMapOfArgs.Find ("xdrawname", aValues))
4304 {
536d98e2 4305 aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
a79f67f8 4306 }
4307 if (aMapOfArgs.Find ("ydrawname", aValues))
4308 {
536d98e2 4309 aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
a79f67f8 4310 }
4311 if (aMapOfArgs.Find ("zdrawname", aValues))
4312 {
536d98e2 4313 aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
a79f67f8 4314 }
4315 if (aMapOfArgs.Find ("xnameoffset", aValues))
4316 {
4317 aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4318 }
4319 if (aMapOfArgs.Find ("ynameoffset", aValues))
4320 {
4321 aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4322 }
4323 if (aMapOfArgs.Find ("znameoffset", aValues))
4324 {
4325 aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4326 }
13a22457 4327
a79f67f8 4328 // COLORS
4329 if (aMapOfArgs.Find ("xnamecolor", aValues))
4330 {
4331 if (!GetColor (aValues->Value(1), aColor))
13a22457 4332 {
23fe70ec 4333 Message::SendFail ("Syntax error: -xnamecolor wrong color name");
a79f67f8 4334 return 1;
13a22457 4335 }
a79f67f8 4336 aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4337 }
4338 if (aMapOfArgs.Find ("ynamecolor", aValues))
4339 {
4340 if (!GetColor (aValues->Value(1), aColor))
13a22457 4341 {
23fe70ec 4342 Message::SendFail ("Syntax error: -ynamecolor wrong color name");
a79f67f8 4343 return 1;
4344 }
4345 aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4346 }
4347 if (aMapOfArgs.Find ("znamecolor", aValues))
4348 {
4349 if (!GetColor (aValues->Value(1), aColor))
4350 {
23fe70ec 4351 Message::SendFail ("Syntax error: -znamecolor wrong color name");
a79f67f8 4352 return 1;
4353 }
4354 aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4355 }
4356 if (aMapOfArgs.Find ("xcolor", aValues))
4357 {
4358 if (!GetColor (aValues->Value(1), aColor))
4359 {
23fe70ec 4360 Message::SendFail ("Syntax error: -xcolor wrong color name");
a79f67f8 4361 return 1;
4362 }
4363 aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
4364 }
4365 if (aMapOfArgs.Find ("ycolor", aValues))
4366 {
4367 if (!GetColor (aValues->Value(1), aColor))
4368 {
23fe70ec 4369 Message::SendFail ("Syntax error: -ycolor wrong color name");
a79f67f8 4370 return 1;
4371 }
4372 aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
4373 }
4374 if (aMapOfArgs.Find ("zcolor", aValues))
4375 {
4376 if (!GetColor (aValues->Value(1), aColor))
4377 {
23fe70ec 4378 Message::SendFail ("Syntax error: -zcolor wrong color name");
a79f67f8 4379 return 1;
4380 }
4381 aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
4382 }
4383
4384 // TICKMARKS
4385 if (aMapOfArgs.Find ("xticks", aValues))
4386 {
536d98e2 4387 aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
a79f67f8 4388 }
4389 if (aMapOfArgs.Find ("yticks", aValues))
4390 {
536d98e2 4391 aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
a79f67f8 4392 }
4393 if (aMapOfArgs.Find ("zticks", aValues))
4394 {
536d98e2 4395 aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
a79f67f8 4396 }
4397 if (aMapOfArgs.Find ("xticklength", aValues))
4398 {
536d98e2 4399 aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
a79f67f8 4400 }
4401 if (aMapOfArgs.Find ("yticklength", aValues))
4402 {
536d98e2 4403 aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
a79f67f8 4404 }
4405 if (aMapOfArgs.Find ("zticklength", aValues))
4406 {
536d98e2 4407 aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
a79f67f8 4408 }
4409 if (aMapOfArgs.Find ("xdrawticks", aValues))
4410 {
536d98e2 4411 aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
a79f67f8 4412 }
4413 if (aMapOfArgs.Find ("ydrawticks", aValues))
4414 {
536d98e2 4415 aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
a79f67f8 4416 }
4417 if (aMapOfArgs.Find ("zdrawticks", aValues))
4418 {
536d98e2 4419 aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
a79f67f8 4420 }
4421
4422 // VALUES
4423 if (aMapOfArgs.Find ("xdrawvalues", aValues))
4424 {
536d98e2 4425 aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
a79f67f8 4426 }
4427 if (aMapOfArgs.Find ("ydrawvalues", aValues))
4428 {
536d98e2 4429 aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
a79f67f8 4430 }
4431 if (aMapOfArgs.Find ("zdrawvalues", aValues))
4432 {
536d98e2 4433 aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
a79f67f8 4434 }
4435 if (aMapOfArgs.Find ("xvaluesoffset", aValues))
4436 {
4437 aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4438 }
4439 if (aMapOfArgs.Find ("yvaluesoffset", aValues))
4440 {
4441 aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4442 }
4443 if (aMapOfArgs.Find ("zvaluesoffset", aValues))
4444 {
4445 aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
4446 }
4447
4448 // ARROWS
4449 if (aMapOfArgs.Find ("arrowlength", aValues))
4450 {
536d98e2 4451 aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
a79f67f8 4452 }
4453
4454 // FONTS
4455 if (aMapOfArgs.Find ("namefont", aValues))
4456 {
4457 aTrihedronData.SetNamesFont (aValues->Value(1));
4458 }
4459 if (aMapOfArgs.Find ("valuesfont", aValues))
4460 {
4461 aTrihedronData.SetValuesFont (aValues->Value(1));
4462 }
4463
536d98e2 4464 if (aMapOfArgs.Find ("drawgrid", aValues))
4465 {
4466 aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
4467 }
4468 if (aMapOfArgs.Find ("drawaxes", aValues))
4469 {
4470 aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
4471 }
4472
a79f67f8 4473 // The final step: display of erase trihedron
4474 if (toDisplay)
4475 {
4476 ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
13a22457 4477 }
7fd59977 4478 else
a79f67f8 4479 {
4480 ViewerTest::CurrentView()->GraduatedTrihedronErase();
4481 }
7fd59977 4482
4483 ViewerTest::GetAISContext()->UpdateCurrentViewer();
a79f67f8 4484 ViewerTest::CurrentView()->Redraw();
13a22457 4485
7fd59977 4486 return 0;
4487}
4488
3bffef55 4489//==============================================================================
4490//function : VTile
4491//purpose :
4492//==============================================================================
4493static int VTile (Draw_Interpretor& theDI,
4494 Standard_Integer theArgNb,
4495 const char** theArgVec)
4496{
4497 Handle(V3d_View) aView = ViewerTest::CurrentView();
4498 if (aView.IsNull())
4499 {
23fe70ec 4500 Message::SendFail ("Error: no active viewer");
3bffef55 4501 return 1;
4502 }
4503
4504 Graphic3d_CameraTile aTile = aView->Camera()->Tile();
4505 if (theArgNb < 2)
4506 {
4507 theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
4508 << "Tile size: " << aTile.TileSize.x() << " " << aTile.TileSize.y() << "\n"
4509 << "Lower left: " << aTile.Offset.x() << " " << aTile.Offset.y() << "\n";
4510 return 0;
4511 }
4512
4513 aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
4514 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4515 {
4516 TCollection_AsciiString anArg (theArgVec[anArgIter]);
4517 anArg.LowerCase();
4518 if (anArg == "-lowerleft"
4519 || anArg == "-upperleft")
4520 {
4521 if (anArgIter + 3 < theArgNb)
4522 {
23fe70ec 4523 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
3bffef55 4524 return 1;
4525 }
4526 aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
4527 aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4528 aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4529 }
4530 else if (anArg == "-total"
4531 || anArg == "-totalsize"
4532 || anArg == "-viewsize")
4533 {
4534 if (anArgIter + 3 < theArgNb)
4535 {
23fe70ec 4536 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
3bffef55 4537 return 1;
4538 }
4539 aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4540 aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4541 if (aTile.TotalSize.x() < 1
4542 || aTile.TotalSize.y() < 1)
4543 {
23fe70ec 4544 Message::SendFail ("Error: total size is incorrect");
3bffef55 4545 return 1;
4546 }
4547 }
4548 else if (anArg == "-tilesize")
4549 {
4550 if (anArgIter + 3 < theArgNb)
4551 {
23fe70ec 4552 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
3bffef55 4553 return 1;
4554 }
4555
4556 aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
4557 aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
4558 if (aTile.TileSize.x() < 1
4559 || aTile.TileSize.y() < 1)
4560 {
23fe70ec 4561 Message::SendFail ("Error: tile size is incorrect");
3bffef55 4562 return 1;
4563 }
4564 }
4565 else if (anArg == "-unset")
4566 {
4567 aView->Camera()->SetTile (Graphic3d_CameraTile());
4568 aView->Redraw();
4569 return 0;
4570 }
4571 }
4572
4573 if (aTile.TileSize.x() < 1
4574 || aTile.TileSize.y() < 1)
4575 {
23fe70ec 4576 Message::SendFail ("Error: tile size is undefined");
3bffef55 4577 return 1;
4578 }
4579 else if (aTile.TotalSize.x() < 1
4580 || aTile.TotalSize.y() < 1)
4581 {
23fe70ec 4582 Message::SendFail ("Error: total size is undefined");
3bffef55 4583 return 1;
4584 }
4585
4586 aView->Camera()->SetTile (aTile);
4587 aView->Redraw();
4588 return 0;
4589}
4590
7c3ef2f7 4591//! Format ZLayer ID.
4592inline const char* formZLayerId (const Standard_Integer theLayerId)
4593{
4594 switch (theLayerId)
4595 {
4596 case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
4597 case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
4598 case Graphic3d_ZLayerId_Top: return "[TOP]";
4599 case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
4600 case Graphic3d_ZLayerId_TopOSD: return "[OVERLAY]";
4601 case Graphic3d_ZLayerId_BotOSD: return "[UNDERLAY]";
4602 }
4603 return "";
4604}
4605
4606//! Print the ZLayer information.
4607inline void printZLayerInfo (Draw_Interpretor& theDI,
4608 const Graphic3d_ZLayerSettings& theLayer)
4609{
4610 if (!theLayer.Name().IsEmpty())
4611 {
4612 theDI << " Name: " << theLayer.Name() << "\n";
4613 }
4614 if (theLayer.IsImmediate())
4615 {
4616 theDI << " Immediate: TRUE\n";
4617 }
4618 theDI << " Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
4ecf34cc 4619 theDI << " Culling distance: " << theLayer.CullingDistance() << "\n";
4620 theDI << " Culling size: " << theLayer.CullingSize() << "\n";
7c3ef2f7 4621 theDI << " Depth test: " << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
4622 theDI << " Depth write: " << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
4623 theDI << " Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
4624 if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
4625 {
4626 theDI << " Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
4627 }
4628}
4629
59f45b7c 4630//==============================================================================
4631//function : VZLayer
4632//purpose : Test z layer operations for v3d viewer
4633//==============================================================================
7c3ef2f7 4634static int VZLayer (Draw_Interpretor& theDI,
4635 Standard_Integer theArgNb,
4636 const char** theArgVec)
59f45b7c 4637{
7c3ef2f7 4638 Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
59f45b7c 4639 if (aContextAIS.IsNull())
4640 {
23fe70ec 4641 Message::SendFail ("Error: no active viewer");
59f45b7c 4642 return 1;
4643 }
4644
4645 const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
7c3ef2f7 4646 if (theArgNb < 2)
59f45b7c 4647 {
7c3ef2f7 4648 TColStd_SequenceOfInteger aLayers;
4649 aViewer->GetAllZLayers (aLayers);
4650 for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4651 {
4652 theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
4653 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
4654 printZLayerInfo (theDI, aSettings);
4655 }
95bdefb2 4656 return 0;
59f45b7c 4657 }
4658
7c3ef2f7 4659 Standard_Integer anArgIter = 1;
4660 Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4661 ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
4662 if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
59f45b7c 4663 {
7c3ef2f7 4664 ++anArgIter;
4665 }
59f45b7c 4666
7c3ef2f7 4667 {
55c8f0f7
BB
4668 TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
4669 if (aFirstArg.IsIntegerValue())
c5751993 4670 {
7c3ef2f7 4671 ++anArgIter;
55c8f0f7 4672 aLayerId = aFirstArg.IntegerValue();
c5751993 4673 }
7c3ef2f7 4674 else
c5751993 4675 {
55c8f0f7 4676 if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
7c3ef2f7 4677 {
55c8f0f7 4678 ++anArgIter;
7c3ef2f7 4679 }
c5751993 4680 }
7c3ef2f7 4681 }
c5751993 4682
1c728f2d 4683 Graphic3d_ZLayerId anOtherLayerId = Graphic3d_ZLayerId_UNKNOWN;
7c3ef2f7 4684 for (; anArgIter < theArgNb; ++anArgIter)
4685 {
4686 // perform operation
4687 TCollection_AsciiString anArg (theArgVec[anArgIter]);
4688 anArg.LowerCase();
4689 if (anUpdateTool.parseRedrawMode (anArg))
c5751993 4690 {
7c3ef2f7 4691 //
c5751993 4692 }
7c3ef2f7 4693 else if (anArg == "-add"
4694 || anArg == "add")
c5751993 4695 {
7c3ef2f7 4696 aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4697 if (!aViewer->AddZLayer (aLayerId))
4698 {
23fe70ec 4699 Message::SendFail ("Error: can not add a new z layer");
7c3ef2f7 4700 return 0;
4701 }
4702
4703 theDI << aLayerId;
c5751993 4704 }
1c728f2d 4705 else if (anArg == "-insertbefore"
4706 && anArgIter + 1 < theArgNb
4707 && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
4708 {
4709 ++anArgIter;
4710 aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4711 if (!aViewer->InsertLayerBefore (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
4712 {
23fe70ec 4713 Message::SendFail ("Error: can not add a new z layer");
1c728f2d 4714 return 0;
4715 }
4716
4717 theDI << aLayerId;
4718 }
4719 else if (anArg == "-insertafter"
4720 && anArgIter + 1 < theArgNb
4721 && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
4722 {
4723 ++anArgIter;
4724 aLayerId = Graphic3d_ZLayerId_UNKNOWN;
4725 if (!aViewer->InsertLayerAfter (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
4726 {
23fe70ec 4727 Message::SendFail ("Error: can not add a new z layer");
1c728f2d 4728 return 0;
4729 }
4730
4731 theDI << aLayerId;
4732 }
7c3ef2f7 4733 else if (anArg == "-del"
4734 || anArg == "-delete"
4735 || anArg == "del")
c5751993 4736 {
7c3ef2f7 4737 if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4738 {
4739 if (++anArgIter >= theArgNb)
4740 {
23fe70ec 4741 Message::SendFail ("Syntax error: id of z layer to remove is missing");
7c3ef2f7 4742 return 1;
4743 }
4744
4745 aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4746 }
4747
4748 if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
4749 || aLayerId == Graphic3d_ZLayerId_Default
4750 || aLayerId == Graphic3d_ZLayerId_Top
4751 || aLayerId == Graphic3d_ZLayerId_Topmost
4752 || aLayerId == Graphic3d_ZLayerId_TopOSD
4753 || aLayerId == Graphic3d_ZLayerId_BotOSD)
4754 {
23fe70ec 4755 Message::SendFail ("Syntax error: standard Z layer can not be removed");
7c3ef2f7 4756 return 1;
4757 }
4758
4759 // move all object displayed in removing layer to default layer
4760 for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
4761 anObjIter.More(); anObjIter.Next())
4762 {
8f521168 4763 const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
7c3ef2f7 4764 if (aPrs.IsNull()
4765 || aPrs->ZLayer() != aLayerId)
4766 {
4767 continue;
4768 }
4769 aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
4770 }
4771
4772 if (!aViewer->RemoveZLayer (aLayerId))
4773 {
23fe70ec 4774 Message::SendFail ("Z layer can not be removed");
7c3ef2f7 4775 }
4776 else
4777 {
4778 theDI << aLayerId << " ";
4779 }
c5751993 4780 }
7c3ef2f7 4781 else if (anArg == "-get"
4782 || anArg == "get")
c5751993 4783 {
7c3ef2f7 4784 TColStd_SequenceOfInteger aLayers;
4785 aViewer->GetAllZLayers (aLayers);
4786 for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4787 {
4788 theDI << aLayeriter.Value() << " ";
4789 }
4790
4791 theDI << "\n";
c5751993 4792 }
7c3ef2f7 4793 else if (anArg == "-name")
c5751993 4794 {
7c3ef2f7 4795 if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
c5751993 4796 {
23fe70ec 4797 Message::SendFail ("Syntax error: id of Z layer is missing");
c5751993 4798 return 1;
4799 }
4800
7c3ef2f7 4801 if (++anArgIter >= theArgNb)
4802 {
23fe70ec 4803 Message::SendFail ("Syntax error: name is missing");
7c3ef2f7 4804 return 1;
4805 }
c5751993 4806
7c3ef2f7 4807 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4808 aSettings.SetName (theArgVec[anArgIter]);
4809 aViewer->SetZLayerSettings (aLayerId, aSettings);
c5751993 4810 }
7c3ef2f7 4811 else if (anArg == "-origin")
c5751993 4812 {
7c3ef2f7 4813 if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4814 {
23fe70ec 4815 Message::SendFail ("Syntax error: id of Z layer is missing");
7c3ef2f7 4816 return 1;
4817 }
4818
4819 if (anArgIter + 2 >= theArgNb)
4820 {
23fe70ec 4821 Message::SendFail ("Syntax error: origin coordinates are missing");
7c3ef2f7 4822 return 1;
4823 }
4824
4825 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4826 gp_XYZ anOrigin;
4827 anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
4828 anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
4829 anOrigin.SetZ (0.0);
4830 if (anArgIter + 3 < theArgNb)
4831 {
4832 anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
4833 anArgIter += 3;
4834 }
4835 else
4836 {
4837 anArgIter += 2;
4838 }
4839 aSettings.SetOrigin (anOrigin);
4840 aViewer->SetZLayerSettings (aLayerId, aSettings);
c5751993 4841 }
4ecf34cc 4842 else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4843 && anArgIter + 1 < theArgNb
4844 && (anArg == "-cullingdistance"
4845 || anArg == "-cullingdist"
4846 || anArg == "-culldistance"
4847 || anArg == "-culldist"
4848 || anArg == "-distcull"
4849 || anArg == "-distculling"
4850 || anArg == "-distanceculling"))
4851 {
4852 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4853 const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
4854 aSettings.SetCullingDistance (aDist);
4855 aViewer->SetZLayerSettings (aLayerId, aSettings);
4856 }
4857 else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
4858 && anArgIter + 1 < theArgNb
4859 && (anArg == "-cullingsize"
4860 || anArg == "-cullsize"
4861 || anArg == "-sizecull"
4862 || anArg == "-sizeculling"))
4863 {
4864 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4865 const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
4866 aSettings.SetCullingSize (aSize);
4867 aViewer->SetZLayerSettings (aLayerId, aSettings);
4868 }
7c3ef2f7 4869 else if (anArg == "-settings"
4870 || anArg == "settings")
c5751993 4871 {
7c3ef2f7 4872 if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4873 {
4874 if (++anArgIter >= theArgNb)
4875 {
23fe70ec 4876 Message::SendFail ("Syntax error: id of Z layer is missing");
7c3ef2f7 4877 return 1;
4878 }
4879
4880 aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4881 }
4882
4883 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4884 printZLayerInfo (theDI, aSettings);
c5751993 4885 }
7c3ef2f7 4886 else if (anArg == "-enable"
4887 || anArg == "enable"
4888 || anArg == "-disable"
4889 || anArg == "disable")
83da37b1 4890 {
7c3ef2f7 4891 const Standard_Boolean toEnable = anArg == "-enable"
4892 || anArg == "enable";
4893 if (++anArgIter >= theArgNb)
4894 {
23fe70ec 4895 Message::SendFail ("Syntax error: option name is missing");
7c3ef2f7 4896 return 1;
4897 }
c5751993 4898
7c3ef2f7 4899 TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
4900 aSubOp.LowerCase();
4901 if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
4902 {
4903 if (++anArgIter >= theArgNb)
4904 {
23fe70ec 4905 Message::SendFail ("Syntax error: id of Z layer is missing");
7c3ef2f7 4906 return 1;
4907 }
c5751993 4908
7c3ef2f7 4909 aLayerId = Draw::Atoi (theArgVec[anArgIter]);
4910 }
c5751993 4911
7c3ef2f7 4912 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
4913 if (aSubOp == "depthtest"
4914 || aSubOp == "test")
4915 {
4916 aSettings.SetEnableDepthTest (toEnable);
4917 }
4918 else if (aSubOp == "depthwrite"
4919 || aSubOp == "write")
4920 {
4921 aSettings.SetEnableDepthWrite (toEnable);
4922 }
4923 else if (aSubOp == "depthclear"
4924 || aSubOp == "clear")
4925 {
4926 aSettings.SetClearDepth (toEnable);
4927 }
4928 else if (aSubOp == "depthoffset"
4929 || aSubOp == "offset")
4930 {
4931 Graphic3d_PolygonOffset aParams;
4932 aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
4933 if (toEnable)
4934 {
4935 if (anArgIter + 2 >= theArgNb)
4936 {
23fe70ec 4937 Message::SendFail ("Syntax error: factor and units values for depth offset are missing");
7c3ef2f7 4938 return 1;
4939 }
c5751993 4940
7c3ef2f7 4941 aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4942 aParams.Units = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
4943 }
4944 aSettings.SetPolygonOffset (aParams);
4945 }
4946 else if (aSubOp == "positiveoffset"
4947 || aSubOp == "poffset")
4948 {
4949 if (toEnable)
4950 {
4951 aSettings.SetDepthOffsetPositive();
4952 }
4953 else
4954 {
4955 aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
4956 }
4957 }
4958 else if (aSubOp == "negativeoffset"
4959 || aSubOp == "noffset")
4960 {
4961 if (toEnable)
4962 {
4963 aSettings.SetDepthOffsetNegative();
4964 }
4965 else
4966 {
4967 aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
4968 }
4969 }
4970 else if (aSubOp == "textureenv")
4971 {
4972 aSettings.SetEnvironmentTexture (toEnable);
4973 }
1c728f2d 4974 else if (aSubOp == "raytracing")
4975 {
4976 aSettings.SetRaytracable (toEnable);
4977 }
7c3ef2f7 4978
4979 aViewer->SetZLayerSettings (aLayerId, aSettings);
c5751993 4980 }
7c3ef2f7 4981 else
83da37b1 4982 {
23fe70ec 4983 Message::SendFail() << "Syntax error: unknown option " << theArgVec[anArgIter];
7c3ef2f7 4984 return 1;
83da37b1 4985 }
59f45b7c 4986 }
4987
4988 return 0;
4989}
4990
c357e426 4991// The interactive presentation of 2d layer item
4992// for "vlayerline" command it provides a presentation of
4993// line with user-defined linewidth, linetype and transparency.
61b0191c 4994class V3d_LineItem : public AIS_InteractiveObject
20637bd2 4995{
4996public:
4997 // CASCADE RTTI
92efcf78 4998 DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
4fe56619 4999
20637bd2 5000 // constructor
5001 Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5002 Standard_Real X2, Standard_Real Y2,
20637bd2 5003 Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5004 Standard_Real theWidth = 0.5,
5005 Standard_Real theTransp = 1.0);
5006
decbff0d 5007private:
61b0191c 5008
decbff0d 5009 virtual void Compute (const Handle(PrsMgr_PresentationManager)& thePrsMgr,
5010 const Handle(Prs3d_Presentation)& thePrs,
5011 const Standard_Integer theMode) Standard_OVERRIDE;
61b0191c 5012
decbff0d 5013 virtual void ComputeSelection (const Handle(SelectMgr_Selection)& ,
5014 const Standard_Integer ) Standard_OVERRIDE
79104795 5015 {}
20637bd2 5016
5017private:
5018
5019 Standard_Real myX1, myY1, myX2, myY2;
eafb234b 5020 Aspect_TypeOfLine myType;
20637bd2 5021 Standard_Real myWidth;
20637bd2 5022};
5023
20637bd2 5024// default constructor for line item
4fe56619 5025V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
20637bd2 5026 Standard_Real X2, Standard_Real Y2,
20637bd2 5027 Aspect_TypeOfLine theType,
5028 Standard_Real theWidth,
5029 Standard_Real theTransp) :
61b0191c 5030 myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5031 myType(theType), myWidth(theWidth)
20637bd2 5032{
61b0191c 5033 SetTransparency (1-theTransp);
20637bd2 5034}
5035
5036// render line
decbff0d 5037void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager)& ,
61b0191c 5038 const Handle(Prs3d_Presentation)& thePresentation,
decbff0d 5039 const Standard_Integer )
20637bd2 5040{
61b0191c 5041 thePresentation->Clear();
ba00aab7 5042 Quantity_Color aColor (Quantity_NOC_RED);
61b0191c 5043 Standard_Integer aWidth, aHeight;
5044 ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
d6c48921 5045 Handle(Graphic3d_Group) aGroup = thePresentation->CurrentGroup();
61b0191c 5046 Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5047 aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5048 aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5049 Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5050 aGroup->SetPrimitivesAspect (anAspect->Aspect());
5051 aGroup->AddPrimitiveArray (aPrim);
20637bd2 5052}
5053
5054//=============================================================================
5055//function : VLayerLine
5056//purpose : Draws line in the v3d view layer with given attributes: linetype,
5057// : linewidth, transparency coefficient
5058//============================================================================
5059static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5060{
5061 // get the active view
5062 Handle(V3d_View) aView = ViewerTest::CurrentView();
5063 if (aView.IsNull())
5064 {
5065 di << "Call vinit before!\n";
5066 return 1;
5067 }
5068 else if (argc < 5)
5069 {
5070 di << "Use: " << argv[0];
5071 di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5072 di << " linetype : { 0 | 1 | 2 | 3 } \n";
5073 di << " 0 - solid \n";
5074 di << " 1 - dashed \n";
5075 di << " 2 - dot \n";
5076 di << " 3 - dashdot\n";
5077 di << " transparency : { 0.0 - 1.0 } \n";
5078 di << " 0.0 - transparent\n";
5079 di << " 1.0 - visible \n";
5080 return 1;
5081 }
5082
61b0191c 5083 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
20637bd2 5084 // get the input params
91322f44 5085 Standard_Real X1 = Draw::Atof(argv[1]);
5086 Standard_Real Y1 = Draw::Atof(argv[2]);
5087 Standard_Real X2 = Draw::Atof(argv[3]);
5088 Standard_Real Y2 = Draw::Atof(argv[4]);
20637bd2 5089
3a4a3962 5090 Standard_Real aWidth = 0.5;
5091 Standard_Real aTransparency = 1.0;
20637bd2 5092
5093 // has width
5094 if (argc > 5)
91322f44 5095 aWidth = Draw::Atof(argv[5]);
20637bd2 5096
3a4a3962 5097 // select appropriate line type
5098 Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5099 if (argc > 6
5100 && !ViewerTest::ParseLineType (argv[6], aLineType))
5101 {
23fe70ec 5102 Message::SendFail() << "Syntax error: unknown line type '" << argv[6] << "'";
3a4a3962 5103 return 1;
5104 }
20637bd2 5105
5106 // has transparency
5107 if (argc > 7)
5108 {
91322f44 5109 aTransparency = Draw::Atof(argv[7]);
4fe56619 5110 if (aTransparency < 0 || aTransparency > 1.0)
20637bd2 5111 aTransparency = 1.0;
5112 }
5113
61b0191c 5114 static Handle (V3d_LineItem) aLine;
5115 if (!aLine.IsNull())
25289ec1 5116 {
0577ae8c 5117 aContext->Erase (aLine, Standard_False);
25289ec1 5118 }
61b0191c 5119 aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5120 aLineType, aWidth,
5121 aTransparency);
25289ec1 5122
778cd667 5123 aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
61b0191c 5124 aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5125 aLine->SetToUpdate();
5126 aContext->Display (aLine, Standard_True);
25289ec1 5127
5128 return 0;
5129}
5130
61b0191c 5131
2bd4c032 5132//==============================================================================
5133//function : VGrid
5134//purpose :
5135//==============================================================================
5136
35e08fe8 5137static int VGrid (Draw_Interpretor& /*theDI*/,
2bd4c032 5138 Standard_Integer theArgNb,
5139 const char** theArgVec)
5140{
2bd4c032 5141 Handle(V3d_View) aView = ViewerTest::CurrentView();
5142 Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5143 if (aView.IsNull() || aViewer.IsNull())
5144 {
23fe70ec 5145 Message::SendFail ("Error: no active viewer");
2bd4c032 5146 return 1;
5147 }
5148
5149 Aspect_GridType aType = aViewer->GridType();
5150 Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
79931835 5151 Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
5152 Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
5153 bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
224f48fa 5154 ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
79931835 5155 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
2bd4c032 5156 {
79931835 5157 TCollection_AsciiString anArg (theArgVec[anArgIter]);
5158 anArg.LowerCase();
5159 if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
224f48fa 5160 {
5161 continue;
5162 }
79931835 5163 else if (anArgIter + 1 < theArgNb
5164 && anArg == "-type")
5165 {
5166 TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5167 anArgNext.LowerCase();
5168 if (anArgNext == "r"
5169 || anArgNext == "rect"
5170 || anArgNext == "rectangular")
5171 {
5172 aType = Aspect_GT_Rectangular;
5173 }
5174 else if (anArgNext == "c"
5175 || anArgNext == "circ"
5176 || anArgNext == "circular")
5177 {
5178 aType = Aspect_GT_Circular;
5179 }
5180 else
5181 {
23fe70ec 5182 Message::SendFail() << "Syntax error at '" << anArgNext << "'";
79931835 5183 return 1;
5184 }
5185 }
5186 else if (anArgIter + 1 < theArgNb
5187 && anArg == "-mode")
5188 {
5189 TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5190 anArgNext.LowerCase();
5191 if (anArgNext == "l"
5192 || anArgNext == "line"
5193 || anArgNext == "lines")
5194 {
5195 aMode = Aspect_GDM_Lines;
5196 }
5197 else if (anArgNext == "p"
5198 || anArgNext == "point"
5199 || anArgNext == "points")
5200 {
5201 aMode = Aspect_GDM_Points;
5202 }
5203 else
5204 {
23fe70ec 5205 Message::SendFail() << "Syntax error at '" << anArgNext << "'";
79931835 5206 return 1;
5207 }
5208 }
5209 else if (anArgIter + 2 < theArgNb
5210 && (anArg == "-origin"
5211 || anArg == "-orig"))
5212 {
5213 hasOrigin = true;
5214 aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5215 Draw::Atof (theArgVec[anArgIter + 2]));
5216 anArgIter += 2;
5217 }
5218 else if (anArgIter + 2 < theArgNb
5219 && anArg == "-step")
5220 {
5221 hasStep = true;
5222 aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5223 Draw::Atof (theArgVec[anArgIter + 2]));
5224 if (aNewStepXY.x() <= 0.0
5225 || aNewStepXY.y() <= 0.0)
5226 {
23fe70ec 5227 Message::SendFail() << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'";
79931835 5228 return 1;
5229 }
5230 anArgIter += 2;
5231 }
5232 else if (anArgIter + 1 < theArgNb
5233 && (anArg == "-angle"
5234 || anArg == "-rotangle"
5235 || anArg == "-rotationangle"))
5236 {
5237 hasRotAngle = true;
5238 aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
5239 }
5240 else if (anArgIter + 1 < theArgNb
5241 && (anArg == "-zoffset"
5242 || anArg == "-dz"))
5243 {
5244 hasZOffset = true;
5245 aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
5246 }
5247 else if (anArgIter + 1 < theArgNb
5248 && anArg == "-radius")
5249 {
5250 hasSize = true;
5251 ++anArgIter;
5252 aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
5253 if (aNewStepXY.x() <= 0.0)
5254 {
23fe70ec 5255 Message::SendFail() << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'";
79931835 5256 return 1;
5257 }
5258 }
5259 else if (anArgIter + 2 < theArgNb
5260 && anArg == "-size")
5261 {
5262 hasSize = true;
5263 aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5264 Draw::Atof (theArgVec[anArgIter + 2]));
5265 if (aNewStepXY.x() <= 0.0
5266 || aNewStepXY.y() <= 0.0)
5267 {
23fe70ec 5268 Message::SendFail() << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'";
79931835 5269 return 1;
5270 }
5271 anArgIter += 2;
5272 }
5273 else if (anArg == "r"
5274 || anArg == "rect"
5275 || anArg == "rectangular")
2bd4c032 5276 {
5277 aType = Aspect_GT_Rectangular;
5278 }
79931835 5279 else if (anArg == "c"
5280 || anArg == "circ"
5281 || anArg == "circular")
2bd4c032 5282 {
5283 aType = Aspect_GT_Circular;
5284 }
79931835 5285 else if (anArg == "l"
5286 || anArg == "line"
5287 || anArg == "lines")
2bd4c032 5288 {
5289 aMode = Aspect_GDM_Lines;
5290 }
79931835 5291 else if (anArg == "p"
5292 || anArg == "point"
5293 || anArg == "points")
2bd4c032 5294 {
5295 aMode = Aspect_GDM_Points;
5296 }
79931835 5297 else if (anArgIter + 1 >= theArgNb
5298 && anArg == "off")
2bd4c032 5299 {
5300 aViewer->DeactivateGrid();
5301 return 0;
5302 }
5303 else
5304 {
23fe70ec 5305 Message::SendFail() << "Syntax error at '" << anArg << "'";
79931835 5306 return 1;
2bd4c032 5307 }
5308 }
5309
2bd4c032 5310 if (aType == Aspect_GT_Rectangular)
5311 {
79931835 5312 Graphic3d_Vec2d anOrigXY, aStepXY;
5313 Standard_Real aRotAngle = 0.0;
5314 aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5315 if (hasOrigin)
5316 {
5317 anOrigXY = aNewOriginXY;
5318 }
5319 if (hasStep)
5320 {
5321 aStepXY = aNewStepXY;
5322 }
5323 if (hasRotAngle)
5324 {
5325 aRotAngle = aNewRotAngle;
5326 }
5327 aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5328 if (hasSize || hasZOffset)
2bd4c032 5329 {
79931835 5330 Graphic3d_Vec3d aSize;
5331 aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5332 if (hasSize)
5333 {
5334 aSize.x() = aNewSizeXY.x();
5335 aSize.y() = aNewSizeXY.y();
5336 }
5337 if (hasZOffset)
5338 {
5339 aSize.z() = aNewZOffset;
5340 }
5341 aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
2bd4c032 5342 }
2bd4c032 5343 }
5344 else if (aType == Aspect_GT_Circular)
5345 {
79931835 5346 Graphic3d_Vec2d anOrigXY;
ee2be2a8 5347 Standard_Real aRadiusStep;
2bd4c032 5348 Standard_Integer aDivisionNumber;
79931835 5349 Standard_Real aRotAngle = 0.0;
5350 aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5351 if (hasOrigin)
5352 {
5353 anOrigXY = aNewOriginXY;
5354 }
5355 if (hasStep)
5356 {
5357 aRadiusStep = aNewStepXY[0];
5358 aDivisionNumber = (int )aNewStepXY[1];
5359 if (aDivisionNumber < 1)
5360 {
23fe70ec 5361 Message::SendFail() << "Syntax error: invalid division number '" << aNewStepXY[1] << "'";
79931835 5362 return 1;
5363 }
5364 }
5365 if (hasRotAngle)
2bd4c032 5366 {
79931835 5367 aRotAngle = aNewRotAngle;
2bd4c032 5368 }
5369
79931835 5370 aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5371 if (hasSize || hasZOffset)
5372 {
5373 Standard_Real aRadius = 0.0, aZOffset = 0.0;
5374 aViewer->CircularGridGraphicValues (aRadius, aZOffset);
5375 if (hasSize)
5376 {
5377 aRadius = aNewSizeXY.x();
5378 if (aNewSizeXY.y() != 0.0)
5379 {
23fe70ec 5380 Message::SendFail ("Syntax error: circular size should be specified as radius");
79931835 5381 return 1;
5382 }
5383 }
5384 if (hasZOffset)
5385 {
5386 aZOffset = aNewZOffset;
5387 }
5388 aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
5389 }
2bd4c032 5390 }
79931835 5391 aViewer->ActivateGrid (aType, aMode);
2bd4c032 5392 return 0;
5393}
5394
c40b7d58 5395//==============================================================================
5396//function : VPriviledgedPlane
5397//purpose :
5398//==============================================================================
5399
5400static int VPriviledgedPlane (Draw_Interpretor& theDI,
5401 Standard_Integer theArgNb,
5402 const char** theArgVec)
5403{
5404 if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
5405 {
23fe70ec 5406 Message::SendFail ("Error: wrong number of arguments! See usage:");
c40b7d58 5407 theDI.PrintHelp (theArgVec[0]);
5408 return 1;
5409 }
5410
5411 // get the active viewer
5412 Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5413 if (aViewer.IsNull())
5414 {
23fe70ec 5415 Message::SendFail ("Error: no active viewer");
c40b7d58 5416 return 1;
5417 }
5418
5419 if (theArgNb == 1)
5420 {
5421 gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
5422 const gp_Pnt& anOrig = aPriviledgedPlane.Location();
5423 const gp_Dir& aNorm = aPriviledgedPlane.Direction();
5424 const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
5425 theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
5426 << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
5427 << "X-dir: " << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
5428 return 0;
5429 }
5430
5431 Standard_Integer anArgIdx = 1;
5432 Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
5433 Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
5434 Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
5435 Standard_Real aNormX = Draw::Atof (theArgVec[anArgIdx++]);
5436 Standard_Real aNormY = Draw::Atof (theArgVec[anArgIdx++]);
5437 Standard_Real aNormZ = Draw::Atof (theArgVec[anArgIdx++]);
5438
5439 gp_Ax3 aPriviledgedPlane;
5440 gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
5441 gp_Dir aNorm (aNormX, aNormY, aNormZ);
5442 if (theArgNb > 7)
5443 {
5444 Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
5445 Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
5446 Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
5447 gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
5448 aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
5449 }
5450 else
5451 {
5452 aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
5453 }
5454
5455 aViewer->SetPrivilegedPlane (aPriviledgedPlane);
5456
5457 return 0;
5458}
5459
f25b82d6 5460//==============================================================================
5461//function : VConvert
5462//purpose :
5463//==============================================================================
5464
5465static int VConvert (Draw_Interpretor& theDI,
5466 Standard_Integer theArgNb,
5467 const char** theArgVec)
5468{
5469 // get the active view
5470 Handle(V3d_View) aView = ViewerTest::CurrentView();
5471 if (aView.IsNull())
5472 {
23fe70ec 5473 Message::SendFail ("Error: no active viewer");
f25b82d6 5474 return 1;
5475 }
5476
5477 enum { Model, Ray, View, Window, Grid } aMode = Model;
5478
5479 // access coordinate arguments
5480 TColStd_SequenceOfReal aCoord;
5481 Standard_Integer anArgIdx = 1;
5482 for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
5483 {
5484 TCollection_AsciiString anArg (theArgVec[anArgIdx]);
d45edf24 5485 if (!anArg.IsRealValue (Standard_True))
f25b82d6 5486 {
5487 break;
5488 }
5489 aCoord.Append (anArg.RealValue());
5490 }
5491
5492 // non-numeric argument too early
5493 if (aCoord.IsEmpty())
5494 {
23fe70ec 5495 Message::SendFail ("Error: wrong number of arguments! See usage:");
f25b82d6 5496 theDI.PrintHelp (theArgVec[0]);
5497 return 1;
5498 }
5499
5500 // collect all other arguments and options
5501 for (; anArgIdx < theArgNb; ++anArgIdx)
5502 {
5503 TCollection_AsciiString anArg (theArgVec[anArgIdx]);
5504 anArg.LowerCase();
5505 if (anArg == "window") aMode = Window;
5506 else if (anArg == "view") aMode = View;
5507 else if (anArg == "grid") aMode = Grid;
5508 else if (anArg == "ray") aMode = Ray;
5509 else
5510 {
23fe70ec 5511 Message::SendFail() << "Error: wrong argument " << anArg << "! See usage:";
f25b82d6 5512 theDI.PrintHelp (theArgVec[0]);
5513 return 1;
5514 }
5515 }
5516
5517 // complete input checks
5518 if ((aCoord.Length() == 1 && theArgNb > 3) ||
5519 (aCoord.Length() == 2 && theArgNb > 4) ||
5520 (aCoord.Length() == 3 && theArgNb > 5))
5521 {
23fe70ec 5522 Message::SendFail ("Error: wrong number of arguments! See usage:");
f25b82d6 5523 theDI.PrintHelp (theArgVec[0]);
5524 return 1;
5525 }
5526
5527 Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
5528 Standard_Integer aXYp[2] = {0, 0};
5529
5530 // convert one-dimensional coordinate
5531 if (aCoord.Length() == 1)
5532 {
5533 switch (aMode)
5534 {
ee2be2a8 5535 case View : theDI << "View Vv: " << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
5536 case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
f25b82d6 5537 default:
23fe70ec 5538 Message::SendFail ("Error: wrong arguments! See usage:");
f25b82d6 5539 theDI.PrintHelp (theArgVec[0]);
5540 return 1;
5541 }
5542 }
5543
5544 // convert 2D coordinates from projection or view reference space
5545 if (aCoord.Length() == 2)
5546 {
5547 switch (aMode)
5548 {
5549 case Model :
5550 aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5551 theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5552 return 0;
5553
5554 case View :
5555 aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
5556 theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
5557 return 0;
5558
5559 case Window :
ee2be2a8 5560 aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
f25b82d6 5561 theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5562 return 0;
5563
5564 case Grid :
5565 aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
5566 aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
5567 theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5568 return 0;
5569
5570 case Ray :
5571 aView->ConvertWithProj ((Standard_Integer) aCoord (1),
5572 (Standard_Integer) aCoord (2),
5573 aXYZ[0], aXYZ[1], aXYZ[2],
5574 aXYZ[3], aXYZ[4], aXYZ[5]);
5575 theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
5576 return 0;
5577
5578 default:
23fe70ec 5579 Message::SendFail ("Error: wrong arguments! See usage:");
f25b82d6 5580 theDI.PrintHelp (theArgVec[0]);
5581 return 1;
5582 }
5583 }
5584
5585 // convert 3D coordinates from view reference space
5586 else if (aCoord.Length() == 3)
5587 {
5588 switch (aMode)
5589 {
5590 case Window :
5591 aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
5592 theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
5593 return 0;
5594
5595 case Grid :
5596 aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
5597 theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
5598 return 0;
5599
5600 default:
23fe70ec 5601 Message::SendFail ("Error: wrong arguments! See usage:");
f25b82d6 5602 theDI.PrintHelp (theArgVec[0]);
5603 return 1;
5604 }
5605 }
5606
5607 return 0;
5608}
5609
208e6839 5610//==============================================================================
5611//function : VFps
5612//purpose :
5613//==============================================================================
5614
5615static int VFps (Draw_Interpretor& theDI,
5616 Standard_Integer theArgNb,
5617 const char** theArgVec)
5618{
5619 // get the active view
5620 Handle(V3d_View) aView = ViewerTest::CurrentView();
5621 if (aView.IsNull())
5622 {
23fe70ec 5623 Message::SendFail ("Error: no active viewer");
208e6839 5624 return 1;
5625 }
5626
e084dbbc 5627 Standard_Integer aFramesNb = -1;
5628 Standard_Real aDuration = -1.0;
5629 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
208e6839 5630 {
e084dbbc 5631 TCollection_AsciiString anArg (theArgVec[anArgIter]);
5632 anArg.LowerCase();
5633 if (aDuration < 0.0
5634 && anArgIter + 1 < theArgNb
5635 && (anArg == "-duration"
5636 || anArg == "-dur"
5637 || anArg == "-time"))
5638 {
5639 aDuration = Draw::Atof (theArgVec[++anArgIter]);
5640 }
5641 else if (aFramesNb < 0
5642 && anArg.IsIntegerValue())
5643 {
5644 aFramesNb = anArg.IntegerValue();
5645 if (aFramesNb <= 0)
5646 {
23fe70ec 5647 Message::SendFail() << "Syntax error at '" << anArg << "'";
e084dbbc 5648 return 1;
5649 }
5650 }
5651 else
5652 {
23fe70ec 5653 Message::SendFail() << "Syntax error at '" << anArg << "'";
e084dbbc 5654 return 1;
5655 }
5656 }
5657 if (aFramesNb < 0 && aDuration < 0.0)
5658 {
5659 aFramesNb = 100;
208e6839 5660 }
5661
5662 // the time is meaningless for first call
5663 // due to async OpenGl rendering
5664 aView->Redraw();
5665
5666 // redraw view in loop to estimate average values
5667 OSD_Timer aTimer;
5668 aTimer.Start();
e084dbbc 5669 Standard_Integer aFrameIter = 1;
5670 for (;; ++aFrameIter)
208e6839 5671 {
5672 aView->Redraw();
e084dbbc 5673 if ((aFramesNb > 0
5674 && aFrameIter >= aFramesNb)
5675 || (aDuration > 0.0
5676 && aTimer.ElapsedTime() >= aDuration))
5677 {
5678 break;
5679 }
208e6839 5680 }
5681 aTimer.Stop();
5682 Standard_Real aCpu;
5683 const Standard_Real aTime = aTimer.ElapsedTime();
5684 aTimer.OSD_Chronometer::Show (aCpu);
5685
e084dbbc 5686 const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
5687 const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
208e6839 5688
5689 // return statistics
5690 theDI << "FPS: " << aFpsAver << "\n"
5691 << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
5692
8c820969 5693 // compute additional statistics in ray-tracing mode
e084dbbc 5694 const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
8c820969 5695 if (aParams.Method == Graphic3d_RM_RAYTRACING)
5696 {
e084dbbc 5697 Graphic3d_Vec2i aWinSize (0, 0);
5698 aView->Window()->Size (aWinSize.x(), aWinSize.y());
8c820969 5699
5700 // 1 shadow ray and 1 secondary ray pew each bounce
e084dbbc 5701 const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
8c820969 5702 theDI << "MRays/sec (upper bound): " << aMRays << "\n";
5703 }
5704
208e6839 5705 return 0;
5706}
5707
a577aaab 5708
f0430952 5709//==============================================================================
5710//function : VMemGpu
5711//purpose :
5712//==============================================================================
5713
5714static int VMemGpu (Draw_Interpretor& theDI,
5715 Standard_Integer theArgNb,
5716 const char** theArgVec)
5717{
5718 // get the context
5719 Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5720 if (aContextAIS.IsNull())
5721 {
23fe70ec 5722 Message::SendFail ("Error: no active viewer");
f0430952 5723 return 1;
5724 }
5725
dc3fe572 5726 Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
f0430952 5727 if (aDriver.IsNull())
5728 {
23fe70ec 5729 Message::SendFail ("Error: graphic driver not available");
f0430952 5730 return 1;
5731 }
5732
5733 Standard_Size aFreeBytes = 0;
5734 TCollection_AsciiString anInfo;
5735 if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
5736 {
23fe70ec 5737 Message::SendFail ("Error: information not available");
f0430952 5738 return 1;
5739 }
5740
5741 if (theArgNb > 1 && *theArgVec[1] == 'f')
5742 {
5743 theDI << Standard_Real (aFreeBytes);
5744 }
5745 else
5746 {
5747 theDI << anInfo;
5748 }
5749
5750 return 0;
5751}
5752
85e096c3 5753// ==============================================================================
5754// function : VReadPixel
5755// purpose :
5756// ==============================================================================
5757static int VReadPixel (Draw_Interpretor& theDI,
5758 Standard_Integer theArgNb,
5759 const char** theArgVec)
5760{
5761 // get the active view
5762 Handle(V3d_View) aView = ViewerTest::CurrentView();
5763 if (aView.IsNull())
5764 {
23fe70ec 5765 Message::SendFail ("Error: no active viewer");
85e096c3 5766 return 1;
5767 }
5768 else if (theArgNb < 3)
5769 {
23fe70ec 5770 Message::SendFail() << "Syntax error: wrong number of arguments.\n"
5771 << "Usage: " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]";
85e096c3 5772 return 1;
5773 }
5774
dc858f4c 5775 Image_Format aFormat = Image_Format_RGBA;
5776 Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
692613e5 5777
85e096c3 5778 Standard_Integer aWidth, aHeight;
5779 aView->Window()->Size (aWidth, aHeight);
91322f44 5780 const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
5781 const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
85e096c3 5782 if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
5783 {
23fe70ec 5784 Message::SendFail() << "Error: pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")";
85e096c3 5785 return 1;
5786 }
5787
ba00aab7 5788 bool toShowName = false, toShowHls = false, toShowHex = false, toShow_sRGB = false;
85e096c3 5789 for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
5790 {
dc858f4c 5791 TCollection_AsciiString aParam (theArgVec[anIter]);
5792 aParam.LowerCase();
55c8f0f7 5793 if (aParam == "-rgb"
ba00aab7 5794 || aParam == "rgb"
5795 || aParam == "-srgb"
5796 || aParam == "srgb")
85e096c3 5797 {
dc858f4c 5798 aFormat = Image_Format_RGB;
692613e5 5799 aBufferType = Graphic3d_BT_RGB;
ba00aab7 5800 toShow_sRGB = aParam == "-srgb" || aParam == "srgb";
85e096c3 5801 }
55c8f0f7
BB
5802 else if (aParam == "-hls"
5803 || aParam == "hls")
85e096c3 5804 {
dc858f4c 5805 aFormat = Image_Format_RGB;
692613e5 5806 aBufferType = Graphic3d_BT_RGB;
85e096c3 5807 toShowHls = Standard_True;
5808 }
55c8f0f7
BB
5809 else if (aParam == "-rgbf"
5810 || aParam == "rgbf")
85e096c3 5811 {
dc858f4c 5812 aFormat = Image_Format_RGBF;
692613e5 5813 aBufferType = Graphic3d_BT_RGB;
85e096c3 5814 }
55c8f0f7 5815 else if (aParam == "-rgba"
ba00aab7 5816 || aParam == "rgba"
5817 || aParam == "-srgba"
5818 || aParam == "srgba")
85e096c3 5819 {
dc858f4c 5820 aFormat = Image_Format_RGBA;
692613e5 5821 aBufferType = Graphic3d_BT_RGBA;
ba00aab7 5822 toShow_sRGB = aParam == "-srgba" || aParam == "srgba";
85e096c3 5823 }
55c8f0f7
BB
5824 else if (aParam == "-rgbaf"
5825 || aParam == "rgbaf")
85e096c3 5826 {
dc858f4c 5827 aFormat = Image_Format_RGBAF;
692613e5 5828 aBufferType = Graphic3d_BT_RGBA;
85e096c3 5829 }
55c8f0f7
BB
5830 else if (aParam == "-depth"
5831 || aParam == "depth")
85e096c3 5832 {
dc858f4c 5833 aFormat = Image_Format_GrayF;
692613e5 5834 aBufferType = Graphic3d_BT_Depth;
85e096c3 5835 }
55c8f0f7
BB
5836 else if (aParam == "-name"
5837 || aParam == "name")
85e096c3 5838 {
5839 toShowName = Standard_True;
5840 }
9196ea9d 5841 else if (aParam == "-hex"
5842 || aParam == "hex")
5843 {
5844 toShowHex = Standard_True;
5845 }
55c8f0f7
BB
5846 else
5847 {
23fe70ec 5848 Message::SendFail() << "Syntax error at '" << aParam << "'";
9196ea9d 5849 return 1;
55c8f0f7 5850 }
85e096c3 5851 }
5852
692613e5 5853 Image_PixMap anImage;
5854 if (!anImage.InitTrash (aFormat, aWidth, aHeight))
5855 {
23fe70ec 5856 Message::SendFail ("Error: image allocation failed");
692613e5 5857 return 1;
5858 }
5859 else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
85e096c3 5860 {
23fe70ec 5861 Message::SendFail ("Error: image dump failed");
85e096c3 5862 return 1;
5863 }
5864
68beaa3c 5865 // redirect possible warning messages that could have been added by ToPixMap
5866 // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
5867 // contaminate result of the command
5868 Standard_CString aWarnLog = theDI.Result();
5869 if (aWarnLog != NULL && aWarnLog[0] != '\0')
5870 {
5871 std::cout << aWarnLog << std::endl;
5872 }
5873 theDI.Reset();
5874
ba00aab7 5875 Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY, true);
85e096c3 5876 if (toShowName)
5877 {
692613e5 5878 if (aBufferType == Graphic3d_BT_RGBA)
85e096c3 5879 {
e958a649 5880 theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
85e096c3 5881 }
5882 else
5883 {
e958a649 5884 theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
85e096c3 5885 }
5886 }
9196ea9d 5887 else if (toShowHex)
5888 {
5889 if (aBufferType == Graphic3d_BT_RGBA)
5890 {
5891 theDI << Quantity_ColorRGBA::ColorToHex (aColor);
5892 }
5893 else
5894 {
5895 theDI << Quantity_Color::ColorToHex (aColor.GetRGB());
5896 }
5897 }
85e096c3 5898 else
5899 {
5900 switch (aBufferType)
5901 {
5902 default:
692613e5 5903 case Graphic3d_BT_RGB:
85e096c3 5904 {
5905 if (toShowHls)
5906 {
e958a649 5907 theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
85e096c3 5908 }
ba00aab7 5909 else if (toShow_sRGB)
5910 {
5911 const Graphic3d_Vec4 aColor_sRGB = Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec4 )aColor);
5912 theDI << aColor_sRGB.r() << " " << aColor_sRGB.g() << " " << aColor_sRGB.b();
5913 }
85e096c3 5914 else
5915 {
e958a649 5916 theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
85e096c3 5917 }
5918 break;
5919 }
692613e5 5920 case Graphic3d_BT_RGBA:
85e096c3 5921 {
ba00aab7 5922 const Graphic3d_Vec4 aVec4 = toShow_sRGB ? Quantity_ColorRGBA::Convert_LinearRGB_To_sRGB ((Graphic3d_Vec4 )aColor) : (Graphic3d_Vec4 )aColor;
5923 theDI << aVec4.r() << " " << aVec4.g() << " " << aVec4.b() << " " << aVec4.a();
85e096c3 5924 break;
5925 }
692613e5 5926 case Graphic3d_BT_Depth:
85e096c3 5927 {
e958a649 5928 theDI << aColor.GetRGB().Red();
85e096c3 5929 break;
5930 }
5931 }
5932 }
5933
5934 return 0;
5935}
5936
fd3f6bd0 5937//! Auxiliary presentation for an image plane.
5938class ViewerTest_ImagePrs : public AIS_InteractiveObject
5939{
5940public:
5941 //! Main constructor.
5942 ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
5943 const Standard_Real theWidth,
5944 const Standard_Real theHeight,
5945 const TCollection_AsciiString& theLabel)
5946 : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
5947 {
5948 SetDisplayMode (0);
5949 SetHilightMode (1);
5950 myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
5951 {
5952 myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
5953 const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
5954 Graphic3d_MaterialAspect aMat;
5955 aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
61168418 5956 aMat.SetAmbientColor (Quantity_NOC_BLACK);
5957 aMat.SetDiffuseColor (Quantity_NOC_WHITE);
5958 aMat.SetSpecularColor (Quantity_NOC_BLACK);
5959 aMat.SetEmissiveColor (Quantity_NOC_BLACK);
fd3f6bd0 5960 aFillAspect->SetFrontMaterial (aMat);
633084b8 5961 aFillAspect->SetTextureMap (new Graphic3d_Texture2D (theImage));
fd3f6bd0 5962 aFillAspect->SetTextureMapOn();
5963 }
5964 {
5965 Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
5966 aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
5967 aTextAspect->SetVerticalJustification (Graphic3d_VTA_CENTER);
5968 myDrawer->SetTextAspect (aTextAspect);
5969 }
5970 {
5971 const gp_Dir aNorm (0.0, 0.0, 1.0);
5972 myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
5973 myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
5974 myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
5975 myTris->AddVertex (gp_Pnt(-myWidth * 0.5, myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
5976 myTris->AddVertex (gp_Pnt( myWidth * 0.5, myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
5977 myTris->AddEdge (1);
5978 myTris->AddEdge (2);
5979 myTris->AddEdge (3);
5980 myTris->AddEdge (3);
5981 myTris->AddEdge (2);
5982 myTris->AddEdge (4);
5983
5984 myRect = new Graphic3d_ArrayOfPolylines (4);
5985 myRect->AddVertex (myTris->Vertice (1));
5986 myRect->AddVertex (myTris->Vertice (3));
5987 myRect->AddVertex (myTris->Vertice (4));
5988 myRect->AddVertex (myTris->Vertice (2));
5989 }
5990 }
5991
5992 //! Returns TRUE for accepted display modes.
5993 virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
5994
5995 //! Compute presentation.
decbff0d 5996 virtual void Compute (const Handle(PrsMgr_PresentationManager)& ,
5997 const Handle(Prs3d_Presentation)& thePrs,
5998 const Standard_Integer theMode) Standard_OVERRIDE
fd3f6bd0 5999 {
6000 switch (theMode)
6001 {
6002 case 0:
6003 {
6004 Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6005 aGroup->AddPrimitiveArray (myTris);
6006 aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
6007 aGroup->AddPrimitiveArray (myRect);
6008 aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6009 return;
6010 }
6011 case 1:
6012 {
6013 Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
6014 Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
6015 aGroup->AddPrimitiveArray (myRect);
6016 aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
6017 return;
6018 }
6019 }
6020 }
6021
6022 //! Compute selection.
6023 virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
6024 {
6025 if (theMode == 0)
6026 {
6027 Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
6028 Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
6029 aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
6030 theSel->Add (aSensitive);
6031 }
6032 }
6033
6034private:
6035 Handle(Graphic3d_ArrayOfTriangles) myTris;
6036 Handle(Graphic3d_ArrayOfPolylines) myRect;
6037 TCollection_AsciiString myLabel;
6038 Standard_Real myWidth;
6039 Standard_Real myHeight;
6040};
6041
692613e5 6042//==============================================================================
6043//function : VDiffImage
6044//purpose : The draw-command compares two images.
6045//==============================================================================
6046
6047static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
6048{
fd3f6bd0 6049 if (theArgNb < 3)
692613e5 6050 {
23fe70ec 6051 Message::SendFail ("Syntax error: not enough arguments");
692613e5 6052 return 1;
6053 }
6054
fd3f6bd0 6055 Standard_Integer anArgIter = 1;
6056 TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
6057 TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
6058 TCollection_AsciiString aDiffImagePath;
6059 Standard_Real aTolColor = -1.0;
6060 Standard_Integer toBlackWhite = -1;
6061 Standard_Integer isBorderFilterOn = -1;
6062 Standard_Boolean isOldSyntax = Standard_False;
6063 TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
6064 for (; anArgIter < theArgNb; ++anArgIter)
6065 {
6066 TCollection_AsciiString anArg (theArgVec[anArgIter]);
6067 anArg.LowerCase();
6068 if (anArgIter + 1 < theArgNb
6069 && (anArg == "-toleranceofcolor"
6070 || anArg == "-tolerancecolor"
6071 || anArg == "-tolerance"
6072 || anArg == "-toler"))
6073 {
6074 aTolColor = Atof (theArgVec[++anArgIter]);
6075 if (aTolColor < 0.0 || aTolColor > 1.0)
6076 {
23fe70ec 6077 Message::SendFail() << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'";
fd3f6bd0 6078 return 1;
6079 }
6080 }
6081 else if (anArg == "-blackwhite")
6082 {
6083 Standard_Boolean toEnable = Standard_True;
6084 if (anArgIter + 1 < theArgNb
dae2a922 6085 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
fd3f6bd0 6086 {
6087 ++anArgIter;
6088 }
6089 toBlackWhite = toEnable ? 1 : 0;
6090 }
6091 else if (anArg == "-borderfilter")
6092 {
6093 Standard_Boolean toEnable = Standard_True;
6094 if (anArgIter + 1 < theArgNb
dae2a922 6095 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
fd3f6bd0 6096 {
6097 ++anArgIter;
6098 }
6099 isBorderFilterOn = toEnable ? 1 : 0;
6100 }
6101 else if (anArg == "-exitonclose")
6102 {
49582f9d 6103 ViewerTest_EventManager::ToExitOnCloseView() = true;
fd3f6bd0 6104 if (anArgIter + 1 < theArgNb
dae2a922 6105 && Draw::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToExitOnCloseView()))
fd3f6bd0 6106 {
6107 ++anArgIter;
6108 }
6109 }
6110 else if (anArg == "-closeonescape"
6111 || anArg == "-closeonesc")
6112 {
49582f9d 6113 ViewerTest_EventManager::ToCloseViewOnEscape() = true;
fd3f6bd0 6114 if (anArgIter + 1 < theArgNb
dae2a922 6115 && Draw::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
fd3f6bd0 6116 {
6117 ++anArgIter;
6118 }
6119 }
6120 else if (anArgIter + 3 < theArgNb
6121 && anArg == "-display")
6122 {
6123 aViewName = theArgVec[++anArgIter];
6124 aPrsNameRef = theArgVec[++anArgIter];
6125 aPrsNameNew = theArgVec[++anArgIter];
6126 if (anArgIter + 1 < theArgNb
6127 && *theArgVec[anArgIter + 1] != '-')
6128 {
6129 aPrsNameDiff = theArgVec[++anArgIter];
6130 }
6131 }
6132 else if (aTolColor < 0.0
d45edf24 6133 && anArg.IsRealValue (Standard_True))
fd3f6bd0 6134 {
6135 isOldSyntax = Standard_True;
6136 aTolColor = anArg.RealValue();
6137 if (aTolColor < 0.0 || aTolColor > 1.0)
6138 {
23fe70ec 6139 Message::SendFail() << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'";
fd3f6bd0 6140 return 1;
6141 }
6142 }
6143 else if (isOldSyntax
6144 && toBlackWhite == -1
6145 && (anArg == "0" || anArg == "1"))
6146 {
6147 toBlackWhite = anArg == "1" ? 1 : 0;
6148 }
6149 else if (isOldSyntax
6150 && isBorderFilterOn == -1
6151 && (anArg == "0" || anArg == "1"))
6152 {
6153 isBorderFilterOn = anArg == "1" ? 1 : 0;
6154 }
6155 else if (aDiffImagePath.IsEmpty())
6156 {
6157 aDiffImagePath = theArgVec[anArgIter];
6158 }
6159 else
6160 {
23fe70ec 6161 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
fd3f6bd0 6162 return 1;
6163 }
6164 }
692613e5 6165
fd3f6bd0 6166 Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
6167 Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
6168 if (!anImgRef->Load (anImgPathRef))
6169 {
23fe70ec 6170 Message::SendFail() << "Error: image file '" << anImgPathRef << "' cannot be read";
fd3f6bd0 6171 return 1;
6172 }
6173 if (!anImgNew->Load (anImgPathNew))
6174 {
23fe70ec 6175 Message::SendFail() << "Error: image file '" << anImgPathNew << "' cannot be read";
fd3f6bd0 6176 return 1;
6177 }
692613e5 6178
6179 // compare the images
6180 Image_Diff aComparer;
fd3f6bd0 6181 Standard_Integer aDiffColorsNb = -1;
6182 if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
692613e5 6183 {
fd3f6bd0 6184 aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
6185 aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
6186 aDiffColorsNb = aComparer.Compare();
6187 theDI << aDiffColorsNb << "\n";
692613e5 6188 }
6189
692613e5 6190 // save image of difference
fd3f6bd0 6191 Handle(Image_AlienPixMap) aDiff;
6192 if (aDiffColorsNb > 0
6193 && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
6194 {
6195 aDiff = new Image_AlienPixMap();
6196 if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
6197 {
23fe70ec 6198 Message::SendFail() << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY();
fd3f6bd0 6199 return 1;
6200 }
6201 aComparer.SaveDiffImage (*aDiff);
6202 if (!aDiffImagePath.IsEmpty()
6203 && !aDiff->Save (aDiffImagePath))
6204 {
23fe70ec 6205 Message::SendFail() << "Error: diff image file '" << aDiffImagePath << "' cannot be written";
fd3f6bd0 6206 return 1;
6207 }
6208 }
6209
6210 if (aViewName.IsEmpty())
6211 {
6212 return 0;
6213 }
6214
6215 ViewerTest_Names aViewNames (aViewName);
6216 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
6217 {
6218 TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
6219 theDI.Eval (aCommand.ToCString());
6220 }
6221
879768fb 6222 ViewerTest_VinitParams aParams;
6223 aParams.ViewName = aViewName;
6224 aParams.Size.x() = float(anImgRef->SizeX() * 2);
6225 aParams.Size.y() = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
6226 ? float(anImgRef->SizeY() * 2)
6227 : float(anImgRef->SizeY());
6228 TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aParams);
fd3f6bd0 6229
6230 Standard_Real aRatio = anImgRef->Ratio();
6231 Standard_Real aSizeX = 1.0;
6232 Standard_Real aSizeY = aSizeX / aRatio;
692613e5 6233 {
fd3f6bd0 6234 OSD_Path aPath (anImgPathRef);
6235 TCollection_AsciiString aLabelRef;
6236 if (!aPath.Name().IsEmpty())
6237 {
6238 aLabelRef = aPath.Name() + aPath.Extension();
6239 }
6240 aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
6241
6242 Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
6243 gp_Trsf aTrsfRef;
6244 aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
6245 anImgRefPrs->SetLocalTransformation (aTrsfRef);
6246 ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
692613e5 6247 }
fd3f6bd0 6248 {
6249 OSD_Path aPath (anImgPathNew);
6250 TCollection_AsciiString aLabelNew;
6251 if (!aPath.Name().IsEmpty())
6252 {
6253 aLabelNew = aPath.Name() + aPath.Extension();
6254 }
6255 aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
692613e5 6256
fd3f6bd0 6257 Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
6258 gp_Trsf aTrsfRef;
6259 aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
6260 anImgNewPrs->SetLocalTransformation (aTrsfRef);
6261 ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
6262 }
6263 Handle(ViewerTest_ImagePrs) anImgDiffPrs;
6264 if (!aDiff.IsNull())
6265 {
6266 anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
6267 gp_Trsf aTrsfDiff;
6268 aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
6269 anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
6270 }
6271 if (!aPrsNameDiff.IsEmpty())
6272 {
6273 ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
6274 }
6275 ViewerTest::CurrentView()->SetProj (V3d_Zpos);
6276 ViewerTest::CurrentView()->FitAll();
692613e5 6277 return 0;
6278}
6279
4754e164 6280//=======================================================================
6281//function : VSelect
6282//purpose : Emulates different types of selection by mouse:
6283// 1) single click selection
6284// 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
6285// 3) selection with polygon having corners at
dc3fe572 6286// pixel positions (x1,y1),...,(xn,yn)
4754e164 6287// 4) any of these selections with shift button pressed
6288//=======================================================================
49582f9d 6289static Standard_Integer VSelect (Draw_Interpretor& ,
6290 Standard_Integer theNbArgs,
6291 const char** theArgVec)
4754e164 6292{
49582f9d 6293 const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
6294 if (aCtx.IsNull())
4754e164 6295 {
23fe70ec 6296 Message::SendFail ("Error: no active viewer");
4754e164 6297 return 1;
6298 }
2157d6ac 6299
49582f9d 6300 NCollection_Sequence<Graphic3d_Vec2i> aPnts;
75cf8250 6301 bool toAllowOverlap = false;
6302 AIS_SelectionScheme aSelScheme = AIS_SelectionScheme_Replace;
49582f9d 6303 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2157d6ac 6304 {
49582f9d 6305 TCollection_AsciiString anArg (theArgVec[anArgIter]);
6306 anArg.LowerCase();
6307 if (anArg == "-allowoverlap")
6308 {
6309 toAllowOverlap = true;
6310 if (anArgIter + 1 < theNbArgs
dae2a922 6311 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toAllowOverlap))
49582f9d 6312 {
6313 ++anArgIter;
6314 }
6315 }
e3d4b879 6316 else if (anArg == "-replace")
6317 {
6318 aSelScheme = AIS_SelectionScheme_Replace;
6319 }
e76471b5 6320 else if (anArg == "-replaceextra")
6321 {
6322 aSelScheme = AIS_SelectionScheme_ReplaceExtra;
6323 }
e3d4b879 6324 else if (anArg == "-xor"
6325 || anArg == "-shift")
6326 {
6327 aSelScheme = AIS_SelectionScheme_XOR;
6328 }
6329 else if (anArg == "-add")
6330 {
6331 aSelScheme = AIS_SelectionScheme_Add;
6332 }
6333 else if (anArg == "-remove")
6334 {
6335 aSelScheme = AIS_SelectionScheme_Remove;
6336 }
49582f9d 6337 else if (anArgIter + 1 < theNbArgs
6338 && anArg.IsIntegerValue()
6339 && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
2157d6ac 6340 {
49582f9d 6341 const TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
6342 aPnts.Append (Graphic3d_Vec2i (anArg.IntegerValue(), anArgNext.IntegerValue()));
6343 }
6344 else if (anArgIter + 1 == theNbArgs
6345 && anArg.IsIntegerValue())
6346 {
75cf8250 6347 if (anArg.IntegerValue() == 1)
6348 {
6349 aSelScheme = AIS_SelectionScheme_XOR;
6350 }
49582f9d 6351 }
6352 else
6353 {
23fe70ec 6354 Message::SendFail() << "Syntax error at '" << anArg << "'";
2157d6ac 6355 return 1;
6356 }
49582f9d 6357 }
a24a7821 6358
49582f9d 6359 if (toAllowOverlap)
6360 {
6361 aCtx->MainSelector()->AllowOverlapDetection (toAllowOverlap);
2157d6ac 6362 }
6363
4754e164 6364 Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
49582f9d 6365 if (aPnts.IsEmpty())
4754e164 6366 {
75cf8250 6367 aCtx->SelectDetected (aSelScheme);
49582f9d 6368 aCtx->CurrentViewer()->Invalidate();
4754e164 6369 }
49582f9d 6370 else if (aPnts.Length() == 2)
4754e164 6371 {
49582f9d 6372 if (toAllowOverlap
6373 && aPnts.First().y() < aPnts.Last().y())
6374 {
6375 std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
6376 }
6377 else if (!toAllowOverlap
6378 && aPnts.First().y() > aPnts.Last().y())
6379 {
6380 std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
6381 }
e3d4b879 6382
6383 aCurrentEventManager->SelectInViewer (aPnts, aSelScheme);
4754e164 6384 }
6385 else
6386 {
e3d4b879 6387 aCurrentEventManager->SelectInViewer (aPnts, aSelScheme);
4754e164 6388 }
49582f9d 6389 aCurrentEventManager->FlushViewEvents (aCtx, ViewerTest::CurrentView(), true);
4754e164 6390 return 0;
6391}
6392
6393//=======================================================================
6394//function : VMoveTo
dc3fe572 6395//purpose : Emulates cursor movement to defined pixel position
4754e164 6396//=======================================================================
1e756cb9 6397static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
8a590580 6398 Standard_Integer theNbArgs,
6399 const char** theArgVec)
4754e164 6400{
8a590580 6401 const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
6402 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
6403 if (aContext.IsNull())
4754e164 6404 {
23fe70ec 6405 Message::SendFail ("Error: no active viewer");
4754e164 6406 return 1;
6407 }
6408
8a590580 6409 Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
6410 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
4754e164 6411 {
8a590580 6412 TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
6413 anArgStr.LowerCase();
6414 if (anArgStr == "-reset"
6415 || anArgStr == "-clear")
6416 {
6417 if (anArgIter + 1 < theNbArgs)
6418 {
23fe70ec 6419 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter + 1] << "'";
8a590580 6420 return 1;
6421 }
6422
5634c81a 6423 const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->IsGridActive()
8a590580 6424 && aContext->CurrentViewer()->GridEcho();
6425 if (toEchoGrid)
6426 {
6427 aContext->CurrentViewer()->HideGridEcho (aView);
6428 }
6429 if (aContext->ClearDetected() || toEchoGrid)
6430 {
6431 aContext->CurrentViewer()->RedrawImmediate();
6432 }
6433 return 0;
6434 }
6435 else if (aMousePos.x() == IntegerLast()
6436 && anArgStr.IsIntegerValue())
6437 {
6438 aMousePos.x() = anArgStr.IntegerValue();
6439 }
6440 else if (aMousePos.y() == IntegerLast()
6441 && anArgStr.IsIntegerValue())
6442 {
6443 aMousePos.y() = anArgStr.IntegerValue();
6444 }
6445 else
6446 {
23fe70ec 6447 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
8a590580 6448 return 1;
6449 }
6450 }
6451
6452 if (aMousePos.x() == IntegerLast()
6453 || aMousePos.y() == IntegerLast())
6454 {
23fe70ec 6455 Message::SendFail ("Syntax error: wrong number of arguments");
4754e164 6456 return 1;
6457 }
8a590580 6458
49582f9d 6459 ViewerTest::CurrentEventManager()->ResetPreviousMoveTo();
6460 ViewerTest::CurrentEventManager()->UpdateMousePosition (aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
6461 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
6462
1e756cb9 6463 gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
6464 const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
6465 for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
6466 {
6467 if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
6468 {
6469 aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
6470 break;
6471 }
6472 }
6473 theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
4754e164 6474 return 0;
6475}
6476
0461e7fd 6477//=======================================================================
6478//function : VSelectByAxis
6479//purpose :
6480//=======================================================================
6481static Standard_Integer VSelectByAxis (Draw_Interpretor& theDI,
6482 Standard_Integer theNbArgs,
6483 const char** theArgVec)
6484{
6485 const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
6486 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
6487 if (aContext.IsNull())
6488 {
6489 Message::SendFail ("Error: no active viewer");
6490 return 1;
6491 }
6492
6493 TCollection_AsciiString aName;
6494 gp_XYZ anAxisLocation(RealLast(), RealLast(), RealLast());
6495 gp_XYZ anAxisDirection(RealLast(), RealLast(), RealLast());
6496 Standard_Boolean isOnlyTop = true;
6497 Standard_Boolean toShowNormal = false;
6498 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
6499 {
6500 TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
6501 anArgStr.LowerCase();
6502 if (anArgStr == "-display")
6503 {
6504 if (anArgIter + 1 >= theNbArgs)
6505 {
6506 Message::SendFail() << "Syntax error at argument '" << anArgStr << "'";
6507 return 1;
6508 }
6509 aName = theArgVec[++anArgIter];
6510 }
6511 else if (anArgStr == "-onlytop")
6512 {
6513 isOnlyTop = true;
6514 if (anArgIter + 1 < theNbArgs
6515 && Draw::ParseOnOff (theArgVec[anArgIter + 1], isOnlyTop))
6516 {
6517 ++anArgIter;
6518 }
6519 }
6520 else if (anArgStr == "-shownormal")
6521 {
6522 toShowNormal = true;
6523 if (anArgIter + 1 < theNbArgs
6524 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toShowNormal))
6525 {
6526 ++anArgIter;
6527 }
6528 }
6529 else if (Precision::IsInfinite(anAxisLocation.X())
6530 && anArgStr.IsRealValue())
6531 {
6532 anAxisLocation.SetX (anArgStr.RealValue());
6533 }
6534 else if (Precision::IsInfinite(anAxisLocation.Y())
6535 && anArgStr.IsRealValue())
6536 {
6537 anAxisLocation.SetY (anArgStr.RealValue());
6538 }
6539 else if (Precision::IsInfinite(anAxisLocation.Z())
6540 && anArgStr.IsRealValue())
6541 {
6542 anAxisLocation.SetZ (anArgStr.RealValue());
6543 }
6544 else if (Precision::IsInfinite(anAxisDirection.X())
6545 && anArgStr.IsRealValue())
6546 {
6547 anAxisDirection.SetX (anArgStr.RealValue());
6548 }
6549 else if (Precision::IsInfinite(anAxisDirection.Y())
6550 && anArgStr.IsRealValue())
6551 {
6552 anAxisDirection.SetY (anArgStr.RealValue());
6553 }
6554 else if (Precision::IsInfinite(anAxisDirection.Z())
6555 && anArgStr.IsRealValue())
6556 {
6557 anAxisDirection.SetZ (anArgStr.RealValue());
6558 }
6559 else
6560 {
6561 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
6562 return 1;
6563 }
6564 }
6565
6566 if (Precision::IsInfinite (anAxisLocation.X()) ||
6567 Precision::IsInfinite (anAxisLocation.Y()) ||
6568 Precision::IsInfinite (anAxisLocation.Z()) ||
6569 Precision::IsInfinite (anAxisDirection.X()) ||
6570 Precision::IsInfinite (anAxisDirection.Y()) ||
6571 Precision::IsInfinite (anAxisDirection.Z()))
6572 {
6573 Message::SendFail() << "Invalid axis location and direction";
6574 return 1;
6575 }
6576
6577 gp_Ax1 anAxis(anAxisLocation, anAxisDirection);
6578 gp_Pnt aTopPnt;
6579 if (!ViewerTest::CurrentEventManager()->PickAxis (aTopPnt, aContext, aView, anAxis))
6580 {
6581 theDI << "There are no any intersections with this axis.";
6582 return 0;
6583 }
6584 NCollection_Sequence<gp_Pnt> aPoints;
6585 NCollection_Sequence<Graphic3d_Vec3> aNormals;
6586 NCollection_Sequence<Standard_Real> aNormalLengths;
6587 for (Standard_Integer aPickIter = 1; aPickIter <= aContext->MainSelector()->NbPicked(); ++aPickIter)
6588 {
6589 const SelectMgr_SortCriterion& aPickedData = aContext->MainSelector()->PickedData (aPickIter);
6590 aPoints.Append (aPickedData.Point);
6591 aNormals.Append (aPickedData.Normal);
6592 Standard_Real aNormalLength = 1.0;
6593 if (!aPickedData.Entity.IsNull())
6594 {
6595 aNormalLength = 0.2 * aPickedData.Entity->BoundingBox().Size().maxComp();
6596 }
6597 aNormalLengths.Append (aNormalLength);
6598 }
6599 if (!aName.IsEmpty())
6600 {
6601 Standard_Boolean wasAuto = aContext->GetAutoActivateSelection();
6602 aContext->SetAutoActivateSelection (false);
6603
6604 // Display axis
6605 Quantity_Color anAxisColor = Quantity_NOC_GREEN;
6606 Handle(Geom_Axis2Placement) anAx2Axis =
6607 new Geom_Axis2Placement (gp_Ax2(anAxisLocation, anAxisDirection));
1f3c5058 6608 Handle(AIS_Axis) anAISAxis = new AIS_Axis (gp_Ax1 (anAxisLocation, anAxisDirection));
6609 anAISAxis->SetColor (anAxisColor);
6610 ViewerTest::Display (TCollection_AsciiString (aName) + "_axis", anAISAxis, false);
0461e7fd 6611
6612 // Display axis start point
6613 Handle(AIS_Point) anAISStartPnt = new AIS_Point (new Geom_CartesianPoint (anAxisLocation));
6614 anAISStartPnt->SetMarker (Aspect_TOM_O);
6615 anAISStartPnt->SetColor (anAxisColor);
6616 ViewerTest::Display (TCollection_AsciiString(aName) + "_start", anAISStartPnt, false);
6617
6618 Standard_Integer anIndex = 0;
6619 for (NCollection_Sequence<gp_Pnt>::Iterator aPntIter(aPoints); aPntIter.More(); aPntIter.Next(), anIndex++)
6620 {
6621 const gp_Pnt& aPoint = aPntIter.Value();
6622
6623 // Display normals in intersection points
6624 if (toShowNormal)
6625 {
6626 const Graphic3d_Vec3& aNormal = aNormals.Value (anIndex + 1);
6627 Standard_Real aNormalLength = aNormalLengths.Value (anIndex + 1);
6628 if (aNormal.SquareModulus() > ShortRealEpsilon())
6629 {
1f3c5058 6630 gp_Dir aNormalDir ((Standard_Real)aNormal.x(), (Standard_Real)aNormal.y(), (Standard_Real)aNormal.z());
6631 Handle(AIS_Axis) anAISNormal = new AIS_Axis (gp_Ax1 (aPoint, aNormalDir), aNormalLength);
0461e7fd 6632 anAISNormal->SetColor (Quantity_NOC_BLUE);
0461e7fd 6633 anAISNormal->SetInfiniteState (false);
6634 ViewerTest::Display (TCollection_AsciiString(aName) + "_normal_" + anIndex, anAISNormal, false);
6635 }
6636 }
6637
6638 // Display intersection points
6639 Handle(Geom_CartesianPoint) anIntersectPnt = new Geom_CartesianPoint (aPoint);
6640 Handle(AIS_Point) anAISIntersectPoint = new AIS_Point (anIntersectPnt);
6641 anAISIntersectPoint->SetMarker (Aspect_TOM_PLUS);
6642 anAISIntersectPoint->SetColor (Quantity_NOC_RED);
6643 ViewerTest::Display (TCollection_AsciiString(aName) + "_intersect_" + anIndex, anAISIntersectPoint, true);
6644 }
6645
6646 aContext->SetAutoActivateSelection (wasAuto);
6647 }
6648
6649 Standard_Integer anIndex = 0;
6650 for (NCollection_Sequence<gp_Pnt>::Iterator anIter(aPoints); anIter.More(); anIter.Next(), anIndex++)
6651 {
6652 const gp_Pnt& aPnt = anIter.Value();
6653 theDI << aPnt.X() << " " << aPnt.Y() << " " << aPnt.Z() << "\n";
6654 }
6655 return 0;
6656}
6657
1beb58d7 6658namespace
6659{
6660 //! Global map storing all animations registered in ViewerTest.
6661 static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
6662
6663 //! The animation calling the Draw Harness command.
6664 class ViewerTest_AnimationProc : public AIS_Animation
6665 {
8f709595 6666 DEFINE_STANDARD_RTTI_INLINE(ViewerTest_AnimationProc, AIS_Animation)
1beb58d7 6667 public:
6668
6669 //! Main constructor.
6670 ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
6671 Draw_Interpretor* theDI,
6672 const TCollection_AsciiString& theCommand)
6673 : AIS_Animation (theAnimationName),
6674 myDrawInter(theDI),
6675 myCommand (theCommand)
6676 {
6677 //
6678 }
6679
6680 protected:
6681
6682 //! Evaluate the command.
6683 virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
6684 {
6685 TCollection_AsciiString aCmd = myCommand;
6686 replace (aCmd, "%pts", TCollection_AsciiString(theProgress.Pts));
6687 replace (aCmd, "%localpts", TCollection_AsciiString(theProgress.LocalPts));
6688 replace (aCmd, "%ptslocal", TCollection_AsciiString(theProgress.LocalPts));
6689 replace (aCmd, "%normalized", TCollection_AsciiString(theProgress.LocalNormalized));
6690 replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
6691 myDrawInter->Eval (aCmd.ToCString());
6692 }
6693
6694 //! Find the keyword in the command and replace it with value.
6695 //! @return the position of the keyword to pass value
6696 void replace (TCollection_AsciiString& theCmd,
6697 const TCollection_AsciiString& theKey,
6698 const TCollection_AsciiString& theVal)
6699 {
6700 TCollection_AsciiString aCmd (theCmd);
6701 aCmd.LowerCase();
6702 const Standard_Integer aPos = aCmd.Search (theKey);
6703 if (aPos == -1)
6704 {
6705 return;
6706 }
6707
6708 TCollection_AsciiString aPart1, aPart2;
6709 Standard_Integer aPart1To = aPos - 1;
6710 if (aPart1To >= 1
6711 && aPart1To <= theCmd.Length())
6712 {
6713 aPart1 = theCmd.SubString (1, aPart1To);
6714 }
6715
6716 Standard_Integer aPart2From = aPos + theKey.Length();
6717 if (aPart2From >= 1
6718 && aPart2From <= theCmd.Length())
6719 {
6720 aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
6721 }
6722
6723 theCmd = aPart1 + theVal + aPart2;
6724 }
6725
6726 protected:
6727
6728 Draw_Interpretor* myDrawInter;
6729 TCollection_AsciiString myCommand;
6730
6731 };
6732
8f709595 6733 //! Auxiliary animation holder.
6734 class ViewerTest_AnimationHolder : public AIS_AnimationCamera
6735 {
6736 DEFINE_STANDARD_RTTI_INLINE(ViewerTest_AnimationHolder, AIS_AnimationCamera)
6737 public:
6738 ViewerTest_AnimationHolder (const Handle(AIS_Animation)& theAnim,
6739 const Handle(V3d_View)& theView,
6740 const Standard_Boolean theIsFreeView)
6741 : AIS_AnimationCamera ("ViewerTest_AnimationHolder", Handle(V3d_View)())
6742 {
6743 if (theAnim->Timer().IsNull())
6744 {
6745 theAnim->SetTimer (new Media_Timer());
6746 }
6747 myTimer = theAnim->Timer();
6748 myView = theView;
6749 if (theIsFreeView)
6750 {
6751 myCamStart = new Graphic3d_Camera (theView->Camera());
6752 }
6753 Add (theAnim);
6754 }
6755
6756 //! Start playback.
6757 virtual void StartTimer (const Standard_Real theStartPts,
6758 const Standard_Real thePlaySpeed,
6759 const Standard_Boolean theToUpdate,
6760 const Standard_Boolean theToStopTimer) Standard_OVERRIDE
6761 {
6762 base_type::StartTimer (theStartPts, thePlaySpeed, theToUpdate, theToStopTimer);
6763 if (theToStopTimer)
6764 {
6765 abortPlayback();
6766 }
6767 }
6768
6769 //! Pause animation.
6770 virtual void Pause() Standard_OVERRIDE
6771 {
6772 myState = AnimationState_Paused;
6773 // default implementation would stop all children,
6774 // but we want to keep wrapped animation paused
6775 myAnimations.First()->Pause();
6776 abortPlayback();
6777 }
6778
6779 //! Stop animation.
6780 virtual void Stop() Standard_OVERRIDE
6781 {
6782 base_type::Stop();
6783 abortPlayback();
6784 }
6785
6786 //! Process one step of the animation according to the input time progress, including all children.
6787 virtual void updateWithChildren (const AIS_AnimationProgress& thePosition) Standard_OVERRIDE
6788 {
6789 Handle(V3d_View) aView = myView;
6790 if (!aView.IsNull()
6791 && !myCamStart.IsNull())
6792 {
6793 myCamStart->Copy (aView->Camera());
6794 }
6795 base_type::updateWithChildren (thePosition);
6796 if (!aView.IsNull()
6797 && !myCamStart.IsNull())
6798 {
6799 aView->Camera()->Copy (myCamStart);
6800 }
6801 }
6802 private:
6803 void abortPlayback()
6804 {
6805 if (!myView.IsNull())
6806 {
6807 myView.Nullify();
6808 }
6809 }
6810 };
6811
1beb58d7 6812 //! Replace the animation with the new one.
6813 static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
6814 Handle(AIS_Animation)& theAnimation,
6815 const Handle(AIS_Animation)& theAnimationNew)
6816 {
6817 theAnimationNew->CopyFrom (theAnimation);
6818 if (!theParentAnimation.IsNull())
6819 {
6820 theParentAnimation->Replace (theAnimation, theAnimationNew);
6821 }
6822 else
6823 {
6824 ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
6825 ViewerTest_AnimationTimelineMap.Bind (theAnimationNew->Name(), theAnimationNew);
6826 }
6827 theAnimation = theAnimationNew;
6828 }
6829
6830 //! Parse the point.
6831 static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
6832 {
6833 const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
d45edf24 6834 if (!anXYZ[0].IsRealValue (Standard_True)
6835 || !anXYZ[1].IsRealValue (Standard_True)
6836 || !anXYZ[2].IsRealValue (Standard_True))
1beb58d7 6837 {
6838 return Standard_False;
6839 }
6840
6841 thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
6842 return Standard_True;
6843 }
6844
6845 //! Parse the quaternion.
6846 static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
6847 {
6848 const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
d45edf24 6849 if (!anXYZW[0].IsRealValue (Standard_True)
6850 || !anXYZW[1].IsRealValue (Standard_True)
6851 || !anXYZW[2].IsRealValue (Standard_True)
6852 || !anXYZW[3].IsRealValue (Standard_True))
1beb58d7 6853 {
6854 return Standard_False;
6855 }
6856
6857 theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
6858 return Standard_True;
6859 }
6860
08f8a185 6861 //! Auxiliary class for flipping image upside-down.
6862 class ImageFlipper
6863 {
6864 public:
6865
6866 //! Empty constructor.
6867 ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
6868
6869 //! Perform flipping.
6870 Standard_Boolean FlipY (Image_PixMap& theImage)
6871 {
6872 if (theImage.IsEmpty()
6873 || theImage.SizeX() == 0
6874 || theImage.SizeY() == 0)
6875 {
6876 return Standard_False;
6877 }
6878
6879 const Standard_Size aRowSize = theImage.SizeRowBytes();
6880 if (myTmp.Size() < aRowSize
6881 && !myTmp.Allocate (aRowSize))
6882 {
6883 return Standard_False;
6884 }
6885
6886 // for odd height middle row should be left as is
6887 Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
6888 for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
6889 {
6890 Standard_Byte* aTop = theImage.ChangeRow (aRowT);
6891 Standard_Byte* aBot = theImage.ChangeRow (aRowB);
6892 memcpy (myTmp.ChangeData(), aTop, aRowSize);
6893 memcpy (aTop, aBot, aRowSize);
6894 memcpy (aBot, myTmp.Data(), aRowSize);
6895 }
6896 return Standard_True;
6897 }
6898
6899 private:
6900 NCollection_Buffer myTmp;
6901 };
6902
1beb58d7 6903}
6904
197ac94e 6905//=================================================================================================
4754e164 6906//function : VViewParams
dc3fe572 6907//purpose : Gets or sets AIS View characteristics
197ac94e 6908//=================================================================================================
6909static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
4754e164 6910{
1beb58d7 6911 Handle(V3d_View) aView = ViewerTest::CurrentView();
6912 if (aView.IsNull())
4754e164 6913 {
23fe70ec 6914 Message::SendFail ("Error: no active viewer");
4754e164 6915 return 1;
6916 }
197ac94e 6917
1beb58d7 6918 Standard_Boolean toSetProj = Standard_False;
6919 Standard_Boolean toSetUp = Standard_False;
6920 Standard_Boolean toSetAt = Standard_False;
6921 Standard_Boolean toSetEye = Standard_False;
6922 Standard_Boolean toSetScale = Standard_False;
6923 Standard_Boolean toSetSize = Standard_False;
6924 Standard_Boolean toSetCenter2d = Standard_False;
ee2be2a8 6925 Standard_Real aViewScale = aView->Scale();
168c27c6 6926 Standard_Real aViewAspect = aView->Camera()->Aspect();
ee2be2a8 6927 Standard_Real aViewSize = 1.0;
1beb58d7 6928 Graphic3d_Vec2i aCenter2d;
6929 gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
6930 aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
6931 aView->Up (aViewUp .ChangeCoord (1), aViewUp .ChangeCoord (2), aViewUp .ChangeCoord (3));
6932 aView->At (aViewAt .ChangeCoord (1), aViewAt .ChangeCoord (2), aViewAt .ChangeCoord (3));
6933 aView->Eye (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
168c27c6 6934 const Graphic3d_Mat4d& anOrientMat = aView->Camera()->OrientationMatrix();
6935 const Graphic3d_Mat4d& aProjMat = aView->Camera()->ProjectionMatrix();
197ac94e 6936 if (theArgsNb == 1)
4754e164 6937 {
197ac94e 6938 // print all of the available view parameters
1beb58d7 6939 char aText[4096];
6940 Sprintf (aText,
168c27c6 6941 "Scale: %g\n"
6942 "Aspect: %g\n"
6943 "Proj: %12g %12g %12g\n"
6944 "Up: %12g %12g %12g\n"
6945 "At: %12g %12g %12g\n"
6946 "Eye: %12g %12g %12g\n"
6947 "OrientMat: %12g %12g %12g %12g\n"
6948 " %12g %12g %12g %12g\n"
6949 " %12g %12g %12g %12g\n"
6950 " %12g %12g %12g %12g\n"
6951 "ProjMat: %12g %12g %12g %12g\n"
6952 " %12g %12g %12g %12g\n"
6953 " %12g %12g %12g %12g\n"
6954 " %12g %12g %12g %12g\n",
6955 aViewScale, aViewAspect,
1beb58d7 6956 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6957 aViewUp.X(), aViewUp.Y(), aViewUp.Z(),
6958 aViewAt.X(), aViewAt.Y(), aViewAt.Z(),
168c27c6 6959 aViewEye.X(), aViewEye.Y(), aViewEye.Z(),
6960 anOrientMat.GetValue (0, 0), anOrientMat.GetValue (0, 1), anOrientMat.GetValue (0, 2), anOrientMat.GetValue (0, 3),
6961 anOrientMat.GetValue (1, 0), anOrientMat.GetValue (1, 1), anOrientMat.GetValue (1, 2), anOrientMat.GetValue (1, 3),
6962 anOrientMat.GetValue (2, 0), anOrientMat.GetValue (2, 1), anOrientMat.GetValue (2, 2), anOrientMat.GetValue (2, 3),
6963 anOrientMat.GetValue (3, 0), anOrientMat.GetValue (3, 1), anOrientMat.GetValue (3, 2), anOrientMat.GetValue (3, 3),
6964 aProjMat.GetValue (0, 0), aProjMat.GetValue (0, 1), aProjMat.GetValue (0, 2), aProjMat.GetValue (0, 3),
6965 aProjMat.GetValue (1, 0), aProjMat.GetValue (1, 1), aProjMat.GetValue (1, 2), aProjMat.GetValue (1, 3),
6966 aProjMat.GetValue (2, 0), aProjMat.GetValue (2, 1), aProjMat.GetValue (2, 2), aProjMat.GetValue (2, 3),
6967 aProjMat.GetValue (3, 0), aProjMat.GetValue (3, 1), aProjMat.GetValue (3, 2), aProjMat.GetValue (3, 3));
1beb58d7 6968 theDi << aText;
197ac94e 6969 return 0;
4754e164 6970 }
197ac94e 6971
1beb58d7 6972 ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
6973 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
197ac94e 6974 {
1beb58d7 6975 TCollection_AsciiString anArg (theArgVec[anArgIter]);
6976 anArg.LowerCase();
6977 if (anUpdateTool.parseRedrawMode (anArg))
197ac94e 6978 {
197ac94e 6979 continue;
6980 }
1beb58d7 6981 else if (anArg == "-cmd"
6982 || anArg == "-command"
6983 || anArg == "-args")
6984 {
6985 char aText[4096];
6986 Sprintf (aText,
6987 "-scale %g "
6988 "-proj %g %g %g "
6989 "-up %g %g %g "
6990 "-at %g %g %g\n",
6991 aViewScale,
6992 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
6993 aViewUp.X(), aViewUp.Y(), aViewUp.Z(),
6994 aViewAt.X(), aViewAt.Y(), aViewAt.Z());
6995 theDi << aText;
6996 }
6997 else if (anArg == "-scale"
6998 || anArg == "-size")
6999 {
7000 if (anArgIter + 1 < theArgsNb
7001 && *theArgVec[anArgIter + 1] != '-')
7002 {
7003 const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
d45edf24 7004 if (aValueArg.IsRealValue (Standard_True))
1beb58d7 7005 {
7006 ++anArgIter;
7007 if (anArg == "-scale")
7008 {
7009 toSetScale = Standard_True;
7010 aViewScale = aValueArg.RealValue();
7011 }
7012 else if (anArg == "-size")
7013 {
7014 toSetSize = Standard_True;
7015 aViewSize = aValueArg.RealValue();
7016 }
7017 continue;
7018 }
7019 }
7020 if (anArg == "-scale")
7021 {
7022 theDi << "Scale: " << aView->Scale() << "\n";
7023 }
7024 else if (anArg == "-size")
7025 {
7026 Graphic3d_Vec2d aSizeXY;
7027 aView->Size (aSizeXY.x(), aSizeXY.y());
7028 theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
7029 }
7030 }
7031 else if (anArg == "-eye"
7032 || anArg == "-at"
7033 || anArg == "-up"
7034 || anArg == "-proj")
7035 {
7036 if (anArgIter + 3 < theArgsNb)
7037 {
7038 gp_XYZ anXYZ;
7039 if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
7040 {
7041 anArgIter += 3;
7042 if (anArg == "-eye")
7043 {
7044 toSetEye = Standard_True;
7045 aViewEye = anXYZ;
7046 }
7047 else if (anArg == "-at")
7048 {
7049 toSetAt = Standard_True;
7050 aViewAt = anXYZ;
7051 }
7052 else if (anArg == "-up")
7053 {
7054 toSetUp = Standard_True;
7055 aViewUp = anXYZ;
7056 }
7057 else if (anArg == "-proj")
7058 {
7059 toSetProj = Standard_True;
7060 aViewProj = anXYZ;
7061 }
7062 continue;
7063 }
7064 }
197ac94e 7065
1beb58d7 7066 if (anArg == "-eye")
7067 {
7068 theDi << "Eye: " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
7069 }
7070 else if (anArg == "-at")
7071 {
7072 theDi << "At: " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
7073 }
7074 else if (anArg == "-up")
7075 {
7076 theDi << "Up: " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
7077 }
7078 else if (anArg == "-proj")
7079 {
7080 theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
7081 }
7082 }
7083 else if (anArg == "-center")
3dfe95cd 7084 {
1beb58d7 7085 if (anArgIter + 2 < theArgsNb)
7086 {
7087 const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
7088 const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
7089 if (anX.IsIntegerValue()
7090 && anY.IsIntegerValue())
7091 {
7092 toSetCenter2d = Standard_True;
7093 aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
7094 }
7095 }
7096 }
7097 else
7098 {
23fe70ec 7099 Message::SendFail() << "Syntax error at '" << anArg << "'";
3dfe95cd 7100 return 1;
7101 }
1beb58d7 7102 }
3dfe95cd 7103
1beb58d7 7104 // change view parameters in proper order
7105 if (toSetScale)
7106 {
7107 aView->SetScale (aViewScale);
7108 }
7109 if (toSetSize)
7110 {
7111 aView->SetSize (aViewSize);
7112 }
7113 if (toSetEye)
7114 {
7115 aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
7116 }
7117 if (toSetAt)
7118 {
7119 aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
7120 }
7121 if (toSetProj)
7122 {
7123 aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
7124 }
7125 if (toSetUp)
7126 {
7127 aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
7128 }
7129 if (toSetCenter2d)
7130 {
7131 aView->SetCenter (aCenter2d.x(), aCenter2d.y());
197ac94e 7132 }
7133
1beb58d7 7134 return 0;
7135}
197ac94e 7136
2e93433e 7137//==============================================================================
7138//function : V2DMode
7139//purpose :
7140//==============================================================================
7141static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
7142{
7143 bool is2dMode = true;
7144 Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
7145 if (aV3dView.IsNull())
7146 {
23fe70ec 7147 Message::SendFail ("Error: no active viewer");
2e93433e 7148 return 1;
7149 }
7150 for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7151 {
7152 const TCollection_AsciiString anArg = theArgVec[anArgIt];
7153 TCollection_AsciiString anArgCase = anArg;
7154 anArgCase.LowerCase();
7155 if (anArgIt + 1 < theArgsNb
7156 && anArgCase == "-name")
7157 {
7158 ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
b2fedee6 7159 const TCollection_AsciiString& aViewName = aViewNames.GetViewName();
2e93433e 7160 if (!ViewerTest_myViews.IsBound1 (aViewName))
7161 {
23fe70ec 7162 Message::SendFail() << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'";
2e93433e 7163 return 1;
7164 }
7165 aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
7166 }
7167 else if (anArgCase == "-mode")
7168 {
7169 if (anArgIt + 1 < theArgsNb
dae2a922 7170 && Draw::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
2e93433e 7171 {
7172 ++anArgIt;
7173 }
7174 }
dae2a922 7175 else if (Draw::ParseOnOff (theArgVec[anArgIt], is2dMode))
2e93433e 7176 {
7177 //
7178 }
7179 else
7180 {
23fe70ec 7181 Message::SendFail() << "Syntax error: unknown argument " << anArg;
2e93433e 7182 return 1;
7183 }
7184 }
7185
7186 aV3dView->SetView2DMode (is2dMode);
7187 return 0;
7188}
7189
1beb58d7 7190//==============================================================================
7191//function : VAnimation
7192//purpose :
7193//==============================================================================
7194static Standard_Integer VAnimation (Draw_Interpretor& theDI,
7195 Standard_Integer theArgNb,
7196 const char** theArgVec)
7197{
7198 Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
7199 if (theArgNb < 2)
4754e164 7200 {
1beb58d7 7201 for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
7202 anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
7203 {
7204 theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
197ac94e 7205 }
1beb58d7 7206 return 0;
7207 }
7208 if (aCtx.IsNull())
7209 {
23fe70ec 7210 Message::SendFail ("Error: no active viewer");
1beb58d7 7211 return 1;
4754e164 7212 }
197ac94e 7213
1beb58d7 7214 Standard_Integer anArgIter = 1;
7215 TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
7216 if (aNameArg.IsEmpty())
7217 {
23fe70ec 7218 Message::SendFail ("Syntax error: animation name is not defined");
1beb58d7 7219 return 1;
7220 }
7221
7222 TCollection_AsciiString aNameArgLower = aNameArg;
7223 aNameArgLower.LowerCase();
7224 if (aNameArgLower == "-reset"
7225 || aNameArgLower == "-clear")
7226 {
7227 ViewerTest_AnimationTimelineMap.Clear();
7228 return 0;
7229 }
7230 else if (aNameArg.Value (1) == '-')
7231 {
23fe70ec 7232 Message::SendFail() << "Syntax error: invalid animation name '" << aNameArg << "'";
1beb58d7 7233 return 1;
7234 }
197ac94e 7235
1beb58d7 7236 const char* aNameSplitter = "/";
7237 Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
7238 if (aSplitPos == -1)
197ac94e 7239 {
1beb58d7 7240 aNameSplitter = ".";
7241 aSplitPos = aNameArg.Search (aNameSplitter);
7242 }
7243
7244 // find existing or create a new animation by specified name within syntax "parent.child".
7245 Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
7246 for (; !aNameArg.IsEmpty();)
7247 {
7248 TCollection_AsciiString aNameParent;
7249 if (aSplitPos != -1)
197ac94e 7250 {
1beb58d7 7251 if (aSplitPos == aNameArg.Length())
7252 {
23fe70ec 7253 Message::SendFail ("Syntax error: animation name is not defined");
1beb58d7 7254 return 1;
7255 }
7256
7257 aNameParent = aNameArg.SubString ( 1, aSplitPos - 1);
7258 aNameArg = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7259
7260 aSplitPos = aNameArg.Search (aNameSplitter);
197ac94e 7261 }
7262 else
7263 {
1beb58d7 7264 aNameParent = aNameArg;
7265 aNameArg.Clear();
197ac94e 7266 }
1beb58d7 7267
7268 if (anAnimation.IsNull())
3dfe95cd 7269 {
1beb58d7 7270 if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7271 {
7272 anAnimation = new AIS_Animation (aNameParent);
7273 ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
7274 }
7275 aRootAnimation = anAnimation;
3dfe95cd 7276 }
7277 else
7278 {
1beb58d7 7279 aParentAnimation = anAnimation;
7280 anAnimation = aParentAnimation->Find (aNameParent);
7281 if (anAnimation.IsNull())
7282 {
7283 anAnimation = new AIS_Animation (aNameParent);
7284 aParentAnimation->Add (anAnimation);
7285 }
3dfe95cd 7286 }
7287 }
4f7ad5fb 7288 if (anAnimation.IsNull())
7289 {
7290 Message::SendFail() << "Syntax error: wrong number of arguments";
7291 return 1;
7292 }
1beb58d7 7293
7294 if (anArgIter >= theArgNb)
197ac94e 7295 {
1beb58d7 7296 // just print the list of children
7297 for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
197ac94e 7298 {
1beb58d7 7299 theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
197ac94e 7300 }
1beb58d7 7301 return 0;
197ac94e 7302 }
1beb58d7 7303
bf7b2ceb 7304 // animation parameters
1beb58d7 7305 Standard_Boolean toPlay = Standard_False;
7306 Standard_Real aPlaySpeed = 1.0;
7307 Standard_Real aPlayStartTime = anAnimation->StartPts();
7308 Standard_Real aPlayDuration = anAnimation->Duration();
b9f787f1 7309 Standard_Boolean isFreeCamera = Standard_False;
8f709595 7310 Standard_Boolean toPauseOnClick = Standard_True;
b9f787f1 7311 Standard_Boolean isLockLoop = Standard_False;
7312 Standard_Boolean toPrintElapsedTime = Standard_False;
08f8a185 7313
7314 // video recording parameters
7315 TCollection_AsciiString aRecFile;
7316 Image_VideoParams aRecParams;
7317
1beb58d7 7318 Handle(V3d_View) aView = ViewerTest::CurrentView();
7319 for (; anArgIter < theArgNb; ++anArgIter)
197ac94e 7320 {
1beb58d7 7321 TCollection_AsciiString anArg (theArgVec[anArgIter]);
7322 anArg.LowerCase();
bf7b2ceb 7323 // general options
1beb58d7 7324 if (anArg == "-reset"
7325 || anArg == "-clear")
197ac94e 7326 {
1beb58d7 7327 anAnimation->Clear();
7328 }
7329 else if (anArg == "-remove"
7330 || anArg == "-del"
7331 || anArg == "-delete")
7332 {
7c3daf20 7333 if (aParentAnimation.IsNull())
1beb58d7 7334 {
7335 ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
7336 }
7337 else
7338 {
7339 aParentAnimation->Remove (anAnimation);
7340 }
7341 }
bf7b2ceb 7342 // playback options
1beb58d7 7343 else if (anArg == "-play")
7344 {
7345 toPlay = Standard_True;
7346 if (++anArgIter < theArgNb)
7347 {
7348 if (*theArgVec[anArgIter] == '-')
7349 {
7350 --anArgIter;
7351 continue;
7352 }
7353 aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
7354
7355 if (++anArgIter < theArgNb)
7356 {
7357 if (*theArgVec[anArgIter] == '-')
7358 {
7359 --anArgIter;
7360 continue;
7361 }
7362 aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7363 }
7364 }
7365 }
b9f787f1 7366 else if (anArg == "-elapsedtime"
7367 || anArg == "-elapsed")
7368 {
7369 toPrintElapsedTime = Standard_True;
7370 }
1beb58d7 7371 else if (anArg == "-resume")
7372 {
7373 toPlay = Standard_True;
7374 aPlayStartTime = anAnimation->ElapsedTime();
7375 if (++anArgIter < theArgNb)
7376 {
7377 if (*theArgVec[anArgIter] == '-')
7378 {
7379 --anArgIter;
7380 continue;
7381 }
7382
7383 aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
7384 }
7385 }
8f709595 7386 else if (anArg == "-pause")
7387 {
7388 anAnimation->Pause();
7389 }
7390 else if (anArg == "-stop")
7391 {
7392 anAnimation->Stop();
7393 }
1beb58d7 7394 else if (anArg == "-playspeed"
7395 || anArg == "-speed")
7396 {
7397 if (++anArgIter >= theArgNb)
7398 {
23fe70ec 7399 Message::SendFail() << "Syntax error at " << anArg << "";
1beb58d7 7400 return 1;
7401 }
7402 aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
7403 }
7404 else if (anArg == "-lock"
7405 || anArg == "-lockloop"
7406 || anArg == "-playlockloop")
7407 {
8f709595 7408 isLockLoop = Draw::ParseOnOffIterator (theArgNb, theArgVec, anArgIter);
1beb58d7 7409 }
7410 else if (anArg == "-freecamera"
8f709595 7411 || anArg == "-nofreecamera"
1beb58d7 7412 || anArg == "-playfreecamera"
8f709595 7413 || anArg == "-noplayfreecamera"
7414 || anArg == "-freelook"
7415 || anArg == "-nofreelook")
7416 {
7417 isFreeCamera = Draw::ParseOnOffNoIterator (theArgNb, theArgVec, anArgIter);
7418 }
7419 else if (anArg == "-pauseonclick"
7420 || anArg == "-nopauseonclick"
7421 || anArg == "-nopause")
1beb58d7 7422 {
8f709595 7423 toPauseOnClick = Draw::ParseOnOffNoIterator (theArgNb, theArgVec, anArgIter);
1beb58d7 7424 }
08f8a185 7425 // video recodring options
7426 else if (anArg == "-rec"
7427 || anArg == "-record")
7428 {
7429 if (++anArgIter >= theArgNb)
7430 {
23fe70ec 7431 Message::SendFail() << "Syntax error at " << anArg;
08f8a185 7432 return 1;
7433 }
7434
7435 aRecFile = theArgVec[anArgIter];
7436 if (aRecParams.FpsNum <= 0)
7437 {
7438 aRecParams.FpsNum = 24;
7439 }
7440
7441 if (anArgIter + 2 < theArgNb
7442 && *theArgVec[anArgIter + 1] != '-'
7443 && *theArgVec[anArgIter + 2] != '-')
7444 {
7445 TCollection_AsciiString aWidthArg (theArgVec[anArgIter + 1]);
7446 TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
7447 if (aWidthArg .IsIntegerValue()
7448 && aHeightArg.IsIntegerValue())
7449 {
7450 aRecParams.Width = aWidthArg .IntegerValue();
7451 aRecParams.Height = aHeightArg.IntegerValue();
7452 anArgIter += 2;
7453 }
7454 }
7455 }
1beb58d7 7456 else if (anArg == "-fps")
7457 {
7458 if (++anArgIter >= theArgNb)
7459 {
23fe70ec 7460 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7461 return 1;
7462 }
bf7b2ceb 7463
7464 TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
7465 Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
7466 if (aSplitIndex == 0)
7467 {
08f8a185 7468 aRecParams.FpsNum = aFpsArg.IntegerValue();
bf7b2ceb 7469 }
7470 else
7471 {
7472 const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
7473 aFpsArg.Split (aFpsArg.Length() - 1);
7474 const TCollection_AsciiString aNumStr = aFpsArg;
08f8a185 7475 aRecParams.FpsNum = aNumStr.IntegerValue();
7476 aRecParams.FpsDen = aDenStr.IntegerValue();
7477 if (aRecParams.FpsDen < 1)
bf7b2ceb 7478 {
23fe70ec 7479 Message::SendFail() << "Syntax error at " << anArg;
bf7b2ceb 7480 return 1;
7481 }
7482 }
1beb58d7 7483 }
08f8a185 7484 else if (anArg == "-format")
7485 {
7486 if (++anArgIter >= theArgNb)
7487 {
23fe70ec 7488 Message::SendFail() << "Syntax error at " << anArg;
08f8a185 7489 return 1;
7490 }
7491 aRecParams.Format = theArgVec[anArgIter];
7492 }
7493 else if (anArg == "-pix_fmt"
7494 || anArg == "-pixfmt"
7495 || anArg == "-pixelformat")
7496 {
7497 if (++anArgIter >= theArgNb)
7498 {
23fe70ec 7499 Message::SendFail() << "Syntax error at " << anArg;
08f8a185 7500 return 1;
7501 }
7502 aRecParams.PixelFormat = theArgVec[anArgIter];
7503 }
7504 else if (anArg == "-codec"
7505 || anArg == "-vcodec"
7506 || anArg == "-videocodec")
7507 {
7508 if (++anArgIter >= theArgNb)
7509 {
23fe70ec 7510 Message::SendFail() << "Syntax error at " << anArg;
08f8a185 7511 return 1;
7512 }
7513 aRecParams.VideoCodec = theArgVec[anArgIter];
7514 }
7515 else if (anArg == "-crf"
7516 || anArg == "-preset"
7517 || anArg == "-qp")
7518 {
7519 const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
7520 if (++anArgIter >= theArgNb)
7521 {
23fe70ec 7522 Message::SendFail() << "Syntax error at " << anArg;
08f8a185 7523 return 1;
7524 }
7525
7526 aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
7527 }
bf7b2ceb 7528 // animation definition options
1beb58d7 7529 else if (anArg == "-start"
7530 || anArg == "-starttime"
7531 || anArg == "-startpts")
7532 {
7533 if (++anArgIter >= theArgNb)
7534 {
23fe70ec 7535 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7536 return 1;
7537 }
7538
7539 anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
7540 aRootAnimation->UpdateTotalDuration();
7541 }
7542 else if (anArg == "-end"
7543 || anArg == "-endtime"
7544 || anArg == "-endpts")
7545 {
7546 if (++anArgIter >= theArgNb)
7547 {
23fe70ec 7548 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7549 return 1;
7550 }
7551
7552 anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
7553 aRootAnimation->UpdateTotalDuration();
7554 }
7555 else if (anArg == "-dur"
7556 || anArg == "-duration")
7557 {
7558 if (++anArgIter >= theArgNb)
7559 {
23fe70ec 7560 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7561 return 1;
7562 }
7563
7564 anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
7565 aRootAnimation->UpdateTotalDuration();
7566 }
7567 else if (anArg == "-command"
7568 || anArg == "-cmd"
7569 || anArg == "-invoke"
7570 || anArg == "-eval"
7571 || anArg == "-proc")
7572 {
7573 if (++anArgIter >= theArgNb)
7574 {
23fe70ec 7575 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7576 return 1;
7577 }
7578
7579 Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
7580 replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
7581 }
7582 else if (anArg == "-objecttrsf"
7583 || anArg == "-objectransformation"
7584 || anArg == "-objtransformation"
7585 || anArg == "-objtrsf"
7586 || anArg == "-object"
7587 || anArg == "-obj")
7588 {
7589 if (++anArgIter >= theArgNb)
7590 {
23fe70ec 7591 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7592 return 1;
7593 }
7594
7595 TCollection_AsciiString anObjName (theArgVec[anArgIter]);
7596 const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8f521168 7597 Handle(AIS_InteractiveObject) anObject;
7598 if (!aMapOfAIS.Find2 (anObjName, anObject))
1beb58d7 7599 {
23fe70ec 7600 Message::SendFail() << "Syntax error: wrong object name at " << anArg;
1beb58d7 7601 return 1;
7602 }
7603
1beb58d7 7604 gp_Trsf aTrsfs [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
7605 gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(), aTrsfs[1].GetRotation() };
7606 gp_XYZ aLocPnts [2] = { aTrsfs[0].TranslationPart(), aTrsfs[1].TranslationPart() };
7607 Standard_Real aScales [2] = { aTrsfs[0].ScaleFactor(), aTrsfs[1].ScaleFactor() };
7608 Standard_Boolean isTrsfSet = Standard_False;
53eae1a9 7609
7610 gp_Ax1 anAxis;
7611 Standard_Real anAngles[2] = { 0.0, 0.0 };
7612 Standard_Boolean isAxisRotationSet = Standard_False;
7613
1beb58d7 7614 Standard_Integer aTrsfArgIter = anArgIter + 1;
7615 for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
7616 {
7617 TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
7618 aTrsfArg.LowerCase();
7619 const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
7620 if (aTrsfArg.StartsWith ("-rotation")
7621 || aTrsfArg.StartsWith ("-rot"))
7622 {
7623 isTrsfSet = Standard_True;
7624 if (aTrsfArgIter + 4 >= theArgNb
7625 || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
7626 {
23fe70ec 7627 Message::SendFail() << "Syntax error at " << aTrsfArg;
1beb58d7 7628 return 1;
7629 }
7630 aTrsfArgIter += 4;
7631 }
7632 else if (aTrsfArg.StartsWith ("-location")
7633 || aTrsfArg.StartsWith ("-loc"))
7634 {
7635 isTrsfSet = Standard_True;
7636 if (aTrsfArgIter + 3 >= theArgNb
7637 || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
7638 {
23fe70ec 7639 Message::SendFail() << "Syntax error at " << aTrsfArg;
1beb58d7 7640 return 1;
7641 }
7642 aTrsfArgIter += 3;
7643 }
7644 else if (aTrsfArg.StartsWith ("-scale"))
7645 {
7646 isTrsfSet = Standard_True;
7647 if (++aTrsfArgIter >= theArgNb)
7648 {
23fe70ec 7649 Message::SendFail() << "Syntax error at " << aTrsfArg;
1beb58d7 7650 return 1;
7651 }
7652
7653 const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
d45edf24 7654 if (!aScaleStr.IsRealValue (Standard_True))
1beb58d7 7655 {
23fe70ec 7656 Message::SendFail() << "Syntax error at " << aTrsfArg;
1beb58d7 7657 return 1;
7658 }
7659 aScales[anIndex] = aScaleStr.RealValue();
7660 }
53eae1a9 7661 else if (aTrsfArg == "-axis")
7662 {
7663 isAxisRotationSet = Standard_True;
7664 gp_XYZ anOrigin, aDirection;
7665 if (aTrsfArgIter + 6 >= theArgNb
7666 || !parseXYZ (theArgVec + aTrsfArgIter + 1, anOrigin)
7667 || !parseXYZ (theArgVec + aTrsfArgIter + 4, aDirection))
7668 {
7669 Message::SendFail() << "Syntax error at " << aTrsfArg;
7670 return 1;
7671 }
7672 anAxis.SetLocation (anOrigin);
7673 anAxis.SetDirection (aDirection);
7674 aTrsfArgIter += 6;
7675 }
7676 else if (aTrsfArg.StartsWith ("-ang"))
7677 {
7678 isAxisRotationSet = Standard_True;
7679 if (++aTrsfArgIter >= theArgNb)
7680 {
7681 Message::SendFail() << "Syntax error at " << aTrsfArg;
7682 return 1;
7683 }
7684
7685 const TCollection_AsciiString anAngleStr (theArgVec[aTrsfArgIter]);
7686 if (!anAngleStr.IsRealValue (Standard_True))
7687 {
7688 Message::SendFail() << "Syntax error at " << aTrsfArg;
7689 return 1;
7690 }
7691 anAngles[anIndex] = anAngleStr.RealValue();
7692 }
1beb58d7 7693 else
7694 {
7695 anArgIter = aTrsfArgIter - 1;
7696 break;
7697 }
7698 }
53eae1a9 7699 if (!isTrsfSet && !isAxisRotationSet)
1beb58d7 7700 {
23fe70ec 7701 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7702 return 1;
7703 }
7704 else if (aTrsfArgIter >= theArgNb)
7705 {
7706 anArgIter = theArgNb;
7707 }
53eae1a9 7708 Handle(AIS_BaseAnimationObject) anObjAnimation;
7709 if (isTrsfSet)
7710 {
7711 aTrsfs[0].SetRotation (aRotQuats[0]);
7712 aTrsfs[1].SetRotation (aRotQuats[1]);
7713 aTrsfs[0].SetTranslationPart (aLocPnts[0]);
7714 aTrsfs[1].SetTranslationPart (aLocPnts[1]);
7715 aTrsfs[0].SetScaleFactor (aScales[0]);
7716 aTrsfs[1].SetScaleFactor (aScales[1]);
1beb58d7 7717
53eae1a9 7718 anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
7719 }
7720 else
7721 {
7722 anObjAnimation = new AIS_AnimationAxisRotation (anAnimation->Name(), aCtx, anObject, anAxis,
7723 anAngles[0] * (M_PI / 180.0), anAngles[1] * (M_PI / 180.0));
7724 }
1beb58d7 7725 replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
7726 }
7727 else if (anArg == "-viewtrsf"
7728 || anArg == "-view")
7729 {
7730 Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
7731 if (aCamAnimation.IsNull())
7732 {
7733 aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
7734 replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
7735 }
7736
7737 Handle(Graphic3d_Camera) aCams[2] =
7738 {
7739 new Graphic3d_Camera (aCamAnimation->View()->Camera()),
7740 new Graphic3d_Camera (aCamAnimation->View()->Camera())
7741 };
7742
7743 Standard_Boolean isTrsfSet = Standard_False;
7744 Standard_Integer aViewArgIter = anArgIter + 1;
7745 for (; aViewArgIter < theArgNb; ++aViewArgIter)
7746 {
7747 TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
7748 aViewArg.LowerCase();
7749 const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
7750 if (aViewArg.StartsWith ("-scale"))
7751 {
7752 isTrsfSet = Standard_True;
7753 if (++aViewArgIter >= theArgNb)
7754 {
23fe70ec 7755 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7756 return 1;
7757 }
7758
7759 const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
d45edf24 7760 if (!aScaleStr.IsRealValue (Standard_True))
1beb58d7 7761 {
23fe70ec 7762 Message::SendFail() << "Syntax error at " << aViewArg;
1beb58d7 7763 return 1;
7764 }
7765 Standard_Real aScale = aScaleStr.RealValue();
7766 aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
7767 aCams[anIndex]->SetScale (aScale);
7768 }
7769 else if (aViewArg.StartsWith ("-eye")
7770 || aViewArg.StartsWith ("-center")
7771 || aViewArg.StartsWith ("-at")
7772 || aViewArg.StartsWith ("-up"))
7773 {
7774 isTrsfSet = Standard_True;
7775 gp_XYZ anXYZ;
7776 if (aViewArgIter + 3 >= theArgNb
7777 || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
7778 {
23fe70ec 7779 Message::SendFail() << "Syntax error at " << aViewArg;
1beb58d7 7780 return 1;
7781 }
7782 aViewArgIter += 3;
7783
7784 if (aViewArg.StartsWith ("-eye"))
7785 {
7786 aCams[anIndex]->SetEye (anXYZ);
7787 }
7788 else if (aViewArg.StartsWith ("-center")
7789 || aViewArg.StartsWith ("-at"))
7790 {
7791 aCams[anIndex]->SetCenter (anXYZ);
7792 }
7793 else if (aViewArg.StartsWith ("-up"))
7794 {
7795 aCams[anIndex]->SetUp (anXYZ);
7796 }
7797 }
7798 else
7799 {
7800 anArgIter = aViewArgIter - 1;
7801 break;
7802 }
7803 }
7804 if (!isTrsfSet)
7805 {
23fe70ec 7806 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7807 return 1;
7808 }
7809 else if (aViewArgIter >= theArgNb)
7810 {
7811 anArgIter = theArgNb;
7812 }
7813
7814 aCamAnimation->SetCameraStart(aCams[0]);
7815 aCamAnimation->SetCameraEnd (aCams[1]);
197ac94e 7816 }
7817 else
7818 {
23fe70ec 7819 Message::SendFail() << "Syntax error at " << anArg;
1beb58d7 7820 return 1;
197ac94e 7821 }
7822 }
1beb58d7 7823
b9f787f1 7824 if (anAnimation.IsNull() || anAnimation->IsStopped())
7825 {
7826 ViewerTest::CurrentEventManager()->AbortViewAnimation();
7827 ViewerTest::CurrentEventManager()->SetObjectsAnimation(Handle(AIS_Animation)());
7828 }
7829
7830 if (toPrintElapsedTime)
7831 {
7832 theDI << "Elapsed Time: " << anAnimation->ElapsedTime() << " s\n";
7833 }
7834
08f8a185 7835 if (!toPlay && aRecFile.IsEmpty())
197ac94e 7836 {
1beb58d7 7837 return 0;
7838 }
7839
7840 // Start animation timeline and process frame updating.
8f709595 7841 if (aRecParams.FpsNum <= 0
7842 && !isLockLoop)
7843 {
7844 Handle(ViewerTest_AnimationHolder) aHolder = new ViewerTest_AnimationHolder (anAnimation, aView, isFreeCamera);
7845 aHolder->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
7846 ViewerTest::CurrentEventManager()->SetPauseObjectsAnimation (toPauseOnClick);
7847 ViewerTest::CurrentEventManager()->SetObjectsAnimation (aHolder);
7848 ViewerTest::CurrentEventManager()->ProcessExpose();
7849 return 0;
1beb58d7 7850 }
7851
8f709595 7852 // Perform video recording
7853 const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
1beb58d7 7854 const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8f709595 7855 anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
1beb58d7 7856
8f709595 7857 OSD_Timer aPerfTimer;
7858 aPerfTimer.Start();
1beb58d7 7859
8f709595 7860 Handle(Image_VideoRecorder) aRecorder;
7861 ImageFlipper aFlipper;
7862 Handle(Draw_ProgressIndicator) aProgress;
7863 if (!aRecFile.IsEmpty())
7864 {
7865 if (aRecParams.Width <= 0
7866 || aRecParams.Height <= 0)
7867 {
7868 aView->Window()->Size (aRecParams.Width, aRecParams.Height);
7869 }
1beb58d7 7870
8f709595 7871 aRecorder = new Image_VideoRecorder();
7872 if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
7873 {
7874 Message::SendFail ("Error: failed to open video file for recording");
7875 return 0;
1beb58d7 7876 }
7877
8f709595 7878 aProgress = new Draw_ProgressIndicator (theDI, 1);
7879 }
7880
7881 // Manage frame-rated animation here
7882 Standard_Real aPts = aPlayStartTime;
7883 int64_t aNbFrames = 0;
7884 Message_ProgressScope aPS(Message_ProgressIndicator::Start(aProgress),
7885 "Video recording, sec", Max(1, Standard_Integer(aPlayDuration / aPlaySpeed)));
7886 Standard_Integer aSecondsProgress = 0;
7887 for (; aPts <= anUpperPts && aPS.More();)
7888 {
7889 Standard_Real aRecPts = 0.0;
7890 if (aRecParams.FpsNum > 0)
1beb58d7 7891 {
8f709595 7892 aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
197ac94e 7893 }
7894 else
7895 {
8f709595 7896 aRecPts = aPlaySpeed * aPerfTimer.ElapsedTime();
197ac94e 7897 }
1beb58d7 7898
8f709595 7899 aPts = aPlayStartTime + aRecPts;
7900 ++aNbFrames;
7901 if (!anAnimation->Update (aPts))
08f8a185 7902 {
8f709595 7903 break;
08f8a185 7904 }
7905
8f709595 7906 if (!aRecorder.IsNull())
197ac94e 7907 {
8f709595 7908 V3d_ImageDumpOptions aDumpParams;
7909 aDumpParams.Width = aRecParams.Width;
7910 aDumpParams.Height = aRecParams.Height;
7911 aDumpParams.BufferType = Graphic3d_BT_RGBA;
7912 aDumpParams.StereoOptions = V3d_SDO_MONO;
7913 aDumpParams.ToAdjustAspect = Standard_True;
7914 if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
08f8a185 7915 {
8f709595 7916 Message::SendFail ("Error: view dump is failed");
7917 return 0;
08f8a185 7918 }
8f709595 7919 aFlipper.FlipY (aRecorder->ChangeFrame());
7920 if (!aRecorder->PushFrame())
08f8a185 7921 {
8f709595 7922 return 0;
08f8a185 7923 }
197ac94e 7924 }
8f709595 7925 else
7926 {
7927 aView->Redraw();
7928 }
bf7b2ceb 7929
8f709595 7930 while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
7931 {
7932 aPS.Next();
7933 ++aSecondsProgress;
7934 }
197ac94e 7935 }
7936
8f709595 7937 aPerfTimer.Stop();
7938 anAnimation->Stop();
7939 const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
7940 theDI << "Average FPS: " << aRecFps << "\n"
7941 << "Nb. Frames: " << Standard_Real(aNbFrames);
7942
7943 aView->Redraw();
1beb58d7 7944 aView->SetImmediateUpdate (wasImmediateUpdate);
4754e164 7945 return 0;
7946}
7947
1beb58d7 7948
4754e164 7949//=======================================================================
7950//function : VChangeSelected
dc3fe572 7951//purpose : Adds the shape to selection or remove one from it
4754e164 7952//=======================================================================
7953static Standard_Integer VChangeSelected (Draw_Interpretor& di,
7954 Standard_Integer argc,
7955 const char ** argv)
7956{
7957 if(argc != 2)
7958 {
7959 di<<"Usage : " << argv[0] << " shape \n";
7960 return 1;
7961 }
7962 //get AIS_Shape:
4754e164 7963 TCollection_AsciiString aName(argv[1]);
7964 Handle(AIS_InteractiveObject) anAISObject;
8f521168 7965 if (!GetMapOfAIS().Find2 (aName, anAISObject)
7966 || anAISObject.IsNull())
4754e164 7967 {
7968 di<<"Use 'vdisplay' before";
7969 return 1;
7970 }
4754e164 7971
8f521168 7972 ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
4754e164 7973 return 0;
7974}
7975
4754e164 7976//=======================================================================
7977//function : VNbSelected
dc3fe572 7978//purpose : Returns number of selected objects
4754e164 7979//=======================================================================
7980static Standard_Integer VNbSelected (Draw_Interpretor& di,
7981 Standard_Integer argc,
7982 const char ** argv)
7983{
7984 if(argc != 1)
7985 {
7986 di << "Usage : " << argv[0] << "\n";
7987 return 1;
7988 }
7989 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
7990 if(aContext.IsNull())
7991 {
7992 di << "use 'vinit' command before " << argv[0] << "\n";
7993 return 1;
7994 }
7995 di << aContext->NbSelected() << "\n";
7996 return 0;
7997}
7998
4754e164 7999//=======================================================================
8000//function : VSetViewSize
8001//purpose :
8002//=======================================================================
8003static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8004 Standard_Integer argc,
8005 const char ** argv)
8006{
8007 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8008 if(aContext.IsNull())
8009 {
8010 di << "use 'vinit' command before " << argv[0] << "\n";
8011 return 1;
8012 }
8013 if(argc != 2)
8014 {
8015 di<<"Usage : " << argv[0] << " Size\n";
8016 return 1;
8017 }
6b62b2da 8018 Standard_Real aSize = Draw::Atof (argv[1]);
4754e164 8019 if (aSize <= 0.)
8020 {
8021 di<<"Bad Size value : " << aSize << "\n";
8022 return 1;
8023 }
8024
8025 Handle(V3d_View) aView = ViewerTest::CurrentView();
8026 aView->SetSize(aSize);
8027 return 0;
8028}
8029
8030//=======================================================================
8031//function : VMoveView
8032//purpose :
8033//=======================================================================
8034static Standard_Integer VMoveView (Draw_Interpretor& di,
8035 Standard_Integer argc,
8036 const char ** argv)
8037{
8038 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8039 if(aContext.IsNull())
8040 {
8041 di << "use 'vinit' command before " << argv[0] << "\n";
8042 return 1;
8043 }
8044 if(argc < 4 || argc > 5)
8045 {
8046 di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8047 return 1;
8048 }
6b62b2da 8049 Standard_Real Dx = Draw::Atof (argv[1]);
8050 Standard_Real Dy = Draw::Atof (argv[2]);
8051 Standard_Real Dz = Draw::Atof (argv[3]);
4754e164 8052 Standard_Boolean aStart = Standard_True;
8053 if (argc == 5)
8054 {
6b62b2da 8055 aStart = (Draw::Atoi (argv[4]) > 0);
4754e164 8056 }
8057
8058 Handle(V3d_View) aView = ViewerTest::CurrentView();
8059 aView->Move(Dx,Dy,Dz,aStart);
8060 return 0;
8061}
8062
8063//=======================================================================
8064//function : VTranslateView
8065//purpose :
8066//=======================================================================
8067static Standard_Integer VTranslateView (Draw_Interpretor& di,
8068 Standard_Integer argc,
8069 const char ** argv)
8070{
8071 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8072 if(aContext.IsNull())
8073 {
8074 di << "use 'vinit' command before " << argv[0] << "\n";
8075 return 1;
8076 }
8077 if(argc < 4 || argc > 5)
8078 {
8079 di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8080 return 1;
8081 }
6b62b2da 8082 Standard_Real Dx = Draw::Atof (argv[1]);
8083 Standard_Real Dy = Draw::Atof (argv[2]);
8084 Standard_Real Dz = Draw::Atof (argv[3]);
4754e164 8085 Standard_Boolean aStart = Standard_True;
dc3fe572 8086 if (argc == 5)
4754e164 8087 {
6b62b2da 8088 aStart = (Draw::Atoi (argv[4]) > 0);
4754e164 8089 }
8090
8091 Handle(V3d_View) aView = ViewerTest::CurrentView();
8092 aView->Translate(Dx,Dy,Dz,aStart);
8093 return 0;
8094}
8095
8096//=======================================================================
8097//function : VTurnView
8098//purpose :
8099//=======================================================================
8100static Standard_Integer VTurnView (Draw_Interpretor& di,
8101 Standard_Integer argc,
8102 const char ** argv)
8103{
8104 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8105 if(aContext.IsNull()) {
8106 di << "use 'vinit' command before " << argv[0] << "\n";
8107 return 1;
8108 }
8109 if(argc < 4 || argc > 5){
8110 di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
8111 return 1;
8112 }
6b62b2da 8113 Standard_Real Ax = Draw::Atof (argv[1]);
8114 Standard_Real Ay = Draw::Atof (argv[2]);
8115 Standard_Real Az = Draw::Atof (argv[3]);
4754e164 8116 Standard_Boolean aStart = Standard_True;
dc3fe572 8117 if (argc == 5)
4754e164 8118 {
6b62b2da 8119 aStart = (Draw::Atoi (argv[4]) > 0);
4754e164 8120 }
8121
8122 Handle(V3d_View) aView = ViewerTest::CurrentView();
8123 aView->Turn(Ax,Ay,Az,aStart);
8124 return 0;
8125}
8126
269294d6 8127//==============================================================================
8128//function : VTextureEnv
8129//purpose : ENables or disables environment mapping
8130//==============================================================================
8131class OCC_TextureEnv : public Graphic3d_TextureEnv
8132{
8133public:
8134 OCC_TextureEnv(const Standard_CString FileName);
8135 OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
8136 void SetTextureParameters(const Standard_Boolean theRepeatFlag,
8137 const Standard_Boolean theModulateFlag,
8138 const Graphic3d_TypeOfTextureFilter theFilter,
8139 const Standard_ShortReal theXScale,
8140 const Standard_ShortReal theYScale,
8141 const Standard_ShortReal theXShift,
8142 const Standard_ShortReal theYShift,
8143 const Standard_ShortReal theAngle);
68858c7d 8144 DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
269294d6 8145};
a3f6f591 8146DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
ec357c5c 8147
269294d6 8148OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
8149 : Graphic3d_TextureEnv(theFileName)
8150{
8151}
8152
8153OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
8154 : Graphic3d_TextureEnv(theTexId)
8155{
8156}
8157
8158void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
8159 const Standard_Boolean theModulateFlag,
8160 const Graphic3d_TypeOfTextureFilter theFilter,
8161 const Standard_ShortReal theXScale,
8162 const Standard_ShortReal theYScale,
8163 const Standard_ShortReal theXShift,
8164 const Standard_ShortReal theYShift,
8165 const Standard_ShortReal theAngle)
8166{
8167 myParams->SetRepeat (theRepeatFlag);
8168 myParams->SetModulate (theModulateFlag);
8169 myParams->SetFilter (theFilter);
8170 myParams->SetScale (Graphic3d_Vec2(theXScale, theYScale));
8171 myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
8172 myParams->SetRotation (theAngle);
8173}
8174
35e08fe8 8175static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
269294d6 8176{
8177 // get the active view
8178 Handle(V3d_View) aView = ViewerTest::CurrentView();
8179 if (aView.IsNull())
8180 {
23fe70ec 8181 Message::SendFail ("Error: no active viewer");
269294d6 8182 return 1;
8183 }
8184
8185 // Checking the input arguments
8186 Standard_Boolean anEnableFlag = Standard_False;
8187 Standard_Boolean isOk = theArgNb >= 2;
8188 if (isOk)
8189 {
8190 TCollection_AsciiString anEnableOpt(theArgVec[1]);
8191 anEnableFlag = anEnableOpt.IsEqual("on");
8192 isOk = anEnableFlag || anEnableOpt.IsEqual("off");
8193 }
8194 if (anEnableFlag)
8195 {
8196 isOk = (theArgNb == 3 || theArgNb == 11);
8197 if (isOk)
8198 {
8199 TCollection_AsciiString aTextureOpt(theArgVec[2]);
8200 isOk = (!aTextureOpt.IsIntegerValue() ||
8201 (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
8202
8203 if (isOk && theArgNb == 11)
8204 {
8205 TCollection_AsciiString aRepeatOpt (theArgVec[3]),
8206 aModulateOpt(theArgVec[4]),
8207 aFilterOpt (theArgVec[5]),
8208 aSScaleOpt (theArgVec[6]),
8209 aTScaleOpt (theArgVec[7]),
8210 aSTransOpt (theArgVec[8]),
8211 aTTransOpt (theArgVec[9]),
8212 anAngleOpt (theArgVec[10]);
8213 isOk = ((aRepeatOpt. IsEqual("repeat") || aRepeatOpt. IsEqual("clamp")) &&
8214 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
8215 (aFilterOpt. IsEqual("nearest") || aFilterOpt. IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
d45edf24 8216 aSScaleOpt.IsRealValue (Standard_True) && aTScaleOpt.IsRealValue (Standard_True) &&
8217 aSTransOpt.IsRealValue (Standard_True) && aTTransOpt.IsRealValue (Standard_True) &&
8218 anAngleOpt.IsRealValue (Standard_True));
269294d6 8219 }
8220 }
8221 }
8222
8223 if (!isOk)
8224 {
23fe70ec 8225 Message::SendFail() << "Usage:\n"
8226 << theArgVec[0] << " off\n"
8227 << theArgVec[0] << " on {index_of_std_texture(0..7)|texture_file_name} [{clamp|repeat} {decal|modulate} {nearest|bilinear|trilinear} scale_s scale_t translation_s translation_t rotation_degrees]";
269294d6 8228 return 1;
8229 }
8230
8231 if (anEnableFlag)
8232 {
8233 TCollection_AsciiString aTextureOpt(theArgVec[2]);
8234 Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
8235 new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
8236 new OCC_TextureEnv(theArgVec[2]);
8237
8238 if (theArgNb == 11)
8239 {
8240 TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
8241 aTexEnv->SetTextureParameters(
8242 aRepeatOpt. IsEqual("repeat"),
8243 aModulateOpt.IsEqual("modulate"),
8244 aFilterOpt. IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
8245 aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
8246 Graphic3d_TOTF_TRILINEAR,
8247 (Standard_ShortReal)Draw::Atof(theArgVec[6]),
8248 (Standard_ShortReal)Draw::Atof(theArgVec[7]),
8249 (Standard_ShortReal)Draw::Atof(theArgVec[8]),
8250 (Standard_ShortReal)Draw::Atof(theArgVec[9]),
8251 (Standard_ShortReal)Draw::Atof(theArgVec[10])
8252 );
8253 }
8254 aView->SetTextureEnv(aTexEnv);
269294d6 8255 }
8256 else // Disabling environment mapping
8257 {
269294d6 8258 Handle(Graphic3d_TextureEnv) aTexture;
8259 aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
8260 }
8261
8262 aView->Redraw();
8263 return 0;
8264}
8265
3e05329c 8266namespace
8267{
8268 typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8269
8270 //! Remove registered clipping plane from all views and objects.
8271 static void removePlane (MapOfPlanes& theRegPlanes,
8272 const TCollection_AsciiString& theName)
8273 {
8274 Handle(Graphic3d_ClipPlane) aClipPlane;
8275 if (!theRegPlanes.Find (theName, aClipPlane))
8276 {
23fe70ec 8277 Message::SendWarning ("Warning: no such plane");
3e05329c 8278 return;
8279 }
8280
8281 theRegPlanes.UnBind (theName);
8282 for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8283 anIObjIt.More(); anIObjIt.Next())
8284 {
8f521168 8285 const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
3e05329c 8286 aPrs->RemoveClipPlane (aClipPlane);
8287 }
8288
1103eb60 8289 for (ViewerTest_ViewerCommandsViewMap::Iterator aViewIt(ViewerTest_myViews);
3e05329c 8290 aViewIt.More(); aViewIt.Next())
8291 {
8292 const Handle(V3d_View)& aView = aViewIt.Key2();
8293 aView->RemoveClipPlane(aClipPlane);
8294 }
8295
8296 ViewerTest::RedrawAllViews();
8297 }
8298}
8299
4269bd1b 8300//===============================================================================================
8301//function : VClipPlane
8302//purpose :
8303//===============================================================================================
8304static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8305{
8306 // use short-cut for created clip planes map of created (or "registered by name") clip planes
4269bd1b 8307 static MapOfPlanes aRegPlanes;
8308
8309 if (theArgsNb < 2)
8310 {
3e05329c 8311 for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
8312 {
8313 theDi << aPlaneIter.Key() << " ";
8314 }
8315 return 0;
4269bd1b 8316 }
8317
8318 TCollection_AsciiString aCommand (theArgVec[1]);
3e05329c 8319 aCommand.LowerCase();
8320 const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
8321 if (anActiveView.IsNull())
8322 {
23fe70ec 8323 Message::SendFail ("Error: no active viewer");
3e05329c 8324 return 1;
8325 }
4269bd1b 8326
8327 // print maximum number of planes for current viewer
3e05329c 8328 if (aCommand == "-maxplanes"
8329 || aCommand == "maxplanes")
4269bd1b 8330 {
3e05329c 8331 theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
8332 << " plane slots provided by driver.\n";
4269bd1b 8333 return 0;
8334 }
8335
8336 // create / delete plane instance
3e05329c 8337 if (aCommand == "-create"
8338 || aCommand == "create"
8339 || aCommand == "-delete"
8340 || aCommand == "delete"
8341 || aCommand == "-clone"
8342 || aCommand == "clone")
4269bd1b 8343 {
8344 if (theArgsNb < 3)
8345 {
23fe70ec 8346 Message::SendFail ("Syntax error: plane name is required");
4269bd1b 8347 return 1;
8348 }
8349
3e05329c 8350 Standard_Boolean toCreate = aCommand == "-create"
8351 || aCommand == "create";
8352 Standard_Boolean toClone = aCommand == "-clone"
8353 || aCommand == "clone";
8354 Standard_Boolean toDelete = aCommand == "-delete"
8355 || aCommand == "delete";
4269bd1b 8356 TCollection_AsciiString aPlane (theArgVec[2]);
8357
8358 if (toCreate)
8359 {
8360 if (aRegPlanes.IsBound (aPlane))
8361 {
3e05329c 8362 std::cout << "Warning: existing plane has been overridden.\n";
8363 toDelete = true;
8364 }
8365 else
8366 {
8367 aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8368 return 0;
4269bd1b 8369 }
4269bd1b 8370 }
8371 else if (toClone) // toClone
8372 {
8373 if (!aRegPlanes.IsBound (aPlane))
8374 {
23fe70ec 8375 Message::SendFail ("Error: no such plane");
4269bd1b 8376 return 1;
8377 }
3e05329c 8378 else if (theArgsNb < 4)
4269bd1b 8379 {
23fe70ec 8380 Message::SendFail ("Syntax error: enter name for new plane");
4269bd1b 8381 return 1;
8382 }
8383
8384 TCollection_AsciiString aClone (theArgVec[3]);
8385 if (aRegPlanes.IsBound (aClone))
8386 {
23fe70ec 8387 Message::SendFail ("Error: plane name is in use");
4269bd1b 8388 return 1;
8389 }
8390
8391 const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
8392
8393 aRegPlanes.Bind (aClone, aClipPlane->Clone());
3e05329c 8394 return 0;
4269bd1b 8395 }
4269bd1b 8396
3e05329c 8397 if (toDelete)
8398 {
8399 if (aPlane == "ALL"
8400 || aPlane == "all"
8401 || aPlane == "*")
4269bd1b 8402 {
3e05329c 8403 for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
8404 {
8405 aPlane = aPlaneIter.Key();
8406 removePlane (aRegPlanes, aPlane);
8407 aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
8408 }
4269bd1b 8409 }
3e05329c 8410 else
4269bd1b 8411 {
3e05329c 8412 removePlane (aRegPlanes, aPlane);
4269bd1b 8413 }
4269bd1b 8414 }
8415
3e05329c 8416 if (toCreate)
8417 {
8418 aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
8419 }
4269bd1b 8420 return 0;
8421 }
8422
8423 // set / unset plane command
3e05329c 8424 if (aCommand == "set"
8425 || aCommand == "unset")
4269bd1b 8426 {
3e05329c 8427 if (theArgsNb < 5)
4269bd1b 8428 {
23fe70ec 8429 Message::SendFail ("Syntax error: need more arguments");
4269bd1b 8430 return 1;
8431 }
8432
3e05329c 8433 // redirect to new syntax
8434 NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
8435 anArgVec.SetValue (1, theArgVec[0]);
8436 anArgVec.SetValue (2, theArgVec[2]);
8437 anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
8438 for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
4269bd1b 8439 {
3e05329c 8440 anArgVec.SetValue (anIt, theArgVec[anIt]);
4269bd1b 8441 }
8442
3e05329c 8443 return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
4269bd1b 8444 }
8445
8446 // change plane command
3e05329c 8447 TCollection_AsciiString aPlaneName;
8448 Handle(Graphic3d_ClipPlane) aClipPlane;
8449 Standard_Integer anArgIter = 0;
8450 if (aCommand == "-change"
8451 || aCommand == "change")
4269bd1b 8452 {
3e05329c 8453 // old syntax support
8454 if (theArgsNb < 3)
4269bd1b 8455 {
23fe70ec 8456 Message::SendFail ("Syntax error: need more arguments");
4269bd1b 8457 return 1;
8458 }
8459
3e05329c 8460 anArgIter = 3;
8461 aPlaneName = theArgVec[2];
8462 if (!aRegPlanes.Find (aPlaneName, aClipPlane))
4269bd1b 8463 {
23fe70ec 8464 Message::SendFail() << "Error: no such plane '" << aPlaneName << "'";
4269bd1b 8465 return 1;
8466 }
3e05329c 8467 }
8468 else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
8469 {
8470 anArgIter = 2;
8471 aPlaneName = theArgVec[1];
8472 }
8473 else
8474 {
8475 anArgIter = 2;
8476 aPlaneName = theArgVec[1];
8477 aClipPlane = new Graphic3d_ClipPlane();
8478 aRegPlanes.Bind (aPlaneName, aClipPlane);
8479 theDi << "Created new plane " << aPlaneName << ".\n";
8480 }
4269bd1b 8481
3e05329c 8482 if (theArgsNb - anArgIter < 1)
8483 {
23fe70ec 8484 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8485 return 1;
8486 }
4269bd1b 8487
3e05329c 8488 for (; anArgIter < theArgsNb; ++anArgIter)
8489 {
8490 const char** aChangeArgs = theArgVec + anArgIter;
8491 Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
8492 TCollection_AsciiString aChangeArg (aChangeArgs[0]);
8493 aChangeArg.LowerCase();
4269bd1b 8494
3e05329c 8495 Standard_Boolean toEnable = Standard_True;
dae2a922 8496 if (Draw::ParseOnOff (aChangeArgs[0], toEnable))
4269bd1b 8497 {
3e05329c 8498 aClipPlane->SetOn (toEnable);
4269bd1b 8499 }
25c35042 8500 else if (aChangeArg.StartsWith ("-equation")
8501 || aChangeArg.StartsWith ("equation"))
4269bd1b 8502 {
3e05329c 8503 if (aNbChangeArgs < 5)
4269bd1b 8504 {
23fe70ec 8505 Message::SendFail ("Syntax error: need more arguments");
4269bd1b 8506 return 1;
8507 }
8508
25c35042 8509 Standard_Integer aSubIndex = 1;
8510 Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
8511 if (aPrefixLen < aChangeArg.Length())
8512 {
8513 TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
8514 if (!aSubStr.IsIntegerValue()
8515 || aSubStr.IntegerValue() <= 0)
8516 {
23fe70ec 8517 Message::SendFail() << "Syntax error: unknown argument '" << aChangeArg << "'";
25c35042 8518 return 1;
8519 }
8520 aSubIndex = aSubStr.IntegerValue();
8521 }
8522
8523 Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
8524 Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
8525 Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
8526 Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
8527 Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8528 for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
8529 {
8530 if (aSubPln->ChainNextPlane().IsNull())
8531 {
8532 aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8533 }
8534 aSubPln = aSubPln->ChainNextPlane();
8535 }
8536 aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8537 aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
3e05329c 8538 anArgIter += 4;
4269bd1b 8539 }
25c35042 8540 else if ((aChangeArg == "-boxinterior"
8541 || aChangeArg == "-boxint"
8542 || aChangeArg == "-box")
8543 && aNbChangeArgs >= 7)
8544 {
8545 Graphic3d_BndBox3d aBndBox;
8546 aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
8547 aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
8548 anArgIter += 6;
8549
8550 Standard_Integer aNbSubPlanes = 6;
8551 const Graphic3d_Vec3d aDirArray[6] =
8552 {
8553 Graphic3d_Vec3d (-1, 0, 0),
8554 Graphic3d_Vec3d ( 1, 0, 0),
8555 Graphic3d_Vec3d ( 0,-1, 0),
8556 Graphic3d_Vec3d ( 0, 1, 0),
8557 Graphic3d_Vec3d ( 0, 0,-1),
8558 Graphic3d_Vec3d ( 0, 0, 1),
8559 };
8560 Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
8561 for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
8562 {
8563 const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
8564 const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
8565 aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
8566 if (aSubPlaneIter + 1 == aNbSubPlanes)
8567 {
8568 aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
8569 }
8570 else
8571 {
8572 aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
8573 }
8574 aSubPln = aSubPln->ChainNextPlane();
8575 }
8576 }
3e05329c 8577 else if (aChangeArg == "-capping"
8578 || aChangeArg == "capping")
4269bd1b 8579 {
3e05329c 8580 if (aNbChangeArgs < 2)
4269bd1b 8581 {
23fe70ec 8582 Message::SendFail ("Syntax error: need more arguments");
4269bd1b 8583 return 1;
8584 }
8585
dae2a922 8586 if (Draw::ParseOnOff (aChangeArgs[1], toEnable))
4269bd1b 8587 {
3e05329c 8588 aClipPlane->SetCapping (toEnable);
8589 anArgIter += 1;
8590 }
8591 else
8592 {
8593 // just skip otherwise (old syntax)
8594 }
8595 }
8596 else if (aChangeArg == "-useobjectmaterial"
8597 || aChangeArg == "-useobjectmat"
8598 || aChangeArg == "-useobjmat"
8599 || aChangeArg == "-useobjmaterial")
8600 {
8601 if (aNbChangeArgs < 2)
8602 {
23fe70ec 8603 Message::SendFail ("Syntax error: need more arguments");
4269bd1b 8604 return 1;
8605 }
8606
dae2a922 8607 if (Draw::ParseOnOff (aChangeArgs[1], toEnable))
4269bd1b 8608 {
3e05329c 8609 aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
8610 anArgIter += 1;
4269bd1b 8611 }
3e05329c 8612 }
8613 else if (aChangeArg == "-useobjecttexture"
8614 || aChangeArg == "-useobjecttex"
8615 || aChangeArg == "-useobjtexture"
8616 || aChangeArg == "-useobjtex")
8617 {
8618 if (aNbChangeArgs < 2)
4269bd1b 8619 {
23fe70ec 8620 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8621 return 1;
8622 }
4269bd1b 8623
dae2a922 8624 if (Draw::ParseOnOff (aChangeArgs[1], toEnable))
3e05329c 8625 {
8626 aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
8627 anArgIter += 1;
8628 }
8629 }
8630 else if (aChangeArg == "-useobjectshader"
8631 || aChangeArg == "-useobjshader")
8632 {
8633 if (aNbChangeArgs < 2)
8634 {
23fe70ec 8635 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8636 return 1;
8637 }
4269bd1b 8638
dae2a922 8639 if (Draw::ParseOnOff (aChangeArgs[1], toEnable))
3e05329c 8640 {
8641 aClipPlane->SetUseObjectShader (toEnable == Standard_True);
8642 anArgIter += 1;
4269bd1b 8643 }
3e05329c 8644 }
8645 else if (aChangeArg == "-color"
8646 || aChangeArg == "color")
8647 {
8648 Quantity_Color aColor;
dae2a922 8649 Standard_Integer aNbParsed = Draw::ParseColor (aNbChangeArgs - 1,
8650 aChangeArgs + 1,
8651 aColor);
3e05329c 8652 if (aNbParsed == 0)
4269bd1b 8653 {
23fe70ec 8654 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8655 return 1;
8656 }
61168418 8657 aClipPlane->SetCappingColor (aColor);
3e05329c 8658 anArgIter += aNbParsed;
8659 }
61168418 8660 else if (aNbChangeArgs >= 1
8661 && (aChangeArg == "-material"
8662 || aChangeArg == "material"))
8663 {
8664 ++anArgIter;
8665 Graphic3d_NameOfMaterial aMatName;
8666 if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeArgs[1], aMatName))
8667 {
23fe70ec 8668 Message::SendFail() << "Syntax error: unknown material '" << aChangeArgs[1] << "'";
61168418 8669 return 1;
8670 }
8671 aClipPlane->SetCappingMaterial (aMatName);
8672 }
1b661a81 8673 else if ((aChangeArg == "-transparency"
8674 || aChangeArg == "-transp")
8675 && aNbChangeArgs >= 2)
8676 {
8677 TCollection_AsciiString aValStr (aChangeArgs[1]);
8678 Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
d45edf24 8679 if (aValStr.IsRealValue (Standard_True))
1b661a81 8680 {
8681 Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
8682 aMat.SetTransparency ((float )aValStr.RealValue());
8683 anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
8684 aClipPlane->SetCappingMaterial (aMat);
8685 }
8686 else
8687 {
8688 aValStr.LowerCase();
8689 Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
8690 if (aValStr == "opaque")
8691 {
8692 aMode = Graphic3d_AlphaMode_Opaque;
8693 }
8694 else if (aValStr == "mask")
8695 {
8696 aMode = Graphic3d_AlphaMode_Mask;
8697 }
8698 else if (aValStr == "blend")
8699 {
8700 aMode = Graphic3d_AlphaMode_Blend;
8701 }
33425a46 8702 else if (aValStr == "maskblend"
8703 || aValStr == "blendmask")
8704 {
8705 aMode = Graphic3d_AlphaMode_MaskBlend;
8706 }
1b661a81 8707 else if (aValStr == "blendauto")
8708 {
8709 aMode = Graphic3d_AlphaMode_BlendAuto;
8710 }
8711 else
8712 {
23fe70ec 8713 Message::SendFail() << "Syntax error at '" << aValStr << "'";
1b661a81 8714 return 1;
8715 }
8716 anAspect->SetAlphaMode (aMode);
8717 aClipPlane->SetCappingAspect (anAspect);
8718 }
8719 anArgIter += 1;
8720 }
3e05329c 8721 else if (aChangeArg == "-texname"
8722 || aChangeArg == "texname")
8723 {
8724 if (aNbChangeArgs < 2)
8725 {
23fe70ec 8726 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8727 return 1;
8728 }
4269bd1b 8729
3e05329c 8730 TCollection_AsciiString aTextureName (aChangeArgs[1]);
633084b8 8731 Handle(Graphic3d_Texture2D) aTexture = new Graphic3d_Texture2D (aTextureName);
3e05329c 8732 if (!aTexture->IsDone())
8733 {
8734 aClipPlane->SetCappingTexture (NULL);
4269bd1b 8735 }
3e05329c 8736 else
4269bd1b 8737 {
3e05329c 8738 aTexture->EnableModulate();
8739 aTexture->EnableRepeat();
8740 aClipPlane->SetCappingTexture (aTexture);
8741 }
8742 anArgIter += 1;
8743 }
8744 else if (aChangeArg == "-texscale"
8745 || aChangeArg == "texscale")
8746 {
8747 if (aClipPlane->CappingTexture().IsNull())
8748 {
23fe70ec 8749 Message::SendFail ("Error: no texture is set");
3e05329c 8750 return 1;
8751 }
4269bd1b 8752
3e05329c 8753 if (aNbChangeArgs < 3)
8754 {
23fe70ec 8755 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8756 return 1;
8757 }
4269bd1b 8758
3e05329c 8759 Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8760 Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8761 aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
8762 anArgIter += 2;
8763 }
8764 else if (aChangeArg == "-texorigin"
8765 || aChangeArg == "texorigin") // texture origin
8766 {
8767 if (aClipPlane->CappingTexture().IsNull())
8768 {
23fe70ec 8769 Message::SendFail ("Error: no texture is set");
3e05329c 8770 return 1;
8771 }
4269bd1b 8772
3e05329c 8773 if (aNbChangeArgs < 3)
8774 {
23fe70ec 8775 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8776 return 1;
4269bd1b 8777 }
3e05329c 8778
8779 Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8780 Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
8781
8782 aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
8783 anArgIter += 2;
8784 }
8785 else if (aChangeArg == "-texrotate"
8786 || aChangeArg == "texrotate") // texture rotation
8787 {
8788 if (aClipPlane->CappingTexture().IsNull())
4269bd1b 8789 {
23fe70ec 8790 Message::SendFail ("Error: no texture is set");
3e05329c 8791 return 1;
8792 }
4269bd1b 8793
3e05329c 8794 if (aNbChangeArgs < 2)
8795 {
23fe70ec 8796 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8797 return 1;
8798 }
4269bd1b 8799
3e05329c 8800 Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
8801 aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
8802 anArgIter += 1;
8803 }
8804 else if (aChangeArg == "-hatch"
8805 || aChangeArg == "hatch")
8806 {
8807 if (aNbChangeArgs < 2)
8808 {
23fe70ec 8809 Message::SendFail ("Syntax error: need more arguments");
3e05329c 8810 return 1;
8811 }
4269bd1b 8812
3e05329c 8813 TCollection_AsciiString aHatchStr (aChangeArgs[1]);
8814 aHatchStr.LowerCase();
8815 if (aHatchStr == "on")
8816 {
8817 aClipPlane->SetCappingHatchOn();
8818 }
8819 else if (aHatchStr == "off")
8820 {
8821 aClipPlane->SetCappingHatchOff();
4269bd1b 8822 }
3e05329c 8823 else
4269bd1b 8824 {
3e05329c 8825 aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
8826 }
8827 anArgIter += 1;
8828 }
8829 else if (aChangeArg == "-delete"
8830 || aChangeArg == "delete")
8831 {
8832 removePlane (aRegPlanes, aPlaneName);
8833 return 0;
8834 }
8835 else if (aChangeArg == "-set"
32ca7711 8836 || aChangeArg == "-unset"
8837 || aChangeArg == "-setoverrideglobal")
3e05329c 8838 {
8839 // set / unset plane command
32ca7711 8840 const Standard_Boolean toSet = aChangeArg.StartsWith ("-set");
8841 const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
3e05329c 8842 Standard_Integer anIt = 1;
8843 for (; anIt < aNbChangeArgs; ++anIt)
8844 {
8845 TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
8846 if (anEntityName.IsEmpty()
8847 || anEntityName.Value (1) == '-')
4269bd1b 8848 {
3e05329c 8849 break;
4269bd1b 8850 }
32ca7711 8851 else if (!toOverrideGlobal
8852 && ViewerTest_myViews.IsBound1 (anEntityName))
4269bd1b 8853 {
b2fedee6 8854 const Handle(V3d_View)& aView = ViewerTest_myViews.Find1 (anEntityName);
3e05329c 8855 if (toSet)
8856 {
8857 aView->AddClipPlane (aClipPlane);
8858 }
8859 else
8860 {
8861 aView->RemoveClipPlane (aClipPlane);
8862 }
8863 continue;
4269bd1b 8864 }
3e05329c 8865 else if (GetMapOfAIS().IsBound2 (anEntityName))
4269bd1b 8866 {
8f521168 8867 Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
3e05329c 8868 if (toSet)
8869 {
8870 aIObj->AddClipPlane (aClipPlane);
8871 }
8872 else
8873 {
8874 aIObj->RemoveClipPlane (aClipPlane);
8875 }
32ca7711 8876 if (!aIObj->ClipPlanes().IsNull())
8877 {
8878 aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
8879 }
4269bd1b 8880 }
3e05329c 8881 else
4269bd1b 8882 {
23fe70ec 8883 Message::SendFail() << "Error: object/view '" << anEntityName << "' is not found";
3e05329c 8884 return 1;
4269bd1b 8885 }
3e05329c 8886 }
8887
8888 if (anIt == 1)
8889 {
8890 // apply to active view
8891 if (toSet)
4269bd1b 8892 {
3e05329c 8893 anActiveView->AddClipPlane (aClipPlane);
4269bd1b 8894 }
8895 else
8896 {
3e05329c 8897 anActiveView->RemoveClipPlane (aClipPlane);
4269bd1b 8898 }
8899 }
3e05329c 8900 else
8901 {
8902 anArgIter = anArgIter + anIt - 1;
8903 }
8904 }
8905 else
8906 {
23fe70ec 8907 Message::SendFail() << "Syntax error: unknown argument '" << aChangeArg << "'";
3e05329c 8908 return 1;
4269bd1b 8909 }
4269bd1b 8910 }
8911
3e05329c 8912 ViewerTest::RedrawAllViews();
8913 return 0;
4269bd1b 8914}
8915
b5ac8292 8916//===============================================================================================
8917//function : VZRange
8918//purpose :
8919//===============================================================================================
8920static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8921{
197ac94e 8922 const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8923
8924 if (aCurrentView.IsNull())
b5ac8292 8925 {
23fe70ec 8926 Message::SendFail ("Error: no active viewer");
b5ac8292 8927 return 1;
8928 }
8929
197ac94e 8930 Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
b5ac8292 8931
8932 if (theArgsNb < 2)
8933 {
8934 theDi << "ZNear: " << aCamera->ZNear() << "\n";
8935 theDi << "ZFar: " << aCamera->ZFar() << "\n";
8936 return 0;
8937 }
8938
8939 if (theArgsNb == 3)
8940 {
6b62b2da 8941 Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
8942 Standard_Real aNewZFar = Draw::Atof (theArgVec[2]);
197ac94e 8943
8944 if (aNewZNear >= aNewZFar)
8945 {
23fe70ec 8946 Message::SendFail ("Syntax error: invalid arguments: znear should be less than zfar");
197ac94e 8947 return 1;
8948 }
8949
8950 if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
8951 {
23fe70ec 8952 Message::SendFail ("Syntax error: invalid arguments: znear, zfar should be positive for perspective camera");
197ac94e 8953 return 1;
8954 }
8955
8956 aCamera->SetZRange (aNewZNear, aNewZFar);
b5ac8292 8957 }
8958 else
8959 {
23fe70ec 8960 Message::SendFail ("Syntax error: wrong command arguments");
b5ac8292 8961 return 1;
8962 }
8963
197ac94e 8964 aCurrentView->Redraw();
8965
b5ac8292 8966 return 0;
8967}
8968
8969//===============================================================================================
8970//function : VAutoZFit
8971//purpose :
8972//===============================================================================================
8973static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
8974{
197ac94e 8975 const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
8976
8977 if (aCurrentView.IsNull())
b5ac8292 8978 {
23fe70ec 8979 Message::SendFail ("Error: no active viewer");
b5ac8292 8980 return 1;
8981 }
8982
c357e426 8983 Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
197ac94e 8984
8985 if (theArgsNb > 3)
b5ac8292 8986 {
23fe70ec 8987 Message::SendFail ("Syntax error: wrong command arguments");
197ac94e 8988 return 1;
b5ac8292 8989 }
8990
197ac94e 8991 if (theArgsNb < 2)
b5ac8292 8992 {
586db386 8993 theDi << "Auto z-fit mode: \n"
c357e426 8994 << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
197ac94e 8995 << "Scale: " << aScale << "\n";
8996 return 0;
b5ac8292 8997 }
197ac94e 8998
8999 Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9000
9001 if (theArgsNb >= 3)
b5ac8292 9002 {
197ac94e 9003 aScale = Draw::Atoi (theArgVec[2]);
b5ac8292 9004 }
9005
c357e426 9006 aCurrentView->SetAutoZFitMode (isOn, aScale);
197ac94e 9007 aCurrentView->Redraw();
b5ac8292 9008 return 0;
9009}
9010
6b62b2da 9011//! Auxiliary function to print projection type
9012inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9013{
9014 switch (theProjType)
9015 {
9016 case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9017 case Graphic3d_Camera::Projection_Perspective: return "perspective";
9018 case Graphic3d_Camera::Projection_Stereo: return "stereoscopic";
9019 case Graphic3d_Camera::Projection_MonoLeftEye: return "monoLeftEye";
9020 case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9021 }
9022 return "UNKNOWN";
9023}
9024
b5ac8292 9025//===============================================================================================
6b62b2da 9026//function : VCamera
b5ac8292 9027//purpose :
9028//===============================================================================================
6b62b2da 9029static int VCamera (Draw_Interpretor& theDI,
9030 Standard_Integer theArgsNb,
9031 const char** theArgVec)
b5ac8292 9032{
6b62b2da 9033 Handle(V3d_View) aView = ViewerTest::CurrentView();
9034 if (aView.IsNull())
b5ac8292 9035 {
23fe70ec 9036 Message::SendFail ("Error: no active viewer");
b5ac8292 9037 return 1;
9038 }
9039
6b62b2da 9040 Handle(Graphic3d_Camera) aCamera = aView->Camera();
9041 if (theArgsNb < 2)
b5ac8292 9042 {
6b62b2da 9043 theDI << "ProjType: " << projTypeName (aCamera->ProjectionType()) << "\n";
9044 theDI << "FOVy: " << aCamera->FOVy() << "\n";
b40cdc2b 9045 theDI << "FOVx: " << aCamera->FOVx() << "\n";
9046 theDI << "FOV2d: " << aCamera->FOV2d() << "\n";
6b62b2da 9047 theDI << "Distance: " << aCamera->Distance() << "\n";
9048 theDI << "IOD: " << aCamera->IOD() << "\n";
9049 theDI << "IODType: " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute ? "absolute" : "relative") << "\n";
9050 theDI << "ZFocus: " << aCamera->ZFocus() << "\n";
9051 theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
168c27c6 9052 theDI << "ZNear: " << aCamera->ZNear() << "\n";
9053 theDI << "ZFar: " << aCamera->ZFar() << "\n";
6b62b2da 9054 return 0;
b5ac8292 9055 }
9056
30a1b24e 9057 TCollection_AsciiString aPrsName;
6b62b2da 9058 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
b5ac8292 9059 {
6b62b2da 9060 Standard_CString anArg = theArgVec[anArgIter];
9061 TCollection_AsciiString anArgCase (anArg);
9062 anArgCase.LowerCase();
9063 if (anArgCase == "-proj"
9064 || anArgCase == "-projection"
9065 || anArgCase == "-projtype"
9066 || anArgCase == "-projectiontype")
9067 {
9068 theDI << projTypeName (aCamera->ProjectionType()) << " ";
9069 }
9070 else if (anArgCase == "-ortho"
9071 || anArgCase == "-orthographic")
b5ac8292 9072 {
9073 aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
6b62b2da 9074 }
9075 else if (anArgCase == "-persp"
9076 || anArgCase == "-perspective"
9077 || anArgCase == "-perspmono"
9078 || anArgCase == "-perspectivemono"
9079 || anArgCase == "-mono")
b5ac8292 9080 {
9081 aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9082 }
6b62b2da 9083 else if (anArgCase == "-stereo"
9084 || anArgCase == "-stereoscopic"
9085 || anArgCase == "-perspstereo"
9086 || anArgCase == "-perspectivestereo")
9087 {
9088 aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9089 }
9090 else if (anArgCase == "-left"
9091 || anArgCase == "-lefteye"
9092 || anArgCase == "-monoleft"
9093 || anArgCase == "-monolefteye"
9094 || anArgCase == "-perpsleft"
9095 || anArgCase == "-perpslefteye")
b5ac8292 9096 {
9097 aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
9098 }
6b62b2da 9099 else if (anArgCase == "-right"
9100 || anArgCase == "-righteye"
9101 || anArgCase == "-monoright"
9102 || anArgCase == "-monorighteye"
9103 || anArgCase == "-perpsright")
b5ac8292 9104 {
9105 aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
9106 }
6b62b2da 9107 else if (anArgCase == "-dist"
9108 || anArgCase == "-distance")
b5ac8292 9109 {
6b62b2da 9110 Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9111 if (anArgValue != NULL
9112 && *anArgValue != '-')
9113 {
9114 ++anArgIter;
9115 aCamera->SetDistance (Draw::Atof (anArgValue));
9116 continue;
9117 }
9118 theDI << aCamera->Distance() << " ";
b5ac8292 9119 }
6b62b2da 9120 else if (anArgCase == "-iod")
b5ac8292 9121 {
6b62b2da 9122 Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9123 if (anArgValue != NULL
9124 && *anArgValue != '-')
9125 {
9126 ++anArgIter;
9127 aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
9128 continue;
9129 }
9130 theDI << aCamera->IOD() << " ";
b5ac8292 9131 }
6b62b2da 9132 else if (anArgCase == "-iodtype")
b5ac8292 9133 {
6b62b2da 9134 Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9135 TCollection_AsciiString anValueCase (anArgValue);
9136 anValueCase.LowerCase();
9137 if (anValueCase == "abs"
9138 || anValueCase == "absolute")
9139 {
9140 ++anArgIter;
9141 aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
9142 continue;
9143 }
9144 else if (anValueCase == "rel"
9145 || anValueCase == "relative")
9146 {
9147 ++anArgIter;
9148 aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
9149 continue;
9150 }
9151 else if (*anArgValue != '-')
9152 {
23fe70ec 9153 Message::SendFail() << "Error: unknown IOD type '" << anArgValue << "'";
6b62b2da 9154 return 1;
9155 }
9156 switch (aCamera->GetIODType())
9157 {
9158 case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
9159 case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
9160 }
b5ac8292 9161 }
6b62b2da 9162 else if (anArgCase == "-zfocus")
b5ac8292 9163 {
6b62b2da 9164 Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9165 if (anArgValue != NULL
9166 && *anArgValue != '-')
9167 {
9168 ++anArgIter;
9169 aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
9170 continue;
9171 }
9172 theDI << aCamera->ZFocus() << " ";
b5ac8292 9173 }
6b62b2da 9174 else if (anArgCase == "-zfocustype")
b5ac8292 9175 {
6b62b2da 9176 Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9177 TCollection_AsciiString anValueCase (anArgValue);
9178 anValueCase.LowerCase();
9179 if (anValueCase == "abs"
9180 || anValueCase == "absolute")
9181 {
9182 ++anArgIter;
9183 aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
9184 continue;
9185 }
9186 else if (anValueCase == "rel"
9187 || anValueCase == "relative")
9188 {
9189 ++anArgIter;
9190 aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
9191 continue;
9192 }
9193 else if (*anArgValue != '-')
9194 {
23fe70ec 9195 Message::SendFail() << "Error: unknown ZFocus type '" << anArgValue << "'";
6b62b2da 9196 return 1;
9197 }
9198 switch (aCamera->ZFocusType())
9199 {
9200 case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
9201 case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
9202 }
9203 }
b40cdc2b 9204 else if (anArgCase == "-lockzup"
9205 || anArgCase == "-turntable")
9206 {
9207 bool toLockUp = true;
9208 if (++anArgIter < theArgsNb
dae2a922 9209 && !Draw::ParseOnOff (theArgVec[anArgIter], toLockUp))
b40cdc2b 9210 {
9211 --anArgIter;
9212 }
9213 ViewerTest::CurrentEventManager()->SetLockOrbitZUp (toLockUp);
9214 }
e1aa4ee3 9215 else if (anArgCase == "-rotationmode"
9216 || anArgCase == "-rotmode")
9217 {
9218 AIS_RotationMode aRotMode = AIS_RotationMode_BndBoxActive;
9219 TCollection_AsciiString aRotStr ((anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "");
9220 aRotStr.LowerCase();
9221 if (aRotStr == "bndboxactive"
9222 || aRotStr == "active")
9223 {
9224 aRotMode = AIS_RotationMode_BndBoxActive;
9225 }
9226 else if (aRotStr == "picklast"
9227 || aRotStr == "pick")
9228 {
9229 aRotMode = AIS_RotationMode_PickLast;
9230 }
9231 else if (aRotStr == "pickcenter")
9232 {
9233 aRotMode = AIS_RotationMode_PickCenter;
9234 }
9235 else if (aRotStr == "cameraat"
9236 || aRotStr == "cameracenter")
9237 {
9238 aRotMode = AIS_RotationMode_CameraAt;
9239 }
9240 else if (aRotStr == "bndboxscene"
9241 || aRotStr == "boxscene")
9242 {
9243 aRotMode = AIS_RotationMode_BndBoxScene;
9244 }
9245 else
9246 {
9247 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
9248 return 1;
9249 }
9250
9251 ViewerTest::CurrentEventManager()->SetRotationMode (aRotMode);
9252 ++anArgIter;
9253 }
9254 else if (anArgCase == "-navigationmode"
9255 || anArgCase == "-navmode")
9256 {
9257 AIS_NavigationMode aNavMode = AIS_NavigationMode_Orbit;
9258 TCollection_AsciiString aNavStr ((anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "");
9259 aNavStr.LowerCase();
9260 if (aNavStr == "orbit")
9261 {
9262 aNavMode = AIS_NavigationMode_Orbit;
9263 }
9264 else if (aNavStr == "flight"
9265 || aNavStr == "fly"
9266 || aNavStr == "copter"
9267 || aNavStr == "helicopter")
9268 {
9269 aNavMode = AIS_NavigationMode_FirstPersonFlight;
9270 }
9271 else if (aNavStr == "walk"
9272 || aNavStr == "shooter")
9273 {
9274 aNavMode = AIS_NavigationMode_FirstPersonWalk;
9275 }
9276 else
9277 {
9278 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
9279 return 1;
9280 }
9281
9282 Handle(ViewerTest_EventManager) aViewMgr = ViewerTest::CurrentEventManager();
9283 aViewMgr->SetNavigationMode (aNavMode);
9284 if (aNavMode == AIS_NavigationMode_Orbit)
9285 {
9286 aViewMgr->ChangeMouseGestureMap().Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit);
9287 }
9288 else
9289 {
9290 aViewMgr->ChangeMouseGestureMap().Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateView);
9291 }
9292 ++anArgIter;
9293 }
6b62b2da 9294 else if (anArgCase == "-fov"
b40cdc2b 9295 || anArgCase == "-fovy"
9296 || anArgCase == "-fovx"
9297 || anArgCase == "-fov2d")
b5ac8292 9298 {
6b62b2da 9299 Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9300 if (anArgValue != NULL
9301 && *anArgValue != '-')
9302 {
9303 ++anArgIter;
b40cdc2b 9304 if (anArgCase == "-fov2d")
9305 {
9306 aCamera->SetFOV2d (Draw::Atof (anArgValue));
9307 }
9308 else if (anArgCase == "-fovx")
9309 {
9310 aCamera->SetFOVy (Draw::Atof (anArgValue) / aCamera->Aspect());///
9311 }
9312 else
9313 {
9314 aCamera->SetFOVy (Draw::Atof (anArgValue));
9315 }
6b62b2da 9316 continue;
9317 }
b40cdc2b 9318 if (anArgCase == "-fov2d")
9319 {
9320 theDI << aCamera->FOV2d() << " ";
9321 }
9322 else if (anArgCase == "-fovx")
9323 {
9324 theDI << aCamera->FOVx() << " ";
9325 }
9326 else
9327 {
9328 theDI << aCamera->FOVy() << " ";
9329 }
9330 }
9331 else if (anArgIter + 1 < theArgsNb
9332 && anArgCase == "-xrpose")
9333 {
9334 TCollection_AsciiString anXRArg (theArgVec[++anArgIter]);
9335 anXRArg.LowerCase();
9336 if (anXRArg == "base")
9337 {
9338 aCamera = aView->View()->BaseXRCamera();
9339 }
9340 else if (anXRArg == "head")
9341 {
9342 aCamera = aView->View()->PosedXRCamera();
9343 }
9344 else
9345 {
9346 Message::SendFail() << "Syntax error: unknown XR pose '" << anXRArg << "'";
9347 return 1;
9348 }
9349 if (aCamera.IsNull())
9350 {
9351 Message::SendFail() << "Error: undefined XR pose";
9352 return 0;
9353 }
9354 if (aView->AutoZFitMode())
9355 {
9356 const Bnd_Box aMinMaxBox = aView->View()->MinMaxValues (false);
9357 const Bnd_Box aGraphicBox = aView->View()->MinMaxValues (true);
9358 aCamera->ZFitAll (aView->AutoZFitScaleFactor(), aMinMaxBox, aGraphicBox);
9359 }
b5ac8292 9360 }
30a1b24e 9361 else if (aPrsName.IsEmpty()
9362 && !anArgCase.StartsWith ("-"))
9363 {
9364 aPrsName = anArg;
9365 }
b5ac8292 9366 else
9367 {
23fe70ec 9368 Message::SendFail() << "Error: unknown argument '" << anArg << "'";
b5ac8292 9369 return 1;
9370 }
9371 }
b5ac8292 9372
30a1b24e 9373 if (aPrsName.IsEmpty()
9374 || theArgsNb > 2)
9375 {
30a1b24e 9376 aView->Redraw();
9377 }
9378
9379 if (!aPrsName.IsEmpty())
9380 {
9381 Handle(AIS_CameraFrustum) aCameraFrustum;
9382 if (GetMapOfAIS().IsBound2 (aPrsName))
9383 {
9384 // find existing object
9385 aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
9386 if (aCameraFrustum.IsNull())
9387 {
23fe70ec 9388 Message::SendFail() << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum";
30a1b24e 9389 return 1;
9390 }
9391 }
9392
9393 if (aCameraFrustum.IsNull())
9394 {
9395 aCameraFrustum = new AIS_CameraFrustum();
9396 }
9397 else
9398 {
9399 // not include displayed object of old camera frustum in the new one.
9400 ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
9401 aView->ZFitAll();
9402 }
b40cdc2b 9403 aCameraFrustum->SetCameraFrustum (aCamera);
30a1b24e 9404
9405 ViewerTest::Display (aPrsName, aCameraFrustum);
9406 }
b5ac8292 9407
9408 return 0;
9409}
9410
f978241f 9411//! Parse stereo output mode
9412inline Standard_Boolean parseStereoMode (Standard_CString theArg,
9413 Graphic3d_StereoMode& theMode)
9414{
9415 TCollection_AsciiString aFlag (theArg);
9416 aFlag.LowerCase();
9417 if (aFlag == "quadbuffer")
9418 {
9419 theMode = Graphic3d_StereoMode_QuadBuffer;
9420 }
9421 else if (aFlag == "anaglyph")
9422 {
9423 theMode = Graphic3d_StereoMode_Anaglyph;
9424 }
9425 else if (aFlag == "row"
9426 || aFlag == "rowinterlaced")
9427 {
9428 theMode = Graphic3d_StereoMode_RowInterlaced;
9429 }
9430 else if (aFlag == "col"
9431 || aFlag == "colinterlaced"
9432 || aFlag == "columninterlaced")
9433 {
9434 theMode = Graphic3d_StereoMode_ColumnInterlaced;
9435 }
9436 else if (aFlag == "chess"
9437 || aFlag == "chessboard")
9438 {
9439 theMode = Graphic3d_StereoMode_ChessBoard;
9440 }
9441 else if (aFlag == "sbs"
9442 || aFlag == "sidebyside")
9443 {
9444 theMode = Graphic3d_StereoMode_SideBySide;
9445 }
9446 else if (aFlag == "ou"
9447 || aFlag == "overunder")
9448 {
9449 theMode = Graphic3d_StereoMode_OverUnder;
9450 }
9451 else if (aFlag == "pageflip"
9452 || aFlag == "softpageflip")
9453 {
9454 theMode = Graphic3d_StereoMode_SoftPageFlip;
9455 }
b40cdc2b 9456 else if (aFlag == "openvr"
9457 || aFlag == "vr")
9458 {
9459 theMode = Graphic3d_StereoMode_OpenVR;
9460 }
f978241f 9461 else
9462 {
9463 return Standard_False;
9464 }
9465 return Standard_True;
9466}
9467
9468//! Parse anaglyph filter
9469inline Standard_Boolean parseAnaglyphFilter (Standard_CString theArg,
9470 Graphic3d_RenderingParams::Anaglyph& theFilter)
9471{
9472 TCollection_AsciiString aFlag (theArg);
9473 aFlag.LowerCase();
9474 if (aFlag == "redcyansimple")
9475 {
9476 theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9477 }
9478 else if (aFlag == "redcyan"
9479 || aFlag == "redcyanoptimized")
9480 {
9481 theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
9482 }
9483 else if (aFlag == "yellowbluesimple")
9484 {
9485 theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
9486 }
9487 else if (aFlag == "yellowblue"
9488 || aFlag == "yellowblueoptimized")
9489 {
9490 theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
9491 }
9492 else if (aFlag == "greenmagenta"
9493 || aFlag == "greenmagentasimple")
9494 {
9495 theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
9496 }
9497 else
9498 {
9499 return Standard_False;
9500 }
9501 return Standard_True;
9502}
9503
b5ac8292 9504//==============================================================================
9505//function : VStereo
9506//purpose :
9507//==============================================================================
9508
9509static int VStereo (Draw_Interpretor& theDI,
9510 Standard_Integer theArgNb,
9511 const char** theArgVec)
9512{
f978241f 9513 Handle(V3d_View) aView = ViewerTest::CurrentView();
b8db9379 9514 if (aView.IsNull())
b5ac8292 9515 {
b8db9379 9516 Message::SendFail ("Error: no active viewer");
9517 return 0;
9518 }
b5ac8292 9519
b8db9379 9520 Handle(Graphic3d_Camera) aCamera = aView->Camera();
9521 Graphic3d_RenderingParams* aParams = &aView->ChangeRenderingParams();
9522 if (theArgNb < 2)
9523 {
9524 Standard_Boolean isActive = aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo;
b5ac8292 9525 theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
bf02aa7d 9526 if (isActive)
9527 {
9528 TCollection_AsciiString aMode;
9529 switch (aView->RenderingParams().StereoMode)
9530 {
2275caec 9531 case Graphic3d_StereoMode_QuadBuffer:
9532 {
9533 aMode = "quadBuffer";
9534 break;
9535 }
9536 case Graphic3d_StereoMode_RowInterlaced:
9537 {
9538 aMode = "rowInterlaced";
9539 if (aView->RenderingParams().ToSmoothInterlacing)
9540 {
9541 aMode.AssignCat (" (smoothed)");
9542 }
9543 break;
9544 }
9545 case Graphic3d_StereoMode_ColumnInterlaced:
9546 {
9547 aMode = "columnInterlaced";
9548 if (aView->RenderingParams().ToSmoothInterlacing)
9549 {
9550 aMode.AssignCat (" (smoothed)");
9551 }
9552 break;
9553 }
9554 case Graphic3d_StereoMode_ChessBoard:
9555 {
9556 aMode = "chessBoard";
9557 if (aView->RenderingParams().ToSmoothInterlacing)
9558 {
9559 aMode.AssignCat (" (smoothed)");
9560 }
9561 break;
9562 }
9563 case Graphic3d_StereoMode_SideBySide:
9564 {
9565 aMode = "sideBySide";
9566 break;
9567 }
9568 case Graphic3d_StereoMode_OverUnder:
9569 {
9570 aMode = "overUnder";
9571 break;
9572 }
9573 case Graphic3d_StereoMode_SoftPageFlip:
9574 {
9575 aMode = "softPageFlip";
9576 break;
9577 }
9578 case Graphic3d_StereoMode_OpenVR:
9579 {
9580 aMode = "openVR";
9581 break;
9582 }
9583 case Graphic3d_StereoMode_Anaglyph:
9584 {
bf02aa7d 9585 aMode = "anaglyph";
9586 switch (aView->RenderingParams().AnaglyphFilter)
9587 {
9588 case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple : aMode.AssignCat (" (redCyanSimple)"); break;
9589 case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized : aMode.AssignCat (" (redCyan)"); break;
9590 case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple : aMode.AssignCat (" (yellowBlueSimple)"); break;
9591 case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)"); break;
9592 case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
2275caec 9593 case Graphic3d_RenderingParams::Anaglyph_UserDefined : aMode.AssignCat (" (userDefined)"); break;
bf02aa7d 9594 }
2275caec 9595 }
bf02aa7d 9596 }
9597 theDI << "Mode " << aMode << "\n";
9598 }
b5ac8292 9599 return 0;
9600 }
9601
b8db9379 9602 Graphic3d_StereoMode aMode = aParams->StereoMode;
f978241f 9603 ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
9604 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
9605 {
9606 Standard_CString anArg = theArgVec[anArgIter];
9607 TCollection_AsciiString aFlag (anArg);
9608 aFlag.LowerCase();
9609 if (anUpdateTool.parseRedrawMode (aFlag))
9610 {
9611 continue;
9612 }
9613 else if (aFlag == "0"
9614 || aFlag == "off")
9615 {
9616 if (++anArgIter < theArgNb)
9617 {
23fe70ec 9618 Message::SendFail ("Error: wrong number of arguments");
f978241f 9619 return 1;
9620 }
9621
b8db9379 9622 if (aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
f978241f 9623 {
9624 aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9625 }
f978241f 9626 return 0;
9627 }
9628 else if (aFlag == "1"
9629 || aFlag == "on")
9630 {
9631 if (++anArgIter < theArgNb)
9632 {
23fe70ec 9633 Message::SendFail ("Error: wrong number of arguments");
f978241f 9634 return 1;
9635 }
9636
b8db9379 9637 aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
b40cdc2b 9638 if (aParams->StereoMode != Graphic3d_StereoMode_OpenVR)
9639 {
9640 return 0;
9641 }
f978241f 9642 }
9643 else if (aFlag == "-reverse"
2275caec 9644 || aFlag == "-noreverse"
f978241f 9645 || aFlag == "-reversed"
2275caec 9646 || aFlag == "-swap"
f978241f 9647 || aFlag == "-noswap")
9648 {
2275caec 9649 aParams->ToReverseStereo = Draw::ParseOnOffNoIterator (theArgNb, theArgVec, anArgIter);
f978241f 9650 }
9651 else if (aFlag == "-mode"
9652 || aFlag == "-stereomode")
9653 {
9654 if (++anArgIter >= theArgNb
9655 || !parseStereoMode (theArgVec[anArgIter], aMode))
9656 {
23fe70ec 9657 Message::SendFail() << "Syntax error at '" << anArg << "'";
f978241f 9658 return 1;
9659 }
9660
9661 if (aMode == Graphic3d_StereoMode_QuadBuffer)
9662 {
b8db9379 9663 Message::SendInfo() << "Warning: make sure to call 'vcaps -stereo 1' before creating a view";
f978241f 9664 }
9665 }
9666 else if (aFlag == "-anaglyph"
9667 || aFlag == "-anaglyphfilter")
9668 {
9669 Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
9670 if (++anArgIter >= theArgNb
9671 || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
9672 {
23fe70ec 9673 Message::SendFail() << "Syntax error at '" << anArg << "'";
f978241f 9674 return 1;
9675 }
9676
9677 aMode = Graphic3d_StereoMode_Anaglyph;
9678 aParams->AnaglyphFilter = aFilter;
9679 }
9680 else if (parseStereoMode (anArg, aMode)) // short syntax
9681 {
9682 if (aMode == Graphic3d_StereoMode_QuadBuffer)
9683 {
b8db9379 9684 Message::SendInfo() << "Warning: make sure to call 'vcaps -stereo 1' before creating a view";
f978241f 9685 }
9686 }
b40cdc2b 9687 else if (anArgIter + 1 < theArgNb
9688 && aFlag == "-hmdfov2d")
9689 {
9690 aParams->HmdFov2d = (float )Draw::Atof (theArgVec[++anArgIter]);
9691 if (aParams->HmdFov2d < 10.0f
9692 || aParams->HmdFov2d > 180.0f)
9693 {
9694 Message::SendFail() << "Error: FOV is out of range";
9695 return 1;
9696 }
9697 }
9698 else if (aFlag == "-mirror"
9699 || aFlag == "-mirrorcomposer")
9700 {
2275caec 9701 aParams->ToMirrorComposer = Draw::ParseOnOffNoIterator (theArgNb, theArgVec, anArgIter);;
9702 }
9703 else if (aFlag == "-smooth"
9704 || aFlag == "-nosmooth"
9705 || aFlag == "-smoothinterlacing"
9706 || aFlag == "-nosmoothinterlacing")
9707 {
9708 aParams->ToSmoothInterlacing = Draw::ParseOnOffNoIterator (theArgNb, theArgVec, anArgIter);
b40cdc2b 9709 }
9710 else if (anArgIter + 1 < theArgNb
9711 && (aFlag == "-unitfactor"
9712 || aFlag == "-unitscale"))
9713 {
9714 aView->View()->SetUnitFactor (Draw::Atof (theArgVec[++anArgIter]));
9715 }
f978241f 9716 else
9717 {
23fe70ec 9718 Message::SendFail() << "Syntax error at '" << anArg << "'";
f978241f 9719 return 1;
9720 }
9721 }
9722
b8db9379 9723 aParams->StereoMode = aMode;
9724 aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9725 if (aParams->StereoMode == Graphic3d_StereoMode_OpenVR)
f978241f 9726 {
b8db9379 9727 // initiate implicit continuous rendering
9728 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
f978241f 9729 }
b5ac8292 9730 return 0;
9731}
9732
392ac980 9733//===============================================================================================
9734//function : VDefaults
9735//purpose :
9736//===============================================================================================
9737static int VDefaults (Draw_Interpretor& theDi,
9738 Standard_Integer theArgsNb,
9739 const char** theArgVec)
9740{
9741 const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
9742 if (aCtx.IsNull())
9743 {
23fe70ec 9744 Message::SendFail ("Error: no active viewer");
392ac980 9745 return 1;
9746 }
9747
9748 Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
9749 if (theArgsNb < 2)
9750 {
9751 if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
9752 {
9753 theDi << "DeflType: relative\n"
9754 << "DeviationCoeff: " << aDefParams->DeviationCoefficient() << "\n";
9755 }
9756 else
9757 {
9758 theDi << "DeflType: absolute\n"
9759 << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
9760 }
67441d0c 9761 theDi << "AngularDeflection: " << (180.0 * aDefParams->DeviationAngle() / M_PI) << "\n";
4c513386 9762 theDi << "AutoTriangulation: " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
392ac980 9763 return 0;
9764 }
9765
9766 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9767 {
9768 TCollection_AsciiString anArg (theArgVec[anArgIter]);
4c513386 9769 anArg.UpperCase();
9770 if (anArg == "-ABSDEFL"
9771 || anArg == "-ABSOLUTEDEFLECTION"
9772 || anArg == "-DEFL"
9773 || anArg == "-DEFLECTION")
392ac980 9774 {
4c513386 9775 if (++anArgIter >= theArgsNb)
9776 {
23fe70ec 9777 Message::SendFail() << "Syntax error at " << anArg;
4c513386 9778 return 1;
9779 }
392ac980 9780 aDefParams->SetTypeOfDeflection (Aspect_TOD_ABSOLUTE);
4c513386 9781 aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
392ac980 9782 }
4c513386 9783 else if (anArg == "-RELDEFL"
9784 || anArg == "-RELATIVEDEFLECTION"
9785 || anArg == "-DEVCOEFF"
9786 || anArg == "-DEVIATIONCOEFF"
9787 || anArg == "-DEVIATIONCOEFFICIENT")
392ac980 9788 {
4c513386 9789 if (++anArgIter >= theArgsNb)
9790 {
23fe70ec 9791 Message::SendFail() << "Syntax error at " << anArg;
4c513386 9792 return 1;
9793 }
392ac980 9794 aDefParams->SetTypeOfDeflection (Aspect_TOD_RELATIVE);
4c513386 9795 aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
392ac980 9796 }
4c513386 9797 else if (anArg == "-ANGDEFL"
9798 || anArg == "-ANGULARDEFL"
9799 || anArg == "-ANGULARDEFLECTION")
392ac980 9800 {
4c513386 9801 if (++anArgIter >= theArgsNb)
9802 {
23fe70ec 9803 Message::SendFail() << "Syntax error at " << anArg;
4c513386 9804 return 1;
9805 }
67441d0c 9806 aDefParams->SetDeviationAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
4c513386 9807 }
385c43e7 9808 else if (anArg == "-AUTOTR"
9809 || anArg == "-AUTOTRIANG"
9810 || anArg == "-AUTOTRIANGULATION")
4c513386 9811 {
14c7f553 9812 ++anArgIter;
9813 bool toTurnOn = true;
9814 if (anArgIter >= theArgsNb
dae2a922 9815 || !Draw::ParseOnOff (theArgVec[anArgIter], toTurnOn))
4c513386 9816 {
23fe70ec 9817 Message::SendFail() << "Syntax error at '" << anArg << "'";
4c513386 9818 return 1;
9819 }
14c7f553 9820 aDefParams->SetAutoTriangulation (toTurnOn);
392ac980 9821 }
9822 else
9823 {
23fe70ec 9824 Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
14c7f553 9825 return 1;
392ac980 9826 }
9827 }
9828
9829 return 0;
9830}
9831
06d40093 9832//! Parse light source type from string.
9833static bool parseLightSourceType (const TCollection_AsciiString& theTypeName,
9834 Graphic3d_TypeOfLightSource& theType)
12381341 9835{
06d40093 9836 TCollection_AsciiString aType (theTypeName);
9837 aType.LowerCase();
9838 if (aType == "amb"
9839 || aType == "ambient"
9840 || aType == "amblight")
12381341 9841 {
06d40093 9842 theType = Graphic3d_TypeOfLightSource_Ambient;
12381341 9843 }
06d40093 9844 else if (aType == "directional"
9845 || aType == "dirlight")
12381341 9846 {
06d40093 9847 theType = Graphic3d_TypeOfLightSource_Directional;
12381341 9848 }
06d40093 9849 else if (aType == "spot"
9850 || aType == "spotlight")
12381341 9851 {
06d40093 9852 theType = Graphic3d_TypeOfLightSource_Spot;
12381341 9853 }
06d40093 9854 else if (aType == "poslight"
9855 || aType == "positional"
9856 || aType == "point"
9857 || aType == "pnt")
12381341 9858 {
06d40093 9859 theType = Graphic3d_TypeOfLightSource_Positional;
12381341 9860 }
9861 else
9862 {
06d40093 9863 return false;
12381341 9864 }
06d40093 9865 return true;
12381341 9866}
9867
06d40093 9868//! Find existing light by name or index.
9869static Handle(V3d_Light) findLightSource (const TCollection_AsciiString& theName)
2daa5d95 9870{
06d40093 9871 Handle(V3d_Light) aLight;
9872 Standard_Integer aLightIndex = -1;
9873 Draw::ParseInteger (theName.ToCString(), aLightIndex);
9874 Standard_Integer aLightIt = 0;
9875 Handle(V3d_View) aView = ViewerTest::CurrentView();
9876 for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
2daa5d95 9877 {
06d40093 9878 if (aLightIndex != -1)
2daa5d95 9879 {
06d40093 9880 if (aLightIt == aLightIndex)
9881 {
9882 return aLightIter.Value();
9883 }
2daa5d95 9884 }
06d40093 9885 else if (aLightIter.Value()->GetId() == theName
9886 || aLightIter.Value()->Name() == theName)
2daa5d95 9887 {
06d40093 9888 if (!aLight.IsNull())
9889 {
9890 Message::SendWarning() << "Warning: ambiguous light name '" << theName << "'";
9891 break;
9892 }
9893 aLight = aLightIter.Value();
2daa5d95 9894 }
9895 }
06d40093 9896 return aLight;
2daa5d95 9897}
9898
12381341 9899//===============================================================================================
9900//function : VLight
9901//purpose :
9902//===============================================================================================
9903static int VLight (Draw_Interpretor& theDi,
9904 Standard_Integer theArgsNb,
9905 const char** theArgVec)
9906{
9907 Handle(V3d_View) aView = ViewerTest::CurrentView();
9908 Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
06d40093 9909 const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12381341 9910 if (aView.IsNull()
9911 || aViewer.IsNull())
9912 {
23fe70ec 9913 Message::SendFail ("Error: no active viewer");
12381341 9914 return 1;
9915 }
9916
12381341 9917 if (theArgsNb < 2)
9918 {
9919 // print lights info
9920 Standard_Integer aLightId = 0;
6a24c6de 9921 for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
12381341 9922 {
6a24c6de 9923 Handle(V3d_Light) aLight = aLightIter.Value();
12381341 9924 const Quantity_Color aColor = aLight->Color();
992ed6b3 9925 theDi << "Light #" << aLightId
9926 << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
06d40093 9927 << " [" << aLight->GetId() << "] "
9928 << (aLight->IsEnabled() ? "ON" : "OFF") << "\n";
12381341 9929 switch (aLight->Type())
9930 {
06aa2001 9931 case Graphic3d_TypeOfLightSource_Ambient:
12381341 9932 {
06d40093 9933 theDi << " Type: Ambient\n"
9934 << " Intensity: " << aLight->Intensity() << "\n";
12381341 9935 break;
9936 }
06aa2001 9937 case Graphic3d_TypeOfLightSource_Directional:
12381341 9938 {
06d40093 9939 theDi << " Type: Directional\n"
9940 << " Intensity: " << aLight->Intensity() << "\n"
9941 << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n"
9942 << " CastShadows:" << (aLight->ToCastShadows() ? "TRUE" : "FALSE") << "\n"
9943 << " Smoothness: " << aLight->Smoothness() << "\n"
9944 << " Direction: " << aLight->PackedDirection().x() << " " << aLight->PackedDirection().y() << " " << aLight->PackedDirection().z() << "\n";
12381341 9945 break;
9946 }
06aa2001 9947 case Graphic3d_TypeOfLightSource_Positional:
12381341 9948 {
06d40093 9949 theDi << " Type: Positional\n"
9950 << " Intensity: " << aLight->Intensity() << "\n"
9951 << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n"
9952 << " CastShadows:" << (aLight->ToCastShadows() ? "TRUE" : "FALSE") << "\n"
9953 << " Smoothness: " << aLight->Smoothness() << "\n"
9954 << " Position: " << aLight->Position().X() << " " << aLight->Position().Y() << " " << aLight->Position().Z() << "\n"
9955 << " Atten.: " << aLight->ConstAttenuation() << " " << aLight->LinearAttenuation() << "\n"
9956 << " Range: " << aLight->Range() << "\n";
12381341 9957 break;
9958 }
06aa2001 9959 case Graphic3d_TypeOfLightSource_Spot:
12381341 9960 {
06d40093 9961 theDi << " Type: Spot\n"
9962 << " Intensity: " << aLight->Intensity() << "\n"
9963 << " Headlight: " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n"
9964 << " CastShadows:" << (aLight->ToCastShadows() ? "TRUE" : "FALSE") << "\n"
9965 << " Position: " << aLight->Position().X() << " " << aLight->Position().Y() << " " << aLight->Position().Z() << "\n"
9966 << " Direction: " << aLight->PackedDirection().x() << " " << aLight->PackedDirection().y() << " " << aLight->PackedDirection().z() << "\n"
9967 << " Atten.: " << aLight->ConstAttenuation() << " " << aLight->LinearAttenuation() << "\n"
9968 << " Angle: " << (aLight->Angle() * 180.0 / M_PI) << "\n"
9969 << " Exponent: " << aLight->Concentration() << "\n"
9970 << " Range: " << aLight->Range() << "\n";
12381341 9971 break;
9972 }
9973 default:
9974 {
189f85a3 9975 theDi << " Type: UNKNOWN\n";
12381341 9976 break;
9977 }
9978 }
06d40093 9979 theDi << " Color: " << aColor.Red() << " " << aColor.Green() << " " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
12381341 9980 }
9981 }
9982
06d40093 9983 Handle(V3d_Light) aLightOld, aLightNew;
992ed6b3 9984 Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
06d40093 9985 bool isGlobal = true;
9986 ViewerTest_AutoUpdater anUpdateTool (aCtx, aView);
9987 Handle(AIS_LightSource) aLightPrs;
12381341 9988 for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
9989 {
12381341 9990 const TCollection_AsciiString anArg (theArgVec[anArgIt]);
9991 TCollection_AsciiString anArgCase (anArg);
06d40093 9992 anArgCase.LowerCase();
761d8807 9993 if (anUpdateTool.parseRedrawMode (anArg))
9994 {
9995 continue;
9996 }
06d40093 9997 else if (anArgCase == "-new"
9998 || anArgCase == "-add"
9999 || anArgCase == "-create"
10000 || anArgCase == "-type"
10001 || (anArgCase == "-reset"
10002 && !aLightNew.IsNull())
10003 || (anArgCase == "-defaults"
10004 && !aLightNew.IsNull())
10005 || anArgCase == "add"
10006 || anArgCase == "new"
10007 || anArgCase == "create")
992ed6b3 10008 {
06d40093 10009 Graphic3d_TypeOfLightSource aType = Graphic3d_TypeOfLightSource_Ambient;
10010 if (anArgCase == "-reset")
992ed6b3 10011 {
06d40093 10012 aType = aLightNew->Type();
992ed6b3 10013 }
06d40093 10014 else if (anArgIt + 1 >= theArgsNb
10015 || !parseLightSourceType (theArgVec[++anArgIt], aType))
992ed6b3 10016 {
06d40093 10017 theDi << "Syntax error at '" << theArgVec[anArgIt] << "'\n";
10018 return 1;
992ed6b3 10019 }
06d40093 10020
10021 TCollection_AsciiString aName;
10022 if (!aLightNew.IsNull())
992ed6b3 10023 {
06d40093 10024 aName = aLightNew->Name();
992ed6b3 10025 }
06d40093 10026 switch (aType)
992ed6b3 10027 {
06d40093 10028 case Graphic3d_TypeOfLightSource_Ambient:
10029 {
10030 aLightNew = new V3d_AmbientLight();
10031 break;
10032 }
10033 case Graphic3d_TypeOfLightSource_Directional:
10034 {
10035 aLightNew = new V3d_DirectionalLight();
10036 break;
10037 }
10038 case Graphic3d_TypeOfLightSource_Spot:
10039 {
10040 aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10041 break;
10042 }
10043 case Graphic3d_TypeOfLightSource_Positional:
10044 {
10045 aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10046 break;
10047 }
992ed6b3 10048 }
06d40093 10049
10050 if (anArgCase == "-type"
10051 && !aLightOld.IsNull())
992ed6b3 10052 {
06d40093 10053 aLightNew->CopyFrom (aLightOld);
992ed6b3 10054 }
06d40093 10055 aLightNew->SetName (aName);
10056 }
10057 else if ((anArgCase == "-layer"
10058 || anArgCase == "-zlayer")
10059 && anArgIt + 1 < theArgsNb)
10060 {
10061 if (!ViewerTest::ParseZLayer (theArgVec[++anArgIt], aLayer)
10062 || aLayer == Graphic3d_ZLayerId_UNKNOWN)
992ed6b3 10063 {
06d40093 10064 Message::SendFail() << "Error: wrong syntax at '" << theArgVec[anArgIt] << "'";
992ed6b3 10065 return 1;
10066 }
10067 }
06d40093 10068 else if (anArgCase == "-glob"
10069 || anArgCase == "-global"
10070 || anArgCase == "-loc"
10071 || anArgCase == "-local")
12381341 10072 {
06d40093 10073 isGlobal = anArgCase.StartsWith ("-glob");
12381341 10074 }
06d40093 10075 else if (anArgCase == "-def"
10076 || anArgCase == "-defaults"
10077 || anArgCase == "-reset")
12381341 10078 {
4fe9ad57 10079 aViewer->SetDefaultLights();
06d40093 10080 aLightOld.Nullify();
10081 aLightNew.Nullify();
10082 aLightPrs.Nullify();
4fe9ad57 10083 }
06d40093 10084 else if (anArgCase == "-clr"
10085 || anArgCase == "-clear"
10086 || anArgCase == "clear")
4fe9ad57 10087 {
992ed6b3 10088 TColStd_SequenceOfInteger aLayers;
10089 aViewer->GetAllZLayers (aLayers);
10090 for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
4fe9ad57 10091 {
992ed6b3 10092 if (aLayeriter.Value() == aLayer
10093 || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10094 {
10095 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10096 aSettings.SetLights (Handle(Graphic3d_LightSet)());
10097 aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10098 if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10099 {
10100 break;
10101 }
10102 }
10103 }
10104
10105 if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10106 {
06d40093 10107 ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
992ed6b3 10108 for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10109 {
10110 Handle(V3d_Light) aLight = aLightIter.Value();
06d40093 10111 Handle(AIS_InteractiveObject) aPrsObject;
10112 GetMapOfAIS().Find2 (aLight->Name(), aPrsObject);
10113 if (Handle(AIS_LightSource) aLightSourceDel = Handle(AIS_LightSource)::DownCast (aPrsObject))
2daa5d95 10114 {
06d40093 10115 aCtx->Remove (aLightSourceDel, false);
10116 aMap.UnBind1 (aLightSourceDel);
2daa5d95 10117 }
992ed6b3 10118 aViewer->DelLight (aLight);
10119 aLightIter = aView->ActiveLightIterator();
10120 }
4fe9ad57 10121 }
12381341 10122
06d40093 10123 aLightOld.Nullify();
992ed6b3 10124 aLightNew.Nullify();
06d40093 10125 aLightPrs.Nullify();
12381341 10126 }
06d40093 10127 else if (!aLightNew.IsNull()
10128 && (anArgCase == "-display"
10129 || anArgCase == "-disp"
10130 || anArgCase == "-presentation"
10131 || anArgCase == "-prs"))
2daa5d95 10132 {
06d40093 10133 TCollection_AsciiString aLightName = aLightNew->Name();
10134 if (anArgIt + 1 < theArgsNb
10135 && theArgVec[anArgIt + 1][0] != '-')
2daa5d95 10136 {
06d40093 10137 // old syntax
10138 aLightName = theArgVec[++anArgIt];
10139 if (aLightNew->Name() != aLightName)
2daa5d95 10140 {
06d40093 10141 if (Handle(V3d_Light) anOtherLight = findLightSource (aLightName))
10142 {
10143 theDi << "Syntax error: light with name '" << aLightName << "' is already defined";
10144 return 1;
10145 }
10146 aLightNew->SetName (aLightName);
2daa5d95 10147 }
10148 }
10149 if (aLightName.IsEmpty())
10150 {
06d40093 10151 Message::SendFail() << "Error: nameless light source cannot be displayed";
12381341 10152 return 1;
10153 }
06d40093 10154 if (aLightPrs.IsNull())
992ed6b3 10155 {
06d40093 10156 aLightPrs = new AIS_LightSource (aLightNew);
992ed6b3 10157 }
06d40093 10158 theDi << aLightName << " ";
10159 }
10160 else if (!aLightNew.IsNull()
10161 && (anArgCase == "-disable"
10162 || anArgCase == "-disabled"
10163 || anArgCase == "-enable"
10164 || anArgCase == "-enabled"))
10165 {
10166 bool toEnable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
10167 if (anArgCase == "-disable"
10168 || anArgCase == "-disabled")
12381341 10169 {
06d40093 10170 toEnable = !toEnable;
12381341 10171 }
06d40093 10172 aLightNew->SetEnabled (toEnable);
12381341 10173 }
06d40093 10174 else if (!aLightNew.IsNull()
10175 && (anArgCase == "-color"
10176 || anArgCase == "-colour"
10177 || anArgCase == "color"))
12381341 10178 {
dae2a922 10179 Quantity_Color aColor;
10180 Standard_Integer aNbParsed = Draw::ParseColor (theArgsNb - anArgIt - 1,
10181 theArgVec + anArgIt + 1,
10182 aColor);
10183 anArgIt += aNbParsed;
06d40093 10184 if (aNbParsed == 0)
12381341 10185 {
23fe70ec 10186 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
12381341 10187 return 1;
10188 }
06d40093 10189 aLightNew->SetColor (aColor);
12381341 10190 }
06d40093 10191 else if (!aLightNew.IsNull()
10192 && (anArgCase == "-pos"
10193 || anArgCase == "-position"
10194 || anArgCase == "-prsposition"
10195 || anArgCase == "-prspos"
10196 || anArgCase == "pos"
10197 || anArgCase == "position")
10198 && (anArgIt + 3) < theArgsNb)
12381341 10199 {
2daa5d95 10200 gp_XYZ aPosXYZ;
06d40093 10201 if (!parseXYZ (theArgVec + anArgIt + 1, aPosXYZ))
12381341 10202 {
23fe70ec 10203 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
12381341 10204 return 1;
10205 }
10206
2daa5d95 10207 anArgIt += 3;
06d40093 10208 if (anArgCase == "-prsposition"
10209 || anArgCase == "-prspos")
2daa5d95 10210 {
06d40093 10211 aLightNew->SetDisplayPosition (aPosXYZ);
2daa5d95 10212 }
10213 else
10214 {
06d40093 10215 if (aLightNew->Type() != Graphic3d_TypeOfLightSource_Positional
10216 && aLightNew->Type() != Graphic3d_TypeOfLightSource_Spot)
2daa5d95 10217 {
10218 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
10219 return 1;
10220 }
10221
06d40093 10222 aLightNew->SetPosition (aPosXYZ);
2daa5d95 10223 }
12381341 10224 }
06d40093 10225 else if (!aLightNew.IsNull()
10226 && (aLightNew->Type() == Graphic3d_TypeOfLightSource_Directional
10227 || aLightNew->Type() == Graphic3d_TypeOfLightSource_Spot)
10228 && (anArgCase == "-dir"
10229 || anArgCase == "-direction")
10230 && (anArgIt + 3) < theArgsNb)
12381341 10231 {
2daa5d95 10232 gp_XYZ aDirXYZ;
06d40093 10233 if (!parseXYZ (theArgVec + anArgIt + 1, aDirXYZ))
12381341 10234 {
23fe70ec 10235 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
12381341 10236 return 1;
10237 }
10238
2daa5d95 10239 anArgIt += 3;
06d40093 10240 aLightNew->SetDirection (gp_Dir (aDirXYZ));
12381341 10241 }
06d40093 10242 else if (!aLightNew.IsNull()
10243 && (anArgCase == "-smoothangle"
10244 || anArgCase == "-smoothradius"
10245 || anArgCase == "-sm"
10246 || anArgCase == "-smoothness")
10247 && anArgIt + 1 < theArgsNb)
189f85a3 10248 {
06d40093 10249 Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[++anArgIt]);
10250 if (aLightNew->Type() == Graphic3d_TypeOfLightSource_Directional)
189f85a3 10251 {
06d40093 10252 aSmoothness = Standard_ShortReal(aSmoothness * M_PI / 180.0);
189f85a3 10253 }
992ed6b3 10254 if (Abs (aSmoothness) <= ShortRealEpsilon())
189f85a3 10255 {
06d40093 10256 aLightNew->SetIntensity (1.f);
189f85a3 10257 }
06d40093 10258 else if (Abs (aLightNew->Smoothness()) <= ShortRealEpsilon())
189f85a3 10259 {
06d40093 10260 aLightNew->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
189f85a3 10261 }
10262 else
10263 {
06d40093 10264 Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightNew->Smoothness());
10265 aLightNew->SetIntensity (aLightNew->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
189f85a3 10266 }
10267
06d40093 10268 if (aLightNew->Type() == Graphic3d_TypeOfLightSource_Positional)
189f85a3 10269 {
06d40093 10270 aLightNew->SetSmoothRadius (aSmoothness);
189f85a3 10271 }
06d40093 10272 else if (aLightNew->Type() == Graphic3d_TypeOfLightSource_Directional)
189f85a3 10273 {
06d40093 10274 aLightNew->SetSmoothAngle (aSmoothness);
189f85a3 10275 }
10276 }
06d40093 10277 else if (!aLightNew.IsNull()
10278 && (anArgCase == "-int"
10279 || anArgCase == "-intensity")
10280 && anArgIt + 1 < theArgsNb)
189f85a3 10281 {
06d40093 10282 Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[++anArgIt]);
10283 aLightNew->SetIntensity (aIntensity);
189f85a3 10284 }
06d40093 10285 else if (!aLightNew.IsNull()
10286 && aLightNew->Type() == Graphic3d_TypeOfLightSource_Spot
10287 && (anArgCase == "-spotangle"
10288 || anArgCase == "-ang"
10289 || anArgCase == "-angle")
10290 && anArgIt + 1 < theArgsNb)
4fe9ad57 10291 {
06d40093 10292 Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[++anArgIt]);
2daa5d95 10293 anAngle = (Standard_ShortReal (anAngle / 180.0 * M_PI));
06d40093 10294 aLightNew->SetAngle (anAngle);
10295 }
10296 else if (!aLightNew.IsNull()
10297 && (aLightNew->Type() == Graphic3d_TypeOfLightSource_Positional
10298 || aLightNew->Type() == Graphic3d_TypeOfLightSource_Spot)
10299 && (anArgCase == "-constatten"
10300 || anArgCase == "-constattenuation")
10301 && anArgIt + 1 < theArgsNb)
10302 {
10303 const Standard_ShortReal aConstAtten = (Standard_ShortReal )Atof (theArgVec[++anArgIt]);
10304 aLightNew->SetAttenuation (aConstAtten, aLightNew->LinearAttenuation());
10305 }
10306 else if (!aLightNew.IsNull()
10307 && (aLightNew->Type() == Graphic3d_TypeOfLightSource_Positional
10308 || aLightNew->Type() == Graphic3d_TypeOfLightSource_Spot)
10309 && (anArgCase == "-linatten"
10310 || anArgCase == "-linearatten"
10311 || anArgCase == "-linearattenuation")
10312 && anArgIt + 1 < theArgsNb)
10313 {
10314 const Standard_ShortReal aLinAtten = (Standard_ShortReal )Atof (theArgVec[++anArgIt]);
10315 aLightNew->SetAttenuation (aLightNew->ConstAttenuation(), aLinAtten);
10316 }
10317 else if (!aLightNew.IsNull()
10318 && aLightNew->Type() == Graphic3d_TypeOfLightSource_Spot
10319 && (anArgCase == "-spotexp"
10320 || anArgCase == "-spotexponent"
10321 || anArgCase == "-exp"
10322 || anArgCase == "-exponent")
10323 && anArgIt + 1 < theArgsNb)
10324 {
10325 aLightNew->SetConcentration ((Standard_ShortReal )Atof (theArgVec[++anArgIt]));
10326 }
10327 else if (!aLightNew.IsNull()
10328 && aLightNew->Type() != Graphic3d_TypeOfLightSource_Ambient
10329 && aLightNew->Type() != Graphic3d_TypeOfLightSource_Directional
10330 && anArgCase == "-range"
10331 && anArgIt + 1 < theArgsNb)
10332 {
10333 Standard_ShortReal aRange ((Standard_ShortReal)Atof (theArgVec[++anArgIt]));
10334 aLightNew->SetRange (aRange);
10335 }
10336 else if (!aLightNew.IsNull()
10337 && aLightNew->Type() != Graphic3d_TypeOfLightSource_Ambient
10338 && (anArgCase == "-head"
10339 || anArgCase == "-headlight"))
12381341 10340 {
06d40093 10341 Standard_Boolean isHeadLight = Standard_True;
10342 if (anArgIt + 1 < theArgsNb
10343 && Draw::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
12381341 10344 {
06d40093 10345 ++anArgIt;
12381341 10346 }
06d40093 10347 aLightNew->SetHeadlight (isHeadLight);
12381341 10348 }
06d40093 10349 else if (!aLightNew.IsNull()
10350 && anArgCase == "-name"
10351 && anArgIt + 1 < theArgsNb)
12381341 10352 {
06d40093 10353 const TCollection_AsciiString aName = theArgVec[++anArgIt];
10354 if (aLightNew->Name() == aName)
12381341 10355 {
06d40093 10356 continue;
12381341 10357 }
10358
06d40093 10359 if (Handle(V3d_Light) anOtherLight = findLightSource (aName))
12381341 10360 {
06d40093 10361 theDi << "Syntax error: light with name '" << aName << "' is already defined";
12381341 10362 return 1;
10363 }
06d40093 10364 aLightNew->SetName (aName);
12381341 10365 }
06d40093 10366 else if (!aLightPrs.IsNull()
10367 && (anArgCase == "-showzoomable"
10368 || anArgCase == "-prszoomable"
10369 || anArgCase == "-zoomable"))
88b312d3 10370 {
06d40093 10371 const bool isZoomable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
10372 aLightPrs->SetZoomable (isZoomable);
10373 }
a3b2aaef 10374 else if (!aLightPrs.IsNull()
10375 && (anArgCase == "-showdraggable"
10376 || anArgCase == "-prsdraggable"
10377 || anArgCase == "-draggable"))
10378 {
10379 const bool isDraggable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
10380 aLightPrs->SetDraggable (isDraggable);
10381 }
06d40093 10382 else if (!aLightPrs.IsNull()
10383 && (anArgCase == "-showname"
10384 || anArgCase == "-prsname"))
10385 {
10386 const bool toDisplay = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
10387 aLightPrs->SetDisplayName (toDisplay);
88b312d3 10388 }
06d40093 10389 else if (!aLightPrs.IsNull()
10390 && (aLightNew->Type() == Graphic3d_TypeOfLightSource_Spot
10391 || aLightNew->Type() == Graphic3d_TypeOfLightSource_Positional)
10392 && (anArgCase == "-showrange"
10393 || anArgCase == "-prsrange"))
12381341 10394 {
06d40093 10395 const bool toDisplay = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
10396 aLightPrs->SetDisplayRange (toDisplay);
10397 }
10398 else if (!aLightPrs.IsNull()
10399 && (anArgCase == "-showsize"
10400 || anArgCase == "-prssize")
10401 && anArgIt + 1 < theArgsNb)
10402 {
10403 Standard_Real aSize = 0.0;
10404 if (!Draw::ParseReal (theArgVec[++anArgIt], aSize)
10405 || aSize <= 0.0
10406 || aLightPrs.IsNull())
12381341 10407 {
23fe70ec 10408 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
12381341 10409 return 1;
10410 }
10411
06d40093 10412 aLightPrs->SetSize (aSize);
10413 }
a3b2aaef 10414 else if (!aLightPrs.IsNull()
10415 && (anArgCase == "-dirarcsize"
10416 || anArgCase == "-arcsize"
10417 || anArgCase == "-arc")
10418 && anArgIt + 1 < theArgsNb)
10419 {
10420 Standard_Integer aSize = 0;
10421 if (!Draw::ParseInteger (theArgVec[anArgIt + 1], aSize)
10422 || aSize <= 0
10423 || aLightPrs->Light()->Type() != Graphic3d_TypeOfLightSource_Directional)
10424 {
10425 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
10426 return 1;
10427 }
10428 ++anArgIt;
10429 aLightPrs->SetArcSize (aSize);
10430 }
06d40093 10431 else if (!aLightNew.IsNull()
10432 && aLightNew->Type() != Graphic3d_TypeOfLightSource_Ambient
10433 && (anArgCase == "-castshadow"
10434 || anArgCase == "-castshadows"
10435 || anArgCase == "-shadows"))
10436 {
10437 bool toCastShadows = true;
992ed6b3 10438 if (anArgIt + 1 < theArgsNb
06d40093 10439 && Draw::ParseOnOff (theArgVec[anArgIt + 1], toCastShadows))
12381341 10440 {
992ed6b3 10441 ++anArgIt;
12381341 10442 }
06d40093 10443 aLightNew->SetCastShadows (toCastShadows);
12381341 10444 }
06d40093 10445 else if (anArgCase == "-del"
10446 || anArgCase == "-delete"
10447 || anArgCase == "-remove"
10448 || anArgCase == "del"
10449 || anArgCase == "delete"
10450 || anArgCase == "remove")
2daa5d95 10451 {
06d40093 10452 if (aLightOld.IsNull())
2daa5d95 10453 {
06d40093 10454 if (!aLightNew.IsNull())
10455 {
10456 aLightNew.Nullify();
10457 continue;
10458 }
10459
10460 if (++anArgIt >= theArgsNb)
10461 {
10462 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
10463 return 1;
10464 }
10465
10466 const TCollection_AsciiString anOldName (theArgVec[anArgIt]);
10467 aLightOld = findLightSource (anOldName);
10468 if (aLightOld.IsNull())
10469 {
10470 Message::SendWarning() << "Warning: light '" << anOldName << "' not found";
10471 continue;
10472 }
2daa5d95 10473 }
06d40093 10474
10475 aLightNew.Nullify();
10476 aLightPrs.Nullify();
2daa5d95 10477 }
06d40093 10478 else if (anArgCase == "-change"
10479 || anArgCase == "change")
2daa5d95 10480 {
06d40093 10481 // just skip old syntax
2daa5d95 10482 }
06d40093 10483 else if (aLightNew.IsNull()
10484 && !anArgCase.StartsWith ("-"))
2daa5d95 10485 {
06d40093 10486 if (!aLightNew.IsNull())
2daa5d95 10487 {
06d40093 10488 continue;
2daa5d95 10489 }
10490
06d40093 10491 const TCollection_AsciiString anOldName (theArgVec[anArgIt]);
10492 aLightOld = findLightSource (anOldName);
10493 if (!aLightOld.IsNull())
2daa5d95 10494 {
06d40093 10495 aLightNew = aLightOld;
10496
10497 Handle(AIS_InteractiveObject) aPrsObject;
10498 GetMapOfAIS().Find2 (aLightOld->Name(), aPrsObject);
10499 aLightPrs = Handle(AIS_LightSource)::DownCast (aPrsObject);
2daa5d95 10500 }
10501 else
10502 {
06d40093 10503 Standard_Integer aLightIndex = -1;
10504 Draw::ParseInteger (anOldName.ToCString(), aLightIndex);
10505 if (aLightIndex != -1)
10506 {
10507 Message::SendFail() << "Syntax error: light source with index '" << aLightIndex << "' is not found";
10508 return 1;
10509 }
10510
10511 aLightNew = new V3d_AmbientLight();
10512 aLightNew->SetName (anOldName);
2daa5d95 10513 }
10514 }
06d40093 10515 else
2daa5d95 10516 {
06d40093 10517 Message::SendFail() << "Warning: unknown argument '" << anArg << "'";
10518 return 1;
10519 }
10520 }
2daa5d95 10521
06d40093 10522 // delete old light source
10523 if (!aLightOld.IsNull()
10524 && aLightOld != aLightNew)
10525 {
10526 TColStd_SequenceOfInteger aLayers;
10527 aViewer->GetAllZLayers (aLayers);
10528 for (TColStd_SequenceOfInteger::Iterator aLayerIter (aLayers); aLayerIter.More(); aLayerIter.Next())
10529 {
10530 if (aLayerIter.Value() == aLayer
10531 || aLayer == Graphic3d_ZLayerId_UNKNOWN)
2daa5d95 10532 {
06d40093 10533 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerIter.Value());
10534 if (!aSettings.Lights().IsNull())
10535 {
10536 aSettings.Lights()->Remove (aLightOld);
10537 if (aSettings.Lights()->IsEmpty())
10538 {
10539 aSettings.SetLights (Handle(Graphic3d_LightSet)());
10540 }
10541 }
10542 aViewer->SetZLayerSettings (aLayerIter.Value(), aSettings);
10543 if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10544 {
10545 break;
10546 }
2daa5d95 10547 }
10548 }
06d40093 10549
10550 if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
2daa5d95 10551 {
06d40093 10552 Handle(AIS_InteractiveObject) aPrsObject;
10553 GetMapOfAIS().Find2 (aLightOld->Name(), aPrsObject);
10554 if (Handle(AIS_LightSource) aLightSourceDel = Handle(AIS_LightSource)::DownCast (aPrsObject))
2daa5d95 10555 {
06d40093 10556 aCtx->Remove (aLightSourceDel, false);
10557 GetMapOfAIS().UnBind1 (aLightSourceDel);
2daa5d95 10558 }
06d40093 10559 aViewer->DelLight (aLightOld);
10560 }
10561 aLightOld.Nullify();
10562 }
2daa5d95 10563
06d40093 10564 // add new light source
10565 if (!aLightNew.IsNull())
10566 {
10567 if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10568 {
10569 aViewer->AddLight (aLightNew);
10570 if (isGlobal)
2daa5d95 10571 {
06d40093 10572 aViewer->SetLightOn (aLightNew);
2daa5d95 10573 }
10574 else
10575 {
06d40093 10576 aView->SetLightOn (aLightNew);
2daa5d95 10577 }
10578 }
06d40093 10579 else
d84e8669 10580 {
06d40093 10581 Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayer);
10582 if (aSettings.Lights().IsNull())
d84e8669 10583 {
06d40093 10584 aSettings.SetLights (new Graphic3d_LightSet());
d84e8669 10585 }
06d40093 10586 aSettings.Lights()->Add (aLightNew);
10587 aViewer->SetZLayerSettings (aLayer, aSettings);
d84e8669 10588 }
06d40093 10589
10590 if (!aLightPrs.IsNull())
12381341 10591 {
06d40093 10592 aLightPrs->SetLight (aLightNew);
10593 ViewerTest::Display (aLightNew->Name(), aLightPrs, false);
12381341 10594 }
10595 }
10596
06d40093 10597 // manage presentations
2daa5d95 10598 struct LightPrsSort
10599 {
10600 bool operator() (const Handle(AIS_LightSource)& theLeft,
10601 const Handle(AIS_LightSource)& theRight)
10602 {
10603 return theLeft->Light()->GetId() < theRight->Light()->GetId();
10604 }
10605 };
10606
10607 AIS_ListOfInteractive aPrsList;
06d40093 10608 aCtx->DisplayedObjects (AIS_KindOfInteractive_LightSource, -1, aPrsList);
2daa5d95 10609 if (!aPrsList.IsEmpty())
10610 {
10611 // update light source presentations
10612 std::vector<Handle(AIS_LightSource)> aLightPrsVec;
10613 for (AIS_ListOfInteractive::Iterator aPrsIter (aPrsList); aPrsIter.More(); aPrsIter.Next())
10614 {
06d40093 10615 if (Handle(AIS_LightSource) aLightPrs2 = Handle(AIS_LightSource)::DownCast (aPrsIter.Value()))
2daa5d95 10616 {
06d40093 10617 aLightPrsVec.push_back (aLightPrs2);
2daa5d95 10618 }
10619 }
10620
10621 // sort objects by id as AIS_InteractiveContext stores them in unordered map
10622 std::sort (aLightPrsVec.begin(), aLightPrsVec.end(), LightPrsSort());
10623
10624 Standard_Integer aTopStack = 0;
10625 for (std::vector<Handle(AIS_LightSource)>::iterator aPrsIter = aLightPrsVec.begin(); aPrsIter != aLightPrsVec.end(); ++aPrsIter)
10626 {
06d40093 10627 Handle(AIS_LightSource) aLightPrs2 = *aPrsIter;
10628 if (!aLightPrs2->TransformPersistence().IsNull()
10629 && aLightPrs2->TransformPersistence()->IsTrihedronOr2d())
2daa5d95 10630 {
06d40093 10631 const Standard_Integer aPrsSize = (Standard_Integer )aLightPrs2->Size();
10632 aLightPrs2->TransformPersistence()->SetOffset2d (Graphic3d_Vec2i (aTopStack + aPrsSize, aPrsSize));
2daa5d95 10633 aTopStack += aPrsSize + aPrsSize / 2;
10634 }
06d40093 10635 aCtx->Redisplay (aLightPrs2, false);
10636 aCtx->SetTransformPersistence (aLightPrs2, aLightPrs2->TransformPersistence());
2daa5d95 10637 }
10638 }
12381341 10639 return 0;
10640}
10641
67312b79 10642//===============================================================================================
10643//function : VPBREnvironment
10644//purpose :
10645//===============================================================================================
10646static int VPBREnvironment (Draw_Interpretor&,
10647 Standard_Integer theArgsNb,
10648 const char** theArgVec)
10649{
10650 if (theArgsNb > 2)
10651 {
23fe70ec 10652 Message::SendFail ("Syntax error: 'vpbrenv' command has only one argument");
67312b79 10653 return 1;
10654 }
10655
10656 Handle(V3d_View) aView = ViewerTest::CurrentView();
10657 if (aView.IsNull())
10658 {
23fe70ec 10659 Message::SendFail ("Error: no active viewer");
67312b79 10660 return 1;
10661 }
10662
10663 TCollection_AsciiString anArg = TCollection_AsciiString (theArgVec[1]);
10664 anArg.LowerCase();
10665
10666 if (anArg == "-generate"
10667 || anArg == "-gen")
10668 {
10669 aView->GeneratePBREnvironment (Standard_True);
10670 }
10671 else if (anArg == "-clear")
10672 {
10673 aView->ClearPBREnvironment (Standard_True);
10674 }
10675 else
10676 {
23fe70ec 10677 Message::SendFail() << "Syntax error: unknown argument [" << theArgVec[1] << "] for 'vpbrenv' command";
67312b79 10678 return 1;
10679 }
10680
10681 return 0;
10682}
10683
15669413 10684//! Read Graphic3d_RenderingParams::PerfCounters flag.
10685static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
10686 Standard_Boolean& theToReset,
10687 Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
10688 Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
10689{
10690 Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
10691 TCollection_AsciiString aVal = theValue;
10692 Standard_Boolean toReverse = Standard_False;
10693 if (aVal == "none")
10694 {
10695 theToReset = Standard_True;
10696 return Standard_True;
10697 }
10698 else if (aVal.StartsWith ("-"))
10699 {
10700 toReverse = Standard_True;
10701 aVal = aVal.SubString (2, aVal.Length());
10702 }
10703 else if (aVal.StartsWith ("no"))
10704 {
10705 toReverse = Standard_True;
10706 aVal = aVal.SubString (3, aVal.Length());
10707 }
10708 else if (aVal.StartsWith ("+"))
10709 {
10710 aVal = aVal.SubString (2, aVal.Length());
10711 }
10712 else
10713 {
10714 theToReset = Standard_True;
10715 }
10716
10717 if ( aVal == "fps"
10718 || aVal == "framerate") aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
10719 else if (aVal == "cpu") aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
10720 else if (aVal == "layers") aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
10721 else if (aVal == "structs"
10722 || aVal == "structures"
10723 || aVal == "objects") aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
10724 else if (aVal == "groups") aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
10725 else if (aVal == "arrays") aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
10726 else if (aVal == "tris"
10727 || aVal == "triangles") aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
10728 else if (aVal == "pnts"
10729 || aVal == "points") aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
b9f43ad1 10730 else if (aVal == "lines") aFlag = Graphic3d_RenderingParams::PerfCounters_Lines;
15669413 10731 else if (aVal == "mem"
10732 || aVal == "gpumem"
10733 || aVal == "estimmem") aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
5e30547b 10734 else if (aVal == "skipimmediate"
10735 || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
10736 else if (aVal == "frametime"
10737 || aVal == "frametimers"
10738 || aVal == "time") aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
15669413 10739 else if (aVal == "basic") aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
10740 else if (aVal == "extended"
10741 || aVal == "verbose"
10742 || aVal == "extra") aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
5e30547b 10743 else if (aVal == "full"
10744 || aVal == "all") aFlag = Graphic3d_RenderingParams::PerfCounters_All;
15669413 10745 else
10746 {
10747 return Standard_False;
10748 }
10749
10750 if (toReverse)
10751 {
10752 theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
10753 }
10754 else
10755 {
10756 theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
10757 }
10758 return Standard_True;
10759}
10760
10761//! Read Graphic3d_RenderingParams::PerfCounters flags.
10762static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
10763 Graphic3d_RenderingParams::PerfCounters& theFlags)
10764{
10765 TCollection_AsciiString aValue = theValue;
10766 Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
10767 Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
10768 Standard_Boolean toReset = Standard_False;
10769 for (;;)
10770 {
10771 Standard_Integer aSplitPos = aValue.Search ("|");
10772 if (aSplitPos <= 0)
10773 {
10774 if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
10775 {
10776 return Standard_False;
10777 }
10778 if (toReset)
10779 {
10780 theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
10781 }
10782 theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags | aFlagsAdd);
10783 theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
10784 return Standard_True;
10785 }
10786
10787 if (aSplitPos > 1)
10788 {
10789 TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
10790 if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
10791 {
10792 return Standard_False;
10793 }
10794 }
10795 aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
10796 }
10797}
10798
e276548b 10799//=======================================================================
bc8c79bb 10800//function : VRenderParams
10801//purpose : Enables/disables rendering features
e276548b 10802//=======================================================================
10803
bc8c79bb 10804static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
10805 Standard_Integer theArgNb,
10806 const char** theArgVec)
e276548b 10807{
7ae4a307 10808 Handle(V3d_View) aView = ViewerTest::CurrentView();
10809 if (aView.IsNull())
e276548b 10810 {
23fe70ec 10811 Message::SendFail ("Error: no active viewer");
e276548b 10812 return 1;
10813 }
bc8c79bb 10814
10815 Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
6b62b2da 10816 TCollection_AsciiString aCmdName (theArgVec[0]);
10817 aCmdName.LowerCase();
10818 if (aCmdName == "vraytrace")
10819 {
10820 if (theArgNb == 1)
10821 {
10822 theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
10823 return 0;
10824 }
10825 else if (theArgNb == 2)
10826 {
10827 TCollection_AsciiString aValue (theArgVec[1]);
10828 aValue.LowerCase();
10829 if (aValue == "on"
10830 || aValue == "1")
10831 {
10832 aParams.Method = Graphic3d_RM_RAYTRACING;
10833 aView->Redraw();
10834 return 0;
10835 }
10836 else if (aValue == "off"
10837 || aValue == "0")
10838 {
10839 aParams.Method = Graphic3d_RM_RASTERIZATION;
10840 aView->Redraw();
10841 return 0;
10842 }
10843 else
10844 {
23fe70ec 10845 Message::SendFail() << "Syntax error: unknown argument '" << theArgVec[1] << "'";
6b62b2da 10846 return 1;
10847 }
10848 }
10849 else
10850 {
23fe70ec 10851 Message::SendFail ("Syntax error: wrong number of arguments");
6b62b2da 10852 return 1;
10853 }
10854 }
bc8c79bb 10855
10856 if (theArgNb < 2)
e276548b 10857 {
bc8c79bb 10858 theDI << "renderMode: ";
10859 switch (aParams.Method)
10860 {
10861 case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
10862 case Graphic3d_RM_RAYTRACING: theDI << "raytrace "; break;
10863 }
10864 theDI << "\n";
a1073ae2 10865 theDI << "transparency: ";
10866 switch (aParams.TransparencyMethod)
10867 {
10868 case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
10869 case Graphic3d_RTM_BLEND_OIT: theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
10870 << TCollection_AsciiString (aParams.OitDepthFactor); break;
78c4e836 10871 case Graphic3d_RTM_DEPTH_PEELING_OIT: theDI << "Depth Peeling Order-Independent Transparency, Nb.Layers: "
10872 << TCollection_AsciiString (aParams.NbOitDepthPeelingLayers); break;
a1073ae2 10873 }
10874 theDI << "\n";
b4327ba8 10875 theDI << "msaa: " << aParams.NbMsaaSamples << "\n";
56689b27 10876 theDI << "rendScale: " << aParams.RenderResolutionScale << "\n";
b4327ba8 10877 theDI << "rayDepth: " << aParams.RaytracingDepth << "\n";
10878 theDI << "fsaa: " << (aParams.IsAntialiasingEnabled ? "on" : "off") << "\n";
10879 theDI << "shadows: " << (aParams.IsShadowEnabled ? "on" : "off") << "\n";
d84e8669 10880 theDI << "shadowMapRes: " << aParams.ShadowMapResolution << "\n";
10881 theDI << "shadowMapBias: " << aParams.ShadowMapBias << "\n";
b4327ba8 10882 theDI << "reflections: " << (aParams.IsReflectionEnabled ? "on" : "off") << "\n";
10883 theDI << "gleam: " << (aParams.IsTransparentShadowEnabled ? "on" : "off") << "\n";
10884 theDI << "GI: " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
10885 theDI << "blocked RNG: " << (aParams.CoherentPathTracingMode ? "on" : "off") << "\n";
10886 theDI << "iss: " << (aParams.AdaptiveScreenSampling ? "on" : "off") << "\n";
10887 theDI << "iss debug: " << (aParams.ShowSamplingTiles ? "on" : "off") << "\n";
10888 theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels ? "on" : "off") << "\n";
b09447ed 10889 theDI << "max radiance: " << aParams.RadianceClampingValue << "\n";
4eaaf9d8 10890 theDI << "nb tiles (iss): " << aParams.NbRayTracingTiles << "\n";
66d1cdc6 10891 theDI << "tile size (iss):" << aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
8625ef7e 10892 theDI << "shadingModel: ";
10893 switch (aView->ShadingModel())
10894 {
13b36bb1 10895 case Graphic3d_TypeOfShadingModel_DEFAULT: theDI << "default"; break;
10896 case Graphic3d_TypeOfShadingModel_Unlit: theDI << "unlit"; break;
10897 case Graphic3d_TypeOfShadingModel_PhongFacet: theDI << "flat"; break;
10898 case Graphic3d_TypeOfShadingModel_Gouraud: theDI << "gouraud"; break;
10899 case Graphic3d_TypeOfShadingModel_Phong: theDI << "phong"; break;
10900 case Graphic3d_TypeOfShadingModel_Pbr: theDI << "pbr"; break;
10901 case Graphic3d_TypeOfShadingModel_PbrFacet: theDI << "pbr_facet"; break;
8625ef7e 10902 }
37f80e16 10903 theDI << "\n";
15669413 10904 {
10905 theDI << "perfCounters:";
10906 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
10907 {
10908 theDI << " fps";
10909 }
10910 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
10911 {
10912 theDI << " cpu";
10913 }
10914 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
10915 {
10916 theDI << " structs";
10917 }
10918 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
10919 {
10920 theDI << " groups";
10921 }
10922 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
10923 {
10924 theDI << " arrays";
10925 }
10926 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
10927 {
10928 theDI << " tris";
10929 }
b9f43ad1 10930 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Lines) != 0)
10931 {
10932 theDI << " lines";
10933 }
15669413 10934 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
10935 {
10936 theDI << " pnts";
10937 }
10938 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
10939 {
10940 theDI << " gpumem";
10941 }
5e30547b 10942 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
10943 {
10944 theDI << " frameTime";
10945 }
10946 if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
10947 {
10948 theDI << " skipimmediate";
10949 }
15669413 10950 if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
10951 {
10952 theDI << " none";
10953 }
10954 theDI << "\n";
10955 }
f88457e6 10956 theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass ? "on" : "off") << "\n";
c40eb6b9 10957 theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage ? "on" : "off") << "\n";
0e3025bc 10958 theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On ? "on" :
10959 aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
10960 "noUpdate") << "\n";
8625ef7e 10961 theDI << "\n";
bc8c79bb 10962 return 0;
e276548b 10963 }
10964
4c7a3fae 10965 bool toPrint = false, toSyncDefaults = false, toSyncAllViews = false;
8625ef7e 10966 ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
e276548b 10967 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10968 {
bc8c79bb 10969 Standard_CString anArg (theArgVec[anArgIter]);
10970 TCollection_AsciiString aFlag (anArg);
10971 aFlag.LowerCase();
8625ef7e 10972 if (anUpdateTool.parseRedrawMode (aFlag))
10973 {
10974 continue;
10975 }
10976 else if (aFlag == "-echo"
10977 || aFlag == "-print")
e276548b 10978 {
bc8c79bb 10979 toPrint = Standard_True;
8625ef7e 10980 anUpdateTool.Invalidate();
e276548b 10981 }
4c7a3fae 10982 else if (aFlag == "-reset")
10983 {
10984 aParams = ViewerTest::GetViewerFromContext()->DefaultRenderingParams();
10985 }
10986 else if (aFlag == "-sync"
10987 && (anArgIter + 1 < theArgNb))
10988 {
10989 TCollection_AsciiString aSyncFlag (theArgVec[++anArgIter]);
10990 aSyncFlag.LowerCase();
10991 if (aSyncFlag == "default"
10992 || aSyncFlag == "defaults"
10993 || aSyncFlag == "viewer")
10994 {
10995 toSyncDefaults = true;
10996 }
10997 else if (aSyncFlag == "allviews"
10998 || aSyncFlag == "views")
10999 {
11000 toSyncAllViews = true;
11001 }
11002 else
11003 {
11004 Message::SendFail ("Syntax error: unknown parameter to -sync argument");
11005 return 1;
11006 }
11007 }
bc8c79bb 11008 else if (aFlag == "-mode"
11009 || aFlag == "-rendermode"
11010 || aFlag == "-render_mode")
e276548b 11011 {
bc8c79bb 11012 if (toPrint)
11013 {
11014 switch (aParams.Method)
11015 {
11016 case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11017 case Graphic3d_RM_RAYTRACING: theDI << "ray-tracing "; break;
11018 }
11019 continue;
11020 }
e276548b 11021 else
bc8c79bb 11022 {
23fe70ec 11023 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
bc8c79bb 11024 return 1;
11025 }
11026 }
11027 else if (aFlag == "-ray"
11028 || aFlag == "-raytrace")
11029 {
11030 if (toPrint)
11031 {
11032 theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11033 continue;
11034 }
11035
4c7a3fae 11036 bool isRayTrace = true;
11037 if (anArgIter + 1 < theArgNb
dae2a922 11038 && Draw::ParseOnOff (theArgVec[anArgIter + 1], isRayTrace))
4c7a3fae 11039 {
11040 ++anArgIter;
11041 }
11042 aParams.Method = isRayTrace ? Graphic3d_RM_RAYTRACING : Graphic3d_RM_RASTERIZATION;
e276548b 11043 }
bc8c79bb 11044 else if (aFlag == "-rast"
11045 || aFlag == "-raster"
11046 || aFlag == "-rasterization")
e276548b 11047 {
bc8c79bb 11048 if (toPrint)
11049 {
11050 theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11051 continue;
11052 }
11053
4c7a3fae 11054 bool isRaster = true;
11055 if (anArgIter + 1 < theArgNb
dae2a922 11056 && Draw::ParseOnOff (theArgVec[anArgIter + 1], isRaster))
4c7a3fae 11057 {
11058 ++anArgIter;
11059 }
11060 aParams.Method = isRaster ? Graphic3d_RM_RASTERIZATION : Graphic3d_RM_RAYTRACING;
bc8c79bb 11061 }
3c4b62a4 11062 else if (aFlag == "-msaa")
11063 {
11064 if (toPrint)
11065 {
11066 theDI << aParams.NbMsaaSamples << " ";
11067 continue;
11068 }
11069 else if (++anArgIter >= theArgNb)
11070 {
23fe70ec 11071 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
3c4b62a4 11072 return 1;
11073 }
11074
11075 const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11076 if (aNbSamples < 0)
11077 {
23fe70ec 11078 Message::SendFail() << "Syntax error: invalid number of MSAA samples " << aNbSamples << "";
3c4b62a4 11079 return 1;
11080 }
11081 else
11082 {
11083 aParams.NbMsaaSamples = aNbSamples;
11084 }
11085 }
2a332745 11086 else if (aFlag == "-linefeather"
11087 || aFlag == "-edgefeather"
11088 || aFlag == "-feather")
11089 {
11090 if (toPrint)
11091 {
11092 theDI << " " << aParams.LineFeather << " ";
11093 continue;
11094 }
11095 else if (++anArgIter >= theArgNb)
11096 {
23fe70ec 11097 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
2a332745 11098 return 1;
11099 }
11100
11101 TCollection_AsciiString aParam = theArgVec[anArgIter];
11102 const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11103 if (aFeather <= 0.0f)
11104 {
23fe70ec 11105 Message::SendFail() << "Syntax error: invalid value of line width feather " << aFeather << ". Should be > 0";
2a332745 11106 return 1;
11107 }
11108 aParams.LineFeather = aFeather;
11109 }
a1073ae2 11110 else if (aFlag == "-oit")
11111 {
11112 if (toPrint)
11113 {
11114 if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11115 {
11116 theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11117 }
78c4e836 11118 else if (aParams.TransparencyMethod == Graphic3d_RTM_DEPTH_PEELING_OIT)
11119 {
11120 theDI << "on, depth peeling layers: " << TCollection_AsciiString (aParams.NbOitDepthPeelingLayers) << " ";
11121 }
a1073ae2 11122 else
11123 {
11124 theDI << "off" << " ";
11125 }
11126 continue;
11127 }
11128 else if (++anArgIter >= theArgNb)
11129 {
23fe70ec 11130 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
a1073ae2 11131 return 1;
11132 }
11133
11134 TCollection_AsciiString aParam = theArgVec[anArgIter];
11135 aParam.LowerCase();
78c4e836 11136 if (aParam == "peeling"
11137 || aParam == "peel")
11138 {
11139 aParams.TransparencyMethod = Graphic3d_RTM_DEPTH_PEELING_OIT;
11140 if (anArgIter + 1 < theArgNb
11141 && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
11142 {
11143 ++anArgIter;
11144 const Standard_Integer aNbLayers = TCollection_AsciiString (theArgVec[anArgIter]).IntegerValue();
11145 if (aNbLayers < 2)
11146 {
11147 Message::SendFail() << "Syntax error: invalid layers number specified for Depth Peeling OIT " << aNbLayers;
11148 return 1;
11149 }
11150 aParams.NbOitDepthPeelingLayers = TCollection_AsciiString (theArgVec[anArgIter]).IntegerValue();
11151 }
11152 }
11153 else if (aParam == "weighted"
11154 || aParam == "weight")
11155 {
11156 aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11157 if (anArgIter + 1 < theArgNb
11158 && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
11159 {
11160 ++anArgIter;
11161 const Standard_ShortReal aWeight = (Standard_ShortReal)TCollection_AsciiString (theArgVec[anArgIter]).RealValue();
11162 if (aWeight < 0.f || aWeight > 1.f)
11163 {
11164 Message::SendFail() << "Syntax error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]";
11165 return 1;
11166 }
11167 aParams.OitDepthFactor = aWeight;
11168 }
11169 }
11170 else if (aParam.IsRealValue())
a1073ae2 11171 {
11172 const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11173 if (aWeight < 0.f || aWeight > 1.f)
11174 {
23fe70ec 11175 Message::SendFail() << "Syntax error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]";
a1073ae2 11176 return 1;
11177 }
11178
11179 aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11180 aParams.OitDepthFactor = aWeight;
11181 }
11182 else if (aParam == "off")
11183 {
11184 aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11185 }
11186 else
11187 {
23fe70ec 11188 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
a1073ae2 11189 return 1;
11190 }
11191 }
d37aef5c 11192 else if (aFlag == "-fonthinting"
11193 || aFlag == "-fonthint")
11194 {
11195 if (toPrint)
11196 {
11197 if ((aParams.FontHinting & Font_Hinting_Normal) != 0)
11198 {
11199 theDI << "normal" << " ";
11200 }
11201 else if ((aParams.FontHinting & Font_Hinting_Normal) != 0)
11202 {
11203 theDI << "light" << " ";
11204 }
11205 else
11206 {
11207 theDI << "off" << " ";
11208 }
11209 continue;
11210 }
11211 else if (anArgIter + 1 >= theArgNb)
11212 {
11213 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
11214 return 1;
11215 }
11216
11217 TCollection_AsciiString aHintStyle (theArgVec[++anArgIter]);
11218 aHintStyle.LowerCase();
11219 if (aHintStyle == "normal"
11220 || aHintStyle == "on"
11221 || aHintStyle == "1")
11222 {
11223 aParams.FontHinting = Font_Hinting(aParams.FontHinting & ~Font_Hinting_Light);
11224 aParams.FontHinting = Font_Hinting(aParams.FontHinting | Font_Hinting_Normal);
11225 }
11226 else if (aHintStyle == "light")
11227 {
11228 aParams.FontHinting = Font_Hinting(aParams.FontHinting & ~Font_Hinting_Normal);
11229 aParams.FontHinting = Font_Hinting(aParams.FontHinting | Font_Hinting_Light);
11230 }
11231 else if (aHintStyle == "no"
11232 || aHintStyle == "off"
11233 || aHintStyle == "0")
11234 {
11235 aParams.FontHinting = Font_Hinting(aParams.FontHinting & ~Font_Hinting_Normal);
11236 aParams.FontHinting = Font_Hinting(aParams.FontHinting & ~Font_Hinting_Light);
11237 }
11238 else
11239 {
11240 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
11241 return 1;
11242 }
11243 }
11244 else if (aFlag == "-fontautohinting"
11245 || aFlag == "-fontautohint")
11246 {
11247 if (toPrint)
11248 {
11249 if ((aParams.FontHinting & Font_Hinting_ForceAutohint) != 0)
11250 {
11251 theDI << "force" << " ";
11252 }
11253 else if ((aParams.FontHinting & Font_Hinting_NoAutohint) != 0)
11254 {
11255 theDI << "disallow" << " ";
11256 }
11257 else
11258 {
11259 theDI << "auto" << " ";
11260 }
11261 continue;
11262 }
11263 else if (anArgIter + 1 >= theArgNb)
11264 {
11265 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
11266 return 1;
11267 }
11268
11269 TCollection_AsciiString aHintStyle (theArgVec[++anArgIter]);
11270 aHintStyle.LowerCase();
11271 if (aHintStyle == "force")
11272 {
11273 aParams.FontHinting = Font_Hinting(aParams.FontHinting & ~Font_Hinting_NoAutohint);
11274 aParams.FontHinting = Font_Hinting(aParams.FontHinting | Font_Hinting_ForceAutohint);
11275 }
11276 else if (aHintStyle == "disallow"
11277 || aHintStyle == "no")
11278 {
11279 aParams.FontHinting = Font_Hinting(aParams.FontHinting & ~Font_Hinting_ForceAutohint);
11280 aParams.FontHinting = Font_Hinting(aParams.FontHinting | Font_Hinting_NoAutohint);
11281 }
11282 else if (aHintStyle == "auto")
11283 {
11284 aParams.FontHinting = Font_Hinting(aParams.FontHinting & ~Font_Hinting_ForceAutohint);
11285 aParams.FontHinting = Font_Hinting(aParams.FontHinting & ~Font_Hinting_NoAutohint);
11286 }
11287 else
11288 {
11289 theDI << "Syntax error at '" << theArgVec[anArgIter] << "'";
11290 return 1;
11291 }
11292 }
f88457e6 11293 else if (aFlag == "-depthprepass")
11294 {
11295 if (toPrint)
11296 {
11297 theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11298 continue;
11299 }
11300 aParams.ToEnableDepthPrepass = Standard_True;
11301 if (anArgIter + 1 < theArgNb
dae2a922 11302 && Draw::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
f88457e6 11303 {
11304 ++anArgIter;
11305 }
11306 }
c40eb6b9 11307 else if (aFlag == "-samplealphatocoverage"
11308 || aFlag == "-alphatocoverage")
11309 {
11310 if (toPrint)
11311 {
11312 theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11313 continue;
11314 }
11315 aParams.ToEnableAlphaToCoverage = Standard_True;
11316 if (anArgIter + 1 < theArgNb
dae2a922 11317 && Draw::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
c40eb6b9 11318 {
11319 ++anArgIter;
11320 }
11321 }
56689b27 11322 else if (aFlag == "-rendscale"
11323 || aFlag == "-renderscale"
11324 || aFlag == "-renderresolutionscale")
11325 {
11326 if (toPrint)
11327 {
11328 theDI << aParams.RenderResolutionScale << " ";
11329 continue;
11330 }
11331 else if (++anArgIter >= theArgNb)
11332 {
23fe70ec 11333 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
56689b27 11334 return 1;
11335 }
11336
11337 const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11338 if (aScale < 0.01)
11339 {
23fe70ec 11340 Message::SendFail() << "Syntax error: invalid rendering resolution scale " << aScale << "";
56689b27 11341 return 1;
11342 }
11343 else
11344 {
11345 aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11346 }
11347 }
bc8c79bb 11348 else if (aFlag == "-raydepth"
11349 || aFlag == "-ray_depth")
11350 {
11351 if (toPrint)
11352 {
11353 theDI << aParams.RaytracingDepth << " ";
11354 continue;
11355 }
11356 else if (++anArgIter >= theArgNb)
11357 {
23fe70ec 11358 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
bc8c79bb 11359 return 1;
11360 }
11361
11362 const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
189f85a3 11363
11364 // We allow RaytracingDepth be more than 10 in case of GI enabled
11365 if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
bc8c79bb 11366 {
23fe70ec 11367 Message::SendFail() << "Syntax error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]";
bc8c79bb 11368 return 1;
11369 }
e276548b 11370 else
bc8c79bb 11371 {
11372 aParams.RaytracingDepth = aDepth;
11373 }
11374 }
11375 else if (aFlag == "-shad"
11376 || aFlag == "-shadows")
11377 {
11378 if (toPrint)
11379 {
11380 theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
11381 continue;
11382 }
11383
11384 Standard_Boolean toEnable = Standard_True;
11385 if (++anArgIter < theArgNb
dae2a922 11386 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
bc8c79bb 11387 {
11388 --anArgIter;
11389 }
11390 aParams.IsShadowEnabled = toEnable;
11391 }
d84e8669 11392 else if (aFlag == "-shadowmapresolution"
11393 || aFlag == "-shadowmap")
11394 {
11395 if (toPrint)
11396 {
11397 theDI << aParams.ShadowMapResolution << " ";
11398 continue;
11399 }
11400 else if (++anArgIter >= theArgNb)
11401 {
11402 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
11403 return 1;
11404 }
11405
11406 aParams.ShadowMapResolution = Draw::Atoi (theArgVec[anArgIter]);
11407 }
11408 else if (aFlag == "-shadowmapbias")
11409 {
11410 if (toPrint)
11411 {
11412 theDI << aParams.ShadowMapBias << " ";
11413 continue;
11414 }
11415 else if (++anArgIter >= theArgNb)
11416 {
11417 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
11418 return 1;
11419 }
11420
11421 aParams.ShadowMapBias = (float )Draw::Atof (theArgVec[anArgIter]);
11422 }
bc8c79bb 11423 else if (aFlag == "-refl"
11424 || aFlag == "-reflections")
11425 {
11426 if (toPrint)
11427 {
11428 theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11429 continue;
11430 }
11431
11432 Standard_Boolean toEnable = Standard_True;
11433 if (++anArgIter < theArgNb
dae2a922 11434 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
bc8c79bb 11435 {
11436 --anArgIter;
11437 }
11438 aParams.IsReflectionEnabled = toEnable;
11439 }
11440 else if (aFlag == "-fsaa")
11441 {
11442 if (toPrint)
11443 {
11444 theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11445 continue;
11446 }
11447
11448 Standard_Boolean toEnable = Standard_True;
11449 if (++anArgIter < theArgNb
dae2a922 11450 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
bc8c79bb 11451 {
11452 --anArgIter;
11453 }
11454 aParams.IsAntialiasingEnabled = toEnable;
11455 }
11456 else if (aFlag == "-gleam")
11457 {
11458 if (toPrint)
11459 {
11460 theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11461 continue;
11462 }
11463
11464 Standard_Boolean toEnable = Standard_True;
11465 if (++anArgIter < theArgNb
dae2a922 11466 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
bc8c79bb 11467 {
11468 --anArgIter;
11469 }
11470 aParams.IsTransparentShadowEnabled = toEnable;
e276548b 11471 }
189f85a3 11472 else if (aFlag == "-gi")
11473 {
11474 if (toPrint)
11475 {
11476 theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11477 continue;
11478 }
11479
11480 Standard_Boolean toEnable = Standard_True;
11481 if (++anArgIter < theArgNb
dae2a922 11482 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
189f85a3 11483 {
11484 --anArgIter;
11485 }
11486 aParams.IsGlobalIlluminationEnabled = toEnable;
11487 if (!toEnable)
11488 {
11489 aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11490 }
11491 }
8c820969 11492 else if (aFlag == "-blockedrng"
11493 || aFlag == "-brng")
11494 {
11495 if (toPrint)
11496 {
11497 theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11498 continue;
11499 }
11500
11501 Standard_Boolean toEnable = Standard_True;
11502 if (++anArgIter < theArgNb
dae2a922 11503 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
8c820969 11504 {
11505 --anArgIter;
11506 }
11507 aParams.CoherentPathTracingMode = toEnable;
11508 }
b09447ed 11509 else if (aFlag == "-maxrad")
11510 {
11511 if (toPrint)
11512 {
11513 theDI << aParams.RadianceClampingValue << " ";
11514 continue;
11515 }
11516 else if (++anArgIter >= theArgNb)
11517 {
23fe70ec 11518 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
b09447ed 11519 return 1;
11520 }
11521
11522 const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
d45edf24 11523 if (!aMaxRadStr.IsRealValue (Standard_True))
b09447ed 11524 {
23fe70ec 11525 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
b09447ed 11526 return 1;
11527 }
11528
11529 const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11530 if (aMaxRadiance <= 0.0)
11531 {
23fe70ec 11532 Message::SendFail() << "Syntax error: invalid radiance clamping value " << aMaxRadiance;
b09447ed 11533 return 1;
11534 }
11535 else
11536 {
11537 aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11538 }
11539 }
3a9b5dc8 11540 else if (aFlag == "-iss")
11541 {
11542 if (toPrint)
11543 {
11544 theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11545 continue;
11546 }
11547
11548 Standard_Boolean toEnable = Standard_True;
11549 if (++anArgIter < theArgNb
dae2a922 11550 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
3a9b5dc8 11551 {
11552 --anArgIter;
11553 }
11554 aParams.AdaptiveScreenSampling = toEnable;
11555 }
e084dbbc 11556 else if (aFlag == "-issatomic")
11557 {
11558 if (toPrint)
11559 {
11560 theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11561 continue;
11562 }
11563
11564 Standard_Boolean toEnable = Standard_True;
11565 if (++anArgIter < theArgNb
dae2a922 11566 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
e084dbbc 11567 {
11568 --anArgIter;
11569 }
11570 aParams.AdaptiveScreenSamplingAtomic = toEnable;
11571 }
3a9b5dc8 11572 else if (aFlag == "-issd")
11573 {
11574 if (toPrint)
11575 {
11576 theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11577 continue;
11578 }
11579
11580 Standard_Boolean toEnable = Standard_True;
11581 if (++anArgIter < theArgNb
dae2a922 11582 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
3a9b5dc8 11583 {
11584 --anArgIter;
11585 }
11586 aParams.ShowSamplingTiles = toEnable;
11587 }
66d1cdc6 11588 else if (aFlag == "-tilesize")
11589 {
11590 if (toPrint)
11591 {
11592 theDI << aParams.RayTracingTileSize << " ";
11593 continue;
11594 }
11595 else if (++anArgIter >= theArgNb)
11596 {
23fe70ec 11597 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
66d1cdc6 11598 return 1;
11599 }
11600
11601 const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11602 if (aTileSize < 1)
11603 {
23fe70ec 11604 Message::SendFail() << "Syntax error: invalid size of ISS tile " << aTileSize;
66d1cdc6 11605 return 1;
11606 }
11607 aParams.RayTracingTileSize = aTileSize;
11608 }
4eaaf9d8 11609 else if (aFlag == "-nbtiles")
11610 {
11611 if (toPrint)
11612 {
11613 theDI << aParams.NbRayTracingTiles << " ";
11614 continue;
11615 }
11616 else if (++anArgIter >= theArgNb)
11617 {
23fe70ec 11618 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
4eaaf9d8 11619 return 1;
11620 }
11621
11622 const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
66d1cdc6 11623 if (aNbTiles < -1)
4eaaf9d8 11624 {
23fe70ec 11625 Message::SendFail() << "Syntax error: invalid number of ISS tiles " << aNbTiles;
4eaaf9d8 11626 return 1;
11627 }
66d1cdc6 11628 else if (aNbTiles > 0
11629 && (aNbTiles < 64
11630 || aNbTiles > 1024))
4eaaf9d8 11631 {
23fe70ec 11632 Message::SendWarning() << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].";
4eaaf9d8 11633 }
66d1cdc6 11634 aParams.NbRayTracingTiles = aNbTiles;
4eaaf9d8 11635 }
189f85a3 11636 else if (aFlag == "-env")
11637 {
11638 if (toPrint)
11639 {
11640 theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
11641 continue;
11642 }
11643
11644 Standard_Boolean toEnable = Standard_True;
11645 if (++anArgIter < theArgNb
dae2a922 11646 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
189f85a3 11647 {
11648 --anArgIter;
11649 }
11650 aParams.UseEnvironmentMapBackground = toEnable;
11651 }
78607702 11652 else if (aFlag == "-ignorenormalmap")
11653 {
11654 if (toPrint)
11655 {
11656 theDI << (aParams.ToIgnoreNormalMapInRayTracing ? "on" : "off") << " ";
11657 continue;
11658 }
11659
11660 Standard_Boolean toEnable = Standard_True;
11661 if (++anArgIter < theArgNb
dae2a922 11662 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
78607702 11663 {
11664 --anArgIter;
11665 }
11666 aParams.ToIgnoreNormalMapInRayTracing = toEnable;
11667 }
b4327ba8 11668 else if (aFlag == "-twoside")
11669 {
11670 if (toPrint)
11671 {
11672 theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
11673 continue;
11674 }
11675
11676 Standard_Boolean toEnable = Standard_True;
11677 if (++anArgIter < theArgNb
dae2a922 11678 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
b4327ba8 11679 {
11680 --anArgIter;
11681 }
11682 aParams.TwoSidedBsdfModels = toEnable;
11683 }
8625ef7e 11684 else if (aFlag == "-shademodel"
11685 || aFlag == "-shadingmodel"
11686 || aFlag == "-shading")
11687 {
11688 if (toPrint)
11689 {
11690 switch (aView->ShadingModel())
11691 {
13b36bb1 11692 case Graphic3d_TypeOfShadingModel_DEFAULT: theDI << "default"; break;
11693 case Graphic3d_TypeOfShadingModel_Unlit: theDI << "unlit "; break;
11694 case Graphic3d_TypeOfShadingModel_PhongFacet: theDI << "flat "; break;
11695 case Graphic3d_TypeOfShadingModel_Gouraud: theDI << "gouraud "; break;
11696 case Graphic3d_TypeOfShadingModel_Phong: theDI << "phong "; break;
11697 case Graphic3d_TypeOfShadingModel_Pbr: theDI << "pbr"; break;
11698 case Graphic3d_TypeOfShadingModel_PbrFacet: theDI << "pbr_facet"; break;
8625ef7e 11699 }
11700 continue;
11701 }
11702
11703 if (++anArgIter >= theArgNb)
11704 {
23fe70ec 11705 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
8625ef7e 11706 }
11707
13b36bb1 11708 Graphic3d_TypeOfShadingModel aModel = Graphic3d_TypeOfShadingModel_DEFAULT;
dc89236f 11709 if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
13b36bb1 11710 && aModel != Graphic3d_TypeOfShadingModel_DEFAULT)
8625ef7e 11711 {
dc89236f 11712 aView->SetShadingModel (aModel);
8625ef7e 11713 }
11714 else
11715 {
23fe70ec 11716 Message::SendFail() << "Syntax error: unknown shading model '" << theArgVec[anArgIter] << "'";
8625ef7e 11717 return 1;
11718 }
11719 }
67312b79 11720 else if (aFlag == "-pbrenvpow2size"
11721 || aFlag == "-pbrenvp2s"
11722 || aFlag == "-pep2s")
11723 {
11724 if (++anArgIter >= theArgNb)
11725 {
23fe70ec 11726 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
67312b79 11727 return 1;
11728 }
11729
11730 const Standard_Integer aPbrEnvPow2Size = Draw::Atoi (theArgVec[anArgIter]);
11731 if (aPbrEnvPow2Size < 1)
11732 {
23fe70ec 11733 Message::SendFail ("Syntax error: 'Pow2Size' of PBR Environment has to be greater or equal 1");
67312b79 11734 return 1;
11735 }
11736 aParams.PbrEnvPow2Size = aPbrEnvPow2Size;
11737 }
11738 else if (aFlag == "-pbrenvspecmaplevelsnumber"
11739 || aFlag == "-pbrenvspecmapnblevels"
11740 || aFlag == "-pbrenvspecmaplevels"
11741 || aFlag == "-pbrenvsmln"
11742 || aFlag == "-pesmln")
11743 {
11744 if (++anArgIter >= theArgNb)
11745 {
23fe70ec 11746 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
67312b79 11747 return 1;
11748 }
11749
11750 const Standard_Integer aPbrEnvSpecMapNbLevels = Draw::Atoi (theArgVec[anArgIter]);
11751 if (aPbrEnvSpecMapNbLevels < 2)
11752 {
23fe70ec 11753 Message::SendFail ("Syntax error: 'SpecMapLevelsNumber' of PBR Environment has to be greater or equal 2");
67312b79 11754 return 1;
11755 }
11756 aParams.PbrEnvSpecMapNbLevels = aPbrEnvSpecMapNbLevels;
11757 }
11758 else if (aFlag == "-pbrenvbakngdiffsamplesnumber"
11759 || aFlag == "-pbrenvbakingdiffsamples"
11760 || aFlag == "-pbrenvbdsn")
11761 {
11762 if (++anArgIter >= theArgNb)
11763 {
23fe70ec 11764 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
67312b79 11765 return 1;
11766 }
11767
11768 const Standard_Integer aPbrEnvBakingDiffNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11769 if (aPbrEnvBakingDiffNbSamples < 1)
11770 {
4551e1be 11771 Message::SendFail ("Syntax error: 'BakingDiffSamplesNumber' of PBR Environment has to be greater or equal 1");
67312b79 11772 return 1;
11773 }
11774 aParams.PbrEnvBakingDiffNbSamples = aPbrEnvBakingDiffNbSamples;
11775 }
11776 else if (aFlag == "-pbrenvbakngspecsamplesnumber"
11777 || aFlag == "-pbrenvbakingspecsamples"
11778 || aFlag == "-pbrenvbssn")
11779 {
11780 if (++anArgIter >= theArgNb)
11781 {
23fe70ec 11782 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
67312b79 11783 return 1;
11784 }
11785
11786 const Standard_Integer aPbrEnvBakingSpecNbSamples = Draw::Atoi(theArgVec[anArgIter]);
11787 if (aPbrEnvBakingSpecNbSamples < 1)
11788 {
4551e1be 11789 Message::SendFail ("Syntax error: 'BakingSpecSamplesNumber' of PBR Environment has to be greater or equal 1");
67312b79 11790 return 1;
11791 }
11792 aParams.PbrEnvBakingSpecNbSamples = aPbrEnvBakingSpecNbSamples;
11793 }
11794 else if (aFlag == "-pbrenvbakingprobability"
11795 || aFlag == "-pbrenvbp")
11796 {
11797 if (++anArgIter >= theArgNb)
11798 {
23fe70ec 11799 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
67312b79 11800 return 1;
11801 }
11802 const Standard_ShortReal aPbrEnvBakingProbability = static_cast<Standard_ShortReal>(Draw::Atof (theArgVec[anArgIter]));
11803 if (aPbrEnvBakingProbability < 0.f
11804 || aPbrEnvBakingProbability > 1.f)
11805 {
4551e1be 11806 Message::SendFail ("Syntax error: 'BakingProbability' of PBR Environment has to be in range of [0, 1]");
67312b79 11807 return 1;
11808 }
11809 aParams.PbrEnvBakingProbability = aPbrEnvBakingProbability;
11810 }
4b1c8733 11811 else if (aFlag == "-resolution")
11812 {
11813 if (++anArgIter >= theArgNb)
11814 {
23fe70ec 11815 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
4b1c8733 11816 return 1;
11817 }
11818
11819 TCollection_AsciiString aResolution (theArgVec[anArgIter]);
11820 if (aResolution.IsIntegerValue())
11821 {
11822 aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
11823 }
11824 else
11825 {
23fe70ec 11826 Message::SendFail() << "Syntax error: wrong syntax at argument'" << anArg << "'";
4b1c8733 11827 return 1;
11828 }
11829 }
d877e610 11830 else if (aFlag == "-rebuildglsl"
11831 || aFlag == "-rebuild")
11832 {
11833 if (toPrint)
11834 {
11835 theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
11836 continue;
11837 }
11838
11839 Standard_Boolean toEnable = Standard_True;
11840 if (++anArgIter < theArgNb
dae2a922 11841 && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable))
d877e610 11842 {
11843 --anArgIter;
11844 }
11845 aParams.RebuildRayTracingShaders = toEnable;
11846 }
b27ab03d 11847 else if (aFlag == "-focal")
11848 {
11849 if (++anArgIter >= theArgNb)
11850 {
23fe70ec 11851 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
b27ab03d 11852 return 1;
11853 }
11854
11855 TCollection_AsciiString aParam (theArgVec[anArgIter]);
d45edf24 11856 if (aParam.IsRealValue (Standard_True))
b27ab03d 11857 {
11858 float aFocalDist = static_cast<float> (aParam.RealValue());
11859 if (aFocalDist < 0)
11860 {
23fe70ec 11861 Message::SendFail() << "Error: parameter can't be negative at argument '" << anArg << "'";
b27ab03d 11862 return 1;
11863 }
11864 aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
11865 }
11866 else
11867 {
23fe70ec 11868 Message::SendFail() << "Syntax error at argument'" << anArg << "'";
b27ab03d 11869 return 1;
11870 }
11871 }
11872 else if (aFlag == "-aperture")
11873 {
11874 if (++anArgIter >= theArgNb)
11875 {
23fe70ec 11876 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
b27ab03d 11877 return 1;
11878 }
11879
11880 TCollection_AsciiString aParam(theArgVec[anArgIter]);
d45edf24 11881 if (aParam.IsRealValue (Standard_True))
b27ab03d 11882 {
11883 float aApertureSize = static_cast<float> (aParam.RealValue());
11884 if (aApertureSize < 0)
11885 {
23fe70ec 11886 Message::SendFail() << "Error: parameter can't be negative at argument '" << anArg << "'";
b27ab03d 11887 return 1;
11888 }
11889 aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
11890 }
11891 else
11892 {
23fe70ec 11893 Message::SendFail() << "Syntax error at argument'" << anArg << "'";
b27ab03d 11894 return 1;
11895 }
11896 }
eb85ed36 11897 else if (aFlag == "-exposure")
11898 {
11899 if (++anArgIter >= theArgNb)
11900 {
23fe70ec 11901 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
eb85ed36 11902 return 1;
11903 }
11904
11905 TCollection_AsciiString anExposure (theArgVec[anArgIter]);
d45edf24 11906 if (anExposure.IsRealValue (Standard_True))
eb85ed36 11907 {
11908 aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
11909 }
11910 else
11911 {
23fe70ec 11912 Message::SendFail() << "Syntax error at argument'" << anArg << "'";
eb85ed36 11913 return 1;
11914 }
11915 }
11916 else if (aFlag == "-whitepoint")
11917 {
11918 if (++anArgIter >= theArgNb)
11919 {
23fe70ec 11920 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
eb85ed36 11921 return 1;
11922 }
11923
11924 TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
d45edf24 11925 if (aWhitePoint.IsRealValue (Standard_True))
eb85ed36 11926 {
11927 aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
11928 }
11929 else
11930 {
23fe70ec 11931 Message::SendFail() << "Syntax error at argument'" << anArg << "'";
eb85ed36 11932 return 1;
11933 }
11934 }
11935 else if (aFlag == "-tonemapping")
11936 {
11937 if (++anArgIter >= theArgNb)
11938 {
23fe70ec 11939 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
eb85ed36 11940 return 1;
11941 }
11942
11943 TCollection_AsciiString aMode (theArgVec[anArgIter]);
11944 aMode.LowerCase();
11945
11946 if (aMode == "disabled")
11947 {
11948 aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
11949 }
11950 else if (aMode == "filmic")
11951 {
11952 aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
11953 }
11954 else
11955 {
23fe70ec 11956 Message::SendFail() << "Syntax error at argument'" << anArg << "'";
eb85ed36 11957 return 1;
11958 }
11959 }
15669413 11960 else if (aFlag == "-performancestats"
11961 || aFlag == "-performancecounters"
11962 || aFlag == "-perfstats"
11963 || aFlag == "-perfcounters"
11964 || aFlag == "-stats")
11965 {
11966 if (++anArgIter >= theArgNb)
11967 {
23fe70ec 11968 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
15669413 11969 return 1;
11970 }
11971
11972 TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
11973 aFlagsStr.LowerCase();
11974 Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
11975 if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
11976 {
23fe70ec 11977 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
15669413 11978 return 1;
11979 }
11980 aView->ChangeRenderingParams().CollectedStats = aFlags;
11981 aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
11982 }
11983 else if (aFlag == "-perfupdateinterval"
11984 || aFlag == "-statsupdateinterval")
11985 {
11986 if (++anArgIter >= theArgNb)
11987 {
23fe70ec 11988 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
15669413 11989 return 1;
11990 }
11991 aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11992 }
5e30547b 11993 else if (aFlag == "-perfchart"
11994 || aFlag == "-statschart")
11995 {
11996 if (++anArgIter >= theArgNb)
11997 {
23fe70ec 11998 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
5e30547b 11999 return 1;
12000 }
12001 aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
12002 }
12003 else if (aFlag == "-perfchartmax"
12004 || aFlag == "-statschartmax")
12005 {
12006 if (++anArgIter >= theArgNb)
12007 {
23fe70ec 12008 Message::SendFail() << "Syntax error at argument '" << anArg << "'";
5e30547b 12009 return 1;
12010 }
12011 aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12012 }
0e3025bc 12013 else if (aFlag == "-frustumculling"
12014 || aFlag == "-culling")
12015 {
12016 if (toPrint)
12017 {
12018 theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On) ? "on" :
12019 (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
12020 "noUpdate") << " ";
12021 continue;
12022 }
12023
12024 Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
12025 if (++anArgIter < theArgNb)
12026 {
12027 TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
12028 aStateStr.LowerCase();
12029 bool toEnable = true;
dae2a922 12030 if (Draw::ParseOnOff (aStateStr.ToCString(), toEnable))
0e3025bc 12031 {
12032 aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
12033 }
12034 else if (aStateStr == "noupdate"
12035 || aStateStr == "freeze")
12036 {
12037 aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
12038 }
12039 else
12040 {
12041 --anArgIter;
12042 }
12043 }
12044 aParams.FrustumCullingState = aState;
12045 }
e276548b 12046 else
12047 {
23fe70ec 12048 Message::SendFail() << "Syntax error: unknown flag '" << anArg << "'";
bc8c79bb 12049 return 1;
e276548b 12050 }
12051 }
189f85a3 12052
4c7a3fae 12053 // set current view parameters as defaults
12054 if (toSyncDefaults)
12055 {
12056 ViewerTest::GetViewerFromContext()->SetDefaultRenderingParams (aParams);
12057 }
12058 if (toSyncAllViews)
12059 {
12060 for (V3d_ListOfViewIterator aViewIter = ViewerTest::GetViewerFromContext()->DefinedViewIterator(); aViewIter.More(); aViewIter.Next())
12061 {
12062 aViewIter.Value()->ChangeRenderingParams() = aParams;
12063 }
12064 }
189f85a3 12065 return 0;
12066}
12067
79b544e6 12068//=======================================================================
12069//function : searchInfo
12070//purpose :
12071//=======================================================================
12072inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
12073 const TCollection_AsciiString& theKey)
12074{
12075 for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
12076 {
12077 if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
12078 {
12079 return anIter.Value();
12080 }
12081 }
12082 return TCollection_AsciiString();
12083}
12084
12085//=======================================================================
12086//function : VStatProfiler
12087//purpose :
12088//=======================================================================
12089static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12090 Standard_Integer theArgNb,
12091 const char** theArgVec)
12092{
12093 Handle(V3d_View) aView = ViewerTest::CurrentView();
12094 if (aView.IsNull())
12095 {
23fe70ec 12096 Message::SendFail ("Error: no active viewer");
79b544e6 12097 return 1;
12098 }
12099
12100 Standard_Boolean toRedraw = Standard_True;
12101 Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12102 Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12103 Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12104 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12105 {
12106 Standard_CString anArg (theArgVec[anArgIter]);
12107 TCollection_AsciiString aFlag (anArg);
12108 aFlag.LowerCase();
12109 if (aFlag == "-noredraw")
12110 {
12111 toRedraw = Standard_False;
12112 }
12113 else
12114 {
12115 Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12116 if (aFlag == "fps") aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12117 else if (aFlag == "cpu") aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12118 else if (aFlag == "alllayers"
12119 || aFlag == "layers") aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12120 else if (aFlag == "allstructs"
a2803f37 12121 || aFlag == "allstructures"
12122 || aFlag == "structs"
12123 || aFlag == "structures") aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
79b544e6 12124 else if (aFlag == "groups") aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12125 else if (aFlag == "allarrays"
12126 || aFlag == "fillarrays"
12127 || aFlag == "linearrays"
12128 || aFlag == "pointarrays"
12129 || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12130 else if (aFlag == "triangles") aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
b9f43ad1 12131 else if (aFlag == "lines") aParam = Graphic3d_RenderingParams::PerfCounters_Lines;
79b544e6 12132 else if (aFlag == "points") aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12133 else if (aFlag == "geommem"
12134 || aFlag == "texturemem"
12135 || aFlag == "framemem") aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12136 else if (aFlag == "elapsedframe"
12137 || aFlag == "cpuframeaverage"
12138 || aFlag == "cpupickingaverage"
12139 || aFlag == "cpucullingaverage"
12140 || aFlag == "cpudynaverage"
12141 || aFlag == "cpuframemax"
12142 || aFlag == "cpupickingmax"
12143 || aFlag == "cpucullingmax"
12144 || aFlag == "cpudynmax") aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12145 else
12146 {
23fe70ec 12147 Message::SendFail() << "Error: unknown argument '" << theArgVec[anArgIter] << "'";
79b544e6 12148 continue;
12149 }
12150
12151 aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12152 }
12153 }
12154
12155 if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12156 {
12157 aView->ChangeRenderingParams().CollectedStats =
12158 Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12159
12160 if (toRedraw)
12161 {
12162 aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12163 aView->Redraw();
12164 aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12165 }
12166
12167 TColStd_IndexedDataMapOfStringString aDict;
12168 aView->StatisticInformation (aDict);
12169
12170 aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12171
12172 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12173 {
12174 Standard_CString anArg(theArgVec[anArgIter]);
12175 TCollection_AsciiString aFlag(anArg);
12176 aFlag.LowerCase();
12177 if (aFlag == "fps")
12178 {
12179 theDI << searchInfo (aDict, "FPS") << " ";
12180 }
12181 else if (aFlag == "cpu")
12182 {
12183 theDI << searchInfo (aDict, "CPU FPS") << " ";
12184 }
12185 else if (aFlag == "alllayers")
12186 {
12187 theDI << searchInfo (aDict, "Layers") << " ";
12188 }
12189 else if (aFlag == "layers")
12190 {
12191 theDI << searchInfo (aDict, "Rendered layers") << " ";
12192 }
a2803f37 12193 else if (aFlag == "allstructs"
12194 || aFlag == "allstructures")
79b544e6 12195 {
12196 theDI << searchInfo (aDict, "Structs") << " ";
12197 }
a2803f37 12198 else if (aFlag == "structs"
12199 || aFlag == "structures")
79b544e6 12200 {
a2803f37 12201 TCollection_AsciiString aRend = searchInfo (aDict, "Rendered structs");
12202 if (aRend.IsEmpty()) // all structures rendered
12203 {
12204 aRend = searchInfo (aDict, "Structs");
12205 }
12206 theDI << aRend << " ";
79b544e6 12207 }
12208 else if (aFlag == "groups")
12209 {
12210 theDI << searchInfo (aDict, "Rendered groups") << " ";
12211 }
12212 else if (aFlag == "allarrays")
12213 {
12214 theDI << searchInfo (aDict, "Rendered arrays") << " ";
12215 }
12216 else if (aFlag == "fillarrays")
12217 {
12218 theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12219 }
12220 else if (aFlag == "linearrays")
12221 {
12222 theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12223 }
12224 else if (aFlag == "pointarrays")
12225 {
12226 theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12227 }
12228 else if (aFlag == "textarrays")
12229 {
12230 theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12231 }
12232 else if (aFlag == "triangles")
12233 {
12234 theDI << searchInfo (aDict, "Rendered triangles") << " ";
12235 }
12236 else if (aFlag == "points")
12237 {
12238 theDI << searchInfo (aDict, "Rendered points") << " ";
12239 }
12240 else if (aFlag == "geommem")
12241 {
12242 theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12243 }
12244 else if (aFlag == "texturemem")
12245 {
12246 theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12247 }
12248 else if (aFlag == "framemem")
12249 {
12250 theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12251 }
12252 else if (aFlag == "elapsedframe")
12253 {
12254 theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12255 }
12256 else if (aFlag == "cpuframe_average")
12257 {
12258 theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12259 }
12260 else if (aFlag == "cpupicking_average")
12261 {
12262 theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12263 }
12264 else if (aFlag == "cpuculling_average")
12265 {
12266 theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12267 }
12268 else if (aFlag == "cpudyn_average")
12269 {
12270 theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12271 }
12272 else if (aFlag == "cpuframe_max")
12273 {
12274 theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12275 }
12276 else if (aFlag == "cpupicking_max")
12277 {
12278 theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12279 }
12280 else if (aFlag == "cpuculling_max")
12281 {
12282 theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12283 }
12284 else if (aFlag == "cpudyn_max")
12285 {
12286 theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12287 }
12288 }
12289 }
12290 else
12291 {
12292 if (toRedraw)
12293 {
12294 aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12295 aView->Redraw();
12296 aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12297 }
12298 theDI << "Statistic info:\n" << aView->StatisticInformation();
12299 }
12300 return 0;
12301}
12302
0717ddc1 12303//=======================================================================
12304//function : VXRotate
12305//purpose :
12306//=======================================================================
12307static Standard_Integer VXRotate (Draw_Interpretor& di,
12308 Standard_Integer argc,
12309 const char ** argv)
12310{
12311 Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12312 if (aContext.IsNull())
12313 {
586db386 12314 di << argv[0] << "ERROR : use 'vinit' command before \n";
0717ddc1 12315 return 1;
12316 }
8693dfd0 12317
0717ddc1 12318 if (argc != 3)
12319 {
586db386 12320 di << "ERROR : Usage : " << argv[0] << " name angle\n";
0717ddc1 12321 return 1;
12322 }
12323
12324 TCollection_AsciiString aName (argv[1]);
12325 Standard_Real anAngle = Draw::Atof (argv[2]);
12326
12327 // find object
12328 ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12329 Handle(AIS_InteractiveObject) anIObj;
8f521168 12330 if (!aMap.Find2 (aName, anIObj))
0717ddc1 12331 {
586db386 12332 di << "Use 'vdisplay' before\n";
0717ddc1 12333 return 1;
12334 }
0717ddc1 12335
8f521168 12336 gp_Trsf aTransform;
12337 aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12338 aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
0717ddc1 12339
8f521168 12340 aContext->SetLocation (anIObj, aTransform);
12341 aContext->UpdateCurrentViewer();
0717ddc1 12342 return 0;
12343}
12344
ff6122e0 12345namespace
12346{
12347 //! Structure for setting AIS_Manipulator::SetPart() property.
12348 struct ManipAxisModeOnOff
12349 {
12350 Standard_Integer Axis;
12351 AIS_ManipulatorMode Mode;
12352 Standard_Boolean ToEnable;
12353
12354 ManipAxisModeOnOff() : Axis (-1), Mode (AIS_MM_None), ToEnable (false) {}
12355 };
12356
12357 enum ManipAjustPosition
12358 {
12359 ManipAjustPosition_Off,
12360 ManipAjustPosition_Center,
12361 ManipAjustPosition_Location,
12362 ManipAjustPosition_ShapeLocation,
12363 };
12364}
12365
625e1958 12366//===============================================================================================
12367//function : VManipulator
12368//purpose :
12369//===============================================================================================
12370static int VManipulator (Draw_Interpretor& theDi,
12371 Standard_Integer theArgsNb,
12372 const char** theArgVec)
12373{
bbf3fcde 12374 Handle(V3d_View) aCurrentView = ViewerTest::CurrentView();
625e1958 12375 Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
bbf3fcde 12376 if (aCurrentView.IsNull()
625e1958 12377 || aViewer.IsNull())
12378 {
23fe70ec 12379 Message::SendFail ("Error: no active viewer");
625e1958 12380 return 1;
12381 }
12382
12383 ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12384 Standard_Integer anArgIter = 1;
ff6122e0 12385 Handle(AIS_Manipulator) aManipulator;
12386 ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12387 TCollection_AsciiString aName;
12388 // parameters
12389 Standard_Integer toAutoActivate = -1, toFollowTranslation = -1, toFollowRotation = -1, toFollowDragging = -1, isZoomable = -1;
12390 Standard_Real aGap = -1.0, aSize = -1.0;
12391 NCollection_Sequence<ManipAxisModeOnOff> aParts;
12392 gp_XYZ aLocation (RealLast(), RealLast(), RealLast()), aVDir, anXDir;
12393 //
12394 bool toDetach = false;
12395 AIS_Manipulator::OptionsForAttach anAttachOptions;
12396 Handle(AIS_InteractiveObject) anAttachObject;
12397 Handle(V3d_View) aViewAffinity;
12398 ManipAjustPosition anAttachPos = ManipAjustPosition_Off;
12399 //
12400 Graphic3d_Vec2i aMousePosFrom(IntegerLast(), IntegerLast());
12401 Graphic3d_Vec2i aMousePosTo (IntegerLast(), IntegerLast());
12402 Standard_Integer toStopMouseTransform = -1;
12403 // explicit transformation
12404 gp_Trsf aTrsf;
12405 gp_XYZ aTmpXYZ;
12406 Standard_Real aTmpReal = 0.0;
12407 gp_XYZ aRotPnt, aRotAxis;
625e1958 12408 for (; anArgIter < theArgsNb; ++anArgIter)
12409 {
ff6122e0 12410 TCollection_AsciiString anArg (theArgVec[anArgIter]);
12411 anArg.LowerCase();
12412 if (anUpdateTool.parseRedrawMode (anArg))
12413 {
12414 continue;
12415 }
12416 else if (anArg == "-help")
12417 {
12418 theDi.PrintHelp (theArgVec[0]);
12419 return 0;
12420 }
12421 //
12422 else if (anArg == "-autoactivate"
12423 || anArg == "-noautoactivate")
12424 {
12425 toAutoActivate = Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0;
12426 }
12427 else if (anArg == "-followtranslation"
12428 || anArg == "-nofollowtranslation")
12429 {
12430 toFollowTranslation = Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0;
12431 }
12432 else if (anArg == "-followrotation"
12433 || anArg == "-nofollowrotation")
12434 {
12435 toFollowRotation = Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0;
12436 }
12437 else if (anArg == "-followdragging"
12438 || anArg == "-nofollowdragging")
12439 {
12440 toFollowDragging = Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0;
12441 }
12442 else if (anArg == "-gap"
12443 && anArgIter + 1 < theArgsNb
12444 && Draw::ParseReal (theArgVec[anArgIter + 1], aGap)
12445 && aGap >= 0.0)
12446 {
12447 ++anArgIter;
12448 }
12449 else if (anArg == "-size"
12450 && anArgIter + 1 < theArgsNb
12451 && Draw::ParseReal (theArgVec[anArgIter + 1], aSize)
12452 && aSize > 0.0)
12453 {
12454 ++anArgIter;
12455 }
12456 else if ((anArg == "-part" && anArgIter + 3 < theArgsNb)
12457 || (anArg == "-parts" && anArgIter + 2 < theArgsNb))
12458 {
12459 ManipAxisModeOnOff aPart;
12460 Standard_Integer aMode = 0;
12461 if (anArg == "-part")
12462 {
12463 if (!Draw::ParseInteger (theArgVec[++anArgIter], aPart.Axis)
12464 || aPart.Axis < 0 || aPart.Axis > 3)
12465 {
12466 Message::SendFail() << "Syntax error: -part axis '" << theArgVec[anArgIter] << "' is out of range [1, 3]";
12467 return 1;
12468 }
12469 }
12470 if (!Draw::ParseInteger (theArgVec[++anArgIter], aMode)
12471 || aMode < 1 || aMode > 4)
12472 {
12473 Message::SendFail() << "Syntax error: -part mode '" << theArgVec[anArgIter] << "' is out of range [1, 4]";
12474 return 1;
12475 }
12476 if (!Draw::ParseOnOff (theArgVec[++anArgIter], aPart.ToEnable))
12477 {
12478 Message::SendFail() << "Syntax error: -part value on/off '" << theArgVec[anArgIter] << "' is incorrect";
12479 return 1;
12480 }
12481 aPart.Mode = static_cast<AIS_ManipulatorMode> (aMode);
12482 aParts.Append (aPart);
12483 }
12484 else if (anArg == "-pos"
12485 && anArgIter + 3 < theArgsNb
12486 && parseXYZ (theArgVec + anArgIter + 1, aLocation))
12487 {
12488 anArgIter += 3;
12489 if (anArgIter + 3 < theArgsNb
12490 && parseXYZ (theArgVec + anArgIter + 1, aVDir)
12491 && aVDir.Modulus() > Precision::Confusion())
12492 {
12493 anArgIter += 3;
12494 }
12495 if (anArgIter + 3 < theArgsNb
12496 && parseXYZ (theArgVec + anArgIter + 1, anXDir)
12497 && anXDir.Modulus() > Precision::Confusion())
12498 {
12499 anArgIter += 3;
12500 }
12501 }
12502 else if (anArg == "-zoomable"
12503 || anArg == "-notzoomable")
12504 {
12505 isZoomable = Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0;
12506 }
12507 //
12508 else if (anArg == "-adjustposition"
12509 || anArg == "-noadjustposition")
12510 {
12511 anAttachPos = ManipAjustPosition_Center;
12512 if (anArgIter + 1 < theArgsNb)
12513 {
12514 TCollection_AsciiString aPosName (theArgVec[++anArgIter]);
12515 aPosName.LowerCase();
12516 if (aPosName == "0")
12517 {
12518 anAttachPos = ManipAjustPosition_Off;
12519 }
12520 else if (aPosName == "1"
12521 || aPosName == "center")
12522 {
12523 anAttachPos = ManipAjustPosition_Center;
12524 }
12525 else if (aPosName == "transformation"
12526 || aPosName == "trsf"
12527 || aPosName == "location"
12528 || aPosName == "loc")
12529 {
12530 anAttachPos = ManipAjustPosition_Location;
12531 }
12532 else if (aPosName == "shapelocation"
12533 || aPosName == "shapeloc")
12534 {
12535 anAttachPos = ManipAjustPosition_ShapeLocation;
12536 }
12537 else
12538 {
12539 --anArgIter;
12540 }
12541 }
12542 anAttachOptions.SetAdjustPosition (anAttachPos == ManipAjustPosition_Center);
12543 }
12544 else if (anArg == "-adjustsize"
12545 || anArg == "-noadjustsize")
12546 {
12547 anAttachOptions.SetAdjustSize (Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0);
12548 }
12549 else if (anArg == "-enablemodes"
12550 || anArg == "-enablemodes")
12551 {
12552 anAttachOptions.SetEnableModes (Draw::ParseOnOffNoIterator (theArgsNb, theArgVec, anArgIter) ? 1 : 0);
12553 }
12554 //
12555 else if (anArg == "-starttransform"
12556 && anArgIter + 2 < theArgsNb
12557 && Draw::ParseInteger (theArgVec[anArgIter + 1], aMousePosFrom.x())
12558 && Draw::ParseInteger (theArgVec[anArgIter + 2], aMousePosFrom.y()))
12559 {
12560 anArgIter += 2;
12561 }
12562 else if (anArg == "-transform"
12563 && anArgIter + 2 < theArgsNb
12564 && Draw::ParseInteger (theArgVec[anArgIter + 1], aMousePosTo.x())
12565 && Draw::ParseInteger (theArgVec[anArgIter + 2], aMousePosTo.y()))
12566 {
12567 anArgIter += 2;
12568 }
12569 else if (anArg == "-stoptransform")
12570 {
12571 toStopMouseTransform = 1;
12572 if (anArgIter + 1 < theArgsNb
12573 && TCollection_AsciiString::IsSameString (theArgVec[anArgIter + 1], "abort", false))
12574 {
12575 ++anArgIter;
12576 toStopMouseTransform = 0;
12577 }
12578 }
12579 //
12580 else if (anArg == "-move"
12581 && anArgIter + 3 < theArgsNb
12582 && parseXYZ (theArgVec + anArgIter + 1, aTmpXYZ))
12583 {
12584 anArgIter += 3;
12585 aTrsf.SetTranslationPart (aTmpXYZ);
12586 }
12587 else if (anArg == "-scale"
12588 && anArgIter + 1 < theArgsNb
12589 && Draw::ParseReal (theArgVec[anArgIter + 1], aTmpReal))
12590 {
12591 ++anArgIter;
12592 aTrsf.SetScale (gp_Pnt(), aTmpReal);
12593 }
12594 else if (anArg == "-rotate"
12595 && anArgIter + 7 < theArgsNb
12596 && parseXYZ (theArgVec + anArgIter + 1, aRotPnt)
12597 && parseXYZ (theArgVec + anArgIter + 4, aRotAxis)
12598 && Draw::ParseReal (theArgVec[anArgIter + 7], aTmpReal))
12599 {
12600 anArgIter += 7;
12601 aTrsf.SetRotation (gp_Ax1 (gp_Pnt (aRotPnt), gp_Dir (aRotAxis)), aTmpReal);
12602 }
12603 //
12604 else if (anArg == "-detach")
12605 {
12606 toDetach = true;
12607 }
12608 else if (anArg == "-attach"
12609 && anArgIter + 1 < theArgsNb)
12610 {
12611 TCollection_AsciiString anObjName (theArgVec[++anArgIter]);
12612 if (!aMapAIS.Find2 (anObjName, anAttachObject))
12613 {
12614 Message::SendFail() << "Syntax error: AIS object '" << anObjName << "' does not exist";
12615 return 1;
12616 }
625e1958 12617
ff6122e0 12618 for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIter (aMapAIS); anIter.More(); anIter.Next())
12619 {
12620 Handle(AIS_Manipulator) aManip = Handle(AIS_Manipulator)::DownCast (anIter.Key1());
12621 if (!aManip.IsNull()
12622 && aManip->IsAttached()
12623 && aManip->Object() == anAttachObject)
12624 {
12625 Message::SendFail() << "Syntax error: AIS object '" << anObjName << "' already has manipulator";
12626 return 1;
12627 }
12628 }
12629 }
12630 else if (anArg == "-view"
12631 && anArgIter + 1 < theArgsNb
12632 && aViewAffinity.IsNull())
12633 {
12634 TCollection_AsciiString aViewString (theArgVec[++anArgIter]);
12635 if (aViewString == "active")
12636 {
12637 aViewAffinity = ViewerTest::CurrentView();
12638 }
12639 else // Check view name
12640 {
12641 ViewerTest_Names aViewNames (aViewString);
12642 if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
12643 {
12644 Message::SendFail() << "Syntax error: wrong view name '" << aViewString << "'";
12645 return 1;
12646 }
12647 aViewAffinity = ViewerTest_myViews.Find1 (aViewNames.GetViewName());
12648 if (aViewAffinity.IsNull())
12649 {
12650 Message::SendFail() << "Syntax error: cannot find view with name '" << aViewString << "'";
12651 return 1;
12652 }
12653 }
12654 }
12655 else if (aName.IsEmpty())
12656 {
12657 aName = theArgVec[anArgIter];
12658 if (!aMapAIS.IsBound2 (aName))
12659 {
12660 aManipulator = new AIS_Manipulator();
12661 aManipulator->SetModeActivationOnDetection (true);
12662 aMapAIS.Bind (aManipulator, aName);
12663 }
12664 else
12665 {
12666 aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12667 if (aManipulator.IsNull())
12668 {
12669 Message::SendFail() << "Syntax error: \"" << aName << "\" is not an AIS manipulator";
12670 return 1;
12671 }
12672 }
12673 }
12674 else
12675 {
12676 theDi << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
12677 }
625e1958 12678 }
12679
625e1958 12680 if (aName.IsEmpty())
12681 {
23fe70ec 12682 Message::SendFail ("Syntax error: please specify AIS manipulator's name as the first argument");
625e1958 12683 return 1;
12684 }
ff6122e0 12685 if (!toDetach
12686 && aManipulator.IsNull())
625e1958 12687 {
8b037fe4 12688 aManipulator = new AIS_Manipulator();
49582f9d 12689 aManipulator->SetModeActivationOnDetection (true);
625e1958 12690 aMapAIS.Bind (aManipulator, aName);
12691 }
625e1958 12692
12693 // -----------------------------------------
12694 // change properties of manipulator instance
12695 // -----------------------------------------
12696
ff6122e0 12697 if (toAutoActivate != -1)
625e1958 12698 {
ff6122e0 12699 aManipulator->SetModeActivationOnDetection (toAutoActivate == 1);
625e1958 12700 }
ff6122e0 12701 if (toFollowTranslation != -1)
625e1958 12702 {
ff6122e0 12703 aManipulator->ChangeTransformBehavior().SetFollowTranslation (toFollowTranslation == 1);
625e1958 12704 }
ff6122e0 12705 if (toFollowRotation != -1)
625e1958 12706 {
ff6122e0 12707 aManipulator->ChangeTransformBehavior().SetFollowRotation (toFollowRotation == 1);
625e1958 12708 }
ff6122e0 12709 if (toFollowDragging != -1)
f522ce50 12710 {
ff6122e0 12711 aManipulator->ChangeTransformBehavior().SetFollowDragging (toFollowDragging == 1);
f522ce50 12712 }
ff6122e0 12713 if (aGap >= 0.0f)
625e1958 12714 {
ff6122e0 12715 aManipulator->SetGap ((float )aGap);
625e1958 12716 }
ff6122e0 12717
12718 for (NCollection_Sequence<ManipAxisModeOnOff>::Iterator aPartIter (aParts); aPartIter.More(); aPartIter.Next())
625e1958 12719 {
ff6122e0 12720 const ManipAxisModeOnOff& aPart = aPartIter.Value();
12721 if (aPart.Axis == -1)
625e1958 12722 {
ff6122e0 12723 aManipulator->SetPart (aPart.Mode, aPart.ToEnable);
625e1958 12724 }
ff6122e0 12725 else
84b904bc 12726 {
ff6122e0 12727 aManipulator->SetPart (aPart.Axis, aPart.Mode, aPart.ToEnable);
84b904bc 12728 }
84b904bc 12729 }
625e1958 12730
ff6122e0 12731 if (aSize > 0.0)
625e1958 12732 {
ff6122e0 12733 aManipulator->SetSize ((float )aSize);
625e1958 12734 }
ff6122e0 12735 if (isZoomable != -1)
625e1958 12736 {
ff6122e0 12737 aManipulator->SetZoomPersistence (isZoomable == 0);
625e1958 12738
12739 if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12740 {
12741 ViewerTest::GetAISContext()->Remove (aManipulator, Standard_False);
12742 ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12743 }
12744 }
12745
ff6122e0 12746 // ----------------------------------
12747 // detach existing manipulator object
12748 // ----------------------------------
12749
12750 if (toDetach)
12751 {
12752 aManipulator->Detach();
12753 aMapAIS.UnBind2 (aName);
12754 ViewerTest::GetAISContext()->Remove (aManipulator, false);
12755 }
12756
625e1958 12757 // ---------------------------------------------------
12758 // attach, detach or access manipulator from an object
12759 // ---------------------------------------------------
12760
ff6122e0 12761 if (!anAttachObject.IsNull())
625e1958 12762 {
ff6122e0 12763 aManipulator->Attach (anAttachObject, anAttachOptions);
12764 }
12765 if (!aViewAffinity.IsNull())
12766 {
1103eb60 12767 for (ViewerTest_ViewerCommandsViewMap::Iterator anIter (ViewerTest_myViews);
8b037fe4 12768 anIter.More(); anIter.Next())
625e1958 12769 {
1103eb60 12770 ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, anIter.Key2(), false);
625e1958 12771 }
ff6122e0 12772 ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, aViewAffinity, true);
12773 }
625e1958 12774
ff6122e0 12775 if (anAttachPos != ManipAjustPosition_Off
12776 && aManipulator->IsAttached()
12777 && (anAttachObject.IsNull() || anAttachPos != ManipAjustPosition_Center))
12778 {
12779 gp_Ax2 aPosition = gp::XOY();
12780 const gp_Trsf aBaseTrsf = aManipulator->Object()->LocalTransformation();
12781 switch (anAttachPos)
bbf3fcde 12782 {
ff6122e0 12783 case ManipAjustPosition_Off:
bbf3fcde 12784 {
ff6122e0 12785 break;
bbf3fcde 12786 }
ff6122e0 12787 case ManipAjustPosition_Location:
bbf3fcde 12788 {
ff6122e0 12789 aPosition = gp::XOY().Transformed (aBaseTrsf);
12790 break;
bbf3fcde 12791 }
ff6122e0 12792 case ManipAjustPosition_ShapeLocation:
bbf3fcde 12793 {
ff6122e0 12794 if (Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aManipulator->Object()))
bbf3fcde 12795 {
ff6122e0 12796 aPosition = gp::XOY().Transformed (aBaseTrsf * aShapePrs->Shape().Location());
bbf3fcde 12797 }
ff6122e0 12798 else
bbf3fcde 12799 {
ff6122e0 12800 Message::SendFail() << "Syntax error: manipulator is not attached to shape";
bbf3fcde 12801 return 1;
12802 }
ff6122e0 12803 break;
bbf3fcde 12804 }
ff6122e0 12805 case ManipAjustPosition_Center:
bbf3fcde 12806 {
ff6122e0 12807 Bnd_Box aBox;
12808 for (AIS_ManipulatorObjectSequence::Iterator anObjIter (*aManipulator->Objects()); anObjIter.More(); anObjIter.Next())
12809 {
12810 Bnd_Box anObjBox;
12811 anObjIter.Value()->BoundingBox (anObjBox);
12812 aBox.Add (anObjBox);
12813 }
12814 aBox = aBox.FinitePart();
12815 if (!aBox.IsVoid())
12816 {
12817 const gp_Pnt aCenter = (aBox.CornerMin().XYZ() + aBox.CornerMax().XYZ()) * 0.5;
12818 aPosition.SetLocation (aCenter);
12819 }
12820 break;
bbf3fcde 12821 }
bbf3fcde 12822 }
ff6122e0 12823 aManipulator->SetPosition (aPosition);
12824 }
12825 if (!Precision::IsInfinite (aLocation.X()))
12826 {
12827 if (aVDir.Modulus() <= Precision::Confusion())
12828 {
12829 aVDir = aManipulator->Position().Direction().XYZ();
12830 }
12831 if (anXDir.Modulus() <= Precision::Confusion())
12832 {
12833 anXDir = aManipulator->Position().XDirection().XYZ();
12834 }
12835 aManipulator->SetPosition (gp_Ax2 (gp_Pnt (aLocation), gp_Dir (aVDir), gp_Dir (anXDir)));
625e1958 12836 }
12837
12838 // --------------------------------------
12839 // apply transformation using manipulator
12840 // --------------------------------------
12841
ff6122e0 12842 if (aMousePosFrom.x() != IntegerLast())
625e1958 12843 {
ff6122e0 12844 aManipulator->StartTransform (aMousePosFrom.x(), aMousePosFrom.y(), ViewerTest::CurrentView());
625e1958 12845 }
ff6122e0 12846 if (aMousePosTo.x() != IntegerLast())
625e1958 12847 {
ff6122e0 12848 aManipulator->Transform (aMousePosTo.x(), aMousePosTo.y(), ViewerTest::CurrentView());
625e1958 12849 }
ff6122e0 12850 if (toStopMouseTransform != -1)
625e1958 12851 {
ff6122e0 12852 aManipulator->StopTransform (toStopMouseTransform == 1);
625e1958 12853 }
12854
ff6122e0 12855 if (aTrsf.Form() != gp_Identity)
625e1958 12856 {
ff6122e0 12857 aManipulator->Transform (aTrsf);
625e1958 12858 }
12859
ff6122e0 12860 if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
625e1958 12861 {
ff6122e0 12862 ViewerTest::GetAISContext()->Redisplay (aManipulator, true);
625e1958 12863 }
625e1958 12864 return 0;
12865}
12866
8e5fb5ea 12867//===============================================================================================
12868//function : VSelectionProperties
12869//purpose :
12870//===============================================================================================
12871static int VSelectionProperties (Draw_Interpretor& theDi,
12872 Standard_Integer theArgsNb,
12873 const char** theArgVec)
12874{
12875 const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12876 if (aCtx.IsNull())
12877 {
23fe70ec 12878 Message::SendFail ("Error: no active viewer");
8e5fb5ea 12879 return 1;
12880 }
12881
be3d8cbc 12882 if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
12883 {
12884 // handle obsolete alias
12885 bool toEnable = true;
12886 if (theArgsNb < 2)
12887 {
12888 theDi << (aCtx->ToHilightSelected() ? "on" : "off");
12889 return 0;
12890 }
12891 else if (theArgsNb != 2
dae2a922 12892 || !Draw::ParseOnOff (theArgVec[1], toEnable))
be3d8cbc 12893 {
23fe70ec 12894 Message::SendFail ("Syntax error: wrong number of parameters");
be3d8cbc 12895 return 1;
12896 }
12897 if (toEnable != aCtx->ToHilightSelected())
12898 {
12899 aCtx->ClearDetected();
12900 aCtx->SetToHilightSelected (toEnable);
12901 }
12902 return 0;
12903 }
12904
f838dac4 12905 Standard_Boolean toPrint = theArgsNb == 1;
12906 Standard_Boolean toRedraw = Standard_False;
12907 Standard_Integer anArgIter = 1;
12908 Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
12909 if (anArgIter < theArgsNb)
12910 {
12911 TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
12912 anArgFirst.LowerCase();
12913 ++anArgIter;
12914 if (anArgFirst == "dynhighlight"
12915 || anArgFirst == "dynhilight"
12916 || anArgFirst == "dynamichighlight"
12917 || anArgFirst == "dynamichilight")
12918 {
12919 aType = Prs3d_TypeOfHighlight_Dynamic;
12920 }
12921 else if (anArgFirst == "localdynhighlight"
12922 || anArgFirst == "localdynhilight"
12923 || anArgFirst == "localdynamichighlight"
12924 || anArgFirst == "localdynamichilight")
12925 {
12926 aType = Prs3d_TypeOfHighlight_LocalDynamic;
12927 }
12928 else if (anArgFirst == "selhighlight"
12929 || anArgFirst == "selhilight"
12930 || anArgFirst == "selectedhighlight"
12931 || anArgFirst == "selectedhilight")
12932 {
12933 aType = Prs3d_TypeOfHighlight_Selected;
12934 }
12935 else if (anArgFirst == "localselhighlight"
12936 || anArgFirst == "localselhilight"
12937 || anArgFirst == "localselectedhighlight"
12938 || anArgFirst == "localselectedhilight")
12939 {
12940 aType = Prs3d_TypeOfHighlight_LocalSelected;
12941 }
12942 else
12943 {
12944 --anArgIter;
12945 }
12946 }
12947 for (; anArgIter < theArgsNb; ++anArgIter)
12948 {
12949 TCollection_AsciiString anArg (theArgVec[anArgIter]);
12950 anArg.LowerCase();
12951 if (anArg == "-help")
12952 {
12953 theDi.PrintHelp (theArgVec[0]);
12954 return 0;
12955 }
12956 else if (anArg == "-print")
12957 {
12958 toPrint = Standard_True;
12959 }
12960 else if (anArg == "-autoactivate")
12961 {
12962 Standard_Boolean toEnable = Standard_True;
12963 if (anArgIter + 1 < theArgsNb
dae2a922 12964 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
f838dac4 12965 {
12966 ++anArgIter;
12967 }
12968 aCtx->SetAutoActivateSelection (toEnable);
12969 }
be3d8cbc 12970 else if (anArg == "-automatichighlight"
12971 || anArg == "-automatichilight"
12972 || anArg == "-autohighlight"
12973 || anArg == "-autohilight")
12974 {
12975 Standard_Boolean toEnable = Standard_True;
12976 if (anArgIter + 1 < theArgsNb
dae2a922 12977 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
be3d8cbc 12978 {
12979 ++anArgIter;
12980 }
12981 aCtx->ClearSelected (false);
12982 aCtx->ClearDetected();
12983 aCtx->SetAutomaticHilight (toEnable);
12984 toRedraw = true;
12985 }
12986 else if (anArg == "-highlightselected"
12987 || anArg == "-hilightselected")
12988 {
12989 Standard_Boolean toEnable = Standard_True;
12990 if (anArgIter + 1 < theArgsNb
dae2a922 12991 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
be3d8cbc 12992 {
12993 ++anArgIter;
12994 }
12995 aCtx->ClearDetected();
12996 aCtx->SetToHilightSelected (toEnable);
12997 toRedraw = true;
12998 }
14c4193d 12999 else if (anArg == "-pickstrategy"
13000 || anArg == "-pickingstrategy")
13001 {
13002 if (++anArgIter >= theArgsNb)
13003 {
23fe70ec 13004 Message::SendFail ("Syntax error: type of highlighting is undefined");
14c4193d 13005 return 1;
13006 }
13007
13008 SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13009 TCollection_AsciiString aVal (theArgVec[anArgIter]);
13010 aVal.LowerCase();
13011 if (aVal == "first"
13012 || aVal == "firstaccepted"
13013 || aVal == "firstacceptable")
13014 {
13015 aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
13016 }
13017 else if (aVal == "topmost"
13018 || aVal == "onlyTopmost")
13019 {
13020 aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
13021 }
13022 else
13023 {
23fe70ec 13024 Message::SendFail() << "Syntax error: unknown picking strategy '" << aVal << "'";
14c4193d 13025 return 1;
13026 }
13027
13028 aCtx->SetPickingStrategy (aStrategy);
13029 }
f838dac4 13030 else if (anArg == "-pixtol"
13031 && anArgIter + 1 < theArgsNb)
13032 {
13033 aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
13034 }
8c36926a 13035 else if (anArg == "-preferclosest")
13036 {
13037 bool toPreferClosest = true;
13038 if (anArgIter + 1 < theArgsNb
13039 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toPreferClosest))
13040 {
13041 ++anArgIter;
13042 }
13043 aCtx->MainSelector()->SetPickClosest (toPreferClosest);
13044 }
13045 else if ((anArg == "-depthtol"
13046 || anArg == "-depthtolerance")
13047 && anArgIter + 1 < theArgsNb)
13048 {
13049 TCollection_AsciiString aTolType (theArgVec[++anArgIter]);
13050 aTolType.LowerCase();
13051 if (aTolType == "uniform")
13052 {
13053 if (anArgIter + 1 >= theArgsNb)
13054 {
13055 Message::SendFail() << "Syntax error: wrong number of arguments";
13056 return 1;
13057 }
13058 aCtx->MainSelector()->SetDepthTolerance (SelectMgr_TypeOfDepthTolerance_Uniform,
13059 Draw::Atof (theArgVec[++anArgIter]));
13060 }
13061 else if (aTolType == "uniformpx")
13062 {
13063 if (anArgIter + 1 >= theArgsNb)
13064 {
13065 Message::SendFail() << "Syntax error: wrong number of arguments";
13066 return 1;
13067 }
13068 aCtx->MainSelector()->SetDepthTolerance (SelectMgr_TypeOfDepthTolerance_UniformPixels,
13069 Draw::Atof (theArgVec[++anArgIter]));
13070 }
13071 else if (aTolType == "sensfactor")
13072 {
13073 aCtx->MainSelector()->SetDepthTolerance (SelectMgr_TypeOfDepthTolerance_SensitivityFactor, 0.0);
13074 }
13075 else
13076 {
13077 Message::SendFail() << "Syntax error at '" << aTolType << "'";
13078 return 1;
13079 }
13080 }
f838dac4 13081 else if ((anArg == "-mode"
13082 || anArg == "-dispmode")
13083 && anArgIter + 1 < theArgsNb)
13084 {
13085 if (aType == Prs3d_TypeOfHighlight_None)
13086 {
23fe70ec 13087 Message::SendFail ("Syntax error: type of highlighting is undefined");
f838dac4 13088 return 1;
13089 }
8e5fb5ea 13090
f838dac4 13091 const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
13092 const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13093 aStyle->SetDisplayMode (aDispMode);
13094 toRedraw = Standard_True;
13095 }
13096 else if (anArg == "-layer"
13097 && anArgIter + 1 < theArgsNb)
13098 {
13099 if (aType == Prs3d_TypeOfHighlight_None)
13100 {
23fe70ec 13101 Message::SendFail ("Syntax error: type of highlighting is undefined");
f838dac4 13102 return 1;
13103 }
8e5fb5ea 13104
55c8f0f7
BB
13105 ++anArgIter;
13106 Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
13107 if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
f838dac4 13108 {
23fe70ec 13109 Message::SendFail() << "Syntax error at " << theArgVec[anArgIter];
55c8f0f7 13110 return 1;
f838dac4 13111 }
8e5fb5ea 13112
f838dac4 13113 const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13114 aStyle->SetZLayer (aNewLayer);
13115 toRedraw = Standard_True;
13116 }
13117 else if (anArg == "-hicolor"
13118 || anArg == "-selcolor"
13119 || anArg == "-color")
13120 {
13121 if (anArg.StartsWith ("-hi"))
13122 {
13123 aType = Prs3d_TypeOfHighlight_Dynamic;
13124 }
13125 else if (anArg.StartsWith ("-sel"))
13126 {
13127 aType = Prs3d_TypeOfHighlight_Selected;
13128 }
13129 else if (aType == Prs3d_TypeOfHighlight_None)
13130 {
23fe70ec 13131 Message::SendFail ("Syntax error: type of highlighting is undefined");
f838dac4 13132 return 1;
13133 }
8e5fb5ea 13134
f838dac4 13135 Quantity_Color aColor;
dae2a922 13136 Standard_Integer aNbParsed = Draw::ParseColor (theArgsNb - anArgIter - 1,
13137 theArgVec + anArgIter + 1,
13138 aColor);
f838dac4 13139 if (aNbParsed == 0)
13140 {
23fe70ec 13141 Message::SendFail ("Syntax error: need more arguments");
f838dac4 13142 return 1;
13143 }
13144 anArgIter += aNbParsed;
8e5fb5ea 13145
f838dac4 13146 const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13147 aStyle->SetColor (aColor);
13148 toRedraw = Standard_True;
13149 }
13150 else if ((anArg == "-transp"
13151 || anArg == "-transparency"
13152 || anArg == "-hitransp"
13153 || anArg == "-seltransp"
13154 || anArg == "-hitransplocal"
13155 || anArg == "-seltransplocal")
13156 && anArgIter + 1 < theArgsNb)
13157 {
13158 if (anArg.StartsWith ("-hi"))
13159 {
13160 aType = Prs3d_TypeOfHighlight_Dynamic;
13161 }
13162 else if (anArg.StartsWith ("-sel"))
13163 {
13164 aType = Prs3d_TypeOfHighlight_Selected;
13165 }
13166 else if (aType == Prs3d_TypeOfHighlight_None)
13167 {
23fe70ec 13168 Message::SendFail ("Syntax error: type of highlighting is undefined");
f838dac4 13169 return 1;
13170 }
8e5fb5ea 13171
f838dac4 13172 const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
13173 const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13174 aStyle->SetTransparency ((Standard_ShortReal )aTransp);
13175 toRedraw = Standard_True;
13176 }
13177 else if ((anArg == "-mat"
13178 || anArg == "-material")
13179 && anArgIter + 1 < theArgsNb)
13180 {
13181 if (aType == Prs3d_TypeOfHighlight_None)
13182 {
23fe70ec 13183 Message::SendFail ("Syntax error: type of highlighting is undefined");
f838dac4 13184 return 1;
13185 }
8e5fb5ea 13186
f838dac4 13187 const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13188 Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
a966542b 13189 if (aMatName != Graphic3d_NameOfMaterial_DEFAULT)
f838dac4 13190 {
13191 ++anArgIter;
13192 Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
13193 *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
13194 Graphic3d_MaterialAspect aMat (aMatName);
13195 aMat.SetColor (aStyle->Color());
13196 aMat.SetTransparency (aStyle->Transparency());
13197 anAspect->SetFrontMaterial (aMat);
13198 anAspect->SetInteriorColor (aStyle->Color());
13199 aStyle->SetBasicFillAreaAspect (anAspect);
13200 }
13201 else
13202 {
13203 aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
13204 }
13205 toRedraw = Standard_True;
13206 }
13207 else
13208 {
23fe70ec 13209 Message::SendFail() << "Syntax error at '" << theArgVec[anArgIter] << "'";
8c36926a 13210 return 1;
f838dac4 13211 }
8e5fb5ea 13212 }
13213
f838dac4 13214 if (toPrint)
8e5fb5ea 13215 {
f838dac4 13216 const Handle(Prs3d_Drawer)& aHiStyle = aCtx->HighlightStyle();
13217 const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
8e5fb5ea 13218 theDi << "Auto-activation : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
be3d8cbc 13219 theDi << "Auto-highlight : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
13220 theDi << "Highlight selected : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
8e5fb5ea 13221 theDi << "Selection pixel tolerance : " << aCtx->MainSelector()->PixelTolerance() << "\n";
f838dac4 13222 theDi << "Selection color : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
13223 theDi << "Dynamic highlight color : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
13224 theDi << "Selection transparency : " << aSelStyle->Transparency() << "\n";
13225 theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
13226 theDi << "Selection mode : " << aSelStyle->DisplayMode() << "\n";
13227 theDi << "Dynamic highlight mode : " << aHiStyle->DisplayMode() << "\n";
13228 theDi << "Selection layer : " << aSelStyle->ZLayer() << "\n";
13229 theDi << "Dynamic layer : " << aHiStyle->ZLayer() << "\n";
8e5fb5ea 13230 }
13231
13232 if (aCtx->NbSelected() != 0 && toRedraw)
13233 {
13234 aCtx->HilightSelected (Standard_True);
13235 }
13236
13237 return 0;
13238}
13239
decdee7d 13240//===============================================================================================
13241//function : VDumpSelectionImage
13242//purpose :
13243//===============================================================================================
13244static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
13245 Standard_Integer theArgsNb,
13246 const char** theArgVec)
13247{
decdee7d 13248 const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
b40cdc2b 13249 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
decdee7d 13250 if (aContext.IsNull())
13251 {
23fe70ec 13252 Message::SendFail ("Error: no active viewer");
decdee7d 13253 return 1;
13254 }
13255
13256 TCollection_AsciiString aFile;
13257 StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
b40cdc2b 13258 Handle(Graphic3d_Camera) aCustomCam;
dc858f4c 13259 Image_Format anImgFormat = Image_Format_BGR;
decdee7d 13260 Standard_Integer aPickedIndex = 1;
13261 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
13262 {
13263 TCollection_AsciiString aParam (theArgVec[anArgIter]);
13264 aParam.LowerCase();
13265 if (aParam == "-type")
13266 {
13267 if (++anArgIter >= theArgsNb)
13268 {
df23a355 13269 Message::SendFail ("Syntax error: wrong number parameters of flag '-type'");
decdee7d 13270 return 1;
13271 }
13272
13273 TCollection_AsciiString aValue (theArgVec[anArgIter]);
13274 aValue.LowerCase();
13275 if (aValue == "depth"
13276 || aValue == "normdepth"
13277 || aValue == "normalizeddepth")
13278 {
13279 aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
dc858f4c 13280 anImgFormat = Image_Format_GrayF;
decdee7d 13281 }
df23a355 13282 else if (aValue == "depthinverted"
13283 || aValue == "normdepthinverted"
13284 || aValue == "normalizeddepthinverted"
13285 || aValue == "inverted")
decdee7d 13286 {
13287 aType = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
dc858f4c 13288 anImgFormat = Image_Format_GrayF;
decdee7d 13289 }
13290 else if (aValue == "unnormdepth"
13291 || aValue == "unnormalizeddepth")
13292 {
13293 aType = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
dc858f4c 13294 anImgFormat = Image_Format_GrayF;
decdee7d 13295 }
13296 else if (aValue == "objectcolor"
13297 || aValue == "object"
13298 || aValue == "color")
13299 {
13300 aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
13301 }
13302 else if (aValue == "entitycolor"
13303 || aValue == "entity")
13304 {
13305 aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
13306 }
9dd8af26 13307 else if (aValue == "entitytypecolor"
13308 || aValue == "entitytype")
13309 {
13310 aType = StdSelect_TypeOfSelectionImage_ColoredEntityType;
13311 }
decdee7d 13312 else if (aValue == "ownercolor"
13313 || aValue == "owner")
13314 {
13315 aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
13316 }
13317 else if (aValue == "selectionmodecolor"
13318 || aValue == "selectionmode"
13319 || aValue == "selmodecolor"
13320 || aValue == "selmode")
13321 {
13322 aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13323 }
114e7a90 13324 else if (aValue == "surfnormal"
13325 || aValue == "surfacenormal"
13326 || aValue == "normal")
13327 {
13328 aType = StdSelect_TypeOfSelectionImage_SurfaceNormal;
13329 }
df23a355 13330 else
13331 {
13332 Message::SendFail() << "Syntax error: unknown type '" << aValue << "'";
13333 return 1;
13334 }
decdee7d 13335 }
13336 else if (aParam == "-picked"
13337 || aParam == "-pickeddepth"
13338 || aParam == "-pickedindex")
13339 {
13340 if (++anArgIter >= theArgsNb)
13341 {
23fe70ec 13342 Message::SendFail() << "Syntax error: wrong number parameters at '" << aParam << "'";
decdee7d 13343 return 1;
13344 }
13345
13346 aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13347 }
b40cdc2b 13348 else if (anArgIter + 1 < theArgsNb
13349 && aParam == "-xrpose")
13350 {
13351 TCollection_AsciiString anXRArg (theArgVec[++anArgIter]);
13352 anXRArg.LowerCase();
13353 if (anXRArg == "base")
13354 {
13355 aCustomCam = aView->View()->BaseXRCamera();
13356 }
13357 else if (anXRArg == "head")
13358 {
13359 aCustomCam = aView->View()->PosedXRCamera();
13360 }
13361 else
13362 {
13363 Message::SendFail() << "Syntax error: unknown XR pose '" << anXRArg << "'";
13364 return 1;
13365 }
13366 if (aCustomCam.IsNull())
13367 {
13368 Message::SendFail() << "Error: undefined XR pose";
13369 return 0;
13370 }
13371 }
decdee7d 13372 else if (aFile.IsEmpty())
13373 {
13374 aFile = theArgVec[anArgIter];
13375 }
13376 else
13377 {
23fe70ec 13378 Message::SendFail() << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
decdee7d 13379 return 1;
13380 }
13381 }
13382 if (aFile.IsEmpty())
13383 {
23fe70ec 13384 Message::SendFail ("Syntax error: image file name is missing");
decdee7d 13385 return 1;
13386 }
13387
decdee7d 13388 Standard_Integer aWidth = 0, aHeight = 0;
13389 aView->Window()->Size (aWidth, aHeight);
13390
13391 Image_AlienPixMap aPixMap;
13392 if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13393 {
23fe70ec 13394 Message::SendFail ("Error: can't allocate image");
decdee7d 13395 return 1;
13396 }
b40cdc2b 13397
13398 const bool wasImmUpdate = aView->SetImmediateUpdate (false);
13399 Handle(Graphic3d_Camera) aCamBack = aView->Camera();
13400 if (!aCustomCam.IsNull())
13401 {
13402 aView->SetCamera (aCustomCam);
13403 }
decdee7d 13404 if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13405 {
23fe70ec 13406 Message::SendFail ("Error: can't generate selection image");
decdee7d 13407 return 1;
13408 }
b40cdc2b 13409 if (!aCustomCam.IsNull())
13410 {
13411 aView->SetCamera (aCamBack);
13412 }
13413 aView->SetImmediateUpdate (wasImmUpdate);
13414
decdee7d 13415 if (!aPixMap.Save (aFile))
13416 {
23fe70ec 13417 Message::SendFail ("Error: can't save selection image");
decdee7d 13418 return 0;
13419 }
13420 return 0;
13421}
13422
2108d9a2 13423//===============================================================================================
13424//function : VViewCube
13425//purpose :
13426//===============================================================================================
13427static int VViewCube (Draw_Interpretor& ,
13428 Standard_Integer theNbArgs,
13429 const char** theArgVec)
13430{
13431 const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13432 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13433 if (aContext.IsNull() || aView.IsNull())
13434 {
23fe70ec 13435 Message::SendFail ("Error: no active viewer");
2108d9a2 13436 return 1;
13437 }
13438 else if (theNbArgs < 2)
13439 {
23fe70ec 13440 Message::SendFail ("Syntax error: wrong number arguments");
2108d9a2 13441 return 1;
13442 }
13443
13444 Handle(AIS_ViewCube) aViewCube;
13445 ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
13446 Quantity_Color aColorRgb;
13447 TCollection_AsciiString aName;
13448 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
13449 {
13450 TCollection_AsciiString anArg (theArgVec[anArgIter]);
13451 anArg.LowerCase();
13452 if (anUpdateTool.parseRedrawMode (anArg))
13453 {
13454 //
13455 }
13456 else if (aViewCube.IsNull())
13457 {
13458 aName = theArgVec[anArgIter];
13459 if (aName.StartsWith ("-"))
13460 {
23fe70ec 13461 Message::SendFail ("Syntax error: object name should be specified");
2108d9a2 13462 return 1;
13463 }
13464 Handle(AIS_InteractiveObject) aPrs;
13465 GetMapOfAIS().Find2 (aName, aPrs);
13466 aViewCube = Handle(AIS_ViewCube)::DownCast (aPrs);
13467 if (aViewCube.IsNull())
13468 {
13469 aViewCube = new AIS_ViewCube();
13470 aViewCube->SetBoxColor (Quantity_NOC_GRAY50);
13471 aViewCube->SetViewAnimation (ViewerTest::CurrentEventManager()->ViewAnimation());
13472 aViewCube->SetFixedAnimationLoop (false);
13473 }
13474 }
13475 else if (anArg == "-reset")
13476 {
13477 aViewCube->ResetStyles();
13478 }
13479 else if (anArg == "-color"
13480 || anArg == "-boxcolor"
13481 || anArg == "-boxsidecolor"
13482 || anArg == "-sidecolor"
13483 || anArg == "-boxedgecolor"
13484 || anArg == "-edgecolor"
13485 || anArg == "-boxcornercolor"
13486 || anArg == "-cornercolor"
13487 || anArg == "-innercolor"
0aeb8984 13488 || anArg == "-textcolor"
13489 || anArg == "-xaxistextcolor"
13490 || anArg == "-yaxistextcolor"
13491 || anArg == "-zaxistextcolor")
2108d9a2 13492 {
dae2a922 13493 Standard_Integer aNbParsed = Draw::ParseColor (theNbArgs - anArgIter - 1,
13494 theArgVec + anArgIter + 1,
13495 aColorRgb);
2108d9a2 13496 if (aNbParsed == 0)
13497 {
23fe70ec 13498 Message::SendFail() << "Syntax error at '" << anArg << "'";
2108d9a2 13499 return 1;
13500 }
13501 anArgIter += aNbParsed;
13502 if (anArg == "-boxcolor")
13503 {
13504 aViewCube->SetBoxColor (aColorRgb);
13505 }
13506 else if (anArg == "-boxsidecolor"
13507 || anArg == "-sidecolor")
13508 {
13509 aViewCube->BoxSideStyle()->SetColor (aColorRgb);
13510 aViewCube->SynchronizeAspects();
13511 }
13512 else if (anArg == "-boxedgecolor"
13513 || anArg == "-edgecolor")
13514 {
13515 aViewCube->BoxEdgeStyle()->SetColor (aColorRgb);
13516 aViewCube->SynchronizeAspects();
13517 }
13518 else if (anArg == "-boxcornercolor"
13519 || anArg == "-cornercolor")
13520 {
13521 aViewCube->BoxCornerStyle()->SetColor (aColorRgb);
13522 aViewCube->SynchronizeAspects();
13523 }
13524 else if (anArg == "-innercolor")
13525 {
13526 aViewCube->SetInnerColor (aColorRgb);
13527 }
13528 else if (anArg == "-textcolor")
13529 {
13530 aViewCube->SetTextColor (aColorRgb);
13531 }
0aeb8984 13532 else if (anArg == "-xaxistextcolor"
13533 || anArg == "-yaxistextcolor"
13534 || anArg == "-zaxistextcolor")
13535 {
13536 Prs3d_DatumParts aDatum = anArg.Value (2) == 'x'
13537 ? Prs3d_DatumParts_XAxis
13538 : (anArg.Value (2) == 'y'
13539 ? Prs3d_DatumParts_YAxis
13540 : Prs3d_DatumParts_ZAxis);
13541 aViewCube->Attributes()->SetOwnDatumAspects();
13542 aViewCube->Attributes()->DatumAspect()->TextAspect (aDatum)->SetColor (aColorRgb);
13543 }
2108d9a2 13544 else
13545 {
13546 aViewCube->SetColor (aColorRgb);
13547 }
13548 }
13549 else if (anArgIter + 1 < theNbArgs
13550 && (anArg == "-transparency"
13551 || anArg == "-boxtransparency"))
13552 {
13553 const Standard_Real aValue = Draw::Atof (theArgVec[++anArgIter]);
13554 if (aValue < 0.0 || aValue > 1.0)
13555 {
23fe70ec 13556 Message::SendFail() << "Syntax error: invalid transparency value " << theArgVec[anArgIter];
2108d9a2 13557 return 1;
13558 }
13559
13560 if (anArg == "-boxtransparency")
13561 {
13562 aViewCube->SetBoxTransparency (aValue);
13563 }
13564 else
13565 {
13566 aViewCube->SetTransparency (aValue);
13567 }
13568 }
13569 else if (anArg == "-axes"
13570 || anArg == "-edges"
13571 || anArg == "-vertices"
13572 || anArg == "-vertexes"
13573 || anArg == "-fixedanimation")
13574 {
13575 bool toShow = true;
13576 if (anArgIter + 1 < theNbArgs
dae2a922 13577 && Draw::ParseOnOff (theArgVec[anArgIter + 1], toShow))
2108d9a2 13578 {
13579 ++anArgIter;
13580 }
13581 if (anArg == "-fixedanimation")
13582 {
13583 aViewCube->SetFixedAnimationLoop (toShow);
13584 }
13585 else if (anArg == "-axes")
13586 {
13587 aViewCube->SetDrawAxes (toShow);
13588 }
13589 else if (anArg == "-edges")
13590 {
13591 aViewCube->SetDrawEdges (toShow);
13592 }
13593 else
13594 {
13595 aViewCube->SetDrawVertices (toShow);
13596 }
13597 }
13598 else if (anArg == "-yup"
13599 || anArg == "-zup")
13600 {
13601 bool isOn = true;
13602 if (anArgIter + 1 < theNbArgs
dae2a922 13603 && Draw::ParseOnOff (theArgVec[anArgIter + 1], isOn))
2108d9a2 13604 {
13605 ++anArgIter;
13606 }
13607 if (anArg == "-yup")
13608 {
13609 aViewCube->SetYup (isOn);
13610 }
13611 else
13612 {
13613 aViewCube->SetYup (!isOn);
13614 }
13615 }
13616 else if (anArgIter + 1 < theNbArgs
13617 && anArg == "-font")
13618 {
13619 aViewCube->SetFont (theArgVec[++anArgIter]);
13620 }
13621 else if (anArgIter + 1 < theNbArgs
13622 && anArg == "-fontheight")
13623 {
13624 aViewCube->SetFontHeight (Draw::Atof (theArgVec[++anArgIter]));
13625 }
13626 else if (anArgIter + 1 < theNbArgs
13627 && (anArg == "-size"
13628 || anArg == "-boxsize"))
13629 {
13630 aViewCube->SetSize (Draw::Atof (theArgVec[++anArgIter]),
13631 anArg != "-boxsize");
13632 }
13633 else if (anArgIter + 1 < theNbArgs
13634 && (anArg == "-boxfacet"
13635 || anArg == "-boxfacetextension"
13636 || anArg == "-facetextension"
13637 || anArg == "-extension"))
13638 {
13639 aViewCube->SetBoxFacetExtension (Draw::Atof (theArgVec[++anArgIter]));
13640 }
13641 else if (anArgIter + 1 < theNbArgs
13642 && (anArg == "-boxedgegap"
13643 || anArg == "-edgegap"))
13644 {
13645 aViewCube->SetBoxEdgeGap (Draw::Atof (theArgVec[++anArgIter]));
13646 }
13647 else if (anArgIter + 1 < theNbArgs
13648 && (anArg == "-boxedgeminsize"
13649 || anArg == "-edgeminsize"))
13650 {
13651 aViewCube->SetBoxEdgeMinSize (Draw::Atof (theArgVec[++anArgIter]));
13652 }
13653 else if (anArgIter + 1 < theNbArgs
13654 && (anArg == "-boxcornerminsize"
13655 || anArg == "-cornerminsize"))
13656 {
13657 aViewCube->SetBoxCornerMinSize (Draw::Atof (theArgVec[++anArgIter]));
13658 }
13659 else if (anArgIter + 1 < theNbArgs
13660 && anArg == "-axespadding")
13661 {
13662 aViewCube->SetAxesPadding (Draw::Atof (theArgVec[++anArgIter]));
13663 }
13664 else if (anArgIter + 1 < theNbArgs
13665 && anArg == "-roundradius")
13666 {
13667 aViewCube->SetRoundRadius (Draw::Atof (theArgVec[++anArgIter]));
13668 }
13669 else if (anArgIter + 1 < theNbArgs
13670 && anArg == "-duration")
13671 {
13672 aViewCube->SetDuration (Draw::Atof (theArgVec[++anArgIter]));
13673 }
6466cc9e 13674 else if (anArgIter + 1 < theNbArgs
13675 && anArg == "-axesradius")
13676 {
13677 aViewCube->SetAxesRadius (Draw::Atof (theArgVec[++anArgIter]));
13678 }
13679 else if (anArgIter + 1 < theNbArgs
13680 && anArg == "-axesconeradius")
13681 {
13682 aViewCube->SetAxesConeRadius (Draw::Atof (theArgVec[++anArgIter]));
13683 }
13684 else if (anArgIter + 1 < theNbArgs
13685 && anArg == "-axessphereradius")
13686 {
13687 aViewCube->SetAxesSphereRadius (Draw::Atof (theArgVec[++anArgIter]));
13688 }
f035e071 13689 else if (anArg == "-orthopers")
13690 {
13691 const Handle(Graphic3d_TransformPers)& aTrsfPers = aViewCube->TransformPersistence();
13692 Handle(Graphic3d_TransformPers) anOrthoPers = new Graphic3d_TransformPers (Graphic3d_TMF_TriedronPers | Graphic3d_TMF_OrthoPers, aTrsfPers->Corner2d(), aTrsfPers->Offset2d());
13693 aViewCube->SetTransformPersistence (anOrthoPers);
13694 }
2108d9a2 13695 else
13696 {
23fe70ec 13697 Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
2108d9a2 13698 return 1;
13699 }
13700 }
13701 if (aViewCube.IsNull())
13702 {
23fe70ec 13703 Message::SendFail ("Syntax error: wrong number of arguments");
2108d9a2 13704 return 1;
13705 }
13706
13707 ViewerTest::Display (aName, aViewCube, false);
13708 return 0;
13709}
13710
cb6c7c45 13711//! Parse color type argument.
13712static bool parseColorType (const char* theString,
13713 Quantity_TypeOfColor& theType)
13714{
13715 TCollection_AsciiString aType (theString);
13716 aType.LowerCase();
13717 if (aType == "rgb") { theType = Quantity_TOC_RGB; }
13718 else if (aType == "srgb") { theType = Quantity_TOC_sRGB; }
13719 else if (aType == "hex") { theType = Quantity_TOC_sRGB; }
13720 else if (aType == "name") { theType = Quantity_TOC_sRGB; }
13721 else if (aType == "hls") { theType = Quantity_TOC_HLS; }
13722 else if (aType == "lab") { theType = Quantity_TOC_CIELab; }
13723 else if (aType == "lch") { theType = Quantity_TOC_CIELch; }
13724 else { return false; }
13725 return true;
13726}
13727
14b741b0 13728//===============================================================================================
13729//function : VColorConvert
13730//purpose :
13731//===============================================================================================
cb6c7c45 13732static int VColorConvert (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgVec)
14b741b0 13733{
cb6c7c45 13734 Quantity_TypeOfColor aTypeFrom = Quantity_TOC_RGB, aTypeTo = Quantity_TOC_RGB;
13735 double anInput[4] = {};
13736 Quantity_ColorRGBA aColor (0.0f, 0.0f, 0.0f, 1.0f);
13737 bool toPrintHex = false, toPrintName = false, hasAlpha = false;
13738 for (int anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
14b741b0 13739 {
cb6c7c45 13740 TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
13741 anArgCase.LowerCase();
13742 if ((anArgCase == "-from"
13743 || anArgCase == "from")
13744 && anArgIter + 1 < theNbArgs
13745 && parseColorType (theArgVec[anArgIter + 1], aTypeFrom))
13746 {
13747 ++anArgIter;
13748 }
13749 else if ((anArgCase == "-to"
13750 || anArgCase == "to")
13751 && anArgIter + 1 < theNbArgs
13752 && parseColorType (theArgVec[anArgIter + 1], aTypeTo))
13753 {
13754 TCollection_AsciiString aToStr (theArgVec[++anArgIter]);
13755 aToStr.LowerCase();
13756 toPrintHex = (aToStr == "hex");
13757 toPrintName = (aToStr == "name");
13758 }
13759 else if (Quantity_ColorRGBA::ColorFromHex (theArgVec[anArgIter], aColor))
13760 {
13761 hasAlpha = anArgCase.Length() >= 8;
13762 }
13763 else if (Quantity_Color::ColorFromName (theArgVec[anArgIter], aColor.ChangeRGB()))
13764 {
13765 //
13766 }
13767 else if (anArgIter + 2 < theNbArgs
13768 && Draw::ParseReal (theArgVec[anArgIter + 0], anInput[0])
13769 && Draw::ParseReal (theArgVec[anArgIter + 1], anInput[1])
13770 && Draw::ParseReal (theArgVec[anArgIter + 2], anInput[2]))
13771 {
13772 if (anArgIter + 3 < theNbArgs
13773 && Draw::ParseReal (theArgVec[anArgIter + 3], anInput[3]))
13774 {
13775 anArgIter += 1;
13776 aColor.SetAlpha ((float )anInput[3]);
13777 hasAlpha = true;
13778 }
13779 anArgIter += 2;
13780 aColor.ChangeRGB().SetValues (anInput[0], anInput[1], anInput[2], aTypeFrom);
13781 }
13782 else
13783 {
13784 theDI << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'";
13785 return 1;
13786 }
14b741b0 13787 }
13788
cb6c7c45 13789 if (toPrintHex)
14b741b0 13790 {
cb6c7c45 13791 if (hasAlpha || aColor.Alpha() < 1.0f)
13792 {
13793 theDI << Quantity_ColorRGBA::ColorToHex (aColor);
13794 }
13795 else
13796 {
13797 theDI << Quantity_Color::ColorToHex (aColor.GetRGB());
13798 }
14b741b0 13799 }
cb6c7c45 13800 else if (toPrintName)
14b741b0 13801 {
cb6c7c45 13802 theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
14b741b0 13803 }
13804 else
13805 {
cb6c7c45 13806 double anOutput[3] = {};
13807 aColor.GetRGB().Values (anOutput[0], anOutput[1], anOutput[2], aTypeTo);
14b741b0 13808
cb6c7c45 13809 // print values with 6 decimal digits
13810 char aBuffer[1024];
13811 if (hasAlpha || aColor.Alpha() < 1.0f)
13812 {
13813 Sprintf (aBuffer, "%.6f %.6f %.6f %.6f", anOutput[0], anOutput[1], anOutput[2], aColor.Alpha());
13814 }
13815 else
13816 {
13817 Sprintf (aBuffer, "%.6f %.6f %.6f", anOutput[0], anOutput[1], anOutput[2]);
13818 }
13819 theDI << aBuffer;
13820 }
14b741b0 13821 return 0;
13822}
13823
13824//===============================================================================================
13825//function : VColorDiff
13826//purpose :
13827//===============================================================================================
13828static int VColorDiff (Draw_Interpretor& theDI, Standard_Integer theNbArgs, const char** theArgVec)
13829{
13830 if (theNbArgs != 7)
13831 {
13832 std::cerr << "Error: command syntax is incorrect, see help" << std::endl;
13833 return 1;
13834 }
13835
13836 double aR1 = Draw::Atof (theArgVec[1]);
13837 double aG1 = Draw::Atof (theArgVec[2]);
13838 double aB1 = Draw::Atof (theArgVec[3]);
13839 double aR2 = Draw::Atof (theArgVec[4]);
13840 double aG2 = Draw::Atof (theArgVec[5]);
13841 double aB2 = Draw::Atof (theArgVec[6]);
13842
13843 Quantity_Color aColor1 (aR1, aG1, aB1, Quantity_TOC_RGB);
13844 Quantity_Color aColor2 (aR2, aG2, aB2, Quantity_TOC_RGB);
13845
13846 theDI << aColor1.DeltaE2000 (aColor2);
13847
13848 return 0;
13849}
13850
6a2fb7a1 13851//===============================================================================================
4551e1be 13852//function : VSelBvhBuild
6a2fb7a1 13853//purpose :
13854//===============================================================================================
13855static int VSelBvhBuild (Draw_Interpretor& /*theDI*/, Standard_Integer theNbArgs, const char** theArgVec)
13856{
13857 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
13858 if (aCtx.IsNull())
13859 {
13860 Message::SendFail ("Error: no active viewer");
13861 return 1;
13862 }
13863
13864 if (theNbArgs < 2)
13865 {
13866 Message::SendFail ("Error: command syntax is incorrect, see help");
13867 return 1;
13868 }
13869
13870 Standard_Integer toEnable = -1;
13871 Standard_Integer aThreadsNb = -1;
13872 Standard_Boolean toWait = Standard_False;
13873
13874 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
13875 {
13876 TCollection_AsciiString anArg (theArgVec[anArgIter]);
13877 anArg.LowerCase();
13878
13879 if (anArg == "-nbthreads"
13880 && anArgIter + 1 < theNbArgs)
13881 {
13882 aThreadsNb = Draw::Atoi (theArgVec[++anArgIter]);
13883 if (aThreadsNb < 1)
13884 {
13885 aThreadsNb = Max (1, OSD_Parallel::NbLogicalProcessors() - 1);
13886 }
13887 }
13888 else if (anArg == "-wait")
13889 {
13890 toWait = Standard_True;
13891 }
13892 else if (toEnable == -1)
13893 {
13894 Standard_Boolean toEnableValue = Standard_True;
13895 if (Draw::ParseOnOff (anArg.ToCString(), toEnableValue))
13896 {
13897 toEnable = toEnableValue ? 1 : 0;
13898 }
13899 else
13900 {
13901 Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
13902 return 1;
13903 }
13904 }
13905 else
13906 {
13907 Message::SendFail() << "Syntax error: unknown argument '" << anArg << "'";
13908 return 1;
13909 }
13910 }
13911
13912 if (aThreadsNb == -1)
13913 {
13914 aThreadsNb = 1;
13915 }
13916 if (toEnable != -1)
13917 {
13918 aCtx->MainSelector()->SetToPrebuildBVH (toEnable == 1, aThreadsNb);
13919 }
13920 if (toWait)
13921 {
13922 aCtx->MainSelector()->WaitForBVHBuild();
13923 }
13924
13925 return 0;
13926}
13927
34213231 13928//=======================================================================
13929//function : VChangeMouseGesture
13930//purpose :
13931//=======================================================================
13932static int VChangeMouseGesture (Draw_Interpretor&,
13933 Standard_Integer theArgsNb,
13934 const char** theArgVec)
13935{
13936 Handle(V3d_View) aView = ViewerTest::CurrentView();
13937 if (aView.IsNull())
13938 {
13939 Message::SendFail ("Error: no active viewer");
13940 return 1;
13941 }
13942
13943 NCollection_DoubleMap<TCollection_AsciiString, AIS_MouseGesture> aGestureMap;
13944 {
13945 aGestureMap.Bind ("none", AIS_MouseGesture_NONE);
13946 aGestureMap.Bind ("selectrectangle", AIS_MouseGesture_SelectRectangle);
13947 aGestureMap.Bind ("selectlasso", AIS_MouseGesture_SelectLasso);
13948 aGestureMap.Bind ("zoom", AIS_MouseGesture_Zoom);
13949 aGestureMap.Bind ("zoomwindow", AIS_MouseGesture_ZoomWindow);
13950 aGestureMap.Bind ("pan", AIS_MouseGesture_Pan);
13951 aGestureMap.Bind ("rotateorbit", AIS_MouseGesture_RotateOrbit);
13952 aGestureMap.Bind ("rotateview", AIS_MouseGesture_RotateView);
13953 aGestureMap.Bind ("drag", AIS_MouseGesture_Drag);
13954 }
13955 NCollection_DoubleMap<TCollection_AsciiString, Standard_UInteger> aMouseButtonMap;
13956 {
13957 aMouseButtonMap.Bind ("none", (Standard_UInteger )Aspect_VKeyMouse_NONE);
13958 aMouseButtonMap.Bind ("left", (Standard_UInteger )Aspect_VKeyMouse_LeftButton);
13959 aMouseButtonMap.Bind ("middle", (Standard_UInteger )Aspect_VKeyMouse_MiddleButton);
13960 aMouseButtonMap.Bind ("right", (Standard_UInteger )Aspect_VKeyMouse_RightButton);
13961 }
13962
13963 Standard_UInteger aButton = (Standard_UInteger )Aspect_VKeyMouse_LeftButton;
13964 AIS_MouseGesture aGesture = AIS_MouseGesture_RotateOrbit;
13965 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
13966 {
13967 Standard_CString anArg = theArgVec[anArgIter];
13968 TCollection_AsciiString anArgCase (anArg);
13969 anArgCase.LowerCase();
13970 if (anArgCase == "-button")
13971 {
13972 TCollection_AsciiString aButtonStr = theArgVec[++anArgIter];
13973 aButtonStr.LowerCase();
13974 aButton = aMouseButtonMap.Find1 (aButtonStr);
13975 }
13976 else if (anArgCase == "-gesture")
13977 {
13978 TCollection_AsciiString aGestureStr = theArgVec[++anArgIter];
13979 aGestureStr.LowerCase();
13980 aGesture = aGestureMap.Find1 (aGestureStr);
13981 }
13982 else
13983 {
13984 Message::SendFail() << "Error: unknown argument '" << anArg << "'";
13985 return 1;
13986 }
13987 }
13988
13989 Handle(ViewerTest_EventManager) aViewMgr = ViewerTest::CurrentEventManager();
13990 aViewMgr->ChangeMouseGestureMap().Bind (aButton, aGesture);
13991
13992 return 0;
13993}
13994
a6049685 13995//=======================================================================
13996//function : ViewerTest_ExitProc
13997//purpose :
13998//=======================================================================
13999static void ViewerTest_ExitProc (ClientData )
14000{
14001 NCollection_List<TCollection_AsciiString> aViewList;
14002 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
14003 anIter.More(); anIter.Next())
14004 {
14005 aViewList.Append (anIter.Key1());
14006 }
14007
14008 for (NCollection_List<TCollection_AsciiString>::Iterator anIter (aViewList);
14009 anIter.More(); anIter.Next())
14010 {
14011 ViewerTest::RemoveView (anIter.Value(), true);
14012 }
14013}
14014
7fd59977 14015//=======================================================================
14016//function : ViewerCommands
14017//purpose :
14018//=======================================================================
14019
14020void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
14021{
a6049685 14022 static bool TheIsInitialized = false;
14023 if (TheIsInitialized)
14024 {
14025 return;
14026 }
14027
14028 TheIsInitialized = true;
14029 // define destruction callback to destroy views in a well-defined order
14030 Tcl_CreateExitHandler (ViewerTest_ExitProc, 0);
7fd59977 14031
44f6e8d5 14032 const char* aGroup = "AIS Viewer";
14033 const char* aFileName = __FILE__;
14034 auto addCmd = [&](const char* theName, Draw_Interpretor::CommandFunction theFunc, const char* theHelp)
14035 {
14036 theCommands.Add (theName, theHelp, aFileName, theFunc, aGroup);
14037 };
14038
14039 addCmd ("vdriver", VDriver, /* [vdriver] */ R"(
14040vdriver [-list] [-default DriverName] [-load DriverName]
14041Manages active graphic driver factory.
14042Prints current active driver when called without arguments.
14043Makes specified driver active when ActiveName argument is specified.
14044 -list print registered factories
14045 -default define which factory should be used by default (to be used by next vinit call)
14046 -load try loading factory plugin and set it as default one
14047)" /* [vdriver] */);
14048
14049 addCmd ("vinit", VInit, /* [vinit] */ R"(
14050vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]
879768fb 14051 [-exitOnClose] [-closeOnEscape] [-cloneActive] [-virtual {0|1}]=0 [-2d_mode {0|1}]=0
14052 [-display displayName] [-dpiAware {0|1}]=0
14053 [-subview] [-parent OtherView] [-composer {0|1}]=0 [-margins DX DY]=0
44f6e8d5 14054Creates new View window with specified name viewName.
14055By default the new view is created in the viewer and in graphic driver shared with active view.
14056 -name {driverName/viewerName/viewName | viewerName/viewName | viewName}
14057 if driverName isn't specified the driver will be shared with active view;
14058 if viewerName isn't specified the viewer will be shared with active view.
14059 -display HostName.DisplayNumber[:ScreenNumber]
14060
14061Display name will be used within creation of graphic driver, when specified.
14062 -left, -top pixel position of left top corner of the window.
14063 -width, -height width and height of window respectively.
14064 -cloneActive flag to copy camera and dimensions of active view.
14065 -exitOnClose when specified, closing the view will exit application.
14066 -closeOnEscape when specified, view will be closed on pressing Escape.
14067 -virtual create an offscreen window within interactive session
879768fb 14068 -subview create a subview within another view
44f6e8d5 14069 -2d_mode when on, view will not react on rotate scene events
2275caec 14070 -dpiAware override dpi aware hint (Windows platform)
44f6e8d5 14071Additional commands for operations with views: vclose, vactivate, vviewlist.
14072)" /* [vinit] */);
14073
14074 addCmd ("vclose", VClose, /* [vclose] */ R"(
14075vclose [view_id [keep_context=0|1]]
14076or vclose ALL - to remove all created views
14077 - removes view(viewer window) defined by its view_id.
14078 - keep_context: by default 0; if 1 and the last view is deleted the current context is not removed.
14079)" /* [vclose] */);
14080
14081 addCmd ("vactivate", VActivate, /* [vactivate] */ R"(
14082vactivate view_id [-noUpdate]
14083Activates view(viewer window) defined by its view_id.
14084)" /* [vactivate] */);
14085
14086 addCmd ("vviewlist", VViewList, /* [vviewlist] */ R"(
14087vviewlist [format={tree, long}]=tree
14088Prints current list of views per viewer and graphic_driver ID shared between viewers
14089 - format: format of result output, if tree the output is a tree view;
14090 otherwise it's a list of full view names.
14091)" /* [vviewlist] */);
14092
14093 addCmd ("vhelp", VHelp, /* [vhelp] */ R"(
14094vhelp : display help on the viewer commands and list of hotkeys.
14095)" /* [vhelp] */);
14096
14097 addCmd ("vviewproj", VViewProj, /* [vviewproj] */ R"(
14098vviewproj [top|bottom|left|right|front|back|axoLeft|axoRight]
14099 [+-X+-Y+-Z] [-Zup|-Yup] [-frame +-X+-Y]
14100Setup view direction
14101 -Yup use Y-up convention instead of Zup (which is default).
14102 +-X+-Y+-Z define direction as combination of DX, DY and DZ;
14103 for example '+Z' will show front of the model,
14104 '-X-Y+Z' will define left axonometric view.
14105 -frame define camera Up and Right directions (regardless Up convention);
14106 for example '+X+Z' will show front of the model with Z-up.
14107)" /* [vviewproj] */);
14108
14109 addCmd ("vtop", VViewProj, /* [vtop] */ R"(
14110vtop or <T> : Display top view (+X+Y) in the 3D viewer window.
14111)" /* [vtop] */);
14112
14113 addCmd ("vbottom", VViewProj, /* [vbottom] */ R"(
14114vbottom : Display bottom view (+X-Y) in the 3D viewer window.
14115)" /* [vbottom] */);
14116
14117 addCmd ("vleft", VViewProj, /* [vleft] */ R"(
14118vleft : Display left view (-Y+Z) in the 3D viewer window.
14119)" /* [vleft] */);
14120
14121 addCmd ("vright", VViewProj, /* [vright] */ R"(
14122vright : Display right view (+Y+Z) in the 3D viewer window.
14123)" /* [vright] */);
14124
14125 addCmd ("vaxo", VViewProj, /* [vaxo] */ R"(
14126vaxo or <A> : Display axonometric view (+X-Y+Z) in the 3D viewer window.
14127)" /* [vaxo] */);
14128
14129 addCmd ("vfront", VViewProj, /* [vfront] */ R"(
14130vfront : Display front view (+X+Z) in the 3D viewer window.
14131)" /* [vfront] */);
14132
14133 addCmd ("vback", VViewProj, /* [vfront] */ R"(
14134vback : Display back view (-X+Z) in the 3D viewer window.
14135)" /* [vback] */);
14136
14137 addCmd ("vpick", VPick, /* [vpick] */ R"(
14138vpick X Y Z [shape subshape]
14139)" /* [vpick] */);
14140
14141 addCmd ("vfit", VFit, /* [vfit] */ R"(
14142vfit or <F> [-selected] [-noupdate]
14143Fit all / selected. Objects in the view are visualized to occupy the maximum surface.
14144)" /* [vfit] */);
14145
14146 addCmd ("vfitarea", VFitArea, /* [vfitarea] */ R"(
14147vfitarea [x1 y1 x2 y2] [x1 y1 z1 x2 y2 z2]
14148Fit view to show area located between two points
14149given in world 2D or 3D coordinates.
14150)" /* [vfitarea] */);
14151
14152 addCmd ("vzfit", VZFit, /* [vzfit] */ R"(
14153vzfit [scale]
14154Automatic depth panning.
14155Matches Z near, Z far view volume planes to the displayed objects.
14156 - "scale" specifies factor to scale computed z range.
14157)" /* [vzfit] */);
14158
14159 addCmd ("vrepaint", VRepaint, /* [vrepaint] */ R"(
14160vrepaint [-immediate] [-continuous FPS]
14161Force redraw of active View.
14162 -immediate flag performs redraw of immediate layers only;
14163 -continuous activates/deactivates continuous redraw of active View,
14164 0 means no continuous rendering,
14165 -1 means non-stop redraws,
14166 >0 specifies target framerate.
14167)" /* [vrepaint] */);
14168
14169 addCmd ("vclear", VClear, /* [vclear] */ R"(
14170vclear : Remove all the object from the viewer
14171)" /* [vclear] */);
14172
14173 addCmd ("vbackground", VBackground, /* [vbackground] */ R"(
14174vbackground [-color Color [-default]]
14175 [-gradient Color1 Color2 [-default]
14176 [-gradientMode {NONE|HORIZONTAL|VERTICAL|DIAG1|DIAG2|CORNER1|CORNER2|CORNER3|ELLIPTICAL}]=VERT]
14177 [-imageFile ImageFile [-imageMode {CENTERED|TILED|STRETCH|NONE}]=CENTERED [-srgb {0|1}]=1]
14178 [-cubemap CubemapFile1 [CubeMapFiles2-5] [-order TilesIndexes1-6] [-invertedz]=0]
16a263dc 14179 [-skydome [-sunDir X Y Z=0 1 0] [-cloud Cloudy=0.2] [-time Time=0.0]
14180 [-fog Haze=0.0] [-size SizePx=512]]
44f6e8d5 14181 [-pbrEnv {ibl|noibl|keep}]
14182Changes background or some background settings.
14183 -color sets background color
14184 -gradient sets background gradient starting and ending colors
14185 -gradientMode sets gradient fill method
14186 -default sets background default gradient or color
14187 -imageFile sets filename of image used as background
14188 -imageMode sets image fill type
14189 -cubemap sets environment cubemap as background
14190 -invertedz sets inversion of Z axis for background cubemap rendering; FALSE when unspecified
14191 -pbrEnv sets on/off Image Based Lighting (IBL) from background cubemap for PBR
14192 -srgb prefer sRGB texture format when applicable; TRUE when unspecified"
14193 -order defines order of tiles in one image cubemap
14194 TileIndexi defubes an index in range [0, 5] for i tile of one image packed cubemap
14195 (has no effect in case of multi-image cubemaps).
16a263dc 14196Skydome background parameters (generated cubemap):
14197 -skydome sets procedurally generated skydome as background
14198 -sunDir sets direction to the sun, direction with negative y component represents moon direction (-x, -y, -z)
14199 -cloud sets cloud intensity (0.0 - clear sky, 1.0 - very high cloudy)
14200 -time might be tweaked to slightly change appearance of clouds
14201 -fog sets mist intensity (0.0 - no mist at all, 1.0 - high mist)
14202 -size sets size in pixels of cubemap side
44f6e8d5 14203)" /* [vbackground] */);
14204
14205 addCmd ("vsetbg", VBackground, /* [vsetbg] */ R"(
14206Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.
14207)" /* [vsetbg] */);
14208
14209 addCmd ("vsetbgmode", VBackground, /* [vsetbgmode] */ R"(
14210Alias for 'vbackground -imageMode FillType'.
14211)" /* [vsetbgmode] */);
14212
14213 addCmd ("vsetgradientbg", VBackground, /* [vsetgradientbg] */ R"(
14214Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.
14215)" /* [vsetgradientbg] */);
14216
14217 addCmd ("vsetgrbgmode", VBackground, /* [vsetgrbgmode] */ R"(
14218Alias for 'vbackground -gradientMode FillMethod'.
14219)" /* [vsetgrbgmode] */);
14220
14221 addCmd ("vsetcolorbg", VBackground, /* [vsetcolorbg] */ R"(
14222Alias for 'vbackground -color Color'.
14223)" /* [vsetcolorbg] */);
14224
14225 addCmd ("vsetdefaultbg", VBackground, /* [vsetdefaultbg] */ R"(
14226Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'
14227 and for 'vbackground -default -color Color'.
14228)" /* [vsetdefaultbg] */);
14229
14230 addCmd ("vscale", VScale, /* [vscale] */ R"(
14231vscale X Y Z
14232)" /* [vscale] */);
14233
14234 addCmd ("vzbufftrihedron", VZBuffTrihedron, /* [vzbufftrihedron] */ R"(
14235vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]
14236 [-position center|left_lower|left_upper|right_lower|right_upper]
14237 [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]
14238 [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]
14239 [-nbfacets value=12] [-colorLabels color=WHITE]
14240 [-colorLabelX color] [-colorLabelY color] [-colorLabelZ color]
14241Displays a trihedron.
14242)" /* [vzbufftrihedron] */);
14243
14244 addCmd ("vrotate", VRotate, /* [vrotate] */ R"(
14245vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]
14246 -mouseStart start rotation according to the mouse position;
14247 -mouseMove continue rotation with angle computed
14248 from last and new mouse position.
14249)" /* [vrotate] */);
14250
14251 addCmd ("vzoom", VZoom, /* [vzoom] */ R"(
14252vzoom coef
14253)" /* [vzoom] */);
14254
14255 addCmd ("vpan", VPan, /* [vpan] */ R"(
14256vpan dx dy
14257)" /* [vpan] */);
14258
14259 addCmd ("vcolorscale", VColorScale, /* [vcolorscale] */ R"(
14260vcolorscale name [-noupdate|-update] [-demo]
14261 [-range RangeMin=0 RangeMax=1 NbIntervals=10]
14262 [-font HeightFont=20]
14263 [-logarithmic {on|off}=off] [-reversed {on|off}=off]
14264 [-smoothTransition {on|off}=off]
14265 [-hueRange MinAngle=230 MaxAngle=0]
14266 [-colorRange MinColor=BLUE1 MaxColor=RED]
14267 [-textPos {left|right|center|none}=right]
14268 [-labelAtBorder {on|off}=on]
14269 [-colors Color1 Color2 ...] [-color Index Color]
14270 [-labels Label1 Label2 ...] [-label Index Label]
14271 [-freeLabels NbOfLabels Label1 Label2 ...]
14272 [-xy Left=0 Bottom=0]
14273 [-uniform lightness hue_from hue_to]
14274 -demo display a color scale with demonstration values
14275 -colors set colors for all intervals
14276 -color set color for specific interval
14277 -uniform generate colors with the same lightness
14278 -textpos horizontal label position relative to color scale bar
14279 -labelAtBorder vertical label position relative to color interval;
14280 at border means the value inbetween neighbor intervals,
14281 at center means the center value within current interval
14282 -labels set labels for all intervals
14283 -freeLabels same as -labels but does not require
14284 matching the number of intervals
14285 -label set label for specific interval
14286 -title set title
14287 -reversed setup smooth color transition between intervals
14288 -smoothTransition swap colorscale direction
14289 -hueRange set hue angles corresponding to minimum and maximum values
14290)" /* [vcolorscale] */);
14291
14292 addCmd ("vgraduatedtrihedron", VGraduatedTrihedron, /* [vgraduatedtrihedron] */ R"(
14293vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]
14294 [-namefont Name] [-valuesfont Name]
14295 [-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]
14296 [-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]
14297 [-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]
14298 [-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]
14299 [-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]
14300 [-xcolor Color] [-ycolor Color] [-zcolor Color]
14301 [-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]
14302 [-xticks Number] [-yticks Number] [-zticks Number]
14303 [-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]
14304 [-drawgrid on/off] [-drawaxes on/off]
14305Display or erase graduated trihedron
14306 - xname, yname, zname - names of axes, default: X, Y, Z
14307 - namefont - font of axes names. Default: Arial
14308 - xnameoffset, ynameoffset, znameoffset - offset of name
14309 from values or tickmarks or axis. Default: 30
14310 - xnamecolor, ynamecolor, znamecolor - colors of axes names
14311 - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values
14312 from tickmarks or axis. Default: 10
14313 - valuesfont - font of axes values. Default: Arial
14314 - xcolor, ycolor, zcolor - color of axis and values
14315 - xticks, yticks, xzicks - number of tickmark on axes. Default: 5
14316 - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10
14317)" /* [vgraduatedtrihedron] */);
14318
14319 addCmd ("vtile", VTile, /* [vtile] */ R"(
14320vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]
14321Setup view to draw a tile (a part of virtual bigger viewport).
14322 -totalSize the size of virtual bigger viewport
14323 -tileSize tile size (the view size will be used if omitted)
14324 -lowerLeft tile offset as lower left corner
14325 -upperLeft tile offset as upper left corner
14326)" /* [vtile] */);
14327
14328 addCmd ("vzlayer", VZLayer, /* [vzlayer] */ R"(
14329vzlayer [layerId]
14330 [-add|-delete|-get|-settings] [-insertBefore AnotherLayer] [-insertAfter AnotherLayer]
14331 [-origin X Y Z] [-cullDist Distance] [-cullSize Size]
14332 [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]
14333 [-enable|-disable {positiveOffset|negativeOffset|textureenv|rayTracing}]
14334ZLayer list management
14335 -add add new z layer to viewer and print its id
14336 -insertBefore add new z layer and insert it before existing one
14337 -insertAfter add new z layer and insert it after existing one
14338 -delete delete z layer
14339 -get print sequence of z layers
14340 -settings print status of z layer settings
14341 -disable disables given setting
14342 -enable enables given setting
14343)" /* [vzlayer] */);
14344
14345 addCmd ("vlayerline", VLayerLine, /* [vlayerline] */ R"(
14346vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]
14347)" /* [vlayerline] */);
14348
14349 addCmd ("vgrid", VGrid, /* [vgrid] */ R"(
14350vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]
14351 [-step X Y] [-size DX DY]
14352 [-step StepRadius NbDivisions] [-radius Radius]
14353)" /* [vgrid] */);
14354
14355 addCmd ("vpriviledgedplane", VPriviledgedPlane, /* [vpriviledgedplane] */ R"(
14356vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]
14357Sets or prints viewer's priviledged plane geometry:
14358 Ox, Oy, Oz - plane origin;
14359 Nx, Ny, Nz - plane normal direction;
14360 Xx, Xy, Xz - plane x-reference axis direction.
14361)" /* [vpriviledgedplane] */);
14362
14363 addCmd ("vconvert", VConvert, /* [vconvert] */ R"(
14364vconvert v [Mode={window|view}]
14365vconvert x y [Mode={window|view|grid|ray}]
14366vconvert x y z [Mode={window|grid}]
14367Convert the given coordinates to window/view/model space:
14368 - window - convert to window coordinates, pixels;
14369 - view - convert to view projection plane;
14370 - grid - convert to model coordinates, given on grid;
14371 - ray - convert projection ray to model coordinates.
14372)" /* [vconvert] */);
14373
14374 addCmd ("vfps", VFps, /* [vfps] */ R"(
14375vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view.
14376)" /* [vfps] */);
14377
14378 addCmd ("vstereo", VStereo, /* [vstereo] */ R"(
14379vstereo [0|1] [-mode Mode] [-reverse {0|1}]
14380 [-mirrorComposer] [-hmdfov2d AngleDegrees] [-unitFactor MetersFactor]
2275caec 14381 [-anaglyph Filter] [-smoothInterlacing]
44f6e8d5 14382Control stereo output mode. Available modes for -mode:
14383 quadBuffer OpenGL QuadBuffer stereo;
14384 requires driver support;
14385 should be called BEFORE vinit!
14386 anaglyph Anaglyph glasses, filters for -anaglyph:
14387 redCyan, redCyanSimple, yellowBlue, yellowBlueSimple, greenMagentaSimple.
14388 rowInterlaced row-interlaced display
2275caec 14389 smooth smooth interlaced output for better text readability
44f6e8d5 14390 columnInterlaced column-interlaced display
14391 chessBoard chess-board output
14392 sideBySide horizontal pair
14393 overUnder vertical pair
14394 openVR OpenVR (HMD), extra options:
14395 -mirrorComposer flag to mirror VR frame in the window (debug);
14396 -unitFactor specifies meters scale factor for mapping VR input.
14397)" /* [vstereo] */);
14398
14399 addCmd ("vmemgpu", VMemGpu, /* [vmemgpu] */ R"(
14400vmemgpu [f]: print system-dependent GPU memory information if available;
14401with f option returns free memory in bytes.
14402)" /* [vmemgpu] */);
14403
14404 addCmd ("vreadpixel", VReadPixel, /* [vreadpixel] */ R"(
14405vreadpixel xPixel yPixel [{rgb|rgba|sRGB|sRGBa|depth|hls|rgbf|rgbaf}=rgba] [-name|-hex]
14406Read pixel value for active view.
14407)" /* [vreadpixel] */);
14408
14409 addCmd ("diffimage", VDiffImage, /* [diffimage] */ R"(
14410diffimage imageFile1 imageFile2 [diffImageFile]
14411 [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]
14412 [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]
14413Compare two images by content and generate difference image.
14414When -exitOnClose is specified, closing the view will exit application.
14415When -closeOnEscape is specified, view will be closed on pressing Escape.
14416)" /* [diffimage] */);
14417
14418 addCmd ("vselect", VSelect, /* [vselect] */ R"(
14419vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1]
14420 [-replace|-replaceextra|-xor|-add|-remove]
14421Emulate different types of selection:
14422 1) Single click selection.
14423 2) Selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2).
14424 3) Selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn).
14425 4) -allowoverlap manages overlap and inclusion detection in rectangular and polygonal selection.
14426 If the flag is set to 1, both sensitives that were included completely
14427 and overlapped partially by defined rectangle or polygon will be detected,
14428 otherwise algorithm will chose only fully included sensitives.
14429 Default behavior is to detect only full inclusion
14430 (partial inclusion - overlap - is not allowed by default).
14431 5) Selection scheme replace, replaceextra, xor, add or remove (replace by default).
14432)" /* [vselect] */);
14433
14434 addCmd ("vmoveto", VMoveTo, /* [vmoveto] */ R"(
14435vmoveto [x y] [-reset]
14436Emulate cursor movement to pixel position (x,y).
14437 -reset resets current highlighting.
14438)" /* [vmoveto] */);
14439
14440 addCmd ("vselaxis", VSelectByAxis, /* [vselaxis] */ R"(
14441vselaxis x y z dx dy dz [-onlyTop 0|1] [-display Name] [-showNormal 0|1]"
14442Provides intersection by given axis and print result intersection points.
14443 -onlyTop switches On/Off mode to find only top point or all;
14444 -display Name displays intersecting axis and result intersection points for debug goals;
14445 -showNormal adds displaying of normal in intersection point or not.
14446)" /* [vselaxis] */);
14447
14448 addCmd ("vviewparams", VViewParams, /* [vviewparams] */ R"(
14449vviewparams [-args] [-scale [s]]
14450 [-eye [x y z]] [-at [x y z]] [-up [x y z]]
14451 [-proj [x y z]] [-center x y] [-size sx]
14452Manage current view parameters (camera orientation) or prints all
14453current values when called without argument.
14454 -scale [s] prints or sets viewport relative scale
14455 -eye [x y z] prints or sets eye location
14456 -at [x y z] prints or sets center of look
14457 -up [x y z] prints or sets direction of up vector
14458 -proj [x y z] prints or sets direction of look
14459 -center x y sets location of center of the screen in pixels
14460 -size [sx] prints viewport projection width and height sizes
14461 or changes the size of its maximum dimension
14462 -args prints vviewparams arguments for restoring current view
14463)" /* [vviewparams] */);
14464
14465 addCmd ("v2dmode", V2DMode, /* [v2dmode] */ R"(
14466v2dmode [-name viewName] [-mode {-on|-off}=-on]
14467 name - name of existing view, if not defined, the active view is changed;
14468 mode - switches On/Off rotation mode.
14469Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:
14470 - rotation of the view by 3rd mouse button with Ctrl active
14471 - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right
14472View camera position might be changed only by commands.
14473)" /* [v2dmode] */);
14474
14475 addCmd ("vanimation", VAnimation, /* [vanimation] */ R"(
14476Alias for vanim
14477)" /* [vanimation] */);
14478
14479 addCmd ("vanim", VAnimation, /* [vanim] */ R"(
14480List existing animations:
14481 vanim
14482
14483Animation playback:
b9f787f1 14484 vanim name {-play|-resume|-pause|-stop} [playFrom [playDuration]] [-speed Coeff]
14485 [-freeLook] [-noPauseOnClick] [-lockLoop] [-elapsedTime]
44f6e8d5 14486
b9f787f1 14487 -speed playback speed (1.0 is normal speed)
14488 -freeLook skip camera animations
44f6e8d5 14489 -noPauseOnClick do not pause animation on mouse click
b9f787f1 14490 -lockLoop disable any interactions
14491 -elapsedTime prints elapsed time in seconds"
44f6e8d5 14492
14493Animation definition:
14494 vanim Name/sub/name [-clear] [-delete]
340b2327 14495 [-start TimeSec] [-duration TimeSec] [-end TimeSec]
44f6e8d5 14496
14497Animation name defined in path-style (anim/name or anim.name)
14498specifies nested animations.
14499There is no syntax to explicitly add new animation,
14500and all non-existing animations within the name will be
14501implicitly created on first use (including parents).
14502
14503Each animation might define the SINGLE action (see below),
14504like camera transition, object transformation or custom callback.
14505Child animations can be used for defining concurrent actions.
14506
14507Camera animation:
14508 vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]
14509 [-at1 X Y Z] [-at2 X Y Z]
14510 [-up1 X Y Z] [-up2 X Y Z]
14511 [-scale1 Scale] [-scale2 Scale]
14512 -eyeX camera Eye positions pair (start and end)
14513 -atX camera Center positions pair
14514 -upX camera Up directions pair
14515 -scaleX camera Scale factors pair
14516
14517Object animation:
14518 vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]
14519 [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]
14520 [-scale1 Scale] [-scale2 Scale]
14521 -locX object Location points pair (translation)
14522 -rotX object Orientations pair (quaternions)
14523 -scaleX object Scale factors pair (quaternions)
14524
53eae1a9 14525 vanim name -object [-axis OX OY OZ DX DY DZ] [-ang1 A] [-ang2 A]
14526 -axis rotation axis
14527 -ang1 start rotation angle in degrees
14528 -ang2 end rotation angle in degrees
14529
44f6e8d5 14530Custom callback:
14531 vanim name -invoke "Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN"
14532
14533 %Pts overall animation presentation timestamp
14534 %LocalPts local animation timestamp
14535 %Normalized local animation normalized value in range 0..1
14536
14537Video recording:
14538 vanim name -record FileName [Width Height] [-fps FrameRate=24]
14539 [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]
14540 [-crf Value] [-preset Preset]
14541 -fps video framerate
14542 -format file format, container (matroska, etc.)
14543 -vcodec video codec identifier (ffv1, mjpeg, etc.)
14544 -pix_fmt image pixel format (yuv420p, rgb24, etc.)
14545 -crf constant rate factor (specific to codec)
14546 -preset codec parameters preset (specific to codec)
14547)" /* [vanim] */);
14548
14549 addCmd ("vchangeselected", VChangeSelected, /* [vchangeselected] */ R"(
14550vchangeselected shape : Add shape to selection or remove one from it.
14551)" /* [vchangeselected] */);
14552
14553 addCmd ("vnbselected", VNbSelected, /* [vnbselected] */ R"(
14554vnbselected : Returns number of selected objects in the interactive context.
14555)" /* [vnbselected] */);
14556
14557 addCmd ("vcamera", VCamera, /* [vcamera] */ R"(
14558vcamera [PrsName] [-ortho] [-projtype]
14559 [-persp]
14560 [-fovy [Angle]] [-distance [Distance]]
14561 [-stereo] [-leftEye] [-rightEye]
14562 [-iod [Distance]] [-iodType [absolute|relative]]
14563 [-zfocus [Value]] [-zfocusType [absolute|relative]]
14564 [-fov2d [Angle]] [-lockZup {0|1}]
14565 [-rotationMode {active|pick|pickCenter|cameraAt|scene}]
14566 [-navigationMode {orbit|walk|flight}]
14567 [-xrPose base|head=base]
14568Manages camera parameters.
14569Displays frustum when presentation name PrsName is specified.
14570Prints current value when option called without argument.
14571
14572Orthographic camera:
14573 -ortho activate orthographic projection.
14574
14575Perspective camera:
14576 -persp activate perspective projection (mono);
14577 -fovy field of view in y axis, in degrees;
14578 -fov2d field of view limit for 2d on-screen elements;
14579 -distance distance of eye from camera center;
14580 -lockZup lock Z up (turntable mode);
14581 -rotationMode rotation mode (gravity point);
14582 -navigationMode navigation mode.
14583
14584Stereoscopic camera:
14585 -stereo perspective projection (stereo);
14586 -leftEye perspective projection (left eye);
14587 -rightEye perspective projection (right eye);
14588 -iod intraocular distance value;
14589 -iodType distance type, absolute or relative;
14590 -zfocus stereographic focus value;
14591 -zfocusType focus type, absolute or relative.
14592)" /* [vcamera] */);
14593
14594 addCmd ("vautozfit", VAutoZFit, /* [vautozfit] */ R"(
14595vautozfit [on={1|0}] [scale]
14596Prints or changes parameters of automatic z-fit mode:
14597 "on" - turns automatic z-fit on or off;
14598 "scale" - specifies factor to scale computed z range.
14599)" /* [vautozfit] */);
14600
14601 addCmd ("vzrange", VZRange, /* [vzrange] */ R"(
14602vzrange [znear] [zfar]
14603Applies provided znear/zfar to view or prints current values.
14604)" /* [vzrange] */);
14605
14606 addCmd ("vsetviewsize", VSetViewSize, /* [vsetviewsize] */ R"(
14607vsetviewsize size
14608)" /* [vsetviewsize] */);
14609
14610 addCmd ("vmoveview", VMoveView, /* [vmoveview] */ R"(
14611vmoveview Dx Dy Dz [Start = 1|0]
14612)" /* [vmoveview] */);
14613
14614 addCmd ("vtranslateview", VTranslateView, /* [vtranslateview] */ R"(
14615vtranslateview Dx Dy Dz [Start = 1|0)]
14616)" /* [vtranslateview] */);
14617
14618 addCmd ("vturnview", VTurnView, /* [vturnview] */ R"(
14619vturnview Ax Ay Az [Start = 1|0]
14620)" /* [vturnview] */);
14621
14622 addCmd ("vtextureenv", VTextureEnv, /* [vtextureenv] */ R"(
14623vtextureenv {on|off} {image_file}
14624 [{clamp|repeat} {decal|modulate} {nearest|bilinear|trilinear} ss st ts tt rot]
14625Enables or disables environment mapping in the 3D view, loading the texture from the given standard
14626or user-defined file and optionally applying texture mapping parameters.
14627 ss, st - scale factors for s and t texture coordinates;
14628 ts, tt - translation for s and t texture coordinates;
14629 rot - texture rotation angle in degrees.
14630)" /* [vtextureenv] */);
14631
14632 addCmd ("vhlr", VHLR, /* [vhlr] */ R"(
14633vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]
14634Hidden Line Removal algorithm.
14635 -showHidden if set ON, hidden lines are drawn as dotted ones;
14636 -algoType type of HLR algorithm:
14637 'algo' - exact HLR algorithm is applied;
14638 'polyAlgo' - polygonal HLR algorithm is applied.
14639)" /* [vhlr] */);
14640
14641 addCmd ("vhlrtype", VHLRType, /* [vhlrtype] */ R"(
14642vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]
14643Changes the type of HLR algorithm using for shapes:
14644 'algo' - exact HLR algorithm is applied;
14645 'polyAlgo' - polygonal HLR algorithm is applied.
14646If shapes are not given - option is applied to all shapes in the view.
14647)" /* [vhlrtype] */);
14648
14649 addCmd ("vclipplane", VClipPlane, /* [vclipplane] */ R"(
14650vclipplane planeName [{0|1}]
14651 [-equation1 A B C D]
14652 [-equation2 A B C D]
14653 [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]
14654 [-set|-unset|-setOverrideGlobal [objects|views]]
14655 [-maxPlanes]
14656 [-capping {0|1}]
14657 [-color R G B] [-transparency Value] [-hatch {on|off|ID}]
14658 [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]
14659 [-texRotate Angle]
14660 [-useObjMaterial {0|1}] [-useObjTexture {0|1}]
14661 [-useObjShader {0|1}]
14662
14663Clipping planes management:
14664 -maxPlanes print plane limit for view;
14665 -delete delete plane with given name;
14666 {off|on|0|1} turn clipping on/off;
14667 -set|-unset set/unset plane for Object or View list;
14668 applied to active View when list is omitted;
14669 -equation A B C D change plane equation;
14670 -clone SourcePlane NewPlane clone the plane definition.
14671
14672Capping options:
14673 -capping {off|on|0|1} turn capping on/off;
14674 -color R G B set capping color;
14675 -transparency Value set capping transparency 0..1;
14676 -texName Texture set capping texture;
14677 -texScale SX SY set capping tex scale;
14678 -texOrigin TX TY set capping tex origin;
14679 -texRotate Angle set capping tex rotation;
14680 -hatch {on|off|ID} set capping hatching mask;
14681 -useObjMaterial {off|on|0|1} use material of clipped object;
14682 -useObjTexture {off|on|0|1} use texture of clipped object;
14683 -useObjShader {off|on|0|1} use shader program of object.
14684)" /* [vclipplane] */);
14685
14686 addCmd ("vdefaults", VDefaults, /* [vdefaults] */ R"(
14687vdefaults [-absDefl value] [-devCoeff value] [-angDefl value]
14688 [-autoTriang {off/on | 0/1}]
14689)" /* [vdefaults] */);
14690
14691 addCmd ("vlight", VLight, /* [vlight] */ R"(
14692vlight [lightName] [-noupdate]
14693 [-clear|-defaults] [-layer Id] [-local|-global] [-disable|-enable]
14694 [-type {ambient|directional|spotlight|positional}] [-name value]
14695 [-position X Y Z] [-direction X Y Z] [-color colorName] [-intensity value]
14696 [-headlight 0|1] [-castShadows 0|1]
14697 [-range value] [-constAttenuation value] [-linearAttenuation value]
14698 [-spotExponent value] [-spotAngle angleDeg]
14699 [-smoothAngle value] [-smoothRadius value]
14700 [-display] [-showName 1|0] [-showRange 1|0] [-prsZoomable 1|0] [-prsSize Value]
14701 [-arcSize Value]
14702
14703Command manages light sources. Without arguments shows list of lights.
14704Arguments affecting the list of defined/active lights:
14705 -clear remove all light sources;
14706 -defaults defines two standard light sources;
14707 -reset resets light source parameters to default values;
14708 -type sets type of light source;
14709 -name sets new name to light source;
14710 -global assigns light source to all views (default state);
14711 -local assigns light source to active view;
14712 -zlayer assigns light source to specified Z-Layer.
14713
14714Ambient light parameters:
14715 -color sets (normalized) light color;
14716 -intensity sets intensity of light source, 1.0 by default;
14717 affects also environment cubemap intensity.
14718
14719Point light parameters:
14720 -color sets (normalized) light color;
14721 -intensity sets PBR intensity;
14722 -range sets clamping distance;
14723 -constAtten (obsolete) sets constant attenuation factor;
14724 -linearAtten (obsolete) sets linear attenuation factor;
14725 -smoothRadius sets PBR smoothing radius.
14726
14727Directional light parameters:
14728 -color sets (normalized) light color;
14729 -intensity sets PBR intensity;
14730 -direction sets direction;
14731 -headlight sets headlight flag;
14732 -castShadows enables/disables shadow casting;
14733 -smoothAngle sets PBR smoothing angle (in degrees) within 0..90 range.
14734
14735Spot light parameters:
14736 -color sets (normalized) light color;
14737 -intensity sets PBR intensity;
14738 -range sets clamping distance;
14739 -position sets position;
14740 -direction sets direction;
14741 -spotAngle sets spotlight angle;
14742 -spotExp sets spotlight exponenta;
14743 -headlight sets headlight flag;
06aa2001 14744 -castShadows enables/disables shadow casting;
44f6e8d5 14745 -constAtten (obsolete) sets constant attenuation factor;
14746 -linearAtten (obsolete) sets linear attenuation factor.
14747
14748Light presentation parameters:
14749 -display adds light source presentation;
14750 -showName shows/hides the name of light source; 1 by default;
14751 -showRange shows/hides the range of spot/positional light source; 1 by default;
14752 -prsZoomable makes light presentation zoomable/non-zoomable;
14753 -prsDraggable makes light presentation draggable/non-draggable;
14754 -prsSize sets light presentation size;
14755 -arcSize sets arc presentation size(in pixels)
14756 for rotation directional light source; 25 by default.
14757
14758Examples:
14759 vlight redlight -type POSITIONAL -headlight 1 -pos 0 1 1 -color RED
14760 vlight redlight -delete
14761)" /* [vlight] */);
14762
14763 addCmd ("vpbrenv", VPBREnvironment, /* [vpbrenv] */ R"(
14764vpbrenv -clear|-generate
14765Clears or generates PBR environment map of active view.
14766 -clear clears PBR environment (fills by white color);
14767 -generate generates PBR environment from current background cubemap.
14768)" /* [vpbrenv] */);
14769
14770 addCmd ("vraytrace", VRenderParams, /* [vraytrace] */ R"(
14771vraytrace [0|1] : Turns on/off ray-tracing renderer.
14772 'vraytrace 0' alias for 'vrenderparams -raster'.
14773 'vraytrace 1' alias for 'vrenderparams -rayTrace'.
14774)" /* [vraytrace] */);
14775
14776 addCmd ("vrenderparams", VRenderParams, /* [vrenderparams] */ R"(
14777Manages rendering parameters, affecting visual appearance, quality and performance.
14778Should be applied taking into account GPU hardware capabilities and performance.
14779
14780Common parameters:
14781vrenderparams [-raster] [-shadingModel {unlit|facet|gouraud|phong|pbr|pbr_facet}=gouraud]
14782 [-msaa 0..8=0] [-rendScale scale=1]
14783 [-resolution value=72] [-fontHinting {off|normal|light}=off]
14784 [-fontAutoHinting {auto|force|disallow}=auto]
14785 [-oit {off|weight|peel}] [-oit weighted [depthFactor=0.0]] [-oit peeling [nbLayers=4]]
14786 [-shadows {on|off}=on] [-shadowMapResolution value=1024] [-shadowMapBias value=0.005]
14787 [-depthPrePass {on|off}=off] [-alphaToCoverage {on|off}=on]
14788 [-frustumCulling {on|off|noupdate}=on] [-lineFeather width=1.0]
14789 [-sync {default|views}] [-reset]
14790 -raster Disables GPU ray-tracing.
14791 -shadingModel Controls shading model.
14792 -msaa Specifies number of samples for MSAA.
14793 -rendScale Rendering resolution scale factor (supersampling, alternative to MSAA).
14794 -resolution Sets new pixels density (PPI) used as text scaling factor.
14795 -fontHinting Enables/disables font hinting for better readability on low-resolution screens.
14796 -fontAutoHinting Manages font autohinting.
14797 -lineFeather Sets line feather factor while displaying mesh edges.
14798 -alphaToCoverage Enables/disables alpha to coverage (needs MSAA).
14799 -oit Enables/disables order-independent transparency (OIT) rendering;
14800 off unordered transparency (but opaque objects implicitly draw first);
14801 weighted weight OIT is managed by depth weight factor 0.0..1.0;
14802 peeling depth peeling OIT is managed by number of peeling layers.
14803 -shadows Enables/disables shadows rendering.
14804 -shadowMapResolution Shadow texture map resolution.
14805 -shadowMapBias Shadow map bias.
14806 -depthPrePass Enables/disables depth pre-pass.
14807 -frustumCulling Enables/disables objects frustum clipping or
14808 sets state to check structures culled previously.
14809 -sync Sets active View parameters as Viewer defaults / to other Views.
14810 -reset Resets active View parameters to Viewer defaults.
14811
14812Diagnostic output (on-screen overlay):
14813vrenderparams [-perfCounters none|fps|cpu|layers|structures|groups|arrays|triangles|points
14814 |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate]
14815 [-perfUpdateInterval nbSeconds=1] [-perfChart nbFrames=1] [-perfChartMax seconds=0.1]
14816 -perfCounters Show/hide performance counters (flags can be combined).
14817 -perfUpdateInterval Performance counters update interval.
14818 -perfChart Show frame timers chart limited by specified number of frames.
14819 -perfChartMax Maximum time in seconds with the chart.
14820
14821Ray-Tracing options:
14822vrenderparams [-rayTrace] [-rayDepth {0..10}=3] [-reflections {on|off}=off]
14823 [-fsaa {on|off}=off] [-gleam {on|off}=off] [-env {on|off}=off]
14824 [-gi {on|off}=off] [-brng {on|off}=off]
14825 [-iss {on|off}=off] [-tileSize {1..4096}=32] [-nbTiles {64..1024}=256]
14826 [-ignoreNormalMap {on|off}=off] [-twoSide {on|off}=off]
14827 [-maxRad {value>0}=30.0]
14828 [-aperture {value>=0}=0.0] [-focal {value>=0.0}=1.0]
14829 [-exposure value=0.0] [-whitePoint value=1.0] [-toneMapping {disabled|filmic}=disabled]
14830 -rayTrace Enables GPU ray-tracing.
14831 -rayDepth Defines maximum ray-tracing depth.
14832 -reflections Enables/disables specular reflections.
14833 -fsaa Enables/disables adaptive anti-aliasing.
14834 -gleam Enables/disables transparency shadow effects.
14835 -gi Enables/disables global illumination effects (Path-Tracing).
14836 -env Enables/disables environment map background.
14837 -ignoreNormalMap Enables/disables normal map ignoring during path tracing.
14838 -twoSide Enables/disables two-sided BSDF models (PT mode).
14839 -iss Enables/disables adaptive screen sampling (PT mode).
14840 -maxRad Value used for clamping radiance estimation (PT mode).
14841 -tileSize Specifies size of screen tiles in ISS mode (32 by default).
14842 -nbTiles Specifies number of screen tiles per Redraw in ISS mode (256 by default).
14843 -aperture Aperture size of perspective camera for depth-of-field effect (0 disables DOF).
14844 -focal Focal distance of perspective camera for depth-of-field effect.
14845 -exposure Exposure value for tone mapping (0.0 value disables the effect).
14846 -whitePoint White point value for filmic tone mapping.
14847 -toneMapping Tone mapping mode (disabled, filmic).
14848
14849PBR environment baking parameters (advanced/debug):
14850vrenderparams [-pbrEnvPow2size {power>0}=9] [-pbrEnvSMLN {levels>1}=6] [-pbrEnvBP {0..1}=0.99]
14851 [-pbrEnvBDSN {samples>0}=1024] [-pbrEnvBSSN {samples>0}=256]
14852 -pbrEnvPow2size Controls size of IBL maps (real size can be calculates as 2^pbrenvpow2size).
14853 -pbrEnvSMLN Controls number of mipmap levels used in specular IBL map.
14854 -pbrEnvBDSN Controls number of samples in Monte-Carlo integration during
14855 diffuse IBL map's sherical harmonics calculation.
14856 -pbrEnvBSSN Controls maximum number of samples per mipmap level
14857 in Monte-Carlo integration during specular IBL maps generation.
14858 -pbrEnvBP Controls strength of samples number reducing
14859 during specular IBL maps generation (1 disables reducing).
14860
14861Debug options:
14862vrenderparams [-issd {on|off}=off] [-rebuildGlsl on|off]
14863 -issd Shows screen sampling distribution in ISS mode.
14864 -rebuildGlsl Rebuild Ray-Tracing GLSL programs (for debugging).
14865 -brng Enables/disables blocked RNG (fast coherent PT).
14866)" /* [vrenderparams] */);
14867
14868 addCmd ("vstatprofiler", VStatProfiler, /* [vstatprofiler] */ R"(
14869vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups
14870 |allArrays|fillArrays|lineArrays|pointArrays|textArrays
14871 |triangles|points|geomMem|textureMem|frameMem
14872 |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage
14873 |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]
14874 [-noredraw]
14875Prints rendering statistics for specified counters or for all when unspecified.
14876Set '-noredraw' flag to avoid additional redraw call and use already collected values.
14877)" /* [vstatprofiler] */);
14878
14879 addCmd ("vplace", VPlace, /* [vplace] */ R"(
14880vplace dx dy : Places the point (in pixels) at the center of the window
14881)" /* [vplace] */);
14882
14883 addCmd ("vxrotate", VXRotate, /* [vxrotate] */ R"(
14884vxrotate
14885)" /* [vxrotate] */);
14886
14887 addCmd ("vmanipulator", VManipulator, /* [vmanipulator] */ R"(
14888vmanipulator Name [-attach AISObject | -detach | ...]
14889Tool to create and manage AIS manipulators.
14890Options:
14891 '-attach AISObject' attach manipulator to AISObject
14892 '-adjustPosition {0|center|location|shapeLocation}' adjust position when attaching
14893 '-adjustSize {0|1}' adjust size when attaching
14894 '-enableModes {0|1}' enable modes when attaching
14895 '-view {active | [name of view]}' display manipulator only in defined view,
14896 by default it is displayed in all views of the current viewer
14897 '-detach' detach manipulator
14898 '-startTransform mouse_x mouse_y' - invoke start of transformation
14899 '-transform mouse_x mouse_y' - invoke transformation
14900 '-stopTransform [abort]' - invoke stop of transformation
14901 '-move x y z' - move attached object
14902 '-rotate x y z dx dy dz angle' - rotate attached object
14903 '-scale factor' - scale attached object
14904 '-autoActivate {0|1}' - set activation on detection
14905 '-followTranslation {0|1}' - set following translation transform
14906 '-followRotation {0|1}' - set following rotation transform
14907 '-followDragging {0|1}' - set following dragging transform
14908 '-gap value' - set gap between sub-parts
14909 '-part axis mode {0|1}' - set visual part
14910 '-parts axis mode {0|1}' - set visual part
14911 '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator
14912 '-size value' - set size of manipulator
14913 '-zoomable {0|1}' - set zoom persistence
14914)" /* [vmanipulator] */);
14915
14916 addCmd ("vselprops", VSelectionProperties, /* [vselprops] */ R"(
14917vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]
14918Customizes selection and dynamic highlight parameters for the whole interactive context:
14919 -autoActivate {0|1} disables|enables default computation
14920 and activation of global selection mode
14921 -autoHighlight {0|1} disables|enables automatic highlighting in 3D Viewer
14922 -highlightSelected {0|1} disables|enables highlighting of detected object in selected state
14923 -pickStrategy {first|topmost} : defines picking strategy
14924 'first' to pick first acceptable (default)
14925 'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)
14926 -pixTol value sets up pixel tolerance
14927 -depthTol {uniform|uniformpx} value : sets tolerance for sorting results by depth
14928 -depthTol {sensfactor} use sensitive factor for sorting results by depth
14929 -preferClosest {0|1} sets if depth should take precedence over priority while sorting results
14930 -dispMode dispMode sets display mode for highlighting
14931 -layer ZLayer sets ZLayer for highlighting
14932 -color {name|r g b} sets highlight color
14933 -transp value sets transparency coefficient for highlight
14934 -material material sets highlight material
14935 -print prints current state of all mentioned parameters
14936)" /* [vselprops] */);
14937
14938 addCmd ("vhighlightselected", VSelectionProperties, /* [vhighlightselected] */ R"(
14939vhighlightselected [0|1] : alias for vselprops -highlightSelected.
14940)" /* [vhighlightselected] */);
14941
14942 addCmd ("vseldump", VDumpSelectionImage, /* [vseldump] */ R"(
14943vseldump file -type {depth|unnormDepth|object|owner|selMode|entity|entityType|surfNormal}=depth
14944 -pickedIndex Index=1
14945 [-xrPose base|head=base]
14946Generate an image based on detection results:
14947 depth normalized depth values
14948 unnormDepth unnormalized depth values
14949 object color of detected object
14950 owner color of detected owner
14951 selMode color of selection mode
14952 entity color of detected entity
14953 entityType color of detected entity type
14954 surfNormal normal direction values
14955)" /* [vseldump] */);
14956
14957 addCmd ("vviewcube", VViewCube, /* [vviewcube] */ R"(
14958vviewcube name
14959Displays interactive view manipulation object. Options:
14960 -reset reset geometric and visual attributes
14961 -size Size adapted size of View Cube
14962 -boxSize Size box size
14963 -axes {0|1} show/hide axes (trihedron)
14964 -edges {0|1} show/hide edges of View Cube
14965 -vertices {0|1} show/hide vertices of View Cube
14966 -Yup {0|1} -Zup {0|1} set Y-up or Z-up view orientation
14967 -color Color color of View Cube
14968 -boxColor Color box color
14969 -boxSideColor Color box sides color
14970 -boxEdgeColor Color box edges color
14971 -boxCornerColor Color box corner color
14972 -textColor Color color of side text of view cube
14973 -innerColor Color inner box color
14974 -transparency Value transparency of object within [0, 1] range
14975 -boxTransparency Value transparency of box within [0, 1] range
14976 -xAxisTextColor Color color of X axis label
14977 -yAxisTextColor Color color of Y axis label
14978 -zAxisTextColor Color color of Z axis label
14979 -font Name font name
14980 -fontHeight Value font height
14981 -boxFacetExtension Value box facet extension
14982 -boxEdgeGap Value gap between box edges and box sides
14983 -boxEdgeMinSize Value minimal box edge size
14984 -boxCornerMinSize Value minimal box corner size
14985 -axesPadding Value padding between box and arrows
14986 -roundRadius Value relative radius of corners of sides within [0.0, 0.5] range
14987 -axesRadius Value radius of axes of the trihedron
14988 -axesConeRadius Value radius of the cone (arrow) of the trihedron
14989 -axesSphereRadius Value radius of the sphere (central point) of trihedron
14990 -fixedAnimation {0|1} uninterruptible animation loop
14991 -duration Seconds animation duration in seconds
f035e071 14992 -orthoPers force orthographic projection persistence.
44f6e8d5 14993)" /* [vviewcube] */);
14994
14995 addCmd ("vcolorconvert", VColorConvert, /* [vcolorconvert] */ R"(
cb6c7c45 14996vcolorconvert [-from {sRGB|HLS|Lab|Lch|RGB}]=RGB [-to {sRGB|HLS|Lab|Lch|RGB|hex|name}]=RGB C1 C2 C2
14997To convert color from specified color space to linear RGB:
14998 vcolorconvert -from {sRGB|HLS|Lab|Lch|RGB} C1 C2 C2
14999To convert linear RGB color to specified color space:
15000 vcolorconvert -to {sRGB|HLS|Lab|Lch|RGB|hex|name} R G B
44f6e8d5 15001)" /* [vcolorconvert] */);
15002
15003 addCmd ("vcolordiff", VColorDiff, /* [vcolordiff] */ R"(
15004vcolordiff R1 G1 B1 R2 G2 B2 : returns CIEDE2000 color difference between two RGB colors.
15005)" /* [vcolordiff] */);
15006
15007 addCmd ("vselbvhbuild", VSelBvhBuild, /* [vselbvhbuild] */ R"(
15008vselbvhbuild [{0|1}] [-nbThreads value] [-wait]
15009Turns on/off prebuilding of BVH within background thread(s).
15010 -nbThreads number of threads, 1 by default; if < 1 then used (NbLogicalProcessors - 1);
15011 -wait waits for building all of BVH.
15012)" /* [vselbvhbuild] */);
34213231 15013
15014 addCmd ("vchangemousegesture", VChangeMouseGesture, /* [vchangemousegesture] */ R"(
15015vchangemousegesture -button {none|left|middle|right}=left
15016 -gesture {none|selectRectangle|selectLasso|zoom|zoomWindow|pan|rotateOrbit|rotateView|drag}=rotateOrbit
15017Changes the gesture for the mouse button.
15018 -button the mouse button;
15019 -gesture the new gesture for the button.
15020)" /* [vchangemousegesture] */);
2108d9a2 15021}