From f0dfd0fa043072f95b9a721ff144b558e6cc0e03 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Sun, 14 Sep 2014 17:36:10 +0200 Subject: [PATCH] Added documentation for Time class --- include/openspace/scripting/scriptengine.h | 4 + include/openspace/util/time.h | 117 +++++++++++- src/engine/openspaceengine.cpp | 7 +- src/util/time.cpp | 197 ++++++++++++--------- 4 files changed, 232 insertions(+), 93 deletions(-) diff --git a/include/openspace/scripting/scriptengine.h b/include/openspace/scripting/scriptengine.h index 186c986d5b..648bc0ca12 100644 --- a/include/openspace/scripting/scriptengine.h +++ b/include/openspace/scripting/scriptengine.h @@ -28,6 +28,10 @@ #include #include +/** + * \defgroup LuaScripts Lua Scripts + */ + namespace openspace { namespace scripting { diff --git a/include/openspace/util/time.h b/include/openspace/util/time.h index 5972bf5b63..2e1b48c6c4 100644 --- a/include/openspace/util/time.h +++ b/include/openspace/util/time.h @@ -26,42 +26,141 @@ #define __TIME_H__ #include - #include namespace openspace { +/** + * This singleton class represents the current simulation time in OpenSpace. It + * internally stores the time and provides methods to set the time directly + * (setTime(double), setTime(std::string)) using a double value using the + * number of seconds passed since the J2000 epoch or a string that denotes + * a valid date string in accordance to the Spice library + * (http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/str2et_c.html). The time can + * be retrieved as the number of seconds since the J2000 epoch with currentTime() or as a + * UTC string following ISO 8601 with the method currentTimeUTC(). + * + * In addition to the time itself, it also stores a delta time value. This value denotes + * the number of seconds that pass for each real-time second. This value is set with + * setDeltaTime(double), retrieved with deltaTime() and solely used in the + * advanceTime(double), which takes a tickTime parameter. The value of the + * parameter is dependent on the usage of the class and must be equal to the real-world + * time that has passed since the last call to the method. For example, if the + * advanceTime(double) method is called each frame, the tickTime has to be + * equal to the frame time. + */ class Time { public: - static bool initialize(); + /** + * Initializes the Time singleton and loads an LSK spice kernel with the provided + * name. + * \param lskKernel The name of the kernel that should be loaded during the + * initialization. If the parameter is empty, no kernel will be loaded + * \return true if the initialization succeeded, false + * otherwise + */ + static bool initialize(const std::string& lskKernel = ""); + + /** + * Deinitializes the Time singleton. This method will not unload the kernel that was + * possibly loaded during the initialize method. + */ static void deinitialize(); + + /** + * Returns the reference to the Time singleton object. + * \return The reference to the Time singleton object + */ static Time& ref(); + + /** + * Returns true if the singleton has been successfully initialized, + * false otherwise + * \return true if the singleton has been successfully initialized, + * false otherwise + */ static bool isInitialized(); - double advanceTime(double tickTime); - + /** + * Sets the current time to the specified value in seconds past the J2000 epoch. This + * value can be negative to represent dates before the epoch. + * \param The number of seconds after the J2000 epoch + */ void setTime(double value); - double currentTime() const; + + /** + * Sets the current time to the specified value given as a Spice compliant string as + * described in the Spice documentation + * (http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/str2et_c.html) + * \param time The time to be set as a date string + */ void setTime(std::string time); + + /** + * Returns the current time as the number of seconds past the J2000 epoch. If the + * current time is a date before that epoch, the returned value will be negative. + * \return The current time as the number of seconds past the J2000 epoch + */ + double currentTime() const; + + /** + * Returns the current time as a formatted date string compliant with ISO 8601 and + * thus also compliant with the Spice library. + * \return The current time as a formatted date string + */ std::string currentTimeUTC() const; + /** + * Sets the delta time value that is the number of seconds that should pass for each + * real-time second. This value is used in the advanceTime(double) method to easily + * advance the simulation time. + * \param deltaT The number of seconds that should pass for each real-time second + */ void setDeltaTime(double deltaT); + + /** + * Returns the delta time, that is the number of seconds that pass in the simulation + * for each real-time second + * \return The number of seconds that pass for each real-time second + */ double deltaTime() const; + /** + * Advances the simulation time using the deltaTime() and the tickTime. + * The deltaTime() is the number of simulation seconds that pass for each real-time + * second. tickTime is the number of real-time seconds that passed since + * the last call to this method. If this method is called in the render loop, the + * tickTime should be equivalent to the frame time. + * \param tickTime The number of real-time seconds that passed since the last call + * to this method + * \return The new time value after advancing the time + */ + double advanceTime(double tickTime); + + /** + * Returns the Lua library that contains all Lua functions available to change the + * current time, retrieve the current time etc. The functions contained are + * - time_setDeltaTime + * - time_deltaTime + * - time_currentTime + * - time_currentTimeUTC + * \return The Lua library that contains all Lua functions available to change the + * Time singleton + */ static scripting::ScriptEngine::LuaLibrary luaLibrary(); private: + /// Creates the time object. Only used in the initialize() method Time(); Time(const Time& src) = delete; Time& operator=(const Time& rhs) = delete; - static Time* _instance; - double _time; + static Time* _instance; ///< The singleton instance + double _time; ///< The time stored as the number of seconds past the J2000 epoch - double _deltaTimePerSecond; + double _deltaTimePerSecond; ///< The delta time that is used to advance the time }; - } // namespace openspace #endif // __TIME_H__ diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 01ec011aa2..f30dd8d8c1 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -323,10 +323,15 @@ bool OpenSpaceEngine::initialize() SysCap.detectCapabilities(); SysCap.logCapabilities(); + std::string timeKernel = ""; + using constants::openspaceengine::keyConfigTimekernel; + if (OsEng.configurationManager().hasKeyAndValue(keyConfigTimekernel)) { + OsEng.configurationManager().getValue(keyConfigTimekernel, timeKernel); + } // initialize OpenSpace helpers SpiceManager::initialize(); - Time::initialize(); + Time::initialize(timeKernel); Spice::init(); Spice::ref().loadDefaultKernels(); FactoryManager::initialize(); diff --git a/src/util/time.cpp b/src/util/time.cpp index a1c6a2ed91..854b38d70c 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -36,78 +36,112 @@ namespace { const std::string _loggerCat = "Time"; - - //tag_error(L, narg, LUA_TNUMBER); - - int time_setDeltaTime(lua_State* L) { - const bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return luaL_error(L, "bad argument (%s)", msg); - } - - const bool isNumber = (lua_isnumber(L, -1) != 0); - if (isNumber) { - double value = lua_tonumber(L, -1); - openspace::Time::ref().setDeltaTime(value); - return 0; - } - else { - const char* msg = lua_pushfstring(L, "%s expected, got %s", - lua_typename(L, LUA_TNUMBER), luaL_typename(L, -1)); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } - - } - - int time_deltaTime(lua_State* L) { - lua_pushnumber(L, openspace::Time::ref().deltaTime()); - return 1; - } - - int time_setTime(lua_State* L) { - const bool isFunction = (lua_isfunction(L, -1) != 0); - if (isFunction) { - // If the top of the stack is a function, it is ourself - const char* msg = lua_pushfstring(L, "method called without argument"); - return luaL_error(L, "bad argument (%s)", 1, msg); - } - - const bool isNumber = (lua_isnumber(L, -1) != 0); - const bool isString = (lua_isstring(L, -1) != 0); - if (!isNumber && !isString) { - const char* msg = lua_pushfstring(L, "%s or %s expected, got %s", - lua_typename(L, LUA_TNUMBER), - lua_typename(L, LUA_TSTRING), luaL_typename(L, -1)); - return luaL_error(L, "bad argument #%d (%s)", 1, msg); - } - if (isNumber) { - double value = lua_tonumber(L, -1); - openspace::Time::ref().setTime(value); - return 0; - } - if (isString) { - const char* time = lua_tostring(L, -1); - openspace::Time::ref().setTime(time); - return 0; - } - return 0; - } - - int time_currentTime(lua_State* L) { - lua_pushnumber(L, openspace::Time::ref().currentTime()); - return 1; - } - - int time_currentTimeUTC(lua_State* L) { - lua_pushstring(L, openspace::Time::ref().currentTimeUTC().c_str()); - return 1; - } } namespace openspace { +namespace luascriptfunctions { + +/** + * \ingroup LuaScripts + * setDeltaTime(number): + * Sets the delta time by calling the Time::setDeltaTime method + */ +int time_setDeltaTime(lua_State* L) { + const bool isFunction = (lua_isfunction(L, -1) != 0); + if (isFunction) { + // If the top of the stack is a function, it is ourself + const char* msg = lua_pushfstring(L, "method called without argument"); + return luaL_error(L, "bad argument (%s)", msg); + } + + const bool isNumber = (lua_isnumber(L, -1) != 0); + if (isNumber) { + double value = lua_tonumber(L, -1); + openspace::Time::ref().setDeltaTime(value); + return 0; + } + else { + const char* msg = lua_pushfstring(L, "%s expected, got %s", + lua_typename(L, LUA_TNUMBER), luaL_typename(L, -1)); + return luaL_error(L, "bad argument #%d (%s)", 1, msg); + } + +} + +/** + * \ingroup LuaScripts + * deltaTime(): + * Returns the delta time by calling the Time::deltaTime method + */ +int time_deltaTime(lua_State* L) { + lua_pushnumber(L, openspace::Time::ref().deltaTime()); + return 1; +} + +/** + * \ingroup LuaScripts + * setTime({number, string}): + * Sets the simulation time to the passed value. If the parameter is a number, it is + * interpreted as the number of seconds past the J2000 epoch and the + * Time::setTime(double) method is called. If the parameter is a string, it is + * interpreted as a structured date string and the Time::setTime(std::string) method + * is called + */ +int time_setTime(lua_State* L) { + const bool isFunction = (lua_isfunction(L, -1) != 0); + if (isFunction) { + // If the top of the stack is a function, it is ourself + const char* msg = lua_pushfstring(L, "method called without argument"); + return luaL_error(L, "bad argument (%s)", 1, msg); + } + + const bool isNumber = (lua_isnumber(L, -1) != 0); + const bool isString = (lua_isstring(L, -1) != 0); + if (!isNumber && !isString) { + const char* msg = lua_pushfstring(L, "%s or %s expected, got %s", + lua_typename(L, LUA_TNUMBER), + lua_typename(L, LUA_TSTRING), luaL_typename(L, -1)); + return luaL_error(L, "bad argument #%d (%s)", 1, msg); + } + if (isNumber) { + double value = lua_tonumber(L, -1); + openspace::Time::ref().setTime(value); + return 0; + } + if (isString) { + const char* time = lua_tostring(L, -1); + openspace::Time::ref().setTime(time); + return 0; + } + return 0; +} + +/** + * \ingroup LuaScripts + * currentTime(): + * Returns the current simulation time as the number of seconds past the J2000 epoch. + * It is returned by calling the Time::currentTime method. + */ +int time_currentTime(lua_State* L) { + lua_pushnumber(L, openspace::Time::ref().currentTime()); + return 1; +} + +/** + * \ingroup LuaScripts + * currentTimeUTC(): + * Returns the current simulation time as a structured ISO 8601 string using the UTC + * timezone by calling the Time::currentTimeUTC method + */ +int time_currentTimeUTC(lua_State* L) { + lua_pushstring(L, openspace::Time::ref().currentTimeUTC().c_str()); + return 1; +} + +} // namespace luascripts + + Time* Time::_instance = nullptr; Time::Time() @@ -116,21 +150,18 @@ Time::Time() { } -bool Time::initialize() { +bool Time::initialize(const std::string& lskKernel) { assert( _instance == nullptr); - _instance = new Time(); - using constants::openspaceengine::keyConfigTimekernel; - if (OsEng.configurationManager().hasKeyAndValue(keyConfigTimekernel)) { - std::string value; - OsEng.configurationManager().getValue(keyConfigTimekernel, value); - const int success = SpiceManager::ref().loadKernel(absPath(value), "TimeKernel"); + if (!lskKernel.empty()) { + const int success = SpiceManager::ref().loadKernel( + absPath(lskKernel), "TimeKernel"); if (success == 0) { - LERROR("Error loading SPICE time kernel '" << value << "'"); - return false; + LERROR("Error loading SPICE time kernel '" << lskKernel << "'"); + return false; } } - + _instance = new Time(); return true; } @@ -184,19 +215,19 @@ scripting::ScriptEngine::LuaLibrary Time::luaLibrary() { { { "setDeltaTime", - &time_setDeltaTime, + &luascriptfunctions::time_setDeltaTime, "setDeltaTime(number): Sets the amount of simulation time that happens " "in one second of real time" }, { "deltaTime", - &time_deltaTime, + &luascriptfunctions::time_deltaTime, "deltaTime: Returns the amount of simulated time that passes in one " "second of real time" }, { "setTime", - &time_setTime, + &luascriptfunctions::time_setTime, "setTime({number, string}): Sets the current simulation time to the " "specified value. If the parameter is a number, the value is the number " "of seconds past the J2000 epoch. If it is a string, it has to be a " @@ -204,13 +235,13 @@ scripting::ScriptEngine::LuaLibrary Time::luaLibrary() { }, { "currentTime", - &time_currentTime, + &luascriptfunctions::time_currentTime, "currentTime(): Returns the current time as the number of seconds since " "the J2000 epoch" }, { "currentTimeUTC", - &time_currentTimeUTC, + &luascriptfunctions::time_currentTimeUTC, "currentTimeUTC: Returns the current time as an ISO 8601 date string " "(YYYY-MM-DDTHH:MN:SS" }