From 0042ee3b585a296bba506bba52089deeefa147b5 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Tue, 25 Apr 2023 18:41:02 +0200 Subject: [PATCH 01/10] don't reset positions while hidden --- src/app.cpp | 47 +++++++++++++++++++++++++++-------------------- src/app.h | 1 + 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 25dea85..2268f74 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -162,31 +162,38 @@ void App::UpdateInput() { panel.SetHidden(_hidden); } - _root_overlay.SetHidden(_hidden || !_edit_mode); - _controllers[0]->SetHidden(_hidden || !_edit_mode); - _controllers[1]->SetHidden(_hidden || !_edit_mode); + UpdateUIVisibility(); } - if (IsInputJustPressed(_input_handles.reset)) + if (!_hidden) { - _root_overlay.SetTransformWorld(&root_start_pose); - _root_overlay.SetWidth(0.25f); - for (auto &panel : _panels) + if (IsInputJustPressed(_input_handles.reset)) { - panel.ResetTransform(); + _root_overlay.SetTransformWorld(&root_start_pose); + _root_overlay.SetWidth(0.25f); + for (auto &panel : _panels) + { + panel.ResetTransform(); + } + } + if (IsInputJustPressed(_input_handles.edit_mode)) + { + _edit_mode = !_edit_mode; + UpdateUIVisibility(); + } + if (_edit_mode) + { + _controllers[0]->Update(); + _controllers[1]->Update(); } } - 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(); - } +} + +void App::UpdateUIVisibility() +{ + bool state = _hidden || !_edit_mode; + _root_overlay.SetHidden(state); + _controllers[0]->SetHidden(state); + _controllers[1]->SetHidden(state); } void App::UpdateFramebuffer() diff --git a/src/app.h b/src/app.h index e1cfab1..9acb260 100644 --- a/src/app.h +++ b/src/app.h @@ -78,4 +78,5 @@ class App void UpdateFramebuffer(); void UpdateInput(); + void UpdateUIVisibility(); }; \ No newline at end of file From d204387e19d46ff30ab3f46c85fceba3e493257d Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 29 Apr 2023 16:44:25 +0200 Subject: [PATCH 02/10] move cursor with lasers --- bindings/action_manifest.json | 14 +++-- bindings/index_controller.json | 20 ++++++- src/app.cpp | 20 ++++--- src/app.h | 3 ++ src/controller.cpp | 95 ++++++++++++++++++++++------------ src/controller.h | 7 +-- src/overlay.cpp | 2 +- src/panel.cpp | 12 +++++ src/panel.h | 13 +++++ src/util.h | 3 ++ 10 files changed, 139 insertions(+), 50 deletions(-) diff --git a/bindings/action_manifest.json b/bindings/action_manifest.json index 01b233b..96383cd 100644 --- a/bindings/action_manifest.json +++ b/bindings/action_manifest.json @@ -21,6 +21,11 @@ "requirement": "mandatory", "type": "boolean" }, + { + "name": "/actions/main/in/activate_cursor", + "requirement": "suggested", + "type": "boolean" + }, { "name": "/actions/main/in/reset", "requirement": "suggested", @@ -42,11 +47,12 @@ { "language_tag": "en_us", "/actions/main": "Overlay actions", - "/actions/main/in/toggle_visibility": "Toggle visibility", - "/actions/main/in/edit_mode": "Toggle edit mode", + "/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", - "/actions/main/in/reset": "Reset positions" + "/actions/main/in/activate_cursor": "activate cursor", + "/actions/main/in/distance": "move away", + "/actions/main/in/reset": "reset positions" } ] } \ No newline at end of file diff --git a/bindings/index_controller.json b/bindings/index_controller.json index 60119a8..bfdf259 100644 --- a/bindings/index_controller.json +++ b/bindings/index_controller.json @@ -650,6 +650,24 @@ }, "mode" : "button", "path" : "/user/hand/left/input/a" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/main/in/activate_cursor" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/main/in/activate_cursor" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/trigger" } ] } @@ -658,7 +676,7 @@ "controller_type" : "knuckles", "description" : "yes", "interaction_profile" : "", - "name" : "Saved sinpin_vr bindings", + "name" : "Default sinpin_vr bindings", "options" : { "mirror_actions" : true, "simulated_controller_type" : "none" diff --git a/src/app.cpp b/src/app.cpp index 2268f74..cb20377 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -1,6 +1,7 @@ #include "app.h" #include "controller.h" #include "util.h" +#include #include #include #include @@ -55,6 +56,8 @@ App::App() assert(action_err == 0); 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/activate_cursor", &_input_handles.activate_cursor); + assert(action_err == 0); 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/reset", &_input_handles.reset); @@ -180,20 +183,15 @@ void App::UpdateInput() _edit_mode = !_edit_mode; UpdateUIVisibility(); } - if (_edit_mode) - { - _controllers[0]->Update(); - _controllers[1]->Update(); - } } + _controllers[0]->Update(); + _controllers[1]->Update(); } void App::UpdateUIVisibility() { bool state = _hidden || !_edit_mode; _root_overlay.SetHidden(state); - _controllers[0]->SetHidden(state); - _controllers[1]->SetHidden(state); } void App::UpdateFramebuffer() @@ -262,7 +260,7 @@ Ray App::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) for (auto &panel : _panels) { - auto r_panel = panel.GetOverlay()->IntersectRay(origin, direction, max_len); + auto r_panel = panel.IntersectRay(origin, direction, max_len); if (r_panel.distance < ray.distance) { ray = r_panel; @@ -288,3 +286,9 @@ CursorPos App::GetCursorPosition() &buttons); return pos; } + +void App::SetCursor(int x, int y) +{ + // I don't know what the return value of XWarpPointer means, it seems to be 1 on success. + XWarpPointer(_xdisplay, _root_window, _root_window, 0, 0, _root_width, _root_height, x, y); +} diff --git a/src/app.h b/src/app.h index 9acb260..6b48ce4 100644 --- a/src/app.h +++ b/src/app.h @@ -22,6 +22,7 @@ struct InputHandles vr::VRActionHandle_t toggle_hidden; vr::VRActionHandle_t distance; vr::VRActionHandle_t grab; + vr::VRActionHandle_t activate_cursor; vr::VRActionHandle_t edit_mode; vr::VRActionHandle_t reset; }; @@ -41,6 +42,7 @@ class App CursorPos GetCursorPosition(); Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); + void SetCursor(int x, int y); Display *_xdisplay; Window _root_window; @@ -69,6 +71,7 @@ class App std::vector _panels; bool _hidden = false; bool _edit_mode = false; + std::optional _active_cursor; private: void InitX11(); diff --git a/src/controller.cpp b/src/controller.cpp index d28d8e3..2103295 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -13,7 +13,7 @@ Controller::Controller(App *app, ControllerSide side) _input_handle = 0; _is_connected = false; _side = side; - _hidden = false; + _cursor_active = false; std::string laser_name = "controller_laser_"; if (side == ControllerSide::Left) @@ -48,12 +48,6 @@ bool Controller::IsConnected() return _is_connected; } -void Controller::SetHidden(bool state) -{ - _hidden = state; - _laser.SetHidden(_hidden); -} - void Controller::ReleaseOverlay() { _grabbed_overlay = nullptr; @@ -77,17 +71,71 @@ glm::vec3 Controller::GetLastRot() void Controller::Update() { UpdateStatus(); - if (!_is_connected || _hidden) + if (!_is_connected) return; UpdateLaser(); - float move = _app->GetInputAnalog(_app->_input_handles.distance, _input_handle).y * 0.1; // TODO use frame time - if (_grabbed_overlay && move != 0.0f) + if (_app->_edit_mode) { - auto transform = _grabbed_overlay->GetTarget()->transform; - transform.m[2][3] = glm::clamp(transform.m[2][3] - move, -5.0f, -0.1f); // moving along z axis - _grabbed_overlay->SetTransformTracker(_device_index, &transform); + if (_last_ray.overlay != nullptr) + { + auto ray = _last_ray; + if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle)) + { + if (ray.overlay->IsHeld()) + { + ray.overlay->ControllerResize(this); + } + else + { + _grabbed_overlay = ray.overlay; + ray.overlay->ControllerGrab(this); + } + } + } + + if (_grabbed_overlay != nullptr) + { + float move = _app->GetInputAnalog(_app->_input_handles.distance, _input_handle).y * 0.1; // TODO use frame time + if (move != 0.0f) + { + auto transform = _grabbed_overlay->GetTarget()->transform; + transform.m[2][3] = glm::clamp(transform.m[2][3] - move, -5.0f, -0.1f); // moving along z axis + _grabbed_overlay->SetTransformTracker(_device_index, &transform); + } + } + } + else //view mode + { + if (_app->IsInputJustPressed(_app->_input_handles.activate_cursor, _input_handle)) + { + if (!_cursor_active && _app->_active_cursor.has_value()) + { + _app->_active_cursor.value()->_cursor_active = false; + _app->_active_cursor = this; + } + _cursor_active = !_cursor_active; + _app->_active_cursor = this; + } + if (_cursor_active) + { + // printf("update cursor on hand %d\n", _side); + if (_last_ray.overlay != nullptr && _last_ray.hit_panel != nullptr) + { + auto pos = glm::vec2(_last_ray.local_pos.x, _last_ray.local_pos.y); + // normalize positions to +-0.5 + pos /= _last_ray.overlay->Width(); + pos.y *= -1; + + // shift to 0-1 + pos.x += 0.5f; + pos.y += 0.5f * _last_ray.overlay->Ratio(); + + pos *= _last_ray.hit_panel->Width(); + _last_ray.hit_panel->SetCursor(pos.x, pos.y); + } + } } } @@ -110,22 +158,7 @@ void Controller::UpdateLaser() VRMat transform = {{{width * hmd_dir.y, 0, width * hmd_dir.x, 0}, {width * -hmd_dir.x, 0, width * hmd_dir.y, 0}, {0, len, 0, len * -0.5f}}}; _laser.SetTransformTracker(_device_index, &transform); - - if (ray.overlay != nullptr) - { - if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle)) - { - if (ray.overlay->IsHeld()) - { - ray.overlay->ControllerResize(this); - } - else - { - _grabbed_overlay = ray.overlay; - ray.overlay->ControllerGrab(this); - } - } - } + _laser.SetHidden(!_is_connected || _app->_hidden || (!_app->_edit_mode && !_cursor_active)); } void Controller::UpdateStatus() @@ -145,8 +178,4 @@ void Controller::UpdateStatus() _device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand); } _is_connected &= _device_index < MAX_TRACKERS; - if (!_is_connected) - { - _laser.SetHidden(true); - } } diff --git a/src/controller.h b/src/controller.h index e5f49b8..982a1b8 100644 --- a/src/controller.h +++ b/src/controller.h @@ -24,8 +24,6 @@ class Controller glm::vec3 GetLastPos(); glm::vec3 GetLastRot(); - void SetHidden(bool state); - void ReleaseOverlay(); void Update(); @@ -39,9 +37,12 @@ class Controller ControllerSide _side; TrackerID _device_index; vr::VRInputValueHandle_t _input_handle; + bool _is_connected; - bool _hidden; + + bool _cursor_active; 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 80f218f..1275a4e 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -169,7 +169,7 @@ Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) { dist = glm::min(r * max_len, max_len); } - return Ray{.overlay = this, .distance = dist}; + return Ray{.overlay = this, .distance = dist, .local_pos = p, .hit_panel = nullptr}; } glm::mat4x4 Overlay::GetTransformAbsolute() diff --git a/src/panel.cpp b/src/panel.cpp index 020eab5..c4d1c49 100644 --- a/src/panel.cpp +++ b/src/panel.cpp @@ -68,6 +68,18 @@ void Panel::SetHidden(bool state) _overlay.SetHidden(state); } +Ray Panel::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len) +{ + auto ray = _overlay.IntersectRay(origin, direction, max_len); + ray.hit_panel = this; + return ray; +} + +void Panel::SetCursor(int x, int y) +{ + _app->SetCursor(x + _x, y + _y); +} + void Panel::UpdateCursor() { auto global_pos = _app->GetCursorPosition(); diff --git a/src/panel.h b/src/panel.h index 830c53b..2dc31c6 100644 --- a/src/panel.h +++ b/src/panel.h @@ -19,6 +19,19 @@ class Panel void SetHidden(bool state); void ResetTransform(); + int Width() + { + return _width; + } + int Height() + { + return _height; + } + + void SetCursor(int x, int y); + + Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); + Overlay *GetOverlay(); private: diff --git a/src/util.h b/src/util.h index 0cf4916..2e510b8 100644 --- a/src/util.h +++ b/src/util.h @@ -11,10 +11,13 @@ const VRMat VRMatIdentity{{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}}}; const int MAX_TRACKERS = vr::k_unMaxTrackedDeviceCount; class Overlay; +class Panel; struct Ray { Overlay *overlay; float distance; + glm::vec3 local_pos; + Panel *hit_panel; }; inline void PrintVec(glm::vec3 v) From 29f45957502efac71a7482a9bc60a8a4e200cacf Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 29 Apr 2023 17:06:02 +0200 Subject: [PATCH 03/10] mouse left & right click --- Makefile | 2 +- bindings/action_manifest.json | 12 ++++++++++++ src/app.cpp | 10 ++++++++++ src/app.h | 3 +++ src/controller.cpp | 10 ++++++++++ 5 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 45b2cd1..18db0c1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION=v0.1.0 # CC := g++ CC := clang++ -LFLAGS := -lX11 -lXrandr -lglfw -lGL +LFLAGS := -lX11 -lXrandr -lXtst -lglfw -lGL LIBS := openvr/libopenvr_api.so SRC := src/*.cpp OUT := ./sinpin_vr diff --git a/bindings/action_manifest.json b/bindings/action_manifest.json index 96383cd..4870f9f 100644 --- a/bindings/action_manifest.json +++ b/bindings/action_manifest.json @@ -31,6 +31,16 @@ "requirement": "suggested", "type": "boolean" }, + { + "name": "/actions/main/in/mouse_left", + "requirement": "suggested", + "type": "boolean" + }, + { + "name": "/actions/main/in/mouse_right", + "requirement": "suggested", + "type": "boolean" + }, { "name": "/actions/main/in/distance", "requirement": "suggested", @@ -52,6 +62,8 @@ "/actions/main/in/grab": "grab panel", "/actions/main/in/activate_cursor": "activate cursor", "/actions/main/in/distance": "move away", + "/actions/main/in/mouse_left": "mouse left", + "/actions/main/in/mouse_right": "mouse right", "/actions/main/in/reset": "reset positions" } ] diff --git a/src/app.cpp b/src/app.cpp index cb20377..718d702 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -2,6 +2,7 @@ #include "controller.h" #include "util.h" #include +#include #include #include #include @@ -64,6 +65,10 @@ App::App() assert(action_err == 0); action_err = vr_input->GetActionHandle("/actions/main/in/distance", &_input_handles.distance); assert(action_err == 0); + action_err = vr_input->GetActionHandle("/actions/main/in/mouse_left", &_input_handles.mouse_left); + assert(action_err == 0); + action_err = vr_input->GetActionHandle("/actions/main/in/mouse_right", &_input_handles.mouse_right); + assert(action_err == 0); action_err = vr_input->GetActionSetHandle("/actions/main", &_input_handles.set); assert(action_err == 0); } @@ -292,3 +297,8 @@ void App::SetCursor(int x, int y) // I don't know what the return value of XWarpPointer means, it seems to be 1 on success. XWarpPointer(_xdisplay, _root_window, _root_window, 0, 0, _root_width, _root_height, x, y); } + +void App::SendMouseInput(unsigned int button, bool state) +{ + XTestFakeButtonEvent(_xdisplay, button, state, 0); +} diff --git a/src/app.h b/src/app.h index 6b48ce4..c1ea145 100644 --- a/src/app.h +++ b/src/app.h @@ -23,6 +23,8 @@ struct InputHandles vr::VRActionHandle_t distance; vr::VRActionHandle_t grab; vr::VRActionHandle_t activate_cursor; + vr::VRActionHandle_t mouse_left; + vr::VRActionHandle_t mouse_right; vr::VRActionHandle_t edit_mode; vr::VRActionHandle_t reset; }; @@ -43,6 +45,7 @@ class App Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len); void SetCursor(int x, int y); + void SendMouseInput(unsigned int button, bool state); Display *_xdisplay; Window _root_window; diff --git a/src/controller.cpp b/src/controller.cpp index 2103295..fb1774e 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -135,6 +135,16 @@ void Controller::Update() pos *= _last_ray.hit_panel->Width(); _last_ray.hit_panel->SetCursor(pos.x, pos.y); } + auto mouse_left = _app->GetInputDigital(_app->_input_handles.mouse_left, _input_handle); + if (mouse_left.bChanged) + { + _app->SendMouseInput(1, mouse_left.bState); + } + auto mouse_right = _app->GetInputDigital(_app->_input_handles.mouse_right, _input_handle); + if (mouse_right.bChanged) + { + _app->SendMouseInput(3, mouse_right.bState); + } } } } From d94e3040bb419d61a3cf0ac6007778a108b8d7f3 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 29 Apr 2023 17:40:03 +0200 Subject: [PATCH 04/10] use separate steamvr action sets for different modes --- bindings/action_manifest.json | 57 +++++++----- bindings/index_controller.json | 165 +++++++++++++++++++++------------ src/app.cpp | 50 ++++++---- src/app.h | 29 ++++-- src/controller.cpp | 10 +- src/overlay.cpp | 4 +- 6 files changed, 196 insertions(+), 119 deletions(-) diff --git a/bindings/action_manifest.json b/bindings/action_manifest.json index 4870f9f..049a317 100644 --- a/bindings/action_manifest.json +++ b/bindings/action_manifest.json @@ -16,55 +16,62 @@ "requirement": "mandatory", "type": "boolean" }, - { - "name": "/actions/main/in/grab", - "requirement": "mandatory", - "type": "boolean" - }, - { - "name": "/actions/main/in/activate_cursor", - "requirement": "suggested", - "type": "boolean" - }, { "name": "/actions/main/in/reset", "requirement": "suggested", "type": "boolean" }, { - "name": "/actions/main/in/mouse_left", - "requirement": "suggested", + "name": "/actions/edit/in/grab", + "requirement": "mandatory", "type": "boolean" }, { - "name": "/actions/main/in/mouse_right", - "requirement": "suggested", - "type": "boolean" - }, - { - "name": "/actions/main/in/distance", + "name": "/actions/edit/in/distance", "requirement": "suggested", "type": "vector2" + }, + { + "name": "/actions/cursor/in/activate_cursor", + "requirement": "suggested", + "type": "boolean" + }, + { + "name": "/actions/cursor/in/mouse_left", + "requirement": "suggested", + "type": "boolean" + }, + { + "name": "/actions/cursor/in/mouse_right", + "requirement": "suggested", + "type": "boolean" } ], "action_sets": [ { "name": "/actions/main", "usage": "leftright" + }, + { + "name": "/actions/edit", + "usage": "single" + }, + { + "name": "/actions/cursor", + "usage": "single" } ], "localization": [ { "language_tag": "en_us", - "/actions/main": "Overlay actions", "/actions/main/in/toggle_visibility": "toggle visibility", "/actions/main/in/edit_mode": "toggle edit mode", - "/actions/main/in/grab": "grab panel", - "/actions/main/in/activate_cursor": "activate cursor", - "/actions/main/in/distance": "move away", - "/actions/main/in/mouse_left": "mouse left", - "/actions/main/in/mouse_right": "mouse right", - "/actions/main/in/reset": "reset positions" + "/actions/main/in/reset": "reset positions", + "/actions/edit/in/grab": "grab panel", + "/actions/edit/in/distance": "push/pull overlay", + "/actions/cursor/in/activate_cursor": "activate cursor", + "/actions/cursor/in/mouse_left": "mouse left", + "/actions/cursor/in/mouse_right": "mouse right" } ] } \ No newline at end of file diff --git a/bindings/index_controller.json b/bindings/index_controller.json index bfdf259..35b1b40 100644 --- a/bindings/index_controller.json +++ b/bindings/index_controller.json @@ -140,6 +140,104 @@ }, "app_key" : "system.generated.sinpin_vr", "bindings" : { + "/actions/cursor" : { + "sources" : [ + { + "inputs" : { + "click" : { + "output" : "/actions/cursor/in/mouse_right" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/a" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/cursor/in/mouse_right" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/a" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/cursor/in/mouse_left" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/cursor/in/mouse_left" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/cursor/in/activate_cursor" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/trackpad" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/cursor/in/activate_cursor" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/trackpad" + } + ] + }, + "/actions/edit" : { + "sources" : [ + { + "inputs" : { + "position" : { + "output" : "/actions/edit/in/distance" + } + }, + "mode" : "joystick", + "path" : "/user/hand/left/input/thumbstick" + }, + { + "inputs" : { + "position" : { + "output" : "/actions/edit/in/distance" + } + }, + "mode" : "joystick", + "path" : "/user/hand/right/input/thumbstick" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/edit/in/grab" + } + }, + "mode" : "button", + "path" : "/user/hand/left/input/trigger" + }, + { + "inputs" : { + "click" : { + "output" : "/actions/edit/in/grab" + } + }, + "mode" : "button", + "path" : "/user/hand/right/input/trigger" + } + ] + }, "/actions/legacy" : { "haptics" : [ { @@ -588,60 +686,6 @@ }, "/actions/main" : { "sources" : [ - { - "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" : { - "position" : { - "output" : "/actions/main/in/distance" - } - }, - "mode" : "joystick", - "path" : "/user/hand/left/input/thumbstick" - }, - { - "inputs" : { - "click" : { - "output" : "/actions/main/in/toggle_visibility" - } - }, - "mode" : "button", - "path" : "/user/hand/left/input/trackpad" - }, - { - "inputs" : { - "click" : { - "output" : "/actions/main/in/edit_mode" - } - }, - "mode" : "button", - "path" : "/user/hand/right/input/trackpad" - }, { "inputs" : { "long" : { @@ -654,20 +698,23 @@ { "inputs" : { "click" : { - "output" : "/actions/main/in/activate_cursor" + "output" : "/actions/main/in/mouse_left" + }, + "long" : { + "output" : "/actions/main/in/toggle_visibility" } }, "mode" : "button", - "path" : "/user/hand/right/input/trigger" + "path" : "/user/hand/left/input/b" }, { "inputs" : { - "click" : { - "output" : "/actions/main/in/activate_cursor" + "long" : { + "output" : "/actions/main/in/edit_mode" } }, "mode" : "button", - "path" : "/user/hand/left/input/trigger" + "path" : "/user/hand/right/input/b" } ] } diff --git a/src/app.cpp b/src/app.cpp index 718d702..9d6acb2 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -53,23 +53,27 @@ 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/edit/in/grab", &_input_handles.edit.grab); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/toggle_visibility", &_input_handles.toggle_hidden); + action_err = vr_input->GetActionHandle("/actions/main/in/toggle_visibility", &_input_handles.main.toggle_hidden); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/activate_cursor", &_input_handles.activate_cursor); + action_err = vr_input->GetActionHandle("/actions/cursor/in/activate_cursor", &_input_handles.cursor.activate); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/edit_mode", &_input_handles.edit_mode); + action_err = vr_input->GetActionHandle("/actions/main/in/edit_mode", &_input_handles.main.edit_mode); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/reset", &_input_handles.reset); + action_err = vr_input->GetActionHandle("/actions/main/in/reset", &_input_handles.main.reset); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/distance", &_input_handles.distance); + action_err = vr_input->GetActionHandle("/actions/edit/in/distance", &_input_handles.edit.distance); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/mouse_left", &_input_handles.mouse_left); + action_err = vr_input->GetActionHandle("/actions/cursor/in/mouse_left", &_input_handles.cursor.mouse_left); assert(action_err == 0); - action_err = vr_input->GetActionHandle("/actions/main/in/mouse_right", &_input_handles.mouse_right); + action_err = vr_input->GetActionHandle("/actions/cursor/in/mouse_right", &_input_handles.cursor.mouse_right); assert(action_err == 0); - action_err = vr_input->GetActionSetHandle("/actions/main", &_input_handles.set); + action_err = vr_input->GetActionSetHandle("/actions/main", &_input_handles.main_set); + assert(action_err == 0); + action_err = vr_input->GetActionSetHandle("/actions/edit", &_input_handles.edit_set); + assert(action_err == 0); + action_err = vr_input->GetActionSetHandle("/actions/cursor", &_input_handles.cursor_set); assert(action_err == 0); } } @@ -151,19 +155,27 @@ void App::Update() void App::UpdateInput() { - vr::VRActiveActionSet_t main; - main.ulActionSet = _input_handles.set; - main.ulRestrictedToDevice = 0; - main.nPriority = 10; - vr::EVRInputError err = vr_input->UpdateActionState(&main, sizeof(vr::VRActiveActionSet_t), 1); - if (err) + vr::VRActiveActionSet_t active_sets[2]; + active_sets[0].ulActionSet = _input_handles.main_set; + active_sets[0].ulRestrictedToDevice = 0; + active_sets[0].nPriority = 10; + int set_count = 1; + if (!_hidden) { - printf("Error: (update action state): %d\n", err); + set_count = 2; + active_sets[1].ulRestrictedToDevice = 0; + active_sets[1].nPriority = 10; + active_sets[1].ulActionSet = _input_handles.cursor_set; + if (_edit_mode) + active_sets[1].ulActionSet = _input_handles.edit_set; } + vr::EVRInputError err = vr_input->UpdateActionState(active_sets, sizeof(vr::VRActiveActionSet_t), set_count); + if (err) + printf("Error updating action state: %d\n", err); vr_sys->GetDeviceToAbsoluteTrackingPose(_tracking_origin, 0, _tracker_poses, MAX_TRACKERS); - if (IsInputJustPressed(_input_handles.toggle_hidden)) + if (IsInputJustPressed(_input_handles.main.toggle_hidden)) { _hidden = !_hidden; for (auto &panel : _panels) @@ -174,7 +186,7 @@ void App::UpdateInput() } if (!_hidden) { - if (IsInputJustPressed(_input_handles.reset)) + if (IsInputJustPressed(_input_handles.main.reset)) { _root_overlay.SetTransformWorld(&root_start_pose); _root_overlay.SetWidth(0.25f); @@ -183,7 +195,7 @@ void App::UpdateInput() panel.ResetTransform(); } } - if (IsInputJustPressed(_input_handles.edit_mode)) + if (IsInputJustPressed(_input_handles.main.edit_mode)) { _edit_mode = !_edit_mode; UpdateUIVisibility(); diff --git a/src/app.h b/src/app.h index c1ea145..fc81339 100644 --- a/src/app.h +++ b/src/app.h @@ -18,15 +18,26 @@ struct CursorPos struct InputHandles { - vr::VRActionSetHandle_t set; - vr::VRActionHandle_t toggle_hidden; - vr::VRActionHandle_t distance; - vr::VRActionHandle_t grab; - vr::VRActionHandle_t activate_cursor; - vr::VRActionHandle_t mouse_left; - vr::VRActionHandle_t mouse_right; - vr::VRActionHandle_t edit_mode; - vr::VRActionHandle_t reset; + struct + { + vr::VRActionHandle_t toggle_hidden; + vr::VRActionHandle_t edit_mode; + vr::VRActionHandle_t reset; + } main; + vr::VRActionSetHandle_t main_set; + struct + { + vr::VRActionHandle_t activate; + vr::VRActionHandle_t mouse_left; + vr::VRActionHandle_t mouse_right; + } cursor; + vr::VRActionSetHandle_t cursor_set; + struct + { + vr::VRActionHandle_t distance; + vr::VRActionHandle_t grab; + } edit; + vr::VRActionSetHandle_t edit_set; }; class App diff --git a/src/controller.cpp b/src/controller.cpp index fb1774e..d4cac9e 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -81,7 +81,7 @@ void Controller::Update() if (_last_ray.overlay != nullptr) { auto ray = _last_ray; - if (_app->IsInputJustPressed(_app->_input_handles.grab, _input_handle)) + if (_app->IsInputJustPressed(_app->_input_handles.edit.grab, _input_handle)) { if (ray.overlay->IsHeld()) { @@ -97,7 +97,7 @@ void Controller::Update() if (_grabbed_overlay != nullptr) { - float move = _app->GetInputAnalog(_app->_input_handles.distance, _input_handle).y * 0.1; // TODO use frame time + float move = _app->GetInputAnalog(_app->_input_handles.edit.distance, _input_handle).y * 0.1; // TODO use frame time if (move != 0.0f) { auto transform = _grabbed_overlay->GetTarget()->transform; @@ -108,7 +108,7 @@ void Controller::Update() } else //view mode { - if (_app->IsInputJustPressed(_app->_input_handles.activate_cursor, _input_handle)) + if (_app->IsInputJustPressed(_app->_input_handles.cursor.activate, _input_handle)) { if (!_cursor_active && _app->_active_cursor.has_value()) { @@ -135,12 +135,12 @@ void Controller::Update() pos *= _last_ray.hit_panel->Width(); _last_ray.hit_panel->SetCursor(pos.x, pos.y); } - auto mouse_left = _app->GetInputDigital(_app->_input_handles.mouse_left, _input_handle); + auto mouse_left = _app->GetInputDigital(_app->_input_handles.cursor.mouse_left, _input_handle); if (mouse_left.bChanged) { _app->SendMouseInput(1, mouse_left.bState); } - auto mouse_right = _app->GetInputDigital(_app->_input_handles.mouse_right, _input_handle); + auto mouse_right = _app->GetInputDigital(_app->_input_handles.cursor.mouse_right, _input_handle); if (mouse_right.bChanged) { _app->SendMouseInput(3, mouse_right.bState); diff --git a/src/overlay.cpp b/src/overlay.cpp index 1275a4e..7f236e0 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -208,10 +208,10 @@ void Overlay::Update() if (_holding_controller != nullptr) { - bool hold_controller_holding = _app->GetInputDigital(_app->_input_handles.grab, _holding_controller->InputHandle()).bState; + bool hold_controller_holding = _app->GetInputDigital(_app->_input_handles.edit.grab, _holding_controller->InputHandle()).bState; if (_resize_controller != nullptr) { - bool resize_controller_holding = _app->GetInputDigital(_app->_input_handles.grab, _resize_controller->InputHandle()).bState; + bool resize_controller_holding = _app->GetInputDigital(_app->_input_handles.edit.grab, _resize_controller->InputHandle()).bState; if (!resize_controller_holding) { _resize_controller = nullptr; From d33eb40c694a0f68a10cd8970b8b836faae3f764 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 29 Apr 2023 18:14:15 +0200 Subject: [PATCH 05/10] color code lasers --- src/app.cpp | 5 +++++ src/controller.cpp | 12 ++++++++---- src/controller.h | 3 ++- src/overlay.cpp | 11 +++++++++++ src/overlay.h | 2 ++ src/util.h | 7 +++++++ 6 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 9d6acb2..f2f56af 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -199,6 +199,11 @@ void App::UpdateInput() { _edit_mode = !_edit_mode; UpdateUIVisibility(); + if (_edit_mode && _active_cursor.has_value()) + { + _active_cursor.value()->_cursor_active = false; + _active_cursor = {}; + } } } _controllers[0]->Update(); diff --git a/src/controller.cpp b/src/controller.cpp index d4cac9e..e4e8722 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -4,7 +4,9 @@ #include "util.h" #include -const float width = 0.004f; +const float laser_width = 0.004f; +const Color edit_col{1, 0.6f, 1}; +const Color cursor_col{0.3f, 1, 1}; Controller::Controller(App *app, ControllerSide side) { @@ -23,7 +25,7 @@ Controller::Controller(App *app, ControllerSide side) _laser = Overlay(app, laser_name); UpdateStatus(); - _laser.SetTextureToColor(255, 200, 255); + _laser.SetTextureToColor(255, 255, 255); _laser.SetAlpha(0.2f); _laser.SetHidden(true); } @@ -78,6 +80,7 @@ void Controller::Update() if (_app->_edit_mode) { + _laser.SetColor(edit_col); if (_last_ray.overlay != nullptr) { auto ray = _last_ray; @@ -106,7 +109,7 @@ void Controller::Update() } } } - else //view mode + else // cursor mode { if (_app->IsInputJustPressed(_app->_input_handles.cursor.activate, _input_handle)) { @@ -117,6 +120,7 @@ void Controller::Update() } _cursor_active = !_cursor_active; _app->_active_cursor = this; + _laser.SetColor(cursor_col); } if (_cursor_active) { @@ -166,7 +170,7 @@ void Controller::UpdateLaser() hmd_local_pos.z = 0; auto hmd_dir = glm::normalize(hmd_local_pos); - VRMat transform = {{{width * hmd_dir.y, 0, width * hmd_dir.x, 0}, {width * -hmd_dir.x, 0, width * hmd_dir.y, 0}, {0, len, 0, len * -0.5f}}}; + VRMat transform = {{{laser_width * hmd_dir.y, 0, laser_width * hmd_dir.x, 0}, {laser_width * -hmd_dir.x, 0, laser_width * hmd_dir.y, 0}, {0, len, 0, len * -0.5f}}}; _laser.SetTransformTracker(_device_index, &transform); _laser.SetHidden(!_is_connected || _app->_hidden || (!_app->_edit_mode && !_cursor_active)); } diff --git a/src/controller.h b/src/controller.h index 982a1b8..cf810d2 100644 --- a/src/controller.h +++ b/src/controller.h @@ -28,6 +28,8 @@ class Controller void Update(); + bool _cursor_active; + private: void UpdateStatus(); void UpdateLaser(); @@ -40,7 +42,6 @@ class Controller bool _is_connected; - bool _cursor_active; Overlay *_grabbed_overlay; Ray _last_ray; diff --git a/src/overlay.cpp b/src/overlay.cpp index 7f236e0..a35f61a 100644 --- a/src/overlay.cpp +++ b/src/overlay.cpp @@ -108,6 +108,17 @@ void Overlay::SetTextureToColor(uint8_t r, uint8_t g, uint8_t b) assert(set_texture_err == 0); } +void Overlay::SetColor(float r, float g, float b) +{ + auto set_color_err = _app->vr_overlay->SetOverlayColor(_id, r, g, b); + assert(set_color_err == 0); +} + +void Overlay::SetColor(Color c) +{ + SetColor(c.r, c.g, c.b); +} + void Overlay::SetTransformTracker(TrackerID tracker, const VRMat *transform) { auto original_pose = _target.transform; diff --git a/src/overlay.h b/src/overlay.h index c2ff311..67d110e 100644 --- a/src/overlay.h +++ b/src/overlay.h @@ -43,6 +43,8 @@ class Overlay void SetRatio(float ratio); void SetTexture(vr::Texture_t *texture); void SetTextureToColor(uint8_t r, uint8_t g, uint8_t b); + void SetColor(float r, float g, float b); + void SetColor(Color c); glm::mat4x4 GetTransformAbsolute(); Target *GetTarget(); diff --git a/src/util.h b/src/util.h index 2e510b8..ecb7484 100644 --- a/src/util.h +++ b/src/util.h @@ -20,6 +20,13 @@ struct Ray Panel *hit_panel; }; +struct Color +{ + float r; + float g; + float b; +}; + inline void PrintVec(glm::vec3 v) { printf("(%.2f, %.2f, %.2f)\n", v.x, v.y, v.z); From 6d69a2466850927da57f400620326a223927c389 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 29 Apr 2023 18:29:35 +0200 Subject: [PATCH 06/10] update README.md --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index eab869f..3305da5 100644 --- a/README.md +++ b/README.md @@ -3,12 +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 +Note: only index controllers have default bindings right now, feel free to make a PR. + ## features - one overlay per screen - shows cursor position -- global visibility toggle (default: press left touch) +- global visibility toggle (default: long press left B) - reset positions (default: long press left A) -- edit mode (default: press right touch) +- activate cursor input (default: press touchpad) + - left mouse default: trigger + - right mouse default: A +- edit mode (default: long press press right B) - move screens around (default: trigger) - resize screens (move with two controllers) - push/pull screens (default: joystick up/down) From 44cf1f2aef8bcf4fb4e1ebf317f2911844dad65d Mon Sep 17 00:00:00 2001 From: Crispy <54243225+CrispyPin@users.noreply.github.com> Date: Sat, 29 Apr 2023 18:31:17 +0200 Subject: [PATCH 07/10] update demo video --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3305da5..024e385 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # 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 +https://user-images.githubusercontent.com/54243225/235313348-2ce9b2d8-8458-49f8-ba94-16e577c4f502.mp4 Note: only index controllers have default bindings right now, feel free to make a PR. From 858da78820cc50e78d53be872062d115d7e40d2f Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 29 Apr 2023 18:31:48 +0200 Subject: [PATCH 08/10] bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 18db0c1..f3fb366 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION=v0.1.0 +VERSION=v0.2.0 # CC := g++ CC := clang++ LFLAGS := -lX11 -lXrandr -lXtst -lglfw -lGL From 035d9e729684b66d25a2cf9cc76365555b9625fc Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 29 Apr 2023 19:38:36 +0200 Subject: [PATCH 09/10] add scrolling --- Makefile | 2 +- bindings/action_manifest.json | 16 ++++++++-- bindings/index_controller.json | 18 +++++++++++ src/app.cpp | 18 +++++++---- src/app.h | 6 ++-- src/controller.cpp | 55 ++++++++++++++++++++++++---------- src/controller.h | 6 +++- src/main.cpp | 4 +-- 8 files changed, 95 insertions(+), 30 deletions(-) diff --git a/Makefile b/Makefile index f3fb366..3264bb6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION=v0.2.0 +VERSION=v0.2.1 # CC := g++ CC := clang++ LFLAGS := -lX11 -lXrandr -lXtst -lglfw -lGL diff --git a/bindings/action_manifest.json b/bindings/action_manifest.json index 049a317..d4621c1 100644 --- a/bindings/action_manifest.json +++ b/bindings/action_manifest.json @@ -45,6 +45,16 @@ "name": "/actions/cursor/in/mouse_right", "requirement": "suggested", "type": "boolean" + }, + { + "name": "/actions/cursor/in/mouse_middle", + "requirement": "optional", + "type": "boolean" + }, + { + "name": "/actions/cursor/in/scroll", + "requirement": "suggested", + "type": "vector2" } ], "action_sets": [ @@ -70,8 +80,10 @@ "/actions/edit/in/grab": "grab panel", "/actions/edit/in/distance": "push/pull overlay", "/actions/cursor/in/activate_cursor": "activate cursor", - "/actions/cursor/in/mouse_left": "mouse left", - "/actions/cursor/in/mouse_right": "mouse right" + "/actions/cursor/in/mouse_left": "left mouse button", + "/actions/cursor/in/mouse_right": "right mouse button", + "/actions/cursor/in/mouse_middle": "middle mouse button", + "/actions/cursor/in/scroll": "scroll" } ] } \ No newline at end of file diff --git a/bindings/index_controller.json b/bindings/index_controller.json index 35b1b40..de796c5 100644 --- a/bindings/index_controller.json +++ b/bindings/index_controller.json @@ -195,6 +195,24 @@ }, "mode" : "button", "path" : "/user/hand/right/input/trackpad" + }, + { + "inputs" : { + "position" : { + "output" : "/actions/cursor/in/scroll" + } + }, + "mode" : "joystick", + "path" : "/user/hand/left/input/thumbstick" + }, + { + "inputs" : { + "position" : { + "output" : "/actions/cursor/in/scroll" + } + }, + "mode" : "joystick", + "path" : "/user/hand/right/input/thumbstick" } ] }, diff --git a/src/app.cpp b/src/app.cpp index f2f56af..a2cdeb1 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -9,6 +9,8 @@ const VRMat root_start_pose = {{{1, 0, 0, 0}, {0, 1, 0, 0.8f}, {0, 0, 1, 0}}}; // 0.8m above origin +const int FRAME_INTERVAL = 4; // number of update loops until the frame buffer is updated + App::App() { _tracking_origin = vr::TrackingUniverseStanding; @@ -69,6 +71,10 @@ App::App() assert(action_err == 0); action_err = vr_input->GetActionHandle("/actions/cursor/in/mouse_right", &_input_handles.cursor.mouse_right); assert(action_err == 0); + action_err = vr_input->GetActionHandle("/actions/cursor/in/mouse_middle", &_input_handles.cursor.mouse_middle); + assert(action_err == 0); + action_err = vr_input->GetActionHandle("/actions/cursor/in/scroll", &_input_handles.cursor.scroll); + assert(action_err == 0); action_err = vr_input->GetActionSetHandle("/actions/main", &_input_handles.main_set); assert(action_err == 0); action_err = vr_input->GetActionSetHandle("/actions/edit", &_input_handles.edit_set); @@ -138,9 +144,9 @@ void App::InitRootOverlay() _root_overlay.SetTextureToColor(110, 30, 190); } -void App::Update() +void App::Update(float dtime) { - UpdateInput(); + UpdateInput(dtime); if (!_hidden) { _root_overlay.Update(); @@ -153,7 +159,7 @@ void App::Update() _frames_since_framebuffer += 1; } -void App::UpdateInput() +void App::UpdateInput(float dtime) { vr::VRActiveActionSet_t active_sets[2]; active_sets[0].ulActionSet = _input_handles.main_set; @@ -206,8 +212,8 @@ void App::UpdateInput() } } } - _controllers[0]->Update(); - _controllers[1]->Update(); + _controllers[0]->Update(dtime); + _controllers[1]->Update(dtime); } void App::UpdateUIVisibility() @@ -218,7 +224,7 @@ void App::UpdateUIVisibility() void App::UpdateFramebuffer() { - if (_frames_since_framebuffer < 2) + if (_frames_since_framebuffer < FRAME_INTERVAL) { return; } diff --git a/src/app.h b/src/app.h index fc81339..232f74a 100644 --- a/src/app.h +++ b/src/app.h @@ -30,6 +30,8 @@ struct InputHandles vr::VRActionHandle_t activate; vr::VRActionHandle_t mouse_left; vr::VRActionHandle_t mouse_right; + vr::VRActionHandle_t mouse_middle; + vr::VRActionHandle_t scroll; } cursor; vr::VRActionSetHandle_t cursor_set; struct @@ -45,7 +47,7 @@ class App public: App(); ~App(); - void Update(); + void Update(float dtime); std::vector GetControllers(); glm::mat4 GetTrackerPose(TrackerID tracker); @@ -94,6 +96,6 @@ class App void InitRootOverlay(); void UpdateFramebuffer(); - void UpdateInput(); + void UpdateInput(float dtime); void UpdateUIVisibility(); }; \ No newline at end of file diff --git a/src/controller.cpp b/src/controller.cpp index e4e8722..6f7891e 100644 --- a/src/controller.cpp +++ b/src/controller.cpp @@ -4,9 +4,10 @@ #include "util.h" #include -const float laser_width = 0.004f; -const Color edit_col{1, 0.6f, 1}; -const Color cursor_col{0.3f, 1, 1}; +const float LASER_WIDTH = 0.004f; +const Color EDIT_COLOR{1, 0.6f, 1}; +const Color CURSOR_COLOR{0.3f, 1, 1}; +const float SCROLL_SPEED = 48.0f; Controller::Controller(App *app, ControllerSide side) { @@ -16,6 +17,7 @@ Controller::Controller(App *app, ControllerSide side) _is_connected = false; _side = side; _cursor_active = false; + _last_sent_scroll = 0; std::string laser_name = "controller_laser_"; if (side == ControllerSide::Left) @@ -70,7 +72,7 @@ glm::vec3 Controller::GetLastRot() return _last_rotation; } -void Controller::Update() +void Controller::Update(float dtime) { UpdateStatus(); if (!_is_connected) @@ -80,7 +82,7 @@ void Controller::Update() if (_app->_edit_mode) { - _laser.SetColor(edit_col); + _laser.SetColor(EDIT_COLOR); if (_last_ray.overlay != nullptr) { auto ray = _last_ray; @@ -100,7 +102,7 @@ void Controller::Update() if (_grabbed_overlay != nullptr) { - float move = _app->GetInputAnalog(_app->_input_handles.edit.distance, _input_handle).y * 0.1; // TODO use frame time + float move = _app->GetInputAnalog(_app->_input_handles.edit.distance, _input_handle).y * dtime * 8; if (move != 0.0f) { auto transform = _grabbed_overlay->GetTarget()->transform; @@ -120,7 +122,7 @@ void Controller::Update() } _cursor_active = !_cursor_active; _app->_active_cursor = this; - _laser.SetColor(cursor_col); + _laser.SetColor(CURSOR_COLOR); } if (_cursor_active) { @@ -139,20 +141,41 @@ void Controller::Update() pos *= _last_ray.hit_panel->Width(); _last_ray.hit_panel->SetCursor(pos.x, pos.y); } - auto mouse_left = _app->GetInputDigital(_app->_input_handles.cursor.mouse_left, _input_handle); - if (mouse_left.bChanged) + UpdateMouseButton(_app->_input_handles.cursor.mouse_left, 1); + UpdateMouseButton(_app->_input_handles.cursor.mouse_middle, 2); + UpdateMouseButton(_app->_input_handles.cursor.mouse_right, 3); + auto scroll_state = _app->GetInputAnalog(_app->_input_handles.cursor.scroll, _input_handle); + if (scroll_state.y != 0) { - _app->SendMouseInput(1, mouse_left.bState); - } - auto mouse_right = _app->GetInputDigital(_app->_input_handles.cursor.mouse_right, _input_handle); - if (mouse_right.bChanged) - { - _app->SendMouseInput(3, mouse_right.bState); + _last_sent_scroll += dtime * glm::abs(scroll_state.y) * SCROLL_SPEED; + if (_last_sent_scroll > 1) + { + _last_sent_scroll = 0; + if (scroll_state.y > 0) + { + _app->SendMouseInput(4, true); + _app->SendMouseInput(4, false); + } + else if (scroll_state.y < 0) + { + _app->SendMouseInput(5, true); + _app->SendMouseInput(5, false); + } + } } } } } +void Controller::UpdateMouseButton(vr::VRActionHandle_t binding, unsigned int button) +{ + auto state = _app->GetInputDigital(binding, _input_handle); + if (state.bChanged) + { + _app->SendMouseInput(button, state.bState); + } +} + void Controller::UpdateLaser() { auto controller_pose = _app->GetTrackerPose(_device_index); @@ -170,7 +193,7 @@ void Controller::UpdateLaser() hmd_local_pos.z = 0; auto hmd_dir = glm::normalize(hmd_local_pos); - VRMat transform = {{{laser_width * hmd_dir.y, 0, laser_width * hmd_dir.x, 0}, {laser_width * -hmd_dir.x, 0, laser_width * hmd_dir.y, 0}, {0, len, 0, len * -0.5f}}}; + VRMat transform = {{{LASER_WIDTH * hmd_dir.y, 0, LASER_WIDTH * hmd_dir.x, 0}, {LASER_WIDTH * -hmd_dir.x, 0, LASER_WIDTH * hmd_dir.y, 0}, {0, len, 0, len * -0.5f}}}; _laser.SetTransformTracker(_device_index, &transform); _laser.SetHidden(!_is_connected || _app->_hidden || (!_app->_edit_mode && !_cursor_active)); } diff --git a/src/controller.h b/src/controller.h index cf810d2..56531f5 100644 --- a/src/controller.h +++ b/src/controller.h @@ -26,7 +26,7 @@ class Controller void ReleaseOverlay(); - void Update(); + void Update(float dtime); bool _cursor_active; @@ -34,6 +34,8 @@ class Controller void UpdateStatus(); void UpdateLaser(); + void UpdateMouseButton(vr::VRActionHandle_t binding, unsigned int button); + App *_app; Overlay _laser; ControllerSide _side; @@ -47,4 +49,6 @@ class Controller Ray _last_ray; glm::vec3 _last_rotation; glm::vec3 _last_pos; + + float _last_sent_scroll; }; diff --git a/src/main.cpp b/src/main.cpp index 617bcc2..ebf2fec 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ #include "app.h" #include -#define UPDATE_RATE 60 +#define UPDATE_RATE 120 bool should_exit = false; @@ -18,8 +18,8 @@ int main() while (!should_exit) { - app.Update(); usleep(1000000 / UPDATE_RATE); + app.Update(1.0 / UPDATE_RATE); } printf("\nShutting down\n"); return 0; From 0b7f841fbffdeb7ebfc71611b13f6f9d1fcd6ba5 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sat, 29 Apr 2023 19:39:51 +0200 Subject: [PATCH 10/10] update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 024e385..2b30833 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ Note: only index controllers have default bindings right now, feel free to make - activate cursor input (default: press touchpad) - left mouse default: trigger - right mouse default: A + - middle mouse default: not bound + - scrolling default: joystick up/down - edit mode (default: long press press right B) - move screens around (default: trigger) - resize screens (move with two controllers)