diff --git a/README.md b/README.md index f7c7452..73d7361 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,3 @@ # ovr-screen -A SteamVR overlay for Linux+X11 that displays the screen in VR. +A SteamVR overlay for Linux+X11 that displays all your screens in VR. diff --git a/src/app.cpp b/src/app.cpp index cdf7552..27c31b6 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -115,7 +115,7 @@ void App::InitGLFW() void App::InitRootOverlay() { _root_overlay = Overlay(this, "root"); - _root_overlay.SetAlpha(0.2f); + _root_overlay.SetAlpha(0.5f); // clang-format off VRMat root_start_pose = {{ {0.25f, 0.0f, 0.0f, 0}, @@ -124,6 +124,7 @@ void App::InitRootOverlay() }}; // clang-format on _root_overlay.SetTransformWorld(&root_start_pose); + _root_overlay.SetTextureToColor(110, 30, 190); _root_overlay._GrabBeginCallback = [this](Controller *controller) { for (auto &panel : _panels) @@ -175,6 +176,8 @@ void App::UpdateInput() { panel.SetHidden(_hidden); } + _controllers[0]->SetHidden(_hidden); + _controllers[1]->SetHidden(_hidden); } _controllers[0]->Update(); _controllers[1]->Update(); @@ -232,22 +235,19 @@ Ray App::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) Ray ray; ray.distance = max_len; ray.overlay = nullptr; + + auto r_root = _root_overlay.IntersectRay(origin, direction, max_len); + if (r_root.distance < ray.distance) { - float root_dist = _root_overlay.IntersectRay(origin, direction, max_len); - if (root_dist < ray.distance) - { - ray.distance = root_dist; - ray.overlay = &_root_overlay; - } + ray = r_root; } for (auto &panel : _panels) { - float dist = panel.GetOverlay()->IntersectRay(origin, direction, max_len); - if (dist < ray.distance) + auto r_panel = panel.GetOverlay()->IntersectRay(origin, direction, max_len); + if (r_panel.distance < ray.distance) { - ray.distance = dist; - ray.overlay = panel.GetOverlay(); + ray = r_panel; } } return ray; diff --git a/src/app.h b/src/app.h index 9665051..c59222f 100644 --- a/src/app.h +++ b/src/app.h @@ -28,6 +28,7 @@ struct Ray { Overlay *overlay; float distance; + // glm::vec3 pos; }; class App diff --git a/src/controller.cpp b/src/controller.cpp index 3a6d14c..07179e1 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -12,6 +12,7 @@ Controller::Controller(App *app, ControllerSide side) _input_handle = 0; _is_connected = false; _side = side; + _hidden = false; std::string laser_name = "controller_laser_"; if (side == ControllerSide::Left) @@ -45,6 +46,28 @@ bool Controller::IsConnected() return _is_connected; } +void Controller::SetHidden(bool state) +{ + _hidden = state; +} + +void Controller::RegisterGrabbedOverlay(Overlay *overlay) +{ + _grabbed_overlays.push_back(overlay); +} + +void Controller::ReleaseOverlay(Overlay *overlay) +{ + for (auto i = _grabbed_overlays.begin(); i != _grabbed_overlays.end(); i++) + { + if (*i == overlay) + { + _grabbed_overlays.erase(i); + break; + } + } +} + void Controller::Update() { UpdateStatus(); @@ -72,6 +95,24 @@ void Controller::Update() ray.overlay->ControllerGrab(this); } } + + if (!_grabbed_overlays.empty()) + { + float move = _app->GetInputAnalog(_app->_input_handles.distance).y * 0.1; // TODO use frame time + if (move != 0.0f) + { + // delta is calculated & clamped for first overlay so that child overlays don't move further than the root + float main_z = _grabbed_overlays[0]->GetTarget()->transform.m[2][3]; + float new_main_z = glm::clamp(main_z - move, -5.0f, -0.1f); + float real_delta = new_main_z - main_z; + + for (auto overlay : _grabbed_overlays) + { + overlay->GetTarget()->transform.m[2][3] += real_delta; + _app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(overlay->Id(), _device_index, &overlay->GetTarget()->transform); + } + } + } } void Controller::UpdateStatus() @@ -91,5 +132,5 @@ void Controller::UpdateStatus() _device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand); } _is_connected &= _device_index < MAX_TRACKERS; - _laser.SetHidden(!_is_connected); + _laser.SetHidden(!_is_connected || _hidden); } diff --git a/src/controller.h b/src/controller.h index 2e20983..28f8239 100644 --- a/src/controller.h +++ b/src/controller.h @@ -1,6 +1,7 @@ #pragma once #include "overlay.h" #include "util.h" +#include class App; @@ -20,6 +21,11 @@ class Controller bool IsConnected(); + void SetHidden(bool state); + + void RegisterGrabbedOverlay(Overlay *overlay); + void ReleaseOverlay(Overlay *overlay); + void Update(); void UpdateStatus(); @@ -30,4 +36,6 @@ class Controller TrackerID _device_index; vr::VRInputValueHandle_t _input_handle; bool _is_connected; + bool _hidden; + std::vector _grabbed_overlays; }; diff --git a/src/overlay.cpp b/src/overlay.cpp index 64022a9..119fcd8 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -2,7 +2,6 @@ #include "app.h" #include "util.h" #include -#include Overlay::Overlay() { @@ -137,7 +136,7 @@ void Overlay::SetTargetWorld() _target.type = TargetType::World; } -float Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) +Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) { float closest_dist = max_len; auto end = origin + direction * max_len; @@ -162,7 +161,7 @@ float Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len closest_dist = dist; } } - return closest_dist; + return Ray{.overlay = this, .distance = closest_dist /* , .pos = p */}; } glm::mat4x4 Overlay::GetTransformAbsolute() @@ -198,6 +197,11 @@ glm::mat4x4 Overlay::GetTransformAbsolute() } } +Target *Overlay::GetTarget() +{ + return &_target; +} + void Overlay::Update() { if (!_initialized) @@ -224,7 +228,9 @@ void Overlay::ControllerGrab(Controller *controller) VRMat relative_pose = ConvertMat(glm::inverse(controller_mat) * abs_mat); _app->vr_overlay->SetOverlayTransformTrackedDeviceRelative(_id, controller->DeviceIndex(), &relative_pose); + _target.transform = relative_pose; + controller->RegisterGrabbedOverlay(this); if (_GrabBeginCallback != nullptr) { _GrabBeginCallback(controller); @@ -235,6 +241,7 @@ void Overlay::ControllerGrab(Controller *controller) void Overlay::ControllerRelease() { + _holding_controller->ReleaseOverlay(this); _app->vr_overlay->SetOverlayColor(_id, 1.0f, 1.0f, 1.0f); auto new_pose = ConvertMat(GetTransformAbsolute()); diff --git a/src/overlay.h b/src/overlay.h index 8cbc9e0..a227b8f 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -5,6 +5,7 @@ #include class App; +struct Ray; class Controller; enum class TargetType @@ -43,6 +44,7 @@ class Overlay void SetTextureToColor(uint8_t r, uint8_t g, uint8_t b); glm::mat4x4 GetTransformAbsolute(); + Target *GetTarget(); void SetTransformTracker(TrackerID tracker, const VRMat *transform); void SetTransformWorld(const VRMat *transform); @@ -50,7 +52,7 @@ class Overlay // void SetTargetTracker(TrackerID tracker); void SetTargetWorld(); - float IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); + Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); std::function _GrabBeginCallback; std::function _GrabEndCallback;