diff --git a/apps/TaskRunner/main.cpp b/apps/TaskRunner/main.cpp index 979da435a8..6fcc1b18ee 100644 --- a/apps/TaskRunner/main.cpp +++ b/apps/TaskRunner/main.cpp @@ -55,6 +55,9 @@ #include #include #include +#ifdef WIN32 +#include +#endif // WIN32 namespace { const std::string ConfigurationFile = "openspace.cfg"; @@ -127,8 +130,21 @@ int main(int argc, char** argv) { constexpr const char* BasePathToken = "${BASE}"; FileSys.registerPathToken(BasePathToken, base); + // Using same configuration for size as in apps/OpenSpace/main.cpp + glm::ivec2 size = glm::ivec2(1920, 1080); +#ifdef WIN32 + DEVMODEW dm = { 0 }; + dm.dmSize = sizeof(DEVMODEW); + BOOL success = EnumDisplaySettingsW(nullptr, ENUM_CURRENT_SETTINGS, &dm); + if (success) { + size.x = dm.dmPelsWidth; + size.y = dm.dmPelsHeight; + } +#endif // WIN32 + *global::configuration = configuration::loadConfigurationFromFile( configFile.string(), + size, "" ); openspace::global::openSpaceEngine->registerPathTokens(); diff --git a/data/assets/scene/solarsystem/planets/uranus/inner_moons.asset b/data/assets/scene/solarsystem/planets/uranus/inner_moons.asset index cfbc96be7f..445962443e 100644 --- a/data/assets/scene/solarsystem/planets/uranus/inner_moons.asset +++ b/data/assets/scene/solarsystem/planets/uranus/inner_moons.asset @@ -59,7 +59,7 @@ local innerMoons = { Spice = parentSpice }, Spice = "BIANCA", - Radii = { 51000, 51000, 51000 }, + Radii = { 64000, 46000, 46000 }, Tags = tags, TrailTags = trailTags, GUI = { diff --git a/include/openspace/navigation/orbitalnavigator.h b/include/openspace/navigation/orbitalnavigator.h index 01150b1d4c..11333623c4 100644 --- a/include/openspace/navigation/orbitalnavigator.h +++ b/include/openspace/navigation/orbitalnavigator.h @@ -57,6 +57,26 @@ class KeyboardInputState; class OrbitalNavigator : public properties::PropertyOwner { public: + struct IdleBehavior : public properties::PropertyOwner { + enum class Behavior { + Orbit = 0, + OrbitAtConstantLat, + OrbitAroundUp + }; + + IdleBehavior(); + + properties::BoolProperty apply; + properties::BoolProperty shouldTriggerWhenIdle; + properties::FloatProperty idleWaitTime; + properties::BoolProperty abortOnCameraInteraction; + properties::FloatProperty speedScale; + properties::FloatProperty dampenInterpolationTime; + + properties::OptionProperty defaultBehavior; + std::optional chosenBehavior = std::nullopt; + }; + OrbitalNavigator(); void updateStatesFromInput(const MouseInputState& mouseInputState, @@ -72,6 +92,9 @@ public: */ void updateOnCameraInteraction(); + void tickIdleBehaviorTimer(double deltaTime); + void triggerIdleBehavior(std::string_view choice = ""); + Camera* camera() const; void setCamera(Camera* camera); void clearPreviousState(); @@ -191,22 +214,8 @@ private: Interpolator _idleBehaviorDampenInterpolator; bool _invertIdleBehaviorInterpolation = false; - struct IdleBehavior : public properties::PropertyOwner { - enum Behavior { - Orbit = 0, - OrbitAtConstantLat, - OrbitAroundUp - }; - - IdleBehavior(); - - properties::BoolProperty apply; - properties::OptionProperty chosenBehavior; - properties::FloatProperty speedScale; - properties::BoolProperty abortOnCameraInteraction; - properties::FloatProperty dampenInterpolationTime; - }; IdleBehavior _idleBehavior; + float _idleBehaviorTriggerTimer = 0.f; /** * Decomposes the camera's rotation in to a global and a local rotation defined by @@ -344,6 +353,8 @@ private: SurfacePositionHandle calculateSurfacePositionHandle(const SceneGraphNode& node, const glm::dvec3 cameraPositionWorldSpace); + void resetIdleBehavior(); + /** * Apply the currently selected idle behavior to the position and rotations */ diff --git a/src/navigation/navigationhandler.cpp b/src/navigation/navigationhandler.cpp index 39aa4bbf65..98c2114fb1 100644 --- a/src/navigation/navigationhandler.cpp +++ b/src/navigation/navigationhandler.cpp @@ -737,6 +737,13 @@ scripting::LuaLibrary NavigationHandler::luaLibrary() { &luascriptfunctions::addGlobalRoll, "double, double", "Directly adds to the global roll of the camera" + }, + { + "triggerIdleBehavior", + &luascriptfunctions::triggerIdleBehavior, + "[string]", + "Immediately start applying the chosen IdleBehavior. If none is " + "specified, use the one set to default in the OrbitalNavigator." } } }; diff --git a/src/navigation/navigationhandler_lua.inl b/src/navigation/navigationhandler_lua.inl index 9ffad40a02..afc2f3e6fc 100644 --- a/src/navigation/navigationhandler_lua.inl +++ b/src/navigation/navigationhandler_lua.inl @@ -343,4 +343,20 @@ int addGlobalRoll(lua_State* L) { return 0; } +int triggerIdleBehavior(lua_State* L) { + ghoul::lua::checkArgumentsAndThrow(L, {0, 1}, "lua::triggerIdleBehavior"); + std::optional choice = ghoul::lua::value>(L); + + try { + global::navigationHandler->orbitalNavigator().triggerIdleBehavior( + choice.value_or("") + ); + } + catch (ghoul::RuntimeError& e) { + return ghoul::lua::luaError(L, e.message); + } + + return 0; +} + } // namespace openspace::luascriptfunctions diff --git a/src/navigation/orbitalnavigator.cpp b/src/navigation/orbitalnavigator.cpp index 16a1f06bda..d47cc89159 100644 --- a/src/navigation/orbitalnavigator.cpp +++ b/src/navigation/orbitalnavigator.cpp @@ -23,6 +23,7 @@ ****************************************************************************************/ #include +#include #include #include #include @@ -159,26 +160,29 @@ namespace { }; constexpr openspace::properties::Property::PropertyInfo - StereoInterpolationTimeInfo = { - "StereoInterpolationTime", - "Stereo Interpolation Time", - "The time to interpolate to a new stereoscopic depth " - "when the anchor node is changed, in seconds." + StereoInterpolationTimeInfo = + { + "StereoInterpolationTime", + "Stereo Interpolation Time", + "The time to interpolate to a new stereoscopic depth " + "when the anchor node is changed, in seconds." }; constexpr openspace::properties::Property::PropertyInfo - RetargetInterpolationTimeInfo = { - "RetargetAnchorInterpolationTime", - "Retarget Interpolation Time", - "The time to interpolate the camera rotation " - "when the anchor or aim node is changed, in seconds." + RetargetInterpolationTimeInfo = + { + "RetargetAnchorInterpolationTime", + "Retarget Interpolation Time", + "The time to interpolate the camera rotation " + "when the anchor or aim node is changed, in seconds." }; constexpr openspace::properties::Property::PropertyInfo - FollowRotationInterpTimeInfo = { - "FollowRotationInterpolationTime", - "Follow Rotation Interpolation Time", - "The interpolation time when toggling following focus node rotation." + FollowRotationInterpTimeInfo = + { + "FollowRotationInterpolationTime", + "Follow Rotation Interpolation Time", + "The interpolation time when toggling following focus node rotation." }; constexpr openspace::properties::Property::PropertyInfo InvertMouseButtons = { @@ -190,31 +194,34 @@ namespace { }; constexpr openspace::properties::Property::PropertyInfo - UseAdaptiveStereoscopicDepthInfo = { - "UseAdaptiveStereoscopicDepth", - "Adaptive Steroscopic Depth", - "Dynamically adjust the view scaling based on the distance to the surface of " - "the anchor and aim nodes. If enabled, view scale will be set to " - "StereoscopicDepthOfFocusSurface / min(anchorDistance, aimDistance). " - "If disabled, view scale will be set to 10^StaticViewScaleExponent." - }; + UseAdaptiveStereoscopicDepthInfo = + { + "UseAdaptiveStereoscopicDepth", + "Adaptive Steroscopic Depth", + "Dynamically adjust the view scaling based on the distance to the surface of " + "the anchor and aim nodes. If enabled, view scale will be set to " + "StereoscopicDepthOfFocusSurface / min(anchorDistance, aimDistance). " + "If disabled, view scale will be set to 10^StaticViewScaleExponent." + }; constexpr openspace::properties::Property::PropertyInfo - StaticViewScaleExponentInfo = { - "StaticViewScaleExponent", - "Static View Scale Exponent", - "Statically scale the world by 10^StaticViewScaleExponent. " - "Only used if UseAdaptiveStereoscopicDepthInfo is set to false." - }; + StaticViewScaleExponentInfo = + { + "StaticViewScaleExponent", + "Static View Scale Exponent", + "Statically scale the world by 10^StaticViewScaleExponent. " + "Only used if UseAdaptiveStereoscopicDepthInfo is set to false." + }; constexpr openspace::properties::Property::PropertyInfo - StereoscopicDepthOfFocusSurfaceInfo = { - "StereoscopicDepthOfFocusSurface", - "Stereoscopic Depth of the Surface in Focus", - "Set the stereoscopically perceived distance (in meters) to the closest " - "point out of the surface of the anchor and the center of the aim node. " - "Only used if UseAdaptiveStereoscopicDepthInfo is set to true." - }; + StereoscopicDepthOfFocusSurfaceInfo = + { + "StereoscopicDepthOfFocusSurface", + "Stereoscopic Depth of the Surface in Focus", + "Set the stereoscopically perceived distance (in meters) to the closest " + "point out of the surface of the anchor and the center of the aim node. " + "Only used if UseAdaptiveStereoscopicDepthInfo is set to true." + }; constexpr openspace::properties::Property::PropertyInfo ApplyIdleBehaviorInfo = { "ApplyIdleBehavior", @@ -230,6 +237,22 @@ namespace { "applied. Each option represents a predefined camera behavior." }; + constexpr openspace::properties::Property::PropertyInfo + ShouldTriggerIdleBehaviorWhenIdleInfo = + { + "ShouldTriggerWhenIdle", + "Should Trigger When Idle", + "If true, the chosen idle behavior will trigger automatically after " + "a certain time (see 'IdleWaitTime' property)." + }; + + constexpr openspace::properties::Property::PropertyInfo IdleWaitTimeInfo = { + "IdleWaitTime", + "Idle Wait Time", + "The time (seconds) until idle behavior starts, if no camera interaction " + "has been performed. Note that friction counts as camera interaction." + }; + constexpr openspace::properties::Property::PropertyInfo IdleBehaviorSpeedInfo = { "SpeedFactor", "Speed Factor", @@ -238,7 +261,8 @@ namespace { }; constexpr openspace::properties::Property::PropertyInfo - AbortOnCameraInteractionInfo = { + AbortOnCameraInteractionInfo = + { "AbortOnCameraInteraction", "Abort on Camera Interaction", "If set to true, the idle behavior is aborted on camera interaction. If false, " @@ -248,12 +272,18 @@ namespace { }; constexpr openspace::properties::Property::PropertyInfo - IdleBehaviorDampenInterpolationTimeInfo = { + IdleBehaviorDampenInterpolationTimeInfo = + { "DampenInterpolationTime", "Start/End Dampen Interpolation Time", "The time to interpolate to/from full speed when an idle behavior is triggered " "or canceled, in seconds." }; + + constexpr const char IdleKeyOrbit[] = "Orbit"; + constexpr const char IdleKeyOrbitAtConstantLat[] = "OrbitAtConstantLatitude"; + constexpr const char IdleKeyOrbitAroundUp[] = "OrbitAroundUp"; + } // namespace namespace openspace::interaction { @@ -274,19 +304,25 @@ OrbitalNavigator::Friction::Friction() OrbitalNavigator::IdleBehavior::IdleBehavior() : properties::PropertyOwner({ "IdleBehavior" }) , apply(ApplyIdleBehaviorInfo, false) - , chosenBehavior(IdleBehaviorInfo) + , defaultBehavior(IdleBehaviorInfo) + , shouldTriggerWhenIdle(ShouldTriggerIdleBehaviorWhenIdleInfo, false) + , idleWaitTime(IdleWaitTimeInfo, 5.f, 0.f, 3600.f) , speedScale(IdleBehaviorSpeedInfo, 1.f, 0.01f, 5.f) , abortOnCameraInteraction(AbortOnCameraInteractionInfo, true) , dampenInterpolationTime(IdleBehaviorDampenInterpolationTimeInfo, 0.5f, 0.f, 10.f) { addProperty(apply); - chosenBehavior.addOptions({ - { IdleBehavior::Behavior::Orbit, "Orbit" }, - { IdleBehavior::Behavior::OrbitAtConstantLat, "OrbitAtConstantLatitude" }, - { IdleBehavior::Behavior::OrbitAroundUp, "OrbitAroundUp" } + using Behavior = IdleBehavior::Behavior; + defaultBehavior.addOptions({ + { static_cast(Behavior::Orbit), IdleKeyOrbit }, + { static_cast(Behavior::OrbitAtConstantLat), IdleKeyOrbitAtConstantLat }, + { static_cast(Behavior::OrbitAroundUp), IdleKeyOrbitAroundUp } }); - chosenBehavior = IdleBehavior::Behavior::Orbit; - addProperty(chosenBehavior); + defaultBehavior = static_cast(IdleBehavior::Behavior::Orbit); + addProperty(defaultBehavior); + addProperty(shouldTriggerWhenIdle); + addProperty(idleWaitTime); + idleWaitTime.setExponent(2.2f); addProperty(speedScale); addProperty(abortOnCameraInteraction); addProperty(dampenInterpolationTime); @@ -454,6 +490,13 @@ OrbitalNavigator::OrbitalNavigator() _idleBehavior.dampenInterpolationTime ); }); + _idleBehavior.shouldTriggerWhenIdle.onChange([&]() { + _idleBehaviorTriggerTimer = _idleBehavior.idleWaitTime; + }); + _idleBehavior.idleWaitTime.onChange([&]() { + _idleBehaviorTriggerTimer = _idleBehavior.idleWaitTime; + }); + addProperty(_anchor); addProperty(_aim); addProperty(_retargetAnchor); @@ -530,6 +573,9 @@ void OrbitalNavigator::updateStatesFromInput(const MouseInputState& mouseInputSt if (interactionHappened) { updateOnCameraInteraction(); } + else { + tickIdleBehaviorTimer(deltaTime); + } } void OrbitalNavigator::updateCameraStateFromStates(double deltaTime) { @@ -699,7 +745,8 @@ void OrbitalNavigator::updateCameraScalingFromAnchor(double deltaTime) { _currentCameraToSurfaceDistance = interpolateCameraToSurfaceDistance( deltaTime, _currentCameraToSurfaceDistance, - targetCameraToSurfaceDistance); + targetCameraToSurfaceDistance + ); } _camera->setScaling( @@ -715,9 +762,19 @@ void OrbitalNavigator::updateCameraScalingFromAnchor(double deltaTime) { void OrbitalNavigator::updateOnCameraInteraction() { // Disable idle behavior if camera interaction happened if (_idleBehavior.apply && _idleBehavior.abortOnCameraInteraction) { - _idleBehavior.apply = false; - // Prevent interpolating stop, to avoid weirdness when changing anchor, etc - _idleBehaviorDampenInterpolator.setInterpolationTime(0.f); + resetIdleBehavior(); + } +} + +void OrbitalNavigator::tickIdleBehaviorTimer(double deltaTime) { + if (!_idleBehavior.shouldTriggerWhenIdle) { + return; + } + if (_idleBehaviorTriggerTimer > 0.f) { + _idleBehaviorTriggerTimer -= static_cast(deltaTime); + } + else { + triggerIdleBehavior(); } } @@ -1502,6 +1559,49 @@ const ScriptCameraStates& OrbitalNavigator::scriptStates() const { return _scriptStates; } +void OrbitalNavigator::triggerIdleBehavior(std::string_view choice) { + OpenSpaceEngine::Mode mode = global::openSpaceEngine->currentMode(); + if (mode != OpenSpaceEngine::Mode::UserControl) { + LERROR( + "Could not start idle behavior. The camera is being controlled " + "by some other part of the system" + ); + return; + } + + if (choice.empty()) { + _idleBehavior.chosenBehavior = std::nullopt; + } + else { + IdleBehavior::Behavior behavior; + if (choice == IdleKeyOrbit) { + behavior = IdleBehavior::Behavior::Orbit; + } + else if (choice == IdleKeyOrbitAtConstantLat) { + behavior = IdleBehavior::Behavior::OrbitAtConstantLat; + } + else if (choice == IdleKeyOrbitAroundUp) { + behavior = IdleBehavior::Behavior::OrbitAroundUp; + } + else { + throw ghoul::RuntimeError( + fmt::format("No existing IdleBehavior with identifier '{}'", choice) + ); + } + _idleBehavior.chosenBehavior = behavior; + } + + _idleBehavior.apply = true; +} + +void OrbitalNavigator::resetIdleBehavior() { + _idleBehavior.apply = false; + _idleBehavior.chosenBehavior = std::nullopt; + // Prevent interpolating stop, to avoid weirdness when changing anchor, etc + _idleBehaviorDampenInterpolator.setInterpolationTime(0.f); + _idleBehaviorTriggerTimer = _idleBehavior.idleWaitTime; +} + void OrbitalNavigator::applyIdleBehavior(double deltaTime, glm::dvec3& position, glm::dquat& localRotation, glm::dquat& globalRotation) @@ -1541,10 +1641,11 @@ void OrbitalNavigator::applyIdleBehavior(double deltaTime, glm::dvec3& position, speedScale *= _invertIdleBehaviorInterpolation ? (1.0 - s) : s; // Apply the chosen behavior - const IdleBehavior::Behavior chosen = - static_cast(_idleBehavior.chosenBehavior.value()); + const IdleBehavior::Behavior choice = _idleBehavior.chosenBehavior.value_or( + static_cast(_idleBehavior.defaultBehavior.value()) + ); - switch (chosen) { + switch (choice) { case IdleBehavior::Behavior::Orbit: orbitAnchor(deltaTime, position, globalRotation, speedScale); break;