mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2025-12-31 16:30:07 -06:00
288 lines
11 KiB
C++
288 lines
11 KiB
C++
/*****************************************************************************************
|
|
* *
|
|
* OpenSpace *
|
|
* *
|
|
* Copyright (c) 2014-2025 *
|
|
* *
|
|
* 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___SESSIONRECORDINGHANDLER___H__
|
|
#define __OPENSPACE_CORE___SESSIONRECORDINGHANDLER___H__
|
|
|
|
#include <openspace/properties/propertyowner.h>
|
|
|
|
#include <openspace/interaction/sessionrecording.h>
|
|
#include <openspace/properties/scalar/boolproperty.h>
|
|
#include <openspace/scripting/lualibrary.h>
|
|
|
|
namespace openspace::interaction {
|
|
|
|
class SessionRecordingHandler : public properties::PropertyOwner {
|
|
public:
|
|
enum class SessionState {
|
|
Idle = 0,
|
|
Recording,
|
|
Playback,
|
|
PlaybackPaused
|
|
};
|
|
|
|
using CallbackHandle = int;
|
|
using StateChangeCallback = std::function<void()>;
|
|
|
|
SessionRecordingHandler();
|
|
~SessionRecordingHandler() override = default;
|
|
|
|
/**
|
|
* This is called with every rendered frame. If in recording state, the camera state
|
|
* will be saved to the recording file (if its state has changed since last). If in
|
|
* playback state, the next keyframe will be used (if it is time to do so).
|
|
*/
|
|
void preSynchronization(double dt);
|
|
|
|
/**
|
|
* If enabled, calling this function will render information about the session
|
|
* recording that is currently taking place to the screen.
|
|
*/
|
|
void render() const;
|
|
|
|
/**
|
|
* Fixed delta time set by user for use during saving of frame during playback mode.
|
|
*/
|
|
double fixedDeltaTimeDuringFrameOutput() const;
|
|
|
|
/**
|
|
* Returns the number of microseconds that have elapsed since playback started, if
|
|
* playback is set to be in the mode where a screenshot is captured with every
|
|
* rendered frame (enableTakeScreenShotDuringPlayback() is used to enable this mode).
|
|
* At the start of playback, this timer is set to the current steady_clock value.
|
|
* However, during playback it is incremented by the fixed framerate of the playback
|
|
* rather than the actual clock value (as in normal operation).
|
|
*
|
|
* \return Number of microseconds elapsed since playback started in terms of the
|
|
* number of rendered frames multiplied by the fixed time increment per frame
|
|
*/
|
|
std::chrono::steady_clock::time_point currentPlaybackInterpolationTime() const;
|
|
|
|
/**
|
|
* Returns the simulated application time. This simulated application time is only
|
|
* used when playback is set to be in the mode where a screenshot is captured with
|
|
* every rendered frame (enableTakeScreenShotDuringPlayback() is used to enable this
|
|
* mode). At the start of playback, this timer is set to the value of the current
|
|
* applicationTime function provided by the window delegate (used during normal mode
|
|
* or playback). However, during playback it is incremented by the fixed framerate of
|
|
* the playback rather than the actual clock value.
|
|
*
|
|
* \return Application time in seconds, for use in playback-with-frames mode
|
|
*/
|
|
double currentApplicationInterpolationTime() const;
|
|
|
|
/**
|
|
* Starts a recording session, which will save data to the provided filename according
|
|
* to the data format specified, and will continue until recording is stopped using
|
|
* stopRecording() method.
|
|
*/
|
|
void startRecording();
|
|
|
|
/**
|
|
* Used to stop a recording in progress. If open, the recording file will be closed,
|
|
* and all keyframes deleted from memory.
|
|
* \param filename File saved with recorded keyframes
|
|
*/
|
|
void stopRecording(const std::filesystem::path& filename, DataMode dataMode,
|
|
bool overwrite = false);
|
|
|
|
/**
|
|
* Used to check if a session recording is in progress.
|
|
*
|
|
* \return `true` if recording is in progress
|
|
*/
|
|
bool isRecording() const;
|
|
|
|
/**
|
|
* Starts a playback session, which can run in one of three different time modes.
|
|
*
|
|
* \param timeline The session recording timeline that should be played back
|
|
* \param loop If true then the file will playback in loop mode, continuously looping
|
|
* back to the beginning until it is manually stopped
|
|
* \param shouldWaitForFinishedTiles If true, the playback will wait for tiles to be
|
|
* finished before progressing to the next frame. This value is only used when
|
|
* `enableTakeScreenShotDuringPlayback` was called before. Otherwise this value
|
|
* will be ignored
|
|
* \param saveScreenshotFps If this value is specified, screenshots will be taken at
|
|
* the provided framerate. If the value is not specified, no screenshots will
|
|
* be taken
|
|
*/
|
|
void startPlayback(SessionRecording timeline, bool loop,
|
|
bool shouldWaitForFinishedTiles, std::optional<int> saveScreenshotFps);
|
|
|
|
/**
|
|
* Used to stop a playback in progress. If open, the playback file will be closed, and
|
|
* all keyframes deleted from memory.
|
|
*/
|
|
void stopPlayback();
|
|
|
|
/**
|
|
* Returns playback pause status.
|
|
*
|
|
* \return `true` if playback is paused
|
|
*/
|
|
bool isPlaybackPaused() const;
|
|
|
|
/**
|
|
* Pauses a playback session. This does both the normal pause functionality of setting
|
|
* simulation delta time to zero, and pausing the progression through the timeline.
|
|
*
|
|
* \param pause If `true`, then will set playback timeline progression to zero
|
|
*/
|
|
void setPlaybackPause(bool pause);
|
|
|
|
/**
|
|
* Enables that rendered frames should be saved during playback.
|
|
*
|
|
* \param fps Number of frames per second.
|
|
*/
|
|
//void enableTakeScreenShotDuringPlayback(int fps);
|
|
|
|
/**
|
|
* Used to disable that renderings are saved during playback.
|
|
*/
|
|
//void disableTakeScreenShotDuringPlayback();
|
|
|
|
/**
|
|
* Used to check if a session playback is in progress.
|
|
*
|
|
* \return `true` if playback is in progress
|
|
*/
|
|
bool isPlayingBack() const;
|
|
|
|
void seek(double recordingTime);
|
|
|
|
/**
|
|
* Is saving frames during playback.
|
|
*/
|
|
bool isSavingFramesDuringPlayback() const;
|
|
|
|
bool shouldWaitForTileLoading() const;
|
|
|
|
/**
|
|
* Used to obtain the state of idle/recording/playback.
|
|
*
|
|
* \return int value of state as defined by struct SessionState
|
|
*/
|
|
SessionState state() const;
|
|
|
|
/**
|
|
* Used to trigger a save of a script to the recording file, but only if a recording
|
|
* is currently in progress.
|
|
*
|
|
* \param script String of the Lua command to be saved
|
|
*/
|
|
void saveScriptKeyframeToTimeline(std::string script);
|
|
|
|
/**
|
|
* \return The Lua library that contains all Lua functions available to affect the
|
|
* interaction
|
|
*/
|
|
static openspace::scripting::LuaLibrary luaLibrary();
|
|
|
|
/**
|
|
* Used to request a callback for notification of playback state change.
|
|
*
|
|
* \param cb Function handle for callback
|
|
* \return CallbackHandle value of callback number
|
|
*/
|
|
CallbackHandle addStateChangeCallback(StateChangeCallback cb);
|
|
|
|
/**
|
|
* Removes the callback for notification of playback state change.
|
|
*
|
|
* \param handle Function handle for the callback
|
|
*/
|
|
void removeStateChangeCallback(CallbackHandle handle);
|
|
|
|
/**
|
|
* Provides list of available playback files.
|
|
*
|
|
* \return Vector of filenames in recordings dir
|
|
*/
|
|
std::vector<std::string> playbackList() const;
|
|
|
|
/**
|
|
* Since session recordings only record changes, the initial conditions aren't
|
|
* preserved when a playback starts. This function is called whenever a property value
|
|
* is set and a recording is in progress. Before the set happens, this function will
|
|
* read the current value of the property and store it so that when the recording is
|
|
* finished, the initial state will be added as a set property command at the
|
|
* beginning of the recording file, to be applied when playback starts.
|
|
*
|
|
* \param prop The property being set
|
|
*/
|
|
void savePropertyBaseline(properties::Property& prop);
|
|
|
|
private:
|
|
void tickPlayback(double dt);
|
|
void tickRecording(double dt);
|
|
|
|
void setupPlayback(double startTime);
|
|
|
|
void cleanUpTimelinesAndKeyframes();
|
|
|
|
void checkIfScriptUsesScenegraphNode(std::string_view script) const;
|
|
|
|
|
|
properties::BoolProperty _renderPlaybackInformation;
|
|
properties::BoolProperty _ignoreRecordedScale;
|
|
properties::BoolProperty _addModelMatrixinAscii;
|
|
|
|
struct {
|
|
double elapsedTime = 0.0;
|
|
bool isLooping = false;
|
|
bool playbackPausedWithDeltaTimePause = false;
|
|
bool waitForLoading = false;
|
|
|
|
struct {
|
|
bool enabled = false;
|
|
double deltaTime = 1.0 / 30.0;
|
|
std::chrono::steady_clock::time_point currentRecordedTime;
|
|
double currentApplicationTime = 0.0;
|
|
} saveScreenshots;
|
|
} _playback;
|
|
|
|
struct {
|
|
double elapsedTime = 0.0;
|
|
} _recording;
|
|
|
|
SessionState _state = SessionState::Idle;
|
|
SessionState _lastState = SessionState::Idle;
|
|
|
|
|
|
SessionRecording _timeline;
|
|
std::vector<SessionRecording::Entry>::const_iterator _currentEntry =
|
|
_timeline.entries.end();
|
|
std::unordered_map<std::string, std::string> _savePropertiesBaseline;
|
|
std::vector<std::string> _loadedNodes;
|
|
|
|
int _nextCallbackHandle = 0;
|
|
std::vector<std::pair<CallbackHandle, StateChangeCallback>> _stateChangeCallbacks;
|
|
};
|
|
|
|
} // namespace openspace::interaction
|
|
|
|
#endif // __OPENSPACE_CORE___SESSIONRECORDINGHANDLER___H__
|