StelScriptMgr.cpp   StelScriptMgr.cpp 
/* /*
* Stellarium * Stellarium
* Copyright (C) 2009 Matthew Gates
* Copyright (C) 2007 Fabien Chereau * Copyright (C) 2007 Fabien Chereau
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U SA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, U SA.
*/ */
#include "fixx11h.h"
#include "StelScriptMgr.hpp" #include "StelScriptMgr.hpp"
#include "StelAudioMgr.hpp" #include "StelMainScriptAPI.hpp"
#include "ConstellationMgr.hpp"
#include "GridLinesMgr.hpp"
#include "LandscapeMgr.hpp"
#include "MeteorMgr.hpp"
#include "StelMovementMgr.hpp"
#include "StelNavigator.hpp"
#include "NebulaMgr.hpp"
#include "SolarSystem.hpp"
#include "StelApp.hpp" #include "StelApp.hpp"
#include "StelCore.hpp" #include "StelCore.hpp"
#include "StelFileMgr.hpp" #include "StelFileMgr.hpp"
#include "StelGui.hpp"
#include "StelModuleMgr.hpp" #include "StelModuleMgr.hpp"
#include "StelObjectMgr.hpp" #include "StelMovementMgr.hpp"
#include "StelUtils.hpp" #include "StelNavigator.hpp"
#include "StelMainGraphicsView.hpp"
#include "StelSkyDrawer.hpp" #include "StelSkyDrawer.hpp"
#include "StelSkyImageMgr.hpp" #include "StelSkyLayerMgr.hpp"
#include "StarMgr.hpp"
#include "StelProjector.hpp"
#include "StelLocation.hpp"
#include "Planet.hpp"
#include "StelLocationMgr.hpp"
#include <QAction> #include <QAction>
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QFile> #include <QFile>
#include <QFileInfo> #include <QFileInfo>
#include <QRegExp>
#include <QSet> #include <QSet>
#include <QDebug>
#include <QStringList> #include <QStringList>
#include <QDateTime>
#include <QRegExp>
#include <QDir>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QVariant>
#include <cmath>
Q_DECLARE_METATYPE(Vec3f); Q_DECLARE_METATYPE(Vec3f);
class StelScriptThread : public QThread class StelScriptThread : public QThread
{ {
public: public:
StelScriptThread(const QString& ascriptCode, QScriptEngine* aengine, QString fileName) : scriptCode(ascriptCode), engine(aengine), fnam e(fileName) {;} StelScriptThread(const QString& ascriptCode, QScriptEngine* aengine, QString fileName) : scriptCode(ascriptCode), engine(aengine), fnam e(fileName) {;}
QString getFileName() {return fname;} QString getFileName() {return fname;}
protected: protected:
void run() void run()
{ {
// seed the QT PRNG // seed the QT PRNG
qsrand(QDateTime::currentDateTime().toTime_t()); qsrand(QDateTime::currentDateTime().toTime_t());
// For startup scripts, the gui object might not // For startup scripts, the gui object might not
// have completed init when we run. Wait for that. // have completed init when we run. Wait for that.
StelGui* gui = GETSTELMODULE(StelGui); Q_ASSERT(StelApp::getInstance().getGui());
while(!gui)
{
msleep(200);
gui = GETSTELMODULE(StelGui);
}
while(!gui->initComplete())
msleep(200);
engine->evaluate(scriptCode); engine->evaluate(scriptCode);
} }
private: private:
QString scriptCode; QString scriptCode;
QScriptEngine* engine; QScriptEngine* engine;
QString fname; QString fname;
}; };
QScriptValue vec3fToScriptValue(QScriptEngine *engine, const Vec3f& c) QScriptValue vec3fToScriptValue(QScriptEngine *engine, const Vec3f& c)
skipping to change at line 118 skipping to change at line 98
QScriptValue createVec3f(QScriptContext* context, QScriptEngine *engine) QScriptValue createVec3f(QScriptContext* context, QScriptEngine *engine)
{ {
Vec3f c; Vec3f c;
c[0] = context->argument(0).toNumber(); c[0] = context->argument(0).toNumber();
c[1] = context->argument(1).toNumber(); c[1] = context->argument(1).toNumber();
c[2] = context->argument(2).toNumber(); c[2] = context->argument(2).toNumber();
return vec3fToScriptValue(engine, c); return vec3fToScriptValue(engine, c);
} }
StelMainScriptAPI::StelMainScriptAPI(QObject *parent) : QObject(parent)
{
if(StelSkyImageMgr* smgr = GETSTELMODULE(StelSkyImageMgr))
{
connect(this, SIGNAL(requestLoadSkyImage(const QString&, con
st QString&, double, double, double, double, double, double, double, double
, double, double, bool)), smgr, SLOT(loadSkyImage(const QString&, const QSt
ring&, double, double, double, double, double, double, double, double, doub
le, double, bool)));
connect(this, SIGNAL(requestRemoveSkyImage(const QString&)),
smgr, SLOT(removeSkyImage(const QString&)));
}
connect(this, SIGNAL(requestLoadSound(const QString&, const QString&
)), StelApp::getInstance().getStelAudioMgr(), SLOT(loadSound(const QString&
, const QString&)));
connect(this, SIGNAL(requestPlaySound(const QString&)), StelApp::get
Instance().getStelAudioMgr(), SLOT(playSound(const QString&)));
connect(this, SIGNAL(requestPauseSound(const QString&)), StelApp::ge
tInstance().getStelAudioMgr(), SLOT(pauseSound(const QString&)));
connect(this, SIGNAL(requestStopSound(const QString&)), StelApp::get
Instance().getStelAudioMgr(), SLOT(stopSound(const QString&)));
connect(this, SIGNAL(requestDropSound(const QString&)), StelApp::get
Instance().getStelAudioMgr(), SLOT(dropSound(const QString&)));
}
StelMainScriptAPI::~StelMainScriptAPI()
{
}
//! Set the current date in Julian Day
//! @param JD the Julian Date
void StelMainScriptAPI::setJDay(double JD)
{
StelApp::getInstance().getCore()->getNavigator()->setJDay(JD);
}
//! Get the current date in Julian Day
//! @return the Julian Date
double StelMainScriptAPI::getJDay(void) const
{
return StelApp::getInstance().getCore()->getNavigator()->getJDay();
}
void StelMainScriptAPI::setDate(const QString& dt, const QString& spec)
{
StelApp::getInstance().getCore()->getNavigator()->setJDay(jdFromDate
String(dt, spec));
}
//! Set time speed in JDay/sec
//! @param ts time speed in JDay/sec
void StelMainScriptAPI::setTimeRate(double ts)
{
// 1 second = .00001157407407407407 JDay
StelApp::getInstance().getCore()->getNavigator()->setTimeRate(ts * 0
.00001157407407407407);
}
//! Get time speed in JDay/sec
//! @return time speed in JDay/sec
double StelMainScriptAPI::getTimeRate(void) const
{
return StelApp::getInstance().getCore()->getNavigator()->getTimeRate
() / 0.00001157407407407407;
}
// This class let's us sleep in milleseconds
class MySleep : public QThread
{
public:
static void msleep(unsigned long msecs)
{
QThread::msleep(msecs);
}
};
void StelMainScriptAPI::wait(double t)
{
MySleep::msleep((unsigned long )(t*1000));
}
void StelMainScriptAPI::waitFor(const QString& dt, const QString& spec)
{
double JD = jdFromDateString(dt, spec);
StelNavigator* nav = StelApp::getInstance().getCore()->getNavigator(
);
Q_ASSERT(nav);
double timeSpeed = nav->getTimeRate();
if (timeSpeed == 0.)
{
qWarning() << "waitFor called with no time passing - would b
e infinite. not waiting!";
return;
}
else if (timeSpeed > 0)
{
while(nav->getJDay() < JD)
MySleep::msleep(50);
}
else
{
while(nav->getJDay() > JD)
MySleep::msleep(50);
}
}
void StelMainScriptAPI::setObserverLocation(double longitude, double latitu
de, double altitude, double duration, const QString& name, const QString& p
lanet)
{
StelNavigator* nav = StelApp::getInstance().getCore()->getNavigator(
);
Q_ASSERT(nav);
SolarSystem* ssmgr = GETSTELMODULE(SolarSystem);
Q_ASSERT(ssmgr);
StelLocation loc = nav->getCurrentLocation();
if (longitude < 180 || longitude > 180)
loc.longitude = longitude;
if (latitude < 180 || latitude > 180)
loc.latitude = latitude;
if (altitude < -1000)
loc.altitude = altitude;
if (ssmgr->searchByName(planet))
loc.planetName = planet;
loc.name = name;
nav->moveObserverTo(loc, duration);
}
void StelMainScriptAPI::setObserverLocation(const QString id, double durati
on)
{
StelNavigator* nav = StelApp::getInstance().getCore()->getNavigator(
);
Q_ASSERT(nav);
StelLocation loc = StelApp::getInstance().getLocationMgr().locationF
orSmallString(id);
// How best to test to see if the lookup of the name was a success?
// On failure, it returns Paris, but maybe we _want_ Paris.
// Ugly. -MNG
if (id!="Paris, France" && (loc.name=="Paris" && loc.country=="Franc
e"))
return; // location find fail
nav->moveObserverTo(loc, duration);
}
void StelMainScriptAPI::screenshot(const QString& prefix, bool invert, cons
t QString& dir)
{
bool oldInvertSetting = StelMainGraphicsView::getInstance().getFlagI
nvertScreenShotColors();
StelMainGraphicsView::getInstance().setFlagInvertScreenShotColors(in
vert);
StelMainGraphicsView::getInstance().saveScreenShot(prefix, dir);
StelMainGraphicsView::getInstance().setFlagInvertScreenShotColors(ol
dInvertSetting);
}
void StelMainScriptAPI::setHideGui(bool b)
{
GETSTELMODULE(StelGui)->getGuiActions("actionToggle_GuiHidden_Global
")->setChecked(b);
}
void StelMainScriptAPI::setMinFps(float m)
{
StelApp::getInstance().setMinFps(m);
}
float StelMainScriptAPI::getMinFps()
{
return StelApp::getInstance().getMinFps();
}
void StelMainScriptAPI::setMaxFps(float m)
{
StelApp::getInstance().setMaxFps(m);
}
float StelMainScriptAPI::getMaxFps()
{
return StelApp::getInstance().getMaxFps();
}
void StelMainScriptAPI::loadSkyImage(const QString& id, const QString& file
name,
double ra0, double dec0,
double ra1, double dec1,
double ra2, double dec2,
double ra3, double dec3,
double minRes, double maxBright, bool v
isible)
{
QString path = "scripts/" + filename;
qDebug() << "StelMainScriptAPI::loadSkyImage" << id << filename
<< "[" << ra0 << dec0 << "],[" << ra1 << dec1 << "],[" << r
a2 << dec2 << "],[" << ra3 << dec3 << "]"
<< minRes << maxBright << visible;
emit(requestLoadSkyImage(id, path, ra0, dec0, ra1, dec1, ra2, dec2,
ra3, dec3, minRes, maxBright, visible));
}
void StelMainScriptAPI::loadSkyImage(const QString& id, const QString& file
name,
const QString& ra0, const QString& dec
0,
const QString& ra1, const QString& dec
1,
const QString& ra2, const QString& dec
2,
const QString& ra3, const QString& dec
3,
double minRes, double maxBright, bool
visible)
{
loadSkyImage(id, filename,
StelUtils::getDecAngle(ra0) *180./M_PI, StelUtils::getD
ecAngle(dec0)*180./M_PI,
StelUtils::getDecAngle(ra1) *180./M_PI, StelUtils::getD
ecAngle(dec1)*180./M_PI,
StelUtils::getDecAngle(ra2) *180./M_PI, StelUtils::getD
ecAngle(dec2)*180./M_PI,
StelUtils::getDecAngle(ra3) *180./M_PI, StelUtils::getD
ecAngle(dec3)*180./M_PI,
minRes, maxBright, visible);
}
void StelMainScriptAPI::loadSkyImage(const QString& id, const QString& file
name,
double ra, double dec, double angSize,
double rotation,
double minRes, double maxBright, bool
visible)
{
Vec3d XYZ;
const double RADIUS_NEB = 1.;
//double angSizeRad = angSize/2/60*M_PI/180.;
StelUtils::spheToRect(ra*M_PI/180., dec*M_PI/180., XYZ);
XYZ*=RADIUS_NEB;
double texSize = RADIUS_NEB * sin(angSize/2/60*M_PI/180);
Mat4f matPrecomp = Mat4f::translation(XYZ) *
Mat4f::zrotation(ra*M_PI/180.) *
Mat4f::yrotation(-dec*M_PI/180.) *
Mat4f::xrotation(rotation*M_PI/180.);
Vec3d corners[4];
corners[0] = matPrecomp * Vec3d(0.,-texSize,-texSize);
corners[1] = matPrecomp * Vec3d(0., texSize,-texSize);
corners[2] = matPrecomp * Vec3d(0.,-texSize, texSize);
corners[3] = matPrecomp * Vec3d(0., texSize, texSize);
// convert back to ra/dec (radians)
Vec3d cornersRaDec[4];
for(int i=0; i<4; i++)
StelUtils::rectToSphe(&cornersRaDec[i][0], &cornersRaDec[i][
1], corners[i]);
loadSkyImage(id, filename,
cornersRaDec[0][0]*180./M_PI, cornersRaDec[0][1]*180./M
_PI,
cornersRaDec[1][0]*180./M_PI, cornersRaDec[1][1]*180./M
_PI,
cornersRaDec[3][0]*180./M_PI, cornersRaDec[3][1]*180./M
_PI,
cornersRaDec[2][0]*180./M_PI, cornersRaDec[2][1]*180./M
_PI,
minRes, maxBright, visible);
}
void StelMainScriptAPI::loadSkyImage(const QString& id, const QString& file
name,
const QString& ra, const QString& dec,
double angSize, double rotation,
double minRes, double maxBright, bool
visible)
{
loadSkyImage(id, filename, StelUtils::getDecAngle(ra)*180./M_PI,
StelUtils::getDecAngle(dec)*180./M_PI, angSize,
rotation, minRes, maxBright, visible);
}
void StelMainScriptAPI::removeSkyImage(const QString& id)
{
emit(requestRemoveSkyImage(id));
}
void StelMainScriptAPI::loadSound(const QString& filename, const QString& i
d)
{
QString path;
try
{
path = StelApp::getInstance().getFileMgr().findFile("scripts
/" + filename);
}
catch(std::runtime_error& e)
{
qWarning() << "cannot play sound" << filename << ":" << e.wh
at();
return;
}
emit(requestLoadSound(path, id));
}
void StelMainScriptAPI::playSound(const QString& id)
{
emit(requestPlaySound(id));
}
void StelMainScriptAPI::pauseSound(const QString& id)
{
emit(requestPauseSound(id));
}
void StelMainScriptAPI::stopSound(const QString& id)
{
emit(requestStopSound(id));
}
void StelMainScriptAPI::dropSound(const QString& id)
{
emit(requestDropSound(id));
}
void StelMainScriptAPI::debug(const QString& s)
{
qDebug() << "script: " << s;
}
double StelMainScriptAPI::jdFromDateString(const QString& dt, const QString
& spec)
{
QDateTime qdt;
double JD;
// 2008-03-24T13:21:01
QRegExp isoRe("^\\d{4}[:\\-]\\d\\d[:\\-]\\d\\dT\\d?\\d:\\d\\d:\\d\\d
$");
QRegExp nowRe("^(now)?(\\s*([+\\-])\\s*(\\d+(\\.\\d+)?)\\s*(second|s
econds|minute|minutes|hour|hours|day|days|week|weeks))(\\s+(sidereal)?)?");
if (dt == "now")
return StelUtils::getJDFromSystem();
else if (isoRe.exactMatch(dt))
{
qdt = QDateTime::fromString(dt, Qt::ISODate);
if (spec=="local")
JD = StelUtils::qDateTimeToJd(qdt.toUTC());
else
JD = StelUtils::qDateTimeToJd(qdt);
return JD;
}
else if (nowRe.exactMatch(dt))
{
double delta;
double unit;
double dayLength = 1.0;
if (nowRe.capturedTexts().at(1)=="now")
JD = StelUtils::getJDFromSystem();
else
JD = StelApp::getInstance().getCore()->getNavigator(
)->getJDay();
if (nowRe.capturedTexts().at(8) == "sidereal")
dayLength = StelApp::getInstance().getCore()->getNav
igator()->getHomePlanet()->getSiderealDay();
QString unitString = nowRe.capturedTexts().at(6);
if (unitString == "seconds" || unitString == "second")
unit = dayLength / (24*3600.);
else if (unitString == "minutes" || unitString == "minute")
unit = dayLength / (24*60.);
else if (unitString == "hours" || unitString == "hour")
unit = dayLength / (24.);
else if (unitString == "days" || unitString == "day")
unit = dayLength;
else if (unitString == "weeks" || unitString == "week")
unit = dayLength * 7.;
else
{
qWarning() << "StelMainScriptAPI::setDate - unknown
time unit:" << nowRe.capturedTexts().at(4);
unit = 0;
}
delta = nowRe.capturedTexts().at(4).toDouble();
if (nowRe.capturedTexts().at(3) == "+")
JD += (unit * delta);
else if (nowRe.capturedTexts().at(3) == "-")
JD -= (unit * delta);
return JD;
}
else
{
qWarning() << "StelMainScriptAPI::jdFromDateString error - d
ate string" << dt << "not recognised, returning \"now\"";
return StelUtils::getJDFromSystem();
}
}
void StelMainScriptAPI::selectObjectByName(const QString& name, bool pointe
r)
{
StelObjectMgr* omgr = GETSTELMODULE(StelObjectMgr);
omgr->setFlagSelectedObjectPointer(pointer);
if (name=="")
omgr->unSelect();
else
omgr->findAndSelect(name);
}
void StelMainScriptAPI::clear(const QString& state)
{
LandscapeMgr* lmgr = GETSTELMODULE(LandscapeMgr);
Q_ASSERT(lmgr);
SolarSystem* ssmgr = GETSTELMODULE(SolarSystem);
Q_ASSERT(ssmgr);
MeteorMgr* mmgr = GETSTELMODULE(MeteorMgr);
Q_ASSERT(mmgr);
StelSkyDrawer* skyd = StelApp::getInstance().getCore()->getSkyDrawer
();
Q_ASSERT(skyd);
ConstellationMgr* cmgr = GETSTELMODULE(ConstellationMgr);
Q_ASSERT(cmgr);
StarMgr* smgr = GETSTELMODULE(StarMgr);
Q_ASSERT(smgr);
NebulaMgr* nmgr = GETSTELMODULE(NebulaMgr);
Q_ASSERT(nmgr);
GridLinesMgr* glmgr = GETSTELMODULE(GridLinesMgr);
Q_ASSERT(glmgr);
StelNavigator* nav = StelApp::getInstance().getCore()->getNavigator(
);
Q_ASSERT(nav);
if (state.toLower() == "natural")
{
nav->setEquatorialMount(false);
skyd->setFlagTwinkle(true);
skyd->setFlagLuminanceAdaptation(true);
ssmgr->setFlagPlanets(true);
ssmgr->setFlagHints(false);
ssmgr->setFlagOrbits(false);
ssmgr->setFlagMoonScale(false);
ssmgr->setFlagTrails(false);
mmgr->setZHR(10);
glmgr->setFlagAzimuthalGrid(false);
glmgr->setFlagEquatorGrid(false);
glmgr->setFlagEquatorLine(false);
glmgr->setFlagEclipticLine(false);
glmgr->setFlagMeridianLine(false);
glmgr->setFlagEquatorJ2000Grid(false);
lmgr->setFlagCardinalsPoints(false);
cmgr->setFlagLines(false);
cmgr->setFlagLabels(false);
cmgr->setFlagBoundaries(false);
cmgr->setFlagArt(false);
smgr->setFlagLabels(false);
ssmgr->setFlagLabels(false);
nmgr->setFlagHints(false);
lmgr->setFlagLandscape(true);
lmgr->setFlagAtmosphere(true);
lmgr->setFlagFog(true);
}
else if (state.toLower() == "starchart")
{
nav->setEquatorialMount(true);
skyd->setFlagTwinkle(false);
skyd->setFlagLuminanceAdaptation(false);
ssmgr->setFlagPlanets(true);
ssmgr->setFlagHints(false);
ssmgr->setFlagOrbits(false);
ssmgr->setFlagMoonScale(false);
ssmgr->setFlagTrails(false);
mmgr->setZHR(0);
glmgr->setFlagAzimuthalGrid(false);
glmgr->setFlagEquatorGrid(true);
glmgr->setFlagEquatorLine(false);
glmgr->setFlagEclipticLine(false);
glmgr->setFlagMeridianLine(false);
glmgr->setFlagEquatorJ2000Grid(false);
lmgr->setFlagCardinalsPoints(false);
cmgr->setFlagLines(true);
cmgr->setFlagLabels(true);
cmgr->setFlagBoundaries(true);
cmgr->setFlagArt(false);
smgr->setFlagLabels(true);
ssmgr->setFlagLabels(true);
nmgr->setFlagHints(true);
lmgr->setFlagLandscape(false);
lmgr->setFlagAtmosphere(false);
lmgr->setFlagFog(false);
}
else if (state.toLower() == "deepspace")
{
nav->setEquatorialMount(true);
skyd->setFlagTwinkle(false);
skyd->setFlagLuminanceAdaptation(false);
ssmgr->setFlagPlanets(false);
ssmgr->setFlagHints(false);
ssmgr->setFlagOrbits(false);
ssmgr->setFlagMoonScale(false);
ssmgr->setFlagTrails(false);
mmgr->setZHR(0);
glmgr->setFlagAzimuthalGrid(false);
glmgr->setFlagEquatorGrid(false);
glmgr->setFlagEquatorLine(false);
glmgr->setFlagEclipticLine(false);
glmgr->setFlagMeridianLine(false);
glmgr->setFlagEquatorJ2000Grid(false);
lmgr->setFlagCardinalsPoints(false);
cmgr->setFlagLines(false);
cmgr->setFlagLabels(false);
cmgr->setFlagBoundaries(false);
cmgr->setFlagArt(false);
smgr->setFlagLabels(false);
ssmgr->setFlagLabels(false);
nmgr->setFlagHints(false);
lmgr->setFlagLandscape(false);
lmgr->setFlagAtmosphere(false);
lmgr->setFlagFog(false);
}
else
{
qWarning() << "WARNING clear(" << state << ") - state not kn
own";
}
}
void StelMainScriptAPI::moveToAltAzi(const QString& alt, const QString& azi
, float duration)
{
StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
Q_ASSERT(mvmgr);
GETSTELMODULE(StelObjectMgr)->unSelect();
Vec3d aim;
double dAlt = StelUtils::getDecAngle(alt);
double dAzi = M_PI - StelUtils::getDecAngle(azi);
StelUtils::spheToRect(dAzi,dAlt,aim);
mvmgr->moveTo(aim, duration, true);
}
void StelMainScriptAPI::moveToRaDec(const QString& ra, const QString& dec,
float duration)
{
StelMovementMgr* mvmgr = GETSTELMODULE(StelMovementMgr);
Q_ASSERT(mvmgr);
GETSTELMODULE(StelObjectMgr)->unSelect();
Vec3d aim;
double dRa = StelUtils::getDecAngle(ra);
double dDec = StelUtils::getDecAngle(dec);
StelUtils::spheToRect(dRa,dDec,aim);
mvmgr->moveTo(aim, duration, false);
}
StelScriptMgr::StelScriptMgr(QObject *parent) StelScriptMgr::StelScriptMgr(QObject *parent)
: QObject(parent), : QObject(parent),
thread(NULL) thread(NULL)
{ {
// Allow Vec3f managment in scripts // Allow Vec3f managment in scripts
qScriptRegisterMetaType(&engine, vec3fToScriptValue, vec3fFromScript Value); qScriptRegisterMetaType(&engine, vec3fToScriptValue, vec3fFromScript Value);
// Constructor // Constructor
QScriptValue ctor = engine.newFunction(createVec3f); QScriptValue ctor = engine.newFunction(createVec3f);
engine.globalObject().setProperty("Vec3f", ctor); engine.globalObject().setProperty("Vec3f", ctor);
// Add the core object to access methods related to core // Add the core object to access methods related to core
StelMainScriptAPI *mainAPI = new StelMainScriptAPI(this); mainAPI = new StelMainScriptAPI(this);
QScriptValue objectValue = engine.newQObject(mainAPI); QScriptValue objectValue = engine.newQObject(mainAPI);
engine.globalObject().setProperty("core", objectValue); engine.globalObject().setProperty("core", objectValue);
// Add all the StelModules into the script engine // Add all the StelModules into the script engine
StelModuleMgr* mmgr = &StelApp::getInstance().getModuleMgr(); StelModuleMgr* mmgr = &StelApp::getInstance().getModuleMgr();
foreach (StelModule* m, mmgr->getAllModules()) foreach (StelModule* m, mmgr->getAllModules())
{ {
objectValue = engine.newQObject(m); objectValue = engine.newQObject(m);
engine.globalObject().setProperty(m->objectName(), objectVal ue); engine.globalObject().setProperty(m->objectName(), objectVal ue);
} }
// Add other classes which we want to be directly accessible from sc ripts // Add other classes which we want to be directly accessible from sc ripts
if(StelSkyImageMgr* smgr = GETSTELMODULE(StelSkyImageMgr)) if(StelSkyLayerMgr* smgr = GETSTELMODULE(StelSkyLayerMgr))
objectValue = engine.newQObject(smgr); objectValue = engine.newQObject(smgr);
// For accessing star scale, twinkle etc.
objectValue = engine.newQObject(StelApp::getInstance().getCore()->ge
tSkyDrawer());
engine.globalObject().setProperty("StelSkyDrawer", objectValue);
} }
StelScriptMgr::~StelScriptMgr() StelScriptMgr::~StelScriptMgr()
{ {
} }
QStringList StelScriptMgr::getScriptList(void) QStringList StelScriptMgr::getScriptList(void)
{ {
QStringList scriptFiles; QStringList scriptFiles;
try try
{ {
StelFileMgr& fileMan(StelApp::getInstance().getFileMgr()); QSet<QString> files = StelFileMgr::listContents("scripts", S
QSet<QString> files = fileMan.listContents("scripts",StelFil telFileMgr::File, true);
eMgr::File, true);
foreach(QString f, files) foreach(QString f, files)
{ {
#ifdef ENABLE_STRATOSCRIPT_COMPAT #ifdef ENABLE_STRATOSCRIPT_COMPAT
QRegExp fileRE("^.*\\.(ssc|sts)$"); QRegExp fileRE("^.*\\.(ssc|sts)$");
#else // ENABLE_STRATOSCRIPT_COMPAT #else // ENABLE_STRATOSCRIPT_COMPAT
QRegExp fileRE("^.*\\.ssc$"); QRegExp fileRE("^.*\\.ssc$");
#endif // ENABLE_STRATOSCRIPT_COMPAT #endif // ENABLE_STRATOSCRIPT_COMPAT
if (fileRE.exactMatch(f)) if (fileRE.exactMatch(f))
scriptFiles << f; scriptFiles << f;
} }
} }
catch (std::runtime_error& e) catch (std::runtime_error& e)
{ {
qWarning() << "WARNING: could not list scripts:" << e.what() QString msg = QString("WARNING: could not list scripts: %1")
; .arg(e.what());
qWarning() << msg;
emit(scriptDebug(msg));
} }
return scriptFiles; return scriptFiles;
} }
bool StelScriptMgr::scriptIsRunning(void) bool StelScriptMgr::scriptIsRunning(void)
{ {
return (thread != NULL); return (thread != NULL);
} }
QString StelScriptMgr::runningScriptId(void) QString StelScriptMgr::runningScriptId(void)
skipping to change at line 693 skipping to change at line 177
if (thread) if (thread)
return thread->getFileName(); return thread->getFileName();
else else
return QString(); return QString();
} }
const QString StelScriptMgr::getHeaderSingleLineCommentText(const QString& s, const QString& id, const QString& notFoundText) const QString StelScriptMgr::getHeaderSingleLineCommentText(const QString& s, const QString& id, const QString& notFoundText)
{ {
try try
{ {
QFile file(StelApp::getInstance().getFileMgr().findFile("scr ipts/" + s, StelFileMgr::File)); QFile file(StelFileMgr::findFile("scripts/" + s, StelFileMgr ::File));
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{ {
qWarning() << "script file " << s << " could not be QString msg = QString("WARNING: script file %1 could
opened for reading"; not be opened for reading").arg(s);
emit(scriptDebug(msg));
qWarning() << msg;
return QString(); return QString();
} }
QRegExp nameExp("^\\s*//\\s*" + id + ":\\s*(.+)$"); QRegExp nameExp("^\\s*//\\s*" + id + ":\\s*(.+)$");
while (!file.atEnd()) { while (!file.atEnd()) {
QString line(file.readLine()); QString line(file.readLine());
if (nameExp.exactMatch(line)) if (nameExp.exactMatch(line))
{ {
file.close(); file.close();
return nameExp.capturedTexts().at(1); return nameExp.capturedTexts().at(1);
} }
} }
file.close(); file.close();
return notFoundText; return notFoundText;
} }
catch(std::runtime_error& e) catch(std::runtime_error& e)
{ {
qWarning() << "script file " << s << " could not be found:" QString msg = QString("WARNING: script file %1 could not be
<< e.what(); found: %2").arg(s).arg(e.what());
emit(scriptDebug(msg));
qWarning() << msg;
return QString(); return QString();
} }
} }
const QString StelScriptMgr::getName(const QString& s) const QString StelScriptMgr::getName(const QString& s)
{ {
return getHeaderSingleLineCommentText(s, "Name", s); return getHeaderSingleLineCommentText(s, "Name", s);
} }
const QString StelScriptMgr::getAuthor(const QString& s) const QString StelScriptMgr::getAuthor(const QString& s)
skipping to change at line 738 skipping to change at line 226
const QString StelScriptMgr::getLicense(const QString& s) const QString StelScriptMgr::getLicense(const QString& s)
{ {
return getHeaderSingleLineCommentText(s, "License", ""); return getHeaderSingleLineCommentText(s, "License", "");
} }
const QString StelScriptMgr::getDescription(const QString& s) const QString StelScriptMgr::getDescription(const QString& s)
{ {
try try
{ {
QFile file(StelApp::getInstance().getFileMgr().findFile("scr ipts/" + s, StelFileMgr::File)); QFile file(StelFileMgr::findFile("scripts/" + s, StelFileMgr ::File));
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
{ {
qWarning() << "script file " << s << " could not be QString msg = QString("WARNING: script file %1 could
opened for reading"; not be opened for reading").arg(s);
emit(scriptDebug(msg));
qWarning() << msg;
return QString(); return QString();
} }
QString desc = ""; QString desc = "";
bool inDesc = false; bool inDesc = false;
QRegExp descExp("^\\s*//\\s*Description:\\s*([^\\s].+)\\s*$" ); QRegExp descExp("^\\s*//\\s*Description:\\s*([^\\s].+)\\s*$" );
QRegExp descNewlineExp("^\\s*//\\s*$"); QRegExp descNewlineExp("^\\s*//\\s*$");
QRegExp descContExp("^\\s*//\\s*([^\\s].*)\\s*$"); QRegExp descContExp("^\\s*//\\s*([^\\s].*)\\s*$");
while (!file.atEnd()) { while (!file.atEnd()) {
QString line(file.readLine()); QString line(file.readLine());
skipping to change at line 782 skipping to change at line 272
return desc; return desc;
} }
desc += d; desc += d;
} }
} }
file.close(); file.close();
return desc; return desc;
} }
catch(std::runtime_error& e) catch(std::runtime_error& e)
{ {
qWarning() << "script file " << s << " could not be found:" QString msg = QString("WARNING: script file %1 could not be
<< e.what(); found: %2").arg(s).arg(e.what());
emit(scriptDebug(msg));
qWarning() << msg;
return QString(); return QString();
} }
} }
// Run the script located at the given location // Run the script located at the given location
bool StelScriptMgr::runScript(const QString& fileName) bool StelScriptMgr::runScript(const QString& fileName, const QString& inclu dePath)
{ {
if (thread!=NULL) if (thread!=NULL)
{ {
qWarning() << "ERROR: there is already a script running, ple QString msg = QString("ERROR: there is already a script runn
ase wait that it's over."; ing, please wait that it's over.");
emit(scriptDebug(msg));
qWarning() << msg;
return false; return false;
} }
QString absPath; QString absPath;
QString scriptDir; QString scriptDir;
try try
{ {
absPath = StelApp::getInstance().getFileMgr().findFile("scri if (QFileInfo(fileName).isAbsolute())
pts/" + fileName); absPath = fileName;
else
absPath = StelFileMgr::findFile("scripts/" + fileNam
e);
scriptDir = QFileInfo(absPath).dir().path(); scriptDir = QFileInfo(absPath).dir().path();
} }
catch (std::runtime_error& e) catch (std::runtime_error& e)
{ {
qWarning() << "WARNING: could not find script file " << file QString msg = QString("WARNING: could not find script file %
Name << ": " << e.what(); 1: %2").arg(fileName).arg(e.what());
emit(scriptDebug(msg));
qWarning() << msg;
return false; return false;
} }
// pre-process the script into a temporary file // pre-process the script into a temporary file
QTemporaryFile tmpFile; QTemporaryFile tmpFile;
bool ok = false; bool ok = false;
if (!tmpFile.open()) if (!tmpFile.open())
{ {
qWarning() << "WARNING: cannot create temporary file for scr QString msg = QString("WARNING: cannot create temporary file
ipt pre-processing"; for script pre-processing");
emit(scriptDebug(msg));
qWarning() << msg;
return false; return false;
} }
QFile fic(absPath); QFile fic(absPath);
if (!fic.open(QIODevice::ReadOnly)) if (!fic.open(QIODevice::ReadOnly))
{ {
qWarning() << "WARNING: cannot open script:" << fileName; QString msg = QString("WARNING: cannot open script: %1").arg
(fileName);
emit(scriptDebug(msg));
qWarning() << msg;
tmpFile.close(); tmpFile.close();
return false; return false;
} }
if (includePath!="" && !includePath.isEmpty())
scriptDir = includePath;
if (fileName.right(4) == ".ssc") if (fileName.right(4) == ".ssc")
ok = preprocessScript(fic, tmpFile, scriptDir); ok = preprocessScript(fic, tmpFile, scriptDir);
#ifdef ENABLE_STRATOSCRIPT_COMPAT #ifdef ENABLE_STRATOSCRIPT_COMPAT
else if (fileName.right(4) == ".sts") else if (fileName.right(4) == ".sts")
ok = preprocessStratoScript(fic, tmpFile, scriptDir); ok = preprocessStratoScript(fic, tmpFile, scriptDir);
#endif #endif
fic.close(); fic.close();
if (ok==false) if (ok==false)
skipping to change at line 852 skipping to change at line 359
connect(thread, SIGNAL(finished()), this, SLOT(scriptEnded())); connect(thread, SIGNAL(finished()), this, SLOT(scriptEnded()));
thread->start(); thread->start();
emit(scriptRunning()); emit(scriptRunning());
return true; return true;
} }
bool StelScriptMgr::stopScript(void) bool StelScriptMgr::stopScript(void)
{ {
if (thread) if (thread)
{ {
qDebug() << "asking running script to exit"; QString msg = QString("INFO: asking running script to exit")
;
emit(scriptDebug(msg));
qDebug() << msg;
thread->terminate(); thread->terminate();
return true; return true;
} }
else else
{ {
qWarning() << "StelScriptMgr::stopScript - no script is runn QString msg = QString("WARNING: no script is running");
ing"; emit(scriptDebug(msg));
qWarning() << msg;
return false; return false;
} }
} }
void StelScriptMgr::setScriptRate(double r)
{
// pre-calculate the new time rate in an effort to prevent there bei
ng much latency
// between setting the script rate and the time rate.
double factor = r / mainAPI->getScriptSleeper().getRate();
StelNavigator* nav = StelApp::getInstance().getCore()->getNavigator(
);
double newTimeRate = nav->getTimeRate() * factor;
mainAPI->getScriptSleeper().setRate(r);
if (scriptIsRunning())
nav->setTimeRate(newTimeRate);
GETSTELMODULE(StelMovementMgr)->setMovementSpeedFactor(newTimeRate);
}
double StelScriptMgr::getScriptRate(void)
{
return mainAPI->getScriptSleeper().getRate();
}
void StelScriptMgr::debug(const QString& msg)
{
emit(scriptDebug(msg));
}
void StelScriptMgr::scriptEnded() void StelScriptMgr::scriptEnded()
{ {
delete thread; mainAPI->getScriptSleeper().setRate(1);
thread->deleteLater();
thread=NULL; thread=NULL;
if (engine.hasUncaughtException()) if (engine.hasUncaughtException())
{ {
qWarning() << "Script error: " << engine.uncaughtException() QString msg = QString("script error: \"%1\" @ line %2").arg(
.toString() << "@ line" << engine.uncaughtExceptionLineNumber(); engine.uncaughtException().toString()).arg(engine.uncaughtExceptionLineNumb
er());
emit(scriptDebug(msg));
qWarning() << msg;
} }
emit(scriptStopped()); emit(scriptStopped());
} }
QMap<QString, QString> StelScriptMgr::mappify(const QStringList& args, bool
lowerKey)
{
QMap<QString, QString> map;
for(int i=0; i+1<args.size(); i++)
if (lowerKey)
map[args.at(i).toLower()] = args.at(i+1);
else
map[args.at(i)] = args.at(i+1);
return map;
}
bool StelScriptMgr::strToBool(const QString& str)
{
if (str.toLower() == "off" || str.toLower() == "no")
return false;
else if (str.toLower() == "on" || str.toLower() == "yes")
return true;
return QVariant(str).toBool();
}
bool StelScriptMgr::preprocessScript(QFile& input, QFile& output, const QSt
ring& scriptDir)
{
while (!input.atEnd())
{
QString line = QString::fromUtf8(input.readLine());
QRegExp includeRe("^include\\s*\\(\\s*\"([^\"]+)\"\\s*\\)\\s
*;\\s*(//.*)?$");
if (includeRe.exactMatch(line))
{
QString fileName = includeRe.capturedTexts().at(1);
QString path;
// Search for the include file. Rules are:
// 1. If path is absolute, just use that
// 2. If path is relative, look in scriptDir + inclu
ded filename
if (QFileInfo(fileName).isAbsolute())
path = fileName;
else
{
try
{
path = StelFileMgr::findFile(scriptD
ir + "/" + fileName);
}
catch(std::runtime_error& e)
{
qWarning() << "WARNING: script inclu
de:" << fileName << e.what();
return false;
}
}
QFile fic(path);
bool ok = fic.open(QIODevice::ReadOnly);
if (ok)
{
qDebug() << "script include: " << path;
preprocessScript(fic, output, scriptDir);
}
else
{
qWarning() << "WARNING: could not open scrip
t include file for reading:" << path;
return false;
}
}
else
{
output.write(line.toUtf8());
}
}
return true;
}
 End of changes. 37 change blocks. 
637 lines changed or deleted 111 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/