Merged in f5soh/librepilot/LP-575_fedora_package (pull request #491)
[librepilot.git] / ground / gcs / src / libs / osgearth / osgQtQuick / OSGFileNode.cpp
blob1369546976c9f5c881002df5491987085fd15705
1 /**
2 ******************************************************************************
4 * @file OSGFileNode.cpp
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2016.
6 * @addtogroup
7 * @{
8 * @addtogroup
9 * @{
10 * @brief
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "OSGFileNode.hpp"
30 #include <osgDB/ReadFile>
31 #include <osgUtil/Optimizer>
33 #include <QUrl>
34 #include <QOpenGLContext>
35 #include <QThread>
36 #include <QElapsedTimer>
37 #include <QDebug>
39 namespace osgQtQuick {
40 enum DirtyFlag { Source = 1 << 0, Async = 1 << 1, OptimizeMode = 1 << 2 };
42 class OSGFileLoader : public QThread {
43 Q_OBJECT
45 public:
46 OSGFileLoader(const QUrl &url) : url(url)
49 void run()
51 osg::Node *node = load();
52 emit loaded(url, node);
55 osg::Node *load()
57 QElapsedTimer t;
59 t.start();
60 // qDebug() << "OSGFileLoader::load - reading node file" << url.path();
61 // qDebug() << "OSGFileLoader - load - currentContext" << QOpenGLContext::currentContext();
62 osg::Node *node = osgDB::readNodeFile(url.path().toStdString());
63 if (!node) {
64 qWarning() << "OSGFileLoader::load - failed to load" << url.path();
66 // qDebug() << "OSGFileLoader::load - reading node" << node << "took" << t.elapsed() << "ms";
67 return node;
70 signals:
71 void loaded(const QUrl & url, osg::Node *node);
73 private:
74 QUrl url;
77 struct OSGFileNode::Hidden : public QObject {
78 Q_OBJECT
80 private:
81 OSGFileNode * const self;
83 public:
84 QUrl source;
85 bool async;
86 OptimizeMode::Enum optimizeMode;
88 Hidden(OSGFileNode *self) : QObject(self), self(self), source(), async(false), optimizeMode(OptimizeMode::None)
91 void updateSource()
93 // qDebug() << "OSGFileNode::updateNode" << source;
94 if (!source.isValid()) {
95 self->setNode(NULL);
96 if (!source.isEmpty()) {
97 qWarning() << "OSGFileNode::updateNode - invalid source" << source;
100 if (false /*async*/) {
101 // not supported yet
102 // it is not clear if thread safety is insured...
103 asyncLoad(source);
104 } else {
105 setNode(syncLoad(source));
109 private:
110 osg::Node *syncLoad(const QUrl &url)
112 OSGFileLoader loader(url);
114 return loader.load();
117 void asyncLoad(const QUrl &url)
119 OSGFileLoader *loader = new OSGFileLoader(url);
121 connect(loader, &OSGFileLoader::loaded, this, &Hidden::onLoaded);
122 connect(loader, &OSGFileLoader::finished, loader, &OSGFileLoader::deleteLater);
123 loader->start();
126 void setNode(osg::Node *node)
128 // qDebug() << "OSGFileNode::setNode" << node;
129 if (node && optimizeMode != OptimizeMode::None) {
130 // qDebug() << "OSGFileNode::acceptNode - optimize" << node << optimizeMode;
131 osgUtil::Optimizer optimizer;
132 optimizer.optimize(node, osgUtil::Optimizer::DEFAULT_OPTIMIZATIONS);
134 self->setNode(node);
137 private slots:
138 void onLoaded(const QUrl &url, osg::Node *node)
140 // called in async mode
141 // question : is it thread safe to call setNode() ?
142 // could calling setDirty help? is setDirty() thread safe ?
143 setNode(node);
147 /* class OSGFileNode */
149 OSGFileNode::OSGFileNode(QObject *parent) : Inherited(parent), h(new Hidden(this))
152 OSGFileNode::~OSGFileNode()
154 delete h;
157 const QUrl OSGFileNode::source() const
159 return h->source;
162 void OSGFileNode::setSource(const QUrl &source)
164 if (h->source != source) {
165 h->source = source;
166 setDirty(Source);
167 emit sourceChanged(source);
171 bool OSGFileNode::async() const
173 return h->async;
176 void OSGFileNode::setAsync(const bool async)
178 if (h->async != async) {
179 h->async = async;
180 setDirty(Async);
181 emit asyncChanged(async);
185 OptimizeMode::Enum OSGFileNode::optimizeMode() const
187 return h->optimizeMode;
190 void OSGFileNode::setOptimizeMode(OptimizeMode::Enum optimizeMode)
192 if (h->optimizeMode != optimizeMode) {
193 h->optimizeMode = optimizeMode;
194 setDirty(OptimizeMode);
195 emit optimizeModeChanged(optimizeMode);
199 osg::Node *OSGFileNode::createNode()
201 // node is created later
202 return NULL;
205 void OSGFileNode::updateNode()
207 Inherited::updateNode();
209 if (isDirty(Async)) {
210 // do nothing...
212 if (isDirty(OptimizeMode)) {
213 // TODO: trigger a node update ?
215 if (isDirty(Source)) {
216 h->updateSource();
219 } // namespace osgQtQuick
221 #include "OSGFileNode.moc"