mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-05-02 08:49:20 -05:00
Merge remote-tracking branch 'origin/master' into feature/aurorasaurus
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -219,7 +219,8 @@ public:
|
||||
* The \p identifier must be a name for a sound that was started through the
|
||||
* #playAudio3d function.
|
||||
*
|
||||
* \param handle A valid handle for a track started through the #playAudio3d function
|
||||
* \param identifier The identifier of a track started through the #playAudio3d
|
||||
* function
|
||||
* \param position The new position from which the track originates
|
||||
*/
|
||||
void set3dSourcePosition(const std::string& identifier,
|
||||
@@ -272,7 +273,7 @@ public:
|
||||
|
||||
/**
|
||||
* Sets the position of the speaker for the provided \p channel to the provided
|
||||
* \position. In general, this is considered an advanced feature to accommodate
|
||||
* \p position. In general, this is considered an advanced feature to accommodate
|
||||
* non-standard audio environments.
|
||||
*
|
||||
* \param channel The channel whose speaker's position should be changed
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -187,18 +187,18 @@ RenderableInterpolatedPoints::Interpolation::Interpolation()
|
||||
);
|
||||
// No syncing, as this was triggered from a property change (which happened
|
||||
// based on an already synced script)
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript({
|
||||
.code = script,
|
||||
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
|
||||
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
|
||||
});
|
||||
};
|
||||
|
||||
interpolateToEnd.onChange([triggerInterpolation, this]() {
|
||||
float remaining = value.maxValue() - value;
|
||||
float duration = remaining / speed;
|
||||
triggerInterpolation(
|
||||
value.fullyQualifiedIdentifier(),
|
||||
value.uri(),
|
||||
value.maxValue(),
|
||||
duration
|
||||
);
|
||||
@@ -206,21 +206,21 @@ RenderableInterpolatedPoints::Interpolation::Interpolation()
|
||||
|
||||
interpolateToStart.onChange([triggerInterpolation, this]() {
|
||||
float duration = value / speed;
|
||||
triggerInterpolation(value.fullyQualifiedIdentifier(), 0.f, duration);
|
||||
triggerInterpolation(value.uri(), 0.f, duration);
|
||||
});
|
||||
|
||||
interpolateToNextStep.onChange([triggerInterpolation, this]() {
|
||||
float prevValue = glm::floor(value);
|
||||
float newValue = glm::min(prevValue + 1.f, value.maxValue());
|
||||
float duration = 1.f / speed;
|
||||
triggerInterpolation(value.fullyQualifiedIdentifier(), newValue, duration);
|
||||
triggerInterpolation(value.uri(), newValue, duration);
|
||||
});
|
||||
|
||||
interpolateToPrevStep.onChange([triggerInterpolation, this]() {
|
||||
float prevValue = glm::ceil(value);
|
||||
float newValue = glm::max(prevValue - 1.f, value.minValue());
|
||||
float duration = 1.f / speed;
|
||||
triggerInterpolation(value.fullyQualifiedIdentifier(), newValue, duration);
|
||||
triggerInterpolation(value.uri(), newValue, duration);
|
||||
});
|
||||
|
||||
addProperty(interpolateToEnd);
|
||||
|
||||
@@ -170,10 +170,10 @@ SizeMappingComponent::SizeMappingComponent(const ghoul::Dictionary& dictionary)
|
||||
const Parameters::ScaleUnit scaleUnit =
|
||||
std::get<Parameters::ScaleUnit>(*p.scaleFactor);
|
||||
const DistanceUnit distanceUnit = codegen::map<DistanceUnit>(scaleUnit);
|
||||
scaleFactor = toMeter(distanceUnit);
|
||||
scaleFactor = static_cast<float>(toMeter(distanceUnit));
|
||||
}
|
||||
else if (std::holds_alternative<double>(*p.scaleFactor)) {
|
||||
scaleFactor = std::get<double>(*p.scaleFactor);
|
||||
scaleFactor = static_cast<float>(std::get<double>(*p.scaleFactor));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -330,10 +330,7 @@ void RenderableSphere::render(const RenderData& data, RendererTasks&) {
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
|
||||
if (renderBin() == Renderable::RenderBin::PreDeferredTransparent) {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
glDepthMask(false);
|
||||
}
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
|
||||
|
||||
_sphere->render();
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/scene/translation.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/util/timeconversion.h>
|
||||
#include <openspace/util/updatestructures.h>
|
||||
#include <optional>
|
||||
|
||||
@@ -124,8 +125,13 @@ namespace {
|
||||
// [[codegen::verbatim(EndTimeInfo.description)]]
|
||||
std::string endTime [[codegen::annotation("A valid date in ISO 8601 format")]];
|
||||
|
||||
// [[codegen::verbatim(SampleIntervalInfo.description)]]
|
||||
double sampleInterval;
|
||||
// The interval between samples of the trajectory. This value (together with
|
||||
// 'TimeStampSubsampleFactor') determines how far apart (in time) the samples are
|
||||
// spaced along the trajectory. The time interval between 'StartTime' and
|
||||
// 'EndTime' is split into 'SampleInterval' * 'TimeStampSubsampleFactor' segments.
|
||||
// If this value is not specified, it will be automatically calculated to produce
|
||||
// one sample every two day between the 'StartTime' and 'EndTime'.
|
||||
std::optional<double> sampleInterval;
|
||||
|
||||
// [[codegen::verbatim(TimeSubSampleInfo.description)]]
|
||||
std::optional<int> timeStampSubsampleFactor;
|
||||
@@ -182,7 +188,13 @@ RenderableTrailTrajectory::RenderableTrailTrajectory(const ghoul::Dictionary& di
|
||||
_endTime.onChange([this] { reset(); });
|
||||
addProperty(_endTime);
|
||||
|
||||
_sampleInterval = p.sampleInterval;
|
||||
if (p.sampleInterval.has_value()) {
|
||||
_sampleInterval = *p.sampleInterval;
|
||||
}
|
||||
else {
|
||||
const double delta = Time::convertTime(_endTime) - Time::convertTime(_startTime);
|
||||
_sampleInterval = delta / (openspace::SecondsPerYear * 2);
|
||||
}
|
||||
_sampleInterval.onChange([this] { reset(); });
|
||||
addProperty(_sampleInterval);
|
||||
|
||||
|
||||
@@ -85,15 +85,16 @@ ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary)
|
||||
_useMainDashboard = p.useMainDashboard.value_or(_useMainDashboard);
|
||||
addProperty(_useMainDashboard);
|
||||
|
||||
_scale = 1.f;
|
||||
_scale.setMaxValue(15.f);
|
||||
|
||||
if (_useMainDashboard && p.items.has_value()) {
|
||||
throw ghoul::RuntimeError("Cannot specify items when using the main dashboard");
|
||||
}
|
||||
|
||||
if (!_useMainDashboard) {
|
||||
addPropertySubOwner(_dashboard);
|
||||
}
|
||||
|
||||
if (p.items.has_value()) {
|
||||
ghoul_assert(_useMainDashboard, "Cannot add items to the main dashboard");
|
||||
ghoul_assert(!_useMainDashboard, "Cannot add items to the main dashboard");
|
||||
for (const ghoul::Dictionary& item : *p.items) {
|
||||
std::unique_ptr<DashboardItem> i = DashboardItem::createFromDictionary(item);
|
||||
_dashboard.addDashboardItem(std::move(i));
|
||||
|
||||
@@ -47,7 +47,9 @@ namespace {
|
||||
|
||||
struct [[codegen::Dictionary(ConstantRotation)]] Parameters {
|
||||
// [[codegen::verbatim(RotationInfo.description)]]
|
||||
std::optional<glm::dvec3> rotationAxis;
|
||||
std::optional<glm::dvec3> rotationAxis
|
||||
[[codegen::inrange(glm::dvec3(-1.0), glm::dvec3(1.0))]];
|
||||
|
||||
// [[codegen::verbatim(RotationRateInfo.description)]]
|
||||
std::optional<float> rotationRate;
|
||||
};
|
||||
@@ -100,7 +102,10 @@ glm::dmat3 ConstantRotation::matrix(const UpdateData& data) const {
|
||||
_accumulatedRotation += glm::tau<double>();
|
||||
}
|
||||
|
||||
const glm::dquat q = glm::angleAxis(_accumulatedRotation, _rotationAxis.value());
|
||||
const glm::dquat q = glm::angleAxis(
|
||||
_accumulatedRotation,
|
||||
glm::normalize(_rotationAxis.value())
|
||||
);
|
||||
return glm::toMat3(q);
|
||||
}
|
||||
|
||||
|
||||
@@ -64,10 +64,6 @@ documentation::Documentation LuaRotation::Documentation() {
|
||||
|
||||
LuaRotation::LuaRotation(const ghoul::Dictionary& dictionary)
|
||||
: _luaScriptFile(ScriptInfo)
|
||||
, _state(
|
||||
ghoul::lua::LuaState::IncludeStandardLibrary::Yes,
|
||||
ghoul::lua::LuaState::StrictState::No
|
||||
)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
|
||||
@@ -63,10 +63,6 @@ documentation::Documentation LuaScale::Documentation() {
|
||||
|
||||
LuaScale::LuaScale(const ghoul::Dictionary& dictionary)
|
||||
: _luaScriptFile(ScriptInfo)
|
||||
, _state(
|
||||
ghoul::lua::LuaState::IncludeStandardLibrary::Yes,
|
||||
ghoul::lua::LuaState::StrictState::No
|
||||
)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ in vec3 vs_normalViewSpace;
|
||||
in vec4 vs_positionCameraSpace;
|
||||
in float vs_screenSpaceDepth;
|
||||
in mat3 vs_TBN;
|
||||
in vec3 vs_color;
|
||||
|
||||
uniform float ambientIntensity = 0.2;
|
||||
uniform float diffuseIntensity = 1.0;
|
||||
@@ -36,6 +37,7 @@ uniform float specularIntensity = 1.0;
|
||||
uniform bool performShading = true;
|
||||
|
||||
uniform bool use_forced_color = false;
|
||||
uniform bool use_vertex_colors = false;
|
||||
uniform bool has_texture_diffuse;
|
||||
uniform bool has_texture_normal;
|
||||
uniform bool has_texture_specular;
|
||||
@@ -95,7 +97,7 @@ Fragment getFragment() {
|
||||
}
|
||||
|
||||
// Base color
|
||||
vec4 diffuseAlbedo;
|
||||
vec4 diffuseAlbedo = vec4(0.0);
|
||||
if (has_texture_diffuse) {
|
||||
diffuseAlbedo = texture(texture_diffuse, vs_st);
|
||||
}
|
||||
@@ -103,6 +105,16 @@ Fragment getFragment() {
|
||||
diffuseAlbedo = color_diffuse;
|
||||
}
|
||||
|
||||
// Multiply with vertex color if specified
|
||||
if (use_vertex_colors) {
|
||||
diffuseAlbedo.rgb *= vs_color;
|
||||
|
||||
// Make sure to not go beyond color range
|
||||
diffuseAlbedo.r = clamp(diffuseAlbedo.r, 0.0, 1.0);
|
||||
diffuseAlbedo.g = clamp(diffuseAlbedo.g, 0.0, 1.0);
|
||||
diffuseAlbedo.b = clamp(diffuseAlbedo.b, 0.0, 1.0);
|
||||
}
|
||||
|
||||
if (performShading) {
|
||||
// Specular color
|
||||
vec3 specularAlbedo;
|
||||
@@ -118,7 +130,7 @@ Fragment getFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
// Bumb mapping
|
||||
// Bump mapping
|
||||
vec3 normal;
|
||||
if (has_texture_normal) {
|
||||
vec3 normalAlbedo = texture(texture_normal, vs_st).rgb;
|
||||
|
||||
@@ -30,12 +30,14 @@ layout(location = 0) in vec4 in_position;
|
||||
layout(location = 1) in vec2 in_st;
|
||||
layout(location = 2) in vec3 in_normal;
|
||||
layout(location = 3) in vec3 in_tangent;
|
||||
layout(location = 4) in vec3 in_color;
|
||||
|
||||
out vec2 vs_st;
|
||||
out vec3 vs_normalViewSpace;
|
||||
out float vs_screenSpaceDepth;
|
||||
out vec4 vs_positionCameraSpace;
|
||||
out mat3 vs_TBN;
|
||||
out vec3 vs_color;
|
||||
|
||||
uniform mat4 modelViewTransform;
|
||||
uniform mat4 projectionTransform;
|
||||
@@ -51,6 +53,7 @@ void main() {
|
||||
|
||||
gl_Position = positionScreenSpace;
|
||||
vs_st = in_st;
|
||||
vs_color = in_color;
|
||||
vs_screenSpaceDepth = positionScreenSpace.w;
|
||||
|
||||
vs_normalViewSpace =
|
||||
|
||||
@@ -40,12 +40,23 @@ uniform float saturation;
|
||||
uniform float gamma = 1.0;
|
||||
uniform vec2 borderWidth = vec2(0.1);
|
||||
uniform vec3 borderColor = vec3(0.0);
|
||||
uniform int borderFeather = 0;
|
||||
|
||||
// Accelerated rendering can be used for the CEF browser
|
||||
#define USE_ACCELERATED_RENDERING #{useAcceleratedRendering}
|
||||
|
||||
Fragment getFragment() {
|
||||
Fragment frag;
|
||||
vec4 originalColor;
|
||||
#if USE_ACCELERATED_RENDERING
|
||||
vec2 flippedTexCoords = vec2(vs_st.x, 1.0 - vs_st.y);
|
||||
// Correcting both orientation and color channels
|
||||
originalColor = texture(tex, flippedTexCoords).bgra;
|
||||
#else
|
||||
originalColor = texture(tex, vs_st);
|
||||
#endif
|
||||
|
||||
vec4 texColor = texture(tex, vs_st) * vec4(color, opacity);
|
||||
vec4 texColor = originalColor * vec4(color, opacity);
|
||||
|
||||
frag.color = texColor.a * texColor + (1.0 - texColor.a) * backgroundColor;
|
||||
|
||||
@@ -53,7 +64,14 @@ Fragment getFragment() {
|
||||
if (vs_st.x < borderWidth.x || vs_st.x > 1 - borderWidth.x ||
|
||||
vs_st.y < borderWidth.y || vs_st.y > 1 - borderWidth.y)
|
||||
{
|
||||
frag.color = vec4(borderColor, 1.0);
|
||||
frag.color = vec4(borderColor, opacity);
|
||||
if (borderFeather == 1) {
|
||||
vec2 f1 = vs_st / borderWidth;
|
||||
float g1 = min(f1.x, f1.y);
|
||||
vec2 f2 = (vec2(1) - vs_st) / borderWidth;
|
||||
float g2 = min(f2.x, f2.y);
|
||||
frag.color *= min(g1, g2);
|
||||
}
|
||||
}
|
||||
|
||||
if (frag.color.a == 0.0) {
|
||||
|
||||
@@ -64,10 +64,6 @@ documentation::Documentation LuaTranslation::Documentation() {
|
||||
|
||||
LuaTranslation::LuaTranslation(const ghoul::Dictionary& dictionary)
|
||||
: _luaScriptFile(ScriptInfo)
|
||||
, _state(
|
||||
ghoul::lua::LuaState::IncludeStandardLibrary::Yes,
|
||||
ghoul::lua::LuaState::StrictState::No
|
||||
)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace {
|
||||
"Position",
|
||||
"This value is used as a static offset (in meters) that is applied to the scene "
|
||||
"graph node that this transformation is attached to relative to its parent.",
|
||||
// @VISIBILITY(2.25)
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -216,6 +216,17 @@ void CefWebGuiModule::internalInitialize(const ghoul::Dictionary& configuration)
|
||||
startOrStopGui();
|
||||
});
|
||||
|
||||
global::callback::postDraw->emplace_back([this]() {
|
||||
bool windowChanged = global::windowDelegate->windowHasResized();
|
||||
if (_instance && (windowChanged || _instance->_shouldReshape)){
|
||||
const glm::ivec2 res = global::windowDelegate->guiWindowResolution();
|
||||
_instance->reshape(static_cast<glm::ivec2>(
|
||||
glm::vec2(res) * global::windowDelegate->dpiScaling()
|
||||
));
|
||||
_instance->_shouldReshape = false;
|
||||
}
|
||||
});
|
||||
|
||||
global::callback::draw2D->emplace_back([this](){
|
||||
ZoneScopedN("CefWebGuiModule");
|
||||
|
||||
@@ -227,13 +238,6 @@ void CefWebGuiModule::internalInitialize(const ghoul::Dictionary& configuration)
|
||||
const bool isMaster = global::windowDelegate->isMaster();
|
||||
|
||||
if (isGuiWindow && isMaster && _instance) {
|
||||
if (global::windowDelegate->windowHasResized() || _instance->_shouldReshape) {
|
||||
const glm::ivec2 csws = global::windowDelegate->guiWindowResolution();
|
||||
_instance->reshape(static_cast<glm::ivec2>(
|
||||
static_cast<glm::vec2>(csws) * global::windowDelegate->dpiScaling()
|
||||
));
|
||||
_instance->_shouldReshape = false;
|
||||
}
|
||||
if (_visible) {
|
||||
_instance->draw();
|
||||
}
|
||||
|
||||
@@ -29,8 +29,14 @@ in vec2 vs_st;
|
||||
out vec4 outputColor;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
#define USE_ACCELERATED_RENDERING #{useAcceleratedRendering}
|
||||
|
||||
void main() {
|
||||
outputColor = texture(tex, vs_st);
|
||||
#if USE_ACCELERATED_RENDERING
|
||||
vec2 flippedTexCoords = vec2(vs_st.x, 1.0 - vs_st.y);
|
||||
vec4 texColor = texture(tex, flippedTexCoords);
|
||||
outputColor = texColor.bgra; // Correcting both orientation and color channels
|
||||
#else
|
||||
outputColor = texture(tex, vs_st);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -38,10 +38,14 @@ namespace openspace {
|
||||
|
||||
GUIRenderHandler::GUIRenderHandler() {
|
||||
LDEBUG("Initializing CEF GL environment...");
|
||||
ghoul::Dictionary define;
|
||||
define.setValue("useAcceleratedRendering", _acceleratedRendering);
|
||||
|
||||
_programObject = ghoul::opengl::ProgramObject::Build(
|
||||
"WebGUICEFProgram",
|
||||
absPath("${MODULE_CEFWEBGUI}/shaders/gui_vs.glsl"),
|
||||
absPath("${MODULE_CEFWEBGUI}/shaders/gui_fs.glsl")
|
||||
absPath("${MODULE_CEFWEBGUI}/shaders/gui_fs.glsl"),
|
||||
define
|
||||
);
|
||||
constexpr std::array<float, 12> Vtx = {
|
||||
-1.f, -1.f, -1.f,
|
||||
@@ -53,7 +57,6 @@ GUIRenderHandler::GUIRenderHandler() {
|
||||
glGenVertexArrays(1, &_vao);
|
||||
glBindVertexArray(_vao);
|
||||
glGenBuffers(1, &_vbo);
|
||||
glGenTextures(1, &_texture);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, Vtx.size() * sizeof(float), Vtx.data(), GL_STATIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
|
||||
#include <modules/debugging/rendering/renderabledebugplane.h>
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/engine/configuration.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/engine/globalscallbacks.h>
|
||||
#include <openspace/engine/windowdelegate.h>
|
||||
#include <openspace/navigation/navigationhandler.h>
|
||||
#include <openspace/navigation/path.h>
|
||||
#include <openspace/navigation/pathnavigator.h>
|
||||
@@ -37,15 +40,100 @@
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/scripting/lualibrary.h>
|
||||
#include <openspace/util/factorymanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/font/fontmanager.h>
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/assert.h>
|
||||
#include <ghoul/misc/templatefactory.h>
|
||||
|
||||
#include "debuggingmodule_lua.inl"
|
||||
|
||||
namespace {
|
||||
constexpr std::string_view KeyFontMono = "Mono";
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ShowStatisticsInfo = {
|
||||
"ShowStatistics",
|
||||
"Show Statistics",
|
||||
"Show updating, rendering, and network statistics on all rendering nodes.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo StatisticsScaleInfo = {
|
||||
"StatisticsScale",
|
||||
"Statistics Scale",
|
||||
"This value is scaling the statatistics window by the provided amount. For flat "
|
||||
"projections this is rarely necessary, but it is important when using a setup "
|
||||
"where the cornders of the image are masked out.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo ShowFrameNumberInfo = {
|
||||
"ShowFrameInformation",
|
||||
"Show Frame Information",
|
||||
"If this value is enabled, the current frame number and frame times are rendered "
|
||||
"into the window.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace openspace {
|
||||
|
||||
DebuggingModule::DebuggingModule() : OpenSpaceModule(Name) {}
|
||||
DebuggingModule::DebuggingModule()
|
||||
: OpenSpaceModule(Name)
|
||||
, _showStatistics(ShowStatisticsInfo, false)
|
||||
, _statisticsScale(StatisticsScaleInfo, 1.f, 0.f, 1.f)
|
||||
, _showFrameInformation(ShowFrameNumberInfo, false)
|
||||
{
|
||||
_showStatistics.onChange([this]() {
|
||||
global::windowDelegate->showStatistics(_showStatistics);
|
||||
// We need to reset the scale as it is not updated when the statistics window is
|
||||
// not currently shown
|
||||
global::windowDelegate->setStatisticsGraphScale(_statisticsScale);
|
||||
});
|
||||
addProperty(_showStatistics);
|
||||
|
||||
_statisticsScale.onChange([this]() {
|
||||
global::windowDelegate->setStatisticsGraphScale(_statisticsScale);
|
||||
});
|
||||
addProperty(_statisticsScale);
|
||||
|
||||
addProperty(_showFrameInformation);
|
||||
|
||||
global::callback::render->push_back([this]() {
|
||||
if (_showFrameInformation) {
|
||||
ZoneScopedN("Show Frame Information");
|
||||
WindowDelegate* del = global::windowDelegate;
|
||||
|
||||
glm::vec2 penPosition = glm::vec2(
|
||||
global::renderEngine->fontResolution().x / 2 - 50,
|
||||
global::renderEngine->fontResolution().y / 3
|
||||
);
|
||||
|
||||
std::string fn = std::to_string(global::renderEngine->frameNumber());
|
||||
const WindowDelegate::Frustum frustum = del->frustumMode();
|
||||
std::string fr = [](WindowDelegate::Frustum f) -> std::string {
|
||||
switch (f) {
|
||||
case WindowDelegate::Frustum::Mono: return "";
|
||||
case WindowDelegate::Frustum::LeftEye: return "(left)";
|
||||
case WindowDelegate::Frustum::RightEye: return "(right)";
|
||||
default: throw ghoul::MissingCaseException();
|
||||
|
||||
}
|
||||
}(frustum);
|
||||
|
||||
std::string sgFn = std::to_string(del->swapGroupFrameNumber());
|
||||
std::string dt = std::to_string(del->deltaTime());
|
||||
std::string avgDt = std::to_string(del->averageDeltaTime());
|
||||
|
||||
const std::string res = std::format(
|
||||
"Frame: {} {}\nSwap group frame: {}\nDt: {}\nAvg Dt: {}",
|
||||
fn, fr, sgFn, dt, avgDt
|
||||
);
|
||||
RenderFont(*_fontFrameInfo, penPosition, res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void DebuggingModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
ghoul::TemplateFactory<Renderable>* fRenderable =
|
||||
@@ -55,6 +143,11 @@ void DebuggingModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
fRenderable->registerClass<RenderableDebugPlane>("RenderableDebugPlane");
|
||||
}
|
||||
|
||||
void DebuggingModule::internalInitializeGL() {
|
||||
const Configuration::FontSizes fontSize = global::configuration->fontSize;
|
||||
_fontFrameInfo = global::fontManager->font(KeyFontMono, fontSize.frameInfo);
|
||||
}
|
||||
|
||||
std::vector<documentation::Documentation> DebuggingModule::documentations() const {
|
||||
return {
|
||||
RenderableDebugPlane::Documentation()
|
||||
@@ -63,13 +156,15 @@ std::vector<documentation::Documentation> DebuggingModule::documentations() cons
|
||||
|
||||
scripting::LuaLibrary DebuggingModule::luaLibrary() const {
|
||||
return {
|
||||
"debugging",
|
||||
{
|
||||
.name = "debugging",
|
||||
.functions = {
|
||||
codegen::lua::RenderCameraPath,
|
||||
codegen::lua::RemoveRenderedCameraPath,
|
||||
codegen::lua::RenderPathControlPoints,
|
||||
codegen::lua::RemovePathControlPoints,
|
||||
codegen::lua::AddCartesianAxes
|
||||
codegen::lua::RemovePathControlPoints
|
||||
},
|
||||
.scripts = {
|
||||
absPath("${MODULE_DEBUGGING}/scripts/axes.lua")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#include <openspace/properties/scalar/boolproperty.h>
|
||||
#include <openspace/properties/scalar/floatproperty.h>
|
||||
#include <ghoul/font/font.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class DebuggingModule : public OpenSpaceModule {
|
||||
@@ -41,6 +45,14 @@ public:
|
||||
|
||||
protected:
|
||||
void internalInitialize(const ghoul::Dictionary&) override;
|
||||
void internalInitializeGL() override;
|
||||
|
||||
private:
|
||||
properties::BoolProperty _showStatistics;
|
||||
properties::FloatProperty _statisticsScale;
|
||||
properties::BoolProperty _showFrameInformation;
|
||||
|
||||
std::shared_ptr<ghoul::fontrendering::Font> _fontFrameInfo;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -64,11 +64,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
|
||||
RenderedPathIdentifier
|
||||
);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
addParentScript,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(addParentScript);
|
||||
|
||||
// Get the poses along the path
|
||||
std::vector<CameraPose> poses;
|
||||
@@ -98,9 +94,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
|
||||
"}";
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
std::format("openspace.addSceneGraphNode({})", pointNode),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
std::format("openspace.addSceneGraphNode({})", pointNode)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -121,9 +115,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
|
||||
"}";
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
std::format("openspace.addSceneGraphNode({})", lineNode),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
std::format("openspace.addSceneGraphNode({})", lineNode)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -158,11 +150,10 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
|
||||
// Removes the currently rendered camera path if there is one.
|
||||
[[codegen::luawrap]] void removeRenderedCameraPath() {
|
||||
using namespace openspace;
|
||||
global::scriptEngine->queueScript(
|
||||
std::format("openspace.removeSceneGraphNode('{}');", RenderedPathIdentifier),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.removeSceneGraphNode('{}');", RenderedPathIdentifier
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -191,11 +182,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
|
||||
RenderedPointsIdentifier
|
||||
);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
addParentScript,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(addParentScript);
|
||||
|
||||
const std::vector<glm::dvec3> points = currentPath->controlPoints();
|
||||
|
||||
@@ -230,9 +217,7 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
|
||||
"}";
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
std::format("openspace.addSceneGraphNode({})", node),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
std::format("openspace.addSceneGraphNode({})", node)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -240,67 +225,10 @@ constexpr glm::vec3 OrientationLineColor = glm::vec3(0.0, 1.0, 1.0);
|
||||
// Removes the rendered control points.
|
||||
[[codegen::luawrap]] void removePathControlPoints() {
|
||||
using namespace openspace;
|
||||
global::scriptEngine->queueScript(
|
||||
std::format("openspace.removeSceneGraphNode('{}');", RenderedPointsIdentifier),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a set of Cartesian axes to the scene graph node identified by the first string, to
|
||||
* illustrate its local coordinate system. The second (optional) argument is a scale
|
||||
* value, in meters.
|
||||
*/
|
||||
[[codegen::luawrap]] void addCartesianAxes(std::string nodeIdentifier,
|
||||
std::optional<double> scale)
|
||||
{
|
||||
using namespace openspace;
|
||||
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(nodeIdentifier);
|
||||
if (!n) {
|
||||
throw ghoul::lua::LuaError("Unknown scene graph node: " + nodeIdentifier);
|
||||
}
|
||||
|
||||
if (!scale.has_value()) {
|
||||
scale = 2.0 * n->boundingSphere();
|
||||
if (n->boundingSphere() <= 0.0) {
|
||||
LWARNINGC(
|
||||
"Debugging: Cartesian Axes",
|
||||
"Using zero bounding sphere for scale of created axes. You need to set "
|
||||
"the scale manually for them to be visible"
|
||||
);
|
||||
scale = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string identifier = makeIdentifier(nodeIdentifier + "_AxesXYZ");
|
||||
const std::string& axes = "{"
|
||||
"Identifier = '" + identifier + "',"
|
||||
"Parent = '" + nodeIdentifier + "',"
|
||||
"Transform = { "
|
||||
"Scale = {"
|
||||
"Type = 'StaticScale',"
|
||||
"Scale = " + std::to_string(*scale) + ""
|
||||
"}"
|
||||
"},"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableCartesianAxes',"
|
||||
"Enabled = true,"
|
||||
"XColor = { 1.0, 0.0, 0.0 },"
|
||||
"YColor = { 0.0, 1.0, 0.0 },"
|
||||
"ZColor = { 0.0, 0.0, 1.0 }"
|
||||
"},"
|
||||
"GUI = {"
|
||||
"Name = '" + identifier + "',"
|
||||
"Path = '" + DebuggingGuiPath + "/Coordiante Systems'"
|
||||
"}"
|
||||
"}";
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
std::format("openspace.addSceneGraphNode({});", axes),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.removeSceneGraphNode('{}');", RenderedPointsIdentifier
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
#include "debuggingmodule_lua_codegen.cpp"
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
openspace.debugging.documentation = {
|
||||
{
|
||||
Name = "createCoordinateAxes",
|
||||
Arguments = {
|
||||
{ "nodeIdentifier", "String?" },
|
||||
{ "scale", "Number?" }
|
||||
},
|
||||
Documentation = [[
|
||||
Creates a new scene graph node that show the coordinate system used for the
|
||||
currently selected focus node. The first argument specifies the name of the
|
||||
scene graph node for which the axes should be added. If this parameter is
|
||||
not specified, the current focus node is used instead. The second argument
|
||||
provides the length of the coordinate axis in meters. If this value is not
|
||||
specified 2.5 times the interaction sphere of the selected node is used
|
||||
instead.
|
||||
]]
|
||||
}
|
||||
}
|
||||
|
||||
openspace.debugging.createCoordinateAxes = function (nodeIdentifier, scale)
|
||||
local node = nodeIdentifier or openspace.navigation.getNavigationState().Anchor
|
||||
local sphere = openspace.propertyValue("Scene." .. node .. ".EvaluatedInteractionSphere")
|
||||
if sphere == -1 then
|
||||
sphere = 1
|
||||
end
|
||||
local size = scale or sphere * 2.5
|
||||
|
||||
local nodespec = {
|
||||
Identifier = node .. "_DebugAxes",
|
||||
Parent = node,
|
||||
Transform = {
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = size
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableCartesianAxes"
|
||||
},
|
||||
GUI = {
|
||||
Name = node .. " (Debug Axes)",
|
||||
Path = openspace.propertyValue("Scene." .. node .. ".GuiPath")
|
||||
}
|
||||
}
|
||||
|
||||
openspace.addSceneGraphNode(nodespec)
|
||||
end
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
namespace openspace {
|
||||
|
||||
ghoul::opengl::ProgramObjectManager DigitalUniverseModule::ProgramObjectManager;
|
||||
ghoul::opengl::TextureManager DigitalUniverseModule::TextureManager;
|
||||
|
||||
DigitalUniverseModule::DigitalUniverseModule()
|
||||
: OpenSpaceModule(DigitalUniverseModule::Name)
|
||||
@@ -50,7 +49,6 @@ void DigitalUniverseModule::internalInitialize(const ghoul::Dictionary&) {
|
||||
|
||||
void DigitalUniverseModule::internalDeinitializeGL() {
|
||||
ProgramObjectManager.releaseAll(ghoul::opengl::ProgramObjectManager::Warnings::Yes);
|
||||
TextureManager.releaseAll(ghoul::opengl::TextureManager::Warnings::Yes);
|
||||
}
|
||||
|
||||
std::vector<documentation::Documentation> DigitalUniverseModule::documentations() const {
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include <openspace/util/openspacemodule.h>
|
||||
|
||||
#include <ghoul/opengl/programobjectmanager.h>
|
||||
#include <ghoul/opengl/texturemanager.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -41,7 +40,6 @@ public:
|
||||
std::vector<documentation::Documentation> documentations() const override;
|
||||
|
||||
static ghoul::opengl::ProgramObjectManager ProgramObjectManager;
|
||||
static ghoul::opengl::TextureManager TextureManager;
|
||||
|
||||
protected:
|
||||
void internalInitialize(const ghoul::Dictionary&) override;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -94,6 +94,15 @@ namespace {
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo PlanetDefaultTextureInfo = {
|
||||
"PlanetDefaultTexture",
|
||||
"Planet Default Texture",
|
||||
"The path to an image that should be used by default for the planets in all "
|
||||
"added exoplanet systems. If not specified, the planets are rendered without a "
|
||||
"texture when added.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo OrbitDiscTextureInfo = {
|
||||
"OrbitDiscTexture",
|
||||
"Orbit Disc Texture",
|
||||
@@ -182,6 +191,9 @@ namespace {
|
||||
// [[codegen::verbatim(NoDataTextureInfo.description)]]
|
||||
std::optional<std::filesystem::path> noDataTexture;
|
||||
|
||||
// [[codegen::verbatim(PlanetDefaultTextureInfo.description)]]
|
||||
std::optional<std::filesystem::path> planetDefaultTexture;
|
||||
|
||||
// [[codegen::verbatim(OrbitDiscTextureInfo.description)]]
|
||||
std::optional<std::filesystem::path> orbitDiscTexture;
|
||||
|
||||
@@ -221,6 +233,7 @@ ExoplanetsModule::ExoplanetsModule()
|
||||
, _starTexturePath(StarTextureInfo)
|
||||
, _starGlareTexturePath(StarGlareTextureInfo)
|
||||
, _noDataTexturePath(NoDataTextureInfo)
|
||||
, _planetDefaultTexturePath(PlanetDefaultTextureInfo)
|
||||
, _orbitDiscTexturePath(OrbitDiscTextureInfo)
|
||||
, _habitableZoneTexturePath(HabitableZoneTextureInfo)
|
||||
, _comparisonCircleColor(
|
||||
@@ -244,6 +257,7 @@ ExoplanetsModule::ExoplanetsModule()
|
||||
addProperty(_starTexturePath);
|
||||
addProperty(_starGlareTexturePath);
|
||||
addProperty(_noDataTexturePath);
|
||||
addProperty(_planetDefaultTexturePath);
|
||||
addProperty(_orbitDiscTexturePath);
|
||||
addProperty(_habitableZoneTexturePath);
|
||||
|
||||
@@ -301,6 +315,10 @@ std::filesystem::path ExoplanetsModule::noDataTexturePath() const {
|
||||
return _noDataTexturePath.value();
|
||||
}
|
||||
|
||||
std::filesystem::path ExoplanetsModule::planetDefaultTexturePath() const {
|
||||
return _planetDefaultTexturePath.value();
|
||||
}
|
||||
|
||||
std::filesystem::path ExoplanetsModule::orbitDiscTexturePath() const {
|
||||
return _orbitDiscTexturePath.value();
|
||||
}
|
||||
@@ -354,6 +372,10 @@ void ExoplanetsModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
_starGlareTexturePath = p.starGlareTexture->string();
|
||||
}
|
||||
|
||||
if (p.planetDefaultTexture.has_value()) {
|
||||
_planetDefaultTexturePath = p.planetDefaultTexture->string();
|
||||
}
|
||||
|
||||
if (p.noDataTexture.has_value()) {
|
||||
_noDataTexturePath = p.noDataTexture->string();
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
std::filesystem::path starTexturePath() const;
|
||||
std::filesystem::path starGlareTexturePath() const;
|
||||
std::filesystem::path noDataTexturePath() const;
|
||||
std::filesystem::path planetDefaultTexturePath() const;
|
||||
std::filesystem::path orbitDiscTexturePath() const;
|
||||
std::filesystem::path habitableZoneTexturePath() const;
|
||||
glm::vec3 comparisonCircleColor() const;
|
||||
@@ -72,6 +73,7 @@ protected:
|
||||
properties::StringProperty _starTexturePath;
|
||||
properties::StringProperty _starGlareTexturePath;
|
||||
properties::StringProperty _noDataTexturePath;
|
||||
properties::StringProperty _planetDefaultTexturePath;
|
||||
properties::StringProperty _orbitDiscTexturePath;
|
||||
properties::StringProperty _habitableZoneTexturePath;
|
||||
|
||||
|
||||
@@ -105,6 +105,17 @@ openspace::exoplanets::ExoplanetSystem findExoplanetSystemInData(
|
||||
return system;
|
||||
}
|
||||
|
||||
void queueAddSceneGraphNodeScript(const std::string& sgnTableAsString) {
|
||||
using namespace openspace;
|
||||
// No sync or send because this will already be called inside a Lua script,
|
||||
// therefor it has already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript({
|
||||
.code = std::format("openspace.addSceneGraphNode({})", sgnTableAsString),
|
||||
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
|
||||
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
|
||||
});
|
||||
}
|
||||
|
||||
void createExoplanetSystem(const std::string& starName,
|
||||
openspace::exoplanets::ExoplanetSystem system)
|
||||
{
|
||||
@@ -155,6 +166,14 @@ void createExoplanetSystem(const std::string& starName,
|
||||
if (!std::isnan(bv)) {
|
||||
starColor = computeStarColor(bv);
|
||||
const std::filesystem::path starTexture = module->starTexturePath();
|
||||
|
||||
if (!starTexture.empty() && !std::filesystem::is_regular_file(starTexture)) {
|
||||
LWARNING(std::format(
|
||||
"Could not find specified star texture set in {} module: '{}'",
|
||||
module->guiName(), starTexture
|
||||
));
|
||||
}
|
||||
|
||||
colorLayers =
|
||||
"{"
|
||||
"Identifier = 'StarColor',"
|
||||
@@ -211,15 +230,44 @@ void createExoplanetSystem(const std::string& starName,
|
||||
"}"
|
||||
"}";
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it has
|
||||
// already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + starParent + ");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
queueAddSceneGraphNodeScript(starParent);
|
||||
|
||||
// Add a label for the star.
|
||||
// The fade values are set based on the values for the Sun label
|
||||
const std::string starLabel = "{"
|
||||
"Identifier = '" + starIdentifier + "_Label',"
|
||||
"Parent = '" + starIdentifier + "',"
|
||||
"Renderable = {"
|
||||
"Type = 'RenderableLabel',"
|
||||
"Enabled = false,"
|
||||
"Text = '" + sanitizedStarName + "',"
|
||||
"FontSize = 70.0,"
|
||||
"Size = 14.17,"
|
||||
"MinMaxSize = { 1, 50 },"
|
||||
"EnableFading = true,"
|
||||
"FadeUnit = 'pc',"
|
||||
"FadeDistances = { 1.33, 15.0 },"
|
||||
"FadeWidths = {1.0, 20.0}"
|
||||
"},"
|
||||
"Tag = {'exoplanet_system_labels'},"
|
||||
"GUI = {"
|
||||
"Name = '" + sanitizedStarName + " Label',"
|
||||
"Path = '" + guiPath + "'"
|
||||
"}"
|
||||
"}";
|
||||
|
||||
queueAddSceneGraphNodeScript(starLabel);
|
||||
|
||||
// Planets
|
||||
|
||||
const std::filesystem::path planetTexture = module->planetDefaultTexturePath();
|
||||
if (!planetTexture.empty() && !std::filesystem::is_regular_file(planetTexture)) {
|
||||
LWARNING(std::format(
|
||||
"Could not find specified planet default texture set in {} module: '{}'",
|
||||
module->guiName(), planetTexture
|
||||
));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < system.planetNames.size(); i++) {
|
||||
// Note that we are here overriding some invalid parameters in the planet data.
|
||||
// Use a reference, so that it is changed down the line
|
||||
@@ -286,6 +334,16 @@ void createExoplanetSystem(const std::string& starName,
|
||||
"Period = " + std::to_string(periodInSeconds) + ""
|
||||
"}";
|
||||
|
||||
std::string planetLayers = "";
|
||||
if (!planetTexture.empty()) {
|
||||
planetLayers = "{"
|
||||
"Identifier = 'PlanetTexture',"
|
||||
"FilePath = openspace.absPath('" + formatPathToLua(planetTexture) + "'),"
|
||||
"BlendMode = 'Color',"
|
||||
"Enabled = true"
|
||||
"}";
|
||||
}
|
||||
|
||||
const std::string planetNode = "{"
|
||||
"Identifier = '" + planetIdentifier + "',"
|
||||
"Parent = '" + starIdentifier + "',"
|
||||
@@ -294,7 +352,9 @@ void createExoplanetSystem(const std::string& starName,
|
||||
"Enabled = " + enabled + ","
|
||||
"Radii = " + std::to_string(planetRadius) + "," // in meters
|
||||
"PerformShading = true,"
|
||||
"Layers = {},"
|
||||
"Layers = {"
|
||||
"ColorLayers = {" + planetLayers + "}"
|
||||
"},"
|
||||
"LightSourceNode = '" + starIdentifier + "'"
|
||||
"},"
|
||||
"Transform = { "
|
||||
@@ -330,14 +390,8 @@ void createExoplanetSystem(const std::string& starName,
|
||||
"}"
|
||||
"}";
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it has
|
||||
// already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + planetTrailNode + ");"
|
||||
"openspace.addSceneGraphNode(" + planetNode + ");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
queueAddSceneGraphNodeScript(planetTrailNode);
|
||||
queueAddSceneGraphNodeScript(planetNode);
|
||||
|
||||
bool hasUpperAUncertainty = !std::isnan(planet.aUpper);
|
||||
bool hasLowerAUncertainty = !std::isnan(planet.aLower);
|
||||
@@ -387,13 +441,7 @@ void createExoplanetSystem(const std::string& starName,
|
||||
"}"
|
||||
"}";
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it
|
||||
// has already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + discNode + ");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
queueAddSceneGraphNodeScript(discNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,13 +485,7 @@ void createExoplanetSystem(const std::string& starName,
|
||||
"}"
|
||||
"}";
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it has
|
||||
// already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + circle + ");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
queueAddSceneGraphNodeScript(circle);
|
||||
|
||||
// Habitable Zone
|
||||
bool hasTeff = !std::isnan(system.starData.teff);
|
||||
@@ -491,13 +533,7 @@ void createExoplanetSystem(const std::string& starName,
|
||||
"}"
|
||||
"}";
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it has
|
||||
// already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + zoneDiscNode + ");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
queueAddSceneGraphNodeScript(zoneDiscNode);
|
||||
|
||||
// Star glare
|
||||
if (starColor.has_value()) {
|
||||
@@ -535,13 +571,7 @@ void createExoplanetSystem(const std::string& starName,
|
||||
"}"
|
||||
"}";
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it
|
||||
// has already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + starGlare + ");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
queueAddSceneGraphNodeScript(starGlare);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -650,11 +680,11 @@ std::vector<std::string> hostStarsWithSufficientData() {
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it has
|
||||
// already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + starIdentifier + "');",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript({
|
||||
.code = "openspace.removeSceneGraphNode('" + starIdentifier + "');",
|
||||
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
|
||||
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -1,102 +1,126 @@
|
||||
openspace.gaia.documentation = {
|
||||
{
|
||||
Name = "addClippingBox",
|
||||
Arguments = {{ "name", "String" },{ "size", "vec3" }, { "position", "vec3" }},
|
||||
Documentation = "Creates a clipping box for the Gaia renderable in the first argument"
|
||||
{
|
||||
Name = "addClippingBox",
|
||||
Arguments = {
|
||||
{ "name", "String" },
|
||||
{ "size", "vec3" },
|
||||
{ "position", "vec3" }
|
||||
},
|
||||
{
|
||||
Name = "removeClippingBox",
|
||||
Arguments = {},
|
||||
Documentation = ""
|
||||
Documentation = "Creates a clipping box for the Gaia renderable in the first argument"
|
||||
},
|
||||
{
|
||||
Name = "removeClippingBox",
|
||||
Arguments = {},
|
||||
Documentation = ""
|
||||
},
|
||||
{
|
||||
Name = "addClippingSphere",
|
||||
Arguments = {
|
||||
{ "name", "String" },
|
||||
{ "radius", "Number" }
|
||||
},
|
||||
{
|
||||
Name = "addClippingSphere",
|
||||
Arguments = {{ "name", "String" }, { "radius", "Number" }},
|
||||
Documentation = "Creates a clipping sphere for the Gaia renderable in the first argument"
|
||||
}
|
||||
Documentation = "Creates a clipping sphere for the Gaia renderable in the first argument"
|
||||
}
|
||||
}
|
||||
|
||||
openspace.gaia.addClippingBox = function (name, size, position)
|
||||
local grid_identifier = "Filtering_Box"
|
||||
local kilo_parsec_in_meter = 30856775814913700000
|
||||
local grid_identifier = "Filtering_Box"
|
||||
local kilo_parsec_in_meter = 30856775814913700000
|
||||
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
|
||||
local grid = {
|
||||
Identifier = grid_identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = { position[1] * kilo_parsec_in_meter, position[2] * kilo_parsec_in_meter, position[3] * kilo_parsec_in_meter }
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableBoxGrid",
|
||||
Color = { 0.6, 0.5, 0.7 },
|
||||
LineWidth = 2.0,
|
||||
Size = { size[1] * kilo_parsec_in_meter, size[2] * kilo_parsec_in_meter, size[3] * kilo_parsec_in_meter}
|
||||
},
|
||||
GUI = {
|
||||
Name = "Filtering Grid",
|
||||
Path = "/Other/Grids"
|
||||
local grid = {
|
||||
Identifier = grid_identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
Position = {
|
||||
position[1] * kilo_parsec_in_meter,
|
||||
position[2] * kilo_parsec_in_meter,
|
||||
position[3] * kilo_parsec_in_meter
|
||||
}
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableBoxGrid",
|
||||
Color = { 0.6, 0.5, 0.7 },
|
||||
LineWidth = 2.0,
|
||||
Size = {
|
||||
size[1] * kilo_parsec_in_meter,
|
||||
size[2] * kilo_parsec_in_meter,
|
||||
size[3] * kilo_parsec_in_meter
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Name = "Filtering Grid",
|
||||
Path = "/Other/Grids"
|
||||
}
|
||||
}
|
||||
|
||||
openspace.addSceneGraphNode(grid)
|
||||
openspace.addSceneGraphNode(grid)
|
||||
|
||||
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosX', { (position[1] - size[1] / 2) * kilo_parsec_in_meter, (position[1] + size[1] / 2) * kilo_parsec_in_meter })
|
||||
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosY', { (position[2] - size[2] / 2) * kilo_parsec_in_meter, (position[2] + size[2] / 2) * kilo_parsec_in_meter })
|
||||
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterPosZ', { (position[3] - size[3] / 2) * kilo_parsec_in_meter, (position[3] + size[3] / 2) * kilo_parsec_in_meter })
|
||||
openspace.setPropertyValue(
|
||||
"Scene." .. name .. ".renderable.FilterPosX",
|
||||
{ (position[1] - size[1] / 2) * kilo_parsec_in_meter, (position[1] + size[1] / 2) * kilo_parsec_in_meter }
|
||||
)
|
||||
openspace.setPropertyValue(
|
||||
"Scene." .. name .. ".renderable.FilterPosY",
|
||||
{ (position[2] - size[2] / 2) * kilo_parsec_in_meter, (position[2] + size[2] / 2) * kilo_parsec_in_meter }
|
||||
)
|
||||
openspace.setPropertyValue(
|
||||
"Scene." .. name .. ".renderable.FilterPosZ",
|
||||
{ (position[3] - size[3] / 2) * kilo_parsec_in_meter, (position[3] + size[3] / 2) * kilo_parsec_in_meter }
|
||||
)
|
||||
end
|
||||
|
||||
openspace.gaia.removeClippingBox = function()
|
||||
local grid_identifier = "Filtering_Box"
|
||||
local grid_identifier = "Filtering_Box"
|
||||
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
openspace.gaia.addClippingSphere = function (name, radius)
|
||||
local grid_identifier = "Filtering_Sphere"
|
||||
local kilo_parsec_in_meter = 30856775814913700000
|
||||
local grid_identifier = "Filtering_Sphere"
|
||||
local kilo_parsec_in_meter = 30856775814913700000
|
||||
|
||||
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
|
||||
local grid = {
|
||||
Identifier = grid_identifier,
|
||||
Transform = {
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = radius * kilo_parsec_in_meter
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid",
|
||||
Color = { 0.6, 0.5, 0.7 },
|
||||
LineWidth = 1.0,
|
||||
},
|
||||
GUI = {
|
||||
Name = "Filtering Sphere",
|
||||
Path = "/Other/Grids"
|
||||
}
|
||||
local grid = {
|
||||
Identifier = grid_identifier,
|
||||
Transform = {
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = radius * kilo_parsec_in_meter
|
||||
}
|
||||
},
|
||||
Renderable = {
|
||||
Type = "RenderableSphericalGrid",
|
||||
Color = { 0.6, 0.5, 0.7 },
|
||||
LineWidth = 1.0,
|
||||
},
|
||||
GUI = {
|
||||
Name = "Filtering Sphere",
|
||||
Path = "/Other/Grids"
|
||||
}
|
||||
}
|
||||
|
||||
openspace.addSceneGraphNode(grid)
|
||||
openspace.addSceneGraphNode(grid)
|
||||
|
||||
openspace.setPropertyValue('Scene.' .. name .. '.renderable.FilterDist', radius * kilo_parsec_in_meter)
|
||||
openspace.setPropertyValue("Scene." .. name .. ".renderable.FilterDist", radius * kilo_parsec_in_meter)
|
||||
end
|
||||
|
||||
openspace.gaia.removeClippingSphere = function()
|
||||
local grid_identifier = "Filtering_Sphere"
|
||||
local grid_identifier = "Filtering_Sphere"
|
||||
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
if openspace.hasSceneGraphNode(grid_identifier) then
|
||||
openspace.removeSceneGraphNode(grid_identifier)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
@@ -74,6 +74,7 @@ set(HEADER_FILES
|
||||
src/tileprovider/texttileprovider.h
|
||||
src/tileprovider/tileindextileprovider.h
|
||||
src/tileprovider/tileprovider.h
|
||||
src/tileprovider/tileproviderbydate.h
|
||||
src/tileprovider/tileproviderbyindex.h
|
||||
src/tileprovider/tileproviderbylevel.h
|
||||
)
|
||||
@@ -120,6 +121,7 @@ set(SOURCE_FILES
|
||||
src/tileprovider/texttileprovider.cpp
|
||||
src/tileprovider/tileindextileprovider.cpp
|
||||
src/tileprovider/tileprovider.cpp
|
||||
src/tileprovider/tileproviderbydate.cpp
|
||||
src/tileprovider/tileproviderbyindex.cpp
|
||||
src/tileprovider/tileproviderbylevel.cpp
|
||||
)
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
#include <modules/globebrowsing/src/tileprovider/temporaltileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileindextileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileproviderbydate.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileproviderbyindex.h>
|
||||
#include <modules/globebrowsing/src/tileprovider/tileproviderbylevel.h>
|
||||
#include <openspace/camera/camera.h>
|
||||
@@ -310,6 +311,7 @@ void GlobeBrowsingModule::internalInitialize(const ghoul::Dictionary& dict) {
|
||||
fTileProvider->registerClass<TemporalTileProvider>("TemporalTileProvider");
|
||||
fTileProvider->registerClass<TileIndexTileProvider>("TileIndexTileProvider");
|
||||
fTileProvider->registerClass<SizeReferenceTileProvider>("SizeReferenceTileProvider");
|
||||
fTileProvider->registerClass<TileProviderByDate>("TileProviderByDate");
|
||||
fTileProvider->registerClass<TileProviderByLevel>("TileProviderByLevel");
|
||||
fTileProvider->registerClass<TileProviderByIndex>("TileProviderByIndex");
|
||||
|
||||
@@ -338,6 +340,7 @@ std::vector<documentation::Documentation> GlobeBrowsingModule::documentations()
|
||||
globebrowsing::SizeReferenceTileProvider::Documentation(),
|
||||
globebrowsing::TemporalTileProvider::Documentation(),
|
||||
globebrowsing::TileIndexTileProvider::Documentation(),
|
||||
globebrowsing::TileProviderByDate::Documentation(),
|
||||
globebrowsing::TileProviderByIndex::Documentation(),
|
||||
globebrowsing::TileProviderByLevel::Documentation(),
|
||||
globebrowsing::GeoJsonManager::Documentation(),
|
||||
|
||||
@@ -284,7 +284,8 @@ namespace {
|
||||
* \param y The y value of the tile index
|
||||
* \param level The level of the tile index
|
||||
*/
|
||||
[[codegen::luawrap]] void goToChunk(std::string globeIdentifier, int x, int y, int level) {
|
||||
[[codegen::luawrap]] void goToChunk(std::string globeIdentifier, int x, int y, int level)
|
||||
{
|
||||
using namespace openspace;
|
||||
using namespace globebrowsing;
|
||||
|
||||
@@ -495,8 +496,8 @@ void flyToGeoInternal(std::string globe, double latitude,
|
||||
}
|
||||
|
||||
/**
|
||||
* Fly the camera to a geographic coordinate (latitude, longitude and altitude) on a globe,
|
||||
* using the path navigation system.
|
||||
* Fly the camera to a geographic coordinate (latitude, longitude and altitude) on a
|
||||
* globe, using the path navigation system.
|
||||
*
|
||||
* \param globe The identifier of a scene graph node that has a RenderableGlobe attached.
|
||||
* If an empty string is provided, the current anchor node is used
|
||||
|
||||
@@ -1,396 +1,433 @@
|
||||
openspace.globebrowsing.documentation = {
|
||||
{
|
||||
Name = "createTemporalGibsGdalXml",
|
||||
Arguments = {{ "layerName", "String" }, { "resolution", "String" }, { "format", "String" }},
|
||||
Documentation = [[
|
||||
Creates an XML configuration for a temporal GIBS dataset to be used in
|
||||
a TemporalTileprovider
|
||||
]]
|
||||
{
|
||||
Name = "createTemporalGibsGdalXml",
|
||||
Arguments = {
|
||||
{ "layerName", "String" },
|
||||
{ "resolution", "String" },
|
||||
{ "format", "String" }
|
||||
},
|
||||
{
|
||||
Name = "createGibsGdalXml",
|
||||
Arguments = {{ "layerName", "String" }, { "date", "String" }, { "resolution", "String" }, { "format", "String" }},
|
||||
Documentation =
|
||||
"Creates an XML configuration for a GIBS dataset." ..
|
||||
"Arguments are: layerName, date, resolution, format." ..
|
||||
"For all specifications, see " ..
|
||||
"https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products" ..
|
||||
"Usage:" ..
|
||||
"openspace.globebrowsing.addLayer(" ..
|
||||
"\"Earth\"," ..
|
||||
"\"ColorLayers\"," ..
|
||||
"{" ..
|
||||
"Name = \"MODIS_Terra_Chlorophyll_A\"," ..
|
||||
"FilePath = openspace.globebrowsing.createGibsGdalXml(" ..
|
||||
"\"MODIS_Terra_Chlorophyll_A\"," ..
|
||||
"\"2013-07-02\"," ..
|
||||
"\"1km\"," ..
|
||||
"\"png\"" ..
|
||||
")" ..
|
||||
"}" ..
|
||||
")"
|
||||
Documentation = [[
|
||||
Creates an XML configuration for a temporal GIBS dataset to be used in a
|
||||
TemporalTileprovider
|
||||
]]
|
||||
},
|
||||
{
|
||||
Name = "createGibsGdalXml",
|
||||
Arguments = {
|
||||
{ "layerName", "String" },
|
||||
{ "date", "String" },
|
||||
{ "resolution", "String" },
|
||||
{ "format", "String" }
|
||||
},
|
||||
{
|
||||
Name = "addGibsLayer",
|
||||
Arguments = {{ "layer", "String" }, { "resolution", "String" }, { "format", "String" }, { "startDate", "String" }, { "endDate", "String" }},
|
||||
Documentation = "Adds a new layer from NASA GIBS to the Earth globe. Arguments " ..
|
||||
"are: imagery layer name, imagery resolution, start date, end date, format. " ..
|
||||
"For all specifications, see " ..
|
||||
"https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products" ..
|
||||
"Usage:" ..
|
||||
"openspace.globebrowsing.addGibsLayer('AIRS_Temperature_850hPa_Night', '2km', '2013-07-15', 'Present', 'png')"
|
||||
Documentation = [[
|
||||
Creates an XML configuration for a GIBS dataset.
|
||||
Arguments are: layerName, date, resolution, format.
|
||||
For all specifications, see
|
||||
https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products
|
||||
|
||||
Usage:
|
||||
openspace.globebrowsing.addLayer(
|
||||
"Earth",
|
||||
"ColorLayers",
|
||||
{
|
||||
Name = "MODIS_Terra_Chlorophyll_A",
|
||||
FilePath = openspace.globebrowsing.createGibsGdalXml(
|
||||
"MODIS_Terra_Chlorophyll_A",
|
||||
"2013-07-02",
|
||||
"1km",
|
||||
"png"
|
||||
)
|
||||
}
|
||||
)
|
||||
]]
|
||||
},
|
||||
{
|
||||
Name = "addGibsLayer",
|
||||
Arguments = {
|
||||
{ "layer", "String" },
|
||||
{ "resolution", "String" },
|
||||
{ "format", "String" },
|
||||
{ "startDate", "String" },
|
||||
{ "endDate", "String" }
|
||||
},
|
||||
{
|
||||
Name = "parseInfoFile",
|
||||
Arguments = {{ "file", "String" }},
|
||||
Documentation =
|
||||
"Parses the passed info file and return the table with the information " ..
|
||||
"provided in the info file. The return table contains the optional keys: " ..
|
||||
"'Color', 'Height', 'Node', 'Location', 'Identifier'." ..
|
||||
"Usage: local t = openspace.globebrowsing.parseInfoFile(file)" ..
|
||||
"openspace.globebrowsing.addLayer(\"Earth\", \"ColorLayers\", t.color)" ..
|
||||
"openspace.globebrowsing.addLayer(\"Earth\", \"HeightLayers\", t.height)"
|
||||
Documentation = [[
|
||||
Adds a new layer from NASA GIBS to the Earth globe. Arguments are: imagery layer
|
||||
name, imagery resolution, start date, end date, format.
|
||||
For all specifications, see
|
||||
https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+Available+Imagery+Products
|
||||
Usage:
|
||||
openspace.globebrowsing.addGibsLayer(
|
||||
"AIRS_Temperature_850hPa_Night", "2km", "2013-07-15", "Present", "png"
|
||||
)
|
||||
]]
|
||||
},
|
||||
{
|
||||
Name = "parseInfoFile",
|
||||
Arguments = {
|
||||
{ "file", "String" }
|
||||
},
|
||||
{
|
||||
Name = "addBlendingLayersFromDirectory",
|
||||
Arguments = {{ "directory", "String" }, { "nodeName", "String" }},
|
||||
Documentation =
|
||||
"Retrieves all info files recursively in the directory passed as the first " ..
|
||||
"argument to this function. The color and height tables retrieved from these " ..
|
||||
"info files are then added to the RenderableGlobe identified by name passed " ..
|
||||
"to the second argument." ..
|
||||
"Usage: openspace.globebrowsing.addBlendingLayersFromDirectory(directory, \"Earth\")"
|
||||
Documentation = [[
|
||||
Parses the passed info file and return the table with the information provided in
|
||||
the info file. The return table contains the optional keys:
|
||||
'Color', 'Height', 'Node', 'Location', 'Identifier'.
|
||||
Usage:
|
||||
local t = openspace.globebrowsing.parseInfoFile(file)
|
||||
openspace.globebrowsing.addLayer("Earth", "ColorLayers", t.color)
|
||||
openspace.globebrowsing.addLayer("Earth", "HeightLayers", t.height)
|
||||
]]
|
||||
},
|
||||
{
|
||||
Name = "addBlendingLayersFromDirectory",
|
||||
Arguments = {
|
||||
{ "directory", "String" },
|
||||
{ "nodeName", "String" }
|
||||
},
|
||||
{
|
||||
Name = "addFocusNodesFromDirectory",
|
||||
Arguments = {{ "directory", "String" }, { "nodeName", "String" }},
|
||||
Documentation =
|
||||
"Retrieves all info files recursively in the directory passed as the first " ..
|
||||
"argument to this function. The name and location retrieved from these info " ..
|
||||
"files are then used to create new SceneGraphNodes that can be used as " ..
|
||||
"focus nodes. " ..
|
||||
"Usage: openspace.globebrowsing.addFocusNodesFromDirectory(directory, \"Mars\")"
|
||||
Documentation = [[
|
||||
Retrieves all info files recursively in the directory passed as the first argument
|
||||
to this function. The color and height tables retrieved from these info files are
|
||||
then added to the RenderableGlobe identified by name passed to the second argument.
|
||||
Usage:
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory(directory, "Earth")
|
||||
]]
|
||||
},
|
||||
{
|
||||
Name = "addFocusNodesFromDirectory",
|
||||
Arguments = {
|
||||
{ "directory", "String" },
|
||||
{ "nodeName", "String" }
|
||||
},
|
||||
{
|
||||
Name = "addFocusNodeFromLatLong",
|
||||
Arguments = {{ "name", "String" }, { "globeIdentifier", "String" }, { "latitude", "Number" }, { "longitude", "Number" }, { "altitude", "Number" }},
|
||||
Documentation =
|
||||
"Creates a new SceneGraphNode that can be used as focus node. " ..
|
||||
"Usage: openspace.globebrowsing.addFocusNodeFromLatLong(" ..
|
||||
"\"Olympus Mons\", \"Mars\", -18.65, 226.2, optionalAltitude)"
|
||||
Documentation = [[
|
||||
Retrieves all info files recursively in the directory passed as the first argument
|
||||
to this function. The name and location retrieved from these info files are then
|
||||
used to create new SceneGraphNodes that can be used as focus nodes.
|
||||
Usage:
|
||||
openspace.globebrowsing.addFocusNodesFromDirectory(directory, "Mars")
|
||||
]]
|
||||
},
|
||||
{
|
||||
Name = "addFocusNodeFromLatLong",
|
||||
Arguments = {
|
||||
{ "name", "String" },
|
||||
{ "globeIdentifier", "String" },
|
||||
{ "latitude", "Number" },
|
||||
{ "longitude", "Number" },
|
||||
{ "altitude", "Number" }
|
||||
},
|
||||
{
|
||||
Name = "loadWMSServersFromFile",
|
||||
Arguments = {{ "filePath", "String" }},
|
||||
Documentation =
|
||||
"Loads all WMS servers from the provided file and passes them to the " ..
|
||||
"'openspace.globebrowsing.loadWMSCapabilities' file."
|
||||
}
|
||||
Documentation = [[
|
||||
Creates a new SceneGraphNode that can be used as focus node.
|
||||
Usage:
|
||||
openspace.globebrowsing.addFocusNodeFromLatLong(
|
||||
"Olympus Mons", "Mars", -18.65, 226.2, optionalAltitude
|
||||
)
|
||||
]]
|
||||
},
|
||||
{
|
||||
Name = "loadWMSServersFromFile",
|
||||
Arguments = {
|
||||
{ "filePath", "String" }
|
||||
},
|
||||
Documentation = [[
|
||||
Loads all WMS servers from the provided file and passes them to the
|
||||
'openspace.globebrowsing.loadWMSCapabilities' file.
|
||||
]]
|
||||
}
|
||||
}
|
||||
|
||||
openspace.globebrowsing.addGibsLayer = function(layerName, resolution, format, startDate, endDate)
|
||||
if endDate == 'Present' then
|
||||
endDate = ''
|
||||
end
|
||||
if endDate == "Present" then
|
||||
endDate = ""
|
||||
end
|
||||
|
||||
local layer = {
|
||||
Identifier = layerName,
|
||||
Type = "TemporalTileLayer",
|
||||
Mode = "Prototyped",
|
||||
Prototyped = {
|
||||
Time = {
|
||||
Start = startDate,
|
||||
End = endDate
|
||||
},
|
||||
TemporalResolution = "1d",
|
||||
TimeFormat = "YYYY-MM-DD",
|
||||
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(layerName, resolution, format)
|
||||
}
|
||||
local layer = {
|
||||
Identifier = layerName,
|
||||
Type = "TemporalTileLayer",
|
||||
Mode = "Prototyped",
|
||||
Prototyped = {
|
||||
Time = {
|
||||
Start = startDate,
|
||||
End = endDate
|
||||
},
|
||||
TemporalResolution = "1d",
|
||||
TimeFormat = "YYYY-MM-DD",
|
||||
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(layerName, resolution, format)
|
||||
}
|
||||
}
|
||||
|
||||
openspace.globebrowsing.addLayer(
|
||||
'Earth',
|
||||
'ColorLayers',
|
||||
layer
|
||||
)
|
||||
openspace.globebrowsing.addLayer("Earth", "ColorLayers", layer)
|
||||
end
|
||||
|
||||
openspace.globebrowsing.createGibsGdalXml = function (layerName, date, resolution, format)
|
||||
local tileLevel = 5
|
||||
-- These resolutions are defined by GIBS: https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+API+for+Developers#GIBSAPIforDevelopers-Script-levelAccessviaGDAL
|
||||
if resolution == "2km" then
|
||||
tileLevel = 5
|
||||
elseif resolution == "1km" then
|
||||
tileLevel = 6
|
||||
elseif resolution == "500m" then
|
||||
tileLevel = 7
|
||||
elseif resolution == "250m" then
|
||||
tileLevel = 8
|
||||
elseif resolution == "125m" then
|
||||
tileLevel = 9
|
||||
elseif resolution == "62.5m" then
|
||||
tileLevel = 10
|
||||
elseif resolution == "31.25m" then
|
||||
tileLevel = 11
|
||||
elseif resolution == "15.625m" then
|
||||
tileLevel = 12
|
||||
else
|
||||
openspace.printError("Unknown resolution: " .. resolution)
|
||||
return ""
|
||||
end
|
||||
local tileLevel = 5
|
||||
-- These resolutions are defined by GIBS: https://wiki.earthdata.nasa.gov/display/GIBS/GIBS+API+for+Developers#GIBSAPIforDevelopers-Script-levelAccessviaGDAL
|
||||
if resolution == "2km" then
|
||||
tileLevel = 5
|
||||
elseif resolution == "1km" then
|
||||
tileLevel = 6
|
||||
elseif resolution == "500m" then
|
||||
tileLevel = 7
|
||||
elseif resolution == "250m" then
|
||||
tileLevel = 8
|
||||
elseif resolution == "125m" then
|
||||
tileLevel = 9
|
||||
elseif resolution == "62.5m" then
|
||||
tileLevel = 10
|
||||
elseif resolution == "31.25m" then
|
||||
tileLevel = 11
|
||||
elseif resolution == "15.625m" then
|
||||
tileLevel = 12
|
||||
else
|
||||
openspace.printError("Unknown resolution: " .. resolution)
|
||||
return ""
|
||||
end
|
||||
|
||||
local rasterCount = 3
|
||||
if format == "jpg" then
|
||||
if layerName == "ASTER_GDEM_Greyscale_Shaded_Relief" then
|
||||
rasterCount = 1
|
||||
else
|
||||
rasterCount = 3
|
||||
end
|
||||
elseif format == "png" then
|
||||
rasterCount = 4
|
||||
local rasterCount = 3
|
||||
if format == "jpg" then
|
||||
if layerName == "ASTER_GDEM_Greyscale_Shaded_Relief" then
|
||||
rasterCount = 1
|
||||
else
|
||||
openspace.printError("Unknown format \"" .. format .. "\". Use 'jpg' or 'png'")
|
||||
return ""
|
||||
rasterCount = 3
|
||||
end
|
||||
elseif format == "png" then
|
||||
rasterCount = 4
|
||||
else
|
||||
openspace.printError("Unknown format \"" .. format .. "\". Use 'jpg' or 'png'")
|
||||
return ""
|
||||
end
|
||||
|
||||
local gdalWmsTemplate =
|
||||
local gdalWmsTemplate =
|
||||
"<GDAL_WMS>" ..
|
||||
"<Service name=\"TMS\">" ..
|
||||
"<ServerUrl>https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/" ..
|
||||
layerName .. "/default/" .. date .. "/" .. resolution ..
|
||||
"/${z}/${y}/${x}." .. format .. "</ServerUrl>" ..
|
||||
"</Service>" ..
|
||||
"<DataWindow>" ..
|
||||
"<UpperLeftX>-180.0</UpperLeftX>" ..
|
||||
"<UpperLeftY>90</UpperLeftY>" ..
|
||||
"<LowerRightX>396.0</LowerRightX>" ..
|
||||
"<LowerRightY>-198</LowerRightY>" ..
|
||||
"<TileLevel>" .. tileLevel .. "</TileLevel>" ..
|
||||
"<TileCountX>2</TileCountX>" ..
|
||||
"<TileCountY>1</TileCountY>" ..
|
||||
"<YOrigin>top</YOrigin>" ..
|
||||
"</DataWindow>" ..
|
||||
"<Projection>EPSG:4326</Projection>" ..
|
||||
"<BlockSizeX>512</BlockSizeX>" ..
|
||||
"<BlockSizeY>512</BlockSizeY>" ..
|
||||
"<BandsCount>" .. rasterCount .. "</BandsCount>" ..
|
||||
"<UnsafeSSL>true</UnsafeSSL>" ..
|
||||
"<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>" ..
|
||||
"<ZeroBlockOnServerException>true</ZeroBlockOnServerException>" ..
|
||||
"<Timeout>5</Timeout>" ..
|
||||
"<Service name=\"TMS\">" ..
|
||||
"<ServerUrl>https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/" ..
|
||||
layerName .. "/default/" .. date .. "/" .. resolution ..
|
||||
"/${z}/${y}/${x}." .. format .. "</ServerUrl>" ..
|
||||
"</Service>" ..
|
||||
"<DataWindow>" ..
|
||||
"<UpperLeftX>-180.0</UpperLeftX>" ..
|
||||
"<UpperLeftY>90</UpperLeftY>" ..
|
||||
"<LowerRightX>396.0</LowerRightX>" ..
|
||||
"<LowerRightY>-198</LowerRightY>" ..
|
||||
"<TileLevel>" .. tileLevel .. "</TileLevel>" ..
|
||||
"<TileCountX>2</TileCountX>" ..
|
||||
"<TileCountY>1</TileCountY>" ..
|
||||
"<YOrigin>top</YOrigin>" ..
|
||||
"</DataWindow>" ..
|
||||
"<Projection>EPSG:4326</Projection>" ..
|
||||
"<BlockSizeX>512</BlockSizeX>" ..
|
||||
"<BlockSizeY>512</BlockSizeY>" ..
|
||||
"<BandsCount>" .. rasterCount .. "</BandsCount>" ..
|
||||
"<UnsafeSSL>true</UnsafeSSL>" ..
|
||||
"<ZeroBlockHttpCodes>400,204,404</ZeroBlockHttpCodes>" ..
|
||||
"<ZeroBlockOnServerException>true</ZeroBlockOnServerException>" ..
|
||||
"<Timeout>5</Timeout>" ..
|
||||
"</GDAL_WMS>"
|
||||
|
||||
return gdalWmsTemplate
|
||||
return gdalWmsTemplate
|
||||
end
|
||||
|
||||
openspace.globebrowsing.createTemporalGibsGdalXml = function (layerName, resolution, format)
|
||||
return openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format)
|
||||
return openspace.globebrowsing.createGibsGdalXml(layerName, "${OpenSpaceTimeId}", resolution, format)
|
||||
end
|
||||
|
||||
openspace.globebrowsing.parseInfoFile = function (file)
|
||||
-- We are loading these values from an external info file and since we are switching
|
||||
-- to a strict Lua, we need to predefine these global variables
|
||||
local function declare(name)
|
||||
rawset(_G, name, "")
|
||||
end
|
||||
-- We are loading these values from an external info file and since we are switching
|
||||
-- to a strict Lua, we need to predefine these global variables
|
||||
local function declare(name)
|
||||
rawset(_G, name, "")
|
||||
end
|
||||
|
||||
declare("Name")
|
||||
declare("Identifier")
|
||||
declare("Description")
|
||||
declare("ColorFile")
|
||||
declare("HeightFile")
|
||||
declare("Location")
|
||||
declare("ZIndex")
|
||||
declare("BlendMode")
|
||||
declare("Name")
|
||||
declare("Identifier")
|
||||
declare("Description")
|
||||
declare("ColorFile")
|
||||
declare("HeightFile")
|
||||
declare("Location")
|
||||
declare("ZIndex")
|
||||
declare("BlendMode")
|
||||
|
||||
local dir = openspace.directoryForPath(file)
|
||||
local file_func, error = loadfile(file)
|
||||
if file_func then
|
||||
file_func()
|
||||
else
|
||||
openspace.printError('Error loading file "' .. file .. '": '.. error)
|
||||
return nil
|
||||
end
|
||||
local dir = openspace.directoryForPath(file)
|
||||
local file_func, error = loadfile(file)
|
||||
if file_func then
|
||||
file_func()
|
||||
else
|
||||
openspace.printError('Error loading file "' .. file .. '": '.. error)
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Hoist the global variables into local space
|
||||
local Name = rawget(_G, "Name")
|
||||
local Identifier = rawget(_G, "Identifier")
|
||||
local Description = rawget(_G, "Description")
|
||||
local ColorFile = rawget(_G, "ColorFile")
|
||||
local HeightFile = rawget(_G, "HeightFile")
|
||||
local Location = rawget(_G, "Location")
|
||||
local ZIndex = rawget(_G, "ZIndex")
|
||||
local BlendMode = rawget(_G, "BlendMode")
|
||||
-- Hoist the global variables into local space
|
||||
local Name = rawget(_G, "Name")
|
||||
local Identifier = rawget(_G, "Identifier")
|
||||
local Description = rawget(_G, "Description")
|
||||
local ColorFile = rawget(_G, "ColorFile")
|
||||
local HeightFile = rawget(_G, "HeightFile")
|
||||
local Location = rawget(_G, "Location")
|
||||
local ZIndex = rawget(_G, "ZIndex")
|
||||
local BlendMode = rawget(_G, "BlendMode")
|
||||
|
||||
-- Now we can start
|
||||
local name = Name or Identifier
|
||||
local identifier = Identifier
|
||||
local zIndex = ZIndex
|
||||
local blendMode = BlendMode
|
||||
if zIndex == "" then
|
||||
zIndex = nil
|
||||
end
|
||||
if blendMode == "" then
|
||||
-- Color blending is the default for .info files if nothing else is specified
|
||||
blendMode = "Color"
|
||||
end
|
||||
-- Now we can start
|
||||
local name = Name or Identifier
|
||||
local identifier = Identifier
|
||||
local zIndex = ZIndex
|
||||
local blendMode = BlendMode
|
||||
if zIndex == "" then
|
||||
zIndex = nil
|
||||
end
|
||||
if blendMode == "" then
|
||||
-- Color blending is the default for .info files if nothing else is specified
|
||||
blendMode = "Color"
|
||||
end
|
||||
|
||||
if identifier == "" then
|
||||
openspace.printError('Error loading file "' .. file .. '": No "Identifier" found')
|
||||
return nil
|
||||
end
|
||||
if identifier == "" then
|
||||
openspace.printError('Error loading file "' .. file .. '": No "Identifier" found')
|
||||
return nil
|
||||
end
|
||||
|
||||
local color = nil
|
||||
if ColorFile and ColorFile ~= "" then
|
||||
color = {
|
||||
Identifier = identifier,
|
||||
Name = name,
|
||||
Description = Description or "",
|
||||
FilePath = dir .. '/' .. ColorFile,
|
||||
BlendMode = blendMode,
|
||||
ZIndex = zIndex
|
||||
}
|
||||
end
|
||||
|
||||
local height = nil
|
||||
if HeightFile and HeightFile ~= "" then
|
||||
height = {
|
||||
Identifier = identifier,
|
||||
Name = name,
|
||||
Description = Description or "",
|
||||
FilePath = dir .. '/' .. HeightFile,
|
||||
TilePixelSize = 65,
|
||||
ZIndex = zIndex
|
||||
}
|
||||
end
|
||||
|
||||
local location = nil
|
||||
if Location then
|
||||
location = Location
|
||||
end
|
||||
|
||||
return {
|
||||
Color = color,
|
||||
Height = height,
|
||||
Name = name,
|
||||
Location = location,
|
||||
Identifier = identifier
|
||||
local color = nil
|
||||
if ColorFile and ColorFile ~= "" then
|
||||
color = {
|
||||
Identifier = identifier,
|
||||
Name = name,
|
||||
Description = Description or "",
|
||||
FilePath = dir .. "/" .. ColorFile,
|
||||
BlendMode = blendMode,
|
||||
ZIndex = zIndex
|
||||
}
|
||||
end
|
||||
|
||||
local height = nil
|
||||
if HeightFile and HeightFile ~= "" then
|
||||
height = {
|
||||
Identifier = identifier,
|
||||
Name = name,
|
||||
Description = Description or "",
|
||||
FilePath = dir .. "/" .. HeightFile,
|
||||
TilePixelSize = 65,
|
||||
ZIndex = zIndex
|
||||
}
|
||||
end
|
||||
|
||||
local location = nil
|
||||
if Location then
|
||||
location = Location
|
||||
end
|
||||
|
||||
return {
|
||||
Color = color,
|
||||
Height = height,
|
||||
Name = name,
|
||||
Location = location,
|
||||
Identifier = identifier
|
||||
}
|
||||
end
|
||||
|
||||
openspace.globebrowsing.addBlendingLayersFromDirectory = function (dir, node_name)
|
||||
local function ends_with(str, ending)
|
||||
return ending == '' or str:sub(-#ending) == ending
|
||||
end
|
||||
|
||||
-- Walking the directory with an empty string will cause the current working directory
|
||||
-- to be walked recursively. This is probably not what the users expects (and it is
|
||||
-- also one of the default values in the globebrowsing customization script), so we
|
||||
-- ignore the empty string here
|
||||
|
||||
if dir == nil or dir == '' then
|
||||
openspace.printError("No directory specified")
|
||||
return
|
||||
end
|
||||
if node_name == nil or node_name == '' then
|
||||
openspace.printError("No node name specified")
|
||||
return
|
||||
end
|
||||
|
||||
local files = openspace.walkDirectoryFiles(dir, true, true)
|
||||
|
||||
for _, file in pairs(files) do
|
||||
if file and file:find('.info') and ends_with(file, '.info') then
|
||||
local t = openspace.globebrowsing.parseInfoFile(file)
|
||||
|
||||
if t and t.Color then
|
||||
openspace.printInfo("Adding color layer '" .. t.Color["Identifier"] .. "'")
|
||||
openspace.globebrowsing.addLayer(node_name, "ColorLayers", t.Color)
|
||||
end
|
||||
if t and t.Height then
|
||||
openspace.printInfo("Adding height layer '" .. t.Height["Identifier"] .. "'")
|
||||
openspace.globebrowsing.addLayer(node_name, "HeightLayers", t.Height)
|
||||
end
|
||||
end
|
||||
local function ends_with(str, ending)
|
||||
return ending == "" or str:sub(-#ending) == ending
|
||||
end
|
||||
|
||||
-- Walking the directory with an empty string will cause the current working directory
|
||||
-- to be walked recursively. This is probably not what the users expects (and it is
|
||||
-- also one of the default values in the globebrowsing customization script), so we
|
||||
-- ignore the empty string here
|
||||
|
||||
if dir == nil or dir == "" then
|
||||
openspace.printError("No directory specified")
|
||||
return
|
||||
end
|
||||
if node_name == nil or node_name == "" then
|
||||
openspace.printError("No node name specified")
|
||||
return
|
||||
end
|
||||
|
||||
local files = openspace.walkDirectoryFiles(dir, true, true)
|
||||
|
||||
for _, file in pairs(files) do
|
||||
if file and file:find(".info") and ends_with(file, ".info") then
|
||||
local t = openspace.globebrowsing.parseInfoFile(file)
|
||||
|
||||
if t and t.Color then
|
||||
openspace.printInfo("Adding color layer '" .. t.Color["Identifier"] .. "'")
|
||||
openspace.globebrowsing.addLayer(node_name, "ColorLayers", t.Color)
|
||||
end
|
||||
if t and t.Height then
|
||||
openspace.printInfo("Adding height layer '" .. t.Height["Identifier"] .. "'")
|
||||
openspace.globebrowsing.addLayer(node_name, "HeightLayers", t.Height)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
openspace.globebrowsing.addFocusNodesFromDirectory = function (dir, node_name)
|
||||
local files = openspace.walkDirectoryFiles(dir, true, true)
|
||||
local files = openspace.walkDirectoryFiles(dir, true, true)
|
||||
|
||||
for _, file in pairs(files) do
|
||||
if file and file:find('.info') then
|
||||
local t = openspace.globebrowsing.parseInfoFile(file)
|
||||
for _, file in pairs(files) do
|
||||
if file and file:find(".info") then
|
||||
local t = openspace.globebrowsing.parseInfoFile(file)
|
||||
|
||||
if node_name and t and t.Location then
|
||||
openspace.printInfo("Creating focus node for '" .. node_name .. "'")
|
||||
if node_name and t and t.Location then
|
||||
openspace.printInfo("Creating focus node for '" .. node_name .. "'")
|
||||
|
||||
local lat = t.Location.Center[1]
|
||||
local long = t.Location.Center[2]
|
||||
local lat = t.Location.Center[1]
|
||||
local long = t.Location.Center[2]
|
||||
|
||||
local identifier = node_name .. " - " .. t.Identifier
|
||||
local name = node_name .. " - " .. t.Name
|
||||
local identifier = node_name .. " - " .. t.Identifier
|
||||
local name = node_name .. " - " .. t.Name
|
||||
|
||||
openspace.addSceneGraphNode({
|
||||
Identifier = identifier,
|
||||
Parent = node_name,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GlobeTranslation",
|
||||
Globe = node_name,
|
||||
Latitude = lat,
|
||||
Longitude = long,
|
||||
UseHeightmap = true
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Path = "/Other/Bookmarks",
|
||||
Name = name
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
openspace.addSceneGraphNode({
|
||||
Identifier = identifier,
|
||||
Parent = node_name,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GlobeTranslation",
|
||||
Globe = node_name,
|
||||
Latitude = lat,
|
||||
Longitude = long,
|
||||
UseHeightmap = true
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Path = "/Other/Bookmarks",
|
||||
Name = name
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
openspace.globebrowsing.addFocusNodeFromLatLong = function (name, globe_identifier, lat, long, altitude)
|
||||
altitude = altitude or 0;
|
||||
altitude = altitude or 0;
|
||||
|
||||
local identifier = globe_identifier .. "-" .. name
|
||||
local identifier = globe_identifier .. "-" .. name
|
||||
|
||||
openspace.addSceneGraphNode({
|
||||
Identifier = identifier,
|
||||
Parent = globe_identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GlobeTranslation",
|
||||
Globe = globe_identifier,
|
||||
Latitude = lat,
|
||||
Longitude = long,
|
||||
FixedAltitude = altitude
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Path = "/Other/Bookmarks",
|
||||
Name = identifier
|
||||
}
|
||||
})
|
||||
openspace.addSceneGraphNode({
|
||||
Identifier = identifier,
|
||||
Parent = globe_identifier,
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "GlobeTranslation",
|
||||
Globe = globe_identifier,
|
||||
Latitude = lat,
|
||||
Longitude = long,
|
||||
FixedAltitude = altitude
|
||||
}
|
||||
},
|
||||
GUI = {
|
||||
Path = "/Other/Bookmarks",
|
||||
Name = identifier
|
||||
}
|
||||
})
|
||||
|
||||
return identifier
|
||||
return identifier
|
||||
end
|
||||
|
||||
|
||||
openspace.globebrowsing.loadWMSServersFromFile = function (file_path)
|
||||
local servers = dofile(file_path)
|
||||
local servers = dofile(file_path)
|
||||
|
||||
for key, value in pairs(servers) do
|
||||
local globe = key
|
||||
for _,val in pairs(value) do
|
||||
openspace.globebrowsing.loadWMSCapabilities(
|
||||
val["Name"],
|
||||
globe,
|
||||
val["URL"]
|
||||
)
|
||||
end
|
||||
for key, value in pairs(servers) do
|
||||
local globe = key
|
||||
for _,val in pairs(value) do
|
||||
openspace.globebrowsing.loadWMSCapabilities(val["Name"], globe, val["URL"] )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,35 +1,50 @@
|
||||
openspace.globebrowsing.documentation = {
|
||||
{
|
||||
Name = "setNodePosition",
|
||||
Arguments = {{ "nodeIdentifer", "String" }, { "globeIdentifier", "String" }, { "latitude", "Number" }, { "longitude", "Number" }, { "altitude", "Number" }},
|
||||
Documentation =
|
||||
"Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations. " ..
|
||||
"Usage: openspace.globebrowsing.setNodePosition(" ..
|
||||
"\"Scale_StatueOfLiberty\", \"Earth\", 40.000, -117.5, optionalAltitude)"
|
||||
Arguments = {
|
||||
{ "nodeIdentifer", "String" },
|
||||
{ "globeIdentifier", "String" },
|
||||
{ "latitude", "Number" },
|
||||
{ "longitude", "Number" },
|
||||
{ "altitude", "Number" }
|
||||
},
|
||||
Documentation = [[
|
||||
Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations.
|
||||
Usage:
|
||||
openspace.globebrowsing.setNodePosition(
|
||||
"Scale_StatueOfLiberty", "Earth", 40.000, -117.5, optionalAltitude
|
||||
)
|
||||
]]
|
||||
},
|
||||
{
|
||||
Name = "setNodePositionFromCamera",
|
||||
Arguments = {{ "nodeIdentifer", "String" }, { "useAltitude", "Boolean" }},
|
||||
Documentation =
|
||||
"Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations" ..
|
||||
" to match the camera. Only uses camera position not rotation. If useAltitude" ..
|
||||
" is true, then the position will also be updated to the camera's altitude." ..
|
||||
"Usage: openspace.globebrowsing.setNodePositionFromCamera(" ..
|
||||
"\"Scale_StatueOfLiberty\", optionalUseAltitude)"
|
||||
Arguments = {
|
||||
{ "nodeIdentifer", "String" },
|
||||
{ "useAltitude", "Boolean" }
|
||||
},
|
||||
Documentation = [[
|
||||
Sets the position of a SceneGraphNode that has GlobeTranslation/GlobeRotations to
|
||||
match the camera. Only uses camera position not rotation. If useAltitude is true,
|
||||
then the position will also be updated to the camera's altitude.
|
||||
Usage:
|
||||
openspace.globebrowsing.setNodePositionFromCamera(
|
||||
"Scale_StatueOfLiberty", optionalUseAltitude
|
||||
)
|
||||
]]
|
||||
}
|
||||
}
|
||||
|
||||
openspace.globebrowsing.setNodePosition = function (node_identifer, globe_identifier, lat, lon, altitude)
|
||||
openspace.setParent(node_identifer, globe_identifier)
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Globe', globe_identifier);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Latitude', lat);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Longitude', lon);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Globe', globe_identifier);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Latitude', lat);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Longitude', lon);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Globe", globe_identifier);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Latitude", lat);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Longitude", lon);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Globe", globe_identifier);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Latitude", lat);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Longitude", lon);
|
||||
if (altitude) then
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', altitude);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', altitude);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Altitude", altitude);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Altitude", altitude);
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,14 +52,14 @@ openspace.globebrowsing.setNodePositionFromCamera = function (node_identifer, us
|
||||
local lat, lon, alt = openspace.globebrowsing.geoPositionForCamera();
|
||||
local camera = openspace.navigation.getNavigationState();
|
||||
openspace.setParent(node_identifer, camera.Anchor)
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Globe', camera.Anchor);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Latitude', lat);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Longitude', lon);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Globe', camera.Anchor);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Latitude', lat);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Rotation.Longitude', lon);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Globe", camera.Anchor);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Latitude", lat);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Longitude", lon);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Globe", camera.Anchor);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Latitude", lat);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Rotation.Longitude", lon);
|
||||
if (use_altitude) then
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', alt);
|
||||
openspace.setPropertyValueSingle('Scene.' .. node_identifer .. '.Translation.Altitude', alt);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Altitude", alt);
|
||||
openspace.setPropertyValueSingle("Scene." .. node_identifer .. ".Translation.Altitude", alt);
|
||||
end
|
||||
end
|
||||
|
||||
@@ -151,15 +151,17 @@ vec4 getSample#{layerGroup}#{i}(vec2 uv, vec3 levelWeights,
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 5) // TileIndexTileProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 6) // TileProviderByIndex
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 6) // TileProviderByDate
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 7) // TileProviderByLevel
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 7) // TileProviderByIndex
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 8) // SolidColor
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 8) // TileProviderByLevel
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 9) // SolidColor
|
||||
c.rgb = #{layerGroup}[#{i}].color;
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 9) // SpoutImageProvider
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 10) // SpoutImageProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 10) // VideoTileProvider
|
||||
#elif (#{#{layerGroup}#{i}LayerType} == 11) // VideoTileProvider
|
||||
c = getTexVal(#{layerGroup}[#{i}].pile, levelWeights, uv);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -860,25 +860,19 @@ void GeoJsonComponent::flyToFeature(std::optional<int> index) const {
|
||||
float lat = centroidLat + _latLongOffset.value().x;
|
||||
float lon = centroidLon + _latLongOffset.value().y;
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
std::format(
|
||||
"openspace.globebrowsing.flyToGeo([[{}]], {}, {}, {})",
|
||||
_globeNode.owner()->identifier(), lat, lon, d
|
||||
),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.globebrowsing.flyToGeo([[{}]], {}, {}, {})",
|
||||
_globeNode.owner()->identifier(), lat, lon, d
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
void GeoJsonComponent::triggerDeletion() const {
|
||||
global::scriptEngine->queueScript(
|
||||
std::format(
|
||||
"openspace.globebrowsing.deleteGeoJson([[{}]], [[{}]])",
|
||||
_globeNode.owner()->identifier(), _identifier
|
||||
),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.globebrowsing.deleteGeoJson([[{}]], [[{}]])",
|
||||
_globeNode.owner()->identifier(), _identifier
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace {
|
||||
"Latitude",
|
||||
"The latitude of the location on the globe's surface. The value can range from "
|
||||
"-90 to 90, with negative values representing the southern hemisphere of the "
|
||||
"globe. The default value is 0.0.",
|
||||
"globe.",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
@@ -58,15 +58,15 @@ namespace {
|
||||
"Longitude",
|
||||
"The longitude of the location on the globe's surface. The value can range from "
|
||||
"-180 to 180, with negative values representing the western hemisphere of the "
|
||||
"globe. The default value is 0.0.",
|
||||
"globe.",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo AngleInfo = {
|
||||
"Angle",
|
||||
"Angle",
|
||||
"A rotation angle that can be used to rotate the object around its own y-axis, "
|
||||
"which will be pointing out of the globe's surface.",
|
||||
"A rotation angle (in degrees) that can be used to rotate the object around its "
|
||||
"own y-axis, which will be pointing out of the globe's surface.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
@@ -82,7 +82,8 @@ namespace {
|
||||
constexpr openspace::properties::Property::PropertyInfo UseCameraInfo = {
|
||||
"UseCamera",
|
||||
"Use Camera",
|
||||
"If this value is 'true', the lat and lon are updated to match the camera.",
|
||||
"If this value is 'true', the latitute and longitude are updated each frame "
|
||||
"to match the location of the camera.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
@@ -92,10 +93,10 @@ namespace {
|
||||
[[codegen::annotation("A valid scene graph node with a RenderableGlobe")]];
|
||||
|
||||
// [[codegen::verbatim(LatitudeInfo.description)]]
|
||||
std::optional<double> latitude;
|
||||
double latitude [[codegen::inrange(-90.0, 90.0)]];
|
||||
|
||||
// [[codegen::verbatim(LongitudeInfo.description)]]
|
||||
std::optional<double> longitude;
|
||||
double longitude [[codegen::inrange(-180.0, 180.0)]];
|
||||
|
||||
// [[codegen::verbatim(AngleInfo.description)]]
|
||||
std::optional<double> angle;
|
||||
@@ -132,11 +133,11 @@ GlobeRotation::GlobeRotation(const ghoul::Dictionary& dictionary)
|
||||
});
|
||||
addProperty(_globe);
|
||||
|
||||
_latitude = p.latitude.value_or(_latitude);
|
||||
_latitude = p.latitude;
|
||||
_latitude.onChange([this]() { setUpdateVariables(); });
|
||||
addProperty(_latitude);
|
||||
|
||||
_longitude = p.longitude.value_or(_longitude);
|
||||
_longitude = p.longitude;
|
||||
_longitude.onChange([this]() { setUpdateVariables(); });
|
||||
addProperty(_longitude);
|
||||
|
||||
@@ -151,7 +152,6 @@ GlobeRotation::GlobeRotation(const ghoul::Dictionary& dictionary)
|
||||
_useCamera = p.useCamera.value_or(_useCamera);
|
||||
_useCamera.onChange([this]() { setUpdateVariables(); });
|
||||
addProperty(_useCamera);
|
||||
|
||||
}
|
||||
|
||||
void GlobeRotation::findGlobe() {
|
||||
|
||||
@@ -74,6 +74,7 @@ void GPULayerGroup::setValue(ghoul::opengl::ProgramObject& program,
|
||||
case layers::Layer::ID::SizeReferenceTileProvider:
|
||||
case layers::Layer::ID::TemporalTileProvider:
|
||||
case layers::Layer::ID::TileIndexTileProvider:
|
||||
case layers::Layer::ID::TileProviderByDate:
|
||||
case layers::Layer::ID::TileProviderByIndex:
|
||||
case layers::Layer::ID::TileProviderByLevel: {
|
||||
const ChunkTilePile& ctp = al.chunkTilePile(
|
||||
@@ -146,6 +147,7 @@ void GPULayerGroup::bind(ghoul::opengl::ProgramObject& p, const LayerGroup& laye
|
||||
case layers::Layer::ID::SizeReferenceTileProvider:
|
||||
case layers::Layer::ID::TemporalTileProvider:
|
||||
case layers::Layer::ID::TileIndexTileProvider:
|
||||
case layers::Layer::ID::TileProviderByDate:
|
||||
case layers::Layer::ID::TileProviderByIndex:
|
||||
case layers::Layer::ID::TileProviderByLevel: {
|
||||
gal.gpuChunkTiles.resize(pileSize);
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/documentation/verifier.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <modules/globebrowsing/src/layergroup.h>
|
||||
#include <modules/globebrowsing/src/layermanager.h>
|
||||
#include <modules/globebrowsing/src/tileindex.h>
|
||||
@@ -130,8 +132,8 @@ namespace {
|
||||
std::optional<std::string> type [[codegen::inlist("DefaultTileProvider",
|
||||
"SingleImageProvider", "ImageSequenceTileProvider",
|
||||
"SizeReferenceTileProvider", "TemporalTileProvider", "TileIndexTileProvider",
|
||||
"TileProviderByIndex", "TileProviderByLevel", "SolidColor",
|
||||
"SpoutImageProvider", "VideoTileProvider")]];
|
||||
"TileProviderByDate", "TileProviderByIndex", "TileProviderByLevel",
|
||||
"SolidColor", "SpoutImageProvider", "VideoTileProvider")]];
|
||||
|
||||
// Determine whether the layer is enabled or not. If this value is not specified,
|
||||
// the layer is disabled
|
||||
@@ -320,7 +322,7 @@ Layer::Layer(layers::Group::ID id, const ghoul::Dictionary& layerDict, LayerGrou
|
||||
_remove.onChange([this]() {
|
||||
if (_tileProvider) {
|
||||
_tileProvider->reset();
|
||||
_parent.deleteLayer(identifier());
|
||||
_parent.scheduleDeleteLayer(identifier());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -342,6 +344,7 @@ Layer::Layer(layers::Group::ID id, const ghoul::Dictionary& layerDict, LayerGrou
|
||||
case layers::Layer::ID::SizeReferenceTileProvider:
|
||||
case layers::Layer::ID::TemporalTileProvider:
|
||||
case layers::Layer::ID::TileIndexTileProvider:
|
||||
case layers::Layer::ID::TileProviderByDate:
|
||||
case layers::Layer::ID::TileProviderByIndex:
|
||||
case layers::Layer::ID::TileProviderByLevel:
|
||||
case layers::Layer::ID::VideoTileProvider:
|
||||
@@ -513,6 +516,7 @@ void Layer::initializeBasedOnType(layers::Layer::ID id, ghoul::Dictionary initDi
|
||||
case layers::Layer::ID::SizeReferenceTileProvider:
|
||||
case layers::Layer::ID::TemporalTileProvider:
|
||||
case layers::Layer::ID::TileIndexTileProvider:
|
||||
case layers::Layer::ID::TileProviderByDate:
|
||||
case layers::Layer::ID::TileProviderByIndex:
|
||||
case layers::Layer::ID::TileProviderByLevel:
|
||||
case layers::Layer::ID::VideoTileProvider:
|
||||
@@ -546,6 +550,7 @@ void Layer::addVisibleProperties() {
|
||||
case layers::Layer::ID::SizeReferenceTileProvider:
|
||||
case layers::Layer::ID::TemporalTileProvider:
|
||||
case layers::Layer::ID::TileIndexTileProvider:
|
||||
case layers::Layer::ID::TileProviderByDate:
|
||||
case layers::Layer::ID::TileProviderByIndex:
|
||||
case layers::Layer::ID::TileProviderByLevel:
|
||||
case layers::Layer::ID::VideoTileProvider:
|
||||
|
||||
@@ -89,6 +89,11 @@ void LayerGroup::deinitialize() {
|
||||
void LayerGroup::update() {
|
||||
ZoneScoped;
|
||||
|
||||
for (const std::string& layer : _layersToDelete) {
|
||||
deleteLayer(layer);
|
||||
}
|
||||
_layersToDelete.clear();
|
||||
|
||||
_activeLayers.clear();
|
||||
|
||||
for (const std::unique_ptr<Layer>& layer : _layers) {
|
||||
@@ -159,23 +164,6 @@ Layer* LayerGroup::addLayer(const ghoul::Dictionary& layerDict) {
|
||||
std::stable_sort(_subOwners.begin(), _subOwners.end(), compareZIndexSubOwners);
|
||||
|
||||
_levelBlendingEnabled.setVisibility(properties::Property::Visibility::User);
|
||||
|
||||
properties::PropertyOwner* layerGroup = ptr->owner();
|
||||
properties::PropertyOwner* layerManager = layerGroup->owner();
|
||||
|
||||
// @TODO (emmbr, 2021-11-03) If the layer is added as part of the globe's
|
||||
// dictionary during construction this function is called in the LayerManager's
|
||||
// initialize function. This means that the layerManager does not exists yet, and
|
||||
// we cannot find which SGN it belongs to... Want to avoid doing this check, so
|
||||
// this should be fixed (probably as part of a cleanup/rewite of the LayerManager)
|
||||
if (layerManager) {
|
||||
properties::PropertyOwner* globe = layerManager->owner();
|
||||
properties::PropertyOwner* sceneGraphNode = globe->owner();
|
||||
global::eventEngine->publishEvent<events::EventLayerAdded>(
|
||||
ptr->uri()
|
||||
);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -189,13 +177,7 @@ void LayerGroup::deleteLayer(const std::string& layerName) {
|
||||
// which will no longer be valid once it is deleted
|
||||
removePropertySubOwner(it->get());
|
||||
(*it)->deinitialize();
|
||||
properties::PropertyOwner* layerGroup = it->get()->owner();
|
||||
properties::PropertyOwner* layerManager = layerGroup->owner();
|
||||
properties::PropertyOwner* globe = layerManager->owner();
|
||||
properties::PropertyOwner* sceneGraphNode = globe->owner();
|
||||
global::eventEngine->publishEvent<events::EventLayerRemoved>(
|
||||
it->get()->uri()
|
||||
);
|
||||
|
||||
// We need to keep the name of the layer since we only get it as a reference
|
||||
// and the name needs to survive the deletion
|
||||
const std::string lName = layerName;
|
||||
@@ -217,6 +199,10 @@ void LayerGroup::deleteLayer(const std::string& layerName) {
|
||||
LERROR("Could not find layer " + layerName);
|
||||
}
|
||||
|
||||
void LayerGroup::scheduleDeleteLayer(const std::string& layerName) {
|
||||
_layersToDelete.push_back(layerName);
|
||||
}
|
||||
|
||||
void LayerGroup::moveLayer(int oldPosition, int newPosition) {
|
||||
if (_layers.size() == 1) {
|
||||
ghoul_assert(
|
||||
@@ -292,6 +278,9 @@ void LayerGroup::moveLayer(int oldPosition, int newPosition) {
|
||||
RenderableGlobe* renderable = dynamic_cast<RenderableGlobe*>(manager->owner());
|
||||
ghoul_assert(manager, "Hierarchy error: LayerManager. Owner is not RenderableGlobe");
|
||||
renderable->invalidateShader();
|
||||
|
||||
// Notify that the layers are in a different order
|
||||
global::eventEngine->publishEvent<events::EventPropertyTreeUpdated>(uri());
|
||||
}
|
||||
|
||||
std::vector<Layer*> LayerGroup::layers() const {
|
||||
|
||||
@@ -53,6 +53,9 @@ struct LayerGroup : public properties::PropertyOwner {
|
||||
|
||||
Layer* addLayer(const ghoul::Dictionary& layerDict);
|
||||
void deleteLayer(const std::string& layerName);
|
||||
|
||||
// The same as `deleteLayer` but executed later before the next frame
|
||||
void scheduleDeleteLayer(const std::string& layerName);
|
||||
void moveLayer(int oldPosition, int newPosition);
|
||||
|
||||
/**
|
||||
@@ -81,6 +84,8 @@ private:
|
||||
std::vector<std::unique_ptr<Layer>> _layers;
|
||||
std::vector<Layer*> _activeLayers;
|
||||
|
||||
std::vector<std::string> _layersToDelete;
|
||||
|
||||
properties::BoolProperty _levelBlendingEnabled;
|
||||
std::function<void(Layer*)> _onChangeCallback;
|
||||
};
|
||||
|
||||
@@ -84,6 +84,7 @@ struct Layer {
|
||||
SizeReferenceTileProvider,
|
||||
TemporalTileProvider,
|
||||
TileIndexTileProvider,
|
||||
TileProviderByDate,
|
||||
TileProviderByIndex,
|
||||
TileProviderByLevel,
|
||||
SolidColor,
|
||||
@@ -95,7 +96,7 @@ struct Layer {
|
||||
std::string_view identifier;
|
||||
};
|
||||
|
||||
constexpr std::array<Layer, 11> Layers = {
|
||||
constexpr std::array<Layer, 12> Layers = {
|
||||
Layer {
|
||||
.id = Layer::ID::DefaultTileProvider,
|
||||
.identifier = "DefaultTileProvider"
|
||||
@@ -120,6 +121,10 @@ constexpr std::array<Layer, 11> Layers = {
|
||||
.id = Layer::ID::TileIndexTileProvider,
|
||||
.identifier = "TileIndexTileProvider"
|
||||
},
|
||||
Layer {
|
||||
.id = Layer::ID::TileProviderByDate,
|
||||
.identifier = "TileProviderByDate"
|
||||
},
|
||||
Layer {
|
||||
.id = Layer::ID::TileProviderByIndex,
|
||||
.identifier = "TileProviderByIndex"
|
||||
|
||||
@@ -176,6 +176,13 @@ namespace {
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo AmbientIntensityInfo = {
|
||||
"AmbientIntensity",
|
||||
"Ambient Intensity",
|
||||
"The intensity factor for the ambient light used for light shading.",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo LightSourceNodeInfo = {
|
||||
"LightSourceNode",
|
||||
"Light Source",
|
||||
@@ -253,13 +260,6 @@ namespace {
|
||||
openspace::properties::Property::Visibility::Developer
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo AmbientIntensityInfo = {
|
||||
"AmbientIntensity",
|
||||
"Ambient Intensity",
|
||||
"The intensity factor for the ambient light used for light shading.",
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo NActiveLayersInfo = {
|
||||
"NActiveLayers",
|
||||
"Number of active layers",
|
||||
@@ -276,9 +276,24 @@ namespace {
|
||||
// [[codegen::verbatim(PerformShadingInfo.description)]]
|
||||
std::optional<bool> performShading;
|
||||
|
||||
// [[codegen::verbatim(AccurateNormalsInfo.description)]]
|
||||
std::optional<bool> useAccurateNormals;
|
||||
|
||||
// [[codegen::verbatim(AmbientIntensityInfo.description)]]
|
||||
std::optional<float> ambientIntensity;
|
||||
|
||||
// [[codegen::verbatim(LightSourceNodeInfo.description)]]
|
||||
std::optional<std::string> lightSourceNode;
|
||||
|
||||
// [[codegen::verbatim(RenderAtDistanceInfo.description)]]
|
||||
std::optional<bool> renderAtDistance;
|
||||
|
||||
// [[codegen::verbatim(TargetLodScaleFactorInfo.description)]]
|
||||
std::optional<float> targetLodScaleFactor;
|
||||
|
||||
// [[codegen::verbatim(OrenNayarRoughnessInfo.description)]]
|
||||
std::optional<float> orenNayarRoughness;
|
||||
|
||||
// A list of layers that should be added to the globe.
|
||||
std::optional<std::map<std::string, ghoul::Dictionary>> layers
|
||||
[[codegen::reference("globebrowsing_layermanager")]];
|
||||
@@ -314,9 +329,6 @@ namespace {
|
||||
|
||||
std::optional<ghoul::Dictionary> shadows
|
||||
[[codegen::reference("globebrowsing_shadows_component")]];
|
||||
|
||||
// [[codegen::verbatim(LightSourceNodeInfo.description)]]
|
||||
std::optional<std::string> lightSourceNode;
|
||||
};
|
||||
#include "renderableglobe_codegen.cpp"
|
||||
} // namespace
|
||||
@@ -570,6 +582,17 @@ documentation::Documentation RenderableGlobe::Documentation() {
|
||||
|
||||
RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
: Renderable(dictionary)
|
||||
, _performShading(PerformShadingInfo, true)
|
||||
, _useAccurateNormals(AccurateNormalsInfo, false)
|
||||
, _ambientIntensity(AmbientIntensityInfo, 0.05f, 0.f, 1.f)
|
||||
, _lightSourceNodeName(LightSourceNodeInfo)
|
||||
, _renderAtDistance(RenderAtDistanceInfo, false)
|
||||
, _eclipseShadowsEnabled(EclipseInfo, false)
|
||||
, _eclipseHardShadows(EclipseHardShadowsInfo, false)
|
||||
, _targetLodScaleFactor(TargetLodScaleFactorInfo, 15.f, 1.f, 50.f)
|
||||
, _currentLodScaleFactor(CurrentLodScaleFactorInfo, 15.f, 1.f, 50.f)
|
||||
, _orenNayarRoughness(OrenNayarRoughnessInfo, 0.f, 0.f, 1.f)
|
||||
, _nActiveLayers(NActiveLayersInfo, 0, 0, OpenGLCap.maxTextureUnits() / 3)
|
||||
, _debugProperties({
|
||||
BoolProperty(ShowChunkEdgeInfo, false),
|
||||
BoolProperty(LevelProjectedAreaInfo, true),
|
||||
@@ -578,31 +601,20 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
IntProperty(ModelSpaceRenderingInfo, 14, 1, 22),
|
||||
IntProperty(DynamicLodIterationCountInfo, 16, 4, 128)
|
||||
})
|
||||
, _generalProperties({
|
||||
BoolProperty(PerformShadingInfo, true),
|
||||
BoolProperty(AccurateNormalsInfo, false),
|
||||
BoolProperty(EclipseInfo, false),
|
||||
BoolProperty(EclipseHardShadowsInfo, false),
|
||||
BoolProperty(ShadowMappingInfo, false),
|
||||
BoolProperty(RenderAtDistanceInfo, false),
|
||||
FloatProperty(ZFightingPercentageInfo, 0.995f, 0.000001f, 1.f),
|
||||
IntProperty(NumberShadowSamplesInfo, 5, 1, 7),
|
||||
FloatProperty(TargetLodScaleFactorInfo, 15.f, 1.f, 50.f),
|
||||
FloatProperty(CurrentLodScaleFactorInfo, 15.f, 1.f, 50.f),
|
||||
FloatProperty(OrenNayarRoughnessInfo, 0.f, 0.f, 1.f),
|
||||
FloatProperty(AmbientIntensityInfo, 0.05f, 0.f, 1.f),
|
||||
IntProperty(NActiveLayersInfo, 0, 0, OpenGLCap.maxTextureUnits() / 3)
|
||||
})
|
||||
, _debugPropertyOwner({ "Debug" })
|
||||
, _shadowMappingPropertyOwner({ "ShadowMapping" })
|
||||
, _shadowMappingProperties({
|
||||
BoolProperty(ShadowMappingInfo, false),
|
||||
FloatProperty(ZFightingPercentageInfo, 0.995f, 0.000001f, 1.f),
|
||||
IntProperty(NumberShadowSamplesInfo, 5, 1, 7)
|
||||
})
|
||||
, _shadowMappingPropertyOwner({ "ShadowMapping", "Shadow Mapping"})
|
||||
, _grid(DefaultSkirtedGridSegments, DefaultSkirtedGridSegments)
|
||||
, _leftRoot(Chunk(LeftHemisphereIndex))
|
||||
, _rightRoot(Chunk(RightHemisphereIndex))
|
||||
, _lightSourceNodeName(LightSourceNodeInfo)
|
||||
{
|
||||
const Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
_generalProperties.currentLodScaleFactor.setReadOnly(true);
|
||||
_currentLodScaleFactor.setReadOnly(true);
|
||||
|
||||
// Read the radii in to its own dictionary
|
||||
if (p.radii.has_value()) {
|
||||
@@ -623,12 +635,6 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
// For globes, the interaction sphere is always the same as the bounding sphere
|
||||
setInteractionSphere(boundingSphere());
|
||||
|
||||
_generalProperties.performShading =
|
||||
p.performShading.value_or(_generalProperties.performShading);
|
||||
|
||||
_generalProperties.renderAtDistance =
|
||||
p.renderAtDistance.value_or(_generalProperties.renderAtDistance);
|
||||
|
||||
// Init layer manager
|
||||
// @TODO (abock, 2021-03-25) The layermanager should be changed to take a
|
||||
// std::map<std::string, ghoul::Dictionary> instead and then we don't need to get it
|
||||
@@ -642,9 +648,18 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
|
||||
addProperty(Fadeable::_opacity);
|
||||
addProperty(_generalProperties.performShading);
|
||||
addProperty(_generalProperties.useAccurateNormals);
|
||||
addProperty(_generalProperties.renderAtDistance);
|
||||
|
||||
_performShading = p.performShading.value_or(_performShading);
|
||||
addProperty(_performShading);
|
||||
|
||||
_useAccurateNormals = p.useAccurateNormals.value_or(_useAccurateNormals);
|
||||
addProperty(_useAccurateNormals);
|
||||
|
||||
_renderAtDistance = p.renderAtDistance.value_or(_renderAtDistance);
|
||||
addProperty(_renderAtDistance);
|
||||
|
||||
_ambientIntensity = p.ambientIntensity.value_or(_ambientIntensity);
|
||||
addProperty(_ambientIntensity);
|
||||
|
||||
_lightSourceNodeName.onChange([this]() {
|
||||
if (_lightSourceNodeName.value().empty()) {
|
||||
@@ -678,29 +693,33 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
_ellipsoid.setShadowConfigurationArray(shadowConfArray);
|
||||
|
||||
addProperty(_generalProperties.eclipseShadowsEnabled);
|
||||
addProperty(_generalProperties.eclipseHardShadows);
|
||||
// TODO: Missing value from parameters
|
||||
addProperty(_eclipseShadowsEnabled);
|
||||
addProperty(_eclipseHardShadows);
|
||||
}
|
||||
|
||||
_shadowMappingPropertyOwner.addProperty(_generalProperties.shadowMapping);
|
||||
_shadowMappingPropertyOwner.addProperty(_generalProperties.zFightingPercentage);
|
||||
_shadowMappingPropertyOwner.addProperty(_generalProperties.nShadowSamples);
|
||||
_generalProperties.nShadowSamples.onChange([this]() {
|
||||
_shadowMappingPropertyOwner.addProperty(_shadowMappingProperties.shadowMapping);
|
||||
_shadowMappingPropertyOwner.addProperty(_shadowMappingProperties.zFightingPercentage);
|
||||
_shadowMappingPropertyOwner.addProperty(_shadowMappingProperties.nShadowSamples);
|
||||
_shadowMappingProperties.nShadowSamples.onChange([this]() {
|
||||
_shadersNeedRecompilation = true;
|
||||
});
|
||||
addPropertySubOwner(_shadowMappingPropertyOwner);
|
||||
|
||||
_generalProperties.targetLodScaleFactor.onChange([this]() {
|
||||
const float sf = _generalProperties.targetLodScaleFactor;
|
||||
_generalProperties.currentLodScaleFactor = sf;
|
||||
_targetLodScaleFactor = p.targetLodScaleFactor.value_or(_targetLodScaleFactor);
|
||||
_targetLodScaleFactor.onChange([this]() {
|
||||
const float sf = _targetLodScaleFactor;
|
||||
_currentLodScaleFactor = sf;
|
||||
_lodScaleFactorDirty = true;
|
||||
});
|
||||
addProperty(_generalProperties.targetLodScaleFactor);
|
||||
addProperty(_generalProperties.currentLodScaleFactor);
|
||||
addProperty(_generalProperties.orenNayarRoughness);
|
||||
addProperty(_generalProperties.ambientIntensity);
|
||||
_generalProperties.nActiveLayers.setReadOnly(true);
|
||||
addProperty(_generalProperties.nActiveLayers);
|
||||
addProperty(_targetLodScaleFactor);
|
||||
addProperty(_currentLodScaleFactor);
|
||||
|
||||
_orenNayarRoughness = p.orenNayarRoughness.value_or(_orenNayarRoughness);
|
||||
addProperty(_orenNayarRoughness);
|
||||
|
||||
_nActiveLayers.setReadOnly(true);
|
||||
addProperty(_nActiveLayers);
|
||||
|
||||
_debugPropertyOwner.addProperty(_debugProperties.showChunkEdges);
|
||||
_debugPropertyOwner.addProperty(_debugProperties.levelByProjectedAreaElseDistance);
|
||||
@@ -708,15 +727,17 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
_debugPropertyOwner.addProperty(_debugProperties.performFrustumCulling);
|
||||
_debugPropertyOwner.addProperty(_debugProperties.modelSpaceRenderingCutoffLevel);
|
||||
_debugPropertyOwner.addProperty(_debugProperties.dynamicLodIterationCount);
|
||||
addPropertySubOwner(_debugPropertyOwner);
|
||||
|
||||
auto notifyShaderRecompilation = [this]() {
|
||||
_shadersNeedRecompilation = true;
|
||||
};
|
||||
_generalProperties.useAccurateNormals.onChange(notifyShaderRecompilation);
|
||||
_generalProperties.eclipseShadowsEnabled.onChange(notifyShaderRecompilation);
|
||||
_generalProperties.eclipseHardShadows.onChange(notifyShaderRecompilation);
|
||||
_generalProperties.performShading.onChange(notifyShaderRecompilation);
|
||||
_useAccurateNormals.onChange(notifyShaderRecompilation);
|
||||
_eclipseShadowsEnabled.onChange(notifyShaderRecompilation);
|
||||
_eclipseHardShadows.onChange(notifyShaderRecompilation);
|
||||
_performShading.onChange(notifyShaderRecompilation);
|
||||
_debugProperties.showChunkEdges.onChange(notifyShaderRecompilation);
|
||||
_shadowMappingProperties.shadowMapping.onChange(notifyShaderRecompilation);
|
||||
|
||||
_layerManager.onChange([this](Layer* l) {
|
||||
_shadersNeedRecompilation = true;
|
||||
@@ -724,8 +745,6 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
_nLayersIsDirty = true;
|
||||
_lastChangedLayer = l;
|
||||
});
|
||||
|
||||
addPropertySubOwner(_debugPropertyOwner);
|
||||
addPropertySubOwner(_layerManager);
|
||||
|
||||
_globalChunkBuffer.resize(2048);
|
||||
@@ -733,6 +752,11 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
_traversalMemory.resize(512);
|
||||
|
||||
_labelsDictionary = p.labels.value_or(_labelsDictionary);
|
||||
if (!_labelsDictionary.isEmpty()) {
|
||||
// Fading of the labels should also depend on the fading of the globe
|
||||
_globeLabelsComponent.setParentFadeable(this);
|
||||
addPropertySubOwner(_globeLabelsComponent);
|
||||
}
|
||||
|
||||
// Init geojson manager
|
||||
_geoJsonManager.initialize(this);
|
||||
@@ -750,9 +774,8 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
_shadowComponent = std::make_unique<ShadowComponent>(dictionary);
|
||||
_shadowComponent->initialize();
|
||||
addPropertySubOwner(_shadowComponent.get());
|
||||
_generalProperties.shadowMapping = true;
|
||||
_shadowMappingProperties.shadowMapping = true;
|
||||
}
|
||||
_generalProperties.shadowMapping.onChange(notifyShaderRecompilation);
|
||||
|
||||
// Use a secondary renderbin for labels, and other things that we want to be able to
|
||||
// render with transparency, on top of the globe, after the atmosphere step
|
||||
@@ -762,10 +785,6 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
|
||||
void RenderableGlobe::initializeGL() {
|
||||
if (!_labelsDictionary.isEmpty()) {
|
||||
_globeLabelsComponent.initialize(_labelsDictionary, this);
|
||||
addPropertySubOwner(_globeLabelsComponent);
|
||||
|
||||
// Fading of the labels should also depend on the fading of the globe
|
||||
_globeLabelsComponent.setParentFadeable(this);
|
||||
}
|
||||
|
||||
_layerManager.update();
|
||||
@@ -831,7 +850,7 @@ void RenderableGlobe::render(const RenderData& data, RendererTasks& rendererTask
|
||||
constexpr int res = 2880;
|
||||
const double distance = res * boundingSphere() / tfov;
|
||||
|
||||
if ((distanceToCamera < distance) || (_generalProperties.renderAtDistance)) {
|
||||
if ((distanceToCamera < distance) || (_renderAtDistance)) {
|
||||
try {
|
||||
if (_shadowComponent && _shadowComponent->isEnabled()) {
|
||||
// Set matrices and other GL states
|
||||
@@ -1055,7 +1074,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
if (_nLayersIsDirty) {
|
||||
std::array<LayerGroup*, LayerManager::NumLayerGroups> lgs =
|
||||
_layerManager.layerGroups();
|
||||
_generalProperties.nActiveLayers = std::accumulate(
|
||||
_nActiveLayers = std::accumulate(
|
||||
lgs.begin(),
|
||||
lgs.end(),
|
||||
0,
|
||||
@@ -1076,7 +1095,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
if (_layerManager.hasAnyBlendingLayersEnabled()) {
|
||||
if (_lodScaleFactorDirty) {
|
||||
const float dsf = static_cast<float>(
|
||||
_generalProperties.currentLodScaleFactor * _ellipsoid.minimumRadius()
|
||||
_currentLodScaleFactor * _ellipsoid.minimumRadius()
|
||||
);
|
||||
|
||||
// We are setting the setIgnoreUniformLocationError as it is not super trivial
|
||||
@@ -1098,12 +1117,12 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
}
|
||||
}
|
||||
|
||||
if (_generalProperties.performShading) {
|
||||
const float onr = _generalProperties.orenNayarRoughness;
|
||||
if (_performShading) {
|
||||
const float onr = _orenNayarRoughness;
|
||||
_localRenderer.program->setUniform("orenNayarRoughness", onr);
|
||||
_globalRenderer.program->setUniform("orenNayarRoughness", onr);
|
||||
|
||||
const float amb = _generalProperties.ambientIntensity;
|
||||
const float amb = _ambientIntensity;
|
||||
_localRenderer.program->setUniform("ambientIntensity", amb);
|
||||
_globalRenderer.program->setUniform("ambientIntensity", amb);
|
||||
}
|
||||
@@ -1124,7 +1143,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
}
|
||||
|
||||
const float dsf = static_cast<float>(
|
||||
_generalProperties.currentLodScaleFactor * _ellipsoid.minimumRadius()
|
||||
_currentLodScaleFactor * _ellipsoid.minimumRadius()
|
||||
);
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
@@ -1146,7 +1165,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
}
|
||||
|
||||
const float dsf = static_cast<float>(
|
||||
_generalProperties.currentLodScaleFactor * _ellipsoid.minimumRadius()
|
||||
_currentLodScaleFactor * _ellipsoid.minimumRadius()
|
||||
);
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_localRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
@@ -1183,7 +1202,13 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
_cachedInverseModelTransform * glm::dvec4(data.camera.positionVec3(), 1.0)
|
||||
);
|
||||
|
||||
using IgnoreError = ghoul::opengl::ProgramObject::IgnoreError;
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::Yes);
|
||||
// The cameraPosition is not used if a globe only has a solid color, but it would
|
||||
// be costlier to figure that out and will only trigger rarely, so instead we just
|
||||
// ignore the location error
|
||||
_globalRenderer.program->setUniform("cameraPosition", glm::vec3(cameraPosition));
|
||||
_globalRenderer.program->setIgnoreUniformLocationError(IgnoreError::No);
|
||||
}
|
||||
|
||||
const glm::mat4 modelViewTransform = glm::mat4(viewTransform * _cachedModelTransform);
|
||||
@@ -1200,7 +1225,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
|
||||
const bool hasHeightLayer =
|
||||
!_layerManager.layerGroup(layers::Group::ID::HeightLayers).activeLayers().empty();
|
||||
if (_generalProperties.useAccurateNormals && hasHeightLayer) {
|
||||
if (_useAccurateNormals && hasHeightLayer) {
|
||||
// Apply an extra scaling to the height if the object is scaled
|
||||
_globalRenderer.program->setUniform(
|
||||
"heightScale",
|
||||
@@ -1216,7 +1241,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
const bool waterLayersActive =
|
||||
!_layerManager.layerGroup(Group::ID::WaterMasks).activeLayers().empty();
|
||||
|
||||
if (nightLayersActive || waterLayersActive || _generalProperties.performShading) {
|
||||
if (nightLayersActive || waterLayersActive || _performShading) {
|
||||
const glm::dvec3 directionToSunWorldSpace =
|
||||
directionToLightSource(data.modelTransform.translation, _lightSourceNode);
|
||||
|
||||
@@ -1242,7 +1267,7 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
data.camera.sgctInternal.projectionMatrix()
|
||||
);
|
||||
|
||||
if (nightLayersActive || waterLayersActive || _generalProperties.performShading) {
|
||||
if (nightLayersActive || waterLayersActive || _performShading) {
|
||||
const glm::dvec3 directionToSunWorldSpace =
|
||||
directionToLightSource(data.modelTransform.translation, _lightSourceNode);
|
||||
|
||||
@@ -1343,21 +1368,19 @@ void RenderableGlobe::renderChunks(const RenderData& data, RendererTasks&,
|
||||
const int iterCount = _debugProperties.dynamicLodIterationCount;
|
||||
const bool exceededIterations =
|
||||
static_cast<int>(_iterationsOfUnavailableData) > iterCount;
|
||||
const float clf = _generalProperties.currentLodScaleFactor;
|
||||
const float clfMin = _generalProperties.currentLodScaleFactor.minValue();
|
||||
const float targetLod = _generalProperties.targetLodScaleFactor;
|
||||
const float clf = _currentLodScaleFactor;
|
||||
const float clfMin = _currentLodScaleFactor.minValue();
|
||||
const float targetLod = _targetLodScaleFactor;
|
||||
const bool validLodFactor = clf > clfMin;
|
||||
if (exceededIterations && validLodFactor) {
|
||||
_generalProperties.currentLodScaleFactor =
|
||||
_generalProperties.currentLodScaleFactor - 0.1f;
|
||||
_currentLodScaleFactor = _currentLodScaleFactor - 0.1f;
|
||||
_iterationsOfUnavailableData = 0;
|
||||
_lodScaleFactorDirty = true;
|
||||
} // Make 2 times the iterations with available data to move it up again
|
||||
else if (static_cast<int>(_iterationsOfAvailableData) >
|
||||
(iterCount * 2) && clf < targetLod)
|
||||
{
|
||||
_generalProperties.currentLodScaleFactor =
|
||||
_generalProperties.currentLodScaleFactor + 0.1f;
|
||||
_currentLodScaleFactor = _currentLodScaleFactor + 0.1f;
|
||||
_iterationsOfAvailableData = 0;
|
||||
_lodScaleFactorDirty = true;
|
||||
}
|
||||
@@ -1410,15 +1433,13 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData&
|
||||
|
||||
setCommonUniforms(program, chunk, data);
|
||||
|
||||
if (_generalProperties.eclipseShadowsEnabled &&
|
||||
!_ellipsoid.shadowConfigurationArray().empty())
|
||||
{
|
||||
if (_eclipseShadowsEnabled && !_ellipsoid.shadowConfigurationArray().empty()) {
|
||||
calculateEclipseShadows(program, data, ShadowCompType::GLOBAL_SHADOW);
|
||||
}
|
||||
|
||||
// Shadow Mapping
|
||||
ghoul::opengl::TextureUnit shadowMapUnit;
|
||||
if (_generalProperties.shadowMapping && shadowData.shadowDepthTexture != 0) {
|
||||
if (_shadowMappingProperties.shadowMapping && shadowData.shadowDepthTexture != 0) {
|
||||
// Adding the model transformation to the final shadow matrix so we have a
|
||||
// complete transformation from the model coordinates to the clip space of the
|
||||
// light position.
|
||||
@@ -1431,9 +1452,12 @@ void RenderableGlobe::renderChunkGlobally(const Chunk& chunk, const RenderData&
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
|
||||
program.setUniform("shadowMapTexture", shadowMapUnit);
|
||||
program.setUniform("zFightingPercentage", _generalProperties.zFightingPercentage);
|
||||
program.setUniform(
|
||||
"zFightingPercentage",
|
||||
_shadowMappingProperties.zFightingPercentage
|
||||
);
|
||||
}
|
||||
else if (_generalProperties.shadowMapping) {
|
||||
else if (_shadowMappingProperties.shadowMapping && _shadowComponent) {
|
||||
shadowMapUnit.activate();
|
||||
// JCC: Avoiding a to recompiling the shaders or having more than one
|
||||
// set of shaders for this step.
|
||||
@@ -1549,15 +1573,13 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
|
||||
|
||||
setCommonUniforms(program, chunk, data);
|
||||
|
||||
if (_generalProperties.eclipseShadowsEnabled &&
|
||||
!_ellipsoid.shadowConfigurationArray().empty())
|
||||
{
|
||||
if (_eclipseShadowsEnabled && !_ellipsoid.shadowConfigurationArray().empty()) {
|
||||
calculateEclipseShadows(program, data, ShadowCompType::LOCAL_SHADOW);
|
||||
}
|
||||
|
||||
// Shadow Mapping
|
||||
ghoul::opengl::TextureUnit shadowMapUnit;
|
||||
if (_generalProperties.shadowMapping && shadowData.shadowDepthTexture != 0) {
|
||||
if (_shadowMappingProperties.shadowMapping && shadowData.shadowDepthTexture != 0) {
|
||||
// Adding the model transformation to the final shadow matrix so we have a
|
||||
// complete transformation from the model coordinates to the clip space of the
|
||||
// light position.
|
||||
@@ -1570,9 +1592,12 @@ void RenderableGlobe::renderChunkLocally(const Chunk& chunk, const RenderData& d
|
||||
glBindTexture(GL_TEXTURE_2D, shadowData.shadowDepthTexture);
|
||||
|
||||
program.setUniform("shadowMapTexture", shadowMapUnit);
|
||||
program.setUniform("zFightingPercentage", _generalProperties.zFightingPercentage);
|
||||
program.setUniform(
|
||||
"zFightingPercentage",
|
||||
_shadowMappingProperties.zFightingPercentage
|
||||
);
|
||||
}
|
||||
else if (_generalProperties.shadowMapping) {
|
||||
else if (_shadowMappingProperties.shadowMapping) {
|
||||
shadowMapUnit.activate();
|
||||
// JCC: Avoiding a to recompiling the shaders or having more than one
|
||||
// set of shaders for this step.
|
||||
@@ -1636,7 +1661,7 @@ void RenderableGlobe::setCommonUniforms(ghoul::opengl::ProgramObject& programObj
|
||||
|
||||
ZoneScoped;
|
||||
|
||||
if (_generalProperties.useAccurateNormals &&
|
||||
if (_useAccurateNormals &&
|
||||
!_layerManager.layerGroup(Group::ID::HeightLayers).activeLayers().empty())
|
||||
{
|
||||
const glm::dvec3 corner00 = _ellipsoid.cartesianSurfacePosition(
|
||||
@@ -1737,31 +1762,22 @@ void RenderableGlobe::recompileShaders() {
|
||||
const bool hasHeightLayer =
|
||||
!_layerManager.layerGroup(layers::Group::ID::HeightLayers).activeLayers().empty();
|
||||
|
||||
pairs.emplace_back("useAccurateNormals",
|
||||
std::to_string(_generalProperties.useAccurateNormals && hasHeightLayer)
|
||||
);
|
||||
pairs.emplace_back(
|
||||
"performShading",
|
||||
std::to_string(_generalProperties.performShading)
|
||||
);
|
||||
pairs.emplace_back(
|
||||
"useEclipseShadows",
|
||||
std::to_string(_generalProperties.eclipseShadowsEnabled)
|
||||
);
|
||||
pairs.emplace_back(
|
||||
"useEclipseHardShadows",
|
||||
std::to_string(_generalProperties.eclipseHardShadows)
|
||||
"useAccurateNormals",
|
||||
std::to_string(_useAccurateNormals && hasHeightLayer)
|
||||
);
|
||||
pairs.emplace_back("performShading", std::to_string(_performShading));
|
||||
pairs.emplace_back("useEclipseShadows", std::to_string(_eclipseShadowsEnabled));
|
||||
pairs.emplace_back("useEclipseHardShadows", std::to_string(_eclipseHardShadows));
|
||||
pairs.emplace_back(
|
||||
"enableShadowMapping",
|
||||
std::to_string(_generalProperties.shadowMapping)
|
||||
std::to_string(_shadowMappingProperties.shadowMapping && _shadowComponent)
|
||||
);
|
||||
pairs.emplace_back("showChunkEdges", std::to_string(_debugProperties.showChunkEdges));
|
||||
pairs.emplace_back("showHeightResolution", "0");
|
||||
pairs.emplace_back("showHeightIntensities", "0");
|
||||
pairs.emplace_back("defaultHeight", std::to_string(DefaultHeight));
|
||||
|
||||
|
||||
//
|
||||
// Create dictionary from layerpreprocessing data
|
||||
//
|
||||
@@ -1850,7 +1866,10 @@ void RenderableGlobe::recompileShaders() {
|
||||
}
|
||||
|
||||
// Shadow Mapping Samples
|
||||
shaderDictionary.setValue("nShadowSamples", _generalProperties.nShadowSamples - 1);
|
||||
shaderDictionary.setValue(
|
||||
"nShadowSamples",
|
||||
_shadowMappingProperties.nShadowSamples - 1
|
||||
);
|
||||
|
||||
// Exclise Shadow Samples
|
||||
const int nEclipseShadows = static_cast<int>(
|
||||
@@ -2274,7 +2293,7 @@ void RenderableGlobe::calculateEclipseShadows(ghoul::opengl::ProgramObject& prog
|
||||
// JCC: Removed in favor of: #define USE_ECLIPSE_HARD_SHADOWS #{useEclipseHardShadows}
|
||||
/*programObject.setUniform(
|
||||
"hardShadows",
|
||||
_generalProperties.eclipseHardShadows
|
||||
_eclipseHardShadows
|
||||
);*/
|
||||
//programObject.setUniform("calculateEclipseShadows", true);
|
||||
}
|
||||
@@ -2312,8 +2331,7 @@ int RenderableGlobe::desiredLevelByDistance(const Chunk& chunk,
|
||||
const double distanceToPatch = glm::length(cameraToChunk);
|
||||
const double distance = distanceToPatch;
|
||||
|
||||
const double scaleFactor = _generalProperties.currentLodScaleFactor *
|
||||
_ellipsoid.minimumRadius();
|
||||
const double scaleFactor = _currentLodScaleFactor * _ellipsoid.minimumRadius();
|
||||
const double projectedScaleFactor = scaleFactor / distance;
|
||||
const int desiredLevel = static_cast<int>(ceil(log2(projectedScaleFactor)));
|
||||
return desiredLevel;
|
||||
@@ -2399,8 +2417,7 @@ int RenderableGlobe::desiredLevelByProjectedArea(const Chunk& chunk,
|
||||
const double areaABC = 0.5 * glm::length(glm::cross(AC, AB));
|
||||
const double projectedChunkAreaApprox = 8 * areaABC;
|
||||
|
||||
const double scaledArea = _generalProperties.currentLodScaleFactor *
|
||||
projectedChunkAreaApprox;
|
||||
const double scaledArea = _currentLodScaleFactor * projectedChunkAreaApprox;
|
||||
return chunk.tileIndex.level + static_cast<int>(round(scaledArea - 1));
|
||||
}
|
||||
|
||||
|
||||
@@ -128,38 +128,6 @@ public:
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
static constexpr int MinSplitDepth = 2;
|
||||
static constexpr int MaxSplitDepth = 22;
|
||||
|
||||
struct {
|
||||
properties::BoolProperty showChunkEdges;
|
||||
properties::BoolProperty levelByProjectedAreaElseDistance;
|
||||
properties::BoolProperty resetTileProviders;
|
||||
properties::BoolProperty performFrustumCulling;
|
||||
properties::IntProperty modelSpaceRenderingCutoffLevel;
|
||||
properties::IntProperty dynamicLodIterationCount;
|
||||
} _debugProperties;
|
||||
|
||||
struct {
|
||||
properties::BoolProperty performShading;
|
||||
properties::BoolProperty useAccurateNormals;
|
||||
properties::BoolProperty eclipseShadowsEnabled;
|
||||
properties::BoolProperty eclipseHardShadows;
|
||||
properties::BoolProperty shadowMapping;
|
||||
properties::BoolProperty renderAtDistance;
|
||||
properties::FloatProperty zFightingPercentage;
|
||||
properties::IntProperty nShadowSamples;
|
||||
properties::FloatProperty targetLodScaleFactor;
|
||||
properties::FloatProperty currentLodScaleFactor;
|
||||
properties::FloatProperty orenNayarRoughness;
|
||||
properties::FloatProperty ambientIntensity;
|
||||
properties::IntProperty nActiveLayers;
|
||||
} _generalProperties;
|
||||
|
||||
properties::PropertyOwner _debugPropertyOwner;
|
||||
|
||||
properties::PropertyOwner _shadowMappingPropertyOwner;
|
||||
|
||||
/**
|
||||
* Test if a specific chunk can safely be culled without affecting the rendered image.
|
||||
*
|
||||
@@ -245,16 +213,49 @@ private:
|
||||
void setCommonUniforms(ghoul::opengl::ProgramObject& programObject,
|
||||
const Chunk& chunk, const RenderData& data);
|
||||
|
||||
|
||||
void recompileShaders();
|
||||
|
||||
|
||||
void splitChunkNode(Chunk& cn, int depth);
|
||||
void mergeChunkNode(Chunk& cn);
|
||||
bool updateChunkTree(Chunk& cn, const RenderData& data, const glm::dmat4& mvp);
|
||||
void updateChunk(Chunk& chunk, const RenderData& data, const glm::dmat4& mvp) const;
|
||||
void freeChunkNode(Chunk* n);
|
||||
|
||||
static constexpr int MinSplitDepth = 2;
|
||||
static constexpr int MaxSplitDepth = 22;
|
||||
|
||||
properties::BoolProperty _performShading;
|
||||
properties::BoolProperty _useAccurateNormals;
|
||||
properties::FloatProperty _ambientIntensity;
|
||||
properties::StringProperty _lightSourceNodeName;
|
||||
|
||||
properties::BoolProperty _renderAtDistance;
|
||||
properties::BoolProperty _eclipseShadowsEnabled;
|
||||
properties::BoolProperty _eclipseHardShadows;
|
||||
properties::FloatProperty _targetLodScaleFactor;
|
||||
properties::FloatProperty _currentLodScaleFactor;
|
||||
properties::FloatProperty _orenNayarRoughness;
|
||||
properties::IntProperty _nActiveLayers;
|
||||
|
||||
struct {
|
||||
properties::BoolProperty showChunkEdges;
|
||||
properties::BoolProperty levelByProjectedAreaElseDistance;
|
||||
properties::BoolProperty resetTileProviders;
|
||||
properties::BoolProperty performFrustumCulling;
|
||||
properties::IntProperty modelSpaceRenderingCutoffLevel;
|
||||
properties::IntProperty dynamicLodIterationCount;
|
||||
} _debugProperties;
|
||||
|
||||
properties::PropertyOwner _debugPropertyOwner;
|
||||
|
||||
struct {
|
||||
properties::BoolProperty shadowMapping;
|
||||
properties::FloatProperty zFightingPercentage;
|
||||
properties::IntProperty nShadowSamples;
|
||||
} _shadowMappingProperties;
|
||||
|
||||
properties::PropertyOwner _shadowMappingPropertyOwner;
|
||||
|
||||
Ellipsoid _ellipsoid;
|
||||
SkirtedGrid _grid;
|
||||
LayerManager _layerManager;
|
||||
@@ -270,7 +271,6 @@ private:
|
||||
std::vector<const Chunk*> _localChunkBuffer;
|
||||
std::vector<const Chunk*> _traversalMemory;
|
||||
|
||||
|
||||
Chunk _leftRoot; // Covers all negative longitudes
|
||||
Chunk _rightRoot; // Covers all positive longitudes
|
||||
|
||||
@@ -293,7 +293,6 @@ private:
|
||||
} _localRenderer;
|
||||
|
||||
SceneGraphNode* _lightSourceNode = nullptr;
|
||||
properties::StringProperty _lightSourceNodeName;
|
||||
|
||||
bool _shadersNeedRecompilation = true;
|
||||
bool _lodScaleFactorDirty = true;
|
||||
|
||||
@@ -200,11 +200,11 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
|
||||
const Time start = Time(p.prototyped->time.start);
|
||||
Time end = Time::now();
|
||||
_prototyped.startTimeJ2000 = start.j2000Seconds();
|
||||
_prototyped.endTimeJ2000 = Time(p.prototyped->time.end).j2000Seconds();
|
||||
if (p.prototyped->time.end == "Yesterday") {
|
||||
end.advanceTime(-60.0 * 60.0 * 24.0); // Go back one day
|
||||
}
|
||||
else if (p.prototyped->time.end != "Today") {
|
||||
_prototyped.endTimeJ2000 = Time(p.prototyped->time.end).j2000Seconds();
|
||||
end.setTime(p.prototyped->time.end);
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,8 @@ Tile TextTileProvider::renderTile(const TileIndex& tileIndex, const std::string&
|
||||
|
||||
fontRenderer->render(*font, position, text, color);
|
||||
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::LinearMipMap);
|
||||
|
||||
tile = Tile{ texture, std::nullopt, Tile::Status::OK };
|
||||
tileCache->put(key, initData.hashKey, tile);
|
||||
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2024 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/src/tileprovider/tileproviderbydate.h>
|
||||
|
||||
#include <openspace/documentation/documentation.h>
|
||||
#include <openspace/engine/globals.h>
|
||||
#include <openspace/util/spicemanager.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <functional>
|
||||
|
||||
namespace {
|
||||
struct [[codegen::Dictionary(TileProviderByDate)]] Parameters {
|
||||
// Specifies the list of tile providers and for which times they are used for. The
|
||||
// tile provider with the earliest time will be used for all dates prior to that
|
||||
// date and the provider with the latest time will be used for all dates
|
||||
// afterwards. In between, a provider is used from the specified time until the
|
||||
// time of the next provider
|
||||
std::map<std::string, ghoul::Dictionary> providers;
|
||||
};
|
||||
#include "tileproviderbydate_codegen.cpp"
|
||||
} // namespace
|
||||
|
||||
namespace openspace::globebrowsing {
|
||||
|
||||
documentation::Documentation TileProviderByDate::Documentation() {
|
||||
return codegen::doc<Parameters>("globebrowsing_tileproviderbydate");
|
||||
}
|
||||
|
||||
TileProviderByDate::TileProviderByDate(const ghoul::Dictionary& dictionary) {
|
||||
ZoneScoped;
|
||||
|
||||
Parameters p = codegen::bake<Parameters>(dictionary);
|
||||
|
||||
// For now we need to inject the LayerGroupID this way. We don't want it to be part of
|
||||
// the parameters struct as that would mean it would be visible to the end user, which
|
||||
// we don't want since this value just comes from whoever creates it, not the user
|
||||
ghoul_assert(dictionary.hasValue<int>("LayerGroupID"), "No Layer Group ID provided");
|
||||
const layers::Group::ID group = static_cast<layers::Group::ID>(
|
||||
dictionary.value<int>("LayerGroupID")
|
||||
);
|
||||
|
||||
for (std::pair<const std::string, ghoul::Dictionary>& prov : p.providers) {
|
||||
prov.second.setValue("LayerGroupID", static_cast<int>(group));
|
||||
|
||||
// Pass down the caching information from the enclosing dictionary
|
||||
if (dictionary.hasValue<std::string>("GlobeName")) {
|
||||
prov.second.setValue("GlobeName", dictionary.value<std::string>("GlobeName"));
|
||||
}
|
||||
layers::Layer::ID typeID = layers::Layer::ID::DefaultTileProvider;
|
||||
|
||||
if (prov.second.hasValue<std::string>("Type")) {
|
||||
const std::string type = prov.second.value<std::string>("Type");
|
||||
typeID = ghoul::from_string<layers::Layer::ID>(type);
|
||||
}
|
||||
|
||||
std::unique_ptr<TileProvider> tp = createFromDictionary(typeID, prov.second);
|
||||
const std::string provId = prov.second.value<std::string>("Identifier");
|
||||
tp->setIdentifier(provId);
|
||||
const std::string providerName = prov.second.value<std::string>("Name");
|
||||
tp->setGuiName(providerName);
|
||||
addPropertySubOwner(tp.get());
|
||||
|
||||
const double time = SpiceManager::ref().ephemerisTimeFromDate(prov.first);
|
||||
_tileProviders.emplace_back(time, std::move(tp));
|
||||
}
|
||||
|
||||
// After we added all tile providers, we need to sort them as they might have been
|
||||
// given in an arbitrary order
|
||||
std::sort(
|
||||
_tileProviders.begin(),
|
||||
_tileProviders.end(),
|
||||
[](const Provider& lhs, const Provider& rhs) {
|
||||
return lhs.startTime < rhs.startTime;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
void TileProviderByDate::internalInitialize() {
|
||||
for (const Provider& p : _tileProviders) {
|
||||
p.tileProvider->initialize();
|
||||
}
|
||||
}
|
||||
|
||||
void TileProviderByDate::internalDeinitialize() {
|
||||
for (const Provider& p : _tileProviders) {
|
||||
p.tileProvider->deinitialize();
|
||||
}
|
||||
}
|
||||
|
||||
Tile TileProviderByDate::tile(const TileIndex& tileIndex) {
|
||||
ZoneScoped;
|
||||
|
||||
return _currentTileProvider ? _currentTileProvider->tile(tileIndex) : Tile();
|
||||
}
|
||||
|
||||
Tile::Status TileProviderByDate::tileStatus(const TileIndex& index) {
|
||||
return
|
||||
_currentTileProvider ?
|
||||
_currentTileProvider->tileStatus(index) :
|
||||
Tile::Status::Unavailable;
|
||||
}
|
||||
|
||||
|
||||
TileDepthTransform TileProviderByDate::depthTransform() {
|
||||
return _currentTileProvider ?
|
||||
_currentTileProvider->depthTransform() :
|
||||
TileDepthTransform(0.f, 1.f);
|
||||
}
|
||||
|
||||
void TileProviderByDate::update() {
|
||||
if (_tileProviders.empty()) {
|
||||
// If there are no tile providers, then there is no work to be done
|
||||
_currentTileProvider = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
// First update all tile providers
|
||||
for (const Provider& p : _tileProviders) {
|
||||
p.tileProvider->update();
|
||||
}
|
||||
|
||||
// Then check update our current tile provider pointer
|
||||
const double time = global::timeManager->time().j2000Seconds();
|
||||
ghoul_assert(!_tileProviders.empty(), "There should be tile providers at this point");
|
||||
|
||||
// We use the first tileprovider for all times before the beginning start
|
||||
if (time < _tileProviders.begin()->startTime) {
|
||||
_currentTileProvider = _tileProviders.begin()->tileProvider.get();
|
||||
return;
|
||||
}
|
||||
|
||||
// And the last tileprovider for all times after the end
|
||||
if (time > _tileProviders.back().startTime) {
|
||||
_currentTileProvider = _tileProviders.back().tileProvider.get();
|
||||
return;
|
||||
}
|
||||
|
||||
_currentTileProvider = _tileProviders.begin()->tileProvider.get();
|
||||
for (const Provider& p : _tileProviders) {
|
||||
if (p.startTime > time) {
|
||||
// We have found the first entry that is larger than the current time, which
|
||||
// means that we are done
|
||||
return;
|
||||
}
|
||||
|
||||
_currentTileProvider = p.tileProvider.get();
|
||||
}
|
||||
}
|
||||
|
||||
void TileProviderByDate::reset() {
|
||||
for (const Provider& p : _tileProviders) {
|
||||
p.tileProvider->reset();
|
||||
}
|
||||
}
|
||||
|
||||
int TileProviderByDate::minLevel() {
|
||||
return _currentTileProvider ? _currentTileProvider->minLevel() : 1;
|
||||
}
|
||||
|
||||
int TileProviderByDate::maxLevel() {
|
||||
return _currentTileProvider ? _currentTileProvider->maxLevel() : 1;
|
||||
}
|
||||
|
||||
float TileProviderByDate::noDataValueAsFloat() {
|
||||
return _currentTileProvider ? _currentTileProvider->noDataValueAsFloat() : 1;
|
||||
}
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
@@ -0,0 +1,65 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2024 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYDATE___H__
|
||||
#define __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYDATE___H__
|
||||
|
||||
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace openspace::globebrowsing {
|
||||
|
||||
class TileProviderByDate : public TileProvider {
|
||||
public:
|
||||
TileProviderByDate(const ghoul::Dictionary& dictionary);
|
||||
|
||||
Tile tile(const TileIndex& tileIndex) override final;
|
||||
Tile::Status tileStatus(const TileIndex& index) override final;
|
||||
TileDepthTransform depthTransform() override final;
|
||||
void update() override final;
|
||||
void reset() override final;
|
||||
int minLevel() override final;
|
||||
int maxLevel() override final;
|
||||
float noDataValueAsFloat() override final;
|
||||
|
||||
static documentation::Documentation Documentation();
|
||||
|
||||
private:
|
||||
struct Provider {
|
||||
// The time at which this provider becomes valid
|
||||
double startTime = 0.0;
|
||||
std::unique_ptr<TileProvider> tileProvider;
|
||||
};
|
||||
|
||||
std::vector<Provider> _tileProviders;
|
||||
TileProvider* _currentTileProvider = nullptr;
|
||||
|
||||
void internalInitialize() override final;
|
||||
void internalDeinitialize() override final;
|
||||
};
|
||||
|
||||
} // namespace openspace::globebrowsing
|
||||
|
||||
#endif // __OPENSPACE_MODULE_GLOBEBROWSING___TILEPROVIDER__TILEPROVIDERBYDATE___H__
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -62,7 +62,6 @@ protected:
|
||||
std::function<std::vector<properties::PropertyOwner*>()> _propertyOwnerFunction;
|
||||
|
||||
properties::BoolProperty _useTreeLayout;
|
||||
properties::StringListProperty _treeOrdering;
|
||||
};
|
||||
|
||||
} // namespace openspace::gui
|
||||
|
||||
@@ -58,7 +58,8 @@ void GuiActionComponent::render() {
|
||||
global::actionManager->triggerAction(
|
||||
p.second,
|
||||
ghoul::Dictionary(),
|
||||
interaction::ActionManager::ShouldBeSynchronized::Yes
|
||||
interaction::ActionManager::ShouldBeSynchronized::Yes,
|
||||
interaction::ActionManager::ShouldBeLogged::Yes
|
||||
);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
@@ -85,7 +86,8 @@ void GuiActionComponent::render() {
|
||||
global::actionManager->triggerAction(
|
||||
action.command,
|
||||
ghoul::Dictionary(),
|
||||
interaction::ActionManager::ShouldBeSynchronized::Yes
|
||||
interaction::ActionManager::ShouldBeSynchronized::Yes,
|
||||
interaction::ActionManager::ShouldBeLogged::Yes
|
||||
);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -145,11 +145,7 @@ void GuiGIBSComponent::render() {
|
||||
"openspace.globebrowsing.addLayer('Earth', 'ColorLayers', {})",
|
||||
layerScript
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
std::move(script),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(std::move(script));
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
@@ -329,9 +329,8 @@ void GuiGlobeBrowsingComponent::render() {
|
||||
std::remove(layerName.begin(), layerName.end(), ' '),
|
||||
layerName.end()
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
std::format(
|
||||
"openspace.globebrowsing.addLayer(\
|
||||
const std::string script = std::format(
|
||||
"openspace.globebrowsing.addLayer(\
|
||||
'{}', \
|
||||
'{}', \
|
||||
{{ \
|
||||
@@ -341,15 +340,13 @@ void GuiGlobeBrowsingComponent::render() {
|
||||
Enabled = true\
|
||||
}}\
|
||||
);",
|
||||
n,
|
||||
type,
|
||||
layerName,
|
||||
l.name,
|
||||
l.url
|
||||
),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
n,
|
||||
type,
|
||||
layerName,
|
||||
l.name,
|
||||
l.url
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
};
|
||||
|
||||
if (addColor) {
|
||||
|
||||
@@ -46,15 +46,6 @@ namespace {
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
constexpr openspace::properties::Property::PropertyInfo OrderingInfo = {
|
||||
"Ordering",
|
||||
"Tree Ordering",
|
||||
"This list determines the order of the first tree layer if it is used. Elements "
|
||||
"present in this list will be shown first, with an alphabetical ordering for "
|
||||
"elements not listed.",
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
int nVisibleProperties(const std::vector<openspace::properties::Property*>& props)
|
||||
{
|
||||
using namespace openspace;
|
||||
@@ -185,10 +176,8 @@ GuiPropertyComponent::GuiPropertyComponent(std::string identifier, std::string g
|
||||
UseTreeLayout useTree)
|
||||
: GuiComponent(std::move(identifier), std::move(guiName))
|
||||
, _useTreeLayout(UseTreeInfo, useTree)
|
||||
, _treeOrdering(OrderingInfo)
|
||||
{
|
||||
addProperty(_useTreeLayout);
|
||||
addProperty(_treeOrdering);
|
||||
}
|
||||
|
||||
void GuiPropertyComponent::setPropertyOwners(
|
||||
@@ -303,14 +292,11 @@ void GuiPropertyComponent::render() {
|
||||
(void)owner; // using [[maybe_unused]] in the for loop gives an error
|
||||
}
|
||||
|
||||
// Sort:
|
||||
// if guigrouping, sort by name and shortest first, but respect the user specified
|
||||
// ordering then all w/o guigroup
|
||||
const std::vector<std::string>& ordering = _treeOrdering;
|
||||
// Sort: by name and shortest first
|
||||
std::stable_sort(
|
||||
owners.begin(),
|
||||
owners.end(),
|
||||
[&ordering](PropertyOwner* lhs, PropertyOwner* rhs) {
|
||||
[](PropertyOwner* lhs, PropertyOwner* rhs) {
|
||||
const std::string lhsGrp = dynamic_cast<SceneGraphNode*>(lhs)->guiPath();
|
||||
const std::string rhsGrp = dynamic_cast<SceneGraphNode*>(rhs)->guiPath();
|
||||
|
||||
@@ -321,38 +307,7 @@ void GuiPropertyComponent::render() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ordering.empty()) {
|
||||
return lhsGrp < rhsGrp;
|
||||
}
|
||||
|
||||
std::vector<std::string> lhsToken = ghoul::tokenizeString(lhsGrp, '/');
|
||||
// The first token is always empty
|
||||
auto lhsIt = std::find(ordering.begin(), ordering.end(), lhsToken[1]);
|
||||
|
||||
std::vector<std::string> rhsToken = ghoul::tokenizeString(rhsGrp, '/');
|
||||
// The first token is always empty
|
||||
auto rhsIt = std::find(ordering.begin(), ordering.end(), rhsToken[1]);
|
||||
|
||||
if (lhsIt != ordering.end() && rhsIt != ordering.end()) {
|
||||
if (lhsToken[1] != rhsToken[1]) {
|
||||
// If both top-level groups are in the ordering list, the
|
||||
// order of the iterators gives us the order of the groups
|
||||
return lhsIt < rhsIt;
|
||||
}
|
||||
else {
|
||||
return lhsGrp < rhsGrp;
|
||||
}
|
||||
}
|
||||
else if (lhsIt != ordering.end() && rhsIt == ordering.end()) {
|
||||
// If only one of them is in the list, we have a sorting
|
||||
return true;
|
||||
}
|
||||
else if (lhsIt == ordering.end() && rhsIt != ordering.end()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return lhsGrp < rhsGrp;
|
||||
}
|
||||
return lhsGrp < rhsGrp;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
#include <openspace/util/timeconversion.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
|
||||
@@ -105,19 +106,12 @@ void GuiSpaceTimeComponent::render() {
|
||||
const bool pressed = ImGui::Button(n->guiName().c_str());
|
||||
ImGui::SameLine();
|
||||
if (pressed) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.setPropertyValue('" +
|
||||
std::string(AnchorProperty) + "', '" +
|
||||
n->identifier() + "');",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.setPropertyValue('" +
|
||||
std::string(RetargetAnchorProperty) + "', nil);",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.setPropertyValue('{}', '{}');"
|
||||
"openspace.setPropertyValue('{}', nil);",
|
||||
AnchorProperty, n->identifier(), RetargetAnchorProperty
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,29 +137,21 @@ void GuiSpaceTimeComponent::render() {
|
||||
|
||||
const bool hasChanged = ImGui::Combo("", ¤tPosition, nodeNames.c_str());
|
||||
if (hasChanged) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.setPropertyValue('" + std::string(AnchorProperty) + "', '" +
|
||||
nodes[currentPosition]->identifier() + "');",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.setPropertyValue('" +
|
||||
std::string(RetargetAnchorProperty) + "', nil);",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.setPropertyValue('{}', '{}');"
|
||||
"openspace.setPropertyValue('{}', nil);",
|
||||
AnchorProperty, nodes[currentPosition]->identifier(), RetargetAnchorProperty
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
const bool pressed = ImGui::Button("Refocus");
|
||||
if (pressed) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.setPropertyValue('" +
|
||||
std::string(RetargetAnchorProperty) + "', nil);",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.setPropertyValue('{}', nil);", RetargetAnchorProperty
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
float interpolationTime = global::navigationHandler->interpolationTime();
|
||||
@@ -210,11 +196,10 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (dateChanged) {
|
||||
// No sync or send because time settings are always synced and sent to the
|
||||
// connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
std::format("openspace.time.setTime([[{}]])", std::string_view(Buffer)),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
const std::string script = std::format(
|
||||
"openspace.time.setTime([[{}]])", std::string_view(Buffer)
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
showTooltip(
|
||||
@@ -239,29 +224,23 @@ void GuiSpaceTimeComponent::render() {
|
||||
std::chrono::hours(24) * std::abs(days)
|
||||
).count();
|
||||
|
||||
const double newTime = days < 0 ?
|
||||
j2000 - seconds :
|
||||
j2000 + seconds;
|
||||
const double newTime = days < 0.f ? j2000 - seconds : j2000 + seconds;
|
||||
|
||||
if (shift) {
|
||||
// If any shift key is pressed we want to always jump to the time.
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.setTime(" + std::to_string(newTime) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
"openspace.time.setTime(" + std::to_string(newTime) + ")"
|
||||
);
|
||||
}
|
||||
else {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateTime(" + std::to_string(newTime) + ", " +
|
||||
std::to_string(duration) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
const std::string script = std::format(
|
||||
"openspace.time.interpolateTime({}, {})", newTime, duration
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -300,11 +279,8 @@ void GuiSpaceTimeComponent::render() {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.setTime(\"" + nowTime + "\")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
std::format("openspace.time.setTime('{}')", nowTime)
|
||||
);
|
||||
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -386,11 +362,9 @@ void GuiSpaceTimeComponent::render() {
|
||||
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(newDt) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript(std::format(
|
||||
"openspace.time.interpolateDeltaTime({})", newDt
|
||||
));
|
||||
}
|
||||
if (unitChanged) {
|
||||
// If only the unit changes, we keep the delta time, but need to convert the
|
||||
@@ -437,22 +411,22 @@ void GuiSpaceTimeComponent::render() {
|
||||
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.setDeltaTime(" + std::to_string(newDeltaTime) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
const std::string s = std::format(
|
||||
"openspace.time.setDeltaTime({})", newDeltaTime
|
||||
);
|
||||
global::scriptEngine->queueScript(s);
|
||||
}
|
||||
if (!ImGui::IsItemActive() && !ImGui::IsItemClicked()) {
|
||||
if (_slidingDelta != 0.f) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.setDeltaTime(" + std::to_string(_oldDeltaTime) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
const std::string script = std::format(
|
||||
"openspace.time.setDeltaTime({})", _oldDeltaTime
|
||||
);
|
||||
|
||||
using Script = scripting::ScriptEngine::Script;
|
||||
global::scriptEngine->queueScript(script);
|
||||
|
||||
}
|
||||
_slidingDelta = 0.f;
|
||||
}
|
||||
@@ -477,11 +451,10 @@ void GuiSpaceTimeComponent::render() {
|
||||
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.setDeltaTime(" + std::to_string(newDeltaTime) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
const std::string script = std::format(
|
||||
"openspace.time.setDeltaTime({})", newDeltaTime
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
else {
|
||||
_accelerationDelta = 0.f;
|
||||
@@ -496,11 +469,7 @@ void GuiSpaceTimeComponent::render() {
|
||||
{ ImGui::GetWindowWidth() / 2 - 7.5f, 0.f }
|
||||
);
|
||||
if (pauseChanged) {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateTogglePause()",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript("openspace.time.interpolateTogglePause()");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
const bool invert = ImGui::Button(
|
||||
@@ -510,22 +479,18 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (invert) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(-1 * openspace.time.deltaTime());",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
const std::string script =
|
||||
"openspace.time.interpolateDeltaTime(-1 * openspace.time.deltaTime());";
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
const bool minusDs = ImGui::Button("-1d/s");
|
||||
if (minusDs) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(-24 * 60 * 60) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript(std::format(
|
||||
"openspace.time.interpolateDeltaTime(-{})", SecondsPerDay
|
||||
));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -533,11 +498,9 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (minusHs) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(-60 * 60) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript(std::format(
|
||||
"openspace.time.interpolateDeltaTime(-{})", SecondsPerHour
|
||||
));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -545,11 +508,9 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (minusMs) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(-60) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript(std::format(
|
||||
"openspace.time.interpolateDeltaTime(-{})", SecondsPerMinute
|
||||
));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -557,11 +518,7 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (minusSs) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(-1) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript("openspace.time.interpolateDeltaTime(-1)");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -569,11 +526,7 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (zero) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(0) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript("openspace.time.interpolateDeltaTime(0)");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -582,11 +535,7 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (plusSs) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(1) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript("openspace.time.interpolateDeltaTime(1)");
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -594,11 +543,9 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (plusMs) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(60) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript(std::format(
|
||||
"openspace.time.interpolateDeltaTime({})", SecondsPerMinute
|
||||
));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -606,11 +553,9 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (plusHs) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(60 * 60) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript(std::format(
|
||||
"openspace.time.interpolateDeltaTime({})", SecondsPerHour
|
||||
));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
@@ -618,11 +563,9 @@ void GuiSpaceTimeComponent::render() {
|
||||
if (plusDs) {
|
||||
// No sync or send because time settings are always synced and sent
|
||||
// to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.time.interpolateDeltaTime(" + std::to_string(24 * 60 * 60) + ")",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript(std::format(
|
||||
"openspace.time.interpolateDeltaTime({})", SecondsPerDay
|
||||
));
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
@@ -65,7 +65,7 @@ void renderTooltip(Property* prop, double delay) {
|
||||
}
|
||||
ImGui::Text(
|
||||
"%s",
|
||||
(std::string("Identifier: ") + prop->fullyQualifiedIdentifier()).c_str()
|
||||
(std::string("Identifier: ") + prop->uri()).c_str()
|
||||
);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
@@ -73,9 +73,7 @@ void renderTooltip(Property* prop, double delay) {
|
||||
|
||||
void executeSetPropertyScript(const std::string& id, const std::string& value) {
|
||||
global::scriptEngine->queueScript(
|
||||
std::format("openspace.setPropertyValueSingle('{}', {});", id, value),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
std::format("openspace.setPropertyValueSingle('{}', {});", id, value)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -95,7 +93,7 @@ void renderBoolProperty(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (value != p->value()) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), value ? "true" : "false");
|
||||
executeSetPropertyScript(p->uri(), value ? "true" : "false");
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -158,7 +156,7 @@ void renderOptionProperty(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
}
|
||||
if (value != p->value() && !isReadOnly) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), std::to_string(value));
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -200,7 +198,7 @@ void renderSelectionProperty(Property* prop, const std::string& ownerName,
|
||||
parameters.pop_back();
|
||||
}
|
||||
parameters += "}";
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), parameters);
|
||||
executeSetPropertyScript(p->uri(), parameters);
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
@@ -231,7 +229,7 @@ void renderStringProperty(Property* prop, const std::string& ownerName,
|
||||
|
||||
if (hasNewValue) {
|
||||
executeSetPropertyScript(
|
||||
p->fullyQualifiedIdentifier(),
|
||||
p->uri(),
|
||||
"[[" + std::string(buffer.data()) + "]]"
|
||||
);
|
||||
}
|
||||
@@ -283,7 +281,7 @@ void renderDoubleListProperty(Property* prop, const std::string& ownerName,
|
||||
ImGui::PushID((ownerName + '.' + name).c_str());
|
||||
|
||||
const std::string value = p->stringValue();
|
||||
renderListProperty(name, p->fullyQualifiedIdentifier(), value);
|
||||
renderListProperty(name, p->uri(), value);
|
||||
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
@@ -301,7 +299,7 @@ void renderIntListProperty(Property* prop, const std::string& ownerName,
|
||||
ImGui::PushID((ownerName + '.' + name).c_str());
|
||||
|
||||
const std::string value = p->stringValue();
|
||||
renderListProperty(name, p->fullyQualifiedIdentifier(), value);
|
||||
renderListProperty(name, p->uri(), value);
|
||||
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
@@ -319,7 +317,7 @@ void renderStringListProperty(Property* prop, const std::string& ownerName,
|
||||
ImGui::PushID((ownerName + '.' + name).c_str());
|
||||
|
||||
const std::string value = p->stringValue();
|
||||
renderListProperty(name, p->fullyQualifiedIdentifier(), value);
|
||||
renderListProperty(name, p->uri(), value);
|
||||
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
@@ -358,7 +356,7 @@ void renderDoubleProperty(properties::Property* prop, const std::string& ownerNa
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), std::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -382,7 +380,7 @@ void renderIntProperty(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), std::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -405,7 +403,7 @@ void renderIVec2Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -428,7 +426,7 @@ void renderIVec3Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -450,7 +448,7 @@ void renderIVec4Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -479,7 +477,7 @@ void renderFloatProperty(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), std::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), std::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -509,7 +507,7 @@ void renderVec2Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -545,7 +543,7 @@ void renderVec3Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -581,7 +579,7 @@ void renderVec4Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -611,7 +609,7 @@ void renderDVec2Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -641,7 +639,7 @@ void renderDVec3Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -671,7 +669,7 @@ void renderDVec4Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -723,7 +721,7 @@ void renderDMat2Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -785,7 +783,7 @@ void renderDMat3Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -857,7 +855,7 @@ void renderDMat4Property(Property* prop, const std::string& ownerName,
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
executeSetPropertyScript(p->fullyQualifiedIdentifier(), ghoul::to_string(value));
|
||||
executeSetPropertyScript(p->uri(), ghoul::to_string(value));
|
||||
}
|
||||
|
||||
ImGui::PopID();
|
||||
@@ -872,7 +870,7 @@ void renderTriggerProperty(Property* prop, const std::string& ownerName,
|
||||
|
||||
const bool pressed = ImGui::Button(name.c_str());
|
||||
if (pressed) {
|
||||
executeSetPropertyScript(prop->fullyQualifiedIdentifier(), "nil");
|
||||
executeSetPropertyScript(prop->uri(), "nil");
|
||||
}
|
||||
if (showTooltip) {
|
||||
renderTooltip(prop, tooltipDelay);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -137,11 +137,9 @@ void IswaCygnet::initializeGL() {
|
||||
else {
|
||||
_delete.onChange([this]() {
|
||||
deinitialize();
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + identifier() + "')",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(std::format(
|
||||
"openspace.removeSceneGraphNode('{}')", identifier()
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -306,9 +304,7 @@ void IswaCygnet::initializeGroup() {
|
||||
[this](ghoul::Dictionary) {
|
||||
LDEBUG(identifier() + " Event clearGroup");
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + identifier() + "')",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
"openspace.removeSceneGraphNode('" + identifier() + "')"
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -152,11 +152,10 @@ void IswaKameleonGroup::updateFieldlineSeeds() {
|
||||
if (it == options.end() && std::get<2>(seedPath.second)) {
|
||||
LDEBUG("Removed fieldlines: " + std::get<0>(seedPath.second));
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + std::get<0>(seedPath.second) + "')",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.removeSceneGraphNode('{}')", std::get<0>(seedPath.second)
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
std::get<2>(seedPath.second) = false;
|
||||
// if this option was turned on
|
||||
}
|
||||
@@ -180,11 +179,10 @@ void IswaKameleonGroup::clearFieldlines() {
|
||||
if (std::get<2>(seedPath.second)) {
|
||||
LDEBUG("Removed fieldlines: " + std::get<0>(seedPath.second));
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + std::get<0>(seedPath.second) + "')",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.removeSceneGraphNode('{}')", std::get<0>(seedPath.second)
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
std::get<2>(seedPath.second) = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,11 +290,10 @@ void KameleonPlane::updateFieldlineSeeds() {
|
||||
}
|
||||
|
||||
LDEBUG("Removed fieldlines: " + std::get<0>(seedPath.second));
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + std::get<0>(seedPath.second) + "')",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.removeSceneGraphNode('{}')", std::get<0>(seedPath.second)
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
std::get<2>(seedPath.second) = false;
|
||||
// if this option was turned on
|
||||
}
|
||||
|
||||
@@ -53,11 +53,10 @@ ScreenSpaceCygnet::ScreenSpaceCygnet(const ghoul::Dictionary& dictionary)
|
||||
_minRealTimeUpdateInterval = 100;
|
||||
|
||||
_delete.onChange([this]() {
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.removeScreenSpaceCygnet("+std::to_string(_cygnetId)+");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.iswa.removeScreenSpaceCygnet({});", _cygnetId
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -85,11 +85,10 @@ namespace {
|
||||
}
|
||||
|
||||
void createScreenSpace(int id) {
|
||||
using namespace openspace;
|
||||
std::string idStr = std::to_string(id);
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
"openspace.iswa.addScreenSpaceCygnet({CygnetId =" + idStr + "});",
|
||||
openspace::scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
openspace::scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.iswa.addScreenSpaceCygnet({CygnetId =" + idStr + "});"
|
||||
);
|
||||
}
|
||||
} // namespace
|
||||
@@ -546,11 +545,7 @@ void IswaManager::createPlane(MetadataFuture& data) {
|
||||
std::string luaTable = jsonPlaneToLuaTable(data);
|
||||
if (!luaTable.empty()) {
|
||||
std::string script = "openspace.addSceneGraphNode(" + luaTable + ");";
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,11 +575,7 @@ void IswaManager::createSphere(MetadataFuture& data) {
|
||||
std::string luaTable = jsonSphereToLuaTable(data);
|
||||
if (luaTable != "") {
|
||||
std::string script = "openspace.addSceneGraphNode(" + luaTable + ");";
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,11 +605,7 @@ void IswaManager::createKameleonPlane(CdfInfo info, std::string cut) {
|
||||
std::string luaTable = parseKWToLuaTable(info, cut);
|
||||
if (!luaTable.empty()) {
|
||||
std::string script = "openspace.addSceneGraphNode(" + luaTable + ");";
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -656,11 +643,7 @@ void IswaManager::createFieldline(std::string name, std::filesystem::path cdfPat
|
||||
"}";
|
||||
if (!luaTable.empty()) {
|
||||
std::string script = "openspace.addSceneGraphNode(" + luaTable + ");";
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -68,11 +68,8 @@ namespace {
|
||||
|
||||
// Remove a Cygnets.
|
||||
[[codegen::luawrap]] void removeCygnet(std::string name) {
|
||||
using namespace openspace;
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + name + "')",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + name + "')"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -94,12 +91,7 @@ namespace {
|
||||
std::string script = std::format(
|
||||
"openspace.unregisterScreenSpaceRenderable('{}');", cygnetInformation[id]->name
|
||||
);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
// Remove a group of Cygnets.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -104,7 +104,6 @@ namespace {
|
||||
"LowerValueBound",
|
||||
"Lower Value Bound",
|
||||
"", // @TODO Missing documentation
|
||||
// @VISIBILITY(?)
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
@@ -112,7 +111,6 @@ namespace {
|
||||
"UpperValueBound",
|
||||
"Upper Value Bound",
|
||||
"", // @TODO Missing documentation
|
||||
// @VISIBILITY(?)
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -79,7 +79,6 @@ namespace {
|
||||
"CurrentTime",
|
||||
"Current Time",
|
||||
"", // @TODO Missing documentation
|
||||
// @VISIBILITY(2.5)
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
@@ -87,7 +86,6 @@ namespace {
|
||||
"MemoryBudget",
|
||||
"Memory Budget",
|
||||
"", // @TODO Missing documentation
|
||||
// @VISIBILITY(3.5)
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
@@ -95,7 +93,6 @@ namespace {
|
||||
"StreamingBudget",
|
||||
"Streaming Budget",
|
||||
"", // @TODO Missing documentation
|
||||
// @VISIBILITY(3.5)
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
@@ -103,7 +100,6 @@ namespace {
|
||||
"UseGlobalTime",
|
||||
"Global Time",
|
||||
"", // @TODO Missing documentation
|
||||
// @VISIBILITY(2.5)
|
||||
openspace::properties::Property::Visibility::User
|
||||
};
|
||||
|
||||
@@ -118,7 +114,6 @@ namespace {
|
||||
"Selector",
|
||||
"Brick Selector",
|
||||
"", // @TODO Missing documentation
|
||||
// @VISIBILITY(3.5)
|
||||
openspace::properties::Property::Visibility::AdvancedUser
|
||||
};
|
||||
|
||||
|
||||
@@ -571,11 +571,11 @@ bool TSP::writeCache() {
|
||||
}
|
||||
|
||||
float TSP::spatialError(unsigned int brickIndex) const {
|
||||
return *reinterpret_cast<const float*>(_data[brickIndex*NUM_DATA + SPATIAL_ERR]);
|
||||
return *reinterpret_cast<const float*>(&_data[brickIndex*NUM_DATA + SPATIAL_ERR]);
|
||||
}
|
||||
|
||||
float TSP::temporalError(unsigned int brickIndex) const {
|
||||
return *reinterpret_cast<const float*>(_data[brickIndex*NUM_DATA + TEMPORAL_ERR]);
|
||||
return *reinterpret_cast<const float*>(&_data[brickIndex*NUM_DATA + TEMPORAL_ERR]);
|
||||
}
|
||||
|
||||
unsigned int TSP::firstOctreeChild(unsigned int brickIndex) const {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -72,7 +72,7 @@ void to_json(json& j, const PropertyOwner* p) {
|
||||
namespace ghoul {
|
||||
|
||||
void to_json(json& j, const Dictionary& d) {
|
||||
json object;
|
||||
json object = json::object();
|
||||
for (const std::string_view k : d.keys()) {
|
||||
const std::string key = std::string(k);
|
||||
if (d.hasValue<glm::dvec4>(key)) {
|
||||
|
||||
@@ -446,11 +446,7 @@ void FlightControllerTopic::processInputState(const nlohmann::json& json) {
|
||||
|
||||
void FlightControllerTopic::processLua(const nlohmann::json &json) {
|
||||
const std::string script = json[LuaScript];
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -190,7 +190,9 @@ void LuaScriptTopic::handleJson(const nlohmann::json& json) {
|
||||
void LuaScriptTopic::runScript(std::string script, bool shouldReturn,
|
||||
bool shouldBeSynchronized)
|
||||
{
|
||||
scripting::ScriptEngine::ScriptCallback callback;
|
||||
using namespace scripting;
|
||||
|
||||
ScriptEngine::Script::Callback callback;
|
||||
if (shouldReturn) {
|
||||
callback = [this](const ghoul::Dictionary& data) {
|
||||
if (_connection) {
|
||||
@@ -205,12 +207,12 @@ void LuaScriptTopic::runScript(std::string script, bool shouldReturn,
|
||||
_waitingForReturnValue = false;
|
||||
}
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
std::move(script),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized(shouldBeSynchronized),
|
||||
scripting::ScriptEngine::ShouldSendToRemote(shouldBeSynchronized),
|
||||
callback
|
||||
);
|
||||
global::scriptEngine->queueScript({
|
||||
.code = std::move(script),
|
||||
.synchronized = ScriptEngine::Script::ShouldBeSynchronized(shouldBeSynchronized),
|
||||
.sendToRemote = ScriptEngine::Script::ShouldSendToRemote(shouldBeSynchronized),
|
||||
.callback = callback
|
||||
});
|
||||
}
|
||||
|
||||
bool LuaScriptTopic::isDone() const {
|
||||
|
||||
@@ -122,13 +122,10 @@ void SetPropertyTopic::handleJson(const nlohmann::json& json) {
|
||||
const nlohmann::json value = json.at("value");
|
||||
std::string literal = luaLiteralFromJson(value);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
std::format(
|
||||
"openspace.setPropertyValueSingle(\"{}\", {})", propertyKey, literal
|
||||
),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
const std::string script = std::format(
|
||||
"openspace.setPropertyValueSingle(\"{}\", {})", propertyKey, literal
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
}
|
||||
catch (const std::out_of_range& e) {
|
||||
|
||||
@@ -58,7 +58,6 @@ std::vector<nlohmann::json> ShortcutTopic::shortcutsJson() const {
|
||||
const nlohmann::json shortcutJson = {
|
||||
{ "identifier", action.identifier },
|
||||
{ "name", action.name },
|
||||
{ "script", action.command },
|
||||
{ "synchronization", static_cast<bool>(!action.isLocal) },
|
||||
{ "documentation", action.documentation },
|
||||
{ "guiPath", action.guiPath },
|
||||
@@ -121,7 +120,6 @@ nlohmann::json ShortcutTopic::shortcutJson(const std::string& identifier) const
|
||||
json.push_back({
|
||||
{ "identifier", action.identifier },
|
||||
{ "name", action.name },
|
||||
{ "script", action.command },
|
||||
{ "synchronization", static_cast<bool>(!action.isLocal) },
|
||||
{ "documentation", action.documentation },
|
||||
{ "guiPath", action.guiPath },
|
||||
|
||||
@@ -40,13 +40,10 @@ namespace openspace {
|
||||
void TriggerPropertyTopic::handleJson(const nlohmann::json& json) {
|
||||
try {
|
||||
const std::string& propertyKey = json.at("property").get<std::string>();
|
||||
global::scriptEngine->queueScript(
|
||||
std::format(
|
||||
"openspace.setPropertyValueSingle(\"{}\", nil)", propertyKey
|
||||
),
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
const std::string script = std::format(
|
||||
"openspace.setPropertyValueSingle(\"{}\", nil)", propertyKey
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
catch (const std::out_of_range& e) {
|
||||
LERROR("Could not trigger property -- key or value is missing in payload");
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -94,6 +94,9 @@ protected:
|
||||
private:
|
||||
class RenderHandler : public WebRenderHandler {
|
||||
public:
|
||||
RenderHandler()
|
||||
: WebRenderHandler(false)
|
||||
{}
|
||||
void draw() override;
|
||||
void render() override;
|
||||
|
||||
|
||||
@@ -345,14 +345,9 @@ void SkyBrowserModule::moveHoverCircle(const std::string& imageUrl, bool useScri
|
||||
// Show the circle
|
||||
if (useScript) {
|
||||
const std::string script = std::format(
|
||||
"openspace.setPropertyValueSingle('Scene.{}.Renderable.Fade', 1.0);",
|
||||
id
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
"openspace.setPropertyValueSingle('Scene.{}.Renderable.Fade', 1.0);", id
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
else {
|
||||
Renderable* renderable = _hoverCircle->renderable();
|
||||
@@ -372,11 +367,7 @@ void SkyBrowserModule::moveHoverCircle(const std::string& imageUrl, bool useScri
|
||||
"openspace.setPropertyValueSingle('Scene.{}.Translation.Position', {});",
|
||||
id, ghoul::to_string(pos)
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
void SkyBrowserModule::disableHoverCircle(bool useScript) {
|
||||
@@ -386,11 +377,7 @@ void SkyBrowserModule::disableHoverCircle(bool useScript) {
|
||||
"openspace.setPropertyValueSingle('Scene.{}.Renderable.Fade', 0.0);",
|
||||
_hoverCircle->identifier()
|
||||
);
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
else {
|
||||
_hoverCircle->renderable()->property("Fade")->set(0.f);
|
||||
|
||||
@@ -249,21 +249,21 @@ std::string prunedIdentifier(std::string identifier) {
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it
|
||||
// has already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript({
|
||||
.code = script,
|
||||
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
|
||||
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
|
||||
});
|
||||
}
|
||||
}
|
||||
// To ensure each node in a cluster calls its own instance of the wwt application
|
||||
// Do not send this script to the other nodes. (Note malej 2023-AUG-23: Due to this
|
||||
// already being inside a Lua function that have already been synced out)
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.skybrowser.sendOutIdsToBrowsers()",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript({
|
||||
.code = "openspace.skybrowser.sendOutIdsToBrowsers()",
|
||||
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
|
||||
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -607,30 +607,18 @@ ghoul::Dictionary wwtImageCollectionUrlDeprecated()
|
||||
|
||||
// No sync or send because this is already inside a Lua script, therefor it has
|
||||
// already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addScreenSpaceRenderable(" + browser + ");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.addSceneGraphNode(" + target + ");",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.skybrowser.addPairToSkyBrowserModule('" + idTarget + "','"
|
||||
+ idBrowser + "');",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.skybrowser.setSelectedBrowser('" + idBrowser + "');",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
const std::string script = std::format(
|
||||
"openspace.addScreenSpaceRenderable({0});"
|
||||
"openspace.addSceneGraphNode({1});"
|
||||
"openspace.skybrowser.addPairToSkyBrowserModule('{2}','{3}');"
|
||||
"openspace.skybrowser.setSelectedBrowser('{3}')",
|
||||
browser, target, idTarget, idBrowser
|
||||
);
|
||||
global::scriptEngine->queueScript({
|
||||
.code = script,
|
||||
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
|
||||
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -650,17 +638,17 @@ ghoul::Dictionary wwtImageCollectionUrlDeprecated()
|
||||
// Remove from engine.
|
||||
// No sync or send because this is already inside a Lua script, therefor it has
|
||||
// already been synced and sent to the connected nodes and peers
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeScreenSpaceRenderable('" + browser + "');",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript({
|
||||
.code = "openspace.removeScreenSpaceRenderable('" + browser + "');",
|
||||
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
|
||||
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
|
||||
});
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
"openspace.removeSceneGraphNode('" + target + "');",
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::No,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::No
|
||||
);
|
||||
global::scriptEngine->queueScript({
|
||||
.code = "openspace.removeSceneGraphNode('" + target + "');",
|
||||
.synchronized = scripting::ScriptEngine::Script::ShouldBeSynchronized::No,
|
||||
.sendToRemote = scripting::ScriptEngine::Script::ShouldSendToRemote::No
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,8 @@ Browser::Browser(const ghoul::Dictionary& dictionary)
|
||||
// Create browser and render handler
|
||||
_browserInstance = std::make_unique<BrowserInstance>(
|
||||
_renderHandler.get(),
|
||||
_keyboardHandler.get()
|
||||
_keyboardHandler.get(),
|
||||
false
|
||||
);
|
||||
|
||||
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();
|
||||
|
||||
@@ -193,7 +193,10 @@ ScreenSpaceSkyBrowser::~ScreenSpaceSkyBrowser() {
|
||||
|
||||
bool ScreenSpaceSkyBrowser::initializeGL() {
|
||||
WwtCommunicator::initializeGL();
|
||||
ScreenSpaceRenderable::initializeGL();
|
||||
// @TODO (ylvse, 2024-08-23) Remove this once the skybrowser has been rewritten
|
||||
ghoul::Dictionary dict;
|
||||
dict.setValue("useAcceleratedRendering", false);
|
||||
createShaders(dict);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,11 +49,7 @@ namespace {
|
||||
"openspace.setPropertyValueSingle('Scene.{}.Translation.Position', {});",
|
||||
id, ghoul::to_string(positionCelestial)
|
||||
);
|
||||
openspace::global::scriptEngine->queueScript(
|
||||
script,
|
||||
openspace::scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
openspace::scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
openspace::global::scriptEngine->queueScript(script);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -328,11 +324,7 @@ void TargetBrowserPair::startFading(float goal, float fadeTime) {
|
||||
_targetNode->identifier(), _browser->identifier(), goal, fadeTime
|
||||
);
|
||||
|
||||
global::scriptEngine->queueScript(
|
||||
script,
|
||||
scripting::ScriptEngine::ShouldBeSynchronized::Yes,
|
||||
scripting::ScriptEngine::ShouldSendToRemote::Yes
|
||||
);
|
||||
global::scriptEngine->queueScript(script);
|
||||
}
|
||||
|
||||
void TargetBrowserPair::stopAnimations() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -287,9 +287,6 @@ void RenderableTravelSpeed::update(const UpdateData& data) {
|
||||
else { // in case we've reached the target
|
||||
reinitiateTravel();
|
||||
}
|
||||
|
||||
_shaderProgram->setUniform("lineColor", _lineColor);
|
||||
_shaderProgram->setUniform("opacity", opacity());
|
||||
}
|
||||
|
||||
void RenderableTravelSpeed::render(const RenderData& data, RendererTasks&) {
|
||||
@@ -304,6 +301,9 @@ void RenderableTravelSpeed::render(const RenderData& data, RendererTasks&) {
|
||||
);
|
||||
_shaderProgram->setUniform("projectionTransform", data.camera.projectionMatrix());
|
||||
|
||||
_shaderProgram->setUniform("lineColor", _lineColor);
|
||||
_shaderProgram->setUniform("opacity", opacity());
|
||||
|
||||
#ifndef __APPLE__
|
||||
glLineWidth(_lineWidth);
|
||||
#else
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
openspace.space.documentation = {
|
||||
{
|
||||
Name = "tleToSpiceTranslation",
|
||||
Arguments = {{ "tlePath", "String" }},
|
||||
Return = "{ Translation, SpiceKernel }",
|
||||
Arguments = {
|
||||
{ "tlePath", "String" }
|
||||
},
|
||||
Return = "( Translation, SpiceKernel )",
|
||||
Documentation = [[
|
||||
Takes the provided TLE file, converts it into a SPICE kernel and returns a
|
||||
SpiceTranslation instance that can be used to access the information in the TLE
|
||||
file using SPICE's superior integral solver.
|
||||
Takes the provided TLE file, converts it into a SPICE kernel and returns a
|
||||
SpiceTranslation instance that can be used to access the information in the TLE
|
||||
file using SPICE's superior integral solver.
|
||||
|
||||
The second return value is the spice kernel that should be loaded and unloaded by
|
||||
whoever called this function.
|
||||
The second return value is the spice kernel that should be loaded and unloaded by
|
||||
whoever called this function.
|
||||
]]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# #
|
||||
# OpenSpace #
|
||||
# #
|
||||
# Copyright (c) 2014-2023 #
|
||||
# Copyright (c) 2014-2024 #
|
||||
# #
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
|
||||
# software and associated documentation files (the "Software"), to deal in the Software #
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user