New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt implementation of ApplicationContext #796

Open
wants to merge 1 commit into
base: master
from
File filter...
Filter file types
Jump to file or symbol
Failed to load files and symbols.
+295 −0
Diff settings

Always

Just for now

@@ -138,6 +138,14 @@ generate_export_header(OgreBites
EXPORT_MACRO_NAME _OgreBitesExport
EXPORT_FILE_NAME ${PROJECT_BINARY_DIR}/include/OgreBitesPrerequisites.h)

find_package(Qt5 COMPONENTS Core Widgets QUIET)
if(Qt5_FOUND)
qt5_wrap_cpp(MOC_SRC "${CMAKE_CURRENT_SOURCE_DIR}/include/OgreApplicationContextQt.h")
add_library(OgreBitesQt ${OGRE_COMP_LIB_TYPE} ${MOC_SRC} "${CMAKE_CURRENT_SOURCE_DIR}/src/OgreApplicationContextQt.cpp")
target_link_libraries(OgreBitesQt PUBLIC Qt5::Widgets OgreBites)
target_link_libraries(OgreBites PUBLIC Qt5::Widgets)
endif()

# install
ogre_config_framework(OgreBites)
ogre_config_component(OgreBites)
@@ -0,0 +1,44 @@
// This file is part of the OGRE project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at https://www.ogre3d.org/licensing.
#ifndef COMPONENTS_BITES_INCLUDE_APPLICATIONCONTEXTQT_H_
#define COMPONENTS_BITES_INCLUDE_APPLICATIONCONTEXTQT_H_

#include "OgreApplicationContextBase.h"

#include <QObject>

namespace OgreBites
{

class _OgreBitesExport ApplicationContextQt : public QObject, public ApplicationContextBase
{
Q_OBJECT
public:
explicit ApplicationContextQt(const Ogre::String& appName = OGRE_VERSION_NAME)
: ApplicationContextBase(appName)
{
}

using ApplicationContextBase::setWindowGrab;
void setWindowGrab(NativeWindowType* win, bool grab = true) override;

NativeWindowPair
createWindow(const Ogre::String& name, uint32_t w = 0, uint32_t h = 0,
Ogre::NameValuePairList miscParams = Ogre::NameValuePairList()) override;

using ApplicationContextBase::addInputListener;
using ApplicationContextBase::removeInputListener;
void addInputListener(NativeWindowType* win, InputListener* lis) override;
void removeInputListener(NativeWindowType* win, InputListener* lis) override;

void pollEvents() override;
void shutdown() override;

protected:
bool eventFilter(QObject *obj, QEvent *event) override;
};

} /* namespace Ogre */

#endif /* COMPONENTS_BITES_INCLUDE_OGREAPPLICATIONCONTEXTQT_H_ */
@@ -0,0 +1,243 @@
/*
* OgreApplicationContextQt.cpp
*
* Created on: 24.06.2018
* Author: pavel
*/

#include "OgreApplicationContextQt.h"

#include "OgreRoot.h"
#include "OgreRenderWindow.h"

#include <QEvent>
#include <QWidget>
#include <QApplication>
#include <QResizeEvent>
#include <QKeyEvent>

namespace OgreBites
{
static Event convert(const QEvent* in)
{
static QPoint lastMousePos;

Event out;

out.type = 0;

switch(in->type())
{
case QEvent::KeyPress:
out.type = KEYDOWN;
OGRE_FALLTHROUGH;
case QEvent::KeyRelease:
if(!out.type)
out.type = KEYUP;
{
auto* key = static_cast<const QKeyEvent*>(in);
out.key.repeat = key->isAutoRepeat();
switch(key->key())
{
case Qt::Key_Escape:
out.key.keysym.sym = SDLK_ESCAPE;
break;
case Qt::Key_Return:
out.key.keysym.sym = SDLK_RETURN;
break;
default:
out.key.keysym.sym = std::tolower(key->key());
break;
}
// out.key.keysym.mod = key->modifiers();
}
break;
case QEvent::MouseButtonRelease:
out.type = MOUSEBUTTONUP;
OGRE_FALLTHROUGH;
case QEvent::MouseButtonPress:
if(!out.type)
out.type = MOUSEBUTTONDOWN;

{
auto* mouse = static_cast<const QMouseEvent*>(in);
out.button.x = mouse->x();
out.button.y = mouse->y();
out.button.button = mouse->button();

if(out.button.button == Qt::RightButton)
out.button.button = BUTTON_RIGHT;
}
break;
case QEvent::Wheel:
out.type = MOUSEWHEEL;
out.wheel.y = static_cast<const QWheelEvent*>(in)->angleDelta().y();
out.wheel.y = out.wheel.y > 0 ? 1 : -1;
break;
case QEvent::MouseMove:
out.type = MOUSEMOTION;
{
auto* mouse = static_cast<const QMouseEvent*>(in);
out.motion.x = mouse->x();
out.motion.y = mouse->y();
out.motion.xrel = mouse->x() - lastMousePos.x();
out.motion.yrel = mouse->y() - lastMousePos.y();

lastMousePos = mouse->pos();

//out.motion.windowID = in.motion.windowID;
}
break;
case QEvent::TouchBegin:
out.type = FINGERDOWN;
OGRE_FALLTHROUGH;
case QEvent::TouchEnd:
if(!out.type)
out.type = FINGERUP;
OGRE_FALLTHROUGH;
case QEvent::TouchUpdate:
if(!out.type)
out.type = FINGERMOTION;
{
auto* touch = static_cast<const QTouchEvent*>(in);
out.tfinger.x = touch->touchPoints()[0].pos().x();
out.tfinger.y = touch->touchPoints()[0].pos().y();
//out.tfinger.dx = in.tfinger.dx;
//out.tfinger.dy = in.tfinger.dy;
out.tfinger.fingerId = touch->touchPoints()[0].id();
}
break;
default:
break;
}
return out;
}


NativeWindowPair ApplicationContextQt::createWindow(const Ogre::String& name, uint32_t w,
uint32_t h,
Ogre::NameValuePairList miscParams)
{
parseWindowOptions(w, h, miscParams);

const auto& ropts = mRoot->getRenderSystem()->getConfigOptions();

if(!QCoreApplication::instance())
{
int argc = 0;
char* argv = 0;
new QApplication(argc, &argv);
}

if(mWindows.empty())
{
QCoreApplication::instance()->installEventFilter(this);
}

QWidget* win = new QWidget();
win->setAttribute(Qt::WA_PaintOnScreen);
win->setMouseTracking(true);
win->resize(w, h);
win->show();

NativeWindowPair ret;
ret.native = (NativeWindowType*)win;


if(ropts.at("Full Screen").currentValue == "Yes"){
win->showFullScreen();
}

#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX
miscParams["parentWindowHandle"] = Ogre::StringConverter::toString(size_t(win->winId()));
#else
miscParams["externalWindowHandle"] = Ogre::StringConverter::toString(size_t(win->winId()));
#endif

ret.render = mRoot->createRenderWindow(name, w, h, false, &miscParams);
mWindows.push_back(ret);

return ret;
}

void ApplicationContextQt::addInputListener(NativeWindowType* win, InputListener* lis)
{
mInputListeners.insert(std::make_pair(((QWidget*)win)->winId(), lis));
}


void ApplicationContextQt::removeInputListener(NativeWindowType* win, InputListener* lis)
{
mInputListeners.erase(std::make_pair(((QWidget*)win)->winId(), lis));
}

void ApplicationContextQt::setWindowGrab(NativeWindowType* win, bool _grab)
{

}

void ApplicationContextQt::pollEvents()
{
QApplication::instance()->processEvents();
}

bool ApplicationContextQt::eventFilter(QObject *obj, QEvent *event)
{
QWidget* w = dynamic_cast<QWidget*>(obj);

if(mWindows.empty() || !w)
{
// not applicable
return QObject::eventFilter(obj, event);
}

switch (event->type())
{
case QEvent::Quit:
mRoot->queueEndRendering();
break;
case QEvent::Paint:
for(WindowList::iterator it = mWindows.begin(); it != mWindows.end(); ++it)
{
if(w->winId() == ((QWidget*)it->native)->winId())
return true;
}
break;
case QEvent::Resize:
for(WindowList::iterator it = mWindows.begin(); it != mWindows.end(); ++it)
{
if(w->winId() != ((QWidget*)it->native)->winId())
continue;

Ogre::RenderWindow* win = it->render;
QSize s = static_cast<QResizeEvent*>(event)->size();
win->resize(s.width(), s.height());
win->windowMovedOrResized();
windowResized(win);
}
break;
default:
_fireInputEvent(convert(event), w->winId());
break;
}

return QObject::eventFilter(obj, event);
}

void ApplicationContextQt::shutdown()
{
ApplicationContextBase::shutdown();

for(WindowList::iterator it = mWindows.begin(); it != mWindows.end(); ++it)
{
if(it->native)
delete (QWidget*)it->native;
}
if(!mWindows.empty()) {
QCoreApplication::instance()->removeEventFilter(this);
}

mWindows.clear();
}

} /* namespace Ogre */
ProTip! Use n and p to navigate between commits in a pull request.