Implementation of the new interface for legacy scripting

pull/3/head
Hleb Valoshka 2019-10-18 22:54:50 +03:00
parent dfd177ffc7
commit 2c2a17aa0a
5 changed files with 188 additions and 115 deletions

View File

@ -108,41 +108,6 @@ static bool is_valid_directory(const fs::path& dir)
}
// Extremely basic implementation of an ExecutionEnvironment for
// running scripts.
class CoreExecutionEnvironment : public ExecutionEnvironment
{
private:
CelestiaCore& core;
public:
CoreExecutionEnvironment(CelestiaCore& _core) : core(_core)
{
}
Simulation* getSimulation() const
{
return core.getSimulation();
}
Renderer* getRenderer() const
{
return core.getRenderer();
}
CelestiaCore* getCelestiaCore() const
{
return &core;
}
void showText(string s, int horig, int vorig, int hoff, int voff,
double duration)
{
core.showText(s, horig, vorig, hoff, voff, duration);
}
};
// If right dragging to rotate, adjust the rotation rate based on the
// distance from the reference object. This makes right drag rotation
// useful even when the camera is very near the surface of an object.
@ -179,7 +144,7 @@ CelestiaCore::CelestiaCore() :
routine will be called much later. */
renderer(new Renderer()),
timer(new Timer()),
execEnv(new CoreExecutionEnvironment(*this)),
m_legacyPlugin(make_unique<LegacyScriptPlugin>(this)),
m_luaPlugin(make_unique<LuaScriptPlugin>(this)),
m_scriptMaps(make_shared<ScriptMaps>())
{
@ -202,7 +167,6 @@ CelestiaCore::~CelestiaCore()
if (movieCapture != nullptr)
recordEnd();
delete execEnv;
delete timer;
delete renderer;
}
@ -314,13 +278,6 @@ void showSelectionInfo(const Selection& sel)
void CelestiaCore::cancelScript()
{
if (runningScript != nullptr)
{
delete runningScript;
scriptState = ScriptCompleted;
runningScript = nullptr;
}
#ifdef CELX
if (m_script != nullptr)
{
if (textEnterMode & KbPassToScript)
@ -328,18 +285,6 @@ void CelestiaCore::cancelScript()
scriptState = ScriptCompleted;
m_script = nullptr;
}
#endif
}
void CelestiaCore::runScript(CommandSequence* script)
{
cancelScript();
if (runningScript == nullptr && script != nullptr && scriptState == ScriptCompleted)
{
scriptState = ScriptRunning;
runningScript = new Execution(*script, *execEnv);
}
}
@ -347,33 +292,12 @@ void CelestiaCore::runScript(const fs::path& filename)
{
cancelScript();
auto localeFilename = LocaleFilename(filename);
ContentType type = DetermineFileType(localeFilename);
if (type == Content_CelestiaLegacyScript)
if (m_legacyPlugin->isOurFile(localeFilename))
{
ifstream scriptfile(localeFilename.string());
if (!scriptfile.good())
{
fatalError(_("Error opening script file."));
}
else
{
CommandParser parser(scriptfile, m_scriptMaps);
CommandSequence* script = parser.parse();
if (script == nullptr)
{
const vector<string>* errors = parser.getErrors();
string errorMsg;
if (errors->size() > 0)
errorMsg = (*errors)[0];
fatalError(errorMsg);
}
else
{
runningScript = new Execution(*script, *execEnv);
scriptState = sim->getPauseState()?ScriptPaused:ScriptRunning;
}
}
m_script = m_legacyPlugin->loadScript(localeFilename);
if (m_script != nullptr)
scriptState = sim->getPauseState() ? ScriptPaused : ScriptRunning;
}
#ifdef CELX
else if (m_luaPlugin->isOurFile(localeFilename))
@ -1316,11 +1240,7 @@ void CelestiaCore::charEntered(const char *c_p, int modifiers)
// If there's a script running then pause it. This has the
// potentially confusing side effect of rendering nonfunctional
// goto, center, and other movement commands.
#ifdef CELX
if (runningScript != nullptr || m_script != nullptr)
#else
if (runningScript != nullptr)
#endif
if (m_script != nullptr)
{
if (scriptState == ScriptRunning)
scriptState = ScriptPaused;
@ -2132,14 +2052,6 @@ void CelestiaCore::tick()
}
// If there's a script running, tick it
if (runningScript != nullptr)
{
bool finished = runningScript->tick(dt);
if (finished)
cancelScript();
}
#ifdef CELX
if (m_script != nullptr)
{
m_script->handleTickEvent(dt);
@ -2150,7 +2062,6 @@ void CelestiaCore::tick()
cancelScript();
}
}
#endif // CELX
if (m_scriptHook != nullptr)
m_scriptHook->call("tick", dt);
@ -3029,16 +2940,8 @@ void CelestiaCore::renderOverlay()
overlay->begin();
#ifdef CELX
if (runningScript || m_script != nullptr)
{
#else
if (runningScript)
{
#endif
if (image != nullptr)
image->render((float) currentTime, width, height);
}
if (m_script != nullptr && image != nullptr)
image->render((float) currentTime, width, height);
if (views.size() > 1)
{

View File

@ -15,8 +15,6 @@
// #include <celutil/watchable.h>
#include <celengine/solarsys.h>
#include <celengine/overlay.h>
#include <celscript/legacy/command.h>
#include <celscript/legacy/execution.h>
#include <celengine/texture.h>
#include <celengine/universe.h>
#include <celengine/render.h>
@ -33,6 +31,7 @@
#include <celscript/lua/luascript.h>
#endif
#include <celscript/common/script.h>
#include <celscript/legacy/legacyscript.h>
#include <celscript/common/scriptmaps.h>
class Url;
@ -247,7 +246,6 @@ class CelestiaCore // : public Watchable<CelestiaCore>
bool isCaptureActive();
bool isRecording();
void runScript(CommandSequence*);
void runScript(const fs::path& filename);
void cancelScript();
void resumeScript();
@ -395,13 +393,11 @@ class CelestiaCore // : public Watchable<CelestiaCore>
Timer* timer{ nullptr };
Execution* runningScript{ nullptr };
ExecutionEnvironment* execEnv{ nullptr };
std::unique_ptr<celestia::scripts::IScript> m_script;
std::unique_ptr<celestia::scripts::IScriptHook> m_scriptHook;
std::unique_ptr<celestia::scripts::LuaScriptPlugin> m_luaPlugin;
std::shared_ptr<celestia::scripts::ScriptMaps> m_scriptMaps;
std::unique_ptr<celestia::scripts::IScript> m_script;
std::unique_ptr<celestia::scripts::IScriptHook> m_scriptHook;
std::unique_ptr<celestia::scripts::LegacyScriptPlugin> m_legacyPlugin;
std::unique_ptr<celestia::scripts::LuaScriptPlugin> m_luaPlugin;
std::shared_ptr<celestia::scripts::ScriptMaps> m_scriptMaps;
enum ScriptState
{

View File

@ -6,6 +6,8 @@ set(LEGACY_SOURCES
execenv.h
execution.cpp
execution.h
legacyscript.cpp
legacyscript.h
)
add_library(cellegacyscript OBJECT ${LEGACY_SOURCES})

View File

@ -0,0 +1,114 @@
// legacyscript.cpp
//
// Copyright (C) 2019, the Celestia Development Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#include <fstream>
#include <string>
#include <celcompat/filesystem.h>
#include <celcompat/memory.h>
#include <celestia/celestiacore.h>
#include <celutil/util.h>
#include "legacyscript.h"
#include "cmdparser.h"
#include "execution.h"
using namespace std;
namespace celestia
{
namespace scripts
{
// Extremely basic implementation of an ExecutionEnvironment for
// running scripts.
class CoreExecutionEnvironment : public ExecutionEnvironment
{
private:
CelestiaCore& core;
public:
CoreExecutionEnvironment(CelestiaCore& _core) : core(_core)
{
}
Simulation* getSimulation() const
{
return core.getSimulation();
}
Renderer* getRenderer() const
{
return core.getRenderer();
}
CelestiaCore* getCelestiaCore() const
{
return &core;
}
void showText(string s, int horig, int vorig, int hoff, int voff,
double duration)
{
core.showText(s, horig, vorig, hoff, voff, duration);
}
};
LegacyScript::LegacyScript(CelestiaCore *core) :
m_appCore(core),
m_execEnv(make_unique<CoreExecutionEnvironment>(*core))
{
}
bool LegacyScript::load(ifstream &scriptfile, const fs::path &path, string &errorMsg)
{
CommandParser parser(scriptfile, m_appCore->scriptMaps());
CommandSequence* script = parser.parse();
if (script == nullptr)
{
const vector<string>* errors = parser.getErrors();
if (errors->size() > 0)
errorMsg = (*errors)[0];
return false;
}
m_runningScript = make_unique<Execution>(*script, *m_execEnv);
return true;
}
bool LegacyScript::tick(double dt)
{
return m_runningScript->tick(dt);
}
bool LegacyScriptPlugin::isOurFile(const fs::path &p) const
{
return p.extension() == ".cel";
}
unique_ptr<IScript> LegacyScriptPlugin::loadScript(const fs::path &path)
{
ifstream scriptfile(path.string());
if (!scriptfile.good())
{
appCore()->fatalError(_("Error opening script file."));
return nullptr;
}
auto script = make_unique<LegacyScript>(appCore());
string errorMsg;
if (!script->load(scriptfile, path, errorMsg))
{
if (errorMsg.empty())
errorMsg = _("Unknown error loading script");
appCore()->fatalError(errorMsg);
return nullptr;
}
return script;
}
}
}

View File

@ -0,0 +1,58 @@
// legacyscript.h
//
// Copyright (C) 2019, the Celestia Development Team
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
#pragma once
#include <celscript/common/script.h>
#include <iosfwd>
class Execution;
class ExecutionEnvironment;
class CelestiaCore;
namespace celestia
{
namespace scripts
{
class LegacyScript : public IScript
{
public:
LegacyScript(CelestiaCore*);
~LegacyScript() override = default;
bool load(std::ifstream&, const fs::path&, std::string&);
bool tick(double) override;
private:
CelestiaCore *m_appCore;
std::unique_ptr<Execution> m_runningScript;
std::unique_ptr<ExecutionEnvironment> m_execEnv;
friend class LegacyScriptPlugin;
};
class LegacyScriptPlugin : public IScriptPlugin
{
public:
LegacyScriptPlugin() = delete;
LegacyScriptPlugin(CelestiaCore *appCore) : IScriptPlugin(appCore) {};
~LegacyScriptPlugin() override = default;
LegacyScriptPlugin(const LegacyScriptPlugin&) = delete;
LegacyScriptPlugin(LegacyScriptPlugin&&) = delete;
LegacyScriptPlugin& operator=(const LegacyScriptPlugin&) = delete;
LegacyScriptPlugin& operator=(LegacyScriptPlugin&&) = delete;
bool isOurFile(const fs::path&) const override;
std::unique_ptr<IScript> loadScript(const fs::path&) override;
};
}
}