diff --git a/apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp b/apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp index 39fb240a24..6e620a6959 100644 --- a/apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp +++ b/apps/OpenSpace/ext/launcher/src/profile/actiondialog.cpp @@ -485,9 +485,9 @@ void ActionDialog::actionRemove() { for (size_t i = 0; i < _actionData.size(); ++i) { if (_actionData[i].identifier == action->identifier) { + clearActionFields(); _actionData.erase(_actionData.begin() + i); delete _actionWidgets.list->takeItem(static_cast(i)); - clearActionFields(); _keybindingWidgets.action->clear(); for (const Profile::Action& a : _actionData) { @@ -661,9 +661,9 @@ void ActionDialog::keybindingRemove() { if (_keybindingsData[i].key == keybinding->key && _keybindingsData[i].action == keybinding->action) { + clearKeybindingFields(); _keybindingsData.erase(_keybindingsData.begin() + i); delete _keybindingWidgets.list->takeItem(static_cast(i)); - clearKeybindingFields(); return; } } diff --git a/data/assets/scene/milkyway/constellations/constellation_art.asset b/data/assets/scene/milkyway/constellations/constellation_art.asset index e123e299f6..d0d1b3080e 100644 --- a/data/assets/scene/milkyway/constellations/constellation_art.asset +++ b/data/assets/scene/milkyway/constellations/constellation_art.asset @@ -62,11 +62,11 @@ local createConstellations = function (baseIdentifier, guiPath, constellationfil BlendMode = "Additive", Opacity = 0.1 }, - Tag = { "ConstellationArtImage", group }, + Tag = { "ImageConstellation", group }, GUI = { Name = name .. " Image", Path = "/Milky Way/" .. guiPath, - Description = name .. " Constellation Image" + Description = name .. " Image" } } table.insert(genConstellations, aconstellation); @@ -83,9 +83,9 @@ local show_art = { Identifier = "constellation_art.show_art", Name = "Show Constellation Art", Command = [[ - openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Opacity", 0); - openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Enabled", true); - openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Opacity", 0.2, 2); + openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Opacity", 0); + openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Enabled", true); + openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Opacity", 0.2, 2); ]], Documentation = "Enables and fades up constellation art work", GuiPath = "/Rendering", @@ -96,7 +96,7 @@ asset.export("ShowArtAction", show_art) local hide_art = { Identifier = "constellation_art.hide_art", Name = "Hide Constellation Art", - Command = [[openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Opacity", 0, 2)]], + Command = [[openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Opacity", 0, 2)]], Documentation = "Fades out constellation artwork", GuiPath = "/Rendering", IsLocal = false @@ -106,7 +106,7 @@ asset.export("HideArtAction", hide_art) local disable_art = { Identifier = "constellation_art.disable_art", Name = "Disable Constellation Art", - Command = [[openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Enabled", false)]], + Command = [[openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Enabled", false)]], Documentation = "Disable constellation artwork", GuiPath = "/Rendering", IsLocal = false @@ -117,7 +117,7 @@ local show_zodiac_art = { Identifier = "constellation_art.show_zodiac_art", Name = "Show Zodiac Art", Command = [[ - openspace.setPropertyValue("Scene.ConstellationArt*.Renderable.Opacity", 0); + openspace.setPropertyValue("Scene.ImageConstellation*.Renderable.Opacity", 0); openspace.setPropertyValue("{zodiac}.Renderable.Enabled",true); openspace.setPropertyValue("{zodiac}.Renderable.Opacity", 1, 2); ]], @@ -142,7 +142,7 @@ local nodes = {} asset.onInitialize(function () local constellationsCSV = images .. "constellation_data.csv" - nodes = createConstellations("ConstellationArt", "Constellation Art", constellationsCSV) + nodes = createConstellations("ImageConstellation", "Constellation Art", constellationsCSV) for _, n in ipairs(nodes) do openspace.addSceneGraphNode(n); end diff --git a/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines.asset b/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines.asset new file mode 100644 index 0000000000..2b33fc303e --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines.asset @@ -0,0 +1,3 @@ +asset.require("./sun_earth_2012_fieldlines_enlil") +asset.require("./sun_earth_2012_fieldlines_batsrus") +asset.require("./sun_earth_2012_fieldlines_pfss") diff --git a/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_batsrus.asset b/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_batsrus.asset new file mode 100644 index 0000000000..f4419c8362 --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_batsrus.asset @@ -0,0 +1,153 @@ +local transforms = asset.require('scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset') + +-- Specifying transfer functions +local transferFunctions = asset.syncedResource({ + Name = "Fieldlines Transfer Functions", + Type = "HttpSynchronization", + Identifier = "sun_earth_event_july_2012-fieldlines_transferfunctions", + Version = 1 +}) + +-- Specifying transfer functions +local fieldlineData = asset.syncedResource({ + Name = "Fieldlines Data", + Type = "HttpSynchronization", + Identifier = "sun_earth_event_july_2012-batsrus", + Version = 1 +}) + +local batsrusTemperatureColorTable = transferFunctions .. "batsrus_temperature.txt" +local batsrusDensityColorTable = transferFunctions .. "batsrus_density.txt" +local batsrusCurrentColorTable = transferFunctions .. "batsrus_current2.txt" +local batsrusVelocityColorTable = transferFunctions .. "batsrus_velocity.txt" +local batsrusTopologyColorTable = transferFunctions .. "batsrus_topology.txt" + +local unzippedDataDestination = { + openClosed = fieldlineData .. "magnetic_fieldlines-open_closed", + velocityFlow = fieldlineData .. "velocity_flowlines-upstream", + asherStatic = fieldlineData .. "ashers_static_seeds" +} + +local colorRanges = { + { 0, 100000000 }, + { 0, 60 }, + { -0.015, 0.015 }, + { 150, 900 }, + { 0, 3 }, +} +----------------------LUTZ's JULY TRACES------------------------- +local BatsrusJ12OpenClosed = { + Identifier = "FL_BATSRUS_J12_OpenClosed", + Parent = transforms.GSMReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.openClosed, + InputFileType = "Osfls", + Color = { 0.7, 0.4, 0.0, 0.6 }, -- Default color + ColorMethod = "By Quantity", -- Color by Quantity + ColorQuantity = 0, -- Temperature + ColorTablePaths = { + batsrusTemperatureColorTable, + batsrusDensityColorTable, + batsrusCurrentColorTable, + batsrusVelocityColorTable, + batsrusTopologyColorTable, + }, + ColorTableRanges = colorRanges, + MaskingEnabled = true, + MaskingQuantity = 4, -- Topology + MaskingRanges = { {2.5, 3.0} }, -- Corresponds to closed fieldlines only + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines BATSRUS J12 Open/Closed", + Path = "/Solar System/Heliosphere" + } +} + +--------------------- VELOCITY FLOWLINES ------------------------ +local BatsrusJ12FlowLines = { + Identifier = "FL_BATSRUS_J12_FlowLines", + Parent = transforms.GSMReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.velocityFlow, + InputFileType = "Osfls", + ColorMethod = "By Quantity", -- Color by Quantity + ColorQuantity = 3, -- Velocity + Color = { 0.7, 0.4, 0.0, 0.12 }, -- Default color + ColorTablePaths = { + batsrusTemperatureColorTable, + batsrusDensityColorTable, + batsrusCurrentColorTable, + batsrusVelocityColorTable, + batsrusTopologyColorTable, + }, + ColorTableRanges = colorRanges, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines BATSRUS J12 Flowlines", + Path = "/Solar System/Heliosphere" + } +} + +--------------------- Ashers seedpoints ------------------------ +local BatsrusAsherStaticSeedsFlowLines = { + Identifier = "FL_BATSRUS_ASHER_STATIC_SSEDS_FlowLines", + Parent = transforms.GSMReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.asherStatic, + Enabled = false, + InputFileType = "Osfls", + ColorTablePaths = { + batsrusTemperatureColorTable, + batsrusDensityColorTable, + batsrusCurrentColorTable, + batsrusVelocityColorTable, + batsrusTopologyColorTable, + }, + ColorTableRanges = colorRanges, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines BATSRUS Asher Static", + Path = "/Solar System/Heliosphere" + } +} + +asset.onInitialize(function () + if not openspace.directoryExists(unzippedDataDestination.openClosed) then + openspace.printInfo("Extracting " .. "Fieldlines from Batsrus model of 2012 event") + openspace.unzipFile(fieldlineData .. "magnetic_fieldlines-open_closed.zip", unzippedDataDestination.openClosed, true) + end + if not openspace.directoryExists(unzippedDataDestination.velocityFlow) then + openspace.printInfo("Extracting " .. "Fieldlines from Batsrus model of 2012 event") + openspace.unzipFile(fieldlineData .. "velocity_flowlines-upstream.zip", unzippedDataDestination.velocityFlow, true) + end + if not openspace.directoryExists(unzippedDataDestination.asherStatic) then + openspace.printInfo("Extracting " .. "Fieldlines from Batsrus model of 2012 event") + openspace.unzipFile(fieldlineData .. "ashers_static_seeds.zip", unzippedDataDestination.asherStatic, true) + end + + openspace.addSceneGraphNode(BatsrusJ12OpenClosed) + openspace.addSceneGraphNode(BatsrusJ12FlowLines) + openspace.addSceneGraphNode(BatsrusAsherStaticSeedsFlowLines) + +end) + +asset.onDeinitialize(function () + openspace.removeSceneGraphNode(BatsrusAsherStaticSeedsFlowLines) + openspace.removeSceneGraphNode(BatsrusJ12FlowLines) + openspace.removeSceneGraphNode(BatsrusJ12OpenClosed) +end) + +asset.meta = { + Name = "Fieldlines from Batsrus model of 2012 event", + Version = "1.0", + Description = "Magnetic fieldlines from Batsrus model for a 2012 CME event", + Author = "CCMC", + URL = "", + License = "CC-BY" +} diff --git a/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_enlil.asset b/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_enlil.asset new file mode 100644 index 0000000000..9a0a8e904e --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_enlil.asset @@ -0,0 +1,228 @@ +local transforms = asset.require('scene/solarsystem/sun/transforms_heliosphere.asset') + +local transferFunctions = asset.syncedResource({ + Name = "Fieldlines Transfer Functions", + Type = "HttpSynchronization", + Identifier = "sun_earth_event_july_2012-fieldlines_transferfunctions", + Version = 1 +}) + +local fieldlineData = asset.syncedResource({ + Name = "Fieldlines Data", + Type = "HttpSynchronization", + Identifier = "sun_earth_event_july_2012-enlil", + Version = 1 +}) + +local enlilDensityColorTable = transferFunctions .. "enlil_density.txt" +local enlilVelocityColorTable = transferFunctions .. "kroyw.txt" + +local unzippedDataDestination = { + EqPlane011AU1 = fieldlineData .. "011AU_eq_plane_1/", + EqPlane011AU2 = fieldlineData .. "011AU_eq_plane_2/", + Lat4011AU1 = fieldlineData .. "011AU_lat4_1/", + Lat4011AU2 = fieldlineData .. "011AU_lat4_2/", + Earth = fieldlineData .. "earth/", + StereoA = fieldlineData .. "stereoa/" +} + +local colorRanges = { + { 0, 1000000 }, + { 100, 2000 } +} + +local ENLILSliceEqPlane11AU1 = { + Identifier = "FL_ENLIL_slice_eqPlane_011AU_1", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.EqPlane011AU1, + InputFileType = "Osfls", + + Color = { 0.4, 0.15, 0.4, 0.6 }, + ColorMethod = "By Quantity", -- Color by Quantity + ColorQuantity = 1, -- Velocity + ColorTablePaths = { + enlilDensityColorTable, + enlilVelocityColorTable, + }, + ColorTableRanges = colorRanges, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines ENLIL Slice Equatorial Plane 0.11 AU 1", + Path = "/Solar System/Heliosphere" + } +} + +local ENLILSliceEqPlane11AU2 = { + Identifier = "FL_ENLIL_slice_eqPlane_011AU_2", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.EqPlane011AU2, + InputFileType = "Osfls", + + Color = { 0.4, 0.15, 0.4, 0.6 }, + ColorMethod = "By Quantity", -- Color by Quantity + ColorQuantity = 1, -- Velocity + ColorTablePaths = { + enlilDensityColorTable, + enlilVelocityColorTable, + }, + ColorTableRanges = colorRanges, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines ENLIL Slice Equatorial Plane 0.11 AU 2", + Path = "/Solar System/Heliosphere" + } +} + +local ENLILSliceLat411AU1 = { + Identifier = "FL_ENLIL_slice_lat4_011AU_1", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.Lat4011AU1, + InputFileType = "Osfls", + + Color = { 0.4, 0.15, 0.4, 0.6 }, + ColorMethod = "By Quantity", -- Color by Quantity + ColorQuantity = 1, -- Velocity + ColorTablePaths = { + enlilDensityColorTable, + enlilVelocityColorTable, + }, + ColorTableRanges = colorRanges, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines ENLIL Slice Latitude 4 0.11 AU 1", + Path = "/Solar System/Heliosphere" + } +} + +local ENLILSliceLat411AU2 = { + Identifier = "FL_ENLIL_slice_lat4_011AU_2", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.Lat4011AU2, + InputFileType = "Osfls", + + Color = { 0.4, 0.15, 0.4, 0.6 }, + ColorMethod = "By Quantity", -- Color by Quantity + ColorQuantity = 1, -- Velocity + ColorTablePaths = { + enlilDensityColorTable, + enlilVelocityColorTable, + }, + ColorTableRanges = colorRanges, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines ENLIL Slice Latitude 4 0.11 AU 2", + Path = "/Solar System/Heliosphere" + } +} + +local ENLILEarth = { + Identifier = "FL_ENLIL_earth", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.Earth, + InputFileType = "Osfls", + Color = { 1.0, 1.0, 1.0, 0.6 }, + ColorTablePaths = { + enlilDensityColorTable, + enlilVelocityColorTable, + }, + ColorTableRanges = colorRanges, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines ENLIL Earth", + Path = "/Solar System/Heliosphere" + } +} + +local ENLILStereoA = { + Identifier = "FL_ENLIL_stereoa", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = unzippedDataDestination.StereoA, + InputFileType = "Osfls", + Color = { 1.0, 1.0, 1.0, 0.6 }, + ColorTablePaths = { + enlilDensityColorTable, + enlilVelocityColorTable, + }, + ColorTableRanges = colorRanges, + FlowEnabled = true, + ReversedFlow = true, + ParticleSize = 5, + ParticleSpacing = 25, + FlowSpeed = 25, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines ENLIL STEREO A", + Path = "/Solar System/Heliosphere" + } +} + +asset.onInitialize(function () + if not openspace.directoryExists(unzippedDataDestination.EqPlane011AU1) then + openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event") + openspace.unzipFile(fieldlineData .. "011AU_eq_plane_1.zip", unzippedDataDestination.EqPlane011AU1, true) + end + if not openspace.directoryExists(unzippedDataDestination.EqPlane011AU2) then + openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event") + openspace.unzipFile(fieldlineData .. "011AU_eq_plane_2.zip", unzippedDataDestination.EqPlane011AU2, true) + end + if not openspace.directoryExists(unzippedDataDestination.Lat4011AU1) then + openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event") + openspace.unzipFile(fieldlineData .. "011AU_lat4_1.zip", unzippedDataDestination.Lat4011AU1, true) + end + if not openspace.directoryExists(unzippedDataDestination.Lat4011AU2) then + openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event") + openspace.unzipFile(fieldlineData .. "011AU_lat4_2.zip", unzippedDataDestination.Lat4011AU2, true) + end + if not openspace.directoryExists(unzippedDataDestination.Earth) then + openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event") + openspace.unzipFile(fieldlineData .. "earth.zip", unzippedDataDestination.Earth, true) + end + if not openspace.directoryExists(unzippedDataDestination.StereoA) then + openspace.printInfo("Extracting " .. "Fieldlines from ENLIL model of 2012 event") + openspace.unzipFile(fieldlineData .. "stereoa.zip", unzippedDataDestination.StereoA, true) + end + + openspace.addSceneGraphNode(ENLILSliceEqPlane11AU1) + openspace.addSceneGraphNode(ENLILSliceEqPlane11AU2) + openspace.addSceneGraphNode(ENLILSliceLat411AU1) + openspace.addSceneGraphNode(ENLILSliceLat411AU2) + openspace.addSceneGraphNode(ENLILEarth) + openspace.addSceneGraphNode(ENLILStereoA) + +end) + +asset.onDeinitialize(function () + openspace.removeSceneGraphNode(ENLILStereoA) + openspace.removeSceneGraphNode(ENLILEarth) + openspace.removeSceneGraphNode(ENLILSliceLat411AU2) + openspace.removeSceneGraphNode(ENLILSliceLat411AU1) + openspace.removeSceneGraphNode(ENLILSliceEqPlane11AU2) + openspace.removeSceneGraphNode(ENLILSliceEqPlane11AU1) +end) + +asset.meta = { + Name = "Fieldlines from ENLIL model of 2012 event", + Version = "1.0", + Description = "Magnetic fieldlines from ENLIL model for a 2012 CME event", + Author = "CCMC", + URL = "", + License = "CC-BY" +} diff --git a/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_pfss.asset b/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_pfss.asset new file mode 100644 index 0000000000..3dc47005db --- /dev/null +++ b/data/assets/scene/solarsystem/heliosphere/2012/sun_earth_2012_fieldlines_pfss.asset @@ -0,0 +1,81 @@ +local transforms = asset.require('scene/solarsystem/sun/transforms_heliosphere.asset') + +local transferFunctions = asset.syncedResource({ + Name = "Fieldlines Transfer Functions", + Type = "HttpSynchronization", + Identifier = "sun_earth_event_july_2012-fieldlines_transferfunctions", + Version = 1 +}) + +local fieldlineData = asset.syncedResource({ + Name = "Fieldlines Data", + Type = "HttpSynchronization", + Identifier = "sun_earth_event_july_2012-pfss", + Version = 1 +}) + +local pfssTransitionColorTable = transferFunctions .. "pfss_transition.txt" +local pfssTopologyColorTable = transferFunctions .. "pfss_topology.txt" +local pfssBsignColorTable = transferFunctions .. "pfss_bsign.txt" + +local PFSSPaths = { + SolarSoft = fieldlineData .. "leilas_solar_soft/" +} + +local PFSS = { + Identifier = "FL_PFSS", + Parent = transforms.HEEQ180ReferenceFrame.Identifier, + Renderable = { + Type = "RenderableFieldlinesSequence", + SourceFolder = PFSSPaths.SolarSoft, + InputFileType = "Osfls", + Color = {0.35, 0.51, 0.875, 0.22}, + FlowEnabled = true, + ReversedFlow = true, + FlowColor = { 1, 0.9, 1, 0.74 }, + ParticleSize = 5, + ParticleSpacing = 250, + FlowSpeed = 75, + ColorTablePaths = { + pfssTopologyColorTable, + pfssBsignColorTable, + }, + ColorTableRanges = { + { 0, 2 }, + { -1, 1 }, + }, + LoadAtRuntime = true + }, + GUI = { + Name = "Fieldlines PFSS", + Path = "/Solar System/Heliosphere" + } +} + +asset.onInitialize(function () + if not openspace.directoryExists(PFSSPaths.SolarSoft) then + openspace.printInfo("Extracting " .. "Fieldlines from PFSS model of 2012 event") + openspace.unzipFile(fieldlineData .. "leilas_solar_soft.zip", PFSSPaths.SolarSoft, true) + end + + openspace.addSceneGraphNode(PFSS) + + -- openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.FlowEnabled", true) + -- openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.Flow.Reversed", true) + --openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.Flow.particleSize", 5) + --openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.Flow.particleSpacing", 250) + --openspace.setPropertyValueSingle("Scene.FL_PFSS.Renderable.Flow.speed", 75.0) +end) + +asset.onDeinitialize(function () + openspace.removeSceneGraphNode(PFSS) +end) + +asset.meta = { + Name = "Fieldlines from PFSS model of 2012 event", + Version = "1.0", + Description = "Magnetic fieldlines from PFSS model for a 2012 CME event", + Author = "CCMC", + URL = "", + License = "CC-BY" +} diff --git a/data/assets/scene/solarsystem/heliosphere/bastille_day/fieldlines.asset b/data/assets/scene/solarsystem/heliosphere/bastille_day/fieldlines.asset index 59a6cd4f4a..231cbc4bb0 100644 --- a/data/assets/scene/solarsystem/heliosphere/bastille_day/fieldlines.asset +++ b/data/assets/scene/solarsystem/heliosphere/bastille_day/fieldlines.asset @@ -34,14 +34,11 @@ local fieldlines = { asset.localResource("transferfunctions/density-fieldlines.txt"), asset.localResource("transferfunctions/velocity-fieldlines.txt") }, - ColorTableMinMax = { + ColorTableRanges = { { 0, 1000000 }, { 100, 2000 } }, SimulationModel = "mas", - Color = { - Uniform = { 0.0, 0.725, 0.75, 1.0 } - } }, GUI = { Path = "/Solar System/Heliosphere/Bastille Day 2000", @@ -71,7 +68,6 @@ end) asset.export(fieldlines) - asset.meta = { Name = "Predictive Science Inc. Fieldlines Bastille Day", Version = "1.0", diff --git a/data/assets/scene/solarsystem/planets/earth/magnetosphere/magnetosphere.asset b/data/assets/scene/solarsystem/planets/earth/magnetosphere/magnetosphere.asset index ffbf81d8ad..7699d7fecc 100644 --- a/data/assets/scene/solarsystem/planets/earth/magnetosphere/magnetosphere.asset +++ b/data/assets/scene/solarsystem/planets/earth/magnetosphere/magnetosphere.asset @@ -1,6 +1,5 @@ local transforms = asset.require("./transforms_magnetosphere") local transferFunction = asset.localResource("./CMR-illuminance2.txt") -local earthAsset = asset.require("scene/solarsystem/planets/earth/earth") local fieldlinesDirectory = asset.syncedResource({ Name = "Magnetosphere 2012 event", @@ -12,8 +11,6 @@ local fieldlinesDirectory = asset.syncedResource({ local earthMagnetosphere = { Identifier = "EarthMagnetosphere", Parent = transforms.GSMReferenceFrame.Identifier, - -- Grabs a value from earths ellipsoid. 1.05 just to make it somewhat bigger than earth - InteractionSphere = earthAsset.Earth.Renderable.Radii[1] * 1.05, Renderable = { Type = "RenderableFieldlinesSequence", SourceFolder = fieldlinesDirectory, @@ -22,16 +19,14 @@ local earthMagnetosphere = { InputFileType = "Osfls", -- OpenSpace Field lines sequence MaskingEnabled = true, MaskingQuantity = 5, -- corresponds to "topology" - MaskingRanges = {{-0, 0}}, + MaskingRanges = {{-0, 0}}, --closed only ColorMethod = "By Quantity", - ColorQuantity = 4, + ColorQuantity = 4, -- speed ColorTableRanges = {{50, 300}}, ColorTablePaths = {transferFunction}, LoadAtRuntime = true, ScaleToMeters = 1.0, - Color = { - Uniform = { 1.0, 0.725, 0.75, 1.0 } - } + Color = { 1.0, 0.725, 0.75, 0.8 } }, GUI = { Path = "/Solar System/Planets/Earth", @@ -49,7 +44,6 @@ end) asset.export(earthMagnetosphere) - asset.meta = { Name = "Static generic magnetosphere of fieldlines", Version = "1.1", diff --git a/data/assets/scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset b/data/assets/scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset index 99491ba857..4490a98423 100644 --- a/data/assets/scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset +++ b/data/assets/scene/solarsystem/planets/earth/magnetosphere/transforms_magnetosphere.asset @@ -24,11 +24,11 @@ local GSMReferenceFrame = { asset.onInitialize(function() openspace.addSceneGraphNode(GSMReferenceFrame) end) - + asset.onDeinitialize(function() openspace.removeSceneGraphNode(GSMReferenceFrame) end) - + asset.export(GSMReferenceFrame) diff --git a/data/assets/scene/solarsystem/sun/transforms_heliosphere.asset b/data/assets/scene/solarsystem/sun/transforms_heliosphere.asset index 5245786469..b092020a81 100644 --- a/data/assets/scene/solarsystem/sun/transforms_heliosphere.asset +++ b/data/assets/scene/solarsystem/sun/transforms_heliosphere.asset @@ -28,11 +28,11 @@ local HEEQ180ReferenceFrame = { asset.onInitialize(function() openspace.addSceneGraphNode(HEEQ180ReferenceFrame) end) - + asset.onDeinitialize(function() openspace.removeSceneGraphNode(HEEQ180ReferenceFrame) end) - + asset.export(HEEQ180ReferenceFrame) diff --git a/data/assets/util/webgui.asset b/data/assets/util/webgui.asset index a0d19c93bd..9d33e74156 100644 --- a/data/assets/util/webgui.asset +++ b/data/assets/util/webgui.asset @@ -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 = "ab0b74ceca72789b31fd2ccf9cc8a1f1cddbea26" +local frontendHash = "cf0c64cfac2642fb05e7d2a076550161f2a112aa" local dataProvider = "data.openspaceproject.com/files/webgui" local frontend = asset.syncedResource({ diff --git a/include/openspace/engine/globals.h b/include/openspace/engine/globals.h index 9dfb8dca64..918a0fba83 100644 --- a/include/openspace/engine/globals.h +++ b/include/openspace/engine/globals.h @@ -99,6 +99,7 @@ inline interaction::SessionRecording* sessionRecording; inline interaction::ShortcutManager* shortcutManager; inline properties::PropertyOwner* rootPropertyOwner; inline properties::PropertyOwner* screenSpaceRootPropertyOwner; +inline properties::PropertyOwner* userPropertyOwner; inline scripting::ScriptEngine* scriptEngine; inline scripting::ScriptScheduler* scriptScheduler; inline Profile* profile; diff --git a/modules/base/rendering/renderabletrailorbit.cpp b/modules/base/rendering/renderabletrailorbit.cpp index 129a14041a..e2359e4105 100644 --- a/modules/base/rendering/renderabletrailorbit.cpp +++ b/modules/base/rendering/renderabletrailorbit.cpp @@ -144,7 +144,7 @@ documentation::Documentation RenderableTrailOrbit::Documentation() { RenderableTrailOrbit::RenderableTrailOrbit(const ghoul::Dictionary& dictionary) : RenderableTrail(dictionary) - , _period(PeriodInfo, 0.0, 0.0, 1e9) + , _period(PeriodInfo, 0.0, 0.0, 250.0 * 365.25) // 250 years should be enough I guess , _resolution(ResolutionInfo, 10000, 1, 1000000) { const Parameters p = codegen::bake(dictionary); @@ -152,10 +152,9 @@ RenderableTrailOrbit::RenderableTrailOrbit(const ghoul::Dictionary& dictionary) _translation->onParameterChange([this]() { _needsFullSweep = true; }); // Period is in days - using namespace std::chrono; - _period = p.period * duration_cast(hours(24)).count(); + _period = p.period; _period.onChange([&] { _needsFullSweep = true; _indexBufferDirty = true; }); - _period.setExponent(5.f); + _period.setExponent(3.f); addProperty(_period); _resolution = p.resolution; @@ -368,7 +367,9 @@ RenderableTrailOrbit::UpdateReport RenderableTrailOrbit::updateTrails( return { false, false, 0 }; } - const double secondsPerPoint = _period / (_resolution - 1); + using namespace std::chrono; + double periodSeconds = _period * duration_cast(hours(24)).count(); + const double secondsPerPoint = periodSeconds / (_resolution - 1); // How much time has passed since the last permanent point const double delta = data.time.j2000Seconds() - _lastPointTime; @@ -486,7 +487,9 @@ void RenderableTrailOrbit::fullSweep(double time) { _lastPointTime = time; - const double secondsPerPoint = _period / (_resolution - 1); + using namespace std::chrono; + const double periodSeconds = _period * duration_cast(hours(24)).count(); + const double secondsPerPoint = periodSeconds / (_resolution - 1); // starting at 1 because the first position is a floating current one for (int i = 1; i < _resolution; ++i) { const glm::vec3 p = _translation->position({ {}, Time(time), Time(0.0) }); diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp index 1e04c66efd..4b300a6412 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.cpp @@ -70,7 +70,7 @@ namespace { "Color Table/Transfer Function to use for 'By Quantity' coloring." }; constexpr openspace::properties::Property::PropertyInfo ColorUniformInfo = { - "Uniform", + "Color", "Uniform Line Color", "The uniform color of lines shown when 'Color Method' is set to 'Uniform'." }; @@ -105,9 +105,9 @@ namespace { "Valid radial range. [Min, Max]" }; constexpr openspace::properties::Property::PropertyInfo FlowColorInfo = { - "Color", - "Color", - "Color of particles." + "FlowColor", + "Flow Color", + "Color of particles flow direction indication." }; constexpr openspace::properties::Property::PropertyInfo FlowEnabledInfo = { "FlowEnabled", @@ -197,6 +197,9 @@ namespace { // Set to true if you are streaming data during runtime std::optional loadAtRuntime; + // [[codegen::verbatim(ColorUniformInfo.description)]] + std::optional color [[codegen::color()]]; + // A list of paths to transferfunction .txt files containing color tables // used for colorizing the fieldlines according to different parameters std::optional> colorTablePaths; @@ -215,6 +218,21 @@ namespace { // would be traveling std::optional flowEnabled; + // [[codegen::verbatim(FlowColorInfo.description)]] + std::optional flowColor; + + // [[codegen::verbatim(FlowReversedInfo.description)]] + std::optional reversedFlow; + + // [[codegen::verbatim(FlowParticleSizeInfo.description)]] + std::optional particleSize; + + // [[codegen::verbatim(FlowParticleSpacingInfo.description)]] + std::optional particleSpacing; + + // [[codegen::verbatim(FlowSpeedInfo.description)]] + std::optional flowSpeed; + // [[codegen::verbatim(MaskingEnabledInfo.description)]] std::optional maskingEnabled; @@ -380,16 +398,29 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence( "{} contains no {} files", sourcePath.string(), fileTypeString )); } - _extraVars = p.extraVariables.value_or(_extraVars); _flowEnabled = p.flowEnabled.value_or(_flowEnabled); + _flowColor = p.flowColor.value_or(_flowColor); + _flowReversed = p.reversedFlow.value_or(_flowReversed); + _flowParticleSize = p.particleSize.value_or(_flowParticleSize); + _flowParticleSpacing = p.particleSpacing.value_or(_flowParticleSpacing); + _flowSpeed = p.flowSpeed.value_or(_flowSpeed); _lineWidth = p.lineWidth.value_or(_lineWidth); _manualTimeOffset = p.manualTimeOffset.value_or(_manualTimeOffset); _modelStr = p.simulationModel.value_or(_modelStr); _seedPointDirectory = p.seedPointDirectory.value_or(_seedPointDirectory); _maskingEnabled = p.maskingEnabled.value_or(_maskingEnabled); _maskingQuantityTemp = p.maskingQuantity.value_or(_maskingQuantityTemp); - _colorTablePaths = p.colorTablePaths.value_or(_colorTablePaths); + if (p.colorTablePaths.has_value()) { + _colorTablePaths = p.colorTablePaths.value(); + } + else { + // Set a default color table, just in case the (optional) user defined paths are + // corrupt or not provided + _colorTablePaths.push_back(FieldlinesSequenceModule::DefaultTransferFunctionFile); + } + + _colorUniform = p.color.value_or(_colorUniform); _colorMethod.addOption(static_cast(ColorMethod::Uniform), "Uniform"); _colorMethod.addOption(static_cast(ColorMethod::ByQuantity), "By Quantity"); @@ -442,12 +473,18 @@ RenderableFieldlinesSequence::RenderableFieldlinesSequence( } void RenderableFieldlinesSequence::initialize() { - // Set a default color table, just in case the (optional) user defined paths are - // corrupt or not provided - _colorTablePaths.push_back(FieldlinesSequenceModule::DefaultTransferFunctionFile); _transferFunction = std::make_unique( absPath(_colorTablePaths[0]).string() ); +} + +void RenderableFieldlinesSequence::initializeGL() { + // Setup shader program + _shaderProgram = global::renderEngine->buildRenderProgram( + "FieldlinesSequence", + absPath("${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_vs.glsl"), + absPath("${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_fs.glsl") + ); // Extract source file type specific information from dictionary // & get states from source @@ -489,17 +526,7 @@ void RenderableFieldlinesSequence::initialize() { computeSequenceEndTime(); setModelDependentConstants(); - setupProperties(); -} - -void RenderableFieldlinesSequence::initializeGL() { - // Setup shader program - _shaderProgram = global::renderEngine->buildRenderProgram( - "FieldlinesSequence", - absPath("${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_vs.glsl"), - absPath("${MODULE_FIELDLINESSEQUENCE}/shaders/fieldlinessequence_fs.glsl") - ); glGenVertexArrays(1, &_vertexArrayObject); glGenBuffers(1, &_vertexPositionBuffer); @@ -631,6 +658,7 @@ void RenderableFieldlinesSequence::setupProperties() { // Each quantity should have its own color table and color table range // no more, no less _colorTablePaths.resize(nExtraQuantities, _colorTablePaths.back()); + _colorTablePath = _colorTablePaths[0]; _colorTableRanges.resize(nExtraQuantities, _colorTableRanges.back()); _maskingRanges.resize(nExtraQuantities, _maskingRanges.back()); } @@ -641,7 +669,6 @@ void RenderableFieldlinesSequence::setupProperties() { // Set defaults _colorQuantity = _colorQuantityTemp; _colorQuantityMinMax = _colorTableRanges[_colorQuantity]; - _colorTablePath = _colorTablePaths[0]; _maskingQuantity = _maskingQuantityTemp; _maskingMinMax = _maskingRanges[_colorQuantity]; @@ -660,7 +687,6 @@ void RenderableFieldlinesSequence::definePropertyCallbackFunctions() { _colorTablePath.onChange([this]() { _transferFunction->setPath(_colorTablePath); - _colorTablePaths[_colorQuantity] = _colorTablePath; }); _colorQuantityMinMax.onChange([this]() { @@ -819,7 +845,7 @@ std::unordered_map> continue; } - std::ifstream seedFile(spFile.path()); + std::ifstream seedFile(seedFilePath); if (!seedFile.good()) { LERROR(fmt::format("Could not open seed points file '{}'", seedFilePath)); outMap.clear(); @@ -848,7 +874,7 @@ std::unordered_map> std::string name = seedFilePath.substr(0, lastIndex); // remove file extention size_t dateAndTimeSeperator = name.find_last_of('_'); std::string time = name.substr(dateAndTimeSeperator + 1, name.length()); - std::string date = name.substr(dateAndTimeSeperator - 8, 8); //8 for yyyymmdd + std::string date = name.substr(dateAndTimeSeperator - 8, 8); // 8 for yyyymmdd std::string dateAndTime = date + time; // add outVec as value and time stamp as int as key @@ -953,10 +979,7 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& textureUnit.activate(); _transferFunction->bind(); // Calls update internally _shaderProgram->setUniform("colorTable", textureUnit); - _shaderProgram->setUniform( - "colorTableRange", - _colorTableRanges[_colorQuantity] - ); + _shaderProgram->setUniform("colorTableRange", _colorTableRanges[_colorQuantity]); } if (_maskingEnabled) { @@ -994,7 +1017,7 @@ void RenderableFieldlinesSequence::render(const RenderData& data, RendererTasks& #endif glMultiDrawArrays( - GL_LINE_STRIP, //_drawingOutputType, + GL_LINE_STRIP, _states[_activeStateIndex].lineStart().data(), _states[_activeStateIndex].lineCount().data(), static_cast(_states[_activeStateIndex].lineStart().size()) @@ -1048,7 +1071,7 @@ void RenderableFieldlinesSequence::update(const UpdateData& data) { } else { // Not in interval => set everything to false - _activeTriggerTimeIndex = -1; + _activeTriggerTimeIndex = -1; mustLoadNewStateFromDisk = false; needUpdate = false; } diff --git a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h index 26ec465c82..8e28af874e 100644 --- a/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h +++ b/modules/fieldlinessequence/rendering/renderablefieldlinessequence.h @@ -92,7 +92,6 @@ private: std::filesystem::path _seedPointDirectory; // optional except when using json input std::string _modelStr; - fls::Model thismodel; // Used for 'runtime-states'. True when loading a new state from disk on another // thread. diff --git a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl index d80132dbf5..9203b489fe 100644 --- a/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl +++ b/modules/fieldlinessequence/shaders/fieldlinessequence_vs.glsl @@ -54,8 +54,8 @@ uniform vec2 domainLimR; // Inputs layout(location = 0) in vec3 in_position; // Should be provided in meters -layout(location = 1) in float in_color_scalar; // The extra value used to color lines. Location must correspond to _VA_COLOR in renderablefieldlinessequence.h -layout(location = 2) in float in_masking_scalar; // The extra value used to mask out parts of lines. Location must correspond to _VA_MASKING in renderablefieldlinessequence.h +layout(location = 1) in float in_color_scalar; // The extra value used to color lines. +layout(location = 2) in float in_masking_scalar; // The extra value used to mask out parts of lines. // These should correspond to the enum 'ColorMethod' in renderablefieldlinesequence.cpp const int uniformColor = 0; diff --git a/modules/space/rendering/renderableorbitalkepler.cpp b/modules/space/rendering/renderableorbitalkepler.cpp index 1106fa92e6..71198a81f5 100644 --- a/modules/space/rendering/renderableorbitalkepler.cpp +++ b/modules/space/rendering/renderableorbitalkepler.cpp @@ -371,21 +371,24 @@ RenderableOrbitalKepler::RenderableOrbitalKepler(const ghoul::Dictionary& dict) const Parameters p = codegen::bake(dict); - _path = p.path; - _path.onChange(_reinitializeTrailBuffers); + addProperty(_opacity); _segmentQuality = static_cast(p.segmentQuality); _segmentQuality.onChange(_reinitializeTrailBuffers); + addProperty(_segmentQuality); _appearance.lineColor = p.color; _appearance.lineFade = p.trailFade.value_or(20.f); _appearance.lineWidth = p.lineWidth.value_or(2.f); addPropertySubOwner(_appearance); + _path = p.path; + _path.onChange(_reinitializeTrailBuffers); + addProperty(_path); + _startRenderIdx = p.startRenderIdx.value_or(0); _sizeRender = p.renderSize.value_or(0u); - } void RenderableOrbitalKepler::initializeGL() { diff --git a/modules/space/speckloader.cpp b/modules/space/speckloader.cpp index f86b959a0e..f7aec38899 100644 --- a/modules/space/speckloader.cpp +++ b/modules/space/speckloader.cpp @@ -145,10 +145,13 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) Dataset res; int nDataValues = 0; + int currentLineNumber = 0; std::string line; // First phase: Loading the header information while (std::getline(file, line)) { + currentLineNumber++; + // Ignore empty line or commented-out lines if (line.empty() || line[0] == '#') { continue; @@ -280,6 +283,7 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) // std::getline, we'd miss the first data value line bool isFirst = true; while (isFirst || std::getline(file, line)) { + currentLineNumber++; isFirst = false; // Ignore empty line or commented-out lines @@ -316,24 +320,39 @@ Dataset loadFile(std::filesystem::path path, SkipAllZeroLines skipAllZeroLines) allZero &= (entry.position == glm::vec3(0.0)); if (!str.good()) { + // Need to subtract one of the line number here as we increase the current + // line count in the beginning of the while loop we are currently in throw ghoul::RuntimeError(fmt::format( "Error loading position information out of data line {} in file {}. " "Value was not a number", - res.entries.size(), path + currentLineNumber - 1, path )); } entry.data.resize(nDataValues); + std::stringstream valueStream; for (int i = 0; i < nDataValues; i += 1) { - str >> entry.data[i]; - allZero &= (entry.data[i] == 0.0); + std::string value; + str >> value; + if (value == "nan" || value == "NaN") { + entry.data[i] = std::numeric_limits::quiet_NaN(); + } + else { + valueStream.clear(); + valueStream.str(value); + valueStream >> entry.data[i]; - 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 - )); + allZero &= (entry.data[i] == 0.0); + if (valueStream.fail()) { + // Need to subtract one of the line number here as we increase the + // current line count in the beginning of the while loop we are + // currently in + throw ghoul::RuntimeError(fmt::format( + "Error loading data value {} out of data line {} in file {}. " + "Value was not a number", + i, currentLineNumber - 1, path + )); + } } } diff --git a/src/engine/globals.cpp b/src/engine/globals.cpp index fec7e42b86..2589c92acf 100644 --- a/src/engine/globals.cpp +++ b/src/engine/globals.cpp @@ -98,6 +98,7 @@ namespace { sizeof(interaction::SessionRecording) + sizeof(properties::PropertyOwner) + sizeof(properties::PropertyOwner) + + sizeof(properties::PropertyOwner) + sizeof(scripting::ScriptEngine) + sizeof(scripting::ScriptScheduler) + sizeof(Profile); @@ -345,6 +346,14 @@ void create() { screenSpaceRootPropertyOwner = new properties::PropertyOwner({ "ScreenSpace" }); #endif // WIN32 +#ifdef WIN32 + userPropertyOwner = new (currentPos) properties::PropertyOwner({ "UserProperties" }); + ghoul_assert(userPropertyOwner, "No userPropertyOwner"); + currentPos += sizeof(properties::PropertyOwner); +#else // ^^^ WIN32 / !WIN32 vvv + userPropertyOwner = new properties::PropertyOwner({ "UserProperties" }); +#endif // WIN32 + #ifdef WIN32 scriptEngine = new (currentPos) scripting::ScriptEngine; ghoul_assert(scriptEngine, "No scriptEngine"); @@ -375,7 +384,6 @@ void initialize() { rootPropertyOwner->addPropertySubOwner(global::moduleEngine); - navigationHandler->setPropertyOwner(global::rootPropertyOwner); // New property subowners also have to be added to the ImGuiModule callback! rootPropertyOwner->addPropertySubOwner(global::navigationHandler); rootPropertyOwner->addPropertySubOwner(global::interactionMonitor); @@ -390,6 +398,8 @@ void initialize() { rootPropertyOwner->addPropertySubOwner(global::luaConsole); rootPropertyOwner->addPropertySubOwner(global::dashboard); + rootPropertyOwner->addPropertySubOwner(global::userPropertyOwner); + syncEngine->addSyncable(global::scriptEngine); } diff --git a/src/navigation/pathnavigator_lua.inl b/src/navigation/pathnavigator_lua.inl index ca1a44da8b..0a60a57bbb 100644 --- a/src/navigation/pathnavigator_lua.inl +++ b/src/navigation/pathnavigator_lua.inl @@ -28,7 +28,7 @@ namespace { [[codegen::luawrap]] bool isFlying() { using namespace openspace; bool hasFinished = global::navigationHandler->pathNavigator().hasFinished(); - return hasFinished; + return !hasFinished; } // Continue playing a paused camera path. diff --git a/src/scene/scene.cpp b/src/scene/scene.cpp index 430dfc2e6f..de13c63935 100644 --- a/src/scene/scene.cpp +++ b/src/scene/scene.cpp @@ -879,6 +879,8 @@ scripting::LuaLibrary Scene::luaLibrary() { "Returns a list of property identifiers that match the passed regular " "expression" }, + codegen::lua::AddCustomProperty, + codegen::lua::RemoveCustomProperty, codegen::lua::AddSceneGraphNode, codegen::lua::RemoveSceneGraphNode, codegen::lua::RemoveSceneGraphNodesFromRegex, diff --git a/src/scene/scene_lua.inl b/src/scene/scene_lua.inl index fc4968091d..375bb74b3b 100644 --- a/src/scene/scene_lua.inl +++ b/src/scene/scene_lua.inl @@ -22,6 +22,36 @@ * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ****************************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + namespace { template @@ -917,6 +947,157 @@ namespace { return is; } +template +void createCustomProperty(openspace::properties::Property::PropertyInfo info, + std::optional onChange) +{ + T* p = new T(info); + if (onChange.has_value()) { + p->onChange( + [p, script = *onChange]() { + using namespace ghoul::lua; + LuaState s; + openspace::global::scriptEngine->initializeLuaState(s); + ghoul::lua::push(s, p->value()); + lua_setglobal(s, "value"); + ghoul::lua::runScript(s, script); + } + ); + } + openspace::global::userPropertyOwner->addProperty(p); +} + +[[codegen::luawrap]] void addCustomProperty(std::string identifier, std::string type, + std::optional guiName, + std::optional description, + std::optional onChange) +{ + using namespace openspace; + + if (identifier.empty()) { + throw ghoul::lua::LuaError("Identifier must not empty"); + } + + if (global::userPropertyOwner->hasProperty(identifier)) { + throw ghoul::lua::LuaError(fmt::format( + "Failed to register property '{}' since a user-defined property with that " + "name already exists", + identifier + )); + } + + // @TODO (abock, 2022-05-01) These if statements here are a bit gnarly since it + // requires us to update them as soon as we add a new property type. It would be nicer + // to have a factory function for this but right now this is the only place where that + // factory would be used. + + const char* gui = + guiName.has_value() && !guiName->empty() ? + guiName->c_str() : + identifier.c_str(); + + properties::Property::PropertyInfo info = { + identifier.c_str(), + gui, + description.has_value() ? description->c_str() : "" + }; + if (type == "DMat2Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "DMat3Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "DMat4Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "Mat2Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "Mat3Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "Mat4Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "BoolProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "DoubleProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "FloatProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "IntProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "LongProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "ShortProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "UIntProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "ULongProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "UShortProperty") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "DVec2Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "DVec3Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "DVec4Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "IVec2Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "IVec3Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "IVec4Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "UVec2Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "UVec3Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "UVec4Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "Vec2Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "Vec3Property") { + createCustomProperty(info, std::move(onChange)); + } + else if (type == "Vec4Property") { + createCustomProperty(info, std::move(onChange)); + } +} + +[[codegen::luawrap]] void removeCustomProperty(std::string identifier) { + using namespace openspace; + properties::Property* p = global::userPropertyOwner->property(identifier); + if (p) { + global::userPropertyOwner->removeProperty(p); + delete p; + } + else { + throw ghoul::lua::LuaError(fmt::format( + "Could not find user-defined property '{}'", identifier + )); + } +} + } // namespace #include "scene_lua_codegen.cpp"