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

Stellarium / stellarium / 3996069357

pending completion
3996069357

push

github

Ruslan Kabatsayev
Shorten some lines

5 of 5 new or added lines in 1 file covered. (100.0%)

14663 of 124076 relevant lines covered (11.82%)

22035.13 hits per line

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

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

23
#include "StelActionMgr.hpp"
24
#include "LandscapeMgr.hpp"
25
#include "Landscape.hpp"
26
#include "AtmospherePreetham.hpp"
27
#include "AtmosphereShowMySky.hpp"
28
#include "StelApp.hpp"
29
#include "SolarSystem.hpp"
30
#include "StelCore.hpp"
31
#include "StelLocaleMgr.hpp"
32
#include "StelModuleMgr.hpp"
33
#include "StelFileMgr.hpp"
34
#include "Planet.hpp"
35
#include "StelIniParser.hpp"
36
#include "StelSkyDrawer.hpp"
37
#include "StelPainter.hpp"
38
#include "StelPropertyMgr.hpp"
39
#include "StelUtils.hpp"
40

41
#include <private/qzipreader_p.h>
42
#include <QTimer>
43
#include <QDebug>
44
#include <QSettings>
45
#include <QString>
46
#include <QDir>
47
#include <QDirIterator>
48
#include <QFile>
49
#include <QTemporaryFile>
50
#include <QMouseEvent>
51
#include <QPainter>
52
#include <QElapsedTimer>
53
#include <QOpenGLPaintDevice>
54

55
#include <stdexcept>
56

57
namespace
58
{
59
constexpr char ATMOSPHERE_MODEL_CONFIG_KEY[]="landscape/atmosphere_model";
60
constexpr char ATMOSPHERE_MODEL_PATH_CONFIG_KEY[]="landscape/atmosphere_model_path";
61
constexpr char ATMOSPHERE_ECLIPSE_SIM_QUALITY_CONFIG_KEY[]="landscape/atmosphere_eclipse_simulation_quality";
62
constexpr char ATMOSPHERE_MODEL_CONF_VAL_PREETHAM[]="preetham";
63
constexpr char ATMOSPHERE_MODEL_CONF_VAL_SHOWMYSKY[]="showmysky";
64
constexpr char ATMOSPHERE_MODEL_CONF_VAL_DEFAULT[]="preetham";
65
}
66

67
Cardinals::Cardinals()
×
68
        : color(0.6f,0.2f,0.2f)
×
69
{
70
        QSettings* conf = StelApp::getInstance().getSettings();
×
71
        Q_ASSERT(conf);
×
72
        screenFontSize = StelApp::getInstance().getScreenFontSize();
×
73
        propMgr = StelApp::getInstance().getStelPropertyManager();
×
74
        // Default font size is 24
75
        font4WCR.setPixelSize(conf->value("viewing/cardinal_font_size", screenFontSize+11).toInt());
×
76
        // Default font size is 18
77
        font8WCR.setPixelSize(conf->value("viewing/ordinal_font_size", screenFontSize+5).toInt());
×
78
        // Draw the principal wind points even smaller.
79
        font16WCR.setPixelSize(conf->value("viewing/16wcr_font_size", screenFontSize+2).toInt());
×
80

81
        // English names for cardinals
82
        labels = {
83
                {   dN,  "N" }, {   dS,  "S" }, {   dE,  "E" }, {   dW,  "W" },
×
84
                {  dNE, "NE" }, {  dSE, "SE" }, {  dSW, "SW" }, {  dNW, "NW" },
×
85
                { dNNE,"NNE" }, { dENE,"ENE" }, { dESE,"ESE" }, { dSSE,"SSE" },
×
86
                { dSSW,"SSW" }, { dWSW,"WSW" }, { dWNW,"WNW" }, { dNNW,"NNW" }
×
87
        };
×
88
}
×
89

90
Cardinals::~Cardinals()
×
91
{
92
}
×
93

94
const QMap<Cardinals::CompassDirection, Vec3f> Cardinals::rose4winds = {
95
        { Cardinals::dN, Vec3f(-1.f, 0.f, 0.f) }, { Cardinals::dS, Vec3f(1.f,  0.f, 0.f) },
96
        { Cardinals::dE, Vec3f( 0.f, 1.f, 0.f) }, { Cardinals::dW, Vec3f(0.f, -1.f, 0.f) }
97
};
98
const QMap<Cardinals::CompassDirection, Vec3f> Cardinals::rose8winds = {
99
        { Cardinals::dNE, Vec3f(-1.f,  1.f, 0.f) }, { Cardinals::dSE, Vec3f( 1.f,  1.f, 0.f) },
100
        { Cardinals::dSW, Vec3f( 1.f, -1.f, 0.f) }, { Cardinals::dNW, Vec3f(-1.f, -1.f, 0.f) }
101
};
102
const QMap<Cardinals::CompassDirection, Vec3f> Cardinals::rose16winds = {
103
        { dNNE, Vec3f(-1.f,   cp, 0.f) }, { dENE, Vec3f( -cp,  1.f, 0.f) },
104
        { dESE, Vec3f(  cp,  1.f, 0.f) }, { dSSE, Vec3f( 1.f,   cp, 0.f) },
105
        { dSSW, Vec3f( 1.f,  -cp, 0.f) }, { dWSW, Vec3f(  cp, -1.f, 0.f) },
106
        { dWNW, Vec3f( -cp, -1.f, 0.f) }, { dNNW, Vec3f(-1.f,  -cp, 0.f) }
107
};
108

109
void Cardinals::update(double deltaTime)
×
110
{
111
        fader4WCR.update(static_cast<int>(deltaTime*1000));
×
112
        fader8WCR.update(static_cast<int>(deltaTime*1000));
×
113
        fader16WCR.update(static_cast<int>(deltaTime*1000));
×
114
}
×
115

116
void Cardinals::setFadeDuration(float duration)
×
117
{
118
        fader4WCR.setDuration(static_cast<int>(duration*1000.f));
×
119
        fader8WCR.setDuration(static_cast<int>(duration*1000.f));
×
120
        fader16WCR.setDuration(static_cast<int>(duration*1000.f));
×
121
}
×
122

123
// Draw the cardinals points : N S E W and the subcardinal and sub-subcardinal.
124
// Handles special cases at poles
125
void Cardinals::draw(const StelCore* core, double latitude) const
×
126
{
127
        // fun polar special cases: no cardinals!
128
        if ((fabs(latitude - 90.0) < 1e-10) || (fabs(latitude + 90.0) < 1e-10))
×
129
                return;
×
130

131
        if (fader4WCR.getInterstate()>0.f)
×
132
        {
133
                const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
×
134
                const float ppx = static_cast<float>(core->getCurrentStelProjectorParams().devicePixelsPerPixel);
×
135
                StelPainter sPainter(prj);
×
136
                sPainter.setFont(font4WCR);
×
137
                float sshift=0.f, bshift=0.f, cshift=0.f, vshift=1.f;
×
138
                bool flagMask = (core->getProjection(StelCore::FrameJ2000)->getMaskType() != StelProjector::MaskDisk);
×
139
                if (propMgr->getProperty("SpecialMarkersMgr.compassMarksDisplayed")->getValue().toBool())
×
140
                        vshift = static_cast<float>(screenFontSize + 12)*ppx;
×
141

142
                Vec3f xy;
×
143
                sPainter.setColor(color, fader4WCR.getInterstate());
×
144
                sPainter.setBlending(true);
×
145
                QMapIterator<Cardinals::CompassDirection, Vec3f> it4w(rose4winds);
×
146
                while(it4w.hasNext())
×
147
                {
148
                        it4w.next();
×
149
                        QString directionLabel = labels.value(it4w.key(), "");
×
150

151
                        if (flagMask)
×
152
                                sshift = ppx*static_cast<float>(sPainter.getFontMetrics().boundingRect(directionLabel).width())*0.5f;
×
153

154
                        if (prj->project(it4w.value(), xy))
×
155
                        {
156
                                Vec3f up(it4w.value()[0], it4w.value()[1], 1.f*M_PI_180f);
×
157
                                Vec3f upPrj;
×
158
                                prj->project(up, upPrj);
×
159
                                float dx=upPrj[0]-xy[0];
×
160
                                float dy=upPrj[1]-xy[1];
×
161
                                float textAngle=atan2(dx, dy);
×
162
                                sPainter.drawText(xy[0], xy[1], directionLabel, -textAngle*M_180_PIf, -sshift, vshift, true);
×
163
                        }
164
                }
×
165

166
                if (fader8WCR.getInterstate()>0.f)
×
167
                {
168
                        float minFader = qMin(fader4WCR.getInterstate(), fader8WCR.getInterstate());
×
169
                        sPainter.setColor(color, minFader);
×
170
                        sPainter.setFont(font8WCR);
×
171

172
                        QMapIterator<Cardinals::CompassDirection, Vec3f> it8w(rose8winds);
×
173
                        while(it8w.hasNext())
×
174
                        {
175
                                it8w.next();
×
176
                                QString directionLabel = labels.value(it8w.key(), "");
×
177

178
                                if (flagMask)
×
179
                                        bshift = ppx*static_cast<float>(sPainter.getFontMetrics().boundingRect(directionLabel).width())*0.5f;
×
180

181
                                if (prj->project(it8w.value(), xy))
×
182
                                {
183
                                        Vec3f up(it8w.value()[0], it8w.value()[1], 1.f*M_PI_180f);
×
184
                                        Vec3f upPrj;
×
185
                                        prj->project(up, upPrj);
×
186
                                        float dx=upPrj[0]-xy[0];
×
187
                                        float dy=upPrj[1]-xy[1];
×
188
                                        float textAngle=atan2(dx, dy);
×
189
                                        sPainter.drawText(xy[0], xy[1], directionLabel, -textAngle*M_180_PIf, -bshift, vshift, true);
×
190
                                }
191
                        }
×
192

193
                        if (fader16WCR.getInterstate()>0.f)
×
194
                        {
195
                                sPainter.setColor(color, qMin(minFader, fader16WCR.getInterstate()));
×
196
                                sPainter.setFont(font16WCR);
×
197

198
                                QMapIterator<Cardinals::CompassDirection, Vec3f> it16w(rose16winds);
×
199
                                while(it16w.hasNext())
×
200
                                {
201
                                        it16w.next();
×
202
                                        QString directionLabel = labels.value(it16w.key(), "");
×
203

204
                                        if (flagMask)
×
205
                                                cshift = ppx*static_cast<float>(sPainter.getFontMetrics().boundingRect(directionLabel).width())*0.5f;
×
206

207
                                        if (prj->project(it16w.value(), xy))
×
208
                                        {
209
                                                Vec3f up(it16w.value()[0], it16w.value()[1], 1.f*M_PI_180f);
×
210
                                                Vec3f upPrj;
×
211
                                                prj->project(up, upPrj);
×
212
                                                float dx=upPrj[0]-xy[0];
×
213
                                                float dy=upPrj[1]-xy[1];
×
214
                                                float textAngle=atan2(dx, dy);
×
215
                                                sPainter.drawText(xy[0], xy[1], directionLabel, -textAngle*M_180_PIf, -cshift, vshift, true);
×
216
                                        }
217
                                }
×
218
                        }
×
219
                }
×
220
        }
×
221
}
222

223
// Translate cardinal labels with gettext to current sky language and update font for the language
224
void Cardinals::updateI18n()
×
225
{
226
        labels = {
227
                // TRANSLATORS: North
228
                { dN,        qc_("N",   "compass direction") },
×
229
                // TRANSLATORS: South
230
                { dS,        qc_("S",   "compass direction") },
×
231
                // TRANSLATORS: East
232
                { dE,        qc_("E",   "compass direction") },
×
233
                // TRANSLATORS: West
234
                { dW,        qc_("W",   "compass direction") },
×
235
                // TRANSLATORS: Northeast
236
                { dNE,        qc_("NE",  "compass direction") },
×
237
                // TRANSLATORS: Southeast
238
                { dSE,        qc_("SE",  "compass direction") },
×
239
                // TRANSLATORS: Southwest
240
                { dSW,        qc_("SW",  "compass direction") },
×
241
                // TRANSLATORS: Northwest
242
                { dNW,        qc_("NW",  "compass direction") },
×
243
                // TRANSLATORS: North-northeast
244
                { dNNE,        qc_("NNE", "compass direction") },
×
245
                // TRANSLATORS: East-northeast
246
                { dENE,        qc_("ENE", "compass direction") },
×
247
                // TRANSLATORS: East-southeast
248
                { dESE,        qc_("ESE", "compass direction") },
×
249
                // TRANSLATORS: South-southeast
250
                { dSSE,        qc_("SSE", "compass direction") },
×
251
                // TRANSLATORS: South-southwest
252
                { dSSW,        qc_("SSW", "compass direction") },
×
253
                // TRANSLATORS: West-southwest
254
                { dWSW,        qc_("WSW", "compass direction") },
×
255
                // TRANSLATORS: West-northwest
256
                { dWNW, qc_("WNW", "compass direction") },
×
257
                // TRANSLATORS: North-northwest
258
                { dNNW,        qc_("NNW", "compass direction") }
×
259
        };
×
260
}
×
261

262
LandscapeMgr::LandscapeMgr()
×
263
        : StelModule()
264
        , atmosphere(Q_NULLPTR)
×
265
        , cardinalPoints(Q_NULLPTR)
×
266
        , landscape(Q_NULLPTR)
×
267
        , oldLandscape(Q_NULLPTR)
×
268
        , messageTimer(new QTimer(this))
×
269
        , flagLandscapeSetsLocation(false)
×
270
        , flagLandscapeAutoSelection(false)
×
271
        , flagLightPollutionFromDatabase(false)
×
272
        , atmosphereNoScatter(false)
×
273
        , flagPolyLineDisplayedOnly(false)
×
274
        , polyLineThickness(1)
×
275
        , flagLandscapeUseMinimalBrightness(false)
×
276
        , defaultMinimalBrightness(0.01)
×
277
        , flagLandscapeSetsMinimalBrightness(false)
×
278
        , flagEnvironmentAutoEnabling(false)
×
279
{
280
        setObjectName("LandscapeMgr"); // should be done by StelModule's constructor.
×
281

282
        //Note: The first entry in the list is used as the default 'default landscape' in removeLandscape().
283
        packagedLandscapeIDs = (QStringList() << "guereins");
×
284
        QDirIterator directories(StelFileMgr::getInstallationDir()+"/landscapes/", QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
×
285
        while(directories.hasNext())
×
286
        {
287
                directories.next();
×
288
                packagedLandscapeIDs << directories.fileName();
×
289
        }
290
        packagedLandscapeIDs.removeDuplicates();
×
291
        landscapeCache.clear();
×
292

293
        messageTimer->setInterval(5000);
×
294
        messageTimer->setSingleShot(true);
×
295
        connect(messageTimer, &QTimer::timeout, this, &LandscapeMgr::clearMessage);
×
296
}
×
297

298
LandscapeMgr::~LandscapeMgr()
×
299
{
300
        delete cardinalPoints;
×
301
        if (oldLandscape)
×
302
        {
303
                delete oldLandscape;
×
304
                oldLandscape=Q_NULLPTR;
×
305
        }
306
        delete landscape;
×
307
        landscape = Q_NULLPTR;
×
308
        qDebug() << "LandscapeMgr: Clearing cache of" << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
309
        landscapeCache.clear(); // deletes all objects within.
×
310
}
×
311

312
/*************************************************************************
313
 Reimplementation of the getCallOrder method
314
*************************************************************************/
315
double LandscapeMgr::getCallOrder(StelModuleActionName actionName) const
×
316
{
317
        if (actionName==StelModule::ActionDraw)
×
318
                return StelApp::getInstance().getModuleMgr().getModule("SporadicMeteorMgr")->getCallOrder(actionName)+20;
×
319
        if (actionName==StelModule::ActionUpdate)
×
320
                return StelApp::getInstance().getModuleMgr().getModule("SolarSystem")->getCallOrder(actionName)+10;
×
321
        // GZ The next 2 lines are only required to test landscape transparency. They should be commented away for releases.
322
        if (actionName==StelModule::ActionHandleMouseClicks)
×
323
                return StelApp::getInstance().getModuleMgr().getModule("StelMovementMgr")->getCallOrder(actionName)-1;
×
324
        return 0.;
×
325
}
326

327
void LandscapeMgr::update(double deltaTime)
×
328
{
329
        if(needToRecreateAtmosphere && !loadingAtmosphere)
×
330
                createAtmosphere();
×
331

332
        const auto core = StelApp::getInstance().getCore();
×
333
        const auto drawer = core->getSkyDrawer();
×
334

335
        if(loadingAtmosphere && loadingAtmosphere->isLoading())
×
336
        {
337
                try
338
                {
339
                        // Use no more than 1/60th of a second for this batch of loading
340
                        QElapsedTimer timer;
×
341
                        timer.start();
×
342
                        Atmosphere::LoadingStatus status;
343
                        while(loadingAtmosphere->isLoading() && timer.elapsed() < 1000/60)
×
344
                                status = loadingAtmosphere->stepDataLoading();
×
345
                        if(loadingAtmosphere->isLoading())
×
346
                        {
347
                                setAtmosphereShowMySkyStoppedWithError(false);
×
348
                                const auto percentDone = std::lround(100.*status.stepsDone/status.stepsToDo);
×
349
                                setAtmosphereShowMySkyStatusText(QString("%1 %2% %3").arg(q_("Loading..."), QString::number(percentDone), qc_("done","percentage of done")));
×
350
                                qDebug() << "Finished this batch of loading at" << percentDone << "%, will continue in the next frame";
×
351
                        }
352
                        else
353
                        {
354
                                setAtmosphereShowMySkyStatusText(q_("Switching models..."));
×
355
                        }
356
                }
357
                catch(AtmosphereShowMySky::InitFailure const& error)
×
358
                {
359
                        qWarning() << "ERROR: Failed to load atmosphere model data:" << error.what();
×
360
                        qWarning() << "WARNING: Falling back to the Preetham's model";
×
361
                        setAtmosphereShowMySkyStoppedWithError(true);
×
362
                        setAtmosphereShowMySkyStatusText(error.what());
×
363
                        loadingAtmosphere.reset();
×
364
                }
×
365
        }
366

367
        if(loadingAtmosphere && loadingAtmosphere->isReadyToRender())
×
368
        {
369
                bool loaded = false;
×
370
                if(drawer->getFlagHasAtmosphere())
×
371
                {
372
                        // Fade out current atmosphere, then fade in the new one
373
                        if(atmosphere->getFlagShow())
×
374
                        {
375
                                atmosphere->setFlagShow(false);
×
376
                        }
377
                        else if(atmosphere->getFadeIntensity() == 0)
×
378
                        {
379
                                loadingAtmosphere->setFlagShow(true);
×
380
                                loadingAtmosphere->setFadeDuration(atmosphere->getFadeDuration());
×
381
                                loadingAtmosphere->setLightPollutionLuminance(atmosphere->getLightPollutionLuminance());
×
382
                                loaded = true;
×
383
                        }
384
                }
385
                else
386
                {
387
                        loaded = true;
×
388
                }
389

390
                if(loaded)
×
391
                {
392
                        atmosphere = std::move(loadingAtmosphere);
×
393
#ifdef ENABLE_SHOWMYSKY
394
                        if(dynamic_cast<AtmosphereShowMySky*>(atmosphere.get()))
×
395
                                setAtmosphereShowMySkyStatusText(q_("Loaded successfully"));
×
396
#endif
397
                        emit atmosphereModelChanged(getAtmosphereModel());
×
398
                }
399
        }
400

401
        atmosphere->update(deltaTime);
×
402

403
        if (oldLandscape)
×
404
        {
405
                // This is only when transitioning to newly loaded landscape. We must draw the old one until the new one is faded in completely.
406
                oldLandscape->update(deltaTime);
×
407
                if (getIsLandscapeFullyVisible())
×
408
                {
409
                        oldLandscape->setFlagShow(false);
×
410

411
                        if (oldLandscape->getEffectiveLandFadeValue()< 0.01f)
×
412
                        {
413
                                // new logic: try to put old landscape to cache.
414
                                //qDebug() << "LandscapeMgr::update: moving oldLandscape " << oldLandscape->getId() << "to Cache. Cost:" << oldLandscape->getMemorySize()/(1024*1024)+1;
415
                                landscapeCache.insert(oldLandscape->getId(), oldLandscape, oldLandscape->getMemorySize()/(1024*1024)+1);
×
416
                                //qDebug() << "--> LandscapeMgr::update(): cache now contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
417
                                oldLandscape=Q_NULLPTR;
×
418
                        }
419
                }
420
        }
421
        landscape->update(deltaTime);
×
422
        cardinalPoints->update(deltaTime);
×
423

424
        // Compute the atmosphere color and intensity
425
        // Compute the sun position in local coordinate
426
        SolarSystem* ssystem = static_cast<SolarSystem*>(StelApp::getInstance().getModuleMgr().getModule("SolarSystem"));
×
427

428
        // Compute the moon position in local coordinate
429
        const auto sun   = ssystem->getSun();
×
430
        const auto moon  = ssystem->getMoon();
×
431
        const auto earth = ssystem->getEarth();
×
432
        const auto currentPlanet = core->getCurrentPlanet();
×
433
        const bool currentIsEarth = currentPlanet->getID() == earth->getID();
×
434
        // First parameter in next call is used for particularly earth-bound computations in Schaefer's sky brightness model. Difference DeltaT makes no difference here.
435
        // Temperature = 15°C, relative humidity = 40%
436
        try
437
        {
438
                atmosphere->computeColor(core, core->getJDE(), *currentPlanet, *sun,
×
439
                                                                 currentIsEarth ? moon.data() : nullptr, core->getCurrentLocation(),
×
440
                                                                 15.f, 40.f, static_cast<float>(drawer->getExtinctionCoefficient()), atmosphereNoScatter);
×
441
        }
442
        catch(AtmosphereShowMySky::InitFailure const& error)
×
443
        {
444
                qWarning().noquote() << "ShowMySky atmosphere model crashed:" << error.what();
×
445
                qWarning() << "Loading Preetham model";
×
446
                showMessage(q_("ShowMySky atmosphere model crashed. Loading Preetham model as a fallback."));
×
447
                resetToFallbackAtmosphere();
×
448
        }
×
449

450
        core->getSkyDrawer()->reportLuminanceInFov(3.75f+atmosphere->getAverageLuminance()*3.5f, true);
×
451

452
        // NOTE: Simple workaround for brightness of landscape when observing from the Sun.
453
        if (currentPlanet->getID() == sun->getID())
×
454
        {
455
                landscape->setBrightness(1.0, 1.0);
×
456
                return;
×
457
        }
458

459
        // Compute the ground luminance based on every planets around
460
        // TBD: Reactivate and verify this code!? Source, reference?
461
//        float groundLuminance = 0;
462
//        const vector<Planet*>& allPlanets = ssystem->getAllPlanets();
463
//        for (auto i=allPlanets.begin();i!=allPlanets.end();++i)
464
//        {
465
//                Vec3d pos = (*i)->getAltAzPos(core);
466
//                pos.normalize();
467
//                if (pos[2] <= 0)
468
//                {
469
//                        // No need to take this body into the landscape illumination computation
470
//                        // because it is under the horizon
471
//                }
472
//                else
473
//                {
474
//                        // Compute the Illuminance E of the ground caused by the planet in lux = lumen/m^2
475
//                        float E = pow10(((*i)->get_mag(core)+13.988)/-2.5);
476
//                        //qDebug() << "mag=" << (*i)->get_mag(core) << " illum=" << E;
477
//                        // Luminance in cd/m^2
478
//                        groundLuminance += E/0.44*pos[2]*pos[2]; // 1m^2 from 1.5 m above the ground is 0.44 sr.
479
//                }
480
//        }
481
//        groundLuminance*=atmosphere->getFadeIntensity();
482
//        groundLuminance=atmosphere->getAverageLuminance()/50;
483
//        qDebug() << "Atmosphere lum=" << atmosphere->getAverageLuminance() << " ground lum=" <<  groundLuminance;
484
//        qDebug() << "Adapted Atmosphere lum=" << eye->adaptLuminance(atmosphere->getAverageLuminance()) << " Adapted ground lum=" << eye->adaptLuminance(groundLuminance);
485

486
        // compute global ground brightness in a simplistic way, directly in RGB
487

488
        double landscapeBrightness=0.0;
×
489
        if (getFlagLandscapeUseMinimalBrightness())
×
490
        {
491
                // Setting from landscape.ini has priority if enabled
492
                if (getFlagLandscapeSetsMinimalBrightness() && landscape->getLandscapeMinimalBrightness()>=0)
×
493
                        landscapeBrightness = landscape->getLandscapeMinimalBrightness();
×
494
                else
495
                        landscapeBrightness = getDefaultMinimalBrightness();
×
496
        }
497

498
        Vec3d sunPos = sun->getAltAzPosAuto(core);
×
499
        sunPos.normalize();
×
500
        Vec3d moonPos = moon->getAltAzPosAuto(core);
×
501
        moonPos.normalize();
×
502

503
        // With atmosphere on, we define the solar brightness contribution zero when the sun is 8 degrees below the horizon.
504
        // The multiplier of 1.5 just looks better, it somehow represents illumination by scattered sunlight.
505
        // Else, we should account for sun's diameter but else just apply Lambertian Cos-rule and check with landscape opacity.
506
        double sinSunAngle = 0.0;
×
507
        if(atmosphere->getFlagShow())
×
508
        {
509
                sinSunAngle=sin(qMin(M_PI_2, asin(sunPos[2])+8.*M_PI/180.));
×
510
                if(sinSunAngle > -0.1/1.5 )
×
511
                        landscapeBrightness +=  1.5*(sinSunAngle+0.1/1.5);
×
512
        }
513
        else
514
        {
515
                // In case we have exceptionally deep horizons ("Little Prince planet"), the sun will rise somehow over that line and demand light on the landscape.
516
                sinSunAngle=sin(qMin(M_PI_2, asin(qBound(-1.0, sunPos[2]-landscape->getSinMinAltitudeLimit(), 1.0) ) + (0.25 *M_PI_180)));
×
517
                if(sinSunAngle > 0.0)
×
518
                        landscapeBrightness +=  (1.0-static_cast<double>(landscape->getOpacity(sunPos)))*sinSunAngle;
×
519
        }
520

521
        // GZ: 2013-09-25 Take light pollution into account!
522
        const float nelm = StelCore::luminanceToNELM(drawer->getLightPollutionLuminance());
×
523
        float pollutionAddonBrightness=(15.5f-2*nelm)*0.025f; // 0..8, so we assume empirical linear brightening 0..0.02
×
524
        float lunarAddonBrightness=0.f;
×
525
        if (currentIsEarth && moonPos[2] > -0.1/1.5)
×
526
                lunarAddonBrightness = qMax(0.2f/-12.f*moon->getVMagnitudeWithExtinction(core),0.f)*static_cast<float>(moonPos[2]);
×
527

528
        landscapeBrightness += static_cast<double>(qMax(lunarAddonBrightness, pollutionAddonBrightness));
×
529

530
        // TODO make this more generic for non-atmosphere planets
531
        if(atmosphere->getFadeIntensity() > 0.99999f )
×
532
        {
533
                // If the atmosphere is on, a solar eclipse might darken the sky
534
                // otherwise we just use the sun position calculation above
535
                landscapeBrightness *= static_cast<double>(atmosphere->getRealDisplayIntensityFactor()+0.1f);
×
536
        }
537
        // TODO: should calculate dimming with solar eclipse even without atmosphere on
538

539
        // Brightness can't be over 1.f (see https://bugs.launchpad.net/stellarium/+bug/1115364)
540
        if (landscapeBrightness>0.95)
×
541
                landscapeBrightness = 0.95;
×
542

543
        // GZ's rules and intentions for lightscape brightness:
544
        // lightscapeBrightness >0 makes sense only for sun below horizon.
545
        // If atmosphere on, we mix it in with darkening twilight. If atmosphere off, we can switch on more apruptly.
546
        // Note however that lightscape rendering does not per se depend on atmosphere on/off.
547
        // This allows for illuminated windows or light panels on spaceships. If a landscape's lightscape
548
        // contains light smog of a city, it should also be shown if atmosphere is switched off.
549
        // (Configure another landscape without light smog to avoid, or just switch off lightscape.)
550
        double lightscapeBrightness=0.0;
×
551
        const double sinSunAlt = sunPos[2];
×
552
        if (atmosphere->getFlagShow())
×
553
        {
554
                // light pollution layer is mixed in at -3...-8 degrees.
555
                if (sinSunAlt<-0.14)
×
556
                        lightscapeBrightness=1.0;
×
557
                else if (sinSunAlt<-0.05)
×
558
                        lightscapeBrightness = 1.0-(sinSunAlt+0.14)/(-0.05+0.14);
×
559
        }
560
        else
561
        {
562
                // If we have no atmosphere, we can assume windows and panels on spaceships etc. are switched on whenever the sun does not shine, i.e. when sun is blocked by landscape.
563
                lightscapeBrightness= static_cast<double>(landscape->getOpacity(sunPos));
×
564
        }
565

566
        landscape->setBrightness(landscapeBrightness, lightscapeBrightness);
×
567

568
        messageFader.update(static_cast<int>(deltaTime*1000));
×
569
}
×
570

571
void LandscapeMgr::draw(StelCore* core)
×
572
{
573
        StelSkyDrawer* drawer=core->getSkyDrawer();
×
574

575
        // Draw the atmosphere
576
        if (!getFlagAtmosphereNoScatter())
×
577
            atmosphere->draw(core);
×
578

579
        // GZ 2016-01: When we draw the atmosphere with a low sun, it is possible that the glaring red ball is overpainted and thus invisible.
580
        // Attempt to draw the sun only here while not having drawn it by SolarSystem:
581
        //if (atmosphere->getFlagShow())
582
        if (drawer->getFlagDrawSunAfterAtmosphere())
×
583
        {
584
                SolarSystem* ssys = GETSTELMODULE(SolarSystem);
×
585
                PlanetP sun=ssys->getSun();
×
586
                QFont font;
×
587
                font.setPixelSize(StelApp::getInstance().getScreenFontSize());
×
588
                sun->draw(core, 0, font);
×
589
        }
×
590

591
        // Draw the landscape
592
        if (oldLandscape)
×
593
                oldLandscape->draw(core, flagPolyLineDisplayedOnly);
×
594
        landscape->draw(core, flagPolyLineDisplayedOnly);
×
595

596
        // Draw the cardinal points
597
        cardinalPoints->draw(core, static_cast<double>(StelApp::getInstance().getCore()->getCurrentLocation().latitude));
×
598

599
        if(messageFader.getInterstate())
×
600
        {
601
                const StelProjectorP prj = core->getProjection(StelCore::FrameEquinoxEqu);
×
602
                StelPainter painter(prj);
×
603
                QFont font;
×
604
                font.setPixelSize(16);
×
605
                painter.setFont(font);
×
606
                painter.setColor(1, 0, 0, messageFader.getInterstate());
×
607
                painter.drawText(83, 70, messageToShow);
×
608
        }
×
609

610
        // Workaround for a bug with spherical mirror mode when we don't show the cardinal points.
611
        // I am not really sure why this seems to fix the problem.  If you want to
612
        // remove this, make sure the spherical mirror mode with cardinal points
613
        // toggled off works properly!
614
        const StelProjectorP prj = core->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
×
615
        QOpenGLPaintDevice device;
×
616
        device.setSize(QSize(prj->getViewportWidth(), prj->getViewportHeight()));
×
617
        QPainter painter(&device);
×
618
}
×
619

620
// Some element in drawing order behind LandscapeMgr can call this at the end of its own draw() to overdraw with the polygon line and gazetteer.
621
void LandscapeMgr::drawPolylineOnly(StelCore* core)
×
622
{
623
        // Draw the landscape
624
        if (oldLandscape && oldLandscape->hasLandscapePolygon())
×
625
                oldLandscape->draw(core, true);
×
626
        if (landscape->hasLandscapePolygon())
×
627
                landscape->draw(core, true);
×
628

629
        // Draw the cardinal points
630
        cardinalPoints->draw(core, static_cast<double>(StelApp::getInstance().getCore()->getCurrentLocation().latitude));
×
631
}
×
632

633
void LandscapeMgr::createAtmosphere()
×
634
{
635
        const auto modelName=getAtmosphereModel();
×
636
        const auto modelConfig=modelName.toLower();
×
637
        bool needResetConfig=false;
×
638
        if(modelConfig==ATMOSPHERE_MODEL_CONF_VAL_PREETHAM)
×
639
        {
640
                loadingAtmosphere.reset(new AtmospherePreetham(skylight));
×
641
        }
642
#ifdef ENABLE_SHOWMYSKY
643
        else if(modelConfig==ATMOSPHERE_MODEL_CONF_VAL_SHOWMYSKY)
×
644
        {
645
                try
646
                {
647
                        // Clear status so that if a repeated error happens, we do emit a signal that will update the GUI.
648
                        setAtmosphereShowMySkyStatusText("");
×
649
                        setAtmosphereShowMySkyStoppedWithError(false);
×
650

651
                        loadingAtmosphere.reset(new AtmosphereShowMySky());
×
652
                        if(!atmosphere)
×
653
                        {
654
                                // We're just loading the first atmosphere in the run of Stellarium. Initialize it synchronously.
655
                                while(loadingAtmosphere->isLoading())
×
656
                                        loadingAtmosphere->stepDataLoading();
×
657

658
                                setAtmosphereShowMySkyStoppedWithError(false);
×
659
                                setAtmosphereShowMySkyStatusText(q_("Loaded successfully"));
×
660
                        }
661
                        else
662
                        {
663
                                setAtmosphereShowMySkyStoppedWithError(false);
×
664
                                setAtmosphereShowMySkyStatusText(QString("%1 0% %2").arg(q_("Loading..."), qc_("done","percentage of done")));
×
665
                        }
666
                }
667
                catch(AtmosphereShowMySky::InitFailure const& error)
×
668
                {
669
                        qWarning() << "ERROR: Failed to initialize ShowMySky atmosphere model:" << error.what();
×
670
                        qWarning() << "WARNING: Falling back to the Preetham's model";
×
671
                        loadingAtmosphere.reset(new AtmospherePreetham(skylight));
×
672
                        needResetConfig=true;
×
673

674
                        setAtmosphereShowMySkyStoppedWithError(true);
×
675
                        setAtmosphereShowMySkyStatusText(error.what());
×
676
                }
×
677
        }
678
#endif
679
        else
680
        {
681
                qWarning() << "Unsupported atmosphere model" << modelName;
×
682
                loadingAtmosphere.reset(new AtmospherePreetham(skylight));
×
683
                needResetConfig=true;
×
684
        }
685
        if(!atmosphere)
×
686
        {
687
                // We're just loading the first atmosphere in the run of Stellarium. The atmosphere is fully loaded by this point.
688
                atmosphere = std::move(loadingAtmosphere);
×
689

690
                const auto conf=StelApp::getInstance().getSettings();
×
691
                setFlagAtmosphere(conf->value("landscape/flag_atmosphere", true).toBool());
×
692
                setAtmosphereFadeDuration(conf->value("landscape/atmosphere_fade_duration",0.5).toFloat());
×
693

694
                const auto drawer = StelApp::getInstance().getCore()->getSkyDrawer();
×
695
                setAtmosphereLightPollutionLuminance(drawer->getLightPollutionLuminance());
×
696
        }
697

698
        if(needResetConfig)
×
699
        {
700
                // We've failed to apply the setting, so reset to the fallback value
701
                const auto conf=StelApp::getInstance().getSettings();
×
702
                conf->setValue(ATMOSPHERE_MODEL_CONFIG_KEY, ATMOSPHERE_MODEL_CONF_VAL_PREETHAM);
×
703
        }
704

705
        needToRecreateAtmosphere=false;
×
706
}
×
707

708
void LandscapeMgr::resetToFallbackAtmosphere()
×
709
{
710
        StelApp::getInstance().getSettings()->setValue(ATMOSPHERE_MODEL_CONFIG_KEY, ATMOSPHERE_MODEL_CONF_VAL_PREETHAM);
×
711
        atmosphere.reset();
×
712
        createAtmosphere();
×
713
}
×
714

715
void LandscapeMgr::init()
×
716
{
717
        QSettings* conf = StelApp::getInstance().getSettings();
×
718
        Q_ASSERT(conf);
×
719
        StelApp *app = &StelApp::getInstance();
×
720
        Q_ASSERT(app);
×
721

722
        landscapeCache.setMaxCost(conf->value("landscape/cache_size_mb", 100).toInt());
×
723
        qDebug() << "LandscapeMgr: initialized Cache for" << landscapeCache.maxCost() << "MB.";
×
724

725
        // SET SIMPLE PROPERTIES FIRST, before loading the landscape (Loading may already make use of them! GH#1237)
726
        setFlagLandscapeSetsLocation(conf->value("landscape/flag_landscape_sets_location",false).toBool());
×
727
        setFlagLandscapeAutoSelection(conf->value("viewing/flag_landscape_autoselection", false).toBool());
×
728
        setFlagEnvironmentAutoEnable(conf->value("viewing/flag_environment_auto_enable",true).toBool());
×
729
        // Set minimal brightness for landscape. This feature has been added for folks which say "landscape is super dark, please add light". --AW
730
        setDefaultMinimalBrightness(conf->value("landscape/minimal_brightness", 0.01).toDouble());
×
731
        setFlagLandscapeUseMinimalBrightness(conf->value("landscape/flag_minimal_brightness", false).toBool());
×
732
        setFlagLandscapeSetsMinimalBrightness(conf->value("landscape/flag_landscape_sets_minimal_brightness",false).toBool());
×
733

734
        const auto var = conf->value(ATMOSPHERE_MODEL_PATH_CONFIG_KEY);
×
735
        if(!var.isValid())
×
736
                conf->setValue(ATMOSPHERE_MODEL_PATH_CONFIG_KEY, getDefaultAtmosphereModelPath());
×
737

738
        createAtmosphere();
×
739
        // Put the atmosphere's Skylight under the StelProperty system (simpler and more consistent GUI)
740
        StelApp::getInstance().getStelPropertyManager()->registerObject(&skylight);
×
741

742
        defaultLandscapeID = conf->value("init_location/landscape_name").toString();
×
743

744
        // We must make sure to allow auto location or command-line location even if landscape usually should set location.
745
        StelCore *core = StelApp::getInstance().getCore();
×
746
        const bool setLocationFromIPorCLI=((conf->value("init_location/location", "auto").toString() == "auto") || (core->getCurrentLocation().state=="CLI"));
×
747
        const bool shouldThenSetLocation=getFlagLandscapeSetsLocation();
×
748
        if (setLocationFromIPorCLI) setFlagLandscapeSetsLocation(false);
×
749
        setCurrentLandscapeID(defaultLandscapeID);
×
750
        setFlagLandscapeSetsLocation(shouldThenSetLocation);
×
751
        setFlagUseLightPollutionFromDatabase(conf->value("viewing/flag_light_pollution_database", false).toBool());
×
752
        setFlagLandscape(conf->value("landscape/flag_landscape", conf->value("landscape/flag_ground", true).toBool()).toBool());
×
753
        setFlagFog(conf->value("landscape/flag_fog",true).toBool());
×
754
        setFlagIllumination(conf->value("landscape/flag_enable_illumination_layer", true).toBool());
×
755
        setFlagLabels(conf->value("landscape/flag_enable_labels", true).toBool());
×
756
        setFlagPolyLineDisplayed(conf->value("landscape/flag_polyline_only", false).toBool());
×
757
        setPolyLineThickness(conf->value("landscape/polyline_thickness", 1).toInt());
×
758
        setLabelFontSize(conf->value("landscape/label_font_size", 18).toInt());
×
759
        setLabelColor(Vec3f(conf->value("landscape/label_color", "0.2,0.8,0.2").toString()));
×
760

761
        cardinalPoints = new Cardinals();
×
762
        cardinalPoints->setFlagShow4WCRLabels(conf->value("viewing/flag_cardinal_points", true).toBool());
×
763
        cardinalPoints->setFlagShow8WCRLabels(conf->value("viewing/flag_ordinal_points", true).toBool());
×
764
        cardinalPoints->setFlagShow16WCRLabels(conf->value("viewing/flag_16wcr_points", false).toBool());
×
765
        // Load colors from config file
766
        QString defaultColor = conf->value("color/default_color").toString();
×
767
        setColorCardinalPoints(Vec3f(conf->value("color/cardinal_color", defaultColor).toString()));
×
768

769
        currentPlanetName = app->getCore()->getCurrentLocation().planetName;
×
770
        //Bortle scale is managed by SkyDrawer
771
        StelSkyDrawer* drawer = app->getCore()->getSkyDrawer();
×
772
        Q_ASSERT(drawer);
×
773
        setAtmosphereLightPollutionLuminance(drawer->getLightPollutionLuminance());
×
774
        connect(app->getCore(), SIGNAL(locationChanged(StelLocation)), this, SLOT(onLocationChanged(StelLocation)));
×
775
        connect(app->getCore(), SIGNAL(targetLocationChanged(StelLocation)), this, SLOT(onTargetLocationChanged(StelLocation)));
×
776
        connect(drawer, &StelSkyDrawer::lightPollutionLuminanceChanged, this, &LandscapeMgr::setAtmosphereLightPollutionLuminance);
×
777
        connect(app, SIGNAL(languageChanged()), this, SLOT(updateI18n()));
×
778

779
        QString displayGroup = N_("Display Options");
×
780
        addAction("actionShow_Atmosphere", displayGroup, N_("Atmosphere"), "atmosphereDisplayed", "A");
×
781
        addAction("actionShow_Fog", displayGroup, N_("Fog"), "fogDisplayed", "F");
×
782
        addAction("actionShow_Cardinal_Points", displayGroup, N_("Cardinal points"), "cardinalPointsDisplayed", "Q");
×
783
        addAction("actionShow_Intercardinal_Points", displayGroup, N_("Ordinal (Intercardinal) points"), "ordinalPointsDisplayed");
×
784
        addAction("actionShow_Secondary_Intercardinal_Points", displayGroup, N_("Secondary Intercardinal points"), "ordinal16WRPointsDisplayed");
×
785
        addAction("actionShow_Ground", displayGroup, N_("Ground"), "landscapeDisplayed", "G");
×
786
        addAction("actionShow_LandscapeIllumination", displayGroup, N_("Landscape illumination"), "illuminationDisplayed", "Shift+G");
×
787
        addAction("actionShow_LandscapeLabels", displayGroup, N_("Landscape labels"), "labelsDisplayed", "Ctrl+Shift+G");
×
788
        addAction("actionShow_LightPollutionFromDatabase", displayGroup, N_("Light pollution data from locations database"), "flagUseLightPollutionFromDatabase");
×
789
        // Details: https://github.com/Stellarium/stellarium/issues/171
790
        addAction("actionShow_LightPollutionIncrease", displayGroup, N_("Increase light pollution"), "increaseLightPollution()");
×
791
        addAction("actionShow_LightPollutionReduce", displayGroup, N_("Reduce light pollution"), "reduceLightPollution()");
×
792
        addAction("actionShow_LightPollutionCyclicChange", displayGroup, N_("Cyclic change in light pollution"), "cyclicChangeLightPollution()");
×
793
}
×
794

795
bool LandscapeMgr::setCurrentLandscapeID(const QString& id, const double changeLocationDuration)
×
796
{
797
        if (id.isEmpty())
×
798
                return false;
×
799

800
        //prevent unnecessary changes/file access
801
        if(id==currentLandscapeID)
×
802
                return false;
×
803

804
        Landscape* newLandscape;
805

806
        // There is a slight chance that we switch back to oldLandscape while oldLandscape is still fading away.
807
        // in this case it is not yet stored in cache, but obviously available. So we just swap places.
808
        if (oldLandscape && oldLandscape->getId()==id)
×
809
        {
810
                newLandscape=oldLandscape;
×
811
        }
812
        else
813
        {
814
                // We want to lookup the landscape ID (dir) from the name.
815
                newLandscape= landscapeCache.take(id);
×
816

817
                if (newLandscape)
×
818
                {
819
#ifndef NDEBUG
820
                        qDebug() << "LandscapeMgr::setCurrentLandscapeID():: taken " << id << "from cache...";
×
821
                        qDebug() << ".-->LandscapeMgr::setCurrentLandscapeID(): cache contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
822
#endif
823
                }
824
                else
825
                {
826
#ifndef NDEBUG
827
                        qDebug() << "LandscapeMgr::setCurrentLandscapeID: Loading from file:" << id ;
×
828
#endif
829
                        newLandscape = createFromFile(StelFileMgr::findFile("landscapes/" + id + "/landscape.ini"), id);
×
830
                }
831

832
                if (!newLandscape)
×
833
                {
834
                        qWarning() << "ERROR while loading landscape " << "landscapes/" + id + "/landscape.ini";
×
835
                        return false;
×
836
                }
837
        }
838

839
        // Keep current landscape for a while, while new landscape fades in!
840
        // This prevents subhorizon sun or grid becoming briefly visible.
841
        if (landscape)
×
842
        {
843
                // Copy display parameters from previous landscape to new one
844
                newLandscape->setFlagShow(landscape->getFlagShow());
×
845
                newLandscape->setFlagShowFog(landscape->getFlagShowFog());
×
846
                newLandscape->setFlagShowIllumination(landscape->getFlagShowIllumination());
×
847
                newLandscape->setFlagShowLabels(landscape->getFlagShowLabels());
×
848
                newLandscape->setLabelFontSize(landscape->getLabelFontSize());
×
849
                newLandscape->setLabelColor(landscape->getLabelColor());
×
850

851
                // If we have an oldLandscape that is not just swapped back, put that into cache.
852
                if (oldLandscape && oldLandscape!=newLandscape)
×
853
                {
854
#ifndef NDEBUG
855
                        qDebug() << "LandscapeMgr::setCurrent: moving oldLandscape " << oldLandscape->getId() << "to Cache. Cost:" << oldLandscape->getMemorySize()/(1024*1024)+1;
×
856
#endif
857
                        landscapeCache.insert(oldLandscape->getId(), oldLandscape, oldLandscape->getMemorySize()/(1024*1024)+1);
×
858
#ifndef NDEBUG
859
                        qDebug() << "-->LandscapeMgr::setCurrentLandscapeId(): cache contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
860
#endif
861
                }
862
                oldLandscape = landscape; // keep old while transitioning!
×
863
        }
864
        landscape=newLandscape;
×
865
        currentLandscapeID = id;
×
866

867
        if (getFlagLandscapeSetsLocation() && landscape->hasLocation())
×
868
        {
869
                StelCore *core = StelApp::getInstance().getCore();
×
870
                core->moveObserverTo(landscape->getLocation(), changeLocationDuration);
×
871
                StelSkyDrawer* drawer=core->getSkyDrawer();
×
872

873
                if (landscape->getLocation().ianaTimeZone.length())
×
874
                {
875
                        core->setCurrentTimeZone(landscape->getLocation().ianaTimeZone);
×
876
                }
877
                if (landscape->getDefaultFogSetting() >-1)
×
878
                {
879
                        setFlagFog(static_cast<bool>(landscape->getDefaultFogSetting()));
×
880
                        landscape->setFlagShowFog(static_cast<bool>(landscape->getDefaultFogSetting()));
×
881
                }
882
                if (landscape->getDefaultLightPollutionLuminance().isValid())
×
883
                {
884
                        drawer->setLightPollutionLuminance(landscape->getDefaultLightPollutionLuminance().toFloat());
×
885
                }
886
                if (landscape->getDefaultAtmosphericExtinction() >= 0.0)
×
887
                {
888
                        drawer->setExtinctionCoefficient(landscape->getDefaultAtmosphericExtinction());
×
889
                }
890
                if (landscape->getDefaultAtmosphericTemperature() > -273.15)
×
891
                {
892
                        drawer->setAtmosphereTemperature(landscape->getDefaultAtmosphericTemperature());
×
893
                }
894
                if (landscape->getDefaultAtmosphericPressure() >= 0.0)
×
895
                {
896
                        drawer->setAtmospherePressure(landscape->getDefaultAtmosphericPressure());
×
897
                }
898
                else if (landscape->getDefaultAtmosphericPressure() < 0.0)
×
899
                {
900
                        // compute standard pressure for standard atmosphere in given altitude if landscape.ini coded as atmospheric_pressure=-1
901
                        // International altitude formula found in Wikipedia.
902
                        double alt=landscape->getLocation().altitude;
×
903
                        double p=1013.25*std::pow(1-(0.0065*alt)/288.15, 5.255);
×
904
                        drawer->setAtmospherePressure(p);
×
905
                }
906
        }
907

908
        emit currentLandscapeChanged(currentLandscapeID,getCurrentLandscapeName());
×
909

910
        // else qDebug() << "Will not set new location; Landscape location: planet: " << landscape->getLocation().planetName << "name: " << landscape->getLocation().name;
911
        return true;
×
912
}
913

914
bool LandscapeMgr::setCurrentLandscapeName(const QString& name, const double changeLocationDuration)
×
915
{
916
        if (name.isEmpty())
×
917
                return false;
×
918
        
919
        QMap<QString,QString> nameToDirMap = getNameToDirMap();
×
920
        if (nameToDirMap.find(name)!=nameToDirMap.end())
×
921
        {
922
                return setCurrentLandscapeID(nameToDirMap[name], changeLocationDuration);
×
923
        }
924
        else
925
        {
926
                qWarning() << "Can't find a landscape with name=" << name << StelUtils::getEndLineChar();
×
927
                return false;
×
928
        }
929
}
×
930

931
// Load a landscape into cache.
932
// @param id the ID of a landscape
933
// @param replace true if existing landscape entry should be replaced (useful during development to reload after edit)
934
// @return false if landscape could not be found, or existed already and replace was false.
935
bool LandscapeMgr::precacheLandscape(const QString& id, const bool replace)
×
936
{
937
        if (landscapeCache.contains(id) && (!replace))
×
938
                return false;
×
939

940
        Landscape* newLandscape = createFromFile(StelFileMgr::findFile("landscapes/" + id + "/landscape.ini"), id);
×
941
        if (!newLandscape)
×
942
        {
943
                qWarning() << "ERROR while preloading landscape " << "landscapes/" + id + "/landscape.ini";
×
944
                return false;
×
945
        }
946

947
        bool res=landscapeCache.insert(id, newLandscape, newLandscape->getMemorySize()/(1024*1024)+1);
×
948
#ifndef NDEBUG
949
        if (res)
×
950
        {
951
                qDebug() << "LandscapeMgr::precacheLandscape(): Successfully added landscape with ID " << id << "to cache";
×
952
        }
953
        qDebug() << "LandscapeMgr::precacheLandscape(): cache contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
954
#endif
955
        return res;
×
956
}
957

958
// Remove a landscape from the cache of loaded landscapes.
959
// @param id the ID of a landscape
960
// @return false if landscape could not be found
961
bool LandscapeMgr::removeCachedLandscape(const QString& id)
×
962
{
963
        bool res= landscapeCache.remove(id);
×
964
#ifndef NDEBUG
965
        qDebug() << "LandscapeMgr::removeCachedLandscape(): cache contains " << landscapeCache.size() << "landscapes totalling about " << landscapeCache.totalCost() << "MB.";
×
966
#endif
967
        return res;
×
968
}
969

970

971
// Change the default landscape to the landscape with the ID specified.
972
bool LandscapeMgr::setDefaultLandscapeID(const QString& id)
×
973
{
974
        if (id.isEmpty())
×
975
                return false;
×
976
        defaultLandscapeID = id;
×
977
        QSettings* conf = StelApp::getInstance().getSettings();
×
978
        conf->setValue("init_location/landscape_name", id);
×
979
        emit defaultLandscapeChanged(id);
×
980
        return true;
×
981
}
982

983
void LandscapeMgr::updateI18n()
×
984
{
985
        // Translate all labels with the new language
986
        if (cardinalPoints) cardinalPoints->updateI18n();
×
987
        landscape->loadLabels(getCurrentLandscapeID());
×
988
}
×
989

990
void LandscapeMgr::setFlagLandscape(const bool displayed)
×
991
{
992
        if (oldLandscape && !displayed)
×
993
                oldLandscape->setFlagShow(false);
×
994
        if(landscape->getFlagShow() != displayed) {
×
995
                landscape->setFlagShow(displayed);
×
996
                emit landscapeDisplayedChanged(displayed);
×
997
        }
998
}
×
999

1000
bool LandscapeMgr::getFlagLandscape() const
×
1001
{
1002
        return landscape->getFlagShow();
×
1003
}
1004

1005
bool LandscapeMgr::getIsLandscapeFullyVisible() const
×
1006
{
1007
        return landscape->getIsFullyVisible();
×
1008
}
1009

1010
double LandscapeMgr::getLandscapeSinMinAltitudeLimit() const
×
1011
{
1012
        return landscape->getSinMinAltitudeLimit();
×
1013
}
1014

1015
bool LandscapeMgr::getFlagUseLightPollutionFromDatabase() const
×
1016
{
1017
        return flagLightPollutionFromDatabase;
×
1018
}
1019

1020
void LandscapeMgr::setFlagUseLightPollutionFromDatabase(const bool usage)
×
1021
{
1022
        if (flagLightPollutionFromDatabase != usage)
×
1023
        {
1024
                flagLightPollutionFromDatabase = usage;
×
1025

1026
                StelCore* core = StelApp::getInstance().getCore();
×
1027

1028
                //this was previously logic in ViewDialog, but should really be on a non-GUI layer
1029
                if (usage)
×
1030
                {
1031
                        StelLocation loc = core->getCurrentLocation();
×
1032
                        onLocationChanged(loc);
×
1033
                }
×
1034

1035
                emit flagUseLightPollutionFromDatabaseChanged(usage);
×
1036
        }
1037
}
×
1038

1039
void LandscapeMgr::onLocationChanged(const StelLocation &loc)
×
1040
{
1041
        if(flagLightPollutionFromDatabase)
×
1042
        {
1043
                //this was previously logic in ViewDialog, but should really be on a non-GUI layer
1044
                StelCore* core = StelApp::getInstance().getCore();
×
1045
                float lum;
1046
                if (!loc.planetName.contains("Earth")) // location not on Earth...
×
1047
                        lum = 0;
×
1048
                else if(loc.lightPollutionLuminance.isValid())
×
1049
                        lum = loc.lightPollutionLuminance.toFloat();
×
1050
                else // ...or it is an observatory, or it is an unknown location
1051
                        lum = loc.DEFAULT_LIGHT_POLLUTION_LUMINANCE;
×
1052

1053
                core->getSkyDrawer()->setLightPollutionLuminance(lum);
×
1054
        }
1055
}
×
1056

1057
void LandscapeMgr::onTargetLocationChanged(const StelLocation &loc)
×
1058
{
1059
        if (loc.planetName != currentPlanetName)
×
1060
        {
1061
                currentPlanetName = loc.planetName;
×
1062
                if (flagLandscapeAutoSelection)
×
1063
                {
1064
                        // If we have a landscape for selected planet then set it, otherwise use zero horizon landscape
1065
                        bool landscapeSetsLocation = getFlagLandscapeSetsLocation();
×
1066
                        setFlagLandscapeSetsLocation(false);
×
1067
                        if (getAllLandscapeNames().indexOf(loc.planetName)>0)
×
1068
                                setCurrentLandscapeName(loc.planetName);
×
1069
                        else
1070
                                setCurrentLandscapeID("zero");
×
1071
                        setFlagLandscapeSetsLocation(landscapeSetsLocation);
×
1072
                }
1073

1074
                if (loc.planetName.contains("Observer", Qt::CaseInsensitive))
×
1075
                {
1076
                        if (flagEnvironmentAutoEnabling)
×
1077
                        {
1078
                                setFlagAtmosphere(false);
×
1079
                                setFlagFog(false);
×
1080
                                setFlagLandscape(false);
×
1081
                                setFlagCardinalPoints(false);
×
1082
                                //setFlagOrdinalsPoints(false);
1083
                                //setFlagOrdinals16WRPoints(false);
1084
                        }
1085
                }
1086
                else
1087
                {
1088
                        SolarSystem* ssystem = static_cast<SolarSystem*>(StelApp::getInstance().getModuleMgr().getModule("SolarSystem"));
×
1089
                        PlanetP pl = ssystem->searchByEnglishName(loc.planetName);
×
1090
                        if (pl && flagEnvironmentAutoEnabling)
×
1091
                        {
1092
                                QSettings* conf = StelApp::getInstance().getSettings();
×
1093
                                setFlagAtmosphere(pl->hasAtmosphere() && conf->value("landscape/flag_atmosphere", true).toBool());
×
1094
                                setFlagFog(pl->hasAtmosphere() && conf->value("landscape/flag_fog", true).toBool());
×
1095
                                setFlagLandscape(true);
×
1096
                                setFlagCardinalPoints(conf->value("viewing/flag_cardinal_points", true).toBool());
×
1097
                                setFlagOrdinalPoints(conf->value("viewing/flag_ordinal_points", true).toBool());
×
1098
                                setFlagOrdinal16WRPoints(conf->value("viewing/flag_16wcr_points", false).toBool());
×
1099
                        }
1100
                }
×
1101
        }
1102
}
×
1103

1104
void LandscapeMgr::setFlagFog(const bool displayed)
×
1105
{
1106
        if (landscape->getFlagShowFog() != displayed) {
×
1107
                landscape->setFlagShowFog(displayed);
×
1108
                emit fogDisplayedChanged(displayed);
×
1109
        }
1110
}
×
1111

1112
bool LandscapeMgr::getFlagFog() const
×
1113
{
1114
        return landscape->getFlagShowFog();
×
1115
}
1116

1117
void LandscapeMgr::setFlagIllumination(const bool displayed)
×
1118
{
1119
        if (landscape->getFlagShowIllumination() != displayed) {
×
1120
                landscape->setFlagShowIllumination(displayed);
×
1121
                emit illuminationDisplayedChanged(displayed);
×
1122
        }
1123
}
×
1124

1125
bool LandscapeMgr::getFlagIllumination() const
×
1126
{
1127
        return landscape->getFlagShowIllumination();
×
1128
}
1129

1130
void LandscapeMgr::setFlagLabels(const bool displayed)
×
1131
{
1132
        if (landscape->getFlagShowLabels() != displayed) {
×
1133
                landscape->setFlagShowLabels(displayed);
×
1134
                emit labelsDisplayedChanged(displayed);
×
1135
        }
1136
}
×
1137

1138
bool LandscapeMgr::getFlagLabels() const
×
1139
{
1140
        return landscape->getFlagShowLabels();
×
1141
}
1142

1143
void LandscapeMgr::setLabelFontSize(const int size)
×
1144
{
1145
        landscape->setLabelFontSize(size);
×
1146
        emit labelFontSizeChanged(size);
×
1147
}
×
1148

1149
int LandscapeMgr::getLabelFontSize() const
×
1150
{
1151
        return landscape->getLabelFontSize();
×
1152
}
1153

1154
void LandscapeMgr::setLabelColor(const Vec3f& c)
×
1155
{
1156
        landscape->setLabelColor(c);
×
1157
        emit labelColorChanged(c);
×
1158
}
×
1159

1160
Vec3f LandscapeMgr::getLabelColor() const
×
1161
{
1162
        return landscape->getLabelColor();
×
1163
}
1164

1165
void LandscapeMgr::setFlagLandscapeAutoSelection(bool enableAutoSelect)
×
1166
{
1167
        if(enableAutoSelect != flagLandscapeAutoSelection)
×
1168
        {
1169
                flagLandscapeAutoSelection = enableAutoSelect;
×
1170
                emit flagLandscapeAutoSelectionChanged(enableAutoSelect);
×
1171
        }
1172
}
×
1173

1174
bool LandscapeMgr::getFlagLandscapeAutoSelection() const
×
1175
{
1176
        return flagLandscapeAutoSelection;
×
1177
}
1178

1179
void LandscapeMgr::setFlagEnvironmentAutoEnable(bool b)
×
1180
{
1181
        if(b != flagEnvironmentAutoEnabling)
×
1182
        {
1183
                flagEnvironmentAutoEnabling = b;
×
1184
                emit setFlagEnvironmentAutoEnableChanged(b);
×
1185
        }
1186
}
×
1187

1188
bool LandscapeMgr::getFlagEnvironmentAutoEnable() const
×
1189
{
1190
        return flagEnvironmentAutoEnabling;
×
1191
}
1192

1193
/*********************************************************************
1194
 Retrieve list of the names of all the available landscapes
1195
 *********************************************************************/
1196
QStringList LandscapeMgr::getAllLandscapeNames() const
×
1197
{
1198
        return getNameToDirMap().keys();
×
1199
}
1200

1201
QStringList LandscapeMgr::getAllLandscapeIDs() const
×
1202
{
1203
        return getNameToDirMap().values();
×
1204
}
1205

1206
QStringList LandscapeMgr::getUserLandscapeIDs() const
×
1207
{
1208
        QStringList result;
×
1209
        QMapIterator<QString, QString> it(getNameToDirMap());
×
1210
        while (it.hasNext())
×
1211
        {
1212
                it.next();
×
1213
                if(!packagedLandscapeIDs.contains(it.value()))
×
1214
                        result.append(it.value());
×
1215
        }
1216
        return result;
×
1217
}
×
1218

1219
QString LandscapeMgr::getCurrentLandscapeName() const
×
1220
{
1221
        return landscape->getName();
×
1222
}
1223

1224
QString LandscapeMgr::getCurrentLandscapeHtmlDescription() const
×
1225
{
1226
        QString desc = getDescription();
×
1227

1228
        QString author = landscape->getAuthorName();
×
1229

1230
        desc += "<p>";
×
1231
        if (!author.isEmpty())
×
1232
                desc += QString("<b>%1</b>: %2<br />").arg(q_("Author"), author);
×
1233

1234
        // This previously showed 0/0 for locationless landscapes!
1235
        if (landscape->hasLocation())
×
1236
        {
1237
                //TRANSLATORS: Unit of measure for distance - meter
1238
                QString alt = qc_("m", "distance");
×
1239

1240
                desc += QString("<b>%1</b>: %2, %3, %4 %5").arg(
×
1241
                                q_("Location"),
×
1242
                                StelUtils::radToDmsStrAdapt(static_cast<double>(landscape->getLocation().latitude) *M_PI_180),
×
1243
                                StelUtils::radToDmsStrAdapt(static_cast<double>(landscape->getLocation().longitude) * M_PI_180),
×
1244
                                QString::number(landscape->getLocation().altitude),
×
1245
                                alt);
×
1246

1247
                QString planetName = landscape->getLocation().planetName;                
×
1248
                if (!planetName.isEmpty())
×
1249
                {
1250
                        const StelTranslator& trans = StelApp::getInstance().getLocaleMgr().getSkyTranslator();
×
1251
                        desc += QString(", %1").arg(trans.qtranslate(planetName, "major planet")); // TODO: Enhance the context support
×
1252
                }
1253
                desc += "<br />";
×
1254

1255
                QStringList atmosphere;
×
1256
                //atmosphere.clear(); // Huh?
1257

1258
                double pressure = landscape->getDefaultAtmosphericPressure();
×
1259
                if (pressure>0.)
×
1260
                {
1261
                        // 1 mbar = 1 hPa
1262
                        //TRANSLATORS: Unit of measure for pressure - hectopascals
1263
                        QString hPa = qc_("hPa", "pressure");
×
1264
                        atmosphere.append(QString("%1 %2").arg(QString::number(pressure, 'f', 1), hPa));
×
1265
                }
×
1266

1267
                double temperature = landscape->getDefaultAtmosphericTemperature();
×
1268
                if (temperature>-1000.0)
×
1269
                        atmosphere.append(QString("%1 %2C").arg(QString::number(temperature, 'f', 1)).arg(QChar(0x00B0)));
×
1270

1271
                double extcoeff = landscape->getDefaultAtmosphericExtinction();
×
1272
                if (extcoeff>-1.0)
×
1273
                        atmosphere.append(QString("%1: %2").arg(q_("extinction coefficient"), QString::number(extcoeff, 'f', 2)));
×
1274

1275
                if (atmosphere.size()>0)
×
1276
                        desc += QString("<b>%1</b>: %2<br />").arg(q_("Atmospheric conditions"), atmosphere.join(", "));
×
1277

1278
                const auto lightPollutionLum = landscape->getDefaultLightPollutionLuminance();
×
1279
                if (lightPollutionLum.isValid())
×
1280
                {
1281
                        const auto lum = lightPollutionLum.toFloat();
×
1282
                        auto scaledLum = lum;
×
1283
                        QString unit = q_("cd/m<sup>2</sup>");
×
1284
                        if(lum < 1e-6f)
×
1285
                        {
1286
                                scaledLum = lum*1e9f;
×
1287
                                unit = q_("ncd/m<sup>2</sup>");
×
1288
                        }
1289
                        else if(lum < 1e-3f)
×
1290
                        {
1291
                                scaledLum = lum*1e6f;
×
1292
                                unit = q_("&mu;cd/m<sup>2</sup>");
×
1293
                        }
1294
                        else if(lum < 1)
×
1295
                        {
1296
                                scaledLum = lum*1e3f;
×
1297
                                unit = q_("mcd/m<sup>2</sup>");
×
1298
                        }
1299
                        desc += q_("<b>Light pollution</b>: %1 %2 (NELM: %3; Bortle class: %4)")
×
1300
                                                .arg(scaledLum).arg(unit).arg(StelCore::luminanceToNELM(lum))
×
1301
                                                .arg(StelCore::luminanceToBortleScaleIndex(lum));
×
1302
                }
×
1303
        }        
×
1304
        return desc;
×
1305
}
×
1306

1307
//! Set flag for displaying cardinal points
1308
void LandscapeMgr::setFlagCardinalPoints(const bool displayed)
×
1309
{
1310
        if (cardinalPoints->getFlagShow4WCRLabels() != displayed)
×
1311
        {
1312
                cardinalPoints->setFlagShow4WCRLabels(displayed);
×
1313
                emit cardinalPointsDisplayedChanged(displayed);
×
1314
        }
1315
}
×
1316

1317
//! Get flag for displaying cardinal points
1318
bool LandscapeMgr::getFlagCardinalPoints() const
×
1319
{
1320
        return cardinalPoints->getFlagShowCardinals();
×
1321
}
1322

1323
//! Set flag for displaying ordinal points
1324
void LandscapeMgr::setFlagOrdinalPoints(const bool displayed)
×
1325
{
1326
        if (cardinalPoints->getFlagShow8WCRLabels() != displayed)
×
1327
        {
1328
                cardinalPoints->setFlagShow8WCRLabels(displayed);
×
1329
                emit ordinalPointsDisplayedChanged(displayed);
×
1330
        }
1331
}
×
1332

1333
//! Get flag for displaying ordinal points
1334
bool LandscapeMgr::getFlagOrdinalPoints() const
×
1335
{
1336
        return cardinalPoints->getFlagShow8WCRLabels();
×
1337
}
1338

1339
//! Set flag for displaying ordinal points
1340
void LandscapeMgr::setFlagOrdinal16WRPoints(const bool displayed)
×
1341
{
1342
        if (cardinalPoints->getFlagShow16WCRLabels() != displayed)
×
1343
        {
1344
                cardinalPoints->setFlagShow16WCRLabels(displayed);
×
1345
                emit ordinal16WRPointsDisplayedChanged(displayed);
×
1346
        }
1347
}
×
1348

1349
//! Get flag for displaying ordinal points
1350
bool LandscapeMgr::getFlagOrdinal16WRPoints() const
×
1351
{
1352
        return cardinalPoints->getFlagShow16WCRLabels();
×
1353
}
1354

1355
//! Set Cardinals Points color
1356
void LandscapeMgr::setColorCardinalPoints(const Vec3f& v)
×
1357
{
1358
        if(v != getColorCardinalPoints())
×
1359
        {
1360
                cardinalPoints->setColor(v);
×
1361
                emit cardinalPointsColorChanged(v);
×
1362
        }
1363
}
×
1364

1365
//! Get Cardinals Points color
1366
Vec3f LandscapeMgr::getColorCardinalPoints() const
×
1367
{
1368
        return cardinalPoints->getColor();
×
1369
}
1370

1371
///////////////////////////////////////////////////////////////////////////////////////
1372
// Atmosphere
1373
//! Set flag for displaying Atmosphere
1374
void LandscapeMgr::setFlagAtmosphere(const bool displayed)
×
1375
{
1376
        if (atmosphere->getFlagShow() != displayed) {
×
1377
                atmosphere->setFlagShow(displayed);
×
1378
                StelApp::getInstance().getCore()->getSkyDrawer()->setFlagHasAtmosphere(displayed);
×
1379
                emit atmosphereDisplayedChanged(displayed);
×
1380
                //if (StelApp::getInstance().getSettings()->value("landscape/flag_fog", true).toBool())
1381
                //        setFlagFog(displayed); // sync of visibility of fog because this is atmospheric phenomena
1382
                // GZ This did not work as it may have been intended. Switch off fog, switch off atmosphere. Switch on atmosphere, and you have fog?
1383
                // --> Fog is only drawn in Landscape if atmosphere is switched on!
1384
        }
1385
}
×
1386

1387
void LandscapeMgr::setAtmosphereModel(const QString& model)
×
1388
{
1389
        const auto modelToSet = model.toLower();
×
1390
        const auto oldModel = getAtmosphereModel().toLower();
×
1391
        if(modelToSet == oldModel)
×
1392
                return;
×
1393

1394
        StelApp::getInstance().getSettings()->setValue(ATMOSPHERE_MODEL_CONFIG_KEY, model);
×
1395

1396
        if(!(oldModel.isEmpty() && modelToSet == ATMOSPHERE_MODEL_CONF_VAL_DEFAULT))
×
1397
        {
1398
                // Can't call createAtmosphere() right now, because we likely have wrong OpenGL context (or even none).
1399
                // So just schedule it for the next draw.
1400
                needToRecreateAtmosphere=true;
×
1401
        }
1402
}
×
1403

1404
void LandscapeMgr::setAtmosphereModelPath(const QString& path)
×
1405
{
1406
        if(getAtmosphereModelPath()==path)
×
1407
                return;
×
1408

1409
        StelApp::getInstance().getSettings()->setValue(ATMOSPHERE_MODEL_PATH_CONFIG_KEY, path);
×
1410
        setAtmosphereModel(ATMOSPHERE_MODEL_CONF_VAL_SHOWMYSKY); // This is the only relevant model for this property
×
1411
        needToRecreateAtmosphere=true;
×
1412

1413
        emit atmosphereModelPathChanged(path);
×
1414
}
1415

1416
void LandscapeMgr::setAtmosphereShowMySkyStoppedWithError(const bool error)
×
1417
{
1418
        if(atmosphereShowMySkyStoppedWithError == error)
×
1419
                return;
×
1420
        atmosphereShowMySkyStoppedWithError = error;
×
1421
        emit atmosphereStoppedWithErrorChanged(error);
×
1422
}
1423

1424
void LandscapeMgr::setAtmosphereShowMySkyStatusText(const QString& text)
×
1425
{
1426
        if(atmosphereShowMySkyStatusText == text)
×
1427
                return;
×
1428
        atmosphereShowMySkyStatusText = text;
×
1429
        emit atmosphereStatusTextChanged(text);
×
1430
}
1431

1432
void LandscapeMgr::setFlagAtmosphereZeroOrderScattering(const bool enable)
×
1433
{
1434
        atmosphereZeroOrderScatteringEnabled=enable;
×
1435
        emit flagAtmosphereZeroOrderScatteringChanged(enable);
×
1436
}
×
1437

1438
void LandscapeMgr::setFlagAtmosphereSingleScattering(const bool enable)
×
1439
{
1440
        atmosphereSingleScatteringEnabled=enable;
×
1441
        emit flagAtmosphereSingleScatteringChanged(enable);
×
1442
}
×
1443

1444
void LandscapeMgr::setFlagAtmosphereMultipleScattering(const bool enable)
×
1445
{
1446
        atmosphereMultipleScatteringEnabled=enable;
×
1447
        emit flagAtmosphereMultipleScatteringChanged(enable);
×
1448
}
×
1449

1450
void LandscapeMgr::setAtmosphereEclipseSimulationQuality(const int quality)
×
1451
{
1452
        if(getAtmosphereEclipseSimulationQuality() == quality)
×
1453
                return;
×
1454

1455
        StelApp::getInstance().getSettings()->setValue(ATMOSPHERE_ECLIPSE_SIM_QUALITY_CONFIG_KEY, quality);
×
1456

1457
        emit atmosphereEclipseSimulationQualityChanged(quality);
×
1458
}
1459

1460
//! Get flag for displaying Atmosphere
1461
bool LandscapeMgr::getFlagAtmosphere() const
×
1462
{
1463
        return atmosphere->getFlagShow();
×
1464
}
1465

1466
//! Set flag for displaying Atmosphere
1467
void LandscapeMgr::setFlagAtmosphereNoScatter(const bool noScatter)
×
1468
{
1469
        atmosphereNoScatter=noScatter;
×
1470
        emit atmosphereNoScatterChanged(noScatter);
×
1471
}
×
1472

1473
//! Get flag for displaying Atmosphere
1474
bool LandscapeMgr::getFlagAtmosphereNoScatter() const
×
1475
{
1476
        return atmosphereNoScatter;
×
1477
}
1478

1479
QString LandscapeMgr::getAtmosphereModel() const
×
1480
{
1481
        const auto conf=StelApp::getInstance().getSettings();
×
1482
        return conf->value(ATMOSPHERE_MODEL_CONFIG_KEY, ATMOSPHERE_MODEL_CONF_VAL_DEFAULT).toString();
×
1483
}
1484

1485
QString LandscapeMgr::getAtmosphereModelPath() const
×
1486
{
1487
        const auto conf=StelApp::getInstance().getSettings();
×
1488

1489
        const auto var = conf->value(ATMOSPHERE_MODEL_PATH_CONFIG_KEY);
×
1490
        if(var.isValid()) return var.toString();
×
1491

1492
        return getDefaultAtmosphereModelPath();
×
1493
}
×
1494

1495
QString LandscapeMgr::getDefaultAtmosphereModelPath() const
×
1496
{
1497
        return QDir::toNativeSeparators(QString("%1/atmosphere/default").arg(StelFileMgr::getInstallationDir()));
×
1498
}
1499

1500
bool LandscapeMgr::getAtmosphereShowMySkyStoppedWithError() const
×
1501
{
1502
        return atmosphereShowMySkyStoppedWithError;
×
1503
}
1504

1505
QString LandscapeMgr::getAtmosphereShowMySkyStatusText() const
×
1506
{
1507
        return atmosphereShowMySkyStatusText;
×
1508
}
1509

1510
bool LandscapeMgr::getFlagAtmosphereZeroOrderScattering() const
×
1511
{
1512
        return atmosphereZeroOrderScatteringEnabled;
×
1513
}
1514

1515
bool LandscapeMgr::getFlagAtmosphereSingleScattering() const
×
1516
{
1517
        return atmosphereSingleScatteringEnabled;
×
1518
}
1519

1520
bool LandscapeMgr::getFlagAtmosphereMultipleScattering() const
×
1521
{
1522
        return atmosphereMultipleScatteringEnabled;
×
1523
}
1524

1525
int LandscapeMgr::getAtmosphereEclipseSimulationQuality() const
×
1526
{
1527
        const auto conf=StelApp::getInstance().getSettings();
×
1528
        return conf->value(ATMOSPHERE_ECLIPSE_SIM_QUALITY_CONFIG_KEY, 1).toInt();
×
1529
}
1530

1531
float LandscapeMgr::getAtmosphereFadeIntensity() const
×
1532
{
1533
        return atmosphere->getFadeIntensity();
×
1534
}
1535

1536
//! Set atmosphere fade duration in s
1537
void LandscapeMgr::setAtmosphereFadeDuration(const float f)
×
1538
{
1539
        atmosphere->setFadeDuration(f);
×
1540
}
×
1541

1542
//! Get atmosphere fade duration in s
1543
float LandscapeMgr::getAtmosphereFadeDuration() const
×
1544
{
1545
        return atmosphere->getFadeDuration();
×
1546
}
1547

1548
//! Set light pollution luminance level
1549
void LandscapeMgr::setAtmosphereLightPollutionLuminance(const float f)
×
1550
{
1551
        atmosphere->setLightPollutionLuminance(f);
×
1552
}
×
1553

1554
//! Get light pollution luminance level
1555
float LandscapeMgr::getAtmosphereLightPollutionLuminance() const
×
1556
{
1557
        return atmosphere->getLightPollutionLuminance();
×
1558
}
1559

1560
void LandscapeMgr::setZRotation(const float d)
×
1561
{
1562
        if (landscape)
×
1563
                landscape->setZRotation(d);
×
1564
}
×
1565

1566
float LandscapeMgr::getLuminance() const
×
1567
{
1568
        return atmosphere->getRealDisplayIntensityFactor();
×
1569
}
1570

1571
float LandscapeMgr::getAtmosphereAverageLuminance() const
×
1572
{
1573
        return atmosphere->getAverageLuminance();
×
1574
}
1575

1576
// Override auto-computed luminance. Only use when you know what you are doing, and don't forget to unfreeze the average by calling this function with a negative value.
1577
void LandscapeMgr::setAtmosphereAverageLuminance(const float overrideLum)
×
1578
{
1579
        atmosphere->setAverageLuminance(overrideLum);
×
1580
}
×
1581

1582
Landscape* LandscapeMgr::createFromFile(const QString& landscapeFile, const QString& landscapeId)
×
1583
{
1584
        QSettings landscapeIni(landscapeFile, StelIniFormat);
×
1585
        QString s;
×
1586
        if (landscapeIni.status() != QSettings::NoError)
×
1587
        {
1588
                qWarning() << "ERROR parsing landscape.ini file: " << QDir::toNativeSeparators(landscapeFile);
×
1589
                s = "";
×
1590
        }
1591
        else
1592
                s = landscapeIni.value("landscape/type").toString();
×
1593

1594
        Landscape* landscape = Q_NULLPTR;
×
1595
        if (s=="old_style")
×
1596
                landscape = new LandscapeOldStyle();
×
1597
        else if (s=="spherical")
×
1598
                landscape = new LandscapeSpherical();
×
1599
        else if (s=="fisheye")
×
1600
                landscape = new LandscapeFisheye();
×
1601
        else if (s=="polygonal")
×
1602
                landscape = new LandscapePolygonal();
×
1603
        else
1604
        {
1605
                qDebug() << "Unknown landscape type: \"" << s << "\"";
×
1606

1607
                // to avoid making this a fatal error, will load as a fisheye
1608
                // if this fails, it just won't draw
1609
                landscape = new LandscapeFisheye();
×
1610
        }
1611

1612
        landscape->load(landscapeIni, landscapeId);
×
1613
        return landscape;
×
1614
}
×
1615

1616

1617
QString LandscapeMgr::nameToID(const QString& name)
×
1618
{
1619
        QMap<QString,QString> nameToDirMap = getNameToDirMap();
×
1620

1621
        if (nameToDirMap.find(name)!=nameToDirMap.end())
×
1622
        {
1623
                Q_ASSERT(0);
×
1624
                return "error";
1625
        }
1626
        else
1627
        {
1628
                return nameToDirMap[name];
×
1629
        }
1630
}
×
1631

1632
/****************************************************************************
1633
 get a map of landscape names (from landscape.ini name field) to ID (dir name)
1634
 ****************************************************************************/
1635
QMap<QString,QString> LandscapeMgr::getNameToDirMap()
×
1636
{
1637
        QMap<QString,QString> result;
×
1638
        const QSet<QString> landscapeDirs = StelFileMgr::listContents("landscapes",StelFileMgr::Directory);
×
1639

1640
        for (const auto& dir : landscapeDirs)
×
1641
        {
1642
                QString fName = StelFileMgr::findFile("landscapes/" + dir + "/landscape.ini");
×
1643
                if (!fName.isEmpty())
×
1644
                {
1645
                        QSettings landscapeIni(fName, StelIniFormat);
×
1646
                        QString k = landscapeIni.value("landscape/name").toString();
×
1647
                        result[k] = dir;
×
1648
                }
×
1649
        }
×
1650
        return result;
×
1651
}
×
1652

1653
QString LandscapeMgr::installLandscapeFromArchive(QString sourceFilePath, const bool display, const bool toMainDirectory)
×
1654
{
1655
        Q_UNUSED(toMainDirectory)
1656
        if (!QFile::exists(sourceFilePath))
×
1657
        {
1658
                qDebug() << "LandscapeMgr: File does not exist:" << QDir::toNativeSeparators(sourceFilePath);
×
1659
                emit errorUnableToOpen(sourceFilePath);
×
1660
                return QString();
×
1661
        }
1662

1663
        QDir parentDestinationDir;
×
1664
        parentDestinationDir.setPath(StelFileMgr::getUserDir());
×
1665

1666
        if (!parentDestinationDir.exists("landscapes"))
×
1667
        {
1668
                //qDebug() << "LandscapeMgr: No 'landscapes' subdirectory exists in" << parentDestinationDir.absolutePath();
1669
                if (!parentDestinationDir.mkdir("landscapes"))
×
1670
                {
1671
                        qWarning() << "LandscapeMgr: Unable to install landscape: Unable to create sub-directory 'landscapes' in" << QDir::toNativeSeparators(parentDestinationDir.absolutePath());
×
1672
                        emit errorUnableToOpen(QDir::cleanPath(parentDestinationDir.filePath("landscapes")));//parentDestinationDir.absolutePath()
×
1673
                        return QString();
×
1674
                }
1675
        }
1676
        QDir destinationDir (parentDestinationDir.absoluteFilePath("landscapes"));
×
1677

1678
        QZipReader reader(sourceFilePath);
×
1679
        if (reader.status() != QZipReader::NoError)
×
1680
        {
1681
                qWarning() << "LandscapeMgr: Unable to open as a ZIP archive:" << QDir::toNativeSeparators(sourceFilePath);
×
1682
                emit errorNotArchive();
×
1683
                return QString();
×
1684
        }
1685

1686
        //Detect top directory
1687
        QString topDir, iniPath;
×
1688
        const auto infoList = reader.fileInfoList();
×
1689
        for (const auto& info : infoList)
×
1690
        {
1691
                QFileInfo fileInfo(info.filePath);
×
1692
                if (fileInfo.fileName() == "landscape.ini")
×
1693
                {
1694
                        iniPath = info.filePath;
×
1695
                        topDir = fileInfo.dir().path();
×
1696
                        break;
×
1697
                }
1698
        }
×
1699
        if (topDir.isEmpty())
×
1700
        {
1701
                qWarning() << "LandscapeMgr: Unable to install landscape. There is no directory that contains a 'landscape.ini' file in the source archive.";
×
1702
                emit errorNotArchive();
×
1703
                return QString();
×
1704
        }
1705
        //Determine the landscape's identifier
1706
        QString landscapeID = QFileInfo(topDir).fileName();
×
1707
        if (landscapeID.length() < 2)
×
1708
        {
1709
                // If the archive has no top level directory
1710
                // use the first 65 characters of its file name for an identifier
1711
                QFileInfo sourceFileInfo(sourceFilePath);
×
1712
                landscapeID = sourceFileInfo.baseName().left(65);
×
1713
        }
×
1714

1715
        //Check for duplicate IDs
1716
        if (getAllLandscapeIDs().contains(landscapeID))
×
1717
        {
1718
                qWarning() << "LandscapeMgr: Unable to install landscape. A landscape with the ID" << landscapeID << "already exists.";
×
1719
                emit errorNotUnique(landscapeID);
×
1720
                return QString();
×
1721
        }
1722

1723
        //Read the .ini file and check if the landscape name is unique
1724
        QTemporaryFile tempLandscapeIni("landscapeXXXXXX.ini");
×
1725
        if (tempLandscapeIni.open())
×
1726
        {
1727
                QByteArray iniData = reader.fileData(iniPath);
×
1728
                tempLandscapeIni.write(iniData);
×
1729
                tempLandscapeIni.close();
×
1730
                QSettings confLandscapeIni(tempLandscapeIni.fileName(), StelIniFormat);
×
1731
                QString landscapeName = confLandscapeIni.value("landscape/name").toString();
×
1732
                if (getAllLandscapeNames().contains(landscapeName))
×
1733
                {
1734
                        qWarning() << "LandscapeMgr: Unable to install landscape. There is already a landscape named" << landscapeName;
×
1735
                        emit errorNotUnique(landscapeName);
×
1736
                        return QString();
×
1737
                }
1738
        }
×
1739

1740
        //Copy the landscape directory to the target
1741
        //This case already has been handled - and commented out - above. :)
1742
        if(destinationDir.exists(landscapeID))
×
1743
        {
1744
                qWarning() << "LandscapeMgr: A subdirectory" << landscapeID << "already exists in" << QDir::toNativeSeparators(destinationDir.absolutePath()) << "Its contents may be overwritten.";
×
1745
        }
1746
        else if(!destinationDir.mkdir(landscapeID))
×
1747
        {
1748
                qWarning() << "LandscapeMgr: Unable to install landscape. Unable to create" << landscapeID << "directory in" << QDir::toNativeSeparators(destinationDir.absolutePath());
×
1749
                emit errorUnableToOpen(QDir::cleanPath(destinationDir.filePath(landscapeID)));
×
1750
                return QString();
×
1751
        }
1752
        destinationDir.cd(landscapeID);
×
1753
        for (const auto& info : infoList)
×
1754
        {
1755
                QFileInfo fileInfo(info.filePath);
×
1756
                if (info.isFile && fileInfo.dir().path() == topDir)
×
1757
                {
1758
                        QByteArray data = reader.fileData(info.filePath);
×
1759
                        QFile out(destinationDir.filePath(fileInfo.fileName()));
×
1760
                        if (out.open(QIODevice::WriteOnly))
×
1761
                        {
1762
                                out.write(data);
×
1763
                                out.close();
×
1764
                        }
1765
                        else
1766
                        {
1767
                                qWarning() << "LandscapeMgr: cannot open " << QDir::toNativeSeparators(fileInfo.absoluteFilePath());
×
1768
                        }
1769
                }
×
1770
        }
×
1771
        reader.close();
×
1772
        //If necessary, make the new landscape the current landscape
1773
        if (display)
×
1774
        {
1775
                setCurrentLandscapeID(landscapeID);
×
1776
        }
1777

1778
        //Make sure that everyone knows that the list of available landscapes has changed
1779
        emit landscapesChanged();
×
1780

1781
        qDebug() << "LandscapeMgr: Successfully installed landscape directory" << landscapeID << "to" << QDir::toNativeSeparators(destinationDir.absolutePath());
×
1782
        return landscapeID;
×
1783
}
×
1784

1785
bool LandscapeMgr::removeLandscape(const QString landscapeID)
×
1786
{
1787
        if (landscapeID.isEmpty())
×
1788
        {
1789
                qWarning() << "LandscapeMgr: Error! No landscape ID passed to removeLandscape().";
×
1790
                return false;
×
1791
        }
1792

1793
        if (packagedLandscapeIDs.contains(landscapeID))
×
1794
        {
1795
                qWarning() << "LandscapeMgr: Landscapes that are part of the default installation cannot be removed.";
×
1796
                return false;
×
1797
        }
1798

1799
        qDebug() << "LandscapeMgr: Trying to remove landscape" << landscapeID;
×
1800

1801
        QString landscapePath = getLandscapePath(landscapeID);
×
1802
        if (landscapePath.isEmpty())
×
1803
                return false;
×
1804

1805
        QDir landscapeDir(landscapePath);
×
1806
        for (auto &fileName : landscapeDir.entryList(QDir::Files | QDir::NoDotAndDotDot))
×
1807
        {
1808
                if(!landscapeDir.remove(fileName))
×
1809
                {
1810
                        qWarning() << "LandscapeMgr: Unable to remove" << QDir::toNativeSeparators(fileName);
×
1811
                        emit errorRemoveManually(landscapeDir.absolutePath());
×
1812
                        return false;
×
1813
                }
1814
        }
×
1815
        landscapeDir.cdUp();
×
1816
        if(!landscapeDir.rmdir(landscapeID))
×
1817
        {
1818
                qWarning() << "LandscapeMgr: Error! Landscape" << landscapeID
×
1819
                                   << "could not be removed. "
×
1820
                                   << "Some files were deleted, but not all."
×
1821
                                   << StelUtils::getEndLineChar()
×
1822
                                   << "LandscapeMgr: You can delete manually" << QDir::cleanPath(landscapeDir.filePath(landscapeID));
×
1823
                emit errorRemoveManually(QDir::cleanPath(landscapeDir.filePath(landscapeID)));
×
1824
                return false;
×
1825
        }
1826

1827
        qDebug() << "LandscapeMgr: Successfully removed" << QDir::toNativeSeparators(landscapePath);
×
1828

1829
        //If the landscape has been selected, revert to the default one
1830
        //TODO: Make this optional?
1831
        if (getCurrentLandscapeID() == landscapeID)
×
1832
        {
1833
                if(getDefaultLandscapeID() == landscapeID)
×
1834
                {
1835
                        setDefaultLandscapeID(packagedLandscapeIDs.first());
×
1836
                        //TODO: Find what happens if a missing landscape is specified in the configuration file
1837
                }
1838

1839
                setCurrentLandscapeID(getDefaultLandscapeID());
×
1840
        }
1841

1842
        //Make sure that everyone knows that the list of available landscapes has changed
1843
        emit landscapesChanged();
×
1844

1845
        return true;
×
1846
}
×
1847

1848
QString LandscapeMgr::getLandscapePath(const QString landscapeID)
×
1849
{
1850
        QString result;
×
1851
        //Is this necessary? This function is private.
1852
        if (landscapeID.isEmpty())
×
1853
                return result;
×
1854

1855
        result = StelFileMgr::findFile("landscapes/" + landscapeID, StelFileMgr::Directory);
×
1856
        if (result.isEmpty())
×
1857
        {
1858
                qWarning() << "LandscapeMgr: Error! Unable to find" << landscapeID;
×
1859
                return result;
×
1860
        }
1861

1862
        return result;
×
1863
}
×
1864

1865
QString LandscapeMgr::loadLandscapeName(const QString landscapeID)
×
1866
{
1867
        QString landscapeName;
×
1868
        if (landscapeID.isEmpty())
×
1869
        {
1870
                qWarning() << "LandscapeMgr: Error! No landscape ID passed to loadLandscapeName().";
×
1871
                return landscapeName;
×
1872
        }
1873

1874
        QString landscapePath = getLandscapePath(landscapeID);
×
1875
        if (landscapePath.isEmpty())
×
1876
                return landscapeName;
×
1877

1878
        QDir landscapeDir(landscapePath);
×
1879
        if (landscapeDir.exists("landscape.ini"))
×
1880
        {
1881
                QString landscapeSettingsPath = landscapeDir.filePath("landscape.ini");
×
1882
                QSettings landscapeSettings(landscapeSettingsPath, StelIniFormat);
×
1883
                landscapeName = landscapeSettings.value("landscape/name").toString();
×
1884
        }
×
1885
        else
1886
        {
1887
                qWarning() << "LandscapeMgr: Error! Landscape directory" << QDir::toNativeSeparators(landscapePath) << "does not contain a 'landscape.ini' file";
×
1888
        }
1889

1890
        return landscapeName;
×
1891
}
×
1892

1893
quint64 LandscapeMgr::loadLandscapeSize(const QString landscapeID) const
×
1894
{
1895
        quint64 landscapeSize = 0;
×
1896
        if (landscapeID.isEmpty())
×
1897
        {
1898
                qWarning() << "LandscapeMgr: Error! No landscape ID passed to loadLandscapeSize().";
×
1899
                return landscapeSize;
×
1900
        }
1901

1902
        QString landscapePath = getLandscapePath(landscapeID);
×
1903
        if (landscapePath.isEmpty())
×
1904
                return landscapeSize;
×
1905

1906
        const QDir landscapeDir(landscapePath);
×
1907
        for (auto &file : landscapeDir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot))
×
1908
        {
1909
                //qDebug() << "name:" << file.baseName() << "size:" << file.size();
1910
                landscapeSize += static_cast<quint64>(file.size());
×
1911
        }
×
1912

1913
        return landscapeSize;
×
1914
}
×
1915

1916
QString LandscapeMgr::getDescription() const
×
1917
{
1918
        QString lang, desc, descFile, locDescriptionFile, engDescriptionFile;
×
1919
        bool hasFile = true;
×
1920

1921
        lang = StelApp::getInstance().getLocaleMgr().getAppLanguage();
×
1922
        locDescriptionFile = StelFileMgr::findFile("landscapes/" + getCurrentLandscapeID(), StelFileMgr::Directory) + "/description." + lang + ".utf8";
×
1923
        engDescriptionFile = StelFileMgr::findFile("landscapes/" + getCurrentLandscapeID(), StelFileMgr::Directory) + "/description.en.utf8";
×
1924

1925
        // OK. Check the file with full name of locale
1926
        if (!QFileInfo::exists(locDescriptionFile))
×
1927
        {
1928
                // Oops...  File not exists! What about short name of locale?
1929
                lang = lang.split("_").at(0);
×
1930
                locDescriptionFile = StelFileMgr::findFile("landscapes/" + getCurrentLandscapeID(), StelFileMgr::Directory) + "/description." + lang + ".utf8";
×
1931
        }
1932

1933
        // Check localized description for landscape
1934
        if (!locDescriptionFile.isEmpty() && QFileInfo::exists(locDescriptionFile))
×
1935
        {                
1936
                descFile = locDescriptionFile;
×
1937
        }
1938
        // OK. Localized description of landscape not exists. What about english description of its?
1939
        else if (!engDescriptionFile.isEmpty() && QFileInfo::exists(engDescriptionFile))
×
1940
        {
1941
                descFile = engDescriptionFile;
×
1942
        }
1943
        // That file not exists too? OK. Will be used description from landscape.ini file.
1944
        else
1945
        {
1946
                hasFile = false;
×
1947
        }
1948

1949
        if (hasFile)
×
1950
        {
1951
                QFile file(descFile);
×
1952
                if(file.open(QIODevice::ReadOnly | QIODevice::Text))
×
1953
                {
1954
                        QTextStream in(&file);
×
1955
#if (QT_VERSION>=QT_VERSION_CHECK(6,0,0))
1956
                        in.setEncoding(QStringConverter::Utf8);
1957
#else
1958
                        in.setCodec("UTF-8");
×
1959
#endif
1960
                        desc = in.readAll();
×
1961
                        file.close();
×
1962
                }
×
1963
        }
×
1964
        else
1965
        {
1966
                desc = QString("<h2>%1</h2>").arg(q_(landscape->getName()));
×
1967
                desc += landscape->getDescription();
×
1968
        }
1969

1970
        return desc;
×
1971
}
×
1972

1973
void LandscapeMgr::increaseLightPollution()
×
1974
{
1975
        StelCore* core = StelApp::getInstance().getCore();
×
1976
        const auto lum = core->getSkyDrawer()->getLightPollutionLuminance();
×
1977
        auto bidx = core->luminanceToBortleScaleIndex(lum) + 1;
×
1978
        if (bidx>9)
×
1979
                bidx = 9;
×
1980
        const auto newLum = core->bortleScaleIndexToLuminance(bidx);
×
1981
        core->getSkyDrawer()->setLightPollutionLuminance(newLum);
×
1982
}
×
1983

1984
void LandscapeMgr::reduceLightPollution()
×
1985
{
1986
        StelCore* core = StelApp::getInstance().getCore();
×
1987
        const auto lum = core->getSkyDrawer()->getLightPollutionLuminance();
×
1988
        auto bidx = core->luminanceToBortleScaleIndex(lum) - 1;
×
1989
        if (bidx<1)
×
1990
                bidx = 1;
×
1991
        const auto newLum = core->bortleScaleIndexToLuminance(bidx);
×
1992
        core->getSkyDrawer()->setLightPollutionLuminance(newLum);
×
1993
}
×
1994

1995
void LandscapeMgr::cyclicChangeLightPollution()
×
1996
{
1997
        StelCore* core = StelApp::getInstance().getCore();
×
1998
        const auto lum = core->getSkyDrawer()->getLightPollutionLuminance();
×
1999
        auto bidx = core->luminanceToBortleScaleIndex(lum) + 1;
×
2000
        if (bidx>9)
×
2001
                bidx = 1;
×
2002
        const auto newLum = core->bortleScaleIndexToLuminance(bidx);
×
2003
        core->getSkyDrawer()->setLightPollutionLuminance(newLum);
×
2004
}
×
2005

2006
/*
2007
// GZ: Addition to identify landscape transparency. Used for development and debugging only, should be commented out in release builds.
2008
// Also, StelMovementMgr l.382 event->accept() must be commented out for this here to work!
2009
void LandscapeMgr::handleMouseClicks(QMouseEvent *event)
2010
{
2011
        switch (event->button())
2012
        {
2013
        case Qt::LeftButton :
2014
                if (event->type()==QEvent::MouseButtonRelease)
2015
                {
2016
                        Vec3d v;
2017
                        StelApp::getInstance().getCore()->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff)->unProject(event->x(),event->y(),v);
2018
                        v.normalize();
2019
                        float trans=landscape->getOpacity(v);
2020
                        qDebug() << "Landscape opacity at screen X=" << event->x() << ", Y=" << event->y() << ": " << trans;
2021
                }
2022
                break;
2023
        default: break;
2024

2025
        }
2026
        // do not event->accept(), so that it is forwarded to other modules.
2027
        return;
2028
}
2029
*/
2030

2031
void LandscapeMgr::showMessage(const QString& message)
×
2032
{
2033
        messageToShow=message;
×
2034
        messageFader=true;
×
2035
        messageTimer->start();
×
2036
}
×
2037

2038
void LandscapeMgr::clearMessage()
×
2039
{
2040
        messageFader = false;
×
2041
}
×
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