diff options
Diffstat (limited to 'facetracknoir/ui.cpp')
-rw-r--r-- | facetracknoir/ui.cpp | 424 |
1 files changed, 424 insertions, 0 deletions
diff --git a/facetracknoir/ui.cpp b/facetracknoir/ui.cpp new file mode 100644 index 00000000..edd3a818 --- /dev/null +++ b/facetracknoir/ui.cpp @@ -0,0 +1,424 @@ +/******************************************************************************* +* FaceTrackNoIR This program is a private project of the some enthusiastic +* gamers from Holland, who don't like to pay much for +* head-tracking. +* +* Copyright (C) 2011 Wim Vriend (Developing) +* Ron Hendriks (Researching and Testing) +* +* Homepage +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License as published by the +* Free Software Foundation; either version 3 of the License, or (at your +* option) any later version. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, see <http://www.gnu.org/licenses/>. +*********************************************************************************/ +#include "ui.h" +#include "opentrack/tracker.h" +#include <QFileDialog> + +#ifndef _WIN32 +# include <unistd.h> +#else +# include <windows.h> +#endif + +MainWindow::MainWindow() : + pose_update_timer(this), + kbd_quit(QKeySequence("Ctrl+Q"), this), + no_feed_pixmap(":/images/no-feed.png") +{ + ui.setupUi(this); + + setFixedSize(size()); + + updateButtonState(false, false); + ui.video_frame_label->setPixmap(no_feed_pixmap); + QDir::setCurrent(QCoreApplication::applicationDirPath()); + + connect(ui.btnLoad, SIGNAL(clicked()), this, SLOT(open())); + connect(ui.btnSave, SIGNAL(clicked()), this, SLOT(save())); + connect(ui.btnSaveAs, SIGNAL(clicked()), this, SLOT(saveAs())); + + connect(ui.btnEditCurves, SIGNAL(clicked()), this, SLOT(showCurveConfiguration())); + connect(ui.btnShortcuts, SIGNAL(clicked()), this, SLOT(showKeyboardShortcuts())); + connect(ui.btnShowEngineControls, SIGNAL(clicked()), this, SLOT(showTrackerSettings())); + connect(ui.btnShowServerControls, SIGNAL(clicked()), this, SLOT(showProtocolSettings())); + connect(ui.btnShowFilterControls, SIGNAL(clicked()), this, SLOT(showFilterSettings())); + + modules.filters().push_front(std::make_shared<dylib>("", dylib::Filter)); + + for (auto x : modules.trackers()) + ui.iconcomboTrackerSource->addItem(x->icon, x->name); + + for (auto x : modules.protocols()) + ui.iconcomboProtocol->addItem(x->icon, x->name); + + for (auto x : modules.filters()) + ui.iconcomboFilter->addItem(x->icon, x->name); + + fill_profile_combobox(); + + tie_setting(s.tracker_dll, ui.iconcomboTrackerSource); + tie_setting(s.protocol_dll, ui.iconcomboProtocol); + tie_setting(s.filter_dll, ui.iconcomboFilter); + + connect(ui.btnStartTracker, SIGNAL(clicked()), this, SLOT(startTracker())); + connect(ui.btnStopTracker, SIGNAL(clicked()), this, SLOT(stopTracker())); + connect(ui.iconcomboProfile, SIGNAL(currentIndexChanged(int)), this, SLOT(profileSelected(int))); + + connect(&pose_update_timer, SIGNAL(timeout()), this, SLOT(showHeadPose())); + connect(&kbd_quit, SIGNAL(activated()), this, SLOT(exit())); + kbd_quit.setEnabled(true); + + ensure_tray(); + if (s.tray_enabled) + hide(); +} + +MainWindow::~MainWindow() +{ + stopTracker(); + save(); + _exit(0); +} + +void MainWindow::open() { + QFileDialog dialog(this); + dialog.setFileMode(QFileDialog::ExistingFile); + + QString fileName = dialog.getOpenFileName( + this, + tr("Open the settings file"), + QCoreApplication::applicationDirPath() + "/settings/", + tr("Settings file (*.ini);;All Files (*)"), + NULL); + + if (! fileName.isEmpty() ) { + { + QSettings settings("opentrack"); + settings.setValue ("SettingsFile", QFileInfo(fileName).absoluteFilePath()); + } + fill_profile_combobox(); + load_settings(); + } +} + +void MainWindow::save_mappings() { + pose.save_mappings(); +} + +#if defined(__unix) || defined(__linux) || defined(__APPLE__) +# include <unistd.h> +#endif + +void MainWindow::save() { + b->save(); + save_mappings(); + +#if defined(__unix) || defined(__linux) + QSettings settings("opentrack"); + const QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); + QByteArray bytes = QFile::encodeName(currentFile); + const char* filename_as_asciiz = bytes.constData(); + + if (access(filename_as_asciiz, R_OK | W_OK)) + { + QMessageBox::warning(this, "Something went wrong", "Check permissions and ownership for your .ini file!", QMessageBox::Ok, QMessageBox::NoButton); + } +#endif +} + +void MainWindow::saveAs() +{ + QSettings settings("opentrack"); + QString oldFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); + + QString fileName = QFileDialog::getSaveFileName(this, tr("Save file"), + oldFile, + tr("Settings file (*.ini);;All Files (*)")); + if (!fileName.isEmpty()) { + + QFileInfo newFileInfo ( fileName ); + if ((newFileInfo.exists()) && (oldFile != fileName)) { + QFile newFileFile ( fileName ); + newFileFile.remove(); + } + + QFileInfo oldFileInfo ( oldFile ); + if (oldFileInfo.exists()) { + QFile oldFileFile ( oldFile ); + oldFileFile.copy( fileName ); + } + + settings.setValue ("SettingsFile", fileName); + save(); + } + + fill_profile_combobox(); +} + +void MainWindow::load_mappings() { + pose.load_mappings(); +} + +void MainWindow::load_settings() { + b->reload(); + load_mappings(); +} + +extern "C" volatile const char* opentrack_version; + +void MainWindow::fill_profile_combobox() +{ + QSettings settings("opentrack"); + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + + "/settings/default.ini" ).toString(); + qDebug() << "Config file now" << currentFile; + QFileInfo pathInfo ( currentFile ); + setWindowTitle(QString( const_cast<const char*>(opentrack_version) + QStringLiteral(" :: ")) + pathInfo.fileName()); + QDir settingsDir( pathInfo.dir() ); + auto iniFileList = settingsDir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); + ui.iconcomboProfile->clear(); + for (auto x : iniFileList) + ui.iconcomboProfile->addItem(QIcon(":/images/settings16.png"), x); + ui.iconcomboProfile->setCurrentText(pathInfo.fileName()); +} + +void MainWindow::updateButtonState(bool running, bool inertialp) +{ + bool not_running = !running; + ui.iconcomboProfile->setEnabled ( not_running ); + ui.btnStartTracker->setEnabled ( not_running ); + ui.btnStopTracker->setEnabled ( running ); + ui.iconcomboProtocol->setEnabled ( not_running ); + ui.iconcomboFilter->setEnabled ( not_running ); + ui.iconcomboTrackerSource->setEnabled(not_running); + ui.btnStartTracker->setEnabled(not_running); + ui.btnStopTracker->setEnabled(running); + ui.video_frame_label->setVisible(not_running || inertialp); +} + +void MainWindow::bindKeyboardShortcuts() +{ + if (work) + work->reload_shortcuts(); +} + +void MainWindow::startTracker( ) { + b->save(); + load_settings(); + bindKeyboardShortcuts(); + + // tracker dtor needs run first + work = nullptr; + + libs = SelectedLibraries(ui.video_frame, current_tracker(), current_protocol(), current_filter()); + work = std::make_shared<Work>(s, pose, libs, this, winId()); + + { + double p[6] = {0,0,0, 0,0,0}; + display_pose(p, p); + } + + if (!libs.correct) + { + QMessageBox::warning(this, "Library load error", + "One of libraries failed to load. Check installation.", + QMessageBox::Ok, + QMessageBox::NoButton); + return; + } + + pose_update_timer.start(50); + + // NB check valid since SelectedLibraries ctor called + // trackers take care of layout state updates + const bool is_inertial = ui.video_frame->layout() == nullptr; + updateButtonState(true, is_inertial); +} + +void MainWindow::stopTracker( ) { + //ui.game_name->setText("Not connected"); + + pose_update_timer.stop(); + ui.pose_display->rotateBy(0, 0, 0); + + if (pTrackerDialog) + { + pTrackerDialog->unregister_tracker(); + pTrackerDialog = nullptr; + } + + if (pProtocolDialog) + { + pProtocolDialog->unregister_protocol(); + pProtocolDialog = nullptr; + } + + if (pFilterDialog) + { + pFilterDialog->unregister_filter(); + pFilterDialog = nullptr; + } + + work = nullptr; + libs = SelectedLibraries(); + + { + double p[6] = {0,0,0, 0,0,0}; + display_pose(p, p); + } + updateButtonState(false, false); +} + +void MainWindow::display_pose(const double *mapped, const double *raw) +{ + ui.pose_display->rotateBy(mapped[Yaw], mapped[Pitch], mapped[Roll]); + + if (mapping_widget) + mapping_widget->update(); + + double mapped_[6], raw_[6]; + + for (int i = 0; i < 6; i++) + { + mapped_[i] = (int) mapped[i]; + raw_[i] = (int) raw[i]; + } + + ui.raw_x->display(raw_[TX]); + ui.raw_y->display(raw_[TY]); + ui.raw_z->display(raw_[TZ]); + ui.raw_yaw->display(raw_[Yaw]); + ui.raw_pitch->display(raw_[Pitch]); + ui.raw_roll->display(raw_[Roll]); + + ui.pose_x->display(mapped_[TX]); + ui.pose_y->display(mapped_[TY]); + ui.pose_z->display(mapped_[TZ]); + ui.pose_yaw->display(mapped_[Yaw]); + ui.pose_pitch->display(mapped_[Pitch]); + ui.pose_roll->display(mapped_[Roll]); +} + +void MainWindow::showHeadPose() +{ + double mapped[6], raw[6]; + + work->tracker->get_raw_and_mapped_poses(mapped, raw); + + display_pose(mapped, raw); + +#if 0 + if (libs.pProtocol) + { + const QString name = libs.pProtocol->game_name(); + ui.game_name->setText(name); + } +#endif +} + +template<typename t> +ptr<t> mk_dialog(ptr<dylib> lib) +{ + if (lib) + { + auto dialog = ptr<t>(reinterpret_cast<t*>(lib->Dialog())); + dialog->setWindowFlags(Qt::Dialog); + dialog->setFixedSize(dialog->size()); + return dialog; + } + + return nullptr; +} + +void MainWindow::showTrackerSettings() +{ + auto dialog = mk_dialog<ITrackerDialog>(current_tracker()); + + if (dialog) { + pTrackerDialog = dialog; + dialog->register_tracker(libs.pTracker.get()); + dialog->show(); + } +} + +void MainWindow::showProtocolSettings() { + auto dialog = mk_dialog<IProtocolDialog>(current_protocol()); + + if (dialog) { + pProtocolDialog = dialog; + dialog->show(); + } +} + +void MainWindow::showFilterSettings() { + auto dialog = mk_dialog<IFilterDialog>(current_filter()); + + if (dialog) { + pFilterDialog = dialog; + dialog->register_filter(libs.pFilter.get()); + dialog->show(); + } +} + +void MainWindow::showKeyboardShortcuts() { + shortcuts_widget = std::make_shared<KeyboardShortcutDialog>(); + shortcuts_widget->setWindowFlags(Qt::Dialog); + connect(shortcuts_widget.get(), SIGNAL(reload()), this, SLOT(bindKeyboardShortcuts())); + shortcuts_widget->show(); +} + +void MainWindow::showCurveConfiguration() { + mapping_widget = std::make_shared<MapWidget>(pose, s); + mapping_widget->setWindowFlags(Qt::Dialog); + mapping_widget->show(); +} + +void MainWindow::exit() { + QCoreApplication::exit(0); +} + +void MainWindow::profileSelected(int index) +{ + QSettings settings("opentrack"); + QString currentFile = settings.value ( "SettingsFile", QCoreApplication::applicationDirPath() + "/settings/default.ini" ).toString(); + QFileInfo pathInfo ( currentFile ); + settings.setValue ("SettingsFile", pathInfo.absolutePath() + "/" + ui.iconcomboProfile->itemText(index)); + load_settings(); +} + +void MainWindow::shortcutRecentered() +{ + qDebug() << "Center"; + if (work) + work->tracker->center(); +} + +void MainWindow::shortcutToggled() +{ + qDebug() << "Toggle"; + if (work) + work->tracker->toggle_enabled(); +} + +void MainWindow::ensure_tray() +{ + tray = nullptr; + if (s.tray_enabled) + { + tray = std::make_shared<QSystemTrayIcon>(this); + tray->setIcon(QIcon(":/images/facetracknoir.png")); + tray->show(); + connect(tray.get(), SIGNAL(activated()), this, SLOT(show())); + } +} |