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
IMPLEMENT_STANDARD_RTTIEXT(AIS_MediaPlayer,AIS_InteractiveObject)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 //================================================================
AIS_MediaPlayer()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_TypeOfShadingModel_Unlit);
60 myFrameAspect->SetTextureMapOn (true);
61 myFrameAspect->SetTextureSet (myFramePair);
62 }
63
64 //================================================================
65 // Function : ~AIS_MediaPlayer
66 // Purpose :
67 //================================================================
~AIS_MediaPlayer()68 AIS_MediaPlayer::~AIS_MediaPlayer()
69 {
70 // stop threads
71 myFramePair.Nullify();
72 }
73
74 // =======================================================================
75 // function : OpenInput
76 // purpose :
77 // =======================================================================
OpenInput(const TCollection_AsciiString & thePath,Standard_Boolean theToWait)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 // =======================================================================
PresentFrame(const Graphic3d_Vec2i & theLeftCorner,const Graphic3d_Vec2i & theMaxSize)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 // =======================================================================
updateSize(const Graphic3d_Vec2i & theLeftCorner,const Graphic3d_Vec2i & theMaxSize)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 // =======================================================================
PlayPause()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 // =======================================================================
Compute(const Handle (PrsMgr_PresentationManager)&,const Handle (Prs3d_Presentation)& thePrs,const Standard_Integer theMode)213 void AIS_MediaPlayer::Compute (const Handle(PrsMgr_PresentationManager)& ,
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 // =======================================================================
ComputeSelection(const Handle (SelectMgr_Selection)& theSel,const Standard_Integer theMode)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 }
251