1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56: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);
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)
{
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
// purpose :
@ -3002,6 +3060,8 @@ void AIS_ViewController::handleMoveTo (const Handle(AIS_InteractiveContext)& the
void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)& ,
const Handle(V3d_View)& theView)
{
Handle(V3d_View) aParentView = theView->IsSubview() ? theView->ParentView() : theView;
// manage animation state
if (!myViewAnimation.IsNull()
&& !myViewAnimation->IsStopped())
@ -3029,31 +3089,82 @@ void AIS_ViewController::handleViewRedraw (const Handle(AIS_InteractiveContext)&
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();
if (aView->IsInvalidated()
|| (myToAskNextFrame && aView == theView))
const bool isSubViewPass = (aSubViewPass == 0);
for (V3d_ListOfViewIterator aViewIter (theView->Viewer()->ActiveViewIterator()); aViewIter.More(); aViewIter.Next())
{
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())
{
aView->RedrawImmediate();
}
}
if (theView->IsSubview()
&& theView->Viewer() != aParentView->Viewer())
{
aParentView->RedrawImmediate();
}
if (myToAskNextFrame)
{
// 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);
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);
const AIS_WalkDelta aWalk = handleNavigationKeys (theCtx, theView);
handleXRInput (theCtx, theView, aWalk);
@ -3315,6 +3456,12 @@ void AIS_ViewController::HandleViewEvents (const Handle(AIS_InteractiveContext)&
theView->SetImmediateUpdate (wasImmediateUpdate);
if (!aPickedView.IsNull()
&& aPickedView != theView)
{
OnSubviewChanged (theCtx, theView, aPickedView);
}
// make sure to not process the same events twice
myGL.Reset();
myToAskNextFrame = false;

View File

@ -492,6 +492,12 @@ public:
const Handle(V3d_View)& theView,
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.
//! This method is expected to be called from rendering thread.
//! @param thePnt [out] result point

View File

@ -40,18 +40,58 @@ class Aspect_Window : public Standard_Transient
DEFINE_STANDARD_RTTIEXT(Aspect_Window, Standard_Transient)
public:
//! Modifies the window background.
Standard_EXPORT void SetBackground (const Aspect_Background& ABack);
//! 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 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.
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.
Standard_EXPORT void SetBackground (const Aspect_GradientBackground& ABackground);
Standard_EXPORT void SetBackground (const Aspect_GradientBackground& theBackground);
//! Modifies the window gradient background.
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>.
Standard_EXPORT virtual void Map() const = 0;
@ -65,25 +105,6 @@ public:
//! and returns TRUE if the window is mapped at screen.
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
//! WIDTH/HEIGHT dimensions
Standard_EXPORT virtual Standard_Real Ratio() const = 0;
@ -103,9 +124,6 @@ public:
//! Returns native Window FB config (GLXFBConfig on Xlib)
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.
virtual void SetTitle (const TCollection_AsciiString& theTitle) { (void )theTitle; }

View File

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

View File

@ -44,12 +44,8 @@ public:
Standard_EXPORT virtual void ReleaseGlResources (const Handle(OpenGl_Context)& theCtx) Standard_OVERRIDE;
//! Creates and maps rendering window to the view.
//! @param theWindow [in] the window.
//! @param theContext [in] the rendering context. If NULL the context will be created internally.
//! @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,
Standard_EXPORT virtual void SetWindow (const Handle(Graphic3d_CView)& theParentVIew,
const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext) Standard_OVERRIDE;
//! 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";
if (!TPrsStd_AISViewer::Find (aRoot, aDocViewer))
{
ViewerTest::ViewerInit (0, 0, 0, 0, aViewName.ToCString(), "");
ViewerTest::ViewerInit (aViewName);
aDocViewer = TPrsStd_AISViewer::New (aRoot, ViewerTest::GetAISContext());
}

View File

@ -13,6 +13,7 @@
#include <Graphic3d_CView.hxx>
#include <Aspect_NeutralWindow.hxx>
#include <Aspect_OpenVRSession.hxx>
#include <Graphic3d_CubeMapPacked.hxx>
#include <Graphic3d_Layer.hxx>
@ -26,18 +27,27 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CView,Graphic3d_DataStructureManager)
//purpose :
//=======================================================================
Graphic3d_CView::Graphic3d_CView (const Handle(Graphic3d_StructureManager)& theMgr)
: myBgColor (Quantity_NOC_BLACK),
myBackgroundType (Graphic3d_TOB_NONE),
myToUpdateSkydome (Standard_False),
myStructureManager (theMgr),
myCamera (new Graphic3d_Camera()),
myHiddenObjects (new Graphic3d_NMapOfTransient()),
myIsInComputedMode (Standard_False),
myIsActive (Standard_False),
myIsRemoved (Standard_False),
myBackfacing (Graphic3d_TypeOfBackfacingModel_Auto),
myVisualization (Graphic3d_TOV_WIREFRAME),
myUnitFactor (1.0)
: myId (0),
//
myParentView (nullptr),
myIsSubviewComposer (Standard_False),
mySubviewCorner (Aspect_TOTP_LEFT_UPPER),
mySubviewSize (1.0, 1.0),
//
myStructureManager (theMgr),
myCamera (new Graphic3d_Camera()),
myHiddenObjects (new Graphic3d_NMapOfTransient()),
myIsInComputedMode (Standard_False),
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);
}
@ -161,8 +171,21 @@ void Graphic3d_CView::Remove()
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())
{
Erase (aStructIter.Value());
@ -181,6 +204,114 @@ void Graphic3d_CView::Remove()
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
// purpose :

View File

@ -48,6 +48,7 @@
#include <Standard_Transient.hxx>
#include <TColStd_IndexedDataMapOfStringString.hxx>
class Aspect_NeutralWindow;
class Aspect_XRSession;
class Graphic3d_CView;
class Graphic3d_Layer;
@ -239,7 +240,7 @@ public:
virtual Standard_Boolean IsInvalidated() = 0;
//! 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:
//! 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;
//! Creates and maps rendering window to the view.
//! @param theWindow [in] the window.
//! @param theContext [in] the rendering context. If NULL the context will be created internally.
virtual void SetWindow (const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext = NULL) = 0;
//! @param[in] theParentVIew parent view or NULL
//! @param[in] theWindow the window
//! @param[in] theContext the rendering context; if NULL the context will be created internally
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.
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
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:
//! Adds the structure to display lists of the view.
@ -576,14 +643,14 @@ protected:
Standard_Integer myId;
Graphic3d_RenderingParams myRenderParams;
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_TypeOfBackground myBackgroundType; //!< Current type of background
Aspect_SkydomeBackground mySkydomeAspect;
Standard_Boolean myToUpdateSkydome;
NCollection_Sequence<Handle(Graphic3d_CView)> mySubviews; //!< list of child views
Graphic3d_CView* myParentView; //!< back-pointer to the parent view
Standard_Boolean myIsSubviewComposer; //!< flag to skip rendering of viewer contents
Aspect_TypeOfTriedronPosition mySubviewCorner; //!< position within parent view
Graphic3d_Vec2i mySubviewTopLeft; //!< subview top-left position relative to parent view
Graphic3d_Vec2i mySubviewMargins; //!< subview margins in pixels
Graphic3d_Vec2d mySubviewSize; //!< subview size
Graphic3d_Vec2d mySubviewOffset; //!< subview corner offset within parent view
Handle(Graphic3d_StructureManager) myStructureManager;
Handle(Graphic3d_Camera) myCamera;
@ -597,6 +664,16 @@ protected:
Graphic3d_TypeOfBackfacingModel myBackfacing;
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(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
@ -604,10 +681,6 @@ protected:
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)
protected:
Graphic3d_GraduatedTrihedron myGTrihedronData;
};
#endif // _Graphic3d_CView_HeaderFile

View File

@ -868,14 +868,16 @@ void OpenGl_GraphicDriver::RemoveView (const Handle(Graphic3d_CView)& theView)
}
// =======================================================================
// function : Window
// function : CreateRenderWindow
// 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)
{
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;
}

View File

@ -88,7 +88,13 @@ public:
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:

View File

@ -15,8 +15,8 @@
#include <OpenGl_View.hxx>
#include <Aspect_NeutralWindow.hxx>
#include <Aspect_RenderingContext.hxx>
#include <Aspect_Window.hxx>
#include <Aspect_XRSession.hxx>
#include <Graphic3d_AspectFillArea3d.hxx>
#include <Graphic3d_Texture2Dmanual.hxx>
@ -366,20 +366,57 @@ Standard_Boolean OpenGl_View::SetImmediateModeDrawToFront (const Standard_Boolea
// =======================================================================
Handle(Aspect_Window) OpenGl_View::Window() const
{
return myWindow->PlatformWindow();
return myWindow->SizeWindow();
}
// =======================================================================
// function : SetWindow
// 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)
{
myWindow = myDriver->CreateRenderWindow (theWindow, theContext);
Standard_ASSERT_RAISE (!myWindow.IsNull(),
"OpenGl_View::SetWindow, "
"Failed to create OpenGl window.");
if (theContext != nullptr
&& !theParentVIew.IsNull())
{
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);
myWorldViewProjState.Reset();
@ -414,10 +451,11 @@ void OpenGl_View::SetWindow (const Handle(Aspect_Window)& theWindow,
// =======================================================================
void OpenGl_View::Resized()
{
if (myWindow.IsNull())
return;
myWindow->Resize();
base_type::Resized();
if (!myWindow.IsNull())
{
myWindow->Resize();
}
}
// =======================================================================
@ -1157,9 +1195,10 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
const bool hasTextureMsaa = aCtx->HasTextureMultisampling();
bool toUseOit = myRenderParams.TransparencyMethod != Graphic3d_RTM_BLEND_UNORDERED
&& !myIsSubviewComposer
&& checkOitCompatibility (aCtx, aNbSamples > 0);
const bool toInitImmediateFbo = myTransientDrawToFront
const bool toInitImmediateFbo = myTransientDrawToFront && !myIsSubviewComposer
&& (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures()));
if ( aFrameBuffer == NULL
@ -1662,7 +1701,7 @@ void OpenGl_View::Redraw()
OpenGl_FrameBuffer* aFrameBuffer = myFBO.get();
bool toSwap = aCtx->IsRender()
&& !aCtx->caps->buffersNoSwap
&& aFrameBuffer == NULL
&& aFrameBuffer == nullptr
&& (!IsActiveXR() || myRenderParams.ToMirrorComposer);
if ( aFrameBuffer == NULL
&& !aCtx->DefaultFrameBuffer().IsNull()
@ -1738,7 +1777,9 @@ void OpenGl_View::Redraw()
{
toSwap = false;
}
else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip && toSwap)
else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
&& toSwap
&& myParentView == nullptr)
{
aCtx->SwapBuffers();
}
@ -1863,7 +1904,8 @@ void OpenGl_View::Redraw()
}
// Swap the buffers
if (toSwap)
if (toSwap
&& myParentView == nullptr)
{
aCtx->SwapBuffers();
if (!myMainSceneFbos[0]->IsValid())
@ -1969,8 +2011,9 @@ void OpenGl_View::RedrawImmediate()
Standard_True) || toSwap;
if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
&& toSwap
&& myFBO.get() == NULL
&& !aCtx->caps->buffersNoSwap)
&& myFBO.get() == nullptr
&& !aCtx->caps->buffersNoSwap
&& myParentView == nullptr)
{
aCtx->SwapBuffers();
}
@ -2035,7 +2078,8 @@ void OpenGl_View::RedrawImmediate()
if (toSwap
&& myFBO.get() == NULL
&& !aCtx->caps->buffersNoSwap)
&& !aCtx->caps->buffersNoSwap
&& myParentView == nullptr)
{
aCtx->SwapBuffers();
}
@ -2159,9 +2203,91 @@ bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProject
render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True);
blitSubviews (theProjection, theDrawFbo);
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
//purpose :
@ -2409,9 +2535,16 @@ void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
OpenGl_FrameBuffer* theOitAccumFbo,
const Standard_Boolean theToDrawImmediate)
{
myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate);
if ( myZLayers.NbStructures() <= 0 )
if (myIsSubviewComposer)
{
return;
}
myZLayers.UpdateCulling (myWorkspace, theToDrawImmediate);
if (myZLayers.NbStructures() <= 0)
{
return;
}
Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
Standard_Boolean toRenderGL = theToDrawImmediate ||

View File

@ -85,9 +85,8 @@ public:
Standard_EXPORT Standard_Boolean SetImmediateModeDrawToFront (const Standard_Boolean theDrawToFrontBuffer) Standard_OVERRIDE;
//! Creates and maps rendering window to the view.
//! @param theWindow [in] the window.
//! @param theContext [in] the rendering context. If NULL the context will be created internally.
Standard_EXPORT virtual void SetWindow (const Handle(Aspect_Window)& theWindow,
Standard_EXPORT virtual void SetWindow (const Handle(Graphic3d_CView)& theParentVIew,
const Handle(Aspect_Window)& theWindow,
const Aspect_RenderingContext theContext) Standard_OVERRIDE;
//! Returns window associated with the view.
@ -345,6 +344,10 @@ protected: //! @name low-level redrawing sub-routines
OpenGl_FrameBuffer* theOitAccumFbo,
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.
Standard_EXPORT bool blitBuffers (OpenGl_FrameBuffer* theReadFbo,
OpenGl_FrameBuffer* theDrawFbo,

View File

@ -169,17 +169,31 @@ namespace
// function : OpenGl_Window
// purpose :
// =======================================================================
OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
const Handle(Aspect_Window)& thePlatformWindow,
Aspect_RenderingContext theGContext,
const Handle(OpenGl_Caps)& theCaps,
const Handle(OpenGl_Context)& theShareCtx)
: myGlContext (new OpenGl_Context (theCaps)),
myOwnGContext (theGContext == 0),
myPlatformWindow (thePlatformWindow),
mySwapInterval (theCaps->swapInterval)
OpenGl_Window::OpenGl_Window()
: myOwnGContext (false),
mySwapInterval (0)
{
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;
@ -193,7 +207,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
&& (EGLContext )theGContext == EGL_NO_CONTEXT))
{
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window, EGL does not provide compatible configurations!");
return;
}
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
const int aSurfAttribs[] =
{
EGL_WIDTH, myWidth,
EGL_HEIGHT, myHeight,
EGL_WIDTH, mySize.x(),
EGL_HEIGHT, mySize.y(),
// 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_NONE
@ -258,8 +271,8 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
#if !defined(__EMSCRIPTEN__) // eglCreatePbufferSurface() is not implemented by Emscripten EGL
const int aSurfAttribs[] =
{
EGL_WIDTH, myWidth,
EGL_HEIGHT, myHeight,
EGL_WIDTH, mySize.x(),
EGL_HEIGHT, mySize.y(),
// 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_NONE
@ -322,7 +335,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: ChoosePixelFormat failed. Error code: ");
aMsg += (int )GetLastError();
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
}
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: ");
aMsg += (int )GetLastError();
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
}
// 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: ");
aMsg += (int )GetLastError();
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: ");
aMsg += (int )GetLastError();
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
}
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)
{
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)
{
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: window Visual does not support GL rendering!");
return;
}
// create new context
@ -635,7 +642,6 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
if (aGContext == NULL)
{
throw Aspect_GraphicDeviceDefinitionError("OpenGl_Window::CreateWindow: glXCreateContext failed.");
return;
}
}
@ -675,7 +681,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
#endif
myGlContext->Share (theShareCtx);
myGlContext->SetSwapInterval (mySwapInterval);
Init();
init();
}
// =======================================================================
@ -758,29 +764,29 @@ Standard_Boolean OpenGl_Window::Activate()
// =======================================================================
void OpenGl_Window::Resize()
{
Standard_Integer aWidth = 0, aHeight = 0;
myPlatformWindow->Size (aWidth, aHeight);
if (myWidth == aWidth
&& myHeight == aHeight)
Graphic3d_Vec2i aWinSize;
mySizeWindow->Size (aWinSize.x(), aWinSize.y());
if (mySize == aWinSize)
{
// if the size is not changed - do nothing
return;
}
myWidth = aWidth;
myHeight = aHeight;
mySize = aWinSize;
Init();
init();
}
// =======================================================================
// function : Init
// function : init
// purpose :
// =======================================================================
void OpenGl_Window::Init()
void OpenGl_Window::init()
{
if (!Activate())
{
return;
}
#if defined(HAVE_EGL)
if ((EGLSurface )myGlContext->myWindow == EGL_NO_SURFACE)
@ -800,7 +806,7 @@ void OpenGl_Window::Init()
OpenGl_ColorFormats aColorFormats;
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");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
@ -810,8 +816,8 @@ void OpenGl_Window::Init()
}
else if (!myPlatformWindow->IsVirtual())
{
eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &myWidth);
eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &myHeight);
eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_WIDTH, &mySize.x());
eglQuerySurface ((EGLDisplay )myGlContext->myDisplay, (EGLSurface )myGlContext->myWindow, EGL_HEIGHT, &mySize.y());
}
#else
//
@ -819,7 +825,7 @@ void OpenGl_Window::Init()
myGlContext->core11fwd->glDisable (GL_DITHER);
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->SetDrawBuffer (GL_BACK);
if (myGlContext->core11ffp != NULL)

View File

@ -37,21 +37,26 @@
class OpenGl_Context;
class OpenGl_GraphicDriver;
class OpenGl_Window;
DEFINE_STANDARD_HANDLE(OpenGl_Window,Standard_Transient)
//! This class represents low-level wrapper over window with GL context.
//! The window itself should be provided to constructor.
class OpenGl_Window : public Standard_Transient
{
DEFINE_STANDARD_RTTIEXT(OpenGl_Window, Standard_Transient)
public:
//! Main constructor - prepare GL context for specified window.
Standard_EXPORT OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
const Handle(Aspect_Window)& thePlatformWindow,
Aspect_RenderingContext theGContext,
const Handle(OpenGl_Caps)& theCaps,
const Handle(OpenGl_Context)& theShareCtx);
//! Empty constructor.
Standard_EXPORT OpenGl_Window();
//! Initialize the new window - prepare GL context for specified window.
//! Throws exception in case of failure.
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
Standard_EXPORT virtual ~OpenGl_Window();
@ -59,44 +64,45 @@ public:
//! Resizes the window.
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; }
Standard_Integer Height() const { return myHeight; }
//! Return window object defining dimensions.
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; }
//! Activates GL context and setup viewport.
Standard_EXPORT void Init();
//! Makes GL context for this window active in current thread
Standard_EXPORT virtual Standard_Boolean Activate();
//! Sets swap interval for this window according to the context's settings.
Standard_EXPORT void SetSwapInterval (Standard_Boolean theToForceNoSync);
protected:
//! Activates GL context and setup viewport.
Standard_EXPORT void init();
protected:
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) mySizeWindow; //!< window object defining dimensions
#if defined(__APPLE__)
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
UIView* myUIView;
#endif
Standard_Integer myWidthPt; //!< window width in logical units
Standard_Integer myHeightPt; //!< window height in logical units
Graphic3d_Vec2i mySizePt; //!< window width x height in logical units
#endif
Standard_Integer myWidth; //!< window width in pixels
Standard_Integer myHeight; //!< window height in pixels
Graphic3d_Vec2i mySize; //!< window width x height in pixels
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

View File

@ -56,25 +56,38 @@
// function : OpenGl_Window
// purpose :
// =======================================================================
OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
const Handle(Aspect_Window)& thePlatformWindow,
Aspect_RenderingContext theGContext,
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)
OpenGl_Window::OpenGl_Window()
: myOwnGContext (false),
mySwapInterval (0)
{
//
}
// =======================================================================
// 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;
myPlatformWindow->Size (myWidth, myHeight);
mySizeWindow->Size (mySize.x(), mySize.y());
#if defined(__APPLE__)
myWidthPt = myWidth;
myHeightPt = myHeight;
mySizePt = mySize;
#endif
#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");
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");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
}
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");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
return;
}
if (aTryStereo == 0
@ -227,7 +237,7 @@ OpenGl_Window::OpenGl_Window (const Handle(OpenGl_GraphicDriver)& theDriver,
myGlContext->Share (theShareCtx);
myGlContext->SetSwapInterval (mySwapInterval);
Init();
init();
}
// =======================================================================
@ -266,9 +276,9 @@ void OpenGl_Window::Resize()
// If the size is not changed - do nothing
Standard_Integer aWidthPt = 0;
Standard_Integer aHeightPt = 0;
myPlatformWindow->Size (aWidthPt, aHeightPt);
if (myWidthPt == aWidthPt
&& myHeightPt == aHeightPt)
mySizeWindow->Size (aWidthPt, aHeightPt);
if (mySizePt.x() == aWidthPt
&& mySizePt.y() == aHeightPt)
{
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
return;
@ -285,25 +295,25 @@ void OpenGl_Window::Resize()
NSRect aBounds = [aView bounds];
NSSize aRes = [aView convertSizeToBacking: aBounds.size];
if (myWidth == Standard_Integer(aRes.width)
&& myHeight == Standard_Integer(aRes.height))
if (mySize.x() == Standard_Integer(aRes.width)
&& mySize.y() == Standard_Integer(aRes.height))
{
return;
}
#endif
}
myWidthPt = aWidthPt;
myHeightPt = aHeightPt;
mySizePt.x() = aWidthPt;
mySizePt.y() = aHeightPt;
Init();
init();
}
// =======================================================================
// function : Init
// function : init
// purpose :
// =======================================================================
void OpenGl_Window::Init()
void OpenGl_Window::init()
{
if (!Activate())
{
@ -329,11 +339,11 @@ void OpenGl_Window::Init()
myGlContext->Functions()->glGenRenderbuffers (1, &aWinRBColor);
myGlContext->Functions()->glBindRenderbuffer (GL_RENDERBUFFER, aWinRBColor);
[aGLCtx renderbufferStorage: GL_RENDERBUFFER fromDrawable: anEaglLayer];
myGlContext->Functions()->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &myWidth);
myGlContext->Functions()->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &myHeight);
myGlContext->Functions()->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &mySize.x());
myGlContext->Functions()->glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &mySize.y());
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");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());
@ -349,8 +359,8 @@ void OpenGl_Window::Init()
return;
}
myWidth = aDefFbo->GetVPSizeX();
myHeight = aDefFbo->GetVPSizeY();
mySize.x() = aDefFbo->GetVPSizeX();
mySize.y() = aDefFbo->GetVPSizeY();
}
myGlContext->SetDefaultFrameBuffer (aDefFbo);
aDefFbo->BindBuffer (myGlContext);
@ -368,21 +378,21 @@ Standard_ENABLE_DEPRECATION_WARNINGS
if ([aView respondsToSelector: @selector(convertSizeToBacking:)])
{
NSSize aRes = [aView convertSizeToBacking: aBounds.size];
myWidth = Standard_Integer(aRes.width);
myHeight = Standard_Integer(aRes.height);
mySize.x() = Standard_Integer(aRes.width);
mySize.y() = Standard_Integer(aRes.height);
}
else
{
myWidth = Standard_Integer(aBounds.size.width);
myHeight = Standard_Integer(aBounds.size.height);
mySize.x() = Standard_Integer(aBounds.size.width);
mySize.y() = Standard_Integer(aBounds.size.height);
}
myWidthPt = Standard_Integer(aBounds.size.width);
myHeightPt = Standard_Integer(aBounds.size.height);
mySizePt.x() = Standard_Integer(aBounds.size.width);
mySizePt.y() = Standard_Integer(aBounds.size.height);
#endif
myGlContext->core11fwd->glDisable (GL_DITHER);
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)
{
myGlContext->core11fwd->glDrawBuffer (GL_BACK);

View File

@ -16,6 +16,7 @@
#include <Aspect_CircularGrid.hxx>
#include <Aspect_GradientBackground.hxx>
#include <Aspect_Grid.hxx>
#include <Aspect_NeutralWindow.hxx>
#include <Aspect_RectangularGrid.hxx>
#include <Aspect_Window.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()
{
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())
{
myView->Remove();
@ -164,7 +186,7 @@ void V3d_View::SetMagnify (const Handle(Aspect_Window)& theWindow,
Standard_Real aU1, aV1, aU2, aV2;
thePreviousView->Convert (theX1, theY1, aU1, aV1);
thePreviousView->Convert (theX2, theY2, aU2, aV2);
myView->SetWindow (theWindow);
myView->SetWindow (Handle(Graphic3d_CView)(), theWindow, nullptr);
FitAll (aU1, aV1, aU2, aV2);
MyViewer->SetViewOn (this);
MyWindow = theWindow;
@ -185,10 +207,14 @@ void V3d_View::SetWindow (const Handle(Aspect_Window)& theWindow,
{
return;
}
if (myParentView != nullptr)
{
throw Standard_ProgramError ("V3d_View::SetWindow() called twice");
}
// method V3d_View::SetWindow() should assign the field MyWindow before calling Redraw()
MyWindow = theWindow;
myView->SetWindow (theWindow, theContext);
myView->SetWindow (Handle(Graphic3d_CView)(), theWindow, theContext);
MyViewer->SetViewOn (this);
SetRatio();
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
//purpose :
@ -212,10 +281,83 @@ void V3d_View::Remove()
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();
Handle(Aspect_Window)& aWin = const_cast<Handle(Aspect_Window)&> (MyWindow);
aWin.Nullify();
MyWindow.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)
class V3d_View : public Standard_Transient
{
DEFINE_STANDARD_RTTIEXT(V3d_View, Standard_Transient)
public:
//! Initializes the view.
@ -97,6 +97,25 @@ public:
Standard_EXPORT void SetWindow (const Handle(Aspect_Window)& theWindow,
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,
const Handle(V3d_View)& thePreviousView,
const Standard_Integer theX1,
@ -953,7 +972,25 @@ public:
//! Dumps the content of me into the stream
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
@ -1033,6 +1070,10 @@ protected:
private:
V3d_Viewer* MyViewer;
NCollection_Sequence<Handle(V3d_View)> mySubviews;
V3d_View* myParentView;
V3d_ListOfLight myActiveLights;
gp_Dir myDefaultViewAxis;
gp_Pnt myDefaultViewPoint;

View File

@ -143,9 +143,23 @@ void V3d_Viewer::SetViewOff (const Handle(V3d_View)& theView)
// ========================================================================
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
{
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
// purpose :
// ========================================================================
void V3d_Viewer::DelView (const Handle(V3d_View)& theView)
void V3d_Viewer::DelView (const V3d_View* theView)
{
myActiveViews.Remove (theView);
myDefinedViews.Remove (theView);
for (V3d_ListOfView::Iterator aViewIter (myActiveViews); aViewIter.More(); aViewIter.Next())
{
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);
//! Delete View in Sequence Of Views.
Standard_EXPORT void DelView (const Handle(V3d_View)& theView);
Standard_EXPORT void DelView (const V3d_View* theView);
private:

View File

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

View File

@ -18,8 +18,10 @@
#include <AIS_KindOfInteractive.hxx>
#include <Aspect_TypeOfLine.hxx>
#include <Aspect_TypeOfMarker.hxx>
#include <Aspect_TypeOfTriedronPosition.hxx>
#include <Draw_Interpretor.hxx>
#include <Graphic3d_TypeOfShadingModel.hxx>
#include <Graphic3d_Vec2.hxx>
#include <Graphic3d_ZLayerId.hxx>
#include <TCollection_AsciiString.hxx>
#include <TColStd_HArray1OfTransient.hxx>
@ -36,6 +38,23 @@ class ViewerTest_EventManager;
class TopoDS_Shape;
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
{
public:
@ -45,25 +64,39 @@ public:
//! Loads all Draw commands of V2d & V3d. Used for plugin.
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.
//! @param thePxLeft left position of newly created window
//! @param thePxTop top position of newly created window
//! @param thePxWidth width of newly created window
//! @param thePxHeight height of newly created window
//! @param theViewName name of newly created View
//! @oaram theDisplayName display name
//! @param theViewToClone when specified, the new View will copy properties of existing one
//! @param theIsVirtual force creation of virtual off-screen window within interactive session
Standard_EXPORT static TCollection_AsciiString ViewerInit (const Standard_Integer thePxLeft = 0,
const Standard_Integer thePxTop = 0,
const Standard_Integer thePxWidth = 0,
const Standard_Integer thePxHeight = 0,
const TCollection_AsciiString& theViewName = "",
const TCollection_AsciiString& theDisplayName = "",
const Handle(V3d_View)& theViewToClone = Handle(V3d_View)(),
const Standard_Boolean theIsVirtual = false);
Standard_EXPORT static TCollection_AsciiString ViewerInit (const ViewerTest_VinitParams& theParams);
//! Creates view.
static TCollection_AsciiString ViewerInit (const TCollection_AsciiString& theViewName = "")
{
ViewerTest_VinitParams aParams;
aParams.ViewName = theViewName;
return ViewerInit (aParams);
}
//! Creates view.
static TCollection_AsciiString ViewerInit (const Standard_Integer thePxLeft,
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 = 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);
@ -72,6 +105,10 @@ public:
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
//! with information about its resources if necessary
Standard_EXPORT static void RemoveView (const TCollection_AsciiString& theViewName,
@ -207,6 +244,10 @@ public:
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
//! 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())
{
myContext->UpdateCurrentViewer();
if (!myView.IsNull()
&& myView->IsSubview()
&& myView->ParentView()->Viewer() != myContext->CurrentViewer())
{
myView->ParentView()->RedrawImmediate();
}
}
else if (!myView.IsNull())
{
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);
}
//=======================================================================
//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
//purpose :
@ -154,6 +178,22 @@ bool ViewerTest_EventManager::UpdateMouseButtons (const Graphic3d_Vec2i& thePoin
Aspect_VKeyFlags theModifiers,
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());
if (theButtons == Aspect_VKeyMouse_LeftButton)
@ -232,22 +272,45 @@ void ViewerTest_EventManager::handleViewRedraw (const Handle(AIS_InteractiveCont
//==============================================================================
void ViewerTest_EventManager::ProcessConfigure (bool theIsResized)
{
if (!myView.IsNull())
if (myView.IsNull())
{
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;
}
myView->Window()->DoResize();
myView->MustBeResized();
myView->Invalidate();
FlushViewEvents (myCtx, myView, true);
return;
}
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;
}
//! Update mouse scroll event.
Standard_EXPORT virtual bool UpdateMouseScroll (const Aspect_ScrollDelta& theDelta) Standard_OVERRIDE;
//! Handle mouse button click event.
Standard_EXPORT virtual bool UpdateMouseClick (const Graphic3d_Vec2i& thePoint,
Aspect_VKeyMouse theButton,
@ -116,6 +119,12 @@ public:
//! Handle KeyPress event.
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:
//! Register hot-keys for specified Action.

View File

@ -932,7 +932,10 @@ static Standard_Integer VListColors (Draw_Interpretor& theDI,
Handle(V3d_View) aView;
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->SetImmediateUpdate (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
//==============================================================================
TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
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)
TCollection_AsciiString ViewerTest::ViewerInit (const ViewerTest_VinitParams& theParams)
{
// Default position and dimension of the viewer window.
// 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).
// The position corresponds to the window's client area, thus some
// gap is added for window frame to be visible.
Standard_Integer aPxLeft = 20, aPxTop = 40;
Standard_Integer aPxWidth = 409, aPxHeight = 409;
Graphic3d_Vec2d aPxTopLeft (20, 40);
Graphic3d_Vec2d aPxSize (409, 409);
Standard_Boolean isDefViewSize = Standard_True;
Standard_Boolean toCreateViewer = Standard_False;
const Standard_Boolean isVirtual = Draw_VirtualWindows || theIsVirtual;
if (!theViewToClone.IsNull())
const Standard_Boolean isVirtual = Draw_VirtualWindows || theParams.IsVirtual;
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;
#if !defined(__EMSCRIPTEN__)
(void )isDefViewSize;
@ -522,40 +517,21 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
}
Handle(Graphic3d_GraphicDriver) aGraphicDriver;
ViewerTest_Names aViewNames(theViewName);
ViewerTest_Names aViewNames (theParams.ViewName);
if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
{
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)
const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
if (isNewDriver)
{
// Get connection string
#if defined(HAVE_XLIB)
if (!theDisplayName.IsEmpty())
if (!theParams.DisplayName.IsEmpty())
{
SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
SetDisplayConnection (new Aspect_DisplayConnection (theParams.DisplayName));
}
else
{
@ -569,7 +545,6 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
}
#else
(void)theDisplayName; // avoid warning on unused argument
SetDisplayConnection (new Aspect_DisplayConnection ());
#endif
@ -588,53 +563,89 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
aGraphicDriver = ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName());
}
//Dispose the window if input parameters are default
if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
{
Standard_Integer aTop = 0,
aLeft = 0,
aRight = 0,
aBottom = 0,
aScreenWidth = 0,
aScreenHeight = 0;
// Get screen resolution
// Get screen resolution
Graphic3d_Vec2i aScreenSize;
#if defined(_WIN32)
RECT aWindowSize;
GetClientRect(GetDesktopWindow(), &aWindowSize);
aScreenHeight = aWindowSize.bottom;
aScreenWidth = aWindowSize.right;
RECT aWindowSize;
GetClientRect(GetDesktopWindow(), &aWindowSize);
aScreenSize.SetValues (aWindowSize.right, aWindowSize.bottom);
#elif defined(HAVE_XLIB)
::Display* aDispX = (::Display* )GetDisplayConnection()->GetDisplayAspect();
Screen* aScreen = DefaultScreenOfDisplay(aDispX);
aScreenWidth = WidthOfScreen(aScreen);
aScreenHeight = HeightOfScreen(aScreen);
::Display* aDispX = (::Display* )GetDisplayConnection()->GetDisplayAspect();
Screen* aScreen = DefaultScreenOfDisplay(aDispX);
aScreenSize.x() = WidthOfScreen(aScreen);
aScreenSize.y() = HeightOfScreen(aScreen);
#elif defined(__APPLE__)
GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
GetCocoaScreenResolution (aScreenSize.x(), aScreenSize.y());
#else
// not implemented
// not implemented
#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);
if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
&& aRight + 2*aPxWidth + 40 > aScreenWidth)
if (IsWindowOverlapped (aRight + 20, (int )aPxTopLeft.y(), aRight + 20 + (int )aPxSize.x(),
(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;
aPxTop = 40;
aPxTopLeft.x() = 20;
aPxTopLeft.y() = 40;
break;
}
aPxLeft = 20;
aPxTop = aBottom + 40;
aPxTopLeft.x() = 20;
aPxTopLeft.y() = aBottom + 40;
}
else
aPxLeft = aRight + 20;
{
aPxTopLeft.x() = aRight + 20;
}
}
}
@ -688,61 +699,76 @@ TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft
}
// Create window
#if defined(_WIN32)
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())
if (!theParams.ParentView.IsNull())
{
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);
Graphic3d_Vec2i aRealSize;
VT_GetWindow()->Size (aRealSize.x(), aRealSize.y());
if (!isDefViewSize || (aRealSize.x() <= 0 && aRealSize.y() <= 0))
{
// 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),
// but resize canvas if vinit has been called with explicitly specified dimensions.
VT_GetWindow()->SetSizeLogical (Graphic3d_Vec2d (aPxWidth, aPxHeight));
VT_GetWindow() = new Wasm_Window (aCanvasId);
Graphic3d_Vec2i aRealSize;
VT_GetWindow()->Size (aRealSize.x(), aRealSize.y());
if (!isDefViewSize || (aRealSize.x() <= 0 && aRealSize.y() <= 0))
{
// 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),
// but resize canvas if vinit has been called with explicitly specified dimensions.
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
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
{
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::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)
{
TCollection_AsciiString aViewName, aDisplayName;
Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
Standard_Boolean isVirtual = false;
Handle(V3d_View) aCopyFrom;
ViewerTest_VinitParams aParams;
TCollection_AsciiString aName, aValue;
int is2dMode = -1, aDpiAware = -1;
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
&& anArgCase == "-name")
{
aViewName = theArgVec[++anArgIt];
aParams.ViewName = theArgVec[++anArgIt];
}
else if (anArgIt + 1 < theArgsNb
&& (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
&& (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
&& (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
&& (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"
|| anArgCase == "-offscreen")
{
isVirtual = true;
if (anArgIt + 1 < theArgsNb
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], isVirtual))
{
++anArgIt;
}
aParams.IsVirtual = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
}
else if (anArgCase == "-composer")
{
aParams.IsComposer = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);
}
else if (anArgCase == "-exitonclose")
{
ViewerTest_EventManager::ToExitOnCloseView() = true;
if (anArgIt + 1 < theArgsNb
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
{
++anArgIt;
}
ViewerTest_EventManager::ToExitOnCloseView() = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
}
else if (anArgCase == "-closeonescape"
|| anArgCase == "-closeonesc")
{
ViewerTest_EventManager::ToCloseViewOnEscape() = true;
if (anArgIt + 1 < theArgsNb
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
{
++anArgIt;
}
ViewerTest_EventManager::ToCloseViewOnEscape() = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
}
else if (anArgCase == "-2d_mode"
|| anArgCase == "-2dmode"
|| anArgCase == "-2d")
{
bool toEnable = true;
if (anArgIt + 1 < theArgsNb
&& Draw::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
{
++anArgIt;
}
bool toEnable = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt);;
is2dMode = toEnable ? 1 : 0;
}
else if (anArgIt + 1 < theArgsNb
&& (anArgCase == "-disp"
|| anArgCase == "-display"))
{
aDisplayName = theArgVec[++anArgIt];
aParams.DisplayName = theArgVec[++anArgIt];
}
else if (anArgCase == "-dpiaware")
{
aDpiAware = Draw::ParseOnOffIterator (theArgsNb, theArgVec, anArgIt) ? 1 : 0;
}
else if (!ViewerTest::CurrentView().IsNull()
&& aCopyFrom.IsNull()
&& aParams.ViewToClone.IsNull()
&& (anArgCase == "-copy"
|| anArgCase == "-clone"
|| anArgCase == "-cloneactive"
|| 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
else if (ViewerTest::SplitParameter (anArg, aName, aValue))
@ -1058,32 +1118,32 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
aName.LowerCase();
if (aName == "name")
{
aViewName = aValue;
aParams.ViewName = aValue;
}
else if (aName == "l"
|| aName == "left")
{
aPxLeft = aValue.IntegerValue();
aParams.Offset.x() = (float)aValue.RealValue();
}
else if (aName == "t"
|| aName == "top")
{
aPxTop = aValue.IntegerValue();
aParams.Offset.y() = (float)aValue.RealValue();
}
else if (aName == "disp"
|| aName == "display")
{
aDisplayName = aValue;
aParams.DisplayName = aValue;
}
else if (aName == "w"
|| aName == "width")
{
aPxWidth = aValue.IntegerValue();
aParams.Size.x() = (float )aValue.RealValue();
}
else if (aName == "h"
|| aName == "height")
{
aPxHeight = aValue.IntegerValue();
aParams.Size.y() = (float)aValue.RealValue();
}
else
{
@ -1091,9 +1151,9 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
return 1;
}
}
else if (aViewName.IsEmpty())
else if (aParams.ViewName.IsEmpty())
{
aViewName = anArg;
aParams.ViewName = anArg;
}
else
{
@ -1134,15 +1194,15 @@ static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const cha
#else
(void )aDpiAware;
#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";
}
#endif
#endif
ViewerTest_Names aViewNames (aViewName);
ViewerTest_Names aViewNames (aParams.ViewName);
if (ViewerTest_myViews.IsBound1 (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;
}
TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
aViewName, aDisplayName, aCopyFrom, isVirtual);
TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aParams);
if (is2dMode != -1)
{
ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
@ -1422,29 +1481,59 @@ static TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWind
void ActivateView (const TCollection_AsciiString& theViewName,
Standard_Boolean theToUpdate = Standard_True)
{
const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
if (aView.IsNull())
if (const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName))
{
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;
}
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));
}
}
ViewerTest::CurrentView (aView);
ViewerTest::SetAISContext (anAISContext);
aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)");
VT_GetWindow() = Handle(ViewerTest_Window)::DownCast(ViewerTest::CurrentView()->Window());
SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
if (theToUpdate)
{
ViewerTest::CurrentView()->Redraw();
}
ViewerTest::CurrentView (aView);
ViewerTest::SetAISContext (anAISContext);
if (aView->IsSubview())
{
aView->ParentView()->Window()->SetTitle (TCollection_AsciiString("3D View - ") + *aViewName + "(*)");
VT_GetWindow() = Handle(ViewerTest_Window)::DownCast(aView->View()->ParentView()->Window());
}
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;
}
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
if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
{
if (ViewerTest_myViews.Extent() > 1)
{
TCollection_AsciiString aNewViewName;
for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
anIter.More(); anIter.Next())
{
if (anIter.Key1() != theViewName)
{
aNewViewName = anIter.Key1();
ActivateView (anIter.Value(), true);
break;
}
}
ActivateView (aNewViewName);
}
else
{
@ -1506,14 +1606,11 @@ void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const S
}
// 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);
aView->Window()->Unmap();
if (!aView->Window().IsNull())
{
aView->Window()->Unmap();
}
aView->Remove();
#if defined(HAVE_XLIB)
@ -3196,47 +3293,13 @@ static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
{
if (++anArgIter >= theArgNb)
{
Message::SendFail() << "Error: wrong syntax at '" << anArg << "'";
Message::SendFail() << "Syntax error at '" << anArg << "'";
return 1;
}
TCollection_AsciiString aPosName (theArgVec[anArgIter]);
aPosName.LowerCase();
if (aPosName == "center")
if (!ViewerTest::ParseCorner (theArgVec[anArgIter], aPosition))
{
aPosition = Aspect_TOTP_CENTER;
}
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 << "'";
Message::SendFail() << "Syntax error at '" << anArg << "' - unknown position '" << theArgVec[anArgIter] << "'";
return 1;
}
}
@ -6158,15 +6221,13 @@ static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const
theDI.Eval (aCommand.ToCString());
}
Standard_Integer aPxLeft = 0;
Standard_Integer aPxTop = 0;
Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
? int(anImgRef->SizeY() * 2)
: int(anImgRef->SizeY());
TCollection_AsciiString aDisplayName;
TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
aViewName, aDisplayName);
ViewerTest_VinitParams aParams;
aParams.ViewName = aViewName;
aParams.Size.x() = float(anImgRef->SizeX() * 2);
aParams.Size.y() = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
? float(anImgRef->SizeY() * 2)
: float(anImgRef->SizeY());
TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aParams);
Standard_Real aRatio = anImgRef->Ratio();
Standard_Real aSizeX = 1.0;
@ -13801,8 +13862,9 @@ Makes specified driver active when ActiveName argument is specified.
addCmd ("vinit", VInit, /* [vinit] */ R"(
vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]
[-exitOnClose] [-closeOnEscape] [-cloneActive] [-virtual {on|off}=off] [-2d_mode {on|off}=off]
[-display displayName] [-dpiAware {on|off}]
[-exitOnClose] [-closeOnEscape] [-cloneActive] [-virtual {0|1}]=0 [-2d_mode {0|1}]=0
[-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.
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}
@ -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.
-closeOnEscape when specified, view will be closed on pressing Escape.
-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
-dpiAware override dpi aware hint (Windows platform)
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";
if (!TPrsStd_AISViewer::Find (aRoot, aDocViewer))
{
ViewerTest::ViewerInit (0, 0, 0, 0, aViewName.ToCString(), "");
ViewerTest::ViewerInit (aViewName);
aDocViewer = TPrsStd_AISViewer::New (aRoot, ViewerTest::GetAISContext());
}
@ -1322,7 +1322,7 @@ static Standard_Integer testDoc (Draw_Interpretor&,
aD1->Open(anApp);
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());
// 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