1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00

0032886: Visualization, V3d_View - introduce interface for creating a subview

V3d_View/Graphic3d_CView pair has been extended to define subview within the other V3d_View instance.
The initialization is done in form of V3d_View::SetWindow() taking parent V3d_View instance on input.

Subview definition includes dimensions defined as a fraction of a parent view and offset from a corner.
This scheme allows splitting window into several subviews automatically occupying entire viewport,
like splitting window into two vertial subviews (100%x50% + 100%x50%),
three horizontal subviews (33%x100% + 30%x100% + 30%x100%),
1 + 2 stacked subviews (50%x100% + 50%x50% + 50%x50%),
as well as thumbnail-alike subviews displayed on top of another larger view.

OpenGl_View::Redraw() blits content of subviews into the window within immediate redraw step.

AIS_ViewController::FlushViewEvents() has been extended
to re-calculate mouse input into local subview coordinates.
AIS_ViewController::handleViewRedraw() first redraws subviews and then parent views.
Introduced new callback AIS_ViewController::OnSubviewChanged()
to switch input focus to another subview on mouse click,
implemented by ViewerTest_EventManager (has to be done at application level).

vinit command has been extended with parameters -subview and -parent to create a subview.
In addition, view dimension arguments now can be defined as a fraction of screen size instead of pixels.
This commit is contained in:
kgv 2022-04-11 20:00:39 +03:00 committed by smoskvin
parent 179fb34661
commit 879768fbf2
34 changed files with 1706 additions and 496 deletions

View File

@ -184,6 +184,53 @@ void AIS_ViewController::FlushViewEvents (const Handle(AIS_InteractiveContext)&
{ {
flushBuffers (theCtx, theView); flushBuffers (theCtx, theView);
flushGestures(theCtx, theView); flushGestures(theCtx, theView);
if (theView->IsSubview())
{
// move input coordinates inside the view
const Graphic3d_Vec2i aDelta = theView->View()->SubviewTopLeft();
if (myGL.MoveTo.ToHilight || myGL.Dragging.ToStart)
{
myGL.MoveTo.Point -= aDelta;
}
if (myGL.Panning.ToStart)
{
myGL.Panning.PointStart -= aDelta;
}
if (myGL.Dragging.ToStart)
{
myGL.Dragging.PointStart -= aDelta;
}
if (myGL.Dragging.ToMove)
{
myGL.Dragging.PointTo -= aDelta;
}
if (myGL.OrbitRotation.ToStart)
{
myGL.OrbitRotation.PointStart -= Graphic3d_Vec2d (aDelta);
}
if (myGL.OrbitRotation.ToRotate)
{
myGL.OrbitRotation.PointTo -= Graphic3d_Vec2d (aDelta);
}
if (myGL.ViewRotation.ToStart)
{
myGL.ViewRotation.PointStart -= Graphic3d_Vec2d (aDelta);
}
if (myGL.ViewRotation.ToRotate)
{
myGL.ViewRotation.PointTo -= Graphic3d_Vec2d (aDelta);
}
for (Graphic3d_Vec2i& aPntIter : myGL.Selection.Points)
{
aPntIter -= aDelta;
}
for (Aspect_ScrollDelta& aZoomIter : myGL.ZoomActions)
{
aZoomIter.Point -= aDelta;
}
}
if (theToHandle) if (theToHandle)
{ {
HandleViewEvents (theCtx, theView); HandleViewEvents (theCtx, theView);
@ -2627,6 +2674,17 @@ void AIS_ViewController::OnSelectionChanged (const Handle(AIS_InteractiveContext
// //
} }
// =======================================================================
// function : OnSubviewChanged
// purpose :
// =======================================================================
void AIS_ViewController::OnSubviewChanged (const Handle(AIS_InteractiveContext)& ,
const Handle(V3d_View)& ,
const Handle(V3d_View)& )
{
//
}
// ======================================================================= // =======================================================================
// function : OnObjectDragged // function : OnObjectDragged
// purpose : // purpose :
@ -3002,6 +3060,8 @@ void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& the
void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& , void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
const Handle(V3d_View)& theView) const Handle(V3d_View)& theView)
{ {
Handle(V3d_View) aParentView = theView->IsSubview() ? theView->ParentView() : theView;
// manage animation state // manage animation state
if (!myViewAnimation.IsNull() if (!myViewAnimation.IsNull()
&& !myViewAnimation->IsStopped()) && !myViewAnimation->IsStopped())
@ -3029,31 +3089,82 @@ void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)&
myToAskNextFrame = true; myToAskNextFrame = true;
} }
for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next()) for (int aSubViewPass = 0; aSubViewPass < 2; ++aSubViewPass)
{ {
const Handle(V3d_View)& aView = aViewIter.Value(); const bool isSubViewPass = (aSubViewPass == 0);
if (aView->IsInvalidated() for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
|| (myToAskNextFrame && aView == theView))
{ {
if (aView->ComputedMode()) const Handle(V3d_View)& aView = aViewIter.Value();
if (isSubViewPass
&& !aView->IsSubview())
{ {
aView->Update(); for (const Handle(V3d_View)& aSubviewIter : aView->Subviews())
{
if (aSubviewIter->Viewer() != theView->Viewer())
{
if (aSubviewIter->IsInvalidated())
{
if (aSubviewIter->ComputedMode())
{
aSubviewIter->Update();
}
else
{
aSubviewIter->Redraw();
}
}
else if (aSubviewIter->IsInvalidatedImmediate())
{
aSubviewIter->RedrawImmediate();
}
}
}
continue;
} }
else else if (!isSubViewPass
&& aView->IsSubview())
{ {
aView->Redraw(); continue;
}
if (aView->IsInvalidated()
|| (myToAskNextFrame && aView == theView))
{
if (aView->ComputedMode())
{
aView->Update();
}
else
{
aView->Redraw();
}
if (aView->IsSubview())
{
aView->ParentView()->InvalidateImmediate();
}
}
else if (aView->IsInvalidatedImmediate())
{
if (aView->IsSubview())
{
aView->ParentView()->InvalidateImmediate();
}
aView->RedrawImmediate();
} }
} }
else if (aView->IsInvalidatedImmediate()) }
{ if (theView->IsSubview()
aView->RedrawImmediate(); && theView->Viewer() != aParentView->Viewer())
} {
aParentView->RedrawImmediate();
} }
if (myToAskNextFrame) if (myToAskNextFrame)
{ {
// ask more frames // ask more frames
theView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)()); aParentView->Window()->InvalidateContent (Handle(Aspect_DisplayConnection)());
} }
} }
@ -3298,6 +3409,36 @@ void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)&
{ {
const bool wasImmediateUpdate = theView->SetImmediateUpdate (false); const bool wasImmediateUpdate = theView->SetImmediateUpdate (false);
Handle(V3d_View) aPickedView;
if (theView->IsSubview()
|| !theView->Subviews().IsEmpty())
{
// activate another subview on mouse click
bool toPickSubview = false;
Graphic3d_Vec2i aClickPoint;
if (myGL.Selection.Tool == AIS_ViewSelectionTool_Picking
&& !myGL.Selection.Points.IsEmpty())
{
aClickPoint = myGL.Selection.Points.Last();
toPickSubview = true;
}
else if (!myGL.ZoomActions.IsEmpty())
{
//aClickPoint = myGL.ZoomActions.Last().Point;
//toPickSubview = true;
}
if (toPickSubview)
{
if (theView->IsSubview())
{
aClickPoint += theView->View()->SubviewTopLeft();
}
Handle(V3d_View) aParent = !theView->IsSubview() ? theView : theView->ParentView();
aPickedView = aParent->PickSubview (aClickPoint);
}
}
handleViewOrientationKeys (theCtx, theView); handleViewOrientationKeys (theCtx, theView);
const AIS_WalkDelta aWalk = handleNavigationKeys (theCtx, theView); const AIS_WalkDelta aWalk = handleNavigationKeys (theCtx, theView);
handleXRInput (theCtx, theView, aWalk); handleXRInput (theCtx, theView, aWalk);
@ -3315,6 +3456,12 @@ void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)&
theView->SetImmediateUpdate (wasImmediateUpdate); theView->SetImmediateUpdate (wasImmediateUpdate);
if (!aPickedView.IsNull()
&& aPickedView != theView)
{
OnSubviewChanged (theCtx, theView, aPickedView);
}
// make sure to not process the same events twice // make sure to not process the same events twice
myGL.Reset(); myGL.Reset();
myToAskNextFrame = false; myToAskNextFrame = false;

View File

@ -492,6 +492,12 @@ public:
const Handle(V3d_View)& theView, const Handle(V3d_View)& theView,
AIS_DragAction theAction); AIS_DragAction theAction);
//! Callback called by HandleViewEvents() on Selection of another (sub)view.
//! This method is expected to be called from rendering thread.
Standard_EXPORT virtual void OnSubviewChanged (const Handle(AIS_InteractiveContext)& theCtx,
const Handle(V3d_View)& theOldView,
const Handle(V3d_View)& theNewView);
//! Pick closest point under mouse cursor. //! Pick closest point under mouse cursor.
//! This method is expected to be called from rendering thread. //! This method is expected to be called from rendering thread.
//! @param thePnt [out] result point //! @param thePnt [out] result point

View File

@ -40,18 +40,58 @@ class Aspect_Window : public Standard_Transient
DEFINE_STANDARD_RTTIEXT(Aspect_Window, Standard_Transient) DEFINE_STANDARD_RTTIEXT(Aspect_Window, Standard_Transient)
public: public:
//! Modifies the window background. //! Returns True if the window <me> is virtual
Standard_EXPORT void SetBackground (const Aspect_Background& ABack); Standard_EXPORT Standard_Boolean IsVirtual() const;
//! Setup the virtual state
Standard_EXPORT void SetVirtual (const Standard_Boolean theVirtual);
//! Returns window top-left corner.
Graphic3d_Vec2i TopLeft() const
{
Graphic3d_Vec2i aTopLeft, aBotRight;
Position (aTopLeft.x(), aTopLeft.y(), aBotRight.x(), aBotRight.y());
return aTopLeft;
}
//! Returns window dimensions.
Graphic3d_Vec2i Dimensions() const
{
Graphic3d_Vec2i aSize;
Size (aSize.x(), aSize.y());
return aSize;
}
//! Returns connection to Display or NULL.
const Handle(Aspect_DisplayConnection)& DisplayConnection() const { return myDisplay; }
//! Returns the window background.
Standard_EXPORT Aspect_Background Background() const;
//! Returns the current image background fill mode.
Standard_EXPORT Aspect_FillMethod BackgroundFillMethod() const;
//! Returns the window gradient background.
Standard_EXPORT Aspect_GradientBackground GradientBackground() const;
//! Modifies the window background. //! Modifies the window background.
Standard_EXPORT void SetBackground (const Quantity_Color& color); Standard_EXPORT void SetBackground (const Aspect_Background& theBack);
//! Modifies the window background.
Standard_EXPORT void SetBackground (const Quantity_Color& theColor);
//! Modifies the window gradient background. //! Modifies the window gradient background.
Standard_EXPORT void SetBackground (const Aspect_GradientBackground& ABackground); Standard_EXPORT void SetBackground (const Aspect_GradientBackground& theBackground);
//! Modifies the window gradient background. //! Modifies the window gradient background.
Standard_EXPORT void SetBackground (const Quantity_Color& theFirstColor, const Quantity_Color& theSecondColor, const Aspect_GradientFillMethod theFillMethod); Standard_EXPORT void SetBackground (const Quantity_Color& theFirstColor, const Quantity_Color& theSecondColor, const Aspect_GradientFillMethod theFillMethod);
public:
//! Returns True if the window <me> is opened
//! and False if the window is closed.
Standard_EXPORT virtual Standard_Boolean IsMapped() const = 0;
//! Opens the window <me>. //! Opens the window <me>.
Standard_EXPORT virtual void Map() const = 0; Standard_EXPORT virtual void Map() const = 0;
@ -65,25 +105,6 @@ public:
//! and returns TRUE if the window is mapped at screen. //! and returns TRUE if the window is mapped at screen.
Standard_EXPORT virtual Standard_Boolean DoMapping() const = 0; Standard_EXPORT virtual Standard_Boolean DoMapping() const = 0;
//! Returns the window background.
Standard_EXPORT Aspect_Background Background() const;
//! Returns the current image background fill mode.
Standard_EXPORT Aspect_FillMethod BackgroundFillMethod() const;
//! Returns the window gradient background.
Standard_EXPORT Aspect_GradientBackground GradientBackground() const;
//! Returns True if the window <me> is opened
//! and False if the window is closed.
Standard_EXPORT virtual Standard_Boolean IsMapped() const = 0;
//! Returns True if the window <me> is virtual
Standard_EXPORT Standard_Boolean IsVirtual() const;
//! Setup the virtual state
Standard_EXPORT void SetVirtual (const Standard_Boolean theVirtual);
//! Returns The Window RATIO equal to the physical //! Returns The Window RATIO equal to the physical
//! WIDTH/HEIGHT dimensions //! WIDTH/HEIGHT dimensions
Standard_EXPORT virtual Standard_Real Ratio() const = 0; Standard_EXPORT virtual Standard_Real Ratio() const = 0;
@ -103,9 +124,6 @@ public:
//! Returns native Window FB config (GLXFBConfig on Xlib) //! Returns native Window FB config (GLXFBConfig on Xlib)
Standard_EXPORT virtual Aspect_FBConfig NativeFBConfig() const = 0; Standard_EXPORT virtual Aspect_FBConfig NativeFBConfig() const = 0;
//! Returns connection to Display or NULL.
const Handle(Aspect_DisplayConnection)& DisplayConnection() const { return myDisplay; }
//! Sets window title. //! Sets window title.
virtual void SetTitle (const TCollection_AsciiString& theTitle) { (void )theTitle; } virtual void SetTitle (const TCollection_AsciiString& theTitle) { (void )theTitle; }

View File

@ -128,7 +128,8 @@ IDirect3DSurface9* D3DHost_View::D3dColorSurface() const
// function : SetWindow // function : SetWindow
// purpose : // purpose :
// ======================================================================= // =======================================================================
void D3DHost_View::SetWindow (const Handle(Aspect_Window)& theWindow, void D3DHost_View::SetWindow (const Handle(Graphic3d_CView)& theParentVIew,
const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext) const Aspect_RenderingContext theContext)
{ {
if (!myD3dWglFbo.IsNull()) if (!myD3dWglFbo.IsNull())
@ -142,7 +143,7 @@ void D3DHost_View::SetWindow (const Handle(Aspect_Window)& theWindow,
myD3dDevice = NULL; myD3dDevice = NULL;
} }
OpenGl_View::SetWindow (theWindow, theContext); OpenGl_View::SetWindow (theParentVIew, theWindow, theContext);
if (!myWindow.IsNull()) if (!myWindow.IsNull())
{ {

View File

@ -44,12 +44,8 @@ public:
Standard_EXPORT virtual void ReleaseGlResources (const Handle(OpenGl_Context)& theCtx) Standard_OVERRIDE; Standard_EXPORT virtual void ReleaseGlResources (const Handle(OpenGl_Context)& theCtx) Standard_OVERRIDE;
//! Creates and maps rendering window to the view. //! Creates and maps rendering window to the view.
//! @param theWindow [in] the window. Standard_EXPORT virtual void SetWindow (const Handle(Graphic3d_CView)& theParentVIew,
//! @param theContext [in] the rendering context. If NULL the context will be created internally. const Handle(Aspect_Window)& theWindow,
//! @param theDisplayCB [in] the display callback function. If is not a NULL value, then the callback will be
//! invoked at the end of the OCC graphic traversal and just before the swap of buffers.
//! @param theClientData [in] the client data for the callback.
Standard_EXPORT virtual void SetWindow (const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext) Standard_OVERRIDE; const Aspect_RenderingContext theContext) Standard_OVERRIDE;
//! Resizes the window. //! Resizes the window.

View File

@ -56,7 +56,7 @@ static Standard_Integer DPrsStd_AISInitViewer (Draw_Interpretor& theDI,
TCollection_AsciiString aViewName = TCollection_AsciiString ("Driver1/Document_") + theArgVec[1] + "/View1"; TCollection_AsciiString aViewName = TCollection_AsciiString ("Driver1/Document_") + theArgVec[1] + "/View1";
if (!TPrsStd_AISViewer::Find (aRoot, aDocViewer)) if (!TPrsStd_AISViewer::Find (aRoot, aDocViewer))
{ {
ViewerTest::ViewerInit (0, 0, 0, 0, aViewName.ToCString(), ""); ViewerTest::ViewerInit (aViewName);
aDocViewer = TPrsStd_AISViewer::New (aRoot, ViewerTest::GetAISContext()); aDocViewer = TPrsStd_AISViewer::New (aRoot, ViewerTest::GetAISContext());
} }

View File

@ -13,6 +13,7 @@
#include <Graphic3d_CView.hxx> #include <Graphic3d_CView.hxx>
#include <Aspect_NeutralWindow.hxx>
#include <Aspect_OpenVRSession.hxx> #include <Aspect_OpenVRSession.hxx>
#include <Graphic3d_CubeMapPacked.hxx> #include <Graphic3d_CubeMapPacked.hxx>
#include <Graphic3d_Layer.hxx> #include <Graphic3d_Layer.hxx>
@ -26,18 +27,27 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CView,Graphic3d_DataStructureManager)
//purpose : //purpose :
//======================================================================= //=======================================================================
Graphic3d_CView::Graphic3d_CView (const Handle(Graphic3d_StructureManager)& theMgr) Graphic3d_CView::Graphic3d_CView (const Handle(Graphic3d_StructureManager)& theMgr)
: myBgColor (Quantity_NOC_BLACK), : myId (0),
myBackgroundType (Graphic3d_TOB_NONE), //
myToUpdateSkydome (Standard_False), myParentView (nullptr),
myStructureManager (theMgr), myIsSubviewComposer (Standard_False),
myCamera (new Graphic3d_Camera()), mySubviewCorner (Aspect_TOTP_LEFT_UPPER),
myHiddenObjects (new Graphic3d_NMapOfTransient()), mySubviewSize (1.0, 1.0),
myIsInComputedMode (Standard_False), //
myIsActive (Standard_False), myStructureManager (theMgr),
myIsRemoved (Standard_False), myCamera (new Graphic3d_Camera()),
myBackfacing (Graphic3d_TypeOfBackfacingModel_Auto), myHiddenObjects (new Graphic3d_NMapOfTransient()),
myVisualization (Graphic3d_TOV_WIREFRAME), myIsInComputedMode (Standard_False),
myUnitFactor (1.0) myIsActive (Standard_False),
myIsRemoved (Standard_False),
myBackfacing (Graphic3d_TypeOfBackfacingModel_Auto),
myVisualization (Graphic3d_TOV_WIREFRAME),
//
myBgColor (Quantity_NOC_BLACK),
myBackgroundType (Graphic3d_TOB_NONE),
myToUpdateSkydome (Standard_False),
//
myUnitFactor (1.0)
{ {
myId = myStructureManager->Identification (this); myId = myStructureManager->Identification (this);
} }
@ -161,8 +171,21 @@ void Graphic3d_CView::Remove()
return; return;
} }
Graphic3d_MapOfStructure aDisplayedStructs (myStructsDisplayed); if (myParentView != nullptr)
{
myParentView->RemoveSubview (this);
myParentView = nullptr;
}
{
NCollection_Sequence<Handle(Graphic3d_CView)> aSubviews = mySubviews;
mySubviews.Clear();
for (const Handle(Graphic3d_CView)& aViewIter : aSubviews)
{
aViewIter->Remove();
}
}
Graphic3d_MapOfStructure aDisplayedStructs (myStructsDisplayed);
for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aDisplayedStructs); aStructIter.More(); aStructIter.Next()) for (Graphic3d_MapIteratorOfMapOfStructure aStructIter (aDisplayedStructs); aStructIter.More(); aStructIter.Next())
{ {
Erase (aStructIter.Value()); Erase (aStructIter.Value());
@ -181,6 +204,114 @@ void Graphic3d_CView::Remove()
myIsRemoved = Standard_True; myIsRemoved = Standard_True;
} }
// ========================================================================
// function : AddSubview
// purpose :
// ========================================================================
void Graphic3d_CView::AddSubview (const Handle(Graphic3d_CView)& theView)
{
mySubviews.Append (theView);
}
// ========================================================================
// function : RemoveSubview
// purpose :
// ========================================================================
bool Graphic3d_CView::RemoveSubview (const Graphic3d_CView* theView)
{
for (NCollection_Sequence<Handle(Graphic3d_CView)>::Iterator aViewIter (mySubviews); aViewIter.More(); aViewIter.Next())
{
if (aViewIter.Value() == theView)
{
mySubviews.Remove (aViewIter);
return true;
}
}
return false;
}
// ========================================================================
// function : Resized
// purpose :
// ========================================================================
void Graphic3d_CView::Resized()
{
if (IsSubview())
{
Handle(Aspect_NeutralWindow) aWindow = Handle(Aspect_NeutralWindow)::DownCast(Window());
SubviewResized (aWindow);
}
}
//! Calculate offset in pixels from fraction.
static int getSubViewOffset (double theOffset, int theWinSize)
{
if (theOffset >= 1.0)
{
return int(theOffset);
}
else
{
return int(theOffset * theWinSize);
}
}
// ========================================================================
// function : SubviewResized
// purpose :
// ========================================================================
void Graphic3d_CView::SubviewResized (const Handle(Aspect_NeutralWindow)& theWindow)
{
if (!IsSubview()
|| theWindow.IsNull())
{
return;
}
const Graphic3d_Vec2i aWinSize (myParentView->Window()->Dimensions());
Graphic3d_Vec2i aViewSize (Graphic3d_Vec2d(aWinSize) * mySubviewSize);
if (mySubviewSize.x() > 1.0)
{
aViewSize.x() = (int)mySubviewSize.x();
}
if (mySubviewSize.y() > 1.0)
{
aViewSize.y() = (int)mySubviewSize.y();
}
Graphic3d_Vec2i anOffset (getSubViewOffset (mySubviewOffset.x(), aWinSize.x()),
getSubViewOffset (mySubviewOffset.y(), aWinSize.y()));
mySubviewTopLeft = (aWinSize - aViewSize) / 2; // Aspect_TOTP_CENTER
if ((mySubviewCorner & Aspect_TOTP_LEFT) != 0)
{
mySubviewTopLeft.x() = anOffset.x();
}
else if ((mySubviewCorner & Aspect_TOTP_RIGHT) != 0)
{
mySubviewTopLeft.x() = Max (aWinSize.x() - anOffset.x() - aViewSize.x(), 0);
}
if ((mySubviewCorner & Aspect_TOTP_TOP) != 0)
{
mySubviewTopLeft.y() = anOffset.y();
}
else if ((mySubviewCorner & Aspect_TOTP_BOTTOM) != 0)
{
mySubviewTopLeft.y() = Max (aWinSize.y() - anOffset.y() - aViewSize.y(), 0);
}
mySubviewTopLeft += mySubviewMargins;
aViewSize -= mySubviewMargins * 2;
const int aRight = Min(mySubviewTopLeft.x() + aViewSize.x(), aWinSize.x());
aViewSize.x() = aRight - mySubviewTopLeft.x();
const int aBot = Min(mySubviewTopLeft.y() + aViewSize.y(), aWinSize.y());
aViewSize.y() = aBot - mySubviewTopLeft.y();
theWindow->SetSize (aViewSize.x(), aViewSize.y());
}
// ======================================================================== // ========================================================================
// function : SetComputedMode // function : SetComputedMode
// purpose : // purpose :

View File

@ -48,6 +48,7 @@
#include <Standard_Transient.hxx> #include <Standard_Transient.hxx>
#include <TColStd_IndexedDataMapOfStringString.hxx> #include <TColStd_IndexedDataMapOfStringString.hxx>
class Aspect_NeutralWindow;
class Aspect_XRSession; class Aspect_XRSession;
class Graphic3d_CView; class Graphic3d_CView;
class Graphic3d_Layer; class Graphic3d_Layer;
@ -239,7 +240,7 @@ public:
virtual Standard_Boolean IsInvalidated() = 0; virtual Standard_Boolean IsInvalidated() = 0;
//! Handle changing size of the rendering window. //! Handle changing size of the rendering window.
virtual void Resized() = 0; Standard_EXPORT virtual void Resized() = 0;
//! @param theDrawToFrontBuffer Advanced option to modify rendering mode: //! @param theDrawToFrontBuffer Advanced option to modify rendering mode:
//! 1. TRUE. Drawing immediate mode structures directly to the front buffer over the scene image. //! 1. TRUE. Drawing immediate mode structures directly to the front buffer over the scene image.
@ -256,10 +257,12 @@ public:
virtual Standard_Boolean SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) = 0; virtual Standard_Boolean SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) = 0;
//! Creates and maps rendering window to the view. //! Creates and maps rendering window to the view.
//! @param theWindow [in] the window. //! @param[in] theParentVIew parent view or NULL
//! @param theContext [in] the rendering context. If NULL the context will be created internally. //! @param[in] theWindow the window
virtual void SetWindow (const Handle(Aspect_Window)& theWindow, //! @param[in] theContext the rendering context; if NULL the context will be created internally
const Aspect_RenderingContext theContext = NULL) = 0; virtual void SetWindow (const Handle(Graphic3d_CView)& theParentVIew,
const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext) = 0;
//! Returns the window associated to the view. //! Returns the window associated to the view.
virtual Handle(Aspect_Window) Window() const = 0; virtual Handle(Aspect_Window) Window() const = 0;
@ -554,6 +557,70 @@ public: //! @name obsolete Graduated Trihedron functionality
//! Dumps the content of me into the stream //! Dumps the content of me into the stream
Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE; Standard_EXPORT virtual void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const Standard_OVERRIDE;
public: //! @name subview properties
//! Return TRUE if this is a subview of another view.
bool IsSubview() const { return myParentView != nullptr; }
//! Return parent View or NULL if this is not a subview.
Graphic3d_CView* ParentView() { return myParentView; }
//! Return TRUE if this is view performs rendering of subviews and nothing else; FALSE by default.
//! By default, view with subviews will render main scene and blit subviews on top of it.
//! Rendering of main scene might become redundant in case if subviews cover entire window of parent view.
//! This flag allows to disable rendering of the main scene in such scenarios
//! without creation of a dedicated V3d_Viewer instance just for composing subviews.
bool IsSubviewComposer() const { return myIsSubviewComposer; }
//! Set if this view should perform composing of subviews and nothing else.
void SetSubviewComposer (bool theIsComposer) { myIsSubviewComposer = theIsComposer; }
//! Return subview list.
const NCollection_Sequence<Handle(Graphic3d_CView)>& Subviews() const { return mySubviews; }
//! Add subview to the list.
Standard_EXPORT void AddSubview (const Handle(Graphic3d_CView)& theView);
//! Remove subview from the list.
Standard_EXPORT bool RemoveSubview (const Graphic3d_CView* theView);
//! Return subview position within parent view; Aspect_TOTP_LEFT_UPPER by default.
Aspect_TypeOfTriedronPosition SubviewCorner() const { return mySubviewCorner; }
//! Set subview position within parent view.
void SetSubviewCorner (Aspect_TypeOfTriedronPosition thePos) { mySubviewCorner = thePos; }
//! Return subview top-left position relative to parent view in pixels.
const Graphic3d_Vec2i& SubviewTopLeft() const { return mySubviewTopLeft; }
//! Return TRUE if subview size is set as proportions relative to parent view.
bool IsSubViewRelativeSize() const { return mySubviewSize.x() <= 1.0 && mySubviewSize.y() <= 1.0; }
//! Return subview dimensions; (1.0, 1.0) by default.
//! Values >= 2 define size in pixels;
//! Values <= 1.0 define size as fraction of parent view.
const Graphic3d_Vec2d& SubviewSize() const { return mySubviewSize; }
//! Set subview size relative to parent view.
void SetSubviewSize (const Graphic3d_Vec2d& theSize) { mySubviewSize = theSize; }
//! Return corner offset within parent view; (0.0,0.0) by default.
//! Values >= 2 define offset in pixels;
//! Values <= 1.0 define offset as fraction of parent view dimensions.
const Graphic3d_Vec2d& SubviewOffset() const { return mySubviewOffset; }
//! Set corner offset within parent view.
void SetSubviewOffset (const Graphic3d_Vec2d& theOffset) { mySubviewOffset = theOffset; }
//! Return subview margins in pixels; (0,0) by default
const Graphic3d_Vec2i& SubviewMargins() const { return mySubviewMargins; }
//! Set subview margins in pixels.
void SetSubviewMargins (const Graphic3d_Vec2i& theMargins) { mySubviewMargins = theMargins; }
//! Update subview position and dimensions.
Standard_EXPORT void SubviewResized (const Handle(Aspect_NeutralWindow)& theWindow);
private: private:
//! Adds the structure to display lists of the view. //! Adds the structure to display lists of the view.
@ -576,14 +643,14 @@ protected:
Standard_Integer myId; Standard_Integer myId;
Graphic3d_RenderingParams myRenderParams; Graphic3d_RenderingParams myRenderParams;
Quantity_ColorRGBA myBgColor; NCollection_Sequence<Handle(Graphic3d_CView)> mySubviews; //!< list of child views
Handle(Graphic3d_TextureMap) myBackgroundImage; Graphic3d_CView* myParentView; //!< back-pointer to the parent view
Handle(Graphic3d_CubeMap) myCubeMapBackground; //!< Cubemap displayed at background Standard_Boolean myIsSubviewComposer; //!< flag to skip rendering of viewer contents
Handle(Graphic3d_CubeMap) myCubeMapIBL; //!< Cubemap used for environment lighting Aspect_TypeOfTriedronPosition mySubviewCorner; //!< position within parent view
Handle(Graphic3d_TextureEnv) myTextureEnvData; Graphic3d_Vec2i mySubviewTopLeft; //!< subview top-left position relative to parent view
Graphic3d_TypeOfBackground myBackgroundType; //!< Current type of background Graphic3d_Vec2i mySubviewMargins; //!< subview margins in pixels
Aspect_SkydomeBackground mySkydomeAspect; Graphic3d_Vec2d mySubviewSize; //!< subview size
Standard_Boolean myToUpdateSkydome; Graphic3d_Vec2d mySubviewOffset; //!< subview corner offset within parent view
Handle(Graphic3d_StructureManager) myStructureManager; Handle(Graphic3d_StructureManager) myStructureManager;
Handle(Graphic3d_Camera) myCamera; Handle(Graphic3d_Camera) myCamera;
@ -597,6 +664,16 @@ protected:
Graphic3d_TypeOfBackfacingModel myBackfacing; Graphic3d_TypeOfBackfacingModel myBackfacing;
Graphic3d_TypeOfVisualization myVisualization; Graphic3d_TypeOfVisualization myVisualization;
Quantity_ColorRGBA myBgColor;
Handle(Graphic3d_TextureMap) myBackgroundImage;
Handle(Graphic3d_CubeMap) myCubeMapBackground; //!< Cubemap displayed at background
Handle(Graphic3d_CubeMap) myCubeMapIBL; //!< Cubemap used for environment lighting
Handle(Graphic3d_TextureEnv) myTextureEnvData;
Graphic3d_GraduatedTrihedron myGTrihedronData;
Graphic3d_TypeOfBackground myBackgroundType; //!< Current type of background
Aspect_SkydomeBackground mySkydomeAspect;
Standard_Boolean myToUpdateSkydome;
Handle(Aspect_XRSession) myXRSession; Handle(Aspect_XRSession) myXRSession;
Handle(Graphic3d_Camera) myBackXRCamera; //!< camera projection parameters to restore after closing XR session (FOV, aspect and similar) Handle(Graphic3d_Camera) myBackXRCamera; //!< camera projection parameters to restore after closing XR session (FOV, aspect and similar)
Handle(Graphic3d_Camera) myBaseXRCamera; //!< neutral camera orientation defining coordinate system in which head tracking is defined Handle(Graphic3d_Camera) myBaseXRCamera; //!< neutral camera orientation defining coordinate system in which head tracking is defined
@ -604,10 +681,6 @@ protected:
Handle(Graphic3d_Camera) myPosedXRCameraCopy; //!< neutral camera orientation copy at the beginning of processing input Handle(Graphic3d_Camera) myPosedXRCameraCopy; //!< neutral camera orientation copy at the beginning of processing input
Standard_Real myUnitFactor; //!< unit scale factor defined as scale factor for m (meters) Standard_Real myUnitFactor; //!< unit scale factor defined as scale factor for m (meters)
protected:
Graphic3d_GraduatedTrihedron myGTrihedronData;
}; };
#endif // _Graphic3d_CView_HeaderFile #endif // _Graphic3d_CView_HeaderFile

View File

@ -868,14 +868,16 @@ void OpenGl_GraphicDriver::RemoveView (const Handle(Graphic3d_CView)& theView)
} }
// ======================================================================= // =======================================================================
// function : Window // function : CreateRenderWindow
// purpose : // purpose :
// ======================================================================= // =======================================================================
Handle(OpenGl_Window) OpenGl_GraphicDriver::CreateRenderWindow (const Handle(Aspect_Window)& theWindow, Handle(OpenGl_Window) OpenGl_GraphicDriver::CreateRenderWindow (const Handle(Aspect_Window)& theNativeWindow,
const Handle(Aspect_Window)& theSizeWindow,
const Aspect_RenderingContext theContext) const Aspect_RenderingContext theContext)
{ {
Handle(OpenGl_Context) aShareCtx = GetSharedContext(); Handle(OpenGl_Context) aShareCtx = GetSharedContext();
Handle(OpenGl_Window) aWindow = new OpenGl_Window (this, theWindow, theContext, myCaps, aShareCtx); Handle(OpenGl_Window) aWindow = new OpenGl_Window();
aWindow->Init (this, theNativeWindow, theSizeWindow, theContext, myCaps, aShareCtx);
return aWindow; return aWindow;
} }

View File

@ -88,7 +88,13 @@ public:
Standard_EXPORT virtual void RemoveView (const Handle(Graphic3d_CView)& theView) Standard_OVERRIDE; Standard_EXPORT virtual void RemoveView (const Handle(Graphic3d_CView)& theView) Standard_OVERRIDE;
Standard_EXPORT virtual Handle(OpenGl_Window) CreateRenderWindow (const Handle(Aspect_Window)& theWindow, const Aspect_RenderingContext theContext); //! Create OpenGL window from native window.
//! @param[in] theNativeWindow native window holder
//! @param[in] theSizeWindow object defining window dimensions
//! @param[in] theContext existing native rendering context
Standard_EXPORT virtual Handle(OpenGl_Window) CreateRenderWindow (const Handle(Aspect_Window)& theNativeWindow,
const Handle(Aspect_Window)& theSizeWindow,
const Aspect_RenderingContext theContext);
public: public:

View File

@ -15,8 +15,8 @@
#include <OpenGl_View.hxx> #include <OpenGl_View.hxx>
#include <Aspect_NeutralWindow.hxx>
#include <Aspect_RenderingContext.hxx> #include <Aspect_RenderingContext.hxx>
#include <Aspect_Window.hxx>
#include <Aspect_XRSession.hxx> #include <Aspect_XRSession.hxx>
#include <Graphic3d_AspectFillArea3d.hxx> #include <Graphic3d_AspectFillArea3d.hxx>
#include <Graphic3d_Texture2Dmanual.hxx> #include <Graphic3d_Texture2Dmanual.hxx>
@ -366,20 +366,57 @@ Standard_Boolean OpenGl_View::SetImmediateModeDrawToFront (const Standard_Boolea
// ======================================================================= // =======================================================================
Handle(Aspect_Window) OpenGl_View::Window() const Handle(Aspect_Window) OpenGl_View::Window() const
{ {
return myWindow->PlatformWindow(); return myWindow->SizeWindow();
} }
// ======================================================================= // =======================================================================
// function : SetWindow // function : SetWindow
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow, void OpenGl_View::SetWindow (const Handle(Graphic3d_CView)& theParentVIew,
const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext) const Aspect_RenderingContext theContext)
{ {
myWindow = myDriver->CreateRenderWindow (theWindow, theContext); if (theContext != nullptr
Standard_ASSERT_RAISE (!myWindow.IsNull(), && !theParentVIew.IsNull())
"OpenGl_View::SetWindow, " {
"Failed to create OpenGl window."); throw Standard_ProgramError ("OpenGl_View::SetWindow(), internal error");
}
if (myParentView != nullptr)
{
myParentView->RemoveSubview (this);
myParentView = nullptr;
}
OpenGl_View* aParentView = dynamic_cast<OpenGl_View*> (theParentVIew.get());
if (!theParentVIew.IsNull())
{
if (aParentView == nullptr
|| aParentView->GlWindow().IsNull()
|| aParentView->GlWindow()->GetGlContext().IsNull())
{
throw Standard_ProgramError ("OpenGl_View::SetWindow(), internal error");
}
myParentView = aParentView;
myParentView->AddSubview (this);
Handle(Aspect_NeutralWindow) aSubWindow = Handle(Aspect_NeutralWindow)::DownCast(theWindow);
SubviewResized (aSubWindow);
const Handle(OpenGl_Window)& aParentGlWindow = aParentView->GlWindow();
Aspect_RenderingContext aRendCtx = aParentGlWindow->GetGlContext()->RenderingContext();
myWindow = myDriver->CreateRenderWindow (aParentGlWindow->PlatformWindow(), theWindow, aRendCtx);
}
else
{
myWindow = myDriver->CreateRenderWindow (theWindow, theWindow, theContext);
}
if (myWindow.IsNull())
{
throw Standard_ProgramError ("OpenGl_View::SetWindow, Failed to create OpenGl window");
}
myWorkspace = new OpenGl_Workspace (this, myWindow); myWorkspace = new OpenGl_Workspace (this, myWindow);
myWorldViewProjState.Reset(); myWorldViewProjState.Reset();
@ -414,10 +451,11 @@ void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow,
// ======================================================================= // =======================================================================
void OpenGl_View::Resized() void OpenGl_View::Resized()
{ {
if (myWindow.IsNull()) base_type::Resized();
return; if (!myWindow.IsNull())
{
myWindow->Resize(); myWindow->Resize();
}
} }
// ======================================================================= // =======================================================================
@ -1157,9 +1195,10 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
const bool hasTextureMsaa = aCtx->HasTextureMultisampling(); const bool hasTextureMsaa = aCtx->HasTextureMultisampling();
bool toUseOit = myRenderParams.TransparencyMethod != Graphic3d_RTM_BLEND_UNORDERED bool toUseOit = myRenderParams.TransparencyMethod != Graphic3d_RTM_BLEND_UNORDERED
&& !myIsSubviewComposer
&& checkOitCompatibility (aCtx, aNbSamples > 0); && checkOitCompatibility (aCtx, aNbSamples > 0);
const bool toInitImmediateFbo = myTransientDrawToFront const bool toInitImmediateFbo = myTransientDrawToFront && !myIsSubviewComposer
&& (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures())); && (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures()));
if ( aFrameBuffer == NULL if ( aFrameBuffer == NULL
@ -1662,7 +1701,7 @@ void OpenGl_View::Redraw()
OpenGl_FrameBuffer* aFrameBuffer = myFBO.get(); OpenGl_FrameBuffer* aFrameBuffer = myFBO.get();
bool toSwap = aCtx->IsRender() bool toSwap = aCtx->IsRender()
&& !aCtx->caps->buffersNoSwap && !aCtx->caps->buffersNoSwap
&& aFrameBuffer == NULL && aFrameBuffer == nullptr
&& (!IsActiveXR() || myRenderParams.ToMirrorComposer); && (!IsActiveXR() || myRenderParams.ToMirrorComposer);
if ( aFrameBuffer == NULL if ( aFrameBuffer == NULL
&& !aCtx->DefaultFrameBuffer().IsNull() && !aCtx->DefaultFrameBuffer().IsNull()
@ -1738,7 +1777,9 @@ void OpenGl_View::Redraw()
{ {
toSwap = false; toSwap = false;
} }
else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap) else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
&& toSwap
&& myParentView == nullptr)
{ {
aCtx->SwapBuffers(); aCtx->SwapBuffers();
} }
@ -1863,7 +1904,8 @@ void OpenGl_View::Redraw()
} }
// Swap the buffers // Swap the buffers
if (toSwap) if (toSwap
&& myParentView == nullptr)
{ {
aCtx->SwapBuffers(); aCtx->SwapBuffers();
if (!myMainSceneFbos[0]->IsValid()) if (!myMainSceneFbos[0]->IsValid())
@ -1969,8 +2011,9 @@ void OpenGl_View::RedrawImmediate()
Standard_True) || toSwap; Standard_True) || toSwap;
if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
&& toSwap && toSwap
&& myFBO.get() == NULL && myFBO.get() == nullptr
&& !aCtx->caps->buffersNoSwap) && !aCtx->caps->buffersNoSwap
&& myParentView == nullptr)
{ {
aCtx->SwapBuffers(); aCtx->SwapBuffers();
} }
@ -2035,7 +2078,8 @@ void OpenGl_View::RedrawImmediate()
if (toSwap if (toSwap
&& myFBO.get() == NULL && myFBO.get() == NULL
&& !aCtx->caps->buffersNoSwap) && !aCtx->caps->buffersNoSwap
&& myParentView == nullptr)
{ {
aCtx->SwapBuffers(); aCtx->SwapBuffers();
} }
@ -2159,9 +2203,91 @@ bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProject
render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True); render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True);
blitSubviews (theProjection, theDrawFbo);
return !toCopyBackToFront; return !toCopyBackToFront;
} }
// =======================================================================
// function : blitSubviews
// purpose :
// =======================================================================
bool OpenGl_View::blitSubviews (const Graphic3d_Camera::Projection ,
OpenGl_FrameBuffer* theDrawFbo)
{
const Handle(OpenGl_Context)& aCtx = myWorkspace->GetGlContext();
if (aCtx->arbFBOBlit == nullptr)
{
return false;
}
bool isChanged = false;
for (const Handle(Graphic3d_CView)& aChildIter : mySubviews)
{
OpenGl_View* aSubView = dynamic_cast<OpenGl_View*> (aChildIter.get());
const Handle(OpenGl_FrameBuffer)& aChildFbo = !aSubView->myImmediateSceneFbos[0].IsNull()
? aSubView->myImmediateSceneFbos[0]
: aSubView->myMainSceneFbos[0];
if (aChildFbo.IsNull() || !aChildFbo->IsValid())
{
continue;
}
aChildFbo->BindReadBuffer (aCtx);
if (theDrawFbo != NULL
&& theDrawFbo->IsValid())
{
theDrawFbo->BindDrawBuffer (aCtx);
}
else
{
aCtx->arbFBO->glBindFramebuffer (GL_DRAW_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
aCtx->SetFrameBufferSRGB (false);
}
Graphic3d_Vec2i aWinSize (aCtx->Viewport()[2], aCtx->Viewport()[3]); //aSubView->GlWindow()->PlatformWindow()->Dimensions();
Graphic3d_Vec2i aSubViewSize = aChildFbo->GetVPSize();
Graphic3d_Vec2i aSubViewPos = aSubView->SubviewTopLeft();
Graphic3d_Vec2i aDestSize = aSubViewSize;
if (aSubView->RenderingParams().RenderResolutionScale != 1.0f)
{
aDestSize = Graphic3d_Vec2i (Graphic3d_Vec2d(aDestSize) / Graphic3d_Vec2d(aSubView->RenderingParams().RenderResolutionScale));
}
aSubViewPos.y() = aWinSize.y() - aDestSize.y() - aSubViewPos.y();
const GLint aFilterGl = aDestSize == aSubViewSize ? GL_NEAREST : GL_LINEAR;
aCtx->arbFBOBlit->glBlitFramebuffer (0, 0, aSubViewSize.x(), aSubViewSize.y(),
aSubViewPos.x(), aSubViewPos.y(), aSubViewPos.x() + aDestSize.x(), aSubViewPos.y() + aDestSize.y(),
GL_COLOR_BUFFER_BIT, aFilterGl);
const int anErr = aCtx->core11fwd->glGetError();
if (anErr != GL_NO_ERROR)
{
TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "FBO blitting has failed [Error " + OpenGl_Context::FormatGlError (anErr) + "]\n"
+ " Please check your graphics driver settings or try updating driver.";
if (aChildFbo->NbSamples() != 0)
{
myToDisableMSAA = true;
aMsg += "\n MSAA settings should not be overridden by driver!";
}
aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
}
if (theDrawFbo != NULL
&& theDrawFbo->IsValid())
{
theDrawFbo->BindBuffer (aCtx);
}
else
{
aCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
aCtx->SetFrameBufferSRGB (false);
}
isChanged = true;
}
return isChanged;
}
//======================================================================= //=======================================================================
//function : renderShadowMap //function : renderShadowMap
//purpose : //purpose :
@ -2409,9 +2535,16 @@ void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
OpenGl_FrameBuffer* theOitAccumFbo, OpenGl_FrameBuffer* theOitAccumFbo,
const Standard_Boolean theToDrawImmediate) const Standard_Boolean theToDrawImmediate)
{ {
myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate); if (myIsSubviewComposer)
if ( myZLayers.NbStructures() <= 0 ) {
return; return;
}
myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate);
if (myZLayers.NbStructures() <= 0)
{
return;
}
Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext(); Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
Standard_Boolean toRenderGL = theToDrawImmediate || Standard_Boolean toRenderGL = theToDrawImmediate ||

View File

@ -85,9 +85,8 @@ public:
Standard_EXPORT Standard_Boolean SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) Standard_OVERRIDE; Standard_EXPORT Standard_Boolean SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) Standard_OVERRIDE;
//! Creates and maps rendering window to the view. //! Creates and maps rendering window to the view.
//! @param theWindow [in] the window. Standard_EXPORT virtual void SetWindow (const Handle(Graphic3d_CView)& theParentVIew,
//! @param theContext [in] the rendering context. If NULL the context will be created internally. const Handle(Aspect_Window)& theWindow,
Standard_EXPORT virtual void SetWindow (const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext) Standard_OVERRIDE; const Aspect_RenderingContext theContext) Standard_OVERRIDE;
//! Returns window associated with the view. //! Returns window associated with the view.
@ -345,6 +344,10 @@ protected: //! @name low-level redrawing sub-routines
OpenGl_FrameBuffer* theOitAccumFbo, OpenGl_FrameBuffer* theOitAccumFbo,
const Standard_Boolean theIsPartialUpdate = Standard_False); const Standard_Boolean theIsPartialUpdate = Standard_False);
//! Blit subviews into this view.
Standard_EXPORT bool blitSubviews (const Graphic3d_Camera::Projection theProjection,
OpenGl_FrameBuffer* theDrawFbo);
//! Blit image from/to specified buffers. //! Blit image from/to specified buffers.
Standard_EXPORT bool blitBuffers (OpenGl_FrameBuffer* theReadFbo, Standard_EXPORT bool blitBuffers (OpenGl_FrameBuffer* theReadFbo,
OpenGl_FrameBuffer* theDrawFbo, OpenGl_FrameBuffer* theDrawFbo,

View File

@ -169,17 +169,31 @@ namespace
// function : OpenGl_Window // function : OpenGl_Window
// purpose : // purpose :
// ======================================================================= // =======================================================================
OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver, OpenGl_Window::OpenGl_Window()
const Handle(Aspect_Window)& thePlatformWindow, : myOwnGContext (false),
Aspect_RenderingContext theGContext, mySwapInterval (0)
const Handle(OpenGl_Caps)& theCaps,
const Handle(OpenGl_Context)& theShareCtx)
: myGlContext (new OpenGl_Context (theCaps)),
myOwnGContext (theGContext == 0),
myPlatformWindow (thePlatformWindow),
mySwapInterval (theCaps->swapInterval)
{ {
myPlatformWindow->Size (myWidth, myHeight); //
}
// =======================================================================
// function : Init
// purpose :
// =======================================================================
void OpenGl_Window::Init (const Handle(OpenGl_GraphicDriver)& theDriver,
const Handle(Aspect_Window)& thePlatformWindow,
const Handle(Aspect_Window)& theSizeWindow,
Aspect_RenderingContext theGContext,
const Handle(OpenGl_Caps)& theCaps,
const Handle(OpenGl_Context)& theShareCtx)
{
myGlContext = new OpenGl_Context (theCaps);
myOwnGContext = (theGContext == 0);
myPlatformWindow = thePlatformWindow;
mySizeWindow = theSizeWindow;
mySwapInterval = theCaps->swapInterval;
mySizeWindow->Size (mySize.x(), mySize.y());
Standard_Boolean isCoreProfile = Standard_False; Standard_Boolean isCoreProfile = Standard_False;
@ -193,7 +207,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
&& (EGLContext )theGContext == EGL_NO_CONTEXT)) && (EGLContext )theGContext == EGL_NO_CONTEXT))
{ {
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!"); throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
return;
} }
EGLSurface anEglSurf = EGL_NO_SURFACE; EGLSurface anEglSurf = EGL_NO_SURFACE;
@ -225,8 +238,8 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
#if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
const int aSurfAttribs[] = const int aSurfAttribs[] =
{ {
EGL_WIDTH, myWidth, EGL_WIDTH, mySize.x(),
EGL_HEIGHT, myHeight, EGL_HEIGHT, mySize.y(),
// EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
//EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR, //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
EGL_NONE EGL_NONE
@ -258,8 +271,8 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
#if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL #if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
const int aSurfAttribs[] = const int aSurfAttribs[] =
{ {
EGL_WIDTH, myWidth, EGL_WIDTH, mySize.x(),
EGL_HEIGHT, myHeight, EGL_HEIGHT, mySize.y(),
// EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer // EGL_KHR_gl_colorspace extension specifies if OpenGL should write into window buffer as into sRGB or RGB framebuffer
//EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR, //EGL_GL_COLORSPACE_KHR, !theCaps->sRGBDisable ? EGL_GL_COLORSPACE_SRGB_KHR : EGL_GL_COLORSPACE_LINEAR_KHR,
EGL_NONE EGL_NONE
@ -322,7 +335,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: "); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
aMsg += (int )GetLastError(); aMsg += (int )GetLastError();
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
} }
DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt); DescribePixelFormat (aWindowDC, aPixelFrmtId, sizeof(aPixelFrmt), &aPixelFrmt);
@ -435,7 +447,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: "); TCollection_AsciiString aMsg("OpenGl_Window::CreateWindow: SetPixelFormat failed. Error code: ");
aMsg += (int )GetLastError(); aMsg += (int )GetLastError();
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
} }
// create GL context with extra options // create GL context with extra options
@ -526,7 +537,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: "); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglCreateContext failed. Error code: ");
aMsg += (int )GetLastError(); aMsg += (int )GetLastError();
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
} }
} }
@ -536,7 +546,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: "); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: wglShareLists failed. Error code: ");
aMsg += (int )GetLastError(); aMsg += (int )GetLastError();
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
} }
myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext, isCoreProfile); myGlContext->Init ((Aspect_Handle )aWindow, (Aspect_Handle )aWindowDC, (Aspect_RenderingContext )aGContext, isCoreProfile);
@ -557,12 +566,10 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
if (aVis.get() == NULL) if (aVis.get() == NULL)
{ {
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: XGetVisualInfo is unable to choose needed configuration in existing OpenGL context. "); throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: XGetVisualInfo is unable to choose needed configuration in existing OpenGL context. ");
return;
} }
else if (glXGetConfig (aDisp, aVis.get(), GLX_USE_GL, &isGl) != 0 || !isGl) else if (glXGetConfig (aDisp, aVis.get(), GLX_USE_GL, &isGl) != 0 || !isGl)
{ {
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!"); throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!");
return;
} }
// create new context // create new context
@ -635,7 +642,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
if (aGContext == NULL) if (aGContext == NULL)
{ {
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed."); throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed.");
return;
} }
} }
@ -675,7 +681,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
#endif #endif
myGlContext->Share (theShareCtx); myGlContext->Share (theShareCtx);
myGlContext->SetSwapInterval (mySwapInterval); myGlContext->SetSwapInterval (mySwapInterval);
Init(); init();
} }
// ======================================================================= // =======================================================================
@ -758,29 +764,29 @@ Standard_Boolean OpenGl_Window::Activate()
// ======================================================================= // =======================================================================
void OpenGl_Window::Resize() void OpenGl_Window::Resize()
{ {
Standard_Integer aWidth = 0, aHeight = 0; Graphic3d_Vec2i aWinSize;
myPlatformWindow->Size (aWidth, aHeight); mySizeWindow->Size (aWinSize.x(), aWinSize.y());
if (myWidth == aWidth if (mySize == aWinSize)
&& myHeight == aHeight)
{ {
// if the size is not changed - do nothing // if the size is not changed - do nothing
return; return;
} }
myWidth = aWidth; mySize = aWinSize;
myHeight = aHeight;
Init(); init();
} }
// ======================================================================= // =======================================================================
// function : Init // function : init
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_Window::Init() void OpenGl_Window::init()
{ {
if (!Activate()) if (!Activate())
{
return; return;
}
#if defined(HAVE_EGL) #if defined(HAVE_EGL)
if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE) if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
@ -800,7 +806,7 @@ void OpenGl_Window::Init()
OpenGl_ColorFormats aColorFormats; OpenGl_ColorFormats aColorFormats;
aColorFormats.Append (GL_RGBA8); aColorFormats.Append (GL_RGBA8);
if (!aDefFbo->InitRenderBuffer (myGlContext, Graphic3d_Vec2i (myWidth, myHeight), aColorFormats, GL_DEPTH24_STENCIL8)) if (!aDefFbo->InitRenderBuffer (myGlContext, mySize, aColorFormats, GL_DEPTH24_STENCIL8))
{ {
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed"); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
@ -810,8 +816,8 @@ void OpenGl_Window::Init()
} }
else if (!myPlatformWindow->IsVirtual()) else if (!myPlatformWindow->IsVirtual())
{ {
eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth); eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &mySize.x());
eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight); eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &mySize.y());
} }
#else #else
// //
@ -819,7 +825,7 @@ void OpenGl_Window::Init()
myGlContext->core11fwd->glDisable (GL_DITHER); myGlContext->core11fwd->glDisable (GL_DITHER);
myGlContext->core11fwd->glDisable (GL_SCISSOR_TEST); myGlContext->core11fwd->glDisable (GL_SCISSOR_TEST);
const Standard_Integer aViewport[4] = { 0, 0, myWidth, myHeight }; const Standard_Integer aViewport[4] = { 0, 0, mySize.x(), mySize.y() };
myGlContext->ResizeViewport (aViewport); myGlContext->ResizeViewport (aViewport);
myGlContext->SetDrawBuffer (GL_BACK); myGlContext->SetDrawBuffer (GL_BACK);
if (myGlContext->core11ffp != NULL) if (myGlContext->core11ffp != NULL)

View File

@ -37,21 +37,26 @@
class OpenGl_Context; class OpenGl_Context;
class OpenGl_GraphicDriver; class OpenGl_GraphicDriver;
class OpenGl_Window;
DEFINE_STANDARD_HANDLE(OpenGl_Window,Standard_Transient) DEFINE_STANDARD_HANDLE(OpenGl_Window,Standard_Transient)
//! This class represents low-level wrapper over window with GL context. //! This class represents low-level wrapper over window with GL context.
//! The window itself should be provided to constructor. //! The window itself should be provided to constructor.
class OpenGl_Window : public Standard_Transient class OpenGl_Window : public Standard_Transient
{ {
DEFINE_STANDARD_RTTIEXT(OpenGl_Window, Standard_Transient)
public: public:
//! Main constructor - prepare GL context for specified window. //! Empty constructor.
Standard_EXPORT OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver, Standard_EXPORT OpenGl_Window();
const Handle(Aspect_Window)& thePlatformWindow,
Aspect_RenderingContext theGContext, //! Initialize the new window - prepare GL context for specified window.
const Handle(OpenGl_Caps)& theCaps, //! Throws exception in case of failure.
const Handle(OpenGl_Context)& theShareCtx); Standard_EXPORT void Init (const Handle(OpenGl_GraphicDriver)& theDriver,
const Handle(Aspect_Window)& thePlatformWindow,
const Handle(Aspect_Window)& theSizeWindow,
Aspect_RenderingContext theGContext,
const Handle(OpenGl_Caps)& theCaps,
const Handle(OpenGl_Context)& theShareCtx);
//! Destructor //! Destructor
Standard_EXPORT virtual ~OpenGl_Window(); Standard_EXPORT virtual ~OpenGl_Window();
@ -59,44 +64,45 @@ public:
//! Resizes the window. //! Resizes the window.
Standard_EXPORT virtual void Resize(); Standard_EXPORT virtual void Resize();
Handle(Aspect_Window) PlatformWindow() { return myPlatformWindow; } //! Return platform window.
const Handle(Aspect_Window)& PlatformWindow() { return myPlatformWindow; }
Standard_Integer Width() const { return myWidth; } //! Return window object defining dimensions.
Standard_Integer Height() const { return myHeight; } const Handle(Aspect_Window)& SizeWindow() { return mySizeWindow; }
Standard_Integer Width() const { return mySize.x(); }
Standard_Integer Height() const { return mySize.y(); }
//! Return OpenGL context.
const Handle(OpenGl_Context)& GetGlContext() const { return myGlContext; } const Handle(OpenGl_Context)& GetGlContext() const { return myGlContext; }
//! Activates GL context and setup viewport.
Standard_EXPORT void Init();
//! Makes GL context for this window active in current thread //! Makes GL context for this window active in current thread
Standard_EXPORT virtual Standard_Boolean Activate(); Standard_EXPORT virtual Standard_Boolean Activate();
//! Sets swap interval for this window according to the context's settings. //! Sets swap interval for this window according to the context's settings.
Standard_EXPORT void SetSwapInterval (Standard_Boolean theToForceNoSync); Standard_EXPORT void SetSwapInterval (Standard_Boolean theToForceNoSync);
protected:
//! Activates GL context and setup viewport.
Standard_EXPORT void init();
protected: protected:
Handle(OpenGl_Context) myGlContext; Handle(OpenGl_Context) myGlContext;
Standard_Boolean myOwnGContext; //!< set to TRUE if GL context was not created by this class Standard_Boolean myOwnGContext; //!< set to TRUE if GL context was not created by this class
Handle(Aspect_Window) myPlatformWindow; //!< software platform window wrapper Handle(Aspect_Window) myPlatformWindow; //!< software platform window wrapper
Handle(Aspect_Window) mySizeWindow; //!< window object defining dimensions
#if defined(__APPLE__) #if defined(__APPLE__)
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
UIView* myUIView; UIView* myUIView;
#endif #endif
Standard_Integer myWidthPt; //!< window width in logical units Graphic3d_Vec2i mySizePt; //!< window width x height in logical units
Standard_Integer myHeightPt; //!< window height in logical units
#endif #endif
Standard_Integer myWidth; //!< window width in pixels Graphic3d_Vec2i mySize; //!< window width x height in pixels
Standard_Integer myHeight; //!< window height in pixels
Standard_Integer mySwapInterval;//!< last assigned swap interval (VSync) for this window Standard_Integer mySwapInterval;//!< last assigned swap interval (VSync) for this window
public:
DEFINE_STANDARD_RTTIEXT(OpenGl_Window,Standard_Transient) // Type definition
DEFINE_STANDARD_ALLOC
}; };
#endif //_OpenGl_Window_Header #endif //_OpenGl_Window_Header

View File

@ -56,25 +56,38 @@
// function : OpenGl_Window // function : OpenGl_Window
// purpose : // purpose :
// ======================================================================= // =======================================================================
OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver, OpenGl_Window::OpenGl_Window()
const Handle(Aspect_Window)& thePlatformWindow, : myOwnGContext (false),
Aspect_RenderingContext theGContext, mySwapInterval (0)
const Handle(OpenGl_Caps)& theCaps,
const Handle(OpenGl_Context)& theShareCtx)
: myGlContext (new OpenGl_Context (theCaps)),
myOwnGContext (theGContext == 0),
myPlatformWindow (thePlatformWindow),
#if defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
myUIView (NULL),
#endif
mySwapInterval (theCaps->swapInterval)
{ {
//
}
// =======================================================================
// function : Init
// purpose :
// =======================================================================
void OpenGl_Window::Init (const Handle(OpenGl_GraphicDriver)& theDriver,
const Handle(Aspect_Window)& thePlatformWindow,
const Handle(Aspect_Window)& theSizeWindow,
Aspect_RenderingContext theGContext,
const Handle(OpenGl_Caps)& theCaps,
const Handle(OpenGl_Context)& theShareCtx)
{
myGlContext = new OpenGl_Context (theCaps);
myOwnGContext = (theGContext == 0);
myPlatformWindow = thePlatformWindow;
mySizeWindow = theSizeWindow;
#if defined(__APPLE__) && defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
myUIView = NULL;
#endif
mySwapInterval = theCaps->swapInterval;
(void )theDriver; (void )theDriver;
myPlatformWindow->Size (myWidth, myHeight); mySizeWindow->Size (mySize.x(), mySize.y());
#if defined(__APPLE__) #if defined(__APPLE__)
myWidthPt = myWidth; mySizePt = mySize;
myHeightPt = myHeight;
#endif #endif
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
@ -102,7 +115,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
{ {
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: EAGLContext creation failed"); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: EAGLContext creation failed");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
} }
} }
@ -114,7 +126,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
{ {
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: EAGLContext can not be assigned"); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: EAGLContext can not be assigned");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
} }
myGlContext->Init (aGLContext, Standard_False); myGlContext->Init (aGLContext, Standard_False);
@ -199,7 +210,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
{ {
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: NSOpenGLContext creation failed"); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: NSOpenGLContext creation failed");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
} }
if (aTryStereo == 0 if (aTryStereo == 0
@ -227,7 +237,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
myGlContext->Share (theShareCtx); myGlContext->Share (theShareCtx);
myGlContext->SetSwapInterval (mySwapInterval); myGlContext->SetSwapInterval (mySwapInterval);
Init(); init();
} }
// ======================================================================= // =======================================================================
@ -266,9 +276,9 @@ void OpenGl_Window::Resize()
// If the size is not changed - do nothing // If the size is not changed - do nothing
Standard_Integer aWidthPt = 0; Standard_Integer aWidthPt = 0;
Standard_Integer aHeightPt = 0; Standard_Integer aHeightPt = 0;
myPlatformWindow->Size (aWidthPt, aHeightPt); mySizeWindow->Size (aWidthPt, aHeightPt);
if (myWidthPt == aWidthPt if (mySizePt.x() == aWidthPt
&& myHeightPt == aHeightPt) && mySizePt.y() == aHeightPt)
{ {
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
return; return;
@ -285,25 +295,25 @@ void OpenGl_Window::Resize()
NSRect aBounds = [aView bounds]; NSRect aBounds = [aView bounds];
NSSize aRes = [aView convertSizeToBacking: aBounds.size]; NSSize aRes = [aView convertSizeToBacking: aBounds.size];
if (myWidth == Standard_Integer(aRes.width) if (mySize.x() == Standard_Integer(aRes.width)
&& myHeight == Standard_Integer(aRes.height)) && mySize.y() == Standard_Integer(aRes.height))
{ {
return; return;
} }
#endif #endif
} }
myWidthPt = aWidthPt; mySizePt.x() = aWidthPt;
myHeightPt = aHeightPt; mySizePt.y() = aHeightPt;
Init(); init();
} }
// ======================================================================= // =======================================================================
// function : Init // function : init
// purpose : // purpose :
// ======================================================================= // =======================================================================
void OpenGl_Window::Init() void OpenGl_Window::init()
{ {
if (!Activate()) if (!Activate())
{ {
@ -329,11 +339,11 @@ void OpenGl_Window::Init()
myGlContext->Functions()->glGenRenderbuffers (1, &aWinRBColor); myGlContext->Functions()->glGenRenderbuffers (1, &aWinRBColor);
myGlContext->Functions()->glBindRenderbuffer (GL_RENDERBUFFER, aWinRBColor); myGlContext->Functions()->glBindRenderbuffer (GL_RENDERBUFFER, aWinRBColor);
[aGLCtx renderbufferStorage: GL_RENDERBUFFER fromDrawable: anEaglLayer]; [aGLCtx renderbufferStorage: GL_RENDERBUFFER fromDrawable: anEaglLayer];
myGlContext->Functions()->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &myWidth); myGlContext->Functions()->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &mySize.x());
myGlContext->Functions()->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &myHeight); myGlContext->Functions()->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &mySize.y());
myGlContext->Functions()->glBindRenderbuffer (GL_RENDERBUFFER, 0); myGlContext->Functions()->glBindRenderbuffer (GL_RENDERBUFFER, 0);
if (!aDefFbo->InitWithRB (myGlContext, Graphic3d_Vec2i (myWidth, myHeight), GL_RGBA8, GL_DEPTH24_STENCIL8, aWinRBColor)) if (!aDefFbo->InitWithRB (myGlContext, mySize, GL_RGBA8, GL_DEPTH24_STENCIL8, aWinRBColor))
{ {
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed"); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
@ -349,8 +359,8 @@ void OpenGl_Window::Init()
return; return;
} }
myWidth = aDefFbo->GetVPSizeX(); mySize.x() = aDefFbo->GetVPSizeX();
myHeight = aDefFbo->GetVPSizeY(); mySize.y() = aDefFbo->GetVPSizeY();
} }
myGlContext->SetDefaultFrameBuffer (aDefFbo); myGlContext->SetDefaultFrameBuffer (aDefFbo);
aDefFbo->BindBuffer (myGlContext); aDefFbo->BindBuffer (myGlContext);
@ -368,21 +378,21 @@ Standard_ENABLE_DEPRECATION_WARNINGS
if ([aView respondsToSelector: @selector(convertSizeToBacking:)]) if ([aView respondsToSelector: @selector(convertSizeToBacking:)])
{ {
NSSize aRes = [aView convertSizeToBacking: aBounds.size]; NSSize aRes = [aView convertSizeToBacking: aBounds.size];
myWidth = Standard_Integer(aRes.width); mySize.x() = Standard_Integer(aRes.width);
myHeight = Standard_Integer(aRes.height); mySize.y() = Standard_Integer(aRes.height);
} }
else else
{ {
myWidth = Standard_Integer(aBounds.size.width); mySize.x() = Standard_Integer(aBounds.size.width);
myHeight = Standard_Integer(aBounds.size.height); mySize.y() = Standard_Integer(aBounds.size.height);
} }
myWidthPt = Standard_Integer(aBounds.size.width); mySizePt.x() = Standard_Integer(aBounds.size.width);
myHeightPt = Standard_Integer(aBounds.size.height); mySizePt.y() = Standard_Integer(aBounds.size.height);
#endif #endif
myGlContext->core11fwd->glDisable (GL_DITHER); myGlContext->core11fwd->glDisable (GL_DITHER);
myGlContext->core11fwd->glDisable (GL_SCISSOR_TEST); myGlContext->core11fwd->glDisable (GL_SCISSOR_TEST);
myGlContext->core11fwd->glViewport (0, 0, myWidth, myHeight); myGlContext->core11fwd->glViewport (0, 0, mySize.x(), mySize.y());
if (myGlContext->GraphicsLibrary() != Aspect_GraphicsLibrary_OpenGLES) if (myGlContext->GraphicsLibrary() != Aspect_GraphicsLibrary_OpenGLES)
{ {
myGlContext->core11fwd->glDrawBuffer (GL_BACK); myGlContext->core11fwd->glDrawBuffer (GL_BACK);

View File

@ -16,6 +16,7 @@
#include <Aspect_CircularGrid.hxx> #include <Aspect_CircularGrid.hxx>
#include <Aspect_GradientBackground.hxx> #include <Aspect_GradientBackground.hxx>
#include <Aspect_Grid.hxx> #include <Aspect_Grid.hxx>
#include <Aspect_NeutralWindow.hxx>
#include <Aspect_RectangularGrid.hxx> #include <Aspect_RectangularGrid.hxx>
#include <Aspect_Window.hxx> #include <Aspect_Window.hxx>
#include <Bnd_Box.hxx> #include <Bnd_Box.hxx>
@ -142,6 +143,27 @@ V3d_View::V3d_View (const Handle(V3d_Viewer)& theViewer, const Handle(V3d_View)&
//============================================================================= //=============================================================================
V3d_View::~V3d_View() V3d_View::~V3d_View()
{ {
if (myParentView != nullptr)
{
myParentView->RemoveSubview (this);
myParentView = nullptr;
}
{
NCollection_Sequence<Handle(V3d_View)> aSubviews = mySubviews;
mySubviews.Clear();
for (const Handle(V3d_View)& aViewIter : aSubviews)
{
//aViewIter->Remove();
aViewIter->myParentView = nullptr;
aViewIter->MyWindow.Nullify();
aViewIter->myView->Remove();
if (aViewIter->MyViewer != nullptr)
{
aViewIter->MyViewer->SetViewOff (aViewIter);
}
}
}
if (!myView->IsRemoved()) if (!myView->IsRemoved())
{ {
myView->Remove(); myView->Remove();
@ -164,7 +186,7 @@ void V3d_View::SetMagnify (const Handle(Aspect_Window)& theWindow,
Standard_Real aU1, aV1, aU2, aV2; Standard_Real aU1, aV1, aU2, aV2;
thePreviousView->Convert (theX1, theY1, aU1, aV1); thePreviousView->Convert (theX1, theY1, aU1, aV1);
thePreviousView->Convert (theX2, theY2, aU2, aV2); thePreviousView->Convert (theX2, theY2, aU2, aV2);
myView->SetWindow (theWindow); myView->SetWindow (Handle(Graphic3d_CView)(), theWindow, nullptr);
FitAll (aU1, aV1, aU2, aV2); FitAll (aU1, aV1, aU2, aV2);
MyViewer->SetViewOn (this); MyViewer->SetViewOn (this);
MyWindow = theWindow; MyWindow = theWindow;
@ -185,10 +207,14 @@ void V3d_View::SetWindow (const Handle(Aspect_Window)& theWindow,
{ {
return; return;
} }
if (myParentView != nullptr)
{
throw Standard_ProgramError ("V3d_View::SetWindow() called twice");
}
// method V3d_View::SetWindow() should assign the field MyWindow before calling Redraw() // method V3d_View::SetWindow() should assign the field MyWindow before calling Redraw()
MyWindow = theWindow; MyWindow = theWindow;
myView->SetWindow (theWindow, theContext); myView->SetWindow (Handle(Graphic3d_CView)(), theWindow, theContext);
MyViewer->SetViewOn (this); MyViewer->SetViewOn (this);
SetRatio(); SetRatio();
if (myImmediateUpdate) if (myImmediateUpdate)
@ -197,6 +223,49 @@ void V3d_View::SetWindow (const Handle(Aspect_Window)& theWindow,
} }
} }
//=============================================================================
//function : SetWindow
//purpose :
//=============================================================================
void V3d_View::SetWindow (const Handle(V3d_View)& theParentView,
const Graphic3d_Vec2d& theSize,
Aspect_TypeOfTriedronPosition theCorner,
const Graphic3d_Vec2d& theOffset,
const Graphic3d_Vec2i& theMargins)
{
if (myView->IsRemoved())
{
return;
}
Handle(V3d_View) aParentView = !theParentView->IsSubview()
? theParentView
: theParentView->ParentView();
if (aParentView != myParentView)
{
if (myParentView != nullptr)
{
throw Standard_ProgramError ("V3d_View::SetWindow() called twice");
}
myParentView = aParentView.get();
aParentView->AddSubview (this);
}
Handle(Aspect_NeutralWindow) aWindow = new Aspect_NeutralWindow();
aWindow->SetVirtual (true);
aWindow->SetSize (4, 4);
myView->SetSubviewCorner (theCorner);
myView->SetSubviewSize (theSize);
myView->SetSubviewOffset (theOffset);
myView->SetSubviewMargins (theMargins);
MyWindow = aWindow;
myView->SetWindow (aParentView->View(), aWindow, 0);
MyViewer->SetViewOn (this);
SetRatio();
}
//============================================================================= //=============================================================================
//function : Remove //function : Remove
//purpose : //purpose :
@ -212,10 +281,83 @@ void V3d_View::Remove()
myTrihedron->Erase(); myTrihedron->Erase();
} }
MyViewer->DelView (this); if (myParentView != nullptr)
{
myParentView->RemoveSubview (this);
myParentView = nullptr;
}
{
NCollection_Sequence<Handle(V3d_View)> aSubviews = mySubviews;
mySubviews.Clear();
for (const Handle(V3d_View)& aViewIter : aSubviews)
{
aViewIter->Remove();
}
}
if (MyViewer != nullptr)
{
MyViewer->DelView (this);
MyViewer = nullptr;
}
myView->Remove(); myView->Remove();
Handle(Aspect_Window)& aWin = const_cast<Handle(Aspect_Window)&> (MyWindow); MyWindow.Nullify();
aWin.Nullify(); }
// =======================================================================
// function : AddSubview
// purpose :
// =======================================================================
void V3d_View::AddSubview (const Handle(V3d_View)& theView)
{
mySubviews.Append (theView);
}
// =======================================================================
// function : RemoveSubview
// purpose :
// =======================================================================
bool V3d_View::RemoveSubview (const V3d_View* theView)
{
for (NCollection_Sequence<Handle(V3d_View)>::Iterator aViewIter (mySubviews); aViewIter.More(); aViewIter.Next())
{
if (aViewIter.Value() == theView)
{
mySubviews.Remove (aViewIter);
return true;
}
}
return false;
}
// =============================================================================
// function : PickSubview
// purpose :
// =============================================================================
Handle(V3d_View) V3d_View::PickSubview (const Graphic3d_Vec2i& thePnt) const
{
if (thePnt.x() < 0
|| thePnt.x() >= MyWindow->Dimensions().x()
|| thePnt.y() < 0
|| thePnt.y() >= MyWindow->Dimensions().y())
{
return Handle(V3d_View)();
}
// iterate in opposite direction - from front to bottom views
for (Standard_Integer aSubviewIter = mySubviews.Upper(); aSubviewIter >= mySubviews.Lower(); --aSubviewIter)
{
const Handle(V3d_View)& aSubview = mySubviews.Value (aSubviewIter);
if (thePnt.x() >= aSubview->View()->SubviewTopLeft().x()
&& thePnt.x() < (aSubview->View()->SubviewTopLeft().x() + aSubview->Window()->Dimensions().x())
&& thePnt.y() >= aSubview->View()->SubviewTopLeft().y()
&& thePnt.y() < (aSubview->View()->SubviewTopLeft().y() + aSubview->Window()->Dimensions().y()))
{
return aSubview;
}
}
return this;
} }
//============================================================================= //=============================================================================

View File

@ -76,7 +76,7 @@ DEFINE_STANDARD_HANDLE(V3d_View, Standard_Transient)
//! View->Move(15.,-5.,0.,False) (Next motion) //! View->Move(15.,-5.,0.,False) (Next motion)
class V3d_View : public Standard_Transient class V3d_View : public Standard_Transient
{ {
DEFINE_STANDARD_RTTIEXT(V3d_View, Standard_Transient)
public: public:
//! Initializes the view. //! Initializes the view.
@ -97,6 +97,25 @@ public:
Standard_EXPORT void SetWindow (const Handle(Aspect_Window)& theWindow, Standard_EXPORT void SetWindow (const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext = NULL); const Aspect_RenderingContext theContext = NULL);
//! Activates the view as subview of another view.
//! @param[in] theParentView parent view to put subview into
//! @param[in] theSize subview dimensions;
//! values >= 2 define size in pixels,
//! values <= 1.0 define size as a fraction of parent view
//! @param[in] theCorner corner within parent view
//! @param[in] theOffset offset from the corner;
//! values >= 1 define offset in pixels,
//! values < 1.0 define offset as a fraction of parent view
//! @param[in] theMargins subview margins in pixels
//!
//! Example: to split parent view horizontally into 2 subview,
//! define one subview with Size=(0.5,1.0),Offset=(0.0,0.0), and 2nd with Size=(0.5,1.0),Offset=(5.0,0.0);
Standard_EXPORT void SetWindow (const Handle(V3d_View)& theParentView,
const Graphic3d_Vec2d& theSize,
Aspect_TypeOfTriedronPosition theCorner = Aspect_TOTP_LEFT_UPPER,
const Graphic3d_Vec2d& theOffset = Graphic3d_Vec2d(),
const Graphic3d_Vec2i& theMargins = Graphic3d_Vec2i());
Standard_EXPORT void SetMagnify (const Handle(Aspect_Window)& theWindow, Standard_EXPORT void SetMagnify (const Handle(Aspect_Window)& theWindow,
const Handle(V3d_View)& thePreviousView, const Handle(V3d_View)& thePreviousView,
const Standard_Integer theX1, const Standard_Integer theX1,
@ -953,7 +972,25 @@ public:
//! Dumps the content of me into the stream //! Dumps the content of me into the stream
Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const; Standard_EXPORT void DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth = -1) const;
DEFINE_STANDARD_RTTIEXT(V3d_View,Standard_Transient) public: //! @name subvew management
//! Return TRUE if this is a subview of another view.
bool IsSubview() const { return myParentView != nullptr; }
//! Return parent View or NULL if this is not a subview.
V3d_View* ParentView() { return myParentView; }
//! Return subview list.
const NCollection_Sequence<Handle(V3d_View)>& Subviews() const { return mySubviews; }
//! Pick subview from the given 2D point.
Standard_EXPORT Handle(V3d_View) PickSubview (const Graphic3d_Vec2i& thePnt) const;
//! Add subview to the list.
Standard_EXPORT void AddSubview (const Handle(V3d_View)& theView);
//! Remove subview from the list.
Standard_EXPORT bool RemoveSubview (const V3d_View* theView);
public: //! @name deprecated methods public: //! @name deprecated methods
@ -1033,6 +1070,10 @@ protected:
private: private:
V3d_Viewer* MyViewer; V3d_Viewer* MyViewer;
NCollection_Sequence<Handle(V3d_View)> mySubviews;
V3d_View* myParentView;
V3d_ListOfLight myActiveLights; V3d_ListOfLight myActiveLights;
gp_Dir myDefaultViewAxis; gp_Dir myDefaultViewAxis;
gp_Pnt myDefaultViewPoint; gp_Pnt myDefaultViewPoint;

View File

@ -143,9 +143,23 @@ void V3d_Viewer::SetViewOff (const Handle(V3d_View)& theView)
// ======================================================================== // ========================================================================
void V3d_Viewer::Redraw() const void V3d_Viewer::Redraw() const
{ {
for (V3d_ListOfView::Iterator aDefViewIter (myDefinedViews); aDefViewIter.More(); aDefViewIter.Next()) for (int aSubViewPass = 0; aSubViewPass < 2; ++aSubViewPass)
{ {
aDefViewIter.Value()->Redraw(); // redraw subviews first
const bool isSubViewPass = (aSubViewPass == 0);
for (const Handle(V3d_View)& aViewIter : myDefinedViews)
{
if (isSubViewPass
&& aViewIter->IsSubview())
{
aViewIter->Redraw();
}
else if (!isSubViewPass
&& !aViewIter->IsSubview())
{
aViewIter->Redraw();
}
}
} }
} }
@ -155,9 +169,23 @@ void V3d_Viewer::Redraw() const
// ======================================================================== // ========================================================================
void V3d_Viewer::RedrawImmediate() const void V3d_Viewer::RedrawImmediate() const
{ {
for (V3d_ListOfView::Iterator aDefViewIter (myDefinedViews); aDefViewIter.More(); aDefViewIter.Next()) for (int aSubViewPass = 0; aSubViewPass < 2; ++aSubViewPass)
{ {
aDefViewIter.Value()->RedrawImmediate(); // redraw subviews first
const bool isSubViewPass = (aSubViewPass == 0);
for (const Handle(V3d_View)& aViewIter : myDefinedViews)
{
if (isSubViewPass
&& aViewIter->IsSubview())
{
aViewIter->RedrawImmediate();
}
else if (!isSubViewPass
&& !aViewIter->IsSubview())
{
aViewIter->RedrawImmediate();
}
}
} }
} }
@ -232,10 +260,24 @@ void V3d_Viewer::AddView (const Handle(V3d_View)& theView)
// function : DelView // function : DelView
// purpose : // purpose :
// ======================================================================== // ========================================================================
void V3d_Viewer::DelView (const Handle(V3d_View)& theView) void V3d_Viewer::DelView (const V3d_View* theView)
{ {
myActiveViews.Remove (theView); for (V3d_ListOfView::Iterator aViewIter (myActiveViews); aViewIter.More(); aViewIter.Next())
myDefinedViews.Remove (theView); {
if (aViewIter.Value() == theView)
{
myActiveViews.Remove (aViewIter);
break;
}
}
for (V3d_ListOfView::Iterator aViewIter (myDefinedViews); aViewIter.More(); aViewIter.Next())
{
if (aViewIter.Value() == theView)
{
myDefinedViews.Remove (aViewIter);
break;
}
}
} }
//======================================================================= //=======================================================================

View File

@ -482,7 +482,7 @@ private:
Standard_EXPORT void AddView (const Handle(V3d_View)& theView); Standard_EXPORT void AddView (const Handle(V3d_View)& theView);
//! Delete View in Sequence Of Views. //! Delete View in Sequence Of Views.
Standard_EXPORT void DelView (const Handle(V3d_View)& theView); Standard_EXPORT void DelView (const V3d_View* theView);
private: private:

View File

@ -4776,11 +4776,14 @@ inline Standard_Boolean parseTrsfPersFlag (const TCollection_AsciiString& theFla
return Standard_True; return Standard_True;
} }
//! Auxiliary method to parse transformation persistence flags // =============================================================================
inline Standard_Boolean parseTrsfPersCorner (const TCollection_AsciiString& theString, // function : ParseCorner
Aspect_TypeOfTriedronPosition& theCorner) // purpose :
// =============================================================================
Standard_Boolean ViewerTest::ParseCorner (Standard_CString theArg,
Aspect_TypeOfTriedronPosition& theCorner)
{ {
TCollection_AsciiString aString (theString); TCollection_AsciiString aString (theArg);
aString.LowerCase(); aString.LowerCase();
if (aString == "center") if (aString == "center")
{ {
@ -4806,25 +4809,33 @@ inline Standard_Boolean parseTrsfPersCorner (const TCollection_AsciiString& theS
} }
else if (aString == "topleft" else if (aString == "topleft"
|| aString == "leftupper" || aString == "leftupper"
|| aString == "upperleft") || aString == "upperleft"
|| aString == "left_upper"
|| aString == "upper_left")
{ {
theCorner = Aspect_TOTP_LEFT_UPPER; theCorner = Aspect_TOTP_LEFT_UPPER;
} }
else if (aString == "bottomleft" else if (aString == "bottomleft"
|| aString == "leftlower" || aString == "leftlower"
|| aString == "lowerleft") || aString == "lowerleft"
|| aString == "left_lower"
|| aString == "lower_left")
{ {
theCorner = Aspect_TOTP_LEFT_LOWER; theCorner = Aspect_TOTP_LEFT_LOWER;
} }
else if (aString == "topright" else if (aString == "topright"
|| aString == "rightupper" || aString == "rightupper"
|| aString == "upperright") || aString == "upperright"
|| aString == "right_upper"
|| aString == "upper_right")
{ {
theCorner = Aspect_TOTP_RIGHT_UPPER; theCorner = Aspect_TOTP_RIGHT_UPPER;
} }
else if (aString == "bottomright" else if (aString == "bottomright"
|| aString == "lowerright" || aString == "lowerright"
|| aString == "rightlower") || aString == "rightlower"
|| aString == "right_lower"
|| aString == "lower_right")
{ {
theCorner = Aspect_TOTP_RIGHT_LOWER; theCorner = Aspect_TOTP_RIGHT_LOWER;
} }
@ -4964,7 +4975,7 @@ static int VDisplay2 (Draw_Interpretor& theDI,
if (anArgIter + 1 < theArgNb) if (anArgIter + 1 < theArgNb)
{ {
Aspect_TypeOfTriedronPosition aCorner = Aspect_TOTP_CENTER; Aspect_TypeOfTriedronPosition aCorner = Aspect_TOTP_CENTER;
if (parseTrsfPersCorner (theArgVec[anArgIter + 1], aCorner)) if (ViewerTest::ParseCorner (theArgVec[anArgIter + 1], aCorner))
{ {
++anArgIter; ++anArgIter;
aTrsfPers->SetCorner2d (aCorner); aTrsfPers->SetCorner2d (aCorner);

View File

@ -18,8 +18,10 @@
#include <AIS_KindOfInteractive.hxx> #include <AIS_KindOfInteractive.hxx>
#include <Aspect_TypeOfLine.hxx> #include <Aspect_TypeOfLine.hxx>
#include <Aspect_TypeOfMarker.hxx> #include <Aspect_TypeOfMarker.hxx>
#include <Aspect_TypeOfTriedronPosition.hxx>
#include <Draw_Interpretor.hxx> #include <Draw_Interpretor.hxx>
#include <Graphic3d_TypeOfShadingModel.hxx> #include <Graphic3d_TypeOfShadingModel.hxx>
#include <Graphic3d_Vec2.hxx>
#include <Graphic3d_ZLayerId.hxx> #include <Graphic3d_ZLayerId.hxx>
#include <TCollection_AsciiString.hxx> #include <TCollection_AsciiString.hxx>
#include <TColStd_HArray1OfTransient.hxx> #include <TColStd_HArray1OfTransient.hxx>
@ -36,6 +38,23 @@ class ViewerTest_EventManager;
class TopoDS_Shape; class TopoDS_Shape;
class WNT_WClass; class WNT_WClass;
//! Parameters for creating new view.
struct ViewerTest_VinitParams
{
TCollection_AsciiString ViewName;
TCollection_AsciiString DisplayName;
Handle(V3d_View) ViewToClone;
Handle(V3d_View) ParentView;
Graphic3d_Vec2d Offset;
Graphic3d_Vec2d Size;
Aspect_TypeOfTriedronPosition Corner;
Graphic3d_Vec2i SubviewMargins;
Standard_Boolean IsVirtual;
Standard_Boolean IsComposer;
ViewerTest_VinitParams() : Corner (Aspect_TOTP_LEFT_UPPER), IsVirtual (false), IsComposer (false) {}
};
class ViewerTest class ViewerTest
{ {
public: public:
@ -45,25 +64,39 @@ public:
//! Loads all Draw commands of V2d & V3d. Used for plugin. //! Loads all Draw commands of V2d & V3d. Used for plugin.
Standard_EXPORT static void Factory (Draw_Interpretor& theDI); Standard_EXPORT static void Factory (Draw_Interpretor& theDI);
//! Creates view with default or custom name
//! and adds this name in map to manage multiple views.
//! Creates view with default or custom name and adds this name in map to manage multiple views.
//! Implemented in ViewerTest_ViewerCommands.cxx. //! Implemented in ViewerTest_ViewerCommands.cxx.
//! @param thePxLeft left position of newly created window Standard_EXPORT static TCollection_AsciiString ViewerInit (const ViewerTest_VinitParams& theParams);
//! @param thePxTop top position of newly created window
//! @param thePxWidth width of newly created window //! Creates view.
//! @param thePxHeight height of newly created window static TCollection_AsciiString ViewerInit (const TCollection_AsciiString& theViewName = "")
//! @param theViewName name of newly created View {
//! @oaram theDisplayName display name ViewerTest_VinitParams aParams;
//! @param theViewToClone when specified, the new View will copy properties of existing one aParams.ViewName = theViewName;
//! @param theIsVirtual force creation of virtual off-screen window within interactive session return ViewerInit (aParams);
Standard_EXPORT static TCollection_AsciiString ViewerInit (const Standard_Integer thePxLeft = 0, }
const Standard_Integer thePxTop = 0,
const Standard_Integer thePxWidth = 0, //! Creates view.
const Standard_Integer thePxHeight = 0, static TCollection_AsciiString ViewerInit (const Standard_Integer thePxLeft,
const TCollection_AsciiString& theViewName = "", const Standard_Integer thePxTop,
const TCollection_AsciiString& theDisplayName = "", const Standard_Integer thePxWidth,
const Handle(V3d_View)& theViewToClone = Handle(V3d_View)(), const Standard_Integer thePxHeight,
const Standard_Boolean theIsVirtual = false); const TCollection_AsciiString& theViewName,
const TCollection_AsciiString& theDisplayName = "",
const Handle(V3d_View)& theViewToClone = Handle(V3d_View)(),
const Standard_Boolean theIsVirtual = false)
{
ViewerTest_VinitParams aParams;
aParams.Offset.SetValues ((float )thePxLeft, (float)thePxTop);
aParams.Size.SetValues ((float)thePxWidth, (float)thePxHeight);
aParams.ViewName = theViewName;
aParams.DisplayName = theDisplayName;
aParams.ViewToClone = theViewToClone;
aParams.IsVirtual = theIsVirtual;
return ViewerInit (aParams);
}
Standard_EXPORT static void RemoveViewName (const TCollection_AsciiString& theName); Standard_EXPORT static void RemoveViewName (const TCollection_AsciiString& theName);
@ -72,6 +105,10 @@ public:
Standard_EXPORT static TCollection_AsciiString GetCurrentViewName(); Standard_EXPORT static TCollection_AsciiString GetCurrentViewName();
//! Make the view active
Standard_EXPORT static void ActivateView (const Handle(V3d_View)& theView,
Standard_Boolean theToUpdate);
//! Removes view and clear all maps //! Removes view and clear all maps
//! with information about its resources if necessary //! with information about its resources if necessary
Standard_EXPORT static void RemoveView (const TCollection_AsciiString& theViewName, Standard_EXPORT static void RemoveView (const TCollection_AsciiString& theViewName,
@ -207,6 +244,10 @@ public:
return parseZLayer (theArg, true, theLayer); return parseZLayer (theArg, true, theLayer);
} }
//! Auxiliary method to parse transformation persistence flags
Standard_EXPORT static Standard_Boolean ParseCorner (Standard_CString theArg,
Aspect_TypeOfTriedronPosition& theCorner);
public: //! @name deprecated methods public: //! @name deprecated methods
//! Parses RGB(A) color argument(s) specified within theArgVec[0], theArgVec[1], theArgVec[2] and theArgVec[3]. //! Parses RGB(A) color argument(s) specified within theArgVec[0], theArgVec[1], theArgVec[2] and theArgVec[3].

View File

@ -108,10 +108,20 @@ void ViewerTest_AutoUpdater::Update()
if (!myContext.IsNull()) if (!myContext.IsNull())
{ {
myContext->UpdateCurrentViewer(); myContext->UpdateCurrentViewer();
if (!myView.IsNull()
&& myView->IsSubview()
&& myView->ParentView()->Viewer() != myContext->CurrentViewer())
{
myView->ParentView()->RedrawImmediate();
}
} }
else if (!myView.IsNull()) else if (!myView.IsNull())
{ {
myView->Redraw(); myView->Redraw();
if (myView->IsSubview())
{
myView->ParentView()->RedrawImmediate();
}
} }
} }
} }

View File

@ -145,6 +145,30 @@ bool ViewerTest_EventManager::UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
return AIS_ViewController::UpdateMouseClick (thePoint, theButton, theModifiers, theIsDoubleClick); return AIS_ViewController::UpdateMouseClick (thePoint, theButton, theModifiers, theIsDoubleClick);
} }
//=======================================================================
//function : UpdateMouseButtons
//purpose :
//=======================================================================
bool ViewerTest_EventManager::UpdateMouseScroll (const Aspect_ScrollDelta& theDelta)
{
if (!myView.IsNull()
&& (myView->IsSubview()
|| !myView->Subviews().IsEmpty()))
{
Handle(V3d_View) aParent = !myView->IsSubview() ? myView : myView->ParentView();
Handle(V3d_View) aPickedView = aParent->PickSubview (theDelta.Point);
if (!aPickedView.IsNull()
&& aPickedView != myView)
{
// switch input focus to another subview
OnSubviewChanged (myCtx, myView, aPickedView);
return true;
}
}
return AIS_ViewController::UpdateMouseScroll (theDelta);
}
//======================================================================= //=======================================================================
//function : UpdateMouseButtons //function : UpdateMouseButtons
//purpose : //purpose :
@ -154,6 +178,22 @@ bool ViewerTest_EventManager::UpdateMouseButtons (const Graphic3d_Vec2i& thePoin
Aspect_VKeyFlags theModifiers, Aspect_VKeyFlags theModifiers,
bool theIsEmulated) bool theIsEmulated)
{ {
if (!myView.IsNull()
&& myMousePressed == Aspect_VKeyMouse_NONE
&& theButtons != Aspect_VKeyMouse_NONE
&& (myView->IsSubview()
|| !myView->Subviews().IsEmpty()))
{
Handle(V3d_View) aParent = !myView->IsSubview() ? myView : myView->ParentView();
Handle(V3d_View) aPickedView = aParent->PickSubview (thePoint);
if (!aPickedView.IsNull()
&& aPickedView != myView)
{
// switch input focus to another subview
OnSubviewChanged (myCtx, myView, aPickedView);
}
}
SetAllowRotation (!ViewerTest_V3dView::IsCurrentViewIn2DMode()); SetAllowRotation (!ViewerTest_V3dView::IsCurrentViewIn2DMode());
if (theButtons == Aspect_VKeyMouse_LeftButton) if (theButtons == Aspect_VKeyMouse_LeftButton)
@ -232,22 +272,45 @@ void ViewerTest_EventManager::handleViewRedraw (const Handle(AIS_InteractiveCont
//============================================================================== //==============================================================================
void ViewerTest_EventManager::ProcessConfigure (bool theIsResized) void ViewerTest_EventManager::ProcessConfigure (bool theIsResized)
{ {
if (!myView.IsNull()) if (myView.IsNull())
{ {
if (!theIsResized return;
// track window moves to reverse stereo pair
&& myView->RenderingParams().StereoMode != Graphic3d_StereoMode_RowInterlaced
&& myView->RenderingParams().StereoMode != Graphic3d_StereoMode_ColumnInterlaced
&& myView->RenderingParams().StereoMode != Graphic3d_StereoMode_ChessBoard)
{
return;
}
myView->Window()->DoResize();
myView->MustBeResized();
myView->Invalidate();
FlushViewEvents (myCtx, myView, true);
} }
if (!theIsResized
// track window moves to reverse stereo pair
&& myView->RenderingParams().StereoMode != Graphic3d_StereoMode_RowInterlaced
&& myView->RenderingParams().StereoMode != Graphic3d_StereoMode_ColumnInterlaced
&& myView->RenderingParams().StereoMode != Graphic3d_StereoMode_ChessBoard)
{
return;
}
Handle(V3d_View) aParent = !myView->IsSubview()
? myView
: myView->ParentView();
aParent->Window()->DoResize();
aParent->MustBeResized();
aParent->Invalidate();
for (const Handle(V3d_View)& aChildIter : aParent->Subviews())
{
aChildIter->Window()->DoResize();
aChildIter->MustBeResized();
aChildIter->Invalidate();
}
FlushViewEvents (myCtx, myView, true);
}
//==============================================================================
//function : OnSubviewChanged
//purpose :
//==============================================================================
void ViewerTest_EventManager::OnSubviewChanged (const Handle(AIS_InteractiveContext)& ,
const Handle(V3d_View)& ,
const Handle(V3d_View)& theNewView)
{
ViewerTest::ActivateView (theNewView, false);
} }
//============================================================================== //==============================================================================

View File

@ -79,6 +79,9 @@ public:
myPickPntArgVec[2] = theArgZ; myPickPntArgVec[2] = theArgZ;
} }
//! Update mouse scroll event.
Standard_EXPORT virtual bool UpdateMouseScroll (const Aspect_ScrollDelta& theDelta) Standard_OVERRIDE;
//! Handle mouse button click event. //! Handle mouse button click event.
Standard_EXPORT virtual bool UpdateMouseClick (const Graphic3d_Vec2i& thePoint, Standard_EXPORT virtual bool UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
Aspect_VKeyMouse theButton, Aspect_VKeyMouse theButton,
@ -116,6 +119,12 @@ public:
//! Handle KeyPress event. //! Handle KeyPress event.
Standard_EXPORT void ProcessKeyPress (Aspect_VKey theKey); Standard_EXPORT void ProcessKeyPress (Aspect_VKey theKey);
//! Callback called on Selection of another (sub)view.
//! This method is expected to be called from rendering thread.
Standard_EXPORT virtual void OnSubviewChanged (const Handle(AIS_InteractiveContext)& theCtx,
const Handle(V3d_View)& theOldView,
const Handle(V3d_View)& theNewView) Standard_OVERRIDE;
protected: protected:
//! Register hot-keys for specified Action. //! Register hot-keys for specified Action.

View File

@ -932,7 +932,10 @@ static Standard_Integer VListColors (Draw_Interpretor& theDI,
Handle(V3d_View) aView; Handle(V3d_View) aView;
if (!aDumpFile.IsEmpty()) if (!aDumpFile.IsEmpty())
{ {
ViewerTest::ViewerInit (0, 0, anImgParams.Width, anImgParams.Height, "TmpDriver/TmpViewer/TmpView"); ViewerTest_VinitParams aParams;
aParams.Size.SetValues ((float )anImgParams.Width, (float)anImgParams.Height);
aParams.ViewName = "TmpDriver/TmpViewer/TmpView";
ViewerTest::ViewerInit (aParams);
aView = ViewerTest::CurrentView(); aView = ViewerTest::CurrentView();
aView->SetImmediateUpdate (false); aView->SetImmediateUpdate (false);
aView->SetBgGradientStyle (Aspect_GradientFillMethod_None, false); aView->SetBgGradientStyle (Aspect_GradientFillMethod_None, false);

View File

@ -477,28 +477,23 @@ TCollection_AsciiString ViewerTest::GetCurrentViewName ()
//purpose : Create the window viewer and initialize all the global variable //purpose : Create the window viewer and initialize all the global variable
//============================================================================== //==============================================================================
TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft, TCollection_AsciiString ViewerTest::ViewerInit (const ViewerTest_VinitParams& theParams)
const Standard_Integer thePxTop,
const Standard_Integer thePxWidth,
const Standard_Integer thePxHeight,
const TCollection_AsciiString& theViewName,
const TCollection_AsciiString& theDisplayName,
const Handle(V3d_View)& theViewToClone,
const Standard_Boolean theIsVirtual)
{ {
// Default position and dimension of the viewer window. // Default position and dimension of the viewer window.
// Note that left top corner is set to be sufficiently small to have // Note that left top corner is set to be sufficiently small to have
// window fit in the small screens (actual for remote desktops, see #23003). // window fit in the small screens (actual for remote desktops, see #23003).
// The position corresponds to the window's client area, thus some // The position corresponds to the window's client area, thus some
// gap is added for window frame to be visible. // gap is added for window frame to be visible.
Standard_Integer aPxLeft = 20, aPxTop = 40; Graphic3d_Vec2d aPxTopLeft (20, 40);
Standard_Integer aPxWidth = 409, aPxHeight = 409; Graphic3d_Vec2d aPxSize (409, 409);
Standard_Boolean isDefViewSize = Standard_True; Standard_Boolean isDefViewSize = Standard_True;
Standard_Boolean toCreateViewer = Standard_False; Standard_Boolean toCreateViewer = Standard_False;
const Standard_Boolean isVirtual = Draw_VirtualWindows || theIsVirtual; const Standard_Boolean isVirtual = Draw_VirtualWindows || theParams.IsVirtual;
if (!theViewToClone.IsNull()) if (!theParams.ViewToClone.IsNull())
{ {
theViewToClone->Window()->Size (aPxWidth, aPxHeight); Graphic3d_Vec2i aCloneSize;
theParams.ViewToClone->Window()->Size (aCloneSize.x(), aCloneSize.y());
aPxSize = Graphic3d_Vec2d (aCloneSize);
isDefViewSize = Standard_False; isDefViewSize = Standard_False;
#if !defined(__EMSCRIPTEN__) #if !defined(__EMSCRIPTEN__)
(void )isDefViewSize; (void )isDefViewSize;
@ -522,40 +517,21 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
} }
Handle(Graphic3d_GraphicDriver) aGraphicDriver; Handle(Graphic3d_GraphicDriver) aGraphicDriver;
ViewerTest_Names aViewNames(theViewName); ViewerTest_Names aViewNames (theParams.ViewName);
if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName())) if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
{ {
aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View")); aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
} }
if (thePxLeft != 0)
{
aPxLeft = thePxLeft;
}
if (thePxTop != 0)
{
aPxTop = thePxTop;
}
if (thePxWidth != 0)
{
isDefViewSize = Standard_False;
aPxWidth = thePxWidth;
}
if (thePxHeight != 0)
{
isDefViewSize = Standard_False;
aPxHeight = thePxHeight;
}
// Get graphic driver (create it or get from another view) // Get graphic driver (create it or get from another view)
const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()); const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
if (isNewDriver) if (isNewDriver)
{ {
// Get connection string // Get connection string
#if defined(HAVE_XLIB) #if defined(HAVE_XLIB)
if (!theDisplayName.IsEmpty()) if (!theParams.DisplayName.IsEmpty())
{ {
SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName)); SetDisplayConnection (new Aspect_DisplayConnection (theParams.DisplayName));
} }
else else
{ {
@ -569,7 +545,6 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
SetDisplayConnection (new Aspect_DisplayConnection (aDispX)); SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
} }
#else #else
(void)theDisplayName; // avoid warning on unused argument
SetDisplayConnection (new Aspect_DisplayConnection ()); SetDisplayConnection (new Aspect_DisplayConnection ());
#endif #endif
@ -588,53 +563,89 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
aGraphicDriver = ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()); aGraphicDriver = ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName());
} }
//Dispose the window if input parameters are default // Get screen resolution
if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0) Graphic3d_Vec2i aScreenSize;
{
Standard_Integer aTop = 0,
aLeft = 0,
aRight = 0,
aBottom = 0,
aScreenWidth = 0,
aScreenHeight = 0;
// Get screen resolution
#if defined(_WIN32) #if defined(_WIN32)
RECT aWindowSize; RECT aWindowSize;
GetClientRect(GetDesktopWindow(), &aWindowSize); GetClientRect(GetDesktopWindow(), &aWindowSize);
aScreenHeight = aWindowSize.bottom; aScreenSize.SetValues (aWindowSize.right, aWindowSize.bottom);
aScreenWidth = aWindowSize.right;
#elif defined(HAVE_XLIB) #elif defined(HAVE_XLIB)
::Display* aDispX = (::Display* )GetDisplayConnection()->GetDisplayAspect(); ::Display* aDispX = (::Display* )GetDisplayConnection()->GetDisplayAspect();
Screen* aScreen = DefaultScreenOfDisplay(aDispX); Screen* aScreen = DefaultScreenOfDisplay(aDispX);
aScreenWidth = WidthOfScreen(aScreen); aScreenSize.x() = WidthOfScreen(aScreen);
aScreenHeight = HeightOfScreen(aScreen); aScreenSize.y() = HeightOfScreen(aScreen);
#elif defined(__APPLE__) #elif defined(__APPLE__)
GetCocoaScreenResolution (aScreenWidth, aScreenHeight); GetCocoaScreenResolution (aScreenSize.x(), aScreenSize.y());
#else #else
// not implemented // not implemented
#endif #endif
TCollection_AsciiString anOverlappedViewId(""); if (!theParams.ParentView.IsNull())
{
aPxTopLeft.SetValues (0, 0);
}
if (theParams.Offset.x() != 0)
{
aPxTopLeft.x() = theParams.Offset.x();
}
if (theParams.Offset.y() != 0)
{
aPxTopLeft.y() = theParams.Offset.y();
}
if (theParams.Size.x() != 0)
{
isDefViewSize = Standard_False;
aPxSize.x() = theParams.Size.x();
if (aPxSize.x() <= 1.0
&& aScreenSize.x() > 0
&& theParams.ParentView.IsNull())
{
aPxSize.x() = aPxSize.x() * double(aScreenSize.x());
}
}
if (theParams.Size.y() != 0)
{
isDefViewSize = Standard_False;
aPxSize.y() = theParams.Size.y();
if (aPxSize.y() <= 1.0
&& aScreenSize.y() > 0
&& theParams.ParentView.IsNull())
{
aPxSize.y() = aPxSize.y() * double(aScreenSize.y());
}
}
while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)) //Dispose the window if input parameters are default
if (!ViewerTest_myViews.IsEmpty()
&& theParams.ParentView.IsNull()
&& theParams.Offset.x() == 0
&& theParams.Offset.y() == 0)
{
Standard_Integer aTop = 0, aLeft = 0, aRight = 0, aBottom = 0;
TCollection_AsciiString anOverlappedViewId("");
while (IsWindowOverlapped ((int )aPxTopLeft.x(), (int )aPxTopLeft.y(),
(int )aPxTopLeft.x() + (int )aPxSize.x(),
(int )aPxTopLeft.y() + (int )aPxSize.y(), anOverlappedViewId))
{ {
ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom); ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId) if (IsWindowOverlapped (aRight + 20, (int )aPxTopLeft.y(), aRight + 20 + (int )aPxSize.x(),
&& aRight + 2*aPxWidth + 40 > aScreenWidth) (int )aPxTopLeft.y() + (int )aPxSize.y(), anOverlappedViewId)
&& aRight + 2 * aPxSize.x() + 40 > aScreenSize.x())
{ {
if (aBottom + aPxHeight + 40 > aScreenHeight) if (aBottom + aPxSize.y() + 40 > aScreenSize.y())
{ {
aPxLeft = 20; aPxTopLeft.x() = 20;
aPxTop = 40; aPxTopLeft.y() = 40;
break; break;
} }
aPxLeft = 20; aPxTopLeft.x() = 20;
aPxTop = aBottom + 40; aPxTopLeft.y() = aBottom + 40;
} }
else else
aPxLeft = aRight + 20; {
aPxTopLeft.x() = aRight + 20;
}
} }
} }
@ -688,61 +699,76 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
} }
// Create window // Create window
#if defined(_WIN32) if (!theParams.ParentView.IsNull())
VT_GetWindow() = new WNT_Window (aTitle.ToCString(), WClass(),
isVirtual ? WS_POPUP : WS_OVERLAPPEDWINDOW,
aPxLeft, aPxTop,
aPxWidth, aPxHeight,
Quantity_NOC_BLACK);
VT_GetWindow()->RegisterRawInputDevices (WNT_Window::RawInputMask_SpaceMouse);
#elif defined(HAVE_XLIB)
VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
aTitle.ToCString(),
aPxLeft, aPxTop,
aPxWidth, aPxHeight);
#elif defined(__APPLE__)
VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
aPxLeft, aPxTop,
aPxWidth, aPxHeight);
ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
#elif defined(__EMSCRIPTEN__)
// current EGL implementation in Emscripten supports only one global WebGL canvas returned by Module.canvas property;
// the code should be revised for handling multiple canvas elements (which is technically also possible)
TCollection_AsciiString aCanvasId = getModuleCanvasId();
if (!aCanvasId.IsEmpty())
{ {
aCanvasId = TCollection_AsciiString("#") + aCanvasId; VT_GetWindow() = Handle(ViewerTest_Window)::DownCast (theParams.ParentView->Window());
} }
else
{
#if defined(_WIN32)
VT_GetWindow() = new WNT_Window (aTitle.ToCString(), WClass(),
isVirtual ? WS_POPUP : WS_OVERLAPPEDWINDOW,
(int )aPxTopLeft.x(), (int )aPxTopLeft.y(),
(int )aPxSize.x(), (int )aPxSize.y(),
Quantity_NOC_BLACK);
VT_GetWindow()->RegisterRawInputDevices (WNT_Window::RawInputMask_SpaceMouse);
#elif defined(HAVE_XLIB)
VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
aTitle.ToCString(),
(int )aPxTopLeft.x(), (int )aPxTopLeft.y(),
(int )aPxSize.x(), (int )aPxSize.y());
#elif defined(__APPLE__)
VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
(int )aPxTopLeft.x(), (int )aPxTopLeft.y(),
(int )aPxSize.x(), (int )aPxSize.y());
ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
#elif defined(__EMSCRIPTEN__)
// current EGL implementation in Emscripten supports only one global WebGL canvas returned by Module.canvas property;
// the code should be revised for handling multiple canvas elements (which is technically also possible)
TCollection_AsciiString aCanvasId = getModuleCanvasId();
if (!aCanvasId.IsEmpty())
{
aCanvasId = TCollection_AsciiString("#") + aCanvasId;
}
VT_GetWindow() = new Wasm_Window (aCanvasId); VT_GetWindow() = new Wasm_Window (aCanvasId);
Graphic3d_Vec2i aRealSize; Graphic3d_Vec2i aRealSize;
VT_GetWindow()->Size (aRealSize.x(), aRealSize.y()); VT_GetWindow()->Size (aRealSize.x(), aRealSize.y());
if (!isDefViewSize || (aRealSize.x() <= 0 && aRealSize.y() <= 0)) if (!isDefViewSize || (aRealSize.x() <= 0 && aRealSize.y() <= 0))
{ {
// Wasm_Window wraps an existing HTML element without creating a new one. // Wasm_Window wraps an existing HTML element without creating a new one.
// Keep size defined on a web page instead of defaulting to 409x409 (as in case of other platform), // Keep size defined on a web page instead of defaulting to 409x409 (as in case of other platform),
// but resize canvas if vinit has been called with explicitly specified dimensions. // but resize canvas if vinit has been called with explicitly specified dimensions.
VT_GetWindow()->SetSizeLogical (Graphic3d_Vec2d (aPxWidth, aPxHeight)); VT_GetWindow()->SetSizeLogical (Graphic3d_Vec2d (aPxSize));
}
#else
// not implemented
VT_GetWindow() = new Aspect_NeutralWindow();
VT_GetWindow()->SetSize ((int )aPxSize.x(), (int )aPxSize.y());
#endif
VT_GetWindow()->SetVirtual (isVirtual);
} }
#else
// not implemented
VT_GetWindow() = new Aspect_NeutralWindow();
VT_GetWindow()->SetSize (aPxWidth, aPxHeight);
#endif
VT_GetWindow()->SetVirtual (isVirtual);
// View setup // View setup
Handle(V3d_View) aView; Handle(V3d_View) aView;
if (!theViewToClone.IsNull()) if (!theParams.ViewToClone.IsNull())
{ {
aView = new ViewerTest_V3dView (a3DViewer, theViewToClone); aView = new ViewerTest_V3dView (a3DViewer, theParams.ViewToClone);
} }
else else
{ {
aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView()); aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
} }
aView->SetWindow (VT_GetWindow()); aView->View()->SetSubviewComposer (theParams.IsComposer);
if (!theParams.ParentView.IsNull())
{
aView->SetWindow (theParams.ParentView, aPxSize, theParams.Corner, aPxTopLeft, theParams.SubviewMargins);
}
else
{
aView->SetWindow (VT_GetWindow());
}
ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer); ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
ViewerTest::CurrentView(aView); ViewerTest::CurrentView(aView);
@ -952,10 +978,7 @@ static int VDriver (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const c
//============================================================================== //==============================================================================
static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec) static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
{ {
TCollection_AsciiString aViewName, aDisplayName; ViewerTest_VinitParams aParams;
Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
Standard_Boolean isVirtual = false;
Handle(V3d_View) aCopyFrom;
TCollection_AsciiString aName, aValue; TCollection_AsciiString aName, aValue;
int is2dMode = -1, aDpiAware = -1; int is2dMode = -1, aDpiAware = -1;
for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt) for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
@ -966,91 +989,128 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
if (anArgIt + 1 < theArgsNb if (anArgIt + 1 < theArgsNb
&& anArgCase == "-name") && anArgCase == "-name")
{ {
aViewName = theArgVec[++anArgIt]; aParams.ViewName = theArgVec[++anArgIt];
} }
else if (anArgIt + 1 < theArgsNb else if (anArgIt + 1 < theArgsNb
&& (anArgCase == "-left" && (anArgCase == "-left"
|| anArgCase == "-l")) || anArgCase == "-l")
&& Draw::ParseReal (theArgVec[anArgIt + 1], aParams.Offset.x()))
{ {
aPxLeft = Draw::Atoi (theArgVec[++anArgIt]); ++anArgIt;
} }
else if (anArgIt + 1 < theArgsNb else if (anArgIt + 1 < theArgsNb
&& (anArgCase == "-top" && (anArgCase == "-top"
|| anArgCase == "-t")) || anArgCase == "-t")
&& Draw::ParseReal (theArgVec[anArgIt + 1], aParams.Offset.y()))
{ {
aPxTop = Draw::Atoi (theArgVec[++anArgIt]); ++anArgIt;
} }
else if (anArgIt + 1 < theArgsNb else if (anArgIt + 1 < theArgsNb
&& (anArgCase == "-width" && (anArgCase == "-width"
|| anArgCase == "-w")) || anArgCase == "-w")
&& Draw::ParseReal (theArgVec[anArgIt + 1], aParams.Size.x()))
{ {
aPxWidth = Draw::Atoi (theArgVec[++anArgIt]); ++anArgIt;
} }
else if (anArgIt + 1 < theArgsNb else if (anArgIt + 1 < theArgsNb
&& (anArgCase == "-height" && (anArgCase == "-height"
|| anArgCase == "-h")) || anArgCase == "-h")
&& Draw::ParseReal (theArgVec[anArgIt + 1], aParams.Size.y()))
{ {
aPxHeight = Draw::Atoi (theArgVec[++anArgIt]); ++anArgIt;
}
else if (anArgIt + 1 < theArgsNb
&& (anArgCase == "-pos"
|| anArgCase == "-position"
|| anArgCase == "-corner")
&& ViewerTest::ParseCorner (theArgVec[anArgIt + 1], aParams.Corner))
{
++anArgIt;
}
else if (anArgIt + 2 < theArgsNb
&& anArgCase == "-margins"
&& Draw::ParseInteger (theArgVec[anArgIt + 1], aParams.SubviewMargins.x())
&& Draw::ParseInteger (theArgVec[anArgIt + 2], aParams.SubviewMargins.y()))
{
anArgIt += 2;
} }
else if (anArgCase == "-virtual" else if (anArgCase == "-virtual"
|| anArgCase == "-offscreen") || anArgCase == "-offscreen")
{ {
isVirtual = true; aParams.IsVirtual = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
if (anArgIt + 1 < theArgsNb }
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], isVirtual)) else if (anArgCase == "-composer")
{ {
++anArgIt; aParams.IsComposer = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
}
} }
else if (anArgCase == "-exitonclose") else if (anArgCase == "-exitonclose")
{ {
ViewerTest_EventManager::ToExitOnCloseView() = true; ViewerTest_EventManager::ToExitOnCloseView() = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
if (anArgIt + 1 < theArgsNb
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
{
++anArgIt;
}
} }
else if (anArgCase == "-closeonescape" else if (anArgCase == "-closeonescape"
|| anArgCase == "-closeonesc") || anArgCase == "-closeonesc")
{ {
ViewerTest_EventManager::ToCloseViewOnEscape() = true; ViewerTest_EventManager::ToCloseViewOnEscape() = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
if (anArgIt + 1 < theArgsNb
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
{
++anArgIt;
}
} }
else if (anArgCase == "-2d_mode" else if (anArgCase == "-2d_mode"
|| anArgCase == "-2dmode" || anArgCase == "-2dmode"
|| anArgCase == "-2d") || anArgCase == "-2d")
{ {
bool toEnable = true; bool toEnable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
if (anArgIt + 1 < theArgsNb
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
{
++anArgIt;
}
is2dMode = toEnable ? 1 : 0; is2dMode = toEnable ? 1 : 0;
} }
else if (anArgIt + 1 < theArgsNb else if (anArgIt + 1 < theArgsNb
&& (anArgCase == "-disp" && (anArgCase == "-disp"
|| anArgCase == "-display")) || anArgCase == "-display"))
{ {
aDisplayName = theArgVec[++anArgIt]; aParams.DisplayName = theArgVec[++anArgIt];
} }
else if (anArgCase == "-dpiaware") else if (anArgCase == "-dpiaware")
{ {
aDpiAware = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt) ? 1 : 0; aDpiAware = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt) ? 1 : 0;
} }
else if (!ViewerTest::CurrentView().IsNull() else if (!ViewerTest::CurrentView().IsNull()
&& aCopyFrom.IsNull() && aParams.ViewToClone.IsNull()
&& (anArgCase == "-copy" && (anArgCase == "-copy"
|| anArgCase == "-clone" || anArgCase == "-clone"
|| anArgCase == "-cloneactive" || anArgCase == "-cloneactive"
|| anArgCase == "-cloneactiveview")) || anArgCase == "-cloneactiveview"))
{ {
aCopyFrom = ViewerTest::CurrentView(); aParams.ViewToClone = ViewerTest::CurrentView();
}
else if (!ViewerTest::CurrentView().IsNull()
&& aParams.ParentView.IsNull()
&& anArgCase == "-subview")
{
aParams.ParentView = ViewerTest::CurrentView();
if (aParams.ParentView.IsNull())
{
Message::SendFail() << "Syntax error: cannot create of subview without parent";
return 1;
}
if (aParams.ParentView->IsSubview())
{
aParams.ParentView = aParams.ParentView->ParentView();
}
}
else if (!ViewerTest::CurrentView().IsNull()
&& aParams.ParentView.IsNull()
&& anArgCase == "-parent"
&& anArgIt + 1 < theArgsNb)
{
TCollection_AsciiString aParentStr (theArgVec[++anArgIt]);
ViewerTest_Names aViewNames (aParentStr);
if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
{
Message::SendFail() << "Syntax error: parent view '" << aParentStr << "' not found";
return 1;
}
aParams.ParentView = ViewerTest_myViews.Find1(aViewNames.GetViewName());
if (aParams.ParentView->IsSubview())
{
aParams.ParentView = aParams.ParentView->ParentView();
}
} }
// old syntax // old syntax
else if (ViewerTest::SplitParameter (anArg, aName, aValue)) else if (ViewerTest::SplitParameter (anArg, aName, aValue))
@ -1058,32 +1118,32 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
aName.LowerCase(); aName.LowerCase();
if (aName == "name") if (aName == "name")
{ {
aViewName = aValue; aParams.ViewName = aValue;
} }
else if (aName == "l" else if (aName == "l"
|| aName == "left") || aName == "left")
{ {
aPxLeft = aValue.IntegerValue(); aParams.Offset.x() = (float)aValue.RealValue();
} }
else if (aName == "t" else if (aName == "t"
|| aName == "top") || aName == "top")
{ {
aPxTop = aValue.IntegerValue(); aParams.Offset.y() = (float)aValue.RealValue();
} }
else if (aName == "disp" else if (aName == "disp"
|| aName == "display") || aName == "display")
{ {
aDisplayName = aValue; aParams.DisplayName = aValue;
} }
else if (aName == "w" else if (aName == "w"
|| aName == "width") || aName == "width")
{ {
aPxWidth = aValue.IntegerValue(); aParams.Size.x() = (float )aValue.RealValue();
} }
else if (aName == "h" else if (aName == "h"
|| aName == "height") || aName == "height")
{ {
aPxHeight = aValue.IntegerValue(); aParams.Size.y() = (float)aValue.RealValue();
} }
else else
{ {
@ -1091,9 +1151,9 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
return 1; return 1;
} }
} }
else if (aViewName.IsEmpty()) else if (aParams.ViewName.IsEmpty())
{ {
aViewName = anArg; aParams.ViewName = anArg;
} }
else else
{ {
@ -1134,15 +1194,15 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
#else #else
(void )aDpiAware; (void )aDpiAware;
#if !defined(HAVE_XLIB) #if !defined(HAVE_XLIB)
if (!aDisplayName.IsEmpty()) if (!aParams.DisplayName.IsEmpty())
{ {
aDisplayName.Clear(); aParams.DisplayName.Clear();
Message::SendWarning() << "Warning: display parameter will be ignored.\n"; Message::SendWarning() << "Warning: display parameter will be ignored.\n";
} }
#endif #endif
#endif #endif
ViewerTest_Names aViewNames (aViewName); ViewerTest_Names aViewNames (aParams.ViewName);
if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName())) if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
{ {
TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName(); TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
@ -1154,8 +1214,7 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
return 0; return 0;
} }
TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight, TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aParams);
aViewName, aDisplayName, aCopyFrom, isVirtual);
if (is2dMode != -1) if (is2dMode != -1)
{ {
ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1); ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
@ -1422,29 +1481,59 @@ static TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWind
void ActivateView (const TCollection_AsciiString& theViewName, void ActivateView (const TCollection_AsciiString& theViewName,
Standard_Boolean theToUpdate = Standard_True) Standard_Boolean theToUpdate = Standard_True)
{ {
const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName); if (const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName))
if (aView.IsNull()) {
ViewerTest::ActivateView (aView, theToUpdate);
}
}
//==============================================================================
//function : ActivateView
//purpose :
//==============================================================================
void ViewerTest::ActivateView (const Handle(V3d_View)& theView,
Standard_Boolean theToUpdate)
{
Handle(V3d_View) aView = theView;
const TCollection_AsciiString* aViewName = ViewerTest_myViews.Seek2 (aView);
if (aViewName == nullptr)
{ {
return; return;
} }
Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView); Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
if (!anAISContext.IsNull()) if (anAISContext.IsNull())
{ {
if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView()) return;
}
if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
{
if (!aCurrentView->Window().IsNull())
{ {
aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView)); aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
} }
}
ViewerTest::CurrentView (aView); ViewerTest::CurrentView (aView);
ViewerTest::SetAISContext (anAISContext); ViewerTest::SetAISContext (anAISContext);
aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)"); if (aView->IsSubview())
VT_GetWindow() = Handle(ViewerTest_Window)::DownCast(ViewerTest::CurrentView()->Window()); {
SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection()); aView->ParentView()->Window()->SetTitle (TCollection_AsciiString("3D View - ") + *aViewName + "(*)");
if (theToUpdate) VT_GetWindow() = Handle(ViewerTest_Window)::DownCast(aView->View()->ParentView()->Window());
{ }
ViewerTest::CurrentView()->Redraw(); else
} {
VT_GetWindow() = Handle(ViewerTest_Window)::DownCast(aView->Window());
}
if (!VT_GetWindow().IsNull())
{
VT_GetWindow()->SetTitle (TCollection_AsciiString("3D View - ") + *aViewName + "(*)");
}
SetDisplayConnection(aView->Viewer()->Driver()->GetDisplayConnection());
if (theToUpdate)
{
aView->Redraw();
} }
} }
@ -1476,22 +1565,33 @@ void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const S
return; return;
} }
Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
aRedrawer.Stop (aView);
if (!aView->Subviews().IsEmpty())
{
NCollection_Sequence<Handle(V3d_View)> aSubviews = aView->Subviews();
for (const Handle(V3d_View)& aSubviewIter : aSubviews)
{
RemoveView (aSubviewIter, isContextRemoved);
}
}
// Activate another view if it's active now // Activate another view if it's active now
if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView()) if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
{ {
if (ViewerTest_myViews.Extent() > 1) if (ViewerTest_myViews.Extent() > 1)
{ {
TCollection_AsciiString aNewViewName;
for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews); for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
anIter.More(); anIter.Next()) anIter.More(); anIter.Next())
{ {
if (anIter.Key1() != theViewName) if (anIter.Key1() != theViewName)
{ {
aNewViewName = anIter.Key1(); ActivateView (anIter.Value(), true);
break; break;
} }
} }
ActivateView (aNewViewName);
} }
else else
{ {
@ -1506,14 +1606,11 @@ void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const S
} }
// Delete view // Delete view
Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
aRedrawer.Stop (aView);
// Remove view resources
ViewerTest_myViews.UnBind1(theViewName); ViewerTest_myViews.UnBind1(theViewName);
aView->Window()->Unmap(); if (!aView->Window().IsNull())
{
aView->Window()->Unmap();
}
aView->Remove(); aView->Remove();
#if defined(HAVE_XLIB) #if defined(HAVE_XLIB)
@ -3196,47 +3293,13 @@ static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
{ {
if (++anArgIter >= theArgNb) if (++anArgIter >= theArgNb)
{ {
Message::SendFail() << "Error: wrong syntax at '" << anArg << "'"; Message::SendFail() << "Syntax error at '" << anArg << "'";
return 1; return 1;
} }
TCollection_AsciiString aPosName (theArgVec[anArgIter]); if (!ViewerTest::ParseCorner (theArgVec[anArgIter], aPosition))
aPosName.LowerCase();
if (aPosName == "center")
{ {
aPosition = Aspect_TOTP_CENTER; Message::SendFail() << "Syntax error at '" << anArg << "' - unknown position '" << theArgVec[anArgIter] << "'";
}
else if (aPosName == "left_lower"
|| aPosName == "lower_left"
|| aPosName == "leftlower"
|| aPosName == "lowerleft")
{
aPosition = Aspect_TOTP_LEFT_LOWER;
}
else if (aPosName == "left_upper"
|| aPosName == "upper_left"
|| aPosName == "leftupper"
|| aPosName == "upperleft")
{
aPosition = Aspect_TOTP_LEFT_UPPER;
}
else if (aPosName == "right_lower"
|| aPosName == "lower_right"
|| aPosName == "rightlower"
|| aPosName == "lowerright")
{
aPosition = Aspect_TOTP_RIGHT_LOWER;
}
else if (aPosName == "right_upper"
|| aPosName == "upper_right"
|| aPosName == "rightupper"
|| aPosName == "upperright")
{
aPosition = Aspect_TOTP_RIGHT_UPPER;
}
else
{
Message::SendFail() << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'";
return 1; return 1;
} }
} }
@ -6158,15 +6221,13 @@ static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const
theDI.Eval (aCommand.ToCString()); theDI.Eval (aCommand.ToCString());
} }
Standard_Integer aPxLeft = 0; ViewerTest_VinitParams aParams;
Standard_Integer aPxTop = 0; aParams.ViewName = aViewName;
Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2); aParams.Size.x() = float(anImgRef->SizeX() * 2);
Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty() aParams.Size.y() = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
? int(anImgRef->SizeY() * 2) ? float(anImgRef->SizeY() * 2)
: int(anImgRef->SizeY()); : float(anImgRef->SizeY());
TCollection_AsciiString aDisplayName; TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aParams);
TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
aViewName, aDisplayName);
Standard_Real aRatio = anImgRef->Ratio(); Standard_Real aRatio = anImgRef->Ratio();
Standard_Real aSizeX = 1.0; Standard_Real aSizeX = 1.0;
@ -13801,8 +13862,9 @@ Makes specified driver active when ActiveName argument is specified.
addCmd ("vinit", VInit, /* [vinit] */ R"( addCmd ("vinit", VInit, /* [vinit] */ R"(
vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx] vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]
[-exitOnClose] [-closeOnEscape] [-cloneActive] [-virtual {on|off}=off] [-2d_mode {on|off}=off] [-exitOnClose] [-closeOnEscape] [-cloneActive] [-virtual {0|1}]=0 [-2d_mode {0|1}]=0
[-display displayName] [-dpiAware {on|off}] [-display displayName] [-dpiAware {0|1}]=0
[-subview] [-parent OtherView] [-composer {0|1}]=0 [-margins DX DY]=0
Creates new View window with specified name viewName. Creates new View window with specified name viewName.
By default the new view is created in the viewer and in graphic driver shared with active view. By default the new view is created in the viewer and in graphic driver shared with active view.
-name {driverName/viewerName/viewName | viewerName/viewName | viewName} -name {driverName/viewerName/viewName | viewerName/viewName | viewName}
@ -13817,6 +13879,7 @@ Display name will be used within creation of graphic driver, when specified.
-exitOnClose when specified, closing the view will exit application. -exitOnClose when specified, closing the view will exit application.
-closeOnEscape when specified, view will be closed on pressing Escape. -closeOnEscape when specified, view will be closed on pressing Escape.
-virtual create an offscreen window within interactive session -virtual create an offscreen window within interactive session
-subview create a subview within another view
-2d_mode when on, view will not react on rotate scene events -2d_mode when on, view will not react on rotate scene events
-dpiAware override dpi aware hint (Windows platform) -dpiAware override dpi aware hint (Windows platform)
Additional commands for operations with views: vclose, vactivate, vviewlist. Additional commands for operations with views: vclose, vactivate, vviewlist.

View File

@ -585,7 +585,7 @@ static Standard_Integer show (Draw_Interpretor& di, Standard_Integer argc, const
TCollection_AsciiString aViewName = TCollection_AsciiString ("Driver1/Document_") + argv[1] + "/View1"; TCollection_AsciiString aViewName = TCollection_AsciiString ("Driver1/Document_") + argv[1] + "/View1";
if (!TPrsStd_AISViewer::Find (aRoot, aDocViewer)) if (!TPrsStd_AISViewer::Find (aRoot, aDocViewer))
{ {
ViewerTest::ViewerInit (0, 0, 0, 0, aViewName.ToCString(), ""); ViewerTest::ViewerInit (aViewName);
aDocViewer = TPrsStd_AISViewer::New (aRoot, ViewerTest::GetAISContext()); aDocViewer = TPrsStd_AISViewer::New (aRoot, ViewerTest::GetAISContext());
} }
@ -1322,7 +1322,7 @@ static Standard_Integer testDoc (Draw_Interpretor&,
aD1->Open(anApp); aD1->Open(anApp);
TCollection_AsciiString aViewName ("Driver1/DummyDocument/View1"); TCollection_AsciiString aViewName ("Driver1/DummyDocument/View1");
ViewerTest::ViewerInit (0, 0, 0, 0, aViewName.ToCString(), ""); ViewerTest::ViewerInit (aViewName);
TPrsStd_AISViewer::New (aD1->GetData()->Root(), ViewerTest::GetAISContext()); TPrsStd_AISViewer::New (aD1->GetData()->Root(), ViewerTest::GetAISContext());
// get shape tool for shape verification // get shape tool for shape verification

View File

@ -0,0 +1,34 @@
puts "========"
puts "0032886: Visualization, V3d_View - introduce interface for creating a subview"
puts "V1/RootView + V2/ViewLeft + V3/ViewRight"
puts "========"
pload MODELING VISUALIZATION
vinit V1/RootView -width 1024 -height 512 -composer 0
vbackground GRAY20
vinit V2/ViewLeft -subView -width 0.5 -height 1.0
vbackground GRAY30
box b 1 2 3
vdisplay -dispMode 1 b
vaspects b -faceBoundaryDraw 1
vfit
vviewcube vc
vinit V3/ViewRight -parent V1/RootView -width 0.5 -height 1.0 -left 0.5
vbackground GRAY40
psphere s 1
vdisplay -dispMode 1 s
vaspects s -material SILVER
vfit
vzbufftrihedron
vactivate V1/RootView
vdump $::imagedir/${::casename}.png
vactivate V2/ViewLeft
vdump $::imagedir/${::casename}_left.png
vactivate V3/ViewRight
vdump $::imagedir/${::casename}_right.png

View File

@ -0,0 +1,36 @@
puts "========"
puts "0032886: Visualization, V3d_View - introduce interface for creating a subview"
puts "V1/RootView + V2/ViewLeft + V3/ViewRight + SSAA"
puts "========"
pload MODELING VISUALIZATION
vinit V1/RootView -width 1024 -height 512 -composer 1
vbackground GRAY20
vinit V2/ViewLeft -subView -width 0.5 -height 1.0
vrenderparams -rendScale 2
vbackground GRAY30
box b 1 2 3
vdisplay -dispMode 1 b
vaspects b -faceBoundaryDraw 1
vfit
vviewcube vc
vinit V3/ViewRight -parent V1/RootView -width 0.5 -height 1.0 -left 0.5
vrenderparams -rendScale 2
vbackground GRAY40
psphere s 1
vdisplay -dispMode 1 s
vaspects s -material SILVER
vfit
vzbufftrihedron
vactivate V1/RootView
vdump $::imagedir/${::casename}.png
vactivate V2/ViewLeft
vdump $::imagedir/${::casename}_left.png
vactivate V3/ViewRight
vdump $::imagedir/${::casename}_right.png

View File

@ -0,0 +1,40 @@
puts "========"
puts "0032886: Visualization, V3d_View - introduce interface for creating a subview"
puts "V1/RootView + V2/ViewLeft + V2/ViewRightTop + V2/ViewRightBottom"
puts "========"
pload MODELING VISUALIZATION
vinit V1/RootView -width 768 -height 512 -composer 1
vbackground GRAY20
vinit V2/ViewLeft -parent V1/RootView -width 0.5 -height 1.0
vbackground GRAY30
vaxo
vcamera -persp
box b 1 2 3
vdisplay -dispMode 1 b
vaspects b -faceBoundaryDraw 1
vfit
vzbufftrihedron
vinit V2/ViewRightTop -parent V1/RootView -width 0.5 -height 0.5 -corner topRight
vbackground GRAY40
vaxo
vfit
vinit V2/ViewRightBottom -parent V1/RootView -width 0.5 -height 0.5 -corner bottomRight
vbackground GRAY50
vaxo
vfit
vactivate V1/RootView
vdump $::imagedir/${::casename}.png
vactivate V2/ViewLeft
vdump $::imagedir/${::casename}_left.png
vactivate V2/ViewRightTop
vdump $::imagedir/${::casename}_righttop.png
vactivate V2/ViewRightBottom
vdump $::imagedir/${::casename}_rightbottom.png

View File

@ -0,0 +1,32 @@
puts "========"
puts "0032886: Visualization, V3d_View - introduce interface for creating a subview"
puts "V1/RootView + V2/View + V2/ThumbView at corner"
puts "========"
pload MODELING VISUALIZATION
vinit V1/RootView -width 380 -height 520
vbackground GRAY20
vinit V2/View -parent V1/RootView -width 1.0 -height 1.0
vbackground GRAY30
vaxo
vcamera -persp
box b 1 2 3
vdisplay -dispMode 1 b
vaspects b -faceBoundaryDraw 1
vfit
vzbufftrihedron
vinit V2/ThumbView -parent V1/RootView -width 0.25 -height 0.25 -corner bottomRight -top 10 -left 10
vbackground GRAY40
vaxo
vfit
vactivate V1/RootView
vdump $::imagedir/${::casename}.png
vactivate V2/View
vdump $::imagedir/${::casename}_view.png
vactivate V2/ThumbView
vdump $::imagedir/${::casename}_thumb.png

View File

@ -0,0 +1,26 @@
puts "========"
puts "0032886: Visualization, V3d_View - introduce interface for creating a subview"
puts "V1/RootView + V1/ThumbView at corner"
puts "========"
pload MODELING VISUALIZATION
vinit V1/RootView -width 380 -height 520 -composer 0
vbackground GRAY20
vaxo
vcamera -persp
box b 1 2 3
vdisplay -dispMode 1 b
vaspects b -faceBoundaryDraw 1
vfit
vzbufftrihedron
vinit V1/ThumbView -parent V1/RootView -width 0.25 -height 0.25 -corner bottomRight -top 10 -left 10
vbackground GRAY40
vaxo
vfit
vactivate V1/RootView
vdump $::imagedir/${::casename}.png
vactivate V1/ThumbView
vdump $::imagedir/${::casename}_thumb.png

View File

@ -0,0 +1,26 @@
puts "========"
puts "0032886: Visualization, V3d_View - introduce interface for creating a subview"
puts "V1/CompView + V1/ThumbView at corner"
puts "========"
pload MODELING VISUALIZATION
vinit V1/CompView -width 380 -height 520 -composer 1
vbackground GRAY20
vaxo
vcamera -persp
box b 1 2 3
vdisplay -dispMode 1 b
vaspects b -faceBoundaryDraw 1
vfit
vzbufftrihedron
vinit V1/ThumbView -parent V1/CompView -width 0.25 -height 0.25 -corner bottomRight -top 10 -left 10
vbackground GRAY40
vaxo
vfit
vactivate V1/CompView
vdump $::imagedir/${::casename}.png
vactivate V1/ThumbView
vdump $::imagedir/${::casename}_thumb.png

View File

@ -0,0 +1,53 @@
puts "========"
puts "0032886: Visualization, V3d_View - introduce interface for creating a subview"
puts "V1/CompView + V2/ViewLeft + V2/ViewRightTop + V2/ViewRightBottom + margins"
puts "========"
pload MODELING VISUALIZATION
vinit V1/CompView -width 768 -height 512 -composer 1
vbackground GRAY20
vinit V2/ViewLeft -parent V1/CompView -width 0.5 -height 1.0 -margins 2 2
vbackground GRAY30
vaxo
vcamera -persp
box b 1 2 3
vdisplay -dispMode 1 b
vaspects b -faceBoundaryDraw 1
vfit
vviewcube vc
vinit V2/ViewRightTop -parent V1/CompView -width 0.5 -height 0.5 -corner topRight -margins 2 2
vbackground GRAY40
vaxo
vfit
verase vc -view
vinit V3/ViewRightBottom -parent V1/CompView -width 0.5 -height 0.5 -corner bottomRight -margins 2 2
vbackground GRAY50
psphere s 1
vdisplay -dispMode 1 s
vaspects s -material SILVER
vaxo
vfit
vzbufftrihedron
vinit V3/ThumbView -parent V1/CompView -width 100 -height 150 -corner topLeft -top 10 -left 10 -margins 2 2
vbackground GRAY40
vaxo
vfit
vactivate V1/CompView
vdump $::imagedir/${::casename}.png
vactivate V2/ViewLeft
vdump $::imagedir/${::casename}_left.png
vactivate V2/ViewRightTop
vdump $::imagedir/${::casename}_righttop.png
vactivate V3/ThumbView
vdump $::imagedir/${::casename}_thumb.png
vactivate V3/ViewRightBottom
vdump $::imagedir/${::casename}_rightbottom.png