1 /*
2  * Stellarium
3  * Copyright (C) 2009 Matthew Gates
4  * Copyright (C) 2007 Fabien Chereau
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA  02110-1335, USA.
19  */
20 
21 #include "StelMainScriptAPI.hpp"
22 #include "StelMainScriptAPIProxy.hpp"
23 #include "StelScriptMgr.hpp"
24 #include "StelLocaleMgr.hpp"
25 
26 #include "ConstellationMgr.hpp"
27 #include "AsterismMgr.hpp"
28 #include "GridLinesMgr.hpp"
29 #include "LandscapeMgr.hpp"
30 #include "SporadicMeteorMgr.hpp"
31 #include "NebulaMgr.hpp"
32 #include "Planet.hpp"
33 #include "SolarSystem.hpp"
34 #include "StarMgr.hpp"
35 #include "StelApp.hpp"
36 #include "StelAudioMgr.hpp"
37 #include "StelVideoMgr.hpp"
38 #include "StelCore.hpp"
39 #include "StelFileMgr.hpp"
40 #include "StelLocation.hpp"
41 #include "StelLocationMgr.hpp"
42 #include "StelMainView.hpp"
43 #include "StelModuleMgr.hpp"
44 #include "StelMovementMgr.hpp"
45 #include "StelPropertyMgr.hpp"
46 #include "StelScriptMgr.hpp"
47 
48 #include "StelObject.hpp"
49 #include "StelObjectMgr.hpp"
50 #include "StelProjector.hpp"
51 #include "StelSkyCultureMgr.hpp"
52 #include "StelSkyDrawer.hpp"
53 #include "StelSkyLayerMgr.hpp"
54 #include "StelUtils.hpp"
55 #include "StelGuiBase.hpp"
56 #include "MilkyWay.hpp"
57 #include "ZodiacalLight.hpp"
58 #include "ToastMgr.hpp"
59 
60 #include <QDateTime>
61 #include <QDebug>
62 #include <QDir>
63 #include <QFile>
64 #include <QFileInfo>
65 #include <QRegularExpression>
66 #include <QSet>
67 #include <QStringList>
68 #include <QTemporaryFile>
69 #include <QTimer>
70 #include <QEventLoop>
71 
72 #include <cmath>
73 
StelMainScriptAPI(QObject * parent)74 StelMainScriptAPI::StelMainScriptAPI(QObject *parent) : QObject(parent)
75 {
76 	if(StelSkyLayerMgr* smgr = GETSTELMODULE(StelSkyLayerMgr))
77 	{
78 		connect(this, SIGNAL(requestLoadSkyImage(const QString&, const QString&, double, double, double, double, double, double, double, double, double, double, bool, StelCore::FrameType, bool)),
79 			smgr, SLOT(         loadSkyImage(const QString&, const QString&, double, double, double, double, double, double, double, double, double, double, bool, StelCore::FrameType, bool)));
80 		connect(this, SIGNAL(requestRemoveSkyImage(const QString&)), smgr, SLOT(removeSkyLayer(const QString&)));
81 	}
82 
83 	connect(this, SIGNAL(requestLoadSound(const QString&, const QString&)), StelApp::getInstance().getStelAudioMgr(), SLOT(loadSound(const QString&, const QString&)));
84 	connect(this, SIGNAL(requestPlaySound(const QString&)), StelApp::getInstance().getStelAudioMgr(), SLOT(playSound(const QString&)));
85 	connect(this, SIGNAL(requestPauseSound(const QString&)), StelApp::getInstance().getStelAudioMgr(), SLOT(pauseSound(const QString&)));
86 	connect(this, SIGNAL(requestStopSound(const QString&)), StelApp::getInstance().getStelAudioMgr(), SLOT(stopSound(const QString&)));
87 	connect(this, SIGNAL(requestDropSound(const QString&)), StelApp::getInstance().getStelAudioMgr(), SLOT(dropSound(const QString&)));
88 
89 	connect(this, SIGNAL(requestLoadVideo(const QString&, const QString&, float, float, bool, float)), StelApp::getInstance().getStelVideoMgr(), SLOT(loadVideo(const QString&, const QString&, float, float, bool, float)));
90 	connect(this, SIGNAL(requestPlayVideo(const QString&, const bool)), StelApp::getInstance().getStelVideoMgr(), SLOT(playVideo(const QString&, const bool)));
91 	connect(this, SIGNAL(requestPlayVideoPopout(QString,float,float,float,float,float,float,float,bool)), StelApp::getInstance().getStelVideoMgr(), SLOT(playVideoPopout(QString,float,float,float,float,float,float,float,bool)));
92 	connect(this, SIGNAL(requestPauseVideo(const QString&)), StelApp::getInstance().getStelVideoMgr(), SLOT(pauseVideo(const QString&)));
93 	connect(this, SIGNAL(requestStopVideo(const QString&)), StelApp::getInstance().getStelVideoMgr(), SLOT(stopVideo(const QString&)));
94 	connect(this, SIGNAL(requestDropVideo(const QString&)), StelApp::getInstance().getStelVideoMgr(), SLOT(dropVideo(const QString&)));
95 	connect(this, SIGNAL(requestSeekVideo(const QString&, qint64, bool)), StelApp::getInstance().getStelVideoMgr(), SLOT(seekVideo(const QString&, qint64, bool)));
96 	connect(this, SIGNAL(requestSetVideoXY(const QString&, float, float, bool)), StelApp::getInstance().getStelVideoMgr(), SLOT(setVideoXY(const QString&, float, float, bool)));
97 	connect(this, SIGNAL(requestSetVideoAlpha(const QString&, float)), StelApp::getInstance().getStelVideoMgr(), SLOT(setVideoAlpha(const QString&, float)));
98 	connect(this, SIGNAL(requestResizeVideo(const QString&, float, float)), StelApp::getInstance().getStelVideoMgr(), SLOT(resizeVideo(const QString&, float, float)));
99 	connect(this, SIGNAL(requestShowVideo(const QString&, bool)), StelApp::getInstance().getStelVideoMgr(), SLOT(showVideo(const QString&, bool)));
100 
101 	connect(this, SIGNAL(requestExit()), this->parent(), SLOT(stopScript()));
102 	connect(this, SIGNAL(requestSetProjectionMode(QString)), StelApp::getInstance().getCore(), SLOT(setCurrentProjectionTypeKey(QString)));
103 	connect(this, SIGNAL(requestSetSkyCulture(QString)), &StelApp::getInstance().getSkyCultureMgr(), SLOT(setCurrentSkyCultureID(QString)));
104 	connect(this, SIGNAL(requestSetDiskViewport(bool)), StelApp::getInstance().getMainScriptAPIProxy(), SLOT(setDiskViewport(bool)));
105 	connect(this, SIGNAL(requestSetHomePosition()), StelApp::getInstance().getCore(), SLOT(returnToHome()));
106 }
107 
~StelMainScriptAPI()108 StelMainScriptAPI::~StelMainScriptAPI()
109 {
110 }
111 
112 //! Set the current date in Julian Day
113 //! @param JD the Julian Date (UT)
setJDay(double JD)114 void StelMainScriptAPI::setJDay(double JD)
115 {
116 	StelApp::getInstance().getCore()->setJD(JD);
117 }
118 
119 //! Get the current date in Julian Day
120 //! @return the Julian Date (UT)
getJDay()121 double StelMainScriptAPI::getJDay()
122 {
123 	return StelApp::getInstance().getCore()->getJD();
124 }
125 
126 //! Set the current date in Modified Julian Day
127 //! @param MJD the Modified Julian Date
setMJDay(double MJD)128 void StelMainScriptAPI::setMJDay(double MJD)
129 {
130 	StelApp::getInstance().getCore()->setMJDay(MJD);
131 }
132 
133 //! Get the current date in Modified Julian Day
134 //! @return the Modified Julian Date
getMJDay()135 double StelMainScriptAPI::getMJDay()
136 {
137 	return StelApp::getInstance().getCore()->getMJDay();
138 }
139 
setDate(const QString & dateStr,const QString & spec,const bool & dateIsDT)140 void StelMainScriptAPI::setDate(const QString& dateStr, const QString& spec, const bool &dateIsDT)
141 {
142 	StelCore* core = StelApp::getInstance().getCore();
143 	double JD = jdFromDateString(dateStr, spec);
144 	if (dateIsDT)
145 		core->setJDE(JD);
146 	else
147 		core->setJD(JD);
148 }
149 
getDate(const QString & spec)150 QString StelMainScriptAPI::getDate(const QString& spec)
151 {
152 	if (spec=="utc")
153 		return StelUtils::julianDayToISO8601String(getJDay());
154 	else
155 		return StelUtils::julianDayToISO8601String(getJDay()+static_cast<double>(StelApp::getInstance().getCore()->getUTCOffset(getJDay()))/24);
156 }
157 
getDeltaT()158 QString StelMainScriptAPI::getDeltaT()
159 {
160 	return StelUtils::hoursToHmsStr(StelApp::getInstance().getCore()->getDeltaT()/3600.);
161 }
162 
getDeltaTsec()163 double StelMainScriptAPI::getDeltaTsec()
164 {
165 	return StelApp::getInstance().getCore()->getDeltaT();
166 }
167 
getDeltaTAlgorithm()168 QString StelMainScriptAPI::getDeltaTAlgorithm()
169 {
170 	return StelApp::getInstance().getCore()->getCurrentDeltaTAlgorithmKey();
171 }
172 
setDeltaTAlgorithm(QString algorithmName)173 void StelMainScriptAPI::setDeltaTAlgorithm(QString algorithmName)
174 {
175 	StelApp::getInstance().getCore()->setCurrentDeltaTAlgorithmKey(algorithmName);
176 }
177 
178 //! Set time speed in JDay/sec
179 //! @param ts time speed in JDay/sec
setTimeRate(double ts)180 void StelMainScriptAPI::setTimeRate(double ts)
181 {
182 	// 1 second = .00001157407407407407 JDay
183 	StelApp::getInstance().getCore()->setTimeRate(ts * 0.00001157407407407407 * StelApp::getInstance().getScriptMgr().getScriptRate());
184 }
185 
186 //! Get time speed in JDay/sec
187 //! @return time speed in JDay/sec
getTimeRate()188 double StelMainScriptAPI::getTimeRate()
189 {
190 	return StelApp::getInstance().getCore()->getTimeRate() / (0.00001157407407407407 * StelApp::getInstance().getScriptMgr().getScriptRate());
191 }
192 
isRealTime()193 bool StelMainScriptAPI::isRealTime()
194 {
195 	return StelApp::getInstance().getCore()->getIsTimeNow();
196 }
197 
setRealTime()198 void StelMainScriptAPI::setRealTime()
199 {
200 	setTimeRate(1.0);
201 	StelApp::getInstance().getCore()->setTimeNow();
202 }
203 
isPlanetocentricCalculations()204 bool StelMainScriptAPI::isPlanetocentricCalculations()
205 {
206 	return !(StelApp::getInstance().getCore()->getUseTopocentricCoordinates());
207 }
208 
setPlanetocentricCalculations(bool f)209 void StelMainScriptAPI::setPlanetocentricCalculations(bool f)
210 {
211 	StelApp::getInstance().getCore()->setUseTopocentricCoordinates(!f);
212 }
213 
setObserverLocation(double longitude,double latitude,double altitude,double duration,const QString & name,const QString & planet)214 void StelMainScriptAPI::setObserverLocation(double longitude, double latitude, double altitude, double duration, const QString& name, const QString& planet)
215 {
216 	StelCore* core = StelApp::getInstance().getCore();
217 	StelLocation loc = core->getCurrentLocation();
218 	loc.longitude = static_cast<float>(longitude);
219 	loc.latitude = static_cast<float>(latitude);
220 	if (altitude > -1000)
221 		loc.altitude = qRound(altitude);
222 	if (!planet.isEmpty())
223 	{
224 		// backward compatible layer: probably we have Solar system body...
225 		PlanetP ssObj = GETSTELMODULE(SolarSystem)->searchByEnglishName(planet);
226 		if (!ssObj.isNull())
227 			loc.planetName = ssObj->getEnglishName();
228 	}
229 
230 	QRegularExpression cico( "^\\s*([^,]+),\\s*(\\S.*)$" );
231 	QRegularExpressionMatch match=cico.match(name);
232 	if( match.hasMatch() )
233 	{
234 		loc.name = match.captured(1);
235 		loc.region = match.captured(2);
236 	}
237 	else
238 		loc.name = name;
239 
240 	core->moveObserverTo(loc, duration, duration);
241 }
242 
setObserverLocation(const QString & id,double duration)243 void StelMainScriptAPI::setObserverLocation(const QString &id, double duration)
244 {
245 	StelCore* core = StelApp::getInstance().getCore();
246 	StelLocation loc = StelApp::getInstance().getLocationMgr().locationForString(id);
247 	if (!loc.isValid())
248 		return;	// location find failed
249 	core->moveObserverTo(loc, duration);
250 }
251 
getObserverLocation()252 QString StelMainScriptAPI::getObserverLocation()
253 {
254 	return StelApp::getInstance().getCore()->getCurrentLocation().getID();
255 }
256 
getObserverLocationInfo()257 QVariantMap StelMainScriptAPI::getObserverLocationInfo()
258 {
259 	StelCore* core = StelApp::getInstance().getCore();
260 	const PlanetP& planet = core->getCurrentPlanet();
261 	QString planetName = core->getCurrentLocation().planetName;
262 	QVariantMap map;
263 	map.insert("longitude", core->getCurrentLocation().longitude);
264 	map.insert("latitude", core->getCurrentLocation().latitude);
265 	map.insert("planet", planetName);
266 	map.insert("altitude", core->getCurrentLocation().altitude);
267 	map.insert("location", core->getCurrentLocation().getID());
268 	// extra data
269 	map.insert("sidereal-year", planet->getSiderealPeriod());
270 	map.insert("sidereal-day", planet->getSiderealDay()*24.);
271 	map.insert("solar-day", planet->getMeanSolarDay()*24.);
272 	unsigned int h, m;
273 	double s;
274 	StelUtils::radToHms(core->getLocalSiderealTime(), h, m, s);
275 	map.insert("local-sidereal-time", static_cast<double>(h) + static_cast<double>(m)/60. + s/3600);
276 	map.insert("local-sidereal-time-hms", StelUtils::radToHmsStr(core->getLocalSiderealTime()));
277 	map.insert("location-timezone", core->getCurrentLocation().ianaTimeZone);
278 	map.insert("timezone", core->getCurrentTimeZone());
279 
280 	return map;
281 }
282 
setTimezone(QString tz,int markAsCustom)283 void StelMainScriptAPI::setTimezone(QString tz, int markAsCustom)
284 {
285 	StelCore* core = StelApp::getInstance().getCore();
286 	core->setCurrentTimeZone(tz);
287 	switch (markAsCustom){
288 		case 0: // and
289 		case 1:	core->setUseCustomTimeZone(static_cast<bool>(markAsCustom));
290 			break;
291 		default: break;
292 	}
293 }
294 
getAllTimezoneNames()295 QStringList StelMainScriptAPI::getAllTimezoneNames()
296 {
297 	return StelApp::getInstance().getLocationMgr().getAllTimezoneNames();
298 }
299 
screenshot(const QString & prefix,bool invert,const QString & dir,const bool overwrite,const QString & format)300 void StelMainScriptAPI::screenshot(const QString& prefix, bool invert, const QString& dir, const bool overwrite, const QString &format)
301 {
302 	bool oldInvertSetting = StelMainView::getInstance().getFlagInvertScreenShotColors();
303 	QString oldFormat=StelMainView::getInstance().getScreenshotFormat();
304 	StelMainView::getInstance().setFlagInvertScreenShotColors(invert);
305 	if ((format.length()>0) && (format.length()<=4))
306 		StelMainView::getInstance().setScreenshotFormat(format);
307 	StelMainView::getInstance().setFlagOverwriteScreenShots(overwrite);
308 	StelMainView::getInstance().saveScreenShot(prefix, dir, overwrite);
309 	StelMainView::getInstance().setFlagInvertScreenShotColors(oldInvertSetting);
310 	StelMainView::getInstance().setScreenshotFormat(oldFormat);
311 }
312 
setGuiVisible(bool b)313 void StelMainScriptAPI::setGuiVisible(bool b)
314 {
315 	StelApp::getInstance().getGui()->setVisible(b);
316 }
317 
setMinFps(float m)318 void StelMainScriptAPI::setMinFps(float m)
319 {
320 	StelMainView::getInstance().setMinFps(m);
321 }
322 
getMinFps()323 float StelMainScriptAPI::getMinFps()
324 {
325 	return StelMainView::getInstance().getMinFps();
326 }
327 
setMaxFps(float m)328 void StelMainScriptAPI::setMaxFps(float m)
329 {
330 	StelMainView::getInstance().setMaxFps(m);
331 }
332 
getMaxFps()333 float StelMainScriptAPI::getMaxFps()
334 {
335 	return StelMainView::getInstance().getMaxFps();
336 }
337 
getMountMode()338 QString StelMainScriptAPI::getMountMode()
339 {
340 	if (GETSTELMODULE(StelMovementMgr)->getMountMode() == StelMovementMgr::MountEquinoxEquatorial)
341 		return "equatorial";
342 	else
343 		return "azimuthal";
344 }
345 
setMountMode(const QString & mode)346 void StelMainScriptAPI::setMountMode(const QString& mode)
347 {
348 	if (mode=="equatorial")
349 		GETSTELMODULE(StelMovementMgr)->setMountMode(StelMovementMgr::MountEquinoxEquatorial);
350 	else if (mode=="azimuthal")
351 		GETSTELMODULE(StelMovementMgr)->setMountMode(StelMovementMgr::MountAltAzimuthal);
352 }
353 
getNightMode()354 bool StelMainScriptAPI::getNightMode()
355 {
356 	return StelApp::getInstance().getVisionModeNight();
357 }
358 
setNightMode(bool b)359 void StelMainScriptAPI::setNightMode(bool b)
360 {
361 	StelApp::getInstance().setVisionModeNight(b);
362 }
363 
getProjectionMode()364 QString StelMainScriptAPI::getProjectionMode()
365 {
366 	return StelApp::getInstance().getCore()->getCurrentProjectionTypeKey();
367 }
368 
setProjectionMode(const QString & id)369 void StelMainScriptAPI::setProjectionMode(const QString& id)
370 {
371 	emit(requestSetProjectionMode(id));
372 }
373 
getAllSkyCultureIDs()374 QStringList StelMainScriptAPI::getAllSkyCultureIDs()
375 {
376 	return StelApp::getInstance().getSkyCultureMgr().getSkyCultureListIDs();
377 }
378 
getSkyCulture()379 QString StelMainScriptAPI::getSkyCulture()
380 {
381 	return StelApp::getInstance().getSkyCultureMgr().getCurrentSkyCultureID();
382 }
383 
setSkyCulture(const QString & id)384 void StelMainScriptAPI::setSkyCulture(const QString& id)
385 {
386 	GETSTELMODULE(StelObjectMgr)->unSelect(); // mistake-proofing!
387 	emit(requestSetSkyCulture(id));
388 }
389 
getSkyCultureName()390 QString StelMainScriptAPI::getSkyCultureName()
391 {
392 	return StelApp::getInstance().getSkyCultureMgr().getCurrentSkyCultureEnglishName();
393 }
394 
getSkyCultureNameI18n()395 QString StelMainScriptAPI::getSkyCultureNameI18n()
396 {
397 	return StelApp::getInstance().getSkyCultureMgr().getCurrentSkyCultureNameI18();
398 }
399 
getFlagGravityLabels()400 bool StelMainScriptAPI::getFlagGravityLabels()
401 {
402 	return StelApp::getInstance().getCore()->getProjection(StelCore::FrameJ2000)->getFlagGravityLabels();
403 }
404 
setFlagGravityLabels(bool b)405 void StelMainScriptAPI::setFlagGravityLabels(bool b)
406 {
407 	StelApp::getInstance().getCore()->setFlagGravityLabels(b);
408 }
409 
getFlipHorz()410 bool StelMainScriptAPI::getFlipHorz()
411 {
412 	return StelApp::getInstance().getCore()->getFlipHorz();
413 }
414 
setFlipHorz(bool b)415 void StelMainScriptAPI::setFlipHorz(bool b)
416 {
417 	StelApp::getInstance().getCore()->setFlipHorz(b);
418 }
419 
getFlipVert()420 bool StelMainScriptAPI::getFlipVert()
421 {
422 	return StelApp::getInstance().getCore()->getFlipVert();
423 }
424 
setFlipVert(bool b)425 void StelMainScriptAPI::setFlipVert(bool b)
426 {
427 	StelApp::getInstance().getCore()->setFlipVert(b);
428 }
429 
getDiskViewport()430 bool StelMainScriptAPI::getDiskViewport()
431 {
432 	return StelApp::getInstance().getCore()->getProjection(StelCore::FrameJ2000)->getMaskType() == StelProjector::MaskDisk;
433 }
434 
setSphericMirror(bool b)435 void StelMainScriptAPI::setSphericMirror(bool b)
436 {
437 	StelCore* core = StelApp::getInstance().getCore();
438 	if (b)
439 	{
440 		core->setCurrentProjectionType(StelCore::ProjectionFisheye);
441 		StelApp::getInstance().setViewportEffect("sphericMirrorDistorter");
442 	}
443 	else
444 	{
445 		core->setCurrentProjectionTypeKey(core->getDefaultProjectionTypeKey());
446 		StelApp::getInstance().setViewportEffect("none");
447 	}
448 }
449 
setDiskViewport(bool b)450 void StelMainScriptAPI::setDiskViewport(bool b)
451 {
452 	emit(requestSetDiskViewport(b));
453 }
454 
setViewportStretch(const float stretch)455 void StelMainScriptAPI::setViewportStretch(const float stretch)
456 {
457 	StelApp::getInstance().getCore()->setViewportStretch(stretch);
458 }
459 
loadSkyImage(const QString & id,const QString & filename,double lon0,double lat0,double lon1,double lat1,double lon2,double lat2,double lon3,double lat3,double minRes,double maxBright,bool visible,const QString & frame,bool withAberration)460 void StelMainScriptAPI::loadSkyImage(const QString& id, const QString& filename,
461 				     double lon0, double lat0,
462 				     double lon1, double lat1,
463 				     double lon2, double lat2,
464 				     double lon3, double lat3,
465 				     double minRes, double maxBright, bool visible, const QString &frame, bool withAberration)
466 {
467 	QString path = "scripts/" + filename;
468 	StelCore::FrameType frameType=StelCore::FrameJ2000;
469 	if (frame=="EqDate")
470 		frameType=StelCore::FrameEquinoxEqu;
471 	else if (frame=="EclJ2000")
472 		frameType=StelCore::FrameObservercentricEclipticJ2000;
473 	else if (frame=="EclDate")
474 		frameType=StelCore::FrameObservercentricEclipticOfDate;
475 	else if (frame.startsWith("Gal"))
476 		frameType=StelCore::FrameGalactic;
477 	else if (frame.startsWith("SuperG"))
478 		frameType=StelCore::FrameSupergalactic;
479 	else if (frame=="AzAlt")
480 		frameType=StelCore::FrameAltAz;
481 	else if (frame!="EqJ2000")
482 	{
483 		qDebug() << "StelMainScriptAPI::loadSkyImage(): unknown frame type " << frame << " requested -- Using Equatorial J2000";
484 	}
485 
486 	emit(requestLoadSkyImage(id, path, lon0, lat0, lon1, lat1, lon2, lat2, lon3, lat3, minRes, maxBright, visible, frameType, withAberration));
487 }
488 
489 // Convenience method:
loadSkyImage(const QString & id,const QString & filename,const QString & lon0,const QString & lat0,const QString & lon1,const QString & lat1,const QString & lon2,const QString & lat2,const QString & lon3,const QString & lat3,double minRes,double maxBright,bool visible,const QString & frame,bool withAberration)490 void StelMainScriptAPI::loadSkyImage(const QString& id, const QString& filename,
491 				     const QString& lon0, const QString& lat0,
492 				     const QString& lon1, const QString& lat1,
493 				     const QString& lon2, const QString& lat2,
494 				     const QString& lon3, const QString& lat3,
495 				     double minRes, double maxBright, bool visible, const QString& frame, bool withAberration)
496 {
497 	loadSkyImage(id, filename,
498 		     StelUtils::getDecAngle(lon0) *M_180_PI, StelUtils::getDecAngle(lat0)*M_180_PI,
499 		     StelUtils::getDecAngle(lon1) *M_180_PI, StelUtils::getDecAngle(lat1)*M_180_PI,
500 		     StelUtils::getDecAngle(lon2) *M_180_PI, StelUtils::getDecAngle(lat2)*M_180_PI,
501 		     StelUtils::getDecAngle(lon3) *M_180_PI, StelUtils::getDecAngle(lat3)*M_180_PI,
502 		     minRes, maxBright, visible, frame, withAberration);
503 }
504 
505 // Convenience method: (Fixed 2017-03: rotation increased by 90deg, makes upright images now!)
loadSkyImage(const QString & id,const QString & filename,double lon,double lat,double angSize,double rotation,double minRes,double maxBright,bool visible,const QString & frame,bool withAberration)506 void StelMainScriptAPI::loadSkyImage(const QString& id, const QString& filename,
507 				     double lon, double lat, double angSize, double rotation,
508 				     double minRes, double maxBright, bool visible, const QString &frame, bool withAberration)
509 {
510 	Vec3f XYZ;
511 	static const float RADIUS_NEB = 1.f;
512 	StelUtils::spheToRect(static_cast<float>(lon*M_PI_180), static_cast<float>(lat*M_PI_180), XYZ);
513 	XYZ*=RADIUS_NEB;
514 	float texSize = RADIUS_NEB * static_cast<float>(sin(angSize/2./60.*M_PI_180));
515 	Mat4f matPrecomp = Mat4f::translation(XYZ) *
516 			   Mat4f::zrotation(static_cast<float>(lon*M_PI_180)) *
517 			   Mat4f::yrotation(static_cast<float>(-lat*M_PI_180)) *
518 			   Mat4f::xrotation(static_cast<float>((rotation+90.0)*M_PI_180));
519 
520 	Vec3f corners[4];
521 	corners[0] = matPrecomp * Vec3f(0.f,-texSize,-texSize);
522 	corners[1] = matPrecomp * Vec3f(0.f,-texSize, texSize);
523 	corners[2] = matPrecomp * Vec3f(0.f, texSize,-texSize);
524 	corners[3] = matPrecomp * Vec3f(0.f, texSize, texSize);
525 
526 	// convert back to ra/dec (radians)
527 	Vec3f cornersRaDec[4];
528 	for(int i=0; i<4; i++)
529 		StelUtils::rectToSphe(&cornersRaDec[i][0], &cornersRaDec[i][1], corners[i]);
530 
531 	loadSkyImage(id, filename,
532 		     static_cast<double>(cornersRaDec[0][0])*(M_180_PI), static_cast<double>(cornersRaDec[0][1])*(M_180_PI),
533 		     static_cast<double>(cornersRaDec[1][0])*(M_180_PI), static_cast<double>(cornersRaDec[1][1])*(M_180_PI),
534 		     static_cast<double>(cornersRaDec[3][0])*(M_180_PI), static_cast<double>(cornersRaDec[3][1])*(M_180_PI),
535 		     static_cast<double>(cornersRaDec[2][0])*(M_180_PI), static_cast<double>(cornersRaDec[2][1])*(M_180_PI),
536 		     minRes, maxBright, visible, frame, withAberration);
537 }
538 
539 // Convenience method:
loadSkyImage(const QString & id,const QString & filename,const QString & lon,const QString & lat,double angSize,double rotation,double minRes,double maxBright,bool visible,const QString & frame,bool withAberration)540 void StelMainScriptAPI::loadSkyImage(const QString& id, const QString& filename,
541 				     const QString& lon, const QString& lat,
542 				     double angSize, double rotation,
543 				     double minRes, double maxBright, bool visible, const QString &frame, bool withAberration)
544 {
545 	loadSkyImage(id, filename, StelUtils::getDecAngle(lon)*M_180_PI,
546 		     StelUtils::getDecAngle(lat)*M_180_PI, angSize,
547 		     rotation, minRes, maxBright, visible, frame, withAberration);
548 }
549 
removeSkyImage(const QString & id)550 void StelMainScriptAPI::removeSkyImage(const QString& id)
551 {
552 	emit(requestRemoveSkyImage(id));
553 }
554 
loadSound(const QString & filename,const QString & id)555 void StelMainScriptAPI::loadSound(const QString& filename, const QString& id)
556 {
557 	QString path = StelFileMgr::findFile("scripts/" + filename);
558 	if (path.isEmpty())
559 	{
560 		qWarning() << "cannot play sound" << QDir::toNativeSeparators(filename);
561 		return;
562 	}
563 
564 	emit(requestLoadSound(path, id));
565 }
566 
playSound(const QString & id)567 void StelMainScriptAPI::playSound(const QString& id)
568 {
569 	emit(requestPlaySound(id));
570 }
571 
pauseSound(const QString & id)572 void StelMainScriptAPI::pauseSound(const QString& id)
573 {
574 	emit(requestPauseSound(id));
575 }
576 
stopSound(const QString & id)577 void StelMainScriptAPI::stopSound(const QString& id)
578 {
579 	emit(requestStopSound(id));
580 }
581 
dropSound(const QString & id)582 void StelMainScriptAPI::dropSound(const QString& id)
583 {
584 	emit(requestDropSound(id));
585 }
586 
getSoundPosition(const QString & id)587 qint64 StelMainScriptAPI::getSoundPosition(const QString& id)
588 {
589 	return StelApp::getInstance().getStelAudioMgr()->position(id);
590 }
591 
getSoundDuration(const QString & id)592 qint64 StelMainScriptAPI::getSoundDuration(const QString& id)
593 {
594 	return StelApp::getInstance().getStelAudioMgr()->duration(id);
595 }
596 
loadVideo(const QString & filename,const QString & id,float x,float y,bool show,float alpha)597 void StelMainScriptAPI::loadVideo(const QString& filename, const QString& id, float x, float y, bool show, float alpha)
598 {
599 	QString path = StelFileMgr::findFile("scripts/" + filename);
600 	if (path.isEmpty())
601 	{
602 		qWarning() << "cannot play video" << QDir::toNativeSeparators(filename);
603 		return;
604 	}
605 
606 	emit(requestLoadVideo(path, id, x, y, show, alpha));
607 }
608 
playVideo(const QString & id,bool keepVisibleAtEnd)609 void StelMainScriptAPI::playVideo(const QString& id, bool keepVisibleAtEnd)
610 {
611 	emit(requestPlayVideo(id, keepVisibleAtEnd));
612 }
613 
playVideoPopout(const QString & id,float fromX,float fromY,float atCenterX,float atCenterY,float finalSizeX,float finalSizeY,float popupDuration,bool frozenInTransition)614 void StelMainScriptAPI::playVideoPopout(const QString& id, float fromX, float fromY, float atCenterX, float atCenterY, float finalSizeX, float finalSizeY, float popupDuration, bool frozenInTransition)
615 {
616 	emit(requestPlayVideoPopout(id, fromX, fromY, atCenterX, atCenterY, finalSizeX, finalSizeY, popupDuration, frozenInTransition));
617 }
618 
pauseVideo(const QString & id)619 void StelMainScriptAPI::pauseVideo(const QString& id)
620 {
621 	emit(requestPauseVideo(id));
622 }
623 
stopVideo(const QString & id)624 void StelMainScriptAPI::stopVideo(const QString& id)
625 {
626 	emit(requestStopVideo(id));
627 }
628 
dropVideo(const QString & id)629 void StelMainScriptAPI::dropVideo(const QString& id)
630 {
631 	emit(requestDropVideo(id));
632 }
633 
seekVideo(const QString & id,qint64 ms,bool pause)634 void StelMainScriptAPI::seekVideo(const QString& id, qint64 ms, bool pause)
635 {
636 	emit(requestSeekVideo(id, ms, pause));
637 }
638 
setVideoXY(const QString & id,float x,float y,bool relative)639 void StelMainScriptAPI::setVideoXY(const QString& id, float x, float y, bool relative)
640 {
641 	emit(requestSetVideoXY(id, x, y, relative));
642 }
643 
setVideoAlpha(const QString & id,float alpha)644 void StelMainScriptAPI::setVideoAlpha(const QString& id, float alpha)
645 {
646 	emit(requestSetVideoAlpha(id, alpha));
647 }
648 
resizeVideo(const QString & id,float w,float h)649 void StelMainScriptAPI::resizeVideo(const QString& id, float w, float h)
650 {
651 	emit(requestResizeVideo(id, w, h));
652 }
653 
showVideo(const QString & id,bool show)654 void StelMainScriptAPI::showVideo(const QString& id, bool show)
655 {
656 	emit(requestShowVideo(id, show));
657 }
658 
getVideoDuration(const QString & id)659 qint64 StelMainScriptAPI::getVideoDuration(const QString& id)
660 {
661 	return StelApp::getInstance().getStelVideoMgr()->getVideoDuration(id);
662 }
663 
getVideoPosition(const QString & id)664 qint64 StelMainScriptAPI::getVideoPosition(const QString& id)
665 {
666 	return StelApp::getInstance().getStelVideoMgr()->getVideoPosition(id);
667 }
668 
getScreenWidth()669 int StelMainScriptAPI::getScreenWidth()
670 {
671 	return StelMainView::getInstance().size().width();
672 }
673 
getScreenHeight()674 int StelMainScriptAPI::getScreenHeight()
675 {
676 	return StelMainView::getInstance().size().height();
677 }
678 
getScriptRate()679 double StelMainScriptAPI::getScriptRate()
680 {
681         return StelApp::getInstance().getScriptMgr().getScriptRate();
682 }
683 
setScriptRate(double r)684 void StelMainScriptAPI::setScriptRate(double r)
685 {
686         return StelApp::getInstance().getScriptMgr().setScriptRate(r);
687 }
688 
pauseScript()689 void StelMainScriptAPI::pauseScript()
690 {
691 	return StelApp::getInstance().getScriptMgr().pauseScript();
692 }
693 
setSelectedObjectInfo(const QString & level)694 void StelMainScriptAPI::setSelectedObjectInfo(const QString& level)
695 {
696 	if (level == "AllInfo")
697 		StelApp::getInstance().getGui()->setInfoTextFilters(StelObject::InfoStringGroup(StelObject::AllInfo));
698 	else if (level == "ShortInfo")
699 		StelApp::getInstance().getGui()->setInfoTextFilters(StelObject::InfoStringGroup(StelObject::ShortInfo));
700 	else if (level == "None")
701 		StelApp::getInstance().getGui()->setInfoTextFilters(StelObject::InfoStringGroup(Q_NULLPTR));
702 	else
703 		qWarning() << "setSelectedObjectInfo unknown level string \"" << level << "\"";
704 }
705 
exit()706 void StelMainScriptAPI::exit()
707 {
708 	emit(requestExit());
709 }
710 
quitStellarium()711 void StelMainScriptAPI::quitStellarium()
712 {
713 	StelApp::getInstance().quit(); // quit from planetarium
714 }
715 
getPropertyList()716 QStringList StelMainScriptAPI::getPropertyList()
717 {
718 	return StelApp::getInstance().getStelPropertyManager()->getPropertyList();
719 }
720 
debug(const QString & s)721 void StelMainScriptAPI::debug(const QString& s)
722 {
723 	qDebug() << "script: " << s;
724 	StelApp::getInstance().getScriptMgr().debug(s);
725 }
726 
output(const QString & s)727 void StelMainScriptAPI::output(const QString &s)
728 {
729 	StelApp::getInstance().getScriptMgr().output(s);
730 }
731 
732 //! print contents of a QVariantMap
733 //! @param map QVariantMap e.g. from getObjectInfo() or getLocationInfo()
mapToString(const QVariantMap & map)734 QString StelMainScriptAPI::mapToString(const QVariantMap& map)
735 {
736 	QString res = QString("[\n");
737 	QList<QVariant::Type> simpleTypeList;
738 	simpleTypeList.push_back(QVariant::Bool);
739 	simpleTypeList.push_back(QVariant::Int);
740 	simpleTypeList.push_back(QVariant::UInt);
741 	simpleTypeList.push_back(QVariant::Double);
742 
743 	for (auto i = map.constBegin(); i != map.constEnd(); ++i)
744 	{
745 		if (i.value().type()==QVariant::String)
746 		{
747 			res.append(QString("[ \"%1\" = \"%2\" ]\n").arg(i.key()).arg(i.value().toString()));
748 		}
749 		else if (simpleTypeList.contains(i.value().type()))
750 		{
751 			res.append(QString("[ \"%1\" = %2 ]\n").arg(i.key()).arg(i.value().toString()));
752 		}
753 		else
754 		{
755 			res.append(QString("[ \"%1\" = \"<%2>:%3\" ]\n").arg(i.key()).arg(i.value().typeName()).arg(i.value().toString()));
756 		}
757 	}
758 	res.append( QString("]\n"));
759 	return res;
760 }
761 
resetOutput(void)762 void StelMainScriptAPI::resetOutput(void)
763 {
764 	StelApp::getInstance().getScriptMgr().resetOutput();
765 }
766 
saveOutputAs(const QString & filename)767 void StelMainScriptAPI::saveOutputAs(const QString &filename)
768 {
769 	StelApp::getInstance().getScriptMgr().saveOutputAs(filename);
770 }
771 
jdFromDateString(const QString & dt,const QString & spec)772 double StelMainScriptAPI::jdFromDateString(const QString& dt, const QString& spec)
773 {
774 	QString tdt = dt.trimmed();
775 	StelCore *core = StelApp::getInstance().getCore();
776 	if (tdt == "now")
777 		return StelUtils::getJDFromSystem();
778 
779 	bool ok;
780 	double jd;
781 	if (spec=="local")
782 		jd = StelApp::getInstance().getLocaleMgr().getJdFromISO8601TimeLocal(tdt, &ok);
783 	else
784 		jd = StelUtils::getJulianDayFromISO8601String(tdt, &ok);
785 
786 	if (ok)
787 		return jd;
788 
789 	QRegularExpression nowRe("(now)?"
790 		      "\\s*([-+])"
791 		      "\\s*(\\d+(?:\\.\\d+)?(?:[eE][-+]?\\d+)?)"
792 		      "\\s*(second|minute|hour|day|sol|week|month|year)s?"
793 		      "(?:\\s+(sidereal))?");
794 	QRegularExpressionMatch nowMatch=nowRe.match(tdt);
795 	if (nowMatch.hasMatch())
796 	{
797 		double delta;
798 		double unit;
799 		double dayLength = 1.0;
800 		double yearLength = 365.242190419; // duration of Earth's mean tropical year
801 		double monthLength = 27.321582241; // duration of Earth's mean tropical month
802 
803 		if (nowMatch.captured(1)=="now")
804 			jd = StelUtils::getJDFromSystem();
805 		else
806 			jd = core->getJD();
807 
808 		if (nowMatch.captured(5) == "sidereal")
809 		{
810 			dayLength = core->getLocalSiderealDayLength();
811 			yearLength = core->getLocalSiderealYearLength();
812 			monthLength = 27.321661; // duration of Earth's sidereal month
813 		}
814 
815 		QString unitString = nowMatch.captured(4);
816 		if ( unitString == "second")
817 			unit = dayLength / (24*3600.);
818 		else if (unitString == "minute")
819 			unit = dayLength / (24*60.);
820 		else if (unitString == "hour")
821 			unit = dayLength / (24.);
822 		else if (unitString == "day")
823 			unit = dayLength;
824 		else if (unitString == "sol")
825 			unit = core->getCurrentPlanet()->getMeanSolarDay();
826 		else if (unitString == "week")
827 			unit = dayLength * 7.;
828 		else if (unitString == "month")
829 			unit = monthLength;
830 		else if (unitString == "year")
831 			unit = yearLength;
832 		else
833 		{
834 			qWarning() << "StelMainScriptAPI::setDate - unknown time unit:" << unitString;
835 			unit = 0;
836 		}
837 
838 		delta = nowMatch.captured(3).toDouble();
839 
840 		if (nowMatch.captured(2) == "+")
841 			jd += (unit * delta);
842 		else if (nowMatch.captured(2) == "-")
843 			jd -= (unit * delta);
844 		return jd;
845 	}
846 
847 	qWarning() << "StelMainScriptAPI::jdFromDateString error: date string" << dt << "not recognised, returning \"now\"";
848 	return StelUtils::getJDFromSystem();
849 }
850 
wait(double t)851 void StelMainScriptAPI::wait(double t)
852 {
853 	StelScriptMgr* scriptMgr = &StelApp::getInstance().getScriptMgr();
854 	QEventLoop* loop = scriptMgr->getWaitEventLoop();
855 	QTimer::singleShot(qRound(1000*t), loop, SLOT(quit()));
856 	if( loop->exec() != 0 )
857 	{
858 		emit(requestExit()); // causes a call of stopScript
859 	}
860 }
861 
waitFor(const QString & dt,const QString & spec)862 void StelMainScriptAPI::waitFor(const QString& dt, const QString& spec)
863 {
864 	double deltaJD = jdFromDateString(dt, spec) - getJDay();
865 	double timeRate = getTimeRate();
866 	if (timeRate == 0.)
867 	{
868 		qDebug() << "waitFor() called with no time passing - would be infinite. Not waiting!";
869 		return;
870 	}
871 	int interval=qRound(1000*deltaJD*86400/timeRate);
872 	if (interval<=0)
873 	{
874 		qDebug() << "waitFor() called, but negative interval (time exceeded before starting timer). Not waiting!";
875 		return;
876 	}
877 	StelScriptMgr* scriptMgr = &StelApp::getInstance().getScriptMgr();
878 	QEventLoop* loop = scriptMgr->getWaitEventLoop();
879 	QTimer::singleShot(interval, loop, SLOT(quit()));
880 	if( loop->exec() != 0 )
881 	{
882 		emit(requestExit()); // causes a call of stopScript
883 	}
884 }
885 
886 
selectObjectByName(const QString & name,bool pointer)887 void StelMainScriptAPI::selectObjectByName(const QString& name, bool pointer)
888 {
889 	StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
890 	omgr->setFlagSelectedObjectPointer(pointer);
891 	bool state = omgr->findAndSelect(name);
892 	// backward compatible layer: probably we have Solar system body...
893 	if (!state)
894 	{
895 		StelObjectP obj = qSharedPointerCast<StelObject>(GETSTELMODULE(SolarSystem)->searchByEnglishName(name));
896 		if (!obj.isNull())
897 			state = omgr->setSelectedObject(obj, StelModule::ReplaceSelection);
898 		else
899 			state = false;
900 	}
901 
902 	if (name.isEmpty() || !state)
903 		omgr->unSelect();
904 }
905 
selectConstellationByName(const QString & name)906 void StelMainScriptAPI::selectConstellationByName(const QString& name)
907 {
908 	StelObjectP constellation = Q_NULLPTR;
909 	if (!name.isEmpty())
910 		constellation = GETSTELMODULE(ConstellationMgr)->searchByName(name);
911 
912 	if (!constellation.isNull())
913 		GETSTELMODULE(StelObjectMgr)->setSelectedObject(constellation);
914 }
915 
getObjectInfo(const QString & name)916 QVariantMap StelMainScriptAPI::getObjectInfo(const QString& name)
917 {
918 	StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
919 	StelObjectP obj = omgr->searchByName(name);
920 	// backward compatible layer: probably we have Solar system body...
921 	if (obj.isNull())
922 		obj = qSharedPointerCast<StelObject>(GETSTELMODULE(SolarSystem)->searchByEnglishName(name));
923 
924 	return StelObjectMgr::getObjectInfo(obj);
925 }
926 
getSelectedObjectInfo()927 QVariantMap StelMainScriptAPI::getSelectedObjectInfo()
928 {
929 	StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
930 	QVariantMap map;
931 	if (omgr->getSelectedObject().isEmpty())
932 	{
933 		debug("getObjectData WARNING - object not selected");
934 		map.insert("found", false);
935 		return map;
936 	}
937 
938 	StelObjectP obj = omgr->getSelectedObject()[0];
939 
940 	return StelObjectMgr::getObjectInfo(obj);
941 }
942 
addToSelectedObjectInfoString(const QString & str,bool replace)943 void StelMainScriptAPI::addToSelectedObjectInfoString(const QString &str, bool replace)
944 {
945 	StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
946 	if (omgr->getSelectedObject().isEmpty())
947 	{
948 		debug("addToSelectedObjectInfoString WARNING - no object selected");
949 		return;
950 	}
951 
952 	StelObjectP obj = omgr->getSelectedObject()[0];
953 	if (obj)
954 	{
955 		if (replace)
956 			obj->setExtraInfoString(StelObject::Script, str);
957 		else
958 			obj->addToExtraInfoString(StelObject::Script, str);
959 	}
960 }
961 
setStelProperty(const QString & propertyName,QVariant propertyValue)962 void StelMainScriptAPI::setStelProperty(const QString& propertyName, QVariant propertyValue)
963 {
964 	StelApp::getInstance().getStelPropertyManager()->setStelPropertyValue(propertyName, propertyValue);
965 }
966 
getStelProperty(const QString & propertyName)967 QVariant StelMainScriptAPI::getStelProperty(const QString& propertyName)
968 {
969 	return StelApp::getInstance().getStelPropertyManager()->getStelPropertyValue(propertyName, true);
970 }
971 
972 
clear(const QString & state)973 void StelMainScriptAPI::clear(const QString& state)
974 {
975 	static const QMap<QString, int>stateMap={
976 		{ "natural",   1},
977 		{ "starchart", 2},
978 		{ "deepspace", 3},
979 		{ "galactic",  4},
980 		{ "supergalactic", 5 }};
981 	const int stateInt = stateMap.value(state.toLower(), 0);
982 	if (stateInt == 0)
983 	{
984 		qWarning() << "WARNING clear(" << state << ") - state not known";
985 	}
986 	else
987 	{
988 		LandscapeMgr* lmgr = GETSTELMODULE(LandscapeMgr);
989 		SolarSystem* ssmgr = GETSTELMODULE(SolarSystem);
990 		SporadicMeteorMgr* mmgr = GETSTELMODULE(SporadicMeteorMgr);
991 		StelSkyDrawer* skyd = StelApp::getInstance().getCore()->getSkyDrawer();
992 		ConstellationMgr* cmgr = GETSTELMODULE(ConstellationMgr);
993 		AsterismMgr* amgr = GETSTELMODULE(AsterismMgr);
994 		StarMgr* smgr = GETSTELMODULE(StarMgr);
995 		NebulaMgr* nmgr = GETSTELMODULE(NebulaMgr);
996 		GridLinesMgr* glmgr = GETSTELMODULE(GridLinesMgr);
997 		StelMovementMgr* movmgr = GETSTELMODULE(StelMovementMgr);
998 		ZodiacalLight* zl = GETSTELMODULE(ZodiacalLight);
999 		StelPropertyMgr* propMgr = StelApp::getInstance().getStelPropertyManager();
1000 
1001 		// Hide artificial satellites through StelProperties to avoid crash if plugin was not loaded
1002 		propMgr->setStelPropertyValue("Satellites.flagHintsVisible",   false);
1003 		propMgr->setStelPropertyValue("Satellites.flagLabelsVisible",  false);
1004 		propMgr->setStelPropertyValue("Satellites.flagOrbitLines", false);
1005 
1006 		// identical for all states
1007 		glmgr->setFlagAllGrids(false);
1008 		glmgr->setFlagAllLines(false);
1009 		glmgr->setFlagAllPoints(false);
1010 		ssmgr->setFlagHints(false);
1011 		ssmgr->setFlagOrbits(false);
1012 		ssmgr->setFlagMoonScale(false);
1013 		ssmgr->setFlagMinorBodyScale(false);
1014 		ssmgr->setFlagTrails(false);
1015 		lmgr->setFlagCardinalsPoints(false);
1016 		amgr->setFlagLines(false);
1017 		amgr->setFlagLabels(false);
1018 		amgr->setFlagRayHelpers(false);
1019 
1020 		// applicable for most states
1021 		skyd->setFlagTwinkle(false);
1022 		skyd->setFlagLuminanceAdaptation(false);
1023 		ssmgr->setFlagPlanets(false);
1024 		mmgr->setZHR(0);
1025 		cmgr->setFlagLines(false);
1026 		cmgr->setFlagLabels(false);
1027 		cmgr->setFlagBoundaries(false);
1028 		cmgr->setFlagArt(false);
1029 		smgr->setFlagLabels(false);
1030 		ssmgr->setFlagLabels(false);
1031 		lmgr->setFlagLandscape(false);
1032 		lmgr->setFlagAtmosphere(false);
1033 		lmgr->setFlagFog(false);
1034 		nmgr->setFlagHints(false);
1035 		zl->setFlagShow(false);
1036 
1037 		switch (stateInt)
1038 		{
1039 			case 1: // natural
1040 			{
1041 				movmgr->setMountMode(StelMovementMgr::MountAltAzimuthal);
1042 				skyd->setFlagTwinkle(true);
1043 				skyd->setFlagLuminanceAdaptation(true);
1044 				ssmgr->setFlagPlanets(true);
1045 				mmgr->setZHR(10);
1046 				lmgr->setFlagLandscape(true);
1047 				lmgr->setFlagAtmosphere(true);
1048 				lmgr->setFlagFog(true);
1049 				zl->setFlagShow(true);
1050 				break;
1051 			}
1052 			case 2: // starchart
1053 			{
1054 				movmgr->setMountMode(StelMovementMgr::MountEquinoxEquatorial);
1055 				ssmgr->setFlagPlanets(true);
1056 				cmgr->setFlagLines(true);
1057 				cmgr->setFlagLabels(true);
1058 				cmgr->setFlagBoundaries(true);
1059 				smgr->setFlagLabels(true);
1060 				ssmgr->setFlagLabels(true);
1061 				nmgr->setFlagHints(true);
1062 				glmgr->setFlagEquatorGrid(true);
1063 				break;
1064 			}
1065 			case 3: // deepspace
1066 				movmgr->setMountMode(StelMovementMgr::MountEquinoxEquatorial);
1067 				break;
1068 			case 4: // galactic
1069 			{
1070 				movmgr->setMountMode(StelMovementMgr::MountGalactic);
1071 				glmgr->setFlagGalacticGrid(true);
1072 				break;
1073 			}
1074 			case 5: // supergalactic
1075 			{
1076 				movmgr->setMountMode(StelMovementMgr::MountSupergalactic);
1077 				glmgr->setFlagSupergalacticGrid(true);
1078 				break;
1079 			}
1080 		}
1081 	}
1082 }
1083 
getViewAltitudeAngle()1084 double StelMainScriptAPI::getViewAltitudeAngle()
1085 {
1086 	const Vec3d& current = StelApp::getInstance().getCore()->j2000ToAltAz(GETSTELMODULE(StelMovementMgr)->getViewDirectionJ2000(), StelCore::RefractionOff);
1087 	double alt, azi;
1088 	StelUtils::rectToSphe(&azi, &alt, current);
1089 	return alt*180/M_PI; // convert to degrees from radians
1090 }
1091 
getViewAzimuthAngle()1092 double StelMainScriptAPI::getViewAzimuthAngle()
1093 {
1094 	const Vec3d& current = StelApp::getInstance().getCore()->j2000ToAltAz(GETSTELMODULE(StelMovementMgr)->getViewDirectionJ2000(), StelCore::RefractionOff);
1095 	double alt, azi;
1096 	StelUtils::rectToSphe(&azi, &alt, current);
1097 	// The returned azimuth angle is in radians and set up such that:
1098 	// N=+/-PI; E=PI/2; S=0; W=-PI/2;
1099 	// But we want compass bearings, i.e. N=0, E=90, S=180, W=270
1100 	return std::fmod(((azi*180/M_PI)*-1)+180., 360.);
1101 }
1102 
getViewRaAngle()1103 double StelMainScriptAPI::getViewRaAngle()
1104 {
1105 	const Vec3d& current = StelApp::getInstance().getCore()->j2000ToEquinoxEqu(GETSTELMODULE(StelMovementMgr)->getViewDirectionJ2000(), StelCore::RefractionOff);
1106 	double ra, dec;
1107 	StelUtils::rectToSphe(&ra, &dec, current);
1108 	// returned RA angle is in range -PI .. PI, but we want 0 .. 360
1109 	return std::fmod((ra*180/M_PI)+360., 360.); // convert to degrees from radians
1110 }
1111 
getViewDecAngle()1112 double StelMainScriptAPI::getViewDecAngle()
1113 {
1114 	const Vec3d& current = StelApp::getInstance().getCore()->j2000ToEquinoxEqu(GETSTELMODULE(StelMovementMgr)->getViewDirectionJ2000(), StelCore::RefractionOff);
1115 	double ra, dec;
1116 	StelUtils::rectToSphe(&ra, &dec, current);
1117 	return dec*180/M_PI; // convert to degrees from radians
1118 }
1119 
getViewRaJ2000Angle()1120 double StelMainScriptAPI::getViewRaJ2000Angle()
1121 {
1122 	Vec3d current = GETSTELMODULE(StelMovementMgr)->getViewDirectionJ2000();
1123 	double ra, dec;
1124 	StelUtils::rectToSphe(&ra, &dec, current);
1125 	// returned RA angle is in range -PI .. PI, but we want 0 .. 360
1126 	return std::fmod((ra*180/M_PI)+360., 360.); // convert to degrees from radians
1127 }
1128 
getViewDecJ2000Angle()1129 double StelMainScriptAPI::getViewDecJ2000Angle()
1130 {
1131 	Vec3d current = GETSTELMODULE(StelMovementMgr)->getViewDirectionJ2000();
1132 	double ra, dec;
1133 	StelUtils::rectToSphe(&ra, &dec, current);
1134 	return dec*180/M_PI; // convert to degrees from radians
1135 }
1136 
moveToObject(const QString & name,float duration)1137 void StelMainScriptAPI::moveToObject(const QString& name, float duration)
1138 {
1139 	if (name.isEmpty())
1140 		return;
1141 
1142 	StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
1143 	StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
1144 	StelObjectP obj = omgr->searchByName(name);
1145 
1146 	if (!obj.isNull())
1147 		mvmgr->moveToObject(obj, duration);
1148 }
1149 
moveToSelectedObject(float duration)1150 void StelMainScriptAPI::moveToSelectedObject(float duration)
1151 {
1152 	StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
1153 	if (omgr->getSelectedObject().isEmpty())
1154 		return;
1155 
1156 	StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
1157 	mvmgr->moveToObject(omgr->getSelectedObject()[0], duration); // Object may be without English name
1158 }
1159 
moveToAltAzi(const QString & alt,const QString & azi,float duration)1160 void StelMainScriptAPI::moveToAltAzi(const QString& alt, const QString& azi, float duration)
1161 {
1162 	StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
1163 	Q_ASSERT(mvmgr);
1164 	GETSTELMODULE(StelObjectMgr)->unSelect();
1165 
1166 	Vec3d aim;
1167 	double dAlt = StelUtils::getDecAngle(alt);
1168 	double dAzi = M_PI - StelUtils::getDecAngle(azi);
1169 
1170 	if (StelApp::getInstance().getFlagSouthAzimuthUsage())
1171 		dAzi -= M_PI;
1172 
1173 	StelUtils::spheToRect(dAzi,dAlt,aim);
1174 
1175 	// make up vector more stable:
1176 	StelMovementMgr::MountMode mountMode=mvmgr->getMountMode();
1177 	Vec3d aimUp;
1178 	if ( (mountMode==StelMovementMgr::MountAltAzimuthal) && (fabs(dAlt)> (0.9*M_PI/2.0)) )
1179 		aimUp=Vec3d(-cos(dAzi), -sin(dAzi), 0.) * (dAlt>0. ? 1. : -1.);
1180 	else
1181 		aimUp=Vec3d(0., 0., 1.);
1182 
1183 	mvmgr->moveToAltAzi(aim, aimUp, duration);
1184 }
1185 
moveToRaDec(const QString & ra,const QString & dec,float duration)1186 void StelMainScriptAPI::moveToRaDec(const QString& ra, const QString& dec, float duration)
1187 {
1188 	StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
1189 	Q_ASSERT(mvmgr);
1190 	StelCore* core = StelApp::getInstance().getCore();
1191 
1192 	GETSTELMODULE(StelObjectMgr)->unSelect();
1193 
1194 	Vec3d aim;
1195 	double dRa = StelUtils::getDecAngle(ra);
1196 	double dDec = StelUtils::getDecAngle(dec);
1197 
1198 	StelUtils::spheToRect(dRa,dDec,aim);
1199 	// make up vector more stable:
1200 	StelMovementMgr::MountMode mountMode=mvmgr->getMountMode();
1201 	Vec3d aimUp;
1202 	if ( (mountMode==StelMovementMgr::MountEquinoxEquatorial) && (fabs(dDec)> (0.9*M_PI/2.0)) )
1203 		aimUp=core->equinoxEquToJ2000(Vec3d(-cos(dRa), -sin(dRa), 0.) * (dDec>0. ? 1. : -1. ), StelCore::RefractionOff);
1204 	else
1205 		aimUp=core->equinoxEquToJ2000(Vec3d(0., 0., 1.), StelCore::RefractionOff);
1206 
1207 	mvmgr->moveToJ2000(StelApp::getInstance().getCore()->equinoxEquToJ2000(aim, StelCore::RefractionOff), aimUp, duration);
1208 }
1209 
moveToRaDecJ2000(const QString & ra,const QString & dec,float duration)1210 void StelMainScriptAPI::moveToRaDecJ2000(const QString& ra, const QString& dec, float duration)
1211 {
1212 	StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
1213 	Q_ASSERT(mvmgr);
1214 	GETSTELMODULE(StelObjectMgr)->unSelect();
1215 
1216 	Vec3d aimJ2000;
1217 	double dRa = StelUtils::getDecAngle(ra);
1218 	double dDec = StelUtils::getDecAngle(dec);
1219 
1220 	StelUtils::spheToRect(dRa,dDec,aimJ2000);
1221 	// make up vector more stable. Not sure if we have to set the up vector in this case though.
1222 	StelMovementMgr::MountMode mountMode=mvmgr->getMountMode();
1223 	Vec3d aimUp;
1224 	if ( (mountMode==StelMovementMgr::MountEquinoxEquatorial) && (fabs(dDec)> (0.9*M_PI/2.0)) )
1225 		aimUp=Vec3d(-cos(dRa), -sin(dRa), 0.) * (dDec>0. ? 1. : -1. );
1226 	else
1227 		aimUp=Vec3d(0., 0., 1.);
1228 
1229 	mvmgr->moveToJ2000(aimJ2000, aimUp, duration);
1230 }
1231 
moveToGalLongLat(const QString & lon,const QString & lat,float duration)1232 void StelMainScriptAPI::moveToGalLongLat(const QString& lon, const QString& lat, float duration)
1233 {
1234 	StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
1235 	Q_ASSERT(mvmgr);
1236 	GETSTELMODULE(StelObjectMgr)->unSelect();
1237 
1238 	Vec3d aimJ2000;
1239 	double dRa = StelUtils::getDecAngle(lon);
1240 	double dDec = StelUtils::getDecAngle(lat);
1241 
1242 	StelUtils::spheToRect(dRa,dDec,aimJ2000);
1243 	aimJ2000=StelApp::getInstance().getCore()->galacticToJ2000(aimJ2000);
1244 	// make up vector more stable. Not sure if we have to set the up vector in this case though.
1245 	StelMovementMgr::MountMode mountMode=mvmgr->getMountMode();
1246 	Vec3d aimUp;
1247 	if ( (mountMode==StelMovementMgr::MountEquinoxEquatorial) && (fabs(dDec)> (0.9*M_PI/2.0)) )
1248 		aimUp=Vec3d(-cos(dRa), -sin(dRa), 0.) * (dDec>0. ? 1. : -1. );
1249 	else
1250 		aimUp=Vec3d(0., 0., 1.);
1251 
1252 	mvmgr->moveToJ2000(aimJ2000, aimUp, duration);
1253 }
1254 
getAppLanguage()1255 QString StelMainScriptAPI::getAppLanguage()
1256 {
1257 	return StelApp::getInstance().getLocaleMgr().getAppLanguage();
1258 }
1259 
setAppLanguage(QString langCode)1260 void StelMainScriptAPI::setAppLanguage(QString langCode)
1261 {
1262 	StelApp::getInstance().getLocaleMgr().setAppLanguage(langCode);
1263 }
1264 
getSkyLanguage()1265 QString StelMainScriptAPI::getSkyLanguage()
1266 {
1267 	return StelApp::getInstance().getLocaleMgr().getSkyLanguage();
1268 }
1269 
setSkyLanguage(QString langCode)1270 void StelMainScriptAPI::setSkyLanguage(QString langCode)
1271 {
1272 	StelApp::getInstance().getLocaleMgr().setSkyLanguage(langCode);
1273 }
1274 
translate(QString englishText)1275 QString StelMainScriptAPI::translate(QString englishText)
1276 {
1277 	return StelApp::getInstance().getLocaleMgr().getScriptsTranslator().qtranslate(englishText);
1278 }
1279 
goHome()1280 void StelMainScriptAPI::goHome()
1281 {
1282 	emit(requestSetHomePosition());
1283 }
1284 
getBortleScaleIndex()1285 int StelMainScriptAPI::getBortleScaleIndex()
1286 {
1287 	return StelApp::getInstance().getCore()->getSkyDrawer()->getBortleScaleIndex();
1288 }
1289 
setBortleScaleIndex(int index)1290 void StelMainScriptAPI::setBortleScaleIndex(int index)
1291 {
1292 	StelApp::getInstance().getCore()->getSkyDrawer()->setBortleScaleIndex(index);
1293 }
1294 
refraction(double altitude,bool apparent)1295 double StelMainScriptAPI::refraction(double altitude, bool apparent)
1296 {
1297 	Vec3d pos(1., 0., 0.);
1298 	// rotate to set altitude.
1299 	pos=Mat4d::yrotation(-altitude*M_PI_180)*pos;
1300 
1301 	const Refraction refraction=StelApp::getInstance().getCore()->getSkyDrawer()->getRefraction();
1302 	if (apparent)
1303 	{
1304 		refraction.backward(pos);
1305 	}
1306 	else
1307 	{
1308 		refraction.forward(pos);
1309 	}
1310 	return asin(pos[2])*M_180_PI;
1311 }
1312 
getScreenXYFromAltAzi(const QString & alt,const QString & azi)1313 QVariantMap StelMainScriptAPI::getScreenXYFromAltAzi(const QString &alt, const QString &azi)
1314 {
1315 	Vec3d aim, v;
1316 	double dAlt = StelUtils::getDecAngle(alt);
1317 	double dAzi = M_PI - StelUtils::getDecAngle(azi);
1318 
1319 	if (StelApp::getInstance().getFlagSouthAzimuthUsage())
1320 		dAzi -= M_PI;
1321 
1322 	StelUtils::spheToRect(dAzi,dAlt,aim);
1323 
1324 	const StelProjectorP prj = StelApp::getInstance().getCore()->getProjection(StelCore::FrameAltAz, StelCore::RefractionOff);
1325 
1326 	prj->project(aim, v);
1327 
1328 	QVariantMap map;
1329 	map.insert("x", qRound(v[0]));
1330 	map.insert("y", prj->getViewportHeight()-qRound(v[1]));
1331 
1332 	return map;
1333 }
1334 
getEnv(const QString & var)1335 QString StelMainScriptAPI::getEnv(const QString &var)
1336 {
1337 #if QT_VERSION >= 0x050A00
1338 	return qEnvironmentVariable(var.toLocal8Bit().constData());
1339 #else
1340 	return QString::fromLocal8Bit(qgetenv(var.toLocal8Bit().constData()));
1341 #endif
1342 }
1343 
1344 // return whether a particular module has been loaded. Mostly useful to check whether a module available as plugin is active.
isModuleLoaded(const QString & moduleID)1345 bool StelMainScriptAPI::isModuleLoaded(const QString &moduleID)
1346 {
1347 	StelModule *module= StelApp::getInstance().getModuleMgr().getModule (moduleID, true);
1348 	return module != Q_NULLPTR;
1349 }
1350 
1351 // return the name of platform where running Stellarium
getPlatformName(void)1352 QString StelMainScriptAPI::getPlatformName(void)
1353 {
1354 	// Get info about operating system
1355 	QString os = StelUtils::getOperatingSystemInfo();
1356 	if (os.contains("FreeBSD", Qt::CaseInsensitive))
1357 		os = "FreeBSD";
1358 	else if (os.contains("NetBSD", Qt::CaseInsensitive))
1359 		os = "NetBSD";
1360 	else if (os.contains("OpenBSD", Qt::CaseInsensitive))
1361 		os = "OpenBSD";
1362 	else if (os.contains("linux", Qt::CaseInsensitive) || QSysInfo::kernelType().contains("linux", Qt::CaseInsensitive))
1363 		os = "Linux";
1364 	else if (os.contains("windows", Qt::CaseInsensitive) || os.contains("winrt", Qt::CaseInsensitive))
1365 		os = "Windows";
1366 	else if (os.contains("osx", Qt::CaseInsensitive) || os.contains("macos", Qt::CaseInsensitive))
1367 		os = "macOS";
1368 	else
1369 		os = "Unknown";
1370 
1371 	return os;
1372 }
1373 
1374 // Get the current status of media playback support
isMediaPlaybackSupported(void)1375 bool StelMainScriptAPI::isMediaPlaybackSupported(void)
1376 {
1377 	#ifdef ENABLE_MEDIA
1378 	return true;
1379 	#else
1380 	return false;
1381 	#endif
1382 }
1383 
1384 // Experimental. Try to play with physical display properties for tonemapping.
setDisplayMaxLuminance(double cdPerSqM)1385 void StelMainScriptAPI::setDisplayMaxLuminance(double cdPerSqM)
1386 {
1387     StelApp::getInstance().getCore()->getToneReproducer()->setMaxDisplayLuminance(static_cast<float>(cdPerSqM));
1388 }
getDisplayMaxLuminance()1389 double StelMainScriptAPI::getDisplayMaxLuminance()
1390 {
1391     return static_cast<double>(StelApp::getInstance().getCore()->getToneReproducer()->getMaxDisplayLuminance());
1392 }
setDisplayGamma(double gamma)1393 void StelMainScriptAPI::setDisplayGamma(double gamma)
1394 {
1395     StelApp::getInstance().getCore()->getToneReproducer()->setDisplayGamma(static_cast<float>(gamma));
1396 }
getDisplayGamma()1397 double StelMainScriptAPI::getDisplayGamma()
1398 {
1399     return static_cast<double>(StelApp::getInstance().getCore()->getToneReproducer()->getDisplayGamma());
1400 }
1401