Skip to content
Snippets Groups Projects
Select Git revision
  • c7b7fb5d0270db08e9efd439f27f87c71e9c53c6
  • master default protected
2 results

index.vue

Blame
  • test_vr_controller.cpp 6.39 KiB
    //------------------------------------------------------------------------------
    // Project Phoenix
    //
    // Copyright (c) 2017-2018 RWTH Aachen University, Germany,
    // Virtual Reality & Immersive Visualization Group.
    //------------------------------------------------------------------------------
    //                                 License
    //
    // Licensed under the 3-Clause BSD License (the "License");
    // you may not use this file except in compliance with the License.
    // See the file LICENSE for the full text.
    // You may obtain a copy of the License at
    //
    //     https://opensource.org/licenses/BSD-3-Clause
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    //------------------------------------------------------------------------------
    
    #include <memory>
    #include <string>
    
    #include "catch/catch.hpp"
    
    #include "phx/core/logger.hpp"
    #include "phx/input/vr_controller.hpp"
    
    #include "mocks/openvr_mock.hpp"
    
    #include "test_utilities/glm_vec.hpp"
    #include "test_utilities/log_capture.hpp"
    
    #include "trompeloeil.hpp"
    
    extern template struct trompeloeil::reporter<trompeloeil::specialized>;
    using trompeloeil::_;
    
    namespace {
    
    auto first_call = std::make_shared<bool>(true);
    
    void CheckForButtonEvent(uint32_t openVR_event_type,
                             phx::VRController::ButtonEvent vr_cont_event,
                             uint32_t button_id, const std::string& side,
                             bool expect_to_fire,
                             phx::VRController* vr_controller) {
      WHEN("a " + side +
           " openVR event (type: " + std::to_string(openVR_event_type) +
           " button id: " + std::to_string(button_id) + " is fired") {
        vr::VREvent_t event;
        event.eventType = openVR_event_type;
        event.data.controller.button = button_id;
        event.trackedDeviceIndex =
            (side == "left" ? 2    // in the mock 2 is given to the left controller
                            : 1);  // in the mock 1 is given to the right controller
        *first_call = true;
        ALLOW_CALL(openvr_mock.GetSystem(), PollNextEvent(_, _))
            .SIDE_EFFECT(*_1 = event)
            .SIDE_EFFECT(*first_call = false)
            .WITH(*first_call == true)
            .RETURN(true);
        ALLOW_CALL(openvr_mock.GetSystem(), PollNextEvent(_, _))
            .WITH(*first_call == false)
            .RETURN(false);
        THEN("we expect the signal to " + (expect_to_fire ? "" : "not") + " fire") {
          bool signal_fired = false;
          vr_controller->RegisterButtonSignal(
              [&signal_fired, vr_cont_event, button_id](
                  phx::VRController::ButtonId id,
                  phx::VRController::ButtonEvent input_event) {
                if (input_event == vr_cont_event &&
                    id == static_cast<phx::VRController::ButtonId>(button_id))
                  signal_fired = true;
              });
          vr_controller->Update();
          REQUIRE(signal_fired == expect_to_fire);
        }
      }
    }
    }  // namespace
    
    SCENARIO("Button click events of openVR get forwarded as signals",
             "[phx][phx::VRController]") {
      OPENVR_MOCK_ALLOW_ANY_CALL
      GIVEN("a VRController") {
        auto vr_controller =
            std::make_unique<phx::VRController>(phx::VRController::LEFT_CONTROLLER);
        THEN("all button events are mapped correctly") {
          CheckForButtonEvent(vr::VREvent_ButtonPress,
                              phx::VRController::BUTTON_PRESSED, vr::k_EButton_Grip,
                              "left", true, vr_controller.get());
          CheckForButtonEvent(
              vr::VREvent_ButtonUnpress, phx::VRController::BUTTON_RELEASED,
              vr::k_EButton_Grip, "left", true, vr_controller.get());
          CheckForButtonEvent(vr::VREvent_ButtonTouch,
                              phx::VRController::BUTTON_TOUCH, vr::k_EButton_Grip,
                              "left", true, vr_controller.get());
          CheckForButtonEvent(vr::VREvent_ButtonUntouch,
                              phx::VRController::BUTTON_UNTOUCH, vr::k_EButton_Grip,
                              "left", true, vr_controller.get());
        }
        THEN("wrong sided events are ignored") {
          CheckForButtonEvent(vr::VREvent_ButtonPress,
                              phx::VRController::BUTTON_PRESSED, vr::k_EButton_Grip,
                              "right", false, vr_controller.get());
        }
    
        THEN(
            "events on other buttons are ignored, respectively the correct button "
            "id is forwarded") {
          CheckForButtonEvent(
              vr::VREvent_ButtonPress, phx::VRController::BUTTON_PRESSED,
              vr::k_EButton_SteamVR_Trigger, "right", false, vr_controller.get());
        }
      }
    }
    
    SCENARIO("we can get the actual position on the analog axes, like the trackpad",
             "[phx][phx::VRController]") {
      OPENVR_MOCK_ALLOW_ANY_CALL
      GIVEN("a VRController") {
        auto vr_controller =
            std::make_unique<phx::VRController>(phx::VRController::LEFT_CONTROLLER);
    
        WHEN("for an axis is asked that does not exist for this mocked device") {
          auto log_capture = std::make_shared<test_utilities::LogCapture>();
          phx::logger = std::make_shared<spdlog::logger>("logcapture", log_capture);
          phx::logger->set_pattern("%w");
          ALLOW_CALL(openvr_mock.GetSystem(), GetControllerAxisTypeNameFromEnum(
                                                  vr::k_eControllerAxis_Trigger))
              .RETURN("k_eControllerAxis_Trigger");
    
          vr_controller->GetAxesValue(phx::VRController::AXES_TRIGGER);
    
          THEN("we expect a warning") {
            REQUIRE(*log_capture ==
                    "VRController device  does not provide the requested axes: "
                    "k_eControllerAxis_Trigger ");
          }
        }
    
        WHEN("we ask for an existing axis the values are returned") {
          ALLOW_CALL(
              openvr_mock.GetSystem(),
              GetControllerStateWithPose(vr::TrackingUniverseStanding, 2, _, _, _))
              .RETURN(true)
              .SIDE_EFFECT(_3->rAxis[0].x = 0.5f)
              .SIDE_EFFECT(_3->rAxis[0].y = 0.7f);
          ALLOW_CALL(openvr_mock.GetSystem(),
                     GetInt32TrackedDeviceProperty(_, vr::Prop_Axis0Type_Int32, _))
              .RETURN(vr::k_eControllerAxis_Trigger);
    
          glm::vec2 value =
              vr_controller->GetAxesValue(phx::VRController::AXES_TRIGGER);
    
          THEN("we get the expected values") {
            REQUIRE(value == glm::vec2(0.5f, 0.7f));
          }
        }
      }
    }
    
    // TODO(JW) try also axes