mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-01-05 19:19:39 -06:00
Merge remote-tracking branch 'origin/master' into thesis/2020/radiation
This commit is contained in:
@@ -203,6 +203,12 @@ begin_header("Configuring Applications")
|
||||
add_subdirectory("${OPENSPACE_APPS_DIR}")
|
||||
end_header("End: Configuring Applications")
|
||||
|
||||
|
||||
if (MSVC AND TARGET OpenSpace)
|
||||
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT OpenSpace)
|
||||
endif()
|
||||
|
||||
|
||||
option(OPENSPACE_HAVE_TESTS "Activate the OpenSpace unit tests" ON)
|
||||
if (OPENSPACE_HAVE_TESTS)
|
||||
begin_header("Generating OpenSpace unit test")
|
||||
|
||||
@@ -660,6 +660,17 @@ void mainCharCallback(unsigned int codepoint, int modifiers) {
|
||||
|
||||
|
||||
|
||||
void mainDropCallback(int amount, const char** paths) {
|
||||
ghoul_assert(amount > 0, "Expected at least one file path");
|
||||
ghoul_assert(paths, "expected non-nullptr");
|
||||
|
||||
for (int i = 0; i < amount; ++i) {
|
||||
global::openSpaceEngine->handleDragDrop(paths[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<std::byte> mainEncodeFun() {
|
||||
ZoneScoped
|
||||
LTRACE("main::mainEncodeFun(begin)");
|
||||
@@ -1025,7 +1036,6 @@ int main(int argc, char* argv[]) {
|
||||
{
|
||||
using namespace ghoul::logging;
|
||||
LogManager::initialize(LogLevel::Debug, LogManager::ImmediateFlush::Yes);
|
||||
LogMgr.addLog(std::make_unique<ConsoleLog>());
|
||||
#ifdef WIN32
|
||||
if (IsDebuggerPresent()) {
|
||||
LogMgr.addLog(std::make_unique<ghoul::logging::VisualStudioOutputLog>());
|
||||
@@ -1252,6 +1262,7 @@ int main(int argc, char* argv[]) {
|
||||
callbacks.mousePos = mainMousePosCallback;
|
||||
callbacks.mouseScroll = mainMouseScrollCallback;
|
||||
callbacks.character = mainCharCallback;
|
||||
callbacks.drop = mainDropCallback;
|
||||
callbacks.encode = mainEncodeFun;
|
||||
callbacks.decode = mainDecodeFun;
|
||||
Log::instance().setNotifyLevel(Log::Level::Debug);
|
||||
|
||||
@@ -4,6 +4,14 @@ local DataPath = asset.syncedResource({
|
||||
Identifier = "exoplanets_data",
|
||||
Version = 2
|
||||
})
|
||||
|
||||
asset.onInitialize(function ()
|
||||
local p = "Modules.Exoplanets.DataFolder";
|
||||
if(openspace.getPropertyValue(p) == "") then
|
||||
openspace.setPropertyValueSingle(p, DataPath)
|
||||
end
|
||||
end)
|
||||
|
||||
asset.export("DataPath", DataPath)
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
asset.require('./../habitable_zones/habitable_zone_textures')
|
||||
local habitableZoneTextures =
|
||||
asset.require('./../habitable_zones/habitable_zone_textures').TexturesPath
|
||||
|
||||
local TexturesPath = asset.syncedResource({
|
||||
Name = "Exoplanet Textures",
|
||||
@@ -6,6 +7,37 @@ local TexturesPath = asset.syncedResource({
|
||||
Identifier = "exoplanets_textures",
|
||||
Version = 2
|
||||
})
|
||||
|
||||
asset.onInitialize(function ()
|
||||
local starTexture = TexturesPath .. "/sun.jpg"
|
||||
local noDataTexture = TexturesPath .. "/grid-32.png"
|
||||
local discTexture = TexturesPath .. "/disc_bw_texture.png"
|
||||
|
||||
local hzTexture = habitableZoneTextures .. "/hot_to_cold_faded.png"
|
||||
|
||||
-- Set the default textures used for the exoplanet system creation
|
||||
-- (Check if already set, to not override value in config file)
|
||||
local p = "Modules.Exoplanets.StarTexture";
|
||||
if(openspace.getPropertyValue(p) == "") then
|
||||
openspace.setPropertyValueSingle(p, starTexture)
|
||||
end
|
||||
|
||||
p = "Modules.Exoplanets.NoDataTexture";
|
||||
if(openspace.getPropertyValue(p) == "") then
|
||||
openspace.setPropertyValueSingle(p, noDataTexture)
|
||||
end
|
||||
|
||||
p = "Modules.Exoplanets.OrbitDiscTexture";
|
||||
if(openspace.getPropertyValue(p) == "") then
|
||||
openspace.setPropertyValueSingle(p, discTexture)
|
||||
end
|
||||
|
||||
p = "Modules.Exoplanets.HabitableZoneTexture";
|
||||
if(openspace.getPropertyValue(p) == "") then
|
||||
openspace.setPropertyValueSingle(p, hzTexture)
|
||||
end
|
||||
end)
|
||||
|
||||
asset.export("TexturesPath", TexturesPath)
|
||||
|
||||
asset.meta = {
|
||||
|
||||
@@ -85,7 +85,9 @@ function satellites(title, file, color, group)
|
||||
SegmentQuality = 3,
|
||||
Color = color,
|
||||
Fade = 1.5,
|
||||
RenderBinMode = "PostDeferredTransparent"
|
||||
RenderBinMode = "PostDeferredTransparent",
|
||||
StartRenderIdx = group.StartRenderIdx,
|
||||
RenderSize = group.RenderSize
|
||||
},
|
||||
Tag = { "earth_satellites" },
|
||||
GUI = {
|
||||
|
||||
Submodule ext/ghoul updated: d850c7bae1...d7dd0a7144
@@ -66,6 +66,8 @@ struct TestResult {
|
||||
std::string offender;
|
||||
/// The Reason that caused this offense
|
||||
Reason reason;
|
||||
/// An optional explanation for when a verification fails
|
||||
std::string explanation;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -79,7 +81,7 @@ struct TestResult {
|
||||
* The reason for the warning
|
||||
*/
|
||||
enum class Reason {
|
||||
Deprecated ///< The value is marked as deprecated and should not used
|
||||
Deprecated ///< The value is marked as deprecated and should not used
|
||||
};
|
||||
|
||||
/// The offending key that caused the Warning. In the case of a nested table,
|
||||
|
||||
@@ -158,6 +158,28 @@ struct StringVerifier : public TemplateVerifier<std::string> {
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Verifier that checks whether a given key inside a ghoul::Dictionary is a string and
|
||||
* refers to an existing file on disk.
|
||||
*/
|
||||
struct FileVerifier : public StringVerifier {
|
||||
TestResult operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const override;
|
||||
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Verifier that checks whether a given key inside a ghoul::Dictionary is a string and
|
||||
* refers to an existing directory on disk.
|
||||
*/
|
||||
struct DirectoryVerifier : public StringVerifier {
|
||||
TestResult operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const override;
|
||||
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Verifier that checks whether a given key inside a ghoul::Dictionary is another
|
||||
* ghoul::Dictionary. The constructor takes a list of DocumentationEntry%s, which are used
|
||||
@@ -243,39 +265,48 @@ struct IntListVerifier : public TableVerifier {
|
||||
*/
|
||||
struct VectorVerifier {};
|
||||
|
||||
/**
|
||||
* This Verifier checks whether the value is of type <code>glm::tvec2<T></code>
|
||||
*/
|
||||
/// This Verifier checks whether the value is of type <code>glm::tvec2<T></code>
|
||||
template <typename T>
|
||||
struct Vector2Verifier : public TemplateVerifier<glm::tvec2<T>>, public VectorVerifier {
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* This Verifier checks whether the value is of type <code>glm::tvec3<T></code>
|
||||
*/
|
||||
/// This Verifier checks whether the value is of type <code>glm::tvec3<T></code>
|
||||
template <typename T>
|
||||
struct Vector3Verifier : public TemplateVerifier<glm::tvec3<T>>, public VectorVerifier {
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* This Verifier checks whether the value is of type <code>glm::tvec4<T></code>
|
||||
*/
|
||||
/// This Verifier checks whether the value is of type <code>glm::tvec4<T></code>
|
||||
template <typename T>
|
||||
struct Vector4Verifier : public TemplateVerifier<glm::tvec4<T>>, public VectorVerifier {
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
struct Color3Verifier : public Vector3Verifier<double> {
|
||||
TestResult operator()(const ghoul::Dictionary& dictionary,
|
||||
const std::string& key) const override;
|
||||
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
struct Color4Verifier : public Vector4Verifier<double> {
|
||||
TestResult operator()(const ghoul::Dictionary& dictionary,
|
||||
const std::string& key) const override;
|
||||
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Verifier that checks whether all values contained in a Table are of
|
||||
* type <code>glm::tvec2<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Vector2ListVerifier : public TableVerifier {
|
||||
Vector2ListVerifier(std::string elementDocumentation = "") : TableVerifier({
|
||||
Vector2ListVerifier(std::string elementDocumentation = "")
|
||||
: TableVerifier({
|
||||
{ "*", new Vector2Verifier<T>, Optional::No, std::move(elementDocumentation) }
|
||||
})
|
||||
})
|
||||
{}
|
||||
|
||||
std::string type() const override {
|
||||
@@ -289,9 +320,10 @@ struct Vector2ListVerifier : public TableVerifier {
|
||||
*/
|
||||
template <typename T>
|
||||
struct Vector3ListVerifier : public TableVerifier {
|
||||
Vector3ListVerifier(std::string elementDocumentation = "") : TableVerifier({
|
||||
{ "*", new Vector3Verifier<T>, Optional::No, std::move(elementDocumentation) }
|
||||
})
|
||||
Vector3ListVerifier(std::string elementDocumentation = "")
|
||||
: TableVerifier({
|
||||
{ "*", new Vector3Verifier<T>, Optional::No, std::move(elementDocumentation) }
|
||||
})
|
||||
{}
|
||||
|
||||
std::string type() const override {
|
||||
@@ -305,15 +337,17 @@ struct Vector3ListVerifier : public TableVerifier {
|
||||
*/
|
||||
template <typename T>
|
||||
struct Vector4ListVerifier : public TableVerifier {
|
||||
Vector4ListVerifier(std::string elementDocumentation = "") : TableVerifier({
|
||||
{ "*", new Vector4Verifier<T>, Optional::No, std::move(elementDocumentation) }
|
||||
})
|
||||
Vector4ListVerifier(std::string elementDocumentation = "")
|
||||
: TableVerifier({
|
||||
{ "*", new Vector4Verifier<T>, Optional::No, std::move(elementDocumentation) }
|
||||
})
|
||||
{}
|
||||
|
||||
std::string type() const override {
|
||||
return "List of ints";
|
||||
}
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// Matrix verifiers
|
||||
//----------------------------------------------------------------------------------------
|
||||
@@ -330,8 +364,7 @@ struct MatrixVerifier {};
|
||||
* This Verifier checks whether the value is of type <code>glm::mat2x2<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix2x2Verifier :
|
||||
public TemplateVerifier<glm::tmat2x2<T>>, public MatrixVerifier
|
||||
struct Matrix2x2Verifier : public TemplateVerifier<glm::tmat2x2<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
@@ -340,8 +373,8 @@ struct Matrix2x2Verifier :
|
||||
* This Verifier checks whether the value is of type <code>glm::mat2x3<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix2x3Verifier :
|
||||
public TemplateVerifier<glm::tmat2x3<T>>, public MatrixVerifier {
|
||||
struct Matrix2x3Verifier : public TemplateVerifier<glm::tmat2x3<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
@@ -349,8 +382,8 @@ struct Matrix2x3Verifier :
|
||||
* This Verifier checks whether the value is of type <code>glm::mat2x4<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix2x4Verifier :
|
||||
public TemplateVerifier<glm::tmat2x4<T>>, public MatrixVerifier {
|
||||
struct Matrix2x4Verifier : public TemplateVerifier<glm::tmat2x4<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
@@ -358,8 +391,8 @@ struct Matrix2x4Verifier :
|
||||
* This Verifier checks whether the value is of type <code>glm::mat3x2<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix3x2Verifier :
|
||||
public TemplateVerifier<glm::tmat3x2<T>>, public MatrixVerifier {
|
||||
struct Matrix3x2Verifier : public TemplateVerifier<glm::tmat3x2<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
@@ -367,8 +400,8 @@ struct Matrix3x2Verifier :
|
||||
* This Verifier checks whether the value is of type <code>glm::mat3x3<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix3x3Verifier :
|
||||
public TemplateVerifier<glm::tmat3x3<T>>, public MatrixVerifier {
|
||||
struct Matrix3x3Verifier : public TemplateVerifier<glm::tmat3x3<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
@@ -376,8 +409,8 @@ struct Matrix3x3Verifier :
|
||||
* This Verifier checks whether the value is of type <code>glm::mat3x4<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix3x4Verifier :
|
||||
public TemplateVerifier<glm::tmat3x4<T>>, public MatrixVerifier {
|
||||
struct Matrix3x4Verifier : public TemplateVerifier<glm::tmat3x4<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
@@ -385,8 +418,8 @@ struct Matrix3x4Verifier :
|
||||
* This Verifier checks whether the value is of type <code>glm::mat4x2<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix4x2Verifier :
|
||||
public TemplateVerifier<glm::tmat4x2<T>>, public MatrixVerifier {
|
||||
struct Matrix4x2Verifier : public TemplateVerifier<glm::tmat4x2<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
@@ -394,8 +427,8 @@ struct Matrix4x2Verifier :
|
||||
* This Verifier checks whether the value is of type <code>glm::mat4x3<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix4x3Verifier :
|
||||
public TemplateVerifier<glm::tmat4x3<T>>, public MatrixVerifier {
|
||||
struct Matrix4x3Verifier : public TemplateVerifier<glm::tmat4x3<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
@@ -403,8 +436,8 @@ struct Matrix4x3Verifier :
|
||||
* This Verifier checks whether the value is of type <code>glm::mat4x4<T></code>
|
||||
*/
|
||||
template <typename T>
|
||||
struct Matrix4x4Verifier :
|
||||
public TemplateVerifier<glm::tmat4x4<T>>, public MatrixVerifier {
|
||||
struct Matrix4x4Verifier : public TemplateVerifier<glm::tmat4x4<T>>, public MatrixVerifier
|
||||
{
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
@@ -465,18 +498,11 @@ struct OperatorVerifier : public T {
|
||||
*/
|
||||
template <typename T>
|
||||
struct LessVerifier : public OperatorVerifier<T, std::less<typename T::Type>> {
|
||||
static_assert(!std::is_base_of<BoolVerifier, T>::value, "T cannot be BoolVerifier");
|
||||
static_assert(
|
||||
!std::is_base_of<BoolVerifier, T>::value,
|
||||
"T cannot be BoolVerifier"
|
||||
);
|
||||
static_assert(
|
||||
!std::is_base_of<StringVerifier, T>::value,
|
||||
"T cannot be StringVerifier"
|
||||
);
|
||||
static_assert(
|
||||
!std::is_base_of<TableVerifier, T>::value,
|
||||
"T cannot be TableVerifier"
|
||||
!std::is_base_of<StringVerifier, T>::value, "T cannot be StringVerifier"
|
||||
);
|
||||
static_assert(!std::is_base_of<TableVerifier, T>::value, "T cannot be TableVerifier");
|
||||
static_assert(
|
||||
!std::is_base_of<VectorVerifier, T>::value,
|
||||
"T cannot be VectorVerifier"
|
||||
@@ -496,18 +522,12 @@ struct LessVerifier : public OperatorVerifier<T, std::less<typename T::Type>> {
|
||||
*/
|
||||
template <typename T>
|
||||
struct LessEqualVerifier : public OperatorVerifier<T, std::less_equal<typename T::Type>> {
|
||||
static_assert(
|
||||
!std::is_base_of<BoolVerifier, T>::value,
|
||||
"T cannot be BoolVerifier"
|
||||
);
|
||||
static_assert(!std::is_base_of<BoolVerifier, T>::value, "T cannot be BoolVerifier");
|
||||
static_assert(
|
||||
!std::is_base_of<StringVerifier, T>::value,
|
||||
"T cannot be StringVerifier"
|
||||
);
|
||||
static_assert(
|
||||
!std::is_base_of<TableVerifier, T>::value,
|
||||
"T cannot be TableVerifier"
|
||||
);
|
||||
static_assert(!std::is_base_of<TableVerifier, T>::value, "T cannot be TableVerifier");
|
||||
static_assert(
|
||||
!std::is_base_of<VectorVerifier, T>::value,
|
||||
"T cannot be VectorVerifier"
|
||||
@@ -527,22 +547,16 @@ struct LessEqualVerifier : public OperatorVerifier<T, std::less_equal<typename T
|
||||
*/
|
||||
template <typename T>
|
||||
struct GreaterVerifier : public OperatorVerifier<T, std::greater<typename T::Type>> {
|
||||
static_assert(
|
||||
!std::is_base_of<BoolVerifier, T>::value,
|
||||
"T cannot be BoolVerifier"
|
||||
);
|
||||
static_assert(!std::is_base_of<BoolVerifier, T>::value, "T cannot be BoolVerifier");
|
||||
static_assert(
|
||||
!std::is_base_of<StringVerifier, T>::value,
|
||||
"T cannot be StringVerifier"
|
||||
);
|
||||
static_assert(
|
||||
!std::is_base_of<TableVerifier, T>::value,
|
||||
"T cannot be TableVerifier"
|
||||
);
|
||||
);
|
||||
static_assert(!std::is_base_of<TableVerifier, T>::value, "T cannot be TableVerifier");
|
||||
static_assert(
|
||||
!std::is_base_of<VectorVerifier, T>::value,
|
||||
"T cannot be VectorVerifier"
|
||||
);
|
||||
);
|
||||
|
||||
using OperatorVerifier<T, std::greater<typename T::Type>>::OperatorVerifier;
|
||||
|
||||
@@ -560,18 +574,12 @@ template <typename T>
|
||||
struct GreaterEqualVerifier : public OperatorVerifier<T,
|
||||
std::greater_equal<typename T::Type>>
|
||||
{
|
||||
static_assert(
|
||||
!std::is_base_of<BoolVerifier, T>::value,
|
||||
"T cannot be BoolVerifier"
|
||||
);
|
||||
static_assert(!std::is_base_of<BoolVerifier, T>::value, "T cannot be BoolVerifier");
|
||||
static_assert(
|
||||
!std::is_base_of<StringVerifier, T>::value,
|
||||
"T cannot be StringVerifier"
|
||||
);
|
||||
static_assert(
|
||||
!std::is_base_of<TableVerifier, T>::value,
|
||||
"T cannot be TableVerifier"
|
||||
);
|
||||
static_assert(!std::is_base_of<TableVerifier, T>::value, "T cannot be TableVerifier");
|
||||
static_assert(
|
||||
!std::is_base_of<VectorVerifier, T>::value,
|
||||
"T cannot be VectorVerifier"
|
||||
|
||||
@@ -86,6 +86,7 @@ public:
|
||||
void touchDetectionCallback(TouchInput input);
|
||||
void touchUpdateCallback(TouchInput input);
|
||||
void touchExitCallback(TouchInput input);
|
||||
void handleDragDrop(const std::string& file);
|
||||
std::vector<std::byte> encode();
|
||||
void decode(std::vector<std::byte> data);
|
||||
|
||||
|
||||
@@ -438,13 +438,11 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
|
||||
);
|
||||
_program->setUniform(
|
||||
_uniformCache.lightIntensities,
|
||||
_lightIntensitiesBuffer.data(),
|
||||
nLightSources
|
||||
_lightIntensitiesBuffer
|
||||
);
|
||||
_program->setUniform(
|
||||
_uniformCache.lightDirectionsViewSpace,
|
||||
_lightDirectionsViewSpaceBuffer.data(),
|
||||
nLightSources
|
||||
_lightDirectionsViewSpaceBuffer
|
||||
);
|
||||
_program->setUniform(
|
||||
_uniformCache.modelViewTransform,
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <ghoul/misc/profiling.h>
|
||||
#include <ghoul/opengl/programobject.h>
|
||||
#include <cmath>
|
||||
#include <optional>
|
||||
|
||||
namespace {
|
||||
constexpr const char* ProgramName = "EphemerisProgram";
|
||||
@@ -144,64 +145,44 @@ namespace {
|
||||
"atmospheres if needed."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableTrail)]] Parameters {
|
||||
// This object is used to compute locations along the path. Any Translation object
|
||||
// can be used here
|
||||
std::monostate translation [[codegen::reference("core_transform_translation")]];
|
||||
|
||||
// [[codegen::verbatim(LineColorInfo.description)]]
|
||||
glm::vec3 color [[codegen::color()]];
|
||||
|
||||
// [[codegen::verbatim(EnableFadeInfo.description)]]
|
||||
std::optional<bool> enableFade;
|
||||
|
||||
// [[codegen::verbatim(FadeInfo.description)]]
|
||||
std::optional<float> fade;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<float> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(PointSizeInfo.description)]]
|
||||
std::optional<int> pointSize;
|
||||
|
||||
enum class RenderingMode {
|
||||
Lines,
|
||||
Points,
|
||||
LinesPoints [[codegen::key("Lines+Points")]],
|
||||
PointsLines [[codegen::key("Lines+Points")]]
|
||||
};
|
||||
// [[codegen::verbatim(RenderingModeInfo.description)]]
|
||||
std::optional<RenderingMode> renderingMode [[codegen::key("Rendering")]];
|
||||
};
|
||||
#include "renderabletrail_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableTrail::Documentation() {
|
||||
using namespace documentation;
|
||||
return {
|
||||
"RenderableTrail",
|
||||
"base_renderable_renderabletrail",
|
||||
{
|
||||
{
|
||||
KeyTranslation,
|
||||
new ReferencingVerifier("core_transform_translation"),
|
||||
Optional::No,
|
||||
"This object is used to compute locations along the path. Any "
|
||||
"Translation object can be used here."
|
||||
},
|
||||
{
|
||||
LineColorInfo.identifier,
|
||||
new DoubleVector3Verifier,
|
||||
Optional::No,
|
||||
LineColorInfo.description
|
||||
},
|
||||
{
|
||||
EnableFadeInfo.identifier,
|
||||
new BoolVerifier,
|
||||
Optional::Yes,
|
||||
EnableFadeInfo.description
|
||||
},
|
||||
{
|
||||
FadeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
FadeInfo.description
|
||||
},
|
||||
{
|
||||
LineWidthInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
LineWidthInfo.description
|
||||
},
|
||||
{
|
||||
PointSizeInfo.identifier,
|
||||
new DoubleVerifier,
|
||||
Optional::Yes,
|
||||
PointSizeInfo.description
|
||||
},
|
||||
{
|
||||
RenderingModeInfo.identifier,
|
||||
new StringInListVerifier(
|
||||
// Taken from the RenderingModeConversion map above
|
||||
{ "Lines", "Points", "Lines+Points", "Points+Lines" }
|
||||
),
|
||||
Optional::Yes,
|
||||
RenderingModeInfo.description
|
||||
}
|
||||
}
|
||||
};
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "base_renderable_renderabletrail";
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableTrail::Appearance::Appearance()
|
||||
@@ -233,6 +214,8 @@ RenderableTrail::Appearance::Appearance()
|
||||
RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
setRenderBin(RenderBin::Overlay);
|
||||
addProperty(_opacity);
|
||||
|
||||
@@ -241,36 +224,25 @@ RenderableTrail::RenderableTrail(const ghoul::Dictionary& dictionary)
|
||||
);
|
||||
addPropertySubOwner(_translation.get());
|
||||
|
||||
_appearance.lineColor = dictionary.value<glm::dvec3>(LineColorInfo.identifier);
|
||||
_appearance.lineColor = p.color;
|
||||
_appearance.useLineFade = p.enableFade.value_or(_appearance.useLineFade);
|
||||
_appearance.lineFade = p.fade.value_or(_appearance.lineFade);
|
||||
_appearance.lineWidth = p.lineWidth.value_or(_appearance.lineWidth);
|
||||
_appearance.pointSize = p.pointSize.value_or(_appearance.pointSize);
|
||||
|
||||
if (dictionary.hasValue<bool>(EnableFadeInfo.identifier)) {
|
||||
_appearance.useLineFade = dictionary.value<bool>(EnableFadeInfo.identifier);
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<double>(FadeInfo.identifier)) {
|
||||
_appearance.lineFade = static_cast<float>(
|
||||
dictionary.value<double>(FadeInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<double>(LineWidthInfo.identifier)) {
|
||||
_appearance.lineWidth = static_cast<float>(dictionary.value<double>(
|
||||
LineWidthInfo.identifier
|
||||
));
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<double>(PointSizeInfo.identifier)) {
|
||||
_appearance.pointSize = static_cast<int>(
|
||||
dictionary.value<double>(PointSizeInfo.identifier)
|
||||
);
|
||||
}
|
||||
|
||||
// This map is not accessed out of order as long as the Documentation is adapted
|
||||
// whenever the map changes. The documentation will check for valid values
|
||||
if (dictionary.hasValue<std::string>(RenderingModeInfo.identifier)) {
|
||||
_appearance.renderingModes = RenderingModeConversion.at(
|
||||
dictionary.value<std::string>(RenderingModeInfo.identifier)
|
||||
);
|
||||
if (p.renderingMode.has_value()) {
|
||||
switch (*p.renderingMode) {
|
||||
case Parameters::RenderingMode::Lines:
|
||||
_appearance.renderingModes = RenderingModeLines;
|
||||
break;
|
||||
case Parameters::RenderingMode::Points:
|
||||
_appearance.renderingModes = RenderingModePoints;
|
||||
break;
|
||||
case Parameters::RenderingMode::LinesPoints:
|
||||
case Parameters::RenderingMode::PointsLines:
|
||||
_appearance.renderingModes = RenderingModeLinesPoints;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
_appearance.renderingModes = RenderingModeLines;
|
||||
|
||||
@@ -38,11 +38,166 @@
|
||||
|
||||
#include "exoplanetsmodule_lua.inl"
|
||||
|
||||
namespace {
|
||||
constexpr const openspace::properties::Property::PropertyInfo DataFolderInfo = {
|
||||
"DataFolder",
|
||||
"Data Folder",
|
||||
"The path to the folder containing the exoplanets data and lookup table"
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo StarTextureInfo = {
|
||||
"StarTexture",
|
||||
"Star Texture",
|
||||
"The path to a grayscale image that is used for the host star surfaces"
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo NoDataTextureInfo = {
|
||||
"NoDataTexture",
|
||||
"No Data Star Texture",
|
||||
"A path to a texture that is used to represent that there is missing data about "
|
||||
"the star. For example no color information"
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo OrbitDiscTextureInfo =
|
||||
{
|
||||
"OrbitDiscTexture",
|
||||
"Orbit Disc Texture",
|
||||
"A path to a 1-dimensional image used as a transfer function for the "
|
||||
"exoplanets' orbit uncertainty disc"
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo
|
||||
HabitableZoneTextureInfo =
|
||||
{
|
||||
"HabitableZoneTexture",
|
||||
"Habitable Zone Texture",
|
||||
"A path to a 1-dimensional image used as a transfer function for the "
|
||||
"habitable zone disc"
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo
|
||||
ShowComparisonCircleInfo =
|
||||
{
|
||||
"ShowComparisonCircle",
|
||||
"Show Comparison Circle",
|
||||
"If true, the 1 AU size comparison circle is enabled per default when an "
|
||||
"exoplanet system is created"
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo
|
||||
ShowHabitableZoneInfo =
|
||||
{
|
||||
"ShowHabitableZone",
|
||||
"Show Habitable Zone",
|
||||
"If true, the habitable zone disc is enabled per default when an "
|
||||
"exoplanet system is created"
|
||||
};
|
||||
|
||||
constexpr const openspace::properties::Property::PropertyInfo UseOptimisticZoneInfo =
|
||||
{
|
||||
"UseOptimisticZone",
|
||||
"Use Optimistic Zone Boundaries",
|
||||
"If true, the habitable zone is computed with optimistic boundaries per default "
|
||||
"when an exoplanet system is created"
|
||||
};
|
||||
|
||||
constexpr const char ExoplanetsDataFileName[] = "exoplanets_data.bin";
|
||||
constexpr const char LookupTableFileName[] = "lookup.txt";
|
||||
|
||||
struct [[codegen::Dictionary(ExoplanetsModule)]] Parameters {
|
||||
// [[codegen::verbatim(DataFolderInfo.description)]]
|
||||
std::optional<std::string> dataFolder;
|
||||
|
||||
// [[codegen::verbatim(StarTextureInfo.description)]]
|
||||
std::optional<std::string> starTexture;
|
||||
|
||||
// [[codegen::verbatim(NoDataTextureInfo.description)]]
|
||||
std::optional<std::string> noDataTexture;
|
||||
|
||||
// [[codegen::verbatim(OrbitDiscTextureInfo.description)]]
|
||||
std::optional<std::string> orbitDiscTexture;
|
||||
|
||||
// [[codegen::verbatim(HabitableZoneTextureInfo.description)]]
|
||||
std::optional<std::string> habitableZoneTexture;
|
||||
|
||||
// [[codegen::verbatim(ShowComparisonCircleInfo.description)]]
|
||||
std::optional<bool> showComparisonCircle;
|
||||
|
||||
// [[codegen::verbatim(ShowHabitableZoneInfo.description)]]
|
||||
std::optional<bool> showHabitableZone;
|
||||
|
||||
// [[codegen::verbatim(UseOptimisticZoneInfo.description)]]
|
||||
std::optional<bool> useOptimisticZone;
|
||||
};
|
||||
#include "exoplanetsmodule_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
using namespace exoplanets;
|
||||
|
||||
ExoplanetsModule::ExoplanetsModule() : OpenSpaceModule(Name) {}
|
||||
ExoplanetsModule::ExoplanetsModule()
|
||||
: OpenSpaceModule(Name)
|
||||
, _exoplanetsDataFolder(DataFolderInfo)
|
||||
, _starTexturePath(StarTextureInfo)
|
||||
, _noDataTexturePath(NoDataTextureInfo)
|
||||
, _orbitDiscTexturePath(OrbitDiscTextureInfo)
|
||||
, _habitableZoneTexturePath(HabitableZoneTextureInfo)
|
||||
, _showComparisonCircle(ShowComparisonCircleInfo, false)
|
||||
, _showHabitableZone(ShowHabitableZoneInfo, true)
|
||||
, _useOptimisticZone(UseOptimisticZoneInfo, true)
|
||||
{
|
||||
_exoplanetsDataFolder.setReadOnly(true);
|
||||
|
||||
addProperty(_exoplanetsDataFolder);
|
||||
addProperty(_starTexturePath);
|
||||
addProperty(_noDataTexturePath);
|
||||
addProperty(_orbitDiscTexturePath);
|
||||
addProperty(_habitableZoneTexturePath);
|
||||
addProperty(_showComparisonCircle);
|
||||
addProperty(_showHabitableZone);
|
||||
addProperty(_useOptimisticZone);
|
||||
}
|
||||
|
||||
std::string ExoplanetsModule::exoplanetsDataPath() const {
|
||||
return absPath(
|
||||
fmt::format("{}/{}", _exoplanetsDataFolder, ExoplanetsDataFileName)
|
||||
);
|
||||
};
|
||||
|
||||
std::string ExoplanetsModule::lookUpTablePath() const {
|
||||
return absPath(
|
||||
fmt::format("{}/{}", _exoplanetsDataFolder, LookupTableFileName)
|
||||
);
|
||||
};
|
||||
|
||||
std::string ExoplanetsModule::starTexturePath() const {
|
||||
return _starTexturePath;
|
||||
}
|
||||
|
||||
std::string ExoplanetsModule::noDataTexturePath() const {
|
||||
return _noDataTexturePath;
|
||||
}
|
||||
|
||||
std::string ExoplanetsModule::orbitDiscTexturePath() const {
|
||||
return _orbitDiscTexturePath;
|
||||
}
|
||||
|
||||
std::string ExoplanetsModule::habitableZoneTexturePath() const {
|
||||
return _habitableZoneTexturePath;
|
||||
}
|
||||
|
||||
bool ExoplanetsModule::showComparisonCircle() const {
|
||||
return _showComparisonCircle;
|
||||
}
|
||||
|
||||
bool ExoplanetsModule::showHabitableZone() const {
|
||||
return _showHabitableZone;
|
||||
}
|
||||
|
||||
bool ExoplanetsModule::useOptimisticZone() const {
|
||||
return _useOptimisticZone;
|
||||
}
|
||||
|
||||
scripting::LuaLibrary ExoplanetsModule::luaLibrary() const {
|
||||
scripting::LuaLibrary res;
|
||||
@@ -83,7 +238,18 @@ scripting::LuaLibrary ExoplanetsModule::luaLibrary() const {
|
||||
return res;
|
||||
}
|
||||
|
||||
void ExoplanetsModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
void ExoplanetsModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
const Parameters p = codegen::bake<Parameters>(dict);
|
||||
_exoplanetsDataFolder = p.dataFolder.value_or(_exoplanetsDataFolder);
|
||||
_starTexturePath = p.starTexture.value_or(_starTexturePath);
|
||||
_noDataTexturePath = p.noDataTexture.value_or(_noDataTexturePath);
|
||||
_orbitDiscTexturePath = p.orbitDiscTexture.value_or(_orbitDiscTexturePath);
|
||||
_habitableZoneTexturePath = p.habitableZoneTexture.value_or(_habitableZoneTexturePath);
|
||||
|
||||
_showComparisonCircle = p.showComparisonCircle.value_or(_showComparisonCircle);
|
||||
_showHabitableZone = p.showHabitableZone.value_or(_showHabitableZone);
|
||||
_useOptimisticZone = p.useOptimisticZone.value_or(_useOptimisticZone);
|
||||
|
||||
auto fTask = FactoryManager::ref().factory<Task>();
|
||||
auto fRenderable = FactoryManager::ref().factory<Renderable>();
|
||||
ghoul_assert(fTask, "No task factory existed");
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -38,11 +40,30 @@ public:
|
||||
ExoplanetsModule();
|
||||
virtual ~ExoplanetsModule() = default;
|
||||
|
||||
std::string exoplanetsDataPath() const;
|
||||
std::string lookUpTablePath() const;
|
||||
std::string starTexturePath() const;
|
||||
std::string noDataTexturePath() const;
|
||||
std::string orbitDiscTexturePath() const;
|
||||
std::string habitableZoneTexturePath() const;
|
||||
bool showComparisonCircle() const;
|
||||
bool showHabitableZone() const;
|
||||
bool useOptimisticZone() const;
|
||||
|
||||
scripting::LuaLibrary luaLibrary() const override;
|
||||
std::vector<documentation::Documentation> documentations() const override;
|
||||
|
||||
protected:
|
||||
void internalInitialize(const ghoul::Dictionary&) override;
|
||||
void internalInitialize(const ghoul::Dictionary& dict) override;
|
||||
|
||||
properties::StringProperty _exoplanetsDataFolder;
|
||||
properties::StringProperty _starTexturePath;
|
||||
properties::StringProperty _noDataTexturePath;
|
||||
properties::StringProperty _orbitDiscTexturePath;
|
||||
properties::StringProperty _habitableZoneTexturePath;
|
||||
properties::BoolProperty _showComparisonCircle;
|
||||
properties::BoolProperty _showHabitableZone;
|
||||
properties::BoolProperty _useOptimisticZone;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <modules/exoplanets/exoplanetshelper.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
#include <openspace/query/query.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
@@ -40,47 +41,42 @@
|
||||
|
||||
namespace {
|
||||
constexpr const char _loggerCat[] = "ExoplanetsModule";
|
||||
|
||||
constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/";
|
||||
|
||||
// Lua cannot handle backslashes, so replace these with forward slashes
|
||||
std::string formatPathToLua(const std::string& path) {
|
||||
std::string resPath = path;
|
||||
std::replace(resPath.begin(), resPath.end(), '\\', '/');
|
||||
return resPath;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace openspace::exoplanets::luascriptfunctions {
|
||||
|
||||
constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/";
|
||||
|
||||
constexpr const char LookUpTablePath[] = "${SYNC}/http/exoplanets_data/2/lookup.txt";
|
||||
constexpr const char ExoplanetsDataPath[] =
|
||||
"${SYNC}/http/exoplanets_data/2/exoplanets_data.bin";
|
||||
|
||||
constexpr const char StarTextureFile[] = "${SYNC}/http/exoplanets_textures/2/sun.jpg";
|
||||
constexpr const char NoDataTextureFile[] =
|
||||
"${SYNC}/http/exoplanets_textures/2/grid-32.png";
|
||||
constexpr const char DiscTextureFile[] =
|
||||
"${SYNC}/http/exoplanets_textures/2/disc_bw_texture.png";
|
||||
constexpr const char HabitableZoneTextureFile[] =
|
||||
"${SYNC}/http/habitable_zone_textures/1/hot_to_cold_faded.png";
|
||||
|
||||
constexpr const float AU = static_cast<float>(distanceconstants::AstronomicalUnit);
|
||||
constexpr const float SolarRadius = static_cast<float>(distanceconstants::SolarRadius);
|
||||
constexpr const float JupiterRadius = static_cast<float>(distanceconstants::JupiterRadius);
|
||||
|
||||
ExoplanetSystem findExoplanetSystemInData(std::string_view starName) {
|
||||
ExoplanetSystem system;
|
||||
const ExoplanetsModule* module = global::moduleEngine->module<ExoplanetsModule>();
|
||||
|
||||
std::ifstream data(absPath(ExoplanetsDataPath), std::ios::in | std::ios::binary);
|
||||
const std::string binPath = module->exoplanetsDataPath();
|
||||
std::ifstream data(absPath(binPath), std::ios::in | std::ios::binary);
|
||||
if (!data.good()) {
|
||||
LERROR(fmt::format(
|
||||
"Failed to open exoplanets data file: '{}'", absPath(ExoplanetsDataPath)
|
||||
));
|
||||
LERROR(fmt::format("Failed to open exoplanets data file: '{}'", binPath));
|
||||
return ExoplanetSystem();
|
||||
}
|
||||
|
||||
std::ifstream lut(absPath(LookUpTablePath));
|
||||
const std::string lutPath = module->lookUpTablePath();
|
||||
std::ifstream lut(absPath(lutPath));
|
||||
if (!lut.good()) {
|
||||
LERROR(fmt::format(
|
||||
"Failed to open exoplanets look-up table: '{}'", absPath(LookUpTablePath)
|
||||
));
|
||||
LERROR(fmt::format("Failed to open exoplanets look-up table: '{}'", lutPath));
|
||||
return ExoplanetSystem();
|
||||
}
|
||||
|
||||
ExoplanetSystem system;
|
||||
|
||||
// 1. search lut for the starname and return the corresponding location
|
||||
// 2. go to that location in the data file
|
||||
// 3. read sizeof(exoplanet) bytes into an exoplanet object.
|
||||
@@ -167,6 +163,8 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ExoplanetsModule* module = global::moduleEngine->module<ExoplanetsModule>();
|
||||
|
||||
const glm::dvec3 starPos =
|
||||
static_cast<glm::dvec3>(starPosInParsec) * distanceconstants::Parsec;
|
||||
const glm::dmat3 exoplanetSystemRotation = computeSystemRotation(starPos);
|
||||
@@ -182,6 +180,7 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
|
||||
if (!std::isnan(bv)) {
|
||||
const glm::vec3 color = starColor(bv);
|
||||
const std::string starTexture = module->starTexturePath();
|
||||
colorLayers =
|
||||
"{"
|
||||
"Identifier = 'StarColor',"
|
||||
@@ -192,18 +191,17 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"},"
|
||||
"{"
|
||||
"Identifier = 'StarTexture',"
|
||||
"FilePath = " +
|
||||
fmt::format("openspace.absPath('{}')", StarTextureFile) + ","
|
||||
"FilePath = openspace.absPath('" + formatPathToLua(starTexture) + "'),"
|
||||
"BlendMode = 'Color',"
|
||||
"Enabled = true"
|
||||
"}";
|
||||
}
|
||||
else {
|
||||
const std::string noDataTexture = module->noDataTexturePath();
|
||||
colorLayers =
|
||||
"{"
|
||||
"Identifier = 'NoDataStarTexture',"
|
||||
"FilePath = " +
|
||||
fmt::format("openspace.absPath('{}')", NoDataTextureFile) + ","
|
||||
"FilePath = openspace.absPath('" + formatPathToLua(noDataTexture) + "'),"
|
||||
"BlendMode = 'Color',"
|
||||
"Enabled = true"
|
||||
"}";
|
||||
@@ -313,7 +311,6 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
const std::string planetNode = "{"
|
||||
"Identifier = '" + planetIdentifier + "',"
|
||||
"Parent = '" + starIdentifier + "',"
|
||||
"Enabled = true,"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableGlobe',"
|
||||
"Enabled = " + enabled + ","
|
||||
@@ -342,7 +339,6 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
const std::string planetTrailNode = "{"
|
||||
"Identifier = '" + planetIdentifier + "_Trail',"
|
||||
"Parent = '" + starIdentifier + "',"
|
||||
"Enabled = true,"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableTrailOrbit',"
|
||||
"Period = " + std::to_string(planet.per) + ","
|
||||
@@ -376,13 +372,16 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
const float lowerOffset = static_cast<float>(planet.aLower / planet.a);
|
||||
const float upperOffset = static_cast<float>(planet.aUpper / planet.a);
|
||||
|
||||
const std::string discTexture = module->orbitDiscTexturePath();
|
||||
|
||||
const std::string discNode = "{"
|
||||
"Identifier = '" + planetIdentifier + "_Disc',"
|
||||
"Parent = '" + starIdentifier + "',"
|
||||
"Enabled = true,"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableOrbitDisc',"
|
||||
"Texture = openspace.absPath('" + DiscTextureFile + "'),"
|
||||
"Texture = openspace.absPath('" +
|
||||
formatPathToLua(discTexture) +
|
||||
"'),"
|
||||
"Size = " + std::to_string(semiMajorAxisInMeter) + ","
|
||||
"Eccentricity = " + std::to_string(planet.ecc) + ","
|
||||
"Offset = { " +
|
||||
@@ -410,7 +409,6 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float meanInclination = 0.f;
|
||||
for (const ExoplanetDataEntry& p : system.planetsData) {
|
||||
meanInclination += p.i;
|
||||
@@ -419,14 +417,16 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
const glm::dmat4 rotation = computeOrbitPlaneRotationMatrix(meanInclination);
|
||||
const glm::dmat3 meanOrbitPlaneRotationMatrix = static_cast<glm::dmat3>(rotation);
|
||||
|
||||
// 1 AU Size Comparison Ring
|
||||
const std::string ringIdentifier = starIdentifier + "_1AU_Ring";
|
||||
const std::string ring = "{"
|
||||
"Identifier = '" + starIdentifier + "_1AU_Ring',"
|
||||
bool isCircleEnabled = module->showComparisonCircle();
|
||||
const std::string isCircleEnabledString = isCircleEnabled ? "true" : "false";
|
||||
|
||||
// 1 AU Size Comparison Circle
|
||||
const std::string circle = "{"
|
||||
"Identifier = '" + starIdentifier + "_1AU_Circle',"
|
||||
"Parent = '" + starIdentifier + "',"
|
||||
"Enabled = false,"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableRadialGrid',"
|
||||
"Enabled = " + isCircleEnabledString + ","
|
||||
"OuterRadius = " + std::to_string(AU) + ","
|
||||
"CircleSegments = 64,"
|
||||
"LineWidth = 2.0,"
|
||||
@@ -438,13 +438,13 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"}"
|
||||
"},"
|
||||
"GUI = {"
|
||||
"Name = '1 AU Size Comparison Ring',"
|
||||
"Name = '1 AU Size Comparison Circle',"
|
||||
"Path = '" + guiPath + "'"
|
||||
"}"
|
||||
"}";
|
||||
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + ring + ");",
|
||||
"openspace.addSceneGraphNode(" + circle + ");",
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
|
||||
@@ -463,16 +463,24 @@ void createExoplanetSystem(const std::string& starName) {
|
||||
"the greenhouse effect would not be able to maintain surface temperature "
|
||||
"above freezing anywhere on the planet.";
|
||||
|
||||
const std::string hzTexture = module->habitableZoneTexturePath();
|
||||
|
||||
bool isHzEnabled = module->showHabitableZone();
|
||||
const std::string isHzEnabledString = isHzEnabled ? "true" : "false";
|
||||
|
||||
bool useOptimistic = module->useOptimisticZone();
|
||||
const std::string useOptimisticString = useOptimistic ? "true" : "false";
|
||||
|
||||
const std::string zoneDiscNode = "{"
|
||||
"Identifier = '" + starIdentifier + "_HZ_Disc',"
|
||||
"Parent = '" + starIdentifier + "',"
|
||||
"Enabled = true,"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableHabitableZone',"
|
||||
"Texture = openspace.absPath('" + HabitableZoneTextureFile + "'),"
|
||||
"Enabled = " + isHzEnabledString + ","
|
||||
"Texture = openspace.absPath('" + formatPathToLua(hzTexture) + "'),"
|
||||
"Luminosity = " + std::to_string(system.starData.luminosity) + ","
|
||||
"EffectiveTemperature = " + std::to_string(system.starData.teff) + ","
|
||||
"Optimistic = true,"
|
||||
"Optimistic = " + useOptimisticString + ","
|
||||
"Opacity = 0.07"
|
||||
"},"
|
||||
"Transform = {"
|
||||
@@ -545,21 +553,25 @@ int removeExoplanetSystem(lua_State* L) {
|
||||
}
|
||||
|
||||
std::vector<std::string> hostStarsWithSufficientData() {
|
||||
const ExoplanetsModule* module = global::moduleEngine->module<ExoplanetsModule>();
|
||||
|
||||
const std::string lutPath = module->lookUpTablePath();
|
||||
std::ifstream lookupTableFile(absPath(lutPath));
|
||||
if (!lookupTableFile.good()) {
|
||||
LERROR(fmt::format("Failed to open lookup table file '{}'", lutPath));
|
||||
return {};
|
||||
}
|
||||
|
||||
const std::string binPath = module->exoplanetsDataPath();
|
||||
std::ifstream data(absPath(binPath), std::ios::in | std::ios::binary);
|
||||
if (!data.good()) {
|
||||
LERROR(fmt::format("Failed to open data file '{}'", binPath));
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::string> names;
|
||||
std::string line;
|
||||
|
||||
std::ifstream lookupTableFile(absPath(LookUpTablePath));
|
||||
if (!lookupTableFile.good()) {
|
||||
LERROR(fmt::format("Failed to open lookup table file '{}'", LookUpTablePath));
|
||||
return {};
|
||||
}
|
||||
|
||||
std::ifstream data(absPath(ExoplanetsDataPath), std::ios::in | std::ios::binary);
|
||||
if (!data.good()) {
|
||||
LERROR(fmt::format("Failed to open data file '{}'", ExoplanetsDataPath));
|
||||
return {};
|
||||
}
|
||||
|
||||
// Read number of lines
|
||||
int nExoplanets = 0;
|
||||
while (std::getline(lookupTableFile, line)) {
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "OrbitalKepler";
|
||||
constexpr const char* ProgramName = "OrbitalKepler";
|
||||
|
||||
// Fragile! Keep in sync with documentation
|
||||
@@ -114,62 +115,6 @@ namespace {
|
||||
LeapSecond{ 2017, 1 }
|
||||
};
|
||||
|
||||
static const openspace::properties::Property::PropertyInfo PathInfo = {
|
||||
"Path",
|
||||
"Path",
|
||||
"The file path to the data file to read"
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo SegmentQualityInfo = {
|
||||
"SegmentQuality",
|
||||
"Segment Quality",
|
||||
"A segment quality value for the orbital trail. A value from 1 (lowest) to "
|
||||
"10 (highest) that controls the number of line segments in the rendering of the "
|
||||
"orbital trail. This does not control the direct number of segments because "
|
||||
"these automatically increase according to the eccentricity of the orbit."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo LineWidthInfo = {
|
||||
"LineWidth",
|
||||
"Line Width",
|
||||
"This value specifies the line width of the trail if the selected rendering "
|
||||
"method includes lines. If the rendering mode is set to Points, this value is "
|
||||
"ignored."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo LineColorInfo = {
|
||||
"Color",
|
||||
"Color",
|
||||
"This value determines the RGB main color for the lines and points of the trail."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo TrailFadeInfo = {
|
||||
"TrailFade",
|
||||
"Trail Fade",
|
||||
"This value determines how fast the trail fades and is an appearance property. "
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo UpperLimitInfo = {
|
||||
"UpperLimit",
|
||||
"Upper Limit",
|
||||
"Upper limit on the number of objects for this renderable, regardless of "
|
||||
"how many objects are contained in the data file. Produces an evenly-distributed"
|
||||
"sample from the data file."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo StartRenderIdxInfo = {
|
||||
"StartRenderIdx",
|
||||
"Starting Index of Render",
|
||||
"Index of object in renderable group to start rendering (all prior objects will "
|
||||
"be ignored)."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo RenderSizeInfo = {
|
||||
"RenderSizeInfo",
|
||||
"Size of Render Block",
|
||||
"Number of objects to render sequentially from StartRenderIdx"
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo RenderBinModeInfo = {
|
||||
"RenderBinMode",
|
||||
"RenderBin Mode",
|
||||
"Determines if the trails will be rendered after all other elements, including"
|
||||
"atmospheres if needed."
|
||||
};
|
||||
|
||||
// Count the number of full days since the beginning of 2000 to the beginning of
|
||||
// the parameter 'year'
|
||||
int countDays(int year) {
|
||||
@@ -238,10 +183,90 @@ namespace {
|
||||
return dayCount;
|
||||
}
|
||||
|
||||
static const openspace::properties::Property::PropertyInfo PathInfo = {
|
||||
"Path",
|
||||
"Path",
|
||||
"The file path to the data file to read"
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo SegmentQualityInfo = {
|
||||
"SegmentQuality",
|
||||
"Segment Quality",
|
||||
"A segment quality value for the orbital trail. A value from 1 (lowest) to "
|
||||
"10 (highest) that controls the number of line segments in the rendering of the "
|
||||
"orbital trail. This does not control the direct number of segments because "
|
||||
"these automatically increase according to the eccentricity of the orbit."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo LineWidthInfo = {
|
||||
"LineWidth",
|
||||
"Line Width",
|
||||
"This value specifies the line width of the trail if the selected rendering "
|
||||
"method includes lines. If the rendering mode is set to Points, this value is "
|
||||
"ignored."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo LineColorInfo = {
|
||||
"Color",
|
||||
"Color",
|
||||
"This value determines the RGB main color for the lines and points of the trail."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo TrailFadeInfo = {
|
||||
"TrailFade",
|
||||
"Trail Fade",
|
||||
"This value determines how fast the trail fades and is an appearance property. "
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo StartRenderIdxInfo = {
|
||||
"StartRenderIdx",
|
||||
"Contiguous Starting Index of Render",
|
||||
"Index of object in renderable group to start rendering (all prior objects will "
|
||||
"be ignored)."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo RenderSizeInfo = {
|
||||
"RenderSize",
|
||||
"Contiguous Size of Render Block",
|
||||
"Number of objects to render sequentially from StartRenderIdx"
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo RenderBinModeInfo = {
|
||||
"RenderBinMode",
|
||||
"RenderBin Mode",
|
||||
"Determines if the trails will be rendered after all other elements, including"
|
||||
"atmospheres if needed."
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableOrbitalKepler)]] Parameters {
|
||||
// [[codegen::verbatim(PathInfo.description)]]
|
||||
std::string path;
|
||||
|
||||
// [[codegen::verbatim(SegmentQualityInfo.description)]]
|
||||
double segmentQuality;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<double> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(LineColorInfo.description)]]
|
||||
glm::dvec3 color;
|
||||
|
||||
// [[codegen::verbatim(TrailFadeInfo.description)]]
|
||||
std::optional<double> trailFade;
|
||||
|
||||
// [[codegen::verbatim(StartRenderIdxInfo.description)]]
|
||||
std::optional<int> startRenderIdx;
|
||||
|
||||
// [[codegen::verbatim(RenderSizeInfo.description)]]
|
||||
std::optional<int> renderSize;
|
||||
|
||||
// [[codegen::verbatim(RenderBinModeInfo.description)]]
|
||||
std::optional<std::string> renderBinMode;
|
||||
};
|
||||
#include "renderableorbitalkepler_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableOrbitalKepler::Documentation() {
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_renderableorbitalkepler";
|
||||
return doc;
|
||||
}
|
||||
|
||||
double RenderableOrbitalKepler::calculateSemiMajorAxis(double meanMotion) const {
|
||||
constexpr const double GravitationalConstant = 6.6740831e-11;
|
||||
constexpr const double MassEarth = 5.9721986e24;
|
||||
@@ -363,7 +388,6 @@ double RenderableOrbitalKepler::epochFromYMDdSubstring(const std::string& epochS
|
||||
|
||||
RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
|
||||
: Renderable(dict)
|
||||
, _upperLimit(UpperLimitInfo, 1000, 1, 1000000)
|
||||
, _segmentQuality(SegmentQualityInfo, 2, 1, 10)
|
||||
, _startRenderIdx(StartRenderIdxInfo, 0, 0, 1)
|
||||
, _sizeRender(RenderSizeInfo, 1, 1, 2)
|
||||
@@ -374,7 +398,6 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
|
||||
dict,
|
||||
"RenderableOrbitalKepler"
|
||||
);
|
||||
|
||||
_path = dict.value<std::string>(PathInfo.identifier);
|
||||
_segmentQuality = static_cast<int>(dict.value<double>(SegmentQualityInfo.identifier));
|
||||
|
||||
@@ -387,20 +410,21 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
|
||||
static_cast<float>(dict.value<double>(TrailFadeInfo.identifier)) :
|
||||
20.f;
|
||||
|
||||
_upperLimit =
|
||||
dict.hasValue<double>(UpperLimitInfo.identifier) ?
|
||||
static_cast<unsigned int>(dict.value<double>(UpperLimitInfo.identifier)) :
|
||||
0u;
|
||||
if (dict.hasValue<double>(StartRenderIdxInfo.identifier)) {
|
||||
_startRenderIdx = static_cast<unsigned int>(
|
||||
dict.value<double>(StartRenderIdxInfo.identifier));
|
||||
}
|
||||
else {
|
||||
_startRenderIdx = 0u;
|
||||
}
|
||||
|
||||
_startRenderIdx =
|
||||
dict.hasValue<double>(StartRenderIdxInfo.identifier) ?
|
||||
static_cast<unsigned int>(dict.value<double>(StartRenderIdxInfo.identifier)) :
|
||||
0u;
|
||||
|
||||
_sizeRender =
|
||||
dict.hasValue<double>(RenderSizeInfo.identifier) ?
|
||||
static_cast<unsigned int>(dict.value<double>(RenderSizeInfo.identifier)) :
|
||||
0u;
|
||||
if (dict.hasValue<double>(RenderSizeInfo.identifier)) {
|
||||
_sizeRender = static_cast<unsigned int>(
|
||||
dict.value<double>(RenderSizeInfo.identifier));
|
||||
}
|
||||
else {
|
||||
_sizeRender = 0u;
|
||||
}
|
||||
|
||||
_appearance.lineWidth =
|
||||
dict.hasValue<double>(LineWidthInfo.identifier) ?
|
||||
@@ -415,13 +439,6 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
|
||||
addProperty(_path);
|
||||
addProperty(_segmentQuality);
|
||||
addProperty(_opacity);
|
||||
addProperty(_startRenderIdx);
|
||||
addProperty(_sizeRender);
|
||||
|
||||
_updateStartRenderIdxSelect = std::function<void()>([this] { initializeGL(); });
|
||||
_updateRenderSizeSelect = std::function<void()>([this] { initializeGL(); });
|
||||
_startRenderIdxCallbackHandle = _startRenderIdx.onChange(_updateStartRenderIdxSelect);
|
||||
_sizeRenderCallbackHandle = _sizeRender.onChange(_updateRenderSizeSelect);
|
||||
|
||||
if (dict.hasValue<std::string>(RenderBinModeInfo.identifier)) {
|
||||
Renderable::RenderBin cfgRenderBin = RenderBinConversion.at(
|
||||
@@ -435,6 +452,8 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict)
|
||||
}
|
||||
|
||||
void RenderableOrbitalKepler::initializeGL() {
|
||||
ghoul_assert(_vertexArray == 0, "Vertex array object already existed");
|
||||
ghoul_assert(_vertexBuffer == 0, "Vertex buffer object already existed");
|
||||
glGenVertexArrays(1, &_vertexArray);
|
||||
glGenBuffers(1, &_vertexBuffer);
|
||||
|
||||
@@ -481,6 +500,11 @@ void RenderableOrbitalKepler::render(const RenderData& data, RendererTasks&) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_updateDataBuffersAtNextRender) {
|
||||
_updateDataBuffersAtNextRender = false;
|
||||
initializeGL();
|
||||
}
|
||||
|
||||
_programObject->activate();
|
||||
_programObject->setUniform(_uniformCache.opacity, _opacity);
|
||||
_programObject->setUniform(_uniformCache.inGameTime, data.time.j2000Seconds());
|
||||
|
||||
@@ -37,6 +37,8 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class RenderableOrbitalKepler : public Renderable {
|
||||
public:
|
||||
RenderableOrbitalKepler(const ghoul::Dictionary& dictionary);
|
||||
@@ -62,9 +64,12 @@ public:
|
||||
virtual void readDataFile(const std::string& filename) = 0;
|
||||
|
||||
protected:
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
double calculateSemiMajorAxis(double meanMotion) const;
|
||||
double epochFromSubstring(const std::string& epochString) const;
|
||||
double epochFromYMDdSubstring(const std::string& epochString);
|
||||
void updateBuffers();
|
||||
|
||||
std::function<void()> _reinitializeTrailBuffers;
|
||||
std::function<void()> _updateStartRenderIdxSelect;
|
||||
@@ -81,15 +86,15 @@ protected:
|
||||
double epoch = 0.0;
|
||||
double period = 0.0;
|
||||
};
|
||||
|
||||
bool _updateDataBuffersAtNextRender = false;
|
||||
std::streamoff _numObjects;
|
||||
bool _isFileReadinitialized = false;
|
||||
inline static constexpr double convertAuToKm = 1.496e8;
|
||||
inline static constexpr double convertDaysToSecs = 86400.0;
|
||||
std::vector<KeplerParameters> _data;
|
||||
std::vector<size_t> _segmentSize;
|
||||
properties::UIntProperty _upperLimit;
|
||||
properties::UIntProperty _segmentQuality;
|
||||
properties::Property::OnChangeHandle _upperLimitCallbackHandle;
|
||||
properties::UIntProperty _startRenderIdx;
|
||||
properties::UIntProperty _sizeRender;
|
||||
properties::Property::OnChangeHandle _startRenderIdxCallbackHandle;
|
||||
@@ -121,7 +126,6 @@ private:
|
||||
GLuint _vertexArray;
|
||||
GLuint _vertexBuffer;
|
||||
|
||||
void updateBuffers();
|
||||
|
||||
ghoul::opengl::ProgramObject* _programObject;
|
||||
properties::StringProperty _path;
|
||||
|
||||
@@ -47,49 +47,15 @@
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "Satellites";
|
||||
|
||||
static const openspace::properties::Property::PropertyInfo PathInfo = {
|
||||
"Path",
|
||||
"Path",
|
||||
"The file path to the TLE file to read"
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo SegmentsInfo = {
|
||||
"Segments",
|
||||
"Segments",
|
||||
"The number of segments to use for each orbit ellipse"
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo LineWidthInfo = {
|
||||
"LineWidth",
|
||||
"Line Width",
|
||||
"This value specifies the line width of the trail if the selected rendering "
|
||||
"method includes lines. If the rendering mode is set to Points, this value is "
|
||||
"ignored."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo LineColorInfo = {
|
||||
"Color",
|
||||
"Color",
|
||||
"This value determines the RGB main color for the lines and points of the trail."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo TrailFadeInfo = {
|
||||
"TrailFade",
|
||||
"Trail Fade",
|
||||
"This value determines how fast the trail fades and is an appearance property. "
|
||||
};
|
||||
|
||||
struct [[codegen::Dictionary(RenderableSatellites)]] Parameters {
|
||||
// [[codegen::verbatim(SegmentsInfo.description)]]
|
||||
double segments;
|
||||
|
||||
// [[codegen::verbatim(PathInfo.description)]]
|
||||
std::string path;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<double> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(LineColorInfo.description)]]
|
||||
glm::dvec3 color;
|
||||
|
||||
// [[codegen::verbatim(TrailFadeInfo.description)]]
|
||||
std::optional<double> trailFade;
|
||||
};
|
||||
#include "renderablesatellites_codegen.cpp"
|
||||
}
|
||||
@@ -98,7 +64,17 @@ namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSatellites::Documentation() {
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_renderable_satellites";
|
||||
doc.id = "space_renderablesatellites";
|
||||
|
||||
// Insert the parents documentation entries until we have a verifier that can deal
|
||||
// with class hierarchy
|
||||
documentation::Documentation parentDoc = RenderableOrbitalKepler::Documentation();
|
||||
doc.entries.insert(
|
||||
doc.entries.end(),
|
||||
parentDoc.entries.begin(),
|
||||
parentDoc.entries.end()
|
||||
);
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
@@ -109,12 +85,29 @@ RenderableSatellites::RenderableSatellites(const ghoul::Dictionary& dictionary)
|
||||
// probably want a codegen::check function that only does the checking without
|
||||
// actually creating a Parameter objects
|
||||
// codegen::bake<Parameters>(dictionary);
|
||||
addProperty(_startRenderIdx);
|
||||
addProperty(_sizeRender);
|
||||
|
||||
_updateStartRenderIdxSelect = [this]() {
|
||||
if ((_numObjects - _startRenderIdx) < _sizeRender) {
|
||||
_sizeRender = _numObjects - _startRenderIdx;
|
||||
}
|
||||
updateBuffers();
|
||||
};
|
||||
_updateRenderSizeSelect = [this]() {
|
||||
if (_sizeRender > (_numObjects - _startRenderIdx)) {
|
||||
_startRenderIdx = _numObjects - _sizeRender;
|
||||
}
|
||||
updateBuffers();
|
||||
};
|
||||
_startRenderIdxCallbackHandle = _startRenderIdx.onChange(_updateStartRenderIdxSelect);
|
||||
_sizeRenderCallbackHandle = _sizeRender.onChange(_updateRenderSizeSelect);
|
||||
}
|
||||
|
||||
void RenderableSatellites::readDataFile(const std::string& filename) {
|
||||
if (!FileSys.fileExists(filename)) {
|
||||
throw ghoul::RuntimeError(fmt::format(
|
||||
"Satellite TLE file {} does not exist.", filename
|
||||
"Satellite TLE file {} does not exist", filename
|
||||
));
|
||||
}
|
||||
_data.clear();
|
||||
@@ -162,7 +155,7 @@ void RenderableSatellites::readDataFile(const std::string& filename) {
|
||||
// 5 12-14 International Designator (Launch number of the year)
|
||||
// 6 15-17 International Designator(piece of the launch) A
|
||||
name += " " + line.substr(2, 15);
|
||||
if (_startRenderIdx > 0 && _startRenderIdx == i) {
|
||||
if (_startRenderIdx == i && _sizeRender == 1) {
|
||||
LINFO(fmt::format(
|
||||
"Set render block to start at object {}",
|
||||
name
|
||||
@@ -251,16 +244,11 @@ void RenderableSatellites::readDataFile(const std::string& filename) {
|
||||
}
|
||||
|
||||
void RenderableSatellites::initializeFileReading() {
|
||||
_startRenderIdx.removeOnChange(_startRenderIdxCallbackHandle);
|
||||
_sizeRender.removeOnChange(_sizeRenderCallbackHandle);
|
||||
_startRenderIdx.setMaxValue(static_cast<unsigned int>(_numObjects - 1));
|
||||
_sizeRender.setMaxValue(static_cast<unsigned int>(_numObjects));
|
||||
_startRenderIdx = static_cast<unsigned int>(0);
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects);
|
||||
_startRenderIdxCallbackHandle = _startRenderIdx.onChange(
|
||||
_updateStartRenderIdxSelect);
|
||||
_sizeRenderCallbackHandle = _sizeRender.onChange(
|
||||
_updateRenderSizeSelect);
|
||||
if (_sizeRender == 0u) {
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSatellites::skipSingleEntryInFile(std::ifstream& file) {
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class RenderableSatellites : public RenderableOrbitalKepler {
|
||||
public:
|
||||
RenderableSatellites(const ghoul::Dictionary& dictionary);
|
||||
|
||||
@@ -48,41 +48,20 @@
|
||||
namespace {
|
||||
constexpr const char* _loggerCat = "SmallSolarSystemBody";
|
||||
|
||||
static const openspace::properties::Property::PropertyInfo PathInfo = {
|
||||
"Path",
|
||||
"Path",
|
||||
"The file path to the SBDB .csv file to read"
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo SegmentQualityInfo = {
|
||||
"SegmentQuality",
|
||||
"Segment Quality",
|
||||
"A segment quality value for the orbital trail. A value from 1 (lowest) to "
|
||||
"100 (highest) that controls the number of line segments in the rendering of the "
|
||||
"orbital trail. This does not control the direct number of segments because "
|
||||
"these automatically increase according to the eccentricity of the orbit."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo LineWidthInfo = {
|
||||
"LineWidth",
|
||||
"Line Width",
|
||||
"This value specifies the line width of the trail if the selected rendering "
|
||||
"method includes lines. If the rendering mode is set to Points, this value is "
|
||||
"ignored."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo LineColorInfo = {
|
||||
"Color",
|
||||
"Color",
|
||||
"This value determines the RGB main color for the lines and points of the trail."
|
||||
};
|
||||
constexpr openspace::properties::Property::PropertyInfo TrailFadeInfo = {
|
||||
"TrailFade",
|
||||
"Trail Fade",
|
||||
"This value determines how fast the trail fades and is an appearance property. "
|
||||
static const openspace::properties::Property::PropertyInfo ContiguousModeInfo = {
|
||||
"ContiguousMode",
|
||||
"Contiguous Mode",
|
||||
"If enabled, then the contiguous set of objects starting from StartRenderIdx "
|
||||
"of size RenderSize will be rendered. If disabled, then the number of objects "
|
||||
"defined by UpperLimit will rendered from an evenly dispersed sample of the "
|
||||
"full length of the data file."
|
||||
};
|
||||
static const openspace::properties::Property::PropertyInfo UpperLimitInfo = {
|
||||
"UpperLimit",
|
||||
"Upper Limit",
|
||||
"Upper limit on the number of objects for this renderable, regardless of "
|
||||
"how many objects are contained in the data file"
|
||||
"how many objects are contained in the data file. Produces an evenly-distributed"
|
||||
"sample from the data file."
|
||||
};
|
||||
|
||||
double importAngleValue(const std::string& angle) {
|
||||
@@ -106,23 +85,11 @@ namespace {
|
||||
}
|
||||
|
||||
struct [[codegen::Dictionary(RenderableSmallBody)]] Parameters {
|
||||
// [[codegen::verbatim(SegmentQualityInfo.description)]]
|
||||
double segmentQuality;
|
||||
// [[codegen::verbatim(ContiguousModeInfo.description)]]
|
||||
std::optional<bool> contiguousMode;
|
||||
|
||||
// [[codegen::verbatim(UpperLimitInfo.description)]]
|
||||
std::optional<int> upperLimit;
|
||||
|
||||
// [[codegen::verbatim(PathInfo.description)]]
|
||||
std::string path;
|
||||
|
||||
// [[codegen::verbatim(LineWidthInfo.description)]]
|
||||
std::optional<double> lineWidth;
|
||||
|
||||
// [[codegen::verbatim(LineColorInfo.description)]]
|
||||
glm::dvec3 color;
|
||||
|
||||
// [[codegen::verbatim(TrailFadeInfo.description)]]
|
||||
std::optional<double> trailFade;
|
||||
};
|
||||
#include "renderablesmallbody_codegen.cpp"
|
||||
} // namespace
|
||||
@@ -131,17 +98,77 @@ namespace openspace {
|
||||
|
||||
documentation::Documentation RenderableSmallBody::Documentation() {
|
||||
documentation::Documentation doc = codegen::doc<Parameters>();
|
||||
doc.id = "space_renderable_small_body";
|
||||
doc.id = "space_renderablesmallbody";
|
||||
|
||||
// Insert the parents documentation entries until we have a verifier that can deal
|
||||
// with class hierarchy
|
||||
documentation::Documentation parentDoc = RenderableOrbitalKepler::Documentation();
|
||||
doc.entries.insert(
|
||||
doc.entries.end(),
|
||||
parentDoc.entries.begin(),
|
||||
parentDoc.entries.end()
|
||||
);
|
||||
return doc;
|
||||
}
|
||||
|
||||
RenderableSmallBody::RenderableSmallBody(const ghoul::Dictionary& dictionary)
|
||||
: RenderableOrbitalKepler(dictionary)
|
||||
, _upperLimit(UpperLimitInfo, 1000, 1, 1000000)
|
||||
, _contiguousMode(ContiguousModeInfo, false)
|
||||
{
|
||||
codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_upperLimitCallbackHandle = _upperLimit.onChange(_reinitializeTrailBuffers);
|
||||
addProperty(_startRenderIdx);
|
||||
addProperty(_sizeRender);
|
||||
addProperty(_contiguousMode);
|
||||
addProperty(_upperLimit);
|
||||
|
||||
if (dictionary.hasValue<double>(UpperLimitInfo.identifier)) {
|
||||
_upperLimit = static_cast<unsigned int>(
|
||||
dictionary.value<double>(UpperLimitInfo.identifier));
|
||||
}
|
||||
else {
|
||||
_upperLimit = 0u;
|
||||
}
|
||||
|
||||
if (dictionary.hasValue<bool>(ContiguousModeInfo.identifier)) {
|
||||
_contiguousMode = static_cast<bool>(
|
||||
dictionary.value<bool>(ContiguousModeInfo.identifier));
|
||||
}
|
||||
else {
|
||||
_contiguousMode = false;
|
||||
}
|
||||
|
||||
_updateStartRenderIdxSelect = std::function<void()>([this] {
|
||||
if (_contiguousMode) {
|
||||
if ((_numObjects - _startRenderIdx) < _sizeRender) {
|
||||
_sizeRender = _numObjects - _startRenderIdx;
|
||||
}
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
}
|
||||
});
|
||||
_updateRenderSizeSelect = std::function<void()>([this] {
|
||||
if (_contiguousMode) {
|
||||
if (_sizeRender > (_numObjects - _startRenderIdx)) {
|
||||
_startRenderIdx = _numObjects - _sizeRender;
|
||||
}
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
}
|
||||
});
|
||||
_updateRenderUpperLimitSelect = std::function<void()>([this] {
|
||||
if (!_contiguousMode) {
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
}
|
||||
});
|
||||
_updateContiguousModeSelect = std::function<void()>([this] {
|
||||
_updateDataBuffersAtNextRender = true;
|
||||
});
|
||||
|
||||
_startRenderIdxCallbackHandle = _startRenderIdx.onChange(_updateStartRenderIdxSelect);
|
||||
_sizeRenderCallbackHandle = _sizeRender.onChange(_updateRenderSizeSelect);
|
||||
_upperLimitCallbackHandle = _upperLimit.onChange(_updateRenderUpperLimitSelect);
|
||||
_contiguousModeCallbackhandle =
|
||||
_contiguousMode.onChange(_updateContiguousModeSelect);
|
||||
}
|
||||
|
||||
void RenderableSmallBody::readDataFile(const std::string& filename) {
|
||||
@@ -183,14 +210,18 @@ void RenderableSmallBody::readDataFile(const std::string& filename) {
|
||||
_isFileReadinitialized = true;
|
||||
initializeFileReading();
|
||||
}
|
||||
|
||||
unsigned int startElement = 0;
|
||||
unsigned int endElement;
|
||||
if (_contiguousMode) {
|
||||
lineSkipFraction = 1.0;
|
||||
startElement = _startRenderIdx;
|
||||
endElement = _startRenderIdx + _sizeRender - 1;
|
||||
}
|
||||
else {
|
||||
if (_sizeRender < _numObjects || _startRenderIdx > 0) {
|
||||
lineSkipFraction = 1.0;
|
||||
}
|
||||
else {
|
||||
lineSkipFraction = static_cast<float>(_upperLimit)
|
||||
/ static_cast<float>(_numObjects);
|
||||
}
|
||||
lineSkipFraction = static_cast<float>(_upperLimit)
|
||||
/ static_cast<float>(_numObjects);
|
||||
endElement = _numObjects - 1;
|
||||
}
|
||||
|
||||
if (line.compare(expectedHeaderLine) != 0) {
|
||||
@@ -202,18 +233,17 @@ void RenderableSmallBody::readDataFile(const std::string& filename) {
|
||||
}
|
||||
|
||||
unsigned int sequentialLineErrors = 0;
|
||||
unsigned int endElement = _startRenderIdx + _sizeRender - 1;
|
||||
endElement =
|
||||
(endElement >= _numObjects) ?
|
||||
static_cast<unsigned int>(_numObjects - 1) :
|
||||
endElement;
|
||||
// Burn lines if not starting at first element
|
||||
for (unsigned int k = 0; k < _startRenderIdx; ++k) {
|
||||
for (unsigned int k = 0; k < startElement; ++k) {
|
||||
skipSingleLineInFile(file);
|
||||
}
|
||||
bool firstDataLine = true;
|
||||
int lastLineCount = -1;
|
||||
for (csvLine = _startRenderIdx + 1;
|
||||
for (csvLine = startElement + 1;
|
||||
csvLine <= endElement + 1;
|
||||
csvLine++, sequentialLineErrors++)
|
||||
{
|
||||
@@ -272,20 +302,16 @@ void RenderableSmallBody::readDataFile(const std::string& filename) {
|
||||
}
|
||||
|
||||
void RenderableSmallBody::initializeFileReading() {
|
||||
_startRenderIdx.removeOnChange(_startRenderIdxCallbackHandle);
|
||||
_sizeRender.removeOnChange(_sizeRenderCallbackHandle);
|
||||
_startRenderIdx.setMaxValue(static_cast<unsigned int>(_numObjects - 1));
|
||||
_sizeRender.setMaxValue(static_cast<unsigned int>(_numObjects));
|
||||
_startRenderIdx = static_cast<unsigned int>(0);
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects);
|
||||
_startRenderIdxCallbackHandle = _startRenderIdx.onChange(_updateStartRenderIdxSelect);
|
||||
_sizeRenderCallbackHandle = _sizeRender.onChange(_updateRenderSizeSelect);
|
||||
// If a limit wasn't specified in dictionary, set it to # lines in file
|
||||
// minus the header line (but temporarily disable callback to avoid 2nd call)
|
||||
_upperLimit.removeOnChange(_upperLimitCallbackHandle);
|
||||
if (_sizeRender == 0u) {
|
||||
_sizeRender = static_cast<unsigned int>(_numObjects);
|
||||
}
|
||||
|
||||
_upperLimit.setMaxValue(static_cast<unsigned int>(_numObjects));
|
||||
_upperLimit = static_cast<unsigned int>(_numObjects);
|
||||
_upperLimitCallbackHandle = _upperLimit.onChange(_reinitializeTrailBuffers);
|
||||
if (_upperLimit == 0u) {
|
||||
_upperLimit = static_cast<unsigned int>(_numObjects);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSmallBody::skipSingleLineInFile(std::ifstream& file) {
|
||||
@@ -312,7 +338,7 @@ void RenderableSmallBody::readOrbitalParamsFromThisLine(bool firstDataLine,
|
||||
|
||||
// Object designator string
|
||||
std::getline(file, name, ',');
|
||||
if (_startRenderIdx > 0 && _startRenderIdx == (csvLine - 1)) {
|
||||
if (_startRenderIdx > 0 && _startRenderIdx == (csvLine - 1) && _sizeRender == 1) {
|
||||
formatObjectName(name);
|
||||
LINFO(fmt::format("Set render block to start at object {}", name));
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
namespace openspace {
|
||||
|
||||
namespace documentation { struct Documentation; }
|
||||
|
||||
class RenderableSmallBody : public RenderableOrbitalKepler {
|
||||
public:
|
||||
RenderableSmallBody(const ghoul::Dictionary& dictionary);
|
||||
@@ -51,10 +53,17 @@ private:
|
||||
void skipSingleLineInFile(std::ifstream& file);
|
||||
|
||||
std::vector<std::string> _sbNames;
|
||||
std::function<void()> _updateContiguousModeSelect;
|
||||
std::function<void()> _updateRenderUpperLimitSelect;
|
||||
|
||||
/// The index array that is potentially used in the draw call. If this is empty, no
|
||||
/// element draw call is used.
|
||||
std::vector<unsigned int> _indexBufferData;
|
||||
bool contiguousMode = true;
|
||||
properties::BoolProperty _contiguousMode;
|
||||
properties::UIntProperty _upperLimit;
|
||||
properties::Property::OnChangeHandle _contiguousModeCallbackhandle;
|
||||
properties::Property::OnChangeHandle _upperLimitCallbackHandle;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -308,10 +308,10 @@ namespace {
|
||||
|
||||
struct [[codegen::Dictionary(RenderableStars)]] Parameters {
|
||||
// The path to the SPECK file containing information about the stars being rendered
|
||||
std::string speckFile [[codegen::key("File")]];
|
||||
std::filesystem::path speckFile [[codegen::key("File")]];
|
||||
|
||||
// [[codegen::verbatim(ColorTextureInfo.description)]]
|
||||
std::string colorMap;
|
||||
std::filesystem::path colorMap;
|
||||
|
||||
enum class ColorOption {
|
||||
Color,
|
||||
@@ -350,7 +350,7 @@ namespace {
|
||||
std::string renderMethod;
|
||||
|
||||
// [[codegen::verbatim(PsfTextureInfo.description)]]
|
||||
std::string texture;
|
||||
std::filesystem::path texture;
|
||||
|
||||
// [[codegen::verbatim(SizeCompositionOptionInfo.description)]]
|
||||
std::optional<std::string> sizeComposition;
|
||||
@@ -434,11 +434,11 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
addProperty(_opacity);
|
||||
registerUpdateRenderBinFromOpacity();
|
||||
|
||||
_speckFile = absPath(p.speckFile);
|
||||
_speckFile = p.speckFile.string();
|
||||
_speckFile.onChange([&]() { _speckFileIsDirty = true; });
|
||||
addProperty(_speckFile);
|
||||
|
||||
_colorTexturePath = absPath(p.colorMap);
|
||||
_colorTexturePath = p.colorMap.string();
|
||||
_colorTextureFile = std::make_unique<File>(_colorTexturePath);
|
||||
|
||||
/*_shapeTexturePath = absPath(dictionary.value<std::string>(
|
||||
@@ -525,7 +525,7 @@ RenderableStars::RenderableStars(const ghoul::Dictionary& dictionary)
|
||||
_renderingMethodOption = RenderOptionTexture;
|
||||
}
|
||||
|
||||
_pointSpreadFunctionTexturePath = absPath(p.texture);
|
||||
_pointSpreadFunctionTexturePath = absPath(p.texture.string());
|
||||
_pointSpreadFunctionFile = std::make_unique<File>(_pointSpreadFunctionTexturePath);
|
||||
_pointSpreadFunctionTexturePath.onChange([&]() {
|
||||
_pointSpreadFunctionTextureIsDirty = true;
|
||||
@@ -1237,13 +1237,13 @@ void RenderableStars::loadShapeTexture() {
|
||||
*/
|
||||
|
||||
void RenderableStars::loadData() {
|
||||
std::string _file = _speckFile;
|
||||
if (!FileSys.fileExists(absPath(_file))) {
|
||||
std::string file = absPath(_speckFile);
|
||||
if (!FileSys.fileExists(file)) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string cachedFile = FileSys.cacheManager()->cachedFilename(
|
||||
_file,
|
||||
file,
|
||||
ghoul::filesystem::CacheManager::Persistent::Yes
|
||||
);
|
||||
|
||||
@@ -1255,7 +1255,7 @@ void RenderableStars::loadData() {
|
||||
bool hasCachedFile = FileSys.fileExists(cachedFile);
|
||||
if (hasCachedFile) {
|
||||
LINFO(fmt::format("Cached file '{}' used for Speck file '{}'",
|
||||
cachedFile, _file
|
||||
cachedFile, file
|
||||
));
|
||||
|
||||
bool success = loadCachedFile(cachedFile);
|
||||
@@ -1263,15 +1263,15 @@ void RenderableStars::loadData() {
|
||||
return;
|
||||
}
|
||||
else {
|
||||
FileSys.cacheManager()->removeCacheFile(_file);
|
||||
FileSys.cacheManager()->removeCacheFile(file);
|
||||
// Intentional fall-through to the 'else' computation to generate the cache
|
||||
// file for the next run
|
||||
}
|
||||
}
|
||||
else {
|
||||
LINFO(fmt::format("Cache for Speck file '{}' not found", _file));
|
||||
LINFO(fmt::format("Cache for Speck file '{}' not found", file));
|
||||
}
|
||||
LINFO(fmt::format("Loading Speck file '{}'", _file));
|
||||
LINFO(fmt::format("Loading Speck file '{}'", file));
|
||||
|
||||
readSpeckFile();
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ glm::dvec3 KeplerTranslation::position(const UpdateData& data) const {
|
||||
_orbitPlaneDirty = false;
|
||||
}
|
||||
|
||||
const double t = data.time.j2000Seconds() -_epoch;
|
||||
const double t = data.time.j2000Seconds() - _epoch;
|
||||
const double meanMotion = glm::two_pi<double>() / _period;
|
||||
const double meanAnomaly = glm::radians(_meanAnomalyAtEpoch.value()) + t * meanMotion;
|
||||
const double e = eccentricAnomaly(meanAnomaly);
|
||||
|
||||
@@ -481,7 +481,7 @@ void RenderablePlanetProjection::imageProjectGPU(
|
||||
if (_geometry->hasProperty("Radius")) {
|
||||
std::any r = _geometry->property("Radius")->get();
|
||||
if (glm::vec3* radius = std::any_cast<glm::vec3>(&r)){
|
||||
_fboProgramObject->setUniform(_fboUniformCache.radius, radius);
|
||||
_fboProgramObject->setUniform(_fboUniformCache.radius, *radius);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -135,8 +135,8 @@ void BasicVolumeRaycaster::preRaycast(const RaycastData& data,
|
||||
int nClips = static_cast<int>(clipNormals.size());
|
||||
|
||||
program.setUniform("nClips_" + id, nClips);
|
||||
program.setUniform("clipNormals_" + id, clipNormals.data(), nClips);
|
||||
program.setUniform("clipOffsets_" + id, clipOffsets.data(), nClips);
|
||||
program.setUniform("clipNormals_" + id, clipNormals);
|
||||
program.setUniform("clipOffsets_" + id, clipOffsets);
|
||||
program.setUniform("opacity_" + id, _opacity);
|
||||
program.setUniform("rNormalization_" + id, _rNormalization);
|
||||
program.setUniform("rUpperBound_" + id, _rUpperBound);
|
||||
|
||||
@@ -101,11 +101,15 @@ void GenerateRawVolumeTask::perform(const Task::ProgressCallback& progressCallba
|
||||
ghoul::lua::LuaState state;
|
||||
ghoul::lua::runScript(state, _valueFunctionLua);
|
||||
|
||||
#if (defined(NDEBUG) || defined(DEBUG))
|
||||
ghoul::lua::verifyStackSize(state, 1);
|
||||
#endif
|
||||
|
||||
int functionReference = luaL_ref(state, LUA_REGISTRYINDEX);
|
||||
|
||||
#if (defined(NDEBUG) || defined(DEBUG))
|
||||
ghoul::lua::verifyStackSize(state, 0);
|
||||
#endif
|
||||
|
||||
glm::vec3 domainSize = _upperDomainBound - _lowerDomainBound;
|
||||
|
||||
@@ -117,14 +121,18 @@ void GenerateRawVolumeTask::perform(const Task::ProgressCallback& progressCallba
|
||||
glm::vec3 coord = _lowerDomainBound +
|
||||
glm::vec3(cell) / glm::vec3(_dimensions) * domainSize;
|
||||
|
||||
#if (defined(NDEBUG) || defined(DEBUG))
|
||||
ghoul::lua::verifyStackSize(state, 0);
|
||||
#endif
|
||||
lua_rawgeti(state, LUA_REGISTRYINDEX, functionReference);
|
||||
|
||||
lua_pushnumber(state, coord.x);
|
||||
lua_pushnumber(state, coord.y);
|
||||
lua_pushnumber(state, coord.z);
|
||||
|
||||
#if (defined(NDEBUG) || defined(DEBUG))
|
||||
ghoul::lua::verifyStackSize(state, 4);
|
||||
#endif
|
||||
|
||||
if (lua_pcall(state, 3, 1, 0) != LUA_OK) {
|
||||
return;
|
||||
|
||||
@@ -167,6 +167,11 @@ ModuleConfigurations = {
|
||||
},
|
||||
Space = {
|
||||
ShowExceptions = false
|
||||
},
|
||||
Exoplanets = {
|
||||
ShowComparisonCircle = false,
|
||||
ShowHabitableZone = true,
|
||||
UseOptimisticZone = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
43
scripts/drag_drop_handler.lua
Normal file
43
scripts/drag_drop_handler.lua
Normal file
@@ -0,0 +1,43 @@
|
||||
-- This script gets two parameters in its global scope:
|
||||
-- filename: The full path for the file that was dropped on the application.
|
||||
-- Example: C:/OpenSpace/openspace.cfg
|
||||
-- basename: Only the name of the actual file with extension, but without the full rest
|
||||
-- of the path.
|
||||
-- Example: openspace.cfg
|
||||
-- extension: The extention of the file
|
||||
-- Example: .cfg
|
||||
--
|
||||
-- From this script, we need to return the script that we want to be executed in response
|
||||
-- to the drag event. If we don't want anything to happen, don't return anything or
|
||||
-- return an empty string
|
||||
|
||||
if filename == nil or filename == "" or
|
||||
basename == nil or basename == "" or
|
||||
extension == nil or extension == "" then
|
||||
do return "" end
|
||||
end
|
||||
|
||||
-- Lua doesn't enjoy \ that are used by Windows extensively. So we convert all \ into /
|
||||
filename = filename:gsub("\\", "/")
|
||||
basename = basename:gsub("\\", "/")
|
||||
basename_without_extension = basename:sub(0, #basename - extension:len())
|
||||
|
||||
is_image_file = function(extension)
|
||||
return extension == ".png" or extension == ".jpg" or extension == ".jpeg" or
|
||||
extension == ".tif" or extension == ".tga" or extension == ".bmp" or
|
||||
extension == ".psd" or extension == ".gif" or extension == ".hdr" or
|
||||
extension == ".pic" or extension == ".pnm"
|
||||
end
|
||||
|
||||
if is_image_file(extension) then
|
||||
identifier = basename_without_extension:gsub(" ", "_")
|
||||
return [[openspace.addScreenSpaceRenderable({
|
||||
Identifier = "]] .. identifier .. [[",
|
||||
Type = "ScreenSpaceImageLocal",
|
||||
TexturePath = "]] .. filename .. [["
|
||||
});]]
|
||||
elseif extension == ".asset" then
|
||||
return [[openspace.asset.add("]] .. filename .. [[")]]
|
||||
elseif extension == ".osrec" or extension == ".osrectxt" then
|
||||
return [[openspace.sessionRecording.startPlayback("]] .. basename .. [[")]]
|
||||
end
|
||||
@@ -71,14 +71,18 @@ std::string to_string(const openspace::documentation::TestResult& value) {
|
||||
}
|
||||
else {
|
||||
std::stringstream stream;
|
||||
stream << "Failure." << '\n';
|
||||
stream << "Specification Failure. ";
|
||||
|
||||
for (const TestResult::Offense& offense : value.offenses) {
|
||||
stream << " " << ghoul::to_string(offense) << '\n';
|
||||
stream << fmt::format(" {}", ghoul::to_string(offense));
|
||||
if (!offense.explanation.empty()) {
|
||||
stream << fmt::format(" ({})", offense.explanation);
|
||||
}
|
||||
stream << '\n';
|
||||
}
|
||||
|
||||
for (const TestResult::Warning& warning : value.warnings) {
|
||||
stream << " " << ghoul::to_string(warning) << '\n';
|
||||
stream << fmt::format(" {}\n", ghoul::to_string(warning));
|
||||
}
|
||||
|
||||
return stream.str();
|
||||
@@ -129,17 +133,26 @@ namespace openspace::documentation {
|
||||
|
||||
const std::string DocumentationEntry::Wildcard = "*";
|
||||
|
||||
//std::string concatenate(const std::vector<TestResult::Offense>& offenses) {
|
||||
// std::string result = "Error in specification (";
|
||||
// for (const TestResult::Offense& o : offenses) {
|
||||
// if (o.explanation.empty()) {
|
||||
// result += fmt::format("{} ({}), ", o.offender, ghoul::to_string(o.reason));
|
||||
// }
|
||||
// else {
|
||||
// result += fmt::format("{} ({}: {}), ", o.offender, ghoul::to_string(o.reason), o.explanation);
|
||||
// }
|
||||
// }
|
||||
// result.pop_back();
|
||||
// result.back() = ')';
|
||||
// return result;
|
||||
//}
|
||||
|
||||
SpecificationError::SpecificationError(TestResult res, std::string comp)
|
||||
: ghoul::RuntimeError("Error in specification", std::move(comp))
|
||||
, result(std::move(res))
|
||||
{
|
||||
ghoul_assert(!result.success, "Result's success must be false");
|
||||
|
||||
message += " (";
|
||||
for (const TestResult::Offense& o : result.offenses) {
|
||||
message += o.offender + ',';
|
||||
}
|
||||
message.back() = ')';
|
||||
}
|
||||
|
||||
DocumentationEntry::DocumentationEntry(std::string k, std::shared_ptr<Verifier> v,
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <openspace/documentation/documentationengine.h>
|
||||
#include <ghoul/misc/misc.h>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
|
||||
namespace openspace::documentation {
|
||||
|
||||
@@ -177,6 +178,121 @@ std::string StringVerifier::type() const {
|
||||
return "String";
|
||||
}
|
||||
|
||||
TestResult FileVerifier::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
{
|
||||
TestResult res = StringVerifier::operator()(dict, key);
|
||||
if (!res.success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string file = dict.value<std::string>(key);
|
||||
if (!std::filesystem::exists(file) || !std::filesystem::is_regular_file(file)) {
|
||||
res.success = false;
|
||||
TestResult::Offense off;
|
||||
off.offender = key;
|
||||
off.reason = TestResult::Offense::Reason::Verification;
|
||||
off.explanation = "File did not exist";
|
||||
res.offenses.push_back(off);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string FileVerifier::type() const {
|
||||
return "File";
|
||||
}
|
||||
|
||||
TestResult DirectoryVerifier::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
{
|
||||
TestResult res = StringVerifier::operator()(dict, key);
|
||||
if (!res.success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string dir = dict.value<std::string>(key);
|
||||
if (!std::filesystem::exists(dir) || !std::filesystem::is_directory(dir)) {
|
||||
res.success = false;
|
||||
TestResult::Offense off;
|
||||
off.offender = key;
|
||||
off.reason = TestResult::Offense::Reason::Verification;
|
||||
off.explanation = "Directory did not exist";
|
||||
res.offenses.push_back(off);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string DirectoryVerifier::type() const {
|
||||
return "Directory";
|
||||
}
|
||||
|
||||
TestResult Color3Verifier::operator()(const ghoul::Dictionary& dictionary,
|
||||
const std::string& key) const
|
||||
{
|
||||
TestResult res = Vector3Verifier<double>::operator()(dictionary, key);
|
||||
if (!res.success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
glm::dvec3 values = dictionary.value<glm::dvec3>(key);
|
||||
if (values.x < 0.0 || values.x > 1.0) {
|
||||
res.success = false;
|
||||
res.offenses.push_back({ key + ".x", TestResult::Offense::Reason::Verification });
|
||||
}
|
||||
|
||||
if (values.y < 0.0 || values.y > 1.0) {
|
||||
res.success = false;
|
||||
res.offenses.push_back({ key + ".y", TestResult::Offense::Reason::Verification });
|
||||
}
|
||||
|
||||
if (values.z < 0.0 || values.z > 1.0) {
|
||||
res.success = false;
|
||||
res.offenses.push_back({ key + ".z", TestResult::Offense::Reason::Verification });
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string Color3Verifier::type() const {
|
||||
return std::string("Color3");
|
||||
}
|
||||
|
||||
TestResult Color4Verifier::operator()(const ghoul::Dictionary& dictionary,
|
||||
const std::string& key) const
|
||||
{
|
||||
TestResult res = Vector4Verifier<double>::operator()(dictionary, key);
|
||||
if (!res.success) {
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<double> values = dictionary.value<std::vector<double>>(key);
|
||||
if (values[0] < 0.0 || values[0] > 1.0) {
|
||||
res.success = false;
|
||||
res.offenses.push_back({ key + ".x", TestResult::Offense::Reason::Verification });
|
||||
}
|
||||
|
||||
if (values[1] < 0.0 || values[1] > 1.0) {
|
||||
res.success = false;
|
||||
res.offenses.push_back({ key + ".y", TestResult::Offense::Reason::Verification });
|
||||
}
|
||||
|
||||
if (values[2] < 0.0 || values[2] > 1.0) {
|
||||
res.success = false;
|
||||
res.offenses.push_back({ key + ".z", TestResult::Offense::Reason::Verification });
|
||||
}
|
||||
|
||||
if (values[3] < 0.0 || values[3] > 1.0) {
|
||||
res.success = false;
|
||||
res.offenses.push_back({ key + ".a", TestResult::Offense::Reason::Verification });
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::string Color4Verifier::type() const {
|
||||
return std::string("Color4");
|
||||
}
|
||||
|
||||
template <>
|
||||
TestResult TemplateVerifier<glm::ivec2>::operator()(const ghoul::Dictionary& dict,
|
||||
const std::string& key) const
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <openspace/engine/moduleengine.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/moduleregistration.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
@@ -58,7 +59,20 @@ void ModuleEngine::initialize(
|
||||
if (it != moduleConfigurations.end()) {
|
||||
configuration = it->second;
|
||||
}
|
||||
m->initialize(configuration);
|
||||
try {
|
||||
m->initialize(configuration);
|
||||
}
|
||||
catch (const documentation::SpecificationError& e) {
|
||||
//LFATALC(e.component, e.message);
|
||||
for (const documentation::TestResult::Offense& o : e.result.offenses) {
|
||||
LERRORC(e.component, o.offender + ": " + ghoul::to_string(o.reason));
|
||||
}
|
||||
for (const documentation::TestResult::Warning& w : e.result.warnings) {
|
||||
LWARNINGC(e.component, w.offender + ": " + ghoul::to_string(w.reason));
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
addPropertySubOwner(m);
|
||||
|
||||
}
|
||||
|
||||
@@ -71,7 +71,6 @@
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/font/fontmanager.h>
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/logging/consolelog.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/logging/visualstudiooutputlog.h>
|
||||
#include <ghoul/misc/profiling.h>
|
||||
@@ -83,6 +82,7 @@
|
||||
#include <ghoul/systemcapabilities/openglcapabilitiescomponent.h>
|
||||
#include <glbinding/glbinding.h>
|
||||
#include <glbinding-aux/types_to_string.h>
|
||||
#include <filesystem>
|
||||
#include <future>
|
||||
#include <numeric>
|
||||
#include <sstream>
|
||||
@@ -234,7 +234,6 @@ void OpenSpaceEngine::initialize() {
|
||||
|
||||
using ImmediateFlush = ghoul::logging::LogManager::ImmediateFlush;
|
||||
ghoul::logging::LogManager::initialize(level, ImmediateFlush(immediateFlush));
|
||||
LogMgr.addLog(std::make_unique<ghoul::logging::ConsoleLog>());
|
||||
|
||||
for (const ghoul::Dictionary& log : global::configuration->logging.logs) {
|
||||
try {
|
||||
@@ -1444,6 +1443,52 @@ void OpenSpaceEngine::touchExitCallback(TouchInput input) {
|
||||
}
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::handleDragDrop(const std::string& file) {
|
||||
std::filesystem::path f(file);
|
||||
|
||||
ghoul::lua::LuaState s(ghoul::lua::LuaState::IncludeStandardLibrary::Yes);
|
||||
std::string absolutePath = absPath("${SCRIPTS}/drag_drop_handler.lua");
|
||||
int status = luaL_loadfile(s, absolutePath.c_str());
|
||||
if (status != LUA_OK) {
|
||||
std::string error = lua_tostring(s, -1);
|
||||
LERROR(error);
|
||||
return;
|
||||
}
|
||||
|
||||
ghoul::lua::push(s, file);
|
||||
lua_setglobal(s, "filename");
|
||||
|
||||
std::string basename = f.filename().string();
|
||||
ghoul::lua::push(s, basename);
|
||||
lua_setglobal(s, "basename");
|
||||
|
||||
std::string extension = f.extension().string();
|
||||
std::transform(
|
||||
extension.begin(), extension.end(),
|
||||
extension.begin(),
|
||||
[](char c) { return static_cast<char>(::tolower(c)); }
|
||||
);
|
||||
ghoul::lua::push(s, extension);
|
||||
lua_setglobal(s, "extension");
|
||||
|
||||
status = lua_pcall(s, 0, 1, 0);
|
||||
if (status != LUA_OK) {
|
||||
std::string error = lua_tostring(s, -1);
|
||||
LERROR(error);
|
||||
return;
|
||||
}
|
||||
|
||||
if (lua_isnil(s, -1)) {
|
||||
LWARNING(fmt::format("Unhandled file dropped: {}", file));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string script = ghoul::lua::value<std::string>(s);
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::RemoteScripting::Yes
|
||||
);
|
||||
}
|
||||
|
||||
std::vector<std::byte> OpenSpaceEngine::encode() {
|
||||
ZoneScoped
|
||||
|
||||
@@ -45,6 +45,9 @@ SceneGraphNode* sceneGraphNode(const std::string& name) {
|
||||
|
||||
const Renderable* renderable(const std::string& name) {
|
||||
SceneGraphNode* node = sceneGraphNode(name);
|
||||
if (!node) {
|
||||
return nullptr;
|
||||
}
|
||||
return node->renderable();
|
||||
}
|
||||
|
||||
|
||||
@@ -520,9 +520,8 @@ bool Asset::initialize() {
|
||||
loader()->callOnInitialize(this);
|
||||
}
|
||||
catch (const ghoul::lua::LuaRuntimeException& e) {
|
||||
LERROR(fmt::format(
|
||||
"Failed to initialize asset {}; {}: {}", id(), e.component, e.message
|
||||
));
|
||||
LERROR(fmt::format("Failed to initialize asset {}", id()));
|
||||
LERROR(fmt::format("{}: {}", e.component, e.message));
|
||||
// TODO: rollback;
|
||||
setState(State::InitializationFailed);
|
||||
return false;
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <ghoul/misc/defer.h>
|
||||
#include <ghoul/misc/easing.h>
|
||||
#include <regex>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -68,59 +67,144 @@ void applyRegularExpression(lua_State* L, const std::string& regex,
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
const bool isGroupMode = !groupName.empty();
|
||||
bool isLiteral = false;
|
||||
|
||||
const int type = lua_type(L, -1);
|
||||
|
||||
// Extract the property and node name to be searched for from regex
|
||||
std::string propertyName = "";
|
||||
std::string nodeName = "";
|
||||
size_t wildPos = regex.find_first_of("*");
|
||||
if (wildPos != std::string::npos) {
|
||||
nodeName = regex.substr(0, wildPos);
|
||||
propertyName = regex.substr(wildPos + 1, regex.length());
|
||||
|
||||
// If none then malformed regular expression
|
||||
if (propertyName.empty() && nodeName.empty()) {
|
||||
LERRORC(
|
||||
"applyRegularExpression",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': "
|
||||
"Empty both before and after '*'", regex
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Currently do not support several wildcards
|
||||
if (regex.find_first_of("*", wildPos + 1) != std::string::npos) {
|
||||
LERRORC(
|
||||
"applyRegularExpression",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': "
|
||||
"Currently only one '*' is supported", regex
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Literal or tag
|
||||
else {
|
||||
propertyName = regex;
|
||||
if (!isGroupMode) {
|
||||
isLiteral = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Stores whether we found at least one matching property. If this is false at the end
|
||||
// of the loop, the property name regex was probably misspelled.
|
||||
bool foundMatching = false;
|
||||
std::regex r(regex);
|
||||
for (properties::Property* prop : properties) {
|
||||
// Check the regular expression for all properties
|
||||
const std::string& id = prop->fullyQualifiedIdentifier();
|
||||
|
||||
if (std::regex_match(id, r)) {
|
||||
// If the fully qualified id matches the regular expression, we queue the
|
||||
// value change if the types agree
|
||||
if (isGroupMode) {
|
||||
properties::PropertyOwner* matchingTaggedOwner =
|
||||
findPropertyOwnerWithMatchingGroupTag(
|
||||
prop,
|
||||
groupName
|
||||
);
|
||||
if (!matchingTaggedOwner) {
|
||||
if (isLiteral && id != propertyName) {
|
||||
continue;
|
||||
}
|
||||
else if (!propertyName.empty()){
|
||||
size_t propertyPos = id.find(propertyName);
|
||||
if (propertyPos != std::string::npos) {
|
||||
// Check that the propertyName fully matches the property in id
|
||||
if ((propertyPos + propertyName.length() + 1) < id.length()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Match node name
|
||||
if (!nodeName.empty() && id.find(nodeName) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check tag
|
||||
if (isGroupMode) {
|
||||
properties::PropertyOwner* matchingTaggedOwner =
|
||||
findPropertyOwnerWithMatchingGroupTag(
|
||||
prop,
|
||||
groupName
|
||||
);
|
||||
if (!matchingTaggedOwner) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!nodeName.empty()) {
|
||||
size_t nodePos = id.find(nodeName);
|
||||
if (nodePos != std::string::npos) {
|
||||
|
||||
// Check tag
|
||||
if (isGroupMode) {
|
||||
properties::PropertyOwner* matchingTaggedOwner =
|
||||
findPropertyOwnerWithMatchingGroupTag(
|
||||
prop,
|
||||
groupName
|
||||
);
|
||||
if (!matchingTaggedOwner) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Check that the nodeName fully matches the node in id
|
||||
else if (nodePos != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (type != prop->typeLua()) {
|
||||
LERRORC(
|
||||
"property_setValue",
|
||||
fmt::format(
|
||||
"{}: Property '{}' does not accept input of type '{}'. "
|
||||
"Requested type: '{}'",
|
||||
errorLocation(L),
|
||||
prop->fullyQualifiedIdentifier(),
|
||||
luaTypeToString(type),
|
||||
luaTypeToString(prop->typeLua())
|
||||
)
|
||||
);
|
||||
// Check that the types match
|
||||
if (type != prop->typeLua()) {
|
||||
LERRORC(
|
||||
"property_setValue",
|
||||
fmt::format(
|
||||
"{}: Property '{}' does not accept input of type '{}'. "
|
||||
"Requested type: '{}'",
|
||||
errorLocation(L),
|
||||
prop->fullyQualifiedIdentifier(),
|
||||
luaTypeToString(type),
|
||||
luaTypeToString(prop->typeLua())
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
// If the fully qualified id matches the regular expression, we queue the
|
||||
// value change if the types agree
|
||||
foundMatching = true;
|
||||
|
||||
if (interpolationDuration == 0.0) {
|
||||
global::renderEngine->scene()->removePropertyInterpolation(prop);
|
||||
prop->setLuaValue(L);
|
||||
}
|
||||
else {
|
||||
foundMatching = true;
|
||||
|
||||
if (interpolationDuration == 0.0) {
|
||||
global::renderEngine->scene()->removePropertyInterpolation(prop);
|
||||
prop->setLuaValue(L);
|
||||
}
|
||||
else {
|
||||
prop->setLuaInterpolationTarget(L);
|
||||
global::renderEngine->scene()->addPropertyInterpolation(
|
||||
prop,
|
||||
static_cast<float>(interpolationDuration),
|
||||
easingFunction
|
||||
);
|
||||
}
|
||||
prop->setLuaInterpolationTarget(L);
|
||||
global::renderEngine->scene()->addPropertyInterpolation(
|
||||
prop,
|
||||
static_cast<float>(interpolationDuration),
|
||||
easingFunction
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,15 +234,8 @@ bool doesUriContainGroupTag(const std::string& command, std::string& groupName)
|
||||
}
|
||||
}
|
||||
|
||||
std::string replaceUriWithGroupName(const std::string& uri, const std::string& ownerName)
|
||||
{
|
||||
size_t pos = uri.find_first_of(".");
|
||||
return ownerName + "." + uri.substr(pos);
|
||||
}
|
||||
|
||||
std::string extractUriWithoutGroupName(const std::string& uri) {
|
||||
size_t pos = uri.find_first_of(".");
|
||||
return uri.substr(pos);
|
||||
std::string removeGroupNameFromUri(const std::string& uri) {
|
||||
return uri.substr(uri.find_first_of("."));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -275,60 +352,31 @@ int property_setValue(lua_State* L) {
|
||||
}
|
||||
|
||||
if (optimization.empty()) {
|
||||
// Replace all wildcards * with the correct regex (.*)
|
||||
size_t startPos = uriOrRegex.find("*");
|
||||
while (startPos != std::string::npos) {
|
||||
uriOrRegex.replace(startPos, 1, "(.*)");
|
||||
startPos += 4; // (.*)
|
||||
startPos = uriOrRegex.find("*", startPos);
|
||||
}
|
||||
|
||||
std::string groupName;
|
||||
if (doesUriContainGroupTag(uriOrRegex, groupName)) {
|
||||
std::string pathRemainderToMatch = extractUriWithoutGroupName(uriOrRegex);
|
||||
// Remove group name from start of regex and replace with '.*'
|
||||
uriOrRegex = replaceUriWithGroupName(uriOrRegex, ".*");
|
||||
// Remove group name from start of regex and replace with '*'
|
||||
uriOrRegex = removeGroupNameFromUri(uriOrRegex);
|
||||
}
|
||||
|
||||
try {
|
||||
applyRegularExpression(
|
||||
L,
|
||||
uriOrRegex,
|
||||
allProperties(),
|
||||
interpolationDuration,
|
||||
groupName,
|
||||
easingMethod
|
||||
);
|
||||
}
|
||||
catch (const std::regex_error& e) {
|
||||
LERRORC(
|
||||
"property_setValue",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': {}", uriOrRegex, e.what()
|
||||
)
|
||||
);
|
||||
}
|
||||
applyRegularExpression(
|
||||
L,
|
||||
uriOrRegex,
|
||||
allProperties(),
|
||||
interpolationDuration,
|
||||
groupName,
|
||||
easingMethod
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
else if (optimization == "regex") {
|
||||
try {
|
||||
applyRegularExpression(
|
||||
L,
|
||||
uriOrRegex,
|
||||
allProperties(),
|
||||
interpolationDuration,
|
||||
"",
|
||||
easingMethod
|
||||
);
|
||||
}
|
||||
catch (const std::regex_error& e) {
|
||||
LERRORC(
|
||||
"property_setValueRegex",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': {}", uriOrRegex, e.what()
|
||||
)
|
||||
);
|
||||
}
|
||||
applyRegularExpression(
|
||||
L,
|
||||
uriOrRegex,
|
||||
allProperties(),
|
||||
interpolationDuration,
|
||||
"",
|
||||
easingMethod
|
||||
);
|
||||
}
|
||||
else if (optimization == "single") {
|
||||
properties::Property* prop = property(uriOrRegex);
|
||||
@@ -445,44 +493,116 @@ int property_getProperty(lua_State* L) {
|
||||
|
||||
std::string groupName;
|
||||
if (doesUriContainGroupTag(regex, groupName)) {
|
||||
std::string pathRemainderToMatch = extractUriWithoutGroupName(regex);
|
||||
// Remove group name from start of regex and replace with '.*'
|
||||
regex = replaceUriWithGroupName(regex, ".*");
|
||||
// Remove group name from start of regex and replace with '*'
|
||||
regex = removeGroupNameFromUri(regex);
|
||||
}
|
||||
|
||||
// Replace all wildcards * with the correct regex (.*)
|
||||
size_t startPos = regex.find("*");
|
||||
while (startPos != std::string::npos) {
|
||||
regex.replace(startPos, 1, "(.*)");
|
||||
startPos += 4; // (.*)
|
||||
startPos = regex.find("*", startPos);
|
||||
// Extract the property and node name to be searched for from regex
|
||||
bool isLiteral = false;
|
||||
std::string propertyName = "";
|
||||
std::string nodeName = "";
|
||||
size_t wildPos = regex.find_first_of("*");
|
||||
if (wildPos != std::string::npos) {
|
||||
nodeName = regex.substr(0, wildPos);
|
||||
propertyName = regex.substr(wildPos + 1, regex.length());
|
||||
|
||||
// If none then malformed regular expression
|
||||
if (propertyName.empty() && nodeName.empty()) {
|
||||
LERRORC(
|
||||
"property_getProperty",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': "
|
||||
"Empty both before and after '*'", regex
|
||||
)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Currently do not support several wildcards
|
||||
if (regex.find_first_of("*", wildPos + 1) != std::string::npos) {
|
||||
LERRORC(
|
||||
"property_getProperty",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': "
|
||||
"Currently only one '*' is supported", regex
|
||||
)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Literal or tag
|
||||
else {
|
||||
propertyName = regex;
|
||||
if (groupName.empty()) {
|
||||
isLiteral = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get all matching property uris and save to res
|
||||
std::regex r(regex);
|
||||
std::vector<properties::Property*> props = allProperties();
|
||||
std::vector<std::string> res;
|
||||
for (properties::Property* prop : props) {
|
||||
// Check the regular expression for all properties
|
||||
const std::string& id = prop->fullyQualifiedIdentifier();
|
||||
|
||||
if (std::regex_match(id, r)) {
|
||||
// Filter on the groupname if there was one
|
||||
if (!groupName.empty()) {
|
||||
properties::PropertyOwner* matchingTaggedOwner =
|
||||
findPropertyOwnerWithMatchingGroupTag(
|
||||
prop,
|
||||
groupName
|
||||
);
|
||||
if (!matchingTaggedOwner) {
|
||||
if (isLiteral && id != propertyName) {
|
||||
continue;
|
||||
}
|
||||
else if (!propertyName.empty()) {
|
||||
size_t propertyPos = id.find(propertyName);
|
||||
if (propertyPos != std::string::npos) {
|
||||
// Check that the propertyName fully matches the property in id
|
||||
if ((propertyPos + propertyName.length() + 1) < id.length()) {
|
||||
continue;
|
||||
}
|
||||
res.push_back(id);
|
||||
|
||||
// Match node name
|
||||
if (!nodeName.empty() && id.find(nodeName) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check tag
|
||||
if (!groupName.empty()) {
|
||||
properties::PropertyOwner* matchingTaggedOwner =
|
||||
findPropertyOwnerWithMatchingGroupTag(
|
||||
prop,
|
||||
groupName
|
||||
);
|
||||
if (!matchingTaggedOwner) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
res.push_back(id);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!nodeName.empty()) {
|
||||
size_t nodePos = id.find(nodeName);
|
||||
if (nodePos != std::string::npos) {
|
||||
|
||||
// Check tag
|
||||
if (!groupName.empty()) {
|
||||
properties::PropertyOwner* matchingTaggedOwner =
|
||||
findPropertyOwnerWithMatchingGroupTag(
|
||||
prop,
|
||||
groupName
|
||||
);
|
||||
if (!matchingTaggedOwner) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// Check that the nodeName fully matches the node in id
|
||||
else if (nodePos != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
res.push_back(id);
|
||||
}
|
||||
|
||||
lua_newtable(L);
|
||||
@@ -528,10 +648,10 @@ int addSceneGraphNode(lua_State* L) {
|
||||
global::renderEngine->scene()->initializeNode(node);
|
||||
}
|
||||
catch (const documentation::SpecificationError& e) {
|
||||
LERRORC("Scene", ghoul::to_string(e.result));
|
||||
return ghoul::lua::luaError(
|
||||
L,
|
||||
fmt::format("Error loading scene graph node: {}: {}",
|
||||
e.what(), ghoul::to_string(e.result))
|
||||
fmt::format("Error loading scene graph node: {}", e.what())
|
||||
);
|
||||
}
|
||||
catch (const ghoul::RuntimeError& e) {
|
||||
@@ -602,33 +722,94 @@ int removeSceneGraphNodesFromRegex(lua_State* L) {
|
||||
const std::vector<SceneGraphNode*>& nodes =
|
||||
global::renderEngine->scene()->allSceneGraphNodes();
|
||||
|
||||
// Replace all wildcards * with the correct regex (.*)
|
||||
size_t startPos = name.find("*");
|
||||
while (startPos != std::string::npos) {
|
||||
name.replace(startPos, 1, "(.*)");
|
||||
startPos += 4; // (.*)
|
||||
startPos = name.find("*", startPos);
|
||||
// Extract the property and node name to be searched for from name
|
||||
bool isLiteral = false;
|
||||
std::string propertyName = "";
|
||||
std::string nodeName = "";
|
||||
size_t wildPos = name.find_first_of("*");
|
||||
if (wildPos != std::string::npos) {
|
||||
nodeName = name.substr(0, wildPos);
|
||||
propertyName = name.substr(wildPos + 1, name.length());
|
||||
|
||||
// If none then malformed regular expression
|
||||
if (propertyName.empty() && nodeName.empty()) {
|
||||
LERRORC(
|
||||
"removeSceneGraphNodesFromRegex",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': "
|
||||
"Empty both before and after '*'", name
|
||||
)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Currently do not support several wildcards
|
||||
if (name.find_first_of("*", wildPos + 1) != std::string::npos) {
|
||||
LERRORC(
|
||||
"removeSceneGraphNodesFromRegex",
|
||||
fmt::format(
|
||||
"Malformed regular expression: '{}': "
|
||||
"Currently only one '*' is supported", name
|
||||
)
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// Literal or tag
|
||||
else {
|
||||
propertyName = name;
|
||||
isLiteral = true;
|
||||
}
|
||||
|
||||
bool foundMatch = false;
|
||||
std::vector<SceneGraphNode*> markedList;
|
||||
std::regex r(name);
|
||||
for (SceneGraphNode* node : nodes) {
|
||||
const std::string& identifier = node->identifier();
|
||||
|
||||
if (std::regex_match(identifier, r)) {
|
||||
foundMatch = true;
|
||||
SceneGraphNode* parent = node->parent();
|
||||
if (!parent) {
|
||||
LERRORC(
|
||||
"removeSceneGraphNodesFromRegex",
|
||||
fmt::format("Cannot remove root node")
|
||||
);
|
||||
if (isLiteral && identifier != propertyName) {
|
||||
continue;
|
||||
}
|
||||
else if (!propertyName.empty()) {
|
||||
size_t propertyPos = identifier.find(propertyName);
|
||||
if (propertyPos != std::string::npos) {
|
||||
// Check that the propertyName fully matches the property in id
|
||||
if ((propertyPos + propertyName.length() + 1) < identifier.length()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Match node name
|
||||
if (!nodeName.empty() && identifier.find(nodeName) == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
markedList.push_back(node);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!nodeName.empty()) {
|
||||
size_t nodePos = identifier.find(nodeName);
|
||||
if (nodePos != std::string::npos) {
|
||||
// Check that the nodeName fully matches the node in id
|
||||
if (nodePos != 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
foundMatch = true;
|
||||
SceneGraphNode* parent = node->parent();
|
||||
if (!parent) {
|
||||
LERRORC(
|
||||
"removeSceneGraphNodesFromRegex",
|
||||
fmt::format("Cannot remove root node")
|
||||
);
|
||||
}
|
||||
else {
|
||||
markedList.push_back(node);
|
||||
}
|
||||
}
|
||||
|
||||
if (!foundMatch) {
|
||||
|
||||
Submodule support/coding/codegen updated: 1e942f53f1...1ca72c0202
Reference in New Issue
Block a user