mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-06 03:29:44 -06:00
Merge branch 'master' into thesis/2022/software-integration
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -78,7 +78,7 @@ public:
|
||||
void setAtmosphereDimmingFactor(float atmosphereDimmingFactor);
|
||||
|
||||
// Relative mutators
|
||||
void rotate(glm::dquat rotation);
|
||||
void rotate(const glm::dquat& rotation);
|
||||
|
||||
// Accessors
|
||||
// Remove Vec3 from the name when psc is gone
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -22,21 +22,21 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_CORE___SCENELICENSEWRITER___H__
|
||||
#define __OPENSPACE_CORE___SCENELICENSEWRITER___H__
|
||||
#ifndef __OPENSPACE_CORE___CSVLOADER___H__
|
||||
#define __OPENSPACE_CORE___CSVLOADER___H__
|
||||
|
||||
#include <openspace/json.h>
|
||||
#include <vector>
|
||||
#include <openspace/data/dataloader.h>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
namespace openspace {
|
||||
namespace openspace::dataloader::csv {
|
||||
|
||||
class SceneLicenseWriter {
|
||||
public:
|
||||
SceneLicenseWriter();
|
||||
nlohmann::json generateJsonList() const;
|
||||
nlohmann::json generateJsonGroupedByLicense() const;
|
||||
};
|
||||
Dataset loadCsvFile(std::filesystem::path path,
|
||||
std::optional<DataMapping> specs = std::nullopt);
|
||||
|
||||
} // namespace openspace
|
||||
std::vector<Dataset::Texture> loadTextureMapFile(std::filesystem::path path,
|
||||
const std::set<int>& texturesInData);
|
||||
|
||||
#endif // __OPENSPACE_CORE___SCENELICENSEWRITER___H__
|
||||
} // namespace openspace::dataloader
|
||||
|
||||
#endif // __OPENSPACE_CORE___CSVLOADER___H__
|
||||
141
include/openspace/data/dataloader.h
Normal file
141
include/openspace/data/dataloader.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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___DATALOADER___H__
|
||||
#define __OPENSPACE_CORE___DATALOADER___H__
|
||||
|
||||
#include <openspace/data/datamapping.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/misc/boolean.h>
|
||||
#include <ghoul/misc/csvreader.h>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace openspace::dataloader {
|
||||
|
||||
/**
|
||||
* A dataset representing objects with positions and various other data columns.
|
||||
* Based on the SPECK format originally used for the digital universe datasets.
|
||||
* Mostly used for point-data.
|
||||
*
|
||||
* The read data files may also have associated texture values to be used for the
|
||||
* points.
|
||||
*/
|
||||
struct Dataset {
|
||||
struct Variable {
|
||||
int index = -1;
|
||||
std::string name;
|
||||
};
|
||||
std::vector<Variable> variables;
|
||||
|
||||
struct Texture {
|
||||
int index = -1;
|
||||
std::string file;
|
||||
};
|
||||
std::vector<Texture> textures;
|
||||
|
||||
int textureDataIndex = -1;
|
||||
int orientationDataIndex = -1;
|
||||
|
||||
struct Entry {
|
||||
glm::vec3 position = glm::vec3(0.f);
|
||||
std::vector<float> data;
|
||||
std::optional<std::string> comment;
|
||||
};
|
||||
std::vector<Entry> entries;
|
||||
|
||||
/// This variable can be used to get an understanding of the world scale size of
|
||||
/// the dataset
|
||||
float maxPositionComponent = 0.f;
|
||||
|
||||
bool isEmpty() const;
|
||||
|
||||
int index(std::string_view variableName) const;
|
||||
bool normalizeVariable(std::string_view variableName);
|
||||
glm::vec2 findValueRange(int variableIndex) const;
|
||||
glm::vec2 findValueRange(std::string_view variableName) const;
|
||||
};
|
||||
|
||||
struct Labelset {
|
||||
int textColorIndex = -1;
|
||||
|
||||
struct Entry {
|
||||
glm::vec3 position = glm::vec3(0.f);
|
||||
std::string identifier;
|
||||
std::string text;
|
||||
bool isEnabled = true;
|
||||
};
|
||||
std::vector<Entry> entries;
|
||||
};
|
||||
|
||||
struct ColorMap {
|
||||
std::optional<glm::vec4> belowRangeColor;
|
||||
std::optional<glm::vec4> aboveRangeColor;
|
||||
std::optional<glm::vec4> nanColor;
|
||||
std::vector<glm::vec4> entries;
|
||||
};
|
||||
|
||||
namespace data {
|
||||
|
||||
Dataset loadFile(std::filesystem::path path,
|
||||
std::optional<DataMapping> specs = std::nullopt);
|
||||
|
||||
std::optional<Dataset> loadCachedFile(const std::filesystem::path& path);
|
||||
void saveCachedFile(const Dataset& dataset, const std::filesystem::path& path);
|
||||
|
||||
Dataset loadFileWithCache(std::filesystem::path path,
|
||||
std::optional<DataMapping> specs = std::nullopt);
|
||||
|
||||
} // namespace data
|
||||
|
||||
namespace label {
|
||||
|
||||
Labelset loadFile(std::filesystem::path path,
|
||||
std::optional<DataMapping> specs = std::nullopt);
|
||||
|
||||
std::optional<Labelset> loadCachedFile(const std::filesystem::path& path);
|
||||
void saveCachedFile(const Labelset& labelset, const std::filesystem::path& path);
|
||||
|
||||
Labelset loadFileWithCache(std::filesystem::path path);
|
||||
|
||||
Labelset loadFromDataset(const dataloader::Dataset& dataset);
|
||||
} // namespace label
|
||||
|
||||
namespace color {
|
||||
|
||||
ColorMap loadFile(std::filesystem::path path,
|
||||
std::optional<DataMapping> specs = std::nullopt);
|
||||
|
||||
std::optional<ColorMap> loadCachedFile(const std::filesystem::path& path);
|
||||
void saveCachedFile(const ColorMap& colorMap, const std::filesystem::path& path);
|
||||
|
||||
ColorMap loadFileWithCache(std::filesystem::path path);
|
||||
|
||||
} // namespace color
|
||||
|
||||
} // namespace openspace::dataloader
|
||||
|
||||
#endif // __OPENSPACE_CORE___DATALOADER___H__
|
||||
84
include/openspace/data/datamapping.h
Normal file
84
include/openspace/data/datamapping.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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___DATAMAPPING___H__
|
||||
#define __OPENSPACE_CORE___DATAMAPPING___H__
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace openspace::documentation { struct Documentation; }
|
||||
namespace ghoul { class Dictionary; }
|
||||
|
||||
namespace openspace::dataloader {
|
||||
|
||||
struct DataMapping {
|
||||
static DataMapping createFromDictionary(const ghoul::Dictionary& dictionary);
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
bool hasExcludeColumns() const;
|
||||
bool isExcludeColumn(std::string_view column) const;
|
||||
|
||||
bool checkIfAllProvidedColumnsExist(const std::vector<std::string>& columns) const;
|
||||
|
||||
std::optional<std::string> xColumnName;
|
||||
std::optional<std::string> yColumnName;
|
||||
std::optional<std::string> zColumnName;
|
||||
std::optional<std::string> nameColumn;
|
||||
std::optional<std::string> textureColumn;
|
||||
|
||||
std::optional<std::filesystem::path> textureMap;
|
||||
|
||||
std::optional<float> missingDataValue;
|
||||
|
||||
bool isCaseSensitive = false;
|
||||
|
||||
std::vector<std::string> excludeColumns;
|
||||
|
||||
// OBS! When new parameters are added they should be included in the generateHash
|
||||
// function
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate a string based on the data mapping, that can be used to uniquely
|
||||
* identify the dataset.
|
||||
*/
|
||||
std::string generateHashString(const DataMapping& dm);
|
||||
|
||||
bool isPositionColumn(const std::string& c, const std::optional<DataMapping>& mapping);
|
||||
|
||||
bool isColumnX(const std::string& c, const std::optional<DataMapping>& mapping);
|
||||
|
||||
bool isColumnY(const std::string& c, const std::optional<DataMapping>& mapping);
|
||||
|
||||
bool isColumnZ(const std::string& c, const std::optional<DataMapping>& mapping);
|
||||
|
||||
bool isNameColumn(const std::string& c, const std::optional<DataMapping>& mapping);
|
||||
|
||||
bool isTextureColumn(const std::string& c, const std::optional<DataMapping>& mapping);
|
||||
|
||||
} // namespace openspace::dataloader
|
||||
|
||||
#endif // __OPENSPACE_CORE___DATAMAPPING___H__
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -22,34 +22,22 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_CORE___CONVERTRECFILEVERSIONTASK___H__
|
||||
#define __OPENSPACE_CORE___CONVERTRECFILEVERSIONTASK___H__
|
||||
#ifndef __OPENSPACE_CORE___SPECKLOADER___H__
|
||||
#define __OPENSPACE_CORE___SPECKLOADER___H__
|
||||
|
||||
#include <openspace/util/task.h>
|
||||
#include <openspace/interaction/sessionrecording.h>
|
||||
|
||||
#include <ghoul/glm.h>
|
||||
#include <openspace/data/dataloader.h>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
|
||||
namespace openspace::interaction {
|
||||
namespace openspace::dataloader::speck {
|
||||
|
||||
class ConvertRecFileVersionTask : public Task {
|
||||
public:
|
||||
ConvertRecFileVersionTask(const ghoul::Dictionary& dictionary);
|
||||
~ConvertRecFileVersionTask() override;
|
||||
std::string description() override;
|
||||
void perform(const Task::ProgressCallback& progressCallback) override;
|
||||
static documentation::Documentation documentation();
|
||||
void convert();
|
||||
SessionRecording* sessRec;
|
||||
Dataset loadSpeckFile(std::filesystem::path path,
|
||||
std::optional<DataMapping> specs = std::nullopt);
|
||||
|
||||
private:
|
||||
std::string _inFilename;
|
||||
std::filesystem::path _inFilePath;
|
||||
std::string _valueFunctionLua;
|
||||
};
|
||||
Labelset loadLabelFile(std::filesystem::path path);
|
||||
|
||||
} // namespace openspace::interaction
|
||||
ColorMap loadCmapFile(std::filesystem::path path);
|
||||
|
||||
#endif // __OPENSPACE_CORE___CONVERTRECFILEVERSIONTASK___H__
|
||||
} // namespace openspace::dataloader::speck
|
||||
|
||||
#endif // __OPENSPACE_CORE___SPECKLOADER___H__
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -36,7 +36,10 @@ namespace ghoul { class Dictionary; }
|
||||
|
||||
namespace openspace::documentation {
|
||||
|
||||
class Verifier;
|
||||
|
||||
BooleanType(Optional);
|
||||
BooleanType(Private);
|
||||
|
||||
/**
|
||||
* The TestResult structure returns the information from the #testSpecification method. It
|
||||
@@ -52,20 +55,24 @@ struct TestResult {
|
||||
* offense.
|
||||
*/
|
||||
struct Offense {
|
||||
/**
|
||||
* The Reason for the offense
|
||||
*/
|
||||
/// The Reason for the offense
|
||||
enum class Reason {
|
||||
MissingKey, ///< The offending key that was requested was not found
|
||||
WrongType, ///< The key's value was not of the expected type
|
||||
Verification, ///< The value did not pass a necessary non-type verifier
|
||||
UnknownIdentifier ///< The identifier for a ReferencingVerifier did not exist
|
||||
/// Unknown reason
|
||||
Unknown,
|
||||
/// The offending key that was requested was not found
|
||||
MissingKey,
|
||||
/// The key's value was not of the expected type
|
||||
WrongType,
|
||||
/// The value did not pass a necessary non-type verifier
|
||||
Verification,
|
||||
/// The identifier for a ReferencingVerifier did not exist
|
||||
UnknownIdentifier
|
||||
};
|
||||
/// The offending key that caused the Offense. In the case of a nested table,
|
||||
/// this value will be the fully qualified name of the key
|
||||
std::string offender;
|
||||
/// The Reason that caused this offense
|
||||
Reason reason;
|
||||
Reason reason = Reason::Unknown;
|
||||
/// An optional explanation for when a verification fails
|
||||
std::string explanation;
|
||||
};
|
||||
@@ -77,11 +84,10 @@ struct TestResult {
|
||||
* might be removed in a latter version.
|
||||
*/
|
||||
struct Warning {
|
||||
/**
|
||||
* The reason for the warning
|
||||
*/
|
||||
/// The reason for the warning
|
||||
enum class Reason {
|
||||
Deprecated ///< The value is marked as deprecated and should not used
|
||||
/// The value is marked as deprecated and should not used
|
||||
Deprecated
|
||||
};
|
||||
|
||||
/// The offending key that caused the Warning. In the case of a nested table,
|
||||
@@ -91,7 +97,6 @@ struct TestResult {
|
||||
Reason reason;
|
||||
};
|
||||
|
||||
|
||||
/// Is `true` if the TestResult is positive, `false` otherwise
|
||||
bool success = false;
|
||||
/// Contains a list of offenses that were found in the test. Is empty if
|
||||
@@ -123,8 +128,6 @@ struct SpecificationError : public ghoul::RuntimeError {
|
||||
|
||||
void logError(const SpecificationError& error, std::string component = "");
|
||||
|
||||
struct Verifier;
|
||||
|
||||
/**
|
||||
* A DocumentationEntry provides the specification for a single key, which is tested using
|
||||
* the provided Verifier. Each DocumentationEntry can contain a textual documentation that
|
||||
@@ -133,10 +136,10 @@ struct Verifier;
|
||||
* DocumentationEntry::Wildcard, any key in the containing Documentation will be tested
|
||||
* against the provided verifier. The most convenient way of creating DocumentationEntry%s
|
||||
* is by using an inline initializer list such as:
|
||||
*\verbatim
|
||||
DocumentationEntry e = { "key", new IntVerifier, "Documentation text", Optional::Yes };
|
||||
\endverbatim
|
||||
|
||||
* ```
|
||||
* DocumentationEntry e = { "key", new IntVerifier, "Documentation text", Optional::Yes };
|
||||
* ```
|
||||
*
|
||||
* Furthermore, these initializer lists can be crated all at once for a Documentation.
|
||||
* Even if the Verifier%s are specified using the `new` operators, they will not leak
|
||||
* memory as the DocumentationEntry takes ownership of them in the constructor.
|
||||
@@ -159,42 +162,50 @@ struct DocumentationEntry {
|
||||
* contains this DocumentationEntry will be matched
|
||||
* \param v The Verifier that is used to test the \p k%'s value to determine if it is
|
||||
* a valid value
|
||||
* \param doc The textual documentation that describes the DocumentationEntry in a
|
||||
* human readable format
|
||||
* \param opt Determines whether the Documentation containing this DocumentationEntry
|
||||
* must have a key \p key, or whether it is optional
|
||||
* \param priv Determines whether the DocumentationEntry is considered private. If it
|
||||
* is, then shall not be reported in a user-facing manner, but its values
|
||||
* should still be checked when verifying the correctness and completeness of
|
||||
* an entry
|
||||
* \param doc The textual documentation that describes the DocumentationEntry in a
|
||||
* human readable format
|
||||
*
|
||||
* \pre \p k must not be empty
|
||||
* \pre \p v must not be nullptr
|
||||
*/
|
||||
DocumentationEntry(std::string k, std::shared_ptr<Verifier> v,
|
||||
Optional opt, std::string doc = "");
|
||||
Optional opt = Optional::No, Private priv = Private::No, std::string doc = "");
|
||||
|
||||
/**
|
||||
* The constructor for a DocumentationEntry describing a key \p k in a Documentation.
|
||||
* The value for the key (or each value in the case of the
|
||||
* DocumentationEntry::Wildcard) is tested using the verifier \p v, that specifies the
|
||||
* conditions that the \p k%'s value has to fulfill. The textual documentation
|
||||
* \p doc shall describe the usage of the key-value pair and will be printed for human
|
||||
* consumption for example in the DocumentationEngine. Each DocumentationEntry can
|
||||
* further be \p opt.
|
||||
*
|
||||
* \param k The key for which this DocumentationEntry is valid. If this valid is
|
||||
* equal to DocumentationEntry::Wildcard, each entry in the Documentation that
|
||||
* contains this DocumentationEntry will be matched
|
||||
* \param v The Verifier that is used to test the \p key%'s value to determine if it is
|
||||
* a valid value. The DocumentationEntry will take ownership of the passed
|
||||
* object
|
||||
* \param doc The textual documentation that describes the DocumentationEntry in a
|
||||
* human readable format
|
||||
* \param opt Determines whether the Documentation containing this DocumentationEntry
|
||||
* must have a key \p key, or whether it is optional
|
||||
*
|
||||
* \pre \p k must not be empty
|
||||
* \pre \p v must not be nullptr
|
||||
*/
|
||||
DocumentationEntry(std::string k, Verifier* v, Optional opt,
|
||||
std::string doc = "");
|
||||
* The constructor for a DocumentationEntry describing a key \p k in a Documentation.
|
||||
* The value for the key (or each value in the case of the
|
||||
* DocumentationEntry::Wildcard) is tested using the verifier \p v, that specifies the
|
||||
* conditions that the \p k%'s value has to fulfill. The textual documentation
|
||||
* \p doc shall describe the usage of the key-value pair and will be printed for human
|
||||
* consumption for example in the DocumentationEngine. Each DocumentationEntry can
|
||||
* further be \p opt.
|
||||
*
|
||||
* \param k The key for which this DocumentationEntry is valid. If this valid is
|
||||
* equal to DocumentationEntry::Wildcard, each entry in the Documentation that
|
||||
* contains this DocumentationEntry will be matched
|
||||
* \param v The Verifier that is used to test the \p key%'s value to determine if it
|
||||
* is a valid value. The DocumentationEntry will take ownership of the passed
|
||||
* object
|
||||
* \param opt Determines whether the Documentation containing this DocumentationEntry
|
||||
* must have a key \p key, or whether it is optional
|
||||
* \param priv Determines whether the DocumentationEntry is considered private. If it
|
||||
* is, then shall not be reported in a user-facing manner, but its values
|
||||
* should still be checked when verifying the correctness and completeness of
|
||||
* an entry
|
||||
* \param doc The textual documentation that describes the DocumentationEntry in a
|
||||
* human readable format
|
||||
*
|
||||
* \pre \p k must not be empty
|
||||
* \pre \p v must not be nullptr
|
||||
*/
|
||||
DocumentationEntry(std::string k, Verifier* v, Optional opt = Optional::No,
|
||||
Private priv = Private::No, std::string doc = "");
|
||||
|
||||
/// The key that is described by this DocumentationEntry
|
||||
std::string key;
|
||||
@@ -202,11 +213,12 @@ struct DocumentationEntry {
|
||||
std::shared_ptr<Verifier> verifier;
|
||||
/// Determines whether the described DocumentationEntry is optional or not
|
||||
Optional optional;
|
||||
/// Determines if the entry should be visible to the user
|
||||
Private isPrivate;
|
||||
/// The textual description of this DocumentationEntry
|
||||
std::string documentation;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This struct contains the documentation and specification for a ghoul::Dictionary. It is
|
||||
* used to impose restrictions on keys and values and determine whether a given
|
||||
@@ -214,16 +226,16 @@ struct DocumentationEntry {
|
||||
* #testSpecificationAndThrow methods). Each Documentation consists of a human-readable
|
||||
* `name`, and a list of DocumentationEntry%s that each describe a single key value. The
|
||||
* most convenient way of creating a Documentation is by using nested initializer lists:
|
||||
*\verbatim
|
||||
Documentation doc = {
|
||||
"Documentation for an arbitrary dictionary",
|
||||
{ // A list of DocumentationEntry%s; also specified using initializer lists
|
||||
{ "key1", new IntVerifier, "Documentation key1", Optional::Yes },
|
||||
{ "key2", new FloatVerifier, "Documentation key2" },
|
||||
{ "key3", new StringVerifier }
|
||||
}
|
||||
};
|
||||
\endverbatim
|
||||
* ```
|
||||
* Documentation doc = {
|
||||
* "Documentation for an arbitrary dictionary",
|
||||
* { // A list of DocumentationEntry%s; also specified using initializer lists
|
||||
* { "key1", new IntVerifier, "Documentation key1", Optional::Yes },
|
||||
* { "key2", new FloatVerifier, "Documentation key2" },
|
||||
* { "key3", new StringVerifier }
|
||||
* }
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* If multiple DocumentationEntries cover the same key, they are all evaluated for that
|
||||
* specific key. The same holds true if there is a DocumentationEntry with a
|
||||
@@ -231,43 +243,14 @@ Documentation doc = {
|
||||
* both the wildcard and the specialized entry will be evaluated.
|
||||
*/
|
||||
struct Documentation {
|
||||
using DocumentationEntries = std::vector<documentation::DocumentationEntry>;
|
||||
|
||||
/**
|
||||
* Creates a Documentation with a human-readable name \p n and a list of entries
|
||||
* \p ents.
|
||||
*
|
||||
* \param n The human-readable name of this Documentation
|
||||
* \param i A unique identifier which can be used by applications (or other
|
||||
* Documentation%s to reference this entry
|
||||
* \param ents A list of DocumentationEntry%s that describe the individual keys for
|
||||
* this entrie Documentation
|
||||
*/
|
||||
Documentation(std::string n, std::string i, DocumentationEntries ents = {});
|
||||
|
||||
/**
|
||||
* Creates a Documentation with a human-readable name \p n.
|
||||
*
|
||||
* \param n The human-readable name of this Documentation
|
||||
* \param ents A list of DocumentationEntry%s that describe the individual keys for
|
||||
* this entrie Documentation
|
||||
*/
|
||||
Documentation(std::string n, DocumentationEntries ents = {});
|
||||
|
||||
/**
|
||||
* Creates a Documentation.
|
||||
*
|
||||
* \param entries A list of DocumentationEntry%s that describe the individual keys for
|
||||
* this entrie Documentation
|
||||
*/
|
||||
Documentation(DocumentationEntries ents = {});
|
||||
|
||||
/// The human-readable name of the Documentation
|
||||
std::string name;
|
||||
/// A unique identifier which can be used to reference this Documentation
|
||||
std::string id;
|
||||
/// A general description for the entire documented entity
|
||||
std::string description;
|
||||
/// A list of specifications that are describing this Documentation
|
||||
DocumentationEntries entries;
|
||||
std::vector<documentation::DocumentationEntry> entries;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -286,20 +269,21 @@ TestResult testSpecification(const Documentation& documentation,
|
||||
const ghoul::Dictionary& dictionary);
|
||||
|
||||
/**
|
||||
* This method tests whether a provided ghoul::Dictionary \p dictionary adheres to the
|
||||
* specification \p documentation. If the \p dictionary does not adhere to the
|
||||
* specification a SpecificationError is thrown, and the exception contains the TestResult
|
||||
* that contains more information about the offending keys. If the \p dictionary adheres to
|
||||
* the \p documentation, the method returns normally.
|
||||
*
|
||||
* \param documentation The Documentation that the \p dictionary is tested against
|
||||
* \param dictionary The ghoul::Dictionary that is to be tested against the
|
||||
* \p documentation
|
||||
* \param component The component that is using this method; this argument is passed to the
|
||||
* SpecificationError that is thrown in case of not adhering to the \p documentation
|
||||
*
|
||||
* \throw SpecificationError If the \p dictionary does not adhere to the \p documentation
|
||||
*/
|
||||
* This method tests whether a provided ghoul::Dictionary \p dictionary adheres to the
|
||||
* specification \p documentation. If the \p dictionary does not adhere to the
|
||||
* specification a SpecificationError is thrown, and the exception contains the TestResult
|
||||
* that contains more information about the offending keys. If the \p dictionary adheres
|
||||
* to the \p documentation, the method returns normally.
|
||||
*
|
||||
* \param documentation The Documentation that the \p dictionary is tested against
|
||||
* \param dictionary The ghoul::Dictionary that is to be tested against the
|
||||
* \p documentation
|
||||
* \param component The component that is using this method; this argument is passed to
|
||||
* the SpecificationError that is thrown in case of not adhering to the
|
||||
* \p documentation
|
||||
*
|
||||
* \throw SpecificationError If the \p dictionary does not adhere to the \p documentation
|
||||
*/
|
||||
void testSpecificationAndThrow(const Documentation& documentation,
|
||||
const ghoul::Dictionary& dictionary, std::string component);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/json.h>
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
#include <ghoul/misc/exception.h>
|
||||
|
||||
namespace openspace::documentation {
|
||||
@@ -47,8 +48,7 @@ public:
|
||||
* Constructor of a DuplicateDocumentationException storing the offending
|
||||
* Documentation for later use.
|
||||
*
|
||||
* \param doc The Documentation whose identifier was previously
|
||||
* registered
|
||||
* \param doc The Documentation whose identifier was previously registered
|
||||
*/
|
||||
DuplicateDocumentationException(Documentation doc);
|
||||
|
||||
@@ -87,12 +87,19 @@ public:
|
||||
*/
|
||||
static DocumentationEngine& ref();
|
||||
|
||||
std::string generateJson() const;
|
||||
void writeJavascriptDocumentation() const;
|
||||
void writeJsonDocumentation() const;
|
||||
|
||||
nlohmann::json generateJsonJson() const;
|
||||
nlohmann::json generateScriptEngineJson() const;
|
||||
nlohmann::json generateFactoryManagerJson() const;
|
||||
nlohmann::json generateKeybindingsJson() const;
|
||||
nlohmann::json generatePropertyOwnerJson(properties::PropertyOwner* owner) const;
|
||||
nlohmann::json generateLicenseGroupsJson() const;
|
||||
nlohmann::json generateLicenseListJson() const;
|
||||
nlohmann::json generateActionJson() const;
|
||||
nlohmann::json generateEventJson() const;
|
||||
|
||||
private:
|
||||
|
||||
/// The list of all Documentation%s that are stored by the DocumentationEngine
|
||||
std::vector<Documentation> _documentations;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -24,390 +24,12 @@
|
||||
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/format.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
|
||||
template <>
|
||||
struct std::less<glm::vec2> {
|
||||
bool operator()(const glm::vec2& a, const glm::vec2& b) const {
|
||||
return a.x < b.x && a.x < b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less<glm::vec3> {
|
||||
bool operator()(const glm::vec3& a, const glm::vec3& b) const {
|
||||
return a.x < b.x && a.x < b.y && a.z < b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less<glm::vec4> {
|
||||
bool operator()(const glm::vec4& a, const glm::vec4& b) const {
|
||||
return a.x < b.x && a.x < b.y && a.z < b.z && a.w < b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less<glm::ivec2> {
|
||||
bool operator()(const glm::ivec2& a, const glm::ivec2& b) const {
|
||||
return a.x < b.x && a.x < b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less<glm::ivec3> {
|
||||
bool operator()(const glm::ivec3& a, const glm::ivec3& b) const {
|
||||
return a.x < b.x && a.x < b.y && a.z < b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less<glm::ivec4> {
|
||||
bool operator()(const glm::ivec4& a, const glm::ivec4& b) const {
|
||||
return a.x < b.x && a.x < b.y && a.z < b.z && a.w < b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less<glm::dvec2> {
|
||||
bool operator()(const glm::dvec2& a, const glm::dvec2& b) const {
|
||||
return a.x < b.x && a.x < b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less<glm::dvec3> {
|
||||
bool operator()(const glm::dvec3& a, const glm::dvec3& b) const {
|
||||
return a.x < b.x && a.x < b.y && a.z < b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less<glm::dvec4> {
|
||||
bool operator()(const glm::dvec4& a, const glm::dvec4& b) const {
|
||||
return a.x < b.x && a.x < b.y && a.z < b.z && a.w < b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::vec2> {
|
||||
bool operator()(const glm::vec2& a, const glm::vec2& b) const {
|
||||
return a.x <= b.x && a.x <= b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::vec3> {
|
||||
bool operator()(const glm::vec3& a, const glm::vec3& b) const {
|
||||
return a.x <= b.x && a.x <= b.y && a.z <= b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::vec4> {
|
||||
bool operator()(const glm::vec4& a, const glm::vec4& b) const {
|
||||
return a.x <= b.x && a.x <= b.y && a.z <= b.z && a.w <= b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::ivec2> {
|
||||
bool operator()(const glm::ivec2& a, const glm::ivec2& b) const {
|
||||
return a.x <= b.x && a.x <= b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::ivec3> {
|
||||
bool operator()(const glm::ivec3& a, const glm::ivec3& b) const {
|
||||
return a.x <= b.x && a.x <= b.y && a.z <= b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::ivec4> {
|
||||
bool operator()(const glm::ivec4& a, const glm::ivec4& b) const {
|
||||
return a.x <= b.x && a.x <= b.y && a.z <= b.z && a.w <= b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::dvec2> {
|
||||
bool operator()(const glm::dvec2& a, const glm::dvec2& b) const {
|
||||
return a.x <= b.x && a.x <= b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::dvec3> {
|
||||
bool operator()(const glm::dvec3& a, const glm::dvec3& b) const {
|
||||
return a.x <= b.x && a.x <= b.y && a.z <= b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::less_equal<glm::dvec4> {
|
||||
bool operator()(const glm::dvec4& a, const glm::dvec4& b) const {
|
||||
return a.x <= b.x && a.x <= b.y && a.z <= b.z && a.w <= b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::vec2> {
|
||||
bool operator()(const glm::vec2& a, const glm::vec2& b) const {
|
||||
return a.x > b.x && a.x > b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::vec3> {
|
||||
bool operator()(const glm::vec3& a, const glm::vec3& b) const {
|
||||
return a.x > b.x && a.x > b.y && a.z > b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::vec4> {
|
||||
bool operator()(const glm::vec4& a, const glm::vec4& b) const {
|
||||
return a.x > b.x && a.x > b.y && a.z > b.z && a.w > b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::ivec2> {
|
||||
bool operator()(const glm::ivec2& a, const glm::ivec2& b) const {
|
||||
return a.x > b.x && a.x > b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::ivec3> {
|
||||
bool operator()(const glm::ivec3& a, const glm::ivec3& b) const {
|
||||
return a.x > b.x && a.x > b.y && a.z > b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::ivec4> {
|
||||
bool operator()(const glm::ivec4& a, const glm::ivec4& b) const {
|
||||
return a.x > b.x && a.x > b.y && a.z > b.z && a.w > b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::dvec2> {
|
||||
bool operator()(const glm::dvec2& a, const glm::dvec2& b) const {
|
||||
return a.x > b.x && a.x > b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::dvec3> {
|
||||
bool operator()(const glm::dvec3& a, const glm::dvec3& b) const {
|
||||
return a.x > b.x && a.x > b.y && a.z > b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater<glm::dvec4> {
|
||||
bool operator()(const glm::dvec4& a, const glm::dvec4& b) const {
|
||||
return a.x > b.x && a.x > b.y && a.z > b.z && a.w > b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::vec2> {
|
||||
bool operator()(const glm::vec2& a, const glm::vec2& b) const {
|
||||
return a.x >= b.x && a.x >= b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::vec3> {
|
||||
bool operator()(const glm::vec3& a, const glm::vec3& b) const {
|
||||
return a.x >= b.x && a.x >= b.y && a.z >= b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::vec4> {
|
||||
bool operator()(const glm::vec4& a, const glm::vec4& b) const {
|
||||
return a.x >= b.x && a.x >= b.y && a.z >= b.z && a.w >= b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::ivec2> {
|
||||
bool operator()(const glm::ivec2& a, const glm::ivec2& b) const {
|
||||
return a.x >= b.x && a.x >= b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::ivec3> {
|
||||
bool operator()(const glm::ivec3& a, const glm::ivec3& b) const {
|
||||
return a.x >= b.x && a.x >= b.y && a.z >= b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::ivec4> {
|
||||
bool operator()(const glm::ivec4& a, const glm::ivec4& b) const {
|
||||
return a.x >= b.x && a.x >= b.y && a.z >= b.z && a.w >= b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::dvec2> {
|
||||
bool operator()(const glm::dvec2& a, const glm::dvec2& b) const {
|
||||
return a.x >= b.x && a.x >= b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::dvec3> {
|
||||
bool operator()(const glm::dvec3& a, const glm::dvec3& b) const {
|
||||
return a.x >= b.x && a.x >= b.y && a.z >= b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::greater_equal<glm::dvec4> {
|
||||
bool operator()(const glm::dvec4& a, const glm::dvec4& b) const {
|
||||
return a.x >= b.x && a.x >= b.y && a.z >= b.z && a.w >= b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::vec2> {
|
||||
bool operator()(const glm::vec2& a, const glm::vec2& b) const {
|
||||
return a.x == b.x && a.x == b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::vec3> {
|
||||
bool operator()(const glm::vec3& a, const glm::vec3& b) const {
|
||||
return a.x == b.x && a.x == b.y && a.z == b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::vec4> {
|
||||
bool operator()(const glm::vec4& a, const glm::vec4& b) const {
|
||||
return a.x == b.x && a.x == b.y && a.z == b.z && a.w == b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::ivec2> {
|
||||
bool operator()(const glm::ivec2& a, const glm::ivec2& b) const {
|
||||
return a.x == b.x && a.x == b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::ivec3> {
|
||||
bool operator()(const glm::ivec3& a, const glm::ivec3& b) const {
|
||||
return a.x == b.x && a.x == b.y && a.z == b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::ivec4> {
|
||||
bool operator()(const glm::ivec4& a, const glm::ivec4& b) const {
|
||||
return a.x == b.x && a.x == b.y && a.z == b.z && a.w == b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::dvec2> {
|
||||
bool operator()(const glm::dvec2& a, const glm::dvec2& b) const {
|
||||
return a.x == b.x && a.x == b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::dvec3> {
|
||||
bool operator()(const glm::dvec3& a, const glm::dvec3& b) const {
|
||||
return a.x == b.x && a.x == b.y && a.z == b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::equal_to<glm::dvec4> {
|
||||
bool operator()(const glm::dvec4& a, const glm::dvec4& b) const {
|
||||
return a.x == b.x && a.x == b.y && a.z == b.z && a.w == b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::vec2> {
|
||||
bool operator()(const glm::vec2& a, const glm::vec2& b) const {
|
||||
return a.x != b.x && a.x != b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::vec3> {
|
||||
bool operator()(const glm::vec3& a, const glm::vec3& b) const {
|
||||
return a.x != b.x && a.x != b.y && a.z != b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::vec4> {
|
||||
bool operator()(const glm::vec4& a, const glm::vec4& b) const {
|
||||
return a.x != b.x && a.x != b.y && a.z != b.z && a.w != b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::ivec2> {
|
||||
bool operator()(const glm::ivec2& a, const glm::ivec2& b) const {
|
||||
return a.x != b.x && a.x != b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::ivec3> {
|
||||
bool operator()(const glm::ivec3& a, const glm::ivec3& b) const {
|
||||
return a.x != b.x && a.x != b.y && a.z != b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::ivec4> {
|
||||
bool operator()(const glm::ivec4& a, const glm::ivec4& b) const {
|
||||
return a.x != b.x && a.x != b.y && a.z != b.z && a.w != b.w;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::dvec2> {
|
||||
bool operator()(const glm::dvec2& a, const glm::dvec2& b) const {
|
||||
return a.x != b.x && a.x != b.y;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::dvec3> {
|
||||
bool operator()(const glm::dvec3& a, const glm::dvec3& b) const {
|
||||
return a.x != b.x && a.x != b.y && a.z != b.z;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::not_equal_to<glm::dvec4> {
|
||||
bool operator()(const glm::dvec4& a, const glm::dvec4& b) const {
|
||||
return a.x != b.x && a.x != b.y && a.z != b.z && a.w != b.w;
|
||||
}
|
||||
};
|
||||
|
||||
namespace openspace::documentation {
|
||||
|
||||
template <>
|
||||
@@ -756,13 +378,13 @@ TestResult InListVerifier<T>::operator()(const ghoul::Dictionary& dict,
|
||||
std::string list = std::accumulate(
|
||||
values.begin() + 1,
|
||||
values.end(),
|
||||
fmt::format("{}", values.front()),
|
||||
std::format("{}", values.front()),
|
||||
[](std::string lhs, typename T::Type rhs) {
|
||||
return fmt::format("{}, {}", lhs, rhs);
|
||||
return std::format("{}, {}", lhs, rhs);
|
||||
}
|
||||
);
|
||||
o.explanation = fmt::format(
|
||||
"{} not in list of accepted values '{}'",
|
||||
o.explanation = std::format(
|
||||
"'{}' not in list of accepted values '{}'",
|
||||
key, list
|
||||
);
|
||||
r.offenses.push_back(o);
|
||||
@@ -782,12 +404,12 @@ std::string InListVerifier<T>::documentation() const {
|
||||
std::copy(
|
||||
values.begin(),
|
||||
values.end(),
|
||||
std::ostream_iterator<typename T::Type>(s, ",")
|
||||
std::ostream_iterator<typename T::Type>(s, ", ")
|
||||
);
|
||||
|
||||
std::string joined = s.str();
|
||||
// We need to remove a trailing ',' at the end of the string
|
||||
result += joined.substr(0, joined.size() - 1);
|
||||
// We need to remove a trailing ',' and whitespace at the end of the string
|
||||
result += joined.substr(0, joined.size() - 2);
|
||||
|
||||
result += " }";
|
||||
return result;
|
||||
@@ -800,7 +422,7 @@ NotInListVerifier<T>::NotInListVerifier(std::vector<typename T::Type> vals)
|
||||
|
||||
template <typename T>
|
||||
TestResult NotInListVerifier<T>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
const std::string& key) const
|
||||
{
|
||||
TestResult res = T::operator()(dict, key);
|
||||
if (res.success) {
|
||||
@@ -1064,30 +686,11 @@ std::string NotInRangeVerifier<T>::documentation() const {
|
||||
template <typename T>
|
||||
AnnotationVerifier<T>::AnnotationVerifier(std::string a)
|
||||
: annotation(std::move(a))
|
||||
{
|
||||
|
||||
}
|
||||
{}
|
||||
|
||||
template <typename T>
|
||||
std::string AnnotationVerifier<T>::documentation() const {
|
||||
return annotation;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
TestResult DeprecatedVerifier<T>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
{
|
||||
TestResult res = T::operator()(dict, key);
|
||||
TestResult::Warning w;
|
||||
w.offender = key;
|
||||
w.reason = TestResult::Warning::Reason::Deprecated;
|
||||
res.warnings.push_back(w);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string DeprecatedVerifier<T>::documentation() const {
|
||||
return T::documentation() + " (deprecated)";
|
||||
}
|
||||
|
||||
} // namespace openspace::documentation
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -34,9 +34,9 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace openspace::documentation { struct Documentation; }
|
||||
namespace openspace {
|
||||
|
||||
namespace openspace::configuration {
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
struct Configuration {
|
||||
Configuration() = default;
|
||||
@@ -45,7 +45,9 @@ struct Configuration {
|
||||
Configuration& operator=(const Configuration&) = delete;
|
||||
Configuration& operator=(Configuration&&) = default;
|
||||
|
||||
std::string windowConfiguration = "${CONFIG}/single.xml";
|
||||
ghoul::Dictionary createDictionary();
|
||||
|
||||
std::string windowConfiguration = "${CONFIG}/single.json";
|
||||
std::string asset;
|
||||
std::string profile;
|
||||
|
||||
@@ -76,6 +78,8 @@ struct Configuration {
|
||||
Logging logging;
|
||||
|
||||
std::string scriptLog;
|
||||
bool verboseScriptLog = false;
|
||||
int scriptLogRotation = 3;
|
||||
|
||||
struct DocumentationInfo {
|
||||
std::string path;
|
||||
@@ -88,7 +92,7 @@ struct Configuration {
|
||||
struct LoadingScreen {
|
||||
bool isShowingMessages = true;
|
||||
bool isShowingNodeNames = true;
|
||||
bool isShowingProgressbar = true;
|
||||
bool isShowingLogMessages = true;
|
||||
};
|
||||
LoadingScreen loadingScreen;
|
||||
|
||||
@@ -102,6 +106,8 @@ struct Configuration {
|
||||
|
||||
bool shouldUseScreenshotDate = false;
|
||||
|
||||
bool sandboxedLua = true;
|
||||
|
||||
std::string onScreenTextScaling = "window";
|
||||
bool usePerProfileCache = false;
|
||||
|
||||
@@ -112,6 +118,15 @@ struct Configuration {
|
||||
bool isConsoleDisabled = false;
|
||||
bool bypassLauncher = false;
|
||||
|
||||
enum LayerServer {
|
||||
All = 0,
|
||||
NewYork,
|
||||
Sweden,
|
||||
Utah,
|
||||
None
|
||||
};
|
||||
LayerServer layerServer = LayerServer::All;
|
||||
|
||||
std::map<std::string, ghoul::Dictionary> moduleConfigurations;
|
||||
|
||||
struct OpenGLDebugContext {
|
||||
@@ -141,15 +156,19 @@ struct Configuration {
|
||||
// Values not read from the openspace.cfg file
|
||||
std::string sgctConfigNameInitialized;
|
||||
|
||||
static documentation::Documentation Documentation;
|
||||
static documentation::Documentation Documentation();
|
||||
ghoul::lua::LuaState state;
|
||||
};
|
||||
|
||||
std::filesystem::path findConfiguration(const std::string& filename = "openspace.cfg");
|
||||
|
||||
Configuration loadConfigurationFromFile(const std::filesystem::path& filename,
|
||||
const glm::ivec2& primaryMonitorResolution, std::string_view overrideScript);
|
||||
Configuration loadConfigurationFromFile(const std::filesystem::path& configurationFile,
|
||||
const std::filesystem::path& settingsFile,
|
||||
const glm::ivec2& primaryMonitorResolution);
|
||||
|
||||
} // namespace openspace::configuration
|
||||
Configuration::LayerServer stringToLayerServer(std::string_view server);
|
||||
std::string layerServerToString(Configuration::LayerServer server);
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_CORE___CONFIGURATION___H__
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
// Since the FileFuture object will be used from multiple threads, we have to be
|
||||
// careful about the access pattern, that is, no values should be read and written
|
||||
// by both the DownloadManager and the outside threads.
|
||||
FileFuture(std::string file);
|
||||
FileFuture(std::filesystem::path file);
|
||||
|
||||
// Values that are written by the DownloadManager to be consumed by others
|
||||
long long currentSize = -1;
|
||||
@@ -53,7 +53,7 @@ public:
|
||||
float secondsRemaining = -1.f;
|
||||
bool isFinished = false;
|
||||
bool isAborted = false;
|
||||
std::string filePath;
|
||||
std::filesystem::path filePath;
|
||||
std::string errorMessage;
|
||||
std::string format;
|
||||
// Values set by others to be consumed by the DownloadManager
|
||||
@@ -104,15 +104,14 @@ public:
|
||||
OverrideFile overrideFile = OverrideFile::Yes,
|
||||
FailOnError failOnError = FailOnError::No, unsigned int timeout_secs = 0,
|
||||
DownloadFinishedCallback finishedCallback = DownloadFinishedCallback(),
|
||||
DownloadProgressCallback progressCallback = DownloadProgressCallback()
|
||||
);
|
||||
DownloadProgressCallback progressCallback = DownloadProgressCallback()) const;
|
||||
|
||||
std::future<MemoryFile> fetchFile(const std::string& url,
|
||||
SuccessCallback successCallback = SuccessCallback(),
|
||||
ErrorCallback errorCallback = ErrorCallback());
|
||||
|
||||
void getFileExtension(const std::string& url,
|
||||
RequestFinishedCallback finishedCallback = RequestFinishedCallback());
|
||||
void fileExtension(const std::string& url,
|
||||
RequestFinishedCallback finishedCallback = RequestFinishedCallback()) const;
|
||||
|
||||
private:
|
||||
bool _useMultithreadedDownload;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -33,6 +33,7 @@ namespace ghoul::fontrendering { class FontManager; }
|
||||
|
||||
namespace openspace {
|
||||
|
||||
struct Configuration;
|
||||
class Dashboard;
|
||||
class DeferredcasterManager;
|
||||
class DownloadManager;
|
||||
@@ -50,16 +51,15 @@ class SyncEngine;
|
||||
class TimeManager;
|
||||
class VersionChecker;
|
||||
struct WindowDelegate;
|
||||
namespace configuration { struct Configuration; }
|
||||
namespace interaction {
|
||||
struct JoystickInputStates;
|
||||
struct WebsocketInputStates;
|
||||
class ActionManager;
|
||||
class InteractionMonitor;
|
||||
class KeybindingManager;
|
||||
class KeyframeRecordingHandler;
|
||||
class NavigationHandler;
|
||||
class SessionRecording;
|
||||
class ShortcutManager;
|
||||
class SessionRecordingHandler;
|
||||
} // namespace interaction
|
||||
namespace properties { class PropertyOwner; }
|
||||
namespace scripting {
|
||||
@@ -88,15 +88,15 @@ inline SyncEngine* syncEngine;
|
||||
inline TimeManager* timeManager;
|
||||
inline VersionChecker* versionChecker;
|
||||
inline WindowDelegate* windowDelegate;
|
||||
inline configuration::Configuration* configuration;
|
||||
inline Configuration* configuration;
|
||||
inline interaction::ActionManager* actionManager;
|
||||
inline interaction::InteractionMonitor* interactionMonitor;
|
||||
inline interaction::JoystickInputStates* joystickInputStates;
|
||||
inline interaction::WebsocketInputStates* websocketInputStates;
|
||||
inline interaction::KeybindingManager* keybindingManager;
|
||||
inline interaction::KeyframeRecordingHandler* keyframeRecording;
|
||||
inline interaction::NavigationHandler* navigationHandler;
|
||||
inline interaction::SessionRecording* sessionRecording;
|
||||
inline interaction::ShortcutManager* shortcutManager;
|
||||
inline interaction::SessionRecordingHandler* sessionRecordingHandler;
|
||||
inline properties::PropertyOwner* rootPropertyOwner;
|
||||
inline properties::PropertyOwner* screenSpaceRootPropertyOwner;
|
||||
inline properties::PropertyOwner* userPropertyOwner;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -66,11 +66,10 @@ inline std::vector<std::function<void(TouchInput)>>* touchExit;
|
||||
/**
|
||||
* If the framerate becomes slow, Chromium Embedded Framework (used in Web Browser Module)
|
||||
* needs to perform its message loop work more frequently than once per frame. If this
|
||||
* method is not called frequently enough, the GUI will become much less responsive.
|
||||
* A future more long-term may decouple the browser's message work loop from the main
|
||||
* render loop altogehter using a separate thread.
|
||||
* Currently, this method is called from within the RenderEngine,
|
||||
* between calls to individual renderables.
|
||||
* method is not called frequently enough, the GUI will become much less responsive. A
|
||||
* future more long-term may decouple the browser's message work loop from the main render
|
||||
* loop altogehter using a separate thread. Currently, this method is called from within
|
||||
* the RenderEngine, between calls to individual renderables.
|
||||
*/
|
||||
extern void (*webBrowserPerformanceHotfix)();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -43,12 +43,14 @@ namespace documentation { struct Documentation; }
|
||||
* logfile should be created. Both logs can be customized using the `Append`,
|
||||
* `TimeStamping`, `DateStamping`, `CategoryStamping`, and `LogLevelStamping` values.
|
||||
*
|
||||
* \param dictionary The dictionary from which the ghoul::logging::Log should be created
|
||||
* \param dictionary The dictionary from which the ghoul::logging::Log should be created
|
||||
* \return The created ghoul::logging::Log
|
||||
* \post The return value will not be `nullptr`
|
||||
* \throw ghoul::RuntimeError If there was an error creating the ghoul::logging::Log
|
||||
* \sa ghoul::logging::TextLog
|
||||
* \sa ghoul::logging::HTMLLog
|
||||
*
|
||||
* \post The return value will not be `nullptr`
|
||||
* \throw ghoul::RuntimeError If there was an error creating the ghoul::logging::Log
|
||||
*
|
||||
* \see ghoul::logging::TextLog
|
||||
* \see ghoul::logging::HTMLLog
|
||||
*/
|
||||
std::unique_ptr<ghoul::logging::Log> createLog(const ghoul::Dictionary& dictionary);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -39,15 +39,16 @@ namespace openspace {
|
||||
|
||||
class OpenSpaceModule;
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
namespace scripting { struct LuaLibrary; }
|
||||
|
||||
/**
|
||||
* The ModuleEngine is the central repository for registering and accessing
|
||||
* OpenSpaceModule for the current application run. By initializing (#initialize) the
|
||||
* ModuleEngine, the default set of OpenSpaceModule%s as generated by CMake in the
|
||||
* `moduleregistration.h` file is automatically registered and created.
|
||||
* Additional OpenSpaceModule%s can be registered with the #registerModule function, which
|
||||
* will internally call the OpenSpaceModule::initialize method.
|
||||
* `moduleregistration.h` file is automatically registered and created. Additional
|
||||
* OpenSpaceModule%s can be registered with the #registerModule function, which will
|
||||
* internally call the OpenSpaceModule::initialize method.
|
||||
*/
|
||||
class ModuleEngine : public properties::PropertyOwner {
|
||||
public:
|
||||
@@ -55,11 +56,10 @@ public:
|
||||
|
||||
/**
|
||||
* Registers all of the OpenSpaceModule%s which are created by the CMake configuration
|
||||
* and stored in the `moduleregistration.h` file. For all of those modules
|
||||
* the OpenSpaceModule::initialize method with will called.
|
||||
* and stored in the `moduleregistration.h` file. For all of those modules the
|
||||
* OpenSpaceModule::initialize method with will called.
|
||||
*
|
||||
* \throw ghoul::RuntimeError If two modules in the default modules have the same
|
||||
* name
|
||||
* \throw ghoul::RuntimeError If two modules in the default modules have the same name
|
||||
*/
|
||||
void initialize(const std::map<std::string, ghoul::Dictionary>& moduleConfigurations);
|
||||
|
||||
@@ -104,7 +104,7 @@ public:
|
||||
* to have the public static member variable `name` which must be equal to
|
||||
* the name of the module used in its constructor.
|
||||
*
|
||||
* \return a pointer to the module of the given subclass
|
||||
* \return A pointer to the module of the given subclass
|
||||
*/
|
||||
template <class ModuleSubClass>
|
||||
ModuleSubClass* module() const;
|
||||
@@ -118,11 +118,16 @@ public:
|
||||
ghoul::systemcapabilities::Version requiredOpenGLVersion() const;
|
||||
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to affect the
|
||||
* modules.
|
||||
*/
|
||||
* Returns the Lua library that contains all Lua functions available to affect the
|
||||
* modules.
|
||||
*/
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
/**
|
||||
* Returns the list of all documentations for all modules.
|
||||
*/
|
||||
std::vector<documentation::Documentation> moduleDocumentations() const;
|
||||
|
||||
private:
|
||||
/// The list of all names of all registered OpenSpaceModules
|
||||
properties::StringListProperty _allModules;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -51,28 +51,35 @@ class Scene;
|
||||
|
||||
namespace scripting { struct LuaLibrary; }
|
||||
|
||||
// Structure that is responsible for the delayed shutdown of the application
|
||||
/**
|
||||
* Structure that is responsible for the delayed shutdown of the application.
|
||||
*/
|
||||
struct ShutdownInformation {
|
||||
// Whether the application is currently in shutdown mode (i.e. counting down the
|
||||
// timer and closing it at '0'
|
||||
/// Whether the application is currently in shutdown mode (i.e. counting down the
|
||||
/// timer and closing it at '0'
|
||||
bool inShutdown = false;
|
||||
// Total amount of time the application will wait before actually shutting down
|
||||
/// Total amount of time the application will wait before actually shutting down
|
||||
float waitTime = 0.f;
|
||||
// Current state of the countdown; if it reaches '0', the application will
|
||||
// close
|
||||
/// Current state of the countdown; if it reaches '0', the application will
|
||||
/// close
|
||||
float timer = 0.f;
|
||||
};
|
||||
|
||||
struct CommandlineArguments {
|
||||
std::string configurationName;
|
||||
std::vector<std::string> configurationOverride;
|
||||
std::optional<std::string> configuration;
|
||||
std::optional<std::string> windowConfig;
|
||||
std::optional<std::string> profile;
|
||||
std::optional<std::string> propertyVisibility;
|
||||
std::optional<bool> bypassLauncher;
|
||||
};
|
||||
|
||||
class OpenSpaceEngine : public properties::PropertyOwner {
|
||||
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
|
||||
/**
|
||||
* 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,
|
||||
@@ -89,12 +96,10 @@ public:
|
||||
void deinitializeGL();
|
||||
void preSynchronization();
|
||||
void postSynchronizationPreDraw();
|
||||
void viewportChanged();
|
||||
void render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix,
|
||||
const glm::mat4& projectionMatrix);
|
||||
void drawOverlays();
|
||||
void postDraw();
|
||||
void resetPropertyChangeFlags();
|
||||
void keyboardCallback(Key key, KeyModifier mod, KeyAction action,
|
||||
IsGuiWindow isGuiWindow);
|
||||
void charCallback(unsigned int codepoint, KeyModifier modifier,
|
||||
@@ -111,7 +116,6 @@ public:
|
||||
void decode(std::vector<std::byte> data);
|
||||
|
||||
properties::Property::Visibility visibility() const;
|
||||
bool showHiddenSceneGraphNodes() const;
|
||||
void toggleShutdownMode();
|
||||
|
||||
Mode currentMode() const;
|
||||
@@ -128,9 +132,11 @@ public:
|
||||
AssetManager& assetManager();
|
||||
LoadingScreen* loadingScreen();
|
||||
|
||||
void writeDocumentation();
|
||||
void createUserDirectoriesIfNecessary();
|
||||
|
||||
uint64_t ramInUse() const;
|
||||
uint64_t vramInUse() const;
|
||||
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to affect the
|
||||
* application.
|
||||
@@ -142,17 +148,14 @@ private:
|
||||
void loadFonts();
|
||||
|
||||
void runGlobalCustomizationScripts();
|
||||
void resetPropertyChangeFlagsOfSubowners(openspace::properties::PropertyOwner* po);
|
||||
|
||||
properties::BoolProperty _printEvents;
|
||||
properties::OptionProperty _visibility;
|
||||
properties::BoolProperty _showHiddenSceneGraphNodes;
|
||||
properties::FloatProperty _fadeOnEnableDuration;
|
||||
properties::BoolProperty _disableAllMouseInputs;
|
||||
|
||||
std::unique_ptr<Scene> _scene;
|
||||
std::unique_ptr<AssetManager> _assetManager;
|
||||
bool _shouldAbortLoading = false;
|
||||
std::unique_ptr<LoadingScreen> _loadingScreen;
|
||||
std::unique_ptr<VersionChecker> _versionChecker;
|
||||
|
||||
@@ -177,7 +180,8 @@ private:
|
||||
* Sets the camera position using the time contents of a profile. The function will
|
||||
* set an absolute position or a go-to-geolocation command using the globebrowsing
|
||||
* module.
|
||||
* \param p The Profile to be read.
|
||||
*
|
||||
* \param p The Profile to be read
|
||||
*/
|
||||
void setCameraFromProfile(const Profile& p);
|
||||
|
||||
@@ -185,21 +189,21 @@ void setCameraFromProfile(const Profile& p);
|
||||
* Reads a list of modules from a profile, and executes scripts based on whether or
|
||||
* not the corresponding module is loaded.
|
||||
*
|
||||
* \param p The Profile to be read.
|
||||
* \param p The Profile to be read
|
||||
*/
|
||||
void setModulesFromProfile(const Profile& p);
|
||||
|
||||
/**
|
||||
* Registers actions from the contents of a profile.
|
||||
*
|
||||
* \param p The Profile to be read.
|
||||
* \param p The Profile to be read
|
||||
*/
|
||||
void setActionsFromProfile(const Profile& p);
|
||||
|
||||
/**
|
||||
* Registers keybindings from the contents of a profile.
|
||||
*
|
||||
* \param p The Profile to be read.
|
||||
* \param p The Profile to be read
|
||||
*/
|
||||
void setKeybindingsFromProfile(const Profile& p);
|
||||
|
||||
@@ -208,7 +212,7 @@ void setKeybindingsFromProfile(const Profile& p);
|
||||
* If any nodes are listed, a script to mark these will be queued with the
|
||||
* script engine.
|
||||
*
|
||||
* \param p The Profile to be read.
|
||||
* \param p The Profile to be read
|
||||
*/
|
||||
void setMarkInterestingNodesFromProfile(const Profile& p);
|
||||
|
||||
@@ -217,7 +221,7 @@ void setMarkInterestingNodesFromProfile(const Profile& p);
|
||||
* at the end of the initialization. Any openspace lua commands are allowed,
|
||||
* and will be added to the script queue.
|
||||
*
|
||||
* \param p The Profile to be read.
|
||||
* \param p The Profile to be read
|
||||
*/
|
||||
void setAdditionalScriptsFromProfile(const Profile& p);
|
||||
|
||||
|
||||
64
include/openspace/engine/settings.h
Normal file
64
include/openspace/engine/settings.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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___SETTINGS___H__
|
||||
#define __OPENSPACE_CORE___SETTINGS___H__
|
||||
|
||||
#include <openspace/engine/configuration.h>
|
||||
#include <openspace/properties/property.h>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
struct Settings {
|
||||
auto operator<=>(const Settings&) const = default;
|
||||
|
||||
std::optional<bool> hasStartedBefore;
|
||||
|
||||
std::optional<std::string> configuration;
|
||||
std::optional<bool> rememberLastConfiguration;
|
||||
std::optional<std::string> profile;
|
||||
std::optional<bool> rememberLastProfile;
|
||||
std::optional<properties::Property::Visibility> visibility;
|
||||
std::optional<bool> bypassLauncher;
|
||||
std::optional<Configuration::LayerServer> layerServer;
|
||||
|
||||
struct MRF {
|
||||
auto operator<=>(const MRF&) const = default;
|
||||
|
||||
std::optional<bool> isEnabled;
|
||||
std::optional<std::string> location;
|
||||
};
|
||||
MRF mrf;
|
||||
};
|
||||
|
||||
std::filesystem::path findSettings(const std::string& filename = "settings.json");
|
||||
|
||||
Settings loadSettings(const std::filesystem::path& filename = findSettings());
|
||||
void saveSettings(const Settings& settings, const std::filesystem::path& filename);
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_CORE___SETTINGS___H__
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -36,72 +36,71 @@ namespace openspace {
|
||||
class Syncable;
|
||||
|
||||
/**
|
||||
* Manages a collection of `Syncable`s and ensures they are synchronized
|
||||
* over SGCT nodes. Encoding/Decoding order is handles internally.
|
||||
* Manages a collection of `Syncable`s and ensures they are synchronized over SGCT nodes.
|
||||
* Encoding/Decoding order is handles internally.
|
||||
*/
|
||||
class SyncEngine {
|
||||
public:
|
||||
BooleanType(IsMaster);
|
||||
|
||||
/**
|
||||
* Creates a new SyncEngine which a buffer size of \p syncBufferSize
|
||||
* Creates a new SyncEngine which a buffer size of \p syncBufferSize.
|
||||
*
|
||||
* \pre syncBufferSize must be bigger than 0
|
||||
*/
|
||||
SyncEngine(unsigned int syncBufferSize);
|
||||
|
||||
/**
|
||||
* Encodes all added Syncables in the injected `SyncBuffer`.
|
||||
* This method is only called on the SGCT master node
|
||||
* Encodes all added Syncables in the injected `SyncBuffer`. This method is only
|
||||
* called on the SGCT master node.
|
||||
*/
|
||||
std::vector<std::byte> encodeSyncables();
|
||||
|
||||
/**
|
||||
* Decodes the `SyncBuffer` into the added Syncables.
|
||||
* This method is only called on the SGCT client nodes
|
||||
* Decodes the `SyncBuffer` into the added Syncables. This method is only called on
|
||||
* the SGCT client nodes.
|
||||
*/
|
||||
void decodeSyncables(std::vector<std::byte> data);
|
||||
|
||||
/**
|
||||
* Invokes the presync method of all added Syncables
|
||||
* Invokes the presync method of all added Syncables.
|
||||
*/
|
||||
void preSynchronization(IsMaster isMaster);
|
||||
|
||||
/**
|
||||
* Invokes the postsync method of all added Syncables
|
||||
* Invokes the postsync method of all added Syncables.
|
||||
*/
|
||||
void postSynchronization(IsMaster isMaster);
|
||||
|
||||
/**
|
||||
* Add a Syncable to be synchronized over the SGCT cluster.
|
||||
* \pre syncable must not be nullptr
|
||||
*
|
||||
* \pre syncable must not be `nullptr`
|
||||
*/
|
||||
void addSyncable(Syncable* syncable);
|
||||
|
||||
/**
|
||||
* Add multiple Syncables to be synchronized over the SGCT cluster
|
||||
* Add multiple Syncables to be synchronized over the SGCT cluster.
|
||||
*
|
||||
* \pre syncables must not contain any nullptr
|
||||
*/
|
||||
void addSyncables(const std::vector<Syncable*>& syncables);
|
||||
|
||||
/**
|
||||
* Remove a Syncable from being synchronized over the SGCT cluster
|
||||
* Remove a Syncable from being synchronized over the SGCT cluster.
|
||||
*/
|
||||
void removeSyncable(Syncable* syncable);
|
||||
|
||||
/**
|
||||
* Remove multiple Syncables from being synchronized over the SGCT cluster
|
||||
* Remove multiple Syncables from being synchronized over the SGCT cluster.
|
||||
*/
|
||||
void removeSyncables(const std::vector<Syncable*>& syncables);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Vector of Syncables. The vectors ensures consistent encode/decode order
|
||||
*/
|
||||
/// Vector of Syncables. The vectors ensures consistent encode/decode order.
|
||||
std::vector<Syncable*> _syncables;
|
||||
|
||||
/**
|
||||
* Databuffer used in encoding/decoding
|
||||
*/
|
||||
/// Databuffer used in encoding/decoding
|
||||
SyncBuffer _syncBuffer;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -34,6 +34,9 @@ namespace openspace {
|
||||
struct WindowDelegate {
|
||||
enum class Frustum { Mono, LeftEye, RightEye };
|
||||
|
||||
enum class Cursor { Arrow, IBeam, CrossHair, PointingHand, ResizeEW, ResizeNS,
|
||||
ResizeNWSE, ResizeNESW, ResizeAll, NotAllowed };
|
||||
|
||||
void (*terminate)() = [](){};
|
||||
|
||||
void (*setBarrier)(bool enabled) = [](bool) {};
|
||||
@@ -114,7 +117,7 @@ struct WindowDelegate {
|
||||
|
||||
uint64_t (*swapGroupFrameNumber)() = []() { return uint64_t(0); };
|
||||
|
||||
void (*setScreenshotFolder)(std::string) = [](std::string) {};
|
||||
void (*setScreenshotFolder)(std::filesystem::path) = [](std::filesystem::path) {};
|
||||
|
||||
void (*showStatistics)(bool) = [](bool) {};
|
||||
|
||||
@@ -122,8 +125,12 @@ struct WindowDelegate {
|
||||
|
||||
int (*currentNode)() = []() { return 0; };
|
||||
|
||||
glm::vec2 (*mousePositionViewportRelative)(glm::vec2 mousePosition) =
|
||||
[](glm::vec2) { return glm::vec2(0); };
|
||||
glm::vec2 (*mousePositionViewportRelative)(const glm::vec2& mousePosition) =
|
||||
[](const glm::vec2&) { return glm::vec2(0); };
|
||||
|
||||
void (*setStatisticsGraphScale)(float scale) = [](float) {};
|
||||
|
||||
void (*setMouseCursor)(Cursor cursor) = [](Cursor) {};
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -58,21 +58,20 @@ struct Event {
|
||||
// if they are triggered by events
|
||||
// 6. Add the new enum entry into the `toString` and `fromString` methods
|
||||
enum class Type : uint8_t {
|
||||
SceneGraphNodeAdded,
|
||||
SceneGraphNodeRemoved,
|
||||
ParallelConnection,
|
||||
ProfileLoadingFinished,
|
||||
AssetLoadingFinished,
|
||||
ApplicationShutdown,
|
||||
ScreenSpaceRenderableAdded,
|
||||
ScreenSpaceRenderableRemoved,
|
||||
CameraFocusTransition,
|
||||
TimeOfInterestReached,
|
||||
MissionEventReached,
|
||||
PlanetEclipsed,
|
||||
InterpolationFinished,
|
||||
FocusNodeChanged,
|
||||
LayerAdded,
|
||||
LayerRemoved,
|
||||
PropertyTreeUpdated,
|
||||
PropertyTreePruned,
|
||||
ActionAdded,
|
||||
ActionRemoved,
|
||||
SessionRecordingPlayback,
|
||||
PointSpacecraft,
|
||||
RenderableEnabled,
|
||||
@@ -80,7 +79,10 @@ struct Event {
|
||||
CameraPathStarted,
|
||||
CameraPathFinished,
|
||||
CameraMovedPosition,
|
||||
Custom
|
||||
ScheduledScriptExecuted,
|
||||
GuiTreeUpdated,
|
||||
Custom,
|
||||
Last // sentinel value
|
||||
};
|
||||
constexpr explicit Event(Type type_) : type(type_) {}
|
||||
|
||||
@@ -110,43 +112,6 @@ void logAllEvents(const Event* e);
|
||||
// Events
|
||||
//
|
||||
|
||||
/**
|
||||
* This event is created whenever a new scene graph node is added to the system. By the
|
||||
* time this event is signalled, the scene graph node has already been created and added
|
||||
* to the scene.
|
||||
*/
|
||||
struct EventSceneGraphNodeAdded : public Event {
|
||||
static constexpr Type Type = Event::Type::SceneGraphNodeAdded;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventSceneGraphNodeAdded event.
|
||||
*
|
||||
* \param node_ The identifier of the node that was added
|
||||
*
|
||||
* \pre node_ must not be nullptr
|
||||
*/
|
||||
explicit EventSceneGraphNodeAdded(const SceneGraphNode* node_);
|
||||
const tstring node;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created whenever a scene graph node was removed. By the time this event
|
||||
* is signalled, the scene graph node has already been removed.
|
||||
*/
|
||||
struct EventSceneGraphNodeRemoved : public Event {
|
||||
static constexpr Type Type = Event::Type::SceneGraphNodeRemoved;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventSceneGraphNodeRemoved event.
|
||||
*
|
||||
* \param node_ The identifier of the node that was removed
|
||||
*
|
||||
* \pre node_ must not be nullptr
|
||||
*/
|
||||
explicit EventSceneGraphNodeRemoved(const SceneGraphNode* node_);
|
||||
const tstring node;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created whenever something in the parallel connection subsystem changes.
|
||||
* The new state is sent as an argument with this event.
|
||||
@@ -164,7 +129,7 @@ struct EventParallelConnection : public Event {
|
||||
/**
|
||||
* Creates an instance of an EventParallelConnection event.
|
||||
*
|
||||
* \param state_ The new state of the parallel connection system; is one of
|
||||
* \param state_ The new state of the parallel connection system; is one of
|
||||
* `Established`, `Lost`, `HostshipGained`, or `HostshipLost`
|
||||
*/
|
||||
explicit EventParallelConnection(State state_);
|
||||
@@ -184,6 +149,20 @@ struct EventProfileLoadingFinished : public Event {
|
||||
EventProfileLoadingFinished();
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when the loading of all assets are finished. This is emitted
|
||||
* regardless of whether it is the initial startup of a profile, or any subsequent asset
|
||||
* being loaded e.g., through add or drag-and-drop.
|
||||
*/
|
||||
struct EventAssetLoadingFinished : public Event {
|
||||
static constexpr Type Type = Event::Type::AssetLoadingFinished;
|
||||
|
||||
/**
|
||||
* Creates an instance of an AssetLoadingFinished event.
|
||||
*/
|
||||
EventAssetLoadingFinished();
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created whenever some information about the application shutdown sequence
|
||||
* changes. This can either be that the seqeuence started, was aborted, or is finished,
|
||||
@@ -201,65 +180,30 @@ struct EventApplicationShutdown : public Event {
|
||||
/**
|
||||
* Creates an instance of an EventApplicationShutdown event.
|
||||
*
|
||||
* \param state_ The next state of the application shutdown sequence; is one of
|
||||
* `Started`, `Aborted`, or `Finished`
|
||||
* \param state_ The next state of the application shutdown sequence; is one of
|
||||
* `Started`, `Aborted`, or `Finished`
|
||||
*/
|
||||
explicit EventApplicationShutdown(State state_);
|
||||
const State state;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when a new screenspace renderable has been created. By the time
|
||||
* this event is craeted, the screenspace renderable is already registered and available.
|
||||
*/
|
||||
struct EventScreenSpaceRenderableAdded : public Event {
|
||||
static constexpr Type Type = Event::Type::ScreenSpaceRenderableAdded;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventScreenSpaceRenderableAdded event.
|
||||
*
|
||||
* \param renderable_ The the new screenspace renderable that was added to the system
|
||||
*
|
||||
* \pre renderable_ must not be nullptr
|
||||
*/
|
||||
explicit EventScreenSpaceRenderableAdded(const ScreenSpaceRenderable* renderable_);
|
||||
const tstring renderable;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when a screenspace renderable has been removed from the system.
|
||||
* When this event is created, the screenspace renderable has already been removed and is
|
||||
* no longer available
|
||||
*/
|
||||
struct EventScreenSpaceRenderableRemoved : public Event {
|
||||
static constexpr Type Type = Event::Type::ScreenSpaceRenderableRemoved;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventScreenSpaceRenderableRemoved event.
|
||||
*
|
||||
* \param renderable_ The the new screenspace renderable that was removed
|
||||
*/
|
||||
explicit EventScreenSpaceRenderableRemoved(const ScreenSpaceRenderable* renderable_);
|
||||
const tstring renderable;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when the camera transitions between different interaction sphere
|
||||
* distances. Right now, only movement relative to camera's focus node is considered.
|
||||
* Each scene graph node has an interaction sphere radius that serves as the reference
|
||||
* distance for all spheres.
|
||||
```
|
||||
Diagram of events for a camera moving from right-to-left. Interaction sphere is 'O' in
|
||||
middle, and ')' are spherical boundaries. The approach factor, reach factor, and
|
||||
interaction sphere radius are all taken from the current focus node.
|
||||
|
||||
|<------------------->| Approach factor * Interaction sphere
|
||||
|<------>| Reach Factor * Interaction sphere
|
||||
|
||||
( ( O ) )
|
||||
^ ^ ^ ^
|
||||
Exiting Receding Reaching Approaching
|
||||
```
|
||||
* ```
|
||||
* Diagram of events for a camera moving from right-to-left. Interaction sphere is 'O' in
|
||||
* middle, and ')' are spherical boundaries. The approach factor, reach factor, and
|
||||
* interaction sphere radius are all taken from the current focus node.
|
||||
*
|
||||
* |<------------------->| Approach factor * Interaction sphere
|
||||
* |<------>| Reach Factor * Interaction sphere
|
||||
*
|
||||
* ( ( O ) )
|
||||
* ^ ^ ^ ^
|
||||
* Exiting Receding Reaching Approaching
|
||||
* ```
|
||||
*/
|
||||
struct EventCameraFocusTransition : public Event {
|
||||
static constexpr Type Type = Event::Type::CameraFocusTransition;
|
||||
@@ -347,7 +291,7 @@ struct EventPlanetEclipsed : public Event {
|
||||
|
||||
/**
|
||||
* This event is created when the interpolation of a property value is finished. If the
|
||||
* interpolation time of a property change is 0s, this event is not fired
|
||||
* interpolation time of a property change is 0s, this event is not fired.
|
||||
*/
|
||||
struct EventInterpolationFinished : public Event {
|
||||
static constexpr Type Type = Event::Type::InterpolationFinished;
|
||||
@@ -387,53 +331,76 @@ struct EventFocusNodeChanged : public Event {
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when a layer is added to to a globe.
|
||||
* This event is created a property owner or property has been added or has changed.
|
||||
*/
|
||||
struct EventLayerAdded : public Event {
|
||||
static constexpr Type Type = Event::Type::LayerAdded;
|
||||
struct EventPropertyTreeUpdated : public Event {
|
||||
static constexpr Type Type = Event::Type::PropertyTreeUpdated;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventLayerAdded event.
|
||||
* Creates an instance of an EventPropertyTreeUpdated event.
|
||||
*
|
||||
* \param node_ The identifier of the globe to which the layer is added
|
||||
* \param layerGroup_ The identifier of the layer group to which the layer is added
|
||||
* \param layer_ The identifier of the layer that was added
|
||||
* \param uri_ A string with the uri of the property or property owner that was added
|
||||
*
|
||||
* \pre node_ must not be empty
|
||||
* \pre layerGroup_ must not be empty
|
||||
* \pre layer_ must not be empty
|
||||
* \pre uri_ must be a valid uri
|
||||
*/
|
||||
explicit EventLayerAdded(std::string_view node_, std::string_view layerGroup_,
|
||||
std::string_view layer_);
|
||||
explicit EventPropertyTreeUpdated(std::string_view uri_);
|
||||
|
||||
const tstring node;
|
||||
const tstring layerGroup;
|
||||
const tstring layer;
|
||||
const tstring uri;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when a layer is removed from a globe.
|
||||
* This event is created when a property owner or property is removed from a the property
|
||||
* tree.
|
||||
*/
|
||||
struct EventLayerRemoved : public Event {
|
||||
static constexpr Type Type = Event::Type::LayerRemoved;
|
||||
struct EventPropertyTreePruned : public Event {
|
||||
static constexpr Type Type = Event::Type::PropertyTreePruned;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventLayerRemoved event.
|
||||
* Creates an instance of an EventPropertyTreePruned event.
|
||||
*
|
||||
* \param node_ The identifier of the globe to which the layer is removed
|
||||
* \param layerGroup_ The identifier of the layer group to which the layer is removed
|
||||
* \param layer_ The identifier of the layer that was removed
|
||||
* \param uri_ The uri of the property or property owner that was removed
|
||||
*
|
||||
* \pre node_ must not be empty
|
||||
* \pre layerGroup_ must not be empty
|
||||
* \pre layer_ must not be empty
|
||||
* \pre uri_ must be a valid uri
|
||||
*/
|
||||
explicit EventLayerRemoved(std::string_view node_, std::string_view layerGroup_,
|
||||
std::string_view layer_);
|
||||
explicit EventPropertyTreePruned(std::string_view uri_);
|
||||
|
||||
const tstring node;
|
||||
const tstring layerGroup;
|
||||
const tstring layer;
|
||||
const tstring uri;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when an action is added.
|
||||
*/
|
||||
struct EventActionAdded : public Event {
|
||||
static constexpr Type Type = Event::Type::ActionAdded;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventActionAdded event.
|
||||
*
|
||||
* \param uri_ A string with the uri of the action that was added
|
||||
*
|
||||
* \pre uri_ must be a valid uri
|
||||
*/
|
||||
explicit EventActionAdded(std::string_view uri_);
|
||||
|
||||
const tstring uri;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when an action is removed.
|
||||
*/
|
||||
struct EventActionRemoved : public Event {
|
||||
static constexpr Type Type = Event::Type::ActionRemoved;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventActionRemoved event.
|
||||
*
|
||||
* \param uri_ The uri of the action that was removed
|
||||
*
|
||||
* \pre uri_ must be a valid uri
|
||||
*/
|
||||
explicit EventActionRemoved(std::string_view uri_);
|
||||
|
||||
const tstring uri;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -562,7 +529,7 @@ struct EventCameraPathFinished : public Event {
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when the a camera moves location
|
||||
* This event is created when the a camera moves location.
|
||||
*/
|
||||
struct EventCameraMovedPosition : public Event {
|
||||
static constexpr Type Type = Event::Type::CameraMovedPosition;
|
||||
@@ -573,6 +540,33 @@ struct EventCameraMovedPosition : public Event {
|
||||
EventCameraMovedPosition();
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when a scheduled script is executed.
|
||||
*/
|
||||
struct EventScheduledScriptExecuted : public Event {
|
||||
static constexpr Type Type = Event::Type::ScheduledScriptExecuted;
|
||||
|
||||
/**
|
||||
* Creates an instance of an ScheduledScriptExecuted event.
|
||||
*/
|
||||
EventScheduledScriptExecuted(std::string_view script_);
|
||||
|
||||
const tstring script;
|
||||
};
|
||||
|
||||
/**
|
||||
* This event is created when the custom ordering for a specific branch in the Scene
|
||||
* GUI tree is changed. It signals to the UI that the tree should be updated.
|
||||
*/
|
||||
struct EventGuiTreeUpdated : public Event {
|
||||
static constexpr Type Type = Event::Type::GuiTreeUpdated;
|
||||
|
||||
/**
|
||||
* Creates an instance of an EventGuiTreeUpdated event.
|
||||
*/
|
||||
EventGuiTreeUpdated();
|
||||
};
|
||||
|
||||
/**
|
||||
* A custom event type that can be used in a pinch when no explicit event type is
|
||||
* available. This should only be used in special circumstances and it should be
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -36,6 +36,8 @@ namespace events { struct Event; }
|
||||
|
||||
class EventEngine {
|
||||
public:
|
||||
using ScriptCallback = std::function<void(ghoul::Dictionary)>;
|
||||
|
||||
struct ActionInfo {
|
||||
events::Event::Type type;
|
||||
uint32_t id = std::numeric_limits<uint32_t>::max();
|
||||
@@ -44,11 +46,16 @@ public:
|
||||
std::optional<ghoul::Dictionary> filter;
|
||||
};
|
||||
|
||||
struct TopicInfo {
|
||||
uint32_t id = std::numeric_limits<uint32_t>::max();
|
||||
ScriptCallback callback;
|
||||
};
|
||||
|
||||
/**
|
||||
* This function returns the first event stored in the EventEngine, or `nullptr` if
|
||||
* no event exists. To navigate the full list of events, you can access the returned
|
||||
* Event's next function. If the end of the list is reached, the next pointer will be
|
||||
* a nullptr
|
||||
* a `nullptr`.
|
||||
*
|
||||
* \return The first event stored in the EventEngine or nullptr if no event exists
|
||||
*/
|
||||
@@ -57,11 +64,11 @@ public:
|
||||
/**
|
||||
* Publish a new event of type T by providing optional arguments Args to the Event's
|
||||
* constructor. An example of usage is
|
||||
* `engine.publishEvent<MyEvent>("a", 2.0);` which would call the
|
||||
* constructor of `MyEvent` with a `const char*` and `double` parameter.
|
||||
* `engine.publishEvent<MyEvent>("a", 2.0);` which would call the constructor of
|
||||
* `MyEvent` with a `const char*` and `double` parameter.
|
||||
*
|
||||
* \param args The arguments that are passed to the constructor of T
|
||||
* \tparam T The subclass of Event that is to be published
|
||||
* \param args The arguments that are passed to the constructor of T
|
||||
*/
|
||||
template <typename T, typename... Args>
|
||||
void publishEvent(Args&&... args);
|
||||
@@ -87,6 +94,16 @@ public:
|
||||
void registerEventAction(events::Event::Type type, std::string identifier,
|
||||
std::optional<ghoul::Dictionary> filter = std::nullopt);
|
||||
|
||||
/**
|
||||
* Registers a new topic for a specific event type.
|
||||
*
|
||||
* \param topicId The id of the topic that will be triggered
|
||||
* \param type The type for which a new topic is registered
|
||||
* \param callback The callback function that will be called on triggered event
|
||||
*/
|
||||
void registerEventTopic(size_t topicId, events::Event::Type type,
|
||||
ScriptCallback callback);
|
||||
|
||||
/**
|
||||
* Removing registration for a type/action combination.
|
||||
*
|
||||
@@ -96,15 +113,24 @@ public:
|
||||
*/
|
||||
void unregisterEventAction(events::Event::Type type,
|
||||
const std::string& identifier,
|
||||
std::optional<ghoul::Dictionary> filter = std::nullopt);
|
||||
const std::optional<ghoul::Dictionary>& filter = std::nullopt);
|
||||
|
||||
/**
|
||||
* Removing registration for a specific event identified by the \p identifier.
|
||||
*
|
||||
* \param identifier The unique identifier of the event that should be removed.
|
||||
* \param identifier The unique identifier of the event that should be removed
|
||||
*/
|
||||
void unregisterEventAction(uint32_t identifier);
|
||||
|
||||
/**
|
||||
* Removing registration for a topic/type combination, does nothing if topicId or type
|
||||
* combination does not exist
|
||||
*
|
||||
* \param topicId The id of the topic that should be unregistered
|
||||
* \param type The type of the topic that should be unregistered
|
||||
*/
|
||||
void unregisterEventTopic(size_t topicId, events::Event::Type type);
|
||||
|
||||
/**
|
||||
* Returns the list of all registered actions, sorted by their identifiers.
|
||||
*
|
||||
@@ -112,6 +138,14 @@ public:
|
||||
*/
|
||||
std::vector<ActionInfo> registeredActions() const;
|
||||
|
||||
/**
|
||||
* Returns the list of all registered actions, grouped by their event type.
|
||||
*
|
||||
* \return The unordered map of all registered actions
|
||||
*/
|
||||
const std::unordered_map<events::Event::Type, std::vector<ActionInfo>>&
|
||||
eventActions() const;
|
||||
|
||||
/**
|
||||
* Enables the event identified by the \p identifier. If the event is already enabled,
|
||||
* this function does nothing.
|
||||
@@ -130,10 +164,16 @@ public:
|
||||
|
||||
/**
|
||||
* Triggers all actions that are registered for events that are in the current event
|
||||
* queue
|
||||
* queue.
|
||||
*/
|
||||
void triggerActions() const;
|
||||
|
||||
/**
|
||||
* Triggers all topics that are registered for events that are in the current event
|
||||
* queue.
|
||||
*/
|
||||
void triggerTopics() const;
|
||||
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
private:
|
||||
@@ -144,12 +184,13 @@ private:
|
||||
/// The last event in the chain of events stored in the memory pool
|
||||
events::Event* _lastEvent = nullptr;
|
||||
|
||||
|
||||
// The type is duplicated in the ActionInfo as well, but we want it in the ActionInfo
|
||||
// to be able to return them to a caller and we want it in this unordered_map to make
|
||||
// the lookup really fast. So having this extra wasted memory is probably worth it
|
||||
/// The type is duplicated in the ActionInfo as well, but we want it in the ActionInfo
|
||||
/// to be able to return them to a caller and we want it in this unordered_map to make
|
||||
/// the lookup really fast. So having this extra wasted memory is probably worth it
|
||||
std::unordered_map<events::Event::Type, std::vector<ActionInfo>> _eventActions;
|
||||
|
||||
std::unordered_map<events::Event::Type, std::vector<TopicInfo>> _eventTopics;
|
||||
|
||||
static uint32_t nextRegisteredEventId;
|
||||
|
||||
#ifdef _DEBUG
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -63,7 +63,7 @@ struct Action {
|
||||
/// current OpenSpace instance. If it is `No`, it is synchronized to other OpenSpace
|
||||
/// instances, for example other nodes in a cluster environment, or to other OpenSpace
|
||||
/// instances using a parallel connection
|
||||
IsLocal isLocal = IsLocal::Yes;
|
||||
IsLocal isLocal = IsLocal::No;
|
||||
};
|
||||
|
||||
} // namespace openspace::interaction
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -35,14 +35,18 @@ namespace openspace::interaction {
|
||||
|
||||
class ActionManager {
|
||||
public:
|
||||
BooleanType(ShouldBeSynchronized);
|
||||
BooleanType(ShouldBeLogged);
|
||||
|
||||
bool hasAction(const std::string& identifier) const;
|
||||
void registerAction(Action action);
|
||||
void removeAction(const std::string& identifier);
|
||||
const Action& action(const std::string& identifier) const;
|
||||
std::vector<Action> actions() const;
|
||||
|
||||
void triggerAction(const std::string& identifier,
|
||||
const ghoul::Dictionary& arguments) const;
|
||||
void triggerAction(const std::string& identifier, const ghoul::Dictionary& arguments,
|
||||
ShouldBeSynchronized shouldBeSynchronized,
|
||||
ShouldBeLogged shouldBeLogged = ShouldBeLogged::No) const;
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
private:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -33,9 +33,9 @@ namespace openspace::interaction {
|
||||
class CameraInteractionStates {
|
||||
public:
|
||||
/**
|
||||
* \param sensitivity
|
||||
* \param velocityScaleFactor can be set to 60 to remove the inertia of the
|
||||
* interaction. Lower value will make it harder to move the camera.
|
||||
* \param sensitivity Interaction sensitivity
|
||||
* \param velocityScaleFactor Can be set to 60 to remove the inertia of the
|
||||
* interaction. Lower value will make it harder to move the camera
|
||||
*/
|
||||
CameraInteractionStates(double sensitivity, double velocityScaleFactor);
|
||||
virtual ~CameraInteractionStates() = default;
|
||||
@@ -54,11 +54,11 @@ public:
|
||||
|
||||
void resetVelocities();
|
||||
|
||||
/*
|
||||
* Returns true if any of the velocities are larger than zero,
|
||||
* i.e. wether an interaction happened
|
||||
/**
|
||||
* Returns true if any of the velocities are larger than zero, i.e. wether an
|
||||
* interaction happened.
|
||||
*/
|
||||
bool hasNonZeroVelocities(bool checkOnlyMovement = false);
|
||||
bool hasNonZeroVelocities(bool checkOnlyMovement = false) const;
|
||||
|
||||
protected:
|
||||
struct InteractionState {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -28,9 +28,9 @@
|
||||
namespace openspace::interaction {
|
||||
|
||||
/**
|
||||
* Class that acts as a smoothing filter to a variable. The filter has a step
|
||||
* response on a form that resembles the function y = 1-e^(-t/scale). The variable
|
||||
* will be updated as soon as it is set to a value (calling the set() function).
|
||||
* Class that acts as a smoothing filter to a variable. The filter has a step response on
|
||||
* a form that resembles the function y = 1-e^(-t/scale). The variable will be updated as
|
||||
* soon as it is set to a value (calling the set() function).
|
||||
*/
|
||||
template <typename T, typename ScaleType>
|
||||
class DelayedVariable {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
|
||||
/*
|
||||
* Called from all places we want to mark activity from. Updates the last registered
|
||||
* interaction time
|
||||
* interaction time.
|
||||
*/
|
||||
void markInteraction();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
namespace openspace::interaction {
|
||||
|
||||
/*
|
||||
/**
|
||||
* Interpolates a typename T using a transfer function.
|
||||
*/
|
||||
template <typename T>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -59,7 +59,7 @@ void Interpolator<T>::setInterpolationTime(float interpolationTime) {
|
||||
template <typename T>
|
||||
void Interpolator<T>::step() {
|
||||
_t += _scaledDeltaTime;
|
||||
_t = glm::clamp(_t, 0.0f, 1.0f);
|
||||
_t = glm::clamp(_t, 0.f, 1.f);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -88,14 +88,14 @@ public:
|
||||
void updateStateFromInput(
|
||||
const JoystickInputStates& joystickInputStates, double deltaTime);
|
||||
|
||||
void setAxisMapping(std::string joystickName, int axis, AxisType mapping,
|
||||
void setAxisMapping(const std::string& joystickName, int axis, AxisType mapping,
|
||||
AxisInvert shouldInvert = AxisInvert::No,
|
||||
JoystickType joystickType = JoystickType::JoystickLike,
|
||||
bool isSticky = false, AxisFlip shouldFlip = AxisFlip::No,
|
||||
double sensitivity = 0.0
|
||||
);
|
||||
|
||||
void setAxisMappingProperty(std::string joystickName, int axis,
|
||||
void setAxisMappingProperty(const std::string& joystickName, int axis,
|
||||
std::string propertyUri, float min = 0.f, float max = 1.f,
|
||||
AxisInvert shouldInvert = AxisInvert::No, bool isRemote = true
|
||||
);
|
||||
@@ -163,19 +163,19 @@ inline std::string to_string(
|
||||
{
|
||||
using T = openspace::interaction::JoystickCameraStates::AxisType;
|
||||
switch (value) {
|
||||
case T::None: return "None";
|
||||
case T::OrbitX: return "Orbit X";
|
||||
case T::OrbitY: return "Orbit Y";
|
||||
case T::ZoomIn: return "Zoom In";
|
||||
case T::ZoomOut: return "Zoom Out";
|
||||
case T::Zoom: return "Zoom In and Out";
|
||||
case T::None: return "None";
|
||||
case T::OrbitX: return "Orbit X";
|
||||
case T::OrbitY: return "Orbit Y";
|
||||
case T::ZoomIn: return "Zoom In";
|
||||
case T::ZoomOut: return "Zoom Out";
|
||||
case T::Zoom: return "Zoom In and Out";
|
||||
case T::LocalRoll: return "LocalRoll";
|
||||
case T::GlobalRoll: return "GlobalRoll";
|
||||
case T::PanX: return "Pan X";
|
||||
case T::PanY: return "Pan Y";
|
||||
case T::Property: return "Property";
|
||||
default: return "";
|
||||
}
|
||||
case T::PanX: return "Pan X";
|
||||
case T::PanY: return "Pan Y";
|
||||
case T::Property: return "Property";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -196,7 +196,7 @@ from_string(std::string_view string)
|
||||
if (string == "Pan Y") { return T::PanY; }
|
||||
if (string == "Property") { return T::Property; }
|
||||
|
||||
throw RuntimeError("Unkonwn axis type '" + std::string(string) + "'");
|
||||
throw RuntimeError(std::format("Unknown axis type '{}'", string), "Joystick");
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -220,7 +220,7 @@ from_string(std::string_view string)
|
||||
if (string == "JoystickLike") { return T::JoystickLike; }
|
||||
if (string == "TriggerLike") { return T::TriggerLike; }
|
||||
|
||||
throw RuntimeError("Unkonwn joystick type '" + std::string(string) + "'");
|
||||
throw RuntimeError(std::format("Unknown joystick type '{}'", string), "Joystick");
|
||||
}
|
||||
|
||||
} // namespace ghoul
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -25,10 +25,10 @@
|
||||
#ifndef __OPENSPACE_CORE___JOYSTICKINPUTSTATE___H__
|
||||
#define __OPENSPACE_CORE___JOYSTICKINPUTSTATE___H__
|
||||
|
||||
#include <ghoul/format.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/misc/exception.h>
|
||||
#include <ghoul/misc/stringconversion.h>
|
||||
#include <ghoul/fmt.h>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -37,7 +37,7 @@ namespace openspace::interaction {
|
||||
|
||||
/**
|
||||
* Actions that any button of a joystick can have. Each button must be in one of these
|
||||
* states
|
||||
* states.
|
||||
*/
|
||||
enum class JoystickAction : uint8_t {
|
||||
/// Idle state if the button is unpressed and has been unpressed since last frame
|
||||
@@ -81,7 +81,7 @@ struct JoystickInputStates : public std::array<JoystickInputState, MaxJoysticks>
|
||||
static constexpr int MaxNumJoysticks = 16;
|
||||
|
||||
/**
|
||||
* This function return the number of axes the joystick with the given name has
|
||||
* This function return the number of axes the joystick with the given name has.
|
||||
*
|
||||
* \param joystickName The name of the joystick to check how many axes it has,
|
||||
* if empty the max number of axes for all joysticks are returned
|
||||
@@ -90,7 +90,7 @@ struct JoystickInputStates : public std::array<JoystickInputState, MaxJoysticks>
|
||||
int numAxes(const std::string& joystickName = "") const;
|
||||
|
||||
/**
|
||||
* This function return the number of buttons the joystick with the given name has
|
||||
* This function return the number of buttons the joystick with the given name has.
|
||||
*
|
||||
* \param joystickName The name of the joystick to check how many buttons it has,
|
||||
* if empty the max number of buttons for all joysticks are returned
|
||||
@@ -150,7 +150,7 @@ constexpr openspace::interaction::JoystickAction from_string(std::string_view st
|
||||
if (string == "Repeat") { return openspace::interaction::JoystickAction::Repeat; }
|
||||
if (string == "Release") { return openspace::interaction::JoystickAction::Release; }
|
||||
|
||||
throw RuntimeError(fmt::format("Unknown action '{}'", string));
|
||||
throw RuntimeError(std::format("Unknown action '{}'", string));
|
||||
}
|
||||
|
||||
} // namespace ghoul
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -38,8 +38,6 @@ namespace openspace::interaction {
|
||||
|
||||
class KeybindingManager {
|
||||
public:
|
||||
KeybindingManager();
|
||||
|
||||
void resetKeyBindings();
|
||||
|
||||
void bindKey(Key key, KeyModifier modifier, std::string action);
|
||||
@@ -53,8 +51,6 @@ public:
|
||||
|
||||
void keyboardCallback(Key key, KeyModifier modifier, KeyAction action);
|
||||
|
||||
nlohmann::json generateJson() const;
|
||||
|
||||
const std::multimap<KeyWithModifier, std::string>& keyBindings() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -22,51 +22,41 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_CORE___KEYFRAMERECORDINGHANDLER___H__
|
||||
#define __OPENSPACE_CORE___KEYFRAMERECORDINGHANDLER___H__
|
||||
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
|
||||
#include <openspace/interaction/sessionrecording.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace openspace::interaction {
|
||||
|
||||
template <class T>
|
||||
T nextKeyframeObj(unsigned int index, const std::vector<T>& keyframeContainer,
|
||||
std::function<void()> finishedCallback)
|
||||
{
|
||||
if (index >= (keyframeContainer.size() - 1)) {
|
||||
if (index == (keyframeContainer.size() - 1)) {
|
||||
finishedCallback();
|
||||
}
|
||||
return keyframeContainer.back();
|
||||
}
|
||||
else if (index < keyframeContainer.size()) {
|
||||
return keyframeContainer[index];
|
||||
}
|
||||
else {
|
||||
return keyframeContainer.back();
|
||||
}
|
||||
}
|
||||
class KeyframeRecordingHandler : public properties::PropertyOwner {
|
||||
public:
|
||||
KeyframeRecordingHandler();
|
||||
|
||||
template <class T>
|
||||
T prevKeyframeObj(unsigned int index, const std::vector<T>& keyframeContainer) {
|
||||
if (index >= keyframeContainer.size()) {
|
||||
return keyframeContainer.back();
|
||||
}
|
||||
else if (index > 0) {
|
||||
return keyframeContainer[index - 1];
|
||||
}
|
||||
else {
|
||||
return keyframeContainer.front();
|
||||
}
|
||||
}
|
||||
void newSequence();
|
||||
void addCameraKeyframe(double sequenceTime);
|
||||
void addScriptKeyframe(double sequenceTime, std::string script);
|
||||
void removeKeyframe(int index);
|
||||
void updateKeyframe(int index);
|
||||
void moveKeyframe(int index, double sequenceTime);
|
||||
void saveSequence(std::filesystem::path filename);
|
||||
void loadSequence(std::filesystem::path filename);
|
||||
void play();
|
||||
bool hasKeyframeRecording() const;
|
||||
std::vector<ghoul::Dictionary> keyframes() const;
|
||||
|
||||
template <typename T>
|
||||
T readFromPlayback(std::ifstream& stream) {
|
||||
T res;
|
||||
stream.read(reinterpret_cast<char*>(&res), sizeof(T));
|
||||
return res;
|
||||
}
|
||||
static openspace::scripting::LuaLibrary luaLibrary();
|
||||
|
||||
template <typename T>
|
||||
T readFromPlayback(std::stringstream& stream) {
|
||||
T res;
|
||||
stream.read(reinterpret_cast<char*>(&res), sizeof(T));
|
||||
return res;
|
||||
}
|
||||
private:
|
||||
SessionRecording _timeline;
|
||||
};
|
||||
|
||||
} // namespace openspace::interaction
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_CORE___KEYFRAMERECORDINGHANDLER___H__
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -36,8 +36,8 @@ class MouseCameraStates : public CameraInteractionStates {
|
||||
public:
|
||||
MouseCameraStates(double sensitivity, double velocityScaleFactor);
|
||||
|
||||
void updateStateFromInput(const MouseInputState& mouseinputState,
|
||||
const KeyboardInputState& keyboardinputState, double deltaTime);
|
||||
void updateStateFromInput(const MouseInputState& mouseState,
|
||||
const KeyboardInputState& keyboardState, double deltaTime);
|
||||
|
||||
void setInvertMouseButton(bool value);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -25,868 +25,62 @@
|
||||
#ifndef __OPENSPACE_CORE___SESSIONRECORDING___H__
|
||||
#define __OPENSPACE_CORE___SESSIONRECORDING___H__
|
||||
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
|
||||
#include <openspace/navigation/keyframenavigator.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
#include <filesystem>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
|
||||
namespace openspace::interaction {
|
||||
|
||||
struct ConversionError : public ghoul::RuntimeError {
|
||||
explicit ConversionError(std::string msg);
|
||||
enum class DataMode {
|
||||
Ascii = 0,
|
||||
Binary
|
||||
};
|
||||
|
||||
class SessionRecording : public properties::PropertyOwner {
|
||||
public:
|
||||
struct SessionRecording {
|
||||
struct Entry {
|
||||
auto operator<=>(const SessionRecording::Entry&) const = default;
|
||||
|
||||
inline static const std::string FileHeaderTitle = "OpenSpace_record/playback";
|
||||
inline static const std::string HeaderCameraAscii = "camera";
|
||||
inline static const std::string HeaderTimeAscii = "time";
|
||||
inline static const std::string HeaderScriptAscii = "script";
|
||||
inline static const std::string HeaderCommentAscii = "#";
|
||||
inline static const char HeaderCameraBinary = 'c';
|
||||
inline static const char HeaderTimeBinary = 't';
|
||||
inline static const char HeaderScriptBinary = 's';
|
||||
inline static const std::string FileExtensionBinary = ".osrec";
|
||||
inline static const std::string FileExtensionAscii = ".osrectxt";
|
||||
using Camera = KeyframeNavigator::CameraPose;
|
||||
using Script = std::string;
|
||||
|
||||
enum class DataMode {
|
||||
Ascii = 0,
|
||||
Binary,
|
||||
Unknown
|
||||
double timestamp = 0.0;
|
||||
double simulationTime = 0.0;
|
||||
std::variant<Camera, Script> value;
|
||||
};
|
||||
|
||||
enum class SessionState {
|
||||
Idle = 0,
|
||||
Recording,
|
||||
Playback,
|
||||
PlaybackPaused
|
||||
};
|
||||
|
||||
struct Timestamps {
|
||||
double timeOs;
|
||||
double timeRec;
|
||||
double timeSim;
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct for storing a script substring that, if found in a saved script,
|
||||
* will be replaced by its substringReplacement counterpart.
|
||||
*/
|
||||
struct ScriptSubstringReplace {
|
||||
std::string substringFound;
|
||||
std::string substringReplacement;
|
||||
ScriptSubstringReplace(std::string found, std::string replace)
|
||||
: substringFound(found)
|
||||
, substringReplacement(replace) {}
|
||||
};
|
||||
|
||||
static const size_t FileHeaderVersionLength = 5;
|
||||
char FileHeaderVersion[FileHeaderVersionLength+1] = "01.00";
|
||||
char TargetConvertVersion[FileHeaderVersionLength+1] = "01.00";
|
||||
static const char DataFormatAsciiTag = 'A';
|
||||
static const char DataFormatBinaryTag = 'B';
|
||||
static const size_t keyframeHeaderSize_bytes = 33;
|
||||
static const size_t saveBufferCameraSize_min = 82;
|
||||
static const size_t saveBufferStringSize_max = 2000;
|
||||
static const size_t _saveBufferMaxSize_bytes = keyframeHeaderSize_bytes +
|
||||
+ saveBufferCameraSize_min + saveBufferStringSize_max;
|
||||
|
||||
using CallbackHandle = int;
|
||||
using StateChangeCallback = std::function<void()>;
|
||||
|
||||
SessionRecording();
|
||||
SessionRecording(bool isGlobal);
|
||||
|
||||
~SessionRecording() override;
|
||||
|
||||
/**
|
||||
* Used to de-initialize the session recording feature. Any recording or playback
|
||||
* in progress will be stopped, files closed, and keyframes in memory deleted.
|
||||
*/
|
||||
void deinitialize();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* If enabled, calling this function will render information about the session
|
||||
* recording that is currently taking place to the screen.
|
||||
*/
|
||||
void render();
|
||||
|
||||
/**
|
||||
* Current time based on playback mode
|
||||
*/
|
||||
double currentTime() 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).
|
||||
*
|
||||
* \returns 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.
|
||||
*
|
||||
* \returns 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.
|
||||
*
|
||||
* \param filename file saved with recorded keyframes.
|
||||
*
|
||||
* \returns true if recording to file starts without errors.
|
||||
*/
|
||||
bool startRecording(const std::string& filename);
|
||||
|
||||
/**
|
||||
* Starts a recording session, which will save data to the provided filename
|
||||
* in ASCII data format until recording is stopped using stopRecording() method.
|
||||
*
|
||||
* \param dataMode The format in which the session recording is stored
|
||||
*/
|
||||
void setRecordDataFormat(DataMode dataMode);
|
||||
|
||||
/**
|
||||
* Used to stop a recording in progress. If open, the recording file will be closed,
|
||||
* and all keyframes deleted from memory.
|
||||
*/
|
||||
void stopRecording();
|
||||
|
||||
/**
|
||||
* 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 filename file containing recorded keyframes to play back. The file path
|
||||
* is relative to the base recordings directory specified in the
|
||||
* config file by the RECORDINGS variable
|
||||
* \param timeMode which of the 3 time modes to use for time reference during
|
||||
* \param forceSimTimeAtStart if true simulation time is forced to that of playback
|
||||
* playback: recorded time, application time, or simulation time. See the
|
||||
* LuaLibrary entry for SessionRecording for details on these time modes
|
||||
* \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
|
||||
*
|
||||
* \return `true` if recording to file starts without errors
|
||||
*/
|
||||
bool startPlayback(std::string& filename, KeyframeTimeRef timeMode,
|
||||
bool forceSimTimeAtStart, bool loop, bool shouldWaitForFinishedTiles);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* \returns true if playback is in progress.
|
||||
*/
|
||||
bool isPlayingBack() const;
|
||||
|
||||
/**
|
||||
* 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 the camera states (position, rotation, focus node,
|
||||
* whether it is following the rotation of a node, and timestamp). The data will be
|
||||
* saved to the recording file only if a recording is currently in progress.
|
||||
*/
|
||||
void saveCameraKeyframeToTimeline();
|
||||
|
||||
/**
|
||||
* Used to trigger a save of the current timing states. The data will be saved to the
|
||||
* recording file only if a recording is currently in progress.
|
||||
*/
|
||||
void saveTimeKeyframeToTimeline();
|
||||
|
||||
/**
|
||||
* Used to trigger a save of a script to the recording file, but only if a recording
|
||||
* is currently in progress.
|
||||
*
|
||||
* \param scriptToSave String of the Lua command to be saved
|
||||
*/
|
||||
void saveScriptKeyframeToTimeline(std::string scriptToSave);
|
||||
|
||||
/**
|
||||
* \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 callback function handle for the callback
|
||||
*/
|
||||
void removeStateChangeCallback(CallbackHandle callback);
|
||||
|
||||
/**
|
||||
* Provides list of available playback files.
|
||||
*
|
||||
* \return vector of filenames in recordings dir
|
||||
*/
|
||||
std::vector<std::string> playbackList() const;
|
||||
|
||||
/**
|
||||
* Reads a camera keyframe from a binary format playback file, and populates input
|
||||
* references with the parameters of the keyframe.
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a camera keyframe which contains camera details
|
||||
* \param file an ifstream reference to the playback file being read
|
||||
* \param lineN keyframe number in playback file where this keyframe resides
|
||||
*
|
||||
* \return true if data read has no errors
|
||||
*/
|
||||
bool readCameraKeyframeBinary(Timestamps& times,
|
||||
datamessagestructures::CameraKeyframe& kf, std::ifstream& file, int lineN);
|
||||
|
||||
/**
|
||||
* Reads a camera keyframe from an ascii format playback file, and populates input
|
||||
* references with the parameters of the keyframe.
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a camera keyframe which contains camera details
|
||||
* \param currentParsingLine string containing the most current line that was read
|
||||
* \param lineN line number in playback file where this keyframe resides
|
||||
*
|
||||
* \return true if data read has no errors
|
||||
*/
|
||||
bool readCameraKeyframeAscii(Timestamps& times,
|
||||
datamessagestructures::CameraKeyframe& kf, std::string currentParsingLine,
|
||||
int lineN);
|
||||
|
||||
/**
|
||||
* Reads a time keyframe from a binary format playback file, and populates input
|
||||
* references with the parameters of the keyframe.
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a time keyframe which contains time details
|
||||
* \param file an ifstream reference to the playback file being read
|
||||
* \param lineN keyframe number in playback file where this keyframe resides
|
||||
*
|
||||
* \return true if data read has no errors
|
||||
*/
|
||||
bool readTimeKeyframeBinary(Timestamps& times,
|
||||
datamessagestructures::TimeKeyframe& kf, std::ifstream& file, int lineN);
|
||||
|
||||
/**
|
||||
* Reads a time keyframe from an ascii format playback file, and populates input
|
||||
* references with the parameters of the keyframe.
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a time keyframe which contains time details
|
||||
* \param currentParsingLine string containing the most current line that was read
|
||||
* \param lineN line number in playback file where this keyframe resides
|
||||
*
|
||||
* \return true if data read has no errors
|
||||
*/
|
||||
bool readTimeKeyframeAscii(Timestamps& times,
|
||||
datamessagestructures::TimeKeyframe& kf, std::string currentParsingLine,
|
||||
int lineN);
|
||||
|
||||
/**
|
||||
* Reads a script keyframe from a binary format playback file, and populates input
|
||||
* references with the parameters of the keyframe.
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a script keyframe which contains the size of the script
|
||||
* (in chars) and the text itself
|
||||
* \param file an ifstream reference to the playback file being read
|
||||
* \param lineN keyframe number in playback file where this keyframe resides
|
||||
*
|
||||
* \return true if data read has no errors
|
||||
*/
|
||||
bool readScriptKeyframeBinary(Timestamps& times,
|
||||
datamessagestructures::ScriptMessage& kf, std::ifstream& file, int lineN);
|
||||
|
||||
/**
|
||||
* Reads a script keyframe from an ascii format playback file, and populates input
|
||||
* references with the parameters of the keyframe.
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a script keyframe which contains the size of the script
|
||||
* (in chars) and the text itself
|
||||
* \param currentParsingLine string containing the most current line that was read
|
||||
* \param lineN line number in playback file where this keyframe resides
|
||||
*
|
||||
* \return true if data read has no errors
|
||||
*/
|
||||
bool readScriptKeyframeAscii(Timestamps& times,
|
||||
datamessagestructures::ScriptMessage& kf, std::string currentParsingLine,
|
||||
int lineN);
|
||||
|
||||
/**
|
||||
* Writes a camera keyframe to a binary format recording file using a CameraKeyframe
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a camera keyframe which contains the camera details
|
||||
* \param kfBuffer a buffer temporarily used for preparing data to be written
|
||||
* \param file an ofstream reference to the recording file being written-to
|
||||
*/
|
||||
void saveCameraKeyframeBinary(Timestamps& times,
|
||||
datamessagestructures::CameraKeyframe& kf, unsigned char* kfBuffer,
|
||||
std::ofstream& file);
|
||||
|
||||
/**
|
||||
* Writes a camera keyframe to an ascii format recording file using a CameraKeyframe
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a camera keyframe which contains the camera details
|
||||
* \param file an ofstream reference to the recording file being written-to
|
||||
*/
|
||||
void saveCameraKeyframeAscii(Timestamps& times,
|
||||
datamessagestructures::CameraKeyframe& kf, std::ofstream& file);
|
||||
|
||||
/**
|
||||
* Writes a time keyframe to a binary format recording file using a TimeKeyframe
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a time keyframe which contains the time details
|
||||
* \param kfBuffer a buffer temporarily used for preparing data to be written
|
||||
* \param file an ofstream reference to the recording file being written-to
|
||||
*/
|
||||
void saveTimeKeyframeBinary(Timestamps& times,
|
||||
datamessagestructures::TimeKeyframe& kf, unsigned char* kfBuffer,
|
||||
std::ofstream& file);
|
||||
|
||||
/**
|
||||
* Writes a time keyframe to an ascii format recording file using a TimeKeyframe
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param kf reference to a time keyframe which contains the time details
|
||||
* \param file an ofstream reference to the recording file being written-to
|
||||
*/
|
||||
void saveTimeKeyframeAscii(Timestamps& times,
|
||||
datamessagestructures::TimeKeyframe& kf, std::ofstream& file);
|
||||
|
||||
/**
|
||||
* Writes a script keyframe to a binary format recording file using a ScriptMessage
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param sm reference to a ScriptMessage object which contains the script details
|
||||
* \param smBuffer a buffer temporarily used for preparing data to be written
|
||||
* \param file an ofstream reference to the recording file being written-to
|
||||
*/
|
||||
void saveScriptKeyframeBinary(Timestamps& times,
|
||||
datamessagestructures::ScriptMessage& sm, unsigned char* smBuffer,
|
||||
std::ofstream& file);
|
||||
|
||||
/**
|
||||
* Writes a script keyframe to an ascii format recording file using a ScriptMessage
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param sm reference to a ScriptMessage which contains the script details
|
||||
* \param file an ofstream reference to the recording file being written-to
|
||||
*/
|
||||
void saveScriptKeyframeAscii(Timestamps& times,
|
||||
datamessagestructures::ScriptMessage& sm, std::ofstream& file);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* Reads header information from a session recording file
|
||||
*
|
||||
* \param stream 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::ifstream& stream, size_t readLen_chars);
|
||||
|
||||
/**
|
||||
* Reads header information from a session recording file
|
||||
*
|
||||
* \param stream 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);
|
||||
|
||||
/**
|
||||
* Writes a header to a binary recording file buffer
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param type single character signifying the keyframe type
|
||||
* \param kfBuffer the char buffer holding the recording info to be written
|
||||
* \param idx index into write buffer (this is updated with the num of chars written)
|
||||
*/
|
||||
static void saveHeaderBinary(Timestamps& times, char type, unsigned char* kfBuffer,
|
||||
size_t& idx);
|
||||
|
||||
/**
|
||||
* Writes a header to an ascii recording file buffer
|
||||
*
|
||||
* \param times reference to a timestamps structure which contains recorded times
|
||||
* \param type string signifying the keyframe type
|
||||
* \param line the stringstream buffer being written to
|
||||
*/
|
||||
static void saveHeaderAscii(Timestamps& times, const std::string& type,
|
||||
std::stringstream& line);
|
||||
|
||||
/**
|
||||
* Saves a keyframe to an ascii recording file
|
||||
*
|
||||
* \param entry the ascii string version of the keyframe (any type)
|
||||
* \param file ofstream object to write to
|
||||
*/
|
||||
static void saveKeyframeToFile(std::string entry, std::ofstream& file);
|
||||
|
||||
/**
|
||||
* Checks if a specified recording file ends with a particular file extension
|
||||
*
|
||||
* \param filename the name of the file to record to
|
||||
* \param extension the file extension to check for
|
||||
*/
|
||||
static bool hasFileExtension(std::string filename, std::string extension);
|
||||
|
||||
/**
|
||||
* Converts file format of a session recording file to the current format version
|
||||
* (will determine the file format conversion to convert from based on the file's
|
||||
* header version number).
|
||||
*
|
||||
* \param filename name of the file to convert
|
||||
* \param depth iteration number to prevent runaway recursion (init call with zero)
|
||||
*
|
||||
* \return string containing the filename of the previous conversion step. This is
|
||||
* used if there are multiple conversion steps where each step has to use
|
||||
* the output of the previous.
|
||||
*/
|
||||
std::string convertFile(std::string filename, int depth = 0);
|
||||
|
||||
/**
|
||||
* Converts file format of a session recording file to the current format version
|
||||
* (will determine the file format conversion to convert from based on the file's
|
||||
* header version number). Accepts a relative path (currently from task runner dir)
|
||||
* rather than a path assumed to be relative to ${RECORDINGS}.
|
||||
*
|
||||
* \param filenameRelative name of the file to convert
|
||||
*/
|
||||
void convertFileRelativePath(std::string filenameRelative);
|
||||
|
||||
/**
|
||||
* Goes to legacy session recording inherited class, and calls its convertFile()
|
||||
* method, and then returns the resulting conversion filename.
|
||||
*
|
||||
* \param filename name of the file to convert
|
||||
* \param depth iteration number to prevent runaway recursion (init call with zero)
|
||||
*
|
||||
* \return string containing the filename of the conversion
|
||||
*/
|
||||
virtual std::string getLegacyConversionResult(std::string filename, int depth);
|
||||
|
||||
/*
|
||||
* Version string for file format version currently supported by this class
|
||||
*
|
||||
* \return string of the file format version this class supports
|
||||
*/
|
||||
virtual std::string fileFormatVersion();
|
||||
|
||||
/*
|
||||
* Version string for file format version that a conversion operation will convert
|
||||
* to (e.g. upgrades to this version). This is only relevant for inherited classes
|
||||
* that support conversion from legacy versions (if called in the base class, it
|
||||
* will return its own current version).
|
||||
*
|
||||
* \return string of the file format version this class supports
|
||||
*/
|
||||
virtual std::string targetFileFormatVersion();
|
||||
|
||||
/*
|
||||
* Determines a filename for the conversion result based on the original filename
|
||||
* and the file format version number.
|
||||
*
|
||||
* \param filename source filename to be converted
|
||||
*
|
||||
* \return pathname of the converted version of the file
|
||||
*/
|
||||
std::string determineConversionOutFilename(const std::string filename, DataMode mode);
|
||||
|
||||
protected:
|
||||
properties::BoolProperty _renderPlaybackInformation;
|
||||
properties::BoolProperty _ignoreRecordedScale;
|
||||
|
||||
enum class RecordedType {
|
||||
Camera = 0,
|
||||
Time,
|
||||
Script,
|
||||
Invalid
|
||||
};
|
||||
struct TimelineEntry {
|
||||
RecordedType keyframeType;
|
||||
unsigned int idxIntoKeyframeTypeArray;
|
||||
Timestamps t3stamps;
|
||||
};
|
||||
double _timestampRecordStarted = 0.0;
|
||||
Timestamps _timestamps3RecordStarted{ 0.0, 0.0, 0.0 };
|
||||
double _timestampPlaybackStarted_application = 0.0;
|
||||
double _timestampPlaybackStarted_simulation = 0.0;
|
||||
double _timestampApplicationStarted_simulation = 0.0;
|
||||
bool hasCameraChangedFromPrev(datamessagestructures::CameraKeyframe kfNew);
|
||||
double appropriateTimestamp(Timestamps t3stamps);
|
||||
double equivalentSimulationTime(double timeOs, double timeRec, double timeSim);
|
||||
double equivalentApplicationTime(double timeOs, double timeRec, double timeSim);
|
||||
void recordCurrentTimePauseState();
|
||||
void recordCurrentTimeRate();
|
||||
bool handleRecordingFile(std::string filenameIn);
|
||||
static bool isPath(std::string& filename);
|
||||
void removeTrailingPathSlashes(std::string& filename);
|
||||
bool playbackCamera();
|
||||
bool playbackTimeChange();
|
||||
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,
|
||||
size_t& idx, std::ofstream& file);
|
||||
static void saveKeyframeToFileBinary(unsigned char* bufferSource, size_t size,
|
||||
std::ofstream& file);
|
||||
|
||||
bool addKeyframe(Timestamps t3stamps,
|
||||
interaction::KeyframeNavigator::CameraPose keyframe, int lineNum);
|
||||
bool addKeyframe(Timestamps t3stamps,
|
||||
datamessagestructures::TimeKeyframe keyframe, int lineNum);
|
||||
bool addKeyframe(Timestamps t3stamps,
|
||||
std::string scriptToQueue, int lineNum);
|
||||
bool addKeyframeToTimeline(std::vector<TimelineEntry>& timeline, RecordedType type,
|
||||
size_t indexIntoTypeKeyframes, Timestamps t3stamps, int lineNum);
|
||||
|
||||
void initializePlayback_time(double now);
|
||||
void initializePlayback_modeFlags();
|
||||
bool initializePlayback_timeline();
|
||||
void initializePlayback_triggerStart();
|
||||
void moveAheadInTime();
|
||||
void lookForNonCameraKeyframesThatHaveComeDue(double currTime);
|
||||
void updateCameraWithOrWithoutNewKeyframes(double currTime);
|
||||
bool isTimeToHandleNextNonCameraKeyframe(double currTime);
|
||||
bool processNextNonCameraKeyframeAheadInTime();
|
||||
bool findNextFutureCameraIndex(double currTime);
|
||||
bool processCameraKeyframe(double now);
|
||||
bool processScriptKeyframe();
|
||||
bool readSingleKeyframeCamera(datamessagestructures::CameraKeyframe& kf,
|
||||
Timestamps& times, DataMode mode, std::ifstream& file,
|
||||
std::string& inLine, const int lineNum);
|
||||
void saveSingleKeyframeCamera(datamessagestructures::CameraKeyframe& kf,
|
||||
Timestamps& times, DataMode mode, std::ofstream& file, unsigned char* buffer);
|
||||
bool readSingleKeyframeTime(datamessagestructures::TimeKeyframe& kf,
|
||||
Timestamps& times, DataMode mode, std::ifstream& file, std::string& inLine,
|
||||
const int lineNum);
|
||||
void saveSingleKeyframeTime(datamessagestructures::TimeKeyframe& kf,
|
||||
Timestamps& times, DataMode mode, std::ofstream& file, unsigned char* buffer);
|
||||
bool readSingleKeyframeScript(datamessagestructures::ScriptMessage& kf,
|
||||
Timestamps& times, DataMode mode, std::ifstream& file, std::string& inLine,
|
||||
const int lineNum);
|
||||
void saveSingleKeyframeScript(datamessagestructures::ScriptMessage& kf,
|
||||
Timestamps& times, DataMode mode, std::ofstream& file, unsigned char* buffer);
|
||||
void saveScriptKeyframeToPropertiesBaseline(std::string script);
|
||||
bool isPropertyAllowedForBaseline(const std::string& propString);
|
||||
unsigned int findIndexOfLastCameraKeyframeInTimeline();
|
||||
bool doesTimelineEntryContainCamera(unsigned int index) const;
|
||||
bool doesStartWithSubstring(const std::string& s, const std::string& matchSubstr);
|
||||
void trimCommandsFromScriptIfFound(std::string& script);
|
||||
void replaceCommandsFromScriptIfFound(std::string& script);
|
||||
|
||||
RecordedType getNextKeyframeType();
|
||||
RecordedType getPrevKeyframeType();
|
||||
double getNextTimestamp();
|
||||
double getPrevTimestamp();
|
||||
void cleanUpPlayback();
|
||||
void cleanUpRecording();
|
||||
void cleanUpTimelinesAndKeyframes();
|
||||
bool convertEntries(std::string& inFilename, std::stringstream& inStream,
|
||||
DataMode mode, int lineNum, std::ofstream& outFile);
|
||||
virtual bool convertCamera(std::stringstream& inStream, DataMode mode, int lineNum,
|
||||
std::string& inputLine, std::ofstream& outFile, unsigned char* buff);
|
||||
virtual bool convertTimeChange(std::stringstream& inStream, DataMode mode,
|
||||
int lineNum, std::string& inputLine, std::ofstream& outFile, unsigned char* buff);
|
||||
virtual bool convertScript(std::stringstream& inStream, DataMode mode, int lineNum,
|
||||
std::string& inputLine, std::ofstream& outFile, unsigned char* buff);
|
||||
DataMode readModeFromHeader(std::string filename);
|
||||
void readPlaybackHeader_stream(std::stringstream& conversionInStream,
|
||||
std::string& version, DataMode& mode);
|
||||
void populateListofLoadedSceneGraphNodes();
|
||||
|
||||
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);
|
||||
|
||||
static void writeToFileBuffer(unsigned char* buf, size_t& idx, double src);
|
||||
static void writeToFileBuffer(unsigned char* buf, size_t& idx, std::vector<char>& cv);
|
||||
static void writeToFileBuffer(unsigned char* buf, size_t& idx, unsigned char c);
|
||||
static void writeToFileBuffer(unsigned char* buf, size_t& idx, bool b);
|
||||
void readFileIntoStringStream(std::string filename,
|
||||
std::ifstream& inputFstream, std::stringstream& stream);
|
||||
|
||||
DataMode _recordingDataMode = DataMode::Binary;
|
||||
SessionState _state = SessionState::Idle;
|
||||
SessionState _lastState = SessionState::Idle;
|
||||
std::string _playbackFilename;
|
||||
std::ifstream _playbackFile;
|
||||
std::string _playbackLineParsing;
|
||||
std::ofstream _recordFile;
|
||||
int _playbackLineNum = 1;
|
||||
int _recordingEntryNum = 1;
|
||||
KeyframeTimeRef _playbackTimeReferenceMode;
|
||||
datamessagestructures::CameraKeyframe _prevRecordedCameraKeyframe;
|
||||
bool _playbackActive_camera = false;
|
||||
bool _playbackActive_time = false;
|
||||
bool _playbackActive_script = false;
|
||||
bool _hasHitEndOfCameraKeyframes = false;
|
||||
bool _playbackPausedWithinDeltaTimePause = false;
|
||||
bool _playbackLoopMode = false;
|
||||
bool _playbackForceSimTimeAtStart = false;
|
||||
double _playbackPauseOffset = 0.0;
|
||||
double _previousTime = 0.0;
|
||||
|
||||
bool _saveRenderingDuringPlayback = false;
|
||||
double _saveRenderingDeltaTime = 1.0 / 30.0;
|
||||
double _saveRenderingCurrentRecordedTime = 0.0;
|
||||
bool _shouldWaitForFinishLoadingWhenPlayback = false;
|
||||
std::chrono::steady_clock::duration _saveRenderingDeltaTime_interpolation_usec;
|
||||
std::chrono::steady_clock::time_point _saveRenderingCurrentRecordedTime_interpolation;
|
||||
double _saveRenderingCurrentApplicationTime_interpolation = 0.0;
|
||||
long long _saveRenderingClockInterpolation_countsPerSec = 1;
|
||||
bool _saveRendering_isFirstFrame = true;
|
||||
|
||||
unsigned char _keyframeBuffer[_saveBufferMaxSize_bytes];
|
||||
|
||||
bool _cleanupNeededRecording = false;
|
||||
bool _cleanupNeededPlayback = false;
|
||||
const std::string scriptReturnPrefix = "return ";
|
||||
|
||||
std::vector<interaction::KeyframeNavigator::CameraPose> _keyframesCamera;
|
||||
std::vector<datamessagestructures::TimeKeyframe> _keyframesTime;
|
||||
std::vector<std::string> _keyframesScript;
|
||||
std::vector<TimelineEntry> _timeline;
|
||||
|
||||
std::vector<std::string> _keyframesSavePropertiesBaseline_scripts;
|
||||
std::vector<TimelineEntry> _keyframesSavePropertiesBaseline_timeline;
|
||||
std::vector<std::string> _propertyBaselinesSaved;
|
||||
const std::vector<std::string> _propertyBaselineRejects = {
|
||||
"NavigationHandler.OrbitalNavigator.Anchor",
|
||||
"NavigationHandler.OrbitalNavigator.Aim",
|
||||
"NavigationHandler.OrbitalNavigator.RetargetAnchor",
|
||||
"NavigationHandler.OrbitalNavigator.RetargetAim"
|
||||
};
|
||||
//A script that begins with an exact match of any of the strings contained in
|
||||
// _scriptRejects will not be recorded
|
||||
const std::vector<std::string> _scriptRejects = {
|
||||
"openspace.sessionRecording.enableTakeScreenShotDuringPlayback",
|
||||
"openspace.sessionRecording.startPlayback",
|
||||
"openspace.sessionRecording.stopPlayback",
|
||||
"openspace.sessionRecording.startRecording",
|
||||
"openspace.sessionRecording.stopRecording",
|
||||
"openspace.scriptScheduler.clear"
|
||||
};
|
||||
const std::vector<std::string> _navScriptsUsingNodes = {
|
||||
"RetargetAnchor",
|
||||
"Anchor",
|
||||
"Aim"
|
||||
};
|
||||
//Any script snippet included in this vector will be trimmed from any script
|
||||
// from the script manager, before it is recorded in the session recording file.
|
||||
// The remainder of the script will be retained.
|
||||
const std::vector<std::string> _scriptsToBeTrimmed = {
|
||||
"openspace.sessionRecording.togglePlaybackPause"
|
||||
};
|
||||
//Any script snippet included in this vector will be trimmed from any script
|
||||
// from the script manager, before it is recorded in the session recording file.
|
||||
// The remainder of the script will be retained.
|
||||
const std::vector<ScriptSubstringReplace> _scriptsToBeReplaced = {
|
||||
{
|
||||
"openspace.time.pauseToggleViaKeyboard",
|
||||
"openspace.time.interpolateTogglePause"
|
||||
}
|
||||
};
|
||||
std::vector<std::string> _loadedNodes;
|
||||
|
||||
unsigned int _idxTimeline_nonCamera = 0;
|
||||
unsigned int _idxTime = 0;
|
||||
unsigned int _idxScript = 0;
|
||||
|
||||
unsigned int _idxTimeline_cameraPtrNext = 0;
|
||||
unsigned int _idxTimeline_cameraPtrPrev = 0;
|
||||
|
||||
unsigned int _idxTimeline_cameraFirstInTimeline = 0;
|
||||
double _cameraFirstInTimeline_timestamp = 0;
|
||||
|
||||
int _nextCallbackHandle = 0;
|
||||
std::vector<std::pair<CallbackHandle, StateChangeCallback>> _stateChangeCallbacks;
|
||||
|
||||
DataMode _conversionDataMode = DataMode::Binary;
|
||||
int _conversionLineNum = 1;
|
||||
const int _maximumRecursionDepth = 50;
|
||||
};
|
||||
|
||||
// Instructions for bumping the file format version with new changes:
|
||||
//
|
||||
// 1. Create a new subclass with the current version # in its name, such as:
|
||||
// SessionRecording_legacy_####, which inherits from SessionRecording
|
||||
// 2. Override any method that changes in the new version. This includes both
|
||||
// methods in SessionRecording class and structs in
|
||||
// openspace::datamessagestructure that do data read/writes. Make the modified
|
||||
// method/struct virtual, and override it in the new legacy subclass. This
|
||||
// override will contain the code as it is before the new changes. This will
|
||||
// need to be done in every legacy subclass/struct that exists, but only if that
|
||||
// subclass does NOT already contain an override of that method/struct.
|
||||
// 3. Override FileHeaderVersion with the version # of the new subclass (which is
|
||||
// the version being replaced by the new changes).
|
||||
// 4. Override TargetConvertVersion with the version # with the new changes. This
|
||||
// is now the version that this legacy subclass converts up to.
|
||||
// 5. Override getLegacyConversionResult method so that it creates an instance of
|
||||
// the new version subclass. This is how the current version looks back to the
|
||||
// legacy version that preceded it.
|
||||
// 6. The convert method for frame types that changed will need to be changed
|
||||
// (for example SessionRecording_legacy_0085::convertScript uses its own
|
||||
// override of script keyframe for the conversion functionality).
|
||||
|
||||
class SessionRecording_legacy_0085 : public SessionRecording {
|
||||
public:
|
||||
SessionRecording_legacy_0085() : SessionRecording() {}
|
||||
~SessionRecording_legacy_0085() override {}
|
||||
char FileHeaderVersion[FileHeaderVersionLength+1] = "00.85";
|
||||
char TargetConvertVersion[FileHeaderVersionLength+1] = "01.00";
|
||||
std::string fileFormatVersion() override {
|
||||
return std::string(FileHeaderVersion);
|
||||
}
|
||||
std::string targetFileFormatVersion() override {
|
||||
return std::string(TargetConvertVersion);
|
||||
}
|
||||
std::string getLegacyConversionResult(std::string filename, int depth) override;
|
||||
|
||||
struct ScriptMessage_legacy_0085 : public datamessagestructures::ScriptMessage {
|
||||
void read(std::istream* in) override {
|
||||
size_t strLen;
|
||||
//Read string length from file
|
||||
in->read(reinterpret_cast<char*>(&strLen), sizeof(strLen));
|
||||
if (strLen > saveBufferStringSize_max) {
|
||||
throw ConversionError("Invalid script size for conversion read");
|
||||
auto operator<=>(const SessionRecording&) const = default;
|
||||
|
||||
std::vector<Entry> entries;
|
||||
|
||||
bool hasCameraFrame() const noexcept;
|
||||
|
||||
// Call the provided \p function for all entries of the specified type \tparam T. The
|
||||
// function calls will be ordered by the entries timestamps. If the callback function
|
||||
// returns `true`, the loop is aborted
|
||||
template <typename T>
|
||||
void forAll(std::function<bool (const T&)> function) {
|
||||
for (const Entry& e : entries) {
|
||||
if (std::holds_alternative<T>(e.value)) {
|
||||
bool cont = function(std::get<T>(e.value));
|
||||
if (cont) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
//Read back full string
|
||||
std::vector<char> temp(strLen + 1);
|
||||
in->read(temp.data(), strLen);
|
||||
temp[strLen] = '\0';
|
||||
|
||||
_script.erase();
|
||||
_script = temp.data();
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
bool convertScript(std::stringstream& inStream, DataMode mode, int lineNum,
|
||||
std::string& inputLine, std::ofstream& outFile, unsigned char* buffer) override;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
SessionRecording loadSessionRecording(const std::filesystem::path& filename);
|
||||
void saveSessionRecording(const std::filesystem::path& filename,
|
||||
const SessionRecording& sessionRecording, DataMode dataMode);
|
||||
|
||||
#include "sessionrecording.inl"
|
||||
std::vector<ghoul::Dictionary> sessionRecordingToDictionary(
|
||||
const SessionRecording& recording);
|
||||
|
||||
} // namespace openspace::interaction
|
||||
|
||||
#endif // __OPENSPACE_CORE___SESSIONRECORDING___H__
|
||||
|
||||
288
include/openspace/interaction/sessionrecordinghandler.h
Normal file
288
include/openspace/interaction/sessionrecordinghandler.h
Normal file
@@ -0,0 +1,288 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* 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.
|
||||
*
|
||||
* \return `true` if recording to file starts without errors
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* 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 filename File containing recorded keyframes to play back. The file path is
|
||||
* relative to the base recordings directory specified in the config
|
||||
* file by the RECORDINGS variable
|
||||
* \param timeMode Which of the 3 time modes to use for time reference during
|
||||
* \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
|
||||
*/
|
||||
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 callback 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 s) 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__
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -26,7 +26,7 @@
|
||||
#define __OPENSPACE_CORE___CONVERTRECFORMATTASK___H__
|
||||
|
||||
#include <openspace/util/task.h>
|
||||
#include <openspace/interaction/sessionrecording.h>
|
||||
#include <openspace/interaction/sessionrecordinghandler.h>
|
||||
|
||||
#include <ghoul/glm.h>
|
||||
#include <filesystem>
|
||||
@@ -41,26 +41,15 @@ public:
|
||||
ToBinary
|
||||
};
|
||||
ConvertRecFormatTask(const ghoul::Dictionary& dictionary);
|
||||
~ConvertRecFormatTask() override;
|
||||
~ConvertRecFormatTask() override = default;
|
||||
std::string description() override;
|
||||
void perform(const Task::ProgressCallback& progressCallback) override;
|
||||
static documentation::Documentation documentation();
|
||||
void convert();
|
||||
|
||||
private:
|
||||
void convertToAscii();
|
||||
void convertToBinary();
|
||||
void determineFormatType();
|
||||
std::string addFileSuffix(const std::string& filePath, const std::string& suffix);
|
||||
std::filesystem::path _inFilePath;
|
||||
std::filesystem::path _outFilePath;
|
||||
std::ifstream _iFile;
|
||||
std::ofstream _oFile;
|
||||
SessionRecording::DataMode _fileFormatType;
|
||||
std::string _version;
|
||||
|
||||
std::string _valueFunctionLua;
|
||||
SessionRecording* sessRec;
|
||||
DataMode _dataMode;
|
||||
};
|
||||
|
||||
} // namespace openspace::interaction
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -37,7 +37,7 @@ namespace openspace::interaction {
|
||||
|
||||
/**
|
||||
* Actions that any button of a websocket can have. Each button must be in one of these
|
||||
* states
|
||||
* states.
|
||||
*/
|
||||
enum class WebsocketAction : uint8_t {
|
||||
/// Idle state if the button is unpressed and has been unpressed since last frame
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -51,8 +51,8 @@ struct Milestone {
|
||||
* phases within phases. Designed for WORM usage (Write Once, Read Multiple), and,
|
||||
* therefore, has only accessors.
|
||||
*
|
||||
* Each MissionPhase is characterized by its MissionPhase::name, a TimeRange, an
|
||||
* optional MissionPhase::description, and optional subphases.
|
||||
* Each MissionPhase is characterized by its MissionPhase::name, a TimeRange, an optional
|
||||
* MissionPhase::description, and optional subphases.
|
||||
*/
|
||||
class MissionPhase {
|
||||
public:
|
||||
@@ -147,6 +147,7 @@ public:
|
||||
/**
|
||||
* Returns the Documentation that describes the ghoul::Dictionarty that this
|
||||
* MissionPhase can be constructed from.
|
||||
*
|
||||
* \return The Documentation that describes the required structure for a Dictionary
|
||||
*/
|
||||
static documentation::Documentation Documentation();
|
||||
@@ -161,7 +162,7 @@ protected:
|
||||
* \param trace The list of MissionPhase%s that are active during the time \p time
|
||||
* \param maxDepth The maximum depth of levels that will be considered
|
||||
*
|
||||
* \pre maxDepth must not be negative
|
||||
* \pre \p maxDepth must not be negative
|
||||
*/
|
||||
void phaseTrace(double time, Trace& trace, int maxDepth) const;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -48,15 +48,11 @@ public:
|
||||
MissionManager();
|
||||
|
||||
/**
|
||||
* Reads a mission from file and maps the mission name to the Mission object. If
|
||||
* this is the first mission to be loaded, the mission will also be set as the
|
||||
* current active mission.
|
||||
* Loads the provided mission. If this is the first mission to be loaded, the mission
|
||||
* will also be set as the current active mission.
|
||||
*
|
||||
* \param filename The file that contains the mission that is to be loaded
|
||||
* \param mission The file that contains the mission that is to be loaded
|
||||
* \return The name of the mission that was loaded
|
||||
* \pre \p filename must not be empty
|
||||
* \pre \p filename must not contain tokens
|
||||
* \pre \p filename must exist
|
||||
*/
|
||||
std::string loadMission(Mission mission);
|
||||
|
||||
@@ -64,7 +60,7 @@ public:
|
||||
* Unloads a previously loaded mission identified by the provided \p missionName.
|
||||
*
|
||||
* \param missionName The name of the mission that should be unloded
|
||||
* \pre \p filename must not be empty
|
||||
*
|
||||
* \pre \p missionName must be a valid mission that has previously been loaded
|
||||
*/
|
||||
void unloadMission(const std::string& missionName);
|
||||
@@ -82,18 +78,18 @@ public:
|
||||
* Sets the mission with the name \p missionName as the current mission. The current
|
||||
* mission is what is return by `currentMission()`.
|
||||
*
|
||||
* \pre missionName must not be empty
|
||||
* \pre \p missionName must not be empty
|
||||
*/
|
||||
void setCurrentMission(const std::string& missionName);
|
||||
|
||||
/**
|
||||
* Returns true if a current mission exists
|
||||
* Returns true if a current mission exists.
|
||||
*/
|
||||
bool hasCurrentMission() const;
|
||||
|
||||
/**
|
||||
* Returns the latest mission specified to `setCurrentMission()`. If no mission has
|
||||
* been specified, the first mission loaded will be returned. If no mission has been
|
||||
* Returns the latest mission specified to #setCurrentMission. If no mission has been
|
||||
* specified, the first mission loaded will be returned. If no mission has been
|
||||
* loaded, a warning will be printed and a dummy mission will be returned.
|
||||
*/
|
||||
const Mission& currentMission();
|
||||
@@ -103,7 +99,6 @@ public:
|
||||
*/
|
||||
const std::map<std::string, Mission>& missionMap();
|
||||
|
||||
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
private:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -57,19 +57,21 @@ public:
|
||||
|
||||
CameraPose() = default;
|
||||
CameraPose(datamessagestructures::CameraKeyframe&& kf);
|
||||
auto operator<=>(const CameraPose&) const = default;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update camera position using the next camera pose keyframe from the timeline.
|
||||
* Returns true if camera was set to a pose from the next keyframe.
|
||||
* Returns false if no keyframes are available after the current time.
|
||||
* \param camera A reference to the camera object to have its pose updated.
|
||||
* \param ignoreFutureKeyframes true if only past keyframes are to be used.
|
||||
* \returns true only if a new future keyframe is available to set camera pose.
|
||||
*/
|
||||
bool updateCamera(Camera& camera, bool ignoreFutureKeyframes);
|
||||
static bool updateCamera(Camera* camera, const CameraPose prevPose,
|
||||
const CameraPose nextPose, double t, bool ignoreFutureKeyframes);
|
||||
* Update camera position using the next camera pose keyframe from the timeline.
|
||||
* Returns true if camera was set to a pose from the next keyframe. Returns false if
|
||||
* no keyframes are available after the current time.
|
||||
*
|
||||
* \param camera A reference to the camera object to have its pose updated
|
||||
* \param ignoreFutureKeyframes `true` if only past keyframes are to be used
|
||||
* \return true only if a new future keyframe is available to set camera pose
|
||||
*/
|
||||
void updateCamera(Camera& camera, bool ignoreFutureKeyframes);
|
||||
static void updateCamera(Camera* camera, const CameraPose& prevPose,
|
||||
const CameraPose& nextPose, double t, bool ignoreFutureKeyframes);
|
||||
|
||||
Timeline<CameraPose>& timeline();
|
||||
void addKeyframe(double timestamp, KeyframeNavigator::CameraPose pose);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -85,7 +85,9 @@ public:
|
||||
OrbitalNavigator& orbitalNavigator();
|
||||
KeyframeNavigator& keyframeNavigator();
|
||||
PathNavigator& pathNavigator();
|
||||
|
||||
bool isKeyFrameInteractionEnabled() const;
|
||||
float jumpToFadeDuration() const;
|
||||
float interpolationTime() const;
|
||||
|
||||
// Callback functions
|
||||
@@ -143,15 +145,15 @@ public:
|
||||
NavigationState navigationState(const SceneGraphNode& referenceFrame) const;
|
||||
|
||||
void saveNavigationState(const std::filesystem::path& filepath,
|
||||
const std::string& referenceFrameIdentifier);
|
||||
const std::string& referenceFrameIdentifier) const;
|
||||
|
||||
void loadNavigationState(const std::string& filepath);
|
||||
void loadNavigationState(const std::string& filepath, bool useTimeStamp);
|
||||
|
||||
/**
|
||||
* Set camera state from a provided navigation state next frame. The actual position
|
||||
* will computed from the scene in the same frame as it is set.
|
||||
*
|
||||
* \param state the navigation state to compute a camera positon from
|
||||
* \param state The navigation state to compute a camera positon from
|
||||
*/
|
||||
void setNavigationStateNextFrame(const NavigationState& state);
|
||||
|
||||
@@ -161,14 +163,26 @@ public:
|
||||
* node info. The actual position will computed from the scene in the same frame as
|
||||
* it is set.
|
||||
*
|
||||
* \param spec the node specification from which to compute the resulting camera pose
|
||||
* \param spec The node specification from which to compute the resulting camera pose
|
||||
*/
|
||||
void setCameraFromNodeSpecNextFrame(NodeCameraStateSpec spec);
|
||||
|
||||
/**
|
||||
* \return The Lua library that contains all Lua functions available to affect the
|
||||
* interaction
|
||||
*/
|
||||
* Trigger a transition script after first fading out the rendering, and fading in
|
||||
* the rendering when the script is finished. One example use case could be to fade
|
||||
* out, move the camera to another focus node, and then fade in
|
||||
*
|
||||
* \param transitionScript The Lua script to handle the transition. Can be anything
|
||||
* \param fadeDuration An optional duration for the fading. If unspecified, use the
|
||||
* JumpToFadeDuration property
|
||||
*/
|
||||
void triggerFadeToTransition(const std::string& transitionScript,
|
||||
std::optional<float> fadeDuration = std::nullopt);
|
||||
|
||||
/**
|
||||
* \return The Lua library that contains all Lua functions available to affect the
|
||||
* interaction
|
||||
*/
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
private:
|
||||
@@ -181,9 +195,9 @@ private:
|
||||
Camera* _camera = nullptr;
|
||||
std::function<void()> _playbackEndCallback;
|
||||
|
||||
static constexpr double InteractionHystersis = 0.0125;
|
||||
bool _inAnchorApproachSphere = false;
|
||||
bool _inAnchorReachSphere = false;
|
||||
const SceneGraphNode* _lastAnchor = nullptr;
|
||||
|
||||
OrbitalNavigator _orbitalNavigator;
|
||||
KeyframeNavigator _keyframeNavigator;
|
||||
@@ -195,6 +209,7 @@ private:
|
||||
properties::BoolProperty _disableMouseInputs;
|
||||
properties::BoolProperty _disableJoystickInputs;
|
||||
properties::BoolProperty _useKeyFrameInteraction;
|
||||
properties::FloatProperty _jumpToFadeDuration;
|
||||
};
|
||||
|
||||
} // namespace openspace::interaction
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -26,6 +26,7 @@
|
||||
#define __OPENSPACE_CORE___NAVIGATIONSTATE___H__
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/json.h>
|
||||
#include <optional>
|
||||
|
||||
namespace openspace {
|
||||
@@ -37,12 +38,15 @@ namespace openspace::interaction {
|
||||
struct NavigationState {
|
||||
NavigationState() = default;
|
||||
explicit NavigationState(const ghoul::Dictionary& dictionary);
|
||||
explicit NavigationState(const nlohmann::json& json);
|
||||
NavigationState(std::string anchor, std::string aim, std::string referenceFrame,
|
||||
glm::dvec3 position, std::optional<glm::dvec3> up = std::nullopt,
|
||||
double yaw = 0.0, double pitch = 0.0);
|
||||
double yaw = 0.0, double pitch = 0.0,
|
||||
std::optional<double> timestamp = std::nullopt);
|
||||
|
||||
CameraPose cameraPose() const;
|
||||
ghoul::Dictionary dictionary() const;
|
||||
nlohmann::json toJson() const;
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
std::string anchor;
|
||||
@@ -52,6 +56,8 @@ struct NavigationState {
|
||||
std::optional<glm::dvec3> up;
|
||||
double yaw = 0.0;
|
||||
double pitch = 0.0;
|
||||
|
||||
std::optional<double> timestamp;
|
||||
};
|
||||
|
||||
} // namespace openspace::interaction
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -37,16 +37,16 @@
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <openspace/properties/scalar/doubleproperty.h>
|
||||
#include <openspace/properties/triggerproperty.h>
|
||||
#include <openspace/util/syncdata.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <optional>
|
||||
|
||||
namespace openspace {
|
||||
class SceneGraphNode;
|
||||
class Camera;
|
||||
struct CameraPose;
|
||||
class SceneGraphNode;
|
||||
struct SurfacePositionHandle;
|
||||
} // namespace
|
||||
|
||||
@@ -88,10 +88,10 @@ public:
|
||||
void updateCameraScalingFromAnchor(double deltaTime);
|
||||
void resetVelocities();
|
||||
|
||||
/*
|
||||
/**
|
||||
* This function should be called on every camera interaction: for example when
|
||||
* navigating using an input device, changing the focus node or starting a path or
|
||||
* a session recording playback
|
||||
* navigating using an input device, changing the focus node or starting a path or a
|
||||
* session recording playback
|
||||
*/
|
||||
void updateOnCameraInteraction();
|
||||
|
||||
@@ -144,16 +144,18 @@ public:
|
||||
glm::quat anchorNodeToCameraRotation() const;
|
||||
|
||||
/**
|
||||
* Compute a camera position that pushed the camera position to
|
||||
* a valid position over the anchor node, accounting for the
|
||||
* minimal allowed distance
|
||||
* Compute a camera position that pushed the camera position to a valid position over
|
||||
* the anchor node, accounting for the minimal allowed distance
|
||||
*/
|
||||
glm::dvec3 pushToSurfaceOfAnchor(const glm::dvec3& cameraPosition) const;
|
||||
|
||||
void updateAnchor();
|
||||
std::vector<Syncable*> syncables();
|
||||
|
||||
/**
|
||||
* \return the Lua library that contains all Lua functions available to affect the
|
||||
* OrbitalNavigator
|
||||
*/
|
||||
* \return The Lua library that contains all Lua functions available to affect the
|
||||
* OrbitalNavigator
|
||||
*/
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
private:
|
||||
@@ -185,12 +187,11 @@ private:
|
||||
|
||||
Friction _friction;
|
||||
|
||||
// Anchor: Node to follow and orbit
|
||||
/// Anchor: Node to follow and orbit
|
||||
properties::StringProperty _anchor;
|
||||
|
||||
// Aim: Node to look at (when camera direction is reset),
|
||||
// Empty string means same as anchor.
|
||||
// If these are the same node we call it the `focus` node
|
||||
/// Aim: Node to look at (when camera direction is reset), empty string means same as
|
||||
/// anchor. If these are the same node we call it the `focus` node
|
||||
properties::StringProperty _aim;
|
||||
|
||||
// Reset camera direction to the anchor node.
|
||||
@@ -214,6 +215,9 @@ private:
|
||||
|
||||
LimitZoom _limitZoom;
|
||||
|
||||
properties::BoolProperty _disableZoom;
|
||||
properties::BoolProperty _disableRoll;
|
||||
|
||||
properties::FloatProperty _mouseSensitivity;
|
||||
properties::FloatProperty _joystickSensitivity;
|
||||
properties::FloatProperty _websocketSensitivity;
|
||||
@@ -230,11 +234,21 @@ private:
|
||||
|
||||
properties::BoolProperty _invertMouseButtons;
|
||||
|
||||
properties::BoolProperty _shouldRotateAroundUp;
|
||||
|
||||
enum class UpDirectionChoice {
|
||||
XAxis = 0,
|
||||
YAxis,
|
||||
ZAxis
|
||||
};
|
||||
properties::OptionProperty _upToUseForRotation;
|
||||
|
||||
MouseCameraStates _mouseStates;
|
||||
JoystickCameraStates _joystickStates;
|
||||
WebsocketCameraStates _websocketStates;
|
||||
ScriptCameraStates _scriptStates;
|
||||
|
||||
SyncData<std::string> _syncedAnchorNode;
|
||||
const SceneGraphNode* _anchorNode = nullptr;
|
||||
const SceneGraphNode* _aimNode = nullptr;
|
||||
|
||||
@@ -265,92 +279,107 @@ private:
|
||||
* from the global to the current total rotation so that
|
||||
* `cameraRotation = globalRotation * localRotation`.
|
||||
*/
|
||||
CameraRotationDecomposition decomposeCameraRotationSurface(const CameraPose pose,
|
||||
const SceneGraphNode& reference);
|
||||
CameraRotationDecomposition decomposeCameraRotationSurface(
|
||||
const CameraPose& cameraPose, const SceneGraphNode& reference);
|
||||
|
||||
/**
|
||||
* Decomposes the camera's rotation in to a global and a local rotation defined by
|
||||
* CameraRotationDecomposition. The global rotation defines the rotation so that the
|
||||
* camera points towards the reference position.
|
||||
*
|
||||
* The local rotation defines the differential from the global to the current total
|
||||
* rotation so that `cameraRotation = globalRotation * localRotation`.
|
||||
*/
|
||||
CameraRotationDecomposition decomposeCameraRotation(const CameraPose pose,
|
||||
glm::dvec3 reference);
|
||||
CameraRotationDecomposition decomposeCameraRotation(const CameraPose& cameraPose,
|
||||
const glm::dvec3& reference);
|
||||
|
||||
/**
|
||||
* Composes a pair of global and local rotations into a quaternion that can be used
|
||||
* as the world rotation for a camera.
|
||||
* Composes a pair of global and local rotations into a quaternion that can be used as
|
||||
* the world rotation for a camera.
|
||||
*/
|
||||
glm::dquat composeCameraRotation(const CameraRotationDecomposition& composition);
|
||||
glm::dquat composeCameraRotation(
|
||||
const CameraRotationDecomposition& decomposition) const;
|
||||
|
||||
/*
|
||||
* Moves and rotates the camera around the anchor node in order to maintain the
|
||||
* screen space position of the aim node. Also interpolates to the aim node, when
|
||||
* retargeting the aim.
|
||||
/**
|
||||
* Moves and rotates the camera around the anchor node in order to maintain the screen
|
||||
* space position of the aim node. Also interpolates to the aim node, when retargeting
|
||||
* the aim.
|
||||
*/
|
||||
CameraPose followAim(CameraPose pose, glm::dvec3 cameraToAnchor,
|
||||
Displacement anchorToAim);
|
||||
CameraPose followAim(CameraPose pose, const glm::dvec3& cameraToAnchor,
|
||||
const Displacement& anchorToAim);
|
||||
|
||||
/*
|
||||
* Perform a camera roll on the local camera rotation
|
||||
* \returns a local camera rotation modified with a roll.
|
||||
/**
|
||||
* Perform a camera roll on the local camera rotation.
|
||||
*
|
||||
* \return A local camera rotation modified with a roll
|
||||
*/
|
||||
glm::dquat roll(double deltaTime, const glm::dquat& localCameraRotation) const;
|
||||
|
||||
/**
|
||||
* Performs rotation around the cameras x and y axes.
|
||||
* \returns a local camera rotation modified with two degrees of freedom.
|
||||
*
|
||||
* \return A local camera rotation modified with two degrees of freedom
|
||||
*/
|
||||
glm::dquat rotateLocally(double deltaTime,
|
||||
const glm::dquat& localCameraRotation) const;
|
||||
|
||||
/**
|
||||
* Interpolates the camera rotation based on active interpolators.
|
||||
* \returns a new rotation quaternion
|
||||
*
|
||||
* \return A new rotation quaternion
|
||||
*/
|
||||
glm::dquat interpolateLocalRotation(double deltaTime,
|
||||
const glm::dquat& localCameraRotation);
|
||||
|
||||
|
||||
Displacement interpolateRetargetAim(double deltaTime, CameraPose pose,
|
||||
glm::dvec3 cameraToAnchor, Displacement anchorToAim);
|
||||
Displacement interpolateRetargetAim(double deltaTime, const CameraPose& pose,
|
||||
const glm::dvec3& prevCameraToAnchor, Displacement anchorToAim);
|
||||
|
||||
double interpolateCameraToSurfaceDistance(double deltaTime, double currentDistance,
|
||||
double targetDistance);
|
||||
|
||||
/**
|
||||
* Modify the camera position and global rotation to rotate around the up vector
|
||||
* of the current anchor based on x-wise input.
|
||||
*
|
||||
* The up-vector to rotate around is determined by the "_upToUseForRotation" property
|
||||
*/
|
||||
void rotateAroundAnchorUp(double deltaTime, double speedScale,
|
||||
glm::dvec3& cameraPosition, glm::dquat& globalCameraRotation);
|
||||
|
||||
/**
|
||||
* Translates the horizontal direction. If far from the anchor object, this will
|
||||
* result in an orbital rotation around the object. This function does not affect the
|
||||
* rotation but only the position.
|
||||
*
|
||||
* \return a position vector adjusted in the horizontal direction.
|
||||
* \return A position vector adjusted in the horizontal direction.
|
||||
*/
|
||||
glm::dvec3 translateHorizontally(double deltaTime, const glm::dvec3& cameraPosition,
|
||||
const glm::dvec3& objectPosition, const glm::dquat& globalCameraRotation,
|
||||
glm::dvec3 translateHorizontally(double deltaTime, double speedScale,
|
||||
const glm::dvec3& cameraPosition, const glm::dvec3& objectPosition,
|
||||
const glm::dquat& globalCameraRotation,
|
||||
const SurfacePositionHandle& positionHandle) const;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Adds rotation to the camera position so that it follows the rotation of the anchor
|
||||
* node defined by the differential anchorNodeRotationDiff.
|
||||
* node defined by the differential \p focusNodeRotationDiff.
|
||||
*
|
||||
* \return a position updated with the rotation defined by anchorNodeRotationDiff
|
||||
* \return A position updated with the rotation defined by \p anchorNodeRotationDiff
|
||||
*/
|
||||
glm::dvec3 followAnchorNodeRotation(const glm::dvec3& cameraPosition,
|
||||
const glm::dvec3& objectPosition, const glm::dquat& anchorNodeRotationDiff) const;
|
||||
const glm::dvec3& objectPosition, const glm::dquat& focusNodeRotationDiff) const;
|
||||
|
||||
/**
|
||||
* Updates the global rotation so that it points towards the anchor node.
|
||||
*
|
||||
* \return a global rotation quaternion defining a rotation towards the anchor node
|
||||
* \return A global rotation quaternion defining a rotation towards the anchor node
|
||||
*/
|
||||
glm::dquat rotateGlobally(const glm::dquat& globalCameraRotation,
|
||||
const glm::dquat& aimNodeRotationDiff,
|
||||
const glm::dquat& focusNodeRotationDiff,
|
||||
const SurfacePositionHandle& positionHandle) const;
|
||||
|
||||
/**
|
||||
* Translates the camera position towards or away from the anchor node.
|
||||
* \returns a position vector adjusted in the vertical direction.
|
||||
*
|
||||
* \return A position vector adjusted in the vertical direction.
|
||||
*/
|
||||
glm::dvec3 translateVertically(double deltaTime, const glm::dvec3& cameraPosition,
|
||||
const glm::dvec3& objectPosition,
|
||||
@@ -359,7 +388,7 @@ private:
|
||||
/**
|
||||
* Rotates the camera around the out vector of the surface.
|
||||
*
|
||||
* \return a quaternion adjusted to rotate around the out vector of the surface
|
||||
* \return A quaternion adjusted to rotate around the out vector of the surface
|
||||
*/
|
||||
glm::dquat rotateHorizontally(double deltaTime,
|
||||
const glm::dquat& globalCameraRotation,
|
||||
@@ -368,7 +397,7 @@ private:
|
||||
/**
|
||||
* Push the camera out to the surface of the object.
|
||||
*
|
||||
* \return a position vector adjusted to be at least _minimumAllowedDistance meters
|
||||
* \return A position vector adjusted to be at least _minimumAllowedDistance meters
|
||||
* above the actual surface of the object
|
||||
*/
|
||||
glm::dvec3 pushToSurface(const glm::dvec3& cameraPosition,
|
||||
@@ -387,16 +416,10 @@ private:
|
||||
glm::dvec3 cameraToSurfaceVector(const glm::dvec3& cameraPos,
|
||||
const glm::dvec3& centerPos, const SurfacePositionHandle& posHandle);
|
||||
|
||||
/**
|
||||
* Calculates a SurfacePositionHandle given a camera position in world space.
|
||||
*/
|
||||
SurfacePositionHandle calculateSurfacePositionHandle(const SceneGraphNode& node,
|
||||
const glm::dvec3& cameraPositionWorldSpace) const;
|
||||
|
||||
void resetIdleBehavior();
|
||||
|
||||
/**
|
||||
* Apply the currently selected idle behavior to the position and rotations
|
||||
* Apply the currently selected idle behavior to the position and rotations.
|
||||
*/
|
||||
void applyIdleBehavior(double deltaTime, glm::dvec3& position,
|
||||
glm::dquat& localRotation, glm::dquat& globalRotation);
|
||||
@@ -407,13 +430,11 @@ private:
|
||||
*
|
||||
* Used for IdleBehavior::Behavior::Orbit
|
||||
*
|
||||
* \param deltaTime The time step to use for the motion. Controls the rotation angle
|
||||
* \param angle The rotation angle to use for the motion
|
||||
* \param position The position of the camera. Will be changed by the function
|
||||
* \param globalRotation The camera's global rotation. Will be changed by the function
|
||||
* \param speedScale A speed scale that controls the speed of the motion
|
||||
*/
|
||||
void orbitAnchor(double deltaTime, glm::dvec3& position,
|
||||
glm::dquat& globalRotation, double speedScale);
|
||||
void orbitAnchor(double angle, glm::dvec3& position, glm::dquat& globalRotation);
|
||||
|
||||
/**
|
||||
* Orbit the current anchor node, by adding a rotation around the given axis. For
|
||||
@@ -422,17 +443,19 @@ private:
|
||||
* vector coincides with the axis, and should be used with care.
|
||||
*
|
||||
* Used for:
|
||||
* IdleBehavior::Behavior::OrbitAtConstantLat (axis = north = z-axis) and
|
||||
* IdleBehavior::Behavior::OrbitAroundUp (axis = up = y-axis)
|
||||
* - IdleBehavior::Behavior::OrbitAtConstantLat (axis = north = z-axis) and
|
||||
* - IdleBehavior::Behavior::OrbitAroundUp (axis = up = y-axis)
|
||||
*
|
||||
* \param axis The axis to arbit around, given in model coordinates of the anchor
|
||||
* \param deltaTime The time step to use for the motion. Controls the rotation angle
|
||||
* \param angle The rotation angle to use for the motion
|
||||
* \param position The position of the camera. Will be changed by the function
|
||||
* \param globalRotation The camera's global rotation. Will be changed by the function
|
||||
* \param speedScale A speed scale that controls the speed of the motion
|
||||
*/
|
||||
void orbitAroundAxis(const glm::dvec3 axis, double deltaTime, glm::dvec3& position,
|
||||
glm::dquat& globalRotation, double speedScale);
|
||||
void orbitAroundAxis(const glm::dvec3& axis, double angle, glm::dvec3& position,
|
||||
glm::dquat& globalRotation);
|
||||
|
||||
double rotationSpeedScaleFromCameraHeight(const glm::dvec3& cameraPosition,
|
||||
const SurfacePositionHandle& positionHandle) const;
|
||||
};
|
||||
|
||||
} // namespace openspace::interaction
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -25,6 +25,7 @@
|
||||
#ifndef __OPENSPACE_CORE___PATH___H__
|
||||
#define __OPENSPACE_CORE___PATH___H__
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/navigation/pathcurve.h>
|
||||
#include <openspace/navigation/waypoint.h>
|
||||
#include <ghoul/misc/dictionary.h>
|
||||
@@ -43,119 +44,136 @@ public:
|
||||
AvoidCollision = 0,
|
||||
ZoomOutOverview,
|
||||
Linear,
|
||||
AvoidCollisionWithLookAt // @TODO (2021-08-13, emmbr) This type right now leads
|
||||
// to rapid rotations, but is useful in specific
|
||||
// scenarios, e.g. close to surfaces. Later we want to
|
||||
// remove it, and create a curve type that looks nicely
|
||||
// at the targets when moving, avoids collisions and
|
||||
// doesn't introduce sudden large changes in rotation
|
||||
|
||||
// @TODO (2021-08-13, emmbr) This type right now leads to rapid rotations, but is
|
||||
// useful in specific scenarios, e.g. close to surfaces. Later we want to remove
|
||||
// it, and create a curve type that looks nicely at the targets when moving,
|
||||
// avoids collisions and doesn't introduce sudden large changes in rotation
|
||||
AvoidCollisionWithLookAt
|
||||
};
|
||||
|
||||
Path(Waypoint start, Waypoint end, Type type,
|
||||
std::optional<double> duration = std::nullopt);
|
||||
std::optional<float> duration = std::nullopt);
|
||||
|
||||
Waypoint startPoint() const;
|
||||
Waypoint endPoint() const;
|
||||
|
||||
/**
|
||||
* Return the total length of the the curve for the path, in meters
|
||||
* Return the total length of the the curve for the path, in meters.
|
||||
*/
|
||||
double pathLength() const;
|
||||
|
||||
/**
|
||||
* Return the remaining distance to traverse, in meters.
|
||||
*/
|
||||
double remainingDistance() const;
|
||||
|
||||
/**
|
||||
* Estimate a value for the remaining time to reach the target, based on the
|
||||
* currently progressed time and the estimation for how long the path will
|
||||
* take to traverse. Note that the computation is not exact.
|
||||
*
|
||||
* \param speedScale The speed scale factor that may affect how fast the camera moves
|
||||
* \return The estimated remaining time
|
||||
*/
|
||||
float estimatedRemainingTime(float speedScale) const;
|
||||
|
||||
/**
|
||||
* Return a vector of positions corresponding to the control points of the path's
|
||||
* spline curve
|
||||
* spline curve.
|
||||
*/
|
||||
std::vector<glm::dvec3> controlPoints() const;
|
||||
|
||||
/**
|
||||
* Take a step along the current path, corresponding to the delta time step \p dt, and
|
||||
* return the resulting camera pose. The \p speedScale is a factor that will be
|
||||
* multiplied with the traversal speed
|
||||
* multiplied with the traversal speed.
|
||||
*/
|
||||
CameraPose traversePath(double dt, float speedScale = 1.f);
|
||||
|
||||
/**
|
||||
* Function that can be used to permaturely quit a path, for example when skipping
|
||||
* to the end
|
||||
* to the end.
|
||||
*/
|
||||
void quitPath();
|
||||
|
||||
/**
|
||||
* Return the identifer of the node that is the current appropriate anchor node, of
|
||||
* the start and end waypoint's reference node. Dtermined based on how far along the
|
||||
* path we have traveled
|
||||
* path we have traveled.
|
||||
*/
|
||||
std::string currentAnchor() const;
|
||||
|
||||
/**
|
||||
* Return wether the path has reached its end point or not
|
||||
* Return wether the path has reached its end point or not.
|
||||
*/
|
||||
bool hasReachedEnd() const;
|
||||
|
||||
/**
|
||||
* Compute the interpolated camera pose at a certain distance along a *linear*
|
||||
* path. Note that the linear path is a special case, to avoid risks of precision
|
||||
* problems for long paths
|
||||
* problems for long paths.
|
||||
*/
|
||||
CameraPose linearInterpolatedPose(double distance, double displacement);
|
||||
|
||||
/**
|
||||
* Compute the interpolated camera pose at a certain distance along the path
|
||||
* Compute the interpolated camera pose at a certain distance along the path.
|
||||
*/
|
||||
CameraPose interpolatedPose(double distance) const;
|
||||
|
||||
/**
|
||||
* Reset variables used to play back path
|
||||
* Reset variables used to play back path.
|
||||
*/
|
||||
void resetPlaybackVariables();
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Interpolate between the paths start and end rotation using the approach that
|
||||
* corresponds to the path's curve type. The interpolation parameter \p t is the
|
||||
* same as for the position interpolation, i.e. the relative traveled distance
|
||||
* along the path, in [0, 1]
|
||||
* corresponds to the path's curve type. The interpolation parameter \p t is the same
|
||||
* as for the position interpolation, i.e. the relative traveled distance along the
|
||||
* path, in [0, 1].
|
||||
*
|
||||
* \param t The interpolation parameter, given as the relative traveled distance
|
||||
along the path, in [0, 1]
|
||||
* \param t The interpolation parameter, given as the relative traveled distance along
|
||||
* the path, in [0, 1]
|
||||
*/
|
||||
glm::dquat interpolateRotation(double t) const;
|
||||
|
||||
/**
|
||||
* Compute the interpolated rotation quaternion using an eased SLERP approach
|
||||
* Compute the interpolated rotation quaternion using an eased SLERP approach.
|
||||
*
|
||||
* \param t The interpolation variable for the rotatation interpolation.
|
||||
* Should be the relative traveled distance, in [0, 1]
|
||||
* \param t The interpolation variable for the rotatation interpolation. Should be the
|
||||
* relative traveled distance, in [0, 1]
|
||||
*/
|
||||
glm::dquat easedSlerpRotation(double t) const;
|
||||
|
||||
/**
|
||||
* Compute the interpolated rotation quaternion using a method that is customized
|
||||
* for linear paths. The camera will first interpoalte to look at the targetted
|
||||
* node, and keep doing so for most of the path. At the end, when within a certain
|
||||
* distance from the target, the rotation is interpolated so that the camera ends up
|
||||
* in the target pose at the end of the path.
|
||||
* Compute the interpolated rotation quaternion using a method that is customized for
|
||||
* linear paths. The camera will first interpoalte to look at the targetted node, and
|
||||
* keep doing so for most of the path. At the end, when within a certain distance from
|
||||
* the target, the rotation is interpolated so that the camera ends up in the target
|
||||
* pose at the end of the path.
|
||||
*
|
||||
* \param t The interpolation variable for the rotatation interpolation.
|
||||
* Should be the relative traveled distance, in [0, 1]
|
||||
* \param t The interpolation variable for the rotatation interpolation. Should be the
|
||||
* relative traveled distance, in [0, 1]
|
||||
*/
|
||||
glm::dquat linearPathRotation(double t) const;
|
||||
|
||||
/**
|
||||
* Compute the interpolated rotation quaternion using an approach that first
|
||||
* interpolates to look at the start node, and then the end node, before
|
||||
* interpolating to the end rotation
|
||||
* interpolates to look at the start node, and then the end node, before interpolating
|
||||
* to the end rotation.
|
||||
*
|
||||
* \param t The interpolation variable for the rotatation interpolation.
|
||||
* Should be the relative traveled distance, in [0, 1]
|
||||
* \param t The interpolation variable for the rotatation interpolation. Should be the
|
||||
* relative traveled distance, in [0, 1]
|
||||
*/
|
||||
glm::dquat lookAtTargetsRotation(double t) const;
|
||||
|
||||
/**
|
||||
* Evaluate the current traversal speed along the path, based on the currently
|
||||
* traveled distance. The final speed will be scaled to match the desired duration
|
||||
* for the path (which might have been specified by the user)
|
||||
* traveled distance. The final speed will be scaled to match the desired duration for
|
||||
* the path (which might have been specified by the user).
|
||||
*
|
||||
* \param traveledDistance The current distance traveled along the path, in meters
|
||||
*/
|
||||
@@ -167,23 +185,24 @@ private:
|
||||
|
||||
std::unique_ptr<PathCurve> _curve;
|
||||
|
||||
double _speedFactorFromDuration = 1.0;
|
||||
float _speedFactorFromDuration = 1.f;
|
||||
float _expectedDuration = 0.f;
|
||||
|
||||
// Playback variables
|
||||
double _traveledDistance = 0.0; // Meters
|
||||
double _progressedTime = 0.0; // Time since playback started (seconds)
|
||||
float _progressedTime = 0.f; // Time since playback started (seconds)
|
||||
bool _shouldQuit = false;
|
||||
CameraPose _prevPose;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a path based on an instruction given as a dictionary. (See top of cpp file
|
||||
* for documentation on keys and values for the dictionary.)
|
||||
* If /p forceType is specified, that type will primarily be used as the type for the
|
||||
* created path. Secondly, the type will be read from the dictionary, and lastly it will
|
||||
* use the default from PathNavigator.
|
||||
* Create a path based on an instruction given as a dictionary (see top of cpp file
|
||||
* for documentation on keys and values for the dictionary). If \p forceType is specified,
|
||||
* that type will primarily be used as the type for the created path. Secondly, the type
|
||||
* will be read from the dictionary, and lastly it will use the default from
|
||||
* PathNavigator.
|
||||
*
|
||||
* \return the created path
|
||||
* \return The created path
|
||||
*/
|
||||
Path createPathFromDictionary(const ghoul::Dictionary& dictionary,
|
||||
std::optional<Path::Type> forceType = std::nullopt);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -36,17 +36,17 @@ class Waypoint;
|
||||
class PathCurve {
|
||||
public:
|
||||
struct InsufficientPrecisionError : public ghoul::RuntimeError {
|
||||
explicit InsufficientPrecisionError(std::string msg);
|
||||
explicit InsufficientPrecisionError(std::string error);
|
||||
};
|
||||
|
||||
struct TooShortPathError : public ghoul::RuntimeError {
|
||||
explicit TooShortPathError(std::string msg);
|
||||
explicit TooShortPathError(std::string error);
|
||||
};
|
||||
|
||||
virtual ~PathCurve() = 0;
|
||||
|
||||
/**
|
||||
* Return the length of the curve, in meters
|
||||
* Return the length of the curve, in meters.
|
||||
*/
|
||||
double length() const;
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
* the full length of the path.
|
||||
*
|
||||
* Can be overridden by subclasses that want more control over the position
|
||||
* interpolation
|
||||
* interpolation.
|
||||
*/
|
||||
virtual glm::dvec3 positionAt(double relativeDistance) const;
|
||||
|
||||
@@ -66,27 +66,26 @@ public:
|
||||
* position. Note that u does not correspond to the relatively traveled distance.
|
||||
*
|
||||
* Can be overridden by subclasses that want more control over the position
|
||||
* interpolation
|
||||
* interpolation.
|
||||
*/
|
||||
virtual glm::dvec3 interpolate(double u) const;
|
||||
|
||||
/**
|
||||
* Return the positions defining the control points for the spline interpolation
|
||||
* Return the positions defining the control points for the spline interpolation.
|
||||
*/
|
||||
std::vector<glm::dvec3> points() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Precompute information related to the spline parameters that are
|
||||
* needed for arc length reparameterization. Must be called after
|
||||
* control point creation.
|
||||
* Precompute information related to the spline parameters that are needed for arc
|
||||
* length reparameterization. Must be called after control point creation.
|
||||
*/
|
||||
void initializeParameterData();
|
||||
|
||||
/**
|
||||
* Compute curve parameter u that matches the input arc length s.
|
||||
* Input s is a length value in meters, in the range [0, _totalLength].
|
||||
* The returned curve parameter u is in range [0, 1].
|
||||
* Compute curve parameter u that matches the input arc length s. Input s is a length
|
||||
* value in meters, in the range [0, _totalLength]. The returned curve parameter u is
|
||||
* in range [0, 1].
|
||||
*/
|
||||
double curveParameter(double s) const;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -64,6 +64,9 @@ public:
|
||||
bool hasCurrentPath() const;
|
||||
bool hasFinished() const;
|
||||
bool isPlayingPath() const;
|
||||
bool isPaused() const;
|
||||
|
||||
float estimatedRemainingTimeInPath() const;
|
||||
|
||||
void updateCamera(double deltaTime);
|
||||
void createPath(const ghoul::Dictionary& dictionary);
|
||||
@@ -78,30 +81,33 @@ public:
|
||||
double minValidBoundingSphere() const;
|
||||
double findValidBoundingSphere(const SceneGraphNode* node) const;
|
||||
|
||||
double defaultArrivalHeight(const std::string& sgnIdentifier) const;
|
||||
|
||||
const std::vector<SceneGraphNode*>& relevantNodes();
|
||||
|
||||
/**
|
||||
* Find a node close to the given node. Closeness is determined by a factor times
|
||||
* the bounding sphere of the object
|
||||
* \return pointer to the SGN if one was found, nullptr otherwise
|
||||
*/
|
||||
* Find a node close to the given node. Closeness is determined by a factor times
|
||||
* the bounding sphere of the object.
|
||||
*
|
||||
* \return Pointer to the SGN if one was found, nullptr otherwise
|
||||
*/
|
||||
static SceneGraphNode* findNodeNearTarget(const SceneGraphNode* node);
|
||||
|
||||
/**
|
||||
* \return The Lua library that contains all Lua functions available to affect the
|
||||
* path navigation
|
||||
*/
|
||||
* \return The Lua library that contains all Lua functions available to affect the
|
||||
* path navigation
|
||||
*/
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
|
||||
private:
|
||||
void handlePathEnd();
|
||||
|
||||
/**
|
||||
* Populate list of nodes that are relevant for collision checks, etc
|
||||
*/
|
||||
* Populate list of nodes that are relevant for collision checks, etc.
|
||||
*/
|
||||
void findRelevantNodes();
|
||||
|
||||
void removeRollRotation(CameraPose& pose, double deltaTime);
|
||||
void removeRollRotation(CameraPose& pose) const;
|
||||
|
||||
std::unique_ptr<Path> _currentPath = nullptr;
|
||||
bool _isPlaying = false;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -39,7 +39,7 @@ struct NavigationState;
|
||||
class Waypoint {
|
||||
public:
|
||||
Waypoint() = default;
|
||||
Waypoint(const glm::dvec3& pos, const glm::dquat& rot, const std::string& ref);
|
||||
Waypoint(const glm::dvec3& pos, const glm::dquat& rot, std::string ref);
|
||||
explicit Waypoint(const NavigationState& ns);
|
||||
|
||||
CameraPose pose() const;
|
||||
@@ -47,6 +47,7 @@ public:
|
||||
glm::dquat rotation() const;
|
||||
SceneGraphNode* node() const;
|
||||
std::string nodeIdentifier() const;
|
||||
std::optional<std::string> aimIdentifier() const;
|
||||
double validBoundingSphere() const;
|
||||
|
||||
private:
|
||||
@@ -54,12 +55,17 @@ private:
|
||||
std::string _nodeIdentifier;
|
||||
// To be able to handle nodes with faulty bounding spheres
|
||||
double _validBoundingSphere = 0.0;
|
||||
|
||||
// Keep track of if there was an aim node, specified in for example the
|
||||
// navigation state used to create this waypoint. It may be required in
|
||||
// certain situations
|
||||
std::optional<std::string> _aimNodeIdentifier;
|
||||
};
|
||||
|
||||
/**
|
||||
* Compute a waypoint from the current camera position.
|
||||
*
|
||||
* \return the computed WayPoint
|
||||
* \return The computed WayPoint
|
||||
*/
|
||||
Waypoint waypointFromCamera();
|
||||
|
||||
@@ -76,17 +82,17 @@ struct NodeCameraStateSpec {
|
||||
* where the camera will be facing the given node. If there is a 'Sun' node in the scene,
|
||||
* it will possibly be used to compute a position on the lit side of the object.
|
||||
*
|
||||
* \param spec details about the node and state to create the waypoint from. Minimal
|
||||
* information is the identifier of the node, but a position or height
|
||||
* above the bounding sphere may also be given.
|
||||
* \param startPoint an optional previous waypoint. If not specified, the current camera
|
||||
* \param spec Details about the node and state to create the waypoint from. Minimal
|
||||
* information is the identifier of the node, but a position or height above
|
||||
* the bounding sphere may also be given.
|
||||
* \param startPoint An optional previous waypoint. If not specified, the current camera
|
||||
* position will be used.
|
||||
* \param userLinear if true, the new waypoint will be computed along a straight line
|
||||
* from the start waypoint to the scene graph node or position.
|
||||
* \return the computed WayPoint
|
||||
* \param useLinear If `true`, the new waypoint will be computed along a straight line
|
||||
* from the start waypoint to the scene graph node or position.
|
||||
* \return The computed WayPoint
|
||||
*/
|
||||
Waypoint computeWaypointFromNodeInfo(const NodeCameraStateSpec& spec,
|
||||
std::optional<Waypoint> startPoint = std::nullopt, bool useLinear = false);
|
||||
const std::optional<Waypoint>& startPoint = std::nullopt, bool useLinear = false);
|
||||
|
||||
} // namespace openspace::interaction
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -25,9 +25,10 @@
|
||||
#ifndef __OPENSPACE_CORE___MESSAGESTRUCTURES___H__
|
||||
#define __OPENSPACE_CORE___MESSAGESTRUCTURES___H__
|
||||
|
||||
#include <ghoul/fmt.h>
|
||||
#include <ghoul/format.h>
|
||||
#include <ghoul/glm.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/stringhelper.h>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
@@ -49,8 +50,8 @@ struct CameraKeyframe {
|
||||
CameraKeyframe(const std::vector<char>& buffer) {
|
||||
deserialize(buffer);
|
||||
}
|
||||
CameraKeyframe(glm::dvec3&& pos, glm::dquat&& rot, std::string&& focusNode,
|
||||
bool&& followNodeRot, float&& scale)
|
||||
CameraKeyframe(glm::dvec3 pos, glm::dquat rot, std::string focusNode,
|
||||
bool followNodeRot, float scale)
|
||||
: _position(pos)
|
||||
, _rotation(rot)
|
||||
, _followNodeRotation(followNodeRot)
|
||||
@@ -66,7 +67,7 @@ struct CameraKeyframe {
|
||||
|
||||
double _timestamp = 0.0;
|
||||
|
||||
void serialize(std::vector<char> &buffer) const {
|
||||
void serialize(std::vector<char>& buffer) const {
|
||||
// Add position
|
||||
buffer.insert(
|
||||
buffer.end(),
|
||||
@@ -188,17 +189,14 @@ struct CameraKeyframe {
|
||||
|
||||
void write(std::stringstream& out) const {
|
||||
// Add camera position
|
||||
out << std::fixed << std::setprecision(7) << _position.x << ' '
|
||||
<< std::fixed << std::setprecision(7) << _position.y << ' '
|
||||
<< std::fixed << std::setprecision(7) << _position.z << ' ';
|
||||
out << std::setprecision(std::numeric_limits<double>::max_digits10);
|
||||
out << _position.x << ' ' << _position.y << ' ' << _position.z << ' ';
|
||||
// Add camera rotation
|
||||
out << std::fixed << std::setprecision(7) << _rotation.x << ' '
|
||||
<< std::fixed << std::setprecision(7) << _rotation.y << ' '
|
||||
<< std::fixed << std::setprecision(7) << _rotation.z << ' '
|
||||
<< std::fixed << std::setprecision(7) << _rotation.w << ' ';
|
||||
out << std::fixed
|
||||
<< std::setprecision(std::numeric_limits<double>::max_digits10)
|
||||
<< _scale << ' ';
|
||||
out << _rotation.x << ' '
|
||||
<< _rotation.y << ' '
|
||||
<< _rotation.z << ' '
|
||||
<< _rotation.w << ' ';
|
||||
out << std::scientific << _scale << ' ';
|
||||
if (_followNodeRotation) {
|
||||
out << "F ";
|
||||
}
|
||||
@@ -407,7 +405,7 @@ struct ScriptMessage {
|
||||
if (buffer.size() != (sizeof(uint32_t) + len)) {
|
||||
LERRORC(
|
||||
"ParallelPeer",
|
||||
fmt::format(
|
||||
std::format(
|
||||
"Received buffer with wrong size. Expected {} got {}",
|
||||
len, buffer.size()
|
||||
)
|
||||
@@ -468,7 +466,7 @@ struct ScriptMessage {
|
||||
std::string tmpReadbackScript;
|
||||
_script.erase();
|
||||
for (int i = 0; i < numScriptLines; ++i) {
|
||||
std::getline(iss, tmpReadbackScript);
|
||||
ghoul::getline(iss, tmpReadbackScript);
|
||||
size_t start = tmpReadbackScript.find_first_not_of(" ");
|
||||
tmpReadbackScript = tmpReadbackScript.substr(start);
|
||||
_script.append(tmpReadbackScript);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -30,25 +30,27 @@
|
||||
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
|
||||
* Method that creates a CameraKeyframe object and populates it with the current
|
||||
* properties of the camera from the navigation handler.
|
||||
*
|
||||
* \return 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
|
||||
* Method that creates a TimeKeyframe object and populates it with the current time values
|
||||
* from the application time manager.
|
||||
*
|
||||
* \return 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.
|
||||
* 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
|
||||
* \return ScriptMessage The ScriptMessage data structure with script
|
||||
*/
|
||||
ScriptMessage generateScriptMessage(std::string script);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
|
||||
struct DataMessage {
|
||||
DataMessage() = default;
|
||||
DataMessage(datamessagestructures::Type t, double timestamp, std::vector<char> c);
|
||||
DataMessage(datamessagestructures::Type t, double time, std::vector<char> c);
|
||||
|
||||
datamessagestructures::Type type;
|
||||
double timestamp;
|
||||
@@ -70,7 +70,7 @@ public:
|
||||
|
||||
class ConnectionLostError : public ghoul::RuntimeError {
|
||||
public:
|
||||
explicit ConnectionLostError(bool shouldLogError = true);
|
||||
explicit ConnectionLostError(bool shouldLogError_ = true);
|
||||
|
||||
bool shouldLogError;
|
||||
};
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
ParallelConnection::Message receiveMessage();
|
||||
|
||||
// Gonna do some UTF-like magic once we reach 255 to introduce a second byte or so
|
||||
static constexpr uint8_t ProtocolVersion = 6;
|
||||
static constexpr uint8_t ProtocolVersion = 7;
|
||||
|
||||
private:
|
||||
std::unique_ptr<ghoul::io::TcpSocket> _socket;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
void connect();
|
||||
void setPort(std::string port);
|
||||
void setAddress(std::string address);
|
||||
void setServerName(std::string name);
|
||||
void setName(std::string name);
|
||||
bool isHost();
|
||||
const std::string& hostName();
|
||||
@@ -66,9 +67,9 @@ public:
|
||||
double latencyStandardDeviation() const;
|
||||
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to affect the
|
||||
* remote OS parallel connection.
|
||||
*/
|
||||
* Returns the Lua library that contains all Lua functions available to affect the
|
||||
* remote OS parallel connection.
|
||||
*/
|
||||
static scripting::LuaLibrary luaLibrary();
|
||||
ParallelConnection::Status status();
|
||||
int nConnections();
|
||||
@@ -97,6 +98,7 @@ private:
|
||||
|
||||
properties::StringProperty _password;
|
||||
properties::StringProperty _hostPassword;
|
||||
properties::StringProperty _serverName;
|
||||
|
||||
// While the port should in theory be an int,
|
||||
// we use a StringProperty to avoid a slider in the GUI.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -73,9 +73,10 @@ protected:
|
||||
std::string generateAdditionalJsonDescription() const override;
|
||||
|
||||
/**
|
||||
* convert a lua formatted value to a JSON formatted value
|
||||
* @param luaValue
|
||||
* @return a json formatted string representation of the given lua value
|
||||
* convert a lua formatted value to a JSON formatted value.
|
||||
*
|
||||
* \param luaValue
|
||||
* \return A JSON formatted string representation of the given Lua value
|
||||
*/
|
||||
std::string luaToJson(std::string luaValue) const;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -110,10 +110,10 @@ void NumericalProperty<T>::setExponent(float exponent) {
|
||||
if (!isValidRange(_minimumValue, _maximumValue)) {
|
||||
LWARNINGC(
|
||||
"NumericalProperty: setExponent",
|
||||
fmt::format(
|
||||
std::format(
|
||||
"Setting exponent for properties with negative values in "
|
||||
"[min, max] range is not yet supported. Property: {}",
|
||||
this->fullyQualifiedIdentifier()
|
||||
this->uri()
|
||||
)
|
||||
);
|
||||
_exponent = 1.f;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -33,15 +33,15 @@ namespace openspace::properties {
|
||||
|
||||
/**
|
||||
* The OptionProperty is a property that provides a number of predefined (using the
|
||||
* addOption method) options consisting of a `description` and a `value`. The available
|
||||
* #addOption method) options consisting of a `description` and a `value`. The available
|
||||
* options can be queried using the options method. Only values representing valid options
|
||||
* can be used to set this property, or an error will be logged
|
||||
* can be used to set this property, or an error will be logged.
|
||||
*/
|
||||
class OptionProperty : public IntProperty {
|
||||
public:
|
||||
/**
|
||||
* The struct storing a single option consisting of an integer `value` and a
|
||||
* `string` description.
|
||||
* The struct storing a single option consisting of an integer `value` and a `string`
|
||||
* description.
|
||||
*/
|
||||
struct Option {
|
||||
int value;
|
||||
@@ -57,7 +57,8 @@ public:
|
||||
* The constructor delegating the `identifier` and the `guiName` to its super class.
|
||||
*
|
||||
* \param info The PropertyInfo structure that contains all the required static
|
||||
* information for initializing this Property.
|
||||
* information for initializing this Property
|
||||
*
|
||||
* \pre \p info.identifier must not be empty
|
||||
* \pre \p info.guiName must not be empty
|
||||
*/
|
||||
@@ -67,7 +68,7 @@ public:
|
||||
* The constructor delegating the `identifier` and the `guiName` to its super class.
|
||||
*
|
||||
* \param info The PropertyInfo structure that contains all the required static
|
||||
* information for initializing this Property.
|
||||
* information for initializing this Property
|
||||
* \param displayType Optional DisplayType for GUI (default RADIO)
|
||||
*
|
||||
* \pre \p info.identifier must not be empty
|
||||
@@ -123,7 +124,7 @@ public:
|
||||
const std::vector<Option>& options() const;
|
||||
|
||||
/**
|
||||
* This function removes all previous options from the OptionProperty
|
||||
* This function removes all previous options from the OptionProperty.
|
||||
*/
|
||||
void clearOptions();
|
||||
|
||||
@@ -151,10 +152,10 @@ public:
|
||||
const Option& option() const;
|
||||
|
||||
/**
|
||||
* Get the description of the option that matches `value`.
|
||||
*
|
||||
* \param value The value of the option
|
||||
*/
|
||||
* Get the description of the option that matches `value`.
|
||||
*
|
||||
* \param value The value of the option
|
||||
*/
|
||||
std::string getDescriptionByValue(int value);
|
||||
|
||||
private:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -41,8 +41,8 @@ class PropertyOwner;
|
||||
/**
|
||||
* A property encapsulates a value which should be user-changeable. A property almost
|
||||
* always belongs to a PropertyOwner who has taken ownership (setPropertyOwner) of the
|
||||
* Property. Per PropertyOwner, the `identifier` needs to be unique and can be
|
||||
* used as a URI. This class is an abstract base class and each subclass (most notable
|
||||
* Property. Per PropertyOwner, the `identifier` needs to be unique and can be used as a
|
||||
* URI. This class is an abstract base class and each subclass (most notable
|
||||
* TemplateProperty) needs to implement the methods Property::className, Property::get,
|
||||
* Property::set, Property::type(), Property::getLuaValue, Property::setLuaValue,
|
||||
* Property::getStringValue, and Property::typeLua to make full use of the infrastructure.
|
||||
@@ -56,24 +56,32 @@ class PropertyOwner;
|
||||
* which might be used in GUI representations. One example would be a glm::vec4 property,
|
||||
* (Vec4Property) that can either represent a 4-dimensional position, a powerscaled
|
||||
* coordinate, a light position, or other things, requiring different GUI representations.
|
||||
*
|
||||
* \see TemplateProperty
|
||||
* \see PropertyOwner
|
||||
*/
|
||||
class Property {
|
||||
public:
|
||||
/**
|
||||
* The visibility classes for Property%s. The classes are strictly ordered as
|
||||
* Hidden > Developer > AdvancedUser > User > NoviceUser > Always
|
||||
*/
|
||||
* The visibility classes for Property%s. The classes are strictly ordered as
|
||||
* Hidden > Developer > AdvancedUser > User > NoviceUser > Always
|
||||
*/
|
||||
enum class Visibility {
|
||||
Hidden = 5, ///< Never visible
|
||||
Developer = 4, ///< Visible in Developer mode
|
||||
AdvancedUser = 3, ///< Visible in Advanced User mode
|
||||
User = 2, ///< Visible in User mode
|
||||
NoviceUser = 1, ///< Visible in Novice User mode
|
||||
Always = 0, ///< Visible for all types, no matter what
|
||||
/// Never visible
|
||||
Hidden = 5,
|
||||
/// Visible in Developer mode
|
||||
Developer = 4,
|
||||
/// Visible in Advanced User mode
|
||||
AdvancedUser = 3,
|
||||
/// Visible in User mode
|
||||
User = 2,
|
||||
/// Visible in Novice User mode
|
||||
NoviceUser = 1,
|
||||
/// Visible for all types, no matter what
|
||||
Always = 0,
|
||||
|
||||
Default = Always ///< The default visibility for properties
|
||||
/// The default visibility for properties
|
||||
Default = Always
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -81,8 +89,10 @@ public:
|
||||
* identifier, a GUI name and descriptive text that are both user facing.
|
||||
*/
|
||||
struct PropertyInfo {
|
||||
/// GCC requires an explicit constructor here, as it does not handle the default
|
||||
/// argument for the struct initialization
|
||||
/**
|
||||
* GCC requires an explicit constructor here, as it does not handle the default
|
||||
* argument for the struct initialization.
|
||||
*/
|
||||
constexpr PropertyInfo(const char* ident, const char* gui, const char* desc)
|
||||
: identifier(ident)
|
||||
, guiName(gui)
|
||||
@@ -208,9 +218,9 @@ public:
|
||||
* Returns the Lua type that will be put onto the stack in the Property::getLua method
|
||||
* and which will be consumed by the Property::setLuaValue method. The returned value
|
||||
* can belong to the set of Lua types: `LUA_TNONE`, `LUA_TNIL`, `LUA_TBOOLEAN`,
|
||||
* `LUA_TLIGHTUSERDATA`, `LUA_TNUMBER`, `LUA_TSTRING`, `LUA_TTABLE`,
|
||||
* `LUA_TFUNCTION`, `LUA_TUSERDATA`, or `LUA_TTHREAD`. The default implementation
|
||||
* will return `LUA_TNONE`.
|
||||
* `LUA_TLIGHTUSERDATA`, `LUA_TNUMBER`, `LUA_TSTRING`, `LUA_TTABLE`, `LUA_TFUNCTION`,
|
||||
* `LUA_TUSERDATA`, or `LUA_TTHREAD`. The default implementation will return
|
||||
* `LUA_TNONE`.
|
||||
*
|
||||
* \return The Lua type that will be consumed or produced by the Property::getLuaValue
|
||||
* and Property::setLuaValue methods.
|
||||
@@ -237,18 +247,18 @@ public:
|
||||
* Property::setLuaValue methods.
|
||||
* \return An OnChangeHandle that can be used in subsequent calls to remove a callback
|
||||
*
|
||||
* \pre The callback must not be empty
|
||||
* \pre The \p callback must not be empty
|
||||
*/
|
||||
OnChangeHandle onChange(std::function<void()> callback);
|
||||
|
||||
/**
|
||||
* This method registers a \p callback function that will be called when the property
|
||||
* is destructed.
|
||||
*
|
||||
* \return An OnDeleteHandle that can be used in subsequent calls to remove a callback
|
||||
*
|
||||
* \pre The callback must not be empty
|
||||
*/
|
||||
* This method registers a \p callback function that will be called when the property
|
||||
* is destructed.
|
||||
*
|
||||
* \return An OnDeleteHandle that can be used in subsequent calls to remove a callback
|
||||
*
|
||||
* \pre The \p callback must not be empty
|
||||
*/
|
||||
OnDeleteHandle onDelete(std::function<void()> callback);
|
||||
|
||||
/**
|
||||
@@ -265,15 +275,15 @@ public:
|
||||
void removeOnChange(OnChangeHandle handle);
|
||||
|
||||
/**
|
||||
* This method deregisters a callback that was previously registered with the onDelete
|
||||
* method.
|
||||
*
|
||||
* \param handle An OnDeleteHandle that was returned from a previous call to onDelete
|
||||
* by this property.
|
||||
*
|
||||
* \pre \p handle must refer to a callback that has been previously registred
|
||||
* \pre \p handle must refer to a callback that has not been removed previously
|
||||
*/
|
||||
* This method deregisters a callback that was previously registered with the onDelete
|
||||
* method.
|
||||
*
|
||||
* \param handle An OnDeleteHandle that was returned from a previous call to onDelete
|
||||
* by this property.
|
||||
*
|
||||
* \pre \p handle must refer to a callback that has been previously registred
|
||||
* \pre \p handle must refer to a callback that has not been removed previously
|
||||
*/
|
||||
void removeOnDelete(OnDeleteHandle handle);
|
||||
|
||||
/**
|
||||
@@ -284,19 +294,21 @@ public:
|
||||
const std::string& identifier() const;
|
||||
|
||||
/**
|
||||
* Returns the fully qualified name for this Property that uniquely identifies this
|
||||
* Property within OpenSpace. It consists of the identifier preceded by all levels of
|
||||
* PropertyOwner%s separated with `.`; for example: `owner1.owner2.identifier`.
|
||||
* Returns the URI for this Property that uniquely identifies this Property within
|
||||
* OpenSpace. It consists of the identifier preceded by all levels of PropertyOwner%s
|
||||
* separated with `.`; for example: `owner1.owner2.identifier`. If the URI is invalid
|
||||
* (the Property hasn't been added to the property tree yet), it returns an empty
|
||||
* string.
|
||||
*
|
||||
* \return The fully qualified identifier for this Property
|
||||
*/
|
||||
std::string fullyQualifiedIdentifier() const;
|
||||
std::string uri() const;
|
||||
|
||||
/**
|
||||
* Returns the PropertyOwner of this Property or `nullptr`, if it does not have an
|
||||
* owner.
|
||||
*
|
||||
* \return The Property of this Property
|
||||
* \return The PropertyOwner of this Property
|
||||
*/
|
||||
PropertyOwner* owner() const;
|
||||
|
||||
@@ -337,8 +349,9 @@ public:
|
||||
void setGroupIdentifier(std::string groupId);
|
||||
|
||||
/**
|
||||
* Returns the group idenfier that this Property belongs to, or `""` if it
|
||||
* belongs to no group.
|
||||
* Returns the group idenfier that this Property belongs to, or `""` if it belongs to
|
||||
* no group.
|
||||
*
|
||||
* \return The group identifier that this Property belongs to
|
||||
*/
|
||||
std::string groupIdentifier() const;
|
||||
@@ -363,18 +376,29 @@ public:
|
||||
* This method determines if this Property should be read-only in external
|
||||
* applications. This setting is only a hint and does not need to be followed by GUI
|
||||
* applications and does not have any effect on the Property::set or
|
||||
* Property::setLuaValue methods. The value is stored in the metaData Dictionary
|
||||
* with the key: `isReadOnly`. The default value is `false`.
|
||||
* Property::setLuaValue methods. The value is stored in the metaData Dictionary with
|
||||
* the key: `isReadOnly`. The default value is `false`.
|
||||
*
|
||||
* \param state `true` if the Property should be read only, `false` otherwise
|
||||
*/
|
||||
void setReadOnly(bool state);
|
||||
|
||||
/**
|
||||
* This method determines if this Property requires confirmation upon every change of
|
||||
* the value. This setting is only a hint and does not need to be followed by GUI
|
||||
* applications and does not have any effect on the Property::set or
|
||||
* Property::setLuaValue methods. The value is stored in the metaData Dictionary with
|
||||
* the key: `needsConfirmation`. The default value is `false`.
|
||||
*
|
||||
* \param state `true` if the Property needs confirmation, `false` otherwise
|
||||
*/
|
||||
void setNeedsConfirmation(bool state);
|
||||
|
||||
/**
|
||||
* Default view options that can be used in the Property::setViewOption method. The
|
||||
* values are:
|
||||
* - Property::ViewOptions::Color = `Color` (Intended for Vec3 and Vec4),
|
||||
* - Property::ViewOptions::MinMaxRange = `MinMaxRange` (Intended for Vec2)
|
||||
* - Property::ViewOptions::Color = `Color` (Intended for Vec3 and Vec4),
|
||||
* - Property::ViewOptions::MinMaxRange = `MinMaxRange` (Intended for Vec2)
|
||||
*/
|
||||
struct ViewOptions {
|
||||
static const char* Color;
|
||||
@@ -385,9 +409,10 @@ public:
|
||||
* This method allows the developer to give hints to the GUI about different
|
||||
* representations for the GUI. The same Property (for example Vec4Property) can be
|
||||
* used in different ways, each requiring a different input method. These values are
|
||||
* stored in the metaData object under `ViewOptions`.
|
||||
* See Property::ViewOptions for a default list of possible options. As these are
|
||||
* only hints, the GUI is free to ignore any suggestion by the developer.
|
||||
* stored in the metaData object under `ViewOptions`. See Property::ViewOptions for a
|
||||
* default list of possible options. As these are only hints, the GUI is free to
|
||||
* ignore any suggestion by the developer.
|
||||
*
|
||||
* \param option The view option that should be modified
|
||||
* \param value Determines if the view option should be active (`true`) or
|
||||
* deactivated (`false`)
|
||||
@@ -401,7 +426,6 @@ public:
|
||||
*
|
||||
* \param option The view option that should be retrieved
|
||||
* \param defaultValue The value that is returned if the \p option was not set
|
||||
*
|
||||
* \return The view option's value
|
||||
*/
|
||||
bool viewOption(const std::string& option, bool defaultValue = false) const;
|
||||
@@ -418,7 +442,7 @@ public:
|
||||
/**
|
||||
* Get a valid JSON formatted representation of the Property's value.
|
||||
*
|
||||
* \return the value in a json compatible format
|
||||
* \return The value in a JSON compatible format
|
||||
*/
|
||||
virtual std::string jsonValue() const;
|
||||
|
||||
@@ -431,8 +455,8 @@ public:
|
||||
|
||||
/**
|
||||
* Creates the information that is general to every Property and adds the
|
||||
* `Identifier`, `Name`, `Type`, and `MetaData` keys and their values. The meta
|
||||
* data is handles by the generateMetaDataJsonDescription method, which has to be
|
||||
* `Identifier`, `Name`, `Type`, and `MetaData` keys and their values. The meta data
|
||||
* is handles by the generateMetaDataJsonDescription method, which has to be
|
||||
* overloaded if a concrete base class wants to add meta data that is not curated by
|
||||
* the Property class.
|
||||
*
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -25,7 +25,6 @@
|
||||
#ifndef __OPENSPACE_CORE___PROPERTYOWNER___H__
|
||||
#define __OPENSPACE_CORE___PROPERTYOWNER___H__
|
||||
|
||||
#include <openspace/json.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -53,7 +52,7 @@ public:
|
||||
static constexpr char URISeparator = '.';
|
||||
|
||||
struct PropertyOwnerInfo {
|
||||
std::string identifier;
|
||||
std::string identifier = "";
|
||||
std::string guiName = "";
|
||||
std::string description = "";
|
||||
};
|
||||
@@ -63,7 +62,7 @@ public:
|
||||
*
|
||||
* \param info The PropertyOwnerInfo struct that contains the
|
||||
* #PropertyOwnerInfo::identifier, #PropertyOwnerInfo::guiName, and
|
||||
* #PropertyOwnerInfo::description of this PropertyOwner.
|
||||
* #PropertyOwnerInfo::description of this PropertyOwner
|
||||
*
|
||||
* \pre The \p info 's #PropertyOwnerInfo::identifier must not contain any whitespaces
|
||||
* \pre The \p info 's #PropertyOwnerInfo::identifier must not contain any `.`
|
||||
@@ -141,33 +140,57 @@ public:
|
||||
|
||||
/**
|
||||
* Retrieves a Property identified by \p uri from this PropertyOwner. If \p uri does
|
||||
* not contain a `.` the identifier must refer to a Property directly owned
|
||||
* by this PropertyOwner. If the identifier contains one or more `.`, the
|
||||
* first part of the name will be recursively extracted and used as a name for a
|
||||
* sub-owner and only the last part of the identifier is referring to a Property owned
|
||||
* by PropertyOwner named by the second-but-last name.
|
||||
* not contain a `.` it is an identifier and must refer to a Property directly owned
|
||||
* by this PropertyOwner. If the identifier contains one or more `.`, the first part
|
||||
* of the name will be recursively extracted and used as a name for a sub-owner and
|
||||
* only the last part of the identifier is referring to a Property owned by a
|
||||
* PropertyOwner named by the second-but-last name.
|
||||
*
|
||||
* \param uri The identifier of the Property that should be extracted
|
||||
* \param uri The uri or identifier of the Property that should be extracted
|
||||
* \return If the Property cannot be found, `nullptr` is returned, otherwise the
|
||||
* pointer to the Property is returned
|
||||
*/
|
||||
Property* property(const std::string& uri) const;
|
||||
|
||||
/**
|
||||
* This method checks if a Property with the provided \p uri exists in this
|
||||
* PropertyOwner (or any sub-owner). If the identifier contains one or more
|
||||
* `.`, the first part of the name will be recursively extracted and is
|
||||
* used as a name for a sub-owner and only the last part of the identifier is
|
||||
* referring to a Property owned by PropertyOwner named by the second-but-last name.
|
||||
* Retrieves a PropertyOwner identified by \p uri from this PropertyOwner. If \p uri
|
||||
* does not contain a `.` it is an identifier and must refer to a PropertyOwner
|
||||
* directly owned by this PropertyOwner. If the uri contains one or more `.`, the
|
||||
* first part of the name will be recursively extracted and used as a name for a sub-
|
||||
* owner and only the last part of the uri is referring to a PropertyOwner owned by a
|
||||
* PropertyOwner named by the second-but-last name.
|
||||
*
|
||||
* \return `true` if the \p uri refers to a Property; `false` otherwise.
|
||||
* \param uri The uri or identifier of the PropertyOwner that should be extracted
|
||||
* \return If the PropertyOwner cannot be found, `nullptr` is returned, otherwise the
|
||||
* pointer to the PropertyOwner is returned
|
||||
*/
|
||||
PropertyOwner* propertyOwner(const std::string& uri) const;
|
||||
|
||||
/**
|
||||
* Returns a uri for this PropertyOwner. This is created by looking up all the owners
|
||||
* of this PropertyOwner. The owner identifiers are separated by ".", which make up
|
||||
* the uri of this PropertyOwner.
|
||||
*
|
||||
* \return The uri of this PropertyOwner
|
||||
*/
|
||||
std::string uri() const;
|
||||
|
||||
/**
|
||||
* This method checks if a Property with the provided \p uri exists in this
|
||||
* PropertyOwner (or any sub-owner). If the identifier contains one or more `.`, the
|
||||
* first part of the name will be recursively extracted and is used as a name for a
|
||||
* sub-owner and only the last part of the identifier is referring to a Property owned
|
||||
* by PropertyOwner named by the second-but-last name.
|
||||
*
|
||||
* \return `true` if the \p uri refers to a Property; `false` otherwise
|
||||
*/
|
||||
bool hasProperty(const std::string& uri) const;
|
||||
|
||||
/**
|
||||
* This method checks if a Property exists in this PropertyOwner.
|
||||
* \return `true` if the Property existed, `false` otherwise.
|
||||
*/
|
||||
* This method checks if a Property exists in this PropertyOwner.
|
||||
*
|
||||
* \return `true` if the Property existed, `false` otherwise
|
||||
*/
|
||||
bool hasProperty(const Property* prop) const;
|
||||
|
||||
void setPropertyOwner(PropertyOwner* owner) { _owner = owner; }
|
||||
@@ -185,11 +208,11 @@ public:
|
||||
/**
|
||||
* This method returns the direct sub-owner of this PropertyOwner with the provided
|
||||
* \p identifier. This means that `identifier` cannot contain any `.` as this
|
||||
* character is not allowed in PropertyOwner names. If the \p name does not name a
|
||||
* valid sub-owner of this PropertyOwner, a `nullptr` will be returned.
|
||||
* character is not allowed in PropertyOwner names. If the \p identifier does not name
|
||||
* a valid sub-owner of this PropertyOwner, a `nullptr` will be returned.
|
||||
*
|
||||
* \param identifier The identifier of the sub-owner that should be returned
|
||||
* \return The PropertyOwner with the given \p name, or `nullptr`
|
||||
* \return The PropertyOwner with the given \p identifier, or `nullptr`
|
||||
*/
|
||||
PropertyOwner* propertySubOwner(const std::string& identifier) const;
|
||||
|
||||
@@ -294,9 +317,6 @@ public:
|
||||
*/
|
||||
void removeTag(const std::string& tag);
|
||||
|
||||
// Generate JSON for documentation
|
||||
nlohmann::json generateJson() const;
|
||||
|
||||
protected:
|
||||
/// The unique identifier of this PropertyOwner
|
||||
std::string _identifier;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -25,19 +25,6 @@
|
||||
#ifndef __OPENSPACE_CORE___SHORTPROPERTY___H__
|
||||
#define __OPENSPACE_CORE___SHORTPROPERTY___H__
|
||||
|
||||
/**
|
||||
* \file shortproperty.h
|
||||
*
|
||||
* \addtogroup openspace
|
||||
* @{
|
||||
* \addtogroup properties
|
||||
* @{
|
||||
|
||||
* \class ShortProperty
|
||||
|
||||
* @} @}
|
||||
*/
|
||||
|
||||
#include <openspace/properties/numericalproperty.h>
|
||||
#include <limits>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -41,10 +41,10 @@ public:
|
||||
int typeLua() const override;
|
||||
|
||||
/**
|
||||
* This method sets the stored value to the provided value `val`.
|
||||
* If the value is different, the listeners are notified. It also removes any
|
||||
* invalid keys in the input set. A key is invalid if it does not correspond to
|
||||
* an existing option in the SelectionProperty
|
||||
* This method sets the stored value to the provided value `val`. If the value is
|
||||
* different, the listeners are notified. It also removes any invalid keys in the
|
||||
* input set. A key is invalid if it does not correspond to an existing option in the
|
||||
* SelectionProperty.
|
||||
*
|
||||
* \param val The new value for this SelectionProperty
|
||||
*/
|
||||
@@ -67,16 +67,16 @@ public:
|
||||
bool isSelected(const std::string& key) const;
|
||||
|
||||
/**
|
||||
* Checks if the SelectionProperty has any selected values, that is, if its
|
||||
* value is empty.
|
||||
* Checks if the SelectionProperty has any selected values, that is, if its value is
|
||||
* empty.
|
||||
*
|
||||
* \return `true` if there are selected options; `false` otherwise
|
||||
*/
|
||||
bool hasSelected() const;
|
||||
|
||||
/**
|
||||
* Returns all available options for this SelectionProperty. Should be
|
||||
* sorted alphabetically.
|
||||
* Returns all available options for this SelectionProperty. Should be sorted
|
||||
* alphabetically.
|
||||
*
|
||||
* \return A list of all available options
|
||||
*/
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
void addOption(const std::string& key);
|
||||
|
||||
/**
|
||||
* This method clears the selection list, that is the value of this SelectionProperty
|
||||
* This method clears the selection list, that is the value of this SelectionProperty.
|
||||
*/
|
||||
void clearSelection();
|
||||
|
||||
@@ -122,7 +122,7 @@ protected:
|
||||
|
||||
private:
|
||||
void sortOptions();
|
||||
bool removeInvalidKeys(std::set<std::string>& keys);
|
||||
bool removeInvalidKeys(std::set<std::string>& keys) const;
|
||||
|
||||
std::string generateAdditionalJsonDescription() const override;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -30,20 +30,21 @@
|
||||
namespace openspace::properties {
|
||||
|
||||
/**
|
||||
* This subclass of Property handles a single parameter value that is of type
|
||||
* `T`. It provides all the necessary methods to automatically access the
|
||||
* value. One notable instantiation of this class is StringProperty, using
|
||||
* `T = std::string` while NumericalProperty is a templated subclass dealing
|
||||
* with numerical parameter types.
|
||||
* This subclass of Property handles a single parameter value that is of type `T`. It
|
||||
* provides all the necessary methods to automatically access the value. One notable
|
||||
* instantiation of this class is StringProperty, using `T = std::string` while
|
||||
* NumericalProperty is a templated subclass dealing with numerical parameter types.
|
||||
*
|
||||
* The accessor operator and assignment operators are overloaded, so that the
|
||||
* TemplateProperty can be used just in the same way as a regular member variable. In the
|
||||
* case that these cannot not be used inline, the Property::get method will work.
|
||||
*
|
||||
* Each instantiation of this class should provide a constructor that deals with the
|
||||
* default value for that specific type `T`, so that a property can be
|
||||
* created from just a Property::PropertyInfo object.
|
||||
* default value for that specific type `T`, so that a property can be created from just a
|
||||
* Property::PropertyInfo object.
|
||||
*
|
||||
* \tparam T The type of value that is stored in this TemplateProperty
|
||||
*
|
||||
* \see Property
|
||||
* \see NumericalProperty
|
||||
*/
|
||||
@@ -66,33 +67,31 @@ public:
|
||||
TemplateProperty(Property::PropertyInfo info, T value);
|
||||
|
||||
/**
|
||||
* Returns the class name for this TemplateProperty. This method has to be
|
||||
* specialized for each new type.
|
||||
* Returns the class name for this TemplateProperty. This method has to be specialized
|
||||
* for each new type.
|
||||
*
|
||||
* \return The class name for the TemplateProperty
|
||||
*/
|
||||
virtual std::string_view className() const override = 0;
|
||||
|
||||
/**
|
||||
* Returns the stored value packed into a ghoul::any object.
|
||||
* Returns the stored value packed into a `std::any` object.
|
||||
*
|
||||
* \return The stored value packed into a ghoul::any object
|
||||
* \return The stored value packed into a `std::any` object
|
||||
*/
|
||||
virtual std::any get() const override;
|
||||
|
||||
/**
|
||||
* Sets the value from the provided ghoul::any object. If the types between
|
||||
* `T` and `value` disagree, an error is logged and the stored
|
||||
* value remains unchanged.
|
||||
* Sets the value from the provided ghoul::any object. If the types between `T` and
|
||||
* `value` disagree, an error is logged and the stored value remains unchanged.
|
||||
*
|
||||
* \param value The value that is used to set this Property
|
||||
*/
|
||||
virtual void set(std::any value) final;
|
||||
|
||||
/**
|
||||
* Returns the `std::type_info` describing the template parameter
|
||||
* `T`. It can be used to test against a ghoul::any value before trying to
|
||||
* assign it.
|
||||
* Returns the `std::type_info` describing the template parameter `T`. It can be used
|
||||
* to test against a ghoul::any value before trying to assign it.
|
||||
*
|
||||
* \return The type info object describing the template parameter `T`
|
||||
*/
|
||||
@@ -113,7 +112,6 @@ public:
|
||||
* decoding is successful, the new value is set, otherwise it remains unchanged.
|
||||
*
|
||||
* \param state The Lua state from which the value will be decoded
|
||||
* \return `true` if the decoding succeeded; `false` otherwise
|
||||
*/
|
||||
virtual void setLuaValue(lua_State* state) override;
|
||||
|
||||
@@ -128,19 +126,11 @@ public:
|
||||
*/
|
||||
virtual std::string stringValue() const override;
|
||||
|
||||
/**
|
||||
* Returns the description for this TemplateProperty as a Lua script that returns a
|
||||
* table on execution.
|
||||
*
|
||||
* \return The description for this TemplateProperty
|
||||
*/
|
||||
//virtual std::string description() override;
|
||||
|
||||
/**
|
||||
* This operator allows the TemplateProperty to be used almost transparently as if it
|
||||
* was of the type `T`. It makes assignments such as
|
||||
* `T v = property;` possible by allowing implicit casts (even though,
|
||||
* internally, not casts are performed. This method is next to zero overhead).
|
||||
* was of the type `T`. It makes assignments such as `T v = property;` possible by
|
||||
* allowing implicit casts (even though, internally, not casts are performed. This
|
||||
* method is next to zero overhead).
|
||||
*
|
||||
* \return The internal representation of the Property
|
||||
*/
|
||||
@@ -148,9 +138,9 @@ public:
|
||||
|
||||
/**
|
||||
* This operator allows the TemplateProperty to be used almost transparently as if it
|
||||
* was of the type `T`. It makes assignments such as
|
||||
* `T v = property;` possible by allowing implicit casts (even though,
|
||||
* internally, not casts are performed. This method is next to zero overhead).
|
||||
* was of the type `T`. It makes assignments such as `T v = property;` possible by
|
||||
* allowing implicit casts (even though, internally, not casts are performed. This
|
||||
* method is next to zero overhead).
|
||||
*
|
||||
* \return The internal representation of the Property
|
||||
*/
|
||||
@@ -166,10 +156,10 @@ public:
|
||||
TemplateProperty<T>& operator=(T val);
|
||||
|
||||
/**
|
||||
* This method sets the stored value to the provided value `val`,
|
||||
* moving it into place. The move only happens if the provided value `val`
|
||||
* is different from the stored value, which needs an operator== to exist for the type
|
||||
* `T`. If the value is different, the listeners are notified.
|
||||
* This method sets the stored value to the provided value `val`, moving it into
|
||||
* place. The move only happens if the provided value `val` is different from the
|
||||
* stored value, which needs an operator== to exist for the type `T`. If the value is
|
||||
* different, the listeners are notified.
|
||||
*
|
||||
* \param val The new value for this TemplateProperty
|
||||
*/
|
||||
@@ -184,17 +174,17 @@ public:
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Decodes the object at the top of the stack to a value of the type `T`
|
||||
* and returns it. This method has to be specialized for each new type.
|
||||
* Decodes the object at the top of the stack to a value of the type `T` and returns
|
||||
* it. This method has to be specialized for each new type.
|
||||
*
|
||||
* \param state The Lua state from which the value will be decoded
|
||||
* \return the decoded value
|
||||
* \return The decoded value
|
||||
*/
|
||||
virtual T fromLuaConversion(lua_State* state) const = 0;
|
||||
|
||||
/**
|
||||
* Encodes the stored value into a Lua object and pushes that object onto
|
||||
* the stack. This method has to be specialized for each new type.
|
||||
* Encodes the stored value into a Lua object and pushes that object onto the stack.
|
||||
* This method has to be specialized for each new type.
|
||||
*
|
||||
* \param state The Lua state onto which the encoded object will be pushed
|
||||
*/
|
||||
@@ -202,8 +192,8 @@ protected:
|
||||
|
||||
/**
|
||||
* Encodes the stored value into a std::string object, in a format that is a valid
|
||||
* JSON representation of the property. This method has to be specialized for each
|
||||
* new type.
|
||||
* JSON representation of the property. This method has to be specialized for each new
|
||||
* type.
|
||||
*
|
||||
* \return The resulting encoding
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
@@ -36,10 +36,11 @@ namespace openspace::properties {
|
||||
class TriggerProperty : public Property {
|
||||
public:
|
||||
/**
|
||||
* Initializes the TriggerProperty by delegating the `identifier` and
|
||||
* `guiName` to the Property constructor.
|
||||
* Initializes the TriggerProperty by delegating the `identifier` and `guiName` to the
|
||||
* Property constructor.
|
||||
*
|
||||
* \param info The PropertyInfo structure that contains all the required static
|
||||
* information for initializing this Property.
|
||||
* information for initializing this Property
|
||||
* \pre \p info.identifier must not be empty
|
||||
* \pre \p info.guiName must not be empty
|
||||
*/
|
||||
@@ -47,25 +48,32 @@ public:
|
||||
|
||||
/**
|
||||
* Returns the class name `TriggerProperty`.
|
||||
*
|
||||
* \return The class name `TriggerProperty`
|
||||
*/
|
||||
std::string_view className() const override;
|
||||
|
||||
/**
|
||||
* Accepts only the `LUA_TNIL` type and will notify all the listeners
|
||||
* that the event has been triggered.
|
||||
* Accepts only the `LUA_TNIL` type and will notify all the listeners that the event
|
||||
* has been triggered.
|
||||
*
|
||||
* \param state The unused Lua state
|
||||
* \return Returns always `true`
|
||||
*/
|
||||
void setLuaValue(lua_State* state) override;
|
||||
|
||||
/**
|
||||
* Silently ignores any value that is passed into this function and will trigger the
|
||||
* listeners regardless of the value
|
||||
*
|
||||
* \param value The ignored value
|
||||
*/
|
||||
void set(std::any value) override;
|
||||
|
||||
/**
|
||||
* Triggers this TriggerProperty.
|
||||
*/
|
||||
void trigger();
|
||||
|
||||
std::string jsonValue() const override;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2023 *
|
||||
* 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 *
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user