1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include "oglwindow.hxx"
11 #include <cppuhelper/supportsservice.hxx>
13 using namespace com::sun::star
;
14 using namespace libgltf
;
16 namespace avmedia
{ namespace ogl
{
18 OGLWindow::OGLWindow( glTFHandle
& rHandle
, const rtl::Reference
<OpenGLContext
> &rContext
, vcl::Window
& rEventHandlerParent
)
19 : m_rHandle( rHandle
)
20 , m_xContext( rContext
)
21 , m_rEventHandler( rEventHandlerParent
)
22 , m_bVisible ( false )
23 , m_aLastMousePos(Point(0,0))
24 , m_bIsOrbitMode( false )
28 OGLWindow::~OGLWindow()
33 void SAL_CALL
OGLWindow::update() throw (css::uno::RuntimeException
, std::exception
)
35 m_xContext
->makeCurrent();
36 int nRet
= gltf_prepare_renderer(&m_rHandle
);
39 SAL_WARN("avmedia.opengl", "Error occurred while preparing for rendering! Error code: " << nRet
);
42 gltf_renderer(&m_rHandle
);
43 gltf_complete_renderer(&m_rHandle
);
44 m_xContext
->swapBuffers();
47 sal_Bool SAL_CALL
OGLWindow::setZoomLevel( css::media::ZoomLevel
/*eZoomLevel*/ ) throw (css::uno::RuntimeException
, std::exception
)
52 css::media::ZoomLevel SAL_CALL
OGLWindow::getZoomLevel() throw (css::uno::RuntimeException
, std::exception
)
54 return media::ZoomLevel_ORIGINAL
;
57 void SAL_CALL
OGLWindow::setPointerType( sal_Int32
) throw (css::uno::RuntimeException
, std::exception
)
61 OUString SAL_CALL
OGLWindow::getImplementationName() throw (css::uno::RuntimeException
, std::exception
)
63 return OUString("com.sun.star.comp.avmedia.Window_OpenGL");
66 sal_Bool SAL_CALL
OGLWindow::supportsService( const OUString
& rServiceName
) throw (css::uno::RuntimeException
, std::exception
)
68 return cppu::supportsService(this, rServiceName
);
71 uno::Sequence
< OUString
> SAL_CALL
OGLWindow::getSupportedServiceNames() throw (css::uno::RuntimeException
, std::exception
)
73 uno::Sequence
< OUString
> aRet(1);
74 aRet
[0] = "com.sun.star.media.Window_OpenGL";
78 void SAL_CALL
OGLWindow::dispose() throw (uno::RuntimeException
, std::exception
)
80 assert(m_rEventHandler
.GetParent());
81 m_rEventHandler
.GetParent()->RemoveEventListener( LINK(this, OGLWindow
, FocusGrabber
));
82 m_rEventHandler
.RemoveEventListener( LINK(this, OGLWindow
, CameraHandler
));
85 void SAL_CALL
OGLWindow::addEventListener( const uno::Reference
< lang::XEventListener
>& )
86 throw (uno::RuntimeException
, std::exception
)
90 void SAL_CALL
OGLWindow::removeEventListener( const uno::Reference
< lang::XEventListener
>& )
91 throw (uno::RuntimeException
, std::exception
)
95 void SAL_CALL
OGLWindow::setPosSize( sal_Int32 nX
, sal_Int32 nY
, sal_Int32 nWidth
, sal_Int32 nHeight
, sal_Int16
/*nFlags*/ )
96 throw (uno::RuntimeException
, std::exception
)
98 if( m_rHandle
.viewport
.x
!= nX
|| m_rHandle
.viewport
.x
!= nY
||
99 m_rHandle
.viewport
.width
!= nWidth
|| m_rHandle
.viewport
.height
!= nHeight
)
101 m_xContext
->setWinSize(Size(nWidth
,nHeight
));
102 m_rHandle
.viewport
.x
= nX
;
103 m_rHandle
.viewport
.y
= nY
;
104 m_rHandle
.viewport
.width
= nWidth
;
105 m_rHandle
.viewport
.height
= nHeight
;
109 awt::Rectangle SAL_CALL
OGLWindow::getPosSize()
110 throw (uno::RuntimeException
, std::exception
)
112 return awt::Rectangle(m_rHandle
.viewport
.x
, m_rHandle
.viewport
.y
,
113 m_rHandle
.viewport
.width
, m_rHandle
.viewport
.height
);
116 void SAL_CALL
OGLWindow::setVisible( sal_Bool bSet
)
117 throw (uno::RuntimeException
, std::exception
)
119 assert(m_rEventHandler
.GetParent());
120 if( bSet
&& !m_bVisible
)
122 m_rEventHandler
.GetParent()->AddEventListener( LINK(this, OGLWindow
, FocusGrabber
));
123 m_rEventHandler
.AddEventListener( LINK(this, OGLWindow
, CameraHandler
));
124 m_rEventHandler
.GrabFocus();
128 m_rEventHandler
.GetParent()->RemoveEventListener( LINK(this, OGLWindow
, FocusGrabber
));
129 m_rEventHandler
.RemoveEventListener( LINK(this, OGLWindow
, CameraHandler
));
134 void SAL_CALL
OGLWindow::setEnable( sal_Bool
)
135 throw (uno::RuntimeException
, std::exception
)
139 void SAL_CALL
OGLWindow::setFocus()
140 throw (uno::RuntimeException
, std::exception
)
144 void SAL_CALL
OGLWindow::addWindowListener( const uno::Reference
< awt::XWindowListener
>& )
145 throw (uno::RuntimeException
, std::exception
)
149 void SAL_CALL
OGLWindow::removeWindowListener( const uno::Reference
< awt::XWindowListener
>& )
150 throw (uno::RuntimeException
, std::exception
)
154 void SAL_CALL
OGLWindow::addFocusListener( const uno::Reference
< awt::XFocusListener
>& )
155 throw (uno::RuntimeException
, std::exception
)
159 void SAL_CALL
OGLWindow::removeFocusListener( const uno::Reference
< awt::XFocusListener
>& )
160 throw (uno::RuntimeException
, std::exception
)
164 void SAL_CALL
OGLWindow::addKeyListener( const uno::Reference
< awt::XKeyListener
>& )
165 throw (uno::RuntimeException
, std::exception
)
169 void SAL_CALL
OGLWindow::removeKeyListener( const uno::Reference
< awt::XKeyListener
>& )
170 throw (uno::RuntimeException
, std::exception
)
174 void SAL_CALL
OGLWindow::addMouseListener( const uno::Reference
< awt::XMouseListener
>& )
175 throw (uno::RuntimeException
, std::exception
)
179 void SAL_CALL
OGLWindow::removeMouseListener( const uno::Reference
< awt::XMouseListener
>& )
180 throw (uno::RuntimeException
, std::exception
)
184 void SAL_CALL
OGLWindow::addMouseMotionListener( const uno::Reference
< awt::XMouseMotionListener
>& )
185 throw (uno::RuntimeException
, std::exception
)
189 void SAL_CALL
OGLWindow::removeMouseMotionListener( const uno::Reference
< awt::XMouseMotionListener
>& )
190 throw (uno::RuntimeException
, std::exception
)
194 void SAL_CALL
OGLWindow::addPaintListener( const uno::Reference
< awt::XPaintListener
>& )
195 throw (uno::RuntimeException
, std::exception
)
199 void SAL_CALL
OGLWindow::removePaintListener( const uno::Reference
< awt::XPaintListener
>& )
200 throw (uno::RuntimeException
, std::exception
)
204 IMPL_LINK(OGLWindow
, FocusGrabber
, VclWindowEvent
*, pEvent
)
206 if( pEvent
->GetId() == VCLEVENT_WINDOW_MOUSEMOVE
)
208 MouseEvent
* pMouseEvt
= static_cast<MouseEvent
*>(pEvent
->GetData());
211 const Point
& rMousePos
= pMouseEvt
->GetPosPixel();
212 const Rectangle
aWinRect(m_rEventHandler
.GetPosPixel(),m_rEventHandler
.GetSizePixel());
213 // Grab focus to the OpenGL window when mouse pointer is over it
214 if( aWinRect
.IsInside(rMousePos
) )
216 if ( !m_rEventHandler
.HasFocus() )
218 m_rEventHandler
.GrabFocus();
221 // Move focus to the document when mouse is not over the OpenGL window
222 else if ( m_rEventHandler
.HasFocus() )
224 m_rEventHandler
.GrabFocusToDocument();
232 IMPL_LINK(OGLWindow
, CameraHandler
, VclWindowEvent
*, pEvent
)
234 if( pEvent
->GetId() == VCLEVENT_WINDOW_KEYINPUT
)
236 KeyEvent
* pKeyEvt
= static_cast<KeyEvent
*>(pEvent
->GetData());
239 const sal_uInt16 nCode
= pKeyEvt
->GetKeyCode().GetCode();
240 if (nCode
== KEY_Q
|| nCode
== KEY_E
||
241 nCode
== KEY_A
|| nCode
== KEY_D
||
242 nCode
== KEY_W
|| nCode
== KEY_S
)
244 // Calculate movement
250 gltf_get_camera_pos(&m_rHandle
, &vEye
,&vView
,&vUp
);
251 float fModelSize
=(float)gltf_get_model_size(&m_rHandle
);
253 glm::vec3 vMove
= vView
-vEye
;
254 vMove
= glm::normalize(vMove
);
256 glm::vec3 vStrafe
= glm::cross(vMove
, vUp
);
257 vStrafe
= glm::normalize(vStrafe
);
259 glm::vec3 vMup
= vUp
* 25.0f
;
261 if( !m_bIsOrbitMode
)
263 if(nCode
== KEY_E
)vMoveBy
+= vMup
*(0.0005f
*fModelSize
);
264 if(nCode
== KEY_Q
)vMoveBy
-= vMup
*(0.0005f
*fModelSize
);
265 if(nCode
== KEY_W
)vMoveBy
+= vMove
*(0.0005f
*fModelSize
);
266 if(nCode
== KEY_S
)vMoveBy
-= vMove
*(0.0005f
*fModelSize
);
267 if(nCode
== KEY_A
)vMoveBy
-= vStrafe
*(0.0005f
*fModelSize
);
268 if(nCode
== KEY_D
)vMoveBy
+= vStrafe
*(0.0005f
*fModelSize
);
272 bool bZoomIn
= false;
273 bool bZoomOut
= false;
276 vMoveBy
+= vMove
*(0.0005f
*fModelSize
);
281 vMoveBy
-= vMove
*(0.0005f
*fModelSize
);
285 // Limit zooming in orbit mode
286 float fCameraDistFromModelGlobe
= glm::length(vEye
+ vMoveBy
- vView
) - fModelSize
/ 2.0f
;
287 if ((fCameraDistFromModelGlobe
< 0.5 * fModelSize
&& bZoomIn
) ||
288 (fCameraDistFromModelGlobe
> 2 * fModelSize
&& bZoomOut
))
290 vMoveBy
= glm::vec3(0.0);
294 gltf_renderer_move_camera(&m_rHandle
, vMoveBy
.x
, vMoveBy
.y
, vMoveBy
.z
, 0.0001);
316 float fSensitivity
= 50.0;
317 gltf_renderer_rotate_model(&m_rHandle
, nDeltaX
*fSensitivity
, nDeltaY
*fSensitivity
, 0.0);
320 else if(nCode
== KEY_M
)
324 gltf_orbit_mode_stop(&m_rHandle
);
325 m_bIsOrbitMode
= false;
329 gltf_orbit_mode_start(&m_rHandle
);
330 m_bIsOrbitMode
= true;
333 else if(nCode
== KEY_F
)
335 gltf_render_FPS_enable(&m_rHandle
);
339 else if( pEvent
->GetId() == VCLEVENT_WINDOW_MOUSEBUTTONDOWN
)
341 MouseEvent
* pMouseEvt
= static_cast<MouseEvent
*>(pEvent
->GetData());
342 if(pMouseEvt
&& pMouseEvt
->IsLeft() && pMouseEvt
->GetClicks() == 1)
344 m_aLastMousePos
= pMouseEvt
->GetPosPixel();
347 else if( pEvent
->GetId() == VCLEVENT_WINDOW_MOUSEMOVE
)
349 if ( !m_rEventHandler
.HasFocus() )
351 m_rEventHandler
.GrabFocus();
353 MouseEvent
* pMouseEvt
= static_cast<MouseEvent
*>(pEvent
->GetData());
354 if(pMouseEvt
&& pMouseEvt
->IsLeft() && m_aLastMousePos
!= Point(0,0))
356 const Point
& aCurPos
= pMouseEvt
->GetPosPixel();
357 float fSensitivity
= std::min(m_rHandle
.viewport
.width
, m_rHandle
.viewport
.height
);
358 if (fSensitivity
== 0.0)
361 fSensitivity
= 540.0 / fSensitivity
;
364 long nDeltaX
= m_aLastMousePos
.X()-aCurPos
.X();
365 long nDeltaY
= m_aLastMousePos
.Y()-aCurPos
.Y();
369 gltf_renderer_rotate_model(&m_rHandle
, (float)nDeltaX
*fSensitivity
, (float)nDeltaY
*fSensitivity
, 0.0);
373 // Filter out too small deltas to avoid rewrite rotation parameter with 0
374 // before rotation is done
375 if( nDeltaX
!= 0 || nDeltaY
!= 0 )
376 gltf_renderer_rotate_camera(&m_rHandle
, (float)nDeltaX
*fSensitivity
, (float)nDeltaY
*fSensitivity
, 0.0);
378 m_aLastMousePos
= aCurPos
;
381 else if( pEvent
->GetId() == VCLEVENT_WINDOW_MOUSEBUTTONUP
)
383 MouseEvent
* pMouseEvt
= static_cast<MouseEvent
*>(pEvent
->GetData());
384 if(pMouseEvt
&& pMouseEvt
->IsLeft() && pMouseEvt
->GetClicks() == 1)
386 m_aLastMousePos
= Point(0,0);
393 } // namespace avmedia
395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */