0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[occt.git] / src / AIS / AIS_MediaPlayer.cxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2019 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <AIS_MediaPlayer.hxx>
16
17 #include <AIS_InteractiveContext.hxx>
18 #include <Media_PlayerContext.hxx>
19 #include <Message.hxx>
20 #include <Message_Messenger.hxx>
21 #include <Graphic3d_ArrayOfTriangles.hxx>
22 #include <Graphic3d_MediaTexture.hxx>
23 #include <SelectMgr_EntityOwner.hxx>
24 #include <Select3D_SensitivePrimitiveArray.hxx>
25 #include <V3d_Viewer.hxx>
26
27 IMPLEMENT_STANDARD_RTTIEXT(AIS_MediaPlayer, AIS_InteractiveObject)
28
29 //! Create an array of triangles defining a rectangle.
30 static Handle(Graphic3d_ArrayOfTriangles) createRectangleArray (const Graphic3d_Vec2i& theLower,
31                                                                 const Graphic3d_Vec2i& theUpper,
32                                                                 Graphic3d_ArrayFlags theFlags)
33 {
34   Handle(Graphic3d_ArrayOfTriangles) aRectTris = new Graphic3d_ArrayOfTriangles (4, 6, theFlags);
35   aRectTris->AddVertex (gp_Pnt (theLower.x(), theLower.y(), 0.0), gp_Pnt2d (0.0, 1.0));
36   aRectTris->AddVertex (gp_Pnt (theLower.x(), theUpper.y(), 0.0), gp_Pnt2d (0.0, 0.0));
37   aRectTris->AddVertex (gp_Pnt (theUpper.x(), theUpper.y(), 0.0), gp_Pnt2d (1.0, 0.0));
38   aRectTris->AddVertex (gp_Pnt (theUpper.x(), theLower.y(), 0.0), gp_Pnt2d (1.0, 1.0));
39   aRectTris->AddEdges (1, 2, 3);
40   aRectTris->AddEdges (1, 3, 4);
41   return aRectTris;
42 }
43
44 //================================================================
45 // Function : AIS_MediaPlayer
46 // Purpose  :
47 //================================================================
48 AIS_MediaPlayer::AIS_MediaPlayer()
49 : myFramePair (new Graphic3d_MediaTextureSet()),
50   myFrameSize (1, 1),
51   myToClosePlayer (false)
52 {
53   SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
54   SetZLayer (Graphic3d_ZLayerId_TopOSD);
55   SetInfiniteState (true);
56
57   Graphic3d_MaterialAspect aMat;
58   myFrameAspect = new Graphic3d_AspectFillArea3d (Aspect_IS_SOLID, Quantity_NOC_WHITE, Quantity_NOC_BLACK, Aspect_TOL_SOLID, 1.0f, aMat, aMat);
59   myFrameAspect->SetShadingModel (Graphic3d_TOSM_UNLIT);
60   myFrameAspect->SetTextureMapOn (true);
61   myFrameAspect->SetTextureSet (myFramePair);
62 }
63
64 //================================================================
65 // Function : ~AIS_MediaPlayer
66 // Purpose  :
67 //================================================================
68 AIS_MediaPlayer::~AIS_MediaPlayer()
69 {
70   // stop threads
71   myFramePair.Nullify();
72 }
73
74 // =======================================================================
75 // function : OpenInput
76 // purpose  :
77 // =======================================================================
78 void AIS_MediaPlayer::OpenInput (const TCollection_AsciiString& thePath,
79                                  Standard_Boolean theToWait)
80 {
81   if (myFramePair->PlayerContext().IsNull()
82    && thePath.IsEmpty())
83   {
84     return;
85   }
86
87   myFramePair->OpenInput (thePath, theToWait);
88   SynchronizeAspects();
89 }
90
91 // =======================================================================
92 // function : PresentFrame
93 // purpose  :
94 // =======================================================================
95 bool AIS_MediaPlayer::PresentFrame (const Graphic3d_Vec2i& theLeftCorner,
96                                     const Graphic3d_Vec2i& theMaxSize)
97 {
98   if (myToClosePlayer)
99   {
100     myToClosePlayer = false;
101     if (!HasInteractiveContext())
102     {
103       return false;
104     }
105
106     if (!myFramePair->PlayerContext().IsNull())
107     {
108       myFramePair->PlayerContext()->Pause();
109     }
110
111     Handle(AIS_InteractiveContext) aCtx = GetContext();
112     Handle(AIS_InteractiveObject) aThis = this;
113     aCtx->Remove (aThis, false);
114     aCtx->CurrentViewer()->Invalidate();
115     return true;
116   }
117
118   if (myFramePair->PlayerContext().IsNull())
119   {
120     return false;
121   }
122
123   bool toRedraw = myFramePair->SwapFrames();
124   toRedraw = updateSize (theLeftCorner, theMaxSize) || toRedraw;
125   if (toRedraw)
126   {
127     myFrameAspect->SetShaderProgram (myFramePair->ShaderProgram());
128     SynchronizeAspects();
129   }
130   return toRedraw;
131 }
132
133 // =======================================================================
134 // function : updateSize
135 // purpose  :
136 // =======================================================================
137 bool AIS_MediaPlayer::updateSize (const Graphic3d_Vec2i& theLeftCorner,
138                                   const Graphic3d_Vec2i& theMaxSize)
139 {
140   const Graphic3d_Vec2i aFrameSize = myFramePair->FrameSize();
141   Graphic3d_Vec2i aNewPos  = theLeftCorner;
142   Graphic3d_Vec2i aNewSize = myFrameSize;
143   if (aFrameSize.x() > 0
144    && aFrameSize.y() > 0)
145   {
146     const double anAspect   = double(theMaxSize.x()) / double(theMaxSize.y());
147     const double aFitAspect = double(aFrameSize.x()) / double(aFrameSize.y());
148     aNewSize = aFrameSize;
149     if (aFitAspect >= anAspect)
150     {
151       aNewSize.y() = int(double(aFrameSize.x()) / aFitAspect);
152     }
153     else
154     {
155       aNewSize.x() = int(double(aFrameSize.y()) * aFitAspect);
156     }
157
158     for (int aCoord = 0; aCoord < 2; ++aCoord)
159     {
160       if (aNewSize[aCoord] > theMaxSize[aCoord])
161       {
162         const double aScale = double(theMaxSize[aCoord]) / double(aNewSize[aCoord]);
163         aNewSize.x() = int(double(aNewSize.x()) * aScale);
164         aNewSize.y() = int(double(aNewSize.y()) * aScale);
165       }
166     }
167
168     aNewPos = theLeftCorner + theMaxSize / 2 - aNewSize / 2;
169   }
170   else if (myFrameSize.x() < 2
171         || myFrameSize.y() < 2)
172   {
173     aNewSize = theMaxSize;
174   }
175
176   if (myFrameSize == aNewSize
177    && myFrameBottomLeft == aNewPos)
178   {
179     return false;
180   }
181
182   myFrameSize = aNewSize;
183   myFrameBottomLeft = aNewPos;
184   if (HasInteractiveContext())
185   {
186     SetToUpdate();
187     GetContext()->Redisplay (this, false);
188     GetContext()->CurrentViewer()->Invalidate();
189   }
190   return true;
191 }
192
193 // =======================================================================
194 // function : PlayPause
195 // purpose  :
196 // =======================================================================
197 void AIS_MediaPlayer::PlayPause()
198 {
199   if (myFramePair->PlayerContext().IsNull())
200   {
201     return;
202   }
203
204   Standard_Real aProgress = 0.0, aDuration = 0.0;
205   bool isPaused = false;
206   myFramePair->PlayerContext()->PlayPause (isPaused, aProgress, aDuration);
207 }
208
209 // =======================================================================
210 // function : Compute
211 // purpose  :
212 // =======================================================================
213 void AIS_MediaPlayer::Compute (const Handle(PrsMgr_PresentationManager3d)& ,
214                                const Handle(Prs3d_Presentation)& thePrs,
215                                const Standard_Integer theMode)
216 {
217   thePrs->SetInfiniteState (IsInfinite());
218   if (theMode != 0)
219   {
220     return;
221   }
222
223   // main frame
224   {
225     Handle(Graphic3d_ArrayOfTriangles) aTris = createRectangleArray (myFrameBottomLeft, myFrameBottomLeft + myFrameSize, Graphic3d_ArrayFlags_VertexTexel);
226     Handle(Graphic3d_Group) aMainGroup = thePrs->NewGroup();
227     aMainGroup->SetGroupPrimitivesAspect (myFrameAspect);
228     aMainGroup->AddPrimitiveArray (aTris);
229   }
230 }
231
232 // =======================================================================
233 // function : ComputeSelection
234 // purpose  :
235 // =======================================================================
236 void AIS_MediaPlayer::ComputeSelection (const Handle(SelectMgr_Selection)& theSel,
237                                         const Standard_Integer theMode)
238 {
239   if (theMode != 0)
240   {
241     return;
242   }
243
244   Handle(Graphic3d_ArrayOfTriangles) aTris = createRectangleArray (myFrameBottomLeft, myFrameBottomLeft + myFrameSize, Graphic3d_ArrayFlags_None);
245
246   Handle(SelectMgr_EntityOwner) anOwner = new SelectMgr_EntityOwner (this, 5);
247   Handle(Select3D_SensitivePrimitiveArray) aSens = new Select3D_SensitivePrimitiveArray (anOwner);
248   aSens->InitTriangulation (aTris->Attributes(), aTris->Indices(), TopLoc_Location());
249   theSel->Add (aSens);
250 }