Introduce engine modes to handle Camera path and session recording transitions

* Clarifies which system is control over time and camera at what time
* Fixes #1845
* Prevent invalid switching between session recoring and camera path playback
* Some cleanup, mosly of SessionRecording and NavigationHandler. Also, remove ExternInteraction and some other unused/nonexisting functions
This commit is contained in:
Emma Broman
2022-01-26 11:00:54 +01:00
parent 6bc7d36920
commit 91b0581d39
22 changed files with 355 additions and 378 deletions

View File

@@ -31,6 +31,7 @@
namespace openspace {
struct CameraPose;
class SceneGraphNode;
/**
@@ -67,6 +68,7 @@ public:
~Camera() = default;
// Mutators
void setPose(CameraPose pose);
void setPositionVec3(glm::dvec3 pos);
void setRotation(glm::dquat rotation);
void setScaling(float scaling);

View File

@@ -65,6 +65,15 @@ struct CommandlineArguments {
class OpenSpaceEngine {
public:
// A mode that specifies which part of the system is currently in control.
// The mode can be used to limit certain features, like setting time, navigation
// or triggering scripts
enum class Mode {
UserControl = 0,
SessionRecordingPlayback,
CameraPath
};
OpenSpaceEngine();
~OpenSpaceEngine();
@@ -94,6 +103,10 @@ public:
void toggleShutdownMode();
Mode currentMode() const;
bool setMode(Mode newMode);
void resetMode();
// Guaranteed to return a valid pointer
AssetManager& assetManager();
LoadingScreen* loadingScreen();
@@ -113,7 +126,6 @@ private:
void loadFonts();
void runGlobalCustomizationScripts();
void configureLogging();
std::string generateFilePath(std::string openspaceRelativePath);
void resetPropertyChangeFlagsOfSubowners(openspace::properties::PropertyOwner* po);
@@ -137,6 +149,8 @@ private:
// The first frame might take some more time in the update loop, so we need to know to
// disable the synchronization; otherwise a hardware sync will kill us after 1 minute
bool _isRenderingFirstFrame = true;
Mode _currentMode = Mode::UserControl;
};
/**

View File

@@ -1,82 +0,0 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___EXTERNINTERACTION___H__
#define __OPENSPACE_CORE___EXTERNINTERACTION___H__
#include <openspace/network/messagestructures.h>
#include <openspace/properties/propertyowner.h>
#include <ghoul/io/socket/tcpsocket.h>
#include <vector>
namespace openspace {
class ExternInteraction : public properties::PropertyOwner {
public:
ExternInteraction();
/**
* Method that generates a keyframeNavigator CameraPose from a CameraKeyframe
* object, and then adds this to the navigationHandler's keyframe navigator.
* \param kf The camera keyframe to add.
*/
void cameraInteraction(datamessagestructures::CameraKeyframe kf);
/**
* Method that generates a TimeKeyframeData from a TimeKeyframe object, and
* then adds this to the timeManager.
* \param kf The time keyframe to add.
*/
void timeInteraction(datamessagestructures::TimeKeyframe kf);
/**
* Method that passes a ScriptMessage object to the script engine, calling its
* queueScript method to add it for execution.
* \param sm The ScriptMessage object to queue in the script engine.
*/
void scriptInteraction(datamessagestructures::ScriptMessage sm);
/**
* Method that accepts a reference to a CameraKeyframe object, and populates
* it with the current properties of the camera from the navigation handler.
* \returns CameraKeyframe with current state from NavigationHandler.
*/
datamessagestructures::CameraKeyframe generateCameraKeyframe();
/**
* Method that accepts a reference to a TimeKeyframe object, and populates
* it with the current time values from the application time manager.
* \returns TimeKeyframe The time keyframe.
*/
datamessagestructures::TimeKeyframe generateTimeKeyframe();
/**
* Method that accepts a reference to a ScriptMessage object and a script
* string, and populates the ScriptMessage with the script and timestamp
* of the current application time.
* \param script The script to execute in std::string form.
* \returns ScriptMessage The ScriptMessage data structure with script.
*/
datamessagestructures::ScriptMessage generateScriptMessage(std::string script);
private:
};
} // namespace openspace
#endif // __OPENSPACE_CORE___EXTERNINTERACTION___H__

View File

@@ -25,7 +25,8 @@
#ifndef __OPENSPACE_CORE___SESSIONRECORDING___H__
#define __OPENSPACE_CORE___SESSIONRECORDING___H__
#include <openspace/interaction/externinteraction.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/navigation/keyframenavigator.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/scripting/lualibrary.h>
@@ -489,12 +490,12 @@ public:
static std::string readHeaderElement(std::ifstream& stream, size_t readLen_chars);
/**
* Reads header information from a session recording file
*
* \param stringstream reference to ifstream that contains the session recording file data
* \param readLen_chars number of characters to be read, which may be the expected
* length of the header line, or an arbitrary number of characters within it
*/
* Reads header information from a session recording file
*
* \param stringstream reference to ifstream that contains the session recording file data
* \param readLen_chars number of characters to be read, which may be the expected
* length of the header line, or an arbitrary number of characters within it
*/
static std::string readHeaderElement(std::stringstream& stream, size_t readLen_chars);
/**
@@ -596,12 +597,11 @@ protected:
Script,
Invalid
};
struct timelineEntry {
struct TimelineEntry {
RecordedType keyframeType;
unsigned int idxIntoKeyframeTypeArray;
Timestamps t3stamps;
};
ExternInteraction _externInteract;
double _timestampRecordStarted = 0.0;
Timestamps _timestamps3RecordStarted;
double _timestampPlaybackStarted_application = 0.0;
@@ -622,6 +622,8 @@ protected:
bool playbackScript();
bool playbackAddEntriesToTimeline();
void signalPlaybackFinishedForComponent(RecordedType type);
void handlePlaybackEnd();
bool findFirstCameraKeyframeInTimeline();
Timestamps generateCurrentTimestamp3(double keyframeTime);
static void saveStringToFile(const std::string& s, unsigned char* kfBuffer,
@@ -635,7 +637,7 @@ protected:
datamessagestructures::TimeKeyframe keyframe, int lineNum);
bool addKeyframe(Timestamps t3stamps,
std::string scriptToQueue, int lineNum);
bool addKeyframeToTimeline(std::vector<timelineEntry>& timeline, RecordedType type,
bool addKeyframeToTimeline(std::vector<TimelineEntry>& timeline, RecordedType type,
size_t indexIntoTypeKeyframes, Timestamps t3stamps, int lineNum);
void initializePlayback_time(double now);
@@ -744,10 +746,10 @@ protected:
std::vector<interaction::KeyframeNavigator::CameraPose> _keyframesCamera;
std::vector<datamessagestructures::TimeKeyframe> _keyframesTime;
std::vector<std::string> _keyframesScript;
std::vector<timelineEntry> _timeline;
std::vector<TimelineEntry> _timeline;
std::vector<std::string> _keyframesSavePropertiesBaseline_scripts;
std::vector<timelineEntry> _keyframesSavePropertiesBaseline_timeline;
std::vector<TimelineEntry> _keyframesSavePropertiesBaseline_timeline;
std::vector<std::string> _propertyBaselinesSaved;
const std::vector<std::string> _propertyBaselineRejects = {
"NavigationHandler.OrbitalNavigator.Anchor",

View File

@@ -76,7 +76,6 @@ public:
void removeKeyframesAfter(double timestamp, Inclusive inclusive = Inclusive::No);
void clearKeyframes();
size_t nKeyframes() const;
const std::vector<datamessagestructures::CameraKeyframe>& keyframes() const;
double currentTime() const;
void setTimeReferenceMode(KeyframeTimeRef refType, double referenceTimestamp);

View File

@@ -68,16 +68,12 @@ public:
// Mutators
void setFocusNode(SceneGraphNode* node);
void resetCameraDirection();
void setCamera(Camera* camera);
void setInterpolationTime(float durationInSeconds);
void updateCamera(double deltaTime);
void setEnableKeyFrameInteraction();
void setDisableKeyFrameInteraction();
void triggerPlaybackStart();
void stopPlayback();
void resetNavigationUpdateVariables();
// Accessors
Camera* camera() const;
@@ -155,8 +151,7 @@ public:
private:
void applyNavigationState(const NavigationState& ns);
void updateCameraTransitions();
bool _playbackModeEnabled = false;
void clearGlobalJoystickStates();
MouseInputState _mouseInputState;
KeyboardInputState _keyboardInputState;

View File

@@ -86,7 +86,7 @@ public:
void startRetargetAim();
float retargetInterpolationTime() const;
void setRetargetInterpolationTime(float durationInSeconds);
void resetNodeMovements();
void updatePreviousStateVariables();
JoystickCameraStates& joystickStates();
const JoystickCameraStates& joystickStates() const;
@@ -131,6 +131,9 @@ private:
bool resetVelocitiesOnChange = true);
void setAimNode(const SceneGraphNode* aimNode);
void updatePreviousAnchorState();
void updatePreviousAimState();
Camera* _camera;
Friction _friction;

View File

@@ -0,0 +1,57 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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___MESSAGESTRUCTURESHELPER___H__
#define __OPENSPACE_CORE___MESSAGESTRUCTURESHELPER___H__
#include <openspace/network/messagestructures.h>
namespace openspace::datamessagestructures {
/**
* Method that creates a CameraKeyframe object and populates
* it with the current properties of the camera from the navigation handler.
* \returns CameraKeyframe with current state from NavigationHandler
*/
CameraKeyframe generateCameraKeyframe();
/**
* Method that creates a TimeKeyframe object and populates
* it with the current time values from the application time manager.
* \returns TimeKeyframe The time keyframe
*/
TimeKeyframe generateTimeKeyframe();
/**
* Method that creates a ScriptMessage object from a given script
* string, and populates the ScriptMessage with the script and timestamp
* of the current application time.
* \param script The script to execute in std::string form
* \returns ScriptMessage The ScriptMessage data structure with script
*/
ScriptMessage generateScriptMessage(std::string script);
} // namespace openspace::datamessagestructures
#endif // __OPENSPACE_CORE___MESSAGESTRUCTURESHELPER___H__

View File

@@ -25,16 +25,13 @@
#ifndef __OPENSPACE_CORE___PARALLELPEER___H__
#define __OPENSPACE_CORE___PARALLELPEER___H__
#include <openspace/network/parallelconnection.h>
#include <openspace/interaction/externinteraction.h>
#include <openspace/network/messagestructures.h>
#include <openspace/util/timemanager.h>
#include <openspace/properties/propertyowner.h>
#include <openspace/network/messagestructures.h>
#include <openspace/network/parallelconnection.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/scalar/floatproperty.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/util/timemanager.h>
#include <ghoul/designpattern/event.h>
#include <atomic>
#include <deque>
@@ -133,8 +130,6 @@ private:
std::unique_ptr<std::thread> _receiveThread = nullptr;
std::shared_ptr<ghoul::Event<>> _connectionEvent;
ExternInteraction _externInteract;
ParallelConnection _connection;
TimeManager::CallbackHandle _timeJumpCallback = -1;

View File

@@ -150,16 +150,6 @@ public:
*/
void setTimeReferenceMode(openspace::interaction::KeyframeTimeRef refType);
/**
* Sets the mode for scripts being run from playback
*/
void triggerPlaybackStart();
/**
* Sets the flag for scripts no longer being run from playback
*/
void stopPlayback();
static LuaLibrary luaLibrary();
void setModeApplicationTime();
void setModeRecordedTime();
@@ -174,7 +164,6 @@ private:
int _currentIndex = 0;
double _currentTime = 0;
bool _playbackModeEnabled = false;
openspace::interaction::KeyframeTimeRef _timeframeMode
= openspace::interaction::KeyframeTimeRef::Absolute_simTimeJ2000;

View File

@@ -126,8 +126,6 @@ public:
void removeTimeChangeCallback(CallbackHandle handle);
void removeDeltaTimeChangeCallback(CallbackHandle handle);
void removeDeltaTimeStepsChangeCallback(CallbackHandle handle);
void triggerPlaybackStart();
void stopPlayback();
void removeTimeJumpCallback(CallbackHandle handle);
void removeTimelineChangeCallback(CallbackHandle handle);
@@ -142,6 +140,8 @@ private:
double currentApplicationTimeForInterpolation() const;
double previousApplicationTimeForInterpolation() const;
bool isPlayingBackSessionRecording() const;
Timeline<TimeKeyframeData> _timeline;
SyncData<Time> _currentTime;
SyncData<Time> _integrateFromTime;
@@ -171,7 +171,6 @@ private:
double _latestConsumedTimestamp = -std::numeric_limits<double>::max();
int _nextCallbackHandle = 0;
bool _playbackModeEnabled = false;
std::vector<std::pair<CallbackHandle, TimeChangeCallback>> _timeChangeCallbacks;
std::vector<std::pair<CallbackHandle, TimeChangeCallback>> _deltaTimeChangeCallbacks;

View File

@@ -58,7 +58,6 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/interaction/keyboardinputstate.cpp
${OPENSPACE_BASE_DIR}/src/interaction/mousecamerastates.cpp
${OPENSPACE_BASE_DIR}/src/interaction/scriptcamerastates.cpp
${OPENSPACE_BASE_DIR}/src/interaction/externinteraction.cpp
${OPENSPACE_BASE_DIR}/src/interaction/sessionrecording.cpp
${OPENSPACE_BASE_DIR}/src/interaction/sessionrecording_lua.inl
${OPENSPACE_BASE_DIR}/src/interaction/websocketinputstate.cpp
@@ -80,6 +79,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/navigation/pathnavigator.cpp
${OPENSPACE_BASE_DIR}/src/navigation/pathnavigator_lua.inl
${OPENSPACE_BASE_DIR}/src/navigation/waypoint.cpp
${OPENSPACE_BASE_DIR}/src/network/messagestructureshelper.cpp
${OPENSPACE_BASE_DIR}/src/network/parallelconnection.cpp
${OPENSPACE_BASE_DIR}/src/network/parallelpeer.cpp
${OPENSPACE_BASE_DIR}/src/network/parallelpeer_lua.inl
@@ -242,7 +242,6 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/interaction/keybindingmanager.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/keyboardinputstate.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/mousecamerastates.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/externinteraction.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/scriptcamerastates.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/sessionrecording.h
${OPENSPACE_BASE_DIR}/include/openspace/interaction/sessionrecording.inl
@@ -266,6 +265,7 @@ set(OPENSPACE_HEADER
${OPENSPACE_BASE_DIR}/include/openspace/network/parallelpeer.h
${OPENSPACE_BASE_DIR}/include/openspace/network/parallelserver.h
${OPENSPACE_BASE_DIR}/include/openspace/network/messagestructures.h
${OPENSPACE_BASE_DIR}/include/openspace/network/messagestructureshelper.h
${OPENSPACE_BASE_DIR}/include/openspace/properties/listproperty.h
${OPENSPACE_BASE_DIR}/include/openspace/properties/listproperty.inl
${OPENSPACE_BASE_DIR}/include/openspace/properties/numericalproperty.h

View File

@@ -24,6 +24,7 @@
#include <openspace/camera/camera.h>
#include <openspace/camera/camerapose.h>
#include <sstream>
namespace openspace {
@@ -43,6 +44,11 @@ Camera::Camera(const Camera& o)
, _cachedLookupVector(o._cachedLookupVector)
{}
void Camera::setPose(CameraPose pose) {
setPositionVec3(std::move(pose.position));
setRotation(std::move(pose.rotation));
}
void Camera::setPositionVec3(glm::dvec3 pos) {
if (!glm::any(glm::isnan(pos))) {
std::lock_guard _lock(_mutex);

View File

@@ -77,6 +77,7 @@
#include <ghoul/font/fontrenderer.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/logging/visualstudiooutputlog.h>
#include <ghoul/misc/exception.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/misc/stacktrace.h>
#include <ghoul/misc/stringconversion.h>
@@ -105,6 +106,16 @@ namespace {
constexpr const char* _loggerCat = "OpenSpaceEngine";
constexpr std::string_view stringify(openspace::OpenSpaceEngine::Mode m) {
using Mode = openspace::OpenSpaceEngine::Mode;
switch (m) {
case Mode::UserControl: return "UserControl";
case Mode::CameraPath: return "CameraPath";
case Mode::SessionRecordingPlayback: return "SessionRecording";
default: throw ghoul::MissingCaseException();
}
}
openspace::properties::Property::PropertyInfo PrintEventsInfo = {
"PrintEvents",
"Print Events",
@@ -784,7 +795,7 @@ void OpenSpaceEngine::loadAssets() {
static_cast<float>(sync->nSynchronizedBytes()) /
static_cast<float>(sync->nTotalBytes());
}(sync);
_loadingScreen->updateItem(
sync->identifier(),
sync->name(),
@@ -813,7 +824,7 @@ void OpenSpaceEngine::loadAssets() {
allAssets.end(),
[](const Asset* asset) { return asset->isInitialized() || asset->isFailed(); }
);
if (finishedLoading) {
break;
}
@@ -1604,6 +1615,39 @@ void OpenSpaceEngine::toggleShutdownMode() {
}
}
OpenSpaceEngine::Mode OpenSpaceEngine::currentMode() const {
return _currentMode;
}
bool OpenSpaceEngine::setMode(Mode newMode) {
if (_currentMode == Mode::CameraPath && newMode == Mode::CameraPath) {
// Special case: It is okay to trigger another camera path while one is
// already playing. So just return that we were successful
return true;
}
else if (newMode == _currentMode) {
LERROR("Cannot switch to the currectly active mode");
return false;
}
else if (_currentMode != Mode::UserControl && newMode != Mode::UserControl) {
LERROR(fmt::format(
"Cannot switch to mode '{}' when in '{}' mode",
stringify(newMode), stringify(_currentMode)
));
return false;
}
LDEBUG(fmt::format("Mode: {}", stringify(newMode)));
_currentMode = newMode;
return true;
}
void OpenSpaceEngine::resetMode() {
_currentMode = Mode::UserControl;
LDEBUG(fmt::format("Reset engine mode to {}", stringify(_currentMode)));
}
void setCameraFromProfile(const Profile& p) {
if (!p.camera.has_value()) {
throw ghoul::RuntimeError("No 'camera' entry exists in the startup profile");

View File

@@ -26,6 +26,7 @@
#include <openspace/camera/camera.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/events/eventengine.h>
#include <openspace/interaction/tasks/convertrecfileversiontask.h>
@@ -33,6 +34,7 @@
#include <openspace/navigation/keyframenavigator.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/orbitalnavigator.h>
#include <openspace/network/messagestructureshelper.h>
#include <openspace/rendering/luaconsole.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/renderengine.h>
@@ -204,7 +206,7 @@ bool SessionRecording::startRecording(const std::string& filename) {
LERROR("Unable to start recording while already in recording mode");
return false;
}
else if (_state == SessionState::Playback || _state == SessionState::PlaybackPaused) {
else if (isPlayingBack()) {
LERROR("Unable to start recording while in session playback mode");
return false;
}
@@ -236,8 +238,8 @@ bool SessionRecording::startRecording(const std::string& filename) {
_timestampRecordStarted = global::windowDelegate->applicationTime();
//Record the current delta time as the first property to save in the file.
//This needs to be saved as a baseline whether or not it changes during recording.
// Record the current delta time as the first property to save in the file.
// This needs to be saved as a baseline whether or not it changes during recording.
_timestamps3RecordStarted = {
_timestampRecordStarted,
0.0,
@@ -268,9 +270,9 @@ void SessionRecording::recordCurrentTimeRate() {
void SessionRecording::stopRecording() {
if (_state == SessionState::Recording) {
//Add all property baseline scripts to the beginning of the recording file
// Add all property baseline scripts to the beginning of the recording file
datamessagestructures::ScriptMessage smTmp;
for (timelineEntry initPropScripts : _keyframesSavePropertiesBaseline_timeline) {
for (TimelineEntry initPropScripts : _keyframesSavePropertiesBaseline_timeline) {
if (initPropScripts.keyframeType == RecordedType::Script) {
smTmp._script = _keyframesSavePropertiesBaseline_scripts
[initPropScripts.idxIntoKeyframeTypeArray];
@@ -283,21 +285,15 @@ void SessionRecording::stopRecording() {
);
}
}
for (timelineEntry entry : _timeline) {
for (TimelineEntry entry : _timeline) {
switch (entry.keyframeType) {
case RecordedType::Camera:
case RecordedType::Camera:
{
interaction::KeyframeNavigator::CameraPose kf
= _keyframesCamera[entry.idxIntoKeyframeTypeArray];
glm::dquat tmpRotation(
std::move(kf.rotation.w),
std::move(kf.rotation.x),
std::move(kf.rotation.y),
std::move(kf.rotation.z)
);
datamessagestructures::CameraKeyframe kfMsg(
std::move(kf.position),
std::move(tmpRotation),
std::move(kf.rotation),
std::move(kf.focusNode),
std::move(kf.followFocusNodeRotation),
std::move(kf.scale)
@@ -311,7 +307,7 @@ void SessionRecording::stopRecording() {
);
break;
}
case RecordedType::Time:
case RecordedType::Time:
{
datamessagestructures::TimeKeyframe tf
= _keyframesTime[entry.idxIntoKeyframeTypeArray];
@@ -324,7 +320,7 @@ void SessionRecording::stopRecording() {
);
break;
}
case RecordedType::Script:
case RecordedType::Script:
{
smTmp._script = _keyframesScript[entry.idxIntoKeyframeTypeArray];
saveSingleKeyframeScript(
@@ -336,7 +332,7 @@ void SessionRecording::stopRecording() {
);
break;
}
default:
default:
{
break;
}
@@ -370,13 +366,13 @@ bool SessionRecording::startPlayback(std::string& filename,
LERROR("Unable to start playback while in session recording mode");
return false;
}
else if (_state == SessionState::Playback || _state == SessionState::PlaybackPaused) {
else if (isPlayingBack()) {
LERROR("Unable to start new playback while in session playback mode");
return false;
}
if (!std::filesystem::is_regular_file(absFilename)) {
LERROR("Cannot find the specified playback file.");
LERROR("Cannot find the specified playback file");
cleanUpPlayback();
return false;
}
@@ -393,7 +389,7 @@ bool SessionRecording::startPlayback(std::string& filename,
FileHeaderTitle.length()
);
if (readBackHeaderString != FileHeaderTitle) {
LERROR("Specified playback file does not contain expected header.");
LERROR("Specified playback file does not contain expected header");
cleanUpPlayback();
return false;
}
@@ -413,7 +409,7 @@ bool SessionRecording::startPlayback(std::string& filename,
readHeaderElement(_playbackFile, 1);
if (_recordingDataMode == DataMode::Binary) {
//Close & re-open the file, starting from the beginning, and do dummy read
// Close & re-open the file, starting from the beginning, and do dummy read
// past the header, version, and data type
_playbackFile.close();
_playbackFile.open(_playbackFilename, std::ifstream::in | std::ios::binary);
@@ -433,7 +429,7 @@ bool SessionRecording::startPlayback(std::string& filename,
return false;
}
_saveRendering_isFirstFrame = true;
//Set time reference mode
// Set time reference mode
_playbackForceSimTimeAtStart = forceSimTimeAtStart;
double now = global::windowDelegate->applicationTime();
_playbackTimeReferenceMode = timeMode;
@@ -454,6 +450,15 @@ bool SessionRecording::startPlayback(std::string& filename,
return false;
}
bool canTriggerPlayback = global::openSpaceEngine->setMode(
OpenSpaceEngine::Mode::SessionRecordingPlayback
);
if (!canTriggerPlayback) {
cleanUpPlayback();
return false;
}
LINFO(fmt::format(
"Playback session started: ({:8.3f},0.0,{:13.3f}) with {}/{}/{} entries, "
"forceTime={}",
@@ -514,9 +519,6 @@ bool SessionRecording::initializePlayback_timeline() {
}
void SessionRecording::initializePlayback_triggerStart() {
global::navigationHandler->triggerPlaybackStart();
global::scriptScheduler->triggerPlaybackStart();
global::timeManager->triggerPlaybackStart();
_state = SessionState::Playback;
}
@@ -593,16 +595,22 @@ void SessionRecording::signalPlaybackFinishedForComponent(RecordedType type) {
initializePlayback_triggerStart();
}
else {
_state = SessionState::Idle;
_cleanupNeeded = true;
LINFO("Playback session finished");
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
events::EventSessionRecordingPlayback::State::Finished
);
handlePlaybackEnd();
}
}
}
void SessionRecording::handlePlaybackEnd() {
_state = SessionState::Idle;
_cleanupNeeded = true;
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
events::EventSessionRecordingPlayback::State::Finished
);
global::openSpaceEngine->resetMode();
global::navigationHandler->resetNavigationUpdateVariables();
}
void SessionRecording::enableTakeScreenShotDuringPlayback(int fps) {
_saveRenderingDuringPlayback = true;
_saveRenderingDeltaTime = 1.0 / fps;
@@ -615,20 +623,13 @@ void SessionRecording::disableTakeScreenShotDuringPlayback() {
}
void SessionRecording::stopPlayback() {
if (_state == SessionState::Playback || _state == SessionState::PlaybackPaused) {
_state = SessionState::Idle;
_cleanupNeeded = true;
if (isPlayingBack()) {
LINFO("Session playback stopped");
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
events::EventSessionRecordingPlayback::State::Finished
);
handlePlaybackEnd();
}
}
void SessionRecording::cleanUpPlayback() {
global::navigationHandler->stopPlayback();
global::timeManager->stopPlayback();
Camera* camera = global::navigationHandler->camera();
ghoul_assert(camera != nullptr, "Camera must not be nullptr");
Scene* scene = camera->parent()->scene();
@@ -646,7 +647,6 @@ void SessionRecording::cleanUpPlayback() {
}
}
}
global::scriptScheduler->stopPlayback();
_playbackFile.close();
@@ -763,7 +763,8 @@ void SessionRecording::saveCameraKeyframeToTimeline() {
// Create a camera keyframe, then call to populate it with current position
// & orientation of camera
datamessagestructures::CameraKeyframe kf = _externInteract.generateCameraKeyframe();
datamessagestructures::CameraKeyframe kf =
datamessagestructures::generateCameraKeyframe();
Timestamps times = generateCurrentTimestamp3(kf._timestamp);
interaction::KeyframeNavigator::CameraPose pbFrame(std::move(kf));
@@ -817,8 +818,9 @@ void SessionRecording::saveCameraKeyframeAscii(Timestamps& times,
}
void SessionRecording::saveTimeKeyframeToTimeline() {
//Create a time keyframe, then call to populate it with current time props
datamessagestructures::TimeKeyframe kf = _externInteract.generateTimeKeyframe();
// Create a time keyframe, then call to populate it with current time props
datamessagestructures::TimeKeyframe kf =
datamessagestructures::generateTimeKeyframe();
Timestamps times = generateCurrentTimestamp3(kf._timestamp);
addKeyframe(times, kf, _recordingEntryNum++);
@@ -847,8 +849,7 @@ void SessionRecording::saveTimeKeyframeAscii(Timestamps& times,
saveKeyframeToFile(keyframeLine.str(), file);
}
void SessionRecording::saveScriptKeyframeToTimeline(std::string script)
{
void SessionRecording::saveScriptKeyframeToTimeline(std::string script) {
if (doesStartWithSubstring(script, scriptReturnPrefix)) {
script = script.substr(scriptReturnPrefix.length());
}
@@ -860,7 +861,7 @@ void SessionRecording::saveScriptKeyframeToTimeline(std::string script)
trimCommandsFromScriptIfFound(script);
replaceCommandsFromScriptIfFound(script);
datamessagestructures::ScriptMessage sm
= _externInteract.generateScriptMessage(script);
= datamessagestructures::generateScriptMessage(script);
Timestamps times = generateCurrentTimestamp3(sm._timestamp);
addKeyframe(times, sm._script, _playbackLineNum);
@@ -887,8 +888,7 @@ void SessionRecording::saveScriptKeyframeToPropertiesBaseline(std::string script
);
}
void SessionRecording::trimCommandsFromScriptIfFound(std::string& script)
{
void SessionRecording::trimCommandsFromScriptIfFound(std::string& script) {
for (std::string trimSnippet : _scriptsToBeTrimmed) {
auto findIdx = script.find(trimSnippet);
if (findIdx != std::string::npos) {
@@ -898,8 +898,7 @@ void SessionRecording::trimCommandsFromScriptIfFound(std::string& script)
}
}
void SessionRecording::replaceCommandsFromScriptIfFound(std::string& script)
{
void SessionRecording::replaceCommandsFromScriptIfFound(std::string& script) {
for (ScriptSubstringReplace replacementSnippet : _scriptsToBeReplaced) {
auto findIdx = script.find(replacementSnippet.substringFound);
if (findIdx != std::string::npos) {
@@ -927,7 +926,6 @@ void SessionRecording::saveScriptKeyframeAscii(Timestamps& times,
datamessagestructures::ScriptMessage& sm,
std::ofstream& file)
{
std::stringstream keyframeLine = std::stringstream();
saveHeaderAscii(times, HeaderScriptAscii, keyframeLine);
sm.write(keyframeLine);
@@ -974,14 +972,14 @@ void SessionRecording::preSynchronization() {
saveTimeKeyframeToTimeline();
}
}
else if (_state == SessionState::Playback || _state == SessionState::PlaybackPaused) {
else if (isPlayingBack()) {
moveAheadInTime();
}
else if (_cleanupNeeded) {
cleanUpPlayback();
}
//Handle callback(s) for change in idle/record/playback state
// Handle callback(s) for change in idle/record/playback state
if (_state != _lastState) {
using K = CallbackHandle;
using V = StateChangeCallback;
@@ -1033,8 +1031,7 @@ bool SessionRecording::isPlayingBack() const {
}
bool SessionRecording::isSavingFramesDuringPlayback() const {
return ((_state == SessionState::Playback || _state == SessionState::PlaybackPaused)
&& _saveRenderingDuringPlayback);
return (isPlayingBack() && _saveRenderingDuringPlayback);
}
SessionRecording::SessionState SessionRecording::state() const {
@@ -1329,7 +1326,7 @@ bool SessionRecording::readCameraKeyframeAscii(Timestamps& times,
iss >> entryType;
iss >> times.timeOs >> times.timeRec >> times.timeSim;
kf.read(iss);
//ASCII format does not contain trailing timestamp so add it here
// ASCII format does not contain trailing timestamp so add it here
kf._timestamp = times.timeOs;
if (iss.fail() || !iss.eof()) {
@@ -1522,7 +1519,7 @@ bool SessionRecording::checkIfScriptUsesScenegraphNode(std::string s) {
if (s.rfind(scriptReturnPrefix, 0) == 0) {
s.erase(0, scriptReturnPrefix.length());
}
//This works for both setPropertyValue and setPropertyValueSingle
// This works for both setPropertyValue and setPropertyValueSingle
if (s.rfind("openspace.setPropertyValue", 0) == 0) {
std::string found;
if (s.find("(\"") != std::string::npos) {
@@ -1582,10 +1579,10 @@ void SessionRecording::eraseSpacesFromString(std::string& s) {
std::string SessionRecording::getNameFromSurroundingQuotes(std::string& s) {
std::string result;
char quote = s.at(0);
//Handle either ' or " marks
// Handle either ' or " marks
if (quote == '\'' || quote == '\"') {
size_t quoteCount = std::count(s.begin(), s.end(), quote);
//Must be an opening and closing quote char
// Must be an opening and closing quote char
if (quoteCount == 2) {
result = s.substr(1, s.rfind(quote) - 1);
}
@@ -1722,7 +1719,7 @@ bool SessionRecording::readScriptKeyframeAscii(Timestamps& times,
return true;
}
bool SessionRecording::addKeyframeToTimeline(std::vector<timelineEntry>& timeline,
bool SessionRecording::addKeyframeToTimeline(std::vector<TimelineEntry>& timeline,
RecordedType type,
size_t indexIntoTypeKeyframes,
Timestamps t3stamps, int lineNum)
@@ -1803,7 +1800,7 @@ void SessionRecording::moveAheadInTime() {
double currTime = currentTime();
lookForNonCameraKeyframesThatHaveComeDue(currTime);
updateCameraWithOrWithoutNewKeyframes(currTime);
//Unfortunately the first frame is sometimes rendered because globebrowsing reports
// Unfortunately the first frame is sometimes rendered because globebrowsing reports
// that all chunks are rendered when they apparently are not.
if (_saveRendering_isFirstFrame) {
_saveRendering_isFirstFrame = false;
@@ -2186,7 +2183,7 @@ void SessionRecording::readPlaybackHeader_stream(std::stringstream& conversionIn
else {
throw ConversionError("Unknown data type in header (needs Ascii or Binary)");
}
//Read to throw out newline at end of header
// Read to throw out newline at end of header
readHeaderElement(conversionInStream, 1);
}
@@ -2269,7 +2266,7 @@ std::string SessionRecording::convertFile(std::string filename, int depth)
);
int conversionLineNum = 1;
//If this instance of the SessionRecording class isn't the instance with the
// If this instance of the SessionRecording class isn't the instance with the
// correct version of the file to be converted, then call getLegacy() to recurse
// to the next level down in the legacy subclasses until we get the right
// version, then proceed with conversion from there.
@@ -2490,7 +2487,7 @@ std::string SessionRecording::getLegacyConversionResult(std::string filename, in
std::string SessionRecording_legacy_0085::getLegacyConversionResult(std::string filename,
int)
{
//This method is overriden in each legacy subclass, but does nothing in this instance
// This method is overriden in each legacy subclass, but does nothing in this instance
// as the oldest supported legacy version.
LERROR(fmt::format(
"Version 00.85 is the oldest supported legacy file format; no conversion "
@@ -2541,13 +2538,7 @@ bool SessionRecording_legacy_0085::convertScript(std::stringstream& inStream,
lineNum
);
if (success) {
saveSingleKeyframeScript(
kf,
times,
mode,
outFile,
buffer
);
saveSingleKeyframeScript(kf, times, mode, outFile, buffer);
}
return success;
}

View File

@@ -27,6 +27,7 @@
#include <openspace/camera/camera.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/events/event.h>
#include <openspace/events/eventengine.h>
#include <openspace/interaction/actionmanager.h>
@@ -122,10 +123,6 @@ void NavigationHandler::setFocusNode(SceneGraphNode* node) {
_camera->setPositionVec3(anchorNode()->worldPosition());
}
void NavigationHandler::resetCameraDirection() {
_orbitalNavigator.startRetargetAnchor();
}
void NavigationHandler::setCamera(Camera* camera) {
_camera = camera;
_orbitalNavigator.setCamera(camera);
@@ -166,55 +163,52 @@ void NavigationHandler::setInterpolationTime(float durationInSeconds) {
void NavigationHandler::updateCamera(double deltaTime) {
ghoul_assert(_camera != nullptr, "Camera must not be nullptr");
// If there is a navigation state to set, do so immediately and then return
if (_pendingNavigationState.has_value()) {
applyNavigationState(*_pendingNavigationState);
_orbitalNavigator.resetVelocities();
_pendingNavigationState.reset();
}
else if (!_playbackModeEnabled && _camera) {
if (_useKeyFrameInteraction) {
_keyframeNavigator.updateCamera(*_camera, _playbackModeEnabled);
}
else if (_pathNavigator.isPlayingPath()) {
_pathNavigator.updateCamera(deltaTime);
updateCameraTransitions();
}
else {
if (_disableJoystickInputs) {
std::fill(
global::joystickInputStates->begin(),
global::joystickInputStates->end(),
JoystickInputState()
);
}
_orbitalNavigator.updateStatesFromInput(
_mouseInputState,
_keyboardInputState,
deltaTime
);
_orbitalNavigator.updateCameraStateFromStates(deltaTime);
updateCameraTransitions();
}
_orbitalNavigator.updateCameraScalingFromAnchor(deltaTime);
return;
}
// If session recording (playback mode) was started in the midst of a camera path,
// abort the path
if (_playbackModeEnabled && _pathNavigator.isPlayingPath()) {
_pathNavigator.abortPath();
OpenSpaceEngine::Mode mode = global::openSpaceEngine->currentMode();
bool playbackMode = (mode == OpenSpaceEngine::Mode::SessionRecordingPlayback);
// If we're in session recording payback mode, the session recording is responsible
// for navigation. So don't do anything more here
if (playbackMode || !_camera) {
return;
}
// Handle navigation, based on what navigator is active
if (_useKeyFrameInteraction) {
_keyframeNavigator.updateCamera(*_camera, playbackMode);
}
else if (mode == OpenSpaceEngine::Mode::CameraPath) {
_pathNavigator.updateCamera(deltaTime);
updateCameraTransitions();
}
else { // orbital navigator
if (_disableJoystickInputs) {
clearGlobalJoystickStates();
}
_orbitalNavigator.updateStatesFromInput(
_mouseInputState,
_keyboardInputState,
deltaTime
);
_orbitalNavigator.updateCameraStateFromStates(deltaTime);
updateCameraTransitions();
}
_orbitalNavigator.updateCameraScalingFromAnchor(deltaTime);
}
void NavigationHandler::applyNavigationState(const NavigationState& ns) {
_orbitalNavigator.setAnchorNode(ns.anchor);
_orbitalNavigator.setAimNode(ns.aim);
_camera->setPose(ns.cameraPose());
CameraPose pose = ns.cameraPose();
_camera->setPositionVec3(pose.position);
_camera->setRotation(pose.rotation);
_orbitalNavigator.clearPreviousState();
_orbitalNavigator.resetNodeMovements();
resetNavigationUpdateVariables();
_pendingNavigationState.reset();
}
void NavigationHandler::updateCameraTransitions() {
@@ -328,23 +322,9 @@ void NavigationHandler::updateCameraTransitions() {
}
}
void NavigationHandler::setEnableKeyFrameInteraction() {
_useKeyFrameInteraction = true;
}
void NavigationHandler::setDisableKeyFrameInteraction() {
_useKeyFrameInteraction = false;
}
void NavigationHandler::triggerPlaybackStart() {
_playbackModeEnabled = true;
}
void NavigationHandler::stopPlayback() {
void NavigationHandler::resetNavigationUpdateVariables() {
_orbitalNavigator.resetVelocities();
_orbitalNavigator.resetNodeMovements();
_playbackModeEnabled = false;
_orbitalNavigator.updatePreviousStateVariables();
}
const SceneGraphNode* NavigationHandler::anchorNode() const {
@@ -593,6 +573,14 @@ std::vector<std::string> NavigationHandler::joystickButtonCommand(
return _orbitalNavigator.joystickStates().buttonCommand(joystickName, button);
}
void NavigationHandler::clearGlobalJoystickStates() {
std::fill(
global::joystickInputStates->begin(),
global::joystickInputStates->end(),
JoystickInputState()
);
}
scripting::LuaLibrary NavigationHandler::luaLibrary() {
return {
"navigation",

View File

@@ -741,9 +741,9 @@ void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) {
posHandle
);
// Update the camera state
_camera->setPositionVec3(pose.position);
_camera->setRotation(composeCameraRotation(camRot));
pose.rotation = composeCameraRotation(camRot);
_camera->setPose(pose);
}
void OrbitalNavigator::updateCameraScalingFromAnchor(double deltaTime) {
@@ -859,34 +859,22 @@ void OrbitalNavigator::setAnchorNode(const SceneGraphNode* anchorNode,
resetVelocities();
}
// Mark a changed anchor node as a camera interaction
if (changedAnchor) {
updateOnCameraInteraction();
}
if (_anchorNode) {
_previousAnchorNodePosition = _anchorNode->worldPosition();
_previousAnchorNodeRotation = glm::quat_cast(_anchorNode->worldRotationMatrix());
}
else {
_previousAnchorNodePosition.reset();
_previousAnchorNodeRotation.reset();
updateOnCameraInteraction(); // Mark a changed anchor node as a camera interaction
updatePreviousAnchorState();
}
}
void OrbitalNavigator::clearPreviousState() {
_previousAnchorNodePosition.reset();
_previousAnchorNodeRotation.reset();
_previousAimNodePosition.reset();
_previousAnchorNodePosition = std::nullopt;
_previousAnchorNodeRotation = std::nullopt;
_previousAimNodePosition = std::nullopt;
}
void OrbitalNavigator::setAimNode(const SceneGraphNode* aimNode) {
_retargetAimInterpolator.end();
_aimNode = aimNode;
if (_aimNode) {
_previousAimNodePosition = _aimNode->worldPosition();
}
updatePreviousAimState();
}
void OrbitalNavigator::setAnchorNode(const std::string& anchorNode) {
@@ -897,17 +885,29 @@ void OrbitalNavigator::setAimNode(const std::string& aimNode) {
_aim.set(aimNode);
}
void OrbitalNavigator::resetNodeMovements() {
void OrbitalNavigator::updatePreviousAnchorState() {
if (_anchorNode) {
_previousAnchorNodePosition = _anchorNode->worldPosition();
_previousAnchorNodeRotation = glm::quat_cast(_anchorNode->worldRotationMatrix());
}
else {
_previousAnchorNodePosition = glm::dvec3(0.0);
_previousAnchorNodeRotation = glm::dquat();
_previousAnchorNodePosition = std::nullopt;
_previousAnchorNodeRotation = std::nullopt;
}
}
_previousAimNodePosition = _aimNode ? _aimNode->worldPosition() : glm::dvec3(0.0);
void OrbitalNavigator::updatePreviousAimState() {
if (_aimNode) {
_previousAimNodePosition = _aimNode->worldPosition();
}
else {
_previousAimNodePosition = std::nullopt;
}
}
void OrbitalNavigator::updatePreviousStateVariables() {
updatePreviousAnchorState();
updatePreviousAimState();
}
void OrbitalNavigator::startRetargetAnchor() {
@@ -954,7 +954,6 @@ void OrbitalNavigator::startRetargetAim() {
_cameraToSurfaceDistanceInterpolator.start();
}
float OrbitalNavigator::retargetInterpolationTime() const {
return _retargetInterpolationTime;
}
@@ -1332,7 +1331,7 @@ double OrbitalNavigator::interpolateCameraToSurfaceDistance(double deltaTime,
_cameraToSurfaceDistanceInterpolator.setDeltaTime(static_cast<float>(deltaTime));
_cameraToSurfaceDistanceInterpolator.step();
// Interpolate distance logarithmically.
// Interpolate distance logarithmically
double result = glm::exp(glm::mix(
glm::log(currentDistance),
glm::log(targetDistance),

View File

@@ -27,7 +27,7 @@
#include <openspace/camera/camera.h>
#include <openspace/camera/camerapose.h>
#include <openspace/engine/globals.h>
#include <openspace/interaction/sessionrecording.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
@@ -174,13 +174,6 @@ void PathNavigator::updateCamera(double deltaTime) {
deltaTime = 0.01;
}
// If for some reason the time is no longer paused, pause it again
// TODO: Before we get here, one time tick happens. Should move this check to engine
if (!global::timeManager->isPaused()) {
global::timeManager->setPause(true);
LINFO("Cannot start simulation time during camera motion");
}
CameraPose newPose = _currentPath->traversePath(deltaTime, _speedScale);
const std::string newAnchor = _currentPath->currentAnchor();
@@ -195,8 +188,7 @@ void PathNavigator::updateCamera(double deltaTime) {
removeRollRotation(newPose, deltaTime);
}
camera()->setPositionVec3(newPose.position);
camera()->setRotation(newPose.rotation);
camera()->setPose(newPose);
if (_currentPath->hasReachedEnd()) {
LINFO("Reached end of path");
@@ -223,13 +215,15 @@ void PathNavigator::createPath(const ghoul::Dictionary& dictionary) {
// We want the user to be able to choose easily
const int pathType = _defaultPathType;
// Ignore paths that are created during session recording, as the camera
// position should have been recorded
if (global::sessionRecording->isPlayingBack()) {
OpenSpaceEngine::Mode m = global::openSpaceEngine->currentMode();
if (m == OpenSpaceEngine::Mode::SessionRecordingPlayback) {
// Silently ignore any paths that are being created during a session recording
// playback. The camera path should already have been recorded
return;
}
clearPath();
try {
_currentPath = std::make_unique<Path>(
createPathFromDictionary(dictionary, Path::Type(pathType))
@@ -253,7 +247,7 @@ void PathNavigator::createPath(const ghoul::Dictionary& dictionary) {
}
void PathNavigator::clearPath() {
LINFO("Clearing path");
LDEBUG("Clearing path");
_currentPath = nullptr;
}
@@ -263,6 +257,11 @@ void PathNavigator::startPath() {
return;
}
if (!global::openSpaceEngine->setMode(OpenSpaceEngine::Mode::CameraPath)) {
LERROR("Could not start camera path");
return; // couldn't switch to camera path mode
}
// Always pause the simulation time when flying, to aovid problem with objects
// moving. However, keep track of whether the time was running before the path
// was started, so we can reset it on finish
@@ -348,6 +347,7 @@ void PathNavigator::handlePathEnd() {
}
_startSimulationTimeOnFinish = false;
clearPath();
global::openSpaceEngine->resetMode();
}
void PathNavigator::findRelevantNodes() {

View File

@@ -22,59 +22,22 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/interaction/externinteraction.h>
#include <openspace/network/messagestructureshelper.h>
#include <openspace/openspace.h>
#include <openspace/camera/camera.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/navigation/keyframenavigator.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/orbitalnavigator.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/time.h>
#include <openspace/util/timemanager.h>
#include <ghoul/logging/logmanager.h>
namespace openspace::datamessagestructures {
namespace openspace {
ExternInteraction::ExternInteraction()
: properties::PropertyOwner({ "ExternInteration", "External Interaction" })
{}
void ExternInteraction::cameraInteraction(datamessagestructures::CameraKeyframe kf) {
interaction::KeyframeNavigator::CameraPose pose;
pose.focusNode = std::move(kf._focusNode);
pose.position = std::move(kf._position);
pose.rotation = std::move(kf._rotation);
pose.scale = std::move(kf._scale);
pose.followFocusNodeRotation = std::move(kf._followNodeRotation);
global::navigationHandler->keyframeNavigator().addKeyframe(kf._timestamp, pose);
}
void ExternInteraction::timeInteraction(datamessagestructures::TimeKeyframe kf) {
TimeKeyframeData timeKfData;
timeKfData.delta = std::move(kf._dt);
timeKfData.pause = std::move(kf._paused);
timeKfData.jump = std::move(kf._requiresTimeJump);
global::timeManager->addKeyframe(kf._timestamp, timeKfData);
}
void ExternInteraction::scriptInteraction(datamessagestructures::ScriptMessage sm) {
global::scriptEngine->queueScript(
std::move(sm._script),
scripting::ScriptEngine::RemoteScripting::No
);
}
datamessagestructures::CameraKeyframe ExternInteraction::generateCameraKeyframe() {
CameraKeyframe generateCameraKeyframe() {
interaction::NavigationHandler& navHandler = *global::navigationHandler;
datamessagestructures::CameraKeyframe kf;
CameraKeyframe kf;
const SceneGraphNode* focusNode = navHandler.orbitalNavigator().anchorNode();
if (!focusNode) {
@@ -102,8 +65,8 @@ datamessagestructures::CameraKeyframe ExternInteraction::generateCameraKeyframe(
return kf;
}
datamessagestructures::TimeKeyframe ExternInteraction::generateTimeKeyframe() {
datamessagestructures::TimeKeyframe kf;
TimeKeyframe generateTimeKeyframe() {
TimeKeyframe kf;
const Time& time = global::timeManager->time();
kf._dt = global::timeManager->deltaTime();
@@ -115,14 +78,13 @@ datamessagestructures::TimeKeyframe ExternInteraction::generateTimeKeyframe() {
return kf;
}
datamessagestructures::ScriptMessage ExternInteraction::generateScriptMessage(
std::string script)
{
datamessagestructures::ScriptMessage sm;
ScriptMessage generateScriptMessage(std::string script) {
ScriptMessage sm;
sm._script = std::move(script);
// Timestamp as current runtime of OpenSpace instance
sm._timestamp = global::windowDelegate->applicationTime();
return sm;
}
} // namespace openspace
} // namespace openspace::datamessagestructures

View File

@@ -239,14 +239,6 @@ void ScriptScheduler::setTimeReferenceMode(interaction::KeyframeTimeRef refType)
_timeframeMode = refType;
}
void ScriptScheduler::triggerPlaybackStart() {
_playbackModeEnabled = true;
}
void ScriptScheduler::stopPlayback() {
_playbackModeEnabled = false;
}
double ScriptScheduler::currentTime() const {
return _currentTime;
}

View File

@@ -23,6 +23,7 @@
****************************************************************************************/
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/interaction/sessionrecording.h>
@@ -228,7 +229,8 @@ int time_interpolateTogglePause(lua_State* L) {
int time_pauseToggleViaKeyboard(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::time_pauseToggleViaKeyboard");
if (global::sessionRecording->isPlayingBack()) {
OpenSpaceEngine::Mode m = global::openSpaceEngine->currentMode();
if (m == OpenSpaceEngine::Mode::SessionRecordingPlayback) {
bool isPlaybackPaused = global::sessionRecording->isPlaybackPaused();
global::sessionRecording->setPlaybackPause(!isPlaybackPaused);
}
@@ -251,7 +253,6 @@ int time_pauseToggleViaKeyboard(lua_State* L) {
int time_setPause(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::time_setPause");
bool pause = ghoul::lua::value<bool>(L);
global::timeManager->setPause(pause);
return 0;
}

View File

@@ -25,6 +25,7 @@
#include <openspace/util/timemanager.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/interaction/actionmanager.h>
#include <openspace/interaction/keybindingmanager.h>
@@ -115,6 +116,12 @@ TimeManager::TimeManager()
void TimeManager::interpolateTime(double targetTime, double durationSeconds) {
ghoul_precondition(durationSeconds > 0.f, "durationSeconds must be positive");
OpenSpaceEngine::Mode m = global::openSpaceEngine->currentMode();
if (m == OpenSpaceEngine::Mode::CameraPath) {
LERROR("Cannot change simulation time during camera path");
return;
}
const double now = currentApplicationTimeForInterpolation();
const bool pause = isPaused();
@@ -240,6 +247,12 @@ TimeKeyframeData TimeManager::interpolate(double applicationTime) {
void TimeManager::progressTime(double dt) {
ZoneScoped
OpenSpaceEngine::Mode m = global::openSpaceEngine->currentMode();
if (m == OpenSpaceEngine::Mode::CameraPath) {
// We don't want to progress time when a camera path is playing, so return
return;
}
_integrateFromTime = static_cast<Time&>(_currentTime);
// Frames | 1 2 |
// |------------------------------------|
@@ -274,7 +287,7 @@ void TimeManager::progressTime(double dt) {
const std::deque<Keyframe<TimeKeyframeData>>& keyframes = _timeline.keyframes();
std::function<bool(const KeyframeBase&, double)> comparisonFunc =
(global::sessionRecording->isPlayingBack()) ?
(isPlayingBackSessionRecording()) ?
&compareKeyframeTimeWithTime_playbackWithFrames : &compareKeyframeTimeWithTime;
auto firstFutureKeyframe = std::lower_bound(
@@ -367,7 +380,7 @@ TimeKeyframeData TimeManager::interpolate(const Keyframe<TimeKeyframeData>& past
void TimeManager::applyKeyframeData(const TimeKeyframeData& keyframeData, double dt) {
const Time& currentTime = keyframeData.time;
_deltaTime = _timePaused ? 0.0 : _targetDeltaTime;
if (global::sessionRecording->isPlayingBack()) {
if (isPlayingBackSessionRecording()) {
_currentTime.data().advanceTime(dt * _deltaTime);
}
else {
@@ -408,6 +421,11 @@ void TimeManager::clearKeyframes() {
}
void TimeManager::setTimeNextFrame(Time t) {
OpenSpaceEngine::Mode m = global::openSpaceEngine->currentMode();
if (global::openSpaceEngine->currentMode() == OpenSpaceEngine::Mode::CameraPath) {
LERROR("Cannot change simulation time during camera path");
return;
}
_shouldSetTime = true;
_timeNextFrame = std::move(t);
clearKeyframes();
@@ -647,14 +665,6 @@ void TimeManager::removeDeltaTimeStepsChangeCallback(CallbackHandle handle) {
_deltaTimeStepsChangeCallbacks.erase(it);
}
void TimeManager::triggerPlaybackStart() {
_playbackModeEnabled = true;
}
void TimeManager::stopPlayback() {
_playbackModeEnabled = false;
}
void TimeManager::removeTimeJumpCallback(CallbackHandle handle) {
const auto it = std::find_if(
_timeJumpCallbacks.begin(),
@@ -734,7 +744,6 @@ void TimeManager::interpolateDeltaTime(double newDeltaTime, double interpolation
return;
}
double now = currentApplicationTimeForInterpolation();
Time newTime(
time().j2000Seconds() + (_deltaTime + newDeltaTime) * 0.5 * interpolationDuration
);
@@ -744,9 +753,10 @@ void TimeManager::interpolateDeltaTime(double newDeltaTime, double interpolation
_targetDeltaTime = newDeltaTime;
if (global::sessionRecording->isPlayingBack()) {
now = previousApplicationTimeForInterpolation();
}
double now = isPlayingBackSessionRecording() ?
previousApplicationTimeForInterpolation() :
currentApplicationTimeForInterpolation();
addKeyframe(now, currentKeyframe);
addKeyframe(now + interpolationDuration, futureKeyframe);
}
@@ -833,7 +843,12 @@ void TimeManager::interpolatePause(bool pause, double interpolationDuration) {
return;
}
double now = currentApplicationTimeForInterpolation();
OpenSpaceEngine::Mode engineMode = global::openSpaceEngine->currentMode();
if (!pause && engineMode == OpenSpaceEngine::Mode::CameraPath) {
LERROR("Cannot unpause simulation time during camera path");
return;
}
double targetDelta = pause ? 0.0 : _targetDeltaTime;
Time newTime(
time().j2000Seconds() + (_deltaTime + targetDelta) * 0.5 * interpolationDuration
@@ -843,9 +858,10 @@ void TimeManager::interpolatePause(bool pause, double interpolationDuration) {
TimeKeyframeData futureKeyframe = { newTime, _targetDeltaTime, pause, false };
_timePaused = pause;
if (global::sessionRecording->isPlayingBack()) {
now = previousApplicationTimeForInterpolation();
}
double now = isPlayingBackSessionRecording() ?
previousApplicationTimeForInterpolation() :
currentApplicationTimeForInterpolation();
clearKeyframes();
if (interpolationDuration > 0) {
addKeyframe(now, currentKeyframe);
@@ -863,7 +879,7 @@ double TimeManager::currentApplicationTimeForInterpolation() const {
}
double TimeManager::previousApplicationTimeForInterpolation() const {
//If playing back with frames, this function needs to be called when a time rate
// If playing back with frames, this function needs to be called when a time rate
// interpolation (either speed change or pause) begins and ends. If the application
// time of the interpolation keyframe timestamp (when it was added to timeline) is
// exactly the same as when it is evaluated, then the interpolation math fails and
@@ -874,6 +890,11 @@ double TimeManager::previousApplicationTimeForInterpolation() const {
return _previousApplicationTime;
}
bool TimeManager::isPlayingBackSessionRecording() const {
return (global::openSpaceEngine->currentMode() ==
OpenSpaceEngine::Mode::SessionRecordingPlayback);
}
void TimeManager::setTimeFromProfile(const Profile& p) {
Time t;