Replace 'required' with 'require' and 'requested' with 'request'

Continue the work of factoring out the serialization and deserialization of the profile files
This commit is contained in:
Alexander Bock
2020-06-17 09:33:41 +02:00
parent 809ee9c753
commit 52ca39fc22
18 changed files with 249 additions and 185 deletions

View File

@@ -2,9 +2,9 @@
1.0
#Asset
scene/solarsystem/planets/earth/moon/moon required
scene/solarsystem/missions/apollo/8/apollo8 required
scene/solarsystem/planets/earth/earth required
scene/solarsystem/planets/earth/moon/moon require
scene/solarsystem/missions/apollo/8/apollo8 require
scene/solarsystem/planets/earth/earth require
#Property
setPropertyValueSingle NavigationHandler.OrbitalNavigator.MinimumAllowedDistance 0.000000

View File

@@ -2,13 +2,13 @@
1.0
#Asset
scene/solarsystem/planets/earth/moon/moon required
scene/solarsystem/missions/apollo/8/apollo8 required
scene/solarsystem/missions/apollo/11/apollo11 required
scene/solarsystem/missions/apollo/17/lem required
scene/solarsystem/missions/apollo/apollo_globebrowsing required
scene/solarsystem/missions/apollo/11/lem_flipbook required
scene/solarsystem/missions/apollo/insignias_map required
scene/solarsystem/planets/earth/moon/moon require
scene/solarsystem/missions/apollo/8/apollo8 require
scene/solarsystem/missions/apollo/11/apollo11 require
scene/solarsystem/missions/apollo/17/lem require
scene/solarsystem/missions/apollo/apollo_globebrowsing require
scene/solarsystem/missions/apollo/11/lem_flipbook require
scene/solarsystem/missions/apollo/insignias_map require
#Property
setPropertyValueSingle Scene.Moon.Renderable.Layers.ColorLayers.A17_travmap.BlendMode 0

View File

@@ -2,9 +2,9 @@
1.0
#Asset
scene/solarsystem/missions/dawn/ceres required
scene/solarsystem/missions/dawn/dawn required
scene/solarsystem/missions/dawn/vesta required
scene/solarsystem/missions/dawn/ceres require
scene/solarsystem/missions/dawn/dawn require
scene/solarsystem/missions/dawn/vesta require
#Time
absolute 2011 AUG 06 00:00:00

View File

@@ -2,8 +2,8 @@
1.0
#Asset
scene/solarsystem/planets/earth/earth required
scene/solarsystem/planets/earth/satellites/satellites required
scene/solarsystem/planets/earth/earth require
scene/solarsystem/planets/earth/satellites/satellites require
#Property
setPropertyValue {earth_satellites}.Renderable.Enabled false

View File

@@ -2,13 +2,13 @@
1.0
#Asset
scene/solarsystem/planets/earth/earth required
scene/solarsystem/planets/jupiter/minor_moons required
scene/solarsystem/planets/saturn/minor_moons required
scene/solarsystem/planets/uranus/minor_moons required
scene/solarsystem/planets/neptune/inner_moons required
scene/solarsystem/planets/neptune/irregular_prograde_moons required
scene/solarsystem/planets/neptune/irregular_retrograde_moons required
scene/solarsystem/planets/earth/earth require
scene/solarsystem/planets/jupiter/minor_moons require
scene/solarsystem/planets/saturn/minor_moons require
scene/solarsystem/planets/uranus/minor_moons require
scene/solarsystem/planets/neptune/inner_moons require
scene/solarsystem/planets/neptune/irregular_prograde_moons require
scene/solarsystem/planets/neptune/irregular_retrograde_moons require
#Time
relative -1d

View File

@@ -5,12 +5,12 @@
Gaia openspace.printFatal('Could not load scene due to missing module "gaia"')
#Asset
scene/solarsystem/planets/earth/earth required
scene/milkyway/gaia/gaiastars required
scene/milkyway/gaia/apogee required
scene/milkyway/gaia/galah required
scene/solarsystem/missions/gaia/gaia required
scene/solarsystem/missions/gaia/trail required
scene/solarsystem/planets/earth/earth require
scene/milkyway/gaia/gaiastars require
scene/milkyway/gaia/apogee require
scene/milkyway/gaia/galah require
scene/solarsystem/missions/gaia/gaia require
scene/solarsystem/missions/gaia/trail require
#Property
setPropertyValueSingle Scene.Stars.Renderable.Enabled false

View File

@@ -2,7 +2,7 @@
1.0
#Asset
scene/solarsystem/missions/insight/edl required
scene/solarsystem/missions/insight/edl require
#Property
setPropertyValueSingle Scene.PlutoBarycenterTrail.Renderable.Enabled false

View File

@@ -2,7 +2,7 @@
1.0
#Asset
scene/solarsystem/missions/juno/juno required
scene/solarsystem/missions/juno/juno require
#Keybinding
1 Setting the simulation speed to 1 seconds per realtime second Set sim speed 1 /Simulation Speed false "openspace.time.interpolateDeltaTime(1)"

View File

@@ -5,7 +5,7 @@
Volume asset.require('scene/solarsystem/missions/messenger/mercurymagnetosphere') openspace.printWarning("Volume module is not loaded, skipping asset: mercurymagnetosphere")
#Asset
scene/solarsystem/missions/messenger/messengerSC required
scene/solarsystem/missions/messenger/messengerSC require
#Keybinding
1 Setting the simulation speed to 1 seconds per realtime second Set sim speed 1 /Simulation Speed false "openspace.time.interpolateDeltaTime(1)"

View File

@@ -2,8 +2,8 @@
1.0
#Asset
scene/solarsystem/missions/newhorizons/newhorizons required
scene/solarsystem/missions/newhorizons/model required
scene/solarsystem/missions/newhorizons/newhorizons require
scene/solarsystem/missions/newhorizons/model require
#Property
setPropertyValueSingle NavigationHandler.OrbitalNavigator.FollowAnchorNodeRotationDistance 20.000000

View File

@@ -2,8 +2,8 @@
1.0
#Asset
scene/solarsystem/missions/osirisrex/model required
scene/solarsystem/missions/osirisrex/osirisrex required
scene/solarsystem/missions/osirisrex/model require
scene/solarsystem/missions/osirisrex/osirisrex require
#Property
setPropertyValueSingle NavigationHandler.OrbitalNavigator.FollowAnchorNodeRotationDistance 20.000000

View File

@@ -5,8 +5,8 @@
Volume asset.require('scene/solarsystem/missions/messenger/mercurymagnetosphere') openspace.printWarning("Volume module is not loaded, skipping asset: mercurymagnetosphere")
#Asset
scene/solarsystem/missions/rosetta/67p required
scene/solarsystem/missions/rosetta/rosetta required
scene/solarsystem/missions/rosetta/67p require
scene/solarsystem/missions/rosetta/rosetta require
#Property
setPropertyValue Scene.67P.Renderable.PerformShading false

View File

@@ -5,8 +5,8 @@
Touch local webGui = asset.require('util/webgui'); webGui.setCefRoute("ontouch") openspace.printFatal('Could not load scene due to missing module "touch"')
#Asset
scene/solarsystem/planets/earth/earth required
util/webgui required
scene/solarsystem/planets/earth/earth require
util/webgui require
#Property
setPropertyValueSingle Scene.Pluto.Renderable.Enabled false

View File

@@ -2,14 +2,14 @@
1.0
#Asset
scene/solarsystem/planets/jupiter/minor_moons required
scene/solarsystem/planets/saturn/minor_moons required
scene/solarsystem/planets/uranus/minor_moons required
scene/solarsystem/planets/neptune/inner_moons required
scene/solarsystem/planets/neptune/irregular_prograde_moons required
scene/solarsystem/planets/neptune/irregular_retrograde_moons required
scene/solarsystem/missions/voyager/voyager1 required
scene/solarsystem/missions/voyager/voyager2 required
scene/solarsystem/planets/jupiter/minor_moons require
scene/solarsystem/planets/saturn/minor_moons require
scene/solarsystem/planets/uranus/minor_moons require
scene/solarsystem/planets/neptune/inner_moons require
scene/solarsystem/planets/neptune/irregular_prograde_moons require
scene/solarsystem/planets/neptune/irregular_retrograde_moons require
scene/solarsystem/missions/voyager/voyager1 require
scene/solarsystem/missions/voyager/voyager2 require
#Keybinding
1 Setting the simulation speed to 1 seconds per realtime second Set sim speed 1 /Simulation Speed false "openspace.time.interpolateDeltaTime(1)"

View File

@@ -43,10 +43,8 @@ namespace openspace {
namespace documentation { struct Documentation; }
namespace scripting { struct LuaLibrary; }
const size_t versionLinesExpected = 1;
const size_t timeLinesExpected = 1;
const size_t cameraLinesExpected = 1;
const size_t versionFieldsExpected = 1;
const size_t moduleFieldsExpected = 3;
const size_t assetFieldsExpected = 2;
const size_t propertyFieldsExpected = 3;
@@ -85,92 +83,96 @@ const size_t cameraGeoFieldLatitude = 2;
const size_t cameraGeoFieldLongitude = 3;
const size_t cameraGeoFieldAltitude = 4;
struct ProfileStruct {
// Version
struct Version {
int major = 0;
int minor = 0;
int patch = 0;
};
Version version;
struct Module {
std::string name;
std::string loadedInstruction;
std::string notLoadedInstruction;
};
std::vector<Module> modules;
struct Asset {
enum class Type {
Require,
Request
};
std::string path;
Type type;
};
std::vector<Asset> assets;
struct Property {
enum class SetType {
SetPropertyValue,
SetPropertyValueSingle
};
SetType setType;
std::string name;
std::string value;
};
std::vector<Property> properties;
struct Keybinding {
std::string key; // @TODO (abock, 2020-06-16) change to key+action
std::string documentation;
std::string name;
std::string guiPath;
bool isLocal;
std::string script;
};
std::vector<Keybinding> keybindings;
struct Time {
enum class Type {
Absolute,
Relative
};
Type type;
std::string time;
};
Time time;
struct CameraNavState {
static constexpr const char* Type = "setNavigationState";
std::string anchor;
std::string aim;
std::string referenceFrame;
std::string position;
std::string up;
std::string yaw;
std::string pitch;
};
struct CameraGoToGeo {
static constexpr const char* Type = "goToGeo";
std::string anchor;
double latitude;
double longitude;
std::optional<double> altitude;
};
std::variant<CameraNavState, CameraGoToGeo> camera;
std::vector<std::string> markNodes;
};
std::string serialize(const ProfileStruct& ps);
class ProfileFile {
public:
struct ProfileStruct {
// Version
struct Version {
int major = 0;
int minor = 0;
int patch = 0;
};
Version version;
struct Module {
std::string name;
std::string loadedInstruction;
std::string notLoadedInstruction;
};
std::vector<Module> modules;
struct Asset {
enum class Type {
Require,
Request
};
std::string path;
Type type;
};
std::vector<Asset> assets;
struct Property {
enum class SetType {
SetPropertyValue,
SetPropertyValueSingle
};
SetType setType;
std::string name;
std::string value;
};
std::vector<Property> properties;
struct Keybinding {
std::string key; // @TODO (abock, 2020-06-16) change to key+action
std::string documentation;
std::string name;
std::string guiPath;
bool isLocal;
std::string script;
};
std::vector<Keybinding> keybindings;
struct Time {
enum class Type {
Absolute,
Relative
};
Type type;
std::string time;
};
Time time;
struct CameraNavState {
std::string anchor;
std::string aim;
std::string referenceFrame;
std::string position;
std::string up;
std::string yaw;
std::string pitch;
};
struct CameraGoToGeo {
std::string anchor;
double latitude;
double longitude;
std::optional<double> altitude;
};
std::variant<CameraNavState, CameraGoToGeo> camera;
std::vector<std::string> markNodes;
};
ProfileStruct profile;
using Lines = std::vector<std::string>;
/**
@@ -181,21 +183,13 @@ public:
*/
ProfileFile(std::string filename);
/**
* Returns the string contents of this object converted to scene/asset
* equivalent syntax, with all section headers and contents of each listed on an
* individual line.
* \return The full contents of the profile file in string format.
*/
std::string writeToString();
/**
* Writes the formatted contents of this object to a file.
* This function calls writeToString() in order to get everything in formatted
* form.
* \param filename The filename to write to.
*/
void writeToFile(const std::string& filename);
void writeToFile(const std::string& filename) const;
/**
* Updates the full string that defines the starting time. The format for this line

View File

@@ -156,7 +156,7 @@ void Profile::saveCurrentSettingsToProfile(const std::string& filename) {
std::string Profile::saveCurrentSettingsToProfile_string() {
ProfileFile pf = collateBaseWithChanges();
return pf.writeToString();
return serialize(pf.profile);
}
bool Profile::usingProfile() const {
@@ -418,10 +418,10 @@ std::string Profile::convertToScene_assets(ProfileFile& pf) {
for (size_t i = 0; i < pf.assets().size(); ++i) {
std::vector<std::string> fields = ghoul::tokenizeString(pf.assets()[i], '\t');
if (fields[assetFieldReqd] == "required") {
if (fields[assetFieldReqd] == "require") {
assetR = "require";
}
else if (fields[assetFieldReqd] == "requested") {
else if (fields[assetFieldReqd] == "request") {
assetR = "request";
}
else if (fields[assetFieldReqd] == "") {
@@ -429,7 +429,7 @@ std::string Profile::convertToScene_assets(ProfileFile& pf) {
}
else {
std::string err = fmt::format(
"Asset {} of {} has bad arg 2/2 which must be 'required' or 'requested'",
"Asset {} of {} has bad arg 2/2 which must be 'require' or 'request'",
i + 1, pf.assets().size()
);
throw ghoul::RuntimeError(err);

View File

@@ -50,6 +50,10 @@ namespace {
constexpr const char* headerCamera = "#Camera";
constexpr const char* headerMarkNodes = "#MarkNodes";
// Helper structs for the visitor pattern of the std::variant
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
struct ProfileError : public ghoul::RuntimeError {
explicit ProfileError(unsigned int lineNum, std::string msg)
: ghoul::RuntimeError(
@@ -62,6 +66,95 @@ namespace {
namespace openspace {
std::string serialize(const ProfileStruct& ps) {
std::string output;
output += fmt::format("{}\n", headerVersion);
output += fmt::format("{}.{}.{}\n", ps.version.major, ps.version.minor, ps.version.patch);
output += fmt::format("\n{}\n", headerModule);
for (const ProfileStruct::Module& m : ps.modules) {
output += fmt::format("{}\t{}\t{}\n", m.name, m.loadedInstruction, m.notLoadedInstruction);
}
output += fmt::format("\n{}\n", headerAsset);
for (const ProfileStruct::Asset& a : ps.assets) {
const std::string type = [](ProfileStruct::Asset::Type t) {
switch (t) {
case ProfileStruct::Asset::Type::Require: return "require";
case ProfileStruct::Asset::Type::Request: return "request";
default: throw ghoul::MissingCaseException();
}
}(a.type);
output += fmt::format("{}\t{}\n", a.path, type);
}
output += fmt::format("\n{}\n", headerProperty);
for (const ProfileStruct::Property& p : ps.properties) {
const std::string type = [](ProfileStruct::Property::SetType t) {
switch (t) {
case ProfileStruct::Property::SetType::SetPropertyValue:
return "setPropertyValue";
case ProfileStruct::Property::SetType::SetPropertyValueSingle:
return "setPropertyValueSingle";
}
}(p.setType);
output += fmt::format("{}\t{}\t{}\n", type, p.name, p.value);
}
output += fmt::format("\n{}\n", headerKeybinding);
for (const ProfileStruct::Keybinding& k : ps.keybindings) {
const std::string local = k.isLocal ? "true" : "false";
output += fmt::format(
"{}\t{}\t{}\t{}\t{}\t{}\n",
k.key, k.documentation, k.name, k.guiPath, local, k.script
);
}
output += fmt::format("\n{}\n", headerTime);
{
const std::string type = [](ProfileStruct::Time::Type t) {
switch (t) {
case ProfileStruct::Time::Type::Absolute: return "absolute";
case ProfileStruct::Time::Type::Relative: return "relative";
default: throw ghoul::MissingCaseException();
}
}(ps.time.type);
output += fmt::format("{}\t{}\n", type, ps.time.time);
}
output += fmt::format("\n{}\n", headerCamera);
output += std::visit(overloaded{
[](const ProfileStruct::CameraNavState& camera) {
return fmt::format(
"{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}\n",
ProfileStruct::CameraNavState::Type,
camera.anchor, camera.aim, camera.referenceFrame, camera.position,
camera.up, camera.yaw, camera.pitch
);
},
[](const ProfileStruct::CameraGoToGeo& camera) {
std::string altitude;
if (camera.altitude.has_value()) {
altitude = std::to_string(*camera.altitude);
}
return fmt::format(
"{}\t{}\t{}\t{}\t{}\n",
ProfileStruct::CameraGoToGeo::Type,
camera.anchor, camera.latitude, camera.longitude, altitude
);
}
}, ps.camera);
output += fmt::format("\n{}\n", headerMarkNodes);
for (const std::string& n : ps.markNodes) {
output += fmt::format("{}\n", n);
}
return output;
}
ProfileFile::ProfileFile(std::string filename) {
clearAllFields();
_lineNum = 1;
@@ -70,7 +163,7 @@ ProfileFile::ProfileFile(std::string filename) {
try {
inFile.open(filename, std::ifstream::in);
}
catch (std::ifstream::failure& e) {
catch (const std::ifstream::failure& e) {
throw ghoul::RuntimeError(fmt::format(
"Exception opening profile file for read: {} ({})", filename, e.what()),
"profileFile"
@@ -85,7 +178,7 @@ ProfileFile::ProfileFile(std::string filename) {
_lineNum++;
}
}
catch (std::ifstream::failure& e) {
catch (const std::ifstream::failure& e) {
throw ProfileError(
_lineNum,
fmt::format("Read error using getline in: {} ({})", filename, e.what()
@@ -110,16 +203,16 @@ void ProfileFile::processIndividualLine(bool& insideSection, std::string line) {
}
}
void ProfileFile::writeToFile(const std::string& filename) {
if (filename.find("/") != std::string::npos) {
void ProfileFile::writeToFile(const std::string& filename) const {
if (filename.find('/') != std::string::npos) {
LERROR("Profile filename must not contain path (/) elements");
return;
}
else if (filename.find(":") != std::string::npos) {
else if (filename.find(':') != std::string::npos) {
LERROR("Profile filename must not contain path (:) elements");
return;
}
else if (filename.find(".") != std::string::npos) {
else if (filename.find('.') != std::string::npos) {
LERROR("Only provide the filename to save without file extension");
return;
}
@@ -138,16 +231,16 @@ void ProfileFile::writeToFile(const std::string& filename) {
try {
outFile.open(absFilename, std::ofstream::out);
}
catch (std::ofstream::failure& e) {
catch (const std::ofstream::failure& e) {
LERROR(fmt::format(
"Exception opening profile file for write: {} ({})", absFilename, e.what()
));
}
try {
outFile << writeToString();
outFile << serialize(profile);
}
catch (std::ofstream::failure& e) {
catch (const std::ofstream::failure& e) {
LERROR("Data write error to file: "
+ absFilename + " (" + e.what() + ")");
}
@@ -155,31 +248,6 @@ void ProfileFile::writeToFile(const std::string& filename) {
outFile.close();
}
std::string ProfileFile::writeToString() {
std::string output;
output = headerVersion + '\n';
output += _version + '\n' + '\n';
output += headerModule + '\n';
output += ghoul::join(_modules, "\n");
output += '\n';
output += headerAsset + '\n';
output += ghoul::join(_assets, "\n");
output += '\n';
output += headerProperty + '\n';
output += ghoul::join(_properties, "\n");
output += '\n';
output += headerKeybinding + '\n';
output += ghoul::join(_keybindings, "\n");
output += '\n';
output += headerTime + '\n';
output += _time + '\n' + '\n';
output += headerCamera + '\n';
output += _camera + '\n' + '\n';
output += headerMarkNodes + '\n';
output += ghoul::join(_markNodes, "\n");
return output;
}
const std::string& ProfileFile::version() const {
return _version;
@@ -268,11 +336,13 @@ ProfileFile::Lines ProfileFile::markNodes() const {
}
void ProfileFile::parseVersion(std::string line) {
if (++_numLinesVersion > versionLinesExpected) {
constexpr const size_t VersionLinesExpected = 1;
if (++_numLinesVersion > VersionLinesExpected) {
throw ProfileError(_lineNum, "Too many lines in Version section");
}
std::vector<std::string> fields = ghoul::tokenizeString(line, '\t');
if (fields.size() > versionFieldsExpected) {
if (fields.size() > 1) {
throw ProfileError(_lineNum, "No tabs allowed in Version entry");
}
_version = line;
@@ -363,7 +433,7 @@ void ProfileFile::parseAsset(std::string line) {
ProfileStruct::Asset a;
a.path = fields[0];
a.type = [&](const std::string& type) -> ProfileStruct::Asset::Type {
if (type == "required") {
if (type == "require") {
return ProfileStruct::Asset::Type::Require;
}
if (type == "request") {
@@ -371,7 +441,7 @@ void ProfileFile::parseAsset(std::string line) {
}
throw ProfileError(
_lineNum,
fmt::format("Expected asset type 'required' or 'request', got {}", type)
fmt::format("Expected asset type 'require' or 'request', got {}", type)
);
}(fields[1]);
profile.assets.push_back(std::move(a));
@@ -573,7 +643,7 @@ void ProfileFile::parseCamera(std::string line) {
if (fields.empty()) {
throw ProfileError(_lineNum, "No values specified for Camera location");
}
if (fields[0] == "setNavigationState") {
if (fields[0] == ProfileStruct::CameraNavState::Type) {
if (fields.size() != 8) {
throw ProfileError(
_lineNum,
@@ -594,7 +664,7 @@ void ProfileFile::parseCamera(std::string line) {
profile.camera = std::move(camera);
return;
}
if (fields[0] == "goToGeo") {
if (fields[0] == ProfileStruct::CameraGoToGeo::Type) {
if (fields.size() != 5) {
throw ProfileError(
_lineNum,

View File

@@ -206,6 +206,6 @@ TEST_CASE("profileFile: Write test", "[profileFile]") {
ProfileFile pf(testFile);
std::string result = pf.writeToString();
std::string result = serialize(pf.profile);
REQUIRE(testFull_string == result);
}