mirror of
https://github.com/CrispyPin/sinpin-vr.git
synced 2024-11-23 02:20:26 +01:00
move cursor with lasers
This commit is contained in:
parent
0042ee3b58
commit
d204387e19
10 changed files with 139 additions and 50 deletions
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -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"
|
||||
|
|
20
src/app.cpp
20
src/app.cpp
|
@ -1,6 +1,7 @@
|
|||
#include "app.h"
|
||||
#include "controller.h"
|
||||
#include "util.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <cassert>
|
||||
#include <glm/matrix.hpp>
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<Panel> _panels;
|
||||
bool _hidden = false;
|
||||
bool _edit_mode = false;
|
||||
std::optional<Controller *> _active_cursor;
|
||||
|
||||
private:
|
||||
void InitX11();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
13
src/panel.h
13
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:
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue