diff --git a/include/openspace/interaction/keyframerecordinghandler.h b/include/openspace/interaction/keyframerecordinghandler.h index 6c0ed328aa..58a21ae810 100644 --- a/include/openspace/interaction/keyframerecordinghandler.h +++ b/include/openspace/interaction/keyframerecordinghandler.h @@ -43,8 +43,11 @@ public: void addCameraKeyframe(double sequenceTime); void addScriptKeyframe(double sequenceTime, std::string script); void removeKeyframe(int index); + void removeKeyframeById(int id); void updateKeyframe(int index); + void updateKeyframeById(int id); void moveKeyframe(int index, double sequenceTime); + void moveKeyframeById(int id, double sequenceTime); void saveSequence(std::filesystem::path filename); void loadSequence(std::filesystem::path filename); void play(); @@ -55,7 +58,7 @@ public: private: SessionRecording _timeline; - size_t id = 1; + int _id = 1; }; } // namespace openspace diff --git a/src/interaction/keyframerecordinghandler.cpp b/src/interaction/keyframerecordinghandler.cpp index 477292cc11..dc175b619f 100644 --- a/src/interaction/keyframerecordinghandler.cpp +++ b/src/interaction/keyframerecordinghandler.cpp @@ -48,7 +48,7 @@ void KeyframeRecordingHandler::addCameraKeyframe(double sequenceTime) { sequenceTime, global::timeManager->time().j2000Seconds(), KeyframeNavigator::CameraPose(std::move(kf)), - id++ + _id++ }; auto it = std::upper_bound( @@ -68,7 +68,7 @@ void KeyframeRecordingHandler::addScriptKeyframe(double sequenceTime, std::strin sequenceTime, global::timeManager->time().j2000Seconds(), std::move(script), - id++ + _id++ }; auto it = std::upper_bound( @@ -89,6 +89,23 @@ void KeyframeRecordingHandler::removeKeyframe(int index) { _timeline.entries.erase(_timeline.entries.begin() + index); } +void KeyframeRecordingHandler::removeKeyframeById(int id) { + auto entry = std::find_if( + _timeline.entries.begin(), + _timeline.entries.end(), + [id](const SessionRecording::Entry& e) { + return e.id == id; + } + ); + + if (entry != _timeline.entries.end()) { + _timeline.entries.erase(entry); + } + else { + throw ghoul::RuntimeError(std::format("Could not find keyframe with id '{}'", id)); + } +} + void KeyframeRecordingHandler::updateKeyframe(int index) { using namespace datamessagestructures; if (index < 0 || static_cast(index) > (_timeline.entries.size() - 1)) { @@ -103,6 +120,24 @@ void KeyframeRecordingHandler::updateKeyframe(int index) { camera = KeyframeNavigator::CameraPose(generateCameraKeyframe()); } +void KeyframeRecordingHandler::updateKeyframeById(int id) { + auto entry = std::find_if( + _timeline.entries.begin(), + _timeline.entries.end(), + [id](const SessionRecording::Entry& e) { + return e.id == id; + } + ); + + if (entry != _timeline.entries.end()) { + int index = static_cast(entry - _timeline.entries.begin()); + updateKeyframeById(index); + } + else { + throw ghoul::RuntimeError(std::format("Could not find keyframe with id '{}'", id)); + } +} + void KeyframeRecordingHandler::moveKeyframe(int index, double sequenceTime) { if (index < 0 || static_cast(index) >(_timeline.entries.size() - 1)) { throw ghoul::RuntimeError(std::format("Index {} out of range", index)); @@ -118,6 +153,21 @@ void KeyframeRecordingHandler::moveKeyframe(int index, double sequenceTime) { ); } +void KeyframeRecordingHandler::moveKeyframeById(int id, double sequenceTime) { + auto entry = std::find_if( + _timeline.entries.begin(), + _timeline.entries.end(), + [id](const SessionRecording::Entry& e) { + return e.id == id; + } + ); + + if (entry != _timeline.entries.end()) { + int index = static_cast(entry - _timeline.entries.begin()); + moveKeyframe(index, sequenceTime); + } +} + void KeyframeRecordingHandler::saveSequence(std::filesystem::path filename) { if (filename.empty()) { throw ghoul::RuntimeError("Failed to save file, reason: Invalid empty file name"); @@ -128,9 +178,9 @@ void KeyframeRecordingHandler::saveSequence(std::filesystem::path filename) { void KeyframeRecordingHandler::loadSequence(std::filesystem::path filename) { _timeline = loadSessionRecording(filename); - id = 1; + _id = 1; for (auto& entry : _timeline.entries) { - entry.id = id++; + entry.id = _id++; } } @@ -154,8 +204,11 @@ scripting::LuaLibrary KeyframeRecordingHandler::luaLibrary() { codegen::lua::AddCameraKeyframe, codegen::lua::AddScriptKeyframe, codegen::lua::RemoveKeyframe, + codegen::lua::RemoveKeyframeById, codegen::lua::UpdateKeyframe, + codegen::lua::UpdateKeyframeById, codegen::lua::MoveKeyframe, + codegen::lua::MoveKeyframeById, codegen::lua::SaveSequence, codegen::lua::LoadSequence, codegen::lua::Play, diff --git a/src/interaction/keyframerecordinghandler_lua.inl b/src/interaction/keyframerecordinghandler_lua.inl index ee8207d581..746511fd49 100644 --- a/src/interaction/keyframerecordinghandler_lua.inl +++ b/src/interaction/keyframerecordinghandler_lua.inl @@ -52,18 +52,36 @@ namespace { global::keyframeRecording->removeKeyframe(index); } +// Removes a keyframe with the specified id +[[codegen::luawrap]] void removeKeyframeById(int id) { + using namespace openspace; + global::keyframeRecording->removeKeyframeById(id); +} + // Update the camera position at keyframe specified by the 0-based index [[codegen::luawrap]] void updateKeyframe(int index) { using namespace openspace; global::keyframeRecording->updateKeyframe(index); } +// Update the camera position at keyframe with the specified id +[[codegen::luawrap]] void updateKeyframeById(int index) { + using namespace openspace; + global::keyframeRecording->updateKeyframeById(index); +} + // Move keyframe of `index` to the new specified `sequenceTime` [[codegen::luawrap]] void moveKeyframe(int index, double sequenceTime) { using namespace openspace; global::keyframeRecording->moveKeyframe(index, sequenceTime); } +// Move keyframe of `id` to the new specified `sequenceTime` +[[codegen::luawrap]] void moveKeyframeById(int id, double sequenceTime) { + using namespace openspace; + global::keyframeRecording->moveKeyframeById(id, sequenceTime); +} + // Saves the current sequence of keyframes to disk by the optionally specified `filename`. [[codegen::luawrap]] void saveSequence(std::filesystem::path filename) { using namespace openspace;