From 533bf45087382014b2ea1f35344f506fd7fa476c Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 22 Apr 2023 17:49:07 +0200 Subject: [PATCH 1/6] resize overlays when grabbed with both controllers --- README.md | 2 +- src/app.h | 6 --- src/controller.cpp | 21 ++++++++- src/controller.h | 6 +++ src/overlay.cpp | 110 ++++++++++++++++++++++++++++++++------------- src/overlay.h | 9 +++- src/util.h | 7 +++ 7 files changed, 120 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index cd4dd5a..065bbd4 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ovr-screen +# sinpin-vr A SteamVR overlay for Linux+X11 that displays all your screens in VR. From my limited testing, this uses about half the CPU performance of Steam's built-in desktop overlay, if running at 60 FPS. Currently the default is 30 FPS which brings the factor to 3-4x. On my machine, the Steam desktop view increases cpu usage by about 100% of a CPU thread (looking only at the `steam` process), while this overlay uses around 25% at 30 FPS and 45% at 60 FPS. diff --git a/src/app.h b/src/app.h index f6bd55d..c1508e8 100644 --- a/src/app.h +++ b/src/app.h @@ -24,12 +24,6 @@ struct InputHandles vr::VRActionHandle_t grab; }; -struct Ray -{ - Overlay *overlay; - float distance; -}; - class App { public: diff --git a/src/controller.cpp b/src/controller.cpp index a6df051..27dc871 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -57,6 +57,21 @@ void Controller::ReleaseOverlay() _grabbed_overlay = nullptr; } +Ray Controller::GetLastRay() +{ + return _last_ray; +} + +glm::vec3 Controller::GetLastPos() +{ + return _last_pos; +} + +glm::vec3 Controller::GetLastRot() +{ + return _last_rotation; +} + void Controller::Update() { UpdateStatus(); @@ -82,6 +97,10 @@ void Controller::UpdateLaser() auto ray = _app->IntersectRay(controller_pos, forward, 5.0f); float len = ray.distance; + _last_pos = controller_pos; + _last_rotation = forward; + _last_ray = ray; + auto hmd_global_pos = GetPos(_app->GetTrackerPose(0)); auto hmd_local_pos = glm::inverse(controller_pose) * glm::vec4(hmd_global_pos - controller_pos, 0); hmd_local_pos.z = 0; @@ -96,7 +115,7 @@ void Controller::UpdateLaser() { if (ray.overlay->IsHeld()) { - // TODO resize mode + ray.overlay->ControllerResize(this); } else { diff --git a/src/controller.h b/src/controller.h index a096c23..e5f49b8 100644 --- a/src/controller.h +++ b/src/controller.h @@ -20,6 +20,9 @@ class Controller ControllerSide Side(); bool IsConnected(); + Ray GetLastRay(); + glm::vec3 GetLastPos(); + glm::vec3 GetLastRot(); void SetHidden(bool state); @@ -39,4 +42,7 @@ class Controller bool _is_connected; bool _hidden; Overlay *_grabbed_overlay; + Ray _last_ray; + glm::vec3 _last_rotation; + glm::vec3 _last_pos; }; diff --git a/src/overlay.cpp b/src/overlay.cpp index 4b8bd5c..80f218f 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -14,6 +14,7 @@ Overlay::Overlay(App *app, std::string name) _name = name; _app = app; _holding_controller = nullptr; + _resize_controller = nullptr; _width_m = 1; _ratio = 1; _hidden = false; @@ -149,7 +150,7 @@ void Overlay::SetTargetWorld() Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) { - float closest_dist = max_len; + float dist = max_len; auto end = origin + direction * max_len; auto panel_transform = GetTransformAbsolute(); @@ -166,46 +167,30 @@ Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) if (b.z < a.z && b.z < 0 && glm::abs(p.x) < (_width_m * 0.5f) && glm::abs(p.y) < (_width_m * 0.5f * _ratio)) { - float dist = r * max_len; - if (dist < closest_dist) - { - closest_dist = dist; - } + dist = glm::min(r * max_len, max_len); } - return Ray{.overlay = this, .distance = closest_dist}; + return Ray{.overlay = this, .distance = dist}; } glm::mat4x4 Overlay::GetTransformAbsolute() { - if (_holding_controller != nullptr) + if (_target.type == TargetType::World) { VRMat pose; - TrackerID tracker; - auto err = _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &tracker, &pose); - assert(err == 0); - auto offset = ConvertMat(pose); - auto controller = _app->GetTrackerPose(_holding_controller->DeviceIndex()); - return controller * offset; + vr::ETrackingUniverseOrigin tracking_universe; + _app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &pose); + return ConvertMat(pose); } - else + if (_target.type == TargetType::Tracker) { - switch (_target.type) - { - case TargetType::World: { - VRMat pose; - vr::ETrackingUniverseOrigin tracking_universe; - _app->vr_overlay->GetOverlayTransformAbsolute(_id, &tracking_universe, &pose); - return ConvertMat(pose); - } - case TargetType::Tracker: { - VRMat pose; - _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_target.id, &pose); - auto offset = ConvertMat(pose); - auto tracker_pose = _app->GetTrackerPose(_target.id); - return tracker_pose * offset; - } - } + VRMat pose; + _app->vr_overlay->GetOverlayTransformTrackedDeviceRelative(_id, &_target.id, &pose); + auto offset = ConvertMat(pose); + auto tracker_pose = _app->GetTrackerPose(_target.id); + return tracker_pose * offset; } + printf("Error: overlay '%s' not set to a valid target", _name.c_str()); + return ConvertMat(VRMatIdentity); } Target *Overlay::GetTarget() @@ -223,7 +208,41 @@ void Overlay::Update() if (_holding_controller != nullptr) { - if (!_app->GetInputDigital(_app->_input_handles.grab, _holding_controller->InputHandle()).bState) + bool hold_controller_holding = _app->GetInputDigital(_app->_input_handles.grab, _holding_controller->InputHandle()).bState; + if (_resize_controller != nullptr) + { + bool resize_controller_holding = _app->GetInputDigital(_app->_input_handles.grab, _resize_controller->InputHandle()).bState; + if (!resize_controller_holding) + { + _resize_controller = nullptr; + } + else if (!hold_controller_holding) + { + _resize_controller = nullptr; + ControllerRelease(); + } + else + { + auto pos_a = _holding_controller->GetLastPos() + _holding_controller->GetLastRot() * _resize_length_a; + auto pos_b = _resize_controller->GetLastPos() + _resize_controller->GetLastRot() * _resize_length_b; + + float distance = glm::length(pos_a - pos_b); + float factor = (distance / _resize_base_distance); + float min_factor = 0.1f / _resize_original_size; + float max_factor = 5.0f / _resize_original_size; + factor = glm::clamp(factor, min_factor, max_factor); + float new_size = _resize_original_size * factor; + + SetWidth(new_size); + + auto transform = _target.transform; + auto pos = _resize_held_offset * factor; + transform.m[0][3] = pos.x; + transform.m[1][3] = pos.y; + SetTransformTracker(_holding_controller->DeviceIndex(), &transform); + } + } + else if (!hold_controller_holding) { ControllerRelease(); } @@ -264,6 +283,33 @@ void Overlay::ControllerRelease() _holding_controller = nullptr; } +void Overlay::ControllerResize(Controller *controller) +{ + if (_resize_controller || controller == _holding_controller) + { + return; + } + for (auto child : _children) + { + if (!child->IsHeld()) + { + child->SetTargetWorld(); + } + } + _resize_controller = controller; + _resize_original_size = _width_m; + + _resize_length_a = _holding_controller->GetLastRay().distance; + _resize_length_b = _resize_controller->GetLastRay().distance; + + auto pos_a = _holding_controller->GetLastPos() + _holding_controller->GetLastRot() * _resize_length_a; + auto pos_b = _resize_controller->GetLastPos() + _resize_controller->GetLastRot() * _resize_length_b; + + // distance between laser points + _resize_base_distance = glm::length(pos_a - pos_b); + _resize_held_offset = GetPos(_target.transform); +} + void Overlay::AddChildOverlay(Overlay *overlay) { _children.push_back(overlay); diff --git a/src/overlay.h b/src/overlay.h index 67dce7b..c2ff311 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -55,8 +55,9 @@ class Overlay Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); - void ControllerRelease(); void ControllerGrab(Controller *controller); + void ControllerRelease(); + void ControllerResize(Controller *controller); void AddChildOverlay(Overlay *child); void RemoveChildOverlay(Overlay *child); @@ -73,6 +74,12 @@ class Overlay float _alpha; float _ratio; Controller *_holding_controller; + Controller *_resize_controller; + float _resize_original_size; + float _resize_base_distance; + float _resize_length_a; + float _resize_length_b; + glm::vec3 _resize_held_offset; std::vector _children; diff --git a/src/util.h b/src/util.h index bd29e39..0cf4916 100644 --- a/src/util.h +++ b/src/util.h @@ -10,6 +10,13 @@ typedef vr::HmdMatrix34_t VRMat; const VRMat VRMatIdentity{{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}}}; const int MAX_TRACKERS = vr::k_unMaxTrackedDeviceCount; +class Overlay; +struct Ray +{ + Overlay *overlay; + float distance; +}; + inline void PrintVec(glm::vec3 v) { printf("(%.2f, %.2f, %.2f)\n", v.x, v.y, v.z); From 1134e37b10e5311c20cb88adbd73618fad9a0512 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 22 Apr 2023 19:21:31 +0200 Subject: [PATCH 2/6] toggle edit mode --- bindings/action_manifest.json | 18 +- bindings/index_controller.json | 689 +++++++++++++++++++++++++++++++-- src/app.cpp | 30 +- src/app.h | 4 +- src/controller.cpp | 9 +- 5 files changed, 700 insertions(+), 50 deletions(-) diff --git a/bindings/action_manifest.json b/bindings/action_manifest.json index ddd3886..71d4d74 100644 --- a/bindings/action_manifest.json +++ b/bindings/action_manifest.json @@ -7,17 +7,22 @@ ], "actions": [ { - "name": "/actions/main/in/ToggleAll", + "name": "/actions/main/in/toggle_visibility", "requirement": "mandatory", "type": "boolean" }, { - "name": "/actions/main/in/Grab", + "name": "/actions/main/in/edit_mode", "requirement": "mandatory", "type": "boolean" }, { - "name": "/actions/main/in/Distance", + "name": "/actions/main/in/grab", + "requirement": "mandatory", + "type": "boolean" + }, + { + "name": "/actions/main/in/distance", "requirement": "suggested", "type": "vector2" } @@ -32,9 +37,10 @@ { "language_tag": "en_us", "/actions/main": "Overlay actions", - "/actions/main/in/ToggleAll": "Toggle all", - "/actions/main/in/Grab": "Grab panel", - "/actions/main/in/Distance": "Move away" + "/actions/main/in/toggle_visibility": "Toggle visibility", + "/actions/main/in/edit_mode": "Toggle edit mode", + "/actions/main/in/grab": "grab panel", + "/actions/main/in/distance": "Move away" } ] } \ No newline at end of file diff --git a/bindings/index_controller.json b/bindings/index_controller.json index ebfb3c8..c93ffc0 100644 --- a/bindings/index_controller.json +++ b/bindings/index_controller.json @@ -1,33 +1,658 @@ { - "/actions/main": { - "sources": [ - { - "path": "/user/hand/right/input/b", - "mode": "button", - "inputs": { - "long": { - "output": "/actions/main/in/toggleall" - } - } - }, - { - "path": "/user/hand/right/input/thumbstick", - "mode": "joystick", - "inputs": { - "position": { - "output": "/actions/main/in/distance" - } - } - }, - { - "path": "/user/hand/right/input/trigger", - "mode": "button", - "inputs": { - "click": { - "output": "/actions/main/in/grab" - } - } - } - ] - } -} \ No newline at end of file + "action_manifest_version" : 0, + "alias_info" : { + "/actions/legacy/in/head_proximity" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis2_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis2_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis3_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis3_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis3_value_e0" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis3_value_e1" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis4_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis4_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis4_value_e0" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_axis4_value_e1" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_system_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/left_system_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_axis3_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_axis3_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_axis3_value_e0" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_axis3_value_e1" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_axis4_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_axis4_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_axis4_value_e0" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_axis4_value_e1" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_system_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy/in/right_system_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis2_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis2_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis3_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis3_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis3_value_e0" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis3_value_e1" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis4_press" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis4_touch" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis4_value_e0" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/axis4_value_e1" : { + "alias_name" : "", + "hidden" : true + }, + "/actions/legacy_mirrored/in/system_press" : { + "alias_name" : "", + "hidden" : true + } + }, + "app_key" : "system.generated.overlay", + "bindings" : { + "/actions/legacy" : { + "haptics" : [ + { + "output" : "/actions/legacy/out/left_haptic", + "path" : "/user/hand/left/output/haptic" + }, + { + "output" : "/actions/legacy/out/right_haptic", + "path" : "/user/hand/right/output/haptic" + } + ], + "poses" : [ + { + "output" : "/actions/legacy/in/Left_Pose", + "path" : "/user/hand/left/pose/raw" + }, + { + "output" : "/actions/legacy/in/Right_Pose", + "path" : "/user/hand/right/pose/raw" + } + ], + "sources" : [ + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_system_press" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/system" + }, + { + "inputs" : { + "pull" : { + "output" : "/actions/legacy/in/left_axis1_value" + }, + "touch" : { + "output" : "/actions/legacy/in/left_axis1_touch" + } + }, + "mode" : "trigger", + "path" : "/user/hand/left/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_system_press" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/system" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_grip_press" + }, + "touch" : { + "output" : "/actions/legacy/in/right_grip_touch" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/a" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_grip_press" + }, + "touch" : { + "output" : "/actions/legacy/in/left_grip_touch" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/a" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_applicationmenu_press" + }, + "touch" : { + "output" : "/actions/legacy/in/left_applicationmenu_touch" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/b" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_applicationmenu_press" + }, + "touch" : { + "output" : "/actions/legacy/in/right_applicationmenu_touch" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/b" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_axis0_press" + }, + "position" : { + "output" : "/actions/legacy/in/left_axis0_value" + }, + "touch" : { + "output" : "/actions/legacy/in/left_axis0_touch" + } + }, + "mode" : "trackpad", + "path" : "/user/hand/left/input/trackpad" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_axis0_press" + }, + "position" : { + "output" : "/actions/legacy/in/right_axis0_value" + }, + "touch" : { + "output" : "/actions/legacy/in/right_axis0_touch" + } + }, + "mode" : "trackpad", + "path" : "/user/hand/right/input/trackpad" + }, + { + "inputs" : { + "pull" : { + "output" : "/actions/legacy/in/right_axis1_value" + }, + "touch" : { + "output" : "/actions/legacy/in/right_axis1_touch" + } + }, + "mode" : "trigger", + "path" : "/user/hand/right/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_axis1_press" + }, + "touch" : { + "output" : "/actions/legacy/in/left_axis1_touch" + } + }, + "mode" : "button", + "parameters" : { + "click_activate_threshold" : "0.55", + "click_deactivate_threshold" : "0.5", + "haptic_amplitude" : "0", + "touch_activate_threshold" : "0.1", + "touch_deactivate_threshold" : "0.05" + }, + "path" : "/user/hand/left/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_axis1_press" + }, + "touch" : { + "output" : "/actions/legacy/in/right_axis1_touch" + } + }, + "mode" : "button", + "parameters" : { + "click_activate_threshold" : "0.55", + "click_deactivate_threshold" : "0.5", + "haptic_amplitude" : "0", + "touch_activate_threshold" : "0.1", + "touch_deactivate_threshold" : "0.05" + }, + "path" : "/user/hand/right/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_axis0_press" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/trackpad" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_axis0_press" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/trackpad" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_axis0_press" + }, + "position" : { + "output" : "/actions/legacy/in/left_axis0_value" + }, + "touch" : { + "output" : "/actions/legacy/in/left_axis0_touch" + } + }, + "mode" : "joystick", + "path" : "/user/hand/left/input/thumbstick" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_axis0_press" + }, + "position" : { + "output" : "/actions/legacy/in/right_axis0_value" + }, + "touch" : { + "output" : "/actions/legacy/in/right_axis0_touch" + } + }, + "mode" : "joystick", + "path" : "/user/hand/right/input/thumbstick" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_axis0_press" + } + }, + "mode" : "button", + "parameters" : { + "click_activate_threshold" : 0.80000000000000004, + "click_deactivate_threshold" : 0.69999999999999996, + "force_input" : "position", + "haptic_amplitude" : 0 + }, + "path" : "/user/hand/left/input/thumbstick" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_axis0_press" + } + }, + "mode" : "button", + "parameters" : { + "click_activate_threshold" : 0.80000000000000004, + "click_deactivate_threshold" : 0.69999999999999996, + "force_input" : "position", + "haptic_amplitude" : 0 + }, + "path" : "/user/hand/right/input/thumbstick" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/left_grip_press" + }, + "touch" : { + "output" : "/actions/legacy/in/left_grip_touch" + } + }, + "mode" : "button", + "parameters" : { + "click_activate_threshold" : "0.8", + "force_input" : "force" + }, + "path" : "/user/hand/left/input/grip" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy/in/right_grip_press" + }, + "touch" : { + "output" : "/actions/legacy/in/right_grip_touch" + } + }, + "mode" : "button", + "parameters" : { + "click_activate_threshold" : "0.8", + "force_input" : "force" + }, + "path" : "/user/hand/right/input/grip" + } + ] + }, + "/actions/legacy_mirrored" : { + "haptics" : [ + { + "output" : "/actions/legacy_mirrored/out/haptic", + "path" : "/user/hand/left/output/haptic" + }, + { + "output" : "/actions/legacy_mirrored/out/haptic", + "path" : "/user/hand/right/output/haptic" + } + ], + "poses" : [ + { + "output" : "/actions/legacy_mirrored/in/pose", + "path" : "/user/hand/left/pose/raw" + }, + { + "output" : "/actions/legacy_mirrored/in/pose", + "path" : "/user/hand/right/pose/raw" + } + ], + "sources" : [ + { + "inputs" : { + "click" : { + "output" : "/actions/legacy_mirrored/in/axis1_press" + }, + "pull" : { + "output" : "/actions/legacy_mirrored/in/axis1_value" + }, + "touch" : { + "output" : "/actions/legacy_mirrored/in/axis1_touch" + } + }, + "mode" : "trigger", + "path" : "/user/hand/left/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy_mirrored/in/axis1_press" + }, + "pull" : { + "output" : "/actions/legacy_mirrored/in/axis1_value" + }, + "touch" : { + "output" : "/actions/legacy_mirrored/in/axis1_touch" + } + }, + "mode" : "trigger", + "path" : "/user/hand/right/input/trigger" + }, + { + "inputs" : { + "position" : { + "output" : "/actions/legacy_mirrored/in/axis0_value" + }, + "touch" : { + "output" : "/actions/legacy_mirrored/in/axis0_touch" + } + }, + "mode" : "trackpad", + "path" : "/user/hand/left/input/trackpad" + }, + { + "inputs" : { + "position" : { + "output" : "/actions/legacy_mirrored/in/axis0_value" + }, + "touch" : { + "output" : "/actions/legacy_mirrored/in/axis0_touch" + } + }, + "mode" : "trackpad", + "path" : "/user/hand/right/input/trackpad" + }, + { + "inputs" : {}, + "mode" : "joystick", + "path" : "/user/hand/left/input/thumbstick" + }, + { + "inputs" : {}, + "mode" : "joystick", + "path" : "/user/hand/right/input/thumbstick" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy_mirrored/in/grip_press" + }, + "touch" : { + "output" : "/actions/legacy_mirrored/in/grip_touch" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/a" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy_mirrored/in/grip_press" + }, + "touch" : { + "output" : "/actions/legacy_mirrored/in/grip_touch" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/a" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy_mirrored/in/applicationmenu_press" + }, + "touch" : { + "output" : "/actions/legacy_mirrored/in/applicationmenu_touch" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/b" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy_mirrored/in/applicationmenu_press" + }, + "touch" : { + "output" : "/actions/legacy_mirrored/in/applicationmenu_touch" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/b" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy_mirrored/in/axis0_press" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/trackpad" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/legacy_mirrored/in/axis0_press" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/trackpad" + } + ] + }, + "/actions/main" : { + "sources" : [ + { + "inputs" : { + "long" : { + "output" : "/actions/main/in/edit_mode" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/b" + }, + { + "inputs" : { + "position" : { + "output" : "/actions/main/in/distance" + } + }, + "mode" : "joystick", + "path" : "/user/hand/right/input/thumbstick" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/main/in/grab" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/main/in/grab" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/trigger" + }, + { + "inputs" : { + "long" : { + "output" : "/actions/main/in/toggle_visibility" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/b" + }, + { + "inputs" : { + "position" : { + "output" : "/actions/main/in/distance" + } + }, + "mode" : "joystick", + "path" : "/user/hand/left/input/thumbstick" + } + ] + } + }, + "category" : "steamvr_input", + "controller_type" : "knuckles", + "description" : "Default binding values for legacy apps using the Index Controller", + "interaction_profile" : "", + "name" : "Saved overlay configuration for Index Controller", + "options" : { + "mirror_actions" : true, + "simulated_controller_type" : "none" + }, + "simulated_actions" : [] +} diff --git a/src/app.cpp b/src/app.cpp index 5f61799..1b37d25 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -57,11 +57,13 @@ App::App() printf("actions path: %s\n", _actions_path.c_str()); vr_input->SetActionManifestPath(_actions_path.c_str()); - auto action_err = vr_input->GetActionHandle("/actions/main/in/Grab", &_input_handles.grab); + auto action_err = vr_input->GetActionHandle("/actions/main/in/grab", &_input_handles.grab); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/ToggleAll", &_input_handles.toggle); + action_err = vr_input->GetActionHandle("/actions/main/in/toggle_visibility", &_input_handles.toggle_hidden); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/Distance", &_input_handles.distance); + action_err = vr_input->GetActionHandle("/actions/main/in/edit_mode", &_input_handles.edit_mode); + assert(action_err == 0); + action_err = vr_input->GetActionHandle("/actions/main/in/distance", &_input_handles.distance); assert(action_err == 0); action_err = vr_input->GetActionSetHandle("/actions/main", &_input_handles.set); assert(action_err == 0); @@ -162,19 +164,29 @@ void App::UpdateInput() vr_sys->GetDeviceToAbsoluteTrackingPose(_tracking_origin, 0, _tracker_poses, MAX_TRACKERS); - if (IsInputJustPressed(_input_handles.toggle)) + if (IsInputJustPressed(_input_handles.toggle_hidden)) { _hidden = !_hidden; - _root_overlay.SetHidden(_hidden); for (auto &panel : _panels) { panel.SetHidden(_hidden); } - _controllers[0]->SetHidden(_hidden); - _controllers[1]->SetHidden(_hidden); + _root_overlay.SetHidden(_hidden || !_edit_mode); + _controllers[0]->SetHidden(_hidden || !_edit_mode); + _controllers[1]->SetHidden(_hidden || !_edit_mode); + } + if (!_hidden && IsInputJustPressed(_input_handles.edit_mode)) + { + _edit_mode = !_edit_mode; + _root_overlay.SetHidden(_hidden || !_edit_mode); + _controllers[0]->SetHidden(_hidden || !_edit_mode); + _controllers[1]->SetHidden(_hidden || !_edit_mode); + } + if (_edit_mode) + { + _controllers[0]->Update(); + _controllers[1]->Update(); } - _controllers[0]->Update(); - _controllers[1]->Update(); } void App::UpdateFramebuffer() diff --git a/src/app.h b/src/app.h index c1508e8..5150f65 100644 --- a/src/app.h +++ b/src/app.h @@ -19,9 +19,10 @@ struct CursorPos struct InputHandles { vr::VRActionSetHandle_t set; - vr::VRActionHandle_t toggle; + vr::VRActionHandle_t toggle_hidden; vr::VRActionHandle_t distance; vr::VRActionHandle_t grab; + vr::VRActionHandle_t edit_mode; }; class App @@ -63,6 +64,7 @@ class App Overlay _root_overlay; std::vector _panels; bool _hidden = false; + bool _edit_mode = false; private: void InitX11(); diff --git a/src/controller.cpp b/src/controller.cpp index 27dc871..d28d8e3 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -25,6 +25,7 @@ Controller::Controller(App *app, ControllerSide side) UpdateStatus(); _laser.SetTextureToColor(255, 200, 255); _laser.SetAlpha(0.2f); + _laser.SetHidden(true); } TrackerID Controller::DeviceIndex() @@ -50,6 +51,7 @@ bool Controller::IsConnected() void Controller::SetHidden(bool state) { _hidden = state; + _laser.SetHidden(_hidden); } void Controller::ReleaseOverlay() @@ -94,7 +96,7 @@ void Controller::UpdateLaser() auto controller_pose = _app->GetTrackerPose(_device_index); auto controller_pos = GetPos(controller_pose); auto forward = -glm::vec3(controller_pose[2]); - auto ray = _app->IntersectRay(controller_pos, forward, 5.0f); + auto ray = _app->IntersectRay(controller_pos, forward, 8.0f); float len = ray.distance; _last_pos = controller_pos; @@ -143,5 +145,8 @@ void Controller::UpdateStatus() _device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand); } _is_connected &= _device_index < MAX_TRACKERS; - _laser.SetHidden(!_is_connected || _hidden); + if (!_is_connected) + { + _laser.SetHidden(true); + } } From cc89c8cbc513c9744a371c3b787e9a8832bfa724 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 22 Apr 2023 19:21:56 +0200 Subject: [PATCH 3/6] rename executable --- .gitignore | 2 +- Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 0c01b56..f1bf125 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -overlay +sinpin_vr .vscode/ diff --git a/Makefile b/Makefile index 926840c..f92c71e 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ CC := clang++ LFLAGS := -lX11 -lXrandr -lglfw -lGL LIBS := openvr/libopenvr_api.so SRC := src/*.cpp -OUT := ./overlay +OUT := ./sinpin_vr CPPFLAGS := -Wall -std=c++17 $(LFLAGS) $(LIBS) $(SRC) -o $(OUT) build: @@ -14,5 +14,5 @@ release: $(CC) $(CPPFLAGS) run: build - ./overlay + $(OUT) From 9cecbc4d9ebd767b7bd1a45642fce6fc95b85020 Mon Sep 17 00:00:00 2001 From: Crispy <54243225+CrispyPin@users.noreply.github.com> Date: Sat, 22 Apr 2023 19:38:26 +0200 Subject: [PATCH 4/6] add demo video to readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 065bbd4..cf35da3 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # sinpin-vr A SteamVR overlay for Linux+X11 that displays all your screens in VR. +https://user-images.githubusercontent.com/54243225/233798783-27d1a6ae-b71d-448f-bb67-76015e539452.mp4 + From my limited testing, this uses about half the CPU performance of Steam's built-in desktop overlay, if running at 60 FPS. Currently the default is 30 FPS which brings the factor to 3-4x. On my machine, the Steam desktop view increases cpu usage by about 100% of a CPU thread (looking only at the `steam` process), while this overlay uses around 25% at 30 FPS and 45% at 60 FPS. + From 1f25d2465cb1e972b3ac3169bdb536871dec2f72 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 22 Apr 2023 20:01:44 +0200 Subject: [PATCH 5/6] add feature list --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cf35da3..9b1c44c 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,17 @@ A SteamVR overlay for Linux+X11 that displays all your screens in VR. https://user-images.githubusercontent.com/54243225/233798783-27d1a6ae-b71d-448f-bb67-76015e539452.mp4 -From my limited testing, this uses about half the CPU performance of Steam's built-in desktop overlay, if running at 60 FPS. Currently the default is 30 FPS which brings the factor to 3-4x. On my machine, the Steam desktop view increases cpu usage by about 100% of a CPU thread (looking only at the `steam` process), while this overlay uses around 25% at 30 FPS and 45% at 60 FPS. +## features +- one overlay per screen +- shows cursor position +- global visibility toggle (default: long press left B) +- edit mode (default: long press right B) + - move screens around (default: trigger) + - resize screens (move with two controllers) + - push/pull screens (default: joystick up/down) + - move all screens at once with the same controls by grabbing the purple square + +## performance +From my limited testing, this uses about half the CPU performance of Steam's built-in desktop overlay, if running at 60 FPS. Currently the default is 30 FPS which brings that factor to 3-4x. On my machine, the Steam desktop view increases cpu usage by about 100% of a CPU thread (looking only at the `steam` process), while this overlay uses around 25% at 30 FPS and 45% at 60 FPS. From 5f773e2d4d893d37a3cf471d5144a0e9e5b03ed5 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 22 Apr 2023 20:02:09 +0200 Subject: [PATCH 6/6] add release to makefile --- .gitignore | 1 + Makefile | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index f1bf125..0aeec18 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ sinpin_vr .vscode/ +*.zip diff --git a/Makefile b/Makefile index f92c71e..45b2cd1 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ - +VERSION=v0.1.0 # CC := g++ CC := clang++ LFLAGS := -lX11 -lXrandr -lglfw -lGL @@ -10,8 +10,8 @@ CPPFLAGS := -Wall -std=c++17 $(LFLAGS) $(LIBS) $(SRC) -o $(OUT) build: $(CC) -g $(CPPFLAGS) -release: - $(CC) $(CPPFLAGS) +release: build + zip -r sinpin_vr-$(VERSION).zip sinpin_vr bindings openvr/libopenvr_api.so run: build $(OUT)