Merge branch 'thesis/2021/skybrowser' of https://github.com/OpenSpace/OpenSpace into thesis/2021/skybrowser

This commit is contained in:
Ylva Selling
2022-03-25 11:34:11 -04:00
126 changed files with 3432 additions and 5396 deletions

View File

@@ -1,4 +1,4 @@
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
local model = asset.syncedResource({
@@ -27,12 +27,7 @@ local animationLoop = {
AnimationStartTime = StartTime,
ModelScale = 3E7,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true
@@ -61,12 +56,7 @@ local animationLoopInf = {
AnimationStartTime = StartTime,
ModelScale = 3E7,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true
@@ -95,12 +85,7 @@ local animationOnce = {
AnimationStartTime = StartTime,
ModelScale = 3E7,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true
@@ -129,12 +114,7 @@ local animationBounceInf = {
AnimationStartTime = StartTime,
ModelScale = 3E7,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true
@@ -163,12 +143,7 @@ local animationBounce = {
AnimationStartTime = StartTime,
ModelScale = 3E7,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true

View File

@@ -1,4 +1,4 @@
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
local generic_action = {
@@ -34,12 +34,7 @@ local obj = {
GeometryFile = model .. "BoxAnimated.glb",
ModelScale = 1.0,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true

View File

@@ -1,4 +1,4 @@
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
local model = asset.syncedResource({
@@ -22,12 +22,7 @@ local model = {
GeometryFile = model .. "BoxAnimated.glb",
ModelScale = 3E7,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true,

View File

@@ -1,20 +1,6 @@
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local transforms = asset.require("./transforms")
local LIGHTS = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local sync = asset.syncedResource({
Name = "Orion Nebula Model",
Type = "HttpSynchronization",
@@ -77,7 +63,14 @@ local OrionNebulaModel = {
DiffuseIntensity = 1.0,
--PerformShading = false,
RotationVector = { 0.000000, 22.300000, 0.000000 },
LightSources = LIGHTS;
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Orion Nebula Model",
@@ -105,7 +98,14 @@ local OrionNebulaShocksModel = {
DiffuseIntensity = 1.0,
--PerformShading = false,
RotationVector = { 0.000000, 22.300000, 0.000000 },
LightSources = LIGHTS;
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Orion Nebula Shocks",
@@ -134,7 +134,14 @@ local OrionNebulaProplydsModel = {
DiffuseIntensity = 1.0,
--PerformShading = false,
RotationVector = { 0.000000, 22.300000, 0.000000 },
LightSources = LIGHTS;
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Orion Nebula Proplyds",

View File

@@ -1,4 +1,4 @@
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local moon_transforms = asset.require("scene/solarsystem/planets/earth/moon/moon")
local descentKeyframes = asset.require("./lem_descent.asset")
@@ -68,12 +68,7 @@ local Apollo11Model = {
Type = "RenderableModel",
GeometryFile = models .. "Apollo_CSM_shrunk_rotated_xy_double_size.obj",
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
@@ -197,12 +192,7 @@ local Apollo11LemDescentModel = {
SpecularIntensity = 0.0,
RotationVector = { 273.750,28.0,309.85 },
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
@@ -235,12 +225,7 @@ local Apollo11LemLandedModel = {
SpecularIntensity = 0.0,
RotationVector = { 273.750,28.0,309.85 },
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",

View File

@@ -1,5 +1,4 @@
-- a11_lem.asset
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local moon_asset = asset.require("scene/solarsystem/planets/earth/moon/moon")
@@ -43,12 +42,7 @@ local Apollo11LemModel = {
GeometryFile = lem_model .. "LM-2_ver2clean.obj",
RotationVector = { 91.044090, 171.229706, 111.666664 },
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",

View File

@@ -1,5 +1,5 @@
local moon_transforms = asset.require("scene/solarsystem/planets/earth/moon/moon")
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
asset.require("spice/base")
local models = asset.syncedResource({
@@ -19,22 +19,6 @@ local kernels = asset.require("scene/solarsystem/missions/apollo/15/kernels").ke
-- Version = 1
-- })
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
-- {
-- Identifier = "Camera",
-- Type = "CameraLightSource",
-- Intensity = 0.5,
-- Enabled = false
-- }
}
local Apollo15 = {
Identifier = "Apollo15",
Parent = moon_transforms.Moon.Identifier,
@@ -57,12 +41,7 @@ local Apollo15 = {
GeometryFile = models .. "ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true

View File

@@ -1,4 +1,4 @@
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local moon_asset = asset.require("scene/solarsystem/planets/earth/moon/moon")
local models = asset.syncedResource({
@@ -8,20 +8,6 @@ local models = asset.syncedResource({
Version = 2
})
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local Station2Boulder1Holder = {
Identifier = "Station_2_Boulder1",
Parent = moon_asset.Moon.Identifier,
@@ -54,7 +40,14 @@ local Station2Boulder1Model = {
Type = "RenderableModel",
GeometryFile = models .. "b1-v2.obj",
RotationVector = { 243.243256 ,206.270264, 309.677429 },
LightSources = LightSources,
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
},
PerformShading = false,
DisableFaceCulling = true
},
@@ -96,7 +89,14 @@ local Station2Boulder2Model = {
Type = "RenderableModel",
GeometryFile = models .. "b2model.obj",
RotationVector = { 66.162155, 7.783780, 114.193550 },
LightSources = LightSources,
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
},
PerformShading = false,
DisableFaceCulling = true
},
@@ -138,7 +138,14 @@ local Station2Boulder3Model = {
Type = "RenderableModel",
GeometryFile = models .. "b3model.obj",
RotationVector = { 161.513519 ,243.243256, 65.806450 },
LightSources = LightSources,
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
},
PerformShading = false,
DisableFaceCulling = true
},

View File

@@ -1,4 +1,4 @@
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local moon_asset = asset.require("scene/solarsystem/planets/earth/moon/moon")
local models = asset.syncedResource({
@@ -8,20 +8,6 @@ local models = asset.syncedResource({
Version = 2
})
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local Station6Frag1Holder = {
Identifier = "Station_6_Fragment1",
@@ -65,7 +51,14 @@ local Station6Frag1Model = {
Type = "RenderableModel",
GeometryFile = models .. "A17-S6-frag1.obj",
RotationVector = { 235.909088,165.000000,286.299194 },
LightSources = LightSources,
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
},
PerformShading = false,
DisableFaceCulling = true
},
@@ -108,7 +101,14 @@ local Station6Frag2Model = {
Type = "RenderableModel",
GeometryFile = models .. "station6_boulder_frag2.obj",
RotationVector = { 336.959991,210.239990,325.984253 },
LightSources = LightSources,
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
},
PerformShading = false,
DisableFaceCulling = true,
},
@@ -139,7 +139,14 @@ local Station6Frag3Model = {
Type = "RenderableModel",
GeometryFile = models .. "station6_boulder_frag3.obj",
RotationVector = { 293.181824,255.000000,4.090910 },
LightSources = LightSources,
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
},
PerformShading = false,
DisableFaceCulling = true
},

View File

@@ -1,4 +1,4 @@
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local moon_asset = asset.require("scene/solarsystem/planets/earth/moon/moon")
local models = asset.syncedResource({
@@ -8,20 +8,6 @@ local models = asset.syncedResource({
Version = 2
})
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local Station7BoulderHolder = {
Identifier = "Station_7_Boulder",
Parent = moon_asset.Moon.Identifier,
@@ -54,7 +40,14 @@ local Station7BoulderModel = {
Type = "RenderableModel",
GeometryFile = models .. "b7model.obj",
RotationVector = { 1.945950,274.378387,212.903214 },
LightSources = LightSources,
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
},
PerformShading = false,
DisableFaceCulling = true
},

View File

@@ -1,4 +1,4 @@
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local moon_asset = asset.require("scene/solarsystem/planets/earth/moon/moon")
local model = asset.syncedResource({
@@ -42,12 +42,7 @@ local Apollo17LemModel = {
SpecularIntensity = 0.0,
RotationVector = { 110.255219,171.229706,126.666664 },
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",

View File

@@ -1,5 +1,5 @@
local earth_transforms = asset.require("scene/solarsystem/planets/earth/transforms")
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local kernels = asset.require("./kernels").kernels
local models = asset.syncedResource({
@@ -53,12 +53,7 @@ local Apollo8LaunchModel = {
GeometryFile = models .. "ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true

View File

@@ -1,5 +1,5 @@
local earth_transforms = asset.require("scene/solarsystem/planets/earth/transforms")
local sun_transforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local kernels = asset.require("./kernels").kernels
local models = asset.syncedResource({
@@ -65,12 +65,7 @@ local Apollo8Model = {
GeometryFile = models .. "ApolloCSM.osmodel",
ModelScale = 0.0001,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sun_transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true

View File

@@ -1,5 +1,5 @@
local transforms = asset.require("scene/solarsystem/sun/transforms")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local kernels = asset.syncedResource({
@@ -622,12 +622,7 @@ local KernelFiles = {
}
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",

View File

@@ -1,5 +1,5 @@
local transforms = asset.require("./transforms")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local model = asset.syncedResource({
Name = "Gaia Model",
@@ -32,12 +32,7 @@ local Gaia = {
Body = "GAIA",
GeometryFile = model .. "gaia.obj",
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 0.3
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",

View File

@@ -1,5 +1,5 @@
asset.require("spice/base")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local mars = asset.require("scene/solarsystem/planets/mars/mars")
local models = asset.syncedResource({
@@ -31,12 +31,7 @@ local RotationMatrix = {
}
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Type = "SceneGraphLightSource",
Identifier = "Mars",

View File

@@ -1,5 +1,5 @@
local transforms = asset.require("scene/solarsystem/planets/jupiter/transforms")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local model = asset.syncedResource({
@@ -152,12 +152,7 @@ local Juno = {
GeometryFile = model .. "Juno.obj",
ModelTransform = RotationMatrix,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",

View File

@@ -1,3 +1,4 @@
local sun = asset.require("scene/solarsystem/sun/sun")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local transforms = asset.require("./transforms")
asset.require("spice/base")
@@ -71,12 +72,7 @@ local JWSTModel = {
AnimationTimeScale = "Millisecond",
AnimationMode = "Once",
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true

View File

@@ -1,3 +1,4 @@
local sun = asset.require("scene/solarsystem/sun/sun")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local mercuryTransforms = asset.require("scene/solarsystem/planets/mercury/transforms")
@@ -56,21 +57,6 @@ local RotationMatrix = {
0, 1, 0
}
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local Messenger = {
Identifier = "Messenger",
Parent = sunTransforms.SolarSystemBarycenter.Identifier,
@@ -105,7 +91,14 @@ local MessengerProbeBlack = {
Type = "RenderableModel",
GeometryFile = models .. "MessengerProbe_black.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "MessengerProbe Black",
@@ -120,7 +113,14 @@ local MessengerProbeFoil = {
Type = "RenderableModel",
GeometryFile = models .. "MessengerProbe_foil.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "MessengerProbe foil",
@@ -135,7 +135,14 @@ local MessengerProbeHeatShield = {
Type = "RenderableModel",
GeometryFile = models .. "MessengerProbe_heatShield.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "MessengerProbe Heat Sheild",
@@ -150,7 +157,14 @@ local MessengerProbeMetal = {
Type = "RenderableModel",
GeometryFile = models .. "MessengerProbe_metal.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "MessengerProbe Metal",
@@ -165,7 +179,14 @@ local MessengerProbePanels = {
Type = "RenderableModel",
GeometryFile = models .. "MessengerProbe_panels.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "MessengerProbe Panels",

View File

@@ -1,5 +1,5 @@
local transforms = asset.require("./transforms")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local models = asset.syncedResource({
Name = "New Horizons Model",
@@ -19,12 +19,7 @@ local NewHorizons = {
DiffuseIntensity = 1.0,
SpecularIntensity = 1.0,
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
}
},
GUI = {

View File

@@ -1,5 +1,5 @@
local transforms = asset.require("./transforms")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local models = asset.syncedResource({
Name = "Bennu Models",
@@ -10,15 +10,6 @@ local models = asset.syncedResource({
local BENNU_BODY = "2101955"
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
}
local Bennu = {
Identifier = "Bennu",
Parent = transforms.BennuBarycenter.Identifier,
@@ -34,7 +25,9 @@ local Bennu = {
Type = "RenderableModel",
Body = BENNU_BODY,
GeometryFile = models .. "Bennu_v20_200k_an.obj",
LightSources = LightSources,
LightSources = {
sun.LightSource
},
SpecularIntensity = 0.0
},
GUI = {

View File

@@ -1,4 +1,5 @@
local transforms = asset.require("./transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local earthTransforms = asset.require("scene/solarsystem/planets/earth/transforms")
@@ -13,21 +14,6 @@ local models = asset.syncedResource({
local BENNU_BODY = "2101955"
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local OsirisRex = {
Identifier = "OsirisRex",
Parent = sunTransforms.SolarSystemBarycenter.Identifier,
@@ -48,7 +34,14 @@ local OsirisRex = {
Type = "RenderableModel",
Body = "OSIRIS-REX",
GeometryFile = models .. "orx_base_resized_12_sep_2016.obj",
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "OSIRIS REx",
@@ -74,7 +67,14 @@ local PolyCam = {
Type = "RenderableModel",
Body = "OSIRIS-REX",
GeometryFile = models .. "orx_polycam_resized_12_sep_2016.obj",
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "OCAMS POLYCAM",
@@ -89,7 +89,14 @@ local Rexis = {
Type = "RenderableModel",
Body = "OSIRIS-REX",
GeometryFile = models .. "orx_rexis_resized_12_sep_2016.obj",
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
Transform = {
Translation = {

View File

@@ -1,22 +1,8 @@
local trail = asset.require("./trail")
local marsTransforms = asset.require("scene/solarsystem/planets/mars/transforms")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
-- asset.require("./fov")
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local models = asset.syncedResource({
Name = "Mars 2020 Kernels",
Type = "HttpSynchronization",
@@ -53,7 +39,14 @@ local Body = {
Type = "RenderableModel",
Body = "MARS SCIENCE LABORATORY",
GeometryFile = models .. "Perseverance.obj",
LightSources = LightSources,
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
},
PerformShading = false,
RotationVector = {65.940000,201.389999,263.980011}
},

View File

@@ -1,4 +1,4 @@
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local modelFolder = asset.syncedResource({
Name = "Pioneer 10/11 Models",
@@ -11,12 +11,7 @@ local ModelRenderable = {
Type = "RenderableModel",
GeometryFile = modelFolder .. "pioneer.fbx",
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
@@ -35,4 +30,4 @@ asset.meta = {
Author = "NASA",
URL = "https://nasa3d.arc.nasa.gov/detail/eoss-pioneer",
License = "NASA"
}
}

View File

@@ -1,3 +1,4 @@
local sun = asset.require("scene/solarsystem/sun/sun")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local transforms = asset.require("./67p")
@@ -65,20 +66,6 @@ local RosettaKernels = {
kernels .. "ROS_CGS_RSOC_V03.TPC"
}
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local RotationMatrix = {
0, 1, 0,
0, 0, 1,
@@ -130,7 +117,14 @@ local RosettaBlackFoil = {
Body = "ROSETTA",
GeometryFile = models .. "black_foil.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Black Foil",
@@ -146,7 +140,14 @@ local RosettaBlackParts = {
Body = "ROSETTA",
GeometryFile = models .. "black_parts.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Black Parts",
@@ -162,7 +163,14 @@ local RosettaDish = {
Body = "ROSETTA",
GeometryFile = models .. "dish.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Dish",
@@ -178,7 +186,14 @@ local RosettaParts = {
Body = "ROSETTA",
GeometryFile = models .. "parts.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Parts",
@@ -194,7 +209,14 @@ local RosettaSilverFoil = {
Body = "ROSETTA",
GeometryFile = models .. "silver_foil.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Silver Foil",
@@ -210,7 +232,14 @@ local RosettaVents = {
Body = "ROSETTA",
GeometryFile = models .. "vents.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Vents",
@@ -226,7 +255,14 @@ local RosettaWingA = {
Body = "ROSETTA",
GeometryFile = models .."wingA.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Wing A",
@@ -242,7 +278,14 @@ local RosettaWingB = {
Body = "ROSETTA",
GeometryFile = models .. "wingB.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Wing B",
@@ -258,7 +301,14 @@ local RosettaYellowFoil = {
Body = "ROSETTA",
GeometryFile = models .. "yellow_foil.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Rosetta Model Part Yellow Foil",
@@ -303,7 +353,14 @@ local PhilaeFoil = {
Body = "ROSETTA",
GeometryFile = models .. "lander_foil.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Philae Model Part Foil",
@@ -319,7 +376,14 @@ local PhilaeLids = {
Body = "ROSETTA",
GeometryFile = models .. "lander_lids.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Philae Model Part Lids",
@@ -335,7 +399,14 @@ local PhilaeParts = {
Body = "ROSETTA",
GeometryFile = models .. "lander_parts.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Philae Model Part Parts",
@@ -351,7 +422,14 @@ local PhilaeSolarPanels = {
Body = "ROSETTA",
GeometryFile = models .. "lander_solarp.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Philae Model Parts Solar Panels",

View File

@@ -1,3 +1,4 @@
local sun = asset.require("scene/solarsystem/sun/sun")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local models = asset.syncedResource({
@@ -31,20 +32,6 @@ local RotationMatrix = {
0, -1, 0
}
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local Voyager1 = {
Identifier = "Voyager_1",
Parent = sunTransforms.SolarSystemBarycenter.Identifier,
@@ -79,7 +66,14 @@ local Voyager1Main = {
Type = "RenderableModel",
GeometryFile = models .. "voyager-main.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Voyager 1 Main",
@@ -94,7 +88,14 @@ local Voyager1Antenna = {
Type = "RenderableModel",
GeometryFile = models .. "voyager-antenna.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Voyager 1 Antenna",

View File

@@ -1,3 +1,4 @@
local sun = asset.require("scene/solarsystem/sun/sun")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
@@ -35,20 +36,6 @@ local RotationMatrix = {
}
local LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
},
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
local Voyager2 = {
Identifier = "Voyager_2",
Parent = sunTransforms.SolarSystemBarycenter.Identifier,
@@ -83,7 +70,14 @@ local Voyager2Main = {
Type = "RenderableModel",
GeometryFile = models .. "voyager-main.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Voyager 2 Main",
@@ -98,7 +92,14 @@ local Voyager2Antenna = {
Type = "RenderableModel",
GeometryFile = models .. "voyager-antenna.obj",
ModelTransform = RotationMatrix,
LightSources = LightSources
LightSources = {
sun.LightSource,
{
Identifier = "Camera",
Type = "CameraLightSource",
Intensity = 0.5
}
}
},
GUI = {
Name = "Voyager 2 Antenna",

View File

@@ -1,6 +1,6 @@
local satelliteHelper = asset.require("util/tle_helper")
local transforms = asset.require("scene/solarsystem/planets/earth/transforms")
local sunTransforms = asset.require("scene/solarsystem/sun/transforms")
local sun = asset.require("scene/solarsystem/sun/sun")
local url = "http://celestrak.com/satcat/tle.php?CATNR=25544"
local identifier = "ISS"
@@ -62,12 +62,7 @@ local initializeAndAddNodes = function()
GeometryFile = models .. "ISS.fbx",
ModelScale = "Centimeter",
LightSources = {
{
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = sunTransforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
sun.LightSource
},
PerformShading = true,
DisableFaceCulling = true

View File

@@ -44,6 +44,13 @@ local SunLabel = {
}
}
local LightSource = {
Type = "SceneGraphLightSource",
Identifier = "Sun",
Node = transforms.SolarSystemBarycenter.Identifier,
Intensity = 1.0
}
asset.onInitialize(function()
openspace.addSceneGraphNode(Sun)
openspace.addSceneGraphNode(SunLabel)
@@ -56,6 +63,7 @@ end)
asset.export(Sun)
asset.export(SunLabel)
asset.export("LightSource", LightSource)

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 = "234ddc8975ff03fd45708f9668c92bd31f7e79e8"
local frontendHash = "1823d1b030e3e8ecc768f936e78496ad43adcf62"
local dataProvider = "data.openspaceproject.com/files/webgui"
local frontend = asset.syncedResource({

View File

@@ -12,17 +12,28 @@
<div class="col-lg-12">
<p>
<a href="#{{urlify name}}" name="{{urlify name}}">
<span class="documentation-key">{{name}}(</span>
<span class="documentation-type">{{arguments}}</span>
<span class="documentation-function-arguments">
{{#each arguments}}
<span class="arguments-name">{{name}}</span>
<span class="arguments-type">({{type}})</span>
{{#unless @last}},{{/unless}}
{{/each}}
</span>
<span class="documentation-key">)</span>
{{#if returnType}}
<span class="documentation-function-return">
<span class="return-arrow"> -></span>
<span class="return-type"> {{returnType}}</span>
</span>
{{/if}}
</a>
</p>
<p class="documentation-description">{{help}}</p>
</div>
</div>
</div>
{{/each}}
{{/each}}
</div>
</div>
{{/each}}

View File

@@ -63,6 +63,23 @@
font-style: italic;
}
.documentation-function-arguments,
.documentation-function-return
{
font-size: 0.8em;
}
.documentation-function-arguments > .arguments-name {
color: #777;
font-style: italic;
}
.documentation-function-arguments > .arguments-type,
.documentation-function-return
{
color: #aaa;
}
.documentation-key {
color: #333;
font-weight: bold;

View File

@@ -213,11 +213,6 @@ void setAdditionalScriptsFromProfile(const Profile& p);
} // namespace openspace
// Lua functions - exposed for testing
namespace openspace::luascriptfunctions {
int createSingleColorImage(lua_State* L);
} // openspace::luascriptfunctions
std::filesystem::path createSingleColorImage(std::string name, glm::dvec3 color);
#endif // __OPENSPACE_CORE___OPENSPACEENGINE___H__

View File

@@ -237,9 +237,7 @@ public:
/**
* Returns the Lua library that contains all Lua functions available to change the
* scene graph. The functions contained are
* - openspace::luascriptfunctions::property_setValue
* - openspace::luascriptfunctions::property_getValue
* scene graph.
* \return The Lua library that contains all Lua functions available to change the
* scene graph
*/

View File

@@ -47,8 +47,18 @@ struct LuaLibrary {
std::string name;
/// The function pointer that is executed if the function is called
lua_CFunction function;
/// A text describing the arguments to this function
std::string argumentText;
struct Argument {
/// The name of the arguments
std::string name;
/// The type of the argument
std::string type;
/// The default value if it exists
std::optional<std::string> defaultValue = std::nullopt;
};
/// The ordered arguments that this function takes
std::vector<Argument> arguments;
/// Information about the type that this function returns
std::string returnType;
/// A help text describing what the function does/
std::string helpText;
};
@@ -61,19 +71,9 @@ struct LuaLibrary {
/// A list of all libraries that are children for this library
std::vector<LuaLibrary> subLibraries = std::vector<LuaLibrary>();
/// This struct contains information about a function or constant that is defined in
/// a Lua script
struct Documentation {
/// The name of the function/variable
std::string name;
/// The description of the parameters for a function
std::string parameter;
/// The description of the function/variable
std::string description;
};
/// The list of documentations will be populated automatically by parsing the Lua
/// scripts
std::vector<Documentation> documentations = std::vector<Documentation>();
std::vector<Function> documentations = std::vector<Function>();
/// Comparison function that compares two LuaLibrary%s name
bool operator<(const LuaLibrary& rhs) const;

View File

@@ -143,8 +143,6 @@ public:
/**
* Sets a relative time from profile.
* \param setTime a string containing time adjustment as described in documentation
* for luascriptfunctions::time_advancedTime
*/
void setTimeRelativeFromProfile(const std::string& setTime);

View File

@@ -350,7 +350,7 @@ void AtmosphereDeferredcaster::preRaycast(const RenderData& data, const Deferred
// Shadow calculations..
_shadowDataArrayCache.clear();
for (const ShadowConfiguration& shadowConf : _shadowConfArray) {
for (ShadowConfiguration& shadowConf : _shadowConfArray) {
// TO REMEMBER: all distances and lengths in world coordinates are in
// meters!!! We need to move this to view space...
double lt;
@@ -374,10 +374,19 @@ void AtmosphereDeferredcaster::preRaycast(const RenderData& data, const Deferred
casterPos *= KM_TO_M; // converting to meters
SceneGraphNode* sourceNode = sceneGraphNode(shadowConf.source.first);
if (!sourceNode) {
if (!shadowConf.printedSourceError) {
LERROR("Invalid scenegraph node for the shadow's receiver");
shadowConf.printedSourceError = true;
}
return;
}
SceneGraphNode* casterNode = sceneGraphNode(shadowConf.caster.first);
if (!sourceNode || !casterNode) {
LERROR("Invalid scenegraph node for the shadow's caster or receiver");
if (!casterNode) {
if (!shadowConf.printedCasterError) {
LERROR("Invalid scenegraph node for the shadow's caster");
shadowConf.printedCasterError = true;
}
return;
}

View File

@@ -53,6 +53,10 @@ struct TransformData;
struct ShadowConfiguration {
std::pair<std::string, double> source;
std::pair<std::string, double> caster;
// Set to 'true' if we printed an error because we couldn't find the source or caster.
// We only want to print a message once
bool printedSourceError = false;
bool printedCasterError = false;
};
namespace documentation { struct Documentation; }

View File

@@ -136,18 +136,8 @@ scripting::LuaLibrary ScreenSpaceDashboard::luaLibrary() {
return {
"dashboard",
{
{
"addDashboardItemToScreenSpace",
&luascriptfunctions::addDashboardItemToScreenSpace,
"string, table",
"Adds a new dashboard item to an existing SceenSpaceDashboard."
},
{
"removeDashboardItemsFromScreenSpace",
&luascriptfunctions::removeDashboardItemsFromScreenSpace,
"string",
"Removes all dashboard items from an existing ScreenSpaceDashboard."
}
codegen::lua::AddDashboardItemToScreenSpace,
codegen::lua::RemoveDashboardItemsFromScreenSpace
}
};
}

View File

@@ -22,56 +22,48 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
namespace openspace::luascriptfunctions {
namespace {
/**
* \ingroup LuaScripts
* addDashboardItemToScreenSpace(string, table):
*/
int addDashboardItemToScreenSpace(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addDashboardItemToScreenSpace");
auto [name, d] = ghoul::lua::values<std::string, ghoul::Dictionary>(L);
//Adds a new dashboard item to an existing SceenSpaceDashboard.
[[codegen::luawrap]] void addDashboardItemToScreenSpace(std::string identifier,
ghoul::Dictionary dashboard)
{
using namespace openspace;
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(identifier);
if (!ssr) {
return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item");
throw ghoul::lua::LuaError("Provided name is not a ScreenSpace item");
}
ScreenSpaceDashboard* dash = dynamic_cast<ScreenSpaceDashboard*>(ssr);
if (!dash) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
"Provided name is a ScreenSpace item but not a dashboard"
);
}
dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(d));
return 0;
dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(dashboard));
}
/**
* \ingroup LuaScripts
* removeDashboardItemsFromScreenSpace(string):
*/
int removeDashboardItemsFromScreenSpace(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeDashboardItemsFromScreenSpace");
const std::string name = ghoul::lua::value<std::string>(L);
// Removes all dashboard items from an existing ScreenSpaceDashboard.
[[codegen::luawrap]] void removeDashboardItemsFromScreenSpace(std::string identifier) {
using namespace openspace;
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(name);
ScreenSpaceRenderable* ssr = global::renderEngine->screenSpaceRenderable(identifier);
if (!ssr) {
return ghoul::lua::luaError(L, "Provided name is not a ScreenSpace item");
throw ghoul::lua::LuaError("Provided identifier is not a ScreenSpace item");
}
ScreenSpaceDashboard* dash = dynamic_cast<ScreenSpaceDashboard*>(ssr);
if (!dash) {
return ghoul::lua::luaError(
L,
"Provided name is a ScreenSpace item but not a dashboard"
throw ghoul::lua::LuaError(
"Provided identifier is a ScreenSpace item but not a dashboard"
);
}
dash->dashboard().clearDashboardItems();
return 0;
}
} // namespace openspace::luascriptfunctions
#include "screenspacedashboard_lua_codegen.cpp"
} // namespace

View File

@@ -26,9 +26,18 @@
#include <modules/debugging/rendering/renderabledebugplane.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/path.h>
#include <openspace/navigation/pathnavigator.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/util/factorymanager.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <ghoul/misc/templatefactory.h>
@@ -53,51 +62,16 @@ std::vector<documentation::Documentation> DebuggingModule::documentations() cons
}
scripting::LuaLibrary DebuggingModule::luaLibrary() const {
scripting::LuaLibrary res;
res.name = "debugging";
res.functions = {
return {
"debugging",
{
"renderCameraPath",
&luascriptfunctions::renderCameraPath,
"[number, bool, number]",
"Render the current camera path from the path navigation system. The "
"first optional argument is the number of samples to take along the path "
"(defaults to 100). If a second optional argument is included and set to "
"true, a line indicating the camera view direction along the path will "
"also be rendered. This can be useful when debugging camera orientations. "
"Finally, the third optional argument can be used to set the length "
"(in meter) of the view direction lines"
},
{
"removeRenderedCameraPath",
&luascriptfunctions::removeRenderedCameraPath,
"",
"Removes the rendered camera path, if there is one"
},
{
"renderPathControlPoints",
&luascriptfunctions::renderPathControlPoints,
"[number]",
"Render the control points for the camera path spline as spheres. The "
"optional argument can be used to set the radius of the created spheres. "
},
{
"removePathControlPoints",
&luascriptfunctions::removePathControlPoints,
"",
"Removes the rendered control points"
},
{
"addCartesianAxes",
&luascriptfunctions::addCartesianAxes,
"string, [number]",
"Adds a set of Cartesian axes to the scene graph node identified by the "
"first string, to illustrate its local coordinate system. The second "
"(optional) argument is a scale value, in meters."
codegen::lua::RenderCameraPath,
codegen::lua::RemoveRenderedCameraPath,
codegen::lua::RenderPathControlPoints,
codegen::lua::RemovePathControlPoints,
codegen::lua::AddCartesianAxes
}
};
return res;
}
} // namespace openspace

View File

@@ -22,46 +22,39 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/globals.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/path.h>
#include <openspace/navigation/pathnavigator.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/logging/logmanager.h>
namespace {
constexpr const char _loggerCat[] = "Debugging";
constexpr const char RenderedPathIdentifier[] = "CurrentCameraPath";
constexpr const char RenderedPointsIdentifier[] = "CurrentPathControlPoints";
constexpr const char DebuggingGuiPath[] = "/Debugging";
constexpr const char RenderedPathIdentifier[] = "CurrentCameraPath";
constexpr const char RenderedPointsIdentifier[] = "CurrentPathControlPoints";
constexpr const char DebuggingGuiPath[] = "/Debugging";
constexpr const glm::vec3 PathColor = { 1.0, 1.0, 0.0 };
constexpr const glm::vec3 OrientationLineColor = { 0.0, 1.0, 1.0 };
constexpr const glm::vec3 PathColor = { 1.0, 1.0, 0.0 };
constexpr const glm::vec3 OrientationLineColor = { 0.0, 1.0, 1.0 };
// Conver the input string to a format that is valid as an identifier
std::string makeIdentifier(std::string s) {
std::replace(s.begin(), s.end(), ' ', '_');
std::replace(s.begin(), s.end(), '.', '-');
// Remove quotes and apostrophe, since they cause problems
// when a string is translated to a script call
s.erase(remove(s.begin(), s.end(), '\"'), s.end());
s.erase(remove(s.begin(), s.end(), '\''), s.end());
return s;
}
} // namespace
namespace openspace::luascriptfunctions {
// Conver the input string to a format that is valid as an identifier
std::string makeIdentifier(std::string s) {
std::replace(s.begin(), s.end(), ' ', '_');
std::replace(s.begin(), s.end(), '.', '-');
// Remove quotes and apostrophe, since they cause problems
// when a string is translated to a script call
s.erase(remove(s.begin(), s.end(), '\"'), s.end());
s.erase(remove(s.begin(), s.end(), '\''), s.end());
return s;
}
/**
* PathNavigation
* Renders the current camera path
* Render the current camera path from the path navigation system. The first optional
* argument is the number of samples to take along the path (defaults to 100). If a second
* optional argument is included and set to true, a line indicating the camera view
* direction along the path will also be rendered. This can be useful when debugging
* camera orientations. Finally, the third optional argument can be used to set the length
* (in meter) of the view direction lines.
*/
int renderCameraPath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 0, 3 }, "lua::renderCameraPath");
[[codegen::luawrap]] void renderCameraPath(int nSteps = 100,
bool renderDirections = false,
double directionLineLength = 6e7)
{
using namespace openspace;
if (!global::navigationHandler->pathNavigator().hasCurrentPath()) {
LWARNINGC("Debugging: PathNavigation", "There is no current path to render");
@@ -70,15 +63,7 @@ int renderCameraPath(lua_State* L) {
const interaction::Path* currentPath =
global::navigationHandler->pathNavigator().currentPath();
auto [nSteps, renderDirections, directionLineLength] = ghoul::lua::values<
std::optional<int>, std::optional<bool>, std::optional<double>
>(L);
nSteps = nSteps.value_or(100);
renderDirections = renderDirections.value_or(false);
directionLineLength = directionLineLength.value_or(6e7);
// Parent node. Note that we only render one path at a time, so remove the previously
// Parent node. Note that we only render one path at a time, so remove the previously
// rendered one, if any
std::string addParentScript = fmt::format(
"if openspace.hasSceneGraphNode('{0}') then "
@@ -88,14 +73,14 @@ int renderCameraPath(lua_State* L) {
RenderedPathIdentifier
);
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
addParentScript,
scripting::ScriptEngine::RemoteScripting::Yes
);
// Get the poses along the path
std::vector<CameraPose> poses;
const double du = 1.0 / (*nSteps);
const double du = 1.0 / nSteps;
const double length = currentPath->pathLength();
for (double u = 0.0; u < 1.0; u += du) {
const CameraPose p = currentPath->interpolatedPose(u * length);
@@ -120,7 +105,7 @@ int renderCameraPath(lua_State* L) {
"}"
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
fmt::format("openspace.addSceneGraphNode({})", pointNode),
scripting::ScriptEngine::RemoteScripting::Yes
);
@@ -142,7 +127,7 @@ int renderCameraPath(lua_State* L) {
"}"
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
fmt::format("openspace.addSceneGraphNode({})", lineNode),
scripting::ScriptEngine::RemoteScripting::Yes
);
@@ -162,43 +147,35 @@ int renderCameraPath(lua_State* L) {
// Add first point separately so that we can create first line in for loop
addPoint(pointIdentifier(0), poses.front().position);
if (*renderDirections) {
addDirectionLine(pointIdentifier(0), poses.front(), *directionLineLength);
if (renderDirections) {
addDirectionLine(pointIdentifier(0), poses.front(), directionLineLength);
}
for (int i = 1; i < static_cast<int>(poses.size()); i++) {
addPoint(pointIdentifier(i), poses[i].position);
addLineBetweenPoints(pointIdentifier(i), pointIdentifier(i - 1), PathColor, 4.f);
if (*renderDirections) {
addDirectionLine(pointIdentifier(i), poses[i], *directionLineLength);
if (renderDirections) {
addDirectionLine(pointIdentifier(i), poses[i], directionLineLength);
}
}
return 0;
}
/**
* PathNavigation
* Removes the currently rendered camera path if there is one
*/
int removeRenderedCameraPath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::removeRenderedCameraPath");
openspace::global::scriptEngine->queueScript(
fmt::format("openspace.removeSceneGraphNode('{}') ", RenderedPathIdentifier),
// Removes the currently rendered camera path if there is one.
[[codegen::luawrap]] void removeRenderedCameraPath() {
using namespace openspace;
global::scriptEngine->queueScript(
fmt::format("openspace.removeSceneGraphNode('{}');", RenderedPathIdentifier),
scripting::ScriptEngine::RemoteScripting::Yes
);
return 0;
}
/**
* PathNavigation
* Renders the control points of the current camera path
* Render the control points for the camera path spline as spheres. The optional argument
* can be used to set the radius of the created spheres.
*/
int renderPathControlPoints(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 0, 1 }, "lua::renderPathControlPoints");
[[codegen::luawrap]] void renderPathControlPoints(double radius = 2000000.0) {
using namespace openspace;
if (!global::navigationHandler->pathNavigator().hasCurrentPath()) {
LWARNINGC(
@@ -209,20 +186,17 @@ int renderPathControlPoints(lua_State* L) {
const interaction::Path* currentPath =
global::navigationHandler->pathNavigator().currentPath();
auto [radius] = ghoul::lua::values<std::optional<double>>(L);
radius = radius.value_or(2000000.0);
// Parent node. Note that we only render one set of points at a time,
// so remove any previously rendered ones
// Parent node. Note that we only render one set of points at a time, so remove any
// previously rendered ones
std::string addParentScript = fmt::format(
"if openspace.hasSceneGraphNode('{0}') then "
"openspace.removeSceneGraphNode('{0}') "
"openspace.removeSceneGraphNode('{0}') "
"end "
"openspace.addSceneGraphNode( {{ Identifier = '{0}' }} )",
RenderedPointsIdentifier
);
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
addParentScript,
scripting::ScriptEngine::RemoteScripting::Yes
);
@@ -234,74 +208,69 @@ int renderPathControlPoints(lua_State* L) {
const char* colorTexturePath = "openspace.absPath("
"openspace.createSingleColorImage('point_color', { 0.0, 1.0, 0.0 })"
")";
")";
for (size_t i = 0; i < points.size(); i++) {
const std::string& node = "{"
"Identifier = 'ControlPoint_" + std::to_string(i) + "',"
"Parent = '" + RenderedPointsIdentifier + "',"
"Transform = { "
"Translation = {"
"Type = 'StaticTranslation',"
"Position = " + ghoul::to_string(points[i]) + ""
"},"
"Translation = {"
"Type = 'StaticTranslation',"
"Position = " + ghoul::to_string(points[i]) + ""
"},"
"},"
"Renderable = {"
"Type = 'RenderableSphere',"
"Enabled = true,"
"Segments = 30,"
"Size = " + std::to_string(*radius) + ","
"Texture = " + colorTexturePath + ""
"Type = 'RenderableSphere',"
"Enabled = true,"
"Segments = 30,"
"Size = " + std::to_string(radius) + ","
"Texture = " + colorTexturePath + ""
"},"
"GUI = {"
"Name = 'Control Point " + std::to_string(i) + "',"
"Path = '" + guiPath + "'"
"Name = 'Control Point " + std::to_string(i) + "',"
"Path = '" + guiPath + "'"
"}"
"}";
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
fmt::format("openspace.addSceneGraphNode({})", node),
scripting::ScriptEngine::RemoteScripting::Yes
);
}
return 0;
}
/**
* PathNavigation
* Removes the rendered control points
*/
int removePathControlPoints(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::removePathControlPoints");
openspace::global::scriptEngine->queueScript(
fmt::format("openspace.removeSceneGraphNode('{}') ", RenderedPointsIdentifier),
// Removes the rendered control points.
[[codegen::luawrap]] void removePathControlPoints() {
using namespace openspace;
global::scriptEngine->queueScript(
fmt::format("openspace.removeSceneGraphNode('{}');", RenderedPointsIdentifier),
scripting::ScriptEngine::RemoteScripting::Yes
);
return 0;
}
/**
* Add a set of cartesian axes to the specified scene graph node
* Adds a set of Cartesian axes to the scene graph node identified by the first string, to
* illustrate its local coordinate system. The second (optional) argument is a scale
* value, in meters.
*/
int addCartesianAxes(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::addCartesianAxes");
auto [nodeIdentifier, scale] =
ghoul::lua::values<std::string, std::optional<double>>(L);
[[codegen::luawrap]] void addCartesianAxes(std::string nodeIdentifier,
std::optional<double> scale)
{
using namespace openspace;
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(nodeIdentifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown scene graph node: " + nodeIdentifier);
throw ghoul::lua::LuaError("Unknown scene graph node: " + nodeIdentifier);
}
if (!scale.has_value()) {
scale = 2.0 * n->boundingSphere();
if (n->boundingSphere() < 1E-3) {
LWARNING("Using zero bounding sphere for scale of created axes. You might "
"have to set the scale manually for them to be visible");
if (n->boundingSphere() <= 0.0) {
LWARNINGC(
"Debugging: Cartesian Axes",
"Using zero bounding sphere for scale of created axes. You need to set "
"the scale manually for them to be visible"
);
scale = 1.0;
}
}
@@ -311,31 +280,30 @@ int addCartesianAxes(lua_State* L) {
"Identifier = '" + identifier + "',"
"Parent = '" + nodeIdentifier + "',"
"Transform = { "
"Scale = {"
"Type = 'StaticScale',"
"Scale = " + std::to_string(*scale) + ""
"}"
"Scale = {"
"Type = 'StaticScale',"
"Scale = " + std::to_string(*scale) + ""
"}"
"},"
"Renderable = {"
"Type = 'RenderableCartesianAxes',"
"Enabled = true,"
"XColor = { 1.0, 0.0, 0.0 },"
"YColor = { 0.0, 1.0, 0.0 },"
"ZColor = { 0.0, 0.0, 1.0 }"
"Type = 'RenderableCartesianAxes',"
"Enabled = true,"
"XColor = { 1.0, 0.0, 0.0 },"
"YColor = { 0.0, 1.0, 0.0 },"
"ZColor = { 0.0, 0.0, 1.0 }"
"},"
"GUI = {"
"Name = '" + identifier + "',"
"Path = '" + DebuggingGuiPath + "/Coordiante Systems'"
"Name = '" + identifier + "',"
"Path = '" + DebuggingGuiPath + "/Coordiante Systems'"
"}"
"}";
openspace::global::scriptEngine->queueScript(
fmt::format("openspace.addSceneGraphNode({})", axes),
global::scriptEngine->queueScript(
fmt::format("openspace.addSceneGraphNode({});", axes),
scripting::ScriptEngine::RemoteScripting::Yes
);
return 0;
}
} // namespace openspace::luascriptfunctions
#include "debuggingmodule_lua_codegen.cpp"
} // namespace

View File

@@ -24,15 +24,29 @@
#include <modules/exoplanets/exoplanetsmodule.h>
#include <modules/exoplanets/exoplanetshelper.h>
#include <modules/exoplanets/rendering/renderableorbitdisc.h>
#include <modules/exoplanets/tasks/exoplanetsdatapreparationtask.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/query/query.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scene/scene.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/distanceconstants.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/timeconversion.h>
#include <openspace/util/timemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/fmt.h>
#include <ghoul/glm.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <filesystem>
#include <fstream>
#include <sstream>
#include "exoplanetsmodule_lua.inl"
@@ -256,41 +270,6 @@ float ExoplanetsModule::habitableZoneOpacity() const {
return _habitableZoneOpacity;
}
scripting::LuaLibrary ExoplanetsModule::luaLibrary() const {
scripting::LuaLibrary res;
res.name = "exoplanets";
res.functions = {
{
"addExoplanetSystem",
&exoplanets::luascriptfunctions::addExoplanetSystem,
"string or list of strings",
"Add one or multiple exoplanet systems to the scene, as specified by the "
"input. An input string should be the name of the system host star"
},
{
"removeExoplanetSystem",
&exoplanets::luascriptfunctions::removeExoplanetSystem,
"string",
"Removes the nodes of the specified exoplanet system from the scene graph"
},
{
"listAvailableExoplanetSystems",
&exoplanets::luascriptfunctions::listAvailableExoplanetSystems,
"",
"Prints a list with the names of all exoplanet systems that can be added to "
"the scene graph to the OpenSpace Log"
},
{
"getListOfExoplanets",
&exoplanets::luascriptfunctions::getListOfExoplanets,
"",
"Gets a list with the names of all exoplanet systems"
}
};
return res;
}
void ExoplanetsModule::internalInitialize(const ghoul::Dictionary& dict) {
const Parameters p = codegen::bake<Parameters>(dict);
@@ -343,4 +322,16 @@ std::vector<documentation::Documentation> ExoplanetsModule::documentations() con
};
}
scripting::LuaLibrary ExoplanetsModule::luaLibrary() const {
return {
"exoplanets",
{
codegen::lua::AddExoplanetSystem,
codegen::lua::RemoveExoplanetSystem,
codegen::lua::GetListOfExoplanets,
codegen::lua::ListAvailableExoplanetSystems
}
};
}
} // namespace openspace

View File

@@ -22,44 +22,25 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/exoplanets/exoplanetshelper.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/query/query.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/distanceconstants.h>
#include <openspace/util/timeconversion.h>
#include <openspace/util/timemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/fmt.h>
#include <ghoul/glm.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/assert.h>
#include <fstream>
#include <sstream>
namespace {
constexpr const char _loggerCat[] = "ExoplanetsModule";
constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/";
constexpr const char _loggerCat[] = "ExoplanetsModule";
// Lua cannot handle backslashes, so replace these with forward slashes
std::string formatPathToLua(const std::string& path) {
std::string resPath = path;
std::replace(resPath.begin(), resPath.end(), '\\', '/');
return resPath;
}
} // namespace
constexpr const char ExoplanetsGuiPath[] = "/Milky Way/Exoplanets/Exoplanet Systems/";
namespace openspace::exoplanets::luascriptfunctions {
// Lua cannot handle backslashes, so replace these with forward slashes
std::string formatPathToLua(const std::string& path) {
std::string resPath = path;
std::replace(resPath.begin(), resPath.end(), '\\', '/');
return resPath;
}
constexpr const float AU = static_cast<float>(distanceconstants::AstronomicalUnit);
constexpr const float SolarRadius = static_cast<float>(distanceconstants::SolarRadius);
constexpr const float JupiterRadius =
static_cast<float>(distanceconstants::JupiterRadius);
openspace::exoplanets::ExoplanetSystem findExoplanetSystemInData(
std::string_view starName)
{
using namespace openspace;
using namespace exoplanets;
ExoplanetSystem findExoplanetSystemInData(std::string_view starName) {
const ExoplanetsModule* module = global::moduleEngine->module<ExoplanetsModule>();
const std::string binPath = module->exoplanetsDataPath();
@@ -135,6 +116,9 @@ ExoplanetSystem findExoplanetSystemInData(std::string_view starName) {
}
void createExoplanetSystem(const std::string& starName) {
using namespace openspace;
using namespace exoplanets;
const std::string starIdentifier = createIdentifier(starName);
std::string sanitizedStarName = starName;
@@ -173,7 +157,7 @@ void createExoplanetSystem(const std::string& starName) {
const glm::dmat3 exoplanetSystemRotation = computeSystemRotation(starPos);
// Star
float radiusInMeter = SolarRadius;
double radiusInMeter = distanceconstants::SolarRadius;
if (!std::isnan(system.starData.radius)) {
radiusInMeter *= system.starData.radius;
}
@@ -242,7 +226,7 @@ void createExoplanetSystem(const std::string& starName) {
"}"
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + starParent + ");",
scripting::ScriptEngine::RemoteScripting::Yes
);
@@ -278,25 +262,25 @@ void createExoplanetSystem(const std::string& starName) {
sEpoch = "2009-05-19T07:11:34.080";
}
float planetRadius;
double planetRadius;
std::string enabled;
if (std::isnan(planet.r)) {
if (std::isnan(planet.rStar)) {
planetRadius = planet.a * 0.001f * AU;
planetRadius = planet.a * 0.001 * distanceconstants::AstronomicalUnit;
}
else {
planetRadius = planet.rStar * 0.1f * SolarRadius;
planetRadius = planet.rStar * 0.1 * distanceconstants::SolarRadius;
}
enabled = "false";
}
else {
planetRadius = static_cast<float>(planet.r) * JupiterRadius;
planetRadius = planet.r * distanceconstants::JupiterRadius;
enabled = "true";
}
const float periodInSeconds = static_cast<float>(planet.per * SecondsPerDay);
const float semiMajorAxisInMeter = planet.a * AU;
const float semiMajorAxisInKm = semiMajorAxisInMeter * 0.001f;
float periodInSeconds = static_cast<float>(planet.per * SecondsPerDay);
double semiMajorAxisInMeter = planet.a * distanceconstants::AstronomicalUnit;
double semiMajorAxisInKm = semiMajorAxisInMeter * 0.001;
const std::string planetIdentifier = createIdentifier(planetName);
@@ -356,7 +340,7 @@ void createExoplanetSystem(const std::string& starName) {
"}"
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + planetTrailNode + ");"
"openspace.addSceneGraphNode(" + planetNode + ");",
scripting::ScriptEngine::RemoteScripting::Yes
@@ -406,7 +390,7 @@ void createExoplanetSystem(const std::string& starName) {
"}"
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + discNode + ");",
scripting::ScriptEngine::RemoteScripting::Yes
);
@@ -442,7 +426,7 @@ void createExoplanetSystem(const std::string& starName) {
"},"
"Scale = {"
"Type = 'StaticScale',"
"Scale = " + std::to_string(AU) + ""
"Scale = " + std::to_string(distanceconstants::AstronomicalUnit) + ""
"}"
"},"
"GUI = {"
@@ -451,7 +435,7 @@ void createExoplanetSystem(const std::string& starName) {
"}"
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + circle + ");",
scripting::ScriptEngine::RemoteScripting::Yes
);
@@ -506,7 +490,7 @@ void createExoplanetSystem(const std::string& starName) {
"}"
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + zoneDiscNode + ");",
scripting::ScriptEngine::RemoteScripting::Yes
);
@@ -547,7 +531,7 @@ void createExoplanetSystem(const std::string& starName) {
"}"
"}";
openspace::global::scriptEngine->queueScript(
global::scriptEngine->queueScript(
"openspace.addSceneGraphNode(" + starGlare + ");",
scripting::ScriptEngine::RemoteScripting::Yes
);
@@ -555,46 +539,9 @@ void createExoplanetSystem(const std::string& starName) {
}
}
int addExoplanetSystem(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addExoplanetSystem");
std::variant<std::string, ghoul::Dictionary> v =
ghoul::lua::value<std::variant<std::string, ghoul::Dictionary>>(L);
if (std::holds_alternative<std::string>(v)) {
// The user provided a single name
std::string starName = std::get<std::string>(v);
createExoplanetSystem(starName);
}
else {
// A list of names was provided
ghoul::Dictionary starNames = ghoul::lua::value<ghoul::Dictionary>(L);
for (size_t i = 1; i <= starNames.size(); ++i) {
if (!starNames.hasValue<std::string>(std::to_string(i))) {
return ghoul::lua::luaError(
L,
fmt::format("List item {} is of invalid type", i)
);
}
const std::string& starName = starNames.value<std::string>(std::to_string(i));
createExoplanetSystem(starName);
}
}
return 0;
}
int removeExoplanetSystem(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeExoplanetSystem");
std::string starName = ghoul::lua::value<std::string>(L);
const std::string starIdentifier = createIdentifier(std::move(starName));
openspace::global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + starIdentifier + "');",
scripting::ScriptEngine::RemoteScripting::Yes
);
return 0;
}
std::vector<std::string> hostStarsWithSufficientData() {
using namespace openspace;
using namespace exoplanets;
const ExoplanetsModule* module = global::moduleEngine->module<ExoplanetsModule>();
if (!module->hasDataFiles()) {
@@ -657,23 +604,42 @@ std::vector<std::string> hostStarsWithSufficientData() {
return names;
}
int getListOfExoplanets(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfExoplanets");
std::vector<std::string> names = hostStarsWithSufficientData();
lua_newtable(L);
int number = 1;
for (const std::string& s : names) {
ghoul::lua::push(L, s);
lua_rawseti(L, -2, number);
++number;
/**
* Add one or multiple exoplanet systems to the scene, as specified by the input. An input
* string should be the name of the system host star.
*/
[[codegen::luawrap]] void addExoplanetSystem(
std::variant<std::string, std::vector<std::string>> starNames)
{
if (std::holds_alternative<std::string>(starNames)) {
// The user provided a single name
std::string starName = std::get<std::string>(starNames);
createExoplanetSystem(starName);
}
else {
std::vector<std::string> sns = std::get<std::vector<std::string>>(starNames);
for (const std::string& starName : sns) {
createExoplanetSystem(starName);
}
}
return 1;
}
int listAvailableExoplanetSystems(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::listAvailableExoplanetSystems");
[[codegen::luawrap]] void removeExoplanetSystem(std::string starName) {
using namespace openspace;
using namespace exoplanets;
const std::string starIdentifier = createIdentifier(std::move(starName));
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + starIdentifier + "');",
scripting::ScriptEngine::RemoteScripting::Yes
);
}
[[codegen::luawrap]] std::vector<std::string> getListOfExoplanets() {
std::vector<std::string> names = hostStarsWithSufficientData();
return names;
}
[[codegen::luawrap]] void listAvailableExoplanetSystems() {
std::vector<std::string> names = hostStarsWithSufficientData();
std::string output;
@@ -687,7 +653,8 @@ int listAvailableExoplanetSystems(lua_State* L) {
"There is data available for the following {} exoplanet systems: {}",
names.size(), output
));
return 0;
}
} //namespace openspace::exoplanets::luascriptfunctions
#include "exoplanetsmodule_lua_codegen.cpp"
} // namespace

View File

@@ -1,22 +1,22 @@
openspace.gaia.documentation = {
{
Name = "addClippingBox",
Arguments = "string, vec3, vec3",
Arguments = { name = "String", size = "vec3", position = "vec3" },
Documentation = "Creates a clipping box for the Gaia renderable in the first argument"
},
{
Name = "removeClippingBox",
Arguments = "",
Arguments = {},
Documentation = ""
},
{
Name = "addClippingSphere",
Arguments = "string, float",
Arguments = { name = "String", radius = "Number" },
Documentation = "Creates a clipping sphere for the Gaia renderable in the first argument"
},
{
Name = "removeClippingBox",
Arguments = "",
Arguments = {},
Documentation = ""
}
}
@@ -104,4 +104,4 @@ openspace.gaia.removeClippingSphere = function()
if openspace.hasSceneGraphNode(grid_identifier) then
openspace.removeSceneGraphNode(grid_identifier)
end
end
end

View File

@@ -33,8 +33,10 @@
#include <modules/globebrowsing/src/globerotation.h>
#include <modules/globebrowsing/src/layer.h>
#include <modules/globebrowsing/src/layeradjustment.h>
#include <modules/globebrowsing/src/layergroup.h>
#include <modules/globebrowsing/src/layermanager.h>
#include <modules/globebrowsing/src/memoryawaretilecache.h>
#include <modules/globebrowsing/src/renderableglobe.h>
#include <modules/globebrowsing/src/tileprovider/defaulttileprovider.h>
#include <modules/globebrowsing/src/tileprovider/imagesequencetileprovider.h>
#include <modules/globebrowsing/src/tileprovider/singleimagetileprovider.h>
@@ -45,13 +47,22 @@
#include <modules/globebrowsing/src/tileprovider/tileprovider.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbyindex.h>
#include <modules/globebrowsing/src/tileprovider/tileproviderbylevel.h>
#include <openspace/camera/camera.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/navigationstate.h>
#include <openspace/navigation/orbitalnavigator.h>
#include <openspace/query/query.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/fmt.h>
@@ -338,141 +349,6 @@ globebrowsing::cache::MemoryAwareTileCache* GlobeBrowsingModule::tileCache() {
return _tileCache.get();
}
scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
std::string listLayerGroups = layerGroupNamesList();
scripting::LuaLibrary res;
res.name = "globebrowsing";
res.functions = {
{
"addLayer",
&globebrowsing::luascriptfunctions::addLayer,
"string, string, table",
"Adds a layer to the specified globe. The first argument specifies the "
"name of the scene graph node of which to add the layer. The renderable "
"of the specified scene graph node needs to be a renderable globe. "
"The second argument is the layer group which can be any of "
+ listLayerGroups + ". The third argument is the dictionary defining the "
"layer."
},
{
"deleteLayer",
&globebrowsing::luascriptfunctions::deleteLayer,
"string, string, (string, table)",
"Removes a layer from the specified globe. The first argument specifies "
"the name of the scene graph node of which to remove the layer. "
"The renderable of the specified scene graph node needs to be a "
"renderable globe. The second argument is the layer group which can be "
"any of " + listLayerGroups + ". The third argument is either the identifier "
"for the layer or a dictionary with the 'Identifier' key that is used instead"
},
{
"getLayers",
&globebrowsing::luascriptfunctions::getLayers,
"string, string",
"Returns the list of layers for the scene graph node specified in the first "
"parameter. The second parameter specifies which layer type should be "
"queried."
},
{
"moveLayer",
&globebrowsing::luascriptfunctions::moveLayer,
"string, string, number, number",
"Rearranges the order of a single layer on a globe. The first parameter"
"is the identifier of the globe, the second parameter specifies "
"the name of the layer group, the third parameter is the original position "
"of the layer that should be moved and the last parameter is the new "
"position in the list. The first position in the list has index 0, and the "
"last position is given by the number of layers minus one. The new position "
"may be -1 to place the layer at the top or any number bigger than the "
"number of layers to place it at the bottom."
},
{
"goToChunk",
&globebrowsing::luascriptfunctions::goToChunk,
"void",
"Go to chunk with given index x, y, level"
},
{
"goToGeo",
&globebrowsing::luascriptfunctions::goToGeo,
"[string], number, number, [number]",
"Go to geographic coordinates of a globe. The first (optional) argument is "
"the identifier of a scene graph node that has a RenderableGlobe attached. "
"If no globe is passed in, the current anchor will be used. "
"The second argument is latitude and the third is longitude (degrees). "
"North and East are expressed as positive angles, while South and West are "
"negative. The optional fourh argument is the altitude in meters. If no "
"altitude is provided, the altitude will be kept as the current distance to "
"the surface of the specified globe."
},
{
// @TODO (2021-06-23, emmbr) Combine with the above function when the camera
// paths work really well close to surfaces
"flyToGeo",
&globebrowsing::luascriptfunctions::flyToGeo,
"[string], number, number, number [, bool, number]",
"Fly the camera to geographic coordinates of a globe, using the path "
"navigation system. The first (optional) argument is the identifier of a "
"scene graph node with a RenderableGlobe. If no globe is passed in, the "
"current anchor will be used. The second and third argument is latitude and "
"longitude (degrees). The fourth argument is the altitude, in meters. The "
"last two optional arguments are: a bool specifying whether the up vector "
"at the target position should be set to the globe's North vector, and a "
"duration for the motion, in seconds. Either of the two can be left out."
},
{
"getLocalPositionFromGeo",
&globebrowsing::luascriptfunctions::getLocalPositionFromGeo,
"string, number, number, number",
"Returns a position in the local Cartesian coordinate system of the globe "
"identified by the first argument, that corresponds to the given geographic "
"coordinates: latitude, longitude and altitude (in degrees and meters). In "
"the local coordinate system, the position (0,0,0) corresponds to the "
"globe's center."
},
{
"getGeoPositionForCamera",
&globebrowsing::luascriptfunctions::getGeoPositionForCamera,
"void",
"Get geographic coordinates of the camera position in latitude, "
"longitude, and altitude (degrees and meters)."
},
{
"loadWMSCapabilities",
&globebrowsing::luascriptfunctions::loadWMSCapabilities,
"string, string, string",
"Loads and parses the WMS capabilities xml file from a remote server. "
"The first argument is the name of the capabilities that can be used to "
"later refer to the set of capabilities. The second argument is the "
"globe for which this server is applicable. The third argument is the "
"URL at which the capabilities file can be found."
},
{
"removeWMSServer",
&globebrowsing::luascriptfunctions::removeWMSServer,
"string",
"Removes the WMS server identified by the first argument from the list "
"of available servers. The parameter corrsponds to the first argument in "
"the loadWMSCapabilities call that was used to load the WMS server."
},
{
"capabilitiesWMS",
&globebrowsing::luascriptfunctions::capabilities,
"string",
"Returns an array of tables that describe the available layers that are "
"supported by the WMS server identified by the provided name. The 'URL'"
"component of the returned table can be used in the 'FilePath' argument "
"for a call to the 'addLayer' function to add the value to a globe."
}
};
res.scripts = {
absPath("${MODULE_GLOBEBROWSING}/scripts/layer_support.lua")
};
return res;
}
std::vector<documentation::Documentation> GlobeBrowsingModule::documentations() const {
return {
globebrowsing::Layer::Documentation(),
@@ -821,4 +697,32 @@ uint64_t GlobeBrowsingModule::wmsCacheSize() const {
return size * 1024 * 1024;
}
scripting::LuaLibrary GlobeBrowsingModule::luaLibrary() const {
std::string listLayerGroups = layerGroupNamesList();
scripting::LuaLibrary res;
res.name = "globebrowsing";
res.functions = {
codegen::lua::AddLayer,
codegen::lua::DeleteLayer,
codegen::lua::GetLayers,
codegen::lua::MoveLayer,
codegen::lua::GoToChunk,
codegen::lua::GoToGeo,
// @TODO (2021-06-23, emmbr) Combine with the above function when the camera
// paths work really well close to surfaces
codegen::lua::FlyToGeo,
codegen::lua::GetLocalPositionFromGeo,
codegen::lua::GetGeoPositionForCamera,
codegen::lua::LoadWMSCapabilities,
codegen::lua::RemoveWMSServer,
codegen::lua::Capabilities
};
res.scripts = {
absPath("${MODULE_GLOBEBROWSING}/scripts/layer_support.lua")
};
return res;
}
} // namespace openspace

View File

@@ -22,89 +22,78 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/globebrowsing/src/renderableglobe.h>
#include <modules/globebrowsing/src/layer.h>
#include <modules/globebrowsing/src/layergroup.h>
#include <modules/globebrowsing/src/layermanager.h>
#include <openspace/camera/camera.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/query/query.h>
#include <openspace/util/updatestructures.h>
namespace openspace::globebrowsing::luascriptfunctions {
namespace {
/**
* Adds a layer to the specified globe.
* Adds a layer to the specified globe. The first argument specifies the name of the scene
* graph node of which to add the layer. The renderable of the specified scene graph node
* needs to be a renderable globe. The second argument is the layer group which can be any
* of the supported layer groups. The third argument is the dictionary defining the layer.
*/
int addLayer(lua_State* L) {
ZoneScoped
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::addLayer");
auto [globeName, layerGroupName, layerDict] =
ghoul::lua::values<std::string, std::string, ghoul::Dictionary>(L);
[[codegen::luawrap]] void addLayer(std::string globeName, std::string layerGroupName,
ghoul::Dictionary layer)
{
using namespace openspace;
using namespace globebrowsing;
// Get the node and make sure it exists
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(globeName);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeName);
throw ghoul::lua::LuaError("Unknown globe name: " + globeName);
}
// Get the renderable globe
RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(n->renderable());
if (!globe) {
return ghoul::lua::luaError(L, "Renderable is not a globe: " + globeName);
throw ghoul::lua::LuaError("Renderable is not a globe: " + globeName);
}
// Get the layer group
layergroupid::GroupID groupID = ghoul::from_string<layergroupid::GroupID>(
layerGroupName
);
);
if (groupID == layergroupid::GroupID::Unknown) {
return ghoul::lua::luaError(L, "Unknown layer group: " + layerGroupName);
throw ghoul::lua::LuaError("Unknown layer group: " + layerGroupName);
}
// Get the dictionary defining the layer
Layer* layer = globe->layerManager().addLayer(groupID, layerDict);
if (layer) {
layer->initialize();
Layer* l = globe->layerManager().addLayer(groupID, layer);
if (l) {
l->initialize();
}
return 0;
}
/**
* Deletes a layer from the specified globe.
* Removes a layer from the specified globe. The first argument specifies the name of the
* scene graph node of which to remove the layer. The renderable of the specified scene
* graph node needs to be a renderable globe. The second argument is the layer group which
* can be any of the supported layer groups. The third argument is either the identifier
* for the layer or a dictionary with the 'Identifier' key that is used instead.
*/
int deleteLayer(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::deleteLayer");
auto [globeName, layerGroupName, layerOrName] = ghoul::lua::values<
std::string, std::string, std::variant<std::string, ghoul::Dictionary>
>(L);
[[codegen::luawrap]] void deleteLayer(std::string globeName, std::string layerGroupName,
std::variant<std::string, ghoul::Dictionary> layerOrName)
{
using namespace openspace;
using namespace globebrowsing;
// Get the node and make sure it exists
SceneGraphNode* n = global::renderEngine->scene()->sceneGraphNode(globeName);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeName);
throw ghoul::lua::LuaError("Unknown globe name: " + globeName);
}
// Get the renderable globe
RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(n->renderable());
if (!globe) {
return ghoul::lua::luaError(L, "Renderable is not a globe: " + globeName);
throw ghoul::lua::LuaError("Renderable is not a globe: " + globeName);
}
// Get the layer group
layergroupid::GroupID groupID = ghoul::from_string<layergroupid::GroupID>(
layerGroupName
);
);
if (groupID == layergroupid::GroupID::Unknown) {
return ghoul::lua::luaError(L, "Unknown layer group: " + layerGroupName);
throw ghoul::lua::LuaError("Unknown layer group: " + layerGroupName);
}
std::string layerName;
@@ -112,15 +101,9 @@ int deleteLayer(lua_State* L) {
layerName = std::get<std::string>(layerOrName);
}
else {
ghoul_assert(
std::holds_alternative<ghoul::Dictionary>(layerOrName),
"Missing case"
);
ghoul::Dictionary d = std::get<ghoul::Dictionary>(layerOrName);
if (!d.hasValue<std::string>("Identifier")) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
"Table passed to deleteLayer does not contain an Identifier"
);
}
@@ -128,131 +111,144 @@ int deleteLayer(lua_State* L) {
}
globe->layerManager().deleteLayer(groupID, layerName);
return 0;
}
int getLayers(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::getLayers");
auto [globeIdentifier, layer] = ghoul::lua::values<std::string, std::string>(L);
/**
* Returns the list of layers for the scene graph node specified in the first parameter.
* The second parameter specifies which layer type should be queried.
*/
[[codegen::luawrap]] std::vector<std::string> getLayers(std::string globeIdentifier,
std::string layer)
{
using namespace openspace;
using namespace globebrowsing;
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
throw ghoul::lua::LuaError("Unknown globe name: " + globeIdentifier);
}
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!globe) {
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
throw ghoul::lua::LuaError("Identifier must be a RenderableGlobe");
}
globebrowsing::layergroupid::GroupID group =
ghoul::from_string<globebrowsing::layergroupid::GroupID>(layer);
if (group == globebrowsing::layergroupid::GroupID::Unknown) {
return ghoul::lua::luaError(L, "Unknown layer groupd: " + layer);
throw ghoul::lua::LuaError("Unknown layer groupd: " + layer);
}
const globebrowsing::LayerGroup& lg = globe->layerManager().layerGroup(group);
std::vector<globebrowsing::Layer*> layers = lg.layers();
lua_newtable(L);
int key = 1;
std::vector<std::string> res;
res.reserve(layers.size());
for (globebrowsing::Layer* l : layers) {
ghoul::lua::push(L, key, l->identifier());
lua_settable(L, -3);
key++;
res.push_back(l->identifier());
}
return 1;
return res;
}
int moveLayer(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::moveLayer");
auto [globeIdentifier, layer, oldPosition, newPosition] =
ghoul::lua::values<std::string, std::string, int, int>(L);
/**
* Rearranges the order of a single layer on a globe. The first parameter is the
* identifier of the globe, the second parameter specifies the name of the layer group,
* the third parameter is the original position of the layer that should be moved and the
* last parameter is the new position in the list. The first position in the list has
* index 0, and the last position is given by the number of layers minus one. The new
* position may be -1 to place the layer at the top or any number bigger than the number
* of layers to place it at the bottom.
*/
[[codegen::luawrap]] void moveLayer(std::string globeIdentifier, std::string layer,
int oldPosition, int newPosition)
{
using namespace openspace;
using namespace globebrowsing;
if (oldPosition == newPosition) {
return 0;
return;
}
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
throw ghoul::lua::LuaError("Unknown globe name: " + globeIdentifier);
}
RenderableGlobe* globe = dynamic_cast<RenderableGlobe*>(n->renderable());
if (!globe) {
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
throw ghoul::lua::LuaError("Identifier must be a RenderableGlobe");
}
globebrowsing::layergroupid::GroupID group =
ghoul::from_string<globebrowsing::layergroupid::GroupID>(layer);
if (group == globebrowsing::layergroupid::GroupID::Unknown) {
return ghoul::lua::luaError(L, "Unknown layer groupd: " + layer);
throw ghoul::lua::LuaError("Unknown layer groupd: " + layer);
}
globebrowsing::LayerGroup& lg = globe->layerManager().layerGroup(group);
lg.moveLayer(oldPosition, newPosition);
return 0;
}
int goToChunk(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::goToChunk");
auto [identifier, x, y, level] = ghoul::lua::values<std::string, int, int, int>(L);
/**
* Go to the chunk on a globe with given index x, y, level.
*/
[[codegen::luawrap]] void goToChunk(std::string identifier, int x, int y, int level) {
using namespace openspace;
using namespace globebrowsing;
SceneGraphNode* n = sceneGraphNode(identifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + identifier);
throw ghoul::lua::LuaError("Unknown globe name: " + identifier);
}
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!globe) {
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
throw ghoul::lua::LuaError("Identifier must be a RenderableGlobe");
}
global::moduleEngine->module<GlobeBrowsingModule>()->goToChunk(*globe, x, y, level);
return 0;
}
int goToGeo(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::goToGeo");
/**
* Go to geographic coordinates of a globe. The first (optional) argument is the
* identifier of a scene graph node that has a RenderableGlobe attached. If no globe is
* passed in, the current anchor will be used. The second argument is latitude and the
* third is longitude (degrees). North and East are expressed as positive angles, while
* South and West are negative. The optional fourh argument is the altitude in meters. If
* no altitude is provided, the altitude will be kept as the current distance to the
* surface of the specified globe.
*/
[[codegen::luawrap]] void goToGeo(std::optional<std::string> globe, double latitude,
double longitude, std::optional<double> altitude)
{
using namespace openspace;
using namespace globebrowsing;
// Check if the user provided a Scene graph node identifier as the first argument.
// lua_isstring returns true for both numbers and strings, so better use !lua_isnumber
const bool providedGlobeIdentifier = !lua_isnumber(L, 1);
const SceneGraphNode* n;
if (providedGlobeIdentifier) {
const std::string& globeIdentifier = ghoul::lua::value<std::string>(L);
n = sceneGraphNode(globeIdentifier);
if (globe.has_value()) {
n = sceneGraphNode(*globe);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
throw ghoul::lua::LuaError("Unknown globe name: " + *globe);
}
}
else {
n = global::navigationHandler->orbitalNavigator().anchorNode();
if (!n) {
return ghoul::lua::luaError(L, "No anchor node is set.");
throw ghoul::lua::LuaError("No anchor node is set.");
}
}
auto [latitude, longitude, altitude] =
ghoul::lua::values<double, double, std::optional<double>>(L);
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!globe) {
if (providedGlobeIdentifier) {
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
}
else {
return ghoul::lua::luaError(
L,
"Current anchor node is not a RenderableGlobe. Either change the anchor "
"to a globe, or specify a globe identifier as the first argument"
);
}
const RenderableGlobe* gl = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!gl) {
throw ghoul::lua::LuaError(
"Current anchor node is not a RenderableGlobe. Either change the anchor "
"to a globe, or specify a globe identifier as the first argument"
);
}
if (altitude.has_value()) {
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
*globe,
*gl,
latitude,
longitude,
*altitude
@@ -260,63 +256,52 @@ int goToGeo(lua_State* L) {
}
else {
global::moduleEngine->module<GlobeBrowsingModule>()->goToGeo(
*globe,
*gl,
latitude,
longitude
);
}
return 0;
}
int flyToGeo(lua_State* L) {
int nArguments = ghoul::lua::checkArgumentsAndThrow(L, { 3, 6 }, "lua::flyToGeo");
// Check if the user provided a Scene graph node identifier as the first argument.
// lua_isstring returns true for both numbers and strings, so better use !lua_isnumber
const bool providedGlobeIdentifier = !lua_isnumber(L, 1);
const int parameterOffset = providedGlobeIdentifier ? 1 : 0;
/**
* Fly the camera to geographic coordinates of a globe, using the path navigation system.
* The first (optional) argument is the identifier of a scene graph node with a
* RenderableGlobe. If no globe is passed in, the current anchor will be used. The second
* and third argument is latitude and longitude (degrees). The fourth argument is the
* altitude, in meters. The last two optional arguments are: a bool specifying whether the
* up vector at the target position should be set to the globe's North vector, and a
* duration for the motion, in seconds. Either of the two can be left out.
*/
[[codegen::luawrap]] void flyToGeo(std::optional<std::string> globe, double latitude,
double longitude, double altitude,
std::optional<double> duration,
std::optional<bool> shouldUseUpVector)
{
using namespace openspace;
using namespace globebrowsing;
const SceneGraphNode* n;
if (providedGlobeIdentifier) {
const std::string& globeIdentifier =
ghoul::lua::value<std::string>(L, 1, ghoul::lua::PopValue::No);
n = sceneGraphNode(globeIdentifier);
if (globe.has_value()) {
n = sceneGraphNode(*globe);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe name: " + globeIdentifier);
throw ghoul::lua::LuaError("Unknown globe name: " + *globe);
}
}
else {
n = global::navigationHandler->orbitalNavigator().anchorNode();
if (!n) {
return ghoul::lua::luaError(L, "No anchor node is set.");
throw ghoul::lua::LuaError("No anchor node is set.");
}
}
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!globe) {
if (providedGlobeIdentifier) {
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
}
else {
return ghoul::lua::luaError(L,
"Current anchor node is not a RenderableGlobe. "
"Either change the anchor to a globe, or specify a globe identifier "
"as the first argument"
);
}
const RenderableGlobe* gl = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!gl) {
throw ghoul::lua::LuaError("Current anchor node is not a RenderableGlobe");
}
const double latitude =
ghoul::lua::value<double>(L, parameterOffset + 1, ghoul::lua::PopValue::No);
const double longitude =
ghoul::lua::value<double>(L, parameterOffset + 2, ghoul::lua::PopValue::No);
const double altitude =
ghoul::lua::value<double>(L, parameterOffset + 3, ghoul::lua::PopValue::No);
// Compute the relative position based on the input values
auto module = global::moduleEngine->module<GlobeBrowsingModule>();
const glm::dvec3 positionModelCoords = module->cartesianCoordinatesFromGeo(
*globe,
*gl,
latitude,
longitude,
altitude
@@ -324,12 +309,12 @@ int flyToGeo(lua_State* L) {
const glm::dvec3 currentPosW = global::navigationHandler->camera()->positionVec3();
const glm::dvec3 currentPosModelCoords =
glm::inverse(globe->modelTransform()) * glm::dvec4(currentPosW, 1.0);
glm::inverse(gl->modelTransform()) * glm::dvec4(currentPosW, 1.0);
constexpr const double LengthEpsilon = 10.0; // meters
if (glm::distance(currentPosModelCoords, positionModelCoords) < LengthEpsilon) {
LINFOC("GlobeBrowsing", "flyToGeo: Already at the requested position");
return 0;
return;
}
ghoul::Dictionary instruction;
@@ -338,83 +323,63 @@ int flyToGeo(lua_State* L) {
instruction.setValue("Position", positionModelCoords);
instruction.setValue("PathType", std::string("ZoomOutOverview"));
// Handle the two optional arguments: duration and use target's up direction argument
// The user can either provide both, or one of them
if (nArguments >= parameterOffset + 4) {
const int firstLocation = parameterOffset + 4;
const bool firstIsNumber = (lua_isnumber(L, firstLocation) != 0);
const bool firstIsBool = (lua_isboolean(L, firstLocation) != 0);
if (!(firstIsNumber || firstIsBool)) {
const char* msg = lua_pushfstring(
L,
"%s or %s expected, got %s",
lua_typename(L, LUA_TNUMBER),
lua_typename(L, LUA_TBOOLEAN),
luaL_typename(L, -1)
);
return ghoul::lua::luaError(
L, fmt::format("bad argument #{} ({})", firstLocation, msg)
);
if (duration.has_value()) {
constexpr const double Epsilon = 1e-5;
if (*duration <= Epsilon) {
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
instruction.setValue("Duration", *duration);
}
int location = firstLocation;
if (firstIsBool) {
const bool useUpFromTarget = (lua_toboolean(L, location) == 1);
instruction.setValue("UseTargetUpDirection", useUpFromTarget);
if (shouldUseUpVector.has_value()) {
instruction.setValue("UseTargetUpDirection", *shouldUseUpVector);
if (nArguments > location) {
location++;
}
}
if (firstIsNumber || nArguments > firstLocation) {
double duration =
ghoul::lua::value<double>(L, location, ghoul::lua::PopValue::No);
constexpr const double Epsilon = 1e-5;
if (duration <= Epsilon) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
}
instruction.setValue("Duration", duration);
}
}
global::navigationHandler->pathNavigator().createPath(instruction);
global::navigationHandler->pathNavigator().startPath();
lua_settop(L, 0);
ghoul_assert(lua_gettop(L) == 0, "Incorrect number of items left on stack");
return 0;
}
int getLocalPositionFromGeo(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::getLocalPositionFromGeo");
auto [globeIdentifier, latitude, longitude, altitude] =
ghoul::lua::values<std::string, double, double, double>(L);
/**
* Returns a position in the local Cartesian coordinate system of the globe identified by
* the first argument, that corresponds to the given geographic coordinates: latitude,
* longitude and altitude (in degrees and meters). In the local coordinate system, the
* position (0,0,0) corresponds to the globe's center.
*/
[[codegen::luawrap]]
std::tuple<double, double, double>
getLocalPositionFromGeo(std::string globeIdentifier, double latitude, double longitude,
double altitude)
{
using namespace openspace;
using namespace globebrowsing;
SceneGraphNode* n = sceneGraphNode(globeIdentifier);
if (!n) {
return ghoul::lua::luaError(L, "Unknown globe identifier: " + globeIdentifier);
throw ghoul::lua::LuaError("Unknown globe identifier: " + globeIdentifier);
}
const RenderableGlobe* globe = dynamic_cast<const RenderableGlobe*>(n->renderable());
if (!globe) {
return ghoul::lua::luaError(L, "Identifier must be a RenderableGlobe");
throw ghoul::lua::LuaError("Identifier must be a RenderableGlobe");
}
GlobeBrowsingModule& mod = *(global::moduleEngine->module<GlobeBrowsingModule>());
glm::vec3 p = mod.cartesianCoordinatesFromGeo(*globe, latitude, longitude, altitude);
ghoul::lua::push(L, p.x, p.y, p.z);
return 3;
return { p.x, p.y, p.z };
}
int getGeoPositionForCamera(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getGeoPositionForCamera");
/**
* Get geographic coordinates of the camera position in latitude, longitude, and altitude
* (degrees and meters).
*/
[[codegen::luawrap]] std::tuple<double, double, double> getGeoPositionForCamera() {
using namespace openspace;
using namespace globebrowsing;
GlobeBrowsingModule* module = global::moduleEngine->module<GlobeBrowsingModule>();
const RenderableGlobe* globe = module->castFocusNodeRenderableToGlobe();
if (!globe) {
return ghoul::lua::luaError(L, "Focus node must be a RenderableGlobe");
throw ghoul::lua::LuaError("Focus node must be a RenderableGlobe");
}
const glm::dvec3 cameraPosition = global::navigationHandler->camera()->positionVec3();
@@ -430,53 +395,66 @@ int getGeoPositionForCamera(lua_State* L) {
const Geodetic2 geo2 = globe->ellipsoid().cartesianToGeodetic2(
posHandle.centerToReferenceSurface
);
const double altitude = glm::length(cameraPositionModelSpace -
posHandle.centerToReferenceSurface);
const double altitude = glm::length(
cameraPositionModelSpace - posHandle.centerToReferenceSurface
);
ghoul::lua::push(L, glm::degrees(geo2.lat), glm::degrees(geo2.lon), altitude);
return 3;
return { glm::degrees(geo2.lat), glm::degrees(geo2.lon), altitude };
}
int loadWMSCapabilities(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::loadWMSCapabilities");
auto [name, globe, url] =
ghoul::lua::values<std::string, std::string, std::string>(L);
/**
* Loads and parses the WMS capabilities xml file from a remote server. The first argument
* is the name of the capabilities that can be used to later refer to the set of
* capabilities. The second argument is the globe for which this server is applicable. The
* third argument is the URL at which the capabilities file can be found.
*/
[[codegen::luawrap]] void loadWMSCapabilities(std::string name, std::string globe,
std::string url)
{
using namespace openspace;
using namespace globebrowsing;
global::moduleEngine->module<GlobeBrowsingModule>()->loadWMSCapabilities(
std::move(name),
std::move(globe),
std::move(url)
);
return 0;
}
int removeWMSServer(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeWMSServer");
const std::string name = ghoul::lua::value<std::string>(L);
/**
* Removes the WMS server identified by the first argument from the list of available
* servers. The parameter corrsponds to the first argument in the loadWMSCapabilities call
* that was used to load the WMS server.
*/
[[codegen::luawrap]] void removeWMSServer(std::string name) {
using namespace openspace;
using namespace globebrowsing;
global::moduleEngine->module<GlobeBrowsingModule>()->removeWMSServer(name);
return 0;
}
int capabilities(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::capabilities");
const std::string name = ghoul::lua::value<std::string>(L);
/**
* Returns an array of tables that describe the available layers that are supported by the
* WMS server identified by the provided name. The 'URL' component of the returned table
* can be used in the 'FilePath' argument for a call to the 'addLayer' function to add the
* value to a globe.
*/
[[codegen::luawrap]] std::vector<ghoul::Dictionary> capabilities(std::string name) {
using namespace openspace;
using namespace globebrowsing;
GlobeBrowsingModule::Capabilities cap =
global::moduleEngine->module<GlobeBrowsingModule>()->capabilities(name);
lua_newtable(L);
std::vector<ghoul::Dictionary> res;
res.reserve(cap.size());
for (size_t i = 0; i < cap.size(); ++i) {
const GlobeBrowsingModule::Layer& l = cap[i];
lua_newtable(L);
ghoul::lua::push(L, "Name", l.name);
lua_settable(L, -3);
ghoul::lua::push(L, "URL", l.url);
lua_settable(L, -3);
lua_rawseti(L, -2, i + 1);
ghoul::Dictionary c;
c.setValue("Name", cap[i].name);
c.setValue("URL", cap[i].url);
res.push_back(c);
}
return 1;
return res;
}
} // namespace openspace::globebrowsing::luascriptfunctions
#include "globebrowsingmodule_lua_codegen.cpp"
} // namespace

View File

@@ -1,7 +1,7 @@
openspace.globebrowsing.documentation = {
{
Name = "createTemporalGibsGdalXml",
Arguments = "string, string, string",
Arguments = { layerName = "String", resolution = "String", format = "String" },
Documentation = [[
Creates an XML configuration for a temporal GIBS dataset to be used in
a TemporalTileprovider
@@ -9,7 +9,7 @@ openspace.globebrowsing.documentation = {
},
{
Name = "createGibsGdalXml",
Arguments = "string, string, string, string",
Arguments = { layerName = "String", date = "String", resolution = "String", format = "String" },
Documentation =
"Creates an XML configuration for a GIBS dataset." ..
"Arguments are: layerName, date, resolution, format." ..
@@ -32,7 +32,7 @@ openspace.globebrowsing.documentation = {
},
{
Name = "addGibsLayer",
Arguments = "string, string, string, string, string",
Arguments = { layer = "String", resolution = "String", format = "String", startDate = "String", endDate = "String" },
Documentation = "Adds a new layer from NASA GIBS to the Earth globe. Arguments " ..
"are: imagery layer name, imagery resolution, start date, end date, format. " ..
"For all specifications, see " ..
@@ -42,7 +42,7 @@ openspace.globebrowsing.documentation = {
},
{
Name = "parseInfoFile",
Arguments = "string",
Arguments = { file = "String" },
Documentation =
"Parses the passed info file and return the table with the information " ..
"provided in the info file. The return table contains the optional keys: " ..
@@ -53,7 +53,7 @@ openspace.globebrowsing.documentation = {
},
{
Name = "addBlendingLayersFromDirectory",
Arguments = "string, string",
Arguments = { directory = "String", nodeName = "String" },
Documentation =
"Retrieves all info files recursively in the directory passed as the first " ..
"argument to this function. The color and height tables retrieved from these " ..
@@ -63,7 +63,7 @@ openspace.globebrowsing.documentation = {
},
{
Name = "addFocusNodesFromDirectory",
Arguments = "string, string",
Arguments = { directory = "String", nodeName = "String" },
Documentation =
"Retrieves all info files recursively in the directory passed as the first " ..
"argument to this function. The name and location retrieved from these info " ..
@@ -73,7 +73,7 @@ openspace.globebrowsing.documentation = {
},
{
Name = "addFocusNodeFromLatLong",
Arguments = "string, string, number, number, number",
Arguments = { name = "String", globeIdentifier = "String", latitude = "Number", longitude = "Number", altitude = "Number" },
Documentation =
"Creates a new SceneGraphNode that can be used as focus node. " ..
"Usage: openspace.globebrowsing.addFocusNodeFromLatLong(" ..
@@ -81,7 +81,7 @@ openspace.globebrowsing.documentation = {
},
{
Name = "loadWMSServersFromFile",
Arguments = "string",
Arguments = { filePath = "String" },
Documentation =
"Loads all WMS servers from the provided file and passes them to the " ..
"'openspace.globebrowsing.loadWMSCapabilities' file."

View File

@@ -186,6 +186,7 @@ TileDepthTransform SpoutImageProvider::depthTransform() {
}
void SpoutImageProvider::update() {
#ifdef OPENSPACE_HAS_SPOUT
if (!spoutUpdate) {
return;
}
@@ -198,10 +199,13 @@ void SpoutImageProvider::update() {
}
spoutReceiver->updateReceiver();
#endif // OPENSPACE_HAS_SPOUT
}
void SpoutImageProvider::reset() {
#ifdef OPENSPACE_HAS_SPOUT
spoutReceiver->updateReceiver();
#endif // OPENSPACE_HAS_SPOUT
}
int SpoutImageProvider::minLevel() {

View File

@@ -35,6 +35,8 @@
#include <modules/kameleon/include/kameleonwrapper.h>
#include <openspace/json.h>
#include <openspace/engine/globals.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/scene/scene.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/spicemanager.h>
@@ -753,54 +755,14 @@ scripting::LuaLibrary IswaManager::luaLibrary() {
return {
"iswa",
{
{
"addCygnet",
&luascriptfunctions::iswa_addCygnet,
"int, string, string",
"Adds a IswaCygnet",
},
{
"addScreenSpaceCygnet",
&luascriptfunctions::iswa_addScreenSpaceCygnet,
"int, string, string",
"Adds a Screen Space Cygnets",
},
{
"addKameleonPlanes",
&luascriptfunctions::iswa_addKameleonPlanes,
"string, int",
"Adds KameleonPlanes from cdf file.",
},
{
"addCdfFiles",
&luascriptfunctions::iswa_addCdfFiles,
"string",
"Adds a cdf files to choose from.",
},
{
"removeCygnet",
&luascriptfunctions::iswa_removeCygnet,
"string",
"Remove a Cygnets",
},
{
"removeScreenSpaceCygnet",
&luascriptfunctions::iswa_removeScrenSpaceCygnet,
"int",
"Remove a Screen Space Cygnets",
},
{
"removeGroup",
&luascriptfunctions::iswa_removeGroup,
"int",
"Remove a group of Cygnets",
},
{
"setBaseUrl",
&luascriptfunctions::iswa_setBaseUrl,
"string",
"sets the base url",
}
codegen::lua::AddCygnet,
codegen::lua::AddScreenSpaceCygnet,
codegen::lua::RemoveCygnet,
codegen::lua::RemoveScreenSpaceCygnet,
codegen::lua::RemoveGroup,
codegen::lua::AddCdfFiles,
codegen::lua::AddKameleonPlanes,
codegen::lua::SetBaseUrl
}
};
}

View File

@@ -22,63 +22,26 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/globals.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/rendering/screenspacerenderable.h>
namespace {
namespace openspace::luascriptfunctions {
int iswa_addCygnet(lua_State* L) {
int nArguments = lua_gettop(L);
int id = -1;
std::string type = "Texture";
std::string group = "";
if (nArguments > 0) {
id = static_cast<int>(lua_tonumber(L, 1));
}
if (nArguments > 1) {
type = luaL_checkstring(L, 2);
}
if (nArguments > 2) {
group = luaL_checkstring(L, 3);
}
IswaManager::ref().addIswaCygnet(id, type, group);
return 0;
// Adds a IswaCygnet.
[[codegen::luawrap]] void addCygnet(int id = -1, std::string type = "Texture",
std::string group = "")
{
openspace::IswaManager::ref().addIswaCygnet(id, type, group);
}
int iswa_addScreenSpaceCygnet(lua_State* L) {
static const std::string _loggerCat = "addScreenSpaceCygnet";
using ghoul::lua::errorLocation;
int nArguments = lua_gettop(L);
if (nArguments != 1) {
return ghoul::lua::luaError(L, fmt::format(
"Expected {} argumemts, got {}", 1, nArguments
));
}
ghoul::Dictionary d;
try {
ghoul::lua::luaDictionaryFromState(L, d);
}
catch (const ghoul::lua::LuaFormatException& e) {
LERROR(e.what());
return 0;
}
// Adds a Screen Space Cygnets.
[[codegen::luawrap]] void addScreenSpaceCygnet(ghoul::Dictionary d) {
using namespace openspace;
int id = static_cast<int>(d.value<double>("CygnetId"));
std::map<int, std::shared_ptr<CygnetInfo>> cygnetInformation =
IswaManager::ref().cygnetInformation();
if (cygnetInformation.find(id) == cygnetInformation.end()) {
LWARNING("Could not find Cygnet with id = " + std::to_string(id));
return 0;
throw ghoul::lua::LuaError(
"Could not find Cygnet with id = " + std::to_string(id)
);
}
std::shared_ptr<CygnetInfo> info = cygnetInformation[id];
@@ -87,8 +50,9 @@ int iswa_addScreenSpaceCygnet(lua_State* L) {
info->selected = true;
if (global::renderEngine->screenSpaceRenderable(name)) {
LERROR("A cygnet with the name \"" + name +"\" already exist");
return 0;
throw ghoul::lua::LuaError(fmt::format(
"A cygnet with the name \"{}\" already exist", name
));
}
else {
d.setValue("Name", name);
@@ -100,99 +64,68 @@ int iswa_addScreenSpaceCygnet(lua_State* L) {
);
global::renderEngine->addScreenSpaceRenderable(std::move(s));
}
return 0;
}
// int iswa_addKameleonPlane(lua_State* L){
// int nArguments = lua_gettop(L);
// std::string kwPath = "";
// std::string type = "x";
// std::string group = "";
// if (nArguments > 0) {
// kwPath = luaL_checkstring(L, 1);
// }
// if (nArguments > 1) {
// type = luaL_checkstring(L, 2);
// }
// if (nArguments > 2) {
// group = luaL_checkstring(L, 3);
// }
// IswaManager::ref().createKameleonPlane(kwPath, type, group);
// return 0;
// }
int iswa_removeCygnet(lua_State* L) {
std::string name = luaL_checkstring(L, -1);
// Remove a Cygnets.
[[codegen::luawrap]] void removeCygnet(std::string name) {
using namespace openspace;
global::scriptEngine->queueScript(
"openspace.removeSceneGraphNode('" + name + "')",
scripting::ScriptEngine::RemoteScripting::Yes
);
// IswaManager::ref().deleteIswaCygnet(s);
return 0;
}
int iswa_removeScrenSpaceCygnet(lua_State* L) {
static const std::string _loggerCat = "removeScreenSpaceCygnet";
int id = static_cast<int>(lua_tonumber(L, 1));
// Remove a Screen Space Cygnets.
[[codegen::luawrap]] void removeScreenSpaceCygnet(int id) {
using namespace openspace;
std::map<int, std::shared_ptr<CygnetInfo>> cygnetInformation =
IswaManager::ref().cygnetInformation();
if (cygnetInformation.find(id) == cygnetInformation.end()) {
LWARNING("Could not find Cygnet with id = " + std::to_string(id));
return 0;
throw ghoul::lua::LuaError(
"Could not find Cygnet with id = " + std::to_string(id)
);
}
std::shared_ptr<CygnetInfo> info = cygnetInformation[id];
info->selected = false;
std::string script =
"openspace.unregisterScreenSpaceRenderable('" +
cygnetInformation[id]->name + "');";
std::string script = fmt::format(
"openspace.unregisterScreenSpaceRenderable('{}');", cygnetInformation[id]->name
);
global::scriptEngine->queueScript(
script,
scripting::ScriptEngine::RemoteScripting::Yes
);
return 0;
}
int iswa_removeGroup(lua_State* L) {
std::string name = luaL_checkstring(L, -1);
// IswaManager::ref().unregisterGroup(id);
// Remove a group of Cygnets.
[[codegen::luawrap]] void removeGroup(std::string name) {
using namespace openspace;
std::map<std::string, std::shared_ptr<IswaBaseGroup>> groups =
IswaManager::ref().groups();
if (groups.find(name) != groups.end()) {
groups[name]->clearGroup();
}
return 0;
}
int iswa_addCdfFiles(lua_State* L) {
std::string path = luaL_checkstring(L, 1);
IswaManager::ref().addCdfFiles(path);
return 0;
// Adds a cdf files to choose from.
[[codegen::luawrap]] void addCdfFiles(std::string path) {
openspace::IswaManager::ref().addCdfFiles(path);
}
int iswa_addKameleonPlanes(lua_State* L) {
std::string group = luaL_checkstring(L, 1);
int pos = static_cast<int>(lua_tonumber(L, 2));
IswaManager::ref().addKameleonCdf(group, pos);
return 0;
// Adds KameleonPlanes from cdf file.
[[codegen::luawrap]] void addKameleonPlanes(std::string group, int pos) {
openspace::IswaManager::ref().addKameleonCdf(group, pos);
}
int iswa_setBaseUrl(lua_State* L) {
std::string url = luaL_checkstring(L, 1);
IswaManager::ref().setBaseUrl(url);
return 0;
// Sets the base url.
[[codegen::luawrap]] void setBaseUrl(std::string url) {
openspace::IswaManager::ref().setBaseUrl(url);
}
} // namespace openspace::luascriptfunctions
#include "iswamanager_lua_codegen.cpp"
} // namespace

View File

@@ -53,7 +53,6 @@ public:
float opacity() const;
double animationSpeed() const;
double stopAnimationThreshold() const;
double smallestFov() const;
void setDimensions(glm::vec2 dimensions);
void setColor(glm::ivec3 color);
@@ -69,7 +68,6 @@ private:
properties::FloatProperty _crossHairSize;
properties::FloatProperty _showRectangleThreshold;
properties::FloatProperty _lineWidth;
properties::DoubleProperty _smallestFov;
properties::DoubleProperty _stopAnimationThreshold;
properties::DoubleProperty _animationSpeed;

View File

@@ -74,6 +74,7 @@ public:
private:
properties::DoubleProperty _animationSpeed;
properties::FloatProperty _textureQuality;
properties::BoolProperty _renderOnlyOnMaster;
std::vector<std::unique_ptr<properties::Vec3Property>> _renderCopies;
void bindTexture() override;

View File

@@ -67,8 +67,6 @@ public:
// Target
void centerTargetOnScreen();
void lock();
void unlock();
void incrementallyAnimateTarget(float deltaTime);
bool hasFinishedFading(float goalState) const;
@@ -116,9 +114,7 @@ private:
bool isTargetFadeFinished(float goalState) const;
bool isBrowserFadeFinished(float goalState) const;
void aimTargetGalactic(glm::dvec3 position);
void setFovTarget(double fov);
void aimTargetGalactic(glm::dvec3 direction);
// Selection
ScreenSpaceSkyBrowser* _selected = nullptr;

View File

@@ -42,7 +42,7 @@ uniform vec3 multiplyColor;
// A factor which states how much thicker vertical lines are rendered than horizontal
// This compensates for the optical illusion that vertical lines appear thinner
const float VerticalThickness = 1.15;
const float VerticalThickness = 1.1;
float createLine(float lineCenter, float lineWidth, float coord) {
// Calculate edges of line
@@ -52,28 +52,13 @@ float createLine(float lineCenter, float lineWidth, float coord) {
return step(startEdge, coord) - step(endEdge, coord);
}
float createFilledRectangle(float width, vec2 coord) {
return createLine(0.5, width, coord.x) * createLine(0.5, width, coord.y);
}
float createRectangle(float linewidthY, float ratio, vec2 coord) {
// Calculate the widths and centers for the lines
float linewidthX = linewidthY * ratio * VerticalThickness;
float linecenterX = linewidthX * 0.5;
float linecenterY = linewidthY * 0.5;
// Create the four lines for the rectangle
float l = createLine(linecenterX, linewidthX, coord.x);
float r = createLine(1.0 - linecenterX, linewidthX, coord.x);
float b = createLine(linecenterY, linewidthY, coord.y);
float t = createLine(1.0 - linecenterY, linewidthY, coord.y);
return l + r + b + t;
float createFilledRectangle(float width, float height, vec2 coord) {
return createLine(0.5, width, coord.x) * createLine(0.5, height, coord.y);
}
float createCrosshair(in float linewidth, in float ratio, in vec2 coord) {
const float Center = 0.5;
float crosshairVertical = createLine(Center, linewidth * ratio * VerticalThickness, coord.x);
float crosshairVertical = createLine(Center, linewidth * VerticalThickness, coord.x);
float crosshairHorizontal = createLine(Center, linewidth, coord.y);
return crosshairHorizontal + crosshairVertical;
@@ -84,14 +69,22 @@ float createCrosshair(in float linewidth, in float ratio, in vec2 coord) {
Fragment getFragment() {
float ratio = dimensions.y / dimensions.x;
float rectangle = 0.0;
float lineWidthUsed = (lineWidth * 0.01)/max(fov,2);
float maxWwtFov = 70;
float crosshair = createCrosshair(lineWidthUsed, ratio, vs_st);
float crossHairBox = createFilledRectangle(crossHairSize/max(fov,2), vs_st);
float crosshair = createCrosshair(lineWidth, ratio, vs_st);
float crossHairHeight = crossHairSize/maxWwtFov;
float crossHairWidth = crossHairHeight * ratio;
float crossHairBox = createFilledRectangle(crossHairHeight, crossHairWidth, vs_st);
crosshair *= crossHairBox;
if (showRectangle) {
rectangle = createRectangle(lineWidthUsed, ratio, vs_st);
float height = fov/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);
rectangle = outerEdge - innerEdge;
}
float result = clamp(crosshair + rectangle, 0.0, 1.0);

View File

@@ -24,17 +24,16 @@
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/include/renderableskytarget.h>
#include <modules/skybrowser/include/screenspaceskybrowser.h>
#include <modules/skybrowser/include/targetbrowserpair.h>
#include <modules/skybrowser/include/RenderableSkyTarget.h>
#include <modules/skybrowser/include/wwtdatahandler.h>
#include <modules/base/rendering/screenspaceimagelocal.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/camera/camera.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/camera/camera.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/util/factorymanager.h>
#include "skybrowsermodule_lua.inl"
@@ -76,199 +75,6 @@ namespace {
} // namespace
namespace openspace {
scripting::LuaLibrary SkyBrowserModule::luaLibrary() const {
scripting::LuaLibrary res;
res.name = "skybrowser";
res.functions = {
{
"getListOfImages",
&skybrowser::luascriptfunctions::getListOfImages,
"",
"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, equatorial Cartesian coordinates, "
"if the image has celestial coordinates, credits text, credits url "
"and the identifier of the image which is a unique number."
},
{
"setHoverCircle",
&skybrowser::luascriptfunctions::setHoverCircle,
"string",
"Takes an identifier to a screen space renderable and adds it to the "
"module."
},
{
"moveCircleToHoverImage",
&skybrowser::luascriptfunctions::moveCircleToHoverImage,
"int",
"Moves the hover circle to the coordinate specified by the image index."
},
{
"disableHoverCircle",
&skybrowser::luascriptfunctions::disableHoverCircle,
"",
"Disables the hover circle, if there is one added to the sky browser "
"module."
},
{
"loadImagesToWWT",
&skybrowser::luascriptfunctions::loadImagesToWWT,
"string",
"Takes an identifier to a sky browser or target and loads the WWT image "
"collection to that browser."
},
{
"selectImage",
&skybrowser::luascriptfunctions::selectImage,
"int",
"Takes an index to an image and selects that image in the currently "
"selected sky browser."
},
{
"removeSelectedImageInBrowser",
&skybrowser::luascriptfunctions::removeSelectedImageInBrowser,
"string, int",
"Takes an identifier to a sky browser or target and an index to an "
"image. Removes that image from that sky browser."
},
{
"adjustCamera",
& skybrowser::luascriptfunctions::adjustCamera,
"string",
"Takes an identifier to a sky browser or sky target. Rotates the camera "
"so that the target is placed in the center of the view."
},
{
"setSelectedBrowser",
& skybrowser::luascriptfunctions::setSelectedBrowser,
"string",
"Takes an identifier to a sky browser or target. Sets that sky browser "
"currently selected."
},
{
"getTargetData",
&skybrowser::luascriptfunctions::getTargetData,
"",
"Returns a table of data regarding the current view and the sky browsers "
"and targets."
},
{
"createTargetBrowserPair",
&skybrowser::luascriptfunctions::createTargetBrowserPair,
"",
"Creates a sky browser and a target."
},
{
"removeTargetBrowserPair",
&skybrowser::luascriptfunctions::removeTargetBrowserPair,
"string",
"Takes in identifier to a sky browser or target and removes them."
},
{
"setOpacityOfImageLayer",
&skybrowser::luascriptfunctions::setOpacityOfImageLayer,
"string, int, double",
"Takes an identifier to a sky browser or sky target, an index to an image"
"and a value for the opacity."
},
{
"sendOutIdsToBrowsers",
&skybrowser::luascriptfunctions::sendOutIdsToBrowsers,
"",
"Sends all sky browsers' identifiers to their respective CEF browser. "
},
{
"initializeBrowser",
&skybrowser::luascriptfunctions::initializeBrowser,
"string",
"Takes an identifier to a sky browser and starts the initialization "
"for that browser. That means that the browser starts to try to connect "
"to the AAS WorldWide Telescope application by sending it messages. And "
"that the target matches its appearance to its corresponding browser."
},
{
"centerTargetOnScreen",
&skybrowser::luascriptfunctions::centerTargetOnScreen,
"string",
"Takes an identifier to a sky browser and animates its corresponding "
"target to the center of the current view."
},
{
"setImageLayerOrder",
&skybrowser::luascriptfunctions::setImageLayerOrder,
"string, int, int",
"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."
},
{
"addPairToSkyBrowserModule",
&skybrowser::luascriptfunctions::addPairToSkyBrowserModule,
"string, string",
"Takes the identifier of the sky target and a sky browser and adds them "
"to the sky browser module."
},
{
"setEquatorialAim",
&skybrowser::luascriptfunctions::setEquatorialAim,
"string, double, double",
"Takes the identifier of a sky browser or a sky target and equatorial "
"coordinates Right Ascension and Declination. The target will animate to "
"this coordinate and the browser will display the coordinate."
},
{
"setVerticalFov",
&skybrowser::luascriptfunctions::setVerticalFov,
"string, float",
"Takes an identifier to a sky browser or a sky target and a vertical "
"field of view. Changes the field of view as specified by the input."
},
{
"setBorderColor",
&skybrowser::luascriptfunctions::setBorderColor,
"string, int, int, int",
"Takes an identifier to a sky browser or a sky target and a rgb color "
"in the ranges [0, 255]."
},
{
"setScreenSpaceSize",
&skybrowser::luascriptfunctions::setScreenSpaceSize,
"string, float, float",
"Sets the screen space size of the sky browser to the numbers specified "
"by the input [x, y]."
},
{
"startSetup",
&skybrowser::luascriptfunctions::startSetup,
"",
"Starts the setup process of the sky browers. This function calls "
"the lua function 'sendOutIdsToBrowsers' in all nodes in the cluster."
},
{
"translateScreenSpaceRenderable",
&skybrowser::luascriptfunctions::translateScreenSpaceRenderable,
"string, float, float, float, float",
"Takes an identifier to a sky browser or sky target and the [x, y] "
"starting position and the [x, y] translation vector."
},
{
"addRenderCopy",
&skybrowser::luascriptfunctions::addRenderCopy,
"string",
"Takes an identifier to a sky browser and adds a rendered copy to it."
},
{
"removeRenderCopy",
&skybrowser::luascriptfunctions::removeRenderCopy,
"string",
"Takes an identifier to a sky browser and removes the latest added "
"rendered copy to it."
},
};
return res;
}
SkyBrowserModule::SkyBrowserModule()
: OpenSpaceModule(SkyBrowserModule::Name)
, _allowMouseInteraction(AllowInteractionInfo, true)
@@ -570,7 +376,7 @@ TargetBrowserPair* SkyBrowserModule::getPair(const std::string& id) {
bool foundBrowser = pair->browserId() == id;
bool foundTarget = pair->targetRenderableId() == id;
bool foundTargetNode = pair->targetNodeId() == id;
return foundBrowser || foundTarget;
return foundBrowser || foundTarget || foundTargetNode;
}
);
if (it == std::end(_targetsBrowsers)) {
@@ -702,4 +508,39 @@ bool SkyBrowserModule::isSelectedPairFacingCamera() {
return false;
}
}
scripting::LuaLibrary SkyBrowserModule::luaLibrary() const {
return {
"skybrowser",
{
codegen::lua::StartSetup,
codegen::lua::InitializeBrowser,
codegen::lua::SendOutIdsToBrowsers,
codegen::lua::GetListOfImages,
codegen::lua::SetHoverCircle,
codegen::lua::MoveCircleToHoverImage,
codegen::lua::DisableHoverCircle,
codegen::lua::LoadImagesToWWT,
codegen::lua::SelectImage,
codegen::lua::RemoveSelectedImageInBrowser,
codegen::lua::AdjustCamera,
codegen::lua::SetSelectedBrowser,
codegen::lua::GetTargetData,
codegen::lua::CreateTargetBrowserPair,
codegen::lua::RemoveTargetBrowserPair,
codegen::lua::SetOpacityOfImageLayer,
codegen::lua::CenterTargetOnScreen,
codegen::lua::SetImageLayerOrder,
codegen::lua::AddPairToSkyBrowserModule,
codegen::lua::SetEquatorialAim,
codegen::lua::SetVerticalFov,
codegen::lua::SetBorderColor,
codegen::lua::TranslateScreenSpaceRenderable,
codegen::lua::AddRenderCopy,
codegen::lua::SetScreenSpaceSize,
codegen::lua::RemoveRenderCopy
}
};
}
} // namespace openspace

View File

@@ -25,8 +25,10 @@
#include <modules/skybrowser/skybrowsermodule.h>
#include <modules/skybrowser/include/utility.h>
#include <openspace/engine/moduleengine.h>
#include <modules/skybrowser/include/targetbrowserpair.h>
#include <modules/skybrowser/include/wwtdatahandler.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/windowdelegate.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scripting/scriptengine.h>
@@ -35,14 +37,16 @@
namespace {
constexpr const char _loggerCat[] = "SkyBrowserModule";
} // namespace
namespace openspace::skybrowser::luascriptfunctions {
using namespace openspace;
int selectImage(lua_State* L) {
/**
* Takes an index to an image and selects that image in the currently
* selected sky browser.
* \param i Index of image
*/
[[codegen::luawrap]] void selectImage(int i) {
// Load image
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::selectImage");
const int i = ghoul::lua::value<int>(L, 1);
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
if (module->isCameraInSolarSystem()) {
@@ -53,66 +57,68 @@ int selectImage(lua_State* L) {
LINFO("Loading image " + image.name);
selected->selectImage(image, i);
bool isInView = isCoordinateInView(image.equatorialCartesian);
bool isInView = skybrowser::isCoordinateInView(image.equatorialCartesian);
// If the coordinate is not in view, rotate camera
if (image.hasCelestialCoords && !isInView) {
module->startRotatingCamera(
equatorialToGalactic(
skybrowser::equatorialToGalactic(
image.equatorialCartesian * skybrowser::CelestialSphereRadius
)
);
}
}
}
return 0;
}
int setHoverCircle(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setHoverCircle");
/**
* Takes an identifier to a screen space renderable and adds it to the module.
* \param id Identifier
*/
[[codegen::luawrap]] void setHoverCircle(std::string id) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
std::string id = ghoul::lua::value<std::string>(L, 1);
SceneGraphNode* circle = global::renderEngine->scene()->sceneGraphNode(id);
module->setHoverCircle(circle);
return 0;
}
int moveCircleToHoverImage(lua_State* L) {
/**
* Moves the hover circle to the coordinate specified by the image index.
* \param i Index of image
*/
[[codegen::luawrap]] void moveCircleToHoverImage(int i) {
// Load image
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::moveCircleToHoverImage");
const int i = ghoul::lua::value<int>(L, 1);
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
module->moveHoverCircle(i);
return 0;
}
int disableHoverCircle(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::disableHoverCircle");
/**
* Disables the hover circle, if there is one added to the sky browser
* module.
*/
[[codegen::luawrap]] void disableHoverCircle() {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
module->disableHoverCircle();
return 0;
}
int setImageLayerOrder(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setImageLayerOrder");
auto [id, i, order] = ghoul::lua::values<std::string, int, int>(L);
/**
* 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 id, int i, int order) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
if (module->getPair(id)) {
module->getPair(id)->setImageOrder(i, order);
}
return 0;
}
int loadImagesToWWT(lua_State* L) {
/**
* Takes an identifier to a sky browser or target and loads the WWT image
* collection to that browser.
* \param id Identifier
*/
[[codegen::luawrap]] void loadImagesToWWT(std::string id) {
// Load images from url
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadImagesToWWT");
const std::string id = ghoul::lua::value<std::string>(L, 1);
LINFO("Connection established to WorldWide Telescope application in " + id);
LINFO("Loading image collections to " + id);
@@ -127,14 +133,13 @@ int loadImagesToWWT(lua_State* L) {
module->getPair(id)->hideChromeInterface(true);
module->getPair(id)->loadImageCollection(root);
}
return 0;
}
int startSetup(lua_State* L) {
/**
* Starts the setup process of the sky browers. This function calls
* the lua function 'sendOutIdsToBrowsers' in all nodes in the cluster.
*/
[[codegen::luawrap]] void startSetup() {
// This is called when the sky_browser website is connected to OpenSpace
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::startSetup");
// Set all border colors to the border color in the master node
if (global::windowDelegate->isMaster()) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
@@ -162,29 +167,28 @@ int startSetup(lua_State* L) {
"openspace.skybrowser.sendOutIdsToBrowsers();",
scripting::ScriptEngine::RemoteScripting::No
);
return 0;
}
int sendOutIdsToBrowsers(lua_State* L) {
/**
* Sends all sky browsers' identifiers to their respective CEF browser.
*/
[[codegen::luawrap]] void sendOutIdsToBrowsers() {
// This is called when the sky_browser website is connected to OpenSpace
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::sendOutIdsToBrowsers");
// Send out identifiers to the browsers
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
std::vector<std::unique_ptr<TargetBrowserPair>>& pairs = module->getPairs();
for (std::unique_ptr<TargetBrowserPair>& pair : pairs) {
pair->sendIdToBrowser();
}
return 0;
}
int initializeBrowser(lua_State* L) {
/**
* Takes an identifier to a sky browser and starts the initialization
* for that browser. That means that the browser starts to try to connect
* to the AAS WorldWide Telescope application by sending it messages. And
* that the target matches its appearance to its corresponding browser.
* \param id Identifier
*/
[[codegen::luawrap]] void initializeBrowser(std::string id) {
// Initialize browser with ID and its corresponding target
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::initializeBrowser");
const std::string id = ghoul::lua::value<std::string>(L, 1);
LINFO("Initializing sky browser " + id);
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* found = module->getPair(id);
@@ -192,30 +196,34 @@ int initializeBrowser(lua_State* L) {
found->setIsSyncedWithWwt(true);
found->initialize();
}
return 0;
}
int addPairToSkyBrowserModule(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addPairToSkyBrowserModule");
auto [targetId, browserId] = ghoul::lua::values<std::string, std::string>(L);
/**
* Takes the identifier of the sky target and a sky browser and adds them
* to the sky browser module.
* \param targetId Identifier of target (either SceneGraphNode or Renderable)
* \param browserId Identifier of browser
*/
[[codegen::luawrap]] void addPairToSkyBrowserModule(std::string targetId, std::string browserId) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
LINFO("Add browser " + browserId + " to sky browser module");
LINFO("Add target " + targetId + " to sky browser module");
module->addTargetBrowserPair(targetId, browserId);
return 0;
}
/**
* 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, equatorial Cartesian coordinates,
* if the image has celestial coordinates, credits text, credits url
* and the identifier of the image which is a unique number.
*/
int getListOfImages(lua_State* L) {
[[codegen::luawrap]] ghoul::Dictionary getListOfImages() {
// Send image list to GUI
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getListOfImages");
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
// 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";
@@ -226,79 +234,64 @@ int getListOfImages(lua_State* L) {
}
// Create Lua table to send to the GUI
lua_newtable(L);
ghoul::Dictionary list;
for (int i = 0; i < module->nLoadedImages(); i++) {
const ImageData& img = module->getWwtDataHandler()->getImage(i);
using namespace std::string_literals;
// Index for current ImageData
ghoul::lua::push(L, i + 1);
lua_newtable(L);
// Push ("Key", value)
ghoul::lua::push(L, "name", img.name);
lua_settable(L, -3);
ghoul::lua::push(L, "thumbnail", img.thumbnailUrl);
lua_settable(L, -3);
ghoul::lua::push(L, "ra", img.equatorialSpherical.x);
lua_settable(L, -3);
ghoul::lua::push(L, "dec", img.equatorialSpherical.y);
lua_settable(L, -3);
ghoul::lua::push(L, "cartesianDirection", img.equatorialCartesian);
lua_settable(L, -3);
ghoul::lua::push(L, "hasCelestialCoords", img.hasCelestialCoords);
lua_settable(L, -3);
ghoul::lua::push(L, "credits", img.credits);
lua_settable(L, -3);
ghoul::lua::push(L, "creditsUrl", img.creditsUrl);
lua_settable(L, -3);
ghoul::lua::push(L, "identifier", std::to_string(i));
lua_settable(L, -3);
ghoul::Dictionary image;
image.setValue("name", img.name);
image.setValue("thumbnail", img.thumbnailUrl);
image.setValue("ra", img.equatorialSpherical.x);
image.setValue("dec", img.equatorialSpherical.y);
image.setValue("cartesianDirection", img.equatorialCartesian);
image.setValue("hasCelestialCoords", img.hasCelestialCoords);
image.setValue("credits", img.credits);
image.setValue("creditsUrl", img.creditsUrl);
image.setValue("identifier", std::to_string(i));
// Index for current ImageData
// Set table for the current ImageData
lua_settable(L, -3);
list.setValue(std::to_string(i + 1), image);
}
return 1;
return list;
}
int getTargetData(lua_State* L) {
// Send image list to GUI
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::getTargetData");
/**
* Returns a table of data regarding the current view and the sky browsers
* and targets.
* \return Dictionary of data regarding the current targets
*/
[[codegen::luawrap]] ghoul::Dictionary getTargetData() {
using namespace std::string_literals;
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
lua_newtable(L);
ghoul::Dictionary data;
// Add the window data for OpenSpace
ghoul::lua::push(L, "OpenSpace");
lua_newtable(L);
// The current viewport data for OpenSpace
ghoul::Dictionary openSpace;
// Camera directions
glm::dvec3 cartesianCam = skybrowser::cameraDirectionEquatorial();
glm::dvec2 sphericalCam = skybrowser::cartesianToSpherical(cartesianCam);
// Calculate the smallest FOV of vertical and horizontal
glm::dvec2 fovs = skybrowser::fovWindow();
double FOV = std::min(fovs.x, fovs.y);
// Push window data
ghoul::lua::push(L, "windowHFOV", FOV);
lua_settable(L, -3);
ghoul::lua::push(L, "cartesianDirection", cartesianCam);
lua_settable(L, -3);
ghoul::lua::push(L, "ra", sphericalCam.x);
lua_settable(L, -3);
ghoul::lua::push(L, "dec", sphericalCam.y);
lua_settable(L, -3);
ghoul::lua::push(L, "selectedBrowserId", module->selectedBrowserId());
lua_settable(L, -3);
ghoul::lua::push(L, "selectedTargetId", module->selectedTargetId());
lua_settable(L, -3);
ghoul::lua::push(L, "isFacingCamera", module->isSelectedPairFacingCamera());
lua_settable(L, -3);
ghoul::lua::push(L, "isUsingRadiusAzimuthElevation", module->isSelectedPairUsingRae());
lua_settable(L, -3);
ghoul::lua::push(L, "cameraInSolarSystem", module->isCameraInSolarSystem());
lua_settable(L, -3);
// Set window data
openSpace.setValue("windowHFOV", FOV);
openSpace.setValue("cartesianDirection", cartesianCam);
openSpace.setValue("ra", sphericalCam.x);
openSpace.setValue("dec", sphericalCam.y);
openSpace.setValue("selectedBrowserId", module->selectedBrowserId());
openSpace.setValue("selectedTargetId", module->selectedTargetId());
openSpace.setValue("isFacingCamera", module->isSelectedPairFacingCamera());
openSpace.setValue("isUsingRadiusAzimuthElevation", module->isSelectedPairUsingRae());
openSpace.setValue("cameraInSolarSystem", module->isCameraInSolarSystem());
// Set table for the current ImageData
lua_settable(L, -3);
data.setValue("OpenSpace", openSpace);
// Pass data for all the browsers and the corresponding targets
if (module->isCameraInSolarSystem()) {
@@ -320,85 +313,76 @@ int getTargetData(lua_State* L) {
glm::dvec2 spherical = pair->targetDirectionEquatorial();
glm::dvec3 cartesian = skybrowser::sphericalToCartesian(spherical);
ghoul::lua::push(L, id);
lua_newtable(L);
// Push ("Key", value)
ghoul::lua::push(L, "id", id);
lua_settable(L, -3);
ghoul::lua::push(L, "name", pair->browserGuiName());
lua_settable(L, -3);
ghoul::lua::push(L, "FOV", pair->verticalFov());
lua_settable(L, -3);
ghoul::lua::push(L, "selectedImages", selectedImagesVector);
lua_settable(L, -3);
ghoul::lua::push(L, "cartesianDirection", cartesian);
lua_settable(L, -3);
ghoul::lua::push(L, "ra", spherical.x);
lua_settable(L, -3);
ghoul::lua::push(L, "dec", spherical.y);
lua_settable(L, -3);
ghoul::lua::push(L, "color", pair->borderColor());
lua_settable(L, -3);
ghoul::lua::push(L, "size", pair->size());
lua_settable(L, -3);
ghoul::Dictionary target;
// Set ("Key", value)
target.setValue("id", id);
target.setValue("name", pair->browserGuiName());
target.setValue("FOV", static_cast<double>(pair->verticalFov()));
target.setValue("selectedImages", selectedImagesVector);
target.setValue("cartesianDirection", cartesian);
target.setValue("ra", spherical.x);
target.setValue("dec", spherical.y);
target.setValue("color", pair->borderColor());
target.setValue("size", glm::dvec2(pair->size()));
// Set table for the current target
lua_settable(L, -3);
data.setValue(id, target);
}
}
return 1;
return data;
}
int adjustCamera(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::adjustCamera");
const std::string id = ghoul::lua::value<std::string>(L, 1);
/**
* Takes an identifier to a sky browser or sky target. Rotates the camera
* so that the target is placed in the center of the view.
* \param id
*/
[[codegen::luawrap]] void adjustCamera(std::string id) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
if (module->isCameraInSolarSystem()) {
module->lookAtTarget(id);
}
return 0;
}
int setOpacityOfImageLayer(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setOpacityOfImageLayer");
auto [id, i, opacity] = ghoul::lua::values<std::string, int, double>(L);
/**
* Takes an identifier to a sky browser or sky target, an index to an image
* and a value for the opacity.
* \param id Identifier
* \param i Image index
* \param opacity
*/
[[codegen::luawrap]] void setOpacityOfImageLayer(std::string id, int i, double opacity) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* found = module->getPair(id);
if (found) {
found->setImageOpacity(i, opacity);
}
return 0;
}
int centerTargetOnScreen(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::centerTargetOnScreen");
const std::string id = ghoul::lua::value<std::string>(L, 1);
/**
* Takes an identifier to a sky browser and animates its corresponding
* target to the center of the current view.
* \param id Identifier
*/
[[codegen::luawrap]] void centerTargetOnScreen(std::string id) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* pair = module->getPair(id);
if (pair) {
pair->centerTargetOnScreen();
}
return 0;
}
int setSelectedBrowser(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setSelectedBrowser");
const std::string id = ghoul::lua::value<std::string>(L, 1);
/**
* Takes an identifier to a sky browser or target. Sets that sky browser
* currently selected.
* \param id
*/
[[codegen::luawrap]] void setSelectedBrowser(std::string id) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
module->setSelectedBrowser(id);
return 0;
}
int createTargetBrowserPair(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::createTargetBrowserPair");
/**
* Creates a sky browser and a target.
*/
[[codegen::luawrap]] void createTargetBrowserPair() {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
int noOfPairs = module->nPairs();
@@ -412,7 +396,7 @@ int createTargetBrowserPair(lua_State* L) {
glm::dvec3 galacticTarget = skybrowser::localCameraToGalactic(positionTarget);
std::string guiPath = "/SkyBrowser";
std::string url = "https://data.openspaceproject.com/dist/skybrowser/page/";
double fov = 5.0;
double fov = 70.0;
double size = skybrowser::sizeFromFov(fov, galacticTarget);
const std::string browser = "{"
@@ -477,13 +461,12 @@ int createTargetBrowserPair(lua_State* L) {
"openspace.skybrowser.setSelectedBrowser('" + idBrowser + "');",
scripting::ScriptEngine::RemoteScripting::No
);
return 0;
}
int removeTargetBrowserPair(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeTargetBrowserPair");
std::string id = ghoul::lua::value<std::string>(L, 1);
/**
* Takes in identifier to a sky browser or target and removes them.
* \param id Identifier
*/
[[codegen::luawrap]] void removeTargetBrowserPair(std::string id) {
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
TargetBrowserPair* found = module->getPair(id);
if (found) {
@@ -503,28 +486,32 @@ int removeTargetBrowserPair(lua_State* L) {
scripting::ScriptEngine::RemoteScripting::Yes
);
}
return 0;
}
int translateScreenSpaceRenderable(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 5, "lua::translateScreenSpaceRenderable");
auto [id, startX, startY, transX, transY] =
ghoul::lua::values<std::string, float, float, float, float>(L);
/**
* Takes an identifier to a sky browser or sky target and the [x, y]
* starting position and the [x, y] translation vector.
* \param id Identifier
* \param startX Starting x-position
* \param startY Starting y-position
* \param transX Translation x-value
* \param transY Translation y-value
*/
[[codegen::luawrap]] void translateScreenSpaceRenderable(std::string id, float startX,
float startY, float transX,
float transY) {
ScreenSpaceRenderable* renderable = global::renderEngine->screenSpaceRenderable(id);
if (renderable) {
renderable->translate(glm::vec2(transX, transY), glm::vec2(startX, startY));
}
return 0;
}
int removeSelectedImageInBrowser(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::removeSelectedImageInBrowser");
auto [id, i] = ghoul::lua::values<std::string, int>(L);
/**
* Takes an identifier to a sky browser or target and an index to an
* image. Removes that image from that sky browser.
* \param id Identifier
* \i Index of image
*/
[[codegen::luawrap]] void removeSelectedImageInBrowser(std::string id, int i) {
// Get browser
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
const ImageData& image = module->getWwtDataHandler()->getImage(i);
@@ -533,14 +520,16 @@ int removeSelectedImageInBrowser(lua_State* L) {
if (pair) {
pair->removeSelectedImage(i);
}
return 0;
}
int setEquatorialAim(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setEquatorialAim");
auto [id, ra, dec] = ghoul::lua::values<std::string, double, double>(L);
/**
* Takes the identifier of a sky browser or a sky target and equatorial
* coordinates Right Ascension and Declination. The target will animate to
* this coordinate and the browser will display the coordinate.
* \param id Identifier
* \param ra Right Ascension
* \param dec Declination
*/
[[codegen::luawrap]] void setEquatorialAim(std::string id, double ra, double dec) {
// Get module
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
@@ -548,14 +537,14 @@ int setEquatorialAim(lua_State* L) {
if (pair) {
pair->setEquatorialAim(glm::dvec2(ra, dec));
}
return 0;
}
int setVerticalFov(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::setVerticalFov");
auto [id, vfov] = ghoul::lua::values<std::string, float>(L);
/**
* Takes an identifier to a sky browser or a sky target and a vertical
* field of view. Changes the field of view as specified by the input.
* \param id Identifier
* \param vfov Vertical Field of View
*/
[[codegen::luawrap]] void setVerticalFov(std::string id, float vfov) {
// Get module
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
@@ -563,14 +552,16 @@ int setVerticalFov(lua_State* L) {
if (pair) {
pair->setVerticalFov(vfov);
}
return 0;
}
int setBorderColor(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 4, "lua::setBorderColor");
auto [id, r, g, b] = ghoul::lua::values<std::string, int, int, int>(L);
/**
* Takes an identifier to a sky browser or a sky target and a rgb color
* in the ranges [0, 255].
* \param id Identifier
* \param r Red
* \param g Green
* \param b Blue
*/
[[codegen::luawrap]] void setBorderColor(std::string id, int r, int g, int b) {
glm::ivec3 color{ r, g, b };
// Get module
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
@@ -579,14 +570,15 @@ int setBorderColor(lua_State* L) {
if (pair) {
pair->setBorderColor(color);
}
return 0;
}
int setScreenSpaceSize(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setScreenSpaceSize");
auto [id, sizeX, sizeY] = ghoul::lua::values<std::string, float, float>(L);
/**
* Sets the screen space size of the sky browser to the numbers specified
* by the input [x, y].
* \param id
* \param sizeX Size on the x-axis
* \param sizeY Size on the y-axis
*/
[[codegen::luawrap]] void setScreenSpaceSize(std::string id, float sizeX, float sizeY) {
// Get module
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
@@ -594,13 +586,12 @@ int setScreenSpaceSize(lua_State* L) {
if (pair) {
pair->setScreenSpaceSize(glm::vec2(sizeX, sizeY));
}
return 0;
}
int addRenderCopy(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::addRenderCopy");
auto [id] = ghoul::lua::values<std::string>(L);
/**
* Takes an identifier to a sky browser and adds a rendered copy to it.
* \param id Identifier
*/
[[codegen::luawrap]] void addRenderCopy(std::string id) {
// Get module
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
@@ -608,14 +599,13 @@ int addRenderCopy(lua_State* L) {
if (pair) {
pair->browser()->addRenderCopy();
}
return 0;
}
int removeRenderCopy(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeRenderCopy");
auto [id] = ghoul::lua::values<std::string>(L);
/**
* Takes an identifier to a sky browser and removes the latest added
* rendered copy to it.
* \param id Identifier
*/
[[codegen::luawrap]] void removeRenderCopy(std::string id) {
// Get module
SkyBrowserModule* module = global::moduleEngine->module<SkyBrowserModule>();
@@ -623,7 +613,8 @@ int removeRenderCopy(lua_State* L) {
if (pair) {
pair->browser()->removeRenderCopy();
}
return 0;
}
} // namespace openspace::skybrowser::luafunctions
#include "skybrowsermodule_lua_codegen.cpp"
} // namespace

View File

@@ -103,8 +103,8 @@ Browser::Browser(const ghoul::Dictionary& dictionary)
_renderHandler = new RenderHandler();
_keyboardHandler = new WebKeyboardHandler();
_browserInstance = std::make_unique<BrowserInstance>(
_renderHandler,
_keyboardHandler
_renderHandler.get(),
_keyboardHandler.get()
);
WebBrowserModule* webBrowser = global::moduleEngine->module<WebBrowserModule>();

View File

@@ -53,7 +53,7 @@ namespace {
{
"CrosshairSize",
"Crosshair Size",
"Determines the size of the crosshair."
"Determines the size of the crosshair. The size is determined in fov (degrees). "
};
constexpr const openspace::properties::Property::PropertyInfo RectangleThresholdInfo =
@@ -85,12 +85,6 @@ namespace {
"The thickness of the line of the target. The larger number, the thicker line."
};
constexpr const openspace::properties::Property::PropertyInfo SmallestFovInfo = {
"SmallestFov",
"Smallest Vertical Field Of View",
"The smallest field of view that the target will display on screen."
};
struct [[codegen::Dictionary(RenderableSkyTarget)]] Parameters {
// [[codegen::verbatim(crossHairSizeInfo.description)]]
std::optional<float> crossHairSize;
@@ -106,9 +100,6 @@ namespace {
// [[codegen::verbatim(LineWidthInfo.description)]]
std::optional<float> lineWidth;
// [[codegen::verbatim(SmallestFovInfo.description)]]
std::optional<float> smallestFov;
};
#include "renderableskytarget_codegen.cpp"
@@ -122,7 +113,6 @@ namespace openspace {
, _stopAnimationThreshold(AnimationThresholdInfo, 5.0f, 1.f, 10.f)
, _animationSpeed(AnimationSpeedInfo, 5.0, 0.1, 10.0)
, _lineWidth(LineWidthInfo, 13.f, 1.f, 100.f)
, _smallestFov(SmallestFovInfo, 3.0, 0.5, 20.0)
, _borderColor(220, 220, 220)
{
// Handle target dimension property
@@ -131,14 +121,12 @@ namespace openspace {
_showRectangleThreshold = p.rectangleThreshold.value_or(_showRectangleThreshold);
_stopAnimationThreshold = p.crossHairSize.value_or(_stopAnimationThreshold);
_animationSpeed = p.animationSpeed.value_or(_animationSpeed);
_smallestFov = p.smallestFov.value_or(_smallestFov);
addProperty(_crossHairSize);
addProperty(_showRectangleThreshold);
addProperty(_stopAnimationThreshold);
addProperty(_animationSpeed);
addProperty(_lineWidth);
addProperty(_smallestFov);
}
void RenderableSkyTarget::bindTexture() {}
@@ -186,7 +174,7 @@ void RenderableSkyTarget::render(const RenderData& data, RendererTasks&) {
_shader->setUniform("crossHairSize", _crossHairSize);
_shader->setUniform("showRectangle", showRectangle);
_shader->setUniform("lineWidth", _lineWidth);
_shader->setUniform("lineWidth", _lineWidth * 0.0001f);
_shader->setUniform("dimensions", _dimensions);
_shader->setUniform("lineColor", color);
_shader->setUniform("fov", static_cast<float>(_verticalFov));
@@ -279,10 +267,6 @@ double RenderableSkyTarget::stopAnimationThreshold() const {
return _stopAnimationThreshold * 0.0001;
}
double RenderableSkyTarget::smallestFov() const {
return _smallestFov;
}
void RenderableSkyTarget::setOpacity(float opacity) {
_opacity = opacity;
}

View File

@@ -61,12 +61,22 @@ namespace {
"be interactive. The position is in RAE (Radius, Azimuth, Elevation) 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."
};
struct [[codegen::Dictionary(ScreenSpaceSkyBrowser)]] Parameters {
// [[codegen::verbatim(AnimationSpeedInfo.description)]]
std::optional<double> animationSpeed;
// [[codegen::verbatim(TextureQualityInfo.description)]]
std::optional<float> textureQuality;
// [[codegen::verbatim(RenderOnMasterInfo.description)]]
std::optional<bool> renderOnlyOnMaster;
};
#include "screenspaceskybrowser_codegen.cpp"
@@ -99,6 +109,7 @@ namespace openspace {
, WwtCommunicator(dictionary)
, _animationSpeed(AnimationSpeedInfo, 5.0, 0.1, 10.0)
, _textureQuality(TextureQualityInfo, 1.f, 0.25f, 1.f)
, _renderOnlyOnMaster(RenderOnMasterInfo, false)
{
_identifier = makeUniqueIdentifier(_identifier);
@@ -106,11 +117,13 @@ namespace openspace {
const Parameters p = codegen::bake<Parameters>(dictionary);
_textureQuality = p.textureQuality.value_or(_textureQuality);
_animationSpeed = p.animationSpeed.value_or(_animationSpeed);
_renderOnlyOnMaster = p.renderOnlyOnMaster.value_or(_renderOnlyOnMaster);
addProperty(_url);
addProperty(_browserPixeldimensions);
addProperty(_reload);
addProperty(_textureQuality);
addProperty(_renderOnlyOnMaster);
_textureQuality.onChange([this]() {
_textureDimensionsIsDirty = true;
@@ -151,7 +164,7 @@ glm::dvec2 ScreenSpaceSkyBrowser::fineTuneVector(glm::dvec2 drag) {
glm::dvec2 resultRelativeOs = angleResult / openSpaceFOV;
// Convert to screen space coordinate system
glm::dvec2 convertToScreenSpace{ (2 * skybrowser::windowRatio()), 2.f };
glm::dvec2 convertToScreenSpace{ (2.f * skybrowser::windowRatio()), 2.f };
glm::dvec2 result = - convertToScreenSpace * resultRelativeOs;
return result;
}
@@ -228,12 +241,23 @@ void ScreenSpaceSkyBrowser::incrementallyAnimateToFov(float deltaTime) {
void ScreenSpaceSkyBrowser::render() {
WwtCommunicator::render();
draw(
globalRotationMatrix() *
translationMatrix() *
localRotationMatrix() *
scaleMatrix()
);
// 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) {
draw(
globalRotationMatrix() *
translationMatrix() *
localRotationMatrix() *
scaleMatrix()
);
}
// Render a copy that is not interactive
for (const std::unique_ptr<properties::Vec3Property>& copy : _renderCopies) {
@@ -274,7 +298,7 @@ void ScreenSpaceSkyBrowser::setVerticalFovWithScroll(float scroll) {
float x = _verticalFov;
float zoomFactor = atan(x / 50.f) + exp(x / 40.f) - 0.999999f;
float zoom = scroll > 0.f ? -zoomFactor : zoomFactor;
_verticalFov = std::clamp(_verticalFov + zoom, 0.001f, 70.0f);
_verticalFov = std::clamp(_verticalFov + zoom, 0.000001f, 70.0f);
}
void ScreenSpaceSkyBrowser::bindTexture() {

View File

@@ -92,24 +92,6 @@ void TargetBrowserPair::aimTargetGalactic(glm::dvec3 direction) {
);
}
void TargetBrowserPair::setFovTarget(double fov) {
std::string id = _targetNode->identifier();
std::string renderableId = _targetRenderable->identifier();
// Uris for properties
std::string sizeUri = "Scene." + id + "." + renderableId + ".Size";
double renderedFov = std::max(fov, _targetRenderable->smallestFov());
double size = skybrowser::sizeFromFov(renderedFov, _targetNode->worldPosition());
std::string setValue = "openspace.setPropertyValueSingle('";
openspace::global::scriptEngine->queueScript(
setValue + sizeUri + "', " + std::to_string(size) + ");",
scripting::ScriptEngine::RemoteScripting::Yes
);
_targetRenderable->setVerticalFov(renderedFov);
}
bool TargetBrowserPair::checkMouseIntersection(const glm::vec2& mousePosition) {
_selected = _browser->isIntersecting(mousePosition) ? _browser : nullptr;
@@ -162,7 +144,7 @@ void TargetBrowserPair::synchronizeAim() {
// target, send the locked coordinates to wwt
glm::dvec2 aim = targetDirectionEquatorial();
_browser->setEquatorialAim(aim);
setFovTarget(_browser->verticalFov());
_targetRenderable->setVerticalFov(_browser->verticalFov());
}
}
@@ -176,7 +158,7 @@ bool TargetBrowserPair::isEnabled() const {
void TargetBrowserPair::initialize() {
_targetRenderable->setColor(_browser->borderColor());
_targetRenderable->setDimensions(_browser->browserPixelDimensions());
_targetRenderable->setDimensions(_browser->screenSpaceDimensions());
_browser->updateBorderColor();
}
@@ -271,7 +253,7 @@ void TargetBrowserPair::setIsSyncedWithWwt(bool isSynced) {
void TargetBrowserPair::setVerticalFov(float vfov) {
_browser->setVerticalFov(vfov);
setFovTarget(vfov);
_targetRenderable->setVerticalFov(vfov);
}
void TargetBrowserPair::setEquatorialAim(const glm::dvec2& aim) {
@@ -290,6 +272,7 @@ void TargetBrowserPair::setBorderColor(const glm::ivec3& color) {
void TargetBrowserPair::setScreenSpaceSize(const glm::vec2& dimensions) {
_browser->setScreenSpaceSize(dimensions);
_targetRenderable->setDimensions(dimensions);
}
void TargetBrowserPair::setVerticalFovWithScroll(float scroll) {
@@ -303,7 +286,7 @@ void TargetBrowserPair::incrementallyAnimateToCoordinate(double deltaTime) {
}
else if (_browser->isAnimated()) {
_browser->incrementallyAnimateToFov(static_cast<float>(deltaTime));
setFovTarget(_browser->verticalFov());
_targetRenderable->setVerticalFov(_browser->verticalFov());
}
}

View File

@@ -188,8 +188,9 @@ glm::dvec2 fovWindow() {
double angleBetweenVectors(const glm::dvec3& start, const glm::dvec3& end) {
// Find smallest angle between the two vectors
double cos = glm::dot(start, end) / (glm::length(start) * glm::length(end));
return std::acos(cos);
double cos = glm::dot(glm::normalize(start), glm::normalize(end));
// Ensure cos is within defined interval [-1,1]
return std::acos(std::clamp(cos, -1.0, 1.0));
}
glm::dmat4 incrementalAnimationMatrix(const glm::dvec3& start, const glm::dvec3& end,

View File

@@ -42,6 +42,7 @@
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/util/coordinateconversion.h>
#include <openspace/util/factorymanager.h>
#include <openspace/util/spicemanager.h>
#include <ghoul/misc/assert.h>
@@ -140,28 +141,13 @@ std::vector<documentation::Documentation> SpaceModule::documentations() const {
}
scripting::LuaLibrary SpaceModule::luaLibrary() const {
scripting::LuaLibrary res;
res.name = "space";
res.functions = {
return {
"space",
{
"convertFromRaDec",
&space::luascriptfunctions::convertFromRaDec,
"string/double, string/double, double",
"Returns the cartesian world position of a ra dec coordinate with distance. "
"If the coordinate is given as strings the format should be ra 'XhYmZs' and "
"dec 'XdYmZs'. If the coordinate is given as numbers the values should be "
"in degrees."
},
{
"convertToRaDec",
&space::luascriptfunctions::convertToRaDec,
"double, double, double",
"Returns the formatted ra, dec strings and distance for a given cartesian "
"world coordinate."
codegen::lua::ConvertFromRaDec,
codegen::lua::ConvertToRaDec
}
};
return res;
}
} // namespace openspace

View File

@@ -22,47 +22,61 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/util/coordinateconversion.h>
namespace {
namespace openspace::space::luascriptfunctions {
int convertFromRaDec(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::convertFromRaDec");
/**
* Returns the cartesian world position of a ra dec coordinate with distance. If the
* coordinate is given as strings the format should be ra 'XhYmZs' and dec 'XdYmZs'. If
* the coordinate is given as numbers the values should be in degrees.
*/
[[codegen::luawrap]] glm::dvec3 convertFromRaDec(
std::variant<double, std::string> rightAscension,
std::variant<double, std::string> declination,
double distance)
{
using namespace openspace;
glm::dvec2 degrees = glm::dvec2(0.0);
if (ghoul::lua::hasValue<std::string>(L, 1) &&
ghoul::lua::hasValue<std::string>(L, 2))
if (std::holds_alternative<double>(rightAscension) &&
std::holds_alternative<double>(declination))
{
auto [ra, dec] = ghoul::lua::values<std::string, std::string>(L);
degrees = icrsToDecimalDegrees(ra, dec);
degrees = glm::dvec2(
std::get<double>(rightAscension),
std::get<double>(declination)
);
}
else if (ghoul::lua::hasValue<double>(L, 1) && ghoul::lua::hasValue<double>(L, 2)) {
auto [x, y] = ghoul::lua::values<double, double>(L);
degrees.x = x;
degrees.y = y;
else if (std::holds_alternative<std::string>(rightAscension) &&
std::holds_alternative<std::string>(declination))
{
degrees = icrsToDecimalDegrees(
std::get<std::string>(rightAscension),
std::get<std::string>(declination)
);
}
else {
throw ghoul::lua::LuaRuntimeException(
throw ghoul::lua::LuaError(
"Ra and Dec have to be of the same type, either String or Number"
);
}
double distance = ghoul::lua::value<double>(L);
glm::dvec3 pos = icrsToGalacticCartesian(degrees.x, degrees.y, distance);
ghoul::lua::push(L, pos);
return 1;
return pos;
}
int convertToRaDec(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::convertToRaDec");
auto [x, y, z] = ghoul::lua::values<double, double, double>(L);
/**
* Returns the formatted ra, dec strings and distance for a given cartesian world
* coordinate.
*/
[[codegen::luawrap]] std::tuple<std::string, std::string, double> convertToRaDec(double x,
double y,
double z)
{
using namespace openspace;
glm::dvec3 deg = galacticCartesianToIcrs(x, y, z);
std::pair<std::string, std::string> raDecPair = decimalDegreesToIcrs(deg.x, deg.y);
// Ra, Dec, Distance
ghoul::lua::push(L, raDecPair.first, raDecPair.second, deg.z);
return 3;
return { raDecPair.first, raDecPair.second, deg.z };
}
} // namespace openspace::space::luascriptfunctions
#include "spacemodule_lua_codegen.cpp"
} // namespace

View File

@@ -315,10 +315,27 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines)
str >> entry.position.x >> entry.position.y >> entry.position.z;
allZero &= (entry.position == glm::vec3(0.0));
if (!str.good()) {
throw ghoul::RuntimeError(fmt::format(
"Error loading position information out of data line {} in file {}. "
"Value was not a number",
res.entries.size(), path
));
}
entry.data.resize(nDataValues);
for (int i = 0; i < nDataValues; i += 1) {
str >> entry.data[i];
bool isGood = str.good();
allZero &= (entry.data[i] == 0.0);
if (!str.good()) {
throw ghoul::RuntimeError(fmt::format(
"Error loading data value {} out of data line {} in file {}. "
"Value was not a number",
i, res.entries.size(), path
));
}
}
if (skipAllZeroLines && allZero) {

View File

@@ -28,10 +28,15 @@
#include <modules/statemachine/include/statemachine.h>
#include <modules/statemachine/include/transition.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/misc.h>
#include <string>
#include <optional>
#include "statemachinemodule_lua.inl"
@@ -140,78 +145,20 @@ void StateMachineModule::saveToFile(const std::string& filename,
}
scripting::LuaLibrary StateMachineModule::luaLibrary() const {
scripting::LuaLibrary res;
res.name = "statemachine";
res.functions = {
{
"createStateMachine",
&luascriptfunctions::createStateMachine,
"table, table, [string]",
"Creates a state machine from a list of states and transitions. See State "
"and Transition documentation for details. The optional thrid argument is "
"the identifier of the desired initial state. If left out, the first state "
"in the list will be used."
},
return {
"statemachine",
{
"destroyStateMachine",
&luascriptfunctions::destroyStateMachine,
"",
"Destroys the current state machine and deletes all the memory."
},
{
"goToState",
&luascriptfunctions::goToState,
"string",
"Triggers a transition from the current state to the state with the given "
"identifier. Requires that the specified string corresponds to an existing "
"state, and that a transition between the two states exists."
},
{
"setInitialState",
&luascriptfunctions::setInitialState,
"string",
"Immediately sets the current state to the state with the given name, if "
"it exists. This is done without doing a transition and completely ignores "
"the previous state."
},
{
"currentState",
&luascriptfunctions::currentState,
"",
"Returns the string name of the current state that the statemachine is in."
},
{
"possibleTransitions",
&luascriptfunctions::possibleTransitions,
"",
"Returns a list with the identifiers of all the states that can be "
"transitioned to from the current state."
},
{
"canGoToState",
&luascriptfunctions::canGoToState,
"string",
"Returns true if there is a defined transition between the current state and "
"the given string name of a state, otherwise false"
},
{
"printCurrentStateInfo",
&luascriptfunctions::printCurrentStateInfo,
"",
"Prints information about the current state and possible transitions to the "
"log."
},
{
"saveToDotFile",
&luascriptfunctions::saveToDotFile,
"string, [string]",
"Saves the current state machine to a .dot file as a directed graph. The "
"resulting graph can be rendered using external tools such as Graphviz. "
"The first parameter is the name of the file, and the second is an optional "
"directory. If no directory is given, the file is saved to the temp folder."
codegen::lua::CreateStateMachine,
codegen::lua::DestroyStateMachine,
codegen::lua::GoToState,
codegen::lua::SetInitialState,
codegen::lua::CurrentState,
codegen::lua::PossibleTransitions,
codegen::lua::CanGoToState,
codegen::lua::PrintCurrentStateInfo,
codegen::lua::SaveToDotFile
}
};
return res;
}
std::vector<documentation::Documentation> StateMachineModule::documentations() const {

View File

@@ -22,90 +22,91 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/statemachine/statemachinemodule.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/misc.h>
#include <optional>
namespace openspace::luascriptfunctions {
int createStateMachine(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::createStateMachine");
auto [states, transitions, startState] = ghoul::lua::values<
ghoul::Dictionary, ghoul::Dictionary, std::optional<std::string>
>(L);
namespace {
/**
* Creates a state machine from a list of states and transitions. See State and Transition
* documentation for details. The optional thrid argument is the identifier of the desired
* initial state. If left out, the first state in the list will be used.
*/
[[codegen::luawrap]] void createStateMachine(ghoul::Dictionary states,
ghoul::Dictionary transitions,
std::optional<std::string> startState)
{
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
module->initializeStateMachine(
std::move(states),
std::move(transitions),
std::move(startState)
);
return 0;
}
int destroyStateMachine(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::destroyStateMachine");
// Destroys the current state machine and deletes all the memory.
[[codegen::luawrap]] void destroyStateMachine() {
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
module->deinitializeStateMachine();
return 0;
}
int goToState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::goToState");
std::string newState = ghoul::lua::value<std::string>(L);
/**
* Triggers a transition from the current state to the state with the given identifier.
* Requires that the specified string corresponds to an existing state, and that a
* transition between the two states exists.
*/
[[codegen::luawrap]] void goToState(std::string newState) {
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
module->transitionTo(newState);
LINFOC("StateMachine", "Transitioning to " + newState);
return 0;
}
int setInitialState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setStartState");
std::string startState = ghoul::lua::value<std::string>(L);
/**
* Immediately sets the current state to the state with the given name, if it exists. This
* is done without doing a transition and completely ignores the previous state.
*/
[[codegen::luawrap]] void setInitialState(std::string startState) {
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
module->setInitialState(startState);
LINFOC("StateMachine", "Initial state set to: " + startState);
return 0;
}
int currentState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::currentState");
// Returns the string name of the current state that the statemachine is in.
[[codegen::luawrap]] std::string currentState() {
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
std::string currentState = module->currentState();
ghoul::lua::push(L, std::move(currentState));
return 1;
return currentState;
}
int possibleTransitions(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::possibleTransitions");
/**
* Returns a list with the identifiers of all the states that can be transitioned to from
* the current state.
*/
[[codegen::luawrap]] std::vector<std::string> possibleTransitions() {
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
std::vector<std::string> transitions = module->possibleTransitions();
ghoul::lua::push(L, transitions);
return 1;
return transitions;
}
int canGoToState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::canGoToState");
std::string state = ghoul::lua::value<std::string>(L);
/**
* Returns true if there is a defined transition between the current state and the given
* string name of a state, otherwise false.
*/
[[codegen::luawrap]] bool canGoToState(std::string state) {
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
ghoul::lua::push(L, module->canGoToState(state));
return 1;
bool canTransition = module->canGoToState(state);
return canTransition;
}
int printCurrentStateInfo(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::printCurrentStateInfo");
/**
* Prints information about the current state and possible transitions to the log.
*/
[[codegen::luawrap]] void printCurrentStateInfo() {
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
if (module->hasStateMachine()) {
std::string currentState = module->currentState();
@@ -119,24 +120,27 @@ int printCurrentStateInfo(lua_State* L) {
else {
LINFOC("StateMachine", "No state machine has been created");
}
return 1;
}
int saveToDotFile(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::saveToDotFile");
auto [filename, directory] =
ghoul::lua::values<std::string, std::optional<std::string>>(L);
/**
* Saves the current state machine to a .dot file as a directed graph. The resulting graph
* can be rendered using external tools such as Graphviz. The first parameter is the name
* of the file, and the second is an optional directory. If no directory is given, the
* file is saved to the temp folder.
*/
[[codegen::luawrap]] void saveToDotFile(std::string filename,
std::optional<std::string> directory)
{
using namespace openspace;
StateMachineModule* module = global::moduleEngine->module<StateMachineModule>();
if (directory.has_value()) {
module->saveToFile(filename, *directory);
}
else {
module->saveToFile(filename);
}
return 0;
}
} //namespace openspace::luascriptfunctions
#include "statemachinemodule_lua_codegen.cpp"
} // namespace

View File

@@ -27,7 +27,9 @@
#include <modules/sync/syncs/httpsynchronization.h>
#include <modules/sync/syncs/urlsynchronization.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/screenspacerenderable.h>
#include <openspace/scripting/lualibrary.h>
@@ -119,30 +121,13 @@ std::vector<documentation::Documentation> SyncModule::documentations() const {
}
scripting::LuaLibrary SyncModule::luaLibrary() const {
scripting::LuaLibrary res;
res.name = "sync";
res.functions = {
return {
"sync",
{
"syncResource",
&luascriptfunctions::syncResource,
"string, number",
"Synchronizes the http resource identified by the name passed as the "
"first parameter and the version provided as the second parameter. The "
"application will hang while the data is being downloaded"
},
{
"unsyncResource",
&luascriptfunctions::unsyncResource,
"string [, number]",
"Unsynchronizes the http resources identified by the name passed as the "
"first parameter by removing all data that was downloaded as part of the "
"original synchronization. If the second parameter is provided, is it "
"the version of the resources that is unsynchronized, if the parameter "
"is not provided, all versions for the specified http resource are "
"removed."
codegen::lua::SyncResource,
codegen::lua::UnsyncResource
}
};
return res;
}
} // namespace openspace

View File

@@ -22,14 +22,15 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
namespace {
namespace openspace::luascriptfunctions {
int syncResource(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::syncResource");
auto [identifier, version] = ghoul::lua::values<std::string, double>(L);
/**
* Synchronizes the http resource identified by the name passed as the first parameter and
* the version provided as the second parameter. The application will hang while the data
* is being downloaded.
*/
[[codegen::luawrap]] bool syncResource(std::string identifier, int version) {
using namespace openspace;
ghoul::Dictionary dict;
dict.setValue("Type", std::string("HttpSynchronization"));
@@ -45,14 +46,20 @@ int syncResource(lua_State* L) {
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
ghoul::lua::push(L, sync->isResolved());
return 1;
bool isResolved = sync->isResolved();
return isResolved;
}
int unsyncResource(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::unsyncResource");
auto [identifier, version] = ghoul::lua::values<std::string, std::optional<int>>(L);
/**
* Unsynchronizes the http resources identified by the name passed as the first parameter
* by removing all data that was downloaded as part of the original synchronization. If
* the second parameter is provided, is it the version of the resources that is
* unsynchronized, if the parameter is not provided, all versions for the specified http
* resource are removed.
*/
[[codegen::luawrap]] void unsyncResource(std::string identifier, std::optional<int> version) {
using namespace openspace;
const SyncModule* module = global::moduleEngine->module<SyncModule>();
std::filesystem::path sync = absPath(module->synchronizationRoot());
std::filesystem::path base = sync / "http" / identifier;
@@ -70,8 +77,8 @@ int unsyncResource(lua_State* L) {
std::filesystem::remove_all(folder);
std::filesystem::remove(base / syncFile);
}
return 0;
}
} // namespace openspace::luascriptfunctions
#include "syncmodule_lua_codegen.cpp"
} // namespace

View File

@@ -55,14 +55,15 @@ cmake_policy(SET CMP0074 NEW)
# Specify the CEF distribution version.
# Release from 04/24/2019 verified to work on Windows.
set(CEF_VERSION "73.1.13+g6e3c989+chromium-73.0.3683.75")
# Release from 03/21/2022 verified to work on Windows.
set(CEF_VERSION "99.2.12+g2977b3a+chromium-99.0.4844.74")
# Removing - micahnyc 03/21/2022
# 73.1.13 has an issue on MacOS: The GUI freezing upon interaction.
# Therefore, we fall back to 3.3578.1867 from 01/29/2019
if (APPLE)
set(CEF_VERSION "3.3578.1867.g0f6d65a")
endif ()
#if (APPLE)
# set(CEF_VERSION "3.3578.1867.g0f6d65a")
#endif ()
# CEF Sandbox is not working with the latest Visual Studio, so we disable it for now.
if (WIN32)

View File

@@ -456,12 +456,10 @@ if(OS_WINDOWS)
# List of CEF binary files.
set(CEF_BINARY_FILES
chrome_elf.dll
d3dcompiler_43.dll
d3dcompiler_47.dll
libcef.dll
libEGL.dll
libGLESv2.dll
natives_blob.bin
snapshot_blob.bin
v8_context_snapshot.bin
#swiftshader
@@ -469,11 +467,9 @@ if(OS_WINDOWS)
# List of CEF resource files.
set(CEF_RESOURCE_FILES
cef.pak
cef_100_percent.pak
cef_200_percent.pak
cef_extensions.pak
devtools_resources.pak
chrome_100_percent.pak
chrome_200_percent.pak
resources.pak
icudtl.dat
locales
)

View File

@@ -41,11 +41,17 @@ namespace openspace {
class DefaultBrowserLauncher : public CefLifeSpanHandler, public CefRequestHandler {
public:
bool OnBeforePopup(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
const CefString& targetUrl, const CefString& targetFrameName,
CefLifeSpanHandler::WindowOpenDisposition targetDisposition, bool userGesture,
const CefPopupFeatures& popupFeatures, CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client, CefBrowserSettings& settings,
bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& targetUrl,
const CefString& targetFrameName,
CefLifeSpanHandler::WindowOpenDisposition targetDisposition,
bool userGesture,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* noJavascriptAccess) override;
//bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,

View File

@@ -48,7 +48,7 @@ BrowserInstance::BrowserInstance(WebRenderHandler* renderer,
: _renderHandler(renderer)
, _keyboardHandler(keyboardHandler)
{
_client = new BrowserClient(_renderHandler, _keyboardHandler);
_client = new BrowserClient(_renderHandler.get(), _keyboardHandler.get());
CefWindowInfo windowInfo;
windowInfo.SetAsWindowless(nullptr);
@@ -62,6 +62,7 @@ BrowserInstance::BrowserInstance(WebRenderHandler* renderer,
_client.get(),
url,
browserSettings,
nullptr,
nullptr
);

View File

@@ -38,6 +38,7 @@ bool DefaultBrowserLauncher::OnBeforePopup(CefRefPtr<CefBrowser>, CefRefPtr<CefF
CefLifeSpanHandler::WindowOpenDisposition,
bool, const CefPopupFeatures&, CefWindowInfo&,
CefRefPtr<CefClient>&, CefBrowserSettings&,
CefRefPtr<CefDictionaryValue>&,
bool*)
{
// never permit CEF popups, always launch in default browser

View File

@@ -94,8 +94,8 @@ ScreenSpaceBrowser::ScreenSpaceBrowser(const ghoul::Dictionary& dictionary)
_renderHandler = new ScreenSpaceRenderHandler;
_keyboardHandler = new WebKeyboardHandler();
_browserInstance = std::make_unique<BrowserInstance>(
_renderHandler,
_keyboardHandler
_renderHandler.get(),
_keyboardHandler.get()
);
_url.onChange([this]() { _isUrlDirty = true; });

View File

@@ -42,8 +42,10 @@ void WebBrowserApp::OnContextCreated(CefRefPtr<CefBrowser>, CefRefPtr<CefFrame>,
void WebBrowserApp::OnBeforeCommandLineProcessing(const CefString&,
CefRefPtr<CefCommandLine> commandLine)
{
commandLine->AppendSwitch("disable-gpu");
commandLine->AppendSwitch("disable-gpu-compositing");
commandLine->AppendSwitch("use-gl=desktop");
commandLine->AppendSwitch("ignore-gpu-blacklist");
commandLine->AppendSwitch("log-gpu-control-list-decisions");
commandLine->AppendSwitch("enable-begin-frame-scheduling");
commandLine->AppendSwitchWithValue("autoplay-policy", "no-user-gesture-required");
}

View File

@@ -1,34 +1,34 @@
openspace.documentation = {
{
Name = "markInterestingNodes",
Arguments = "List of nodes",
Arguments = { sceneGraphNode = "[ String ]" },
Documentation = "This function marks the scene graph nodes identified by name " ..
"as interesting, which will provide shortcut access to focus buttons and " ..
"featured properties."
},
{
Name = "markInterestingTimes",
Arguments = "List of { Name = '...', Time = '...' } or { '<name>', '<time>' }",
Arguments = { times = "[ Table ]" },
Documentation = "This function marks interesting times for the current scene, " ..
"which will create shortcuts for a quick access."
},
{
Name = "removeInterestingNodes",
Arguments = "List of nodes",
Arguments = { sceneGraphNode = "[ String ]" },
Documentation = "This function removes unmarks the scene graph nodes " ..
"identified by name as interesting, thus removing the shortcuts from the " ..
"features properties list."
},
{
Name = "setDefaultGuiSorting",
Arguments = "",
Arguments = {},
Documentation = "This function sets the default GUI sorting for the space " ..
"environment to increasing size, from solar system, through Milky Way, " ..
"Universe and finishing with other elements"
},
{
Name = "setDefaultDashboard",
Arguments = "",
Arguments = {},
Documentation = "This function sets the default values for the dashboard " ..
"consisting of 'DashboardItemDate', 'DashboardItemSimulationIncrement', " ..
"'DashboardItemDistance', 'DashboardItemFramerate', and " ..
@@ -36,7 +36,7 @@ openspace.documentation = {
},
{
Name = "rebindKey",
Arguments = "string, string",
Arguments = { oldKey = "String", newKey = "String" },
Documentation = "Rebinds all scripts from the old key (first argument) to the " ..
"new key (second argument)."
}

View File

@@ -158,6 +158,7 @@ set(OPENSPACE_SOURCE
${OPENSPACE_BASE_DIR}/src/scripting/scriptscheduler.cpp
${OPENSPACE_BASE_DIR}/src/scripting/scriptscheduler_lua.inl
${OPENSPACE_BASE_DIR}/src/scripting/systemcapabilitiesbinding.cpp
${OPENSPACE_BASE_DIR}/src/scripting/systemcapabilitiesbinding_lua.inl
${OPENSPACE_BASE_DIR}/src/util/blockplaneintersectiongeometry.cpp
${OPENSPACE_BASE_DIR}/src/util/boxgeometry.cpp
${OPENSPACE_BASE_DIR}/src/util/collisionhelper.cpp

View File

@@ -243,7 +243,7 @@ std::future<DownloadManager::MemoryFile> DownloadManager::fetchFile(
curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); // NOLINT
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); // NOLINT
// NOLINTNEXTLINE
curl_easy_setopt(curl, CURLOPT_USERAGENT, "OpenSpace"); // NOLINT
curl_easy_setopt(curl, CURLOPT_WRITEDATA, reinterpret_cast<void*>(&file));
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeMemoryCallback); // NOLINT
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L); // NOLINT

View File

@@ -25,6 +25,7 @@
#include <openspace/engine/moduleengine.h>
#include <openspace/documentation/documentation.h>
#include <openspace/engine/globals.h>
#include <openspace/moduleregistration.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/scripting/scriptengine.h>
@@ -168,12 +169,7 @@ scripting::LuaLibrary ModuleEngine::luaLibrary() {
return {
"modules",
{
{
"isLoaded",
&luascriptfunctions::isLoaded,
"string",
"Checks whether a specific module is loaded"
}
codegen::lua::IsLoaded
}
};
}

View File

@@ -22,28 +22,20 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/globals.h>
#include <ghoul/lua/ghoul_lua.h>
namespace {
namespace openspace::luascriptfunctions {
// Checks whether the passed OpenSpaceModule is loaded.
[[codegen::luawrap]] bool isLoaded(std::string moduleName) {
using namespace openspace;
/**
* \ingroup LuaScripts
* isLoaded(string):
* Checks whether the passed OpenSpaceModule is loaded or not
*/
int isLoaded(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::isLoaded");
const std::string name = ghoul::lua::value<std::string>(L);
const std::vector<OpenSpaceModule*>& modules = global::moduleEngine->modules();
const auto it = std::find_if(
modules.cbegin(), modules.cend(),
[name](OpenSpaceModule* module) { return module->identifier() == name; }
);
ghoul::lua::push(L, it != modules.cend());
return 1;
for (OpenSpaceModule* module : global::moduleEngine->modules()) {
if (module->identifier() == moduleName) {
return true;
}
}
return false;
}
} // namespace openspace::luascriptfunctions
#include "moduleengine_lua_codegen.cpp"
} // namespace

View File

@@ -29,6 +29,7 @@
#include <openspace/documentation/core_registration.h>
#include <openspace/documentation/documentationengine.h>
#include <openspace/engine/configuration.h>
#include <openspace/engine/downloadmanager.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/globalscallbacks.h>
#include <openspace/engine/logfactory.h>
@@ -50,6 +51,7 @@
#include <openspace/rendering/loadingscreen.h>
#include <openspace/rendering/luaconsole.h>
#include <openspace/rendering/renderable.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/asset.h>
#include <openspace/scene/assetmanager.h>
#include <openspace/scene/profile.h>
@@ -71,6 +73,7 @@
#include <openspace/util/timemanager.h>
#include <openspace/util/transformationmanager.h>
#include <ghoul/ghoul.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/font/fontmanager.h>
#include <ghoul/font/fontrenderer.h>
@@ -101,7 +104,7 @@
namespace {
// Helper structs for the visitor pattern of the std::variant
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template <class... Ts> overloaded(Ts...)->overloaded<Ts...>;
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
constexpr const char* _loggerCat = "OpenSpaceEngine";
@@ -180,6 +183,10 @@ void OpenSpaceEngine::initialize() {
LTRACE("OpenSpaceEngine::initialize(begin)");
global::initialize();
// Initialize the general capabilities component
SysCap.addComponent(
std::make_unique<ghoul::systemcapabilities::GeneralCapabilitiesComponent>()
);
_printEvents = global::configuration->isPrintingEvents;
@@ -403,11 +410,8 @@ void OpenSpaceEngine::initializeGL() {
glbinding::Binding::initialize(global::windowDelegate->openGLProcedureAddress);
//glbinding::Binding::useCurrentContext();
LDEBUG("Adding system components");
LDEBUG("Adding OpenGL capabilities components");
// Detect and log OpenCL and OpenGL versions and available devices
SysCap.addComponent(
std::make_unique<ghoul::systemcapabilities::GeneralCapabilitiesComponent>()
);
SysCap.addComponent(
std::make_unique<ghoul::systemcapabilities::OpenGLCapabilitiesComponent>()
);
@@ -1797,61 +1801,14 @@ scripting::LuaLibrary OpenSpaceEngine::luaLibrary() {
return {
"",
{
{
"toggleShutdown",
&luascriptfunctions::toggleShutdown,
"",
"Toggles the shutdown mode that will close the application after the "
"count down timer is reached"
},
{
"writeDocumentation",
&luascriptfunctions::writeDocumentation,
"",
"Writes out documentation files"
},
{
"downloadFile",
&luascriptfunctions::downloadFile,
"",
"Downloads a file from Lua scope"
},
{
"setScreenshotFolder",
&luascriptfunctions::setScreenshotFolder,
"string",
"Sets the folder used for storing screenshots or session recording frames"
},
{
"addTag",
&luascriptfunctions::addTag,
"string, string",
"Adds a tag (second argument) to a scene graph node (first argument)"
},
{
"removeTag",
&luascriptfunctions::removeTag,
"string, string",
"Removes a tag (second argument) from a scene graph node (first argument)"
},
{
"createSingleColorImage",
&luascriptfunctions::createSingleColorImage,
"string, vec3",
"Creates a 1 pixel image with a certain color in the cache folder and "
"returns the path to the file. If a cached file with the given name "
"already exists, the path to that file is returned. The first argument "
"is the name of the file, without extension. The second is the RGB "
"color, given as {r, g, b} with values between 0 and 1."
},
{
"isMaster",
&luascriptfunctions::isMaster,
"",
"Returns whether the current OpenSpace instance is the master node of a "
"cluster configuration. If this instance is not part of a cluster, this "
"function also returns 'true'."
}
codegen::lua::ToggleShutdown,
codegen::lua::WriteDocumentation,
codegen::lua::SetScreenshotFolder,
codegen::lua::AddTag,
codegen::lua::RemoveTag,
codegen::lua::DownloadFile,
codegen::lua::CreateSingleColorImage,
codegen::lua::IsMaster
},
{
absPath("${SCRIPTS}/core_scripts.lua")

View File

@@ -22,48 +22,29 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/documentation/documentation.h>
#include <openspace/documentation/verifier.h>
#include <openspace/engine/downloadmanager.h>
#include <openspace/engine/globals.h>
#include <openspace/properties/triggerproperty.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scenegraphnode.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <filesystem>
namespace openspace::luascriptfunctions {
namespace {
/**
* \ingroup LuaScripts
* toggleShutdown():
* Toggles the shutdown mode that will close the application after the countdown timer is
* reached
* Toggles the shutdown mode that will close the application after the countdown timer
* is reached
*/
int toggleShutdown(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::toggleShutdown");
global::openSpaceEngine->toggleShutdownMode();
return 0;
[[codegen::luawrap]] void toggleShutdown() {
openspace::global::openSpaceEngine->toggleShutdownMode();
}
/**
* \ingroup LuaScripts
* writeDocumentation():
* Writes out documentation files
*/
int writeDocumentation(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::writeDocumentation");
global::openSpaceEngine->writeStaticDocumentation();
global::openSpaceEngine->writeSceneDocumentation();
return 0;
[[codegen::luawrap]] void writeDocumentation() {
openspace::global::openSpaceEngine->writeStaticDocumentation();
openspace::global::openSpaceEngine->writeSceneDocumentation();
}
int setScreenshotFolder(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setScreenshotFolder");
const std::string arg = ghoul::lua::value<std::string>(L);
// Sets the folder used for storing screenshots or session recording frames
[[codegen::luawrap]] void setScreenshotFolder(std::string newFolder) {
using namespace openspace;
std::filesystem::path folder = absPath(arg);
std::filesystem::path folder = absPath(newFolder);
if (!std::filesystem::exists(folder)) {
std::filesystem::create_directory(folder);
}
@@ -75,108 +56,90 @@ int setScreenshotFolder(lua_State* L) {
);
global::windowDelegate->setScreenshotFolder(folder.string());
return 0;
}
/**
* \ingroup LuaScripts
* addTag()
* Adds a Tag to a SceneGraphNode
*/
int addTag(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTag");
auto [uri, tag] = ghoul::lua::values<std::string, std::string>(L);
// Adds a Tag to a SceneGraphNode identified by the provided uri
[[codegen::luawrap]] void addTag(std::string uri, std::string tag) {
using namespace openspace;
SceneGraphNode* node = global::renderEngine->scene()->sceneGraphNode(uri);
if (!node) {
return ghoul::lua::luaError(L, fmt::format("Unknown scene graph node '{}'", uri));
throw ghoul::lua::LuaError(fmt::format("Unknown scene graph node '{}'", uri));
}
node->addTag(std::move(tag));
return 0;
}
/**
* \ingroup LuaScripts
* removeTag():
* Removes a tag from a SceneGraphNode
*/
int removeTag(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::removeTag");
auto [uri, tag] = ghoul::lua::values<std::string, std::string>(L);
// Removes a tag (second argument) from a scene graph node (first argument)
[[codegen::luawrap]] void removeTag(std::string uri, std::string tag) {
using namespace openspace;
SceneGraphNode* node = global::renderEngine->scene()->sceneGraphNode(uri);
if (!node) {
return ghoul::lua::luaError(L, fmt::format("Unknown scene graph node '{}'", uri));
throw ghoul::lua::LuaError(fmt::format("Unknown scene graph node '{}'", uri));
}
node->removeTag(tag);
return 0;
}
/**
* \ingroup LuaScripts
* downloadFile():
* Downloads a file from Lua interpreter
*/
int downloadFile(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::downloadFile");
auto [uri, savePath, waitForComplete] =
ghoul::lua::values<std::string, std::string, std::optional<bool>>(L);
waitForComplete = waitForComplete.value_or(false);
// Downloads a file from Lua interpreter
[[codegen::luawrap]] void downloadFile(std::string url, std::string savePath,
bool waitForCompletion = false)
{
using namespace openspace;
LINFOC("OpenSpaceEngine", fmt::format("Downloading file from {}", uri));
LINFOC("OpenSpaceEngine", fmt::format("Downloading file from {}", url));
std::shared_ptr<DownloadManager::FileFuture> future =
global::downloadManager->downloadFile(
uri,
url,
savePath,
DownloadManager::OverrideFile::Yes,
DownloadManager::FailOnError::Yes,
5
);
if (waitForComplete) {
while (!future->isFinished && future->errorMessage.empty() ) {
//just wait
if (waitForCompletion) {
while (!future->isFinished && future->errorMessage.empty()) {
// just wait
LTRACEC("OpenSpaceEngine", fmt::format("waiting {}", future->errorMessage));
}
}
if (!future || !future->isFinished) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
future ? "Download failed: " + future->errorMessage : "Download failed"
);
}
return 0;
}
} // namespace
// Closing the anoynmous namespace here to allow a unit test to access this function
/**
* \ingroup LuaScripts
* createSingleColorImage():
* Creates a one pixel image with a given color and returns the path to the cached file
* Creates a 1 pixel image with a certain color in the cache folder and returns the path
* to the file. If a cached file with the given name already exists, the path to that file
* is returned. The first argument is the name of the file, without extension. The second
* is the RGB color, given as {r, g, b} with values between 0 and 1.
*/
int createSingleColorImage(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::createSingleColorImage");
auto [name, d] = ghoul::lua::values<std::string, ghoul::Dictionary>(L);
[[codegen::luawrap]] std::filesystem::path createSingleColorImage(std::string name,
glm::dvec3 color)
{
using namespace openspace;
// @TODO (emmbr 2020-12-18) Verify that the input dictionary is a vec3
// Would like to clean this up with a more direct use of the Verifier in the future
const std::string& key = "color";
ghoul::Dictionary colorDict;
colorDict.setValue(key, d);
colorDict.setValue(key, color);
documentation::TestResult res = documentation::Color3Verifier()(colorDict, key);
if (!res.success) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
"Invalid color. Expected three double values {r, g, b} in range 0 to 1"
);
}
const glm::dvec3 color = colorDict.value<glm::dvec3>(key);
std::filesystem::path fileName = FileSys.cacheManager()->cachedFilename(
name + ".ppm",
""
@@ -184,8 +147,7 @@ int createSingleColorImage(lua_State* L) {
const bool hasCachedFile = std::filesystem::is_regular_file(fileName);
if (hasCachedFile) {
LDEBUGC("OpenSpaceEngine", fmt::format("Cached file '{}' used", fileName));
ghoul::lua::push(L, fileName);
return 1;
return fileName;
}
else {
// Write the color to a ppm file
@@ -201,25 +163,30 @@ int createSingleColorImage(lua_State* L) {
img[1] = static_cast<unsigned char>(255 * color.g);
img[2] = static_cast<unsigned char>(255 * color.b);
if (ppmFile.is_open()) {
ppmFile << "P6" << std::endl;
ppmFile << width << " " << height << std::endl;
ppmFile << 255 << std::endl;
ppmFile.write(reinterpret_cast<char*>(&img[0]), size * 3);
ppmFile.close();
ghoul::lua::push(L, fileName);
return 1;
}
else {
return ghoul::lua::luaError(L, "Could not open ppm file for writing.");
if (!ppmFile.is_open()) {
throw ghoul::lua::LuaError("Could not open ppm file for writing");
}
ppmFile << "P6" << std::endl;
ppmFile << width << " " << height << std::endl;
ppmFile << 255 << std::endl;
ppmFile.write(reinterpret_cast<char*>(img.data()), size * 3);
ppmFile.close();
return fileName;
}
}
int isMaster(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::isMaster");
ghoul::lua::push(L, global::windowDelegate->isMaster());
return 1;
namespace {
/**
* Returns whether the current OpenSpace instance is the master node of a cluster
* configuration. If this instance is not part of a cluster, this function also returns
* 'true'.
*/
[[codegen::luawrap]] bool isMaster() {
return openspace::global::windowDelegate->isMaster();
}
} // namespace openspace::luascriptfunctions
#include "openspaceengine_lua_codegen.cpp"
} // namespace

View File

@@ -107,25 +107,13 @@ void EventEngine::triggerActions() const {
}
scripting::LuaLibrary EventEngine::luaLibrary() {
scripting::LuaLibrary res;
res.name = "event";
res.functions.push_back({
"registerEventAction",
&luascriptfunctions::registerEventAction,
"string, string [, table]",
"Registers an action (second parameter) to be executed whenever an event (first "
"parameter) is encountered. If the optional third parameter is provided, it "
"describes a filter that the event is being checked against and only if it "
"passes the filter, the action is triggered"
});
res.functions.push_back({
"unregisterEventAction",
&luascriptfunctions::unregisterEventAction,
"string, string [, table]",
"Unregisters a specific combination of event (first parameter), action (second "
"parameter), and potentially a filter (optional third argument)"
});
return res;
return {
"event",
{
codegen::lua::RegisterEventAction,
codegen::lua::UnregisterEventAction
}
};
}
} // namespace openspace

View File

@@ -22,28 +22,32 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
namespace openspace::luascriptfunctions {
int registerEventAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::registerEventAction");
auto [event, action, filter] =
ghoul::lua::values<std::string, std::string, std::optional<ghoul::Dictionary>>(L);
namespace {
/**
* Registers an action to be executed whenever an event is encountered. If the optional
* third parameter is provided, it describes a filter that the event is being checked
* against and only if it passes the filter, the action is triggered.
*/
[[codegen::luawrap]] void registerEventAction(std::string event, std::string action,
std::optional<ghoul::Dictionary> filter)
{
using namespace openspace;
events::Event::Type type = events::fromString(event);
global::eventEngine->registerEventAction(type, std::move(action), std::move(filter));
return 0;
}
int unregisterEventAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 3 }, "lua::unregisterEventAction");
auto [event, action, filter] =
ghoul::lua::values<std::string, std::string, std::optional<ghoul::Dictionary>>(L);
/**
* Unregisters a specific combination of event, action, and potentially a filter.
*/
[[codegen::luawrap]] void unregisterEventAction(std::string event, std::string action,
std::optional<ghoul::Dictionary> filter)
{
using namespace openspace;
events::Event::Type type = events::fromString(event);
global::eventEngine->unregisterEventAction(type, action, filter);
return 0;
}
} // namespace openspace::luascriptfunctions
#include "eventengine_lua_codegen.cpp"
} // namespace

View File

@@ -24,6 +24,7 @@
#include <openspace/interaction/actionmanager.h>
#include <openspace/engine/globals.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/logging/logmanager.h>
@@ -110,55 +111,12 @@ scripting::LuaLibrary ActionManager::luaLibrary() {
return {
"action",
{
{
"hasAction",
&luascriptfunctions::hasAction,
"string",
"Checks if the passed identifier corresponds to an action"
},
{
"removeAction",
&luascriptfunctions::removeAction,
"(string, table)",
"Removes an existing action from the list of possible actions. The "
"action is identifies either by the passed name, or if it is a table, "
"the value behind the 'Identifier' key is extract and used instead"
},
{
"registerAction",
&luascriptfunctions::registerAction,
"table",
"Registers a new action. The table must at least contain the keys "
"'Identifier' and 'Command' represeting the unique identifier and the "
"Lua script that belong to this new action. Optional keys are 'Name' for "
"a human-readable name, 'Documentation' for a description of what the "
"action does, 'GuiPath' for a path used for grouping a user interface. "
"All of these parameters must be strings. The last parameter is "
"'IsLocal' and represents whether the action should be executed locally "
"(= false) or remotely (= true, the default)"
},
{
"action",
&luascriptfunctions::action,
"string",
"Returns information about the action as a table with the keys "
"'Identifier', 'Command', 'Name', 'Documentation', 'GuiPath', and "
"'Synchronization'"
},
{
"actions",
&luascriptfunctions::actions,
"",
"Returns all registered actions in the system as a table of tables each "
"containing the keys 'Identifier', 'Command', 'Name', 'Documentation', "
"'GuiPath', and 'Synchronization'"
},
{
"triggerAction",
&luascriptfunctions::triggerAction,
"string",
"Triggers the action given by the specified identifier"
}
codegen::lua::HasAction,
codegen::lua::RemoveAction,
codegen::lua::RegisterAction,
codegen::lua::Action,
codegen::lua::Actions,
codegen::lua::TriggerAction
}
};
}

View File

@@ -22,47 +22,35 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/globals.h>
namespace openspace::luascriptfunctions {
/**
* \ingroup LuaScripts
* hasAction():
* Checks if the passed identifier corresponds to an action.
*/
int hasAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::hasAction");
const std::string identifier = ghoul::lua::value<std::string>(L);
namespace {
// Checks if the passed identifier corresponds to an action.
[[codegen::luawrap]] bool hasAction(std::string identifier) {
if (identifier.empty()) {
return ghoul::lua::luaError(L, "Identifier must not be empty");
throw ghoul::lua::LuaError("Identifier must not be empty");
}
const bool res = global::actionManager->hasAction(identifier);
ghoul::lua::push(L, res);
return 1;
const bool res = openspace::global::actionManager->hasAction(identifier);
return res;
}
/**
* \ingroup LuaScripts
* removeAction():
* Removes an existing action from the list of possible actions.
*/
int removeAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::removeAction");
std::variant v = ghoul::lua::value<std::variant<std::string, ghoul::Dictionary>>(L);
* Removes an existing action from the list of possible actions.The action is identifies
* either by the passed name, or if it is a table, the value behind the 'Identifier' key
* is extract and used instead.
*/
[[codegen::luawrap]] void removeAction(
std::variant<std::string, ghoul::Dictionary> action)
{
using namespace openspace;
std::string identifier;
if (std::holds_alternative<std::string>(v)) {
identifier = std::get<std::string>(v);
if (std::holds_alternative<std::string>(action)) {
identifier = std::get<std::string>(action);
}
else {
ghoul_assert(std::holds_alternative<ghoul::Dictionary>(v), "Missing case");
ghoul::Dictionary d = std::get<ghoul::Dictionary>(v);
ghoul::Dictionary d = std::get<ghoul::Dictionary>(action);
if (!d.hasValue<std::string>("Identifier")) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
"Table passed to removeAction does not contain an Identifier"
);
}
@@ -70,22 +58,18 @@ int removeAction(lua_State* L) {
}
if (identifier.empty()) {
return ghoul::lua::luaError(L, "Identifier must not be empty");
throw ghoul::lua::LuaError("Identifier must not be empty");
}
if (!global::actionManager->hasAction(identifier)) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
fmt::format("Identifier '{}' for action not found", identifier)
);
}
global::actionManager->removeAction(identifier);
return 0;
}
/**
* \ingroup LuaScripts
* registerAction():
* Registers a new action. The first argument is the identifier which cannot have been
* used to register a previous action before, the second argument is the Lua command that
* is to be executed, and the optional third argument is the name used in a user-interface
@@ -94,154 +78,124 @@ int removeAction(lua_State* L) {
* whether the action should be executed locally (= false) or remotely (= true, the
* default).
*/
int registerAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::registerAction");
const ghoul::Dictionary d = ghoul::lua::value<ghoul::Dictionary>(L);
[[codegen::luawrap]] void registerAction(ghoul::Dictionary action) {
using namespace openspace;
if (!d.hasValue<std::string>("Identifier")) {
return ghoul::lua::luaError(L, "Identifier must to provided to register action");
if (!action.hasValue<std::string>("Identifier")) {
throw ghoul::lua::LuaError("Identifier must to provided to register action");
}
std::string identifier = d.value<std::string>("Identifier");
std::string identifier = action.value<std::string>("Identifier");
if (global::actionManager->hasAction(identifier)) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
fmt::format("Action for identifier '{}' already existed", identifier)
);
}
if (global::actionManager->hasAction(identifier)) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
fmt::format("Identifier '{}' for action already registered", identifier)
);
}
if (!d.hasValue<std::string>("Command")) {
return ghoul::lua::luaError(
L,
if (!action.hasValue<std::string>("Command")) {
throw ghoul::lua::LuaError(
fmt::format(
"Identifier '{}' does not provide a Lua command to execute", identifier
)
);
}
interaction::Action action;
action.identifier = std::move(identifier);
action.command = d.value<std::string>("Command");
if (d.hasValue<std::string>("Name")) {
action.name = d.value<std::string>("Name");
interaction::Action a;
a.identifier = std::move(identifier);
a.command = action.value<std::string>("Command");
if (action.hasValue<std::string>("Name")) {
a.name = action.value<std::string>("Name");
}
if (d.hasValue<std::string>("Documentation")) {
action.documentation = d.value<std::string>("Documentation");
if (action.hasValue<std::string>("Documentation")) {
a.documentation = action.value<std::string>("Documentation");
}
if (d.hasValue<std::string>("GuiPath")) {
action.guiPath = d.value<std::string>("GuiPath");
if (action.hasValue<std::string>("GuiPath")) {
a.guiPath = action.value<std::string>("GuiPath");
}
if (d.hasValue<bool>("IsLocal")) {
bool value = d.value<bool>("IsLocal");
action.synchronization = interaction::Action::IsSynchronized(value);
if (action.hasValue<bool>("IsLocal")) {
bool value = action.value<bool>("IsLocal");
a.synchronization = interaction::Action::IsSynchronized(value);
}
global::actionManager->registerAction(std::move(action));
return 0;
global::actionManager->registerAction(std::move(a));
}
/**
* \ingroup LuaScripts
* action():
* Returns information about the action with the identifier equal to the provided
* identifier.
* Returns information about the action as a table with the keys 'Identifier', 'Command',
* 'Name', 'Documentation', 'GuiPath', and 'Synchronization'.
*/
int action(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::action");
const std::string identifier = ghoul::lua::value<std::string>(L);
[[codegen::luawrap]] ghoul::Dictionary action(std::string identifier) {
using namespace openspace;
if (identifier.empty()) {
return ghoul::lua::luaError(L, "Identifier must not be empty");
throw ghoul::lua::LuaError("Identifier must not be empty");
}
if (!global::actionManager->hasAction(identifier)) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
fmt::format("Identifier '{}' for action not found", identifier)
);
}
const interaction::Action& action = global::actionManager->action(identifier);
lua_newtable(L);
ghoul::lua::push(L, "Identifier", action.identifier);
lua_settable(L, -3);
ghoul::lua::push(L, "Command", action.command);
lua_settable(L, -3);
ghoul::lua::push(L, "Name", action.name);
lua_settable(L, -3);
ghoul::lua::push(L, "Documentation", action.documentation);
lua_settable(L, -3);
ghoul::lua::push(L, "GuiPath", action.guiPath);
lua_settable(L, -3);
ghoul::lua::push(
L,
ghoul::Dictionary res;
res.setValue("Identifier", action.identifier);
res.setValue("Command", action.command);
res.setValue("Name", action.name);
res.setValue("Documentation", action.documentation);
res.setValue("GuiPath", action.guiPath);
res.setValue(
"Synchronization",
action.synchronization == interaction::Action::IsSynchronized::Yes
);
lua_settable(L, -3);
return 1;
return res;
}
/**
* \ingroup LuaScripts
* actions():
* Returns all registered actions in the system.
* Returns all registered actions in the system as a table of tables each containing the
* keys 'Identifier', 'Command', 'Name', 'Documentation', 'GuiPath', and
* 'Synchronization'.
*/
int actions(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::actions");
[[codegen::luawrap]] std::vector<ghoul::Dictionary> actions() {
using namespace openspace;
lua_newtable(L);
std::vector<ghoul::Dictionary> res;
const std::vector<interaction::Action>& actions = global::actionManager->actions();
for (size_t i = 0; i < actions.size(); ++i) {
const interaction::Action& action = actions[i];
ghoul::lua::push(L, i + 1);
lua_newtable(L);
ghoul::lua::push(L, "Identifier", action.identifier);
lua_settable(L, -3);
ghoul::lua::push(L, "Command", action.command);
lua_settable(L, -3);
ghoul::lua::push(L, "Name", action.name);
lua_settable(L, -3);
ghoul::lua::push(L, "Documentation", action.documentation);
lua_settable(L, -3);
ghoul::lua::push(L, "GuiPath", action.guiPath);
lua_settable(L, -3);
ghoul::lua::push(
L,
for (const interaction::Action& action : actions) {
ghoul::Dictionary d;
d.setValue("Identifier", action.identifier);
d.setValue("Command", action.command);
d.setValue("Name", action.name);
d.setValue("Documentation", action.documentation);
d.setValue("GuiPath", action.guiPath);
d.setValue(
"Synchronization",
action.synchronization == interaction::Action::IsSynchronized::Yes
);
lua_settable(L, -3);
lua_settable(L, -3);
res.push_back(d);
}
return 1;
return res;
}
/**
* \ingroup LuaScripts
* triggerAction():
* Triggers the action given by the specified identifier.
*/
int triggerAction(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::triggerAction");
auto [id, arg] = ghoul::lua::values<std::string, std::optional<ghoul::Dictionary>>(L);
arg = arg.value_or(ghoul::Dictionary());
// Triggers the action given by the specified identifier.
[[codegen::luawrap]] void triggerAction(std::string id,
ghoul::Dictionary arg = ghoul::Dictionary())
{
using namespace openspace;
if (id.empty()) {
return ghoul::lua::luaError(L, "Identifier must not be empty");
throw ghoul::lua::LuaError("Identifier must not be empty");
}
if (!global::actionManager->hasAction(id)) {
return ghoul::lua::luaError(L, fmt::format("Action '{}' not found", id));
throw ghoul::lua::LuaError(fmt::format("Action '{}' not found", id));
}
global::actionManager->triggerAction(id, *arg);
return 0;
global::actionManager->triggerAction(id, arg);
}
} // namespace openspace::luascriptfunctions
#include "actionmanager_lua_codegen.cpp"
} // namespace

View File

@@ -29,6 +29,7 @@
#include <openspace/scripting/lualibrary.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/json_helper.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/glm.h>
#include <sstream>
@@ -142,32 +143,10 @@ scripting::LuaLibrary KeybindingManager::luaLibrary() {
return {
"",
{
{
"clearKeys",
&luascriptfunctions::clearKeys,
"",
"Clear all key bindings"
},
{
"clearKey",
&luascriptfunctions::clearKey,
"string or strings",
"Unbinds the key or keys that have been provided. This function can be "
"called with a single key or with an array of keys to remove all of the "
"provided keys at once"
},
{
"bindKey",
&luascriptfunctions::bindKey,
"string, string",
"Binds a key by name to the action identified by the second argument"
},
{
"getKeyBinding",
&luascriptfunctions::getKeyBindings,
"string",
"Returns a list of information about the keybindings for the provided key"
}
codegen::lua::BindKey,
codegen::lua::KeyBindings,
codegen::lua::ClearKey,
codegen::lua::ClearKeys
}
};
}

View File

@@ -22,48 +22,36 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/globals.h>
#include <ghoul/logging/logmanager.h>
namespace openspace::luascriptfunctions {
namespace {
/**
* \ingroup LuaScripts
* bindKey():
* Binds a key to Lua command to both execute locally and broadcast to all clients if this
* node is hosting a parallel connection.
*/
int bindKey(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::bindKey");
auto [key, action] = ghoul::lua::values<std::string, std::string>(L);
[[codegen::luawrap]] void bindKey(std::string key, std::string action) {
using namespace openspace;
if (action.empty()) {
return ghoul::lua::luaError(L, "Action must not be empty");
throw ghoul::lua::LuaError("Action must not be empty");
}
if (!global::actionManager->hasAction(action)) {
return ghoul::lua::luaError(L, fmt::format("Action '{}' does not exist", action));
throw ghoul::lua::LuaError(fmt::format("Action '{}' does not exist", action));
}
openspace::KeyWithModifier iKey = openspace::stringToKey(key);
if (iKey.key == openspace::Key::Unknown) {
std::string error = fmt::format("Could not find key '{}'", key);
LERRORC("lua.bindKey", error);
return ghoul::lua::luaError(L, error);
throw ghoul::lua::LuaError(fmt::format("Could not find key '{}'", key));
}
global::keybindingManager->bindKey(iKey.key, iKey.modifier, std::move(action));
return 0;
}
/**
* \ingroup LuaScripts
* getKeyBindings(string):
* Returns the strings of the script that are bound to the passed key and whether they were
* local or remote key binds
*/
int getKeyBindings(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::getKeyBindings");
const std::string& key = ghoul::lua::value<std::string>(L);
* Returns the strings of the script that are bound to the passed key and whether they
* were local or remote key binds.
*/
[[codegen::luawrap]] std::vector<std::string> keyBindings(std::string key) {
using namespace openspace;
using K = KeyWithModifier;
using V = std::string;
@@ -71,50 +59,39 @@ int getKeyBindings(lua_State* L) {
stringToKey(key)
);
lua_createtable(L, static_cast<int>(info.size()), 0);
int i = 1;
std::vector<std::string> res;
res.reserve(info.size());
for (const std::pair<K, V>& it : info) {
lua_pushnumber(L, i);
ghoul::lua::push(L, it.second);
lua_settable(L, -3);
++i;
res.push_back(it.second);
}
return 1;
return res;
}
/**
* \ingroup LuaScripts
* clearKey(string):
* Clears the keybinding of the key named as argument
*/
int clearKey(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::clearKey");
* Unbinds the key or keys that have been provided. This function can be called with a
* single key or with an array of keys to remove all of the provided keys at once.
*/
[[codegen::luawrap]] void clearKey(
std::variant<std::string, std::vector<std::string>> key)
{
using namespace openspace;
std::variant key = ghoul::lua::value<std::variant<std::string, ghoul::Dictionary>>(L);
if (std::holds_alternative<std::string>(key)) {
KeyWithModifier k = stringToKey(std::get<std::string>(key));
global::keybindingManager->removeKeyBinding(k);
}
else {
ghoul::Dictionary d = std::get<ghoul::Dictionary>(key);
for (size_t i = 1; i <= d.size(); ++i) {
const std::string& k = d.value<std::string>(std::to_string(i));
for (const std::string& k : std::get<std::vector<std::string>>(key)) {
global::keybindingManager->removeKeyBinding(stringToKey(k));
}
}
return 0;
}
/**
* \ingroup LuaScripts
* clearKeys():
* Clears all key bindings
*/
int clearKeys(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::clearKeys");
global::keybindingManager->resetKeyBindings();
return 0;
// Clear all key bindings
[[codegen::luawrap]] void clearKeys() {
openspace::global::keybindingManager->resetKeyBindings();
}
} // namespace openspace::luascriptfunctions
#include "keybindingmanager_lua_codegen.cpp"
} // namespace

View File

@@ -58,6 +58,8 @@
#include <windows.h>
#endif // WIN32
#include "sessionrecording_lua.inl"
namespace {
constexpr const char* _loggerCat = "SessionRecording";
@@ -76,11 +78,8 @@ namespace {
};
constexpr const bool UsingTimeKeyframes = false;
} // namespace
#include "sessionrecording_lua.inl"
namespace openspace::interaction {
ConversionError::ConversionError(std::string msg)
@@ -2546,118 +2545,20 @@ scripting::LuaLibrary SessionRecording::luaLibrary() {
return {
"sessionRecording",
{
{
"startRecording",
&luascriptfunctions::startRecording,
"string",
"Starts a recording session. The string argument is the filename used "
"for the file where the recorded keyframes are saved. "
"The file data format is binary."
},
{
"startRecordingAscii",
&luascriptfunctions::startRecordingAscii,
"string",
"Starts a recording session. The string argument is the filename used "
"for the file where the recorded keyframes are saved. "
"The file data format is ASCII."
},
{
"stopRecording",
&luascriptfunctions::stopRecording,
"void",
"Stops a recording session"
},
{
"startPlayback",
&luascriptfunctions::startPlaybackDefault,
"string [, bool]",
"Starts a playback session with keyframe times that are relative to "
"the time since the recording was started (the same relative time "
"applies to the playback). When playback starts, the simulation time "
"is automatically set to what it was at recording time. The string "
"argument is the filename to pull playback keyframes from (the file "
"path is relative to the RECORDINGS variable specified in the config "
"file). If a second input value of true is given, then playback will "
"continually loop until it is manually stopped."
},
{
"startPlaybackApplicationTime",
&luascriptfunctions::startPlaybackApplicationTime,
"string",
"Starts a playback session with keyframe times that are relative to "
"application time (seconds since OpenSpace application started). "
"The string argument is the filename to pull playback keyframes from "
"(the file path is relative to the RECORDINGS variable specified in the "
"config file)."
},
{
"startPlaybackRecordedTime",
&luascriptfunctions::startPlaybackRecordedTime,
"string [, bool]",
"Starts a playback session with keyframe times that are relative to "
"the time since the recording was started (the same relative time "
"applies to the playback). The string argument is the filename to pull "
"playback keyframes from (the file path is relative to the RECORDINGS "
"variable specified in the config file). If a second input value of "
"true is given, then playback will continually loop until it is "
"manually stopped."
},
{
"startPlaybackSimulationTime",
&luascriptfunctions::startPlaybackSimulationTime,
"string",
"Starts a playback session with keyframe times that are relative to "
"the simulated date & time. The string argument is the filename to pull "
"playback keyframes from (the file path is relative to the RECORDINGS "
"variable specified in the config file)."
},
{
"stopPlayback",
&luascriptfunctions::stopPlayback,
"",
"Stops a playback session before playback of all keyframes is complete"
},
{
"enableTakeScreenShotDuringPlayback",
&luascriptfunctions::enableTakeScreenShotDuringPlayback,
"[int]",
"Enables that rendered frames should be saved during playback. The "
"parameter determines the number of frames that are exported per second "
"if this value is not provided, 60 frames per second will be exported."
},
{
"disableTakeScreenShotDuringPlayback",
&luascriptfunctions::disableTakeScreenShotDuringPlayback,
"",
"Used to disable that renderings are saved during playback"
},
{
"fileFormatConversion",
&luascriptfunctions::fileFormatConversion,
"string",
"Performs a conversion of the specified file to the most most recent "
"file format, creating a copy of the recording file."
},
{
"setPlaybackPause",
&luascriptfunctions::setPlaybackPause,
"bool",
"Pauses or resumes the playback progression through keyframes"
},
{
"togglePlaybackPause",
&luascriptfunctions::togglePlaybackPause,
"",
"Toggles the pause function, i.e. temporarily setting the delta time to 0"
" and restoring it afterwards"
},
{
"isPlayingBack",
& luascriptfunctions::isPlayingBack,
"",
"Returns true if session recording is currently playing back a recording"
}
codegen::lua::StartRecording,
codegen::lua::StartRecordingAscii,
codegen::lua::StopRecording,
codegen::lua::StartPlaybackDefault,
codegen::lua::StartPlaybackApplicationTime,
codegen::lua::StartPlaybackRecordedTime,
codegen::lua::StartPlaybackSimulationTime,
codegen::lua::StopPlayback,
codegen::lua::EnableTakeScreenShotDuringPlayback,
codegen::lua::DisableTakeScreenShotDuringPlayback,
codegen::lua::FileFormatConversion,
codegen::lua::SetPlaybackPause,
codegen::lua::TogglePlaybackPause,
codegen::lua::IsPlayingBack
}
};
}

View File

@@ -22,137 +22,179 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
namespace openspace::luascriptfunctions {
namespace {
int startRecording(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startRecording");
const std::string recordFilePath = ghoul::lua::value<std::string>(L);
/**
* Starts a recording session. The string argument is the filename used for the file where
* the recorded keyframes are saved. The file data format is binary.
*/
[[codegen::luawrap]] void startRecording(std::string recordFilePath) {
using namespace openspace;
if (recordFilePath.empty()) {
return luaL_error(L, "filepath string is empty");
throw ghoul::lua::LuaError("Filepath string is empty");
}
global::sessionRecording->setRecordDataFormat(
interaction::SessionRecording::DataMode::Binary
);
global::sessionRecording->startRecording(recordFilePath);
return 0;
}
int startRecordingAscii(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startRecordingAscii");
const std::string recordFilePath = ghoul::lua::value<std::string>(L);
/**
* Starts a recording session. The string argument is the filename used for the file where
* the recorded keyframes are saved. The file data format is ASCII.
*/
[[codegen::luawrap]] void startRecordingAscii(std::string recordFilePath) {
using namespace openspace;
if (recordFilePath.empty()) {
return luaL_error(L, "filepath string is empty");
throw ghoul::lua::LuaError("Filepath string is empty");
}
global::sessionRecording->setRecordDataFormat(
interaction::SessionRecording::DataMode::Ascii
);
global::sessionRecording->startRecording(recordFilePath);
return 0;
}
int stopRecording(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopRecording");
global::sessionRecording->stopRecording();
return 0;
// Stops a recording session.
[[codegen::luawrap]] void stopRecording() {
openspace::global::sessionRecording->stopRecording();
}
int startPlayback(lua_State* L, interaction::KeyframeTimeRef timeMode,
bool forceSimTimeAtStart)
{
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlayback");
auto [file, loop] = ghoul::lua::values<std::string, std::optional<bool>>(L);
loop = loop.value_or(false);
/**
* Starts a playback session with keyframe times that are relative to the time since the
* recording was started (the same relative time applies to the playback). When playback
* starts, the simulation time is automatically set to what it was at recording time. The
* string argument is the filename to pull playback keyframes from (the file path is
* relative to the RECORDINGS variable specified in the config file). If a second input
* value of true is given, then playback will continually loop until it is manually
* stopped.
*/
[[codegen::luawrap]] void startPlaybackDefault(std::string file, bool loop = false) {
using namespace openspace;
if (file.empty()) {
return ghoul::lua::luaError(L, "Filepath string is empty");
throw ghoul::lua::LuaError("Filepath string is empty");
}
global::sessionRecording->startPlayback(file, timeMode, forceSimTimeAtStart, *loop);
return 0;
global::sessionRecording->startPlayback(
file,
interaction::KeyframeTimeRef::Relative_recordedStart,
true,
loop
);
}
int startPlaybackDefault(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlaybackDefault");
return startPlayback(L, interaction::KeyframeTimeRef::Relative_recordedStart, true);
}
int startPlaybackApplicationTime(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startPlaybackApplicationTime");
return startPlayback(
L,
/**
* Starts a playback session with keyframe times that are relative to application time
* (seconds since OpenSpace application started). The string argument is the filename to
* pull playback keyframes from (the file path is relative to the RECORDINGS variable
* specified in the config file).
*/
[[codegen::luawrap]] void startPlaybackApplicationTime(std::string file) {
using namespace openspace;
if (file.empty()) {
throw ghoul::lua::LuaError("Filepath string is empty");
}
global::sessionRecording->startPlayback(
file,
interaction::KeyframeTimeRef::Relative_applicationStart,
false,
false
);
}
int startPlaybackRecordedTime(lua_State* L) {
using interaction::KeyframeNavigator;
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::startPlaybackRecordedTime");
return startPlayback(L, interaction::KeyframeTimeRef::Relative_recordedStart, false);
}
int startPlaybackSimulationTime(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::startPlaybackSimulationTime");
return startPlayback(L, interaction::KeyframeTimeRef::Absolute_simTimeJ2000, false);
}
int stopPlayback(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPlayback");
global::sessionRecording->stopPlayback();
return 0;
}
int enableTakeScreenShotDuringPlayback(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(
L,
{ 0, 1 },
"lua::enableTakeScreenShotDuringPlayback"
);
std::optional<int> fps = ghoul::lua::value<std::optional<int>>(L);
fps = fps.value_or(60);
global::sessionRecording->enableTakeScreenShotDuringPlayback(*fps);
return 0;
}
int disableTakeScreenShotDuringPlayback(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::disableTakeScreenShotDuringPlayback");
global::sessionRecording->disableTakeScreenShotDuringPlayback();
return 0;
}
int fileFormatConversion(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::fileFormatConversion");
const std::string convertFilePath = ghoul::lua::value<std::string>(L);
if (convertFilePath.empty()) {
return luaL_error(L, "Filepath string must not be empty");
/**
* Starts a playback session with keyframe times that are relative to the time since the
* recording was started (the same relative time applies to the playback). The string
* argument is the filename to pull playback keyframes from (the file path is relative to
* the RECORDINGS variable specified in the config file). If a second input value of true
* is given, then playback will continually loop until it is manually stopped.
*/
[[codegen::luawrap]] void startPlaybackRecordedTime(std::string file, bool loop = false) {
using namespace openspace;
if (file.empty()) {
throw ghoul::lua::LuaError("Filepath string is empty");
}
global::sessionRecording->convertFile(convertFilePath);
return 0;
global::sessionRecording->startPlayback(
file,
interaction::KeyframeTimeRef::Relative_recordedStart,
false,
loop
);
}
int setPlaybackPause(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setPlaybackPause");
const bool pause = ghoul::lua::value<bool>(L);
global::sessionRecording->setPlaybackPause(pause);
return 0;
/**
* Starts a playback session with keyframe times that are relative to the simulated date &
* time. The string argument is the filename to pull playback keyframes from (the file
* path is relative to the RECORDINGS variable specified in the config file).
*/
[[codegen::luawrap]] void startPlaybackSimulationTime(std::string file) {
using namespace openspace;
if (file.empty()) {
throw ghoul::lua::LuaError("Filepath string is empty");
}
global::sessionRecording->startPlayback(
file,
interaction::KeyframeTimeRef::Absolute_simTimeJ2000,
false,
false
);
}
int togglePlaybackPause(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::togglePlaybackPause");
// Stops a playback session before playback of all keyframes is complete.
[[codegen::luawrap]] void stopPlayback() {
openspace::global::sessionRecording->stopPlayback();
}
/**
* Enables that rendered frames should be saved during playback. The parameter determines
* the number of frames that are exported per second if this value is not provided, 60
* frames per second will be exported.
*/
[[codegen::luawrap]] void enableTakeScreenShotDuringPlayback(int fps = 60) {
openspace::global::sessionRecording->enableTakeScreenShotDuringPlayback(fps);
}
// Used to disable that renderings are saved during playback.
[[codegen::luawrap]] void disableTakeScreenShotDuringPlayback() {
openspace::global::sessionRecording->disableTakeScreenShotDuringPlayback();
}
/**
* Performs a conversion of the specified file to the most most recent file format,
* creating a copy of the recording file.
*/
[[codegen::luawrap]] void fileFormatConversion(std::string convertFilePath) {
if (convertFilePath.empty()) {
throw ghoul::lua::LuaError("Filepath string must not be empty");
}
openspace::global::sessionRecording->convertFile(convertFilePath);
}
// Pauses or resumes the playback progression through keyframes.
[[codegen::luawrap]] void setPlaybackPause(bool pause) {
openspace::global::sessionRecording->setPlaybackPause(pause);
}
/**
* Toggles the pause function, i.e. temporarily setting the delta time to 0 and restoring
* it afterwards.
*/
[[codegen::luawrap]] void togglePlaybackPause() {
using namespace openspace;
bool isPlaybackPaused = global::sessionRecording->isPlaybackPaused();
global::sessionRecording->setPlaybackPause(!isPlaybackPaused);
return 0;
}
int isPlayingBack(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::isPlayingBack");
ghoul::lua::push(L, global::sessionRecording->isPlayingBack());
return 1;
// Returns true if session recording is currently playing back a recording.
[[codegen::luawrap]] bool isPlayingBack() {
return openspace::global::sessionRecording->isPlayingBack();
}
} // namespace openspace::luascriptfunctions
#include "sessionrecording_lua_codegen.cpp"
} // namespace

View File

@@ -24,6 +24,7 @@
#include <openspace/mission/missionmanager.h>
#include <openspace/engine/globals.h>
#include <openspace/scripting/scriptengine.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/filesystem/filesystem.h>
@@ -108,30 +109,10 @@ scripting::LuaLibrary MissionManager::luaLibrary() {
return {
"",
{
{
"loadMission",
&luascriptfunctions::loadMission,
"string",
"Load mission phases from file"
},
{
"unloadMission",
&luascriptfunctions::unloadMission,
"string",
"Unloads a previously loaded mission"
},
{
"hasMission",
&luascriptfunctions::hasMission,
"string",
"Returns whether a mission with the provided name has been loaded"
},
{
"setCurrentMission",
&luascriptfunctions::setCurrentMission,
"string",
"Set the currnet mission"
},
codegen::lua::LoadMission,
codegen::lua::UnloadMission,
codegen::lua::HasMission,
codegen::lua::SetCurrentMission
}
};
}

View File

@@ -22,61 +22,47 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/engine/globals.h>
namespace openspace::luascriptfunctions {
int loadMission(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadMission");
const std::string& missionFileName = ghoul::lua::value<std::string>(L);
// Load mission phases from file.
[[codegen::luawrap]] std::string loadMission(std::string missionFileName) {
if (missionFileName.empty()) {
return ghoul::lua::luaError(L, "Filepath is empty");
throw ghoul::lua::LuaError("Filepath is empty");
}
const std::string name = global::missionManager->loadMission(missionFileName);
ghoul::lua::push(L, name);
return 1;
std::string name = openspace::global::missionManager->loadMission(missionFileName);
return name;
}
int unloadMission(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::unloadMission");
const std::string missionName = ghoul::lua::value<std::string>(L);
// Unloads a previously loaded mission.
[[codegen::luawrap]] void unloadMission(std::string missionName) {
using namespace openspace;
if (missionName.empty()) {
return ghoul::lua::luaError(L, "Mission name is empty");
throw ghoul::lua::LuaError("Mission name is empty");
}
if (!global::missionManager->hasMission(missionName)) {
return ghoul::lua::luaError(L, "Mission was not previously loaded");
throw ghoul::lua::LuaError("Mission was not previously loaded");
}
global::missionManager->unloadMission(missionName);
return 0;
}
int hasMission(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::hasMission");
const std::string missionName = ghoul::lua::value<std::string>(L);
// Returns whether a mission with the provided name has been loaded.
[[codegen::luawrap]] bool hasMission(std::string missionName) {
if (missionName.empty()) {
return ghoul::lua::luaError(L, "Missing name is empty");
throw ghoul::lua::LuaError("Missing name is empty");
}
const bool hasMission = global::missionManager->hasMission(missionName);
ghoul::lua::push(L, hasMission);
return 1;
bool hasMission = openspace::global::missionManager->hasMission(missionName);
return hasMission;
}
int setCurrentMission(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setCurrentMission");
const std::string missionName = ghoul::lua::value<std::string>(L);
// Set the currnet mission.
[[codegen::luawrap]] void setCurrentMission(std::string missionName) {
if (missionName.empty()) {
return ghoul::lua::luaError(L, "Mission name is empty");
throw ghoul::lua::LuaError("Mission name is empty");
}
global::missionManager->setCurrentMission(missionName);
return 0;
openspace::global::missionManager->setCurrentMission(missionName);
}
} // namespace openspace::luascriptfunction
#include "missionmanager_lua_codegen.cpp"

View File

@@ -31,6 +31,7 @@
#include <openspace/events/event.h>
#include <openspace/events/eventengine.h>
#include <openspace/interaction/actionmanager.h>
#include <openspace/interaction/scriptcamerastates.h>
#include <openspace/navigation/navigationstate.h>
#include <openspace/network/parallelpeer.h>
#include <openspace/scene/profile.h>
@@ -47,11 +48,14 @@
#include <glm/gtx/vector_angle.hpp>
#include <filesystem>
#include <fstream>
#include <numeric>
#include "navigationhandler_lua.inl"
namespace {
// Helper structs for the visitor pattern of the std::variant
template <class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template <class... Ts> overloaded(Ts...)->overloaded<Ts...>;
template <class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
constexpr const char* _loggerCat = "NavigationHandler";
@@ -76,8 +80,6 @@ namespace {
};
} // namespace
#include "navigationhandler_lua.inl"
namespace openspace::interaction {
NavigationHandler::NavigationHandler()
@@ -583,168 +585,26 @@ scripting::LuaLibrary NavigationHandler::luaLibrary() {
return {
"navigation",
{
{
"getNavigationState",
&luascriptfunctions::getNavigationState,
"[string]",
"Return the current navigation state as a lua table. The optional "
"argument is the scene graph node to use as reference frame. By default, "
"the reference frame will picked based on whether the orbital navigator "
"is currently following the anchor node rotation. If it is, the anchor "
"will be chosen as reference frame. If not, the reference frame will be "
"set to the scene graph root."
},
{
"setNavigationState",
&luascriptfunctions::setNavigationState,
"table",
"Set the navigation state. The argument must be a valid Navigation State."
},
{
"saveNavigationState",
&luascriptfunctions::saveNavigationState,
"string, [string]",
"Save the current navigation state to a file with the path given by the "
"first argument. The optoinal second argument is the scene graph node to "
"use as reference frame. By default, the reference frame will picked "
"based on whether the orbital navigator is currently following the "
"anchor node rotation. If it is, the anchor will be chosen as reference "
"frame. If not, the reference frame will be set to the scene graph root."
},
{
"loadNavigationState",
&luascriptfunctions::loadNavigationState,
"string",
"Load a navigation state from file. The file should be a lua file "
"returning the navigation state as a table formatted as a "
"Navigation State, such as the output files of saveNavigationState."
},
{
"retargetAnchor",
&luascriptfunctions::retargetAnchor,
"void",
"Reset the camera direction to point at the anchor node"
},
{
"retargetAim",
&luascriptfunctions::retargetAim,
"void",
"Reset the camera direction to point at the aim node"
},
{
"bindJoystickAxis",
&luascriptfunctions::bindJoystickAxis,
"name, axis, axisType [, isInverted, joystickType, isSticky, sensitivity]",
"Finds the input joystick with the given 'name' and binds the axis "
"identified by the second argument to be used as the type identified by "
"the third argument. If 'isInverted' is 'true', the axis value is "
"inverted. 'joystickType' is if the joystick behaves more like a "
"joystick or a trigger, where the first is the default. If 'isSticky' is "
"'true', the value is calculated relative to the previous value. If "
"'sensitivity' is given then that value will affect the sensitivity of "
"the axis together with the global sensitivity."
},
{
"bindJoystickAxisProperty",
&luascriptfunctions::bindJoystickAxisProperty,
"name, axis, propertyUri [, min, max, isInverted, isSticky, sensitivity, "
"isRemote]",
"Finds the input joystick with the given 'name' and binds the axis "
"identified by the second argument to be bound to the property "
"identified by the third argument. 'min' and 'max' is the minimum and "
"the maximum allowed value for the given property and the axis value is "
"rescaled from [-1, 1] to [min, max], default is [0, 1]. If 'isInverted' "
"is 'true', the axis value is inverted. The last argument determines "
"whether the property change is going to be executed locally or "
"remotely, where the latter is the default."
},
{
"joystickAxis",
&luascriptfunctions::joystickAxis,
"name, axis",
"Finds the input joystick with the given 'name' and returns the joystick "
"axis information for the passed axis. The information that is returned "
"is the current axis binding as a string, whether the values are "
"inverted as bool, the joystick type as a string, whether the axis is "
"sticky as bool, the sensitivity as number, the property uri bound to "
"the axis as string (empty is type is not Property), the min and max "
"values for the property as numbers and whether the property change will "
"be executed remotly as bool."
},
{
"setAxisDeadZone",
&luascriptfunctions::setJoystickAxisDeadzone,
"name, axis, float",
"Finds the input joystick with the given 'name' and sets the deadzone "
"for a particular joystick axis, which means that any input less than "
"this value is completely ignored."
},
{
"bindJoystickButton",
&luascriptfunctions::bindJoystickButton,
"name, button, string [, string, string, bool]",
"Finds the input joystick with the given 'name' and binds a Lua script "
"given by the third argument to be executed when the joystick button "
"identified by the second argument is triggered. The fifth argument "
"determines when the script should be executed, this defaults to "
"'Press', which means that the script is run when the user presses the "
"button. The fourth arguemnt is the documentation of the script in the "
"third argument. The sixth argument determines whether the command is "
"going to be executable locally or remotely, where the latter is the "
"default."
},
{
"clearJoystickButton",
&luascriptfunctions::clearJoystickButton,
"name, button",
"Finds the input joystick with the given 'name' and removes all commands "
"that are currently bound to the button identified by the second argument."
},
{
"joystickButton",
&luascriptfunctions::joystickButton,
"name, button",
"Finds the input joystick with the given 'name' and returns the script "
"that is currently bound to be executed when the provided button is "
"pressed."
},
{
"addGlobalRotation",
&luascriptfunctions::addGlobalRotation,
"double, double",
"Directly adds to the global rotation of the camera"
},
{
"addLocalRotation",
&luascriptfunctions::addLocalRotation,
"double, double",
"Directly adds to the local rotation of the camera"
},
{
"addTruckMovement",
&luascriptfunctions::addTruckMovement,
"double, double",
"Directly adds to the truck movement of the camera"
},
{
"addLocalRoll",
&luascriptfunctions::addLocalRoll,
"double, double",
"Directly adds to the local roll of the camera"
},
{
"addGlobalRoll",
&luascriptfunctions::addGlobalRoll,
"double, double",
"Directly adds to the global roll of the camera"
},
{
"triggerIdleBehavior",
&luascriptfunctions::triggerIdleBehavior,
"[string]",
"Immediately start applying the chosen IdleBehavior. If none is "
"specified, use the one set to default in the OrbitalNavigator."
}
codegen::lua::LoadNavigationState,
codegen::lua::GetNavigationState,
codegen::lua::SetNavigationState,
codegen::lua::SaveNavigationState,
codegen::lua::RetargetAnchor,
codegen::lua::RetargetAim,
codegen::lua::BindJoystickAxis,
codegen::lua::BindJoystickAxisProperty,
codegen::lua::JoystickAxis,
codegen::lua::SetJoystickAxisDeadZone,
codegen::lua::JoystickAxisDeadzone,
codegen::lua::BindJoystickButton,
codegen::lua::ClearJoystickButton,
codegen::lua::JoystickButton,
codegen::lua::AddGlobalRotation,
codegen::lua::AddLocalRotation,
codegen::lua::AddTruckMovement,
codegen::lua::AddLocalRoll,
codegen::lua::AddGlobalRoll,
codegen::lua::TriggerIdleBehavior
}
};
}

View File

@@ -22,34 +22,38 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/interaction/scriptcamerastates.h>
#include <openspace/navigation/navigationstate.h>
#include <numeric>
namespace openspace::luascriptfunctions {
int loadNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::loadNavigationState");
const std::string cameraStateFilePath = ghoul::lua::value<std::string>(L);
namespace {
/**
* Load a navigation state from file. The file should be a lua file returning the
* navigation state as a table formatted as a Navigation State, such as the output files
* of saveNavigationState.
*/
[[codegen::luawrap]] void loadNavigationState(std::string cameraStateFilePath) {
if (cameraStateFilePath.empty()) {
return ghoul::lua::luaError(L, "filepath string is empty");
throw ghoul::lua::LuaError("Filepath string is empty");
}
global::navigationHandler->loadNavigationState(cameraStateFilePath);
return 0;
openspace::global::navigationHandler->loadNavigationState(cameraStateFilePath);
}
int getNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 0, 1 }, "lua::getNavigationState");
std::optional<std::string> frame = ghoul::lua::value<std::optional<std::string>>(L);
/**
* Return the current navigation state as a lua table. The optional argument is the scene
* graph node to use as reference frame. By default, the reference frame will picked based
* on whether the orbital navigator is currently following the anchor node rotation. If it
* is, the anchor will be chosen as reference frame. If not, the reference frame will be
* set to the scene graph root.
*/
[[codegen::luawrap]] ghoul::Dictionary getNavigationState(
std::optional<std::string> frame)
{
using namespace openspace;
interaction::NavigationState state;
if (frame.has_value()) {
const SceneGraphNode* referenceFrame = sceneGraphNode(*frame);
if (!referenceFrame) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
fmt::format("Could not find node '{}' as reference frame", *frame)
);
}
@@ -59,157 +63,147 @@ int getNavigationState(lua_State* L) {
state = global::navigationHandler->navigationState();
}
const auto pushVector = [](lua_State* s, const glm::dvec3& v) {
lua_newtable(s);
ghoul::lua::push(s, 1, v.x);
lua_rawset(s, -3);
ghoul::lua::push(s, 2, v.y);
lua_rawset(s, -3);
ghoul::lua::push(s, 3, v.z);
lua_rawset(s, -3);
};
lua_newtable(L);
ghoul::lua::push(L, "Anchor", state.anchor);
lua_rawset(L, -3);
ghoul::Dictionary res;
res.setValue("Anchor", state.anchor);
if (!state.aim.empty()) {
ghoul::lua::push(L, "Aim", state.aim);
lua_rawset(L, -3);
res.setValue("Aim", state.aim);
}
if (!state.referenceFrame.empty()) {
ghoul::lua::push(L, "ReferenceFrame", state.referenceFrame);
lua_rawset(L, -3);
res.setValue("ReferenceFrame", state.referenceFrame);
}
ghoul::lua::push(L, "Position");
pushVector(L, state.position);
lua_rawset(L, -3);
res.setValue("ReferenceFrame", state.position);
if (state.up.has_value()) {
ghoul::lua::push(L, "Up");
pushVector(L, *state.up);
lua_rawset(L, -3);
res.setValue("Up", *state.up);
}
if (state.yaw != 0) {
ghoul::lua::push(L, "Yaw", state.yaw);
lua_rawset(L, -3);
res.setValue("Up", state.yaw);
}
if (state.pitch != 0) {
ghoul::lua::push(L, "Pitch", state.pitch);
lua_rawset(L, -3);
res.setValue("Pitch", state.pitch);
}
return 1;
return res;
}
int setNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::setNavigationState");
ghoul::Dictionary navigationStateDictionary = ghoul::lua::value<ghoul::Dictionary>(L);
// Set the navigation state. The argument must be a valid Navigation State.
[[codegen::luawrap]] void setNavigationState(ghoul::Dictionary navigationState) {
using namespace openspace;
openspace::documentation::TestResult r = openspace::documentation::testSpecification(
documentation::TestResult r = documentation::testSpecification(
interaction::NavigationState::Documentation(),
navigationStateDictionary
navigationState
);
if (!r.success) {
return ghoul::lua::luaError(
L,
throw ghoul::lua::LuaError(
fmt::format("Could not set camera state: {}", ghoul::to_string(r))
);
}
global::navigationHandler->setNavigationStateNextFrame(
interaction::NavigationState(navigationStateDictionary)
interaction::NavigationState(navigationState)
);
return 0;
}
int saveNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::saveNavigationState");
auto [path, frame] = ghoul::lua::values<std::string, std::optional<std::string>>(L);
frame = frame.value_or("");
/**
* Save the current navigation state to a file with the path given by the first argument.
* The optional second argument is the scene graph node to use as reference frame. By
* default, the reference frame will picked based on whether the orbital navigator is
* currently following the anchor node rotation. If it is, the anchor will be chosen as
* reference frame. If not, the reference frame will be set to the scene graph root.
*/
[[codegen::luawrap]] void saveNavigationState(std::string path, std::string frame = "") {
if (path.empty()) {
return ghoul::lua::luaError(L, "Filepath string is empty");
throw ghoul::lua::LuaError("Filepath string is empty");
}
global::navigationHandler->saveNavigationState(path, *frame);
return 0;
openspace::global::navigationHandler->saveNavigationState(path, frame);
}
int retargetAnchor(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::retargetAnchor");
global::navigationHandler->orbitalNavigator().startRetargetAnchor();
return 0;
// Reset the camera direction to point at the anchor node.
[[codegen::luawrap]] void retargetAnchor() {
openspace::global::navigationHandler->orbitalNavigator().startRetargetAnchor();
}
int retargetAim(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::retargetAim");
global::navigationHandler->orbitalNavigator().startRetargetAim();
return 0;
// Reset the camera direction to point at the aim node.
[[codegen::luawrap]] void retargetAim() {
openspace::global::navigationHandler->orbitalNavigator().startRetargetAim();
}
int bindJoystickAxis(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 3, 7 }, "lua::bindJoystickAxis");
auto [joystickName, axis, axisType, shouldInvert, joystickType, isSticky,
sensitivity] =
ghoul::lua::values<
std::string, int, std::string, std::optional<bool>,
std::optional<std::string>, std::optional<bool>, std::optional<double>
>(L);
shouldInvert = shouldInvert.value_or(false);
isSticky = isSticky.value_or(false);
sensitivity = sensitivity.value_or(0.0);
joystickType = joystickType.value_or("JoystickLike");
/**
* Finds the input joystick with the given 'name' and binds the axis identified by the
* second argument to be used as the type identified by the third argument. If
* 'isInverted' is 'true', the axis value is inverted. 'joystickType' is if the joystick
* behaves more like a joystick or a trigger, where the first is the default. If
* 'isSticky' is 'true', the value is calculated relative to the previous value. If
* 'sensitivity' is given then that value will affect the sensitivity of the axis together
* with the global sensitivity.
*/
[[codegen::luawrap]] void bindJoystickAxis(std::string joystickName, int axis,
std::string axisType,
bool shouldInvert = false,
std::string joystickType = "JoystickLike",
bool isSticky = false,
double sensitivity = 0.0)
{
using namespace openspace;
using JoystickCameraStates = interaction::JoystickCameraStates;
global::navigationHandler->setJoystickAxisMapping(
std::move(joystickName),
axis,
ghoul::from_string<interaction::JoystickCameraStates::AxisType>(axisType),
interaction::JoystickCameraStates::AxisInvert(*shouldInvert),
ghoul::from_string<interaction::JoystickCameraStates::JoystickType>(*joystickType),
*isSticky,
*sensitivity
ghoul::from_string<JoystickCameraStates::AxisType>(axisType),
JoystickCameraStates::AxisInvert(shouldInvert),
ghoul::from_string<JoystickCameraStates::JoystickType>(joystickType),
isSticky,
sensitivity
);
return 0;
}
int bindJoystickAxisProperty(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 3, 7 }, "lua::bindJoystickAxisProperty");
auto [joystickName, axis, propertyUri, min, max, shouldInvert, isRemote] =
ghoul::lua::values<
std::string, int, std::string, std::optional<float>, std::optional<float>,
std::optional<bool>, std::optional<bool>
>(L);
min = min.value_or(0.f);
max = max.value_or(1.f);
shouldInvert = shouldInvert.value_or(false);
isRemote = isRemote.value_or(true);
/**
* Finds the input joystick with the given 'name' and binds the axis identified by the
* second argument to be bound to the property identified by the third argument. 'min' and
* 'max' is the minimum and the maximum allowed value for the given property and the axis
* value is rescaled from [-1, 1] to [min, max], default is [0, 1]. If 'isInverted' is
* 'true', the axis value is inverted. The last argument determines whether the property
* change is going to be executed locally or remotely, where the latter is the default.
*/
[[codegen::luawrap]] void bindJoystickAxisProperty(std::string joystickName, int axis,
std::string propertyUri,
float min = 0.f, float max = 1.f,
bool shouldInvert = false,
bool isRemote = true)
{
using namespace openspace;
global::navigationHandler->setJoystickAxisMappingProperty(
std::move(joystickName),
axis,
std::move(propertyUri),
*min,
*max,
interaction::JoystickCameraStates::AxisInvert(*shouldInvert),
*isRemote
min,
max,
interaction::JoystickCameraStates::AxisInvert(shouldInvert),
isRemote
);
return 0;
}
int joystickAxis(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::joystickAxis");
auto [joystickName, axis] = ghoul::lua::values<std::string, int>(L);
/**
* Finds the input joystick with the given 'name' and returns the joystick axis
* information for the passed axis. The information that is returned is the current axis
* binding as a string, whether the values are inverted as bool, the joystick type as a
* string, whether the axis is sticky as bool, the sensitivity as number, the property uri
* bound to the axis as string (empty is type is not Property), the min and max values for
* the property as numbers and whether the property change will be executed remotly as
* bool.
*/
[[codegen::luawrap]]
std::tuple<std::string, bool, std::string, bool, double, std::string, float, float, bool>
joystickAxis(std::string joystickName, int axis)
{
using namespace openspace;
using AI = interaction::JoystickCameraStates::AxisInformation;
AI info = global::navigationHandler->joystickAxisMapping(joystickName, axis);
interaction::JoystickCameraStates::AxisInformation info =
global::navigationHandler->joystickAxisMapping(joystickName, axis);
ghoul::lua::push(
L,
return {
ghoul::to_string(info.type),
static_cast<bool>(info.invert),
info.invert,
ghoul::to_string(info.joystickType),
info.isSticky,
info.sensitivity,
@@ -217,67 +211,74 @@ int joystickAxis(lua_State* L) {
info.minValue,
info.maxValue,
info.isRemote
);
return 9;
};
}
int setJoystickAxisDeadzone(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 3, "lua::setJoystickAxisDeadzone");
auto [joystickName, axis, deadzone] = ghoul::lua::values<std::string, int, float>(L);
/**
* Finds the input joystick with the given 'name' and sets the deadzone for a particular
* joystick axis, which means that any input less than this value is completely ignored.
*/
[[codegen::luawrap]] void setJoystickAxisDeadZone(std::string joystickName, int axis,
float deadzone)
{
using namespace openspace;
global::navigationHandler->setJoystickAxisDeadzone(joystickName, axis, deadzone);
return 0;
}
int joystickAxisDeadzone(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::joystickAxisDeadzone");
auto [joystickName, axis] = ghoul::lua::values<std::string, int>(L);
const float deadzone = global::navigationHandler->joystickAxisDeadzone(joystickName, axis);
ghoul::lua::push(L, deadzone);
return 1;
/**
* Returns the deadzone for the desired axis of the provided joystick.
*/
[[codegen::luawrap]] float joystickAxisDeadzone(std::string joystickName, int axis) {
float deadzone = openspace::global::navigationHandler->joystickAxisDeadzone(
joystickName,
axis
);
return deadzone;
}
int bindJoystickButton(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 4, 6 }, "lua::bindJoystickButton");
auto [joystickName, button, command, documentation, actionStr, isRemote] =
ghoul::lua::values<
std::string,
int,
std::string,
std::string,
std::optional<std::string>,
std::optional<bool>
>(L);
actionStr = actionStr.value_or("Press");
isRemote = isRemote.value_or(true);
interaction::JoystickAction action =
ghoul::from_string<interaction::JoystickAction>(*actionStr);
/**
* Finds the input joystick with the given 'name' and binds a Lua script given by the
* third argument to be executed when the joystick button identified by the second
* argument is triggered. The fifth argument determines when the script should be
* executed, this defaults to 'Press', which means that the script is run when the user
* presses the button. The fourth arguemnt is the documentation of the script in the third
* argument. The sixth argument determines whether the command is going to be executable
* locally or remotely, where the latter is the default.
*/
[[codegen::luawrap]] void bindJoystickButton(std::string joystickName, int button,
std::string command,
std::string documentation,
std::string action = "Press",
bool isRemote = true)
{
using namespace openspace;
interaction::JoystickAction act =
ghoul::from_string<interaction::JoystickAction>(action);
global::navigationHandler->bindJoystickButtonCommand(
joystickName,
button,
command,
action,
interaction::JoystickCameraStates::ButtonCommandRemote(*isRemote),
act,
interaction::JoystickCameraStates::ButtonCommandRemote(isRemote),
documentation
);
return 0;
}
int clearJoystickButton(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::clearJoystickButton");
auto [joystickName, button] = ghoul::lua::values<std::string, int>(L);
global::navigationHandler->clearJoystickButtonCommand(joystickName, button);
return 0;
/**
* Finds the input joystick with the given 'name' and removes all commands that are
* currently bound to the button identified by the second argument.
*/
[[codegen::luawrap]] void clearJoystickButton(std::string joystickName, int button) {
openspace::global::navigationHandler->clearJoystickButtonCommand(joystickName, button);
}
int joystickButton(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::joystickButton");
auto [joystickName, button] = ghoul::lua::values<std::string, int>(L);
/**
* Finds the input joystick with the given 'name' and returns the script that is currently
* bound to be executed when the provided button is pressed.
*/
[[codegen::luawrap]] std::string joystickButton(std::string joystickName, int button) {
using namespace openspace;
const std::vector<std::string>& cmds =
global::navigationHandler->joystickButtonCommand(joystickName, button);
@@ -289,74 +290,63 @@ int joystickButton(lua_State* L) {
return lhs + ";" + rhs;
}
);
ghoul::lua::push(L, cmd);
return 1;
return cmd;
}
int addGlobalRotation(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addGlobalRotation");
auto [v1, v2] = ghoul::lua::values<double, double>(L);
// Directly adds to the global rotation of the camera.
[[codegen::luawrap]] void addGlobalRotation(double v1, double v2) {
using namespace openspace;
global::navigationHandler->orbitalNavigator().scriptStates().addGlobalRotation(
glm::dvec2(v1, v2)
);
return 0;
}
int addLocalRotation(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addLocalRotation");
auto [v1, v2] = ghoul::lua::values<double, double>(L);
// Directly adds to the local rotation of the camera.
[[codegen::luawrap]] void addLocalRotation(double v1, double v2) {
using namespace openspace;
global::navigationHandler->orbitalNavigator().scriptStates().addLocalRotation(
glm::dvec2(v1, v2)
);
return 0;
}
int addTruckMovement(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addTruckMovement");
auto [v1, v2] = ghoul::lua::values<double, double>(L);
// Directly adds to the truck movement of the camera.
[[codegen::luawrap]] void addTruckMovement(double v1, double v2) {
using namespace openspace;
global::navigationHandler->orbitalNavigator().scriptStates().addTruckMovement(
glm::dvec2(v1, v2)
);
return 0;
}
int addLocalRoll(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addLocalRoll");
auto [v1, v2] = ghoul::lua::values<double, double>(L);
// Directly adds to the local roll of the camera.
[[codegen::luawrap]] void addLocalRoll(double v1, double v2) {
using namespace openspace;
global::navigationHandler->orbitalNavigator().scriptStates().addLocalRoll(
glm::dvec2(v1, v2)
);
return 0;
}
int addGlobalRoll(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 2, "lua::addGlobalRoll");
auto [v1, v2] = ghoul::lua::values<double, double>(L);
// Directly adds to the global roll of the camera.
[[codegen::luawrap]] void addGlobalRoll(double v1, double v2) {
using namespace openspace;
global::navigationHandler->orbitalNavigator().scriptStates().addGlobalRoll(
glm::dvec2(v1, v2)
);
return 0;
}
int triggerIdleBehavior(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, {0, 1}, "lua::triggerIdleBehavior");
std::optional<std::string> choice = ghoul::lua::value<std::optional<std::string>>(L);
/**
* Immediately start applying the chosen IdleBehavior. If none is specified, use the one
* set to default in the OrbitalNavigator.
*/
[[codegen::luawrap]] void triggerIdleBehavior(std::string choice = "") {
using namespace openspace;
try {
global::navigationHandler->orbitalNavigator().triggerIdleBehavior(
choice.value_or("")
);
global::navigationHandler->orbitalNavigator().triggerIdleBehavior(choice);
}
catch (ghoul::RuntimeError& e) {
return ghoul::lua::luaError(L, e.message);
throw ghoul::lua::LuaError(e.message);
}
return 0;
}
} // namespace openspace::luascriptfunctions
#include "navigationhandler_lua_codegen.cpp"
} // namespace

View File

@@ -27,18 +27,28 @@
#include <openspace/camera/camera.h>
#include <openspace/camera/camerapose.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/engine/openspaceengine.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/navigationstate.h>
#include <openspace/navigation/pathnavigator.h>
#include <openspace/query/query.h>
#include <openspace/rendering/renderengine.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/scripting/scriptengine.h>
#include <openspace/util/timemanager.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <vector>
#include "pathnavigator_lua.inl"
namespace {
constexpr const char* _loggerCat = "PathNavigator";
@@ -97,8 +107,6 @@ namespace {
};
} // namespace
#include "pathnavigator_lua.inl"
namespace openspace::interaction {
PathNavigator::PathNavigator()
@@ -467,95 +475,17 @@ scripting::LuaLibrary PathNavigator::luaLibrary() {
return {
"pathnavigation",
{
{
"isFlying",
&luascriptfunctions::isFlying,
"",
"Returns true if a camera path is currently running, and false otherwise"
},
{
"continuePath",
&luascriptfunctions::continuePath,
"",
"Continue playing a paused camera path"
},
{
"pausePath",
&luascriptfunctions::pausePath,
"",
"Pause a playing camera path"
},
{
"stopPath",
&luascriptfunctions::stopPath,
"",
"Stops a path, if one is being played"
},
{
"flyTo",
&luascriptfunctions::flyTo,
"string [, bool, double]",
"Move the camera to the node with the specified identifier. The optional "
"double specifies the duration of the motion, in seconds. If the optional "
"bool is set to true the target up vector for camera is set based on the "
"target node. Either of the optional parameters can be left out."
},
{
"flyToHeight",
&luascriptfunctions::flyToHeight,
"string, double [, bool, double]",
"Move the camera to the node with the specified identifier. The second "
"argument is the desired target height above the target node's bounding "
"sphere, in meters. The optional double specifies the duration of the "
"motion, in seconds. If the optional bool is set to true, the target "
"up vector for camera is set based on the target node. Either of the "
"optional parameters can be left out."
},
{
"flyToNavigationState",
&luascriptfunctions::flyToNavigationState,
"table, [double]",
"Create a path to the navigation state described by the input table. "
"The optional double specifies the target duration of the motion, "
"in seconds. Note that roll must be included for the target up "
"direction to be taken into account."
},
{
"zoomToFocus",
&luascriptfunctions::zoomToFocus,
"[duration]",
"Zoom linearly to the current focus node, using the default distance."
"The optional input parameter specifies the duration for the motion, "
"in seconds."
},
{
"zoomToDistance",
&luascriptfunctions::zoomToDistance,
"distance, [duration]",
"Fly linearly to a specific distance in relation to the focus node. "
"The distance is given in meters above the bounding sphere of the "
"current focus node."
"The optional input parameter specifies the duration for the motion, "
"in seconds."
},
{
"zoomToDistanceRelative",
&luascriptfunctions::zoomToDistanceRelative,
"distance, [duration]",
"Fly linearly to a specific distance in relation to the focus node. "
"The distance is given as a multiple of the bounding sphere of the "
"current focus node. That is, a value of 1 will result in a position "
"at a distance of one times the size of the bounding sphere away from "
"the object."
"The optional input parameter specifies the duration for the motion, "
"in seconds."
},
{
"createPath",
&luascriptfunctions::createPath,
"table",
"Create a camera path as described by the lua table input argument"
},
codegen::lua::IsFlying,
codegen::lua::ContinuePath,
codegen::lua::PausePath,
codegen::lua::StopPath,
codegen::lua::FlyTo,
codegen::lua::FlyToHeight,
codegen::lua::FlyToNavigationState,
codegen::lua::ZoomToFocus,
codegen::lua::ZoomToDistance,
codegen::lua::ZoomToDistanceRelative,
codegen::lua::CreatePath
}
};
}

View File

@@ -22,63 +22,50 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <openspace/camera/camera.h>
#include <openspace/engine/globals.h>
#include <openspace/engine/moduleengine.h>
#include <openspace/navigation/navigationhandler.h>
#include <openspace/navigation/navigationstate.h>
#include <openspace/navigation/pathnavigator.h>
#include <openspace/scene/scenegraphnode.h>
#include <openspace/scripting/lualibrary.h>
#include <openspace/util/updatestructures.h>
#include <openspace/query/query.h>
#include <ghoul/filesystem/file.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <glm/gtx/vector_angle.hpp>
namespace openspace::luascriptfunctions {
int isFlying(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::isFlying");
namespace {
// Returns true if a camera path is currently running, and false otherwise.
[[codegen::luawrap]] bool isFlying() {
using namespace openspace;
bool hasFinished = global::navigationHandler->pathNavigator().hasFinished();
ghoul::lua::push(L, !hasFinished);
return 1;
return hasFinished;
}
int continuePath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::continuePath");
global::navigationHandler->pathNavigator().continuePath();
return 0;
// Continue playing a paused camera path.
[[codegen::luawrap]] void continuePath() {
openspace::global::navigationHandler->pathNavigator().continuePath();
}
int pausePath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::pausePath");
global::navigationHandler->pathNavigator().pausePath();
return 0;
// Pause a playing camera path.
[[codegen::luawrap]] void pausePath() {
openspace::global::navigationHandler->pathNavigator().pausePath();
}
int stopPath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 0, "lua::stopPath");
global::navigationHandler->pathNavigator().abortPath();
return 0;
// Stops a path, if one is being played.
[[codegen::luawrap]] void stopPath() {
openspace::global::navigationHandler->pathNavigator().abortPath();
}
int flyTo(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 3 }, "lua::flyTo");
auto [nodeIdentifier, useUpFromTargetOrDuration, duration] = ghoul::lua::values<
std::string, std::optional<std::variant<bool, double>>, std::optional<double>
>(L);
/**
* Move the camera to the node with the specified identifier. The optional double
* specifies the duration of the motion, in seconds. If the optional bool is set to true
* the target up vector for camera is set based on the target node. Either of the optional
* parameters can be left out.
*/
[[codegen::luawrap]] void flyTo(std::string nodeIdentifier,
std::optional<std::variant<bool, double>> useUpFromTargetOrDuration,
std::optional<double> duration)
{
using namespace openspace;
if (useUpFromTargetOrDuration.has_value() &&
std::holds_alternative<double>(*useUpFromTargetOrDuration)
&& duration.has_value())
std::holds_alternative<double>(*useUpFromTargetOrDuration) &&
duration.has_value())
{
return ghoul::lua::luaError(L, "Duration cannot be specified twice");
throw ghoul::lua::LuaError("Duration cannot be specified twice");
}
if (!sceneGraphNode(nodeIdentifier)) {
return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier);
throw ghoul::lua::LuaError("Unknown node name: " + nodeIdentifier);
}
ghoul::Dictionary insDict;
@@ -94,7 +81,7 @@ int flyTo(lua_State* L) {
else {
double d = std::get<double>(*useUpFromTargetOrDuration);
if (d <= 0.0) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
@@ -102,7 +89,7 @@ int flyTo(lua_State* L) {
if (duration.has_value()) {
double d = *duration;
if (d <= 0.0) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
@@ -112,20 +99,22 @@ int flyTo(lua_State* L) {
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
return 0;
}
int flyToHeight(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 2, 4 }, "lua::flyToHeight");
auto [nodeIdentifier, height, useUpFromTargetOrDuration, duration] =
ghoul::lua::values<
std::string, double, std::optional<std::variant<bool, double>>,
std::optional<double>
>(L);
/**
* Move the camera to the node with the specified identifier. The second argument is the
* desired target height above the target node's bounding sphere, in meters. The optional
* double specifies the duration of the motion, in seconds. If the optional bool is set to
* true, the target up vector for camera is set based on the target node. Either of the
* optional parameters can be left out.
*/
[[codegen::luawrap]] void flyToHeight(std::string nodeIdentifier, double height,
std::optional<std::variant<bool, double>> useUpFromTargetOrDuration,
std::optional<double> duration)
{
using namespace openspace;
if (!sceneGraphNode(nodeIdentifier)) {
return ghoul::lua::luaError(L, "Unknown node name: " + nodeIdentifier);
throw ghoul::lua::LuaError("Unknown node name: " + nodeIdentifier);
}
ghoul::Dictionary insDict;
@@ -142,7 +131,7 @@ int flyToHeight(lua_State* L) {
else {
double d = std::get<double>(*useUpFromTargetOrDuration);
if (d <= 0.0) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
@@ -150,7 +139,7 @@ int flyToHeight(lua_State* L) {
if (duration.has_value()) {
double d = *duration;
if (d <= 0.0) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
@@ -160,27 +149,27 @@ int flyToHeight(lua_State* L) {
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
return 0;
}
int flyToNavigationState(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::flyToNavigationState");
auto [navigationState, duration] =
ghoul::lua::values<ghoul::Dictionary, std::optional<double>>(L);
/**
* Create a path to the navigation state described by the input table. The optional
* double specifies the target duration of the motion, in seconds. Note that roll must be
* included for the target up direction to be taken into account.
*/
[[codegen::luawrap]] void flyToNavigationState(ghoul::Dictionary navigationState,
std::optional<double> duration)
{
using namespace openspace;
try {
openspace::documentation::testSpecificationAndThrow(
documentation::testSpecificationAndThrow(
interaction::NavigationState::Documentation(),
navigationState,
"NavigationState"
);
}
catch (documentation::SpecificationError& e) {
catch (const documentation::SpecificationError& e) {
LERRORC("flyToNavigationState", ghoul::to_string(e.result));
return ghoul::lua::luaError(
L, fmt::format("Unable to create a path: {}", e.what())
);
throw ghoul::lua::LuaError(fmt::format("Unable to create a path: {}", e.what()));
}
ghoul::Dictionary instruction;
@@ -190,7 +179,7 @@ int flyToNavigationState(lua_State* L) {
if (duration.has_value()) {
double d = *duration;
if (d <= 0.0) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
instruction.setValue("Duration", d);
}
@@ -200,16 +189,17 @@ int flyToNavigationState(lua_State* L) {
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
return 0;
}
int zoomToFocus(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 0, 1 }, "lua::zoomToFocus");
std::optional<double> duration = ghoul::lua::value<std::optional<double>>(L);
/**
* Zoom linearly to the current focus node, using the default distance. The optional input
* parameter specifies the duration for the motion, in seconds.
*/
[[codegen::luawrap]] void zoomToFocus(std::optional<double> duration) {
using namespace openspace;
const SceneGraphNode* node = global::navigationHandler->anchorNode();
if (!node) {
return ghoul::lua::luaError(L, "Could not determine current focus node");
throw ghoul::lua::LuaError("Could not determine current focus node");
}
ghoul::Dictionary insDict;
@@ -220,7 +210,7 @@ int zoomToFocus(lua_State* L) {
if (duration.has_value()) {
double d = *duration;
if (d <= 0.0) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
@@ -230,22 +220,23 @@ int zoomToFocus(lua_State* L) {
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
return 0;
}
int zoomToDistance(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::zoomToDistance");
auto [distance, duration] =
ghoul::lua::values<double, std::optional<double>>(L);
/**
* Fly linearly to a specific distance in relation to the focus node. The distance is
* given in meters above the bounding sphere of the current focus node. The optional input
* parameter specifies the duration for the motion, in seconds.
*/
[[codegen::luawrap]] void zoomToDistance(double distance, std::optional<double> duration)
{
using namespace openspace;
if (distance <= 0.0) {
return ghoul::lua::luaError(L, "The distance must be larger than zero");
throw ghoul::lua::LuaError("The distance must be larger than zero");
}
const SceneGraphNode* node = global::navigationHandler->anchorNode();
if (!node) {
return ghoul::lua::luaError(L, "Could not determine current focus node");
throw ghoul::lua::LuaError("Could not determine current focus node");
}
ghoul::Dictionary insDict;
@@ -257,7 +248,7 @@ int zoomToDistance(lua_State* L) {
if (duration.has_value()) {
double d = *duration;
if (d <= 0.0) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
@@ -267,22 +258,26 @@ int zoomToDistance(lua_State* L) {
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
return 0;
}
int zoomToDistanceRelative(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, { 1, 2 }, "lua::zoomToDistanceRelative");
auto [distance, duration] =
ghoul::lua::values<double, std::optional<double>>(L);
/**
* Fly linearly to a specific distance in relation to the focus node. The distance is
* given as a multiple of the bounding sphere of the current focus node. That is, a value
* of 1 will result in a position at a distance of one times the size of the bounding
* sphere away from the object. The optional input parameter specifies the duration for
* the motion, in seconds.
*/
[[codegen::luawrap]] void zoomToDistanceRelative(double distance,
std::optional<double> duration)
{
using namespace openspace;
if (distance <= 0.0) {
return ghoul::lua::luaError(L, "The distance must be larger than zero");
throw ghoul::lua::LuaError("The distance must be larger than zero");
}
const SceneGraphNode* node = global::navigationHandler->anchorNode();
if (!node) {
return ghoul::lua::luaError(L, "Could not determine current focus node");
throw ghoul::lua::LuaError("Could not determine current focus node");
}
distance *= node->boundingSphere();
@@ -296,7 +291,7 @@ int zoomToDistanceRelative(lua_State* L) {
if (duration.has_value()) {
double d = *duration;
if (d <= 0.0) {
return ghoul::lua::luaError(L, "Duration must be larger than zero");
throw ghoul::lua::LuaError("Duration must be larger than zero");
}
insDict.setValue("Duration", d);
}
@@ -306,19 +301,17 @@ int zoomToDistanceRelative(lua_State* L) {
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
return 0;
}
int createPath(lua_State* L) {
ghoul::lua::checkArgumentsAndThrow(L, 1, "lua::createPath");
ghoul::Dictionary dictionary = ghoul::lua::value<ghoul::Dictionary>(L);
global::navigationHandler->pathNavigator().createPath(dictionary);
// Create a camera path as described by the lua table input argument.
[[codegen::luawrap]] void createPath(ghoul::Dictionary path) {
using namespace openspace;
global::navigationHandler->pathNavigator().createPath(path);
if (global::navigationHandler->pathNavigator().hasCurrentPath()) {
global::navigationHandler->pathNavigator().startPath();
}
return 0;
}
} // namespace openspace::luascriptfunctions
#include "pathnavigator_lua_codegen.cpp"
} // namespace

View File

@@ -733,30 +733,10 @@ scripting::LuaLibrary ParallelPeer::luaLibrary() {
return {
"parallel",
{
{
"connect",
&luascriptfunctions::connect,
"",
"Connect to parallel"
},
{
"disconnect",
&luascriptfunctions::disconnect,
"",
"Disconnect from parallel"
},
{
"requestHostship",
&luascriptfunctions::requestHostship,
"",
"Request to be the host for this session"
},
{
"resignHostship",
&luascriptfunctions::resignHostship,
"",
"Resign hostship"
},
codegen::lua::Connect,
codegen::lua::Disconnect,
codegen::lua::RequestHostship,
codegen::lua::ResignHostship
}
};
}

Some files were not shown because too many files have changed in this diff Show More