mirror of
https://github.com/CrispyPin/sinpin-vr.git
synced 2024-11-10 04:20:25 +01:00
Compare commits
10 commits
edca13ca09
...
0b7f841fbf
Author | SHA1 | Date | |
---|---|---|---|
0b7f841fbf | |||
035d9e7296 | |||
858da78820 | |||
|
44cf1f2aef | ||
6d69a24668 | |||
d33eb40c69 | |||
d94e3040bb | |||
29f4595750 | |||
d204387e19 | |||
0042ee3b58 |
14 changed files with 476 additions and 165 deletions
4
Makefile
4
Makefile
|
@ -1,7 +1,7 @@
|
||||||
VERSION=v0.1.0
|
VERSION=v0.2.1
|
||||||
# CC := g++
|
# CC := g++
|
||||||
CC := clang++
|
CC := clang++
|
||||||
LFLAGS := -lX11 -lXrandr -lglfw -lGL
|
LFLAGS := -lX11 -lXrandr -lXtst -lglfw -lGL
|
||||||
LIBS := openvr/libopenvr_api.so
|
LIBS := openvr/libopenvr_api.so
|
||||||
SRC := src/*.cpp
|
SRC := src/*.cpp
|
||||||
OUT := ./sinpin_vr
|
OUT := ./sinpin_vr
|
||||||
|
|
13
README.md
13
README.md
|
@ -1,14 +1,21 @@
|
||||||
# sinpin-vr
|
# sinpin-vr
|
||||||
A SteamVR overlay for Linux+X11 that displays all your screens in 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.
|
||||||
|
|
||||||
## features
|
## features
|
||||||
- one overlay per screen
|
- one overlay per screen
|
||||||
- shows cursor position
|
- 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)
|
- 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
|
||||||
|
- middle mouse default: not bound
|
||||||
|
- scrolling default: joystick up/down
|
||||||
|
- edit mode (default: long press press right B)
|
||||||
- move screens around (default: trigger)
|
- move screens around (default: trigger)
|
||||||
- resize screens (move with two controllers)
|
- resize screens (move with two controllers)
|
||||||
- push/pull screens (default: joystick up/down)
|
- push/pull screens (default: joystick up/down)
|
||||||
|
|
|
@ -16,18 +16,43 @@
|
||||||
"requirement": "mandatory",
|
"requirement": "mandatory",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "/actions/main/in/grab",
|
|
||||||
"requirement": "mandatory",
|
|
||||||
"type": "boolean"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "/actions/main/in/reset",
|
"name": "/actions/main/in/reset",
|
||||||
"requirement": "suggested",
|
"requirement": "suggested",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "/actions/main/in/distance",
|
"name": "/actions/edit/in/grab",
|
||||||
|
"requirement": "mandatory",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "/actions/cursor/in/mouse_middle",
|
||||||
|
"requirement": "optional",
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "/actions/cursor/in/scroll",
|
||||||
"requirement": "suggested",
|
"requirement": "suggested",
|
||||||
"type": "vector2"
|
"type": "vector2"
|
||||||
}
|
}
|
||||||
|
@ -36,17 +61,29 @@
|
||||||
{
|
{
|
||||||
"name": "/actions/main",
|
"name": "/actions/main",
|
||||||
"usage": "leftright"
|
"usage": "leftright"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "/actions/edit",
|
||||||
|
"usage": "single"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "/actions/cursor",
|
||||||
|
"usage": "single"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"localization": [
|
"localization": [
|
||||||
{
|
{
|
||||||
"language_tag": "en_us",
|
"language_tag": "en_us",
|
||||||
"/actions/main": "Overlay actions",
|
"/actions/main/in/toggle_visibility": "toggle visibility",
|
||||||
"/actions/main/in/toggle_visibility": "Toggle visibility",
|
"/actions/main/in/edit_mode": "toggle edit mode",
|
||||||
"/actions/main/in/edit_mode": "Toggle edit mode",
|
"/actions/main/in/reset": "reset positions",
|
||||||
"/actions/main/in/grab": "grab panel",
|
"/actions/edit/in/grab": "grab panel",
|
||||||
"/actions/main/in/distance": "Move away",
|
"/actions/edit/in/distance": "push/pull overlay",
|
||||||
"/actions/main/in/reset": "Reset positions"
|
"/actions/cursor/in/activate_cursor": "activate cursor",
|
||||||
|
"/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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -140,6 +140,122 @@
|
||||||
},
|
},
|
||||||
"app_key" : "system.generated.sinpin_vr",
|
"app_key" : "system.generated.sinpin_vr",
|
||||||
"bindings" : {
|
"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"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"/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" : {
|
"/actions/legacy" : {
|
||||||
"haptics" : [
|
"haptics" : [
|
||||||
{
|
{
|
||||||
|
@ -588,60 +704,6 @@
|
||||||
},
|
},
|
||||||
"/actions/main" : {
|
"/actions/main" : {
|
||||||
"sources" : [
|
"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" : {
|
"inputs" : {
|
||||||
"long" : {
|
"long" : {
|
||||||
|
@ -650,6 +712,27 @@
|
||||||
},
|
},
|
||||||
"mode" : "button",
|
"mode" : "button",
|
||||||
"path" : "/user/hand/left/input/a"
|
"path" : "/user/hand/left/input/a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs" : {
|
||||||
|
"click" : {
|
||||||
|
"output" : "/actions/main/in/mouse_left"
|
||||||
|
},
|
||||||
|
"long" : {
|
||||||
|
"output" : "/actions/main/in/toggle_visibility"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode" : "button",
|
||||||
|
"path" : "/user/hand/left/input/b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs" : {
|
||||||
|
"long" : {
|
||||||
|
"output" : "/actions/main/in/edit_mode"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mode" : "button",
|
||||||
|
"path" : "/user/hand/right/input/b"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -658,7 +741,7 @@
|
||||||
"controller_type" : "knuckles",
|
"controller_type" : "knuckles",
|
||||||
"description" : "yes",
|
"description" : "yes",
|
||||||
"interaction_profile" : "",
|
"interaction_profile" : "",
|
||||||
"name" : "Saved sinpin_vr bindings",
|
"name" : "Default sinpin_vr bindings",
|
||||||
"options" : {
|
"options" : {
|
||||||
"mirror_actions" : true,
|
"mirror_actions" : true,
|
||||||
"simulated_controller_type" : "none"
|
"simulated_controller_type" : "none"
|
||||||
|
|
106
src/app.cpp
106
src/app.cpp
|
@ -1,12 +1,16 @@
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/extensions/XTest.h>
|
||||||
#include <X11/extensions/Xrandr.h>
|
#include <X11/extensions/Xrandr.h>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <glm/matrix.hpp>
|
#include <glm/matrix.hpp>
|
||||||
|
|
||||||
const VRMat root_start_pose = {{{1, 0, 0, 0}, {0, 1, 0, 0.8f}, {0, 0, 1, 0}}}; // 0.8m above origin
|
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()
|
App::App()
|
||||||
{
|
{
|
||||||
_tracking_origin = vr::TrackingUniverseStanding;
|
_tracking_origin = vr::TrackingUniverseStanding;
|
||||||
|
@ -51,17 +55,31 @@ App::App()
|
||||||
printf("actions path: %s\n", _actions_path.c_str());
|
printf("actions path: %s\n", _actions_path.c_str());
|
||||||
vr_input->SetActionManifestPath(_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);
|
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);
|
assert(action_err == 0);
|
||||||
action_err = vr_input->GetActionHandle("/actions/main/in/edit_mode", &_input_handles.edit_mode);
|
action_err = vr_input->GetActionHandle("/actions/cursor/in/activate_cursor", &_input_handles.cursor.activate);
|
||||||
assert(action_err == 0);
|
assert(action_err == 0);
|
||||||
action_err = vr_input->GetActionHandle("/actions/main/in/reset", &_input_handles.reset);
|
action_err = vr_input->GetActionHandle("/actions/main/in/edit_mode", &_input_handles.main.edit_mode);
|
||||||
assert(action_err == 0);
|
assert(action_err == 0);
|
||||||
action_err = vr_input->GetActionHandle("/actions/main/in/distance", &_input_handles.distance);
|
action_err = vr_input->GetActionHandle("/actions/main/in/reset", &_input_handles.main.reset);
|
||||||
assert(action_err == 0);
|
assert(action_err == 0);
|
||||||
action_err = vr_input->GetActionSetHandle("/actions/main", &_input_handles.set);
|
action_err = vr_input->GetActionHandle("/actions/edit/in/distance", &_input_handles.edit.distance);
|
||||||
|
assert(action_err == 0);
|
||||||
|
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/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);
|
||||||
|
assert(action_err == 0);
|
||||||
|
action_err = vr_input->GetActionSetHandle("/actions/cursor", &_input_handles.cursor_set);
|
||||||
assert(action_err == 0);
|
assert(action_err == 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,9 +144,9 @@ void App::InitRootOverlay()
|
||||||
_root_overlay.SetTextureToColor(110, 30, 190);
|
_root_overlay.SetTextureToColor(110, 30, 190);
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::Update()
|
void App::Update(float dtime)
|
||||||
{
|
{
|
||||||
UpdateInput();
|
UpdateInput(dtime);
|
||||||
if (!_hidden)
|
if (!_hidden)
|
||||||
{
|
{
|
||||||
_root_overlay.Update();
|
_root_overlay.Update();
|
||||||
|
@ -141,32 +159,40 @@ void App::Update()
|
||||||
_frames_since_framebuffer += 1;
|
_frames_since_framebuffer += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void App::UpdateInput()
|
void App::UpdateInput(float dtime)
|
||||||
{
|
{
|
||||||
vr::VRActiveActionSet_t main;
|
vr::VRActiveActionSet_t active_sets[2];
|
||||||
main.ulActionSet = _input_handles.set;
|
active_sets[0].ulActionSet = _input_handles.main_set;
|
||||||
main.ulRestrictedToDevice = 0;
|
active_sets[0].ulRestrictedToDevice = 0;
|
||||||
main.nPriority = 10;
|
active_sets[0].nPriority = 10;
|
||||||
vr::EVRInputError err = vr_input->UpdateActionState(&main, sizeof(vr::VRActiveActionSet_t), 1);
|
int set_count = 1;
|
||||||
if (err)
|
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);
|
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;
|
_hidden = !_hidden;
|
||||||
for (auto &panel : _panels)
|
for (auto &panel : _panels)
|
||||||
{
|
{
|
||||||
panel.SetHidden(_hidden);
|
panel.SetHidden(_hidden);
|
||||||
}
|
}
|
||||||
_root_overlay.SetHidden(_hidden || !_edit_mode);
|
UpdateUIVisibility();
|
||||||
_controllers[0]->SetHidden(_hidden || !_edit_mode);
|
|
||||||
_controllers[1]->SetHidden(_hidden || !_edit_mode);
|
|
||||||
}
|
}
|
||||||
if (IsInputJustPressed(_input_handles.reset))
|
if (!_hidden)
|
||||||
|
{
|
||||||
|
if (IsInputJustPressed(_input_handles.main.reset))
|
||||||
{
|
{
|
||||||
_root_overlay.SetTransformWorld(&root_start_pose);
|
_root_overlay.SetTransformWorld(&root_start_pose);
|
||||||
_root_overlay.SetWidth(0.25f);
|
_root_overlay.SetWidth(0.25f);
|
||||||
|
@ -175,23 +201,30 @@ void App::UpdateInput()
|
||||||
panel.ResetTransform();
|
panel.ResetTransform();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!_hidden && IsInputJustPressed(_input_handles.edit_mode))
|
if (IsInputJustPressed(_input_handles.main.edit_mode))
|
||||||
{
|
{
|
||||||
_edit_mode = !_edit_mode;
|
_edit_mode = !_edit_mode;
|
||||||
_root_overlay.SetHidden(_hidden || !_edit_mode);
|
UpdateUIVisibility();
|
||||||
_controllers[0]->SetHidden(_hidden || !_edit_mode);
|
if (_edit_mode && _active_cursor.has_value())
|
||||||
_controllers[1]->SetHidden(_hidden || !_edit_mode);
|
|
||||||
}
|
|
||||||
if (_edit_mode)
|
|
||||||
{
|
{
|
||||||
_controllers[0]->Update();
|
_active_cursor.value()->_cursor_active = false;
|
||||||
_controllers[1]->Update();
|
_active_cursor = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
_controllers[0]->Update(dtime);
|
||||||
|
_controllers[1]->Update(dtime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::UpdateUIVisibility()
|
||||||
|
{
|
||||||
|
bool state = _hidden || !_edit_mode;
|
||||||
|
_root_overlay.SetHidden(state);
|
||||||
|
}
|
||||||
|
|
||||||
void App::UpdateFramebuffer()
|
void App::UpdateFramebuffer()
|
||||||
{
|
{
|
||||||
if (_frames_since_framebuffer < 2)
|
if (_frames_since_framebuffer < FRAME_INTERVAL)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +288,7 @@ Ray App::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len)
|
||||||
|
|
||||||
for (auto &panel : _panels)
|
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)
|
if (r_panel.distance < ray.distance)
|
||||||
{
|
{
|
||||||
ray = r_panel;
|
ray = r_panel;
|
||||||
|
@ -281,3 +314,14 @@ CursorPos App::GetCursorPosition()
|
||||||
&buttons);
|
&buttons);
|
||||||
return pos;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void App::SendMouseInput(unsigned int button, bool state)
|
||||||
|
{
|
||||||
|
XTestFakeButtonEvent(_xdisplay, button, state, 0);
|
||||||
|
}
|
||||||
|
|
30
src/app.h
30
src/app.h
|
@ -18,12 +18,28 @@ struct CursorPos
|
||||||
|
|
||||||
struct InputHandles
|
struct InputHandles
|
||||||
{
|
{
|
||||||
vr::VRActionSetHandle_t set;
|
struct
|
||||||
|
{
|
||||||
vr::VRActionHandle_t toggle_hidden;
|
vr::VRActionHandle_t toggle_hidden;
|
||||||
vr::VRActionHandle_t distance;
|
|
||||||
vr::VRActionHandle_t grab;
|
|
||||||
vr::VRActionHandle_t edit_mode;
|
vr::VRActionHandle_t edit_mode;
|
||||||
vr::VRActionHandle_t reset;
|
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;
|
||||||
|
vr::VRActionHandle_t mouse_middle;
|
||||||
|
vr::VRActionHandle_t scroll;
|
||||||
|
} cursor;
|
||||||
|
vr::VRActionSetHandle_t cursor_set;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
vr::VRActionHandle_t distance;
|
||||||
|
vr::VRActionHandle_t grab;
|
||||||
|
} edit;
|
||||||
|
vr::VRActionSetHandle_t edit_set;
|
||||||
};
|
};
|
||||||
|
|
||||||
class App
|
class App
|
||||||
|
@ -31,7 +47,7 @@ class App
|
||||||
public:
|
public:
|
||||||
App();
|
App();
|
||||||
~App();
|
~App();
|
||||||
void Update();
|
void Update(float dtime);
|
||||||
|
|
||||||
std::vector<TrackerID> GetControllers();
|
std::vector<TrackerID> GetControllers();
|
||||||
glm::mat4 GetTrackerPose(TrackerID tracker);
|
glm::mat4 GetTrackerPose(TrackerID tracker);
|
||||||
|
@ -41,6 +57,8 @@ class App
|
||||||
CursorPos GetCursorPosition();
|
CursorPos GetCursorPosition();
|
||||||
|
|
||||||
Ray IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len);
|
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;
|
Display *_xdisplay;
|
||||||
Window _root_window;
|
Window _root_window;
|
||||||
|
@ -69,6 +87,7 @@ class App
|
||||||
std::vector<Panel> _panels;
|
std::vector<Panel> _panels;
|
||||||
bool _hidden = false;
|
bool _hidden = false;
|
||||||
bool _edit_mode = false;
|
bool _edit_mode = false;
|
||||||
|
std::optional<Controller *> _active_cursor;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitX11();
|
void InitX11();
|
||||||
|
@ -77,5 +96,6 @@ class App
|
||||||
void InitRootOverlay();
|
void InitRootOverlay();
|
||||||
|
|
||||||
void UpdateFramebuffer();
|
void UpdateFramebuffer();
|
||||||
void UpdateInput();
|
void UpdateInput(float dtime);
|
||||||
|
void UpdateUIVisibility();
|
||||||
};
|
};
|
|
@ -4,7 +4,10 @@
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
const float width = 0.004f;
|
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)
|
Controller::Controller(App *app, ControllerSide side)
|
||||||
{
|
{
|
||||||
|
@ -13,7 +16,8 @@ Controller::Controller(App *app, ControllerSide side)
|
||||||
_input_handle = 0;
|
_input_handle = 0;
|
||||||
_is_connected = false;
|
_is_connected = false;
|
||||||
_side = side;
|
_side = side;
|
||||||
_hidden = false;
|
_cursor_active = false;
|
||||||
|
_last_sent_scroll = 0;
|
||||||
|
|
||||||
std::string laser_name = "controller_laser_";
|
std::string laser_name = "controller_laser_";
|
||||||
if (side == ControllerSide::Left)
|
if (side == ControllerSide::Left)
|
||||||
|
@ -23,7 +27,7 @@ Controller::Controller(App *app, ControllerSide side)
|
||||||
|
|
||||||
_laser = Overlay(app, laser_name);
|
_laser = Overlay(app, laser_name);
|
||||||
UpdateStatus();
|
UpdateStatus();
|
||||||
_laser.SetTextureToColor(255, 200, 255);
|
_laser.SetTextureToColor(255, 255, 255);
|
||||||
_laser.SetAlpha(0.2f);
|
_laser.SetAlpha(0.2f);
|
||||||
_laser.SetHidden(true);
|
_laser.SetHidden(true);
|
||||||
}
|
}
|
||||||
|
@ -48,12 +52,6 @@ bool Controller::IsConnected()
|
||||||
return _is_connected;
|
return _is_connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::SetHidden(bool state)
|
|
||||||
{
|
|
||||||
_hidden = state;
|
|
||||||
_laser.SetHidden(_hidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::ReleaseOverlay()
|
void Controller::ReleaseOverlay()
|
||||||
{
|
{
|
||||||
_grabbed_overlay = nullptr;
|
_grabbed_overlay = nullptr;
|
||||||
|
@ -74,22 +72,109 @@ glm::vec3 Controller::GetLastRot()
|
||||||
return _last_rotation;
|
return _last_rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::Update()
|
void Controller::Update(float dtime)
|
||||||
{
|
{
|
||||||
UpdateStatus();
|
UpdateStatus();
|
||||||
if (!_is_connected || _hidden)
|
if (!_is_connected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateLaser();
|
UpdateLaser();
|
||||||
|
|
||||||
float move = _app->GetInputAnalog(_app->_input_handles.distance, _input_handle).y * 0.1; // TODO use frame time
|
if (_app->_edit_mode)
|
||||||
if (_grabbed_overlay && move != 0.0f)
|
{
|
||||||
|
_laser.SetColor(EDIT_COLOR);
|
||||||
|
if (_last_ray.overlay != nullptr)
|
||||||
|
{
|
||||||
|
auto ray = _last_ray;
|
||||||
|
if (_app->IsInputJustPressed(_app->_input_handles.edit.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.edit.distance, _input_handle).y * dtime * 8;
|
||||||
|
if (move != 0.0f)
|
||||||
{
|
{
|
||||||
auto transform = _grabbed_overlay->GetTarget()->transform;
|
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
|
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);
|
_grabbed_overlay->SetTransformTracker(_device_index, &transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else // cursor mode
|
||||||
|
{
|
||||||
|
if (_app->IsInputJustPressed(_app->_input_handles.cursor.activate, _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;
|
||||||
|
_laser.SetColor(CURSOR_COLOR);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
_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()
|
void Controller::UpdateLaser()
|
||||||
{
|
{
|
||||||
|
@ -108,24 +193,9 @@ void Controller::UpdateLaser()
|
||||||
hmd_local_pos.z = 0;
|
hmd_local_pos.z = 0;
|
||||||
auto hmd_dir = glm::normalize(hmd_local_pos);
|
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.SetTransformTracker(_device_index, &transform);
|
||||||
|
_laser.SetHidden(!_is_connected || _app->_hidden || (!_app->_edit_mode && !_cursor_active));
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::UpdateStatus()
|
void Controller::UpdateStatus()
|
||||||
|
@ -145,8 +215,4 @@ void Controller::UpdateStatus()
|
||||||
_device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
|
_device_index = _app->vr_sys->GetTrackedDeviceIndexForControllerRole(vr::TrackedControllerRole_RightHand);
|
||||||
}
|
}
|
||||||
_is_connected &= _device_index < MAX_TRACKERS;
|
_is_connected &= _device_index < MAX_TRACKERS;
|
||||||
if (!_is_connected)
|
|
||||||
{
|
|
||||||
_laser.SetHidden(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,25 +24,31 @@ class Controller
|
||||||
glm::vec3 GetLastPos();
|
glm::vec3 GetLastPos();
|
||||||
glm::vec3 GetLastRot();
|
glm::vec3 GetLastRot();
|
||||||
|
|
||||||
void SetHidden(bool state);
|
|
||||||
|
|
||||||
void ReleaseOverlay();
|
void ReleaseOverlay();
|
||||||
|
|
||||||
void Update();
|
void Update(float dtime);
|
||||||
|
|
||||||
|
bool _cursor_active;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdateStatus();
|
void UpdateStatus();
|
||||||
void UpdateLaser();
|
void UpdateLaser();
|
||||||
|
|
||||||
|
void UpdateMouseButton(vr::VRActionHandle_t binding, unsigned int button);
|
||||||
|
|
||||||
App *_app;
|
App *_app;
|
||||||
Overlay _laser;
|
Overlay _laser;
|
||||||
ControllerSide _side;
|
ControllerSide _side;
|
||||||
TrackerID _device_index;
|
TrackerID _device_index;
|
||||||
vr::VRInputValueHandle_t _input_handle;
|
vr::VRInputValueHandle_t _input_handle;
|
||||||
|
|
||||||
bool _is_connected;
|
bool _is_connected;
|
||||||
bool _hidden;
|
|
||||||
Overlay *_grabbed_overlay;
|
Overlay *_grabbed_overlay;
|
||||||
|
|
||||||
Ray _last_ray;
|
Ray _last_ray;
|
||||||
glm::vec3 _last_rotation;
|
glm::vec3 _last_rotation;
|
||||||
glm::vec3 _last_pos;
|
glm::vec3 _last_pos;
|
||||||
|
|
||||||
|
float _last_sent_scroll;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
#define UPDATE_RATE 60
|
#define UPDATE_RATE 120
|
||||||
|
|
||||||
bool should_exit = false;
|
bool should_exit = false;
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ int main()
|
||||||
|
|
||||||
while (!should_exit)
|
while (!should_exit)
|
||||||
{
|
{
|
||||||
app.Update();
|
|
||||||
usleep(1000000 / UPDATE_RATE);
|
usleep(1000000 / UPDATE_RATE);
|
||||||
|
app.Update(1.0 / UPDATE_RATE);
|
||||||
}
|
}
|
||||||
printf("\nShutting down\n");
|
printf("\nShutting down\n");
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -108,6 +108,17 @@ void Overlay::SetTextureToColor(uint8_t r, uint8_t g, uint8_t b)
|
||||||
assert(set_texture_err == 0);
|
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)
|
void Overlay::SetTransformTracker(TrackerID tracker, const VRMat *transform)
|
||||||
{
|
{
|
||||||
auto original_pose = _target.transform;
|
auto original_pose = _target.transform;
|
||||||
|
@ -169,7 +180,7 @@ Ray Overlay::IntersectRay(glm::vec3 origin, glm::vec3 direction, float max_len)
|
||||||
{
|
{
|
||||||
dist = glm::min(r * max_len, 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()
|
glm::mat4x4 Overlay::GetTransformAbsolute()
|
||||||
|
@ -208,10 +219,10 @@ void Overlay::Update()
|
||||||
|
|
||||||
if (_holding_controller != nullptr)
|
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)
|
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)
|
if (!resize_controller_holding)
|
||||||
{
|
{
|
||||||
_resize_controller = nullptr;
|
_resize_controller = nullptr;
|
||||||
|
|
|
@ -43,6 +43,8 @@ class Overlay
|
||||||
void SetRatio(float ratio);
|
void SetRatio(float ratio);
|
||||||
void SetTexture(vr::Texture_t *texture);
|
void SetTexture(vr::Texture_t *texture);
|
||||||
void SetTextureToColor(uint8_t r, uint8_t g, uint8_t b);
|
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();
|
glm::mat4x4 GetTransformAbsolute();
|
||||||
Target *GetTarget();
|
Target *GetTarget();
|
||||||
|
|
|
@ -68,6 +68,18 @@ void Panel::SetHidden(bool state)
|
||||||
_overlay.SetHidden(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()
|
void Panel::UpdateCursor()
|
||||||
{
|
{
|
||||||
auto global_pos = _app->GetCursorPosition();
|
auto global_pos = _app->GetCursorPosition();
|
||||||
|
|
13
src/panel.h
13
src/panel.h
|
@ -19,6 +19,19 @@ class Panel
|
||||||
void SetHidden(bool state);
|
void SetHidden(bool state);
|
||||||
void ResetTransform();
|
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();
|
Overlay *GetOverlay();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
10
src/util.h
10
src/util.h
|
@ -11,10 +11,20 @@ const VRMat VRMatIdentity{{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}}};
|
||||||
const int MAX_TRACKERS = vr::k_unMaxTrackedDeviceCount;
|
const int MAX_TRACKERS = vr::k_unMaxTrackedDeviceCount;
|
||||||
|
|
||||||
class Overlay;
|
class Overlay;
|
||||||
|
class Panel;
|
||||||
struct Ray
|
struct Ray
|
||||||
{
|
{
|
||||||
Overlay *overlay;
|
Overlay *overlay;
|
||||||
float distance;
|
float distance;
|
||||||
|
glm::vec3 local_pos;
|
||||||
|
Panel *hit_panel;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Color
|
||||||
|
{
|
||||||
|
float r;
|
||||||
|
float g;
|
||||||
|
float b;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void PrintVec(glm::vec3 v)
|
inline void PrintVec(glm::vec3 v)
|
||||||
|
|
Loading…
Reference in a new issue