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

Stellarium / stellarium / 15670918640

16 Jun 2025 02:08AM UTC coverage: 11.775% (-0.2%) from 11.931%
15670918640

push

github

alex-w
Updated data

14700 of 124846 relevant lines covered (11.77%)

18324.52 hits per line

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

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

20
#include "StelApp.hpp"
21

22
#include "Dithering.hpp"
23
#include "StelCore.hpp"
24
#include "StelMainView.hpp"
25
#include "StelSplashScreen.hpp"
26
#include "StelUtils.hpp"
27
#include "StelTextureMgr.hpp"
28
#include "StelObjectMgr.hpp"
29
#include "ConstellationMgr.hpp"
30
#include "AsterismMgr.hpp"
31
#include "HipsMgr.hpp"
32
#include "NebulaMgr.hpp"
33
#include "LandscapeMgr.hpp"
34
#include "CustomObjectMgr.hpp"
35
#include "HighlightMgr.hpp"
36
#include "GridLinesMgr.hpp"
37
#include "MilkyWay.hpp"
38
#include "ZodiacalLight.hpp"
39
#include "LabelMgr.hpp"
40
#include "MarkerMgr.hpp"
41
#include "SolarSystem.hpp"
42
#include "NomenclatureMgr.hpp"
43
#include "SporadicMeteorMgr.hpp"
44
#include "SpecificTimeMgr.hpp"
45
#include "StarMgr.hpp"
46
#include "StelProjector.hpp"
47
#include "StelLocationMgr.hpp"
48
#include "ToastMgr.hpp"
49
#include "StelActionMgr.hpp"
50
#include "StelPropertyMgr.hpp"
51
#include "StelProgressController.hpp"
52
#include "StelModuleMgr.hpp"
53
#include "StelLocaleMgr.hpp"
54
#include "StelSkyCultureMgr.hpp"
55
#include "StelFileMgr.hpp"
56
#include "StelSkyLayerMgr.hpp"
57
#include "StelAudioMgr.hpp"
58
#include "StelVideoMgr.hpp"
59
#include "SpecialMarkersMgr.hpp"
60
#include "StelViewportEffect.hpp"
61
#include "StelGuiBase.hpp"
62
#include "StelGui.hpp"
63
#include "StelGuiItems.hpp"
64
#include "StelPainter.hpp"
65
#ifdef ENABLE_SCRIPTING
66
 #include "StelScriptMgr.hpp"
67
 #include "StelMainScriptAPIProxy.hpp"
68

69
#ifdef USE_STATIC_PLUGIN_CALENDARS
70
 #include "../plugins/Calendars/src/Calendars.hpp"
71
#endif
72
#endif
73

74

75
#include <cstdlib>
76
#include <iostream>
77
#include <QDebug>
78
#include <QFile>
79
#include <QFileInfo>
80
#include <QMouseEvent>
81
#include <QNetworkAccessManager>
82
#include <QNetworkDiskCache>
83
#include <QNetworkProxy>
84
#include <QNetworkReply>
85
#include <QOpenGLBuffer>
86
#include <QOpenGLContext>
87
#include <QOpenGLShaderProgram>
88
#include <QOpenGLVertexArrayObject>
89
#include <QOpenGLFramebufferObject>
90
#include <QOpenGLFunctions_3_3_Core>
91
#include <QString>
92
#include <QStringList>
93
#include <QSysInfo>
94
#include <QTextStream>
95
#include <QTimer>
96
#include <QDir>
97
#include <QCoreApplication>
98
#include <QGuiApplication>
99
#include <QScreen>
100
#include <QDateTime>
101
#include <QRegularExpression>
102
#include <QRandomGenerator>
103
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
104
#include <QImageReader>
105
#endif
106
#ifdef ENABLE_SPOUT
107
#include <QMessageBox>
108
#include "SpoutSender.hpp"
109
#endif
110

111
#ifdef USE_STATIC_PLUGIN_HELLOSTELMODULE
112
Q_IMPORT_PLUGIN(HelloStelModuleStelPluginInterface)
113
#endif
114

115
#ifdef USE_STATIC_PLUGIN_SIMPLEDRAWLINE
116
Q_IMPORT_PLUGIN(SimpleDrawLineStelPluginInterface)
117
#endif
118

119
#ifdef USE_STATIC_PLUGIN_ANGLEMEASURE
120
Q_IMPORT_PLUGIN(AngleMeasureStelPluginInterface)
19✔
121
#endif
122

123
#ifdef USE_STATIC_PLUGIN_ARCHAEOLINES
124
Q_IMPORT_PLUGIN(ArchaeoLinesStelPluginInterface)
19✔
125
#endif
126

127
#ifdef USE_STATIC_PLUGIN_CALENDARS
128
Q_IMPORT_PLUGIN(CalendarsStelPluginInterface)
19✔
129
#endif
130

131
#ifdef USE_STATIC_PLUGIN_SATELLITES
132
Q_IMPORT_PLUGIN(SatellitesStelPluginInterface)
19✔
133
#endif
134

135
#ifdef USE_STATIC_PLUGIN_TEXTUSERINTERFACE
136
Q_IMPORT_PLUGIN(TextUserInterfaceStelPluginInterface)
19✔
137
#endif
138

139
#ifdef USE_STATIC_PLUGIN_OCULARS
140
Q_IMPORT_PLUGIN(OcularsStelPluginInterface)
19✔
141
#endif
142

143
#ifdef USE_STATIC_PLUGIN_OCULUS
144
Q_IMPORT_PLUGIN(OculusStelPluginInterface)
145
#endif
146

147
#ifdef USE_STATIC_PLUGIN_TELESCOPECONTROL
148
Q_IMPORT_PLUGIN(TelescopeControlStelPluginInterface)
19✔
149
#endif
150

151
#ifdef USE_STATIC_PLUGIN_SOLARSYSTEMEDITOR
152
Q_IMPORT_PLUGIN(SolarSystemEditorStelPluginInterface)
19✔
153
#endif
154

155
#ifdef USE_STATIC_PLUGIN_LENSDISTORTIONESTIMATOR
156
Q_IMPORT_PLUGIN(LensDistortionEstimatorStelPluginInterface)
19✔
157
#endif
158

159
#ifdef USE_STATIC_PLUGIN_METEORSHOWERS
160
Q_IMPORT_PLUGIN(MeteorShowersStelPluginInterface)
19✔
161
#endif
162

163
#ifdef USE_STATIC_PLUGIN_NAVSTARS
164
Q_IMPORT_PLUGIN(NavStarsStelPluginInterface)
19✔
165
#endif
166

167
#ifdef USE_STATIC_PLUGIN_NOVAE
168
Q_IMPORT_PLUGIN(NovaeStelPluginInterface)
19✔
169
#endif
170

171
#ifdef USE_STATIC_PLUGIN_SUPERNOVAE
172
Q_IMPORT_PLUGIN(SupernovaeStelPluginInterface)
19✔
173
#endif
174

175
#ifdef USE_STATIC_PLUGIN_QUASARS
176
Q_IMPORT_PLUGIN(QuasarsStelPluginInterface)
19✔
177
#endif
178

179
#ifdef USE_STATIC_PLUGIN_PULSARS
180
Q_IMPORT_PLUGIN(PulsarsStelPluginInterface)
19✔
181
#endif
182

183
#ifdef USE_STATIC_PLUGIN_EXOPLANETS
184
Q_IMPORT_PLUGIN(ExoplanetsStelPluginInterface)
19✔
185
#endif
186

187
#ifdef USE_STATIC_PLUGIN_EQUATIONOFTIME
188
Q_IMPORT_PLUGIN(EquationOfTimeStelPluginInterface)
19✔
189
#endif
190

191
#ifdef USE_STATIC_PLUGIN_POINTERCOORDINATES
192
Q_IMPORT_PLUGIN(PointerCoordinatesStelPluginInterface)
19✔
193
#endif
194

195
#ifdef USE_STATIC_PLUGIN_OBSERVABILITY
196
Q_IMPORT_PLUGIN(ObservabilityStelPluginInterface)
19✔
197
#endif
198

199
#ifdef USE_STATIC_PLUGIN_SCENERY3D
200
Q_IMPORT_PLUGIN(Scenery3dStelPluginInterface)
19✔
201
#endif
202

203
#ifdef USE_STATIC_PLUGIN_REMOTECONTROL
204
Q_IMPORT_PLUGIN(RemoteControlStelPluginInterface)
19✔
205
#endif
206

207
#ifdef USE_STATIC_PLUGIN_REMOTESYNC
208
Q_IMPORT_PLUGIN(RemoteSyncStelPluginInterface)
19✔
209
#endif
210

211
#ifdef USE_STATIC_PLUGIN_VTS
212
Q_IMPORT_PLUGIN(VtsStelPluginInterface)
213
#endif
214

215
#ifdef USE_STATIC_PLUGIN_ONLINEQUERIES
216
Q_IMPORT_PLUGIN(OnlineQueriesPluginInterface)
19✔
217
#endif
218

219
#ifdef USE_STATIC_PLUGIN_NEBULATEXTURES
220
Q_IMPORT_PLUGIN(NebulaTexturesStelPluginInterface)
19✔
221
#endif
222

223
#ifdef USE_STATIC_PLUGIN_MOSAICCAMERA
224
Q_IMPORT_PLUGIN(MosaicCameraStelPluginInterface)
19✔
225
#endif
226

227
// Initialize static variables
228
StelApp* StelApp::singleton = Q_NULLPTR;
229
qint64 StelApp::startMSecs = 0;
230
double StelApp::animationScale = 1.;
231

232
void StelApp::initStatic()
×
233
{
234
        StelApp::startMSecs = QDateTime::currentMSecsSinceEpoch();
×
235
}
×
236

237
void StelApp::deinitStatic()
×
238
{
239
        StelApp::startMSecs = 0;
×
240
}
×
241

242
/*************************************************************************
243
 Create and initialize the main Stellarium application.
244
*************************************************************************/
245
StelApp::StelApp(StelMainView *parent)
×
246
        : QObject(parent)
247
        , randomGenerator(Q_NULLPTR)
×
248
        , mainWin(parent)
×
249
        , core(Q_NULLPTR)
×
250
        , moduleMgr(Q_NULLPTR)
×
251
        , localeMgr(Q_NULLPTR)
×
252
        , skyCultureMgr(Q_NULLPTR)
×
253
        , actionMgr(Q_NULLPTR)
×
254
        , propMgr(Q_NULLPTR)
×
255
        , textureMgr(Q_NULLPTR)
×
256
        , stelObjectMgr(Q_NULLPTR)
×
257
        , planetLocationMgr(Q_NULLPTR)
×
258
        , networkAccessManager(Q_NULLPTR)
×
259
        , audioMgr(Q_NULLPTR)
×
260
        , videoMgr(Q_NULLPTR)
×
261
        , skyImageMgr(Q_NULLPTR)
×
262
#ifdef ENABLE_SCRIPTING
263
        , scriptAPIProxy(Q_NULLPTR)
×
264
        , scriptMgr(Q_NULLPTR)
×
265
#endif
266
        , stelGui(Q_NULLPTR)
×
267
        , devicePixelsPerPixel(1.)
×
268
        , fps(0)
×
269
        , frame(0)
×
270
        , frameTimeAccum(0.)
×
271
        , flagNightVision(false)
×
272
        , confSettings(Q_NULLPTR)
×
273
        , initialized(false)
×
274
        , saveProjW(-1.)
×
275
        , saveProjH(-1.)
×
276
        , nbDownloadedFiles(0)
×
277
        , totalDownloadedSize(0)
×
278
        , nbUsedCache(0)
×
279
        , totalUsedCacheSize(0)
×
280
        , screenFontSize(getDefaultGuiFontSize())
×
281
        , renderBuffer(Q_NULLPTR)
×
282
        , viewportEffect(Q_NULLPTR)
×
283
        , gl(Q_NULLPTR)
×
284
        , flagShowDecimalDegrees(false)
×
285
        , flagUseAzimuthFromSouth(false)
×
286
        , flagUseFormattingOutput(false)
×
287
        , flagUseCCSDesignation(false)
×
288
        , flagOverwriteInfoColor(false)
×
289
        , overwriteInfoColor(Vec3f(1.f))
×
290
        , daylightInfoColor(Vec3f(0.f))
×
291
        #ifdef ENABLE_SPOUT
292
        , spoutSender(Q_NULLPTR)
293
        #endif
294
        , currentFbo(0)
×
295
{
296
        setObjectName("StelApp");
×
297

298
        // Can't create 2 StelApp instances
299
        Q_ASSERT(!singleton);
×
300
        singleton = this;
×
301

302
        moduleMgr = new StelModuleMgr();
×
303
        randomGenerator = new QRandomGenerator(static_cast<quint32>(QDateTime::currentMSecsSinceEpoch()));
×
304
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
305
        // QImageReader has a new limitation. For super-large landscapes or other textures, we need to circumvent this.
306
        QImageReader::setAllocationLimit(1024); // Allow max texture size 16k x 16k
×
307
#endif
308
}
×
309

310
/*************************************************************************
311
 Deinitialize and destroy the main Stellarium application.
312
*************************************************************************/
313
StelApp::~StelApp()
×
314
{
315
        qInfo() << qPrintable(QString("Downloaded %1 files (%2 kbytes) in a session of %3 sec (average of %4 kB/s + %5 files from cache (%6 kB)).").arg(nbDownloadedFiles).arg(totalDownloadedSize/1024).arg(getTotalRunTime()).arg(static_cast<double>(totalDownloadedSize/1024)/getTotalRunTime()).arg(nbUsedCache).arg(totalUsedCacheSize/1024));
×
316

317
        stelObjectMgr->unSelect();
×
318
        moduleMgr->unloadModule("StelVideoMgr", false);  // We need to delete it afterward
×
319
        moduleMgr->unloadModule("StelSkyLayerMgr", false);  // We need to delete it afterward
×
320
        moduleMgr->unloadModule("StelObjectMgr", false);// We need to delete it afterward
×
321
        moduleMgr->unloadModule("StelSkyCultureMgr", true);// No need to delete only later!
×
322
        StelModuleMgr* tmp = moduleMgr;
×
323
        moduleMgr = new StelModuleMgr(); // Create a secondary instance to avoid crashes at other deinit
×
324
        delete tmp; tmp=Q_NULLPTR;
×
325
        delete skyImageMgr; skyImageMgr=Q_NULLPTR;
×
326
        delete core; core=Q_NULLPTR;
×
327
        delete localeMgr; localeMgr=Q_NULLPTR;
×
328
        delete audioMgr; audioMgr=Q_NULLPTR;
×
329
        delete videoMgr; videoMgr=Q_NULLPTR;
×
330
        delete stelObjectMgr; stelObjectMgr=Q_NULLPTR; // Delete the module by hand afterward
×
331
        delete textureMgr; textureMgr=Q_NULLPTR;
×
332
        delete planetLocationMgr; planetLocationMgr=Q_NULLPTR;
×
333
        delete moduleMgr; moduleMgr=Q_NULLPTR; // Delete the secondary instance
×
334
        delete actionMgr; actionMgr = Q_NULLPTR;
×
335
        delete propMgr; propMgr = Q_NULLPTR;
×
336
        delete renderBuffer; renderBuffer = Q_NULLPTR;
×
337
        delete randomGenerator; randomGenerator=Q_NULLPTR;
×
338
        Q_ASSERT(singleton);
×
339
        singleton = Q_NULLPTR;
×
340
}
×
341

342
void StelApp::setupNetworkProxy()
×
343
{
344
        QString proxyHost = confSettings->value("proxy/host_name").toString();
×
345
        QString proxyPort = confSettings->value("proxy/port").toString();
×
346
        QString proxyUser = confSettings->value("proxy/user").toString();
×
347
        QString proxyPass = confSettings->value("proxy/password").toString();
×
348
        QString proxyType = confSettings->value("proxy/type").toString();
×
349

350
        // If proxy settings not found in config, use environment variable
351
        // if it is defined.  (Config file over-rides environment).
352
        if (proxyHost.isEmpty() && proxyUser.isEmpty() && proxyPass.isEmpty() && proxyPort.isEmpty())
×
353
        {
354
                char *httpProxyEnv;
355
                httpProxyEnv = std::getenv("http_proxy");
×
356
                if (!httpProxyEnv)
×
357
                {
358
                        httpProxyEnv = std::getenv("HTTP_PROXY");
×
359
                }
360
                if (httpProxyEnv)
×
361
                {
362
                        QString proxyString = QString(httpProxyEnv);
×
363
                        if (!proxyString.isEmpty())
×
364
                        {
365
                                // Handle http_proxy of the form
366
                                // proto://username:password@fqdn:port
367
                                // e.g.:
368
                                // http://usr:pass@proxy.loc:3128/
369
                                // http://proxy.loc:3128/
370
                                // http://2001:62a:4:203:6ab5:99ff:fef2:560b:3128/
371
                                // http://foo:bar@2001:62a:4:203:6ab5:99ff:fef2:560b:3128/
372
                                static const QRegularExpression pre("^([^:]+://)?(?:([^:]+):([^@]*)@)?(.+):([\\d]+)");
×
373
                                QRegularExpressionMatch preMatch=pre.match(proxyString);
×
374
                                if (proxyString.indexOf(pre) >= 0)
×
375
                                {
376
                                        proxyType = preMatch.captured(1);
×
377
                                        proxyUser = preMatch.captured(2);
×
378
                                        proxyPass = preMatch.captured(3);
×
379
                                        proxyHost = preMatch.captured(4);
×
380
                                        proxyPort = preMatch.captured(5);
×
381
                                }
382
                                else
383
                                {
384
                                        qDebug() << "indecipherable environment variable http_proxy:" << proxyString;
×
385
                                        return;
×
386
                                }
387
                        }
×
388
                }
×
389
        }
390

391
        bool useSocksProxy = proxyType.contains("socks", Qt::CaseInsensitive);
×
392

393
        if (!proxyHost.isEmpty())
×
394
        {
395
                QNetworkProxy proxy;
×
396
                if (useSocksProxy)
×
397
                        proxy.setType(QNetworkProxy::Socks5Proxy);
×
398
                else
399
                        proxy.setType(QNetworkProxy::HttpProxy);
×
400
                proxy.setHostName(proxyHost);
×
401
                if (!proxyPort.isEmpty())
×
402
                        proxy.setPort(proxyPort.toUShort());
×
403

404
                if (!proxyUser.isEmpty())
×
405
                        proxy.setUser(proxyUser);
×
406

407
                if (!proxyPass.isEmpty())
×
408
                        proxy.setPassword(proxyPass);
×
409

410
                QString ppDisp = proxyPass;
×
411
                ppDisp.fill('*');
×
412
                if (useSocksProxy)
×
413
                        qDebug() << "Using SOCKS proxy:" << proxyUser << ppDisp << proxyHost << proxyPort;
×
414
                else
415
                        qDebug() << "Using HTTP proxy:" << proxyUser << ppDisp << proxyHost << proxyPort;
×
416
                QNetworkProxy::setApplicationProxy(proxy);
×
417
        }
×
418
}
×
419

420
#ifdef ENABLE_SCRIPTING
421
void StelApp::initScriptMgr()
×
422
{
423
        scriptMgr->addModules();
×
424

425
#ifdef USE_STATIC_PLUGIN_CALENDARS
426
        Calendars *cal=GETSTELMODULE_SILENT(Calendars);
×
427
        if (cal)
×
428
                cal->makeCalendarsScriptable(scriptMgr);
×
429
#endif
430
        QString startupScript;
×
431
        if (qApp->property("onetime_startup_script").isValid())
×
432
                startupScript = qApp->property("onetime_startup_script").toString();
×
433
        else
434
                startupScript = confSettings->value("scripts/startup_script", "startup.ssc").toString();
×
435
        // Use a queued slot call to start the script only once the main qApp event loop is running...
436
        QMetaObject::invokeMethod(scriptMgr,
×
437
                                  "runScript",
438
                                  Qt::QueuedConnection,
439
                                  Q_ARG(QString, startupScript));
×
440
}
×
441
#else
442
void StelApp::initScriptMgr() {}
443
#endif
444

445
QStringList StelApp::getCommandlineArguments()
×
446
{
447
        return qApp->property("stelCommandLine").toStringList();
×
448
}
449

450
void StelApp::init(QSettings* conf)
×
451
{
452
        gl = QOpenGLContext::currentContext()->functions();
×
453
        confSettings = conf;
×
454

455
        devicePixelsPerPixel = StelMainView::getInstance().devicePixelRatioF();
×
456
        qInfo() << "Initial high-DPI scaling factor:" << devicePixelsPerPixel;
×
457

458
        setScreenFontSize(confSettings->value("gui/screen_font_size", getDefaultGuiFontSize()).toInt());
×
459
        setGuiFontSize(confSettings->value("gui/gui_font_size", getDefaultGuiFontSize()).toInt());
×
460
        setScreenButtonScale(confSettings->value("gui/screen_button_scale", 100).toDouble());
×
461

462
        SplashScreen::present(guiFontSizeRatio());
×
463

464
        setFlagImmediateSave(confSettings->value("gui/immediate_save_details", false).toBool());
×
465

466
        core = new StelCore();
×
467
        if (!fuzzyEquals(saveProjW, -1.) && !fuzzyEquals(saveProjH, -1.))
×
468
                core->windowHasBeenResized(0, 0, saveProjW, saveProjH);
×
469
        
470
        //Initializing locale at the beginning to show all strings translated
471
        localeMgr = new StelLocaleMgr();
×
472
        localeMgr->init();
×
473
        //SplashScreen::showMessage(q_("Initializing locales..."));
474

475
        SplashScreen::showMessage(q_("Initializing textures..."));
×
476
        // Initialize AFTER creation of openGL context
477
        textureMgr = new StelTextureMgr();
×
478

479
        SplashScreen::showMessage(q_("Initializing network access..."));
×
480
        networkAccessManager = new QNetworkAccessManager(this);
×
481
        networkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
×
482
        SplashScreen::showMessage(q_("Initializing network disk cache..."));
×
483
        // Activate http cache if Qt version >= 4.5
484
        QNetworkDiskCache* cache = new QNetworkDiskCache(networkAccessManager);
×
485
        //make maximum cache size configurable (in MB)
486
        //the default Qt value (50 MB) is quite low, especially for DSS
487
        cache->setMaximumCacheSize(confSettings->value("main/network_cache_size",300).toInt() * 1024 * 1024);
×
488
        QString cachePath = StelFileMgr::getCacheDir();
×
489

490
        qInfo().noquote() << "Cache directory:" << QDir::toNativeSeparators(cachePath);
×
491
        cache->setCacheDirectory(cachePath);
×
492
        networkAccessManager->setCache(cache);        
×
493
        connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(reportFileDownloadFinished(QNetworkReply*)));
×
494

495
        // Proxy Initialisation
496
        SplashScreen::showMessage(q_("Initializing network proxy..."));
×
497
        setupNetworkProxy();
×
498

499
        //create non-StelModule managers
500
        propMgr = new StelPropertyMgr();
×
501
        skyCultureMgr = new StelSkyCultureMgr();
×
502
        skyCultureMgr->init();
×
503
        getModuleMgr().registerModule(skyCultureMgr);
×
504

505
        planetLocationMgr = new StelLocationMgr();
×
506
        actionMgr = new StelActionMgr();
×
507

508
        // register non-modules for StelProperty tracking
509
        propMgr->registerObject(this);
×
510
        propMgr->registerObject(mainWin);
×
511

512
        // Stel Object Data Base manager
513
        SplashScreen::showMessage(q_("Initializing Object Database..."));
×
514
        stelObjectMgr = new StelObjectMgr();
×
515
        stelObjectMgr->init();
×
516
        getModuleMgr().registerModule(stelObjectMgr);        
×
517

518
        // Hips surveys
519
        SplashScreen::showMessage(q_("Initializing HiPS survey..."));
×
520
        HipsMgr* hipsMgr = new HipsMgr();
×
521
        hipsMgr->init();
×
522
        getModuleMgr().registerModule(hipsMgr);
×
523

524
        // Init the solar system first
525
        SplashScreen::showMessage(q_("Initializing Solar System objects..."));
×
526
        SolarSystem* ssystem = new SolarSystem();
×
527
        ssystem->init();
×
528
        getModuleMgr().registerModule(ssystem);
×
529

530
        // Init the nomenclature for Solar system bodies
531
        SplashScreen::showMessage(q_("Initializing planetary nomenclature..."));
×
532
        NomenclatureMgr* nomenclature = new NomenclatureMgr();
×
533
        nomenclature->init();
×
534
        getModuleMgr().registerModule(nomenclature);
×
535

536
        // Load stars & their names
537
        SplashScreen::showMessage(q_("Initializing stars..."));
×
538
        StarMgr* hip_stars = new StarMgr();
×
539
        hip_stars->init();
×
540
        getModuleMgr().registerModule(hip_stars);
×
541

542
        SplashScreen::showMessage(q_("Initializing core..."));
×
543
        core->init();
×
544

545
        // Init nebulas
546
        SplashScreen::showMessage(q_("Initializing deep-sky objects..."));
×
547
        NebulaMgr* nebulas = new NebulaMgr();
×
548
        nebulas->init();
×
549
        getModuleMgr().registerModule(nebulas);
×
550

551
        // Init milky way
552
        SplashScreen::showMessage(q_("Initializing Milky Way..."));
×
553
        MilkyWay* milky_way = new MilkyWay();
×
554
        milky_way->init();
×
555
        getModuleMgr().registerModule(milky_way);
×
556

557
        // Init zodiacal light
558
        SplashScreen::showMessage(q_("Initializing zodiacal light..."));
×
559
        ZodiacalLight* zodiacal_light = new ZodiacalLight();
×
560
        zodiacal_light->init();
×
561
        getModuleMgr().registerModule(zodiacal_light);
×
562

563
        // Init sky image manager
564
        SplashScreen::showMessage(q_("Initializing sky image layer..."));
×
565
        skyImageMgr = new StelSkyLayerMgr();
×
566
        skyImageMgr->init();
×
567
        getModuleMgr().registerModule(skyImageMgr);
×
568

569
        // Toast surveys
570
        SplashScreen::showMessage(q_("Initializing TOAST surveys..."));
×
571
        ToastMgr* toasts = new ToastMgr();
×
572
        toasts->init();
×
573
        getModuleMgr().registerModule(toasts);
×
574

575
        // Init audio manager. When media support is disabled,
576
        // we silently create dummy managers.
577
#ifdef ENABLE_MEDIA
578
        const bool audioOK = !(qApp->property("onetime_no-audio").toBool())
×
579
                        && confSettings->value("audio/enabled", true).toBool();
×
580
#else
581
        const bool audioOK = false;
582
#endif
583
        if (audioOK)
×
584
                SplashScreen::showMessage(q_("Initializing audio..."));
×
585
        audioMgr = new StelAudioMgr(audioOK);
×
586
        // QtMultimedia can create and destroy intermediate contexts during initialization,
587
        // displacing our main context, see GH#4143. So restore our context.
588
        ensureGLContextCurrent();
×
589

590
        // Init video manager
591
#ifdef ENABLE_MEDIA
592
        SplashScreen::showMessage(q_("Initializing video..."));
×
593
#endif
594
        videoMgr = new StelVideoMgr(audioOK);
×
595
        videoMgr->init();
×
596
        getModuleMgr().registerModule(videoMgr);
×
597

598
        // Constellations
599
        SplashScreen::showMessage(q_("Initializing constellations..."));
×
600
        ConstellationMgr* constellations = new ConstellationMgr(hip_stars);
×
601
        constellations->init();
×
602
        getModuleMgr().registerModule(constellations);
×
603

604
        // Asterisms
605
        SplashScreen::showMessage(q_("Initializing asterisms..."));
×
606
        AsterismMgr* asterisms = new AsterismMgr(hip_stars);
×
607
        asterisms->init();
×
608
        getModuleMgr().registerModule(asterisms);
×
609

610
        // Landscape, atmosphere & cardinal points section
611
        SplashScreen::showMessage(q_("Initializing landscape..."));
×
612
        LandscapeMgr* landscape = new LandscapeMgr();
×
613
        landscape->init();
×
614
        getModuleMgr().registerModule(landscape);
×
615
        // Only now we can switch to auto-landscape. (GH:#3550)
616
        if (landscape->getFlagLandscapeAutoSelection() && (confSettings->value("init_location/location", "auto").toString() == "auto"))
×
617
        {
618
                StelLocation loc=core->getCurrentLocation();
×
619
                QColor color=planetLocationMgr->getColorForCoordinates(loc.getLongitude(), loc.getLatitude());
×
620
                QString landscapeAutoName=QString("ZeroColor(%1)").arg(Vec3f(color).toStr());
×
621
                emit core->targetLocationChanged(loc, landscapeAutoName); // inform others about our next location. E.g., let LandscapeMgr load a new landscape.
×
622
        }
×
623

624
        SplashScreen::showMessage(q_("Initializing grid lines..."));
×
625
        GridLinesMgr* gridLines = new GridLinesMgr();
×
626
        gridLines->init();
×
627
        getModuleMgr().registerModule(gridLines);
×
628
        
629
        SplashScreen::showMessage(q_("Initializing special markers..."));
×
630
        SpecialMarkersMgr* specialMarkers = new SpecialMarkersMgr();
×
631
        specialMarkers->init();
×
632
        getModuleMgr().registerModule(specialMarkers);
×
633

634
        // Sporadic Meteors
635
        SplashScreen::showMessage(q_("Initializing sporadic meteors..."));
×
636
        SporadicMeteorMgr* meteors = new SporadicMeteorMgr(10, 72);
×
637
        meteors->init();
×
638
        getModuleMgr().registerModule(meteors);
×
639

640
        // User labels
641
        SplashScreen::showMessage(q_("Initializing user labels..."));
×
642
        LabelMgr* skyLabels = new LabelMgr();
×
643
        skyLabels->init();
×
644
        getModuleMgr().registerModule(skyLabels);
×
645

646
        SplashScreen::showMessage(q_("Initializing sky cultures..."));
×
647
        skyCultureMgr->init();
×
648

649
        // User markers
650
        SplashScreen::showMessage(q_("Initializing user markers..."));
×
651
        MarkerMgr* skyMarkers = new MarkerMgr();
×
652
        skyMarkers->init();
×
653
        getModuleMgr().registerModule(skyMarkers);
×
654

655
        // Init custom objects
656
        SplashScreen::showMessage(q_("Initializing custom objects..."));
×
657
        CustomObjectMgr* custObj = new CustomObjectMgr();
×
658
        custObj->init();
×
659
        getModuleMgr().registerModule(custObj);
×
660

661
        // Init highlights
662
        SplashScreen::showMessage(q_("Initializing highlights..."));
×
663
        HighlightMgr* hlMgr = new HighlightMgr();
×
664
        hlMgr->init();
×
665
        getModuleMgr().registerModule(hlMgr);
×
666

667
        // Init specific time
668
        SplashScreen::showMessage(q_("Initializing specific time..."));
×
669
        SpecificTimeMgr* specificTime = new SpecificTimeMgr();
×
670
        specificTime->init();
×
671
        getModuleMgr().registerModule(specificTime);
×
672

673
        //Create the script manager here, maybe some modules/plugins may want to connect to it
674
        //It has to be initialized later after all modules have been loaded by calling initScriptMgr
675
#ifdef ENABLE_SCRIPTING
676
        SplashScreen::showMessage(q_("Initializing scripting..."));
×
677
        scriptAPIProxy = new StelMainScriptAPIProxy(this);
×
678
        scriptMgr = new StelScriptMgr(this);
×
679
#endif
680

681
        SplashScreen::showMessage(q_("Initializing color scheme..."));
×
682
        // Initialisation of the color scheme
683
        emit colorSchemeChanged("default");
×
684
        setVisionModeNight(confSettings->value("viewing/flag_night", false).toBool());
×
685

686
        // Enable viewport effect at startup if he set
687
        setViewportEffect(confSettings->value("video/viewport_effect", "none").toString());
×
688

689
        SplashScreen::clearMessage();
×
690
        updateI18n();
×
691

692
        // Init actions.
693
        actionMgr->addAction("actionShow_Night_Mode", N_("Display Options"), N_("Night mode"), this, "nightMode", "Ctrl+N");
×
694

695
        setFlagShowDecimalDegrees(confSettings->value("gui/flag_show_decimal_degrees", false).toBool());
×
696
        setFlagSouthAzimuthUsage(confSettings->value("gui/flag_use_azimuth_from_south", false).toBool());
×
697
        setFlagUseFormattingOutput(confSettings->value("gui/flag_use_formatting_output", false).toBool());
×
698
        setFlagUseCCSDesignation(confSettings->value("gui/flag_use_ccs_designations", false).toBool());
×
699
        setFlagOverwriteInfoColor(confSettings->value("gui/flag_overwrite_info_color", false).toBool());        
×
700
        setOverwriteInfoColor(Vec3f(confSettings->value("color/info_text_color", "1.0,1.0,1.0").toString()));
×
701
        setDaylightInfoColor(Vec3f(confSettings->value("color/daylight_text_color", "0.0,0.0,0.0").toString()));
×
702

703
        // Animation
704
        animationScale = confSettings->value("gui/pointer_animation_speed", 1.).toDouble();
×
705

706
        ditherPatternTex = StelApp::getInstance().getTextureManager().getDitheringTexture(0);
×
707
        setupPostProcessor();
×
708
        
709
#ifdef ENABLE_SPOUT
710
        //qDebug() << "Property spout is" << qApp->property("spout").toString();
711
        //qDebug() << "Property spoutName is" << qApp->property("spoutName").toString();
712
        if (qApp->property("spout").toString() != "none")
713
        {
714
                //if we are on windows and we have GLES, we are most likely on ANGLE
715
                bool isANGLE=QOpenGLContext::currentContext()->isOpenGLES();
716

717
                if (isANGLE)
718
                {
719
                        qCritical() << "SPOUT: Does not run in ANGLE/OpenGL ES mode!";
720
                }
721
                else
722
                {
723
                        SplashScreen::showMessage(q_("Initializing SPOUT sender..."));
724
                        // Create the SpoutSender object.
725
                        QString spoutName = qApp->property("spoutName").toString();
726
                        if(spoutName.isEmpty())
727
                                spoutName = "stellarium";
728

729
                        spoutSender = new SpoutSender(spoutName);
730

731
                        if (!spoutSender->isValid())
732
                        {
733
                                QMessageBox::warning(&StelMainView::getInstance(), "Stellarium SPOUT", q_("Cannot create Spout sender. See log for details."), QMessageBox::Ok);
734
                                delete spoutSender;
735
                                spoutSender = Q_NULLPTR;
736
                                qApp->setProperty("spout", "");
737
                        }
738
                        SplashScreen::clearMessage();
739
                }
740
        }
741
        else
742
        {
743
                qApp->setProperty("spout", "");
744
        }
745
#endif
746

747
        initialized = true;
×
748
}
×
749

750
// Load and initialize external modules (plugins)
751
void StelApp::initPlugIns()
×
752
{
753
        // Load dynamically all the modules found in the modules/ directories
754
        // which are configured to be loaded at startup
755
        const QList<StelModuleMgr::PluginDescriptor> pluginList=moduleMgr->getPluginsList();
×
756
        for (const auto& i : pluginList)
×
757
        {
758
                if (i.loadAtStartup==false)
×
759
                        continue;
×
760
                SplashScreen::showMessage(QString("%1 \"%2\"...").arg(q_("Loading plugin"), q_(i.info.displayedName)));
×
761
                StelModule* m = moduleMgr->loadPlugin(i.info.id);
×
762
                if (m!=Q_NULLPTR)
×
763
                {
764
                        moduleMgr->registerModule(m, true);
×
765
                        //load extensions after the module is registered
766
                        moduleMgr->loadExtensions(i.info.id);
×
767
                        m->init();
×
768
                }
769
        }
770
        SplashScreen::clearMessage();
×
771
}
×
772

773
void StelApp::deinit()
×
774
{
775
#ifdef         ENABLE_SPOUT
776
        delete spoutSender;
777
        spoutSender = Q_NULLPTR;
778
#endif
779
#ifdef ENABLE_SCRIPTING
780
        if (scriptMgr->scriptIsRunning())
×
781
                scriptMgr->stopScript();
×
782
#endif
783
        QCoreApplication::processEvents();
×
784
        getModuleMgr().unloadAllPlugins();
×
785
        QCoreApplication::processEvents();
×
786
        StelPainter::deinitGLShaders();
×
787
}
×
788

789

790
StelProgressController* StelApp::addProgressBar()
×
791
{
792
        StelProgressController* p = new StelProgressController(this);
×
793
        progressControllers.append(p);
×
794
        emit progressBarAdded(p);
×
795
        return p;
×
796
}
797

798
void StelApp::removeProgressBar(StelProgressController* p)
×
799
{
800
        progressControllers.removeOne(p);        
×
801
        emit progressBarRemoved(p);
×
802
        delete p;
×
803
}
×
804

805

806
void StelApp::update(double deltaTime)
×
807
{
808
        if (!initialized)
×
809
                return;
×
810

811
        ++frame;
×
812
        frameTimeAccum+=deltaTime;
×
813
        if (frameTimeAccum > 1.)
×
814
        {
815
                // Calc the FPS rate every seconds
816
                fps=static_cast<float>(frame)/static_cast<float>(frameTimeAccum);
×
817
                frame = 0;
×
818
                frameTimeAccum=0.;
×
819
        }
820
                
821
        core->update(deltaTime);
×
822

823
        moduleMgr->update();
×
824

825
        // Send the event to every StelModule
826
        for (auto* i : moduleMgr->getCallOrders(StelModule::ActionUpdate))
×
827
        {
828
                i->update(deltaTime);
×
829
        }
830

831
        stelObjectMgr->update(deltaTime);
×
832
}
833

834
void StelApp::prepareRenderBuffer()
×
835
{
836
        if (!viewportEffect) return;
×
837
        if (!renderBuffer)
×
838
        {
839
                StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
×
840
                int w = params.viewportXywh[2];
×
841
                int h = params.viewportXywh[3];
×
842
                renderBuffer = new QOpenGLFramebufferObject(w, h, QOpenGLFramebufferObject::Depth); // we only need depth here
×
843
        }
844
        renderBuffer->bind();
×
845
}
846

847
void StelApp::applyRenderBuffer(GLuint drawFbo)
×
848
{
849
        if (!renderBuffer) return;
×
850
        GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, drawFbo));
×
851
        viewportEffect->paintViewportBuffer(renderBuffer);
×
852
}
853

854
void StelApp::setupPostProcessor()
×
855
{
856
        postProcessorVBO.reset(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
×
857
        postProcessorVBO->create();
×
858
        postProcessorVBO->bind();
×
859
        const GLfloat vertices[]=
×
860
        {
861
                // full screen quad
862
                -1, -1,
863
                 1, -1,
864
                -1,  1,
865
                 1,  1,
866
        };
867
        GL(gl->glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW));
×
868

869
        postProcessorVAO.reset(new QOpenGLVertexArrayObject);
×
870
        postProcessorVAO->create();
×
871
        postProcessorVAO->bind();
×
872
        gl->glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
×
873
        postProcessorVBO->release();
×
874
        gl->glEnableVertexAttribArray(0);
×
875
        postProcessorVAO->release();
×
876

877
        postProcessorProgram.reset(new QOpenGLShaderProgram);
×
878
        postProcessorProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
×
879
                StelOpenGL::globalShaderPrefix(StelOpenGL::VERTEX_SHADER) + R"(
×
880
ATTRIBUTE vec3 vertex;
881
VARYING vec2 texcoord;
882
void main()
883
{
884
        gl_Position = vec4(vertex, 1.);
885
        texcoord = 0.5*vertex.xy+0.5;
886
}
887
)");
888
        postProcessorProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
×
889
                StelOpenGL::globalShaderPrefix(StelOpenGL::FRAGMENT_SHADER) +
×
890
                makeDitheringShader() + R"(
×
891
VARYING vec2 texcoord;
892
uniform sampler2D tex;
893

894
void main()
895
{
896
        vec4 rgba = texture2D(tex, texcoord);
897
        FRAG_COLOR = vec4(dither(rgba.rgb), rgba.a);
898
}
899
)");
900
        StelPainter::linkProg(postProcessorProgram.get(), "Post-processing program");
×
901
        postProcessorProgram->bind();
×
902
        postProcessorUniformLocations.tex           = postProcessorProgram->uniformLocation("tex");
×
903
        postProcessorUniformLocations.rgbMaxValue   = postProcessorProgram->uniformLocation("rgbMaxValue");
×
904
        postProcessorUniformLocations.ditherPattern = postProcessorProgram->uniformLocation("ditherPattern");
×
905
        postProcessorProgram->release();
×
906

907
        if(StelMainView::getInstance().getGLInformation().isHighGraphicsMode)
×
908
        {
909
                postProcessorProgramMS.reset(new QOpenGLShaderProgram);
×
910
                postProcessorProgramMS->addShaderFromSourceCode(QOpenGLShader::Vertex,
×
911
                        StelOpenGL::globalShaderPrefix(StelOpenGL::VERTEX_SHADER) + R"(
×
912
ATTRIBUTE vec3 vertex;
913
void main()
914
{
915
        gl_Position = vec4(vertex, 1.);
916
}
917
)");
918
                postProcessorProgramMS->addShaderFromSourceCode(QOpenGLShader::Fragment,
×
919
                        StelOpenGL::globalShaderPrefix(StelOpenGL::FRAGMENT_SHADER) +
×
920
                        makeDitheringShader() + R"(
×
921
uniform sampler2DMS tex;
922
uniform int numMultiSamples;
923

924
void main()
925
{
926
        vec4 rgba = vec4(0);
927
        for(int n = 0; n < numMultiSamples; ++n)
928
                rgba += texelFetch(tex, ivec2(gl_FragCoord.xy), n);
929
        rgba /= float(numMultiSamples);
930
        FRAG_COLOR = vec4(dither(rgba.rgb), rgba.a);
931
}
932
)");
933
                StelPainter::linkProg(postProcessorProgramMS.get(), "Multisampled post-processing program");
×
934
                postProcessorProgramMS->bind();
×
935
                postProcessorUniformLocationsMS.tex               = postProcessorProgramMS->uniformLocation("tex");
×
936
                postProcessorUniformLocationsMS.rgbMaxValue       = postProcessorProgramMS->uniformLocation("rgbMaxValue");
×
937
                postProcessorUniformLocationsMS.ditherPattern     = postProcessorProgramMS->uniformLocation("ditherPattern");
×
938
                postProcessorUniformLocationsMS.numMultiSamples   = postProcessorProgramMS->uniformLocation("numMultiSamples");
×
939
                postProcessorProgramMS->release();
×
940
        }
941
}
×
942

943
void StelApp::highGraphicsModeDraw()
×
944
{
945
#if !QT_CONFIG(opengles2)
946
        const auto targetFBO = currentFbo;
×
947
        StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
×
948
        const auto w = params.viewportXywh[2] * params.devicePixelsPerPixel;
×
949
        const auto h = params.viewportXywh[3] * params.devicePixelsPerPixel;
×
950
        StelOpenGL::checkGLErrors(__FILE__, __LINE__);
×
951
        if(!sceneFBO || sceneFBO->size() != QSize(w,h))
×
952
        {
953
                GLint viewport[4] = {};
×
954
                GL(gl->glGetIntegerv(GL_VIEWPORT, viewport));
×
955
                qInfo() << "OpenGL viewport size:" << viewport[2] << "x" << viewport[3];
×
956

957
                qInfo().nospace() << "Creating scene FBO with size " << w << "x" << h;
×
958
                const auto internalFormat = GL_RGBA16;
×
959
                QOpenGLFramebufferObjectFormat format;
×
960
                format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
×
961
                format.setInternalTextureFormat(internalFormat);
×
962
                sceneFBO.reset(new QOpenGLFramebufferObject(w, h, format));
×
963
                GLint maxSamples = 1;
×
964
                GL(gl->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples));
×
965
                const auto samples = confSettings->value("video/multisampling", 0).toInt();
×
966
                numMultiSamples = std::min(samples, maxSamples);
×
967
                if(numMultiSamples > 1)
×
968
                {
969
                        const auto gl = StelOpenGL::highGraphicsFunctions();
×
970
                        if(sceneMultisampledFBO)
×
971
                        {
972
                                GL(gl->glDeleteFramebuffers(1, &sceneMultisampledFBO));
×
973
                                GL(gl->glDeleteTextures(1, &sceneMultisampledTex));
×
974
                                GL(gl->glDeleteRenderbuffers(1, &sceneMultisampledRenderbuffer));
×
975
                        }
976
                        GL(gl->glGenFramebuffers(1, &sceneMultisampledFBO));
×
977
                        GL(gl->glGenTextures(1, &sceneMultisampledTex));
×
978
                        GL(gl->glGenRenderbuffers(1, &sceneMultisampledRenderbuffer));
×
979

980
                        GL(gl->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, sceneMultisampledTex));
×
981
                        GL(gl->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numMultiSamples,
×
982
                                                                internalFormat, w, h, true));
983

984
                        GL(gl->glBindRenderbuffer(GL_RENDERBUFFER, sceneMultisampledRenderbuffer));
×
985
                        GL(gl->glRenderbufferStorageMultisample(GL_RENDERBUFFER, numMultiSamples,
×
986
                                                                         GL_DEPTH24_STENCIL8, w, h));
987

988
                        GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, sceneMultisampledFBO));
×
989
                        GL(gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
×
990
                                                      GL_TEXTURE_2D_MULTISAMPLE, sceneMultisampledTex, 0));
991
                        GL(gl->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
×
992
                                                         GL_RENDERBUFFER, sceneMultisampledRenderbuffer));
993
                        const auto status = gl->glCheckFramebufferStatus(GL_FRAMEBUFFER);
×
994
                        if(status != GL_FRAMEBUFFER_COMPLETE)
×
995
                        {
996
                                qCritical().nospace() << __FILE__ << ":" << __LINE__
×
997
                                                      << ": warning: framebuffer incomplete, status: "
×
998
                                                      << status;
×
999
                        }
1000
                }
1001
        }
×
1002

1003
        if(sceneMultisampledFBO)
×
1004
        {
1005
                GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, sceneMultisampledFBO));
×
1006
                currentFbo = sceneMultisampledFBO;
×
1007
        }
1008
        else
1009
        {
1010
                sceneFBO->bind();
×
1011
                currentFbo = sceneFBO->handle();
×
1012
        }
1013
        StelOpenGL::checkGLErrors(__FILE__, __LINE__);
×
1014

1015
        GL(gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
×
1016

1017
        const QList<StelModule*> modules = moduleMgr->getCallOrders(StelModule::ActionDraw);
×
1018

1019
        for(auto* module : modules)
×
1020
        {
1021
                module->draw(core);
×
1022
        }
1023

1024
        if(sceneMultisampledFBO)
×
1025
        {
1026
                GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, targetFBO));
×
1027
                postProcessorProgramMS->bind();
×
1028

1029
                const int sceneTexSampler = 0;
×
1030
                GL(gl->glActiveTexture(GL_TEXTURE0 + sceneTexSampler));
×
1031
                GL(gl->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, sceneMultisampledTex));
×
1032
                postProcessorProgramMS->setUniformValue(postProcessorUniformLocationsMS.tex, sceneTexSampler);
×
1033

1034
                const int ditherTexSampler = 1;
×
1035
                ditherPatternTex->bind(ditherTexSampler);
×
1036
                postProcessorProgramMS->setUniformValue(postProcessorUniformLocationsMS.ditherPattern, ditherTexSampler);
×
1037
                const auto rgbMaxValue=calcRGBMaxValue(core->getDitheringMode());
×
1038
                postProcessorProgramMS->setUniformValue(postProcessorUniformLocationsMS.rgbMaxValue,
×
1039
                                                        rgbMaxValue[0], rgbMaxValue[1], rgbMaxValue[2]);
×
1040
                postProcessorProgramMS->setUniformValue(postProcessorUniformLocationsMS.numMultiSamples, numMultiSamples);
×
1041
        }
1042
        else
1043
        {
1044
                GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, targetFBO));
×
1045
                postProcessorProgram->bind();
×
1046

1047
                const int sceneTexSampler = 0;
×
1048
                GL(gl->glActiveTexture(GL_TEXTURE0 + sceneTexSampler));
×
1049
                GL(gl->glBindTexture(GL_TEXTURE_2D, sceneFBO->texture()));
×
1050
                postProcessorProgram->setUniformValue(postProcessorUniformLocations.tex, sceneTexSampler);
×
1051

1052
                const int ditherTexSampler = 1;
×
1053
                ditherPatternTex->bind(ditherTexSampler);
×
1054
                postProcessorProgram->setUniformValue(postProcessorUniformLocations.ditherPattern, ditherTexSampler);
×
1055
                const auto rgbMaxValue=calcRGBMaxValue(core->getDitheringMode());
×
1056
                postProcessorProgram->setUniformValue(postProcessorUniformLocations.rgbMaxValue,
×
1057
                                                      rgbMaxValue[0], rgbMaxValue[1], rgbMaxValue[2]);
×
1058
        }
1059

1060
        postProcessorVAO->bind();
×
1061
        GL(gl->glEnable(GL_BLEND));
×
1062
        GL(gl->glBlendFunc(GL_ONE,GL_ONE));
×
1063
        GL(gl->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
×
1064
        GL(gl->glDisable(GL_BLEND));
×
1065
        postProcessorVAO->release();
×
1066
#endif
1067
}
×
1068

1069
//! Main drawing function called at each frame
1070
void StelApp::draw()
×
1071
{
1072
        if (!initialized)
×
1073
                return;
×
1074

1075
        //find out which framebuffer is the current one
1076
        //this is usually NOT the "zero" FBO, but one provided by QOpenGLWidget
1077
        GLint drawFbo;
1078
        GL(gl->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &drawFbo));
×
1079

1080
        prepareRenderBuffer();
×
1081
        currentFbo = renderBuffer ? renderBuffer->handle() : static_cast<GLuint>(drawFbo);
×
1082

1083
        core->preDraw();
×
1084

1085
        if(StelMainView::getInstance().getGLInformation().isHighGraphicsMode)
×
1086
        {
1087
                highGraphicsModeDraw();
×
1088
        }
1089
        else
1090
        {
1091
                const QList<StelModule*> modules = moduleMgr->getCallOrders(StelModule::ActionDraw);
×
1092
                for (auto* module : modules)
×
1093
                {
1094
                        module->draw(core);
×
1095
                }
1096
        }
×
1097

1098
        core->postDraw();
×
1099
#ifdef ENABLE_SPOUT
1100
        // At this point, the sky scene has been drawn, but no GUI panels.
1101
        if(spoutSender)
1102
                spoutSender->captureAndSendFrame(static_cast<GLuint>(drawFbo));
1103
#endif
1104
        applyRenderBuffer(static_cast<GLuint>(drawFbo));
×
1105
}
1106

1107
/*************************************************************************
1108
 Call this when the virtual size of the GL window has changed
1109
*************************************************************************/
1110
void StelApp::glWindowHasBeenResized(const QRectF& rect)
×
1111
{
1112
        // Remove the effect before resizing the core, or things get messy.
1113
        QString effect = getViewportEffect();
×
1114
        setViewportEffect("none");
×
1115
        if (core)
×
1116
        {
1117
                core->windowHasBeenResized(rect.x(), rect.y(), rect.width(), rect.height());
×
1118
        }
1119
        else
1120
        {
1121
                saveProjW = rect.width();
×
1122
                saveProjH = rect.height();
×
1123
        }
1124
        // Force to recreate the viewport effect if any.
1125
        setViewportEffect(effect);
×
1126
#ifdef ENABLE_SPOUT
1127
        if (spoutSender)
1128
                spoutSender->resize(static_cast<uint>(rect.width()),static_cast<uint>(rect.height()));
1129
#endif
1130
}
×
1131

1132
/*************************************************************************
1133
 Call this when the physical size of the GL window has changed
1134
*************************************************************************/
1135
void StelApp::glPhysicalWindowHasBeenResized(const QRectF& rect)
×
1136
{
1137
#ifdef ENABLE_SPOUT
1138
        if (spoutSender)
1139
                spoutSender->resize(static_cast<uint>(rect.width()),static_cast<uint>(rect.height()));
1140
#else
1141
        Q_UNUSED(rect)
1142
#endif
1143
}
×
1144

1145
// Handle mouse clics
1146
void StelApp::handleClick(QMouseEvent* inputEvent)
×
1147
{
1148
        QPointF pos = inputEvent->pos();
×
1149
        qreal x, y;
1150
        x = pos.x();
×
1151
        y = pos.y();
×
1152
        if (viewportEffect)
×
1153
                viewportEffect->distortXY(x, y);
×
1154

1155
        QMouseEvent event(inputEvent->type(), QPoint(qRound(x*devicePixelsPerPixel), qRound(y*devicePixelsPerPixel)), inputEvent->button(), inputEvent->buttons(), inputEvent->modifiers());
×
1156
        event.setAccepted(false);
×
1157
        
1158
        // Send the event to every StelModule
1159
        for (auto* i : moduleMgr->getCallOrders(StelModule::ActionHandleMouseClicks))
×
1160
        {
1161
                i->handleMouseClicks(&event);
×
1162
                if (event.isAccepted())
×
1163
                {
1164
                        inputEvent->setAccepted(true);
×
1165
                        return;
×
1166
                }
1167
        }
1168
}
×
1169

1170
// Handle mouse wheel.
1171
void StelApp::handleWheel(QWheelEvent* event)
×
1172
{
1173
        event->setAccepted(false);
×
1174
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
1175
        QWheelEvent deltaEvent(event->position()*devicePixelsPerPixel,
×
1176
                               event->globalPosition()*devicePixelsPerPixel,
×
1177
                               event->pixelDelta(), event->angleDelta(), event->buttons(), event->modifiers(), Qt::ScrollUpdate, false);
×
1178
#else
1179
        QWheelEvent deltaEvent(QPoint(qRound(event->pos().x()*devicePixelsPerPixel), qRound(event->pos().y()*devicePixelsPerPixel)),
1180
                               QPoint(qRound(event->globalPos().x()*devicePixelsPerPixel), qRound(event->globalPos().y()*devicePixelsPerPixel)),
1181
                               event->delta(), event->buttons(), event->modifiers(), event->orientation());
1182
#endif
1183
        deltaEvent.setAccepted(false);
×
1184
        // Send the event to every StelModule
1185
        for (auto* i : moduleMgr->getCallOrders(StelModule::ActionHandleMouseClicks)) {
×
1186
                i->handleMouseWheel(&deltaEvent);
×
1187
                if (deltaEvent.isAccepted()) {
×
1188
                        event->accept();
×
1189
                        break;
×
1190
                }
1191
        }
1192
}
×
1193

1194
// Handle mouse move
1195
bool StelApp::handleMove(qreal x, qreal y, Qt::MouseButtons b)
×
1196
{
1197
        if (viewportEffect)
×
1198
                viewportEffect->distortXY(x, y);
×
1199
        // Send the event to every StelModule
1200
        for (auto* i : moduleMgr->getCallOrders(StelModule::ActionHandleMouseMoves))
×
1201
        {
1202
                if (i->handleMouseMoves(qRound(x*devicePixelsPerPixel), qRound(y*devicePixelsPerPixel), b))
×
1203
                        return true;
×
1204
        }
1205
        return false;
×
1206
}
1207

1208
// Handle key press and release
1209
void StelApp::handleKeys(QKeyEvent* event)
×
1210
{
1211
        event->setAccepted(false);
×
1212
        // First try to trigger a shortcut.
1213
        if (event->type() == QEvent::KeyPress)
×
1214
        {
1215
                if (getStelActionManager()->pushKey(event->key() + int(event->modifiers())))
×
1216
                {
1217
                        event->setAccepted(true);
×
1218
                        return;
×
1219
                }
1220
        }
1221
        // Send the event to every StelModule
1222
        for (auto* i : moduleMgr->getCallOrders(StelModule::ActionHandleKeys))
×
1223
        {
1224
                i->handleKeys(event);
×
1225
                if (event->isAccepted())
×
1226
                        return;
×
1227
        }
1228
}
1229

1230
// Handle pinch on multi touch devices
1231
void StelApp::handlePinch(qreal scale, bool started)
×
1232
{
1233
        // Send the event to every StelModule
1234
        for (auto* i : moduleMgr->getCallOrders(StelModule::ActionHandleMouseMoves))
×
1235
        {
1236
                if (i->handlePinch(scale, started))
×
1237
                        return;
×
1238
        }
1239
}
1240

1241
//! Set flag for activating night vision mode
1242
void StelApp::setVisionModeNight(bool b)
×
1243
{
1244
        if (flagNightVision!=b)
×
1245
        {
1246
                flagNightVision=b;
×
1247
                emit visionNightModeChanged(b);
×
1248
        }
1249
}
×
1250

1251
void StelApp::setFlagOverwriteInfoColor(bool b)
×
1252
{
1253
        if (flagOverwriteInfoColor!=b)
×
1254
        {
1255
                flagOverwriteInfoColor=b;
×
1256
                StelApp::immediateSave("gui/flag_overwrite_info_color", b);
×
1257
                emit flagOverwriteInfoColorChanged(b);
×
1258
        }
1259
}
×
1260

1261
void StelApp::setFlagShowDecimalDegrees(bool b)
×
1262
{
1263
        if (flagShowDecimalDegrees!=b)
×
1264
        {
1265
                flagShowDecimalDegrees = b;
×
1266
                StelApp::immediateSave("gui/flag_show_decimal_degrees", b);
×
1267
                emit flagShowDecimalDegreesChanged(b);
×
1268
        }
1269
}
×
1270

1271
void StelApp::setFlagSouthAzimuthUsage(bool use)
×
1272
{
1273
        if (flagUseAzimuthFromSouth!=use)
×
1274
        {
1275
                flagUseAzimuthFromSouth=use;
×
1276
                StelApp::immediateSave("gui/flag_use_azimuth_from_south", use);
×
1277
                emit flagUseAzimuthFromSouthChanged(use);
×
1278
        }
1279
}
×
1280

1281

1282
void StelApp::setFlagUseFormattingOutput(bool b)
×
1283
{
1284
        if (flagUseFormattingOutput!=b)
×
1285
        {
1286
                flagUseFormattingOutput = b;
×
1287
                StelApp::immediateSave("gui/flag_use_formatting_output", flagUseFormattingOutput);
×
1288
                emit flagUseFormattingOutputChanged(b);
×
1289
        }
1290
}
×
1291

1292
void StelApp::setFlagUseCCSDesignation(bool b)
×
1293
{
1294
        if (flagUseCCSDesignation!=b)
×
1295
        {
1296
                flagUseCCSDesignation = b;
×
1297
                StelApp::immediateSave("gui/flag_use_ccs_designations", flagUseCCSDesignation);
×
1298
                emit flagUseCCSDesignationChanged(b);
×
1299
        }
1300
}
×
1301

1302
void StelApp::setOverwriteInfoColor(const Vec3f& color)
×
1303
{
1304
        if (color != overwriteInfoColor)
×
1305
        {
1306
                overwriteInfoColor = color;
×
1307
                emit overwriteInfoColorChanged(color);
×
1308
        }
1309
}
×
1310

1311
Vec3f StelApp::getOverwriteInfoColor() const
×
1312
{
1313
        return overwriteInfoColor;
×
1314
}
1315

1316
void StelApp::setDaylightInfoColor(const Vec3f& color)
×
1317
{
1318
        if (color != daylightInfoColor)
×
1319
        {
1320
                daylightInfoColor = color;
×
1321
                emit daylightInfoColorChanged(color);
×
1322
        }
1323
}
×
1324

1325
Vec3f StelApp::getDaylightInfoColor() const
×
1326
{
1327
        return daylightInfoColor;
×
1328
}
1329

1330
void StelApp::setFlagImmediateSave(bool b)
×
1331
{
1332
        if (flagImmediateSave!=b)
×
1333
        {
1334
                flagImmediateSave = b;
×
1335
                // To not accidentally activate this mode permanently, you must use the "save settings" button to activate!
1336
                if (!b)
×
1337
                        StelApp::immediateSave("gui/immediate_save_details", false);
×
1338
                emit flagImmediateSaveChanged(b);
×
1339
        }
1340
}
×
1341

1342
void StelApp::immediateSave(const QString &key, const QVariant &value)
×
1343
{
1344
        if (getInstance().getFlagImmediateSave())
×
1345
                getInstance().getSettings()->setValue(key, value);
×
1346
}
×
1347

1348

1349
// Update translations and font for sky everywhere in the program
1350
void StelApp::updateI18n()
×
1351
{
1352
#ifdef ENABLE_NLS
1353
        emit languageChanged();
1354
#endif
1355
}
×
1356

1357
void StelApp::ensureGLContextCurrent()
×
1358
{
1359
        mainWin->glContextMakeCurrent();
×
1360
}
×
1361

1362
// Return the time since when stellarium is running in second.
1363
double StelApp::getTotalRunTime()
×
1364
{
1365
        return static_cast<double>(QDateTime::currentMSecsSinceEpoch() - StelApp::startMSecs)/1000.;
×
1366
}
1367

1368
// Return the scaled time since when stellarium is running in second.
1369
double StelApp::getAnimationTime()
×
1370
{
1371
        return static_cast<double>(QDateTime::currentMSecsSinceEpoch() - StelApp::startMSecs)*StelApp::animationScale/1000.;
×
1372
}
1373

1374
void StelApp::reportFileDownloadFinished(QNetworkReply* reply)
×
1375
{
1376
        bool fromCache = reply->attribute(QNetworkRequest::SourceIsFromCacheAttribute).toBool();
×
1377
        if (fromCache)
×
1378
        {
1379
                ++nbUsedCache;
×
1380
                totalUsedCacheSize+=reply->bytesAvailable();
×
1381
        }
1382
        else
1383
        {
1384
                ++nbDownloadedFiles;
×
1385
                totalDownloadedSize+=reply->bytesAvailable();
×
1386
        }
1387
}
×
1388

1389
void StelApp::quit()
×
1390
{
1391
        emit aboutToQuit();
×
1392
        // Let's allow exit from Stellarium via startup script!
1393
        QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
×
1394
}
×
1395

1396
void StelApp::setDevicePixelsPerPixel(qreal dppp)
×
1397
{
1398
        // Check that the device-independent pixel size didn't change
1399
        if (!viewportEffect && !fuzzyEquals(devicePixelsPerPixel, dppp))
×
1400
        {
1401
                qDebug() << "Changing high-DPI scaling factor from" << devicePixelsPerPixel << "to" << dppp;
×
1402
                devicePixelsPerPixel = dppp;
×
1403
                StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
×
1404
                params.devicePixelsPerPixel = devicePixelsPerPixel;
×
1405
                core->setCurrentStelProjectorParams(params);
×
1406
        }
1407
}
×
1408

1409
void StelApp::setViewportEffect(const QString& name)
×
1410
{
1411
        if (name == getViewportEffect()) return;
×
1412
        StelApp::immediateSave("video/viewport_effect", name);
×
1413
        if (renderBuffer)
×
1414
        {
1415
                ensureGLContextCurrent();
×
1416
                delete renderBuffer;
×
1417
                renderBuffer = Q_NULLPTR;
×
1418
        }
1419
        if (viewportEffect)
×
1420
        {
1421
                delete viewportEffect;
×
1422
                viewportEffect = Q_NULLPTR;
×
1423
        }
1424
        if (name == "none") return;
×
1425

1426
        if (!core)
×
1427
        {
1428
                qDebug() << "No core to set viewport effect";
×
1429
                return;
×
1430
        }
1431
        StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
×
1432
        int w = params.viewportXywh[2];
×
1433
        int h = params.viewportXywh[3];
×
1434
        if (name == "sphericMirrorDistorter")
×
1435
        {
1436
                viewportEffect = new StelViewportDistorterFisheyeToSphericMirror(w, h);
×
1437
        }
1438
        else
1439
        {
1440
                qDebug() << "unknown viewport effect name:" << name;
×
1441
                Q_ASSERT(false);
×
1442
        }
1443
}
1444

1445
QString StelApp::getViewportEffect() const
×
1446
{
1447
        if (viewportEffect)
×
1448
                return viewportEffect->getName();
×
1449
        return "none";
×
1450
}
1451

1452
// Diagnostics
1453
void StelApp::dumpModuleActionPriorities(StelModule::StelModuleActionName actionName) const
×
1454
{
1455
        const QList<StelModule*> modules = moduleMgr->getCallOrders(actionName);
×
1456
        QMetaEnum me = QMetaEnum::fromType<StelModule::StelModuleActionName>();
×
1457
        qDebug() << "Module Priorities for action named" << me.valueToKey(actionName);
×
1458

1459
        for (auto* module : modules)
×
1460
        {
1461
                module->draw(core);
×
1462
                qDebug() << " -- " << module->getCallOrder(actionName) << "Module: " << module->objectName();
×
1463
        }
1464
}
×
1465

1466
StelModule* StelApp::getModule(const QString& moduleID) const
×
1467
{
1468
        return getModuleMgr().getModule(moduleID);
×
1469
}
1470
void StelApp::setScreenFontSize(int s)
×
1471
{
1472
        if (screenFontSize!=s)
×
1473
        {
1474
                screenFontSize=s;
×
1475
                StelApp::immediateSave("gui/screen_font_size", s);
×
1476
                emit screenFontSizeChanged(s);
×
1477
        }
1478
}
×
1479

1480
void StelApp::setScreenButtonScale(const double s)
×
1481
{
1482
        if (screenButtonScale!=s)
×
1483
        {
1484
                screenButtonScale = s;
×
1485
                StelApp::immediateSave("gui/screen_button_scale", s);
×
1486
                emit screenButtonScaleChanged(s);
×
1487
        }
1488
}
×
1489

1490
double StelApp::screenFontSizeRatio() const
×
1491
{
1492
        return double(getScreenFontSize()) / getDefaultGuiFontSize();
×
1493
}
1494

1495
void StelApp::setGuiFontSize(int s)
×
1496
{
1497
        if (getGuiFontSize()!=s)
×
1498
        {
1499
                QFont font=QGuiApplication::font();
×
1500
                font.setPixelSize(s);
×
1501
                QGuiApplication::setFont(font);
×
1502
                StelApp::immediateSave("gui/gui_font_size", s);
×
1503
                emit guiFontSizeChanged(s);
×
1504
        }
×
1505
}
×
1506
int StelApp::getGuiFontSize() const
×
1507
{
1508
        return QGuiApplication::font().pixelSize();
×
1509
}
1510

1511
float StelApp::getScreenScale() const
×
1512
{
1513
        const float dppRatio = StelApp::getInstance().getDevicePixelsPerPixel();
×
1514
        const float fontRatio = StelApp::getInstance().screenFontSizeRatio();
×
1515
        return dppRatio * fontRatio;
×
1516
}
1517

1518
void StelApp::setAppFont(QFont font)
×
1519
{
1520
        int oldSize=QGuiApplication::font().pixelSize();
×
1521
        font.setPixelSize(oldSize);
×
1522
        #if (QT_VERSION>=QT_VERSION_CHECK(5,15,0))
1523
        font.setStyleHint(QFont::AnyStyle, QFont::PreferAntialias);
×
1524
        #else
1525
        font.setStyleHint(QFont::AnyStyle, QFont::OpenGLCompatible);
1526
        #endif
1527
        QGuiApplication::setFont(font);
×
1528
        emit fontChanged(font);
×
1529
}
×
1530

1531
QString StelApp::getVersion() const
×
1532
{
1533
        return StelUtils::getApplicationVersion();
×
1534
}
1535

1536
void StelApp::enableBottomStelBarUpdates(bool enable)
×
1537
{
1538
        StelGui *gui=dynamic_cast<StelGui*>(getGui());
×
1539
        gui->getButtonBar()->enableTopoCentricUpdate(enable);
×
1540
}
×
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