• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Stellarium / stellarium / 4853788370

pending completion
4853788370

push

github

Alexander V. Wolf
Special patch for John Simple

3 of 3 new or added lines in 3 files covered. (100.0%)

14729 of 125046 relevant lines covered (11.78%)

20166.5 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/plugins/Scenery3d/src/Scenery3d.cpp
1
/*
2
 * Stellarium Scenery3d Plug-in
3
 *
4
 * Copyright (C) 2011 Simon Parzer, Peter Neubauer, Georg Zotti, Andrei Borza
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
19
 */
20

21
#include <QDebug>
22
#include <QSettings>
23
#include <QString>
24
#include <QDir>
25
#include <QFile>
26
#include <QKeyEvent>
27
#include <QTimer>
28
#include <QOpenGLShaderProgram>
29
#include <QtConcurrent>
30

31
#include <stdexcept>
32
#include <memory>
33

34
#include "Scenery3d.hpp"
35
#include "Scenery3dRemoteControlService.hpp"
36
#include "S3DRenderer.hpp"
37
#include "S3DScene.hpp"
38
#include "Scenery3dDialog.hpp"
39
#include "StoredViewDialog.hpp"
40
#include "StelApp.hpp"
41
#include "StelCore.hpp"
42
#include "StelActionMgr.hpp"
43
#include "StelMovementMgr.hpp"
44
#include "StelGui.hpp"
45
#include "StelGuiItems.hpp"
46
#include "StelFileMgr.hpp"
47
#include "StelPainter.hpp"
48
#include "StelModuleMgr.hpp"
49
#include "StelTranslator.hpp"
50
#include "LandscapeMgr.hpp"
51
#include "StelMainView.hpp"
52

53
Q_LOGGING_CATEGORY(scenery3d,"stel.plugin.scenery3d")
×
54

55
#define S3D_CONFIG_PREFIX QString("Scenery3d")
56

57
Scenery3d::Scenery3d() :
×
58
        renderer(Q_NULLPTR),
×
59
        flagEnabled(false),
×
60
        cleanedUp(false),
×
61
        movementKeyInput(0.0,0.0,0.0),
×
62
        oldProjectionType(StelCore::ProjectionPerspective),
×
63
        forceHorizonPolyline(false),
×
64
        loadCancel(false),
×
65
        progressBar(Q_NULLPTR),
×
66
        currentLoadScene(),
×
67
        currentScene(Q_NULLPTR),
×
68
        currentLoadFuture(this)
×
69
{
70
        setObjectName("Scenery3d");
×
71
        scenery3dDialog = new Scenery3dDialog();
×
72
        storedViewDialog = new StoredViewDialog();
×
73

74
        font.setPixelSize(16);
×
75
        messageFader.setDuration(500);
×
76
        messageTimer = new QTimer(this);
×
77
        messageTimer->setInterval(2000);
×
78
        messageTimer->setSingleShot(true);
×
79
        connect(messageTimer, &QTimer::timeout, this, &Scenery3d::clearMessage);
×
80
        connect(&currentLoadFuture,&QFutureWatcherBase::finished, this, &Scenery3d::loadSceneCompleted);
×
81

82
        connect(this, &Scenery3d::progressReport, this, &Scenery3d::progressReceive, Qt::QueuedConnection);
×
83

84
        //get the global configuration object
85
        conf = StelApp::getInstance().getSettings();
×
86

87
        core = StelApp::getInstance().getCore();
×
88
        mvMgr = GETSTELMODULE(StelMovementMgr);
×
89

90
        //create scenery3d object
91
        renderer = new S3DRenderer();
×
92
        connect(renderer, SIGNAL(message(QString)), this, SLOT(showMessage(QString)));
×
93
}
×
94

95
Scenery3d::~Scenery3d()
×
96
{
97
        if(!cleanedUp)
×
98
                Scenery3d::deinit();
×
99

100
        delete storedViewDialog;
×
101
        delete scenery3dDialog;
×
102
}
×
103

104
double Scenery3d::getCallOrder(StelModuleActionName actionName) const
×
105
{
106
        if (actionName == StelModule::ActionDraw)
×
107
                return StelApp::getInstance().getModuleMgr().getModule("LandscapeMgr")->getCallOrder(actionName) + 5; // between Landscape and compass marks!
×
108
        if (actionName == StelModule::ActionUpdate)
×
109
                return StelApp::getInstance().getModuleMgr().getModule("LandscapeMgr")->getCallOrder(actionName) + 10;
×
110
        if (actionName == StelModule::ActionHandleKeys)
×
111
                return 3; // GZ: low number means high precedence!
×
112
        return 0;
×
113
}
114

115
void Scenery3d::handleKeys(QKeyEvent* e)
×
116
{
117
        if (!flagEnabled)
×
118
                return;
×
119

120
        static const Qt::KeyboardModifier S3D_SPEEDBASE_MODIFIER = Qt::ShiftModifier;
121

122
        //on OSX, there is a still-unfixed bug which prevents the command key (=Qt's Control key) to be used here
123
        //see https://bugreports.qt.io/browse/QTBUG-36839
124
        //we have to use the option/ALT key instead to activate walking around, and CMD is used as multiplier.
125
#ifdef Q_OS_MACOS
126
        static const Qt::KeyboardModifier S3D_CTRL_MODIFIER = Qt::AltModifier;
127
        static const Qt::KeyboardModifier S3D_SPEEDMUL_MODIFIER = Qt::ControlModifier;
128
#else
129
        static const Qt::KeyboardModifier S3D_CTRL_MODIFIER = Qt::ControlModifier;
130
        static const Qt::KeyboardModifier S3D_SPEEDMUL_MODIFIER = Qt::AltModifier;
131
#endif
132

133
        if ((e->type() == QKeyEvent::KeyPress) && (e->modifiers() & S3D_CTRL_MODIFIER))
×
134
        {
135
                // Pressing CTRL+ALT: 5x, CTRL+SHIFT: 10x speedup; CTRL+SHIFT+ALT: 50x!
136
                double speedup=((e->modifiers() & S3D_SPEEDBASE_MODIFIER)? 10.0 : 1.0);
×
137
                speedup *= ((e->modifiers() & S3D_SPEEDMUL_MODIFIER)? 5.0 : 1.0);
×
138

139
                switch (e->key())
×
140
                {
141
                        case Qt::Key_Plus:      // or
×
142
                        case Qt::Key_PageUp:    movementKeyInput[2] =  1.0 * speedup; e->accept(); break;
×
143
                        case Qt::Key_Minus:     // or
×
144
                        case Qt::Key_PageDown:  movementKeyInput[2] = -1.0 * speedup; e->accept(); break;
×
145
                        case Qt::Key_Up:        movementKeyInput[1] =  1.0 * speedup; e->accept(); break;
×
146
                        case Qt::Key_Down:      movementKeyInput[1] = -1.0 * speedup; e->accept(); break;
×
147
                        case Qt::Key_Right:     movementKeyInput[0] =  1.0 * speedup; e->accept(); break;
×
148
                        case Qt::Key_Left:      movementKeyInput[0] = -1.0 * speedup; e->accept(); break;
×
149
#ifdef QT_DEBUG
150
                                //leave this out on non-debug builds to reduce conflict chance
151
                        case Qt::Key_P:         renderer->saveFrusts(); e->accept(); break;
×
152
#endif
153
                }
154
        }
155
        // FS: No modifier here!? GZ: I want the lock feature. If this does not work for MacOS, it is not there, but only on that platform...
156
#ifdef Q_OS_MACOS
157
        else if ((e->type() == QKeyEvent::KeyRelease) )
158
#else
159
        else if ((e->type() == QKeyEvent::KeyRelease) && (e->modifiers() & S3D_CTRL_MODIFIER))
×
160
#endif
161
        {
162
                //if a movement key is released, stop moving in that direction
163
                //we do not accept the event on MacOS to allow further handling the event in other modules. (Else the regular view motion stop does not work!)
164
                switch (e->key())
×
165
                {
166
                        case Qt::Key_Plus:
×
167
                        case Qt::Key_PageUp:
168
                        case Qt::Key_Minus:
169
                        case Qt::Key_PageDown:
170
                                movementKeyInput[2] = 0.0;
×
171
#ifndef Q_OS_MACOS
172
                                e->accept();
×
173
#endif
174
                                break;
×
175
                        case Qt::Key_Up:
×
176
                        case Qt::Key_Down:
177
                                movementKeyInput[1] = 0.0;
×
178
#ifndef Q_OS_MACOS
179
                                e->accept();
×
180
#endif
181
                                break;
×
182
                        case Qt::Key_Right:
×
183
                        case Qt::Key_Left:
184
                                movementKeyInput[0] = 0.0;
×
185
#ifndef Q_OS_MACOS
186
                                e->accept();
×
187
#endif
188
                                break;
×
189
                }
190
        }
191
}
192

193

194
void Scenery3d::update(double deltaTime)
×
195
{
196
        if (flagEnabled && currentScene)
×
197
        {
198
                //update view direction
199
                Vec3d mainViewDir = mvMgr->getViewDirectionJ2000();
×
200
                mainViewDir = core->j2000ToAltAz(mainViewDir, StelCore::RefractionOff);
×
201
                currentScene->setViewDirection(mainViewDir);
×
202

203
                //perform movement
204
                //when zoomed in more than 5°, we slow down movement
205
                if(movementKeyInput.normSquared() > 0.00001)
×
206
                        currentScene->moveViewer(movementKeyInput * deltaTime * 0.01 * std::max(5.0, mvMgr->getCurrentFov()));
×
207

208
                //update material fade info, if necessary
209
                double curTime = core->getJD();
×
210
                S3DScene::MaterialList& matList = currentScene->getMaterialList();
×
211
                for(int i = 0; i<matList.size();++i)
×
212
                {
213
                        S3DScene::Material& mat = matList[i];
×
214
                        if(mat.traits.hasTimeFade)
×
215
                                mat.updateFadeInfo(curTime);
×
216
                }
217
        }
218

219
        messageFader.update(static_cast<int>(deltaTime*1000));
×
220
}
×
221

222
void Scenery3d::draw(StelCore* core)
×
223
{
224
        if (flagEnabled && currentScene)
×
225
        {
226
                renderer->draw(core,*currentScene);
×
227
        }
228

229
        if (forceHorizonPolyline)
×
230
                GETSTELMODULE(LandscapeMgr)->drawPolylineOnly(core); // Allow a check with background line.
×
231

232
        //the message is always drawn
233
        if (messageFader.getInterstate() > 0.000001f)
×
234
        {
235
                const StelProjectorP prj = core->getProjection(StelCore::FrameEquinoxEqu);
×
236
                StelPainter painter(prj);
×
237
                painter.setFont(font);
×
238
                painter.setColor(textColor[0], textColor[1], textColor[2], messageFader.getInterstate());
×
239
                painter.drawText(83, 120, currentMessage);
×
240
        }
×
241
}
×
242

243
void Scenery3d::init()
×
244
{
245
        qCDebug(scenery3d) << "Scenery3d plugin - press KGA button to toggle 3D scenery, KGA tool button for settings";
×
246

247
        //Initialize the renderer - this also finds out what features are supported
248
        qCDebug(scenery3d) << "Initializing Scenery3d renderer...";
×
249
        renderer->init();
×
250
        qCDebug(scenery3d) << "Initializing Scenery3d renderer...done";
×
251

252
        //make sure shadows are off if unsupported
253
        if(! renderer->areShadowsSupported())
×
254
                setEnableShadows(false);
×
255
        if(! renderer->isShadowFilteringSupported())
×
256
        {
257
                setShadowFilterQuality(S3DEnum::SFQ_OFF);
×
258
                setEnablePCSS(false);
×
259
        }
260

261
        //load config and create interface actions
262
        loadConfig();
×
263
        createActions();
×
264
        createToolbarButtons();
×
265

266
        connect(&StelMainView::getInstance(), SIGNAL(reloadShadersRequested()), this, SLOT(reloadShaders()));
×
267

268
        //finally, hook up the lightscape toggle event (external to this plugin) to cubemap redraw
269
        StelAction* action = StelApp::getInstance().getStelActionManager()->findAction("actionShow_LandscapeIllumination");
×
270
        Q_ASSERT(action);
×
271
        connect(action, &StelAction::toggled, this, &Scenery3d::forceCubemapRedraw);
×
272

273
#ifndef NDEBUG
274
        showMessage(q_("Scenery3d plugin loaded!"));
×
275
#endif
276
}
×
277

278
void Scenery3d::deinit()
×
279
{
280
        //wait until loading is finished. (If test added after hint from Coverity)
281
        if(renderer)
×
282
        {
283
                loadCancel = true;
×
284
                currentLoadFuture.waitForFinished();
×
285
        }
286
        //this is correct the place to delete all OpenGL related stuff, not the destructor
287
        delete renderer;
×
288
        renderer = Q_NULLPTR;
×
289
        delete currentScene;
×
290
        currentScene = Q_NULLPTR;
×
291

292
        cleanedUp = true;
×
293
}
×
294

295
void Scenery3d::loadConfig()
×
296
{
297
        conf->beginGroup(S3D_CONFIG_PREFIX);
×
298

299
        textColor = Vec3f(conf->value("text_color", "0.5,0.5,1").toString());
×
300
        renderer->setCubemappingMode( static_cast<S3DEnum::CubemappingMode>(conf->value("cubemap_mode",0).toInt()) );
×
301
        renderer->setCubemapSize(conf->value("cubemap_size",2048).toInt());
×
302
        renderer->setShadowmapSize(conf->value("shadowmap_size", 1024).toInt());
×
303
        renderer->setShadowFilterQuality( static_cast<S3DEnum::ShadowFilterQuality>(conf->value("shadow_filter_quality", 1).toInt()) );
×
304
        renderer->setPCSS(conf->value("flag_pcss").toBool());
×
305
        renderer->setTorchEnabled(conf->value("torch_enabled", false).toBool());
×
306
        renderer->setTorchBrightness(conf->value("torch_brightness", 0.5f).toFloat());
×
307
        renderer->setTorchRange(conf->value("torch_range",5.0f).toFloat());
×
308
        renderer->setBumpsEnabled(conf->value("flag_bumpmap", false).toBool());
×
309
        renderer->setShadowsEnabled(conf->value("flag_shadow", false).toBool());
×
310
        renderer->setUseSimpleShadows(conf->value("flag_shadow_simple", false).toBool());
×
311
        renderer->setUseFullCubemapShadows(conf->value("flag_cubemap_fullshadows", false).toBool());
×
312
        renderer->setLazyCubemapEnabled(conf->value("flag_lazy_cubemap", true).toBool());
×
313
        renderer->setLazyCubemapInterval(conf->value("cubemap_lazy_interval",1.0).toDouble());
×
314
        renderer->setPixelLightingEnabled(conf->value("flag_pixel_lighting", false).toBool());
×
315
        renderer->setLocationInfoEnabled(conf->value("flag_location_info", false).toBool());
×
316

317
        forceHorizonPolyline = conf->value("force_landscape_polyline", false).toBool();
×
318

319
        bool v1 = conf->value("flag_lazy_dominantface",false).toBool();
×
320
        bool v2 = conf->value("flag_lazy_seconddominantface",true).toBool();
×
321
        renderer->setLazyCubemapUpdateOnlyDominantFaceOnMoving(v1,v2);
×
322

323
        defaultScenery3dID = conf->value("default_location_id","").toString();
×
324

325
        conf->endGroup();
×
326
}
×
327

328
void Scenery3d::createActions()
×
329
{
330
        QString groupName = N_("Scenery3d: 3D landscapes");
×
331

332
        //enable action will be set checkable if a scene was loaded
333
        addAction("actionShow_Scenery3d",                  groupName, N_("Toggle 3D landscape"),      this,          "enableScene",       "Ctrl+W");
×
334
        addAction("actionShow_Scenery3d_dialog",           groupName, N_("Show settings dialog"),  scenery3dDialog,  "visible",           "Ctrl+Shift+W");
×
335
        addAction("actionShow_Scenery3d_storedViewDialog", groupName, N_("Show viewpoint dialog"), storedViewDialog, "visible",           "Ctrl+Alt+W");
×
336
        addAction("actionShow_Scenery3d_shadows",          groupName, N_("Toggle shadows"),           this,          "enableShadows",     "Ctrl+R, S");
×
337
        addAction("actionShow_Scenery3d_debuginfo",        groupName, N_("Toggle debug information"), this,          "enableDebugInfo",   "Ctrl+R, D");
×
338
        addAction("actionShow_Scenery3d_locationinfo",     groupName, N_("Toggle location text"),     this,          "enableLocationInfo","Ctrl+R, T");
×
339
        addAction("actionShow_Scenery3d_torchlight",       groupName, N_("Toggle torchlight"),        this,          "enableTorchLight",  "Ctrl+R, L");
×
340
}
×
341

342
void Scenery3d::createToolbarButtons() const
×
343
{
344
        // Add 3 toolbar buttons (copy/paste widely from AngleMeasure): activate, settings, and viewpoints.
345
        try
346
        {
347
                StelGui* gui = dynamic_cast<StelGui*>(StelApp::getInstance().getGui());
×
348

349
                if (gui!=Q_NULLPTR)
×
350
                {
351
                        StelButton* toolbarEnableButton =        new StelButton(Q_NULLPTR,
352
                                                                               QPixmap(":/Scenery3d/bt_scenery3d_on.png"),
×
353
                                                                               QPixmap(":/Scenery3d/bt_scenery3d_off.png"),
×
354
                                                                               QPixmap(":/graphicGui/miscGlow32x32.png"),
×
355
                                                                               "actionShow_Scenery3d",
356
                                                                               false,
357
                                                                               "actionShow_Scenery3d_dialog");
×
358
                        StelButton* toolbarStoredViewButton =        new StelButton(Q_NULLPTR,
359
                                                                               QPixmap(":/Scenery3d/bt_scenery3d_eyepoint_on.png"),
×
360
                                                                               QPixmap(":/Scenery3d/bt_scenery3d_eyepoint_off.png"),
×
361
                                                                               QPixmap(":/graphicGui/miscGlow32x32.png"),
×
362
                                                                               "actionShow_Scenery3d_storedViewDialog");
×
363

364
                        gui->getButtonBar()->addButton(toolbarEnableButton, "065-pluginsGroup");
×
365
                        gui->getButtonBar()->addButton(toolbarStoredViewButton, "065-pluginsGroup");
×
366
                }
367
        }
368
        catch (std::runtime_error& e)
×
369
        {
370
                qCWarning(scenery3d) << "WARNING: unable to create toolbar buttons for Scenery3d plugin: " << e.what();
×
371
        }
×
372
}
×
373

374
void Scenery3d::relativeMove(const Vec3d &move)
×
375
{
376
        if(currentScene)
×
377
        {
378
                currentScene->moveViewer(move);
×
379
        }
380
}
×
381

382
void Scenery3d::reloadShaders()
×
383
{
384
        showMessage(q_("Scenery3d shaders reloaded"));
×
385
        qCDebug(scenery3d)<<"Reloading Scenery3d shaders";
×
386

387
        renderer->getShaderManager().clearCache();
×
388
}
×
389

390
bool Scenery3d::configureGui(bool show)
×
391
{
392
        if (show)
×
393
                scenery3dDialog->setVisible(show);
×
394
        return true;
×
395
}
396

397
void Scenery3d::showStoredViewDialog()
×
398
{
399
        storedViewDialog->setVisible(true);
×
400
}
×
401

402
void Scenery3d::updateProgress(const QString &str, int val, int min, int max) const
×
403
{
404
        emit progressReport(str,val,min,max);
×
405
}
×
406

407
void Scenery3d::progressReceive(const QString &str, int val, int min, int max)
×
408
{
409
        //update progress bar
410
        if(progressBar)
×
411
        {
412
                progressBar->setFormat(str);
×
413
                progressBar->setRange(min,max);
×
414
                progressBar->setValue(val);
×
415
        }
416
}
×
417

418
void Scenery3d::loadScene(const SceneInfo& scene)
×
419
{
420
        loadCancel = true;
×
421

422
        //If currently loading, we have to wait until it is finished
423
        //This currently blocks the GUI thread until the loading can be canceled
424
        //  (which is for now rather rough-grained and so may take a while)
425
        currentLoadFuture.waitForFinished();
×
426
        loadCancel = false;
×
427

428
        if(progressBar)
×
429
        {
430
                //kinda hack: it can be that this here is executed before loadSceneBackground is called
431
                //so we push the call back into the queue to ensure correct execution order
432
                QMetaObject::invokeMethod(this,"loadScene",Qt::QueuedConnection,Q_ARG(SceneInfo, scene));
×
433
                return;
×
434
        }
435

436
        // Loading may take a while...
437
        showMessage(QString(q_("Loading scene. Please be patient!")));
×
438
        progressBar = StelApp::getInstance().addProgressBar();
×
439
        progressBar->setFormat(q_("Loading scene '%1'").arg(scene.name));
×
440
        progressBar->setValue(0);
×
441

442
        currentLoadScene = scene;
×
443
        emit loadingSceneIDChanged(currentLoadScene.id);
×
444

445
#if (QT_VERSION>=QT_VERSION_CHECK(6,0,0))
446
        QFuture<S3DScene*> future = QtConcurrent::run(&Scenery3d::loadSceneBackground,this,scene);
447
#else
448
        QFuture<S3DScene*> future = QtConcurrent::run(this,&Scenery3d::loadSceneBackground,scene);
×
449
#endif
450
        currentLoadFuture.setFuture(future);
×
451
}
×
452

453
S3DScene* Scenery3d::loadSceneBackground(const SceneInfo& scene) const
×
454
{
455
        //the scoped pointer ensures this scene is deleted when errors occur
456
        std::unique_ptr<S3DScene> newScene(new S3DScene(scene));
×
457

458
        if(loadCancel)
×
459
                return Q_NULLPTR;
×
460

461
        updateProgress(q_("Loading model..."),1,0,6);
×
462

463
        //load model
464
        StelOBJ modelOBJ;
×
465
        QString modelFile = StelFileMgr::findFile( scene.fullPath+ "/" + scene.modelScenery);
×
466
        qCDebug(scenery3d)<<"Loading scene from "<<modelFile;
×
467
        if(!modelOBJ.load(modelFile, scene.vertexOrderEnum, scene.sceneryGenerateNormals))
×
468
        {
469
            qCCritical(scenery3d)<<"Failed to load OBJ file"<<modelFile;
×
470
            return Q_NULLPTR;
×
471
        }
472

473
        if(loadCancel)
×
474
                return Q_NULLPTR;
×
475

476
        updateProgress(q_("Transforming model..."),2,0,6);
×
477
        newScene->setModel(modelOBJ);
×
478

479
        if(loadCancel)
×
480
                return Q_NULLPTR;
×
481

482
        if(scene.modelGround.isEmpty())
×
483
        {
484
                updateProgress(q_("Calculating collision map..."),5,0,6);
×
485
                newScene->setGround(modelOBJ);
×
486
        }
487
        else if (scene.modelGround != "NULL")
×
488
        {
489
                updateProgress(q_("Loading ground..."),3,0,6);
×
490

491
                StelOBJ groundOBJ;
×
492
                modelFile = StelFileMgr::findFile(scene.fullPath + "/" + scene.modelGround);
×
493
                qCDebug(scenery3d)<<"Loading ground from"<<modelFile;
×
494
                if(!groundOBJ.load(modelFile, scene.vertexOrderEnum, scene.groundGenerateNormals))
×
495
                {
496
                        qCCritical(scenery3d)<<"Failed to load ground model"<<modelFile;
×
497
                        return Q_NULLPTR;
×
498
                }
499

500
                updateProgress(q_("Transforming ground..."),4,0,6);
×
501
                if(loadCancel)
×
502
                        return Q_NULLPTR;
×
503

504
                updateProgress(q_("Calculating collision map..."),5,0,6);
×
505
                newScene->setGround(groundOBJ);
×
506
        }
×
507

508
        if(loadCancel)
×
509
                return Q_NULLPTR;
×
510

511
        updateProgress(q_("Finalizing load..."),6,0,6);
×
512

513
        return newScene.release();
×
514
}
×
515

516
void Scenery3d::loadSceneCompleted()
×
517
{
518
        S3DScene* result = currentLoadFuture.result();
×
519

520
        progressBar->setValue(100);
×
521
        StelApp::getInstance().removeProgressBar(progressBar);
×
522
        progressBar=Q_NULLPTR;
×
523

524
        if(!result)
×
525
        {
526
                showMessage(q_("Could not load scene, please check log for error messages!"));
×
527
                return;
×
528
        }
529
        else
530
                showMessage(q_("Scene successfully loaded."));
×
531

532
        //do stuff that requires the main thread
533
        const SceneInfo& info = result->getSceneInfo();
×
534

535
        //move to the location specified by the scene
536
        LandscapeMgr* lmgr = GETSTELMODULE(LandscapeMgr);
×
537
        const bool landscapeSetsLocation=lmgr->getFlagLandscapeSetsLocation();
×
538
        lmgr->setFlagLandscapeSetsLocation(true);
×
539
        lmgr->setCurrentLandscapeName(info.landscapeName, 0.); // took a second, implicitly.
×
540
        // Switched to immediate landscape loading: Else,
541
        // Landscape and Navigator at this time have old coordinates! But it should be possible to
542
        // delay rot_z computation up to this point and live without an own location section even
543
        // with meridian_convergence=from_grid.
544
        lmgr->setFlagLandscapeSetsLocation(landscapeSetsLocation); // restore
×
545

546

547
        if (info.hasLocation())
×
548
        {
549
                qCDebug(scenery3d) << "Setting location to given coordinates";
×
550
                StelApp::getInstance().getCore()->moveObserverTo(*info.location, 0., 0.);
×
551
        }
552
        else qCDebug(scenery3d) << "No coordinates given in scenery3d.ini";
×
553

554
        if (info.hasLookAtFOV())
×
555
        {
556
                qCDebug(scenery3d) << "Setting orientation";
×
557
                Vec3f lookat=currentLoadScene.lookAt_fov;
×
558
                // This vector is (az_deg, alt_deg, fov_deg)
559
                Vec3d v;
×
560
                StelUtils::spheToRect(lookat[0]*M_PI/180.0, lookat[1]*M_PI/180.0, v);
×
561
                mvMgr->setViewDirectionJ2000(StelApp::getInstance().getCore()->altAzToJ2000(v, StelCore::RefractionOff));
×
562
                mvMgr->zoomTo(lookat[2]);
×
563
        } else qCDebug(scenery3d) << "No orientation given in scenery3d.ini";
×
564

565
        //clear loading scene
566
        currentLoadScene = SceneInfo();
×
567
        emit loadingSceneIDChanged(QString());
×
568

569
        //switch scenes
570
        delete currentScene;
×
571
        currentScene = result;
×
572

573
        //show the scene
574
        setEnableScene(true);
×
575

576
        emit currentSceneChanged(info);
×
577
        emit currentSceneIDChanged(info.id);
×
578
}
579

580
SceneInfo Scenery3d::loadScenery3dByID(const QString& id)
×
581
{
582
        if (id.isEmpty())
×
583
                return SceneInfo();
×
584

585
        SceneInfo scene;
×
586
        try
587
        {
588
                if(!SceneInfo::loadByID(id,scene))
×
589
                {
590
                        showMessage(q_("Could not load scene info, please check log for error messages!"));
×
591
                        return SceneInfo();
×
592
                }
593
        }
594
        catch (std::runtime_error& e)
×
595
        {
596
                //TODO do away with the exceptions if possible
597
                qCCritical(scenery3d) << "ERROR while loading 3D scenery with id " <<  id  << ", (" << e.what() << ")";
×
598
                return SceneInfo();
×
599
        }
×
600

601
        loadScene(scene);
×
602
        return scene;
×
603
}
×
604

605
SceneInfo Scenery3d::loadScenery3dByName(const QString& name)
×
606
{
607
        if (name.isEmpty())
×
608
            return SceneInfo();
×
609

610
        QString id = SceneInfo::getIDFromName(name);
×
611

612
        if(id.isEmpty())
×
613
        {
614
                showMessage(QString(q_("Could not find scene ID for %1")).arg(name));
×
615
                return SceneInfo();
×
616
        }
617
        return loadScenery3dByID(id);
×
618
}
×
619

620
SceneInfo Scenery3d::getCurrentScene() const
×
621
{
622
        if(currentScene)
×
623
                return currentScene->getSceneInfo();
×
624
        return SceneInfo();
×
625
}
626

627
QString Scenery3d::getCurrentSceneID() const
×
628
{
629
        return currentScene ? currentScene->getSceneInfo().id : QString();
×
630
}
631

632
QString Scenery3d::getLoadingSceneID() const
×
633
{
634
        return currentLoadScene.id;
×
635
}
636

637
void Scenery3d::setDefaultScenery3dID(const QString& id)
×
638
{
639
        defaultScenery3dID = id;
×
640

641
        conf->setValue(S3D_CONFIG_PREFIX + "/default_location_id", id);
×
642
}
×
643

644
void Scenery3d::setEnableScene(const bool enable)
×
645
{
646
        if(enable && ! getCurrentScene().isValid)
×
647
        {
648
                //check if a default scene is set and load that
649
                QString id = getDefaultScenery3dID();
×
650
                if(!id.isEmpty())
×
651
                {
652
                        if(!currentLoadScene.isValid)
×
653
                                loadScenery3dByID(id);
×
654
                        return;
×
655
                }
656
                else
657
                {
658
                        flagEnabled = false;
×
659
                        showMessage(q_("Please load a scene first!"));
×
660
                        emit enableSceneChanged(false);
×
661
                }
662
        }
×
663
        if(enable!=flagEnabled)
×
664
        {
665
                flagEnabled=enable;
×
666
                if (renderer->getCubemapSize()==0)
×
667
                {
668
                        //TODO FS: remove this?
669
                        if (flagEnabled)
×
670
                        {
671
                                oldProjectionType= StelApp::getInstance().getCore()->getCurrentProjectionType();
×
672
                                StelApp::getInstance().getCore()->setCurrentProjectionType(StelCore::ProjectionPerspective);
×
673
                        }
674
                        else
675
                                StelApp::getInstance().getCore()->setCurrentProjectionType(oldProjectionType);
×
676
                }
677

678
                emit enableSceneChanged(flagEnabled);
×
679
        }
680
}
681

682
bool Scenery3d::getEnablePixelLighting() const
×
683
{
684
        return renderer->getPixelLightingEnabled();
×
685
}
686

687
void Scenery3d::setEnablePixelLighting(const bool val)
×
688
{
689
        if(val != getEnablePixelLighting())
×
690
        {
691
                if(!val)
×
692
                {
693
                        setEnableBumps(false);
×
694
                        setEnableShadows(false);
×
695
                }
696
                showMessage(QString(q_("Per-Pixel shading %1.")).arg(val? qc_("on","enable") : qc_("off","disable")));
×
697

698
                renderer->setPixelLightingEnabled(val);
×
699
                conf->setValue(S3D_CONFIG_PREFIX + "/flag_pixel_lighting", val);
×
700
                emit enablePixelLightingChanged(val);
×
701
        }
702
}
×
703

704
bool Scenery3d::getEnableShadows() const
×
705
{
706
        return renderer->getShadowsEnabled();
×
707
}
708

709
void Scenery3d::setEnableShadows(const bool enableShadows)
×
710
{
711
        if(enableShadows != getEnableShadows())
×
712
        {
713
                if (renderer->getShadowmapSize() && getEnablePixelLighting())
×
714
                {
715
                        showMessage(QString(q_("Shadows %1.")).arg(enableShadows? qc_("on","enable") : qc_("off","disable")));
×
716
                        renderer->setShadowsEnabled(enableShadows);
×
717
                        emit enableShadowsChanged(enableShadows);
×
718
                } else
719
                {
720
                        showMessage(QString(q_("Shadows deactivated or not possible.")));
×
721
                        renderer->setShadowsEnabled(false);
×
722
                        emit enableShadowsChanged(false);
×
723
                }
724

725
                conf->setValue(S3D_CONFIG_PREFIX + "/flag_shadow",getEnableShadows());
×
726
        }
727
}
×
728

729
bool Scenery3d::getUseSimpleShadows() const
×
730
{
731
        return renderer->getUseSimpleShadows();
×
732
}
733

734
void Scenery3d::setUseSimpleShadows(const bool simpleShadows)
×
735
{
736
        renderer->setUseSimpleShadows(simpleShadows);
×
737

738
        conf->setValue(S3D_CONFIG_PREFIX + "/flag_shadow_simple",simpleShadows);
×
739
        emit useSimpleShadowsChanged(simpleShadows);
×
740
}
×
741

742
bool Scenery3d::getEnableBumps() const
×
743
{
744
        return renderer->getBumpsEnabled();
×
745
}
746

747
void Scenery3d::setEnableBumps(const bool enableBumps)
×
748
{
749
        if(enableBumps != getEnableBumps())
×
750
        {
751
                showMessage(QString(q_("Surface bumps %1.")).arg(enableBumps? qc_("on","enable") : qc_("off","disable")));
×
752
                renderer->setBumpsEnabled(enableBumps);
×
753

754
                conf->setValue(S3D_CONFIG_PREFIX + "/flag_bumpmap", enableBumps);
×
755
                emit enableBumpsChanged(enableBumps);
×
756
        }
757
}
×
758

759
S3DEnum::ShadowFilterQuality Scenery3d::getShadowFilterQuality() const
×
760
{
761
        return renderer->getShadowFilterQuality();
×
762
}
763

764
void Scenery3d::setShadowFilterQuality(const S3DEnum::ShadowFilterQuality val)
×
765
{
766
        S3DEnum::ShadowFilterQuality oldVal = getShadowFilterQuality();
×
767
        if(oldVal == val)
×
768
                return;
×
769

770
        conf->setValue(S3D_CONFIG_PREFIX + "/shadow_filter_quality",val);
×
771
        renderer->setShadowFilterQuality(val);
×
772
        emit shadowFilterQualityChanged(val);
×
773
}
774

775
bool Scenery3d::getEnablePCSS() const
×
776
{
777
        return renderer->getPCSS();
×
778
}
779

780
void Scenery3d::setEnablePCSS(const bool val)
×
781
{
782
        renderer->setPCSS(val);
×
783
        conf->setValue(S3D_CONFIG_PREFIX + "/flag_pcss",val);
×
784

785
        emit enablePCSSChanged(val);
×
786
}
×
787

788
S3DEnum::CubemappingMode Scenery3d::getCubemappingMode() const
×
789
{
790
        return renderer->getCubemappingMode();
×
791
}
792

793
void Scenery3d::setCubemappingMode(const S3DEnum::CubemappingMode val)
×
794
{
795
        renderer->setCubemappingMode(val);
×
796
        S3DEnum::CubemappingMode realVal = renderer->getCubemappingMode();
×
797

798
        if(val!=realVal)
×
799
                showMessage(q_("Selected cubemap mode not supported, falling back to '6 Textures'"));
×
800

801
        conf->setValue(S3D_CONFIG_PREFIX + "/cubemap_mode",realVal);
×
802
        emit cubemappingModeChanged(realVal);
×
803
}
×
804

805
bool Scenery3d::getUseFullCubemapShadows() const
×
806
{
807
        return renderer->getUseFullCubemapShadows();
×
808
}
809

810
void Scenery3d::setUseFullCubemapShadows(const bool useFullCubemapShadows)
×
811
{
812
        renderer->setUseFullCubemapShadows(useFullCubemapShadows);
×
813

814
        conf->setValue(S3D_CONFIG_PREFIX + "/flag_cubemap_fullshadows",useFullCubemapShadows);
×
815
        emit useFullCubemapShadowsChanged(useFullCubemapShadows);
×
816
}
×
817

818
bool Scenery3d::getEnableDebugInfo() const
×
819
{
820
        return renderer->getDebugEnabled();
×
821
}
822

823
void Scenery3d::setEnableDebugInfo(const bool debugEnabled)
×
824
{
825
        if(debugEnabled != getEnableDebugInfo())
×
826
        {
827
                renderer->setDebugEnabled(debugEnabled);
×
828
                emit enableDebugInfoChanged(debugEnabled);
×
829
        }
830
}
×
831

832
bool Scenery3d::getEnableLocationInfo() const
×
833
{
834
        return renderer->getLocationInfoEnabled();
×
835
}
836

837
void Scenery3d::setEnableLocationInfo(const bool enableLocationInfo)
×
838
{
839
        if(enableLocationInfo != getEnableLocationInfo())
×
840
        {
841
                renderer->setLocationInfoEnabled(enableLocationInfo);
×
842

843
                conf->setValue(S3D_CONFIG_PREFIX + "/flag_location_info",enableLocationInfo);
×
844

845
                emit enableLocationInfoChanged(enableLocationInfo);
×
846
        }
847
}
×
848

849
void Scenery3d::setForceHorizonPolyline(const bool forcePolyline)
×
850
{
851
        if(forcePolyline != getForceHorizonPolyline())
×
852
        {
853
                forceHorizonPolyline=forcePolyline;
×
854

855
                conf->setValue(S3D_CONFIG_PREFIX + "/force_landscape_polyline",forcePolyline);
×
856

857
                emit forceHorizonPolylineChanged(forcePolyline);
×
858
        }
859
}
×
860

861
bool Scenery3d::getForceHorizonPolyline() const
×
862
{
863
        return forceHorizonPolyline;
×
864
}
865

866
bool Scenery3d::getEnableTorchLight() const
×
867
{
868
        return renderer->getTorchEnabled();
×
869
}
870

871
void Scenery3d::setEnableTorchLight(const bool enableTorchLight)
×
872
{
873
        if(enableTorchLight != getEnableTorchLight())
×
874
        {
875
                renderer->setTorchEnabled(enableTorchLight);
×
876

877
                conf->setValue(S3D_CONFIG_PREFIX + "/torch_enabled",enableTorchLight);
×
878

879
                emit enableTorchLightChanged(enableTorchLight);
×
880
        }
881
}
×
882

883
float Scenery3d::getTorchStrength() const
×
884
{
885
        return renderer->getTorchBrightness();
×
886
}
887

888
void Scenery3d::setTorchStrength(const float torchStrength)
×
889
{
890
        renderer->setTorchBrightness(torchStrength);
×
891

892
        conf->setValue(S3D_CONFIG_PREFIX + "/torch_brightness",torchStrength);
×
893

894
        emit torchStrengthChanged(torchStrength);
×
895
}
×
896

897
float Scenery3d::getTorchRange() const
×
898
{
899
        return renderer->getTorchRange();
×
900
}
901

902
void Scenery3d::setTorchRange(const float torchRange)
×
903
{
904
        renderer->setTorchRange(torchRange);
×
905

906
        conf->setValue(S3D_CONFIG_PREFIX+ "/torch_range",torchRange);
×
907

908
        emit torchRangeChanged(torchRange);
×
909
}
×
910

911
bool Scenery3d::getEnableLazyDrawing() const
×
912
{
913
        return renderer->getLazyCubemapEnabled();
×
914
}
915

916
void Scenery3d::setEnableLazyDrawing(const bool val)
×
917
{
918
        showMessage(QString(q_("Lazy cubemapping: %1")).arg(val?q_("enabled"):q_("disabled")));
×
919
        renderer->setLazyCubemapEnabled(val);
×
920

921
        conf->setValue(S3D_CONFIG_PREFIX + "/flag_lazy_cubemap",val);
×
922
        emit enableLazyDrawingChanged(val);
×
923
}
×
924

925
double Scenery3d::getLazyDrawingInterval() const
×
926
{
927
        return renderer->getLazyCubemapInterval();
×
928
}
929

930
void Scenery3d::setLazyDrawingInterval(const double val)
×
931
{
932
        renderer->setLazyCubemapInterval(val);
×
933

934
        conf->setValue(S3D_CONFIG_PREFIX + "/cubemap_lazy_interval",val);
×
935
        emit lazyDrawingIntervalChanged(val);
×
936
}
×
937

938
bool Scenery3d::getOnlyDominantFaceWhenMoving() const
×
939
{
940
        bool v1,v2;
941
        renderer->getLazyCubemapUpdateOnlyDominantFaceOnMoving(v1,v2);
×
942
        return v1;
×
943
}
944

945
void Scenery3d::setOnlyDominantFaceWhenMoving(const bool val)
×
946
{
947
        bool v1,v2;
948
        renderer->getLazyCubemapUpdateOnlyDominantFaceOnMoving(v1,v2);
×
949
        renderer->setLazyCubemapUpdateOnlyDominantFaceOnMoving(val,v2);
×
950

951
        conf->setValue(S3D_CONFIG_PREFIX + "/flag_lazy_dominantface",val);
×
952
        emit onlyDominantFaceWhenMovingChanged(val);
×
953
}
×
954

955
bool Scenery3d::getSecondDominantFaceWhenMoving() const
×
956
{
957
        bool v1,v2;
958
        renderer->getLazyCubemapUpdateOnlyDominantFaceOnMoving(v1,v2);
×
959
        return v2;
×
960
}
961

962
void Scenery3d::setSecondDominantFaceWhenMoving(const bool val)
×
963
{
964
        bool v1,v2;
965
        renderer->getLazyCubemapUpdateOnlyDominantFaceOnMoving(v1,v2);
×
966
        renderer->setLazyCubemapUpdateOnlyDominantFaceOnMoving(v1,val);
×
967

968
        conf->setValue(S3D_CONFIG_PREFIX + "/flag_lazy_seconddominantface",val);
×
969
        emit secondDominantFaceWhenMovingChanged(val);
×
970
}
×
971

972
void Scenery3d::forceCubemapRedraw()
×
973
{
974
        renderer->invalidateCubemap();
×
975
}
×
976

977
uint Scenery3d::getCubemapSize() const
×
978
{
979
        return renderer->getCubemapSize();
×
980
}
981

982
void Scenery3d::setCubemapSize(const uint val)
×
983
{
984
        if(val != getCubemapSize())
×
985
        {
986
                renderer->setCubemapSize(val);
×
987

988
                //hardware may not support the value, get real value set
989
                uint realVal = renderer->getCubemapSize();
×
990
                if(realVal==val)
×
991
                        showMessage(q_("Cubemap size changed"));
×
992
                else
993
                        showMessage(QString(q_("Cubemap size not supported, set to %1")).arg(realVal));
×
994

995
                conf->setValue(S3D_CONFIG_PREFIX + "/cubemap_size",realVal);
×
996
                emit cubemapSizeChanged(realVal);
×
997
        }
998
}
×
999

1000
uint Scenery3d::getShadowmapSize() const
×
1001
{
1002
        return renderer->getShadowmapSize();
×
1003
}
1004

1005
void Scenery3d::setShadowmapSize(const uint val)
×
1006
{
1007
        if(val != getShadowmapSize())
×
1008
        {
1009
                renderer->setShadowmapSize(val);
×
1010

1011
                //hardware may not support the value, get real value set
1012
                uint realVal = renderer->getShadowmapSize();
×
1013
                if(realVal==val)
×
1014
                        showMessage(q_("Shadowmap size changed"));
×
1015
                else
1016
                        showMessage(QString(q_("Shadowmap size not supported, set to %1")).arg(realVal));
×
1017

1018
                conf->setValue(S3D_CONFIG_PREFIX + "/shadowmap_size",realVal);
×
1019
                emit shadowmapSizeChanged(realVal);
×
1020
        }
1021
}
×
1022

1023
bool Scenery3d::getIsGeometryShaderSupported() const
×
1024
{
1025
        return renderer->isGeometryShaderCubemapSupported();
×
1026
}
1027

1028
bool Scenery3d::getAreShadowsSupported() const
×
1029
{
1030
        return renderer->areShadowsSupported();
×
1031
}
1032

1033
bool Scenery3d::getIsShadowFilteringSupported() const
×
1034
{
1035
        return renderer->isShadowFilteringSupported();
×
1036
}
1037

1038
bool Scenery3d::getIsANGLE() const
×
1039
{
1040
        return renderer->isANGLEContext();
×
1041
}
1042

1043
uint Scenery3d::getMaximumFramebufferSize() const
×
1044
{
1045
        return renderer->getMaximumFramebufferSize();
×
1046
}
1047

1048
void Scenery3d::setView(const StoredView &view, const bool setDate)
×
1049
{
1050
        if(!currentScene)
×
1051
        {
1052
                qCWarning(scenery3d)<<"Can't set current view, no scene loaded!";
×
1053
                return;
×
1054
        }
1055

1056
        //update position
1057
        //important: set eye height first
1058
        currentScene->setEyeHeight(view.position[3]);
×
1059
        //then, set grid position
1060
        currentScene->setGridPosition(Vec3d(view.position[0],view.position[1],view.position[2]));
×
1061

1062
        //update time, if relevant and wanted.
1063
        if (view.jdIsRelevant && setDate)
×
1064
        {
1065
                StelCore *core=StelApp::getInstance().getCore();
×
1066
                core->setJD(view.jd);
×
1067
        }
1068

1069
        //update view vector
1070
        // This vector is (az_deg, alt_deg, fov_deg)
1071
        Vec3d v;
×
1072
        StelUtils::spheToRect((180.0-view.view_fov[0])*M_PI/180.0, view.view_fov[1]*M_PI/180.0, v);
×
1073
        mvMgr->setViewDirectionJ2000(StelApp::getInstance().getCore()->altAzToJ2000(v, StelCore::RefractionOff));
×
1074
        mvMgr->zoomTo(view.view_fov[2]);
×
1075
}
1076

1077
StoredView Scenery3d::getCurrentView()
×
1078
{
1079
        if(!currentScene)
×
1080
        {
1081
                qCWarning(scenery3d)<<"Can't return current view, no scene loaded!";
×
1082
                return StoredView();
×
1083
        }
1084

1085
        StoredView view;
×
1086
        view.isGlobal = false;
×
1087
        StelCore* core = StelApp::getInstance().getCore();
×
1088

1089
        //get view vec
1090
        Vec3d vd = mvMgr->getViewDirectionJ2000();
×
1091
        //convert to alt/az format
1092
        vd = core->j2000ToAltAz(vd, StelCore::RefractionOff);
×
1093
        //convert to spherical angles
1094
        StelUtils::rectToSphe(&view.view_fov[0],&view.view_fov[1],vd);
×
1095
        //convert to degrees
1096
        view.view_fov[0]*=180.0f/M_PIf;
×
1097
        view.view_fov[1]*=180.0f/M_PIf;
×
1098
        // we must patch azimuth
1099
        view.view_fov[0]=180.0f-view.view_fov[0];
×
1100
        //3rd comp is fov
1101
        view.view_fov[2] = static_cast<float>(mvMgr->getAimFov());
×
1102

1103
        //get current grid pos + eye height
1104
        Vec3d pos = currentScene->getGridPosition();
×
1105
        view.position[0] = pos[0];
×
1106
        view.position[1] = pos[1];
×
1107
        view.position[2] = pos[2];
×
1108
        view.position[3] = currentScene->getEyeHeight();
×
1109

1110
        return view;
×
1111
}
×
1112

1113
void Scenery3d::showMessage(const QString& message)
×
1114
{
1115
        currentMessage=message;
×
1116
        messageFader=true;
×
1117
        messageTimer->start();
×
1118
}
×
1119

1120
void Scenery3d::clearMessage()
×
1121
{
1122
        messageFader = false;
×
1123
}
×
1124

1125
/////////////////////////////////////////////////////////////////////
1126
StelModule* Scenery3dStelPluginInterface::getStelModule() const
×
1127
{
1128
        return new Scenery3d();
×
1129
}
1130

1131
StelPluginInfo Scenery3dStelPluginInterface::getPluginInfo() const
×
1132
{
1133
        // Allow to load the resources when used as a static plugin
1134
        Q_INIT_RESOURCE(Scenery3d);
×
1135

1136
        StelPluginInfo info;
×
1137
        info.id = "Scenery3d";
×
1138
        info.version = SCENERY3D_PLUGIN_VERSION;
×
1139
        info.license = SCENERY3D_PLUGIN_LICENSE;
×
1140
        info.displayedName = N_("3D Sceneries");
×
1141
        info.authors = "Georg Zotti, Simon Parzer, Peter Neubauer, Andrei Borza, Florian Schaukowitsch";
×
1142
        info.contact = "https://homepage.univie.ac.at/Georg.Zotti";
×
1143
        info.description = N_("<p>3D foreground renderer. Walk around, find and avoid obstructions in your garden, "
×
1144
                              "find and demonstrate possible astronomical alignments in temples, see shadows on sundials etc.</p>"
1145
                              "<p>To move around, press Ctrl+cursor keys. To lift eye height, use Ctrl+PgUp/PgDn. "
1146
                              "Movement speed is linked to field of view (i.e. zoom in for fine adjustments). "
1147
                              "You can even keep moving by releasing Ctrl before cursor key.</p>");
1148
        info.acknowledgements=N_("Development of this plugin was in parts supported by the Austrian Science Fund (FWF) project ASTROSIM (P 21208-G19; https://astrosim.univie.ac.at/). <br/>"
×
1149
                                 "Further development is in parts supported by the Ludwig Boltzmann Institute for Archaeological Prospection and Virtual Archaeology, Vienna, Austria (http://archpro.lbg.ac.at/).");
1150
        return info;
×
1151
}
×
1152

1153
QObjectList Scenery3dStelPluginInterface::getExtensionList() const
×
1154
{
1155
        QObjectList ret;
×
1156
        ret.append(new Scenery3dRemoteControlService());
×
1157
        return ret;
×
1158
}
×
1159
/////////////////////////////////////////////////////////////////////
1160

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc