-
-
Notifications
You must be signed in to change notification settings - Fork 865
/
Copy pathStelApp.cpp
1468 lines (1292 loc) · 43.5 KB
/
StelApp.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Stellarium
* Copyright (C) 2006 Fabien Chereau
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
*/
#include "StelApp.hpp"
#include "Dithering.hpp"
#include "StelCore.hpp"
#include "StelMainView.hpp"
#include "StelSplashScreen.hpp"
#include "StelUtils.hpp"
#include "StelTextureMgr.hpp"
#include "StelObjectMgr.hpp"
#include "ConstellationMgr.hpp"
#include "AsterismMgr.hpp"
#include "HipsMgr.hpp"
#include "NebulaMgr.hpp"
#include "LandscapeMgr.hpp"
#include "CustomObjectMgr.hpp"
#include "HighlightMgr.hpp"
#include "GridLinesMgr.hpp"
#include "MilkyWay.hpp"
#include "ZodiacalLight.hpp"
#include "LabelMgr.hpp"
#include "MarkerMgr.hpp"
#include "SolarSystem.hpp"
#include "NomenclatureMgr.hpp"
#include "SporadicMeteorMgr.hpp"
#include "SpecificTimeMgr.hpp"
#include "StarMgr.hpp"
#include "StelProjector.hpp"
#include "StelLocationMgr.hpp"
#include "ToastMgr.hpp"
#include "StelActionMgr.hpp"
#include "StelPropertyMgr.hpp"
#include "StelProgressController.hpp"
#include "StelModuleMgr.hpp"
#include "StelLocaleMgr.hpp"
#include "StelSkyCultureMgr.hpp"
#include "StelFileMgr.hpp"
#include "StelSkyLayerMgr.hpp"
#include "StelAudioMgr.hpp"
#include "StelVideoMgr.hpp"
#include "SpecialMarkersMgr.hpp"
#include "StelViewportEffect.hpp"
#include "StelGuiBase.hpp"
#include "StelPainter.hpp"
#ifdef ENABLE_SCRIPTING
#include "StelScriptMgr.hpp"
#include "StelMainScriptAPIProxy.hpp"
#ifdef USE_STATIC_PLUGIN_CALENDARS
#include "../plugins/Calendars/src/Calendars.hpp"
#endif
#endif
#include <cstdlib>
#include <iostream>
#include <QDebug>
#include <QFile>
#include <QFileInfo>
#include <QMouseEvent>
#include <QNetworkAccessManager>
#include <QNetworkDiskCache>
#include <QNetworkProxy>
#include <QNetworkReply>
#include <QOpenGLBuffer>
#include <QOpenGLContext>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QOpenGLFramebufferObject>
#include <QOpenGLFunctions_3_3_Core>
#include <QString>
#include <QStringList>
#include <QSysInfo>
#include <QTextStream>
#include <QTimer>
#include <QDir>
#include <QCoreApplication>
#include <QGuiApplication>
#include <QScreen>
#include <QDateTime>
#include <QRegularExpression>
#include <QRandomGenerator>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QImageReader>
#endif
#ifdef ENABLE_SPOUT
#include <QMessageBox>
#include "SpoutSender.hpp"
#endif
#ifdef USE_STATIC_PLUGIN_HELLOSTELMODULE
Q_IMPORT_PLUGIN(HelloStelModuleStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_SIMPLEDRAWLINE
Q_IMPORT_PLUGIN(SimpleDrawLineStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_ANGLEMEASURE
Q_IMPORT_PLUGIN(AngleMeasureStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_ARCHAEOLINES
Q_IMPORT_PLUGIN(ArchaeoLinesStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_CALENDARS
Q_IMPORT_PLUGIN(CalendarsStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_SATELLITES
Q_IMPORT_PLUGIN(SatellitesStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_TEXTUSERINTERFACE
Q_IMPORT_PLUGIN(TextUserInterfaceStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_OCULARS
Q_IMPORT_PLUGIN(OcularsStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_OCULUS
Q_IMPORT_PLUGIN(OculusStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_TELESCOPECONTROL
Q_IMPORT_PLUGIN(TelescopeControlStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_SOLARSYSTEMEDITOR
Q_IMPORT_PLUGIN(SolarSystemEditorStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_METEORSHOWERS
Q_IMPORT_PLUGIN(MeteorShowersStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_MISSINGSTARS
Q_IMPORT_PLUGIN(MissingStarsStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_NAVSTARS
Q_IMPORT_PLUGIN(NavStarsStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_NOVAE
Q_IMPORT_PLUGIN(NovaeStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_SUPERNOVAE
Q_IMPORT_PLUGIN(SupernovaeStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_QUASARS
Q_IMPORT_PLUGIN(QuasarsStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_PULSARS
Q_IMPORT_PLUGIN(PulsarsStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_EXOPLANETS
Q_IMPORT_PLUGIN(ExoplanetsStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_EQUATIONOFTIME
Q_IMPORT_PLUGIN(EquationOfTimeStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_POINTERCOORDINATES
Q_IMPORT_PLUGIN(PointerCoordinatesStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_OBSERVABILITY
Q_IMPORT_PLUGIN(ObservabilityStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_SCENERY3D
Q_IMPORT_PLUGIN(Scenery3dStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_REMOTECONTROL
Q_IMPORT_PLUGIN(RemoteControlStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_REMOTESYNC
Q_IMPORT_PLUGIN(RemoteSyncStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_VTS
Q_IMPORT_PLUGIN(VtsStelPluginInterface)
#endif
#ifdef USE_STATIC_PLUGIN_ONLINEQUERIES
Q_IMPORT_PLUGIN(OnlineQueriesPluginInterface)
#endif
// Initialize static variables
StelApp* StelApp::singleton = Q_NULLPTR;
qint64 StelApp::startMSecs = 0;
double StelApp::animationScale = 1.;
void StelApp::initStatic()
{
StelApp::startMSecs = QDateTime::currentMSecsSinceEpoch();
}
void StelApp::deinitStatic()
{
StelApp::startMSecs = 0;
}
/*************************************************************************
Create and initialize the main Stellarium application.
*************************************************************************/
StelApp::StelApp(StelMainView *parent)
: QObject(parent)
, randomGenerator(Q_NULLPTR)
, mainWin(parent)
, core(Q_NULLPTR)
, moduleMgr(Q_NULLPTR)
, localeMgr(Q_NULLPTR)
, skyCultureMgr(Q_NULLPTR)
, actionMgr(Q_NULLPTR)
, propMgr(Q_NULLPTR)
, textureMgr(Q_NULLPTR)
, stelObjectMgr(Q_NULLPTR)
, planetLocationMgr(Q_NULLPTR)
, networkAccessManager(Q_NULLPTR)
, audioMgr(Q_NULLPTR)
, videoMgr(Q_NULLPTR)
, skyImageMgr(Q_NULLPTR)
#ifdef ENABLE_SCRIPTING
, scriptAPIProxy(Q_NULLPTR)
, scriptMgr(Q_NULLPTR)
#endif
, stelGui(Q_NULLPTR)
, devicePixelsPerPixel(1.)
, globalScalingRatio(1.f)
, fps(0)
, frame(0)
, frameTimeAccum(0.)
, flagNightVision(false)
, confSettings(Q_NULLPTR)
, initialized(false)
, saveProjW(-1.)
, saveProjH(-1.)
, nbDownloadedFiles(0)
, totalDownloadedSize(0)
, nbUsedCache(0)
, totalUsedCacheSize(0)
, screenFontSize(13)
, renderBuffer(Q_NULLPTR)
, viewportEffect(Q_NULLPTR)
, gl(Q_NULLPTR)
, flagShowDecimalDegrees(false)
, flagUseAzimuthFromSouth(false)
, flagUseFormattingOutput(false)
, flagUseCCSDesignation(false)
, flagOverwriteInfoColor(false)
, overwriteInfoColor(Vec3f(1.f))
, daylightInfoColor(Vec3f(0.f))
#ifdef ENABLE_SPOUT
, spoutSender(Q_NULLPTR)
#endif
, currentFbo(0)
{
setObjectName("StelApp");
// Can't create 2 StelApp instances
Q_ASSERT(!singleton);
singleton = this;
moduleMgr = new StelModuleMgr();
randomGenerator = new QRandomGenerator(static_cast<quint32>(QDateTime::currentMSecsSinceEpoch()));
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// QImageReader has a new limitation. For super-large landscapes or other textures, we need to circumvent this.
QImageReader::setAllocationLimit(1024); // Allow max texture size 16k x 16k
#endif
}
/*************************************************************************
Deinitialize and destroy the main Stellarium application.
*************************************************************************/
StelApp::~StelApp()
{
qDebug() << 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));
stelObjectMgr->unSelect();
moduleMgr->unloadModule("StelVideoMgr", false); // We need to delete it afterward
moduleMgr->unloadModule("StelSkyLayerMgr", false); // We need to delete it afterward
moduleMgr->unloadModule("StelObjectMgr", false);// We need to delete it afterward
StelModuleMgr* tmp = moduleMgr;
moduleMgr = new StelModuleMgr(); // Create a secondary instance to avoid crashes at other deinit
delete tmp; tmp=Q_NULLPTR;
delete skyImageMgr; skyImageMgr=Q_NULLPTR;
delete core; core=Q_NULLPTR;
delete skyCultureMgr; skyCultureMgr=Q_NULLPTR;
delete localeMgr; localeMgr=Q_NULLPTR;
delete audioMgr; audioMgr=Q_NULLPTR;
delete videoMgr; videoMgr=Q_NULLPTR;
delete stelObjectMgr; stelObjectMgr=Q_NULLPTR; // Delete the module by hand afterward
delete textureMgr; textureMgr=Q_NULLPTR;
delete planetLocationMgr; planetLocationMgr=Q_NULLPTR;
delete moduleMgr; moduleMgr=Q_NULLPTR; // Delete the secondary instance
delete actionMgr; actionMgr = Q_NULLPTR;
delete propMgr; propMgr = Q_NULLPTR;
delete renderBuffer; renderBuffer = Q_NULLPTR;
delete randomGenerator; randomGenerator=Q_NULLPTR;
Q_ASSERT(singleton);
singleton = Q_NULLPTR;
}
void StelApp::setupNetworkProxy()
{
QString proxyHost = confSettings->value("proxy/host_name").toString();
QString proxyPort = confSettings->value("proxy/port").toString();
QString proxyUser = confSettings->value("proxy/user").toString();
QString proxyPass = confSettings->value("proxy/password").toString();
QString proxyType = confSettings->value("proxy/type").toString();
// If proxy settings not found in config, use environment variable
// if it is defined. (Config file over-rides environment).
if (proxyHost.isEmpty() && proxyUser.isEmpty() && proxyPass.isEmpty() && proxyPort.isEmpty())
{
char *httpProxyEnv;
httpProxyEnv = std::getenv("http_proxy");
if (!httpProxyEnv)
{
httpProxyEnv = std::getenv("HTTP_PROXY");
}
if (httpProxyEnv)
{
QString proxyString = QString(httpProxyEnv);
if (!proxyString.isEmpty())
{
// Handle http_proxy of the form
// proto://username:password@fqdn:port
// e.g.:
// http://usr:[email protected]:3128/
// http://proxy.loc:3128/
// http://2001:62a:4:203:6ab5:99ff:fef2:560b:3128/
// http://foo:bar@2001:62a:4:203:6ab5:99ff:fef2:560b:3128/
static const QRegularExpression pre("^([^:]+://)?(?:([^:]+):([^@]*)@)?(.+):([\\d]+)");
QRegularExpressionMatch preMatch=pre.match(proxyString);
if (proxyString.indexOf(pre) >= 0)
{
proxyType = preMatch.captured(1);
proxyUser = preMatch.captured(2);
proxyPass = preMatch.captured(3);
proxyHost = preMatch.captured(4);
proxyPort = preMatch.captured(5);
}
else
{
qDebug() << "indecipherable environment variable http_proxy:" << proxyString;
return;
}
}
}
}
bool useSocksProxy = proxyType.contains("socks", Qt::CaseInsensitive);
if (!proxyHost.isEmpty())
{
QNetworkProxy proxy;
if (useSocksProxy)
proxy.setType(QNetworkProxy::Socks5Proxy);
else
proxy.setType(QNetworkProxy::HttpProxy);
proxy.setHostName(proxyHost);
if (!proxyPort.isEmpty())
proxy.setPort(proxyPort.toUShort());
if (!proxyUser.isEmpty())
proxy.setUser(proxyUser);
if (!proxyPass.isEmpty())
proxy.setPassword(proxyPass);
QString ppDisp = proxyPass;
ppDisp.fill('*');
if (useSocksProxy)
qDebug() << "Using SOCKS proxy:" << proxyUser << ppDisp << proxyHost << proxyPort;
else
qDebug() << "Using HTTP proxy:" << proxyUser << ppDisp << proxyHost << proxyPort;
QNetworkProxy::setApplicationProxy(proxy);
}
}
#ifdef ENABLE_SCRIPTING
void StelApp::initScriptMgr()
{
scriptMgr->addModules();
#ifdef USE_STATIC_PLUGIN_CALENDARS
Calendars *cal=GETSTELMODULE_SILENT(Calendars);
if (cal)
cal->makeCalendarsScriptable(scriptMgr);
#endif
QString startupScript;
if (qApp->property("onetime_startup_script").isValid())
startupScript = qApp->property("onetime_startup_script").toString();
else
startupScript = confSettings->value("scripts/startup_script", "startup.ssc").toString();
// Use a queued slot call to start the script only once the main qApp event loop is running...
QMetaObject::invokeMethod(scriptMgr,
"runScript",
Qt::QueuedConnection,
Q_ARG(QString, startupScript));
}
#else
void StelApp::initScriptMgr() {}
#endif
QStringList StelApp::getCommandlineArguments()
{
return qApp->property("stelCommandLine").toStringList();
}
void StelApp::init(QSettings* conf)
{
gl = QOpenGLContext::currentContext()->functions();
confSettings = conf;
devicePixelsPerPixel = QOpenGLContext::currentContext()->screen()->devicePixelRatio();
if (devicePixelsPerPixel>1)
qDebug() << "Detected a high resolution device! Device pixel ratio:" << devicePixelsPerPixel;
setScreenFontSize(confSettings->value("gui/screen_font_size", 13).toInt());
setGuiFontSize(confSettings->value("gui/gui_font_size", 13).toInt());
setFlagImmediateSave(confSettings->value("gui/immediate_save_details", false).toBool());
core = new StelCore();
if (!fuzzyEquals(saveProjW, -1.) && !fuzzyEquals(saveProjH, -1.))
core->windowHasBeenResized(0, 0, saveProjW, saveProjH);
//Initializing locale at the beginning to show all strings translated
localeMgr = new StelLocaleMgr();
localeMgr->init();
//SplashScreen::showMessage(q_("Initializing locales..."));
SplashScreen::showMessage(q_("Initializing textures..."));
// Initialize AFTER creation of openGL context
textureMgr = new StelTextureMgr();
SplashScreen::showMessage(q_("Initializing network access..."));
networkAccessManager = new QNetworkAccessManager(this);
networkAccessManager->setRedirectPolicy(QNetworkRequest::NoLessSafeRedirectPolicy);
SplashScreen::showMessage(q_("Initializing network disk cache..."));
// Activate http cache if Qt version >= 4.5
QNetworkDiskCache* cache = new QNetworkDiskCache(networkAccessManager);
//make maximum cache size configurable (in MB)
//the default Qt value (50 MB) is quite low, especially for DSS
cache->setMaximumCacheSize(confSettings->value("main/network_cache_size",300).toInt() * 1024 * 1024);
QString cachePath = StelFileMgr::getCacheDir();
qDebug().noquote() << "Cache directory:" << QDir::toNativeSeparators(cachePath);
cache->setCacheDirectory(cachePath);
networkAccessManager->setCache(cache);
connect(networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(reportFileDownloadFinished(QNetworkReply*)));
// Proxy Initialisation
SplashScreen::showMessage(q_("Initializing network proxy..."));
setupNetworkProxy();
//create non-StelModule managers
propMgr = new StelPropertyMgr();
skyCultureMgr = new StelSkyCultureMgr();
propMgr->registerObject(skyCultureMgr);
planetLocationMgr = new StelLocationMgr();
actionMgr = new StelActionMgr();
// register non-modules for StelProperty tracking
propMgr->registerObject(this);
propMgr->registerObject(mainWin);
// Stel Object Data Base manager
SplashScreen::showMessage(q_("Initializing Object Database..."));
stelObjectMgr = new StelObjectMgr();
stelObjectMgr->init();
getModuleMgr().registerModule(stelObjectMgr);
// Hips surveys
SplashScreen::showMessage(q_("Initializing HiPS survey..."));
HipsMgr* hipsMgr = new HipsMgr();
hipsMgr->init();
getModuleMgr().registerModule(hipsMgr);
// Init the solar system first
SplashScreen::showMessage(q_("Initializing Solar System objects..."));
SolarSystem* ssystem = new SolarSystem();
ssystem->init();
getModuleMgr().registerModule(ssystem);
// Init the nomenclature for Solar system bodies
SplashScreen::showMessage(q_("Initializing planetary nomenclature..."));
NomenclatureMgr* nomenclature = new NomenclatureMgr();
nomenclature->init();
getModuleMgr().registerModule(nomenclature);
// Load stars & their names
SplashScreen::showMessage(q_("Initializing stars..."));
StarMgr* hip_stars = new StarMgr();
hip_stars->init();
getModuleMgr().registerModule(hip_stars);
SplashScreen::showMessage(q_("Initializing core..."));
core->init();
// Init nebulas
SplashScreen::showMessage(q_("Initializing deep-sky objects..."));
NebulaMgr* nebulas = new NebulaMgr();
nebulas->init();
getModuleMgr().registerModule(nebulas);
// Init milky way
SplashScreen::showMessage(q_("Initializing Milky Way..."));
MilkyWay* milky_way = new MilkyWay();
milky_way->init();
getModuleMgr().registerModule(milky_way);
// Init zodiacal light
SplashScreen::showMessage(q_("Initializing zodiacal light..."));
ZodiacalLight* zodiacal_light = new ZodiacalLight();
zodiacal_light->init();
getModuleMgr().registerModule(zodiacal_light);
// Init sky image manager
SplashScreen::showMessage(q_("Initializing sky image layer..."));
skyImageMgr = new StelSkyLayerMgr();
skyImageMgr->init();
getModuleMgr().registerModule(skyImageMgr);
// Toast surveys
SplashScreen::showMessage(q_("Initializing TOAST surveys..."));
ToastMgr* toasts = new ToastMgr();
toasts->init();
getModuleMgr().registerModule(toasts);
// Init audio manager
SplashScreen::showMessage(q_("Initializing audio..."));
audioMgr = new StelAudioMgr();
// Init video manager
SplashScreen::showMessage(q_("Initializing video..."));
videoMgr = new StelVideoMgr();
videoMgr->init();
getModuleMgr().registerModule(videoMgr);
// Constellations
SplashScreen::showMessage(q_("Initializing constellations..."));
ConstellationMgr* constellations = new ConstellationMgr(hip_stars);
constellations->init();
getModuleMgr().registerModule(constellations);
// Asterisms
SplashScreen::showMessage(q_("Initializing asterisms..."));
AsterismMgr* asterisms = new AsterismMgr(hip_stars);
asterisms->init();
getModuleMgr().registerModule(asterisms);
// Landscape, atmosphere & cardinal points section
SplashScreen::showMessage(q_("Initializing landscape..."));
LandscapeMgr* landscape = new LandscapeMgr();
landscape->init();
getModuleMgr().registerModule(landscape);
SplashScreen::showMessage(q_("Initializing grid lines..."));
GridLinesMgr* gridLines = new GridLinesMgr();
gridLines->init();
getModuleMgr().registerModule(gridLines);
SplashScreen::showMessage(q_("Initializing special markers..."));
SpecialMarkersMgr* specialMarkers = new SpecialMarkersMgr();
specialMarkers->init();
getModuleMgr().registerModule(specialMarkers);
// Sporadic Meteors
SplashScreen::showMessage(q_("Initializing sporadic meteors..."));
SporadicMeteorMgr* meteors = new SporadicMeteorMgr(10, 72);
meteors->init();
getModuleMgr().registerModule(meteors);
// User labels
SplashScreen::showMessage(q_("Initializing user labels..."));
LabelMgr* skyLabels = new LabelMgr();
skyLabels->init();
getModuleMgr().registerModule(skyLabels);
SplashScreen::showMessage(q_("Initializing sky cultures..."));
skyCultureMgr->init();
// User markers
SplashScreen::showMessage(q_("Initializing user markers..."));
MarkerMgr* skyMarkers = new MarkerMgr();
skyMarkers->init();
getModuleMgr().registerModule(skyMarkers);
// Init custom objects
SplashScreen::showMessage(q_("Initializing custom objects..."));
CustomObjectMgr* custObj = new CustomObjectMgr();
custObj->init();
getModuleMgr().registerModule(custObj);
// Init highlights
SplashScreen::showMessage(q_("Initializing highlights..."));
HighlightMgr* hlMgr = new HighlightMgr();
hlMgr->init();
getModuleMgr().registerModule(hlMgr);
// Init specific time
SplashScreen::showMessage(q_("Initializing specific time..."));
SpecificTimeMgr* specificTime = new SpecificTimeMgr();
specificTime->init();
getModuleMgr().registerModule(specificTime);
//Create the script manager here, maybe some modules/plugins may want to connect to it
//It has to be initialized later after all modules have been loaded by calling initScriptMgr
#ifdef ENABLE_SCRIPTING
SplashScreen::showMessage(q_("Initializing scripting..."));
scriptAPIProxy = new StelMainScriptAPIProxy(this);
scriptMgr = new StelScriptMgr(this);
#endif
SplashScreen::showMessage(q_("Initializing color scheme..."));
// Initialisation of the color scheme
emit colorSchemeChanged("default");
setVisionModeNight(confSettings->value("viewing/flag_night", false).toBool());
// Enable viewport effect at startup if he set
setViewportEffect(confSettings->value("video/viewport_effect", "none").toString());
SplashScreen::clearMessage();
updateI18n();
// Init actions.
actionMgr->addAction("actionShow_Night_Mode", N_("Display Options"), N_("Night mode"), this, "nightMode", "Ctrl+N");
setFlagShowDecimalDegrees(confSettings->value("gui/flag_show_decimal_degrees", false).toBool());
setFlagSouthAzimuthUsage(confSettings->value("gui/flag_use_azimuth_from_south", false).toBool());
setFlagUseFormattingOutput(confSettings->value("gui/flag_use_formatting_output", false).toBool());
setFlagUseCCSDesignation(confSettings->value("gui/flag_use_ccs_designations", false).toBool());
setFlagOverwriteInfoColor(confSettings->value("gui/flag_overwrite_info_color", false).toBool());
setOverwriteInfoColor(Vec3f(confSettings->value("color/info_text_color", "1.0,1.0,1.0").toString()));
setDaylightInfoColor(Vec3f(confSettings->value("color/daylight_text_color", "0.0,0.0,0.0").toString()));
// Animation
animationScale = confSettings->value("gui/pointer_animation_speed", 1.).toDouble();
ditherPatternTex = StelApp::getInstance().getTextureManager().getDitheringTexture(0);
setupPostProcessor();
#ifdef ENABLE_SPOUT
//qDebug() << "Property spout is" << qApp->property("spout").toString();
//qDebug() << "Property spoutName is" << qApp->property("spoutName").toString();
if (qApp->property("spout").toString() != "none")
{
//if we are on windows and we have GLES, we are most likely on ANGLE
bool isANGLE=QOpenGLContext::currentContext()->isOpenGLES();
if (isANGLE)
{
qCritical() << "SPOUT: Does not run in ANGLE/OpenGL ES mode!";
}
else
{
SplashScreen::showMessage(q_("Initializing SPOUT sender..."));
// Create the SpoutSender object.
QString spoutName = qApp->property("spoutName").toString();
if(spoutName.isEmpty())
spoutName = "stellarium";
spoutSender = new SpoutSender(spoutName);
if (!spoutSender->isValid())
{
QMessageBox::warning(&StelMainView::getInstance(), "Stellarium SPOUT", q_("Cannot create Spout sender. See log for details."), QMessageBox::Ok);
delete spoutSender;
spoutSender = Q_NULLPTR;
qApp->setProperty("spout", "");
}
SplashScreen::clearMessage();
}
}
else
{
qApp->setProperty("spout", "");
}
#endif
initialized = true;
}
// Load and initialize external modules (plugins)
void StelApp::initPlugIns()
{
// Load dynamically all the modules found in the modules/ directories
// which are configured to be loaded at startup
const QList<StelModuleMgr::PluginDescriptor> pluginList=moduleMgr->getPluginsList();
for (const auto& i : pluginList)
{
if (i.loadAtStartup==false)
continue;
SplashScreen::showMessage(QString("%1 \"%2\"...").arg(q_("Loading plugin"), q_(i.info.displayedName)));
StelModule* m = moduleMgr->loadPlugin(i.info.id);
if (m!=Q_NULLPTR)
{
moduleMgr->registerModule(m, true);
//load extensions after the module is registered
moduleMgr->loadExtensions(i.info.id);
m->init();
}
}
SplashScreen::clearMessage();
}
void StelApp::deinit()
{
#ifdef ENABLE_SPOUT
delete spoutSender;
spoutSender = Q_NULLPTR;
#endif
#ifdef ENABLE_SCRIPTING
if (scriptMgr->scriptIsRunning())
scriptMgr->stopScript();
#endif
QCoreApplication::processEvents();
getModuleMgr().unloadAllPlugins();
QCoreApplication::processEvents();
StelPainter::deinitGLShaders();
}
StelProgressController* StelApp::addProgressBar()
{
StelProgressController* p = new StelProgressController(this);
progressControllers.append(p);
emit progressBarAdded(p);
return p;
}
void StelApp::removeProgressBar(StelProgressController* p)
{
progressControllers.removeOne(p);
emit progressBarRemoved(p);
delete p;
}
void StelApp::update(double deltaTime)
{
if (!initialized)
return;
++frame;
frameTimeAccum+=deltaTime;
if (frameTimeAccum > 1.)
{
// Calc the FPS rate every seconds
fps=static_cast<float>(frame)/static_cast<float>(frameTimeAccum);
frame = 0;
frameTimeAccum=0.;
}
core->update(deltaTime);
moduleMgr->update();
// Send the event to every StelModule
for (auto* i : moduleMgr->getCallOrders(StelModule::ActionUpdate))
{
i->update(deltaTime);
}
stelObjectMgr->update(deltaTime);
}
void StelApp::prepareRenderBuffer()
{
if (!viewportEffect) return;
if (!renderBuffer)
{
StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
int w = params.viewportXywh[2];
int h = params.viewportXywh[3];
renderBuffer = new QOpenGLFramebufferObject(w, h, QOpenGLFramebufferObject::Depth); // we only need depth here
}
renderBuffer->bind();
}
void StelApp::applyRenderBuffer(GLuint drawFbo)
{
if (!renderBuffer) return;
GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, drawFbo));
viewportEffect->paintViewportBuffer(renderBuffer);
}
void StelApp::setupPostProcessor()
{
postProcessorVBO.reset(new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer));
postProcessorVBO->create();
postProcessorVBO->bind();
const GLfloat vertices[]=
{
// full screen quad
-1, -1,
1, -1,
-1, 1,
1, 1,
};
GL(gl->glBufferData(GL_ARRAY_BUFFER, sizeof vertices, vertices, GL_STATIC_DRAW));
postProcessorVAO.reset(new QOpenGLVertexArrayObject);
postProcessorVAO->create();
postProcessorVAO->bind();
gl->glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
postProcessorVBO->release();
gl->glEnableVertexAttribArray(0);
postProcessorVAO->release();
postProcessorProgram.reset(new QOpenGLShaderProgram);
postProcessorProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,
StelOpenGL::globalShaderPrefix(StelOpenGL::VERTEX_SHADER) + R"(
ATTRIBUTE vec3 vertex;
VARYING vec2 texcoord;
void main()
{
gl_Position = vec4(vertex, 1.);
texcoord = 0.5*vertex.xy+0.5;
}
)");
postProcessorProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,
StelOpenGL::globalShaderPrefix(StelOpenGL::FRAGMENT_SHADER) +
makeDitheringShader() + R"(
VARYING vec2 texcoord;
uniform sampler2D tex;
void main()
{
vec4 rgba = texture2D(tex, texcoord);
FRAG_COLOR = vec4(dither(rgba.rgb), rgba.a);
}
)");
StelPainter::linkProg(postProcessorProgram.get(), "Post-processing program");
postProcessorProgram->bind();
postProcessorUniformLocations.tex = postProcessorProgram->uniformLocation("tex");
postProcessorUniformLocations.rgbMaxValue = postProcessorProgram->uniformLocation("rgbMaxValue");
postProcessorUniformLocations.ditherPattern = postProcessorProgram->uniformLocation("ditherPattern");
postProcessorProgram->release();
if(StelMainView::getInstance().getGLInformation().isHighGraphicsMode)
{
postProcessorProgramMS.reset(new QOpenGLShaderProgram);
postProcessorProgramMS->addShaderFromSourceCode(QOpenGLShader::Vertex,
StelOpenGL::globalShaderPrefix(StelOpenGL::VERTEX_SHADER) + R"(
ATTRIBUTE vec3 vertex;
void main()
{
gl_Position = vec4(vertex, 1.);
}
)");
postProcessorProgramMS->addShaderFromSourceCode(QOpenGLShader::Fragment,
StelOpenGL::globalShaderPrefix(StelOpenGL::FRAGMENT_SHADER) +
makeDitheringShader() + R"(
uniform sampler2DMS tex;
uniform int numMultiSamples;
void main()
{
vec4 rgba = vec4(0);
for(int n = 0; n < numMultiSamples; ++n)
rgba += texelFetch(tex, ivec2(gl_FragCoord.xy), n);
rgba /= float(numMultiSamples);
FRAG_COLOR = vec4(dither(rgba.rgb), rgba.a);
}
)");
StelPainter::linkProg(postProcessorProgramMS.get(), "Multisampled post-processing program");
postProcessorProgramMS->bind();
postProcessorUniformLocationsMS.tex = postProcessorProgramMS->uniformLocation("tex");
postProcessorUniformLocationsMS.rgbMaxValue = postProcessorProgramMS->uniformLocation("rgbMaxValue");
postProcessorUniformLocationsMS.ditherPattern = postProcessorProgramMS->uniformLocation("ditherPattern");
postProcessorUniformLocationsMS.numMultiSamples = postProcessorProgramMS->uniformLocation("numMultiSamples");
postProcessorProgramMS->release();
}
}
void StelApp::highGraphicsModeDraw()
{
#if !QT_CONFIG(opengles2)
const auto targetFBO = currentFbo;
StelProjector::StelProjectorParams params = core->getCurrentStelProjectorParams();
const auto w = params.viewportXywh[2] * params.devicePixelsPerPixel;
const auto h = params.viewportXywh[3] * params.devicePixelsPerPixel;
StelOpenGL::checkGLErrors(__FILE__, __LINE__);
if(!sceneFBO || sceneFBO->size() != QSize(w,h))
{
qDebug().nospace() << "Creating scene FBO with size " << w << "x" << h;
const auto internalFormat = GL_RGBA16;
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setInternalTextureFormat(internalFormat);
sceneFBO.reset(new QOpenGLFramebufferObject(w, h, format));
GLint maxSamples = 1;
GL(gl->glGetIntegerv(GL_MAX_SAMPLES, &maxSamples));
const auto samples = confSettings->value("video/multisampling", 0).toInt();
numMultiSamples = std::min(samples, maxSamples);
if(numMultiSamples > 1)
{
const auto gl = StelOpenGL::highGraphicsFunctions();
if(sceneMultisampledFBO)
{
GL(gl->glDeleteFramebuffers(1, &sceneMultisampledFBO));
GL(gl->glDeleteTextures(1, &sceneMultisampledTex));
GL(gl->glDeleteRenderbuffers(1, &sceneMultisampledRenderbuffer));
}
GL(gl->glGenFramebuffers(1, &sceneMultisampledFBO));
GL(gl->glGenTextures(1, &sceneMultisampledTex));
GL(gl->glGenRenderbuffers(1, &sceneMultisampledRenderbuffer));
GL(gl->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, sceneMultisampledTex));
GL(gl->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, numMultiSamples,
internalFormat, w, h, true));
GL(gl->glBindRenderbuffer(GL_RENDERBUFFER, sceneMultisampledRenderbuffer));
GL(gl->glRenderbufferStorageMultisample(GL_RENDERBUFFER, numMultiSamples,
GL_DEPTH24_STENCIL8, w, h));
GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, sceneMultisampledFBO));
GL(gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D_MULTISAMPLE, sceneMultisampledTex, 0));
GL(gl->glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, sceneMultisampledRenderbuffer));
const auto status = gl->glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
qCritical().nospace() << __FILE__ << ":" << __LINE__
<< ": warning: framebuffer incomplete, status: "
<< status;
}
}
}
if(sceneMultisampledFBO)
{
GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, sceneMultisampledFBO));
currentFbo = sceneMultisampledFBO;
}
else
{
sceneFBO->bind();
currentFbo = sceneFBO->handle();
}
StelOpenGL::checkGLErrors(__FILE__, __LINE__);
GL(gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT));
const QList<StelModule*> modules = moduleMgr->getCallOrders(StelModule::ActionDraw);
if (core->getFlagClearSky())
for (auto* module : modules)
{
module->draw(core);
}
else
for (auto* module : modules)
{
if (! QStringList({"MilkyWay", "ZodiacalLight", "GridLinesMgr", "NebulaMgr"}).contains(module->objectName()))
module->draw(core);
}
if(sceneMultisampledFBO)
{
GL(gl->glBindFramebuffer(GL_FRAMEBUFFER, targetFBO));
postProcessorProgramMS->bind();
const int sceneTexSampler = 0;
GL(gl->glActiveTexture(GL_TEXTURE0 + sceneTexSampler));
GL(gl->glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, sceneMultisampledTex));
postProcessorProgramMS->setUniformValue(postProcessorUniformLocationsMS.tex, sceneTexSampler);