mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-02-24 22:09:10 -06:00
Issue/2121 : SessionRecording wildcard and syntax improvements
This commit is contained in:
@@ -604,7 +604,7 @@ protected:
|
||||
Timestamps t3stamps;
|
||||
};
|
||||
double _timestampRecordStarted = 0.0;
|
||||
Timestamps _timestamps3RecordStarted;
|
||||
Timestamps _timestamps3RecordStarted{ 0.0, 0.0, 0.0 };
|
||||
double _timestampPlaybackStarted_application = 0.0;
|
||||
double _timestampPlaybackStarted_simulation = 0.0;
|
||||
double _timestampApplicationStarted_simulation = 0.0;
|
||||
@@ -696,10 +696,12 @@ protected:
|
||||
std::string& version, DataMode& mode);
|
||||
void populateListofLoadedSceneGraphNodes();
|
||||
|
||||
bool checkIfScriptUsesScenegraphNode(std::string s);
|
||||
void checkForScenegraphNodeAccess_Scene(std::string& s, std::string& result);
|
||||
void checkForScenegraphNodeAccess_Nav(std::string& s, std::string& result);
|
||||
void checkIfScriptUsesScenegraphNode(std::string s);
|
||||
bool checkForScenegraphNodeAccessScene(std::string& s);
|
||||
bool checkForScenegraphNodeAccessNav(std::string& navTerm);
|
||||
std::string extractScenegraphNodeFromScene(std::string& s);
|
||||
bool checkIfInitialFocusNodeIsLoaded(unsigned int firstCamIndex);
|
||||
std::string isolateTermFromQuotes(std::string s);
|
||||
void eraseSpacesFromString(std::string& s);
|
||||
std::string getNameFromSurroundingQuotes(std::string& s);
|
||||
|
||||
@@ -733,11 +735,11 @@ protected:
|
||||
|
||||
bool _saveRenderingDuringPlayback = false;
|
||||
double _saveRenderingDeltaTime = 1.0 / 30.0;
|
||||
double _saveRenderingCurrentRecordedTime;
|
||||
double _saveRenderingCurrentRecordedTime = 0.0;
|
||||
std::chrono::steady_clock::duration _saveRenderingDeltaTime_interpolation_usec;
|
||||
std::chrono::steady_clock::time_point _saveRenderingCurrentRecordedTime_interpolation;
|
||||
double _saveRenderingCurrentApplicationTime_interpolation;
|
||||
long long _saveRenderingClockInterpolation_countsPerSec;
|
||||
double _saveRenderingCurrentApplicationTime_interpolation = 0.0;
|
||||
long long _saveRenderingClockInterpolation_countsPerSec = 1;
|
||||
bool _saveRendering_isFirstFrame = true;
|
||||
|
||||
unsigned char _keyframeBuffer[_saveBufferMaxSize_bytes];
|
||||
|
||||
@@ -253,6 +253,17 @@ public:
|
||||
*/
|
||||
void setPropertiesFromProfile(const Profile& p);
|
||||
|
||||
/**
|
||||
* Searches for any properties that match the regex propertyString, and returns
|
||||
* the results in a vector.
|
||||
*
|
||||
* \param propertyString the regex string that is intended to match one or more
|
||||
* properties in the currently-available properties
|
||||
* \return Vector of Property objs containing property names that matched the regex
|
||||
*/
|
||||
std::vector<properties::Property*> propertiesMatchingRegex(
|
||||
std::string propertyString);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Accepts string version of a property value from a profile, converts it to the
|
||||
|
||||
@@ -271,7 +271,7 @@ void SessionRecording::stopRecording() {
|
||||
if (_state == SessionState::Recording) {
|
||||
// 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];
|
||||
@@ -1514,7 +1514,7 @@ bool SessionRecording::playbackScript() {
|
||||
_playbackLineNum
|
||||
);
|
||||
|
||||
success &= checkIfScriptUsesScenegraphNode(kf._script);
|
||||
checkIfScriptUsesScenegraphNode(kf._script);
|
||||
|
||||
if (success) {
|
||||
success = addKeyframe(
|
||||
@@ -1534,61 +1534,100 @@ void SessionRecording::populateListofLoadedSceneGraphNodes() {
|
||||
}
|
||||
}
|
||||
|
||||
bool SessionRecording::checkIfScriptUsesScenegraphNode(std::string s) {
|
||||
void SessionRecording::checkIfScriptUsesScenegraphNode(std::string s) {
|
||||
if (s.rfind(scriptReturnPrefix, 0) == 0) {
|
||||
s.erase(0, scriptReturnPrefix.length());
|
||||
}
|
||||
// This works for both setPropertyValue and setPropertyValueSingle
|
||||
if (s.rfind("openspace.setPropertyValue", 0) == 0) {
|
||||
std::string found;
|
||||
if (s.find("(\"") != std::string::npos) {
|
||||
std::string subj = s.substr(s.find("(\"") + 2);
|
||||
checkForScenegraphNodeAccess_Scene(subj, found);
|
||||
checkForScenegraphNodeAccess_Nav(subj, found);
|
||||
if (found.length() > 0) {
|
||||
auto it = std::find(_loadedNodes.begin(), _loadedNodes.end(), found);
|
||||
bool containsSetPropertyVal = (s.rfind("openspace.setPropertyValue", 0) == 0);
|
||||
bool containsParensStart = (s.find("(") != std::string::npos);
|
||||
if (containsSetPropertyVal && containsParensStart) {
|
||||
std::string subjectOfSetProp = isolateTermFromQuotes(s.substr(s.find("(") + 1));
|
||||
if (checkForScenegraphNodeAccessNav(subjectOfSetProp)) {
|
||||
size_t commaPos = s.find(",");
|
||||
std::string navNode = isolateTermFromQuotes(s.substr(commaPos + 1));
|
||||
if (navNode != "nil") {
|
||||
std::vector<std::string>::iterator it =
|
||||
std::find(_loadedNodes.begin(), _loadedNodes.end(), navNode);
|
||||
if (it == _loadedNodes.end()) {
|
||||
LERROR(fmt::format(
|
||||
"Playback file requires scenegraph node '{}', which is "
|
||||
"not currently loaded", found
|
||||
LWARNING(fmt::format(
|
||||
"Playback file contains a property setting of navigation using"
|
||||
" scenegraph node '{}', which is not currently loaded", navNode
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (checkForScenegraphNodeAccessScene(subjectOfSetProp)) {
|
||||
std::string found = extractScenegraphNodeFromScene(subjectOfSetProp);
|
||||
if (!found.empty()) {
|
||||
std::vector<properties::Property*> matchHits =
|
||||
global::renderEngine->scene()->propertiesMatchingRegex(
|
||||
subjectOfSetProp
|
||||
);
|
||||
if (matchHits.empty()) {
|
||||
LWARNING(fmt::format(
|
||||
"Playback file contains a property setting of scenegraph"
|
||||
" node '{}', which is not currently loaded", found
|
||||
));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SessionRecording::checkForScenegraphNodeAccess_Scene(std::string& s,
|
||||
std::string& result)
|
||||
{
|
||||
bool SessionRecording::checkForScenegraphNodeAccessScene(std::string& s) {
|
||||
const std::string scene = "Scene.";
|
||||
auto posScene = s.find(scene);
|
||||
return (s.find(scene) != std::string::npos);
|
||||
}
|
||||
|
||||
std::string SessionRecording::extractScenegraphNodeFromScene(std::string& s) {
|
||||
const std::string scene = "Scene.";
|
||||
std::string extracted;
|
||||
size_t posScene = s.find(scene);
|
||||
if (posScene != std::string::npos) {
|
||||
auto posDot = s.find(".", posScene + scene.length() + 1);
|
||||
size_t posDot = s.find(".", posScene + scene.length() + 1);
|
||||
if (posDot > posScene && posDot != std::string::npos) {
|
||||
result = s.substr(posScene + scene.length(), posDot
|
||||
- (posScene + scene.length()));
|
||||
extracted = s.substr(posScene + scene.length(), posDot -
|
||||
(posScene + scene.length()));
|
||||
}
|
||||
}
|
||||
return extracted;
|
||||
}
|
||||
|
||||
void SessionRecording::checkForScenegraphNodeAccess_Nav(std::string& s,
|
||||
std::string& result)
|
||||
{
|
||||
bool SessionRecording::checkForScenegraphNodeAccessNav(std::string& navTerm) {
|
||||
const std::string nextTerm = "NavigationHandler.OrbitalNavigator.";
|
||||
auto posNav = s.find(nextTerm);
|
||||
size_t posNav = navTerm.find(nextTerm);
|
||||
if (posNav != std::string::npos) {
|
||||
for (std::string accessName : _navScriptsUsingNodes) {
|
||||
if (s.substr(posNav + nextTerm.length()).rfind(accessName) == 0) {
|
||||
std::string postName = s.substr(posNav + nextTerm.length()
|
||||
+ accessName.length() + 2);
|
||||
eraseSpacesFromString(postName);
|
||||
result = getNameFromSurroundingQuotes(postName);
|
||||
}
|
||||
if (navTerm.find(accessName) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string SessionRecording::isolateTermFromQuotes(std::string s) {
|
||||
//Remove any leading spaces
|
||||
while (s.front() == ' ') {
|
||||
s.erase(0, 1);
|
||||
}
|
||||
const std::string possibleQuotes = "\'\"[]";
|
||||
while (possibleQuotes.find(s.front()) != std::string::npos) {
|
||||
s.erase(0, 1);
|
||||
}
|
||||
for (char q : possibleQuotes) {
|
||||
if (s.find(q) != std::string::npos) {
|
||||
s = s.substr(0, s.find(q));
|
||||
return s;
|
||||
}
|
||||
}
|
||||
//If no quotes found, remove other possible characters from end
|
||||
std::string unwantedChars = " );";
|
||||
while (unwantedChars.find(s.back()) != std::string::npos) {
|
||||
s.pop_back();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void SessionRecording::eraseSpacesFromString(std::string& s) {
|
||||
|
||||
@@ -812,6 +812,12 @@ PropertyValueType Scene::propertyValueType(const std::string& value) {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<properties::Property*> Scene::propertiesMatchingRegex(
|
||||
std::string propertyString)
|
||||
{
|
||||
return findMatchesInAllProperties(propertyString, allProperties(), "");
|
||||
}
|
||||
|
||||
scripting::LuaLibrary Scene::luaLibrary() {
|
||||
return {
|
||||
"",
|
||||
|
||||
@@ -81,21 +81,17 @@ openspace::properties::PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* p
|
||||
return tagMatchOwner;
|
||||
}
|
||||
|
||||
void applyRegularExpression(lua_State* L, const std::string& regex,
|
||||
const std::vector<openspace::properties::Property*>& properties,
|
||||
double interpolationDuration,
|
||||
const std::string& groupName,
|
||||
ghoul::EasingFunction easingFunction)
|
||||
std::vector<openspace::properties::Property*> findMatchesInAllProperties(
|
||||
const std::string& regex,
|
||||
const std::vector<openspace::properties::Property*>& properties,
|
||||
const std::string& groupName)
|
||||
{
|
||||
using namespace openspace;
|
||||
using ghoul::lua::errorLocation;
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
std::vector<properties::Property*> matches;
|
||||
const bool isGroupMode = !groupName.empty();
|
||||
bool isLiteral = false;
|
||||
|
||||
const int type = lua_type(L, -1);
|
||||
|
||||
// Extract the property and node name to be searched for from regex
|
||||
std::string propertyName;
|
||||
std::string nodeName;
|
||||
@@ -107,25 +103,25 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
|
||||
// If none then malformed regular expression
|
||||
if (propertyName.empty() && nodeName.empty()) {
|
||||
LERRORC(
|
||||
"applyRegularExpression",
|
||||
"findMatchesInAllProperties",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': Empty both before and after '*'",
|
||||
regex
|
||||
)
|
||||
);
|
||||
return;
|
||||
return matches;
|
||||
}
|
||||
|
||||
// Currently do not support several wildcards
|
||||
if (regex.find_first_of("*", wildPos + 1) != std::string::npos) {
|
||||
LERRORC(
|
||||
"applyRegularExpression",
|
||||
"findMatchesInAllProperties",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': Currently only one '*' is "
|
||||
"supported", regex
|
||||
)
|
||||
);
|
||||
return;
|
||||
return matches;
|
||||
}
|
||||
}
|
||||
// Literal or tag
|
||||
@@ -146,7 +142,7 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
|
||||
if (isLiteral && id != propertyName) {
|
||||
continue;
|
||||
}
|
||||
else if (!propertyName.empty()){
|
||||
else if (!propertyName.empty()) {
|
||||
size_t propertyPos = id.find(propertyName);
|
||||
if (propertyPos != std::string::npos) {
|
||||
// Check that the propertyName fully matches the property in id
|
||||
@@ -192,6 +188,36 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
matches.push_back(prop);
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
|
||||
void applyRegularExpression(lua_State* L, const std::string& regex,
|
||||
const std::vector<openspace::properties::Property*>& properties,
|
||||
double interpolationDuration,
|
||||
const std::string& groupName,
|
||||
ghoul::EasingFunction easingFunction)
|
||||
{
|
||||
using namespace openspace;
|
||||
using ghoul::lua::errorLocation;
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
const bool isGroupMode = !groupName.empty();
|
||||
bool isLiteral = false;
|
||||
|
||||
const int type = lua_type(L, -1);
|
||||
|
||||
std::vector<properties::Property*> matchingProps = findMatchesInAllProperties(
|
||||
regex,
|
||||
properties,
|
||||
groupName
|
||||
);
|
||||
|
||||
// Stores whether we found at least one matching property. If this is false at the
|
||||
// end of the loop, the property name regex was probably misspelled.
|
||||
bool foundMatching = false;
|
||||
for (properties::Property* prop : matchingProps) {
|
||||
|
||||
// Check that the types match
|
||||
if (type != prop->typeLua()) {
|
||||
|
||||
Reference in New Issue
Block a user