gui: Add gui for tracking overrides

This commit is contained in:
Christoph Haag 2021-02-16 22:19:50 +01:00
parent 5e4c62c8aa
commit de169bf575
6 changed files with 332 additions and 0 deletions

View file

@ -15,6 +15,7 @@ set(GUI_SOURCE_FILES
gui_scene_main_menu.c
gui_scene_remote.c
gui_scene_video.c
gui_scene_tracking_overrides.c
../../../external/imgui/imgui/cimgui.cpp
../../../external/imgui/imgui/cimgui.h
../../../external/imgui/imgui/cimplot.cpp

View file

@ -197,6 +197,14 @@ gui_scene_main_menu(struct gui_program *p);
void
gui_scene_select_video_calibrate(struct gui_program *p);
/*!
* Shows a UI that lets you set up tracking overrides.
*
* @ingroup gui
*/
void
gui_scene_tracking_overrides(struct gui_program *p);
/*!
* Regular debug UI.
*

View file

@ -34,6 +34,12 @@ scene_render(struct gui_scene *scene, struct gui_program *p)
gui_scene_select_video_calibrate(p);
}
if (igButton("Tracking Overrides", button_dims)) {
gui_scene_delete_me(p, scene);
gui_scene_tracking_overrides(p);
}
if (igButton("Debug Test", button_dims)) {
gui_scene_delete_me(p, scene);

View file

@ -0,0 +1,314 @@
// Copyright 2021, Collabora, Ltd.
// SPDX-License-Identifier: BSL-1.0
/*!
* @file
* @brief A very small scene that lets the user configure tracking overrides.
* @author Christoph Haag <christoph.haag@collabora.com>
* @author Jakob Bornecrantz <jakob@collabora.com>
* @ingroup gui
*/
#include "util/u_misc.h"
#include "util/u_format.h"
#include "util/u_config_json.h"
#include "math/m_api.h"
#include "xrt/xrt_prober.h"
#include "xrt/xrt_settings.h"
#include "gui_common.h"
#include "gui_imgui.h"
struct gui_tracking_overrides
{
struct gui_scene base;
int editing_override;
bool add_one;
int add_target;
int add_tracker;
struct u_config_json config;
struct xrt_pose reset_offset;
size_t num_overrides;
struct xrt_tracking_override overrides[XRT_MAX_TRACKING_OVERRIDES];
};
static ImVec2 button_dims = {256 + 64, 0};
/*
*
* Internal functions.
*
*/
#define NAME_LENGTH XRT_DEVICE_NAME_LEN * 2 + 5
static void
make_name(struct xrt_device *xdev, char *buf)
{
snprintf(buf, NAME_LENGTH, "%s | %s", xdev->str, xdev->serial);
}
static void
handle_draggable_vec3_f32(const char *name, struct xrt_vec3 *v, const struct xrt_vec3 *reset)
{
float min = -256.0f;
float max = 256.0f;
char tmp[256];
snprintf(tmp, sizeof(tmp), "%s.reset", name);
if (igArrowButton(tmp, ImGuiDir_Left)) {
*v = *reset;
}
igSameLine(0, 3);
igDragFloat3(name, (float *)v, 0.005f, min, max, "%+f", 1.0f);
}
static void
handle_draggable_quat(const char *name, struct xrt_quat *q, const struct xrt_quat *reset)
{
float min = -1.0f;
float max = 1.0f;
char tmp[256];
snprintf(tmp, sizeof(tmp), "%s.reset", name);
if (igArrowButton(tmp, ImGuiDir_Left)) {
*q = *reset;
}
igSameLine(0, 3);
igDragFloat4(name, (float *)q, 0.005f, min, max, "%+f", 1.0f);
// Avoid invalid
if (q->x == 0.0f && q->y == 0.0f && q->z == 0.0f && q->w == 0.0f) {
q->w = 1.0f;
}
// And make sure it's a unit rotation.
math_quat_normalize(q);
}
static bool
get_indices(struct gui_program *p,
struct gui_tracking_overrides *ts,
struct xrt_tracking_override *override,
int *out_target,
int *out_tracker)
{
bool has_target = false;
bool has_tracker = false;
for (int i = 0; i < NUM_XDEVS; i++) {
if (!p->xdevs[i]) {
continue;
}
if (strcmp(p->xdevs[i]->serial, override->target_device_serial) == 0) {
has_target = true;
*out_target = i;
}
if (strcmp(p->xdevs[i]->serial, override->tracker_device_serial) == 0) {
has_tracker = true;
*out_tracker = i;
}
}
return has_tracker && has_target;
}
static struct xrt_pose identity = {.position = {.x = 0, .y = 0, .z = 0},
.orientation = {.x = 0, .y = 0, .z = 0, .w = 1}};
static void
add_one(struct gui_program *p, struct gui_tracking_overrides *ts)
{
igBegin("Target Device", NULL, 0);
for (int i = 0; i < 8; i++) {
if (!p->xdevs[i]) {
continue;
}
char buf[NAME_LENGTH];
make_name(p->xdevs[i], buf);
bool selected = ts->add_target == i;
if (igCheckbox(buf, &selected)) {
ts->add_target = i;
}
}
igEnd();
igBegin("Tracker Device", NULL, 0);
for (int i = 0; i < 8; i++) {
if (!p->xdevs[i]) {
continue;
}
char buf[NAME_LENGTH];
make_name(p->xdevs[i], buf);
bool selected = ts->add_tracker == i;
if (igCheckbox(buf, &selected)) {
ts->add_tracker = i;
}
}
igEnd();
if (ts->add_target >= 0 && ts->add_tracker >= 0 && ts->add_target != ts->add_tracker) {
struct xrt_tracking_override *o = &ts->overrides[ts->num_overrides];
o->input_name = XRT_INPUT_GENERIC_TRACKER_POSE;
strncpy(o->target_device_serial, p->xdevs[ts->add_target]->serial, XRT_DEVICE_NAME_LEN);
strncpy(o->tracker_device_serial, p->xdevs[ts->add_tracker]->serial, XRT_DEVICE_NAME_LEN);
o->offset = identity;
ts->num_overrides += 1;
ts->add_target = -1;
ts->add_tracker = -1;
ts->add_one = false;
}
}
static void
scene_render(struct gui_scene *scene, struct gui_program *p)
{
struct gui_tracking_overrides *ts = (struct gui_tracking_overrides *)scene;
if (ts->editing_override >= 0) {
struct xrt_tracking_override *o = &ts->overrides[ts->editing_override];
igBegin("Tracker Device Offset", NULL, 0);
int target, tracker;
if (get_indices(p, ts, o, &target, &tracker)) {
igText("Editing %s [%s] <- %s [%s]", p->xdevs[target]->str, o->target_device_serial,
p->xdevs[tracker]->str, o->tracker_device_serial);
} else {
igText("Editing unconnected %s <- %s", o->target_device_serial, o->tracker_device_serial);
}
handle_draggable_vec3_f32("Position", &o->offset.position, &ts->reset_offset.position);
handle_draggable_quat("Orientation", &o->offset.orientation, &ts->reset_offset.orientation);
igEnd();
}
if (ts->add_one) {
add_one(p, ts);
}
igBegin("Tracking Overrides", NULL, 0);
igText("Existing Overrides");
for (size_t i = 0; i < ts->num_overrides; i++) {
// make the delete buttons work
igPushIDInt(i);
igSeparator();
bool checked = ts->editing_override == (int)i;
const int len = XRT_DEVICE_NAME_LEN * 2 + 10;
char buf[len];
snprintf(buf, len, "%s <- %s", ts->overrides[i].target_device_serial,
ts->overrides[i].tracker_device_serial);
if (igCheckbox(buf, &checked)) {
ts->editing_override = i;
ts->reset_offset = ts->overrides[i].offset;
}
if (igButton("Delete this one", button_dims)) {
for (size_t j = i; j < ts->num_overrides - 1; j++) {
ts->overrides[j] = ts->overrides[j + 1];
}
ts->num_overrides--;
if (ts->editing_override >= (int)i) {
ts->editing_override -= 1;
}
}
igSeparator();
igPopID();
}
igSeparator();
if (igButton("Add one", button_dims)) {
if (ts->num_overrides < XRT_MAX_TRACKING_OVERRIDES) {
ts->add_one = true;
}
}
igSeparator();
if (igButton("Save", button_dims)) {
gui_scene_delete_me(p, scene);
}
if (igButton("Exit", button_dims)) {
gui_scene_delete_me(p, scene);
}
igEnd();
}
static void
scene_destroy(struct gui_scene *scene, struct gui_program *p)
{
// struct tracking_overrides *ts = (struct tracking_overrides *)scene;
free(scene);
}
static struct gui_tracking_overrides *
create(struct gui_program *p)
{
struct gui_tracking_overrides *ts = U_TYPED_CALLOC(struct gui_tracking_overrides);
ts->base.render = scene_render;
ts->base.destroy = scene_destroy;
ts->editing_override = -1;
ts->add_one = false;
ts->add_target = -1;
ts->add_tracker = -1;
u_config_json_open_or_create_main_file(&ts->config);
u_config_json_get_tracking_overrides(&ts->config, ts->overrides, &ts->num_overrides);
return ts;
}
/*
*
* 'Exported' functions.
*
*/
void
gui_scene_tracking_overrides(struct gui_program *p)
{
if (p->xp == NULL) {
// No prober, nothing to create.
return;
}
// If we have created a prober select devices now.
if (p->xp != NULL) {
gui_prober_select(p);
}
struct gui_tracking_overrides *ts = create(p);
gui_scene_push_front(p, &ts->base);
}

View file

@ -12,6 +12,7 @@ gui_sources = [
'gui_scene_main_menu.c',
'gui_scene_remote.c',
'gui_scene_video.c',
'gui_scene_tracking_overrides.c',
'../../../external/imgui/imgui/cimgui.cpp',
'../../../external/imgui/imgui/cimgui.h',
'../../../external/imgui/imgui/cimplot.cpp',

View file

@ -39,6 +39,8 @@ main(int argc, char **argv)
gui_scene_debug(&p.base);
} else if (argc >= 2 && strcmp("calibrate", argv[1]) == 0) {
gui_scene_select_video_calibrate(&p.base);
} else if (argc >= 2 && strcmp("tracking_overrides", argv[1]) == 0) {
gui_scene_tracking_overrides(&p.base);
} else if (argc >= 2 && strcmp("remote", argv[1]) == 0) {
gui_scene_remote(&p.base);
} else {