From 167222c8144d14ce79658c0018ee38211040baa6 Mon Sep 17 00:00:00 2001 From: Alexander Bock Date: Wed, 13 Dec 2017 17:11:54 -0500 Subject: [PATCH] Feature/dashboard (#431) Merging Dashboard branch that introduces the Dashboard, DashboardItem and moves most of the screen rendering code into a component-based layout that can also be displayed as a screenspace renderable * Add Onscreen Dashboard * Add Dashboard class * Add DashboardItem classes and subclasses * Added font and fontsize customization to dashboarditems * Add default dashboard specifications to all scenes * Add tests.scene to test dashboard items * Add configuration options to DashboardItemDistance * Fix distance conversion to correctly use singular or plural values * Make DashboardItems unique when adding them to a dashboard * Correctly position test with different font sizes * Add Dashboard Item that enables spacing between other items * Add performance measurement to dashboard rendering * Add method to DashboardItemDistance that computes distance to surface * Add DashboardItemAngle that computes and prints the angle between three objects * Add DashboardItemInstruments that shows the instruments on New Horizons * Add ability to OpenSpaceModules to return a list of Luascripts defined by child objects * Make it possible for ScreenSpaceDashboard to work with its own dashboard or the main one --- data/scene/atmosphereearth.scene | 1 + data/scene/dawn.scene | 1 + data/scene/default.scene | 1 + data/scene/fieldlines.scene | 1 + data/scene/juno.scene | 2 + data/scene/newhorizons.scene | 19 +- data/scene/osirisrex.scene | 1 + data/scene/rosetta.scene | 1 + data/scene/tests.scene | 237 +++++++++ data/scene/volumetricmilkyway.scene | 1 + data/scene/voyager.scene | 1 + ext/ghoul | 2 +- include/openspace/engine/openspaceengine.h | 3 + include/openspace/rendering/dashboard.h | 67 +++ include/openspace/rendering/dashboarditem.h | 58 ++ include/openspace/rendering/renderengine.h | 17 - include/openspace/util/openspacemodule.h | 9 + modules/base/CMakeLists.txt | 16 + modules/base/basemodule.cpp | 44 ++ modules/base/basemodule.h | 2 + modules/base/dashboard/dashboarditemangle.cpp | 443 ++++++++++++++++ modules/base/dashboard/dashboarditemangle.h | 82 +++ modules/base/dashboard/dashboarditemdate.cpp | 132 +++++ modules/base/dashboard/dashboarditemdate.h | 61 +++ .../base/dashboard/dashboarditemdistance.cpp | 383 ++++++++++++++ .../base/dashboard/dashboarditemdistance.h | 85 +++ .../base/dashboard/dashboarditemframerate.cpp | 220 ++++++++ .../base/dashboard/dashboarditemframerate.h | 69 +++ .../base/dashboard/dashboarditemmission.cpp | 247 +++++++++ modules/base/dashboard/dashboarditemmission.h | 61 +++ .../dashboarditemparallelconnection.cpp | 221 ++++++++ .../dashboarditemparallelconnection.h | 61 +++ .../dashboarditemsimulationincrement.cpp | 141 +++++ .../dashboarditemsimulationincrement.h | 60 +++ .../base/dashboard/dashboarditemspacing.cpp | 86 +++ modules/base/dashboard/dashboarditemspacing.h | 53 ++ .../base/rendering/screenspacedashboard.cpp | 186 +++++-- modules/base/rendering/screenspacedashboard.h | 17 +- modules/imgui/imguimodule.cpp | 4 +- modules/imgui/src/gui.cpp | 12 +- modules/spacecraftinstruments/CMakeLists.txt | 2 + .../dashboard/dashboarditeminstruments.cpp | 498 ++++++++++++++++++ .../dashboard/dashboarditeminstruments.h | 64 +++ .../spacecraftinstrumentsmodule.cpp | 7 + scripts/scene_helper.lua | 32 +- src/CMakeLists.txt | 5 + src/documentation/core_registration.cpp | 15 +- src/engine/openspaceengine.cpp | 19 +- src/rendering/dashboard.cpp | 114 ++++ src/rendering/dashboard_lua.inl | 74 +++ src/rendering/dashboarditem.cpp | 65 +++ src/rendering/renderengine.cpp | 459 +--------------- src/rendering/renderengine_lua.inl | 4 +- src/rendering/screenspacerenderable.cpp | 5 +- src/util/distanceconversion.cpp | 65 ++- src/util/openspacemodule.cpp | 4 + 56 files changed, 3981 insertions(+), 559 deletions(-) create mode 100644 data/scene/tests.scene create mode 100644 include/openspace/rendering/dashboard.h create mode 100644 include/openspace/rendering/dashboarditem.h create mode 100644 modules/base/dashboard/dashboarditemangle.cpp create mode 100644 modules/base/dashboard/dashboarditemangle.h create mode 100644 modules/base/dashboard/dashboarditemdate.cpp create mode 100644 modules/base/dashboard/dashboarditemdate.h create mode 100644 modules/base/dashboard/dashboarditemdistance.cpp create mode 100644 modules/base/dashboard/dashboarditemdistance.h create mode 100644 modules/base/dashboard/dashboarditemframerate.cpp create mode 100644 modules/base/dashboard/dashboarditemframerate.h create mode 100644 modules/base/dashboard/dashboarditemmission.cpp create mode 100644 modules/base/dashboard/dashboarditemmission.h create mode 100644 modules/base/dashboard/dashboarditemparallelconnection.cpp create mode 100644 modules/base/dashboard/dashboarditemparallelconnection.h create mode 100644 modules/base/dashboard/dashboarditemsimulationincrement.cpp create mode 100644 modules/base/dashboard/dashboarditemsimulationincrement.h create mode 100644 modules/base/dashboard/dashboarditemspacing.cpp create mode 100644 modules/base/dashboard/dashboarditemspacing.h create mode 100644 modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp create mode 100644 modules/spacecraftinstruments/dashboard/dashboarditeminstruments.h create mode 100644 src/rendering/dashboard.cpp create mode 100644 src/rendering/dashboard_lua.inl create mode 100644 src/rendering/dashboarditem.cpp diff --git a/data/scene/atmosphereearth.scene b/data/scene/atmosphereearth.scene index 7688996950..80c6ae04b5 100644 --- a/data/scene/atmosphereearth.scene +++ b/data/scene/atmosphereearth.scene @@ -5,6 +5,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/dawn.scene b/data/scene/dawn.scene index 68c09bd636..42f6c756ed 100644 --- a/data/scene/dawn.scene +++ b/data/scene/dawn.scene @@ -5,6 +5,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/default.scene b/data/scene/default.scene index 7fe255644f..150a4d886d 100644 --- a/data/scene/default.scene +++ b/data/scene/default.scene @@ -25,6 +25,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/fieldlines.scene b/data/scene/fieldlines.scene index eec14509f8..68105fd851 100644 --- a/data/scene/fieldlines.scene +++ b/data/scene/fieldlines.scene @@ -5,6 +5,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/juno.scene b/data/scene/juno.scene index 23fc7bcab7..1fb89600e7 100755 --- a/data/scene/juno.scene +++ b/data/scene/juno.scene @@ -5,6 +5,8 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() + openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/newhorizons.scene b/data/scene/newhorizons.scene index 34c5545542..dc4a0983c5 100644 --- a/data/scene/newhorizons.scene +++ b/data/scene/newhorizons.scene @@ -26,7 +26,24 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- - openspace.set_default_gui_sorting() + openspace.set_default_dashboard() + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSpacing", + Spacing = 50 + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDistance", + SourceType = "Node", + SourceNodeName = "NewHorizons", + DestinationType = "Node Surface", + DestinationNodeName = "Pluto" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemInstruments" + }) openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/osirisrex.scene b/data/scene/osirisrex.scene index ca77dc7cdf..449e9d12e4 100644 --- a/data/scene/osirisrex.scene +++ b/data/scene/osirisrex.scene @@ -7,6 +7,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/rosetta.scene b/data/scene/rosetta.scene index 8c6f0acd04..43935f9856 100644 --- a/data/scene/rosetta.scene +++ b/data/scene/rosetta.scene @@ -5,6 +5,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/tests.scene b/data/scene/tests.scene new file mode 100644 index 0000000000..1c57635e7f --- /dev/null +++ b/data/scene/tests.scene @@ -0,0 +1,237 @@ +function preInitialization() + --[[ + The scripts in this function are executed after the scene is loaded but before the + scene elements have been initialized, thus they should be used to set the time at + which the scene should start and other settings that might determine initialization + critical objects. + ]]-- + -- dofile(openspace.absPath('${SCRIPTS}/default_setup.lua')) + + local TestFontSize1 = 20 + local TestFontSize2 = 14 + + -- DashboardItemDate tests + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDate" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDate", + FontName = "Console" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDate", + FontName = "Light", + FontSize = TestFontSize1 + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDate", + FontSize = TestFontSize2 + }) + + -- DashboardItemDistance tests + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDistance" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDistance", + FontName = "Console", + SourceType = "Node", + SourceNodeName = "Moon" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDistance", + FontName = "Light", + FontSize = TestFontSize1, + SourceType = "Focus", + DestinationType = "Camera" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDistance", + FontSize = TestFontSize2, + SourceType = "Focus", + DestinationType = "Node", + DestinationNodeName = "Sun" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDistance", + SourceType = "Camera", + DestinationType = "Focus" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDistance", + SourceType = "Camera", + SourceType = "Node", + SourceNodeName = "Saturn", + DestinationType = "Node", + DestinationNodeName = "Sun" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSpacing", + Spacing = 100 + }) + + -- DashboardItemFramerate + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemFramerate" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemFramerate", + FontName = "Light", + FontSize = TestFontSize1, + FrametimeType = "Average Deltatime" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemFramerate", + FontName = "Console", + FrametimeType = "Frames per second" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemFramerate", + FontSize = TestFontSize2, + FrametimeType = "Average frames per second" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemFramerate", + FrametimeType = "None" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSpacing" + }) + + -- DashboardItemSimulationIncrement + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSimulationIncrement" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSimulationIncrement", + FontName = "Light", + FontSize = TestFontSize1, + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSimulationIncrement", + FontName = "Console" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSimulationIncrement", + FontSize = TestFontSize2 + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSpacing" + }) + + -- DashboardItemAngle + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemAngle", + ReferenceType = "Node", + ReferenceNodeName = "Moon", + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemAngle", + FontName = "Console", + SourceType = "Node", + SourceNodeName = "Moon", + ReferenceType = "Node", + ReferenceNodeName = "Moon", + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemAngle", + FontName = "Light", + FontSize = TestFontSize1, + SourceType = "Focus", + ReferenceType = "Node", + ReferenceNodeName = "Moon", + DestinationType = "Camera" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemAngle", + FontSize = TestFontSize2, + SourceType = "Focus", + ReferenceType = "Node", + ReferenceNodeName = "Moon", + DestinationType = "Node", + DestinationNodeName = "Sun" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemAngle", + SourceType = "Camera", + ReferenceType = "Node", + ReferenceNodeName = "Moon", + DestinationType = "Focus" + }) + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemAngle", + SourceType = "Camera", + SourceType = "Node", + SourceNodeName = "Saturn", + ReferenceType = "Node", + ReferenceNodeName = "Moon", + DestinationType = "Node", + DestinationNodeName = "Sun" + }) + + + openspace.spice.loadKernel("${SPICE}/naif0012.tls") + openspace.spice.loadKernel("${SPICE}/pck00010.tpc") + + openspace.time.setTime("2000 JAN 01") + dofile(openspace.absPath('${SCRIPTS}/bind_common_keys.lua')) +end + +function postInitialization() + openspace.printInfo("Setting default values") + + openspace.setPropertyValueSingle("Global Properties.GlobeBrowsing.GdalWrapper.LogGdalErrors", false) + openspace.setPropertyValueSingle("Earth.RenderableGlobe.Debug.LevelByProjectedAreaElseDistance", false) + + openspace.globebrowsing.goToGeo(58.5877, 16.1924, 20000000) + + openspace.printInfo("Done setting default values") + + -- Defined in scene_helper.lua + -- Used to create focus buttons for a subset of scenegraph nodes + mark_interesting_nodes({ + "Earth" + }) +end + + +return { + ScenePath = ".", + CommonFolder = "common", + Camera = { + Focus = "Earth", + Position = {0, 0, 0}, + Rotation = {0.758797, 0.221490, -0.605693, -0.091135}, + }, + Modules = { + -- # Solar system objects + "sun", + "mercury", + "venus", + "earth", + "moon", + "mars", + "jupiter", + "saturn", + "uranus", + "neptune", + -- "satellites", + + -- "grids", + -- "digitaluniverse", + "stars/digitaluniverse", + "milkyway/digitaluniverse", + + -- "missions/voyager" + } +} + diff --git a/data/scene/volumetricmilkyway.scene b/data/scene/volumetricmilkyway.scene index 0a82b3b19a..fb723772dd 100644 --- a/data/scene/volumetricmilkyway.scene +++ b/data/scene/volumetricmilkyway.scene @@ -5,6 +5,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/data/scene/voyager.scene b/data/scene/voyager.scene index 7be5b4a3cf..c02ce885ba 100644 --- a/data/scene/voyager.scene +++ b/data/scene/voyager.scene @@ -5,6 +5,7 @@ function preInitialization() which the scene should start and other settings that might determine initialization critical objects. ]]-- + openspace.set_default_dashboard() openspace.spice.loadKernel("${SPICE}/naif0012.tls") openspace.spice.loadKernel("${SPICE}/pck00010.tpc") diff --git a/ext/ghoul b/ext/ghoul index e5ef9ee61e..bbf1018920 160000 --- a/ext/ghoul +++ b/ext/ghoul @@ -1 +1 @@ -Subproject commit e5ef9ee61e5523ccf08655e941400fedd48541f4 +Subproject commit bbf1018920fd1d774ff4851971543e18c08422f5 diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index 860c9f69bc..528218e52e 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -43,6 +43,7 @@ namespace ghoul::fontrendering { class FontManager; } namespace openspace { class ConfigurationManager; +class Dashboard; class DownloadManager; class GUI; class LoadingScreen; @@ -107,6 +108,7 @@ public: // Guaranteed to return a valid pointer ConfigurationManager& configurationManager(); LuaConsole& console(); + Dashboard& dashboard(); DownloadManager& downloadManager(); ModuleEngine& moduleEngine(); LoadingScreen& loadingScreen(); @@ -183,6 +185,7 @@ private: // Components std::unique_ptr _configurationManager; std::unique_ptr _sceneManager; + std::unique_ptr _dashboard; std::unique_ptr _downloadManager; std::unique_ptr _console; std::unique_ptr _moduleEngine; diff --git a/include/openspace/rendering/dashboard.h b/include/openspace/rendering/dashboard.h new file mode 100644 index 0000000000..8493f76698 --- /dev/null +++ b/include/openspace/rendering/dashboard.h @@ -0,0 +1,67 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___DASHBOARD___H__ +#define __OPENSPACE_CORE___DASHBOARD___H__ + +#include + +#include + +#include + +#include +#include + +namespace openspace { + +namespace scripting { struct LuaLibrary; } + +class DashboardItem; + +class Dashboard : public properties::PropertyOwner { +public: + Dashboard(); + + void render(glm::vec2& penPosition); + + void addDashboardItem(std::unique_ptr item); + bool hasItem(int index) const; + const DashboardItem& item(int index) const; + void removeDashboardItem(int index); + void removeDashboardItems(); + + /** + * Returns the Lua library that contains all Lua functions available to affect the + * rendering. + */ + static scripting::LuaLibrary luaLibrary(); + +private: + std::vector> _items; +}; + +} // openspace + +#endif // __OPENSPACE_CORE___DASHBOARD___H__ diff --git a/include/openspace/rendering/dashboarditem.h b/include/openspace/rendering/dashboarditem.h new file mode 100644 index 0000000000..b91ae71e17 --- /dev/null +++ b/include/openspace/rendering/dashboarditem.h @@ -0,0 +1,58 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___DASHBOARDITEM___H__ +#define __OPENSPACE_CORE___DASHBOARDITEM___H__ + +#include + +#include + +#include +#include + +#include + +namespace openspace { + +class DashboardItem : public properties::PropertyOwner { +public: + static std::unique_ptr createFromDictionary( + ghoul::Dictionary dictionary + ); + + DashboardItem(std::string name); + + bool isEnabled() const; + virtual void render(glm::vec2& penPosition) = 0; + + virtual glm::vec2 size() const = 0; + +protected: + properties::BoolProperty _isEnabled; +}; + +} // openspace + +#endif // __OPENSPACE_CORE___DASHBOARDITEM___H__ diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index a1410cecfd..283d8949e6 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -62,13 +62,6 @@ public: Invalid }; - enum class FrametimeType { - DtTimeAvg = 0, - FPS, - FPSAvg, - None - }; - RenderEngine(); ~RenderEngine(); @@ -126,8 +119,6 @@ public: std::string csPath, const ghoul::Dictionary& dictionary = ghoul::Dictionary()); - std::string progressToStr(int size, double t); - void removeRenderProgram( const std::unique_ptr& program); @@ -179,8 +170,6 @@ private: void setRenderer(std::unique_ptr renderer); RendererImplementation rendererFromString(const std::string& method) const; - void renderInformation(); - Camera* _camera; Scene* _scene; std::unique_ptr _raycasterManager; @@ -194,12 +183,6 @@ private: ghoul::Dictionary _resolveData; ScreenLog* _log; - properties::OptionProperty _frametimeType; - - //FrametimeType _frametimeType; - - properties::BoolProperty _showDate; - properties::BoolProperty _showInfo; properties::BoolProperty _showLog; properties::BoolProperty _showVersionInfo; properties::BoolProperty _showCameraInfo; diff --git a/include/openspace/util/openspacemodule.h b/include/openspace/util/openspacemodule.h index 97eaf3c9d0..8bc31baa04 100644 --- a/include/openspace/util/openspacemodule.h +++ b/include/openspace/util/openspacemodule.h @@ -82,6 +82,15 @@ public: */ virtual scripting::LuaLibrary luaLibrary() const; + /** + * Returns the Lua libraries that are defined by objects contained in this + * OpenSpaceModule. Note that the #luaLibrary library is *not* contained in this list + * as this is solely the list of libraries as defined by, for example Renderables, + * defined in the OpenSpaceModule. + * \return A list of libraries defined by items contained in this OpenSpaceModule + */ + virtual std::vector luaLibraries() const; + /** * Returns the minimum required OpenGL version of this OpenSpaceModule. Unless * overwritten, it returns an OpenGL version of 3.3. diff --git a/modules/base/CMakeLists.txt b/modules/base/CMakeLists.txt index dd6592ce96..6f35acd911 100644 --- a/modules/base/CMakeLists.txt +++ b/modules/base/CMakeLists.txt @@ -25,6 +25,14 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemangle.h + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemdate.h + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemdistance.h + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemframerate.h + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemmission.h + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemparallelconnection.h + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemsimulationincrement.h + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemspacing.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/modelgeometry.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.h @@ -49,6 +57,14 @@ set(HEADER_FILES source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemangle.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemdate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemdistance.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemframerate.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemmission.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemparallelconnection.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemsimulationincrement.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditemspacing.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/modelgeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/multimodelgeometry.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablemodel.cpp diff --git a/modules/base/basemodule.cpp b/modules/base/basemodule.cpp index 1b5b75c9f4..d4d434d7db 100644 --- a/modules/base/basemodule.cpp +++ b/modules/base/basemodule.cpp @@ -31,6 +31,15 @@ #include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -78,6 +87,22 @@ void BaseModule::internalInitialize() { fSsRenderable->registerClass("ScreenSpaceImageOnline"); fSsRenderable->registerClass("ScreenSpaceFramebuffer"); + auto fDashboard = FactoryManager::ref().factory(); + ghoul_assert(fDashboard, "Dashboard factory was not created"); + + fDashboard->registerClass("DashboardItemAngle"); + fDashboard->registerClass("DashboardItemDate"); + fDashboard->registerClass("DashboardItemDistance"); + fDashboard->registerClass("DashboardItemFramerate"); + fDashboard->registerClass("DashboardItemMission"); + fDashboard->registerClass( + "DashboardItemParallelConnection" + ); + fDashboard->registerClass( + "DashboardItemSimulationIncrement" + ); + fDashboard->registerClass("DashboardItemSpacing"); + auto fRenderable = FactoryManager::ref().factory(); ghoul_assert(fRenderable, "Renderable factory was not created"); @@ -114,24 +139,43 @@ void BaseModule::internalInitialize() { std::vector BaseModule::documentations() const { return { + DashboardItemDate::Documentation(), + DashboardItemDistance::Documentation(), + DashboardItemFramerate::Documentation(), + DashboardItemMission::Documentation(), + DashboardItemParallelConnection::Documentation(), + DashboardItemSimulationIncrement::Documentation(), + DashboardItemSpacing::Documentation(), + RenderableModel::Documentation(), RenderablePlane::Documentation(), RenderableSphere::Documentation(), RenderableTrailOrbit::Documentation(), RenderableTrailTrajectory::Documentation(), + ScreenSpaceDashboard::Documentation(), ScreenSpaceFramebuffer::Documentation(), ScreenSpaceImageLocal::Documentation(), ScreenSpaceImageOnline::Documentation(), + FixedRotation::Documentation(), LuaRotation::Documentation(), StaticRotation::Documentation(), + LuaScale::Documentation(), StaticScale::Documentation(), + LuaTranslation::Documentation(), StaticTranslation::Documentation(), + modelgeometry::ModelGeometry::Documentation(), }; } +std::vector BaseModule::luaLibraries() const { + return { + ScreenSpaceDashboard::luaLibrary() + }; +} + } // namespace openspace diff --git a/modules/base/basemodule.h b/modules/base/basemodule.h index 8cb316d515..d984e69bfa 100644 --- a/modules/base/basemodule.h +++ b/modules/base/basemodule.h @@ -35,7 +35,9 @@ public: BaseModule(); virtual ~BaseModule() = default; + std::vector documentations() const override; + std::vector luaLibraries() const override; protected: void internalInitialize() override; diff --git a/modules/base/dashboard/dashboarditemangle.cpp b/modules/base/dashboard/dashboarditemangle.cpp new file mode 100644 index 0000000000..5ac9dceb97 --- /dev/null +++ b/modules/base/dashboard/dashboarditemangle.cpp @@ -0,0 +1,443 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace { + const char* KeyFontMono = "Mono"; + + const float DefaultFontSize = 10.f; + + static const openspace::properties::Property::PropertyInfo FontNameInfo = { + "FontName", + "Font Name", + "This value is the name of the font that is used. It can either refer to an " + "internal name registered previously, or it can refer to a path that is used." + }; + + static const openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "This value determines the size of the font that is used to render the date." + }; + + static const openspace::properties::Property::PropertyInfo SourceTypeInfo = { + "SourceType", + "Source Type", + "The type of position that is used as the triangle apex used to calculate the " + "angle. The default value is 'Camera'." + }; + + static const openspace::properties::Property::PropertyInfo SourceNodeNameInfo = { + "SourceNodeName", + "Source Node Name", + "If a scene graph node is selected as type, this value specifies the name of the " + "node that is to be used as the apex of the triangle used to calculate the " + "angle. The computed angle is the incident angle to Source in the triangle (" + "Source, Reference, Destination)." + }; + + static const openspace::properties::Property::PropertyInfo ReferenceTypeInfo = { + "ReferenceType", + "Reference Type", + "The type of position that is used as the destination of the reference line used " + "to calculate the angle. The computed angle is the incident angle to Source in " + "the triangle (Source, Reference, Destination)." + }; + + static const openspace::properties::Property::PropertyInfo ReferenceNodeNameInfo = { + "ReferenceNodeName", + "Reference Node Name", + "If a scene graph node is selected as type, this value specifies the name of the " + "node that is to be used as the reference direction to compute the angle." + }; + + static const openspace::properties::Property::PropertyInfo DestinationTypeInfo = { + "DestinationType", + "Destination Type", + "The type of position that is used as the destination to calculate the angle. " + "The computed angle is the incident angle to Source in the triangle (" + "Source, Reference, Destination). The default value for this is 'Focus'." + }; + + static const openspace::properties::Property::PropertyInfo DestinationNodeNameInfo = { + "DestinationNodeName", + "Destination Node Name", + "If a scene graph node is selected as type, this value specifies the name of the " + "node that is to be used as the destination for computing the angle." + }; +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemAngle::Documentation() { + using namespace documentation; + return { + "DashboardItem Angle", + "base_dashboarditem_angle", + { + { + "Type", + new StringEqualVerifier("DashboardItemAngle"), + Optional::No + }, + { + FontNameInfo.identifier, + new StringVerifier, + Optional::Yes, + FontNameInfo.description + }, + { + FontSizeInfo.identifier, + new IntVerifier, + Optional::Yes, + FontSizeInfo.description + }, + { + SourceTypeInfo.identifier, + new StringInListVerifier({ + "Node", "Focus", "Camera" + }), + Optional::Yes, + SourceTypeInfo.description + }, + { + SourceNodeNameInfo.identifier, + new StringVerifier, + Optional::Yes, + SourceNodeNameInfo.description + }, + { + ReferenceTypeInfo.identifier, + new StringInListVerifier({ + "Node", "Focus", "Camera" + }), + Optional::No, + ReferenceTypeInfo.description + }, + { + ReferenceNodeNameInfo.identifier, + new StringVerifier, + Optional::Yes, + ReferenceNodeNameInfo.description + }, + { + DestinationTypeInfo.identifier, + new StringInListVerifier({ + "Node", "Focus", "Camera" + }), + Optional::Yes, + DestinationTypeInfo.description + }, + { + DestinationNodeNameInfo.identifier, + new StringVerifier, + Optional::Yes, + DestinationNodeNameInfo.description + } + } + }; +} + +DashboardItemAngle::DashboardItemAngle(ghoul::Dictionary dictionary) + : DashboardItem("Distance") + , _fontName(FontNameInfo, KeyFontMono) + , _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f) + , _source{ + properties::OptionProperty( + SourceTypeInfo, + properties::OptionProperty::DisplayType::Dropdown + ), + properties::StringProperty(SourceNodeNameInfo), + nullptr + } + , _reference{ + properties::OptionProperty( + ReferenceTypeInfo, + properties::OptionProperty::DisplayType::Dropdown + ), + properties::StringProperty(ReferenceNodeNameInfo), + nullptr + } + , _destination{ + properties::OptionProperty( + DestinationTypeInfo, + properties::OptionProperty::DisplayType::Dropdown + ), + properties::StringProperty(DestinationNodeNameInfo), + nullptr + } +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemAngle" + ); + + if (dictionary.hasKey(FontNameInfo.identifier)) { + _fontName = dictionary.value(FontNameInfo.identifier); + } + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = static_cast( + dictionary.value(FontSizeInfo.identifier) + ); + } + + _fontName.onChange([this]() { + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontName); + + _fontSize.onChange([this]() { + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontSize); + + _source.type.addOptions({ + { Type::Node, "Node" }, + { Type::Focus, "Focus" }, + { Type::Camera, "Camera" } + }); + _source.type.onChange([this]() { + _source.nodeName.setVisibility( + properties::Property::Visibility(_source.type == Type::Node) + ); + }); + if (dictionary.hasKey(SourceTypeInfo.identifier)) { + std::string value = dictionary.value(SourceTypeInfo.identifier); + if (value == "Node") { + _source.type = Type::Node; + } + else if (value == "Focus") { + _source.type = Type::Focus; + } + else { + _source.type = Type::Camera; + } + } + else { + _source.type = Type::Camera; + } + addProperty(_source.type); + + _source.nodeName.onChange([this]() { + _source.node = nullptr; + }); + if (_source.type == Type::Node) { + if (dictionary.hasKey(SourceNodeNameInfo.identifier)) { + _source.nodeName = dictionary.value( + SourceNodeNameInfo.identifier + ); + } + else { + LERRORC( + "DashboardItemAngle", + "Node type was selected for source but no node specified" + ); + } + } + addProperty(_source.nodeName); + + + _reference.type.addOptions({ + { Type::Node, "Node" }, + { Type::Focus, "Focus" }, + { Type::Camera, "Camera" } + }); + _reference.type.onChange([this]() { + _reference.nodeName.setVisibility( + properties::Property::Visibility(_reference.type == Type::Node) + ); + }); + std::string value = dictionary.value(ReferenceTypeInfo.identifier); + if (value == "Node") { + _reference.type = Type::Node; + } + else if (value == "Focus") { + _reference.type = Type::Focus; + } + else { + _reference.type = Type::Camera; + } + addProperty(_reference.type); + + _reference.nodeName.onChange([this]() { + _reference.node = nullptr; + }); + if (_reference.type == Type::Node) { + if (dictionary.hasKey(ReferenceNodeNameInfo.identifier)) { + _reference.nodeName = dictionary.value( + ReferenceNodeNameInfo.identifier + ); + } + else { + LERRORC( + "DashboardItemAngle", + "Node type was selected for reference but no node specified" + ); + } + } + addProperty(_source.nodeName); + + _destination.type.addOptions({ + { Type::Node, "Node" }, + { Type::Focus, "Focus" }, + { Type::Camera, "Camera" } + }); + _destination.type.onChange([this]() { + _destination.nodeName.setVisibility( + properties::Property::Visibility(_source.type == Type::Node) + ); + }); + if (dictionary.hasKey(DestinationTypeInfo.identifier)) { + std::string value = dictionary.value(DestinationTypeInfo.identifier); + if (value == "Node") { + _destination.type = Type::Node; + } + else if (value == "Focus") { + _destination.type = Type::Focus; + } + else { + _destination.type = Type::Camera; + } + } + else { + _destination.type = Type::Focus; + } + addProperty(_destination.type); + _destination.nodeName.onChange([this]() { + _destination.node = nullptr; + }); + if (_destination.type == Type::Node) { + if (dictionary.hasKey(DestinationNodeNameInfo.identifier)) { + _destination.nodeName = dictionary.value( + DestinationNodeNameInfo.identifier + ); + } + else { + LERRORC( + "DashboardItemAngle", + "Node type was selected for destination but no node specified" + ); + } + } + addProperty(_destination.nodeName); + + _font = OsEng.fontManager().font(_fontName, _fontSize); +} + +std::pair DashboardItemAngle::positionAndLabel( + Component& comp) const +{ + if (comp.type == Type::Node) { + if (!comp.node) { + comp.node = OsEng.renderEngine().scene()->sceneGraphNode( + comp.nodeName + ); + + if (!comp.node) { + LERRORC( + "DashboardItemAngle", + "Could not find node '" + comp.nodeName.value() + "'" + ); + return { glm::dvec3(0.0), "Node" }; + } + } + } + + switch (comp.type) { + case Type::Node: + return { comp.node->worldPosition(), comp.node->name() }; + case Type::Focus: + return { + OsEng.navigationHandler().focusNode()->worldPosition(), + "focus" + }; + case Type::Camera: + return { OsEng.renderEngine().camera()->positionVec3(), "camera" }; + default: + return { glm::dvec3(0.0), "Unknown" }; + } +}; + +void DashboardItemAngle::render(glm::vec2& penPosition) { + std::pair sourceInfo = positionAndLabel(_source); + std::pair referenceInfo = positionAndLabel(_reference); + std::pair destinationInfo = positionAndLabel(_destination); + + glm::dvec3 a = referenceInfo.first - sourceInfo.first; + glm::dvec3 b = destinationInfo.first - sourceInfo.first; + + if (glm::length(a) == 0.0 || glm::length(b) == 0) { + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + "Could not compute angle at %s between %s and %s", + sourceInfo.second.c_str(), + destinationInfo.second.c_str(), + referenceInfo.second.c_str() + ); + } + else { + double angle = glm::degrees( + glm::acos(glm::dot(a, b) / (glm::length(a) * glm::length(b))) + ); + + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + "Angle at %s between %s and %s: %f degrees", + sourceInfo.second.c_str(), + destinationInfo.second.c_str(), + referenceInfo.second.c_str(), + angle + ); + } +} + +glm::vec2 DashboardItemAngle::size() const { + double angle = 120; + + return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Angle: %f %s", + angle + ).boundingBox; +} + +} // namespace openspace diff --git a/modules/base/dashboard/dashboarditemangle.h b/modules/base/dashboard/dashboarditemangle.h new file mode 100644 index 0000000000..a272c6e6a4 --- /dev/null +++ b/modules/base/dashboard/dashboarditemangle.h @@ -0,0 +1,82 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMANGLE___H__ +#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMANGLE___H__ + +#include + +#include +#include +#include + +#include + +namespace ghoul::fontrendering { class Font; } + +namespace openspace { + +class SceneGraphNode; + +namespace documentation { struct Documentation; } + +class DashboardItemAngle : public DashboardItem { +public: + DashboardItemAngle(ghoul::Dictionary dictionary); + virtual ~DashboardItemAngle() = default; + + void render(glm::vec2& penPosition) override; + + glm::vec2 size() const override; + + static documentation::Documentation Documentation(); + +private: + enum Type { + Node = 0, + Focus, + Camera + }; + + struct Component { + properties::OptionProperty type; + properties::StringProperty nodeName; + SceneGraphNode* node; + }; + + std::pair positionAndLabel(Component& mainComp) const; + + properties::StringProperty _fontName; + properties::FloatProperty _fontSize; + + Component _source; + Component _reference; + Component _destination; + + std::shared_ptr _font; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___DASHBOARDITEMANGLE___H__ diff --git a/modules/base/dashboard/dashboarditemdate.cpp b/modules/base/dashboard/dashboarditemdate.cpp new file mode 100644 index 0000000000..79e0cc15e6 --- /dev/null +++ b/modules/base/dashboard/dashboarditemdate.cpp @@ -0,0 +1,132 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +namespace { + const char* KeyFontMono = "Mono"; + const float DefaultFontSize = 15.f; + + static const openspace::properties::Property::PropertyInfo FontNameInfo = { + "FontName", + "Font Name", + "This value is the name of the font that is used. It can either refer to an " + "internal name registered previously, or it can refer to a path that is used." + }; + + static const openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "This value determines the size of the font that is used to render the date." + }; +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemDate::Documentation() { + using namespace documentation; + return { + "DashboardItem Date", + "base_dashboarditem_date", + { + { + "Type", + new StringEqualVerifier("DashboardItemDate"), + Optional::No + }, + { + FontNameInfo.identifier, + new StringVerifier, + Optional::Yes, + FontNameInfo.description + }, + { + FontSizeInfo.identifier, + new IntVerifier, + Optional::Yes, + FontSizeInfo.description + } + } + }; +} + +DashboardItemDate::DashboardItemDate(ghoul::Dictionary dictionary) + : DashboardItem("Date") + , _fontName(FontNameInfo, KeyFontMono) + , _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemDate" + ); + + if (dictionary.hasKey(FontNameInfo.identifier)) { + _fontName = dictionary.value(FontNameInfo.identifier); + } + _fontName.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontName); + + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = static_cast( + dictionary.value(FontSizeInfo.identifier) + ); + } + _fontSize.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontSize); + + _font = OsEng.fontManager().font(_fontName, _fontSize); +} + +void DashboardItemDate::render(glm::vec2& penPosition) { + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + "Date: %s", + OsEng.timeManager().time().UTC().c_str() + ); +} + +glm::vec2 DashboardItemDate::size() const { + return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Date: %s", + OsEng.timeManager().time().UTC().c_str() + ).boundingBox; +} + +} // namespace openspace diff --git a/modules/base/dashboard/dashboarditemdate.h b/modules/base/dashboard/dashboarditemdate.h new file mode 100644 index 0000000000..6359b604a2 --- /dev/null +++ b/modules/base/dashboard/dashboarditemdate.h @@ -0,0 +1,61 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMDATE___H__ +#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMDATE___H__ + +#include + +#include +#include + +namespace ghoul::fontrendering { + class Font; +} // namespace ghoul::fontrendering + +namespace openspace { + +namespace documentation { struct Documentation; } + +class DashboardItemDate : public DashboardItem { +public: + DashboardItemDate(ghoul::Dictionary dictionary); + ~DashboardItemDate() = default; + + void render(glm::vec2& penPosition) override; + + glm::vec2 size() const override; + + static documentation::Documentation Documentation(); + +private: + properties::StringProperty _fontName; + properties::FloatProperty _fontSize; + + std::shared_ptr _font; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___DASHBOARDITEMDATE___H__ diff --git a/modules/base/dashboard/dashboarditemdistance.cpp b/modules/base/dashboard/dashboarditemdistance.cpp new file mode 100644 index 0000000000..4be8128b6c --- /dev/null +++ b/modules/base/dashboard/dashboarditemdistance.cpp @@ -0,0 +1,383 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace { + const char* KeyFontMono = "Mono"; + + const float DefaultFontSize = 10.f; + + static const openspace::properties::Property::PropertyInfo FontNameInfo = { + "FontName", + "Font Name", + "This value is the name of the font that is used. It can either refer to an " + "internal name registered previously, or it can refer to a path that is used." + }; + + static const openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "This value determines the size of the font that is used to render the date." + }; + + static const openspace::properties::Property::PropertyInfo SourceTypeInfo = { + "SourceType", + "Source Type", + "The type of position that is used as the source to calculate the distance. The " + "default value is 'Camera'." + }; + + static const openspace::properties::Property::PropertyInfo SourceNodeNameInfo = { + "SourceNodeName", + "Source Node Name", + "If a scene graph node is selected as type, this value specifies the name of the " + "node that is to be used as the source for computing the distance." + }; + + static const openspace::properties::Property::PropertyInfo DestinationTypeInfo = { + "DestinationType", + "Destination Type", + "The type of position that is used as the destination to calculate the distance. " + "The default value for this is 'Focus'." + }; + + static const openspace::properties::Property::PropertyInfo DestinationNodeNameInfo = { + "DestinationNodeName", + "Destination Node Name", + "If a scene graph node is selected as type, this value specifies the name of the " + "node that is to be used as the destination for computing the distance." + }; +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemDistance::Documentation() { + using namespace documentation; + return { + "DashboardItem Distance", + "base_dashboarditem_distance", + { + { + "Type", + new StringEqualVerifier("DashboardItemDistance"), + Optional::No + }, + { + FontNameInfo.identifier, + new StringVerifier, + Optional::Yes, + FontNameInfo.description + }, + { + FontSizeInfo.identifier, + new IntVerifier, + Optional::Yes, + FontSizeInfo.description + }, + { + SourceTypeInfo.identifier, + new StringInListVerifier({ + "Node", "Node Surface", "Focus", "Camera" + }), + Optional::Yes, + SourceTypeInfo.description + }, + { + SourceNodeNameInfo.identifier, + new StringVerifier, + Optional::Yes, + SourceNodeNameInfo.description + }, + { + DestinationTypeInfo.identifier, + new StringInListVerifier({ + "Node", "Node Surface", "Focus", "Camera" + }), + Optional::Yes, + DestinationTypeInfo.description + }, + { + DestinationNodeNameInfo.identifier, + new StringVerifier, + Optional::Yes, + DestinationNodeNameInfo.description + } + } + }; +} + +DashboardItemDistance::DashboardItemDistance(ghoul::Dictionary dictionary) + : DashboardItem("Distance") + , _fontName(FontNameInfo, KeyFontMono) + , _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f) + , _source{ + properties::OptionProperty( + SourceTypeInfo, + properties::OptionProperty::DisplayType::Dropdown + ), + properties::StringProperty(SourceNodeNameInfo), + nullptr + } + , _destination{ + properties::OptionProperty( + DestinationTypeInfo, + properties::OptionProperty::DisplayType::Dropdown + ), + properties::StringProperty(DestinationNodeNameInfo), + nullptr + } +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemDistance" + ); + + if (dictionary.hasKey(FontNameInfo.identifier)) { + _fontName = dictionary.value(FontNameInfo.identifier); + } + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = static_cast( + dictionary.value(FontSizeInfo.identifier) + ); + } + + _fontName.onChange([this]() { + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontName); + + _fontSize.onChange([this]() { + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontSize); + + _source.type.addOptions({ + { Type::Node, "Node" }, + { Type::NodeSurface, "Node Surface" }, + { Type::Focus, "Focus" }, + { Type::Camera, "Camera" } + }); + _source.type.onChange([this]() { + _source.nodeName.setVisibility( + properties::Property::Visibility( + _source.type == Type::Node || _source.type == Type::NodeSurface + ) + ); + }); + if (dictionary.hasKey(SourceTypeInfo.identifier)) { + std::string value = dictionary.value(SourceTypeInfo.identifier); + if (value == "Node") { + _source.type = Type::Node; + } + else if (value == "Node Surface") { + _source.type = Type::NodeSurface; + } + else if (value == "Focus") { + _source.type = Type::Focus; + } + else { + _source.type = Type::Camera; + } + } + else { + _source.type = Type::Camera; + } + addProperty(_source.type); + + _source.nodeName.onChange([this]() { + _source.node = nullptr; + }); + if (_source.type == Type::Node || _source.type == Type::NodeSurface) { + if (dictionary.hasKey(SourceNodeNameInfo.identifier)) { + _source.nodeName = dictionary.value( + SourceNodeNameInfo.identifier + ); + } + else { + LERRORC( + "DashboardItemDistance", + "Node type was selected for source but no node specified" + ); + } + } + addProperty(_source.nodeName); + + _destination.type.addOptions({ + { Type::Node, "Node" }, + { Type::NodeSurface, "Node Surface" }, + { Type::Focus, "Focus" }, + { Type::Camera, "Camera" } + }); + _destination.type.onChange([this]() { + _destination.nodeName.setVisibility( + properties::Property::Visibility( + _source.type == Type::Node || _source.type == Type::NodeSurface + ) + ); + }); + if (dictionary.hasKey(DestinationTypeInfo.identifier)) { + std::string value = dictionary.value(DestinationTypeInfo.identifier); + if (value == "Node") { + _destination.type = Type::Node; + } + else if (value == "Node Surface") { + _destination.type = Type::NodeSurface; + } + else if (value == "Focus") { + _destination.type = Type::Focus; + } + else { + _destination.type = Type::Camera; + } + } + else { + _destination.type = Type::Focus; + } + addProperty(_destination.type); + _destination.nodeName.onChange([this]() { + _destination.node = nullptr; + }); + if (_destination.type == Type::Node || _destination.type == Type::NodeSurface) { + if (dictionary.hasKey(DestinationNodeNameInfo.identifier)) { + _destination.nodeName = dictionary.value( + DestinationNodeNameInfo.identifier + ); + } + else { + LERRORC( + "DashboardItemDistance", + "Node type was selected for destination but no node specified" + ); + } + } + addProperty(_destination.nodeName); + + _font = OsEng.fontManager().font(_fontName, _fontSize); +} + +std::pair DashboardItemDistance::positionAndLabel( + Component& mainComp, + Component& otherComp) const +{ + if (mainComp.type == Type::Node || mainComp.type == Type::NodeSurface) { + if (!mainComp.node) { + mainComp.node = OsEng.renderEngine().scene()->sceneGraphNode( + mainComp.nodeName + ); + + if (!mainComp.node) { + LERRORC( + "DashboardItemDistance", + "Could not find node '" + mainComp.nodeName.value() + "'" + ); + return { glm::dvec3(0.0), "Node" }; + } + } + } + + switch (mainComp.type) { + case Type::Node: + return { mainComp.node->worldPosition(), mainComp.node->name() }; + case Type::NodeSurface: + { + glm::dvec3 otherPos; + if (otherComp.type == Type::NodeSurface) { + // We are only interested in the direction, and we want to prevent + // infinite recursion + otherPos = otherComp.node->worldPosition(); + } + else { + otherPos = positionAndLabel(otherComp, mainComp).first; + } + glm::dvec3 thisPos = mainComp.node->worldPosition(); + + glm::dvec3 dir = glm::normalize(otherPos - thisPos); + glm::dvec3 dirLength = dir * glm::dvec3(mainComp.node->boundingSphere()); + + return { thisPos + dirLength, "surface of " + mainComp.node->name() }; + } + case Type::Focus: + return { + OsEng.navigationHandler().focusNode()->worldPosition(), + "focus" + }; + case Type::Camera: + return { OsEng.renderEngine().camera()->positionVec3(), "camera" }; + default: + return { glm::dvec3(0.0), "Unknown" }; + } +}; + +void DashboardItemDistance::render(glm::vec2& penPosition) { + std::pair sourceInfo = positionAndLabel( + _source, + _destination + ); + std::pair destinationInfo = positionAndLabel( + _destination, + _source + ); + + double distance = glm::length(sourceInfo.first - destinationInfo.first); + std::pair dist = simplifyDistance(distance); + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + "Distance from %s to %s: %f %s", + sourceInfo.second.c_str(), + destinationInfo.second.c_str(), + dist.first, + dist.second.c_str() + ); +} + +glm::vec2 DashboardItemDistance::size() const { + double distance = 1e20; + std::pair dist = simplifyDistance(distance); + + return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Distance from focus: %f %s", + dist.first, + dist.second.c_str() + ).boundingBox; +} + +} // namespace openspace diff --git a/modules/base/dashboard/dashboarditemdistance.h b/modules/base/dashboard/dashboarditemdistance.h new file mode 100644 index 0000000000..bffdd2ab15 --- /dev/null +++ b/modules/base/dashboard/dashboarditemdistance.h @@ -0,0 +1,85 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMDISTANCE___H__ +#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMDISTANCE___H__ + +#include + +#include +#include +#include + +#include + +namespace ghoul::fontrendering { class Font; } + +namespace openspace { + +class SceneGraphNode; + +namespace documentation { struct Documentation; } + +class DashboardItemDistance : public DashboardItem { +public: + DashboardItemDistance(ghoul::Dictionary dictionary); + virtual ~DashboardItemDistance() = default; + + void render(glm::vec2& penPosition) override; + + glm::vec2 size() const override; + + static documentation::Documentation Documentation(); + +private: + enum Type { + Node = 0, + NodeSurface, + Focus, + Camera + }; + + struct Component { + properties::OptionProperty type; + properties::StringProperty nodeName; + SceneGraphNode* node; + }; + + std::pair positionAndLabel(Component& mainComp, + Component& otherComp) const; + + properties::StringProperty _fontName; + properties::FloatProperty _fontSize; + + + + Component _source; + Component _destination; + + std::shared_ptr _font; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___DASHBOARDITEMDISTANCE___H__ diff --git a/modules/base/dashboard/dashboarditemframerate.cpp b/modules/base/dashboard/dashboarditemframerate.cpp new file mode 100644 index 0000000000..23063067f9 --- /dev/null +++ b/modules/base/dashboard/dashboarditemframerate.cpp @@ -0,0 +1,220 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include + +#include +#include + +namespace { + const char* KeyFontMono = "Mono"; + const float DefaultFontSize = 10.f; + + static const openspace::properties::Property::PropertyInfo FontNameInfo = { + "FontName", + "Font Name", + "This value is the name of the font that is used. It can either refer to an " + "internal name registered previously, or it can refer to a path that is used." + }; + + static const openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "This value determines the size of the font that is used to render the date." + }; + + static const openspace::properties::Property::PropertyInfo FrametimeInfo = { + "FrametimeType", + "Type of the frame time display", + "This value determines the units in which the frame time is displayed." + }; +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemFramerate::Documentation() { + using namespace documentation; + return { + "DashboardItem Framerate", + "base_dashboarditem_framerate", + { + { + "Type", + new StringEqualVerifier("DashboardItemFramerate"), + Optional::No + }, + { + FontNameInfo.identifier, + new StringVerifier, + Optional::Yes, + FontNameInfo.description + }, + { + FontSizeInfo.identifier, + new IntVerifier, + Optional::Yes, + FontSizeInfo.description + }, + { + FrametimeInfo.identifier, + new StringInListVerifier({ + "Average Deltatime", "Frames per second", "Average frames per second", + "None" + }), + Optional::Yes, + FrametimeInfo.description + } + } + }; +} + +DashboardItemFramerate::DashboardItemFramerate(ghoul::Dictionary dictionary) + : DashboardItem("Framerate") + , _fontName(FontNameInfo, KeyFontMono) + , _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f) + , _frametimeType(FrametimeInfo, properties::OptionProperty::DisplayType::Dropdown) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemDate" + ); + + if (dictionary.hasKey(FontNameInfo.identifier)) { + _fontName = dictionary.value(FontNameInfo.identifier); + } + _fontName.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontName); + + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = static_cast( + dictionary.value(FontSizeInfo.identifier) + ); + } + _fontSize.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontSize); + + _frametimeType.addOptions({ + { static_cast(FrametimeType::DtTimeAvg), "Average Deltatime" }, + { static_cast(FrametimeType::FPS), "Frames per second" }, + { static_cast(FrametimeType::FPSAvg), "Average frames per second" }, + { static_cast(FrametimeType::None), "None" } + }); + + if (dictionary.hasKey(FrametimeInfo.identifier)) { + std::string value = dictionary.value(FrametimeInfo.identifier); + if (value == "Average Deltatime") { + _frametimeType = static_cast(FrametimeType::DtTimeAvg); + } + else if (value == "Frames per second") { + _frametimeType = static_cast(FrametimeType::FPS); + } + else if (value == "Average frames per second") { + _frametimeType = static_cast(FrametimeType::FPSAvg); + } + else { + _frametimeType = static_cast(FrametimeType::None); + } + } + else { + _frametimeType = static_cast(FrametimeType::FPS); + } + addProperty(_frametimeType); + + _font = OsEng.fontManager().font(_fontName, _fontSize); +} + +void DashboardItemFramerate::render(glm::vec2& penPosition) { + FrametimeType frametimeType = FrametimeType(_frametimeType.value()); + switch (frametimeType) { + case FrametimeType::DtTimeAvg: + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + "Avg. Frametime: %.5f", + OsEng.windowWrapper().averageDeltaTime() + ); + break; + case FrametimeType::FPS: + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + "FPS: %3.2f", + 1.0 / OsEng.windowWrapper().deltaTime() + ); + break; + case FrametimeType::FPSAvg: + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + "Avg. FPS: %3.2f", + 1.0 / OsEng.windowWrapper().averageDeltaTime() + ); + break; + case FrametimeType::None: + break; + } +} + +glm::vec2 DashboardItemFramerate::size() const { + FrametimeType frametimeType = FrametimeType(_frametimeType.value()); + switch (frametimeType) { + case FrametimeType::DtTimeAvg: + return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Avg. Frametime: %.5f", + OsEng.windowWrapper().averageDeltaTime() + ).boundingBox; + case FrametimeType::FPS: + return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "FPS: %3.2f", + 1.0 / OsEng.windowWrapper().deltaTime() + ).boundingBox; + case FrametimeType::FPSAvg: + return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Avg. FPS: %3.2f", + 1.0 / OsEng.windowWrapper().averageDeltaTime() + ).boundingBox; + case FrametimeType::None: + return { 0.f, 0.f }; + default: + return { 0.f, 0.f }; + } +} + +} // namespace openspace diff --git a/modules/base/dashboard/dashboarditemframerate.h b/modules/base/dashboard/dashboarditemframerate.h new file mode 100644 index 0000000000..1ede425ba8 --- /dev/null +++ b/modules/base/dashboard/dashboarditemframerate.h @@ -0,0 +1,69 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_CORE___DASHBOARDFRAMERATE___H__ +#define __OPENSPACE_CORE___DASHBOARDFRAMERATE___H__ + +#include + +#include +#include +#include + +#include + +namespace ghoul::fontrendering { + class Font; +} // namespace ghoul::fontrendering + +namespace openspace { + +namespace documentation { struct Documentation; } + +class DashboardItemFramerate : public DashboardItem { +public: + enum class FrametimeType { + DtTimeAvg = 0, + FPS, + FPSAvg, + None + }; + + DashboardItemFramerate(ghoul::Dictionary dict); + + void render(glm::vec2& penPosition) override; + glm::vec2 size() const override; + static documentation::Documentation Documentation(); + +private: + properties::StringProperty _fontName; + properties::FloatProperty _fontSize; + properties::OptionProperty _frametimeType; + + std::shared_ptr _font; +}; + +} // openspace + +#endif // __OPENSPACE_CORE___DASHBOARDFRAMERATE___H__ diff --git a/modules/base/dashboard/dashboarditemmission.cpp b/modules/base/dashboard/dashboarditemmission.cpp new file mode 100644 index 0000000000..9201466191 --- /dev/null +++ b/modules/base/dashboard/dashboarditemmission.cpp @@ -0,0 +1,247 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace { + const char* KeyFontMono = "Mono"; + const float DefaultFontSize = 15.f; + + static const openspace::properties::Property::PropertyInfo FontNameInfo = { + "FontName", + "Font Name", + "This value is the name of the font that is used. It can either refer to an " + "internal name registered previously, or it can refer to a path that is used." + }; + + static const openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "This value determines the size of the font that is used to render the date." + }; + + std::string progressToStr(int size, double t) { + std::string progress = "|"; + int g = static_cast((t * (size - 1)) + 1); + g = std::max(g, 0); + for (int i = 0; i < g; i++) { + progress.append("-"); + } + progress.append(">"); + for (int i = 0; i < size - g; i++) { + progress.append(" "); + } + progress.append("|"); + return progress; + } + +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemMission::Documentation() { + using namespace documentation; + return { + "DashboardItem Mission", + "base_dashboarditem_mission", + { + { + "Type", + new StringEqualVerifier("DashboardItemMission"), + Optional::No + }, + { + FontNameInfo.identifier, + new StringVerifier, + Optional::Yes, + FontNameInfo.description + }, + { + FontSizeInfo.identifier, + new IntVerifier, + Optional::Yes, + FontSizeInfo.description + } + } + }; +} + +DashboardItemMission::DashboardItemMission(ghoul::Dictionary dictionary) + : DashboardItem("Mission") + , _fontName(FontNameInfo, KeyFontMono) + , _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemDate" + ); + + if (dictionary.hasKey(FontNameInfo.identifier)) { + _fontName = dictionary.value(FontNameInfo.identifier); + } + _fontName.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontName); + + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = static_cast( + dictionary.value(FontSizeInfo.identifier) + ); + } + _fontSize.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontSize); + + _font = OsEng.fontManager().font(_fontName, _fontSize); +} + +void DashboardItemMission::render(glm::vec2& penPosition) { + if (MissionManager::ref().hasCurrentMission()) { + double currentTime = OsEng.timeManager().time().j2000Seconds(); + const Mission& mission = MissionManager::ref().currentMission(); + + if (mission.phases().size() > 0) { + static const glm::vec4 nextMissionColor(0.7, 0.3, 0.3, 1); + //static const glm::vec4 missionProgressColor(0.4, 1.0, 1.0, 1); + static const glm::vec4 currentMissionColor(0.0, 0.5, 0.5, 1); + static const glm::vec4 missionProgressColor = currentMissionColor; + // static const glm::vec4 currentLeafMissionColor = missionProgressColor; + static const glm::vec4 nonCurrentMissionColor(0.3, 0.3, 0.3, 1); + + // Add spacing + RenderFontCr(*_font, penPosition, nonCurrentMissionColor, " "); + + auto phaseTrace = mission.phaseTrace(currentTime); + + if (phaseTrace.size()) { + const MissionPhase& phase = phaseTrace.back().get(); + std::string title = "Current Mission Phase: " + phase.name(); + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + missionProgressColor, + title.c_str() + ); + double remaining = phase.timeRange().end - currentTime; + float t = static_cast( + 1.0 - remaining / phase.timeRange().duration() + ); + std::string progress = progressToStr(25, t); + penPosition.y -= _font->height(); + RenderFont(*_font, penPosition, missionProgressColor, + "%.0f s %s %.1f %%", remaining, progress.c_str(), t * 100); + } + else { + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + nextMissionColor, + "Next Mission:" + ); + double remaining = mission.timeRange().start - currentTime; + penPosition.y -= _font->height(); + RenderFont(*_font, penPosition, nextMissionColor, + "%.0f s", remaining); + } + + bool showAllPhases = false; + + typedef std::pair PhaseWithDepth; + std::stack S; + int pixelIndentation = 20; + S.push({ &mission, 0 }); + while (!S.empty()) { + const MissionPhase* phase = S.top().first; + int depth = S.top().second; + S.pop(); + + bool isCurrentPhase = phase->timeRange().includes(currentTime); + + penPosition.x += depth * pixelIndentation; + if (isCurrentPhase) { + double remaining = phase->timeRange().end - currentTime; + float t = static_cast( + 1.0 - remaining / phase->timeRange().duration() + ); + std::string progress = progressToStr(25, t); + penPosition.y -= _font->height(); + RenderFont(*_font, penPosition, currentMissionColor, + "%s %s %.1f %%", + phase->name().c_str(), + progress.c_str(), + t * 100 + ); + } + else { + if (!phase->name().empty()) { + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + nonCurrentMissionColor, + phase->name().c_str() + ); + } + } + penPosition.x -= depth * pixelIndentation; + + if (isCurrentPhase || showAllPhases) { + // phases are sorted increasingly by start time, and will be + // popped last-in-first-out from the stack, so add them in + // reversed order. + int indexLastPhase = static_cast( + phase->phases().size() + ) - 1; + for (int i = indexLastPhase; 0 <= i; --i) { + S.push({ &phase->phases()[i], depth + 1 }); + } + } + } + } + } +} + +glm::vec2 DashboardItemMission::size() const { + // @TODO fix this up ---abock + return { 0.f, 0.f }; +} + +} // namespace openspace diff --git a/modules/base/dashboard/dashboarditemmission.h b/modules/base/dashboard/dashboarditemmission.h new file mode 100644 index 0000000000..65c0fe531d --- /dev/null +++ b/modules/base/dashboard/dashboarditemmission.h @@ -0,0 +1,61 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMMISSION___H__ +#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMMISSION___H__ + +#include + +#include +#include + +namespace ghoul::fontrendering { + class Font; +} // namespace ghoul::fontrendering + +namespace openspace { + +namespace documentation { struct Documentation; } + +class DashboardItemMission : public DashboardItem { +public: + DashboardItemMission(ghoul::Dictionary dictionary); + virtual ~DashboardItemMission() = default; + + void render(glm::vec2& penPosition) override; + + glm::vec2 size() const override; + + static documentation::Documentation Documentation(); + +private: + properties::StringProperty _fontName; + properties::FloatProperty _fontSize; + + std::shared_ptr _font; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___DASHBOARDITEMMISSION___H__ diff --git a/modules/base/dashboard/dashboarditemparallelconnection.cpp b/modules/base/dashboard/dashboarditemparallelconnection.cpp new file mode 100644 index 0000000000..93df3e1fbe --- /dev/null +++ b/modules/base/dashboard/dashboarditemparallelconnection.cpp @@ -0,0 +1,221 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace { + const char* KeyFontMono = "Mono"; + const float DefaultFontSize = 10.f; + + static const openspace::properties::Property::PropertyInfo FontNameInfo = { + "FontName", + "Font Name", + "This value is the name of the font that is used. It can either refer to an " + "internal name registered previously, or it can refer to a path that is used." + }; + + static const openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "This value determines the size of the font that is used to render the date." + }; +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemParallelConnection::Documentation() { + using namespace documentation; + return { + "DashboardItem Parallel Connection", + "base_dashboarditem_parallelconnection", + { + { + "Type", + new StringEqualVerifier("DashboardItemParallelConnection"), + Optional::No + }, + { + FontNameInfo.identifier, + new StringVerifier, + Optional::Yes, + FontNameInfo.description + }, + { + FontSizeInfo.identifier, + new IntVerifier, + Optional::Yes, + FontSizeInfo.description + } + } + }; +} + +DashboardItemParallelConnection::DashboardItemParallelConnection(ghoul::Dictionary dictionary) + : DashboardItem("Parallel Connection") + , _fontName(FontNameInfo, KeyFontMono) + , _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemDate" + ); + + if (dictionary.hasKey(FontNameInfo.identifier)) { + _fontName = dictionary.value(FontNameInfo.identifier); + } + _fontName.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontName); + + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = static_cast( + dictionary.value(FontSizeInfo.identifier) + ); + } + _fontSize.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontSize); + + _font = OsEng.fontManager().font(_fontName, _fontSize); +} + +void DashboardItemParallelConnection::render(glm::vec2& penPosition) { + ParallelConnection::Status status = OsEng.parallelConnection().status(); + size_t nConnections = OsEng.parallelConnection().nConnections(); + const std::string& hostName = OsEng.parallelConnection().hostName(); + + std::string connectionInfo = ""; + int nClients = static_cast(nConnections); + if (status == ParallelConnection::Status::Host) { + nClients--; + if (nClients == 1) { + connectionInfo = "Hosting session with 1 client"; + } + else { + connectionInfo = + "Hosting session with " + std::to_string(nClients) + " clients"; + } + } + else if (status == ParallelConnection::Status::ClientWithHost) { + nClients--; + connectionInfo = "Session hosted by '" + hostName + "'"; + } + else if (status == ParallelConnection::Status::ClientWithoutHost) { + connectionInfo = "Host is disconnected"; + } + + if (status == ParallelConnection::Status::ClientWithHost || + status == ParallelConnection::Status::ClientWithoutHost) { + connectionInfo += "\n"; + if (nClients > 2) { + std::string c = std::to_string(nClients - 1); + connectionInfo += "You and " + c + " more clients are tuned in"; + } + else if (nClients == 2) { + std::string c = std::to_string(nClients - 1); + connectionInfo += "You and " + c + " more client are tuned in"; + } + else if (nClients == 1) { + connectionInfo += "You are the only client"; + } + } + + if (!connectionInfo.empty()) { + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + connectionInfo.c_str() + ); + } +} + +glm::vec2 DashboardItemParallelConnection::size() const { + ParallelConnection::Status status = OsEng.parallelConnection().status(); + size_t nConnections = OsEng.parallelConnection().nConnections(); + const std::string& hostName = OsEng.parallelConnection().hostName(); + + std::string connectionInfo = ""; + int nClients = static_cast(nConnections); + if (status == ParallelConnection::Status::Host) { + nClients--; + if (nClients == 1) { + connectionInfo = "Hosting session with 1 client"; + } + else { + connectionInfo = + "Hosting session with " + std::to_string(nClients) + " clients"; + } + } + else if (status == ParallelConnection::Status::ClientWithHost) { + nClients--; + connectionInfo = "Session hosted by '" + hostName + "'"; + } + else if (status == ParallelConnection::Status::ClientWithoutHost) { + connectionInfo = "Host is disconnected"; + } + + if (status == ParallelConnection::Status::ClientWithHost || + status == ParallelConnection::Status::ClientWithoutHost) { + connectionInfo += "\n"; + if (nClients > 2) { + std::string c = std::to_string(nClients - 1); + connectionInfo += "You and " + c + " more clients are tuned in"; + } + else if (nClients == 2) { + std::string c = std::to_string(nClients - 1); + connectionInfo += "You and " + c + " more client are tuned in"; + } + else if (nClients == 1) { + connectionInfo += "You are the only client"; + } + } + + if (!connectionInfo.empty()) { + return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + connectionInfo.c_str() + ).boundingBox; + } + else { + return { 0.f, 0.f }; + } +} + +} // namespace openspace diff --git a/modules/base/dashboard/dashboarditemparallelconnection.h b/modules/base/dashboard/dashboarditemparallelconnection.h new file mode 100644 index 0000000000..1b163e3179 --- /dev/null +++ b/modules/base/dashboard/dashboarditemparallelconnection.h @@ -0,0 +1,61 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMPARALLELCONNECTION___H__ +#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMPARALLELCONNECTION___H__ + +#include + +#include +#include + +namespace ghoul::fontrendering { + class Font; +} // namespace ghoul::fontrendering + +namespace openspace { + +namespace documentation { struct Documentation; } + +class DashboardItemParallelConnection : public DashboardItem { +public: + DashboardItemParallelConnection(ghoul::Dictionary dictionary); + virtual ~DashboardItemParallelConnection() = default; + + void render(glm::vec2& penPosition) override; + + glm::vec2 size() const override; + + static documentation::Documentation Documentation(); + +private: + properties::StringProperty _fontName; + properties::FloatProperty _fontSize; + + std::shared_ptr _font; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___DASHBOARDITEMPARALLELCONNECTION___H__ diff --git a/modules/base/dashboard/dashboarditemsimulationincrement.cpp b/modules/base/dashboard/dashboarditemsimulationincrement.cpp new file mode 100644 index 0000000000..f2e4b2c8ef --- /dev/null +++ b/modules/base/dashboard/dashboarditemsimulationincrement.cpp @@ -0,0 +1,141 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +namespace { + const char* KeyFontMono = "Mono"; + const float DefaultFontSize = 10.f; + + static const openspace::properties::Property::PropertyInfo FontNameInfo = { + "FontName", + "Font Name", + "This value is the name of the font that is used. It can either refer to an " + "internal name registered previously, or it can refer to a path that is used." + }; + + static const openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "This value determines the size of the font that is used to render the date." + }; +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemSimulationIncrement::Documentation() { + using namespace documentation; + return { + "DashboardItem Simulation Increment", + "base_dashboarditem_simulationincrement", + { + { + "Type", + new StringEqualVerifier("DashboardItemSimulationIncrement"), + Optional::No + }, + { + FontNameInfo.identifier, + new StringVerifier, + Optional::Yes, + FontNameInfo.description + }, + { + FontSizeInfo.identifier, + new IntVerifier, + Optional::Yes, + FontSizeInfo.description + } + } + }; +} + +DashboardItemSimulationIncrement::DashboardItemSimulationIncrement(ghoul::Dictionary dictionary) + : DashboardItem("Simulation Increment") + , _fontName(FontNameInfo, KeyFontMono) + , _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemDate" + ); + + if (dictionary.hasKey(FontNameInfo.identifier)) { + _fontName = dictionary.value(FontNameInfo.identifier); + } + _fontName.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontName); + + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = static_cast( + dictionary.value(FontSizeInfo.identifier) + ); + } + _fontSize.onChange([this](){ + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontSize); + + _font = OsEng.fontManager().font(_fontName, _fontSize); +} + +void DashboardItemSimulationIncrement::render(glm::vec2& penPosition) { + std::pair deltaTime = simplifyTime( + OsEng.timeManager().time().deltaTime() + ); + penPosition.y -= _font->height(); + RenderFont( + *_font, + penPosition, + "Simulation increment: %.1f %s / second", + deltaTime.first, + deltaTime.second.c_str() + ); +} + +glm::vec2 DashboardItemSimulationIncrement::size() const { + std::pair deltaTime = simplifyTime( + OsEng.timeManager().time().deltaTime() + ); + return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Simulation increment: %.1f %s / second", + deltaTime.first, + deltaTime.second.c_str() + ).boundingBox; +} + +} // namespace openspace diff --git a/modules/base/dashboard/dashboarditemsimulationincrement.h b/modules/base/dashboard/dashboarditemsimulationincrement.h new file mode 100644 index 0000000000..492d529b75 --- /dev/null +++ b/modules/base/dashboard/dashboarditemsimulationincrement.h @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMSIMULATIONINCREMENT___H__ +#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMSIMULATIONINCREMENT___H__ + +#include + +#include +#include + +namespace ghoul::fontrendering { + class Font; +} // namespace ghoul::fontrendering + +namespace openspace { + +namespace documentation { struct Documentation; } + +class DashboardItemSimulationIncrement : public DashboardItem { +public: + DashboardItemSimulationIncrement(ghoul::Dictionary dictionary); + virtual ~DashboardItemSimulationIncrement() = default; + + void render(glm::vec2& penPosition) override; + glm::vec2 size() const override; + + static documentation::Documentation Documentation(); + +private: + properties::StringProperty _fontName; + properties::FloatProperty _fontSize; + + std::shared_ptr _font; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___DASHBOARDITEMSIMULATIONINCREMENT___H__ diff --git a/modules/base/dashboard/dashboarditemspacing.cpp b/modules/base/dashboard/dashboarditemspacing.cpp new file mode 100644 index 0000000000..3848163cfb --- /dev/null +++ b/modules/base/dashboard/dashboarditemspacing.cpp @@ -0,0 +1,86 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +namespace { + static const openspace::properties::Property::PropertyInfo SpacingInfo = { + "Spacing", + "Spacing", + "This value determines the spacing (in pixels) that this item represents. The " + "default value is 15." + }; +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemSpacing::Documentation() { + using namespace documentation; + return { + "DashboardItem Spacing", + "base_dashboarditem_spacing", + { + { + "Type", + new StringEqualVerifier("DashboardItemSpacing"), + Optional::No + }, + { + SpacingInfo.identifier, + new DoubleVerifier, + Optional::Yes, + SpacingInfo.description + } + } + }; +} + +DashboardItemSpacing::DashboardItemSpacing(ghoul::Dictionary dictionary) + : DashboardItem("Spacing") + , _spacing(SpacingInfo, 15.f, 0.f, 2048.f) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemSpacing" + ); + + if (dictionary.hasKey(SpacingInfo.identifier)) { + _spacing = static_cast(dictionary.value(SpacingInfo.identifier)); + } + addProperty(_spacing); +} + +void DashboardItemSpacing::render(glm::vec2& penPosition) { + penPosition.y -= _spacing; +} + +glm::vec2 DashboardItemSpacing::size() const { + return { 0.f, _spacing }; +} + +} // namespace openspace diff --git a/modules/base/dashboard/dashboarditemspacing.h b/modules/base/dashboard/dashboarditemspacing.h new file mode 100644 index 0000000000..ef2458525e --- /dev/null +++ b/modules/base/dashboard/dashboarditemspacing.h @@ -0,0 +1,53 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_BASE___DASHBOARDITEMSPACING___H__ +#define __OPENSPACE_MODULE_BASE___DASHBOARDITEMSPACING___H__ + +#include + +#include + +namespace openspace { + +namespace documentation { struct Documentation; } + +class DashboardItemSpacing : public DashboardItem { +public: + DashboardItemSpacing(ghoul::Dictionary dictionary); + virtual ~DashboardItemSpacing() = default; + + void render(glm::vec2& penPosition) override; + + glm::vec2 size() const override; + + static documentation::Documentation Documentation(); + +private: + properties::FloatProperty _spacing; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_BASE___DASHBOARDITEMSPACING___H__ diff --git a/modules/base/rendering/screenspacedashboard.cpp b/modules/base/rendering/screenspacedashboard.cpp index 58d8d1d9fa..1700e4063d 100644 --- a/modules/base/rendering/screenspacedashboard.cpp +++ b/modules/base/rendering/screenspacedashboard.cpp @@ -36,17 +36,98 @@ #include #include +#include + #include #include namespace { const char* KeyName = "Name"; - const char* KeyFontMono = "Mono"; + static const openspace::properties::Property::PropertyInfo UseMainInfo = { + "UseMainDashboard", + "Use main dashboard", + "If this value is set to 'true', this ScreenSpaceDashboard will use the " + "main dashboard instead of creating an independent one." + }; } // namespace namespace openspace { +namespace luascriptfunctions { + +/** +* \ingroup LuaScripts +* addDashboardItemToScreenSpace(string, table): +*/ +int addDashboardItemToScreenSpace(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 2) { + return luaL_error(L, "Expected %i arguments, got %i", 2, nArguments); + } + + std::string name = luaL_checkstring(L, -2); + int type = lua_type(L, -1); + if (type != LUA_TTABLE) { + return luaL_error(L, "Expected argument of type 'table'"); + } + else { + ghoul::Dictionary d; + try { + ghoul::lua::luaDictionaryFromState(L, d); + } + catch (const ghoul::lua::LuaFormatException& e) { + LERRORC("addDashboardItem", e.what()); + return 0; + } + + std::shared_ptr ssr = + OsEng.renderEngine().screenSpaceRenderable(name); + + if (!ssr) { + return luaL_error(L, "Provided name is not a ScreenSpace item"); + } + + ScreenSpaceDashboard* dash = dynamic_cast(ssr.get()); + if (!dash) { + return luaL_error(L, "Provided name is a ScreenSpace item but not a dashboard"); + } + + dash->dashboard().addDashboardItem(DashboardItem::createFromDictionary(d)); + return 0; + } +} + +/** +* \ingroup LuaScripts +* removeDashboardItemsFromScreenSpace(string): +*/ +int removeDashboardItemsFromScreenSpace(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 1) { + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + } + + std::string name = luaL_checkstring(L, -1); + std::shared_ptr ssr = + OsEng.renderEngine().screenSpaceRenderable(name); + + if (!ssr) { + return luaL_error(L, "Provided name is not a ScreenSpace item"); + } + + ScreenSpaceDashboard* dash = dynamic_cast(ssr.get()); + if (!dash) { + return luaL_error(L, "Provided name is a ScreenSpace item but not a dashboard"); + } + + dash->dashboard().removeDashboardItems(); + return 0; +} + +} // namespace luascriptfunctions + + documentation::Documentation ScreenSpaceDashboard::Documentation() { using namespace openspace::documentation; return { @@ -58,6 +139,12 @@ documentation::Documentation ScreenSpaceDashboard::Documentation() { new StringVerifier, Optional::Yes, "Specifies the GUI name of the ScreenSpaceDashboard" + }, + { + UseMainInfo.identifier, + new BoolVerifier, + Optional::Yes, + UseMainInfo.description } } }; @@ -65,9 +152,7 @@ documentation::Documentation ScreenSpaceDashboard::Documentation() { ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary) : ScreenSpaceFramebuffer(dictionary) - , _fontRenderer(nullptr) - , _fontDate(nullptr) - , _fontInfo(nullptr) + , _useMainDashboard(UseMainInfo, false) { documentation::testSpecificationAndThrow( Documentation(), @@ -89,12 +174,13 @@ ScreenSpaceDashboard::ScreenSpaceDashboard(const ghoul::Dictionary& dictionary) ++id; } + if (dictionary.hasKey(UseMainInfo.identifier)) { + _useMainDashboard = dictionary.value(UseMainInfo.identifier); + } + addProperty(_useMainDashboard); + _scale = 1.f; _scale.setMaxValue(15.f); - - _size.onChange([this]() { - _fontRenderer->setFramebufferSize({ _size.value().z, _size.value().w }); - }); } ScreenSpaceDashboard::~ScreenSpaceDashboard() {} @@ -102,71 +188,32 @@ ScreenSpaceDashboard::~ScreenSpaceDashboard() {} bool ScreenSpaceDashboard::initializeGL() { ScreenSpaceFramebuffer::initializeGL(); - _fontRenderer = ghoul::fontrendering::FontRenderer::createDefault(); - _fontRenderer->setFramebufferSize({ _size.value().z, _size.value().w }); - - - _fontDate = OsEng.fontManager().font( - KeyFontMono, - 48 - ); - _fontInfo = OsEng.fontManager().font( - KeyFontMono, - 32 - ); - addRenderFunction([this]() { - glm::vec2 penPosition = glm::vec2( 10.f, _size.value().w ); - penPosition.y -= _fontDate->height(); - RenderFontCr( - *_fontDate, - penPosition, - "Date: %s", - OsEng.timeManager().time().UTC().c_str() - ); - - std::pair deltaTime = simplifyTime( - OsEng.timeManager().time().deltaTime() - ); - RenderFontCr( - *_fontInfo, - penPosition, - "Simulation increment: %.1f %s / second", - deltaTime.first, - deltaTime.second.c_str() - ); - - double distance = glm::length( - OsEng.renderEngine().camera()->positionVec3() - - OsEng.navigationHandler().focusNode()->worldPosition() - ); - std::pair dist = simplifyDistance(distance); - RenderFontCr( - *_fontInfo, - penPosition, - "Distance from focus: %f %s", - dist.first, - dist.second.c_str() - ); + if (_useMainDashboard) { + OsEng.dashboard().render(penPosition); + } + else { + _dashboard.render(penPosition); + } }); return true; } bool ScreenSpaceDashboard::deinitializeGL() { - _fontRenderer = nullptr; + //_fontRenderer = nullptr; return ScreenSpaceFramebuffer::deinitializeGL(); } bool ScreenSpaceDashboard::isReady() const { - return (_fontRenderer != nullptr) && + return /*(_fontRenderer != nullptr) && (_fontDate != nullptr) && - (_fontInfo != nullptr) && + (_fontInfo != nullptr) &&*/ ScreenSpaceFramebuffer::isReady(); } @@ -179,4 +226,31 @@ void ScreenSpaceDashboard::update() { } } +Dashboard& ScreenSpaceDashboard::dashboard() { + return _dashboard; +} + +const Dashboard& ScreenSpaceDashboard::dashboard() const { + return _dashboard; +} + +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." + } + } + }; +} } // namespace openspace diff --git a/modules/base/rendering/screenspacedashboard.h b/modules/base/rendering/screenspacedashboard.h index fe2b3e6c23..9746af2b1e 100644 --- a/modules/base/rendering/screenspacedashboard.h +++ b/modules/base/rendering/screenspacedashboard.h @@ -27,6 +27,9 @@ #include +#include +#include + namespace ghoul::fontrendering { class Font; class FontRenderer; @@ -35,6 +38,7 @@ namespace ghoul::fontrendering { namespace openspace { namespace documentation { struct Documentation; } +namespace scripting { struct LuaLibrary; } class ScreenSpaceDashboard: public ScreenSpaceFramebuffer { public: @@ -47,13 +51,20 @@ public: bool isReady() const override; void update() override; + Dashboard& dashboard(); + const Dashboard& dashboard() const; + + static scripting::LuaLibrary luaLibrary(); + static documentation::Documentation Documentation(); private: - std::unique_ptr _fontRenderer; + Dashboard _dashboard; + properties::BoolProperty _useMainDashboard; + //std::unique_ptr _fontRenderer; - std::shared_ptr _fontDate; - std::shared_ptr _fontInfo; + //std::shared_ptr _fontDate; + //std::shared_ptr _fontInfo; }; } // namespace openspace diff --git a/modules/imgui/imguimodule.cpp b/modules/imgui/imguimodule.cpp index 10c0d1360b..9e329b9119 100644 --- a/modules/imgui/imguimodule.cpp +++ b/modules/imgui/imguimodule.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -68,7 +69,8 @@ ImGUIModule::ImGUIModule() : OpenSpaceModule(Name) { &(OsEng.navigationHandler()), &(OsEng.renderEngine()), &(OsEng.parallelConnection()), - &(OsEng.console()) + &(OsEng.console()), + &(OsEng.dashboard()) }; return res; } diff --git a/modules/imgui/src/gui.cpp b/modules/imgui/src/gui.cpp index 91ba7517d0..9f9c3f549c 100644 --- a/modules/imgui/src/gui.cpp +++ b/modules/imgui/src/gui.cpp @@ -893,7 +893,7 @@ void GUI::render() { addScreenSpaceRenderableOnline(std::string(addImageOnlineBuffer)); } - bool addDashboard = ImGui::Button("Add Dashboard"); + bool addDashboard = ImGui::Button("Add New Dashboard"); if (addDashboard) { OsEng.scriptEngine().queueScript( "openspace.addScreenSpaceRenderable({ Type = 'ScreenSpaceDashboard' });", @@ -901,6 +901,16 @@ void GUI::render() { ); } + bool addDashboardCopy = ImGui::Button("Add Copy of Main Dashboard"); + if (addDashboardCopy) { + OsEng.scriptEngine().queueScript( + "openspace.addScreenSpaceRenderable({ " + "Type = 'ScreenSpaceDashboard', UseMainDashboard = true " + "});", + openspace::scripting::ScriptEngine::RemoteScripting::Yes + ); + } + ImGui::Checkbox("ImGUI Internals", &_showInternals); if (_showInternals) { ImGui::Begin("Style Editor"); diff --git a/modules/spacecraftinstruments/CMakeLists.txt b/modules/spacecraftinstruments/CMakeLists.txt index 1a31aa5e9e..888ab68c08 100644 --- a/modules/spacecraftinstruments/CMakeLists.txt +++ b/modules/spacecraftinstruments/CMakeLists.txt @@ -25,6 +25,7 @@ include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake) set(HEADER_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditeminstruments.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablecrawlingline.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefov.h ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplaneprojection.h @@ -47,6 +48,7 @@ set(HEADER_FILES source_group("Header Files" FILES ${HEADER_FILES}) set(SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/dashboard/dashboarditeminstruments.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablecrawlingline.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablefov.cpp ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderableplaneprojection.cpp diff --git a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp new file mode 100644 index 0000000000..93e12d863d --- /dev/null +++ b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.cpp @@ -0,0 +1,498 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace { + const char* KeyFontMono = "Mono"; + const float DefaultFontSize = 10.f; + + static const openspace::properties::Property::PropertyInfo FontNameInfo = { + "FontName", + "Font Name", + "This value is the name of the font that is used. It can either refer to an " + "internal name registered previously, or it can refer to a path that is used." + }; + + static const openspace::properties::Property::PropertyInfo FontSizeInfo = { + "FontSize", + "Font Size", + "This value determines the size of the font that is used to render the date." + }; + + static const openspace::properties::Property::PropertyInfo ActiveColorInfo = { + "ActiveColor", + "Active Color", + "This value determines the color that the active instrument is rendered in. " + "Shortly after activation, the used color is mixture of this and the flash color. " + "The default value is (0.6, 1.0, 0.0)." + }; + + static const openspace::properties::Property::PropertyInfo FlashColorInfo = { + "FlashColor", + "Flash Color", + "This value determines the color that is used shortly after an instrument " + "activation. The default value is (0.9, 1.0, 0.75)" + }; + + std::string progressToStr(int size, double t) { + std::string progress = "|"; + int g = static_cast((t * (size - 1)) + 1); + g = std::max(g, 0); + for (int i = 0; i < g; i++) { + progress.append("-"); + } + progress.append(">"); + for (int i = 0; i < size - g; i++) { + progress.append(" "); + } + progress.append("|"); + return progress; + } + + glm::vec2 addToBoundingbox(glm::vec2 lhs, glm::vec2 rhs) { + return { + std::max(lhs.x, rhs.x), + lhs.y + rhs.y + }; + } +} // namespace + +namespace openspace { + +documentation::Documentation DashboardItemInstruments::Documentation() { + using namespace documentation; + return { + "DashboardItem Instruments", + "spacecraftinstruments_dashboarditem_instuments", + { + { + "Type", + new StringEqualVerifier("DashboardItemInstruments"), + Optional::No + }, + { + FontNameInfo.identifier, + new StringVerifier, + Optional::Yes, + FontNameInfo.description + }, + { + FontSizeInfo.identifier, + new IntVerifier, + Optional::Yes, + FontSizeInfo.description + }, + { + ActiveColorInfo.identifier, + new DoubleVector3Verifier, + Optional::Yes, + ActiveColorInfo.description + }, + { + FlashColorInfo.identifier, + new DoubleVector3Verifier, + Optional::Yes, + FlashColorInfo.description + } + } + }; +} + +DashboardItemInstruments::DashboardItemInstruments(ghoul::Dictionary dictionary) + : DashboardItem("Instruments") + , _fontName(FontNameInfo, KeyFontMono) + , _fontSize(FontSizeInfo, DefaultFontSize, 6.f, 144.f, 1.f) + , _activeColor( + ActiveColorInfo, + glm::vec3(0.6f, 1.f, 0.f), + glm::vec3(0.f), + glm::vec3(1.f) + ) + , _activeFlash(FlashColorInfo, + glm::vec3(0.9f, 1.f, 0.75f), + glm::vec3(0.f), + glm::vec3(1.f) + ) + , _font(OsEng.fontManager().font(KeyFontMono, 10)) +{ + documentation::testSpecificationAndThrow( + Documentation(), + dictionary, + "DashboardItemInstruments" + ); + + if (dictionary.hasKey(FontNameInfo.identifier)) { + _fontName = dictionary.value(FontNameInfo.identifier); + } + if (dictionary.hasKey(FontSizeInfo.identifier)) { + _fontSize = static_cast( + dictionary.value(FontSizeInfo.identifier) + ); + } + + _fontName.onChange([this]() { + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontName); + + _fontSize.onChange([this]() { + _font = OsEng.fontManager().font(_fontName, _fontSize); + }); + addProperty(_fontSize); + + _activeColor.setViewOption(properties::Property::ViewOptions::Color); + addProperty(_activeColor); + _activeFlash.setViewOption(properties::Property::ViewOptions::Color); + addProperty(_activeFlash); + + _font = OsEng.fontManager().font(_fontName, _fontSize); +} + +void DashboardItemInstruments::render(glm::vec2& penPosition) { + double currentTime = OsEng.timeManager().time().j2000Seconds(); + + if (ImageSequencer::ref().isReady()) { + penPosition.y -= 25.f; + + glm::vec4 targetColor(0.f, 0.75f, 1.f, 1.f); + + double remaining = ImageSequencer::ref().getNextCaptureTime() - currentTime; + float t = static_cast( + 1.0 - remaining / ImageSequencer::ref().getIntervalLength() + ); + + if (remaining > 0) { + RenderFontCr(*_font, + penPosition, + glm::vec4(glm::mix(_activeColor.value(), _activeFlash.value(), t), 1.f), + //active * t + brigther_active, + "Next instrument activity:" + ); + + const int Size = 25; + int p = std::max(static_cast((t * (Size - 1)) + 1), 0); + RenderFontCr(*_font, + penPosition, + glm::vec4(glm::mix(_activeColor.value(), _activeFlash.value(), t), 1.f), + "%4.0f s |%s>%s| %.1f %%", + remaining, + std::string(p, '-').c_str(), + std::string(Size - p, ' ').c_str(), + t * 100 + ); + + std::string str = SpiceManager::ref().dateFromEphemerisTime( + ImageSequencer::ref().getNextCaptureTime(), + "YYYY MON DD HR:MN:SC" + ); + + RenderFontCr(*_font, + penPosition, + glm::vec4(_activeColor.value(), 1.f), + "Data acquisition time: %s", + str.c_str() + ); + } + std::pair nextTarget = ImageSequencer::ref().getNextTarget(); + std::pair currentTarget = + ImageSequencer::ref().getCurrentTarget(); + + if (currentTarget.first > 0.0) { + using namespace std::chrono; + seconds tls = seconds(static_cast(nextTarget.first - currentTime)); + + hours tlh = duration_cast(tls); + tls -= tlh; + minutes tlm = duration_cast(tls); + tls -= tlm; + + RenderFontCr(*_font, + penPosition, + targetColor, + "Next image: [%02i:%02i:%02i]", + tlh.count(), tlm.count(), tls.count() + ); + + penPosition.y -= _font->height(); + + std::map activeMap = + ImageSequencer::ref().getActiveInstruments(); + glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1); + glm::vec4 notFiring(0.5, 0.5, 0.5, 1); + + RenderFontCr(*_font, + penPosition, + glm::vec4(_activeColor.value(), 1.f), + "Active Instruments:" + ); + + for (auto m : activeMap) { + if (m.second == false) { + RenderFont(*_font, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + "| |" + ); + RenderFontCr(*_font, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + " %5s", + m.first.c_str() + ); + + } + else { + RenderFont(*_font, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + "|" + ); + if (m.first == "NH_LORRI") { + RenderFont(*_font, + penPosition, + firing, + " + " + ); + } + RenderFont(*_font, + penPosition, + glm::vec4(0.3, 0.3, 0.3, 1), + " |" + ); + RenderFontCr(*_font, + penPosition, + glm::vec4(_activeColor.value(), 1.f), + " %5s", + m.first.c_str() + ); + } + } + } + } +} + +glm::vec2 DashboardItemInstruments::size() const { + glm::vec2 size = { 0.f, 0.f }; + //return ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + bool hasNewHorizons = OsEng.renderEngine().scene()->sceneGraphNode("NewHorizons"); + double currentTime = OsEng.timeManager().time().j2000Seconds(); + + if (ImageSequencer::ref().isReady()) { + glm::vec4 targetColor(0.f, 0.75f, 1.f, 1.f); + + if (hasNewHorizons) { + try { + double lt; + glm::dvec3 p = SpiceManager::ref().targetPosition( + "PLUTO", + "NEW HORIZONS", + "GALACTIC", + {}, + currentTime, + lt + ); + psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate( + p.x, + p.y, + p.z + ); + float a, b; + glm::dvec3 radii; + SpiceManager::ref().getValue("PLUTO", "RADII", radii); + a = static_cast(radii.x); + b = static_cast(radii.y); + float radius = (a + b) / 2.f; + float distToSurf = glm::length(nhPos.vec3()) - radius; + + size = addToBoundingbox( + size, + ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Distance to Pluto: % .1f (KM)", + distToSurf + ).boundingBox + ); + } + catch (...) { + // @CLEANUP: This is bad as it will discard all exceptions + // without telling us about it! ---abock + } + } + + double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - + currentTime; + float t = static_cast( + 1.0 - remaining / openspace::ImageSequencer::ref().getIntervalLength() + ); + + std::string str = SpiceManager::ref().dateFromEphemerisTime( + ImageSequencer::ref().getNextCaptureTime(), + "YYYY MON DD HR:MN:SC" + ); + + + if (remaining > 0) { + std::string progress = progressToStr(25, t); + + size = addToBoundingbox( + size, + ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Next instrument activity:" + ).boundingBox + ); + + size = addToBoundingbox( + size, + ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "%.0f s %s %.1f %%", + remaining, progress.c_str(), t * 100 + ).boundingBox + ); + + size = addToBoundingbox( + size, + ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Data acquisition time: %s", + str.c_str() + ).boundingBox + ); + } + std::pair nextTarget = ImageSequencer::ref().getNextTarget(); + std::pair currentTarget = + ImageSequencer::ref().getCurrentTarget(); + + if (currentTarget.first > 0.0) { + int timeleft = static_cast(nextTarget.first - currentTime); + + int hour = timeleft / 3600; + int second = timeleft % 3600; + int minute = second / 60; + second = second % 60; + + std::string hh, mm, ss; + + if (hour < 10) + hh.append("0"); + if (minute < 10) + mm.append("0"); + if (second < 10) + ss.append("0"); + + hh.append(std::to_string(hour)); + mm.append(std::to_string(minute)); + ss.append(std::to_string(second)); + + size = addToBoundingbox( + size, + ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Data acquisition adjacency: [%s:%s:%s]", + hh.c_str(), mm.c_str(), ss.c_str() + ).boundingBox + ); + + size.y += _font->height(); + + std::map activeMap = + ImageSequencer::ref().getActiveInstruments(); + glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1); + glm::vec4 notFiring(0.5, 0.5, 0.5, 1); + + size = addToBoundingbox( + size, + ghoul::fontrendering::FontRenderer::defaultRenderer().boundingBox( + *_font, + "Active Instruments:" + ).boundingBox + ); + + // @TODO: Fix this up ---abock + + //for (auto m : activeMap) { + // if (m.second == false) { + // RenderFont(*_font, + // penPosition, + // glm::vec4(0.3, 0.3, 0.3, 1), + // "| |" + // ); + // RenderFontCr(*_font, + // penPosition, + // glm::vec4(0.3, 0.3, 0.3, 1), + // " %5s", + // m.first.c_str() + // ); + + // } + // else { + // RenderFont(*_font, + // penPosition, + // glm::vec4(0.3, 0.3, 0.3, 1), + // "|" + // ); + // if (m.first == "NH_LORRI") { + // RenderFont(*_font, + // penPosition, + // firing, + // " + " + // ); + // } + // RenderFont(*_font, + // penPosition, + // glm::vec4(0.3, 0.3, 0.3, 1), + // " |" + // ); + // RenderFontCr(*_font, + // penPosition, + // active, + // " %5s", + // m.first.c_str() + // ); + // } + //} + } + } + + return size; +} + +} // namespace openspace diff --git a/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.h b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.h new file mode 100644 index 0000000000..c67e293c14 --- /dev/null +++ b/modules/spacecraftinstruments/dashboard/dashboarditeminstruments.h @@ -0,0 +1,64 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#ifndef __OPENSPACE_MODULE_SPACECRAFTINSTRUMENTS___DASHBOARDITEMINSTRUMENTS___H__ +#define __OPENSPACE_MODULE_SPACECRAFTINSTRUMENTS___DASHBOARDITEMINSTRUMENTS___H__ + +#include + +#include +#include +#include + +namespace ghoul::fontrendering { class Font; } + +namespace openspace { + +namespace documentation { struct Documentation; } + +class DashboardItemInstruments : public DashboardItem { +public: + DashboardItemInstruments(ghoul::Dictionary dictionary); + ~DashboardItemInstruments() = default; + + void render(glm::vec2& penPosition) override; + + glm::vec2 size() const override; + + static documentation::Documentation Documentation(); + +private: + properties::StringProperty _fontName; + properties::FloatProperty _fontSize; + + properties::Vec3Property _activeColor; + properties::Vec3Property _activeFlash; + + + std::shared_ptr _font; +}; + +} // namespace openspace + +#endif // __OPENSPACE_MODULE_SPACECRAFTINSTRUMENTS___DASHBOARDITEMINSTRUMENTS___H__ diff --git a/modules/spacecraftinstruments/spacecraftinstrumentsmodule.cpp b/modules/spacecraftinstruments/spacecraftinstrumentsmodule.cpp index 22a46eacb2..e021a9c86b 100644 --- a/modules/spacecraftinstruments/spacecraftinstrumentsmodule.cpp +++ b/modules/spacecraftinstruments/spacecraftinstrumentsmodule.cpp @@ -24,6 +24,8 @@ #include +#include + #include #include #include @@ -53,6 +55,11 @@ void SpacecraftInstrumentsModule::internalInitialize() { "Decoder" ); + auto fDashboard = FactoryManager::ref().factory(); + ghoul_assert(fDashboard, "Dashboard factory was not created"); + + fDashboard->registerClass("DashboardItemInstruments"); + auto fRenderable = FactoryManager::ref().factory(); ghoul_assert(fRenderable, "No renderable factory existed"); diff --git a/scripts/scene_helper.lua b/scripts/scene_helper.lua index e8d19c7e98..5f3c10f246 100644 --- a/scripts/scene_helper.lua +++ b/scripts/scene_helper.lua @@ -12,6 +12,14 @@ openspace.documentation = { 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 = "set_default_dashboard", + Arguments = "", + Documentation = "This function sets the default values for the dashboard " .. + "consisting of 'DashboardItemDate', 'DashboardItemSimulationIncrement', " .. + "'DashboardItemDistance', 'DashboardItemFramerate', and " .. + "'DashboardItemParallelConnection'." } } @@ -23,6 +31,28 @@ openspace.mark_interesting_nodes = function(nodes) end end +openspace.set_default_dashboard = function() + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDate" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemSimulationIncrement" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemDistance" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemFramerate" + }) + + openspace.dashboard.addDashboardItem({ + Type = "DashboardItemParallelConnection" + }) +end + openspace.set_default_gui_sorting = function() openspace.setPropertyValueSingle( 'Global Properties.ImGUI.Main.Properties.Ordering', @@ -30,4 +60,4 @@ openspace.set_default_gui_sorting = function() "Solar System", "Milky Way", "Universe", "Other" } ) -end \ No newline at end of file +end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1970212ed7..652be337c4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -120,6 +120,9 @@ set(OPENSPACE_SOURCE ${OPENSPACE_BASE_DIR}/src/properties/vector/vec4property.cpp ${OPENSPACE_BASE_DIR}/src/query/query.cpp ${OPENSPACE_BASE_DIR}/src/rendering/abufferrenderer.cpp + ${OPENSPACE_BASE_DIR}/src/rendering/dashboard.cpp + ${OPENSPACE_BASE_DIR}/src/rendering/dashboard_lua.inl + ${OPENSPACE_BASE_DIR}/src/rendering/dashboarditem.cpp ${OPENSPACE_BASE_DIR}/src/rendering/framebufferrenderer.cpp ${OPENSPACE_BASE_DIR}/src/rendering/loadingscreen.cpp ${OPENSPACE_BASE_DIR}/src/rendering/raycastermanager.cpp @@ -286,6 +289,8 @@ set(OPENSPACE_HEADER ${OPENSPACE_BASE_DIR}/include/openspace/properties/vector/vec4property.h ${OPENSPACE_BASE_DIR}/include/openspace/query/query.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/abufferrenderer.h + ${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboard.h + ${OPENSPACE_BASE_DIR}/include/openspace/rendering/dashboarditem.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/framebufferrenderer.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/loadingscreen.h ${OPENSPACE_BASE_DIR}/include/openspace/rendering/raycasterlistener.h diff --git a/src/documentation/core_registration.cpp b/src/documentation/core_registration.cpp index c06fcc4721..03c058e98a 100644 --- a/src/documentation/core_registration.cpp +++ b/src/documentation/core_registration.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -51,8 +52,8 @@ namespace openspace { void registerCoreClasses(documentation::DocumentationEngine& engine) { - engine.addDocumentation(LogFactoryDocumentation()); engine.addDocumentation(ConfigurationManager::Documentation()); + engine.addDocumentation(LogFactoryDocumentation()); engine.addDocumentation(Mission::Documentation()); engine.addDocumentation(Renderable::Documentation()); engine.addDocumentation(Rotation::Documentation()); @@ -65,19 +66,19 @@ void registerCoreClasses(documentation::DocumentationEngine& engine) { } void registerCoreClasses(scripting::ScriptEngine& engine) { + engine.addLibrary(Dashboard::luaLibrary()); + engine.addLibrary(MissionManager::luaLibrary()); + engine.addLibrary(ModuleEngine::luaLibrary()); engine.addLibrary(OpenSpaceEngine::luaLibrary()); - engine.addLibrary(SpiceManager::luaLibrary()); + engine.addLibrary(ParallelConnection::luaLibrary()); engine.addLibrary(RenderEngine::luaLibrary()); + engine.addLibrary(SpiceManager::luaLibrary()); engine.addLibrary(Scene::luaLibrary()); engine.addLibrary(Time::luaLibrary()); + engine.addLibrary(WindowWrapper::luaLibrary()); engine.addLibrary(interaction::KeyBindingManager::luaLibrary()); engine.addLibrary(interaction::NavigationHandler::luaLibrary()); - engine.addLibrary(ParallelConnection::luaLibrary()); - engine.addLibrary(ModuleEngine::luaLibrary()); engine.addLibrary(scripting::ScriptScheduler::luaLibrary()); - engine.addLibrary(WindowWrapper::luaLibrary()); - engine.addLibrary(MissionManager::luaLibrary()); - engine.addLibrary(scripting::generalSystemCapabilities()); engine.addLibrary(scripting::openglSystemCapabilities()); } diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index a4606c6e01..0e6ae23832 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include #include @@ -146,6 +148,7 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName, std::unique_ptr windowWrapper) : _configurationManager(new ConfigurationManager) , _sceneManager(new SceneManager) + , _dashboard(new Dashboard) , _downloadManager(nullptr) , _console(new LuaConsole) , _moduleEngine(new ModuleEngine) @@ -177,13 +180,14 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName, { _navigationHandler->setPropertyOwner(_globalPropertyNamespace.get()); - // New property subowners also have to be added to the OnScreenGuiModule callback! + // New property subowners also have to be added to the ImGuiModule callback! _globalPropertyNamespace->addPropertySubOwner(_navigationHandler.get()); _globalPropertyNamespace->addPropertySubOwner(_settingsEngine.get()); _globalPropertyNamespace->addPropertySubOwner(_renderEngine.get()); _globalPropertyNamespace->addPropertySubOwner(_windowWrapper.get()); _globalPropertyNamespace->addPropertySubOwner(_parallelConnection.get()); _globalPropertyNamespace->addPropertySubOwner(_console.get()); + _globalPropertyNamespace->addPropertySubOwner(_dashboard.get()); _versionInformation.versionString.setReadOnly(true); @@ -212,6 +216,10 @@ OpenSpaceEngine::OpenSpaceEngine(std::string programName, std::make_unique>(), "Task" ); + FactoryManager::ref().addFactory( + std::make_unique>(), + "DashboardItem" + ); SpiceManager::initialize(); TransformationManager::initialize(); @@ -515,6 +523,10 @@ void OpenSpaceEngine::initialize() { for (OpenSpaceModule* module : _moduleEngine->modules()) { _scriptEngine->addLibrary(module->luaLibrary()); + + for (scripting::LuaLibrary& l : module->luaLibraries()) { + _scriptEngine->addLibrary(l); + } } // TODO: Maybe move all scenegraph and renderengine stuff to initializeGL @@ -1627,6 +1639,11 @@ LuaConsole& OpenSpaceEngine::console() { return *_console; } +Dashboard& OpenSpaceEngine::dashboard() { + ghoul_assert(_dashboard, "Dashboard must not be nullptr"); + return *_dashboard; +} + DownloadManager& OpenSpaceEngine::downloadManager() { ghoul_assert(_downloadManager, "Download Manager must not be nullptr"); return *_downloadManager; diff --git a/src/rendering/dashboard.cpp b/src/rendering/dashboard.cpp new file mode 100644 index 0000000000..c62dab5170 --- /dev/null +++ b/src/rendering/dashboard.cpp @@ -0,0 +1,114 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include +#include + +#include "dashboard_lua.inl" + +namespace openspace { + +Dashboard::Dashboard() + : properties::PropertyOwner({ "Dashboard" }) +{} + +void Dashboard::addDashboardItem(std::unique_ptr item) { + std::string originalName = item->name(); + int suffix = 1; + while (true) { + auto it = std::find_if( + _items.begin(), + _items.end(), + [&item](const std::unique_ptr& i) { + return (i->name() == item->name()); + } + ); + + if (it == _items.end()) { + // We found a unique name + break; + } + else { + item->setName(originalName + " " + std::to_string(suffix)); + ++suffix; + } + } + + addPropertySubOwner(item.get()); + _items.push_back(std::move(item)); +} + +void Dashboard::removeDashboardItem(int index) { + ghoul_assert(index < _items.size(), "Invalid index"); + removePropertySubOwner(_items[index].get()); + _items.erase(_items.begin() + index); +} + +bool Dashboard::hasItem(int index) const { + return (index >= 0) && (index < _items.size()); +} + +const DashboardItem& Dashboard::item(int index) const { + ghoul_assert(index < _items.size(), "Invalid index"); + return *_items[index]; +} + +void Dashboard::removeDashboardItems() { + for (const std::unique_ptr& item : _items) { + removePropertySubOwner(item.get()); + } + _items.clear(); +} + +void Dashboard::render(glm::vec2& penPosition) { + for (const std::unique_ptr& item : _items) { + if (item->isEnabled()) { + item->render(penPosition); + } + } +} + +scripting::LuaLibrary Dashboard::luaLibrary() { + return { + "dashboard", + { + { + "addDashboardItem", + &luascriptfunctions::addDashboardItem, + "table", + "Adds a new dashboard item to the main dashboard." + }, + { + "removeDashboardItems", + &luascriptfunctions::removeDashboardItems, + "", + "Removes all dashboard items from the main dashboard." + } + } + }; +} + +} // namespace openspace diff --git a/src/rendering/dashboard_lua.inl b/src/rendering/dashboard_lua.inl new file mode 100644 index 0000000000..ea5ba1dcb8 --- /dev/null +++ b/src/rendering/dashboard_lua.inl @@ -0,0 +1,74 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include +#include +#include + +namespace openspace::luascriptfunctions { + +/** +* \ingroup LuaScripts +* addDashboardItem(table): +*/ +int addDashboardItem(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments != 1) { + return luaL_error(L, "Expected %i arguments, got %i", 1, nArguments); + } + + int type = lua_type(L, -1); + if (type == LUA_TTABLE) { + ghoul::Dictionary d; + try { + ghoul::lua::luaDictionaryFromState(L, d); + } + catch (const ghoul::lua::LuaFormatException& e) { + LERRORC("addDashboardItem", e.what()); + return 0; + } + + OsEng.dashboard().addDashboardItem(DashboardItem::createFromDictionary(d)); + return 0; + } + else { + return luaL_error(L, "Expected argument of type 'string' or 'table'"); + } +} + +/** +* \ingroup LuaScripts +* removeDashboardItems(): +*/ +int removeDashboardItems(lua_State* L) { + int nArguments = lua_gettop(L); + if (nArguments > 1) { + return luaL_error(L, "Expected %i or %i arguments, got %i", 0, 1, nArguments); + } + + OsEng.dashboard().removeDashboardItems(); + return 0; +} + +}// namespace openspace::luascriptfunctions diff --git a/src/rendering/dashboarditem.cpp b/src/rendering/dashboarditem.cpp new file mode 100644 index 0000000000..dd4275312d --- /dev/null +++ b/src/rendering/dashboarditem.cpp @@ -0,0 +1,65 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014-2017 * + * * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this * + * software and associated documentation files (the "Software"), to deal in the Software * + * without restriction, including without limitation the rights to use, copy, modify, * + * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * + * permit persons to whom the Software is furnished to do so, subject to the following * + * conditions: * + * * + * The above copyright notice and this permission notice shall be included in all copies * + * or substantial portions of the Software. * + * * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * + * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * + * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * + ****************************************************************************************/ + +#include + +#include + +#include + +namespace { + const char* KeyType = "Type"; + + static const openspace::properties::Property::PropertyInfo EnabledInfo = { + "Enabled", + "Is Enabled", + "If this value is set to 'true' this dashboard item is shown in the dashboard" + }; +} // namespace + +namespace openspace { + +std::unique_ptr DashboardItem::createFromDictionary( + ghoul::Dictionary dictionary) +{ + auto factory = FactoryManager::ref().factory(); + ghoul_assert(factory, "DashboardItem factory did not exist"); + + std::string dashboardType = dictionary.value(KeyType); + + return factory->create(dashboardType, dictionary); +} + +DashboardItem::DashboardItem(std::string name) + : properties::PropertyOwner({ std::move(name) }) + , _isEnabled(EnabledInfo, true) +{ + addProperty(_isEnabled); +} + +bool DashboardItem::isEnabled() const { + return _isEnabled; +} + +} // namespace openspace diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index 657d451b09..417d297bf5 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -24,9 +24,6 @@ #include -#ifdef OPENSPACE_MODULE_SPACECRAFTINSTRUMENTS_ENABLED -#include -#endif #include #include @@ -37,7 +34,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -46,12 +46,9 @@ #include #include #include -#include #include -#include #include #include -#include #include #include @@ -100,12 +97,6 @@ namespace { "performance." }; - static const openspace::properties::Property::PropertyInfo FrametimeInfo = { - "FrametimeType", - "Type of the frame time display", - "This value determines the units in which the frame time is displayed." - }; - static const openspace::properties::Property::PropertyInfo ShowDateInfo = { "ShowDate", "Show Date Information", @@ -211,9 +202,6 @@ RenderEngine::RenderEngine() , _renderer(nullptr) , _rendererImplementation(RendererImplementation::Invalid) , _log(nullptr) - , _frametimeType(FrametimeInfo, properties::OptionProperty::DisplayType::Dropdown) - , _showDate(ShowDateInfo, true) - , _showInfo(ShowInfoInfo, true) , _showLog(ShowLogInfo, true) , _showVersionInfo(ShowVersionInfo, true) , _showCameraInfo(ShowCameraInfo, true) @@ -261,16 +249,6 @@ RenderEngine::RenderEngine() }); addProperty(_doPerformanceMeasurements); - _frametimeType.addOptions({ - { static_cast(FrametimeType::DtTimeAvg), "Average Deltatime" }, - { static_cast(FrametimeType::FPS), "Frames per second" }, - { static_cast(FrametimeType::FPSAvg), "Average frames per second" }, - { static_cast(FrametimeType::None), "None" } - }); - addProperty(_frametimeType); - - addProperty(_showDate); - addProperty(_showInfo); addProperty(_showLog); addProperty(_showVersionInfo); addProperty(_showCameraInfo); @@ -554,7 +532,21 @@ void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMat // Print some useful information on the master viewport if (wrapper.isMaster() && wrapper.isSimpleRendering()) { - renderInformation(); + std::unique_ptr perf; + if (_performanceManager) { + perf = std::make_unique( + "Main Dashboard::render", + OsEng.renderEngine().performanceManager() + ); + } + glm::vec2 penPosition = glm::vec2( + 10.f, + fontResolution().y + ); + + penPosition.y -= OsEng.console().currentHeight(); + + OsEng.dashboard().render(penPosition); } if (_showFrameNumber) { @@ -939,421 +931,6 @@ RenderEngine::RendererImplementation RenderEngine::rendererFromString( } } -std::string RenderEngine::progressToStr(int size, double t) { - std::string progress = "|"; - int g = static_cast((t * (size - 1)) + 1); - g = std::max(g, 0); - for (int i = 0; i < g; i++) { - progress.append("-"); - } - progress.append(">"); - for (int i = 0; i < size - g; i++) { - progress.append(" "); - } - progress.append("|"); - return progress; -} - -void RenderEngine::renderInformation() { - using ghoul::fontrendering::RenderFont; - - glm::vec2 penPosition = glm::vec2( - 10.f, - fontResolution().y - ); - - // If the console is opened, move all text downwards - penPosition.y -= OsEng.console().currentHeight(); - - if (_showDate && _fontDate) { - penPosition.y -= _fontDate->height(); - RenderFontCr( - *_fontDate, - penPosition, - "Date: %s", - OsEng.timeManager().time().UTC().c_str() - ); - } - else { - penPosition.y -= _fontInfo->height(); - } - - if (_showInfo && _fontInfo) { - std::pair deltaTime = simplifyTime( - OsEng.timeManager().time().deltaTime() - ); - RenderFontCr( - *_fontInfo, - penPosition, - "Simulation increment: %.1f %s / second", - deltaTime.first, - deltaTime.second.c_str() - ); - - double distance = glm::length( - _camera->positionVec3() - - OsEng.navigationHandler().focusNode()->worldPosition() - ); - std::pair dist = simplifyDistance(distance); - RenderFontCr( - *_fontInfo, - penPosition, - "Distance from focus: %f %s", - dist.first, - dist.second.c_str() - ); - - FrametimeType frametimeType = FrametimeType(_frametimeType.value()); - switch (frametimeType) { - case FrametimeType::DtTimeAvg: - RenderFontCr( - *_fontInfo, - penPosition, - "Avg. Frametime: %.5f", - OsEng.windowWrapper().averageDeltaTime() - ); - break; - case FrametimeType::FPS: - RenderFontCr( - *_fontInfo, - penPosition, - "FPS: %3.2f", - 1.0 / OsEng.windowWrapper().deltaTime() - ); - break; - case FrametimeType::FPSAvg: - RenderFontCr( - *_fontInfo, - penPosition, - "Avg. FPS: %3.2f", - 1.0 / OsEng.windowWrapper().averageDeltaTime() - ); - break; - case FrametimeType::None: - break; - } - - ParallelConnection::Status status = OsEng.parallelConnection().status(); - size_t nConnections = OsEng.parallelConnection().nConnections(); - const std::string& hostName = OsEng.parallelConnection().hostName(); - - std::string connectionInfo = ""; - int nClients = static_cast(nConnections); - if (status == ParallelConnection::Status::Host) { - nClients--; - if (nClients == 1) { - connectionInfo = "Hosting session with 1 client"; - } else { - connectionInfo = - "Hosting session with " + std::to_string(nClients) + " clients"; - } - } else if (status == ParallelConnection::Status::ClientWithHost) { - nClients--; - connectionInfo = "Session hosted by '" + hostName + "'"; - } else if (status == ParallelConnection::Status::ClientWithoutHost) { - connectionInfo = "Host is disconnected"; - } - - if (status == ParallelConnection::Status::ClientWithHost || - status == ParallelConnection::Status::ClientWithoutHost) { - connectionInfo += "\n"; - if (nClients > 2) { - std::string c = std::to_string(nClients - 1); - connectionInfo += "You and " + c + " more clients are tuned in"; - } else if (nClients == 2) { - std::string c = std::to_string(nClients - 1); - connectionInfo += "You and " + c + " more client are tuned in"; - } else if (nClients == 1) { - connectionInfo += "You are the only client"; - } - } - - if (!connectionInfo.empty()) { - RenderFontCr( - *_fontInfo, - penPosition, - connectionInfo.c_str() - ); - } - - -#ifdef OPENSPACE_MODULE_SPACECRAFTINSTRUMENTS_ENABLED - bool hasNewHorizons = scene()->sceneGraphNode("NewHorizons"); - double currentTime = OsEng.timeManager().time().j2000Seconds(); - - //if (MissionManager::ref().hasCurrentMission()) { - - // const Mission& mission = MissionManager::ref().currentMission(); - - // if (mission.phases().size() > 0) { - // static const glm::vec4 nextMissionColor(0.7, 0.3, 0.3, 1); - // //static const glm::vec4 missionProgressColor(0.4, 1.0, 1.0, 1); - // static const glm::vec4 currentMissionColor(0.0, 0.5, 0.5, 1); - // static const glm::vec4 missionProgressColor = currentMissionColor; - // // static const glm::vec4 currentLeafMissionColor = missionProgressColor; - // static const glm::vec4 nonCurrentMissionColor(0.3, 0.3, 0.3, 1); - - // // Add spacing - // RenderFontCr(*_fontInfo, penPosition, nonCurrentMissionColor, " "); - - // auto phaseTrace = mission.phaseTrace(currentTime); - - // if (phaseTrace.size()) { - // const MissionPhase& phase = phaseTrace.back().get(); - // std::string title = "Current Mission Phase: " + phase.name(); - // RenderFontCr( - // *_fontInfo, - // penPosition, - // missionProgressColor, - // title.c_str() - // ); - // double remaining = phase.timeRange().end - currentTime; - // float t = static_cast( - // 1.0 - remaining / phase.timeRange().duration() - // ); - // std::string progress = progressToStr(25, t); - // //RenderFontCr(*_fontInfo, penPosition, missionProgressColor, - // // "%.0f s %s %.1f %%", remaining, progress.c_str(), t * 100); - // } - // else { - // RenderFontCr( - // *_fontInfo, - // penPosition, - // nextMissionColor, - // "Next Mission:" - // ); - // double remaining = mission.timeRange().start - currentTime; - // RenderFontCr(*_fontInfo, penPosition, nextMissionColor, - // "%.0f s", remaining); - // } - - // bool showAllPhases = false; - - // typedef std::pair PhaseWithDepth; - // std::stack S; - // int pixelIndentation = 20; - // S.push({ &mission, 0 }); - // while (!S.empty()) { - // const MissionPhase* phase = S.top().first; - // int depth = S.top().second; - // S.pop(); - - // bool isCurrentPhase = phase->timeRange().includes(currentTime); - - // penPosition.x += depth * pixelIndentation; - // if (isCurrentPhase) { - // double remaining = phase->timeRange().end - currentTime; - // float t = static_cast( - // 1.0 - remaining / phase->timeRange().duration() - // ); - // std::string progress = progressToStr(25, t); - // RenderFontCr(*_fontInfo, penPosition, currentMissionColor, - // "%s %s %.1f %%", - // phase->name().c_str(), - // progress.c_str(), - // t * 100 - // ); - // } - // else { - // RenderFontCr( - // *_fontInfo, - // penPosition, - // nonCurrentMissionColor, - // phase->name().c_str() - // ); - // } - // penPosition.x -= depth * pixelIndentation; - - // if (isCurrentPhase || showAllPhases) { - // // phases are sorted increasingly by start time, and will be - // // popped last-in-first-out from the stack, so add them in - // // reversed order. - // int indexLastPhase = static_cast( - // phase->phases().size() - // ) - 1; - // for (int i = indexLastPhase; 0 <= i; --i) { - // S.push({ &phase->phases()[i], depth + 1 }); - // } - // } - // } - // } - // } - - - - if (openspace::ImageSequencer::ref().isReady()) { - penPosition.y -= 25.f; - - glm::vec4 targetColor(0.00, 0.75, 1.00, 1); - - if (hasNewHorizons) { - try { - double lt; - glm::dvec3 p = SpiceManager::ref().targetPosition( - "PLUTO", - "NEW HORIZONS", - "GALACTIC", - {}, - currentTime, - lt - ); - psc nhPos = PowerScaledCoordinate::CreatePowerScaledCoordinate( - p.x, - p.y, - p.z - ); - float a, b; - glm::dvec3 radii; - SpiceManager::ref().getValue("PLUTO", "RADII", radii); - a = static_cast(radii.x); - b = static_cast(radii.y); - float radius = (a + b) / 2.f; - float distToSurf = glm::length(nhPos.vec3()) - radius; - - RenderFont(*_fontInfo, - penPosition, - "Distance to Pluto: % .1f (KM)", - distToSurf - ); - penPosition.y -= _fontInfo->height(); - } - catch (...) { - // @CLEANUP: This is bad as it will discard all exceptions - // without telling us about it! ---abock - } - } - - double remaining = openspace::ImageSequencer::ref().getNextCaptureTime() - - currentTime; - float t = static_cast( - 1.0 - remaining / openspace::ImageSequencer::ref().getIntervalLength() - ); - - std::string str = SpiceManager::ref().dateFromEphemerisTime( - ImageSequencer::ref().getNextCaptureTime(), - "YYYY MON DD HR:MN:SC" - ); - - glm::vec4 active(0.6, 1, 0.00, 1); - glm::vec4 brigther_active(0.9, 1, 0.75, 1); - - if (remaining > 0) { - std::string progress = progressToStr(25, t); - brigther_active *= (1 - t); - - RenderFontCr(*_fontInfo, - penPosition, - active * t + brigther_active, - "Next instrument activity:" - ); - - RenderFontCr(*_fontInfo, - penPosition, - active * t + brigther_active, - "%.0f s %s %.1f %%", - remaining, progress.c_str(), t * 100 - ); - - RenderFontCr(*_fontInfo, - penPosition, - active, - "Data acquisition time: %s", - str.c_str() - ); - } - std::pair nextTarget = - ImageSequencer::ref().getNextTarget(); - std::pair currentTarget = - ImageSequencer::ref().getCurrentTarget(); - - if (currentTarget.first > 0.0) { - int timeleft = static_cast(nextTarget.first - currentTime); - - int hour = timeleft / 3600; - int second = timeleft % 3600; - int minute = second / 60; - second = second % 60; - - std::string hh, mm, ss; - - if (hour < 10) - hh.append("0"); - if (minute < 10) - mm.append("0"); - if (second < 10) - ss.append("0"); - - hh.append(std::to_string(hour)); - mm.append(std::to_string(minute)); - ss.append(std::to_string(second)); - - RenderFontCr(*_fontInfo, - penPosition, - targetColor, - "Data acquisition adjacency: [%s:%s:%s]", - hh.c_str(), mm.c_str(), ss.c_str() - ); - - penPosition.y -= _fontInfo->height(); - - std::map activeMap = - ImageSequencer::ref().getActiveInstruments(); - glm::vec4 firing(0.58 - t, 1 - t, 1 - t, 1); - glm::vec4 notFiring(0.5, 0.5, 0.5, 1); - - RenderFontCr(*_fontInfo, - penPosition, - active, - "Active Instruments:" - ); - - for (auto m : activeMap) { - if (m.second == false) { - RenderFont(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - "| |" - ); - RenderFontCr(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - " %5s", - m.first.c_str() - ); - - } - else { - RenderFont(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - "|" - ); - if (m.first == "NH_LORRI") { - RenderFont(*_fontInfo, - penPosition, - firing, - " + " - ); - } - RenderFont(*_fontInfo, - penPosition, - glm::vec4(0.3, 0.3, 0.3, 1), - " |" - ); - RenderFontCr(*_fontInfo, - penPosition, - active, - " %5s", - m.first.c_str() - ); - } - } - } - } -#endif - } -} - void RenderEngine::renderCameraInformation() { if (!_showCameraInfo) { return; diff --git a/src/rendering/renderengine_lua.inl b/src/rendering/renderengine_lua.inl index cdd14c5247..54b090e354 100644 --- a/src/rendering/renderengine_lua.inl +++ b/src/rendering/renderengine_lua.inl @@ -119,7 +119,7 @@ int addScreenSpaceRenderable(lua_State* L) { ); OsEng.renderEngine().addScreenSpaceRenderable(s); - return 1; + return 0; } int removeScreenSpaceRenderable(lua_State* L) { @@ -145,7 +145,7 @@ int removeScreenSpaceRenderable(lua_State* L) { OsEng.renderEngine().removeScreenSpaceRenderable(s); - return 1; + return 0; } }// namespace openspace::luascriptfunctions diff --git a/src/rendering/screenspacerenderable.cpp b/src/rendering/screenspacerenderable.cpp index ec240858d5..47abbf74ac 100644 --- a/src/rendering/screenspacerenderable.cpp +++ b/src/rendering/screenspacerenderable.cpp @@ -238,7 +238,6 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary addProperty(_depth); addProperty(_scale); addProperty(_alpha); - addProperty(_delete); if (dictionary.hasKey(EnabledInfo.identifier)) { _enabled = dictionary.value(EnabledInfo.identifier); @@ -298,9 +297,10 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary "openspace.removeScreenSpaceRenderable('" + name() + "');"; OsEng.scriptEngine().queueScript( script, - scripting::ScriptEngine::RemoteScripting::Yes + scripting::ScriptEngine::RemoteScripting::No ); }); + addProperty(_delete); } bool ScreenSpaceRenderable::initialize() { @@ -506,6 +506,7 @@ void ScreenSpaceRenderable::draw(glm::mat4 modelTransform) { _shader->setUniform("OcclusionDepth", 1.f - _depth); _shader->setUniform("Alpha", _alpha); _shader->setUniform("ModelTransform", modelTransform); + _shader->setUniform( "ViewProjectionMatrix", OsEng.renderEngine().camera()->viewProjectionMatrix() diff --git a/src/util/distanceconversion.cpp b/src/util/distanceconversion.cpp index 2484517e7f..d73fbdfad8 100644 --- a/src/util/distanceconversion.cpp +++ b/src/util/distanceconversion.cpp @@ -26,48 +26,63 @@ #include +#include + namespace openspace { std::pair simplifyDistance(double meters) { - if (meters > 1e-3 && meters < 1e3) { - return { meters, "meter" }; + double metersVal = glm::abs(meters); + + if (metersVal == 0.0) { + return { 0.0, "meters"}; + } + else if (metersVal > 1e-3 && metersVal < 1e3) { + return { meters, meters == 1.0 ? "meter" : "meters" }; } - if (meters < 1e-9) { - return { meters / 1e-9, "nanometer" }; + if (metersVal < 1e-9) { + return { meters / 1e-9, (meters / 1e-9) == 1.0 ? "nanometer" : "nanometers" }; } - else if (meters < 1e-6) { - return { meters / 1e-6, "micrometer" }; + else if (metersVal < 1e-6) { + return { meters / 1e-6, (meters / 1e-6) == 1.0 ? "micrometer" : "micrometers" }; } - else if (meters < 1e-3) { - return { meters / 1e-3, "millimeter" }; + else if (metersVal < 1e-3) { + return { meters / 1e-3, (meters / 1e-3) == 1.0 ? "millimeter" : "millimeters" }; } - if (meters > (1e9 * distanceconstants::Parsec)) { - return { meters / (1e9 * distanceconstants::Parsec) , "Gigaparsec" }; + if (metersVal > (1e9 * distanceconstants::Parsec)) { + double val = meters / (1e9 * distanceconstants::Parsec); + return { val, val == 1.0 ? "Gigaparsec" : "Gigaparsecs" }; } - else if (meters > (1e6 * distanceconstants::Parsec)) { - return { meters / (1e6 * distanceconstants::Parsec), "Megaparsec" }; + else if (metersVal > (1e6 * distanceconstants::Parsec)) { + double val = meters / (1e6 * distanceconstants::Parsec); + return { val, val == 1.0 ? "Megaparsec" : "Megaparsecs" }; } - else if (meters > (1e3 * distanceconstants::Parsec)) { - return { meters / (1e3 * distanceconstants::Parsec), "Kiloparsec" }; + else if (metersVal > (1e3 * distanceconstants::Parsec)) { + double val = meters / (1e3 * distanceconstants::Parsec); + return { val, val == 1.0 ? "Kiloparsec" : "Kiloparsecs" }; } - else if (meters > distanceconstants::Parsec) { - return { meters / distanceconstants::Parsec, "Parsec" }; + else if (metersVal > distanceconstants::Parsec) { + double val = meters / distanceconstants::Parsec; + return { val, val == 1.0 ? "Parsec" : "Parsecs" }; } - else if (meters > distanceconstants::LightYear) { - return { meters / distanceconstants::LightYear, "Lightyears" }; + else if (metersVal > distanceconstants::LightYear) { + double val = meters / distanceconstants::LightYear; + return { val, val == 1.0 ? "Lightyear" : "Lightyears" }; } - else if (meters > distanceconstants::LightMonth) { - return { meters / distanceconstants::LightMonth, "Lightmonth" }; + else if (metersVal > distanceconstants::LightMonth) { + double val = meters / distanceconstants::LightMonth; + return { val, val == 1.0 ? "Lightmonth" : "Lightmonths" }; } - else if (meters > distanceconstants::LightDay) { - return { meters / distanceconstants::LightDay, "Lightday" }; + else if (metersVal > distanceconstants::LightDay) { + double val = meters / distanceconstants::LightDay; + return { val, val == 1.0 ? "Lightday" : "Lightdays" }; } - else if (meters > distanceconstants::LightHour) { - return { meters / distanceconstants::LightDay, "Lighthour" }; + else if (metersVal > distanceconstants::LightHour) { + double val = meters / distanceconstants::LightDay; + return { val, val == 1.0 ? "Lighthour" : "Lighthours" }; } - else if (meters > distanceconstants::AstronomicalUnit) { + else if (metersVal > distanceconstants::AstronomicalUnit) { return { meters / distanceconstants::AstronomicalUnit, "AU" }; } else { diff --git a/src/util/openspacemodule.cpp b/src/util/openspacemodule.cpp index 3a0694d68f..b3f3a0137b 100644 --- a/src/util/openspacemodule.cpp +++ b/src/util/openspacemodule.cpp @@ -78,6 +78,10 @@ scripting::LuaLibrary OpenSpaceModule::luaLibrary() const { return {}; } +std::vector OpenSpaceModule::luaLibraries() const { + return {}; +} + ghoul::systemcapabilities::Version OpenSpaceModule::requiredOpenGLVersion() const { return { 3, 3, 0 }; }