219 lines
8.4 KiB
C++
219 lines
8.4 KiB
C++
|
#include "vr.h"
|
||
|
#include "misc/vrutil.h"
|
||
|
#include "util/logging.h"
|
||
|
#include "games/io.h"
|
||
|
#include "games/drs/drs.h"
|
||
|
#include "avs/game.h"
|
||
|
#include "overlay/imgui/extensions.h"
|
||
|
|
||
|
namespace overlay::windows {
|
||
|
|
||
|
VRWindow::VRWindow(SpiceOverlay *overlay) : Window(overlay) {
|
||
|
this->title = "VR";
|
||
|
this->flags = ImGuiWindowFlags_None;
|
||
|
this->toggle_button = games::OverlayButtons::ToggleVRControl;
|
||
|
this->init_size = ImVec2(500, 800);
|
||
|
this->size_min = ImVec2(250, 200);
|
||
|
}
|
||
|
|
||
|
VRWindow::~VRWindow() {
|
||
|
}
|
||
|
|
||
|
void VRWindow::build_content() {
|
||
|
ImGui::BeginTabBar("VRTabBar");
|
||
|
if (ImGui::BeginTabItem("Info")) {
|
||
|
build_info();
|
||
|
ImGui::EndTabItem();
|
||
|
}
|
||
|
if (avs::game::is_model("REC")) {
|
||
|
if (ImGui::BeginTabItem("Dancefloor")) {
|
||
|
build_dancefloor();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void VRWindow::build_info() {
|
||
|
|
||
|
// status
|
||
|
auto status = vrutil::STATUS;
|
||
|
switch (status) {
|
||
|
case vrutil::VRStatus::Disabled:
|
||
|
ImGui::TextColored(
|
||
|
ImVec4(0.4f, 0.4f, 0.4f, 1.f),
|
||
|
"Disabled");
|
||
|
if (ImGui::Button("Start")) {
|
||
|
vrutil::init();
|
||
|
if (avs::game::is_model("REC")) {
|
||
|
games::drs::start_vr();
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case vrutil::VRStatus::Error:
|
||
|
ImGui::TextColored(
|
||
|
ImVec4(0.8f, 0.1f, 0.1f, 1.f),
|
||
|
"Error");
|
||
|
if (ImGui::Button("Restart")) {
|
||
|
vrutil::shutdown();
|
||
|
vrutil::init();
|
||
|
}
|
||
|
break;
|
||
|
case vrutil::VRStatus::Running:
|
||
|
ImGui::TextColored(
|
||
|
ImVec4(0.1f, 0.8f, 0.1f, 1.f),
|
||
|
"Running");
|
||
|
if (ImGui::Button("Stop")) {
|
||
|
vrutil::shutdown();
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// rescan
|
||
|
if (ImGui::Button("Rescan Devices")) {
|
||
|
vrutil::scan(true);
|
||
|
}
|
||
|
|
||
|
// data table header
|
||
|
ImGui::Columns(2);
|
||
|
ImGui::Text("Device");
|
||
|
ImGui::NextColumn();
|
||
|
ImGui::Text("Position");
|
||
|
ImGui::NextColumn();
|
||
|
ImGui::Separator();
|
||
|
|
||
|
// HMD/Left/Right data
|
||
|
vr::TrackedDevicePose_t hmd_pose, left_pose, right_pose;
|
||
|
vr::VRControllerState_t left_state, right_state;
|
||
|
vrutil::get_hmd_pose(&hmd_pose);
|
||
|
vrutil::get_con_pose(vrutil::INDEX_LEFT, &left_pose, &left_state);
|
||
|
vrutil::get_con_pose(vrutil::INDEX_RIGHT, &right_pose, &right_state);
|
||
|
auto hmd_pos = vrutil::get_translation(hmd_pose.mDeviceToAbsoluteTracking);
|
||
|
auto left_pos = vrutil::get_translation(left_pose.mDeviceToAbsoluteTracking);
|
||
|
auto right_pos = vrutil::get_translation(right_pose.mDeviceToAbsoluteTracking);
|
||
|
ImGui::Text("HMD");
|
||
|
ImGui::NextColumn();
|
||
|
ImGui::TextUnformatted(fmt::format(
|
||
|
"X={:3f} Y={:3f} Z={:3f}",
|
||
|
hmd_pos.x, hmd_pos.y, hmd_pos.z).c_str());
|
||
|
ImGui::NextColumn();
|
||
|
ImGui::Text("Left");
|
||
|
ImGui::NextColumn();
|
||
|
ImGui::TextUnformatted(fmt::format(
|
||
|
"X={:3f} Y={:3f} Z={:3f}",
|
||
|
left_pos.x, left_pos.y, left_pos.z).c_str());
|
||
|
ImGui::NextColumn();
|
||
|
ImGui::Text("Right");
|
||
|
ImGui::NextColumn();
|
||
|
ImGui::TextUnformatted(fmt::format(
|
||
|
"X={:3f} Y={:3f} Z={:3f}",
|
||
|
right_pos.x, right_pos.y, right_pos.z).c_str());
|
||
|
ImGui::NextColumn();
|
||
|
}
|
||
|
|
||
|
void VRWindow::build_dancefloor() {
|
||
|
ImGui::Separator();
|
||
|
|
||
|
// settings
|
||
|
ImGui::DragFloat3("Scale", &games::drs::VR_SCALE[0], 0.1f);
|
||
|
ImGui::DragFloat3("Offset", &games::drs::VR_OFFSET[0], 0.1f);
|
||
|
ImGui::DragFloat("Rotation", &games::drs::VR_ROTATION, 0.5f);
|
||
|
for (int i = 0; i < (int) std::size(games::drs::VR_FOOTS); ++i) {
|
||
|
auto &foot = games::drs::VR_FOOTS[i];
|
||
|
ImGui::Separator();
|
||
|
ImGui::PushID(&foot);
|
||
|
ImGui::Text("%s Foot", i == 0 ? "Left" : "Right");
|
||
|
ImGui::InputInt("Device Index", (int*) &foot.index, 1, 1);
|
||
|
ImGui::DragFloat("Length", &foot.length,
|
||
|
0.005f, 0.001f, 1000.f);
|
||
|
ImGui::DragFloat("Size Base", &foot.size_base,
|
||
|
0.005f, 0.001f, 1000.f);
|
||
|
ImGui::DragFloat("Size Scale", &foot.size_scale,
|
||
|
0.005f, 0.001f, 1000.f);
|
||
|
ImGui::DragFloat4("Rotation Quat", &foot.rotation.x, 0.001f, -1, 1);
|
||
|
if (ImGui::Button("Calibrate")) {
|
||
|
vr::TrackedDevicePose_t pose;
|
||
|
vr::VRControllerState_t state;
|
||
|
vrutil::get_con_pose(foot.get_index(), &pose, &state);
|
||
|
foot.length = foot.height + 0.02f;
|
||
|
auto pose_rot = vrutil::get_rotation(pose.mDeviceToAbsoluteTracking.m);
|
||
|
foot.rotation = linalg::qmul(linalg::qinv(pose_rot),
|
||
|
vrutil::get_rotation((float) M_PI * -0.5f, 0, 0));
|
||
|
}
|
||
|
ImGui::SameLine();
|
||
|
ImGui::HelpMarker("Place the controller to the lower part of your leg "
|
||
|
"and press this button to auto calibrate angle and length");
|
||
|
ImGui::PopID();
|
||
|
}
|
||
|
|
||
|
// prepare view
|
||
|
auto draw_list = ImGui::GetWindowDrawList();
|
||
|
auto canvas_pos = ImGui::GetCursorScreenPos();
|
||
|
auto canvas_size = ImGui::GetContentRegionAvail();
|
||
|
float offset_x = canvas_size.x * 0.5f;
|
||
|
float offset_y = canvas_size.y * 0.1f;
|
||
|
float off_x = offset_x + canvas_pos.x;
|
||
|
float off_y = offset_y + canvas_pos.y;
|
||
|
float scale = std::min(canvas_size.x, canvas_size.y) / 60;
|
||
|
|
||
|
// axis
|
||
|
draw_list->AddLine(
|
||
|
ImVec2(canvas_pos.x, off_y),
|
||
|
ImVec2(canvas_pos.x + canvas_size.x, off_y),
|
||
|
ImColor(255, 0, 0, 128));
|
||
|
draw_list->AddLine(
|
||
|
ImVec2(off_x, canvas_pos.y),
|
||
|
ImVec2(off_x, canvas_pos.y + canvas_size.y),
|
||
|
ImColor(0, 255, 0, 128));
|
||
|
|
||
|
// tiles
|
||
|
for (int x = 0; x < 38; x++) {
|
||
|
for (int y = 0; y < 49; y++) {
|
||
|
auto &led = games::drs::DRS_TAPELED[x + y * 38];
|
||
|
ImColor color((int) led[0], (int) led[1], (int) led[2]);
|
||
|
ImVec2 p1((x - 19) * scale + off_x, (y + 0) * scale + off_y);
|
||
|
ImVec2 p2((x - 18) * scale + off_x, (y + 1) * scale + off_y);
|
||
|
draw_list->AddRectFilled(p1, p2, color, 0.f);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// foots
|
||
|
const float foot_box = 2.f * scale;
|
||
|
for (auto &foot : games::drs::VR_FOOTS) {
|
||
|
vr::TrackedDevicePose_t pose;
|
||
|
vr::VRControllerState_t state;
|
||
|
vrutil::get_con_pose(foot.get_index(), &pose, &state);
|
||
|
if (pose.bPoseIsValid) {
|
||
|
|
||
|
// position
|
||
|
auto pos = vrutil::get_translation(pose.mDeviceToAbsoluteTracking);
|
||
|
pos = foot.to_world(pos);
|
||
|
pos.x -= 19;
|
||
|
pos *= scale;
|
||
|
ImColor color(255, 0, 255);
|
||
|
if (foot.event.type == games::drs::DRS_DOWN
|
||
|
|| (foot.event.type == games::drs::DRS_MOVE)) {
|
||
|
auto size_factor = foot.event.width / (foot.size_base + foot.size_scale);
|
||
|
color = ImColor((int) (size_factor * 127) + 128, 0, 0);
|
||
|
}
|
||
|
ImVec2 p1(pos.x + off_x - foot_box * 0.5f,
|
||
|
pos.y + off_y - foot_box * 0.5f);
|
||
|
ImVec2 p2(pos.x + off_x + foot_box * 0.5f,
|
||
|
pos.y + off_y + foot_box * 0.5f);
|
||
|
draw_list->AddRectFilled(p1, p2, color, 0.f);
|
||
|
|
||
|
// direction
|
||
|
auto direction = -linalg::qzdir(linalg::qmul(
|
||
|
vrutil::get_rotation(pose.mDeviceToAbsoluteTracking.m),
|
||
|
foot.rotation));
|
||
|
direction = linalg::aliases::float3 {
|
||
|
-direction.z, direction.x, direction.y
|
||
|
};
|
||
|
auto end = pos + direction * foot.length * scale;
|
||
|
draw_list->AddLine(
|
||
|
ImVec2(pos.x + off_x, pos.y + off_y),
|
||
|
ImVec2(end.x + off_x, end.y + off_y),
|
||
|
ImColor(0, 255, 0));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|