[osg-users] qt5 qml plugin
Roy Arents
osgforum at tevs.eu
Sun Nov 15 03:23:45 PST 2015
Hi,
I'm trying to create a qml pluing to display qt5 qtQuick qml files in osg directly.
The code below seems to work and I can see qml being draw and events are processed. However, the qml image does not seem to be updated/redrawn after receiving events. The image seems static.
I'm not sure were the problem lies. Does qt not update the osg image, or does osg does not show a new image. Perhaps someone can help with this?
Thank you!
Cheers,
Roy
Code:
#include "pluginsQML.h"
#include "QMLParameters.h"
#include <osg/MatrixTransform>
#include <osg/TextureRectangle>
#include <osg/Texture2D>
#include <osg/Object>
#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgQt/QWidgetImage>
#include <osgViewer/ViewerEventHandlers>
#include <QQuickWidget>
#include <QVBoxLayout>
class QmlEventHandler : public osgGA::GUIEventHandler
{
public:
QmlEventHandler(QQuickWidget* widget) : _widget(widget) {}
virtual bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{
switch(ea.getEventType())
{
case(osgGA::GUIEventAdapter::FRAME):
{
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
// QCoreApplication::postEvent(_widget,new QEvent(QEvent::UpdateRequest));
// _widget->repaint();
// _widget->update();
break;
}
default:
break;
}
return false;
}
protected:
QQuickWidget* _widget;
};
static QmlEventHandler* qmlEventHandler = NULL;
class ReaderWriterQML : public osgDB::ReaderWriter
{
public:
ReaderWriterQML()
{
supportsExtension("qml", "");
//supportsOption("shmem", "Enable shared memory");
}
virtual ~ReaderWriterQML()
{
}
virtual const char * className() const
{
return "ReaderWriterQML";
}
virtual ReadResult readNode(const std::string & filename, const osgDB::ReaderWriter::Options* options) const
{
const std::string ext = osgDB::getLowerCaseFileExtension(filename);
if (ext=="qml")
{
osg::ref_ptr<osgQML::QMLParameters> parameters(new osgQML::QMLParameters);
parseOptions(parameters.get(), options);
std::string cmd = filename + " " + parameters->getOptionString();
bool inScene = true;
// There should be one QApplication
if(!QApplication::instance())
{
char *argv[] = {"app", (char*)filename.c_str(), NULL};
int argc = sizeof(argv) / sizeof(char*) - 1;
new QApplication(argc,argv);
}
//QWidget* widget = new QWidget;
//widget->setLayout(new QVBoxLayout);
QQuickWidget* widget = new QQuickWidget;
widget->setSource(QUrl::fromLocalFile(filename.c_str()));
//widget->layout()->addWidget(quickWidget);
// Size hack
QSize initSize = widget->initialSize();
if(initSize.width() != initSize.height()) osg::notify(osg::WARN) << "ReaderWriterQML - qml files with square size seem to work better in osg" << std::endl;
widget->setGeometry(0, 0, 2*initSize.width(),2*initSize.height());
osg::ref_ptr<osgQt::QWidgetImage> widgetImage = new osgQt::QWidgetImage(widget);
//widgetImage->setDataVariance(osg::Object::DYNAMIC);
#if (QT_VERSION >= QT_VERSION_CHECK(4, 5, 0))
widgetImage->getQWidget()->setAttribute(Qt::WA_TranslucentBackground);
#endif
widgetImage->getQGraphicsViewAdapter()->setBackgroundColor(QColor(0, 0, 0, 0));
widgetImage->getQGraphicsViewAdapter()->resize(initSize.width(), initSize.height()); // Size hack
QGraphicsScene* graphicsScene = widgetImage->getQGraphicsViewAdapter()->getQGraphicsScene();
osg::Camera* camera = 0; // Will stay NULL in the inScene case.
osg::Geometry* quad = osg::createTexturedQuadGeometry(osg::Vec3(0,0,0), osg::Vec3(1,0,0), osg::Vec3(0,1,0), 1, 1);
osg::Geode* geode = new osg::Geode;
geode->addDrawable(quad);
osg::MatrixTransform* mt = new osg::MatrixTransform;
osg::Texture2D* texture = new osg::Texture2D(widgetImage.get());
texture->setResizeNonPowerOfTwoHint(false);
texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
mt->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
osgViewer::InteractiveImageHandler* handler;
if (inScene)
{
mt->setMatrix(osg::Matrix::rotate(osg::Vec3(0,1,0), osg::Vec3(0,0,1)));
mt->addChild(geode);
handler = new osgViewer::InteractiveImageHandler(widgetImage.get());
}
else // fullscreen
{
// The HUD camera's viewport needs to follow the size of the
// window. MyInteractiveImageHandler will make sure of this.
// As for the quad and the camera's projection, setting the
// projection resize policy to FIXED takes care of them, so
// they can stay the same: (0,1,0,1) with a quad that fits.
// Set the HUD camera's projection and viewport to match the screen.
camera = new osg::Camera;
camera->setProjectionResizePolicy(osg::Camera::FIXED);
camera->setProjectionMatrix(osg::Matrix::ortho2D(0,1,0,1));
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setViewMatrix(osg::Matrix::identity());
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
camera->setRenderOrder(osg::Camera::POST_RENDER);
camera->addChild(geode);
camera->setViewport(0, 0, 1024, 768);
mt->addChild(camera);
handler = new osgViewer::InteractiveImageHandler(widgetImage.get(), texture, camera);
}
mt->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
mt->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
mt->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
mt->getOrCreateStateSet()->setAttribute(new osg::Program);
osg::Group* overlay = new osg::Group;
overlay->addChild(mt);
//root->addChild(overlay);
quad->setEventCallback(handler);
quad->setCullCallback(handler);
if(!qmlEventHandler) // Only add ONE QmlEventHandler to process all qt events
{
qmlEventHandler = new QmlEventHandler(widget);
overlay->setEventCallback(qmlEventHandler);
}
return overlay;
}
return ReadResult::FILE_NOT_HANDLED;
}
private:
void parseOptions(osgQML::QMLParameters* parameters, const osgDB::ReaderWriter::Options * options) const
{
if(!options) return;
const std::string name = options->getName();
int numPluginData = options->getNumPluginData();
int numPluginStringData = options->getNumPluginStringData();
const std::string optionString = options->getOptionString();
if (options && options->getNumPluginStringData()>0)
{
const FormatDescriptionMap& supportedOptList = supportedOptions();
for (FormatDescriptionMap::const_iterator itr = supportedOptList.begin();
itr != supportedOptList.end(); ++itr)
{
// Find the name
std::string name(itr->first);
size_t found = name.find("=");
if(found!=std::string::npos)
{
name = name.substr(0,found);
}
name.insert(0,"-");
const std::string value = options->getPluginStringData(name);
parameters->parse(name, value);
}
}
}
};
REGISTER_OSGPLUGIN(qml, ReaderWriterQML)
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=65646#65646
More information about the osg-users
mailing list