diff --git a/Jenkinsfile b/Jenkinsfile index 57ff97f0f2..b97149c963 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -25,50 +25,56 @@ echo flags stage('Build') { parallel linux: { - node('linux') { - checkout scm - sh 'git submodule update --init --recursive' - sh ''' - mkdir -p build - cd build - cmake .. ''' + - flags + ''' .. - make - ''' + timeout(time: 30, unit: 'MINUTES') { + node('linux') { + checkout scm + sh 'git submodule update --init --recursive' + sh ''' + mkdir -p build + cd build + cmake .. ''' + + flags + ''' .. + make + ''' + } } }, windows: { - node('windows') { - checkout scm - bat ''' - git submodule update --init --recursive - if not exist "build" mkdir "build" - cd build - cmake -G "Visual Studio 14 2015 Win64" .. ''' + - flags + ''' .. - msbuild.exe OpenSpace.sln /m:8 /p:Configuration=Debug - ''' + timeout(time: 30, unit: 'MINUTES') { + node('windows') { + checkout scm + bat ''' + git submodule update --init --recursive + if not exist "build" mkdir "build" + cd build + cmake -G "Visual Studio 14 2015 Win64" .. ''' + + flags + ''' .. + msbuild.exe OpenSpace.sln /m:8 /p:Configuration=Debug + ''' + } } }, osx: { - node('osx') { - checkout scm - sh 'git submodule update --init --recursive' - sh ''' - export PATH=${PATH}:/usr/local/bin:/Applications/CMake.app/Contents/bin - export CMAKE_BUILD_TOOL=/Applications/CMake.app/Contents/bin/CMake - srcDir=$PWD - if [ ! -d ${srcDir} ]; then - mkdir ${srcDir} - fi - if [ ! -d ${srcDir}/build ]; then - mkdir ${srcDir}/build - fi - cd ${srcDir}/build - /Applications/CMake.app/Contents/bin/cmake -G Xcode -D NASM=/usr/local/Cellar/nasm/2.11.08/bin/nasm ${srcDir} .. ''' + - flags + ''' - xcodebuild - ''' + timeout(time: 30, unit: 'MINUTES') { + node('osx') { + checkout scm + sh 'git submodule update --init --recursive' + sh ''' + export PATH=${PATH}:/usr/local/bin:/Applications/CMake.app/Contents/bin + export CMAKE_BUILD_TOOL=/Applications/CMake.app/Contents/bin/CMake + srcDir=$PWD + if [ ! -d ${srcDir} ]; then + mkdir ${srcDir} + fi + if [ ! -d ${srcDir}/build ]; then + mkdir ${srcDir}/build + fi + cd ${srcDir}/build + /Applications/CMake.app/Contents/bin/cmake -G Xcode -D NASM=/usr/local/Cellar/nasm/2.11.08/bin/nasm ${srcDir} .. ''' + + flags + ''' + xcodebuild + ''' + } } } } \ No newline at end of file diff --git a/apps/Launcher/main.cpp b/apps/Launcher/main.cpp index ccf862687c..8b7f06e18d 100644 --- a/apps/Launcher/main.cpp +++ b/apps/Launcher/main.cpp @@ -23,7 +23,6 @@ ****************************************************************************************/ #include - #include #include "mainwindow.h" diff --git a/apps/Launcher/mainwindow.cpp b/apps/Launcher/mainwindow.cpp index d1f6012f14..51fe2e9207 100644 --- a/apps/Launcher/mainwindow.cpp +++ b/apps/Launcher/mainwindow.cpp @@ -29,12 +29,14 @@ #include #include +#include #include #include #include #include #include +#include #include #include @@ -168,7 +170,77 @@ MainWindow::~MainWindow() { delete _informationWidget; } + +void MainWindow::configureLogging() { + const std::string KeyLogLevel = + openspace::ConfigurationManager::KeyLauncher + '.' + openspace::ConfigurationManager::PartLogLevel; + const std::string KeyLogImmediateFlush = + openspace::ConfigurationManager::KeyLauncher + '.' + openspace::ConfigurationManager::PartImmediateFlush; + const std::string KeyLogs = + openspace::ConfigurationManager::KeyLauncher + '.' + openspace::ConfigurationManager::PartLogs; + + ghoul::logging::LogLevel ghoulLogLevel; + std::string logLevel = "None"; + bool immediateFlush = false; + + if (_optionParser->isSet("d")) { + ghoulLogLevel = static_cast(_optionParser->value("d").toInt()); + } else { + if (_configuration->hasKeyAndValue(KeyLogLevel)) { + _configuration->getValue(KeyLogLevel, logLevel); + _configuration->getValue(KeyLogImmediateFlush, immediateFlush); + } + ghoulLogLevel = ghoul::logging::levelFromString(logLevel); + } + printf("%d", ghoulLogLevel); + + using ImmediateFlush = ghoul::logging::LogManager::ImmediateFlush; + + ghoul::logging::LogManager::initialize( + ghoulLogLevel, + immediateFlush ? ImmediateFlush::Yes : ImmediateFlush::No + ); + LogMgr.addLog(std::make_unique()); + // TODO: This can crash the system in cases where the logfile can't be created ---abock + LogMgr.addLog(std::make_unique< ghoul::logging::HTMLLog >("LauncherLog.html", ghoul::logging::HTMLLog::Append::No)); + LogMgr.addLog(std::make_unique< QLog >()); + + if (_configuration->hasKeyAndValue(KeyLogs)) { + ghoul::Dictionary logs; + _configuration->getValue(KeyLogs, logs); + + for (size_t i = 1; i <= logs.size(); ++i) { + ghoul::Dictionary logInfo; + logs.getValue(std::to_string(i), logInfo); + + try { + LogMgr.addLog(openspace::createLog(logInfo)); + } + catch (const ghoul::RuntimeError& e) { + LERRORC(e.component, e.message); + } + } + } + +#ifdef WIN32 + if (IsDebuggerPresent()) { + LogMgr.addLog(std::make_unique()); + } +#endif // WIN32 + +#ifndef GHOUL_LOGGING_ENABLE_TRACE + if (ghoulLogLevel == ghoul::logging::LogLevel::Trace) { + LWARNING("Desired logging level is set to 'Trace' but application was " << + "compiled without Trace support"); + } +#endif // GHOUL_LOGGING_ENABLE_TRACE + +} + void MainWindow::initialize() { + // ParseOptions + generateOptions(); + // Get the news information QNetworkRequest request; request.setUrl(QUrl(NewsURL)); @@ -189,18 +261,14 @@ void MainWindow::initialize() { _syncWidget->setWindowModality(Qt::WindowModal); _syncWidget->hide(); - ghoul::logging::LogManager::initialize(ghoul::logging::LogLevel::Debug); - LogMgr.addLog( std::make_unique< ghoul::logging::ConsoleLog >() ); - // TODO: This can crash the system in cases where the logfile can't be created ---abock - LogMgr.addLog( std::make_unique< ghoul::logging::HTMLLog >("LauncherLog.html", ghoul::logging::HTMLLog::Append::No) ); - LogMgr.addLog( std::make_unique< QLog >() ); - std::string configurationFile = _configurationFile; - + _configuration = new openspace::ConfigurationManager; configurationFile = _configuration->findConfiguration( configurationFile ); _configuration->loadFromFile(configurationFile); + configureLogging(); + // Load all available scenes QString modulesDirectory = QString::fromStdString(absPath("${SCENE}")); QDir d(modulesDirectory); @@ -263,3 +331,20 @@ void MainWindow::newsReadyRead() { _informationWidget->setText(news); _newsReply->deleteLater(); } + +void MainWindow::generateOptions() { + + _optionParser = new QCommandLineParser; + _optionParser->setApplicationDescription("OpenSpace Launcher"); + _optionParser->addHelpOption(); + _optionParser->addVersionOption(); + + _optionParser->addOptions({ + { { "d", "debug" }, + QCoreApplication::translate("main", "Debug output level"), + QCoreApplication::translate("main", "0, 1, 2, 3, 4, 5, 6, 7"), + QCoreApplication::translate("main", "1"), + } + }); + _optionParser->process(*QApplication::instance()); +} diff --git a/apps/Launcher/mainwindow.h b/apps/Launcher/mainwindow.h index 9fd2626d4d..9c1e56449c 100644 --- a/apps/Launcher/mainwindow.h +++ b/apps/Launcher/mainwindow.h @@ -31,6 +31,7 @@ #include #include #include +#include class QComboBox; class QNetworkAccessManager; @@ -56,9 +57,12 @@ private slots: void newsNetworkError(); void newsReadyRead(); + void generateOptions(); + private: void initialize(); - + void configureLogging(); + QNetworkReply* _newsReply; QTextEdit* _informationWidget; @@ -74,42 +78,9 @@ private: QNetworkAccessManager _networkManager; openspace::ConfigurationManager* _configuration; + + QCommandLineParser* _optionParser; }; -//class MainWindow : public QWidget { -//Q_OBJECT -//public: -// MainWindow(); -// ~MainWindow(); -// -// std::string nextTarget() const; -// -//public slots: -// void sendScript(QString script); -// -//private slots: -// void onConnect(QString host, QString port); -// void onDisconnect(); -// -// void onSocketConnected(); -// void onSocketDisconnected(); -// -// void readTcpData(); -// void handleStatusMessage(QByteArray data); -// void handlePlaybook(QByteArray data); -// -// void fullyConnected(); -// -//private: -// ConfigurationWidget* _configurationWidget; -// ControlWidget* _timeControlWidget; -// InformationWidget* _informationWidget; -// TimelineWidget* _timelineWidget; -// -// QTcpSocket* _socket; -// -// bool _hasHongKangTimeline = false; -// bool _hasLabelTimeline = false; -//}; #endif // __OPENSPACE_APP_LAUNCHER___MAINWINDOW___H__ diff --git a/data/fonts/Inconsolata/Inconsolata-Regular.ttf b/data/fonts/Inconsolata/Inconsolata-Regular.ttf new file mode 100644 index 0000000000..592ccd2007 Binary files /dev/null and b/data/fonts/Inconsolata/Inconsolata-Regular.ttf differ diff --git a/include/openspace/engine/configurationmanager.h b/include/openspace/engine/configurationmanager.h index 92909e6789..8ec3aa167d 100644 --- a/include/openspace/engine/configurationmanager.h +++ b/include/openspace/engine/configurationmanager.h @@ -93,6 +93,8 @@ public: /// The key that stores the verbosity (None, Minimal, Default, Full) of the system /// capabilities components static const std::string PartCapabilitiesVerbosity; + /// The key that stores the settings for determining Launcher-related settings + static const std::string KeyLauncher; /// The full key that stores the verbosity of the system capabilities component static const std::string KeyCapabilitiesVerbosity; /// The key that stores the time (in seconds) that the application will wait before diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index 891dfca494..162404d227 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -65,7 +65,6 @@ public: // Interaction mode setters void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict); - void setInteractionMode(const std::string& interactionModeKey); InteractionMode* interactionMode(); void goToChunk(int x, int y, int level); @@ -73,9 +72,10 @@ public: void resetKeyBindings(); - void addKeyframe(const datamessagestructures::CameraKeyframe &kf); + void addKeyframe(double timestamp, KeyframeInteractionMode::CameraPose pose); void removeKeyframesAfter(double timestamp); void clearKeyframes(); + size_t nKeyframes() const; const std::vector& keyframes() const; void bindKeyLocal( @@ -134,7 +134,7 @@ private: std::string generateJson() const override; - void setInteractionMode(std::shared_ptr interactionMode); + void setInteractionMode(InteractionMode* interactionMode); bool _cameraUpdatedFromScript = false; @@ -143,14 +143,18 @@ private: std::unique_ptr _inputState; Camera* _camera; - std::shared_ptr _currentInteractionMode; + InteractionMode* _currentInteractionMode; - std::map> _interactionModes; std::shared_ptr _mouseStates; + std::unique_ptr _orbitalInteractionMode; + std::unique_ptr _globeBrowsingInteractionMode; + std::unique_ptr _keyframeInteractionMode; + // Properties properties::StringProperty _origin; - + properties::OptionProperty _interactionModeOption; + properties::BoolProperty _rotationalFriction; properties::BoolProperty _horizontalFriction; properties::BoolProperty _verticalFriction; diff --git a/include/openspace/interaction/interactionmode.h b/include/openspace/interaction/interactionmode.h index 0698e2992e..dc99ec1498 100644 --- a/include/openspace/interaction/interactionmode.h +++ b/include/openspace/interaction/interactionmode.h @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED #include @@ -80,14 +81,6 @@ namespace interaction { void mousePositionCallback(double mouseX, double mouseY); void mouseScrollWheelCallback(double mouseScrollDelta); - // Mutators - void addKeyframe(const datamessagestructures::CameraKeyframe &kf); - void removeKeyframesAfter(double timestamp); - void clearKeyframes(); - void clearOldKeyframes(); - - static bool compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b); - // Accessors const std::list >& getPressedKeys() const; const std::list& getPressedMouseButtons() const; @@ -104,9 +97,6 @@ namespace interaction { std::list _mouseButtonsDown; glm::dvec2 _mousePosition; double _mouseScrollDelta; - - // Remote input via keyframes - std::vector _keyframes; }; @@ -194,16 +184,23 @@ protected: class KeyframeInteractionMode : public InteractionMode { public: + struct CameraPose { + glm::dvec3 position; + glm::quat rotation; + std::string focusNode; + bool followFocusNodeRotation; + }; + KeyframeInteractionMode(); ~KeyframeInteractionMode(); virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime); virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime); bool followingNodeRotation() const override; + Timeline& timeline(); private: - std::vector _keyframes; - double _currentKeyframeTime; + Timeline _cameraPoseTimeline; }; class GlobeBrowsingInteractionMode; diff --git a/include/openspace/interaction/luaconsole.h b/include/openspace/interaction/luaconsole.h index 77beaf3109..09ff1c1bf8 100644 --- a/include/openspace/interaction/luaconsole.h +++ b/include/openspace/interaction/luaconsole.h @@ -28,12 +28,19 @@ #include #include #include +#include #include #include #include #include +namespace ghoul { +namespace opengl { + class ProgramObject; +} // namespace opengl +} // namespace ghoul + namespace openspace { class LuaConsole : public properties::PropertyOwner { @@ -46,7 +53,9 @@ public: bool keyboardCallback(Key key, KeyModifier modifier, KeyAction action); void charCallback(unsigned int codepoint, KeyModifier modifier); + void update(); void render(); + float currentHeight() const; private: void parallelConnectionChanged(const ParallelConnection::Status& status); @@ -55,6 +64,14 @@ private: properties::BoolProperty _isVisible; properties::BoolProperty _remoteScripting; + properties::Vec4Property _backgroundColor; + properties::Vec4Property _highlightColor; + properties::Vec4Property _separatorColor; + properties::Vec4Property _entryTextColor; + properties::Vec4Property _historyTextColor; + properties::IntProperty _historyLength; + + size_t _inputPosition; std::vector _commandsHistory; size_t _activeCommand; @@ -65,6 +82,17 @@ private: bool hasInitialValue; std::string initialValue; } _autoCompleteInfo; + + float _currentHeight; + float _targetHeight; + float _fullHeight; + + std::shared_ptr _font; + std::shared_ptr _historyFont; + + std::unique_ptr _program; + GLuint _vao; + GLuint _vbo; }; } // namespace openspace diff --git a/include/openspace/properties/property.h b/include/openspace/properties/property.h index 54e7a07532..5fbc8e6a78 100644 --- a/include/openspace/properties/property.h +++ b/include/openspace/properties/property.h @@ -68,9 +68,9 @@ public: */ enum class Visibility { All = 3, ///< Visible for all types, no matter what - Developer = 2, ///< Visible in Developer mode - User = 1, ///< Visible in User mode - Hidden = 0 ///< Never visible + Hidden = 2, ///< Never visible + Developer = 1, ///< Visible in Developer mode + User = 0 ///< Visible in User mode }; /** @@ -292,6 +292,18 @@ public: */ void setReadOnly(bool state); + /** + * Default view options that can be used in the Property::setViewOption method. The + * values are: Property::ViewOptions::Color = color, + * Property::ViewOptions::LightPosition = lightPosition, + * Property::ViewOptions::PowerScaledScalar = powerScaledScalar, and + * Property::ViewOptions::PowerScaledCoordinate = powerScaledCoordinate. + */ + struct ViewOptions { + static const char* Color; + static const char* LightPosition; + }; + /** * This method allows the developer to give hints to the GUI about different * representations for the GUI. The same Property (for example Vec4Property) can be @@ -307,18 +319,14 @@ public: void setViewOption(std::string option, bool value = true); /** - * Default view options that can be used in the Property::setViewOption method. The - * values are: Property::ViewOptions::Color = color, - * Property::ViewOptions::LightPosition = lightPosition, - * Property::ViewOptions::PowerScaledScalar = powerScaledScalar, and - * Property::ViewOptions::PowerScaledCoordinate = powerScaledCoordinate. + * This method returns the state of a \p option hint. See Property::ViewOptions for a + * default list of possible options. As these are only hints, the GUI is free to + * ignore any suggestion by the developer. + * \param option The view option that should be retrieved + * \param defaultValue The value that is returned if the \p option was not set + * \return The view option's value */ - struct ViewOptions { - static const char* Color; - static const char* LightPosition; - static const char* PowerScaledScalar; - static const char* PowerScaledCoordinate; - }; + bool viewOption(const std::string& option, bool defaultValue = false) const; /** * Returns the metaData that contains all information for external applications to diff --git a/include/openspace/util/time.h b/include/openspace/util/time.h index 5241d21a61..947f7a0948 100644 --- a/include/openspace/util/time.h +++ b/include/openspace/util/time.h @@ -55,8 +55,6 @@ namespace openspace { * The synchronization of the simulation time requires */ -class SyncBuffer; - class Time { public: /** @@ -90,20 +88,6 @@ public: static Time now(); - /** - * Returns the reference to the Time singleton object. - * \return The reference to the Time singleton object - * \pre The Time singleton must have been initialized - */ - 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(); /** * Sets the current time to the specified value in seconds past the J2000 epoch. This @@ -210,15 +194,10 @@ public: */ static scripting::LuaLibrary luaLibrary(); - std::vector getSyncables(); - private: - static Time* _instance; ///< The singleton instance - - SyncData _time; - SyncData _dt; - SyncData _timeJumped; - + double _time; + double _dt; + bool _timeJumped; bool _timePaused = false; }; diff --git a/include/openspace/util/timeline.h b/include/openspace/util/timeline.h new file mode 100644 index 0000000000..794aecf96a --- /dev/null +++ b/include/openspace/util/timeline.h @@ -0,0 +1,96 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___TIMELINE___H__ +#define __OPENSPACE_CORE___TIMELINE___H__ + +#include +#include +#include + +namespace openspace { + +/** +* Base class for keyframes +*/ +struct KeyframeBase { + size_t id; + double timestamp; +}; + +/** +* Templated class for keyframes containing data +*/ +template +struct Keyframe : public KeyframeBase { + Keyframe(size_t i, double t, T p) + : KeyframeBase{i, t} + , data(p) + {} + T data; +}; + +/** +* Templated class for timelines +*/ +template +class Timeline { +public: + Timeline(); + virtual ~Timeline(); + void addKeyframe(double time, T data); + void clearKeyframes(); + void removeKeyframe(size_t id); + void removeKeyframesBefore(double timestamp, bool inclusive = false); + void removeKeyframesAfter(double timestamp, bool inclusive = false); + void removeKeyframesBetween(double begin, double end, bool inclusiveBegin = false, bool inclusiveEnd = false); + size_t nKeyframes() const; + const Keyframe* firstKeyframeAfter(double timestamp, bool inclusive = false) const; + const Keyframe* lastKeyframeBefore(double timestamp, bool inclusive = false) const; + const std::deque>& keyframes() const; +private: + size_t _nextKeyframeId; + std::deque> _keyframes; +}; + +/** +* Return true if the timestamp of a is smaller the timestamp of b. +*/ +bool compareKeyframeTimes(const KeyframeBase& a, const KeyframeBase& b); + +/** +* Return true if a is smaller than the timestamp of b. +*/ +bool compareTimeWithKeyframeTime(double a, const KeyframeBase& b); + +/** +* Return true if the timestamp of a is smaller than b. +*/ +bool compareKeyframeTimeWithTime(const KeyframeBase& a, double b); + +} // namespace openspace + +#include ; + +#endif // __OPENSPACE_CORE___TIMELINE___H__ diff --git a/include/openspace/util/timeline.inl b/include/openspace/util/timeline.inl new file mode 100644 index 0000000000..f3b4a3774f --- /dev/null +++ b/include/openspace/util/timeline.inl @@ -0,0 +1,121 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +namespace openspace { + +template +Timeline::Timeline() + : _nextKeyframeId(1) +{} + +template +Timeline::~Timeline() {} + +template +void Timeline::addKeyframe(double timestamp, T data) { + Keyframe keyframe(++_nextKeyframeId, timestamp, data); + auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), keyframe, &compareKeyframeTimes); + _keyframes.insert(iter, keyframe); +} + +template +void Timeline::removeKeyframesAfter(double timestamp, bool inclusive) { + auto iter = inclusive + ? std::lower_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareKeyframeTimeWithTime) + : std::upper_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareTimeWithKeyframeTime); + + _keyframes.erase(iter, _keyframes.end()); +} + +template +void Timeline::removeKeyframesBefore(double timestamp, bool inclusive) { + auto iter = inclusive + ? std::upper_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareTimeWithKeyframeTime) + : std::lower_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareKeyframeTimeWithTime); + + _keyframes.erase(_keyframes.begin(), iter); +} + +template +void Timeline::removeKeyframesBetween(double begin, double end, bool inclusiveBegin, bool inclusiveEnd) { + auto beginIter = inclusiveBegin + ? std::lower_bound(_keyframes.begin(), _keyframes.end(), begin, &compareKeyframeTimeWithTime) + : std::upper_bound(_keyframes.begin(), _keyframes.end(), begin, &compareTimeWithKeyframeTime); + + auto endIter = inclusiveEnd + ? std::upper_bound(beginIter, _keyframes.end(), end, &compareTimeWithKeyframeTime) + : std::lower_bound(beginIter, _keyframes.end(), end, &compareKeyframeTimeWithTime); + + _keyframes.erase(beginIter, endIter); +} + +template +void Timeline::clearKeyframes() { + _keyframes.clear(); +} + +template +void Timeline::removeKeyframe(size_t id) { + _keyframes.erase(std::remove_if(_keyframes.begin(), _keyframes.end(), [id] (Keyframe keyframe) { + return keyframe.id == id; + }), _keyframes.end()); +} + +template +size_t Timeline::nKeyframes() const { + return _keyframes.size(); +} + +template +const Keyframe* Timeline::firstKeyframeAfter(double timestamp, bool inclusive) const { + auto it = inclusive + ? std::lower_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareKeyframeTimeWithTime) + : std::upper_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareTimeWithKeyframeTime); + if (it == _keyframes.end()) { + return nullptr; + } + return &(*it); +} + +template +const Keyframe* Timeline::lastKeyframeBefore(double timestamp, bool inclusive) const { + auto it = inclusive + ? std::upper_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareTimeWithKeyframeTime) + : std::lower_bound(_keyframes.begin(), _keyframes.end(), timestamp, &compareKeyframeTimeWithTime); + if (it == _keyframes.begin()) { + return nullptr; + } + it--; + return &(*it); +} + + +template +const std::deque>& Timeline::keyframes() const { + return _keyframes; +} + + +} + diff --git a/include/openspace/util/timemanager.h b/include/openspace/util/timemanager.h index 018765fbf6..a499c2d400 100644 --- a/include/openspace/util/timemanager.h +++ b/include/openspace/util/timemanager.h @@ -27,24 +27,26 @@ #include #include -#include +#include +#include +#include namespace openspace { class TimeManager { public: + Time& time(); + std::vector getSyncables(); void preSynchronization(double dt); - void addKeyframe(const datamessagestructures::TimeKeyframe& kf); + void addKeyframe(double timestamp, Time kf); void removeKeyframesBefore(double timestamp); void removeKeyframesAfter(double timestamp); void clearKeyframes(); - const std::deque& keyframes() const; + size_t nKeyframes() const; private: + Timeline