Merge branch 'master' into feature/jwst-spice-update

This commit is contained in:
Malin E
2022-05-06 09:31:35 +02:00
97 changed files with 2489 additions and 800 deletions

View File

@@ -395,7 +395,9 @@ void LauncherWindow::populateProfilesList(std::string preset) {
}
_profileBox->addItem(QString::fromStdString("--- User Profiles ---"));
const QStandardItemModel* model = qobject_cast<const QStandardItemModel*>(_profileBox->model());
const QStandardItemModel* model = qobject_cast<const QStandardItemModel*>(
_profileBox->model()
);
model->item(_userAssetCount)->setEnabled(false);
++_userAssetCount;
@@ -410,7 +412,10 @@ void LauncherWindow::populateProfilesList(std::string preset) {
}
std::sort(profiles.begin(), profiles.end());
for (const fs::directory_entry& p : profiles) {
_profileBox->addItem(QString::fromStdString(p.path().stem().string()));
_profileBox->addItem(
QString::fromStdString(p.path().stem().string()),
QString::fromStdString(p.path().string())
);
}
_profileBox->addItem(QString::fromStdString("--- OpenSpace Profiles ---"));
@@ -430,14 +435,30 @@ void LauncherWindow::populateProfilesList(std::string preset) {
// Add sorted items to list
for (const fs::directory_entry& profile : profiles) {
_profileBox->addItem(QString::fromStdString(profile.path().stem().string()));
std::string abc = profile.path().string();
_profileBox->addItem(
QString::fromStdString(profile.path().stem().string()),
QString::fromStdString(profile.path().string())
);
}
// Try to find the requested profile and set it as the current one
const int idx = _profileBox->findText(QString::fromStdString(std::move(preset)));
if (idx != -1) {
_profileBox->setCurrentIndex(idx);
int idx = _profileBox->findText(QString::fromStdString(preset));
if (idx == -1) {
// We didn't find the preset, so the user probably specified a path in the
// configuration file that doesn't match any value in the list
_profileBox->addItem(QString::fromStdString("--- Configuration File ---"));
model = qobject_cast<const QStandardItemModel*>(_profileBox->model());
model->item(_profileBox->count() - 1)->setEnabled(false);
_profileBox->addItem(
QString::fromStdString(preset),
QString::fromStdString(preset)
);
idx = _profileBox->count() - 1;
}
_profileBox->setCurrentIndex(idx);
}
// Returns 'true' if the file was a configuration file, 'false' otherwise
@@ -602,7 +623,8 @@ bool LauncherWindow::wasLaunchSelected() const {
}
std::string LauncherWindow::selectedProfile() const {
return _profileBox->currentText().toStdString();
// The user data stores the full path to the profile
return _profileBox->currentData().toString().toStdString();
}
std::string LauncherWindow::selectedWindowConfig() const {

View File

@@ -0,0 +1,89 @@
local ctx_enable_action = {
Identifier = "os.mars.ctx.fadein",
Name = "Fade in CTX",
Command = [[
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.CTX_blended_01.Enabled", true)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.CTX_blended_01.Settings.Opacity", 0)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.CTX_blended_01.Settings.Opacity", 1, 2.0)]],
Documentation = "Enables and fades in CTX layer for Mars",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("ctx_enable_action", ctx_enable_action.Identifier)
local ctx_disable_action = {
Identifier = "os.mars.ctx.fadedout",
Name = "Fade out CTX Layer",
Command = [[openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.CTX_blended_01.Settings.Opacity", 0, 2.0)]],
Documentation = "Fade out CTX",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("ctx_disable_action", ctx_disable_action.Identifier)
local hirise_enable_action = {
Identifier = "os.mars.hirise.fadein",
Name = "Fade in HiRISE",
Command = [[
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-PSP.Enabled", true)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-PSP.Settings.Opacity", 0)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-PSP.Settings.Opacity", 1, 2.0)]],
Documentation = "Enables and fades in HiRise layer for Mars",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("hirise_enable_action", hirise_enable_action.Identifier)
local hirise_disable_action = {
Identifier = "os.mars.hirise.fadedout",
Name = "Fade out HiRISE",
Command = [[openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-PSP.Settings.Opacity", 0, 2.0)]],
Documentation = "Fade out HiRISE layer for Mars",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("hirise_disable_action", hirise_disable_action.Identifier)
local lshirise_enable_action = {
Identifier = "os.mars.lshirise.fadein",
Name = "Fade in HiRISE Local Set",
Command = [[
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Enabled", true)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled", true)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Settings.Opacity", 0)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Settings.Opacity", 1, 2.0)]],
Documentation = "Enables and fades in HiRise local set layers for Mars (including height)",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("lshirise_enable_action", lshirise_enable_action.Identifier)
local lshirise_disable_action = {
Identifier = "os.mars.lshirise.fadedout",
Name = "Fade out HiRISE Local Set",
Command = [[openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.ColorLayers.HiRISE-LS.Settings.Opacity", 0, 2.0)
openspace.setPropertyValueSingle("Scene.Mars.Renderable.Layers.HeightLayers.HiRISE-LS-DEM.Enabled", false)]],
Documentation = "Fade out HiRISE local set layer for Mars",
GuiPath = "/Solar System/Mars",
IsLocal = true
}
asset.export("lshirise_disable_action", lshirise_disable_action.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(ctx_enable_action)
openspace.action.registerAction(ctx_disable_action)
openspace.action.registerAction(hirise_enable_action)
openspace.action.registerAction(hirise_disable_action)
openspace.action.registerAction(lshirise_enable_action)
openspace.action.registerAction(lshirise_disable_action)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(lshirise_disable_action)
openspace.action.removeAction(lshirise_enable_action)
openspace.action.removeAction(hirise_disable_action)
openspace.action.removeAction(hirise_enable_action)
openspace.action.removeAction(ctx_disable_action)
openspace.action.removeAction(ctx_enable_action)
end)

View File

@@ -0,0 +1,126 @@
local function getIlluminationCommand(node, global)
local commandString = "local node = \"" .. node .. "\"\n"
if (node == "Current Focus") then
commandString = "local node = openspace.navigation.getNavigationState().Anchor\n"
end
if (global) then
commandString = commandString .. [[
if (openspace.hasProperty("Scene."..node..".Renderable.UseAccurateNormals")) then
local list = openspace.getProperty("Scene." .. node .. ".Renderable.Layers.NightLayers.*.Enabled")
if (#list > 0) then
openspace.setPropertyValue("Scene." .. node .. ".Renderable.Layers.NightLayers.*.Enabled", false)
else
openspace.setPropertyValueSingle("Scene." .. node .. ".Renderable.PerformShading", false)
end
if openspace.hasSceneGraphNode(node .. "Atmosphere") then
openspace.setPropertyValueSingle("Scene." .. node .. "Atmosphere.Renderable.SunFollowingCamera", true)
end
if openspace.hasProperty("Scene." .. node .. ".Renderable.ShadowsComponent.DistanceFraction") then
openspace.setPropertyValueSingle("Scene." .. node .. ".Renderable.ShadowsComponent.DistanceFraction", 3000)
end
else
openspace.printWarning("Illumination action only available for globes")
end]]
else
--todo @micahnyc this 40 wont do once we have more rings
commandString = commandString .. [[if (openspace.hasProperty("Scene."..node..".Renderable.UseAccurateNormals")) then
local list = openspace.getProperty("Scene." .. node .. ".Renderable.Layers.NightLayers.*.Enabled")
if (#list > 0) then
openspace.setPropertyValue(list[1], true)
else
openspace.setPropertyValueSingle("Scene." .. node .. ".Renderable.PerformShading", true)
end
if openspace.hasSceneGraphNode(node .. "Atmosphere") then
openspace.setPropertyValueSingle("Scene." .. node .. "Atmosphere.Renderable.SunFollowingCamera", false)
end
if openspace.hasProperty("Scene." .. node .. ".Renderable.ShadowsComponent.DistanceFraction") then
openspace.setPropertyValueSingle("Scene." .. node .. ".Renderable.ShadowsComponent.DistanceFraction", 40)
end
else
openspace.printWarning("Illumination action only available for globes")
end]]
end
return commandString
end
local function getIlluminationAction(node, global)
local actionString = "_standard_illumination"
local actionName = "Standard Illumination"
local actionCommand = getIlluminationCommand(node, global)
if (global) then
actionString = "_global_illumination"
actionName = "Global Illumination"
actionCommand = getIlluminationCommand(node, global)
end
local action = {
Identifier = "os." .. string.gsub(node, "%s+", "") .. actionString,
Name = node .. " " .. actionName,
Command = actionCommand,
Documentation = "Enables " .. string.lower(actionName) .. " for" .. node,
GuiPath = "/Solar System/" .. node,
IsLocal = true
}
return action
end
local current_focus_global = getIlluminationAction("Current Focus", true)
asset.export("current_focus_global", current_focus_global.Identifier)
local current_focus_standard = getIlluminationAction("Current Focus", false)
asset.export("current_focus_standard", current_focus_standard.Identifier)
local earth_global = getIlluminationAction("Earth", true)
asset.export("earth_global", earth_global.Identifier)
local earth_standard = getIlluminationAction("Earth", false)
asset.export("earth_standard", earth_standard.Identifier)
local mars_global = getIlluminationAction("Mars", true)
asset.export("mars_global", mars_global.Identifier)
local mars_standard = getIlluminationAction("Mars", false)
asset.export("mars_standard", mars_standard.Identifier)
local venus_global = getIlluminationAction("Venus", true)
asset.export("venus_global", venus_global.Identifier)
local venus_standard = getIlluminationAction("Venus", false)
asset.export("venus_standard", venus_standard.Identifier)
local titan_global = getIlluminationAction("Titan", true)
asset.export("titan_global", titan_global.Identifier)
local titan_standard = getIlluminationAction("Titan", false)
asset.export("titan_standard", titan_standard.Identifier)
local saturn_global = getIlluminationAction("Saturn", true)
asset.export("saturn_global", saturn_global.Identifier)
local saturn_standard = getIlluminationAction("Saturn", false)
asset.export("titan_standard", saturn_standard.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(current_focus_global)
openspace.action.registerAction(current_focus_standard)
openspace.action.registerAction(earth_global)
openspace.action.registerAction(earth_standard)
openspace.action.registerAction(mars_global)
openspace.action.registerAction(mars_standard)
openspace.action.registerAction(venus_global)
openspace.action.registerAction(venus_standard)
openspace.action.registerAction(titan_global)
openspace.action.registerAction(titan_standard)
openspace.action.registerAction(saturn_global)
openspace.action.registerAction(saturn_standard)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(saturn_standard)
openspace.action.removeAction(saturn_global)
openspace.action.removeAction(titan_standard)
openspace.action.removeAction(titan_global)
openspace.action.removeAction(venus_standard)
openspace.action.removeAction(venus_global)
openspace.action.removeAction(mars_standard)
openspace.action.removeAction(mars_global)
openspace.action.removeAction(earth_standard)
openspace.action.removeAction(earth_global)
openspace.action.removeAction(current_focus_standard)
openspace.action.removeAction(current_focus_global)
end)

View File

@@ -0,0 +1,127 @@
local function getScaleCommand(identifier, scale, speed)
local command = 'openspace.setPropertyValue("' .. identifier .. '.Scale.Scale", '
command = command .. scale .. ", " .. speed
if (scale == 1) then
command = command .. ")"
else
command = command .. ', "CubicEaseOut")'
end
return command
end
local function getScaleAction(identifier, scale, name, speed)
local actionString = "Grow"
if (scale == 1) then
actionString = "Shrink"
end
local action = {
Identifier = "os." .. actionString .. "_" .. identifier,
Name = actionString .. " " .. name,
Command = getScaleCommand(identifier, scale, speed),
Documentation = "Scales " .. name .. " to " .. scale .. "x",
GuiPath = "/Solar System/Scale",
IsLocal = true
}
return action
end
local function getToggleScaleAction(identifier, scale, name, speedup, speedown)
local action = {
Identifier = "os.toggle_" .. string.gsub(name, "%s+", "") .. "_scale",
Name = "Toggle " .. name .. " Scale",
Command = [[
local list = openspace.getProperty("]] .. identifier .. [[.Scale.Scale");
if #list == 0 then
openspace.printWarning("No planets to resize");
else
local prop = list[1];
local currentScale = openspace.getPropertyValue(prop);
local newScale = 1;
if (currentScale == 1) then
]] .. getScaleCommand(identifier, scale, speedup) .. [[
else
]] .. getScaleCommand(identifier, 1, speedown) .. [[
end
end
]],
GuiPath = "/Solar System/Scale",
Documentation = "Toggle the scale of " .. name,
IsLocal = true
}
return action
end
local grow_planets = getScaleAction("{planet_solarSystem}", 3400, "Planets", 3)
asset.export("grow_planets", grow_planets.Identifier)
local shrink_planets = getScaleAction("{planet_solarSystem}", 1, "Planets", 2)
asset.export("shrink_planets", shrink_planets.Identifier)
local toggle_planet_scale = getToggleScaleAction("{planet_solarSystem}", 3400, "Planets", 3, 2)
asset.export("toggle_planet_scale", toggle_planet_scale.Identifier)
local grow_inner_planets = getScaleAction("{planet_terrestrial}", 3400, "Inner Planets", 3)
asset.export("grow_inner_planets", grow_inner_planets.Identifier)
local shrink_inner_planets = getScaleAction("{planet_terrestrial}", 1, "Inner Planets", 2)
asset.export("shrink_inner_planets", shrink_inner_planets.Identifier)
local toggle_inner_planet_scale = getToggleScaleAction("{planet_terrestrial}", 3400, "Inner Planets", 3, 2)
asset.export("toggle_inner_planet_scale", toggle_inner_planet_scale.Identifier)
local grow_outter_planets = getScaleAction("{planet_giants}", 3400, "Outter Planets", 3)
asset.export("grow_outter_planets", grow_outter_planets.Identifier)
local shrink_outter_planets = getScaleAction("{planet_giants}", 1, "Outter Planets", 2)
asset.export("shrink_outter_planets", shrink_outter_planets.Identifier)
local toggle_outter_planet_scale = getToggleScaleAction("{planet_giants}", 3400, "Outter Planets", 3, 2)
asset.export("toggle_outter_planet_scale", toggle_outter_planet_scale.Identifier)
local grow_jupiter_moons = getScaleAction("{moon_jupiter}", 50, "Jupiter Moons", 3)
asset.export("grow_jupiter_moons", grow_jupiter_moons.Identifier)
local shrink_jupiter_moons = getScaleAction("{moon_jupiter}", 1, "Jupiter Moons", 2)
asset.export("shrink_jupiter_moons", shrink_jupiter_moons.Identifier)
local toggle_jupiter_moon_scales = getToggleScaleAction("{moon_jupiter}", 50, "Jupiter Moons", 3, 2)
asset.export("toggle_jupiter_moon_scales", toggle_jupiter_moon_scales.Identifier)
local grow_moon = getScaleAction("Scene.Moon", 25, "Moon", 3)
asset.export("grow_moon", grow_moon.Identifier)
local shrink_moon = getScaleAction("Scene.Moon", 1, "Moon", 2)
asset.export("shrink_moon", shrink_moon.Identifier)
local toggle_moon_scale = getToggleScaleAction("Scene.Moon", 25, "Moon", 3, 2)
asset.export("toggle_moon_scale", toggle_moon_scale.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(grow_planets)
openspace.action.registerAction(shrink_planets)
openspace.action.registerAction(toggle_planet_scale)
openspace.action.registerAction(grow_inner_planets)
openspace.action.registerAction(shrink_inner_planets)
openspace.action.registerAction(toggle_inner_planet_scale)
openspace.action.registerAction(grow_outter_planets)
openspace.action.registerAction(shrink_outter_planets)
openspace.action.registerAction(toggle_outter_planet_scale)
openspace.action.registerAction(grow_jupiter_moons)
openspace.action.registerAction(shrink_jupiter_moons)
openspace.action.registerAction(toggle_jupiter_moon_scales)
openspace.action.registerAction(grow_moon)
openspace.action.registerAction(shrink_moon)
openspace.action.registerAction(toggle_moon_scale)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_moon_scale)
openspace.action.removeAction(shrink_moon)
openspace.action.removeAction(grow_moon)
openspace.action.removeAction(toggle_outter_planet_scale)
openspace.action.removeAction(shrink_outter_planets)
openspace.action.removeAction(grow_outter_planets)
openspace.action.removeAction(toggle_inner_planet_scale)
openspace.action.removeAction(shrink_inner_planets)
openspace.action.removeAction(grow_inner_planets)
openspace.action.removeAction(toggle_planet_scale)
openspace.action.removeAction(shrink_planets)
openspace.action.removeAction(grow_planets)
end)

View File

@@ -0,0 +1,67 @@
local fade_up_trails = {
Identifier = "os.fade_up_trails",
Name = "Show All Trails",
Command = [[
openspace.setPropertyValue("Scene.*Trail.Renderable.Fade", 1, 2);
openspace.setPropertyValue("Scene.*trail.Renderable.Fade", 1, 2);
]],
Documentation = "Fade up all enabled trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("fade_up_trails", fade_up_trails.Identifier)
local fade_down_trails = {
Identifier = "os.fade_down_trails",
Name = "Hide All Trails",
Command = [[
openspace.setPropertyValue("Scene.*Trail.Renderable.Fade", 0, 2);
openspace.setPropertyValue("Scene.*trail.Renderable.Fade", 0, 2);
]],
Documentation = "Fade down all enabled trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("fade_down_trails", fade_down_trails.Identifier)
local toggle_trails = {
Identifier = "os.toggle_trails",
Name = "Toggle All Trails",
Command = [[
local capList = openspace.getProperty("*Trail.Renderable.Fade");
local list = openspace.getProperty("*trail.Renderable.Fade");
if (#capList == 0) and (#list == 0) then
openspace.printWarning("No trails to toggle");
else
local prop;
if #capList > 0 then
prop = capList[1];
else
prop = list[1];
end
local currentFade = openspace.getPropertyValue(prop);
local newFade = 0;
if currentFade < 1 then
newFade = 1;
end
openspace.setPropertyValue("Scene.*Trail.Renderable.Fade", newFade, 2);
openspace.setPropertyValue("Scene.*trail.Renderable.Fade", newFade, 2);
end
]],
Documentation = "Toggle fade for all trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("toggle_trails", toggle_trails.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(fade_up_trails)
openspace.action.registerAction(fade_down_trails)
openspace.action.registerAction(toggle_trails)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_trails)
openspace.action.removeAction(fade_down_trails)
openspace.action.removeAction(fade_up_trails)
end)

View File

@@ -0,0 +1,24 @@
local toggle_trails = {
Identifier = "os_default.toggle_trails",
Name = "Toggle Planet and Moon Trails (Instant)",
Command = [[
local list = openspace.getProperty("{planetTrail_solarSystem}.Renderable.Enabled");
for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end
local moonlist = openspace.getProperty("{moonTrail_solarSystem}.Renderable.Enabled");
for _,v in pairs(moonlist) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end
]],
Documentation = "Toggles the visibility of planet and moon trails",
GuiPath = "/Solar System",
IsLocal = false,
}
asset.onInitialize(function()
openspace.action.registerAction(toggle_trails)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_trails)
end)
asset.export(toggle_trails)

View File

@@ -0,0 +1,67 @@
local fade_up_trails = {
Identifier = "os.fade_up_trails_planets_moon",
Name = "Show Planet and Moon Trails",
Command = [[
openspace.setPropertyValue("{planetTrail_solarSystem}.Renderable.Fade", 1, 2);
openspace.setPropertyValue("{moonTrail_solarSystem}.Renderable.Fade", 1, 2);
]],
Documentation = "Fade up all planet and moon trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("fade_up_trails", fade_up_trails.Identifier)
local fade_down_trails = {
Identifier = "os.fade_down_trails_planets_moon",
Name = "Hide Planet and Moon Trails",
Command = [[
openspace.setPropertyValue("{planetTrail_solarSystem}.Renderable.Fade", 0, 2);
openspace.setPropertyValue("{moonTrail_solarSystem}.Renderable.Fade", 0, 2);
]],
Documentation = "Fade down all planet and moon trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("fade_down_trails", fade_down_trails.Identifier)
local toggle_trails = {
Identifier = "os.toggle_trails_planets_moon",
Name = "Toggle Planet and Moon Trails",
Command = [[
local capList = openspace.getProperty("{planetTrail_solarSystem}.Renderable.Fade");
local list = openspace.getProperty("{moonTrail_solarSystem}.Renderable.Fade");
if (#capList == 0) and (#list == 0) then
openspace.printWarning("No trails to toggle");
else
local prop;
if (#capList > 0) then
prop = capList[1];
else
prop = list[1];
end
local currentFade = openspace.getPropertyValue(prop);
local newFade = 0;
if currentFade < 1 then
newFade = 1;
end
openspace.setPropertyValue("{planetTrail_solarSystem}.Renderable.Fade", newFade, 2);
openspace.setPropertyValue("{moonTrail_solarSystem}.Renderable.Fade", newFade, 2);
end
]],
Documentation = "Toggle fade for planet and moon trails in the Scene",
GuiPath = "/Trails",
IsLocal = true
}
asset.export("toggle_trails", toggle_trails)
asset.onInitialize(function()
openspace.action.registerAction(fade_up_trails)
openspace.action.registerAction(fade_down_trails)
openspace.action.registerAction(toggle_trails)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_trails)
openspace.action.removeAction(fade_down_trails)
openspace.action.removeAction(fade_up_trails)
end)

View File

@@ -0,0 +1,163 @@
local enable_trail_fading = {
Identifier = "os.enable_trail_fading",
Name = "Enable Trail Fading",
Command = [[
openspace.setPropertyValue("Scene.*Trail.Renderable.Appearance.EnableFade", true);
openspace.setPropertyValue("Scene.*trail.Renderable.Appearance.EnableFade", true);
]],
Documentation = "Set orbits to fade out towards the end",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
asset.export("enable_trail_fading", enable_trail_fading.Identifier)
local disable_trail_fading = {
Identifier = "os.disable_trail_fading",
Name = "Disable Trail Fading",
Command = [[
openspace.setPropertyValue("Scene.*Trail.Renderable.Appearance.EnableFade", false);
openspace.setPropertyValue("Scene.*trail.Renderable.Appearance.EnableFade", false);
]],
Documentation = "Sets trails not to fade out torwards end",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
asset.export("disable_trail_fading", disable_trail_fading.Identifier)
local toggle_trail_fading = {
Identifier = "os.toggle_trail_fading",
Name = "Toggle Trail Fading",
Command = [[
local capList = openspace.getProperty("*Trail.Renderable.Appearance.EnableFade")
local list = openspace.getProperty("*trail.Renderable.Appearance.EnableFade")
if (#capList == 0) and (#list == 0) then
openspace.printWarning("No trails to toggle");
else
local prop;
if #capList > 0 then
prop = capList[1];
else
prop = list[1];
end
local currentFade = openspace.getPropertyValue(prop);
local newFade = not currentFade;
openspace.setPropertyValue("Scene.*Trail.Renderable.Appearance.EnableFade", newFade);
openspace.setPropertyValue("Scene.*trail.Renderable.Appearance.EnableFade", newFade);
end
]],
Documentation = "Toggle trails to fade out towards the end for all trails in the Scene",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
asset.export("toggle_trail_fading", toggle_trail_fading.Identifier)
local function getHightlightCommand(identifierString, value)
local easeFunction = "QuinticEaseOut"
if value > 1 then
easeFunction = "QuinticEaseIn"
end
local command = 'openspace.setPropertyValue("'
command = command .. identifierString .. '.Renderable.Appearance.Fade", '
command = command .. value .. ', 2, "' .. easeFunction .. '")'
return command;
end
local function getHighlightAction(identifierString, value, nameString)
local actionString = 'Dehighlight'
if value > 1 then
actionString = 'Highlight'
end
local action = {
Identifier = "os." .. actionString .. identifierString .. "_trail",
Name = actionString .. " " .. nameString .. " Trail",
Command = getHightlightCommand(identifierString, value),
Documentation = "Animates the trail fade of " .. nameString .. "'s Trail",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
return action
end
local function getToggleHighlightAction(identifierString, value, nameString)
local action = {
Identifier = "os.toggle_" .. identifierString .. "_trail_highlight",
Name = "Toggle " .. nameString .. " Trail Highlight",
Command = [[
local list = openspace.getProperty("]] .. identifierString .. [[.Renderable.Appearance.Fade");
if #list == 0 then
openspace.printWarning("No planets to resize");
else
local prop = list[1];
local fadeValue = openspace.getPropertyValue(prop)
if fadeValue > 1 then
]] .. getHightlightCommand(identifierString, 1, nameString) .. "\n" .. [[
else
]] .. getHightlightCommand(identifierString, value, nameString) .. "\n" .. [[
end
end]],
Documentation = "Animates the trail fade of " .. nameString .. "'s trail",
GuiPath = "/Trails/Appearance",
IsLocal = true
}
return action
end
local earthTrailIdentifer = "Scene.EarthTrail"
local highlight_earth_trail = getHighlightAction(earthTrailIdentifer, 10, "Earth")
asset.export("highlight_earth_trail", highlight_earth_trail.Identifier)
local dehighlight_earth_trail = getHighlightAction(earthTrailIdentifer, 1, "Earth")
asset.export("dehighlight_earth_trail", dehighlight_earth_trail.Identifier)
local toggle_earth_trail_highlight = getToggleHighlightAction(earthTrailIdentifer, 10, "Earth")
asset.export("toggle_earth_trail_highlight", toggle_earth_trail_highlight.Identifier)
local highlight_inner_trails = getHighlightAction("{planetTrail_terrestrial}", 50, "Inner Planet")
asset.export("highlight_inner_trails", highlight_inner_trails.Identifier)
local dehighlight_inner_trails = getHighlightAction("{planetTrail_terrestrial}", 1, "Inner Planet")
asset.export("dehighlight_inner_trails", dehighlight_inner_trails.Identifier)
local toggle_inner_trail_highlight = getToggleHighlightAction("{planetTrail_terrestrial}", 50, "Inner Planet")
asset.export("toggle_inner_trail_highlight", toggle_inner_trail_highlight.Identifier)
local highlight_outter_trails = getHighlightAction("{planetTrail_giants}", 100, "Outter Planet")
asset.export("highlight_outter_trails", highlight_outter_trails.Identifier)
local dehighlight_outter_trails = getHighlightAction("{planetTrail_giants}", 1, "Outter Planet")
asset.export("dehighlight_outter_trails", dehighlight_outter_trails.Identifier)
local toggle_outter_trail_highlight = getToggleHighlightAction("{planetTrail_giants}", 100, "Outter Planet")
asset.export("toggle_outter_trail_highlight", toggle_outter_trail_highlight.Identifier)
asset.onInitialize(function()
openspace.action.registerAction(enable_trail_fading)
openspace.action.registerAction(disable_trail_fading)
openspace.action.registerAction(toggle_trail_fading)
openspace.action.registerAction(highlight_earth_trail)
openspace.action.registerAction(dehighlight_earth_trail)
openspace.action.registerAction(toggle_earth_trail_highlight)
openspace.action.registerAction(highlight_inner_trails)
openspace.action.registerAction(dehighlight_inner_trails)
openspace.action.registerAction(toggle_inner_trail_highlight)
openspace.action.registerAction(highlight_outter_trails)
openspace.action.registerAction(dehighlight_outter_trails)
openspace.action.registerAction(toggle_outter_trail_highlight)
end)
asset.onDeinitialize(function()
openspace.action.removeAction(toggle_outter_trail_highlight)
openspace.action.removeAction(dehighlight_outter_trails)
openspace.action.removeAction(highlight_outter_trails)
openspace.action.removeAction(highlight_inner_trails)
openspace.action.removeAction(dehighlight_inner_trails)
openspace.action.removeAction(toggle_inner_trail_highlight)
openspace.action.removeAction(highlight_earth_trail)
openspace.action.removeAction(dehighlight_earth_trail)
openspace.action.removeAction(toggle_earth_trail_highlight)
openspace.action.removeAction(toggle_trail_fading)
openspace.action.removeAction(disable_trail_fading)
openspace.action.removeAction(enable_trail_fading)
end)

View File

@@ -60,6 +60,7 @@ asset.require("scene/digitaluniverse/tully")
asset.require("scene/digitaluniverse/voids")
asset.require("customization/globebrowsing")
asset.require("util/default_actions")
local toggle_trails = {
Identifier = "os_default.toggle_trails",
@@ -92,10 +93,10 @@ local toggle_planet_labels = {
Key = "l"
}
local trailAction = asset.require("actions/trails/toggle_trails_planets_moons").toggle_trails
asset.onInitialize(function ()
openspace.action.registerAction(toggle_trails)
openspace.bindKey(toggle_trails.Key, toggle_trails.Identifier)
openspace.bindKey("h", trailAction.Identifier)
openspace.action.registerAction(toggle_planet_labels)
openspace.bindKey(toggle_planet_labels.Key, toggle_planet_labels.Identifier)
@@ -106,7 +107,6 @@ asset.onInitialize(function ()
end)
asset.onDeinitialize(function ()
openspace.action.removeAction(toggle_trails)
openspace.clearKey(toggle_trails.Key)
openspace.action.removeAction(toggle_planet_labels)

View File

@@ -0,0 +1,27 @@
local action = asset.require("actions/trails/toggle_all_trails")
asset.onInitialize(function()
openspace.event.registerEventAction(
"CameraFocusTransition",
action.fade_up_trails,
{ Transition = "Exiting" }
)
openspace.event.registerEventAction(
"CameraFocusTransition",
action.fade_down_trails,
{ Transition = "Approaching" }
)
end)
asset.onDeinitialize(function()
openspace.event.unregisterEventAction(
"CameraFocusTransition",
action.fade_up_trails,
{ Transition = "Exiting" }
)
openspace.event.unregisterEventAction(
"CameraFocusTransition",
action.fade_down_trails,
{ Transition = "Approaching" }
)
end)

View File

@@ -22,7 +22,7 @@ local toggle_sun = {
Documentation = [[Toggles the visibility of the Sun glare and the Sun globe when the
camera is approaching either so that from far away the Sun Glare is rendered and when
close up, the globe is rendered instead.]],
GuiPath = "/Sun",
GuiPath = "/Solar System/Sun",
IsLocal = false
}

View File

@@ -1,4 +1,4 @@
local action = asset.require("actions/toggle_trail")
local action = asset.require("actions/trails/toggle_trail")
asset.onInitialize(function()
openspace.event.registerEventAction(

View File

@@ -0,0 +1,27 @@
local action = asset.require("actions/trails/toggle_trails_planets_moons")
asset.onInitialize(function()
openspace.event.registerEventAction(
"CameraFocusTransition",
action.fade_up_trails,
{ Transition = "Exiting" }
)
openspace.event.registerEventAction(
"CameraFocusTransition",
action.fade_down_trails,
{ Transition = "Approaching" }
)
end)
asset.onDeinitialize(function()
openspace.event.unregisterEventAction(
"CameraFocusTransition",
action.fade_up_trails,
{ Transition = "Exiting" }
)
openspace.event.unregisterEventAction(
"CameraFocusTransition",
action.fade_down_trails,
{ Transition = "Approaching" }
)
end)

View File

@@ -9,7 +9,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
asset.onInitialize(function ()

View File

@@ -1,5 +1,6 @@
asset.onInitialize(function ()
openspace.setPropertyValueSingle("Modules.SkyBrowser.Enabled", true)
openspace.setPropertyValueSingle("Modules.SkyBrowser.ShowTitleInGuiBrowser", false)
-- More settings are available, but for now using the default values
end)

View File

@@ -16,7 +16,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
local textures = asset.syncedResource({

View File

@@ -9,7 +9,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
local textures = asset.syncedResource({
@@ -27,13 +27,14 @@ local gaia_abundance_apogee = {
File = speck .. "GaiaAbundApogee.speck",
ColorOption = "Other Data",
OtherData = "FeH",
MagnitudeExponent = 6.2,
MagnitudeExponent = 7.25,
SizeComposition = "Distance Modulus",
RenderMethod = "Texture Based",
Texture = textures .. "halo.png",
ColorRange = { { -0.8, 0.6 } },
-- ShapeTexture = textures .. "disc.png",
ColorMap = colormaps .. "colorbv.cmap",
OtherDataColorMap = colormaps .. "viridis.cmap",
OtherDataColorMap = colormaps .. "RainbowGradient.cmap",
StaticFilter = -9999,
StaticFilterReplacement = 0.0,
DataMapping = {

View File

@@ -16,7 +16,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
local textures = asset.syncedResource({
@@ -32,7 +32,7 @@ local GaiaStars = {
Type = "RenderableGaiaStars",
File = starsFolder,
FileReaderOption = "StreamOctree",
RenderOption = "Motion",
RenderMode = "Motion",
ShaderOption = "Point_SSBO",
Texture = textures .. "halo.png",
ColorMap = colormaps .. "colorbv.cmap",

View File

@@ -9,7 +9,7 @@ local colormaps = asset.syncedResource({
Name = "Stars Color Table",
Type = "HttpSynchronization",
Identifier = "stars_colormap",
Version = 2
Version = 3
})
local textures = asset.syncedResource({
@@ -27,13 +27,14 @@ local gaia_abundance_galah = {
File = speck .. "GaiaAbundGalah.speck",
Texture = textures .. "halo.png",
-- ShapeTexture = textures .. "disc.png",
MagnitudeExponent = 6.2,
MagnitudeExponent = 7.25,
SizeComposition = "Distance Modulus",
RenderMethod = "Texture Based",
ColorOption = "Other Data",
OtherData = "FeH",
ColorMap = colormaps .. "colorbv.cmap",
OtherDataColorMap = colormaps .. "viridis.cmap",
OtherDataColorMap = colormaps .. "RainbowGradient.cmap",
ColorRange = { { -0.8, 0.6 } },
StaticFilter = -9999,
StaticFilterReplacement = 0.0,
DataMapping = {

View File

@@ -151,7 +151,7 @@ local RotationKeyframes = {
local InsightParent = {
Identifier = "InsightParent",
Parent = mars.Identifier,
Parent = mars.Mars.Identifier,
Transform = {
Translation ={
Type = "TimelineTranslation",

View File

@@ -3,7 +3,7 @@ local marsTransforms = asset.require("scene/solarsystem/planets/mars/transforms"
local sun = asset.require("scene/solarsystem/sun/sun")
local models = asset.syncedResource({
Name = "Mars 2020 Kernels",
Name = "Perseverance Model",
Type = "HttpSynchronization",
Identifier = "perseverance_models",
Version = 2

View File

@@ -48,7 +48,7 @@ local PerseveranceNode = {
TimeFrame = {
Type = "TimeFrameInterval",
Start = "2020 JUL 30 12:52:43.643",
End = "2021 FEB 18 20:44:58.828"
End = "2021 FEB 18 20:43:48"
}
}
@@ -83,12 +83,12 @@ local PerseveranceTrailMars = {
Translation = {
Type = "SpiceTranslation",
Target = perseverance_id,
Observer = "MARS",
Observer = "MARS BARYCENTER",
Kernels = m2020_kernels
},
Color = { 0.7, 0.9, 0.6 },
StartTime = approachMars,
EndTime = endTime,
EndTime = "2021 FEB 18 20:43:48",
SampleInterval = 100,
Enabled = false
},

View File

@@ -18,8 +18,8 @@ asset.require("./layers/heightlayers/blue_marble_height")
local heightLayer = asset.require("./layers/heightlayers/terrain_tileset")
-- Night layers
asset.require("./layers/nightlayers/earth_night_texture")
local nightLayer = asset.require("./layers/nightlayers/earth_at_night_2012")
asset.require("./layers/nightlayers/earth_night_texture")
asset.require("./layers/nightlayers/earth_at_night_temporal")
-- Overlays

View File

@@ -0,0 +1,46 @@
local globeIdentifier = asset.require("../../earth").Earth.Identifier
local layer = {
Identifier = "VIIRS_NOAA20_Temporal",
Name = "VIIRS NOAA20 (Temporal)",
Type = "TemporalTileLayer",
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2020-04-25",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"VIIRS_NOAA20_CorrectedReflectance_TrueColor",
"250m",
"jpg"
)
},
Description = [[ Temporal coverage: 11 November 2015 - Present. The imagery resolution
is 0.25 km, and the temporal resolution is daily.]]
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "ColorLayers", layer)
end)
asset.export("layer", layer)
asset.meta = {
Name = "VIIRS NOAA20 (Temporal)",
Version = "1.1",
Description = [[ This layer has the best daily Earth Image. GIBS hosted layer created
with openspace.globebrowsing.createTemporalGibsGdalXml ]],
Author = "NASA EOSDIS Global Imagery Browse Services",
URL = "https://earthdata.nasa.gov/eosdis/science-system-description/" ..
"eosdis-components/gibs",
License = "NASA"
}

View File

@@ -0,0 +1,61 @@
local globeIdentifier = asset.require("../../earth").Earth.Identifier
local layer = {
Identifier = "Earth_at_Night_Temporal_Blue_Yellow",
Name = "Earth at Night Blue Yellow (Temporal)",
Type = "TemporalTileLayer",
Mode = "Prototyped",
Prototyped = {
Time = {
Start = "2021-04-30",
End = "Yesterday"
},
TemporalResolution = "1d",
TimeFormat = "YYYY-MM-DD",
Prototype = openspace.globebrowsing.createTemporalGibsGdalXml(
"VIIRS_SNPP_DayNightBand_AtSensor_M15",
"500m",
"jpg"
)
},
Description = [[ The VIIRS Nighttime Imagery (Day/Night Band, Enhanced Near Constant
Contrast) layer shows the Earth's surface and atmosphere using a sensor designed
to capture low-light emission sources, under varying illumination conditions. It
is displayed as a grey-scale image. Sources of illumination include both natural
and anthropogenic sources of light emissions. Lunar reflection can be used to
highlight the location and features of clouds and other terrestrial features such
as sea ice and snow cover when there is partial to full moon conditions. When
there is no moonlight, natural and anthropogenic night time light emissions are
highlighted such as city lights, lightning, auroras, fires, gas flares, and
fishing fleets. This layer is useful for showing patterns of human activity and
energy behaviors such as cities and highways, the holiday periods, the tracking
of shipping and fishing fleets at night and, the burning of waste natural gas
(gas flares) from on and offshore oil/gas production sites. <br><br>The VIIRS
Nighttime Imagery (Day/Night Band, Enhanced Near Constant Contrast) layer is
available from the Visible Infrared Imaging Radiometer Suite (VIIRS) on the joint
NASA/NOAA Suomi National Polar orbiting Partnership (Suomi NPP) satellite.
The sensor resolution is 750 m at nadir, imagery resolution is 500 m, and the
temporal resolution is daily. (Description from NASA Worldview)]],
}
asset.onInitialize(function()
openspace.globebrowsing.addLayer(globeIdentifier, "NightLayers", layer)
end)
asset.onDeinitialize(function()
openspace.globebrowsing.deleteLayer(globeIdentifier, "NightLayers", layer)
end)
asset.export("layer", layer)
asset.meta = {
Name = "Earth at Night Blue Yellow(Temporal)",
Version = "1.1",
Description = [[Temporal layer for earth with daily night image. This layer is a GIBS
hosted layer created with openspace.globebrowsing.createTemporalGibsGdalXml ]],
Author = "OpenSpace Team",
URL = "https://worldview.earthdata.nasa.gov/?l=VIIRS_SNPP_DayNightBand_ENCC",
License = "NASA"
}

View File

@@ -4,13 +4,13 @@ local texturesPath = asset.syncedResource({
Name = "Earth Textures",
Type = "HttpSynchronization",
Identifier = "earth_textures",
Version = 2
Version = 3
})
local layer = {
Identifier = "Earth_Night_Texture",
Name = "Earth Night Texture",
FilePath = texturesPath .. "earth_night.jpg",
FilePath = texturesPath .. "earth_night.png",
Description = [[ Earth's city lights are clearly visible from space ]]
}

View File

@@ -41,36 +41,36 @@ local initializeAndAddNodes = function()
},
Tag = { "earth_satellite", "ISS" },
GUI = {
Path = "/Solar System/Planets/Earth/Satellites/ISS"
Path = "/Solar System/Planets/Earth/Satellites/ISS"
}
}
local parentNode = {
Identifier = "ISSModel",
Parent = iss.Identifier,
Transform = {
Rotation = {
Type = "FixedRotation",
Attached = "ISSModel",
XAxis = { 0.01, -1.0, 0.56 },
XAxisOrthogonal = true,
YAxis = transforms.EarthInertial.Identifier
}
},
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "ISS.fbx",
ModelScale = "Centimeter",
LightSources = {
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true
},
GUI = {
Name = "ISS Model",
Path = "/Solar System/Planets/Earth/Satellites/ISS"
Identifier = "ISSModel",
Parent = iss.Identifier,
Transform = {
Rotation = {
Type = "FixedRotation",
Attached = "ISSModel",
XAxis = { 0.01, -1.0, 0.56 },
XAxisOrthogonal = true,
YAxis = transforms.EarthInertial.Identifier
}
},
Renderable = {
Type = "RenderableModel",
GeometryFile = models .. "ISS.fbx",
ModelScale = "Centimeter",
LightSources = {
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true
},
GUI = {
Name = "ISS Model",
Path = "/Solar System/Planets/Earth/Satellites/ISS"
}
}
local issTrail = {

View File

@@ -0,0 +1,48 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
asset.require("spice/base")
local EarthBarycenterTrail = {
Identifier = "EarthBarycenterTrail",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = "EARTH BARYCENTER",
Observer = "SSB"
},
Color = { 0.5, 0.8, 1.0 },
Period = 365.242,
Resolution = 1000,
Enabled = false
},
Tag = { "planetTrail_solarSystem", "planetTrail_terrestrial" },
GUI = {
Name = "Earth Barycenter Trail",
Path = "/Solar System/Planets/Earth"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(EarthBarycenterTrail)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(EarthBarycenterTrail)
end)
asset.export(EarthBarycenterTrail)
asset.meta = {
Name = "Earth Trail",
Version = "1.1",
Description = [[ Trail of Earth's Barycenter as observed by the Sun. Data from NASA Spice (see
base spice asset)]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -0,0 +1,48 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
asset.require("spice/base")
local JupiterBarycenterTrail = {
Identifier = "JupiterBarycenterTrail",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = "JUPITER BARYCENTER",
Observer = "SSB"
},
Color = { 0.8, 0.7, 0.7 },
Period = 4330.595,
Resolution = 1000,
Enabled = false
},
Tag = { "planetTrail_solarSystem", "planetTrail_giants" },
GUI = {
Name = "Jupiter Barycenter Trail",
Path = "/Solar System/Planets/Jupiter"
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(JupiterBarycenterTrail)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(JupiterBarycenterTrail)
end)
asset.export(JupiterBarycenterTrail)
asset.meta = {
Name = "Jupiter Trail",
Version = "1.1",
Description = [[ Trail of Jupiter's Barycenter as observed by the Sun. Data from NASA Spice (see
base spice asset)]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -0,0 +1,49 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
asset.require("spice/base")
local MarsBarycenterTrail = {
Identifier = "MarsBarycenterTrail",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = "MARS BARYCENTER",
Observer = "SSB"
},
Color = { 0.814, 0.305, 0.220 },
Period = 686.973,
Resolution = 1000,
Enabled = false
},
Tag = { "planetTrail_solarSystem", "planetTrail_terrestrial" },
GUI = {
Name = "Mars Barycenter Trail",
Path = "/Solar System/Planets/Mars",
Description = [[ Trail of Mars' Barycenter as observed by the Sun. Data from NASA Spice (see
base spice asset)]],
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(MarsBarycenterTrail)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(MarsBarycenterTrail)
end)
asset.export(MarsBarycenterTrail)
asset.meta = {
Name = "Mars Trail",
Version = "1.1",
Description = [[ Barycenter Mars trail from SPICE.]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -0,0 +1,49 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
asset.require("spice/base")
local MercuryBarycenterTrail = {
Identifier = "MercuryBarycenterTrail",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = "MERCURY BARYCENTER",
Observer = "SSB"
},
Color = { 0.6, 0.5, 0.5 },
Period = 87.968,
Resolution = 1000,
Enabled = false
},
Tag = { "planetTrail_solarSystem", "planetTrail_terrestrial" },
GUI = {
Name = "Mercury Barycenter Trail",
Path = "/Solar System/Planets/Mercury",
Description = [[ Barycenter Trail of Mercury as observed by the Sun.]],
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(MercuryBarycenterTrail)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(MercuryBarycenterTrail)
end)
asset.export(MercuryBarycenterTrail)
asset.meta = {
Name = "Mercury Trail",
Version = "1.1",
Description = [[ Trail for Mercury's Barycenter. Data from NASA Spice (see
base spice asset)]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -0,0 +1,48 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
asset.require("spice/base")
local NeptuneBarycenterTrail = {
Identifier = "NeptuneBarycenterTrail",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = "NEPTUNE BARYCENTER",
Observer = "SSB"
},
Color = { 0.2, 0.5, 1.0 },
Period = 60266,
Resolution = 1000,
Enabled = false
},
Tag = { "planetTrail_solarSystem", "planetTrail_giants" },
GUI = {
Name = "Neptune Barycenter Trail",
Path = "/Solar System/Planets/Neptune",
Description = [[ BarycenterTrail of Neptune as observed by the Sun.]]
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(NeptuneBarycenterTrail)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(NeptuneBarycenterTrail)
end)
asset.export(NeptuneBarycenterTrail)
asset.meta = {
Name = "Neptune Trail",
Version = "1.1",
Description = [[ Trail of Neptune's Barycenter. Data from NASA Spice (see base spice asset)]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -0,0 +1,47 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
local SaturnBarycenterTrail = {
Identifier = "SaturnBarycenterTrail",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = "SATURN BARYCENTER",
Observer = "SSB"
},
Color = { 0.85, 0.75, 0.51 },
Period = 10746.94,
Resolution = 1000,
Enabled = false
},
Tag = { "planetTrail_solarSystem", "planetTrail_giants" },
GUI = {
Name = "Saturn Barycenter Trail",
Path = "/Solar System/Planets/Saturn",
Description = [[ Trail of Saturn's Barycenter as observed by the Sun.]]
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(SaturnBarycenterTrail)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(SaturnBarycenterTrail)
end)
asset.export(SaturnBarycenterTrail)
asset.meta = {
Name = "Saturn Trail",
Version = "1.1",
Description = [[ Trail of Saturn's Barycenter. Data from NASA Spice (see base spice asset)]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -0,0 +1,47 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
local UranusBarycenterTrail = {
Identifier = "UranusBarycenterTrail",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = "URANUS BARYCENTER",
Observer = "SSB"
},
Color = { 0.60, 0.95, 1.00 },
Period = 30588.740,
Resolution = 1000,
Enabled = false
},
Tag = { "planetTrail_solarSystem", "planetTrail_giants" },
GUI = {
Name = "Uranus Barycenter Trail",
Path = "/Solar System/Planets/Uranus",
Description = [[ Trail of Uranus as observed by the Sun.]],
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(UranusBarycenterTrail)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(UranusBarycenterTrail)
end)
asset.export(UranusBarycenterTrail)
asset.meta = {
Name = "Uranus Trail",
Version = "1.1",
Description = [[ Trail of Uranus' Barycenter. Data from NASA Spice (see base spice asset)]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -0,0 +1,47 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
asset.require("spice/base")
local VenusBarycenterTrail = {
Identifier = "VenusBarycenterTrail",
Parent = transforms.SolarSystemBarycenter.Identifier,
Renderable = {
Type = "RenderableTrailOrbit",
Translation = {
Type = "SpiceTranslation",
Target = "VENUS BARYCENTER",
Observer = "SSB"
},
Color = { 1.0, 0.5, 0.2 },
Period = 224.695,
Resolution = 1000,
Enabled = false
},
Tag = { "planetTrail_solarSystem", "planetTrail_terrestrial" },
GUI = {
Name = "Venus Barycenter Trail",
Path = "/Solar System/Planets/Venus",
Description = "Berycenter trail for Venus",
Hidden = false
}
}
asset.onInitialize(function()
openspace.addSceneGraphNode(VenusBarycenterTrail)
end)
asset.onDeinitialize(function()
openspace.removeSceneGraphNode(VenusBarycenterTrail)
end)
asset.export(VenusBarycenterTrail)
asset.meta = {
Name = "Venus Trail",
Version = "1.1",
Description = [[ Barycenter Trail of Venus as observed by the Sun. Data from NASA Spice (see
base spice asset)]],
Author = "OpenSpace Team",
URL = "http://openspaceproject.com",
License = "MIT license"
}

View File

@@ -8,8 +8,8 @@ local SolarSystemBarycenter = {
-- No parent; this node is attached to the scene graph root
TimeFrame = { -- Using Spice kernels for 1850-2150
Type = "TimeFrameInterval",
Start = "1850-JAN-01",
End = "2150-JAN-01"
Start = "1550-JAN-01",
End = "2650-JAN-22"
},
GUI = {
Name = "Solar System Barycenter",

View File

@@ -2,14 +2,14 @@ local syncedDirectory = asset.syncedResource({
Name = "General SPK Kernels",
Type = "HttpSynchronization",
Identifier = "general_spk",
Version = 1
Version = 2
})
local kernels = {
asset.localResource("naif0012.tls"),
-- Leapseconds:
asset.localResource("pck00010.tpc"),
syncedDirectory .. "de430_1850-2150.bsp"
syncedDirectory .. "de430.bsp"
}
asset.onInitialize(function()

View File

@@ -0,0 +1,3 @@
asset.require("actions/trails/toggle_all_trails");
asset.require("actions/trails/toggle_trails_planets_moons");
asset.require("actions/planets/planet_lighting");

View File

@@ -5,7 +5,7 @@ local toggle_native_ui = {
Name = "Show Native GUI",
Command = propertyHelper.invert("Modules.ImGUI.Enabled"),
Documentation = "Shows or hides the native UI",
GuiPath = "/Native GUI",
GuiPath = "/System/GUI",
IsLocal = true,
Key = "F1"
@@ -26,7 +26,7 @@ local take_screenshot = {
Name = "Take Screenshot",
Command = "openspace.takeScreenshot()",
Documentation = "Saves the contents of the screen to a file in the ${SCREENSHOTS} directory.",
GuiPath = "/Rendering",
GuiPath = "/System/Rendering",
IsLocal = true,
Key = "F12"
@@ -37,7 +37,7 @@ local toggle_pause_interpolated = {
Name = "Toggle Pause (Interpolated)",
Command = "openspace.time.pauseToggleViaKeyboard()",
Documentation = "Smoothly starts and stops the simulation time.",
GuiPath = "/Simulation Speed",
GuiPath = "/Time/Simulation Speed",
IsLocal = true,
Key = "SPACE"
@@ -48,7 +48,7 @@ local toggle_pause_immediate = {
Name = "Toggle Pause (Immediate)",
Command = "openspace.time.togglePause()",
Documentation = "Immediately starts and stops the simulation time.",
GuiPath = "/Simulation Speed",
GuiPath = "/Time/Simulation Speed",
IsLocal = true,
Key = "Shift+SPACE"
@@ -109,7 +109,7 @@ local toggle_main_gui = {
Name = "Toggle main GUI",
Command = propertyHelper.invert("Modules.CefWebGui.Visible"),
Documentation = "Toggles the main GUI",
GuiPath = "/GUI",
GuiPath = "/System/GUI",
IsLocal = true,
Key = "Tab"
@@ -125,7 +125,7 @@ openspace.setPropertyValueSingle("RenderEngine.ShowLog", not isEnabled);
openspace.setPropertyValueSingle("RenderEngine.ShowVersion", not isEnabled);
openspace.setPropertyValueSingle("RenderEngine.ShowCamera", not isEnabled)]],
Documentation = "Toggles the dashboard and overlays",
GuiPath = "/GUI",
GuiPath = "/System/GUI",
IsLocal = true,
Key = "Shift+Tab"
@@ -136,7 +136,7 @@ local toggle_master_rendering = {
Name = "Toggle rendering on master",
Command = propertyHelper.invert("RenderEngine.DisableMasterRendering"),
Documentation = "Toggles the rendering on master",
GuiPath = "/Rendering",
GuiPath = "/System/Rendering",
IsLocal = true,
Key = "Alt+R"
@@ -147,7 +147,7 @@ local next_delta_step_interpolate = {
Name = "Next Delta Time Step (Interpolate)",
Command = "openspace.time.interpolateNextDeltaTimeStep()",
Documentation = "Smoothly interpolates the simulation speed to the next delta time step, if one exists.",
GuiPath = "/Simulation Speed",
GuiPath = "/Time/Simulation Speed",
IsLocal = true,
Key = "Right"
@@ -158,7 +158,7 @@ local next_delta_step_immediate = {
Name = "Next Delta Time Step (Immediate)",
Command = "openspace.time.setNextDeltaTimeStep()",
Documentation = "Immediately set the simulation speed to the next delta time step, if one exists.",
GuiPath = "/Simulation Speed",
GuiPath = "/Time/Simulation Speed",
IsLocal = true,
Key = "Shift+Right"
@@ -169,7 +169,7 @@ local previous_delta_step_interpolate = {
Name = "Previous Delta Time Step (Interpolate)",
Command = "openspace.time.interpolatePreviousDeltaTimeStep()",
Documentation = "Smoothly interpolates the simulation speed to the previous delta time step, if one exists.",
GuiPath = "/Simulation Speed",
GuiPath = "/Time/Simulation Speed",
IsLocal = true,
Key = "Left"
@@ -180,12 +180,27 @@ local previous_delta_step_immediate = {
Name = "Previous Delta Time Step (Immediate)",
Command = "openspace.time.setPreviousDeltaTimeStep()",
Documentation = "Immediately set the simulation speed to the previous delta time step, if one exists.",
GuiPath = "/Simulation Speed",
GuiPath = "/Time/Simulation Speed",
IsLocal = true,
Key = "Shift+Left"
}
local toggle_planet_labels = {
Identifier = "os_default.toggle_planet_labels",
Name = "Toggle planet labels",
Command = [[
local list = openspace.getProperty("{solarsystem_labels}.Renderable.Enabled");
for _,v in pairs(list) do openspace.setPropertyValueSingle(v, not openspace.getPropertyValue(v)) end
]],
Documentation = "Turns on visibility for all solar system labels",
GuiPath = "/Solar System",
IsLocal = false,
Key = "l"
}
local Actions = {
toggle_native_ui,toggle_shutdown,take_screenshot,toggle_pause_interpolated,toggle_pause_immediate,
toggle_rotation_friction,toggle_zoom_friction,toggle_roll_friction,fade_to_black,
@@ -198,7 +213,6 @@ asset.onInitialize(function()
openspace.action.registerAction(action)
openspace.bindKey(action.Key, action.Identifier)
end
-- The take screenshot function is a bit special since we want to bind two keys to that action
openspace.bindKey("PRINT_SCREEN", take_screenshot.Identifier)
end)

View File

@@ -3,7 +3,7 @@ asset.require("./static_server")
local guiCustomization = asset.require("customization/gui")
-- Select which commit hashes to use for the frontend and backend
local frontendHash = "cf0c64cfac2642fb05e7d2a076550161f2a112aa"
local frontendHash = "edaa282c626e0417ce7d6c0a8267349f7d40f6c2"
local dataProvider = "data.openspaceproject.com/files/webgui"
local frontend = asset.syncedResource({

View File

@@ -2,7 +2,7 @@
"actions": [
{
"documentation": "Toggle trails on or off for satellites around Earth",
"gui_path": "/Earth",
"gui_path": "/Solar System/Earth",
"identifier": "profile.toggle.satellite",
"is_local": false,
"name": "Toggle satellite trails",
@@ -10,7 +10,7 @@
},
{
"documentation": "Refocuses the camera on the ISS",
"gui_path": "/Earth",
"gui_path": "/Solar System/Earth",
"identifier": "profile.focus.iss",
"is_local": false,
"name": "Focus ISS",
@@ -18,7 +18,7 @@
},
{
"documentation": "Retargets the camera on Earth",
"gui_path": "/Earth",
"gui_path": "/Solar System/Earth",
"identifier": "profile.focus.earth",
"is_local": false,
"name": "Focus on Earth",

View File

@@ -681,6 +681,8 @@ protected:
double getNextTimestamp();
double getPrevTimestamp();
void cleanUpPlayback();
void cleanUpRecording();
void cleanUpTimelinesAndKeyframes();
bool convertEntries(std::string& inFilename, std::stringstream& inStream,
DataMode mode, int lineNum, std::ofstream& outFile);
virtual bool convertCamera(std::stringstream& inStream, DataMode mode, int lineNum,
@@ -740,7 +742,8 @@ protected:
unsigned char _keyframeBuffer[_saveBufferMaxSize_bytes];
bool _cleanupNeeded = false;
bool _cleanupNeededRecording = false;
bool _cleanupNeededPlayback = false;
const std::string scriptReturnPrefix = "return ";
std::vector<interaction::KeyframeNavigator::CameraPose> _keyframesCamera;

View File

@@ -74,6 +74,7 @@ public:
bool isFacingCamera() const;
void setEnabled(bool isEnabled);
float depth();
float scale() const;
// Screen space functionality in these coords: [-1,1][-ratio,ratio]
glm::vec2 screenSpacePosition();

View File

@@ -70,18 +70,9 @@ public:
const ghoul::Dictionary& dictionary);
/**
* Generates a unique identifying string for the dictionary that is based on the
* \c Type and the \c Identifier values of the passed \p dictionary. All other
* parameters are ignored, but as long as the \c Type and/or the \c Identifier values
* differ, the resulting string will be different.
*
* \param dictionary The dictionary containing the \c Type and the \c Identifier used
* to create a unique identifier
*
* \throw SpecificationError If the \p dictionary does not contain a \c Type, an
* \c Identifier, and a \c Name
* Generates a unique identifying string for ResourceSynchronizaiton.
*/
static std::string generateUid(const ghoul::Dictionary& dictionary);
virtual std::string generateUid() = 0;
/// Defaulted virtual constructor
virtual ~ResourceSynchronization() = default;

View File

@@ -485,6 +485,20 @@ bool FixedRotation::initialize() {
return res;
}
void FixedRotation::update(const UpdateData& data) {
bool anyAxisIsObjectType = (
_xAxis.type == Axis::Type::Object ||
_yAxis.type == Axis::Type::Object ||
_zAxis.type == Axis::Type::Object
);
if (_attachedNode || anyAxisIsObjectType) {
requireUpdate();
}
Rotation::update(data);
}
glm::dmat3 FixedRotation::matrix(const UpdateData&) const {
if (!_enabled) {
return glm::dmat3();

View File

@@ -47,6 +47,7 @@ public:
static documentation::Documentation Documentation();
void update(const UpdateData& data) override;
glm::dmat3 matrix(const UpdateData& data) const override;
private:

View File

@@ -219,7 +219,7 @@ namespace {
std::optional<bool> flowEnabled;
// [[codegen::verbatim(FlowColorInfo.description)]]
std::optional<glm::vec4> flowColor;
std::optional<glm::vec4> flowColor [[codegen::color()]];
// [[codegen::verbatim(FlowReversedInfo.description)]]
std::optional<bool> reversedFlow;
@@ -419,7 +419,7 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence(
// corrupt or not provided
_colorTablePaths.push_back(FieldlinesSequenceModule::DefaultTransferFunctionFile);
}
_colorUniform = p.color.value_or(_colorUniform);
_colorMethod.addOption(static_cast<int>(ColorMethod::Uniform), "Uniform");

View File

@@ -27,7 +27,7 @@
namespace openspace::gaia {
enum RenderOption {
enum RenderMode {
Static = 0,
Color = 1,
Motion = 2

View File

@@ -395,7 +395,7 @@ void OctreeManager::findAndFetchNeighborNode(unsigned long long firstParentId, i
std::map<int, std::vector<float>> OctreeManager::traverseData(const glm::dmat4& mvp,
const glm::vec2& screenSize,
int& deltaStars,
gaia::RenderOption option,
gaia::RenderMode mode,
float lodPixelThreshold)
{
std::map<int, std::vector<float>> renderData;
@@ -471,7 +471,7 @@ std::map<int, std::vector<float>> OctreeManager::traverseData(const glm::dmat4&
mvp,
screenSize,
deltaStars,
option
mode
);
// Avoid freezing when switching render mode for large datasets by only fetching
@@ -521,11 +521,11 @@ std::map<int, std::vector<float>> OctreeManager::traverseData(const glm::dmat4&
return renderData;
}
std::vector<float> OctreeManager::getAllData(gaia::RenderOption option) {
std::vector<float> OctreeManager::getAllData(gaia::RenderMode mode) {
std::vector<float> fullData;
for (size_t i = 0; i < 8; ++i) {
std::vector<float> tmpData = getNodeData(*_root->Children[i], option);
std::vector<float> tmpData = getNodeData(*_root->Children[i], mode);
fullData.insert(fullData.end(), tmpData.begin(), tmpData.end());
}
return fullData;
@@ -1102,7 +1102,7 @@ std::map<int, std::vector<float>> OctreeManager::checkNodeIntersection(OctreeNod
const glm::dmat4& mvp,
const glm::vec2& screenSize,
int& deltaStars,
gaia::RenderOption option)
gaia::RenderMode mode)
{
std::map<int, std::vector<float>> fetchedData;
//int depth = static_cast<int>(log2( MAX_DIST / node->halfDimension ));
@@ -1172,7 +1172,7 @@ std::map<int, std::vector<float>> OctreeManager::checkNodeIntersection(OctreeNod
// Insert data and adjust stars added in this frame.
fetchedData[node.bufferIndex] = constructInsertData(
node,
option,
mode,
deltaStars
);
}
@@ -1191,7 +1191,7 @@ std::map<int, std::vector<float>> OctreeManager::checkNodeIntersection(OctreeNod
// Insert data and adjust stars added in this frame.
fetchedData[node.bufferIndex] = constructInsertData(
node,
option,
mode,
deltaStars
);
}
@@ -1211,7 +1211,7 @@ std::map<int, std::vector<float>> OctreeManager::checkNodeIntersection(OctreeNod
mvp,
screenSize,
deltaStars,
option
mode
);
fetchedData.insert(tmpData.begin(), tmpData.end());
}
@@ -1255,18 +1255,18 @@ std::map<int, std::vector<float>> OctreeManager::removeNodeFromCache(OctreeNode&
}
std::vector<float> OctreeManager::getNodeData(const OctreeNode& node,
gaia::RenderOption option)
gaia::RenderMode mode)
{
// Return node data if node is a leaf.
if (node.isLeaf) {
int dStars = 0;
return constructInsertData(node, option, dStars);
return constructInsertData(node, mode, dStars);
}
// If we're not in a leaf, get data from all children recursively.
std::vector<float> nodeData;
for (size_t i = 0; i < 8; ++i) {
std::vector<float> tmpData = getNodeData(*node.Children[i], option);
std::vector<float> tmpData = getNodeData(*node.Children[i], mode);
nodeData.insert(nodeData.end(), tmpData.begin(), tmpData.end());
}
return nodeData;
@@ -1362,7 +1362,7 @@ bool OctreeManager::updateBufferIndex(OctreeNode& node) {
}
std::vector<float> OctreeManager::constructInsertData(const OctreeNode& node,
gaia::RenderOption option,
gaia::RenderMode mode,
int& deltaStars)
{
// Return early if node doesn't contain any stars!
@@ -1376,12 +1376,12 @@ std::vector<float> OctreeManager::constructInsertData(const OctreeNode& node,
if (_useVBO) {
insertData.resize(POS_SIZE * MAX_STARS_PER_NODE, 0.f);
}
if (option != gaia::RenderOption::Static) {
if (mode != gaia::RenderMode::Static) {
insertData.insert(insertData.end(), node.colData.begin(), node.colData.end());
if (_useVBO) {
insertData.resize((POS_SIZE + COL_SIZE) * MAX_STARS_PER_NODE, 0.f);
}
if (option == gaia::RenderOption::Motion) {
if (mode == gaia::RenderMode::Motion) {
insertData.insert(insertData.end(), node.velData.begin(), node.velData.end());
if (_useVBO) {
insertData.resize(

View File

@@ -119,13 +119,13 @@ public:
* call.
*/
std::map<int, std::vector<float>> traverseData(const glm::dmat4& mvp,
const glm::vec2& screenSize, int& deltaStars, gaia::RenderOption option,
const glm::vec2& screenSize, int& deltaStars, gaia::RenderMode mode,
float lodPixelThreshold);
/**
* Builds full render data structure by traversing all leaves in the Octree.
*/
std::vector<float> getAllData(gaia::RenderOption option);
std::vector<float> getAllData(gaia::RenderMode mode);
/**
* Removes all data from Octree, or only from a specific branch if specified.
@@ -244,7 +244,7 @@ private:
*/
std::map<int, std::vector<float>> checkNodeIntersection(OctreeNode& node,
const glm::dmat4& mvp, const glm::vec2& screenSize, int& deltaStars,
gaia::RenderOption option);
gaia::RenderMode mode);
/**
* Checks if specified node existed in cache, and removes it if that's the case.
@@ -258,7 +258,7 @@ private:
/**
* Get data in node and its descendants regardless if they are visible or not.
*/
std::vector<float> getNodeData(const OctreeNode& node, gaia::RenderOption option);
std::vector<float> getNodeData(const OctreeNode& node, gaia::RenderMode mode);
/**
* Clear data from node and its descendants and shrink vectors to deallocate memory.
@@ -285,7 +285,7 @@ private:
* \param deltaStars keeps track of how many stars that were added.
*/
std::vector<float> constructInsertData(const OctreeNode& node,
gaia::RenderOption option, int& deltaStars);
gaia::RenderMode mode, int& deltaStars);
/**
* Write a node to outFileStream. \param writeData defines if data should be included

View File

@@ -73,9 +73,9 @@ namespace {
"option is suited for bigger datasets.)"
};
constexpr openspace::properties::Property::PropertyInfo RenderOptionInfo = {
"RenderOption",
"Render Option",
constexpr openspace::properties::Property::PropertyInfo RenderModeInfo = {
"RenderMode",
"Render Mode",
"This value determines which predefined columns to use in rendering. If "
"'Static' only the position of the stars is used. 'Color' uses position + color "
"parameters and 'Motion' uses pos, color as well as velocity for the stars."
@@ -315,13 +315,13 @@ namespace {
// [[codegen::verbatim(FileReaderOptionInfo.description)]]
FileReader fileReaderOption;
enum class [[codegen::map(openspace::gaia::RenderOption)]] RenderOption {
enum class [[codegen::map(openspace::gaia::RenderMode)]] RenderMode {
Static,
Color,
Motion
};
// [[codegen::verbatim(RenderOptionInfo.description)]]
std::optional<RenderOption> renderOption;
// [[codegen::verbatim(RenderModeInfo.description)]]
std::optional<RenderMode> renderMode;
enum class [[codegen::map(openspace::gaia::ShaderOption)]] ShaderOption {
PointSSBO [[codegen::key("Point_SSBO")]],
@@ -446,7 +446,7 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
FileReaderOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
)
, _renderOption(RenderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
, _renderMode(RenderModeInfo, properties::OptionProperty::DisplayType::Dropdown)
, _shaderOption(ShaderOptionInfo, properties::OptionProperty::DisplayType::Dropdown)
, _nRenderedStars(NumRenderedStarsInfo, 0, 0, 2000000000) // 2 Billion stars
, _cpuRamBudgetProperty(CpuRamBudgetInfo, 0.f, 0.f, 1.f)
@@ -476,16 +476,16 @@ RenderableGaiaStars::RenderableGaiaStars(const ghoul::Dictionary& dictionary)
});
_fileReaderOption = codegen::map<gaia::FileReaderOption>(p.fileReaderOption);
_renderOption.addOptions({
{ gaia::RenderOption::Static, "Static" },
{ gaia::RenderOption::Color, "Color" },
{ gaia::RenderOption::Motion, "Motion" }
_renderMode.addOptions({
{ gaia::RenderMode::Static, "Static" },
{ gaia::RenderMode::Color, "Color" },
{ gaia::RenderMode::Motion, "Motion" }
});
if (p.renderOption.has_value()) {
_renderOption = codegen::map<gaia::RenderOption>(*p.renderOption);
if (p.renderMode.has_value()) {
_renderMode = codegen::map<gaia::RenderMode>(*p.renderMode);
}
_renderOption.onChange([&]() { _buffersAreDirty = true; });
addProperty(_renderOption);
_renderMode.onChange([&]() { _buffersAreDirty = true; });
addProperty(_renderMode);
_shaderOption.addOptions({
{ gaia::ShaderOption::PointSSBO, "Point_SSBO" },
@@ -952,13 +952,13 @@ void RenderableGaiaStars::render(const RenderData& data, RendererTasks&) {
}
// Traverse Octree and build a map with new nodes to render, uses mvp matrix to decide
const int renderOption = _renderOption;
const int renderOption = _renderMode;
int deltaStars = 0;
std::map<int, std::vector<float>> updateData = _octreeManager.traverseData(
modelViewProjMat,
screenSize,
deltaStars,
gaia::RenderOption(renderOption),
gaia::RenderMode(renderOption),
_lodPixelThreshold
);
@@ -1081,7 +1081,7 @@ void RenderableGaiaStars::render(const RenderData& data, RendererTasks&) {
}
// Update Color VBO if render option is 'Color' or 'Motion'.
if (renderOption != gaia::RenderOption::Static) {
if (renderOption != gaia::RenderMode::Static) {
glBindBuffer(GL_ARRAY_BUFFER, _vboCol);
float colMemoryShare = static_cast<float>(ColorSize) / _nRenderValuesPerStar;
size_t colChunkSize = maxStarsPerNode * ColorSize;
@@ -1112,7 +1112,7 @@ void RenderableGaiaStars::render(const RenderData& data, RendererTasks&) {
}
// Update Velocity VBO if specified.
if (renderOption == gaia::RenderOption::Motion) {
if (renderOption == gaia::RenderMode::Motion) {
glBindBuffer(GL_ARRAY_BUFFER, _vboVel);
float velMemoryShare = static_cast<float>(VelocitySize) /
_nRenderValuesPerStar;
@@ -1163,7 +1163,7 @@ void RenderableGaiaStars::render(const RenderData& data, RendererTasks&) {
_uniformCache.time,
static_cast<float>(data.time.j2000Seconds())
);
_program->setUniform(_uniformCache.renderOption, _renderOption);
_program->setUniform(_uniformCache.renderOption, _renderMode);
_program->setUniform(_uniformCache.viewScaling, viewScaling);
_program->setUniform(_uniformCache.cutOffThreshold, _cutOffThreshold);
_program->setUniform(_uniformCache.luminosityMultiplier, _luminosityMultiplier);
@@ -1340,7 +1340,7 @@ void RenderableGaiaStars::checkGlErrors(const std::string& identifier) const {
void RenderableGaiaStars::update(const UpdateData&) {
const int shaderOption = _shaderOption;
const int renderOption = _renderOption;
const int renderOption = _renderMode;
// Don't update anything if we are in the middle of a rebuild.
if (_octreeManager.isRebuildOngoing()) {
@@ -1675,10 +1675,10 @@ void RenderableGaiaStars::update(const UpdateData&) {
LDEBUG("Regenerating buffers");
// Set values per star slice depending on render option.
if (renderOption == gaia::RenderOption::Static) {
if (renderOption == gaia::RenderMode::Static) {
_nRenderValuesPerStar = PositionSize;
}
else if (renderOption == gaia::RenderOption::Color) {
else if (renderOption == gaia::RenderMode::Color) {
_nRenderValuesPerStar = PositionSize + ColorSize;
}
else { // (renderOption == gaia::RenderOption::Motion)
@@ -1847,7 +1847,7 @@ void RenderableGaiaStars::update(const UpdateData&) {
glBindVertexArray(_vao);
switch (renderOption) {
case gaia::RenderOption::Static: {
case gaia::RenderMode::Static: {
glBindBuffer(GL_ARRAY_BUFFER, _vboPos);
GLint positionAttrib = _program->attributeLocation("in_position");
glEnableVertexAttribArray(positionAttrib);
@@ -1863,7 +1863,7 @@ void RenderableGaiaStars::update(const UpdateData&) {
break;
}
case gaia::RenderOption::Color: {
case gaia::RenderMode::Color: {
glBindBuffer(GL_ARRAY_BUFFER, _vboPos);
GLint positionAttrib = _program->attributeLocation("in_position");
glEnableVertexAttribArray(positionAttrib);
@@ -1891,7 +1891,7 @@ void RenderableGaiaStars::update(const UpdateData&) {
);
break;
}
case gaia::RenderOption::Motion: {
case gaia::RenderMode::Motion: {
glBindBuffer(GL_ARRAY_BUFFER, _vboPos);
GLint positionAttrib = _program->attributeLocation("in_position");
glEnableVertexAttribArray(positionAttrib);

View File

@@ -155,7 +155,7 @@ private:
properties::StringListProperty _columnNamesList;
std::vector<std::string> _columnNames;
properties::OptionProperty _fileReaderOption;
properties::OptionProperty _renderOption;
properties::OptionProperty _renderMode;
properties::OptionProperty _shaderOption;
properties::IntProperty _nRenderedStars;
// LongLongProperty doesn't show up in menu, use FloatProperty instead.

View File

@@ -43,6 +43,7 @@ set(HEADER_FILES
include/topics/shortcuttopic.h
include/topics/subscriptiontopic.h
include/topics/timetopic.h
include/topics/skybrowsertopic.h
include/topics/topic.h
include/topics/triggerpropertytopic.h
include/topics/versiontopic.h
@@ -67,6 +68,7 @@ set(SOURCE_FILES
src/topics/shortcuttopic.cpp
src/topics/subscriptiontopic.cpp
src/topics/timetopic.cpp
src/topics/skybrowsertopic.cpp
src/topics/topic.cpp
src/topics/triggerpropertytopic.cpp
src/topics/versiontopic.cpp

View File

@@ -1 +1,5 @@
set(DEFAULT_MODULE ON)
set(OPENSPACE_DEPENDENCIES
skybrowser
)

View File

@@ -39,14 +39,20 @@ using TopicId = size_t;
class Topic;
class Connection {
// @TODO (abock, 2022-05-06) This is not really elegant as there is no need for a
// Connection to be held by a shared_ptr, but there was a problem with the LuaScriptTopic
// otherwise (issue #1940).
// The problem there is that the LuaScriptTopic is keeping a copy of the _connection in
// its lambda to return a script back to the caller. The script is only queued, so is
// executed a bit longer. If the UI gets reloaded in between the creation of the lambda
// and the execution, the _connection will be an invalid pointer and the program will
// crash. Making this a shared_ptr circumvents that problem my having the lamdba retain
// ownership of the _connection and keeping it alive until the message is sent. The
// message doesn't go anywhere since noone is listening, but it's better than a crash.
class Connection : public std::enable_shared_from_this<Connection> {
public:
Connection(
std::unique_ptr<ghoul::io::Socket> s,
std::string address,
bool authorized = false,
const std::string& password = ""
);
Connection(std::unique_ptr<ghoul::io::Socket> s, std::string address,
bool authorized = false, const std::string& password = "");
void handleMessage(const std::string& message);
void sendMessage(const std::string& message);

View File

@@ -31,9 +31,6 @@ namespace openspace {
class LuaScriptTopic : public Topic {
public:
LuaScriptTopic() = default;
virtual ~LuaScriptTopic() = default;
void handleJson(const nlohmann::json& json) override;
bool isDone() const override;

View File

@@ -0,0 +1,56 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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_SERVER___SKY_BROWSER_TOPIC___H__
#define __OPENSPACE_MODULE_SERVER___SKY_BROWSER_TOPIC___H__
#include <modules/server/include/topics/topic.h>
#include <chrono>
namespace openspace {
class SkyBrowserTopic : public Topic {
public:
SkyBrowserTopic();
virtual ~SkyBrowserTopic();
void handleJson(const nlohmann::json& json) override;
bool isDone() const override;
private:
const int UnsetOnChangeHandle = -1;
void sendBrowserData();
int _targetDataCallbackHandle = UnsetOnChangeHandle;
bool _isDone = false;
std::chrono::system_clock::time_point _lastUpdateTime;
std::string _lastUpdateJsonString;
std::chrono::milliseconds _skyBrowserUpdateTime = std::chrono::milliseconds(100);
};
} // namespace openspace
#endif // __OPENSPACE_MODULE_SERVER___SKY_BROWSER_TOPIC___H__

View File

@@ -33,10 +33,9 @@ class Connection;
class Topic {
public:
Topic() {}
virtual ~Topic();
virtual ~Topic() = default;
void initialize(Connection* connection, size_t topicId);
void initialize(std::shared_ptr<Connection> connection, size_t topicId);
nlohmann::json wrappedPayload(const nlohmann::json& payload) const;
nlohmann::json wrappedError(std::string message = "Could not complete request.",
int code = 500);
@@ -45,7 +44,7 @@ public:
protected:
size_t _topicId = 0;
Connection* _connection;
std::shared_ptr<Connection> _connection;
};
} // namespace openspace

View File

@@ -72,6 +72,10 @@ ServerInterface* ServerModule::serverInterfaceByIdentifier(const std::string& id
return si->get();
}
int ServerModule::skyBrowserUpdateTime() const {
return _skyBrowserUpdateTime;
}
void ServerModule::internalInitialize(const ghoul::Dictionary& configuration) {
global::callback::preSync->emplace_back([this]() {
ZoneScopedN("ServerModule")
@@ -110,6 +114,11 @@ void ServerModule::internalInitialize(const ghoul::Dictionary& configuration) {
_interfaces.push_back(std::move(serverInterface));
}
}
if (configuration.hasValue<double>("SkyBrowserUpdateTime")) {
_skyBrowserUpdateTime = static_cast<int>(
configuration.value<double>("SkyBrowserUpdateTime")
);
}
}
void ServerModule::preSync() {
@@ -207,7 +216,7 @@ void ServerModule::handleConnection(std::shared_ptr<Connection> connection) {
messageString.reserve(256);
while (connection->socket()->getMessage(messageString)) {
std::lock_guard lock(_messageQueueMutex);
_messageQueue.push_back({ connection, std::move(messageString) });
_messageQueue.push_back({ connection, messageString });
}
}

View File

@@ -55,6 +55,8 @@ public:
ServerInterface* serverInterfaceByIdentifier(const std::string& identifier);
int skyBrowserUpdateTime() const;
protected:
void internalInitialize(const ghoul::Dictionary& configuration) override;
@@ -76,6 +78,7 @@ private:
std::vector<ConnectionData> _connections;
std::vector<std::unique_ptr<ServerInterface>> _interfaces;
properties::PropertyOwner _interfaceOwner;
int _skyBrowserUpdateTime = 100;
};
} // namespace openspace

View File

@@ -34,6 +34,7 @@
#include <modules/server/include/topics/sessionrecordingtopic.h>
#include <modules/server/include/topics/setpropertytopic.h>
#include <modules/server/include/topics/shortcuttopic.h>
#include <modules/server/include/topics/skybrowsertopic.h>
#include <modules/server/include/topics/subscriptiontopic.h>
#include <modules/server/include/topics/timetopic.h>
#include <modules/server/include/topics/topic.h>
@@ -69,14 +70,13 @@ namespace {
constexpr const char* TriggerPropertyTopicKey = "trigger";
constexpr const char* BounceTopicKey = "bounce";
constexpr const char* FlightControllerTopicKey = "flightcontroller";
constexpr const char* SkyBrowserKey = "skybrowser";
} // namespace
namespace openspace {
Connection::Connection(std::unique_ptr<ghoul::io::Socket> s,
std::string address,
bool authorized,
const std::string& password)
Connection::Connection(std::unique_ptr<ghoul::io::Socket> s, std::string address,
bool authorized, const std::string& password)
: _socket(std::move(s))
, _address(std::move(address))
, _isAuthorized(authorized)
@@ -109,6 +109,7 @@ Connection::Connection(std::unique_ptr<ghoul::io::Socket> s,
_topicFactory.registerClass<BounceTopic>(BounceTopicKey);
_topicFactory.registerClass<FlightControllerTopic>(FlightControllerTopicKey);
_topicFactory.registerClass<VersionTopic>(VersionTopicKey);
_topicFactory.registerClass<SkyBrowserTopic>(SkyBrowserKey);
}
void Connection::handleMessage(const std::string& message) {
@@ -118,14 +119,16 @@ void Connection::handleMessage(const std::string& message) {
nlohmann::json j = nlohmann::json::parse(message.c_str());
try {
handleJson(j);
} catch (const std::domain_error& e) {
}
catch (const std::domain_error& e) {
LERROR(fmt::format("JSON handling error from: {}. {}", message, e.what()));
}
} catch (const std::out_of_range& e) {
LERROR(fmt::format("JSON handling error from: {}. {}", message, e.what()));
}
catch (const std::exception& e) {
LERROR(e.what());
}
catch (const std::out_of_range& e) {
LERROR(fmt::format("JSON handling error from: {}. {}", message, e.what()));
}
catch (const std::exception& e) {
LERROR(e.what());
} catch (...) {
if (!isAuthorized()) {
_socket->disconnect();
@@ -174,10 +177,7 @@ void Connection::handleJson(const nlohmann::json& json) {
// The topic id is not registered: Initialize a new topic.
auto typeJson = json.find(MessageKeyType);
if (typeJson == json.end() || !typeJson->is_string()) {
LERROR(fmt::format(
"A type must be specified (`{}`) as a string when "
"a new topic is initialized", MessageKeyType
));
LERROR("Type must be specified as a string when a new topic is initialized");
return;
}
std::string type = *typeJson;
@@ -188,7 +188,7 @@ void Connection::handleJson(const nlohmann::json& json) {
}
std::unique_ptr<Topic> topic = std::unique_ptr<Topic>(_topicFactory.create(type));
topic->initialize(this, topicId);
topic->initialize(shared_from_this(), topicId);
topic->handleJson(*payloadJson);
if (!topic->isDone()) {
_topics.emplace(topicId, std::move(topic));
@@ -200,7 +200,7 @@ void Connection::handleJson(const nlohmann::json& json) {
return;
}
// Dispatch the message to the existing topic.
// Dispatch the message to the existing topic
Topic& topic = *topicIt->second;
topic.handleJson(*payloadJson);
if (topic.isDone()) {

View File

@@ -182,7 +182,8 @@ void LuaScriptTopic::runScript(std::string script, bool shouldReturn) {
callback = [this](ghoul::Dictionary data) {
if (_connection) {
nlohmann::json j = data;
_connection->sendJson(wrappedPayload(j));
nlohmann::json payload = wrappedPayload(j);
_connection->sendJson(payload);
_waitingForReturnValue = false;
}
};

View File

@@ -0,0 +1,131 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2022 *
* *
* 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/server/include/topics/skybrowsertopic.h"
#include <modules/server/include/connection.h>
#include <modules/server/servermodule.h>
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/include/targetbrowserpair.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/globals.h>
#include <openspace/properties/property.h>
#include <openspace/query/query.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char* EventKey = "event";
constexpr const char* SubscribeEvent = "start_subscription";
constexpr const char* UnsubscribeEvent = "stop_subscription";
} // namespace
using nlohmann::json;
namespace openspace {
SkyBrowserTopic::SkyBrowserTopic()
: _lastUpdateTime(std::chrono::system_clock::now())
{
ServerModule* module = global::moduleEngine->module<ServerModule>();
if (module) {
_skyBrowserUpdateTime = std::chrono::milliseconds(module->skyBrowserUpdateTime());
}
}
SkyBrowserTopic::~SkyBrowserTopic() {
if (_targetDataCallbackHandle != UnsetOnChangeHandle) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
if (module) {
module->removePreSyncCallback(_targetDataCallbackHandle);
}
}
}
bool SkyBrowserTopic::isDone() const {
return _isDone;
}
void SkyBrowserTopic::handleJson(const nlohmann::json& json) {
std::string event = json.at(EventKey).get<std::string>();
if (event == UnsubscribeEvent) {
_isDone = true;
return;
}
if (event != SubscribeEvent) {
_isDone = true;
return;
}
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
_targetDataCallbackHandle = module->addPreSyncCallback(
[this]() {
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
if (now - _lastUpdateTime > _skyBrowserUpdateTime) {
sendBrowserData();
_lastUpdateTime = std::chrono::system_clock::now();
}
}
);
}
void SkyBrowserTopic::sendBrowserData() {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
ghoul::Dictionary data;
// Set general data
data.setValue("selectedBrowserId", module->selectedBrowserId());
data.setValue("cameraInSolarSystem", module->isCameraInSolarSystem());
// Pass data for all the browsers and the corresponding targets
if (module->isCameraInSolarSystem()) {
const std::vector<std::unique_ptr<TargetBrowserPair>>& pairs = module->getPairs();
ghoul::Dictionary targets;
for (const std::unique_ptr<TargetBrowserPair>& pair : pairs) {
std::string id = pair->browserId();
ghoul::Dictionary target = pair->dataAsDictionary();
targets.setValue(id, target);
}
data.setValue("browsers", targets);
}
std::string jsonString = ghoul::formatJson(data);
// Only send message if data actually changed
if (jsonString != _lastUpdateJsonString) {
json jsonData = json::parse(jsonString.begin(), jsonString.end());
_connection->sendJson(wrappedPayload(jsonData));
}
// @TODO (2022-04-28, emmbr) The message is still sent very often; every time the
// camera moves or the time is changes, because this changes the "roll" parameter
// of the browser. This is the update that occurs most often. Maybe it could be
// separated into it's own topic?
_lastUpdateJsonString = jsonString;
}
} // namespace openspace

View File

@@ -30,12 +30,8 @@
namespace openspace {
Topic::~Topic() {
_connection = nullptr;
}
void Topic::initialize(Connection* connection, size_t topicId) {
_connection = connection;
void Topic::initialize(std::shared_ptr<Connection> connection, size_t topicId) {
_connection = std::move(connection);
_topicId = topicId;
}

View File

@@ -51,9 +51,15 @@ set(SOURCE_FILES
)
source_group("Source Files" FILES ${SOURCE_FILES})
set(SHADER_FILES
shaders/target_fs.glsl
shaders/target_vs.glsl
)
source_group("Shader Files" FILES ${SHADER_FILES})
create_new_module(
"SkyBrowser"
skybrowser_module
STATIC
${HEADER_FILES} ${SOURCE_FILES}
${HEADER_FILES} ${SOURCE_FILES} ${SHADER_FILES}
)

View File

@@ -86,6 +86,10 @@ protected:
void executeJavascript(const std::string& script) const;
bool _isUrlDirty = false;
bool _isDimensionsDirty = false;
bool _shouldReload = false;
private:
class RenderHandler : public WebRenderHandler {
public:
@@ -98,10 +102,6 @@ private:
std::unique_ptr<BrowserInstance> _browserInstance;
CefRefPtr<RenderHandler> _renderHandler;
CefRefPtr<WebKeyboardHandler> _keyboardHandler;
bool _isUrlDirty = false;
bool _isDimensionsDirty = false;
bool _shouldReload = false;
};
} // namespace openspace

View File

@@ -46,31 +46,27 @@ public:
void bindTexture() override;
glm::ivec3 borderColor() const;
float opacity() const;
double animationSpeed() const;
double stopAnimationThreshold() const;
void setDimensions(glm::vec2 dimensions);
void setRatio(float ratio);
void setColor(glm::ivec3 color);
void setOpacity(float opacity);
void setVerticalFov(double fov);
// Display
void highlight(const glm::ivec3& addition);
void removeHighlight(const glm::ivec3& removal);
static documentation::Documentation Documentation();
private:
// Properties
properties::FloatProperty _crossHairSize;
properties::FloatProperty _showRectangleThreshold;
properties::FloatProperty _lineWidth;
properties::DoubleProperty _stopAnimationThreshold;
properties::DoubleProperty _animationSpeed;
double _verticalFov = 10.0;
glm::ivec3 _borderColor = glm::ivec3(230);
glm::vec2 _dimensions = glm::vec2(1.f);
float _ratio = 1.f;
};
} // namespace openspace

View File

@@ -47,37 +47,40 @@ public:
void update() override;
float opacity() const;
glm::vec2 size() const;
glm::dvec2 fineTuneVector(const glm::dvec2& drag);
bool isInitialized() const;
void setVerticalFovWithScroll(float scroll);
void setOpacity(float opacity);
void setScreenSpaceSize(glm::vec2 newSize);
void updateScreenSpaceSize();
glm::dvec2 fineTuneVector(const glm::dvec2& drag);
void setRatio(float ratio);
void setIdInBrowser() const;
void setIsInitialized(bool isInitialized);
void updateTextureResolution();
// Copies rendered
void addRenderCopy(const glm::vec3& raePosition, int nCopies);
void removeRenderCopy();
std::vector<std::pair<std::string, glm::dvec3>> renderCopies() const;
void moveRenderCopy(int i, glm::vec3 raePosition);
void addDisplayCopy(const glm::vec3& raePosition, int nCopies);
void removeDisplayCopy();
std::vector<std::pair<std::string, glm::dvec3>> displayCopies() const;
std::vector<std::pair<std::string, bool>> showDisplayCopies() const;
static documentation::Documentation Documentation();
private:
properties::FloatProperty _textureQuality;
properties::BoolProperty _renderOnlyOnMaster;
std::vector<std::unique_ptr<properties::Vec3Property>> _renderCopies;
properties::BoolProperty _isHidden;
std::vector<std::unique_ptr<properties::Vec3Property>> _displayCopies;
std::vector<std::unique_ptr<properties::BoolProperty>> _showDisplayCopies;
void bindTexture() override;
// Flags
bool _isSyncedWithWwt = false;
bool _textureDimensionsIsDirty = false;
bool _sizeIsDirty = false;
bool _ratioIsDirty = false;
bool _isInitialized = false;
glm::vec2 _size = glm::vec2(1.f, 1.f);
float _ratio = 1.f;
};
} // namespace openspace

View File

@@ -29,6 +29,8 @@
#include <openspace/documentation/documentation.h>
#include <deque>
namespace ghoul { class Dictionary; }
namespace openspace {
struct ImageData;
@@ -44,14 +46,13 @@ public:
// Target & Browser
void initialize();
// Highlighting
void removeHighlight(const glm::ivec3& color);
void highlight(const glm::ivec3& color);
// Animation
void startAnimation(glm::dvec3 coordsEnd, double fovEnd);
void incrementallyAnimateToCoordinate();
void startFading(float goal, float fadeTime);
void incrementallyFade();
void stopAnimations();
// Mouse interaction
void startFinetuningTarget();
void fineTuneTarget(const glm::vec2& startMouse, const glm::vec2& translation);
@@ -60,25 +61,25 @@ public:
// Browser
void sendIdToBrowser() const;
void updateBrowserSize();
std::vector<std::pair<std::string, glm::dvec3>> renderCopies() const;
std::vector<std::pair<std::string, glm::dvec3>> displayCopies() const;
bool isImageCollectionLoaded();
// Target
void centerTargetOnScreen();
double targetRoll();
double targetRoll() const;
bool hasFinishedFading() const;
bool isFacingCamera() const;
bool isUsingRadiusAzimuthElevation() const;
bool isEnabled() const;
void setEnabled(bool enable);
void setOpacity(float opacity);
void setIsSyncedWithWwt(bool isSynced);
void setVerticalFov(double vfov);
void setEquatorialAim(const glm::dvec2& aim);
void setBorderColor(const glm::ivec3& color);
void setScreenSpaceSize(const glm::vec2& dimensions);
void setBrowserRatio(float ratio);
void setVerticalFovWithScroll(float scroll);
void setImageCollectionIsLoaded(bool isLoaded);
double verticalFov() const;
glm::ivec3 borderColor() const;
@@ -88,19 +89,22 @@ public:
std::string browserId() const;
std::string targetRenderableId() const;
std::string targetNodeId() const;
glm::vec2 size() const;
float browserRatio() const;
SceneGraphNode* targetNode() const;
ScreenSpaceSkyBrowser* browser() const;
const std::deque<int>& selectedImages() const;
std::vector<int> selectedImages() const;
ghoul::Dictionary dataAsDictionary() const;
// WorldWide Telescope image handling
void setImageOrder(int i, int order);
void selectImage(const ImageData& image, int i);
void addImageLayerToWwt(const std::string& url, int i);
void removeSelectedImage(int i);
void loadImageCollection(const std::string& collection);
void setImageOpacity(int i, float opacity);
void hideChromeInterface(bool shouldHide);
void hideChromeInterface();
friend bool operator==(const TargetBrowserPair& lhs, const TargetBrowserPair& rhs);
friend bool operator!=(const TargetBrowserPair& lhs, const TargetBrowserPair& rhs);
@@ -114,19 +118,13 @@ private:
SceneGraphNode* _targetNode = nullptr;
// Animation
skybrowser::Animation<float> _fadeBrowser = skybrowser::Animation(0.f, 0.f, 0.f);
skybrowser::Animation<float> _fadeTarget = skybrowser::Animation(0.f, 0.f, 0.f);
skybrowser::Animation<double> _fovAnimation = skybrowser::Animation(0.0, 0.0, 0.0);
skybrowser::Animation<glm::dvec3> _moveTarget =
skybrowser::Animation<glm::dvec3> _targetAnimation =
skybrowser::Animation(glm::dvec3(0.0), glm::dvec3(0.0), 0.0);
bool _targetIsAnimating = false;
// Dragging
glm::dvec3 _startTargetPosition = glm::dvec3(0.0);
glm::dvec2 _equatorialAim = glm::dvec2(0.0);
glm::ivec3 _borderColor = glm::ivec3(255);
glm::vec2 _dimensions = glm::vec2(0.5f);
};
} // namespace openspace

View File

@@ -207,21 +207,21 @@ public:
{
_animationTime = std::chrono::milliseconds(static_cast<int>(time * 1000));
}
void start() {
_isStarted = true;
_startTime = std::chrono::system_clock::now();
}
void stop() {
_isStarted = false;
}
bool isAnimating() const {
bool timeLeft = timeSpent().count() < _animationTime.count() ? true : false;
return timeLeft && _isStarted;
}
T getNewValue();
glm::dmat4 getRotationMatrix();
@@ -231,20 +231,11 @@ private:
std::chrono::duration<double, std::milli> timeSpent = now - _startTime;
return timeSpent;
}
double percentageSpent() const {
return timeSpent().count() / _animationTime.count();
}
double easeOutExpo(double x) {
double epsilon = std::numeric_limits<double>::epsilon();
return std::abs(x - 1.0) < epsilon ? 1.0 : 1.0 - pow(2.0, -10.0 * x);
}
double easeInOutSine(double x) {
return -(cos(glm::pi<double>() * x) - 1.0) / 2.0;
}
// Animation
bool _isStarted = false;
double _lastPercentage = 0;

View File

@@ -44,42 +44,42 @@ public:
void update();
// WorldWide Telescope communication
void displayImage(const std::string& url, int i);
void selectImage(const std::string& url, int i);
void addImageLayerToWwt(const std::string& url, int i);
void removeSelectedImage(int i);
void setImageOrder(int i, int order);
void loadImageCollection(const std::string& collection);
void setImageOpacity(int i, float opacity) const;
void hideChromeInterface(bool shouldHide) const;
void setImageOpacity(int i, float opacity);
void hideChromeInterface() const;
bool isImageCollectionLoaded() const;
bool hasLoadedImages() const;
double verticalFov() const;
glm::ivec3 borderColor() const;
glm::dvec2 equatorialAim() const;
glm::dvec2 fieldsOfView() const;
const std::deque<int>& getSelectedImages() const;
std::vector<int> selectedImages() const;
std::vector<double> opacities() const;
void setHasLoadedImages(bool isLoaded);
void setImageCollectionIsLoaded(bool isLoaded);
void setVerticalFov(double vfov);
void setIsSyncedWithWwt(bool isSynced);
void setEquatorialAim(glm::dvec2 equatorial);
void setBorderColor(glm::ivec3 color);
void setTargetRoll(double roll);
void highlight(const glm::ivec3& addition) const;
// The removal parameter decides what will be removed from the border color
void removeHighlight(const glm::ivec3& removal) const;
void updateBorderColor() const;
void updateAim() const;
protected:
void setIdInBrowser(const std::string& id) const;
std::deque<std::pair<int, double>>::iterator findSelectedImage(int i);
double _verticalFov = 10.0f;
glm::ivec3 _borderColor = glm::ivec3(70);
glm::dvec2 _equatorialAim = glm::dvec2(0.0);
double _targetRoll = 0.0;
bool _hasLoadedImages = false;
std::deque<int> _selectedImages;
bool _isImageCollectionLoaded = false;
std::deque<std::pair<int, double>> _selectedImages;
private:
void setWebpageBorderColor(glm::ivec3 color) const;
@@ -96,7 +96,6 @@ private:
ghoul::Dictionary setImageOpacityMessage(const std::string& id, double opacity) const;
ghoul::Dictionary setLayerOrderMessage(const std::string& id, int version);
bool _isSyncedWithWwt = false;
bool _borderColorIsDirty = false;
bool _equatorialAimIsDirty = false;
int messageCounter = 0;

View File

@@ -32,12 +32,12 @@ in vec4 vs_position;
uniform float crossHairSize;
uniform bool showRectangle;
uniform float lineWidth;
uniform vec2 dimensions;
uniform float ratio;
uniform vec4 lineColor;
uniform float fov;
uniform bool additiveBlending;
uniform float opacity = 1.0;
uniform float opacity;
uniform vec3 multiplyColor;
// A factor which states how much thicker vertical lines are rendered than horizontal
@@ -67,23 +67,22 @@ float createCrosshair(in float linewidth, in float ratio, in vec2 coord) {
#include "fragment.glsl"
Fragment getFragment() {
float ratio = dimensions.y / dimensions.x;
float rectangle = 0.0;
float maxWwtFov = 70;
float crosshair = createCrosshair(lineWidth, ratio, vs_st);
float crossHairHeight = crossHairSize/maxWwtFov;
float crossHairWidth = crossHairHeight * ratio;
float crossHairBox = createFilledRectangle(crossHairHeight, crossHairWidth, vs_st);
float crossHairBox = createFilledRectangle(crossHairWidth, crossHairHeight, vs_st);
crosshair *= crossHairBox;
if (showRectangle) {
float height = (fov * 0.5)/maxWwtFov;
float width = height * ratio;
float outerEdge = createFilledRectangle(height, width, vs_st);
float lineWidthX = lineWidth * 2 * VerticalThickness;
float lineWidthY = lineWidth * 2;
float innerEdge = createFilledRectangle(height-lineWidthX, width-lineWidthY, vs_st);
float height = ((fov * 0.5)/maxWwtFov)-lineWidthX;
float width = (height * ratio) - lineWidthY;
float outerEdge = createFilledRectangle(width, height, vs_st);
float innerEdge = createFilledRectangle(width-lineWidthY, height-lineWidthX, vs_st);
rectangle = outerEdge - innerEdge;
}

View File

@@ -45,6 +45,15 @@ namespace {
"Decides if the GUI for this module should be enabled."
};
constexpr const openspace::properties::Property::PropertyInfo
ShowTitleInGuiBrowserInfo =
{
"ShowTitleInGuiBrowser",
"Show Title in Gui Browser",
"If true, the name of the currently selected sky browser is shown in the WebGUI "
"browser."
};
constexpr const openspace::properties::Property::PropertyInfo AllowRotationInfo = {
"AllowCameraRotation",
"Allow Camera Rotation",
@@ -67,10 +76,37 @@ namespace {
constexpr const openspace::properties::Property::PropertyInfo BrowserSpeedInfo = {
"BrowserAnimationSpeed",
"Field Of View Animation Speed",
"Field of View Animation Speed",
"This determines the speed of the animation of the field of view in the browser."
};
constexpr const openspace::properties::Property::PropertyInfo HideWithGuiInfo = {
"HideTargetsBrowsersWithGui",
"Hide Targets and Browsers with GUI",
"If checked, the targets and browsers will be disabled when the sky browser "
"panel is minimized."
};
constexpr const openspace::properties::Property::PropertyInfo InverseZoomInfo = {
"InverseZoomDirection",
"Inverse Zoom Direction",
"If checked, the zoom direction of the scroll over the AAS WWT browser will be "
"inversed."
};
constexpr const openspace::properties::Property::PropertyInfo SpaceCraftTimeInfo = {
"SpaceCraftAnimationTime",
"Space Craft Animation Time",
"Sets the duration (in seconds) of the animation of the space craft when it is "
"pointed to where the target is aiming."
};
constexpr const openspace::properties::Property::PropertyInfo ImageCollectionInfo = {
"WwtImageCollectionUrl",
"AAS WorldWide Telescope Image Collection Url",
"The url of the image collection which is loaded into AAS WorldWide Telescope."
};
struct [[codegen::Dictionary(SkyBrowserModule)]] Parameters {
// [[codegen::verbatim(EnabledInfo.description)]]
std::optional<bool> enabled;
@@ -86,6 +122,18 @@ namespace {
// [[codegen::verbatim(BrowserSpeedInfo.description)]]
std::optional<double> browserSpeed;
// [[codegen::verbatim(HideWithGuiInfo.description)]]
std::optional<bool> hideTargetsBrowsersGui;
// [[codegen::verbatim(InverseZoomInfo.description)]]
std::optional<bool> inverseZoomDirection;
// [[codegen::verbatim(SpaceCraftTimeInfo.description)]]
std::optional<double> spaceCraftAnimationTime;
// [[codegen::verbatim(SpaceCraftTimeInfo.description)]]
std::optional<std::string> wwtImageCollectionUrl;
};
#include "skybrowsermodule_codegen.cpp"
@@ -96,16 +144,28 @@ namespace openspace {
SkyBrowserModule::SkyBrowserModule()
: OpenSpaceModule(SkyBrowserModule::Name)
, _enabled(EnabledInfo)
, _showTitleInGuiBrowser(ShowTitleInGuiBrowserInfo, true)
, _allowCameraRotation(AllowRotationInfo, true)
, _cameraRotationSpeed(CameraRotSpeedInfo, 0.5, 0.0, 1.0)
, _targetAnimationSpeed(TargetSpeedInfo, 0.2, 0.0, 1.0)
, _browserAnimationSpeed(BrowserSpeedInfo, 5.0, 0.0, 10.0)
, _hideTargetsBrowsersWithGui(HideWithGuiInfo, false)
, _inverseZoomDirection(InverseZoomInfo, false)
, _spaceCraftAnimationTime(SpaceCraftTimeInfo, 2.0, 0.0, 10.0)
, _wwtImageCollectionUrl(ImageCollectionInfo,
"https://data.openspaceproject.com/wwt/1/imagecollection.wtml")
{
addProperty(_enabled);
addProperty(_showTitleInGuiBrowser);
addProperty(_allowCameraRotation);
addProperty(_cameraRotationSpeed);
addProperty(_targetAnimationSpeed);
addProperty(_browserAnimationSpeed);
addProperty(_hideTargetsBrowsersWithGui);
addProperty(_inverseZoomDirection);
addProperty(_spaceCraftAnimationTime);
addProperty(_wwtImageCollectionUrl);
_wwtImageCollectionUrl.setReadOnly(true);
// Set callback functions
global::callback::mouseButton->emplace(global::callback::mouseButton->begin(),
@@ -126,45 +186,41 @@ SkyBrowserModule::SkyBrowserModule()
_isCameraInSolarSystem = glm::length(cameraPos) < SolarSystemRadius;
bool vizModeChanged = _isCameraInSolarSystem != camWasInSolarSystem;
// Visualization mode changed. Start fading
if (vizModeChanged && !_isCameraInSolarSystem) {
// Camera moved into the solar system
_isFading = true;
_goal = Transparency::Transparent;
// Visualization mode changed. Start fading in/out
if (vizModeChanged) {
constexpr float FadeDuration = 2.f;
float transparency = [](Transparency goal) {
switch (goal) {
case Transparency::Transparent: return 0.f;
case Transparency::Opaque: return 1.f;
default: throw ghoul::MissingCaseException();
if (camWasInSolarSystem) { // Camera moved out of the solar system => fade out
for (const std::unique_ptr<TargetBrowserPair>& pair : _targetsBrowsers) {
pair->startFading(0.f, FadeDuration);
}
}(_goal);
std::for_each(
_targetsBrowsers.begin(),
_targetsBrowsers.end(),
[&](const std::unique_ptr<TargetBrowserPair>& pair) {
pair->startFading(transparency, 2.f);
// Also hide the hover circle
disableHoverCircle();
}
else { // Camera moved into the solar system => fade in
for (const std::unique_ptr<TargetBrowserPair>& pair : _targetsBrowsers) {
pair->startFading(1.f, FadeDuration);
}
);
}
// Fade pairs if the camera moved in or out the solar system
if (_isFading) {
incrementallyFadeBrowserTargets(_goal);
}
}
if (_isCameraInSolarSystem) {
std::for_each(
_targetsBrowsers.begin(),
_targetsBrowsers.end(),
[&](const std::unique_ptr<TargetBrowserPair>& pair) {
pair->synchronizeAim();
}
);
for (const std::unique_ptr<TargetBrowserPair>& pair : _targetsBrowsers) {
pair->synchronizeAim();
}
incrementallyAnimateTargets();
}
if (_cameraRotation.isAnimating() && _allowCameraRotation) {
incrementallyRotateCamera();
}
// Trigger callbacks (should maybe have a check to see if update is needed)
using K = CallbackHandle;
using V = CallbackFunction;
for (const std::pair<const K, V>& it : _preSyncCallbacks) {
it.second(); // call function
}
});
}
@@ -172,6 +228,18 @@ void SkyBrowserModule::internalInitialize(const ghoul::Dictionary& dict) {
const Parameters p = codegen::bake<Parameters>(dict);
_enabled = p.enabled.value_or(true);
_allowCameraRotation = p.allowCameraRotation.value_or(_allowCameraRotation);
_cameraRotationSpeed = p.cameraRotSpeed.value_or(_cameraRotationSpeed);
_targetAnimationSpeed = p.targetSpeed.value_or(_targetAnimationSpeed);
_browserAnimationSpeed = p.browserSpeed.value_or(_browserAnimationSpeed);
_inverseZoomDirection = p.inverseZoomDirection.value_or(_inverseZoomDirection);
_wwtImageCollectionUrl = p.wwtImageCollectionUrl.value_or(_wwtImageCollectionUrl);
_hideTargetsBrowsersWithGui = p.hideTargetsBrowsersGui.value_or(
_hideTargetsBrowsersWithGui
);
_spaceCraftAnimationTime = p.spaceCraftAnimationTime.value_or(
_spaceCraftAnimationTime
);
ghoul::TemplateFactory<ScreenSpaceRenderable>* fScreenSpaceRenderable =
FactoryManager::ref().factory<ScreenSpaceRenderable>();
@@ -208,10 +276,11 @@ void SkyBrowserModule::addTargetBrowserPair(const std::string& targetId,
if (browser && target) {
_targetsBrowsers.push_back(std::make_unique<TargetBrowserPair>(target, browser));
}
_uniqueIdentifierCounter++;
}
void SkyBrowserModule::removeTargetBrowserPair(const std::string& id) {
TargetBrowserPair* found = getPair(id);
TargetBrowserPair* found = pair(id);
if (!found) {
return;
}
@@ -222,18 +291,17 @@ void SkyBrowserModule::removeTargetBrowserPair(const std::string& id) {
[&](const std::unique_ptr<TargetBrowserPair>& pair) {
// should this be?
// found == pair.get()
return *found == *(pair.get());
return found == pair.get();
}
);
_targetsBrowsers.erase(it, _targetsBrowsers.end());
_mouseOnPair = nullptr;
}
void SkyBrowserModule::lookAtTarget(const std::string& id) {
TargetBrowserPair* pair = getPair(id);
if (pair) {
startRotatingCamera(pair->targetDirectionGalactic());
TargetBrowserPair* found = pair(id);
if (found) {
startRotatingCamera(found->targetDirectionGalactic());
}
}
@@ -241,23 +309,39 @@ void SkyBrowserModule::setHoverCircle(SceneGraphNode* circle) {
_hoverCircle = circle;
}
void SkyBrowserModule::moveHoverCircle(int i) {
void SkyBrowserModule::moveHoverCircle(int i, bool useScript) {
const ImageData& image = _dataHandler->getImage(i);
// Only move and show circle if the image has coordinates
if (_hoverCircle && image.hasCelestialCoords && _isCameraInSolarSystem) {
// Make circle visible
_hoverCircle->renderable()->property("Enabled")->set(true);
const std::string id = _hoverCircle->identifier();
// Show the circle
if (useScript) {
const std::string script = fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.Fade', 1.0);",
id
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::RemoteScripting::Yes
);
}
else {
Renderable* renderable = _hoverCircle->renderable();
if (renderable) {
renderable->property("Fade")->set(1.f);
}
}
// Set the exact target position
// Move it slightly outside of the celestial sphere so it doesn't overlap with
// the target
glm::dvec3 pos = skybrowser::equatorialToGalactic(image.equatorialCartesian);
pos *= skybrowser::CelestialSphereRadius * 1.1;
// Uris for properties
std::string id = _hoverCircle->identifier();
std::string script = fmt::format(
// Note that the position can only be set through the script engine
const std::string script = fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Translation.Position', {});",
id, ghoul::to_string(pos)
);
@@ -268,9 +352,21 @@ void SkyBrowserModule::moveHoverCircle(int i) {
}
}
void SkyBrowserModule::disableHoverCircle() {
void SkyBrowserModule::disableHoverCircle(bool useScript) {
if (_hoverCircle && _hoverCircle->renderable()) {
_hoverCircle->renderable()->property("Enabled")->set(false);
if (useScript) {
const std::string script = fmt::format(
"openspace.setPropertyValueSingle('Scene.{}.Renderable.Fade', 0.0);",
_hoverCircle->identifier()
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::RemoteScripting::Yes
);
}
else {
_hoverCircle->renderable()->property("Fade")->set(0.f);
}
}
}
@@ -296,7 +392,7 @@ int SkyBrowserModule::nPairs() const {
return static_cast<int>(_targetsBrowsers.size());
}
TargetBrowserPair* SkyBrowserModule::getPair(const std::string& id) const {
TargetBrowserPair* SkyBrowserModule::pair(const std::string& id) const {
auto it = std::find_if(
_targetsBrowsers.begin(),
_targetsBrowsers.end(),
@@ -307,7 +403,11 @@ TargetBrowserPair* SkyBrowserModule::getPair(const std::string& id) const {
return foundBrowser || foundTarget || foundTargetNode;
}
);
return it != _targetsBrowsers.end() ? it->get() : nullptr;
TargetBrowserPair* found = it != _targetsBrowsers.end() ? it->get() : nullptr;
if (found == nullptr) {
LINFO(fmt::format("Identifier '{}' not found", id));
}
return found;
}
void SkyBrowserModule::startRotatingCamera(glm::dvec3 endAnimation) {
@@ -326,29 +426,6 @@ void SkyBrowserModule::incrementallyRotateCamera() {
}
}
void SkyBrowserModule::incrementallyFadeBrowserTargets(Transparency goal) {
bool isAllFinished = true;
for (std::unique_ptr<TargetBrowserPair>& pair : _targetsBrowsers) {
if (pair->isEnabled()) {
bool isPairFinished = pair->hasFinishedFading();
if (!isPairFinished) {
pair->incrementallyFade();
}
else if (isPairFinished && goal == Transparency::Transparent) {
pair->setEnabled(false);
pair->setOpacity(1.0);
}
isAllFinished &= isPairFinished;
}
}
// The transition is over when the fade is finished
if (isAllFinished) {
_isFading = false;
}
}
void SkyBrowserModule::incrementallyAnimateTargets() {
for (std::unique_ptr<TargetBrowserPair>& pair : _targetsBrowsers) {
if (pair->isEnabled()) {
@@ -365,8 +442,16 @@ double SkyBrowserModule::browserAnimationSpeed() const {
return _browserAnimationSpeed;
}
double SkyBrowserModule::spaceCraftAnimationTime() const {
return _spaceCraftAnimationTime;
}
std::string SkyBrowserModule::wwtImageCollectionUrl() const {
return _wwtImageCollectionUrl;
}
void SkyBrowserModule::setSelectedBrowser(const std::string& id) {
TargetBrowserPair* found = getPair(id);
TargetBrowserPair* found = pair(id);
if (found) {
_selectedBrowser = id;
}
@@ -377,12 +462,12 @@ std::string SkyBrowserModule::selectedBrowserId() const {
}
std::string SkyBrowserModule::selectedTargetId() const {
TargetBrowserPair* found = getPair(_selectedBrowser);
TargetBrowserPair* found = pair(_selectedBrowser);
return found ? found->targetRenderableId() : "";
}
glm::ivec3 SkyBrowserModule::highlight() const {
return _highlightAddition;
int SkyBrowserModule::uniqueIdentifierCounter() const {
return _uniqueIdentifierCounter;
}
bool SkyBrowserModule::isCameraInSolarSystem() const {
@@ -390,15 +475,47 @@ bool SkyBrowserModule::isCameraInSolarSystem() const {
}
bool SkyBrowserModule::isSelectedPairUsingRae() const {
TargetBrowserPair* found = getPair(_selectedBrowser);
TargetBrowserPair* found = pair(_selectedBrowser);
return found ? found->isUsingRadiusAzimuthElevation() : false;
}
bool SkyBrowserModule::isSelectedPairFacingCamera() const {
TargetBrowserPair* found = getPair(_selectedBrowser);
TargetBrowserPair* found = pair(_selectedBrowser);
return found ? found->isFacingCamera() : false;
}
SkyBrowserModule::CallbackHandle SkyBrowserModule::addPreSyncCallback(
CallbackFunction cb)
{
CallbackHandle handle = _nextCallbackHandle++;
_preSyncCallbacks.emplace_back(handle, std::move(cb));
return handle;
}
void SkyBrowserModule::removePreSyncCallback(CallbackHandle handle) {
const auto it = std::find_if(
_preSyncCallbacks.begin(),
_preSyncCallbacks.end(),
[handle](const std::pair<CallbackHandle, CallbackFunction>& cb) {
return cb.first == handle;
}
);
ghoul_assert(
it != _preSyncCallbacks.end(),
"handle must be a valid callback handle"
);
_preSyncCallbacks.erase(it);
}
std::vector<documentation::Documentation> SkyBrowserModule::documentations() const {
return {
RenderableSkyTarget::Documentation(),
ScreenSpaceSkyBrowser::Documentation()
};
}
scripting::LuaLibrary SkyBrowserModule::luaLibrary() const {
return {
"skybrowser",
@@ -426,12 +543,17 @@ scripting::LuaLibrary SkyBrowserModule::luaLibrary() const {
codegen::lua::SetVerticalFov,
codegen::lua::SetBorderColor,
codegen::lua::TranslateScreenSpaceRenderable,
codegen::lua::AddRenderCopy,
codegen::lua::SetScreenSpaceSize,
codegen::lua::RemoveRenderCopy,
codegen::lua::AddDisplayCopy,
codegen::lua::SetBrowserRatio,
codegen::lua::RemoveDisplayCopy,
codegen::lua::StartFinetuningTarget,
codegen::lua::FinetuneTargetPosition,
codegen::lua::ScrollOverBrowser
codegen::lua::ScrollOverBrowser,
codegen::lua::LoadingImageCollectionComplete,
codegen::lua::ShowAllTargetsAndBrowsers,
codegen::lua::PointSpaceCraft,
codegen::lua::GetWwtImageCollectionUrl,
codegen::lua::StopAnimations
}
};
}

View File

@@ -33,6 +33,7 @@
#include <openspace/util/mouse.h>
#include <openspace/properties/scalar/boolproperty.h>
#include <openspace/properties/scalar/doubleproperty.h>
#include <openspace/properties/stringproperty.h>
#include <fstream>
namespace openspace {
@@ -43,30 +44,21 @@ class TargetBrowserPair;
class SceneGraphNode;
struct ImageData;
enum class Transparency {
Transparent,
Opaque
};
enum class MouseInteraction {
Hover,
Drag,
FineTune
};
class SkyBrowserModule : public OpenSpaceModule {
public:
constexpr static const char* Name = "SkyBrowser";
using CallbackHandle = int;
using CallbackFunction = std::function<void()>;
SkyBrowserModule();
std::vector<std::unique_ptr<TargetBrowserPair>>& getPairs();
int nPairs() const;
TargetBrowserPair* getPair(const std::string& id) const;
TargetBrowserPair* pair(const std::string& id) const;
const std::unique_ptr<WwtDataHandler>& getWwtDataHandler() const;
std::string selectedBrowserId() const;
std::string selectedTargetId() const;
glm::ivec3 highlight() const;
int uniqueIdentifierCounter() const;
void setSelectedBrowser(const std::string& id);
void setHoverCircle(SceneGraphNode* circle);
@@ -75,10 +67,11 @@ public:
void lookAtTarget(const std::string& id);
void startRotatingCamera(glm::dvec3 endAnimation); // Pass in galactic coordinate
void incrementallyRotateCamera();
void incrementallyFadeBrowserTargets(Transparency goal);
void incrementallyAnimateTargets();
double targetAnimationSpeed() const;
double browserAnimationSpeed() const;
double spaceCraftAnimationTime() const;
std::string wwtImageCollectionUrl() const;
bool isCameraInSolarSystem() const;
bool isSelectedPairFacingCamera() const;
@@ -89,45 +82,42 @@ public:
void addTargetBrowserPair(const std::string& targetId, const std::string& browserId);
// Hover circle
void moveHoverCircle(int i);
void disableHoverCircle();
void moveHoverCircle(int i, bool useScript = true);
void disableHoverCircle(bool useScript = true);
// Image collection handling
void loadImages(const std::string& root, const std::filesystem::path& directory);
int nLoadedImages() const;
CallbackHandle addPreSyncCallback(CallbackFunction cb);
void removePreSyncCallback(CallbackHandle handle);
scripting::LuaLibrary luaLibrary() const override;
//std::vector<documentation::Documentation> documentations() const override;
std::vector<documentation::Documentation> documentations() const override;
protected:
void internalInitialize(const ghoul::Dictionary& dict) override;
private:
properties::BoolProperty _enabled;
properties::BoolProperty _showTitleInGuiBrowser;
properties::BoolProperty _allowCameraRotation;
properties::BoolProperty _hideTargetsBrowsersWithGui;
properties::BoolProperty _inverseZoomDirection;
properties::DoubleProperty _cameraRotationSpeed;
properties::DoubleProperty _targetAnimationSpeed;
properties::DoubleProperty _browserAnimationSpeed;
glm::ivec3 _highlightAddition = glm::ivec3(35); // Highlight object when mouse hovers
properties::DoubleProperty _spaceCraftAnimationTime;
properties::StringProperty _wwtImageCollectionUrl;
// The browsers and targets
std::vector<std::unique_ptr<TargetBrowserPair>> _targetsBrowsers;
TargetBrowserPair* _mouseOnPair = nullptr;
SceneGraphNode* _hoverCircle = nullptr;
std::string _selectedBrowser = ""; // Currently selected browser
// Fading
Transparency _goal = Transparency::Opaque;
int _uniqueIdentifierCounter = 0;
// Flags
bool _isCameraInSolarSystem = true; // Visualization modes
bool _isFading = false;
// Mouse interaction
glm::vec2 _mousePosition; // Current mouse position in screen space coordinates
glm::vec2 _startMousePosition;
glm::vec2 _startDragPosition;
glm::dvec3 _startTargetPosition;
// Animation of rotation of camera to look at coordinate galactic coordinates
skybrowser::Animation<glm::dvec3> _cameraRotation =
@@ -135,6 +125,10 @@ private:
// Data handler for the image collections
std::unique_ptr<WwtDataHandler> _dataHandler;
// Callbacks for tiggering topic
int _nextCallbackHandle = 0;
std::vector<std::pair<CallbackHandle, CallbackFunction>> _preSyncCallbacks;
};
} // namespace openspace

View File

@@ -27,6 +27,7 @@
#include <modules/skybrowser/include/utility.h>
#include <modules/skybrowser/include/targetbrowserpair.h>
#include <modules/skybrowser/include/wwtdatahandler.h>
#include <openspace/events/eventengine.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/windowdelegate.h>
@@ -44,21 +45,21 @@ namespace {
*/
[[codegen::luawrap]] void selectImage(int imageIndex) {
using namespace openspace;
// Load image
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
if (module->isCameraInSolarSystem()) {
TargetBrowserPair* selected = module->getPair(module->selectedBrowserId());
TargetBrowserPair* selected = module->pair(module->selectedBrowserId());
if (selected) {
const ImageData& image = module->getWwtDataHandler()->getImage(imageIndex);
// Load image into browser
std::string str = image.name;
// Check if character is ASCII - if it isn't, remove
str.erase(
std::remove_if(
str.begin(), str.end(),
[](char c) {
// Check if character is ASCII - if it isn't, remove
return c < 0 || c >= 128;
}
),
@@ -84,7 +85,7 @@ namespace {
*/
[[codegen::luawrap]] void setHoverCircle(std::string identifier) {
using namespace openspace;
SceneGraphNode* circle = global::renderEngine->scene()->sceneGraphNode(identifier);
global::moduleEngine->module<SkyBrowserModule>()->setHoverCircle(circle);
}
@@ -94,8 +95,8 @@ namespace {
*/
[[codegen::luawrap]] void moveCircleToHoverImage(int imageIndex) {
using namespace openspace;
global::moduleEngine->module<SkyBrowserModule>()->moveHoverCircle(imageIndex);
global::moduleEngine->module<SkyBrowserModule>()->moveHoverCircle(imageIndex, false);
}
/**
@@ -103,17 +104,14 @@ namespace {
*/
[[codegen::luawrap]] void disableHoverCircle() {
using namespace openspace;
global::moduleEngine->module<SkyBrowserModule>()->disableHoverCircle();
global::moduleEngine->module<SkyBrowserModule>()->disableHoverCircle(false);
}
/**
* Takes an identifier to a sky browser or a sky target, an image index and the order
* which it should have in the selected image list. The image is then changed to have this
* order.
* \param id Identifier
* \param i Image index
* \param order Order of image
*/
[[codegen::luawrap]] void setImageLayerOrder(std::string identifier, int imageIndex,
int imageOrder)
@@ -121,7 +119,7 @@ namespace {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->setImageOrder(imageIndex, imageOrder);
}
@@ -133,20 +131,17 @@ namespace {
*/
[[codegen::luawrap]] void loadImagesToWWT(std::string identifier) {
using namespace openspace;
// Load images from url
LINFO("Connection established to WorldWide Telescope application in " + identifier);
LINFO("Loading image collections to " + identifier);
// Load the collections here because we know that the browser can execute javascript
std::string root = "https://raw.githubusercontent.com/WorldWideTelescope/"
"wwt-web-client/master/assets/webclient-explore-root.wtml";
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->hideChromeInterface(true);
pair->loadImageCollection(root);
pair->hideChromeInterface();
pair->loadImageCollection(module->wwtImageCollectionUrl());
}
}
@@ -156,7 +151,7 @@ namespace {
*/
[[codegen::luawrap]] void startSetup() {
using namespace openspace;
// This is called when the sky_browser website is connected to OpenSpace
// Set all border colors to the border color in the master node
if (global::windowDelegate->isMaster()) {
@@ -189,7 +184,7 @@ namespace {
*/
[[codegen::luawrap]] void sendOutIdsToBrowsers() {
using namespace openspace;
// This is called when the sky_browser website is connected to OpenSpace
// Send out identifiers to the browsers
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
@@ -207,13 +202,12 @@ namespace {
*/
[[codegen::luawrap]] void initializeBrowser(std::string identifier) {
using namespace openspace;
// Initialize browser with ID and its corresponding target
LINFO("Initializing sky browser " + identifier);
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->setIsSyncedWithWwt(true);
pair->initialize();
}
}
@@ -234,6 +228,17 @@ namespace {
module->addTargetBrowserPair(targetId, browserId);
}
/**
* Returns the AAS WorldWide Telescope image collection url.
*/
[[codegen::luawrap]] ghoul::Dictionary getWwtImageCollectionUrl() {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
ghoul::Dictionary url;
url.setValue("url", module->wwtImageCollectionUrl());
return url;
}
/**
* Returns a list of all the loaded AAS WorldWide Telescope images that have been loaded.
* Each image has a name, thumbnail url, equatorial spherical coordinates RA and Dec,
@@ -242,17 +247,14 @@ namespace {
*/
[[codegen::luawrap]] ghoul::Dictionary getListOfImages() {
using namespace openspace;
// Send image list to GUI
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
std::string url = module->wwtImageCollectionUrl();
// If no data has been loaded yet, download the data from the web!
if (module->nLoadedImages() == 0) {
std::string root = "https://raw.githubusercontent.com/WorldWideTelescope/"
"wwt-web-client/master/assets/webclient-explore-root.wtml";
std::filesystem::path directory = absPath("${MODULE_SKYBROWSER}/wwtimagedata/");
module->loadImages(root, directory);
module->loadImages(url, directory);
}
// Create Lua table to send to the GUI
@@ -285,11 +287,11 @@ namespace {
/**
* Returns a table of data regarding the current view and the sky browsers and targets.
* \return Dictionary of data regarding the current targets
* returns a table of data regarding the current targets.
*/
[[codegen::luawrap]] ghoul::Dictionary getTargetData() {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
ghoul::Dictionary data;
@@ -323,16 +325,6 @@ namespace {
for (const std::unique_ptr<TargetBrowserPair>& pair : pairs) {
std::string id = pair->browserId();
// Convert deque to vector so ghoul can read it
std::vector<int> selectedImagesVector;
const std::deque<int> selectedImages = pair->selectedImages();
std::for_each(
selectedImages.begin(),
selectedImages.end(),
[&](int i) {
selectedImagesVector.push_back(i);
}
);
glm::dvec2 spherical = pair->targetDirectionEquatorial();
glm::dvec3 cartesian = skybrowser::sphericalToCartesian(spherical);
@@ -342,20 +334,19 @@ namespace {
target.setValue("id", id);
target.setValue("name", pair->browserGuiName());
target.setValue("FOV", static_cast<double>(pair->verticalFov()));
target.setValue("selectedImages", selectedImagesVector);
target.setValue("selectedImages", pair->selectedImages());
target.setValue("cartesianDirection", cartesian);
target.setValue("ra", spherical.x);
target.setValue("dec", spherical.y);
target.setValue("roll", pair->targetRoll());
target.setValue("color", pair->borderColor());
target.setValue("size", glm::dvec2(pair->size()));
std::vector<std::pair<std::string, glm::dvec3>> copies = pair->renderCopies();
std::vector<std::pair<std::string, glm::dvec3>> copies = pair->displayCopies();
ghoul::Dictionary copiesData;
for (size_t i = 0; i < copies.size(); i++) {
copiesData.setValue(copies[i].first, copies[i].second);
}
// Set table for the current target
target.setValue("renderCopies", copiesData);
target.setValue("displayCopies", copiesData);
data.setValue(id, target);
}
}
@@ -369,7 +360,7 @@ namespace {
*/
[[codegen::luawrap]] void adjustCamera(std::string id) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
if (module->isCameraInSolarSystem()) {
module->lookAtTarget(id);
@@ -384,9 +375,9 @@ namespace {
float opacity)
{
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->setImageOpacity(imageIndex, opacity);
}
@@ -398,9 +389,9 @@ namespace {
*/
[[codegen::luawrap]] void centerTargetOnScreen(std::string identifier) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->centerTargetOnScreen();
}
@@ -412,7 +403,7 @@ namespace {
*/
[[codegen::luawrap]] void setSelectedBrowser(std::string identifier) {
using namespace openspace;
global::moduleEngine->module<SkyBrowserModule>()->setSelectedBrowser(identifier);
}
@@ -421,20 +412,20 @@ namespace {
*/
[[codegen::luawrap]] void createTargetBrowserPair() {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
int noOfPairs = module->nPairs();
std::string nameBrowser = "Sky Browser " + std::to_string(noOfPairs);
std::string nameTarget = "Sky Target " + std::to_string(noOfPairs);
std::string idBrowser = "SkyBrowser" + std::to_string(noOfPairs);
std::string idTarget = "SkyTarget" + std::to_string(noOfPairs);
int uniqueIdentifier = module->uniqueIdentifierCounter();
std::string nameBrowser = "Sky Browser " + std::to_string(uniqueIdentifier);
std::string nameTarget = "Sky Target " + std::to_string(uniqueIdentifier);
std::string idBrowser = "SkyBrowser" + std::to_string(uniqueIdentifier);
std::string idTarget = "SkyTarget" + std::to_string(uniqueIdentifier);
// Determine starting point on screen for the target
glm::vec3 positionBrowser = glm::vec3(-3.f, -3.f, -2.1f);
glm::vec3 positionBrowser = glm::vec3(0.f, 0.f, -2.1f);
glm::vec3 positionTarget = glm::vec3(0.9f, 0.4f, -2.1f);
glm::dvec3 galacticTarget = skybrowser::localCameraToGalactic(positionTarget);
std::string guiPath = "/Sky Browser";
std::string url = "https://data.openspaceproject.com/dist/skybrowser/page/";
std::string url = "http://wwt.openspaceproject.com/1/openspace/";
double fov = 70.0;
double size = skybrowser::sizeFromFov(fov, galacticTarget);
@@ -445,7 +436,7 @@ namespace {
"Url = '" + url + "',"
"FaceCamera = false,"
"CartesianPosition = " + ghoul::to_string(positionBrowser) +
"}";
"}";
const std::string target = "{"
"Identifier = '" + idTarget + "',"
@@ -454,10 +445,10 @@ namespace {
"Transform = {"
"Translation = {"
"Type = 'StaticTranslation',"
"Position = {"
+ std::to_string(galacticTarget.x) + ", "
+ std::to_string(galacticTarget.y) + ", "
+ std::to_string(galacticTarget.z) + ", "
"Position = {" +
std::to_string(galacticTarget.x) + ", " +
std::to_string(galacticTarget.y) + ", " +
std::to_string(galacticTarget.z) + ", " +
"},"
"},"
"Rotation = {"
@@ -475,7 +466,7 @@ namespace {
"Opacity = 0.99"
"},"
"GUI = {"
"Name = 'Sky Target', "
"Name = '" + nameTarget + "', "
"Path = '/SkyBrowser', "
"}"
"}";
@@ -507,9 +498,9 @@ namespace {
*/
[[codegen::luawrap]] void removeTargetBrowserPair(std::string identifier) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* found = module->getPair(identifier);
TargetBrowserPair* found = module->pair(identifier);
if (found) {
std::string browser = found->browserId();
std::string target = found->targetNodeId();
@@ -540,7 +531,7 @@ namespace {
float translationY)
{
using namespace openspace;
ScreenSpaceRenderable* renderable =
global::renderEngine->screenSpaceRenderable(identifier);
@@ -559,11 +550,11 @@ namespace {
int imageIndex)
{
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
const ImageData& image = module->getWwtDataHandler()->getImage(imageIndex);
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->removeSelectedImage(imageIndex);
}
@@ -578,9 +569,9 @@ namespace {
double declination)
{
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->setEquatorialAim(glm::dvec2(rightAscension, declination));
}
@@ -594,9 +585,9 @@ namespace {
float verticalFieldOfView)
{
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->setVerticalFov(verticalFieldOfView);
}
@@ -608,9 +599,9 @@ namespace {
*/
[[codegen::luawrap]] void scrollOverBrowser(std::string identifier, float scroll) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->setVerticalFovWithScroll(scroll);
}
@@ -624,9 +615,9 @@ namespace {
int blue)
{
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->setBorderColor(glm::ivec3(red, green, blue));
}
@@ -636,46 +627,45 @@ namespace {
* Sets the screen space size of the sky browser to the numbers specified by the input
* [x, y].
*/
[[codegen::luawrap]] void setScreenSpaceSize(std::string identifier, float sizeX,
float sizeY)
[[codegen::luawrap]] void setBrowserRatio(std::string identifier, float ratio)
{
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->setScreenSpaceSize(glm::vec2(sizeX, sizeY));
pair->setBrowserRatio(ratio);
}
}
/**
* Takes an identifier to a sky browser and adds a rendered copy to it.
* \param raePosition Position in radius, azimuth, elevation coordinates
* \param nCopies Number of copies
* Takes an identifier to a sky browser and adds a rendered copy to it. The first argument
* is the position of the first copy. The position is in RAE or Cartesian coordinates,
* depending on if 'Use Radius Azimuth Elevation' is checked. The second argument is the
* number of copies. If RAE is used, they will be evenly spread out on the azimuth.
*/
[[codegen::luawrap]] void addRenderCopy(std::string identifier,
int numberOfCopies = 1,
glm::vec3 radiusAzimuthElevationPosition = glm::vec3(2.1f, 0.f, 0.f))
[[codegen::luawrap]] void addDisplayCopy(std::string identifier, int numberOfCopies = 1,
glm::vec3 position = glm::vec3(2.1f, 0.f, 0.f))
{
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->browser()->addRenderCopy(radiusAzimuthElevationPosition, numberOfCopies);
pair->browser()->addDisplayCopy(position, numberOfCopies);
}
}
/**
* Takes an identifier to a sky browser and removes the latest added rendered copy to it.
*/
[[codegen::luawrap]] void removeRenderCopy(std::string identifier) {
[[codegen::luawrap]] void removeDisplayCopy(std::string identifier) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->browser()->removeRenderCopy();
pair->browser()->removeDisplayCopy();
}
}
@@ -684,16 +674,18 @@ namespace {
*/
[[codegen::luawrap]] void startFinetuningTarget(std::string identifier) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
pair->startFinetuningTarget();
}
}
/**
* Finetunes the target depending on a mouse drag. rendered copy to it.
* Finetunes the target depending on a mouse drag. rendered copy to it. First argument
* is the identifier of the sky browser, second is the start position of the drag
* and third is the end position of the drag.
*/
[[codegen::luawrap]] void finetuneTargetPosition(std::string identifier,
glm::vec2 startPosition,
@@ -702,7 +694,7 @@ namespace {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(identifier);
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
glm::vec2 startScreenSpace = skybrowser::pixelToScreenSpace2d(startPosition);
glm::vec2 endScreenSpace = skybrowser::pixelToScreenSpace2d(endPosition);
@@ -711,6 +703,70 @@ namespace {
}
}
/**
* Sets the image collection as loaded in the sky browser. Takes an identifier to the sky
* browser.
*/
[[codegen::luawrap]] void loadingImageCollectionComplete(std::string identifier) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->pair(identifier);
if (pair) {
LINFO("Image collection is loaded in Screen Space Sky Browser " + identifier);
pair->setImageCollectionIsLoaded(true);
// Add all selected images to WorldWide Telescope
const std::vector<int>& images = pair->selectedImages();
std::for_each(
images.rbegin(), images.rend(),
[&](int index) {
const ImageData& image = module->getWwtDataHandler()->getImage(index);
// Index of image is used as layer ID as it is unique in the image data set
pair->browser()->addImageLayerToWwt(image.imageUrl, index);
}
);
}
}
/**
* Show or hide all targets and browsers. Takes a boolean that sets it to either be shown
* or not.
*/
[[codegen::luawrap]] void showAllTargetsAndBrowsers(bool show) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
const std::vector<std::unique_ptr<TargetBrowserPair>>& pairs = module->getPairs();
for (const std::unique_ptr<TargetBrowserPair>& pair : pairs) {
pair->setEnabled(show);
}
}
/**
* Point spacecraft to the equatorial coordinates the target points to. Takes an
* identifier to a sky browser.
*/
[[codegen::luawrap]] void pointSpaceCraft(std::string identifier) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->pair(identifier);
glm::dvec2 equatorial = pair->targetDirectionEquatorial();
global::eventEngine->publishEvent<events::EventPointSpacecraft>(
equatorial.x,
equatorial.y,
module->spaceCraftAnimationTime()
);
}
/**
* Stop animations. Takes an identifier to a sky browser.
*/
[[codegen::luawrap]] void stopAnimations(std::string identifier) {
using namespace openspace;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->pair(identifier);
pair->stopAnimations();
}
#include "skybrowsermodule_lua_codegen.cpp"
} // namespace

View File

@@ -92,7 +92,7 @@ Browser::Browser(const ghoul::Dictionary& dictionary)
if (dictionary.hasValue<std::string>(UrlInfo.identifier)) {
_url = dictionary.value<std::string>(UrlInfo.identifier);
}
// Handle target dimension property
const Parameters p = codegen::bake<Parameters>(dictionary);
_url = p.url.value_or(_url);

View File

@@ -63,21 +63,6 @@ namespace {
"be rendered in the target."
};
constexpr const openspace::properties::Property::PropertyInfo AnimationSpeedInfo = {
"AnimationSpeed",
"Animation Speed",
"The factor which is multiplied with the animation speed of the target."
};
constexpr const openspace::properties::Property::PropertyInfo AnimationThresholdInfo =
{
"AnimationThreshold",
"Animation Threshold",
"The threshold for when the target is determined to have appeared at its "
"destination. Angle in radians between the destination and the target position "
"in equatorial Cartesian coordinate system."
};
constexpr const openspace::properties::Property::PropertyInfo LineWidthInfo = {
"LineWidth",
"Line Width",
@@ -91,12 +76,6 @@ namespace {
// [[codegen::verbatim(RectangleThresholdInfo.description)]]
std::optional<float> rectangleThreshold;
// [[codegen::verbatim(AnimationSpeedInfo.description)]]
std::optional<double> animationSpeed;
// [[codegen::verbatim(AnimationThresholdInfo.description)]]
std::optional<float> animationThreshold;
// [[codegen::verbatim(LineWidthInfo.description)]]
std::optional<float> lineWidth;
};
@@ -106,29 +85,25 @@ namespace {
namespace openspace {
documentation::Documentation RenderableSkyTarget::Documentation() {
return codegen::doc<Parameters>("skybrowser_renderableskytarget");
}
RenderableSkyTarget::RenderableSkyTarget(const ghoul::Dictionary& dictionary)
: RenderablePlane(dictionary)
, _crossHairSize(crossHairSizeInfo, 2.f, 1.f, 10.f)
, _showRectangleThreshold(RectangleThresholdInfo, 5.f, 0.1f, 70.f)
, _stopAnimationThreshold(AnimationThresholdInfo, 5.0f, 1.f, 10.f)
, _animationSpeed(AnimationSpeedInfo, 5.0, 0.1, 10.0)
, _lineWidth(LineWidthInfo, 13.f, 1.f, 100.f)
, _borderColor(220, 220, 220)
{
// Handle target dimension property
const Parameters p = codegen::bake<Parameters>(dictionary);
_crossHairSize = p.crossHairSize.value_or(_crossHairSize);
addProperty(_crossHairSize);
_showRectangleThreshold = p.rectangleThreshold.value_or(_showRectangleThreshold);
addProperty(_showRectangleThreshold);
_stopAnimationThreshold = p.crossHairSize.value_or(_stopAnimationThreshold);
addProperty(_stopAnimationThreshold);
_animationSpeed = p.animationSpeed.value_or(_animationSpeed);
addProperty(_animationSpeed);
addProperty(_lineWidth);
}
@@ -166,15 +141,15 @@ void RenderableSkyTarget::render(const RenderData& data, RendererTasks&) {
ZoneScoped
const bool showRectangle = _verticalFov > _showRectangleThreshold;
glm::vec4 color = { glm::vec3(_borderColor) / 255.f, _opacity.value() };
glm::vec4 color = { glm::vec3(_borderColor) / 255.f, 1.0 };
_shader->activate();
_shader->setUniform("opacity", _opacity);
_shader->setUniform("opacity", opacity());
_shader->setUniform("crossHairSize", _crossHairSize);
_shader->setUniform("showRectangle", showRectangle);
_shader->setUniform("lineWidth", _lineWidth * 0.0001f);
_shader->setUniform("dimensions", _dimensions);
_shader->setUniform("ratio", _ratio);
_shader->setUniform("lineColor", color);
_shader->setUniform("fov", static_cast<float>(_verticalFov));
@@ -239,10 +214,10 @@ void RenderableSkyTarget::render(const RenderData& data, RendererTasks&) {
_shader->deactivate();
}
void RenderableSkyTarget::setDimensions(glm::vec2 dimensions) {
void RenderableSkyTarget::setRatio(float ratio) {
// To avoid flooring of the size of the target, multiply by factor of 100
// Object size is really the pixel size so this calculation is not exact
_dimensions = glm::ivec2(dimensions * 100.f);
_ratio = ratio;
}
void RenderableSkyTarget::highlight(const glm::ivec3& addition) {
@@ -253,22 +228,6 @@ void RenderableSkyTarget::removeHighlight(const glm::ivec3& removal) {
_borderColor -= removal;
}
float RenderableSkyTarget::opacity() const {
return _opacity;
}
double RenderableSkyTarget::animationSpeed() const {
return _animationSpeed;
}
double RenderableSkyTarget::stopAnimationThreshold() const {
return _stopAnimationThreshold * 0.0001;
}
void RenderableSkyTarget::setOpacity(float opacity) {
_opacity = opacity;
}
void RenderableSkyTarget::setVerticalFov(double fov) {
_verticalFov = fov;
}

View File

@@ -48,32 +48,38 @@ namespace {
"frame rate."
};
constexpr const openspace::properties::Property::PropertyInfo RenderCopyInfo = {
"RenderCopy",
"RAE Position Of A Copy Of The Sky Browser",
"Render a copy of this sky browser at an additional position. This copy will not "
"be interactive. The position is in RAE (Radius, Azimuth, Elevation) coordinates."
constexpr const openspace::properties::Property::PropertyInfo DisplayCopyInfo = {
"DisplayCopy",
"Display Copy Position",
"Display a copy of this sky browser at an additional position. This copy will not "
"be interactive. The position is in RAE (Radius, Azimuth, Elevation) coordinates "
"or Cartesian, depending on if the browser uses RAE or Cartesian coordinates."
};
constexpr const openspace::properties::Property::PropertyInfo RenderOnMasterInfo = {
"RenderOnlyOnMaster",
"Render Only On Master",
"Render the interactive sky browser only on the master node (this setting won't "
"affect the copies). This setting allows mouse interactions in a dome "
"environment."
constexpr const openspace::properties::Property::PropertyInfo DisplayCopyShowInfo = {
"ShowDisplayCopy",
"Show Display Copy",
"Show the display copy."
};
constexpr const openspace::properties::Property::PropertyInfo IsHiddenInfo = {
"IsHidden",
"Is Hidden",
"If checked, the browser will be not be displayed. If it is not checked, it will "
"be."
};
struct [[codegen::Dictionary(ScreenSpaceSkyBrowser)]] Parameters {
// [[codegen::verbatim(TextureQualityInfo.description)]]
std::optional<float> textureQuality;
// [[codegen::verbatim(RenderOnMasterInfo.description)]]
std::optional<bool> renderOnlyOnMaster;
// [[codegen::verbatim(IsHiddenInfo.description)]]
std::optional<bool> isHidden;
};
#include "screenspaceskybrowser_codegen.cpp"
glm::ivec3 randomBorderColor(glm::ivec3 highlight) {
glm::ivec3 randomBorderColor() {
// Generate a random border color with sufficient lightness and a n
std::random_device rd;
// Hue is in the unit degrees [0, 360]
@@ -82,13 +88,8 @@ namespace {
// Value in saturation are in the unit percent [0,1]
float value = 0.9f; // Brightness
float saturation = 0.5f;
glm::ivec3 rgbColor;
glm::ivec3 highlighted;
do {
glm::vec3 hsvColor = glm::vec3(hue(rd), saturation, value);
rgbColor = glm::ivec3(glm::rgbColor(hsvColor) * 255.f);
highlighted = rgbColor + highlight;
} while (highlighted.x < 255 && highlighted.y < 255 && highlighted.z < 255);
glm::vec3 hsvColor = glm::vec3(hue(rd), saturation, value);
glm::ivec3 rgbColor = glm::ivec3(glm::rgbColor(hsvColor) * 255.f);
return rgbColor;
}
@@ -96,41 +97,60 @@ namespace {
namespace openspace {
documentation::Documentation ScreenSpaceSkyBrowser::Documentation() {
return codegen::doc<Parameters>("skybrowser_screenspaceskybrowser");
}
ScreenSpaceSkyBrowser::ScreenSpaceSkyBrowser(const ghoul::Dictionary& dictionary)
: ScreenSpaceRenderable(dictionary)
, WwtCommunicator(dictionary)
, _textureQuality(TextureQualityInfo, 0.5f, 0.25f, 1.f)
, _renderOnlyOnMaster(RenderOnMasterInfo, false)
, _isHidden(IsHiddenInfo, true)
{
_identifier = makeUniqueIdentifier(_identifier);
// Handle target dimension property
const Parameters p = codegen::bake<Parameters>(dictionary);
_textureQuality = p.textureQuality.value_or(_textureQuality);
_renderOnlyOnMaster = p.renderOnlyOnMaster.value_or(_renderOnlyOnMaster);
_isHidden = p.isHidden.value_or(_isHidden);
addProperty(_isHidden);
addProperty(_url);
addProperty(_browserPixeldimensions);
addProperty(_reload);
addProperty(_textureQuality);
addProperty(_renderOnlyOnMaster);
_textureQuality.onChange([this]() { _textureDimensionsIsDirty = true; });
// Ensure that the browser is placed at the z-coordinate of the screen space plane
glm::vec2 screenPosition = _cartesianPosition.value();
_cartesianPosition = glm::vec3(screenPosition, skybrowser::ScreenSpaceZ);
if (global::windowDelegate->isMaster()) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
_borderColor = randomBorderColor(module->highlight());
_borderColor = randomBorderColor();
}
_scale = _size.y * 0.5f;
_scale.onChange([this]() {
updateTextureResolution();
});
_useRadiusAzimuthElevation.onChange(
[this]() {
std::for_each(
_displayCopies.begin(),
_displayCopies.end(),
[this](std::unique_ptr<properties::Vec3Property>& copy) {
if (_useRadiusAzimuthElevation) {
*copy = sphericalToRae(cartesianToSpherical(copy->value()));
}
else {
*copy = sphericalToCartesian(raeToSpherical(copy->value()));
}
});
});
}
ScreenSpaceSkyBrowser::~ScreenSpaceSkyBrowser() {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
if (module && module->getPair(identifier())) {
if (module && module->pair(identifier())) {
module->removeTargetBrowserPair(identifier());
}
}
@@ -157,10 +177,18 @@ glm::dvec2 ScreenSpaceSkyBrowser::fineTuneVector(const glm::dvec2& drag) {
return result;
}
bool ScreenSpaceSkyBrowser::isInitialized() const {
return _isInitialized;
}
void ScreenSpaceSkyBrowser::setIdInBrowser() const {
WwtCommunicator::setIdInBrowser(identifier());
}
void ScreenSpaceSkyBrowser::setIsInitialized(bool isInitialized) {
_isInitialized = isInitialized;
}
void ScreenSpaceSkyBrowser::updateTextureResolution() {
// Scale texture depending on the height of the window
// Set texture size to the actual pixel size it covers
@@ -168,8 +196,7 @@ void ScreenSpaceSkyBrowser::updateTextureResolution() {
// If the scale is 1, it covers half the window. Hence multiplication with 2
float newResY = pixels.y * 2.f * _scale;
float ratio = _size.x / _size.y;
float newResX = newResY * ratio;
float newResX = newResY * _ratio;
glm::vec2 newSize = glm::vec2(newResX , newResY) * _textureQuality.value();
_browserPixeldimensions = glm::ivec2(newSize);
@@ -177,55 +204,63 @@ void ScreenSpaceSkyBrowser::updateTextureResolution() {
_objectSize = glm::ivec3(_texture->dimensions());
}
void ScreenSpaceSkyBrowser::addRenderCopy(const glm::vec3& raePosition, int nCopies) {
size_t start = _renderCopies.size();
void ScreenSpaceSkyBrowser::addDisplayCopy(const glm::vec3& raePosition, int nCopies) {
size_t start = _displayCopies.size();
for (int i = 0; i < nCopies; i++) {
openspace::properties::Property::PropertyInfo info = RenderCopyInfo;
openspace::properties::Property::PropertyInfo info = DisplayCopyInfo;
float azimuth = i * glm::two_pi<float>() / nCopies;
glm::vec3 position = raePosition + glm::vec3(0.f, azimuth, 0.f);
std::string id = "RenderCopy" + std::to_string(start + i);
info.identifier = id.c_str();
_renderCopies.push_back(
std::string idDisplayCopy = "DisplayCopy" + std::to_string(start + i);
info.identifier = idDisplayCopy.c_str();
_displayCopies.push_back(
std::make_unique<properties::Vec3Property>(
info,
position,
glm::vec3(0.f, -glm::pi<float>(), -glm::half_pi<float>()),
glm::vec3(10.f, glm::pi<float>(), glm::half_pi<float>())
glm::vec3(-4.f, -4.f, -10.f),
glm::vec3(4.f, 4.f, glm::half_pi<float>())
)
);
addProperty(_renderCopies.back().get());
openspace::properties::Property::PropertyInfo showInfo = DisplayCopyShowInfo;
std::string idDisplayCopyVisible = "ShowDisplayCopy" + std::to_string(start + i);
showInfo.identifier = idDisplayCopyVisible.c_str();
_showDisplayCopies.push_back(
std::make_unique<properties::BoolProperty>(
showInfo,
true
)
);
addProperty(_displayCopies.back().get());
addProperty(_showDisplayCopies.back().get());
}
}
void ScreenSpaceSkyBrowser::removeRenderCopy() {
if (!_renderCopies.empty()) {
removeProperty(_renderCopies.back().get());
_renderCopies.pop_back();
void ScreenSpaceSkyBrowser::removeDisplayCopy() {
if (!_displayCopies.empty()) {
removeProperty(_displayCopies.back().get());
_displayCopies.pop_back();
}
}
std::vector<std::pair<std::string, glm::dvec3>>
ScreenSpaceSkyBrowser::renderCopies() const
ScreenSpaceSkyBrowser::displayCopies() const
{
std::vector<std::pair<std::string, glm::dvec3>> vec;
std::for_each(
_renderCopies.begin(),
_renderCopies.end(),
[&](const std::unique_ptr<properties::Vec3Property>& copy) {
std::pair<std::string, glm::dvec3> pair = {
copy.get()->identifier(),
glm::dvec3(copy.get()->value())
};
vec.push_back(pair);
}
);
using vec3Property = std::unique_ptr<properties::Vec3Property>;
for (const vec3Property& copy : _displayCopies) {
vec.push_back({ copy->identifier(), copy->value() });
}
return vec;
}
void ScreenSpaceSkyBrowser::moveRenderCopy(int i, glm::vec3 raePosition) {
if (i < static_cast<int>(_renderCopies.size()) && i >= 0) {
*_renderCopies[i].get() = raePosition;
std::vector<std::pair<std::string, bool>>
ScreenSpaceSkyBrowser::showDisplayCopies() const
{
std::vector<std::pair<std::string, bool>> vec;
using boolProperty = std::unique_ptr<properties::BoolProperty>;
for (const boolProperty& copy : _showDisplayCopies) {
vec.push_back({copy->identifier(), copy->value()});
}
return vec;
}
bool ScreenSpaceSkyBrowser::deinitializeGL() {
@@ -237,12 +272,7 @@ bool ScreenSpaceSkyBrowser::deinitializeGL() {
void ScreenSpaceSkyBrowser::render() {
WwtCommunicator::render();
// If the sky browser only should be rendered on master, don't use the
// global rotation
if (_renderOnlyOnMaster && global::windowDelegate->isMaster()) {
draw(translationMatrix() * localRotationMatrix() * scaleMatrix());
}
else if (!_renderOnlyOnMaster) {
if (!_isHidden) {
draw(
globalRotationMatrix() *
translationMatrix() *
@@ -251,20 +281,29 @@ void ScreenSpaceSkyBrowser::render() {
);
}
// Render a copy that is not interactive
for (const std::unique_ptr<properties::Vec3Property>& copy : _renderCopies) {
glm::vec3 spherical = sphericalToCartesian(raeToSpherical(copy.get()->value()));
glm::mat4 localRotation = glm::inverse(glm::lookAt(
glm::vec3(0.f),
glm::normalize(spherical),
glm::vec3(0.f, 1.f, 0.f)
));
draw(
globalRotationMatrix() *
glm::translate(glm::mat4(1.f), spherical) *
localRotation *
scaleMatrix()
);
// Render the display copies
for (size_t i = 0; i < _displayCopies.size(); i++) {
if (_showDisplayCopies[i]->value()) {
glm::vec3 coordinates = _displayCopies[i]->value();
if (_useRadiusAzimuthElevation) {
coordinates = sphericalToCartesian(raeToSpherical(coordinates));
}
glm::mat4 localRotation = glm::mat4(1.f);
if (_faceCamera) {
localRotation = glm::inverse(glm::lookAt(
glm::vec3(0.f),
glm::normalize(coordinates),
glm::vec3(0.f, 1.f, 0.f)
));
}
draw(
globalRotationMatrix() *
glm::translate(glm::mat4(1.f), coordinates) *
localRotation *
scaleMatrix()
);
}
}
}
@@ -276,9 +315,9 @@ void ScreenSpaceSkyBrowser::update() {
updateTextureResolution();
_textureDimensionsIsDirty = false;
}
if (_sizeIsDirty) {
updateScreenSpaceSize();
_sizeIsDirty = false;
if (_ratioIsDirty) {
updateTextureResolution();
_ratioIsDirty = false;
}
WwtCommunicator::update();
@@ -289,7 +328,7 @@ void ScreenSpaceSkyBrowser::setVerticalFovWithScroll(float scroll) {
// Make scroll more sensitive the smaller the FOV
double x = _verticalFov;
double zoomFactor = atan(x / 50.0) + exp(x / 40.0) - 0.99999999999999999999999999999;
double zoom = scroll > 0.0 ? -zoomFactor : zoomFactor;
double zoom = scroll > 0.0 ? zoomFactor : -zoomFactor;
_verticalFov = std::clamp(_verticalFov + zoom, 0.0, 70.0);
}
@@ -313,22 +352,13 @@ void ScreenSpaceSkyBrowser::setOpacity(float opacity) {
_opacity = opacity;
}
void ScreenSpaceSkyBrowser::setScreenSpaceSize(glm::vec2 newSize) {
_size = std::move(newSize);
_sizeIsDirty = true;
}
void ScreenSpaceSkyBrowser::updateScreenSpaceSize() {
_scale = abs(_size.y) * 0.5f;
updateTextureResolution();
void ScreenSpaceSkyBrowser::setRatio(float ratio) {
_ratio = ratio;
_ratioIsDirty = true;
}
float ScreenSpaceSkyBrowser::opacity() const {
return _opacity;
}
glm::vec2 ScreenSpaceSkyBrowser::size() const {
return _size;
}
} // namespace openspace

View File

@@ -63,16 +63,6 @@ void TargetBrowserPair::setImageOrder(int i, int order) {
_browser->setImageOrder(i, order);
}
void TargetBrowserPair::removeHighlight(const glm::ivec3& color) {
_targetRenderable->removeHighlight(color);
_browser->removeHighlight(color);
}
void TargetBrowserPair::highlight(const glm::ivec3& color) {
_browser->highlight(color);
_targetRenderable->highlight(color);
}
void TargetBrowserPair::aimTargetGalactic(glm::dvec3 direction) {
std::string id = _targetNode->identifier();
glm::dvec3 positionCelestial = glm::normalize(direction) *
@@ -114,7 +104,7 @@ void TargetBrowserPair::fineTuneTarget(const glm::vec2& startMouse,
}
void TargetBrowserPair::synchronizeAim() {
if (!_moveTarget.isAnimating()) {
if (!_targetAnimation.isAnimating() && _browser->isInitialized()) {
_browser->setEquatorialAim(targetDirectionEquatorial());
_browser->setTargetRoll(targetRoll());
_targetRenderable->setVerticalFov(_browser->verticalFov());
@@ -123,7 +113,7 @@ void TargetBrowserPair::synchronizeAim() {
void TargetBrowserPair::setEnabled(bool enable) {
_browser->setEnabled(enable);
_targetRenderable->property("Enabled")->set(false);
_targetRenderable->property("Enabled")->set(enable);
}
void TargetBrowserPair::setOpacity(float opacity) {
@@ -137,8 +127,11 @@ bool TargetBrowserPair::isEnabled() const {
void TargetBrowserPair::initialize() {
_targetRenderable->setColor(_browser->borderColor());
_targetRenderable->setDimensions(_browser->screenSpaceDimensions());
glm::vec2 dim = _browser->screenSpaceDimensions();
_targetRenderable->setRatio(dim.x / dim.y);
_browser->updateBorderColor();
_browser->hideChromeInterface();
_browser->setIsInitialized(true);
}
glm::ivec3 TargetBrowserPair::borderColor() const {
@@ -172,31 +165,70 @@ std::string TargetBrowserPair::targetNodeId() const {
return _targetNode->identifier();
}
glm::vec2 TargetBrowserPair::size() const {
return _browser->size();
float TargetBrowserPair::browserRatio() const {
return _browser->browserRatio();
}
double TargetBrowserPair::verticalFov() const {
return _browser->verticalFov();
}
const std::deque<int>& TargetBrowserPair::selectedImages() const {
return _browser->getSelectedImages();
std::vector<int> TargetBrowserPair::selectedImages() const {
return _browser->selectedImages();
}
ghoul::Dictionary TargetBrowserPair::dataAsDictionary() const {
glm::dvec2 spherical = targetDirectionEquatorial();
glm::dvec3 cartesian = skybrowser::sphericalToCartesian(spherical);
ghoul::Dictionary res;
res.setValue("id", browserId());
res.setValue("name", browserGuiName());
res.setValue("fov", static_cast<double>(verticalFov()));
res.setValue("ra", spherical.x);
res.setValue("dec", spherical.y);
res.setValue("roll", targetRoll());
res.setValue("color", borderColor());
res.setValue("cartesianDirection", cartesian);
res.setValue("ratio", static_cast<double>(browserRatio()));
res.setValue("isFacingCamera", isFacingCamera());
res.setValue("isUsingRae", isUsingRadiusAzimuthElevation());
res.setValue("selectedImages", selectedImages());
res.setValue("scale", static_cast<double>(_browser->scale()));
res.setValue("opacities", _browser->opacities());
std::vector<std::pair<std::string, glm::dvec3>> copies = displayCopies();
std::vector<std::pair<std::string, bool>> showCopies = _browser->showDisplayCopies();
ghoul::Dictionary copiesData;
for (size_t i = 0; i < copies.size(); i++) {
ghoul::Dictionary copy;
copy.setValue("position", copies[i].second);
copy.setValue("show", showCopies[i].second);
copy.setValue("idShowProperty", showCopies[i].first);
copiesData.setValue(copies[i].first, copy);
}
// Set table for the current target
res.setValue("displayCopies", copiesData);
return res;
}
void TargetBrowserPair::selectImage(const ImageData& image, int i) {
// Load image into browser
_browser->displayImage(image.imageUrl, i);
_browser->selectImage(image.imageUrl, i);
// If the image has coordinates, move the target
if (image.hasCelestialCoords) {
// Animate the target to the image coordinate position
// unlock();
glm::dvec3 galactic = skybrowser::equatorialToGalactic(image.equatorialCartesian);
startAnimation(galactic * skybrowser::CelestialSphereRadius, image.fov);
}
}
void TargetBrowserPair::addImageLayerToWwt(const std::string& url, int i) {
_browser->addImageLayerToWwt(url, i);
}
void TargetBrowserPair::removeSelectedImage(int i) {
_browser->removeSelectedImage(i);
}
@@ -209,8 +241,8 @@ void TargetBrowserPair::setImageOpacity(int i, float opacity) {
_browser->setImageOpacity(i, opacity);
}
void TargetBrowserPair::hideChromeInterface(bool shouldHide) {
_browser->hideChromeInterface(shouldHide);
void TargetBrowserPair::hideChromeInterface() {
_browser->hideChromeInterface();
}
void TargetBrowserPair::sendIdToBrowser() const {
@@ -221,12 +253,12 @@ void TargetBrowserPair::updateBrowserSize() {
_browser->updateBrowserSize();
}
std::vector<std::pair<std::string, glm::dvec3>> TargetBrowserPair::renderCopies() const {
return _browser->renderCopies();
std::vector<std::pair<std::string, glm::dvec3>> TargetBrowserPair::displayCopies() const {
return _browser->displayCopies();
}
void TargetBrowserPair::setIsSyncedWithWwt(bool isSynced) {
_browser->setIsSyncedWithWwt(isSynced);
bool TargetBrowserPair::isImageCollectionLoaded() {
return _browser->isImageCollectionLoaded();
}
void TargetBrowserPair::setVerticalFov(double vfov) {
@@ -235,7 +267,6 @@ void TargetBrowserPair::setVerticalFov(double vfov) {
}
void TargetBrowserPair::setEquatorialAim(const glm::dvec2& aim) {
_equatorialAim = aim;
aimTargetGalactic(
skybrowser::equatorialToGalactic(skybrowser::sphericalToCartesian(aim))
);
@@ -243,28 +274,31 @@ void TargetBrowserPair::setEquatorialAim(const glm::dvec2& aim) {
}
void TargetBrowserPair::setBorderColor(const glm::ivec3& color) {
_borderColor = color;
_targetRenderable->setColor(color);
_browser->setBorderColor(color);
}
void TargetBrowserPair::setScreenSpaceSize(const glm::vec2& dimensions) {
_browser->setScreenSpaceSize(dimensions);
_targetRenderable->setDimensions(dimensions);
void TargetBrowserPair::setBrowserRatio(float ratio) {
_browser->setRatio(ratio);
_targetRenderable->setRatio(ratio);
}
void TargetBrowserPair::setVerticalFovWithScroll(float scroll) {
_browser->setVerticalFovWithScroll(scroll);
}
void TargetBrowserPair::setImageCollectionIsLoaded(bool isLoaded) {
_browser->setImageCollectionIsLoaded(isLoaded);
}
void TargetBrowserPair::incrementallyAnimateToCoordinate() {
// Animate the target before the field of view starts to animate
if (_moveTarget.isAnimating()) {
aimTargetGalactic(_moveTarget.getNewValue());
if (_targetAnimation.isAnimating()) {
aimTargetGalactic(_targetAnimation.getNewValue());
}
else if (!_moveTarget.isAnimating() && _targetIsAnimating) {
else if (!_targetAnimation.isAnimating() && _targetIsAnimating) {
// Set the finished position
aimTargetGalactic(_moveTarget.getNewValue());
aimTargetGalactic(_targetAnimation.getNewValue());
_fovAnimation.start();
_targetIsAnimating = false;
}
@@ -275,10 +309,21 @@ void TargetBrowserPair::incrementallyAnimateToCoordinate() {
}
void TargetBrowserPair::startFading(float goal, float fadeTime) {
_fadeTarget = skybrowser::Animation(_targetRenderable->opacity(), goal, fadeTime);
_fadeBrowser = skybrowser::Animation(_browser->opacity(), goal, fadeTime);
_fadeTarget.start();
_fadeBrowser.start();
const std::string script = fmt::format(
"openspace.setPropertyValueSingle('Scene.{0}.Renderable.Fade', {2}, {3});"
"openspace.setPropertyValueSingle('ScreenSpace.{1}.Fade', {2}, {3});",
_targetNode->identifier(), _browser->identifier(), goal, fadeTime
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::RemoteScripting::Yes
);
}
void TargetBrowserPair::stopAnimations() {
_fovAnimation.stop();
_targetAnimation.stop();
}
void TargetBrowserPair::startAnimation(glm::dvec3 galacticCoords, double fovEnd) {
@@ -294,8 +339,8 @@ void TargetBrowserPair::startAnimation(glm::dvec3 galacticCoords, double fovEnd)
skybrowser::CelestialSphereRadius;
double targetSpeed = module->targetAnimationSpeed();
double angle = skybrowser::angleBetweenVectors(start, galacticCoords);
_moveTarget = skybrowser::Animation(start, galacticCoords, angle / targetSpeed);
_moveTarget.start();
_targetAnimation = skybrowser::Animation(start, galacticCoords, angle / targetSpeed);
_targetAnimation.start();
_targetIsAnimating = true;
}
@@ -307,9 +352,9 @@ void TargetBrowserPair::centerTargetOnScreen() {
startAnimation(viewDirection, currentFov);
}
double TargetBrowserPair::targetRoll() {
double TargetBrowserPair::targetRoll() const {
// To remove the lag effect when moving the camera while having a locked
// target, send the locked coordinates to wwt
// target, send the locked coordinates to wwt
glm::dvec3 normal = glm::normalize(
_targetNode->worldPosition() -
global::navigationHandler->camera()->positionVec3()
@@ -324,10 +369,6 @@ double TargetBrowserPair::targetRoll() {
return skybrowser::targetRoll(up, normal);
}
bool TargetBrowserPair::hasFinishedFading() const {
return !_fadeBrowser.isAnimating() && !_fadeTarget.isAnimating();
}
bool TargetBrowserPair::isFacingCamera() const {
return _browser->isFacingCamera();
}
@@ -344,15 +385,6 @@ ScreenSpaceSkyBrowser* TargetBrowserPair::browser() const {
return _browser;
}
void TargetBrowserPair::incrementallyFade() {
if (_fadeBrowser.isAnimating()) {
_browser->setOpacity(_fadeBrowser.getNewValue());
}
if (_fadeTarget.isAnimating()) {
_targetRenderable->setOpacity(_fadeTarget.getNewValue());
}
}
bool operator==(const TargetBrowserPair& lhs, const TargetBrowserPair& rhs) {
return lhs._targetNode == rhs._targetNode && lhs._browser == rhs._browser;
}

View File

@@ -28,6 +28,7 @@
#include <openspace/engine/globals.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/navigation/navigationhandler.h>
#include <ghoul/misc/easing.h>
#include <glm/gtx/vector_angle.hpp>
#include <cmath>
@@ -216,7 +217,7 @@ float Animation<float>::getNewValue() {
}
else {
float percentage = static_cast<float>(percentageSpent());
float diff = static_cast<float>((_goal - _start) * easeOutExpo(percentage));
float diff = static_cast<float>((_goal - _start) * ghoul::exponentialEaseOut(percentage));
return _start + diff;
}
}
@@ -227,7 +228,7 @@ double Animation<double>::getNewValue() {
}
else {
double percentage = percentageSpent();
double diff = (_goal - _start) * easeOutExpo(percentage);
double diff = (_goal - _start) * ghoul::exponentialEaseOut(percentage);
return _start + diff;
}
}
@@ -236,8 +237,8 @@ glm::dmat4 Animation<glm::dvec3>::getRotationMatrix() {
if (!isAnimating()) {
return glm::dmat4(1.0);
}
double percentage = easeInOutSine(percentageSpent());
double percentage = ghoul::sineEaseInOut(percentageSpent());
double increment = percentage - _lastPercentage;
_lastPercentage = percentage;
@@ -256,7 +257,7 @@ glm::dvec3 Animation<glm::dvec3>::getNewValue() {
glm::dmat4 rotMat = skybrowser::incrementalAnimationMatrix(
glm::normalize(_start),
glm::normalize(_goal),
easeOutExpo(percentageSpent())
ghoul::exponentialEaseOut(percentageSpent())
);
// Rotate direction
return glm::dvec3(rotMat * glm::dvec4(_start, 1.0));;

View File

@@ -42,21 +42,30 @@ WwtCommunicator::WwtCommunicator(const ghoul::Dictionary& dictionary)
WwtCommunicator::~WwtCommunicator() {}
void WwtCommunicator::displayImage(const std::string& url, int i) {
void WwtCommunicator::selectImage(const std::string& url, int i) {
// Ensure there are no duplicates
auto it = std::find(_selectedImages.begin(), _selectedImages.end(), i);
auto it = findSelectedImage(i);
if (it == _selectedImages.end()) {
// Push newly selected image to front
_selectedImages.push_front(i);
// Index of image is used as layer ID as it is unique in the image data set
sendMessageToWwt(addImageMessage(std::to_string(i), url));
sendMessageToWwt(setImageOpacityMessage(std::to_string(i), 1.0));
_selectedImages.push_front(std::pair<int, double>(i, 1.0));
// If wwt has not loaded the collection yet, wait with passing the message
if (_isImageCollectionLoaded) {
addImageLayerToWwt(url, i);
}
}
}
void WwtCommunicator::addImageLayerToWwt(const std::string& url, int i) {
// Index of image is used as layer ID as it is unique in the image data set
sendMessageToWwt(addImageMessage(std::to_string(i), url));
sendMessageToWwt(setImageOpacityMessage(std::to_string(i), 1.0));
}
void WwtCommunicator::removeSelectedImage(int i) {
// Remove from selected list
auto it = std::find(_selectedImages.begin(), _selectedImages.end(), i);
auto it = findSelectedImage(i);
if (it != _selectedImages.end()) {
_selectedImages.erase(it);
@@ -69,8 +78,20 @@ void WwtCommunicator::sendMessageToWwt(const ghoul::Dictionary& msg) const {
executeJavascript(script);
}
const std::deque<int>& WwtCommunicator::getSelectedImages() const {
return _selectedImages;
std::vector<int> WwtCommunicator::selectedImages() const {
std::vector<int> selectedImagesVector;
for (const std::pair<int, double>& image : _selectedImages) {
selectedImagesVector.push_back(image.first);
}
return selectedImagesVector;
}
std::vector<double> WwtCommunicator::opacities() const {
std::vector<double> opacities;
for (const std::pair<int, double>& image : _selectedImages) {
opacities.push_back(image.second);
}
return opacities;
}
void WwtCommunicator::setTargetRoll(double roll) {
@@ -88,10 +109,6 @@ void WwtCommunicator::setWebpageBorderColor(glm::ivec3 color) const {
executeJavascript(scr);
}
void WwtCommunicator::setIsSyncedWithWwt(bool isSynced) {
_isSyncedWithWwt = isSynced;
}
void WwtCommunicator::setEquatorialAim(glm::dvec2 equatorial) {
_equatorialAim = std::move(equatorial);
_equatorialAimIsDirty = true;
@@ -102,14 +119,6 @@ void WwtCommunicator::setBorderColor(glm::ivec3 color) {
_borderColorIsDirty = true;
}
void WwtCommunicator::highlight(const glm::ivec3& addition) const {
setWebpageBorderColor(_borderColor + addition);
}
void WwtCommunicator::removeHighlight(const glm::ivec3& removal) const {
setWebpageBorderColor(_borderColor - removal);
}
void WwtCommunicator::updateBorderColor() const {
setWebpageBorderColor(_borderColor);
}
@@ -125,8 +134,16 @@ glm::dvec2 WwtCommunicator::fieldsOfView() const {
return browserFov;
}
bool WwtCommunicator::hasLoadedImages() const {
return _hasLoadedImages;
bool WwtCommunicator::isImageCollectionLoaded() const {
return _isImageCollectionLoaded;
}
std::deque<std::pair<int, double>>::iterator WwtCommunicator::findSelectedImage(int i) {
auto it = std::find_if(_selectedImages.begin(), _selectedImages.end(),
[i](std::pair<int, double>& pair) {
return (pair.first == i);
});
return it;
}
glm::dvec2 WwtCommunicator::equatorialAim() const {
@@ -135,7 +152,7 @@ glm::dvec2 WwtCommunicator::equatorialAim() const {
void WwtCommunicator::setImageOrder(int i, int order) {
// Find in selected images list
auto current = std::find(_selectedImages.begin(), _selectedImages.end(), i);
auto current = findSelectedImage(i);
auto target = _selectedImages.begin() + order;
// Make sure the image was found in the list
@@ -150,23 +167,26 @@ void WwtCommunicator::setImageOrder(int i, int order) {
}
void WwtCommunicator::loadImageCollection(const std::string& collection) {
sendMessageToWwt(loadCollectionMessage(collection));
_hasLoadedImages = true;
if (!_isImageCollectionLoaded) {
sendMessageToWwt(loadCollectionMessage(collection));
}
}
void WwtCommunicator::setImageOpacity(int i, float opacity) const {
void WwtCommunicator::setImageOpacity(int i, float opacity) {
auto it = findSelectedImage(i);
it->second = opacity;
ghoul::Dictionary msg = setImageOpacityMessage(std::to_string(i), opacity);
sendMessageToWwt(msg);
}
void WwtCommunicator::hideChromeInterface(bool shouldHide) const {
void WwtCommunicator::hideChromeInterface() const {
std::string script = "sendMessageToWWT({event : \"modify_settings\", "
"settings : [[\"hideAllChrome\", true]], target: \"app\"});";
executeJavascript(script);
}
void WwtCommunicator::update() {
Browser::update();
// Cap how messages are passed
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::chrono::system_clock::duration timeSinceLastUpdate = now - _lastUpdateTime;
@@ -180,12 +200,16 @@ void WwtCommunicator::update() {
updateBorderColor();
_borderColorIsDirty = false;
}
if (_shouldReload) {
_isImageCollectionLoaded = false;
}
_lastUpdateTime = std::chrono::system_clock::now();
}
Browser::update();
}
void WwtCommunicator::setHasLoadedImages(bool isLoaded) {
_hasLoadedImages = isLoaded;
void WwtCommunicator::setImageCollectionIsLoaded(bool isLoaded) {
_isImageCollectionLoaded = isLoaded;
}
void WwtCommunicator::setIdInBrowser(const std::string& id) const {
@@ -207,7 +231,7 @@ ghoul::Dictionary WwtCommunicator::moveCameraMessage(const glm::dvec2& celestCoo
bool shouldMoveInstantly) const
{
using namespace std::string_literals;
ghoul::Dictionary msg;
msg.setValue("event", "center_on_coordinates"s);
msg.setValue("ra", celestCoords.x);
@@ -220,7 +244,7 @@ ghoul::Dictionary WwtCommunicator::moveCameraMessage(const glm::dvec2& celestCoo
ghoul::Dictionary WwtCommunicator::loadCollectionMessage(const std::string& url) const {
using namespace std::string_literals;
ghoul::Dictionary msg;
msg.setValue("event", "load_image_collection"s);
msg.setValue("url", url);
@@ -230,7 +254,7 @@ ghoul::Dictionary WwtCommunicator::loadCollectionMessage(const std::string& url)
ghoul::Dictionary WwtCommunicator::setForegroundMessage(const std::string& name) const {
using namespace std::string_literals;
ghoul::Dictionary msg;
msg.setValue("event", "set_foreground_by_name"s);
msg.setValue("name", name);
@@ -241,7 +265,7 @@ ghoul::Dictionary WwtCommunicator::addImageMessage(const std::string& id,
const std::string& url) const
{
using namespace std::string_literals;
ghoul::Dictionary msg;
msg.setValue("event", "image_layer_create"s);
msg.setValue("id", id);
@@ -253,7 +277,7 @@ ghoul::Dictionary WwtCommunicator::addImageMessage(const std::string& id,
ghoul::Dictionary WwtCommunicator::removeImageMessage(const std::string& imageId) const {
using namespace std::string_literals;
ghoul::Dictionary msg;
msg.setValue("event", "image_layer_remove"s);
msg.setValue("id", imageId);
@@ -264,7 +288,7 @@ ghoul::Dictionary WwtCommunicator::setImageOpacityMessage(const std::string& ima
double opacity) const
{
using namespace std::string_literals;
ghoul::Dictionary msg;
msg.setValue("event", "image_layer_set"s);
msg.setValue("id", imageId);
@@ -278,7 +302,7 @@ ghoul::Dictionary WwtCommunicator::setLayerOrderMessage(const std::string& id, i
// The lower the layer order, the more towards the back the image is placed
// 0 is the background
using namespace std::string_literals;
ghoul::Dictionary msg;
msg.setValue("event", "image_layer_order"s);
msg.setValue("id", id);

View File

@@ -117,6 +117,10 @@ void HttpSynchronization::cancel() {
_state = State::Unsynced;
}
std::string HttpSynchronization::generateUid() {
return fmt::format("{}/{}", _identifier, _version);
}
bool HttpSynchronization::trySyncFromUrl(std::string listUrl) {
HttpMemoryDownload fileListDownload(std::move(listUrl));
fileListDownload.onProgress([&c = _shouldCancel](int64_t, std::optional<int64_t>) {

View File

@@ -87,6 +87,8 @@ public:
/// Cancels any ongoing synchronization of this ResourceSynchronization
void cancel() override;
std::string generateUid() override;
static documentation::Documentation Documentation();
private:

View File

@@ -245,4 +245,8 @@ void UrlSynchronization::cancel() {
_state = State::Unsynced;
}
std::string UrlSynchronization::generateUid() {
return _identifier;
}
} // namespace openspace

View File

@@ -73,6 +73,8 @@ public:
/// Cancels any ongoing synchronization of this ResourceSynchronization
void cancel() override;
std::string generateUid() override;
static documentation::Documentation Documentation();
private:

View File

@@ -42,8 +42,10 @@ void WebBrowserApp::OnContextCreated(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>,
void WebBrowserApp::OnBeforeCommandLineProcessing(const CefString&,
CefRefPtr<CefCommandLine> commandLine)
{
commandLine->AppendSwitch("use-gl=desktop");
commandLine->AppendSwitch("ignore-gpu-blacklist");
commandLine->AppendSwitch("--enable-gpu-rasterization");
commandLine->AppendSwitch("--use-gl=desktop");
commandLine->AppendSwitch("--enable-webgl2-compute-context");
commandLine->AppendSwitch("ignore-gpu-blocklist");
commandLine->AppendSwitch("log-gpu-control-list-decisions");
commandLine->AppendSwitch("use-mock-keychain");
commandLine->AppendSwitch("enable-begin-frame-scheduling");

View File

@@ -140,11 +140,6 @@ void WebBrowserModule::internalInitialize(const ghoul::Dictionary& dictionary) {
_enabled = dictionary.value<bool>("Enabled");
}
const bool isMaster = global::windowDelegate->isMaster();
if (!_enabled || (!isMaster)) {
return;
}
LDEBUG(fmt::format("CEF using web helper executable: {}", _webHelperLocation));
_cefHost = std::make_unique<CefHost>(_webHelperLocation.string());
LDEBUG("Starting CEF... done!");

View File

@@ -151,6 +151,7 @@ ModuleConfigurations = {
},
Server = {
AllowAddresses = { "127.0.0.1", "localhost" },
SkyBrowserUpdateTime = 50,
Interfaces = {
{
Type = "TcpSocket",
@@ -188,7 +189,7 @@ ModuleConfigurations = {
Space = {
ShowExceptions = false
}
-- OBS! The settings for the SkyBrowser and Exoplanets modules are
-- OBS! The settings for the SkyBrowser and Exoplanets modules are
-- set in individual assets, see "data/assets/modules". Note that
-- any settings addded here might be overwritten by those assets
}

View File

@@ -303,41 +303,50 @@ void OpenSpaceEngine::initialize() {
// Process profile file (must be provided in configuration file)
if (!global::configuration->profile.empty()) {
std::string inputProfilePath = absPath("${PROFILES}").string();
std::string outputScenePath = absPath("${TEMPORARY}").string();
std::string inputProfile = inputProfilePath + "/" + global::configuration->profile
+ ".profile";
std::string inputUserProfile = absPath("${USER_PROFILES}").string() + "/" +
global::configuration->profile + ".profile";
std::filesystem::path profile;
if (!std::filesystem::is_regular_file(global::configuration->profile)) {
std::filesystem::path userCandidate = absPath(fmt::format(
"${{USER_PROFILES}}/{}.profile", global::configuration->profile
));
std::filesystem::path profileCandidate = absPath(fmt::format(
"${{PROFILES}}/{}.profile", global::configuration->profile
));
if (std::filesystem::is_regular_file(inputUserProfile)) {
inputProfile = inputUserProfile;
}
if (!std::filesystem::is_regular_file(inputProfile)) {
LERROR(fmt::format(
"Could not load profile '{}': File does not exist", inputProfile)
);
// Give the user profile priority if there are both
if (std::filesystem::is_regular_file(userCandidate)) {
profile = userCandidate;
}
else if (std::filesystem::is_regular_file(profileCandidate)) {
profile = profileCandidate;
}
else {
throw ghoul::RuntimeError(fmt::format(
"Could not load profile '{}': File does not exist",
global::configuration->profile
));
}
}
else {
// Load the profile
std::ifstream inFile;
try {
inFile.open(inputProfile, std::ifstream::in);
}
catch (const std::ifstream::failure& e) {
throw ghoul::RuntimeError(fmt::format(
"Exception opening profile file for read: {} ({})",
inputProfile, e.what())
);
}
std::string content(
(std::istreambuf_iterator<char>(inFile)),
std::istreambuf_iterator<char>()
);
*global::profile = Profile(content);
profile = global::configuration->profile;
}
// Load the profile
std::ifstream inFile;
try {
inFile.open(profile, std::ifstream::in);
}
catch (const std::ifstream::failure& e) {
throw ghoul::RuntimeError(fmt::format(
"Exception opening profile file for read: {} ({})",
profile, e.what())
);
}
std::string content(
(std::istreambuf_iterator<char>(inFile)),
std::istreambuf_iterator<char>()
);
*global::profile = Profile(content);
}
// Set up asset loader

View File

@@ -342,7 +342,7 @@ void SessionRecording::stopRecording() {
}
// Close the recording file
_recordFile.close();
_cleanupNeeded = true;
_cleanupNeededRecording = true;
}
bool SessionRecording::startPlayback(std::string& filename,
@@ -602,7 +602,7 @@ void SessionRecording::signalPlaybackFinishedForComponent(RecordedType type) {
void SessionRecording::handlePlaybackEnd() {
_state = SessionState::Idle;
_cleanupNeeded = true;
_cleanupNeededPlayback = true;
global::eventEngine->publishEvent<events::EventSessionRecordingPlayback>(
events::EventSessionRecordingPlayback::State::Finished
);
@@ -633,23 +633,31 @@ void SessionRecording::cleanUpPlayback() {
ghoul_assert(camera != nullptr, "Camera must not be nullptr");
Scene* scene = camera->parent()->scene();
if (!_timeline.empty()) {
if (_timeline.size() > 0) {
unsigned int p =
_timeline[_idxTimeline_cameraPtrPrev].idxIntoKeyframeTypeArray;
if (_keyframesCamera.size() > 0) {
const SceneGraphNode* n = scene->sceneGraphNode(
_keyframesCamera[p].focusNode);
if (n) {
global::navigationHandler->orbitalNavigator().setFocusNode(
n->identifier());
}
unsigned int p =
_timeline[_idxTimeline_cameraPtrPrev].idxIntoKeyframeTypeArray;
if (_keyframesCamera.size() > 0) {
const SceneGraphNode* n = scene->sceneGraphNode(
_keyframesCamera[p].focusNode
);
if (n) {
global::navigationHandler->orbitalNavigator().setFocusNode(
n->identifier()
);
}
}
}
_playbackFile.close();
cleanUpTimelinesAndKeyframes();
_cleanupNeededPlayback = false;
}
// Clear all timelines and keyframes
void SessionRecording::cleanUpRecording() {
cleanUpTimelinesAndKeyframes();
_cleanupNeededRecording = false;
}
void SessionRecording::cleanUpTimelinesAndKeyframes() {
_timeline.clear();
_keyframesCamera.clear();
_keyframesTime.clear();
@@ -669,8 +677,6 @@ void SessionRecording::cleanUpPlayback() {
_playbackPauseOffset = 0.0;
_playbackLoopMode = false;
_playbackForceSimTimeAtStart = false;
_cleanupNeeded = false;
}
void SessionRecording::writeToFileBuffer(unsigned char* buf,
@@ -987,9 +993,12 @@ void SessionRecording::preSynchronization() {
else if (isPlayingBack()) {
moveAheadInTime();
}
else if (_cleanupNeeded) {
else if (_cleanupNeededPlayback) {
cleanUpPlayback();
}
else if (_cleanupNeededRecording) {
cleanUpRecording();
}
// Handle callback(s) for change in idle/record/playback state
if (_state != _lastState) {

View File

@@ -63,25 +63,7 @@ namespace {
state = global::navigationHandler->navigationState();
}
ghoul::Dictionary res;
res.setValue("Anchor", state.anchor);
if (!state.aim.empty()) {
res.setValue("Aim", state.aim);
}
if (!state.referenceFrame.empty()) {
res.setValue("ReferenceFrame", state.referenceFrame);
}
res.setValue("ReferenceFrame", state.position);
if (state.up.has_value()) {
res.setValue("Up", *state.up);
}
if (state.yaw != 0) {
res.setValue("Up", state.yaw);
}
if (state.pitch != 0) {
res.setValue("Pitch", state.pitch);
}
return res;
return state.dictionary();
}
// Set the navigation state. The argument must be a valid Navigation State.
@@ -143,10 +125,10 @@ namespace {
std::string currAnchor =
global::navigationHandler->orbitalNavigator().anchorNode()->identifier();
auto it = std::find(markNodes.begin(), markNodes.end(), currAnchor);
if (it == markNodes.end() || ((it + 1) == markNodes.end())) {
// We want to use the first node either if
// We want to use the first node either if
// 1. The current node is not an interesting node
// 2. The current node is the last interesting node
global::navigationHandler->orbitalNavigator().setFocusNode(markNodes.front());

View File

@@ -505,6 +505,14 @@ glm::dvec3 computeGoodStepDirection(const SceneGraphNode* targetNode,
const glm::dvec3 targetToPrev = prevPos - nodePos;
const glm::dvec3 targetToSun = sunPos - nodePos;
// Check against zero vectors, as this will lead to nan-values from cross product
if (glm::length(targetToSun) < LengthEpsilon ||
glm::length(targetToPrev) < LengthEpsilon)
{
// Same situation as if sun does not exist. Any direction will do
return glm::dvec3(0.0, 0.0, 1.0);
}
constexpr const float defaultPositionOffsetAngle = -30.f; // degrees
constexpr const float angle = glm::radians(defaultPositionOffsetAngle);
const glm::dvec3 axis = glm::normalize(glm::cross(targetToPrev, targetToSun));

View File

@@ -73,7 +73,7 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo CartesianPositionInfo = {
"CartesianPosition",
"Cartesian coordinates",
"Cartesian Coordinates",
"This value determines the position of this screen space plane in Cartesian "
"three-dimensional coordinates (meters)."
};
@@ -88,7 +88,7 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo ScaleInfo = {
"Scale",
"Scale value",
"Scale Value",
"This value determines a scale factor for the plane. The default size of a plane "
"is determined by the concrete instance and reflects, for example, the size of "
"the image being displayed."
@@ -96,7 +96,7 @@ namespace {
constexpr openspace::properties::Property::PropertyInfo LocalRotationInfo = {
"Rotation",
"Local rotation",
"Local Rotation",
"An euler rotation (x, y, z) to apply to the plane."
};
@@ -436,6 +436,10 @@ float ScreenSpaceRenderable::depth() {
cartesianToSpherical(_cartesianPosition).x;
}
float ScreenSpaceRenderable::scale() const {
return _scale;
}
void ScreenSpaceRenderable::createShaders() {
ghoul::Dictionary dict = ghoul::Dictionary();

View File

@@ -495,14 +495,13 @@ void AssetManager::setUpAssetLuaTable(Asset* asset) {
Asset* thisAsset = ghoul::lua::userData<Asset>(L, 2);
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::syncedResourceLua");
ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
std::string uid = ResourceSynchronization::generateUid(d);
std::unique_ptr<ResourceSynchronization> s =
ResourceSynchronization::createFromDictionary(d);
std::string uid = d.value<std::string>("Type") + "/" + s->generateUid();
SyncItem* syncItem = nullptr;
auto it = manager->_synchronizations.find(uid);
if (it == manager->_synchronizations.end()) {
std::unique_ptr<ResourceSynchronization> s =
ResourceSynchronization::createFromDictionary(d);
auto si = std::make_unique<SyncItem>();
si->synchronization = std::move(s);
si->assets.push_back(thisAsset);

View File

@@ -68,11 +68,6 @@ std::unique_ptr<ResourceSynchronization> ResourceSynchronization::createFromDict
return std::unique_ptr<ResourceSynchronization>(sync);
}
std::string ResourceSynchronization::generateUid(const ghoul::Dictionary& dictionary) {
const Parameters p = codegen::bake<Parameters>(dictionary);
return fmt::format("{}/{}", p.type, p.identifier);
}
ResourceSynchronization::ResourceSynchronization(
std::filesystem::path synchronizationRoot)
: _synchronizationRoot(std::move(synchronizationRoot))

View File

@@ -74,7 +74,7 @@ namespace {
"when interpolating"
};
constexpr const char* DeltaTimeStepsKeybindsGuiPath = "/Delta Time Steps";
constexpr const char* DeltaTimeStepsKeybindsGuiPath = "/Time/Delta Time Steps";
}
namespace openspace {