0029631: Samples: build AndroidQt sample together with OCCT on Windows platform IR-2018-03-23
authornds <nds@opencascade.com>
Fri, 23 Mar 2018 07:36:07 +0000 (10:36 +0300)
committernds <nds@opencascade.com>
Fri, 23 Mar 2018 12:27:22 +0000 (15:27 +0300)
- _WIN32 definition provides functionality for sample on Windows
- CMake procedure is changed to have Qt5_FOUND variable defined before compilation modules. Searching of Qt packages is moved into qt.cmake.

CMakeLists.txt
adm/cmake/qt.cmake
adm/cmake/qt_macro.cmake
adm/templates/sample.bat
samples/qt/AndroidQt/res/qml/main.qml
samples/qt/AndroidQt/src/AndroidQt.cxx
samples/qt/AndroidQt/src/AndroidQt.h
samples/qt/AndroidQt/src/AndroidQt_TouchParameters.cxx
samples/qt/AndroidQt/src/AndroidQt_Window.cxx
samples/qt/AndroidQt/src/Main.cxx

index 3007cc6..7799627 100644 (file)
@@ -1018,9 +1018,9 @@ endif()
 OCCT_MODULES_AND_TOOLKITS (SAMPLES "SAMPLES_TOOLKITS" OCCT_SAMPLES)
 
 if (BUILD_MODULE_QtSamples)
-  if (NOT Qt5_FOUND OR NOT USE_GLES2)
+  if (NOT Qt5_FOUND OR NOT WIN32)
     list (REMOVE_ITEM qt_SAMPLES_TOOLKITS AndroidQt)
-    message (STATUS "Info: AndroidQt sample excluded due to Qt5 or GLES2 usage are disabled")
+    message (STATUS "Info: AndroidQt sample excluded due to Qt5 usage is disabled or OS is not Windows")
   endif()
 
   if (NOT BUILD_Inspector)
index 922177b..2eacf8f 100644 (file)
@@ -18,3 +18,19 @@ UNSET (${3RDPARTY_QT_LIBRARY_DIR} CACHE)
 
 set (USED_3RDPARTY_QT_DIR "${3RDPARTY_QT_DIR}")
 message (STATUS "Info: Qt is used from folder: ${3RDPARTY_QT_DIR}")
+
+# Now set CMAKE_PREFIX_PATH to point to local Qt installation.
+# Without this setting find_package() will not work
+set(CMAKE_PREFIX_PATH ${3RDPARTY_QT_DIR})
+
+# Now we can apply standard CMake finder for Qt5. We do this mostly
+# to have qt5_wrap_cpp() function available and Qt5_FOUND variable filled
+find_package(Qt5 QUIET COMPONENTS Widgets Quick PATHS ${3RDPARTY_QT_DIR} NO_DEFAULT_PATH)
+if (NOT ${Qt5_FOUND})
+  # Now we can apply standard CMake finder for Qt. We do this mostly
+  # to have qt4_wrap_cpp() function available
+  find_package(Qt4)
+  #message (STATUS "Qt4 cmake configuration")
+else()
+  #message (STATUS "Qt5 cmake configuration")
+endif()
index c535772..7870d60 100644 (file)
@@ -6,13 +6,6 @@ macro (FIND_QT_PACKAGE PROJECT_LIBRARIES_DEBUG PROJECT_LIBRARIES_RELEASE PROJECT
     message (FATAL_ERROR "Empty Qt dir")
   endif()
 
-  # Now set CMAKE_PREFIX_PATH to point to local Qt installation.
-  # Without this setting find_package() will not work
-  set(CMAKE_PREFIX_PATH ${3RDPARTY_QT_DIR})
-
-  # Now we can apply standard CMake finder for Qt5. We do this mostly
-  # to have qt5_wrap_cpp() function available
-  find_package(Qt5 QUIET COMPONENTS Widgets Quick PATHS ${3RDPARTY_QT_DIR} NO_DEFAULT_PATH)
   if (${Qt5_FOUND})
     #message (STATUS "Qt5 cmake configuration")
 
@@ -28,10 +21,6 @@ macro (FIND_QT_PACKAGE PROJECT_LIBRARIES_DEBUG PROJECT_LIBRARIES_RELEASE PROJECT
     GET_FILENAME_COMPONENT(QT_BINARY_DIR ${QT_LRELEASE_EXECUTABLE} DIRECTORY)
     MARK_AS_ADVANCED(QT_BINARY_DIR)
   else()
-    # Now we can apply standard CMake finder for Qt. We do this mostly
-    # to have qt4_wrap_cpp() function available
-    find_package(Qt4)
-
     #message (STATUS "Qt4 cmake configuration")
     set(PROJECT_INCLUDES ${QT_INCLUDES})
     if (WIN32)
index 0233466..e7446dd 100644 (file)
@@ -25,6 +25,7 @@ if ["%1"] == [""] (
 )
 
 call "%~dp0env.bat" %2 %3 %4
+if not ["%QTDIR%"] == [""] if exist "%QTDIR%\qml" if ["%QML2_IMPORT_PATH%"] == [""] set "QML2_IMPORT_PATH=%QTDIR%/qml"
 set "EXE_PATH=%CSF_OCCTBinPath%/%1.exe"
 
 if not exist "%EXE_PATH%" (
index 2566fb2..f933ccc 100644 (file)
@@ -28,6 +28,9 @@ Window {
   id: root_window
   visible: true
 
+  width:  (Qt.platform.os == "android" || Qt.platform.os == "ios") ? Screen.width : 600
+  height: (Qt.platform.os == "android" || Qt.platform.os == "ios") ? Screen.height : 400
+
   Item {
     id: root_item
     anchors.fill: parent
@@ -52,8 +55,8 @@ Window {
       anchors.left: parent.left
 
       // size
-      width:  200
-      height: 200
+      width:  (Qt.platform.os == "android" || Qt.platform.os == "ios") ? 200 : 150
+      height: (Qt.platform.os == "android" || Qt.platform.os == "ios") ? 200 : 150
 
       color: "white"
 
index 70026c1..54a339c 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <AndroidQt_Window.h>
-#include <AndroidQt.h>
-#include <AndroidQt_UserInteractionParameters.h>
+#if defined(_WIN32)
+  #include <windows.h>
+#endif
+
+#include "AndroidQt.h"
+#include "AndroidQt_UserInteractionParameters.h"
+#include "AndroidQt_Window.h"
 
 #include <AIS_Shape.hxx>
 #include <BRepTools.hxx>
 #include <BRep_Builder.hxx>
+#include <Message.hxx>
+#include <Message_Messenger.hxx>
 #include <OpenGl_GraphicDriver.hxx>
 #include <Quantity_Color.hxx>
 #include <Standard_ErrorHandler.hxx>
@@ -25,6 +31,7 @@
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Shape.hxx>
 #include <UnitsAPI.hxx>
+#include <WNT_Window.hxx>
 
 #include <EGL/egl.h>
 #include <QFileInfo>
@@ -36,7 +43,7 @@
 AndroidQt::AndroidQt()
 : myFitAllAction (false)
 {
-  connect (this, SIGNAL(windowChanged(QQuickWindow*)), this, SLOT(handleWindowChanged(QQuickWindow*)));
+  connect (this, SIGNAL (windowChanged (QQuickWindow*)), this, SLOT (handleWindowChanged (QQuickWindow*)));
 
   // set shaders location variable
   QByteArray aDataRoot = "/data/data/org.qtproject.example.AndroidQt/files/opencascade/shared";
@@ -138,7 +145,7 @@ void AndroidQt::handleWindowChanged (QQuickWindow* theWin)
     return;
   }
 
-  connect(theWin, SIGNAL(beforeSynchronizing()), this, SLOT(sync()), Qt::DirectConnection);
+  connect (theWin, SIGNAL (beforeSynchronizing()), this, SLOT (sync()), Qt::DirectConnection);
 
   theWin->setClearBeforeRendering (false);
 }
@@ -151,28 +158,54 @@ void AndroidQt::sync()
 {
   myViewportSize = window()->size() * window()->devicePixelRatio();
 
+  Graphic3d_Vec2i aWinTopLeft (window()->x(), window()->y());
+  Graphic3d_Vec2i aWinSize (myViewportSize.width(), myViewportSize.height());
+  const bool isChangedLeft = (myWinTopLeft.x() != aWinTopLeft.x());
+  const bool isChangedTop = (myWinTopLeft.y() != aWinTopLeft.y());
+  myWinTopLeft = aWinTopLeft;
+
   if (myViewer.IsNull())
   {
-    initViewer();
-    connect (window(), SIGNAL(beforeRendering()), this, SLOT(paint()), Qt::DirectConnection);
+    initViewer (Aspect_Drawable (window()->winId()));
+    connect (window(), SIGNAL (beforeRendering()), this, SLOT (paint()), Qt::DirectConnection);
   }
   else
   {
     Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (myViewer->Driver());
+  #ifdef __ANDROID__
     if (aDriver->getRawGlContext() != eglGetCurrentContext())
     {
-      initViewer();
+      initViewer (Aspect_Drawable (window()->winId()));
     }
     else
+  #endif
     {
-      Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window());
+    #ifdef __ANDROID__
+      Handle(AndroidQt_Window) aWindow = Handle(AndroidQt_Window)::DownCast(myView->Window());
       aWindow->SetSize (myViewportSize.width(), myViewportSize.height());
       //myView->MustBeResized(); // can be used instead of SetWindow() when EGLsurface has not been changed
 
       EGLContext anEglContext = eglGetCurrentContext();
       myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
+    #else
+      if (aWinSize.x() != myWinSize.x()
+       || aWinSize.y() != myWinSize.y())
+      {
+        myView->MustBeResized();
+        myView->Invalidate();
+      }
+      else if (isChangedTop)
+      {
+        myView->MustBeResized();
+      }
+      else if (isChangedLeft)
+      {
+        myView->MustBeResized();
+      }
+    #endif
     }
   }
+  myWinSize = aWinSize;
 }
 
 // =======================================================================
@@ -183,7 +216,7 @@ void AndroidQt::paint()
 {
   myMutex.lock();
 
-  if (Abs(myTouchPoint.DevX()) + Abs(myTouchPoint.DevY()) > 1)
+  if (Abs (myTouchPoint.DevX()) + Abs (myTouchPoint.DevY()) > 1)
   {
     myView->StartRotation (myTouchPoint.X().first,  myTouchPoint.Y().first);
     myView->Rotation      (myTouchPoint.X().second, myTouchPoint.Y().second);
@@ -206,10 +239,12 @@ void AndroidQt::paint()
 // function : initViewer
 // purpose  :
 // =======================================================================
-bool AndroidQt::initViewer()
+bool AndroidQt::initViewer (Aspect_Drawable theWin)
 {
-  EGLint aCfgId = 0;
   int aWidth = 0, aHeight = 0;
+  Handle(Aspect_DisplayConnection) aDisplayConnection;
+#ifdef __ANDROID__
+  EGLint aCfgId = 0;
   EGLDisplay anEglDisplay = eglGetCurrentDisplay();
   EGLContext anEglContext = eglGetCurrentContext();
   EGLSurface anEglSurf    = eglGetCurrentSurface (EGL_DRAW);
@@ -232,6 +267,7 @@ bool AndroidQt::initViewer()
 
   if (eglChooseConfig (anEglDisplay, aConfigAttribs, &anEglConfig, 1, &aNbConfigs) != EGL_TRUE)
   {
+    Message::DefaultMessenger()->Send ("Error: EGL does not provide compatible configurations", Message_Fail);
     release();
     return false;
   }
@@ -242,6 +278,7 @@ bool AndroidQt::initViewer()
     Handle(AndroidQt_Window)     aWindow = Handle(AndroidQt_Window)::DownCast (myView->Window());
     if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
     {
+      Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized", Message_Fail);
       release();
       return false;
     }
@@ -251,14 +288,45 @@ bool AndroidQt::initViewer()
   }
 
   Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (NULL, Standard_False);
+#elif defined(_WIN32)
+  HWND  aWinHandle = (HWND)theWin;
+  HDC   aWindowDC = wglGetCurrentDC();
+  HGLRC aRendCtx   = wglGetCurrentContext();
+  if (aWinHandle == NULL
+   || aWindowDC  == NULL
+   || aRendCtx   == NULL)
+  {
+    Message::DefaultMessenger()->Send ("Error: No active WGL context!", Message_Fail);
+    release();
+    return false;
+  }
+
+  RECT aRect;
+  ::GetClientRect (aWinHandle, &aRect);
+  aWidth  = aRect.right - aRect.left;
+  aHeight = aRect.bottom - aRect.top;
+  myWinSize.x() = aWidth;
+  myWinSize.y() = aHeight;
+  if (!myViewer.IsNull())
+  {
+    Handle(WNT_Window) aWindow = new WNT_Window (aWinHandle);
+    myView->SetWindow (aWindow, (Aspect_RenderingContext)aRendCtx);
+    return true;
+  }
+  Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (aDisplayConnection, Standard_False);
+#endif
+
   aDriver->ChangeOptions().buffersNoSwap = Standard_True;
   //aDriver->ChangeOptions().glslWarnings  = Standard_True; // for GLSL shaders debug
 
+#ifdef __ANDROID__
   if (!aDriver->InitEglContext (anEglDisplay, anEglContext, anEglConfig))
   {
+    Message::DefaultMessenger()->Send ("Error: OpenGl_GraphicDriver can not be initialized", Message_Fail);
     release();
     return false;
   }
+#endif
 
   // create viewer
   myViewer = new V3d_Viewer (aDriver);
@@ -270,10 +338,20 @@ bool AndroidQt::initViewer()
   myContext = new AIS_InteractiveContext (myViewer);
   myContext->SetDisplayMode (AIS_Shaded, false);
 
+#ifdef __ANDROID__
   Handle(AndroidQt_Window) aWindow = new AndroidQt_Window (aWidth, aHeight);
+#elif defined(_WIN32)
+  Handle(WNT_Window)       aWindow = new WNT_Window (aWinHandle);
+#endif
+
   myView = myViewer->CreateView();
+  myView->SetImmediateUpdate (Standard_False);
 
+#ifdef __ANDROID__
   myView->SetWindow (aWindow, (Aspect_RenderingContext )anEglContext);
+#else
+  myView->SetWindow (aWindow, (Aspect_RenderingContext )aRendCtx);
+#endif
   myView->TriedronDisplay (Aspect_TOTP_RIGHT_LOWER, Quantity_NOC_WHITE, 0.08, V3d_ZBUFFER);
 
   return true;
index 9bc0e57..0e5462e 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <QMutex>
 
-#include <AndroidQt_TouchParameters.h>
+#include "AndroidQt_TouchParameters.h"
 
 //! QML item with embedded OCCT viewer.
 class AndroidQt : public QQuickItem
@@ -67,7 +67,8 @@ private slots:
 private:
 
   //! (Re-)initialize viewer on OpenGL context change.
-  bool initViewer();
+  //! \param theWin handle to GUI window
+  bool initViewer (Aspect_Drawable theWin);
 
   //! Close viewer
   void release();
@@ -77,6 +78,8 @@ private:
   Handle(V3d_Viewer)             myViewer;       //!< 3D viewer
   Handle(V3d_View)               myView;         //!< 3D view
   Handle(AIS_InteractiveContext) myContext;      //!< interactive context
+  Graphic3d_Vec2i                myWinTopLeft;   //!< cached window position (top-left)
+  Graphic3d_Vec2i                myWinSize;      //!< cached window width-height
 
   QMutex                         myMutex;        //!< mutex for interconnection with rendering thread
   QSize                          myViewportSize; //!< QML item size
index c844e26..4e8cd0e 100644 (file)
@@ -11,7 +11,7 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <AndroidQt_TouchParameters.h>
+#include "AndroidQt_TouchParameters.h"
 
 // =======================================================================
 // function : AndroidQt_TouchParameters
index 024b74d..9dc603a 100644 (file)
@@ -11,7 +11,7 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <AndroidQt_Window.h>
+#include "AndroidQt_Window.h"
 
 IMPLEMENT_STANDARD_RTTIEXT(AndroidQt_Window, Aspect_Window)
 
index dca2797..51ae7c1 100644 (file)
 #include <QApplication>
 #include <QQmlApplicationEngine>
 
-#include <AndroidQt.h>
+#include "AndroidQt.h"
+
+#include <OSD_Environment.hxx>
 
 int main(int argc, char *argv[])
 {
+#if defined(_WIN32) && (QT_VERSION > 0x050000)
+  TCollection_AsciiString aPlugindsDirName = OSD_Environment ("QTDIR").Value();
+  if (!aPlugindsDirName.IsEmpty())
+    QApplication::addLibraryPath (QString (aPlugindsDirName.ToCString()) + "/plugins");
+#endif
+
   QApplication app(argc, argv);
 
   qmlRegisterType<AndroidQt>("AndroidQt", 1, 0, "AndroidQt");