save sixense settings and some UI cleanup

This commit is contained in:
Andrew Meadows 2015-10-05 23:25:05 -07:00
parent 76264ae704
commit 0680be0422
12 changed files with 168 additions and 63 deletions

View file

@ -2351,6 +2351,7 @@ void Application::saveSettings() {
Menu::getInstance()->saveSettings();
getMyAvatar()->saveData();
PluginManager::getInstance()->saveSettings();
}
bool Application::importEntities(const QString& urlOrFilename) {

View file

@ -200,9 +200,6 @@ void PreferencesDialog::loadPreferences() {
ui.sixenseReticleMoveSpeedSpin->setValue(InputDevice::getReticleMoveSpeed());
SixenseManager& sixense = SixenseManager::getInstance();
ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons());
// LOD items
auto lodManager = DependencyManager::get<LODManager>();
ui.desktopMinimumFPSSpin->setValue(lodManager->getDesktopLODDecreaseFPS());
@ -276,9 +273,7 @@ void PreferencesDialog::savePreferences() {
qApp->getApplicationCompositor().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value());
SixenseManager& sixense = SixenseManager::getInstance();
InputDevice::setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked());
auto audio = DependencyManager::get<AudioClient>();
MixedProcessedAudioStream& stream = audio->getReceivedAudioStream();

View file

@ -2768,40 +2768,6 @@
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_26">
<property name="topMargin">
<number>7</number>
</property>
<property name="bottomMargin">
<number>7</number>
</property>
<item>
<widget class="QCheckBox" name="invertSixenseButtonsCheckBox">
<property name="baseSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="font">
<font>
<family>Arial</family>
</font>
</property>
<property name="text">
<string>Invert Mouse Buttons</string>
</property>
<property name="iconSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_16">
<property name="spacing">

View file

@ -37,3 +37,9 @@ InputPluginList getInputPlugins() {
}
return result;
}
void saveInputPluginSettings(const InputPluginList& plugins) {
foreach (auto inputPlugin, plugins) {
inputPlugin->saveSettings();
}
}

View file

@ -16,6 +16,7 @@
#include <GLMHelpers.h>
#include <NumericalConstants.h>
#include <PerfStat.h>
#include <SettingHandle.h>
#include <plugins/PluginContainer.h>
#include "NumericalConstants.h"
@ -38,7 +39,7 @@ const unsigned int RIGHT_MASK = 1U << 1;
#ifdef HAVE_SIXENSE
const int CALIBRATION_STATE_IDLE = 0;
const int CALIBRATION_STATE_X = 1;
const int CALIBRATION_STATE_IN_PROGRESS = 1;
const int CALIBRATION_STATE_COMPLETE = 2;
const glm::vec3 DEFAULT_AVATAR_POSITION(-0.25f, -0.35f, -0.3f); // in hydra frame
@ -56,25 +57,23 @@ typedef int (*SixenseTakeIntAndSixenseControllerData)(int, sixenseControllerData
#endif
const QString SixenseManager::NAME = "Sixense";
const QString SixenseManager::HYDRA_ID_STRING = "Razer Hydra";
const QString MENU_PARENT = "Avatar";
const QString MENU_NAME = "Sixense";
const QString MENU_PATH = MENU_PARENT + ">" + MENU_NAME;
const QString TOGGLE_SMOOTH = "Smooth Sixense Movement";
const float DEFAULT_REACH_LENGTH = 1.5f;
SixenseManager& SixenseManager::getInstance() {
static SixenseManager sharedInstance;
return sharedInstance;
}
SixenseManager::SixenseManager() :
InputDevice("Hydra"),
#ifdef __APPLE__
_sixenseLibrary(NULL),
#endif
_reachLength(DEFAULT_REACH_LENGTH),
_hydrasConnected(false)
{
}
bool SixenseManager::isSupported() const {
@ -92,7 +91,7 @@ void SixenseManager::activate() {
CONTAINER->addMenu(MENU_PATH);
CONTAINER->addMenuItem(MENU_PATH, TOGGLE_SMOOTH,
[this] (bool clicked) { this->setFilter(clicked); },
[this] (bool clicked) { this->setSixenseFilter(clicked); },
true, true);
#ifdef __APPLE__
@ -120,6 +119,7 @@ void SixenseManager::activate() {
SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit");
#endif
loadSettings();
sixenseInit();
#endif
}
@ -144,7 +144,7 @@ void SixenseManager::deactivate() {
#endif
}
void SixenseManager::setFilter(bool filter) {
void SixenseManager::setSixenseFilter(bool filter) {
#ifdef HAVE_SIXENSE
#ifdef __APPLE__
SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled");
@ -282,6 +282,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y));
xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis));
_reachLength = glm::dot(xAxis, _reachRight - _reachLeft);
_avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis)));
const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f;
_avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR;
@ -317,7 +318,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
_lastDistance = reach;
_lockExpiry = usecTimestampNow() + LOCK_DURATION;
// move to next state
_calibrationState = CALIBRATION_STATE_X;
_calibrationState = CALIBRATION_STATE_IN_PROGRESS;
}
return;
}
@ -327,7 +328,7 @@ void SixenseManager::updateCalibration(void* controllersX) {
_averageLeft = 0.9f * _averageLeft + 0.1f * positionLeft;
_averageRight = 0.9f * _averageRight + 0.1f * positionRight;
if (_calibrationState == CALIBRATION_STATE_X) {
if (_calibrationState == CALIBRATION_STATE_IN_PROGRESS) {
// compute new sliding average
float distance = glm::distance(_averageLeft, _averageRight);
if (fabsf(distance - _lastDistance) > MAXIMUM_NOISE_LEVEL) {
@ -340,7 +341,6 @@ void SixenseManager::updateCalibration(void* controllersX) {
// lock has expired so clamp the data and move on
_lockExpiry = now + LOCK_DURATION;
_lastDistance = 0.0f;
_reachUp = 0.5f * (_reachLeft + _reachRight);
_calibrationState = CALIBRATION_STATE_COMPLETE;
qCDebug(inputplugins, "success: sixense calibration: left");
}
@ -543,6 +543,31 @@ void SixenseManager::assignDefaultInputMapping(UserInputMapper& mapper) {
}
// virtual
void SixenseManager::saveSettings() const {
Settings settings;
QString idString = getID();
settings.beginGroup(idString);
{
settings.setVec3Value(QString("avatarPosition"), _avatarPosition);
settings.setQuatValue(QString("avatarRotation"), _avatarRotation);
settings.setValue(QString("reachLength"), QVariant(_reachLength));
}
settings.endGroup();
}
void SixenseManager::loadSettings() {
Settings settings;
QString idString = getID();
settings.beginGroup(idString);
{
settings.getVec3ValueIfValid(QString("avatarPosition"), _avatarPosition);
settings.getQuatValueIfValid(QString("avatarRotation"), _avatarRotation);
settings.getFloatValueIfValid(QString("reachLength"), _reachLength);
}
settings.endGroup();
}
UserInputMapper::Input SixenseManager::makeInput(unsigned int button, int index) {
return UserInputMapper::Input(_deviceID, button | (index == 0 ? LEFT_MASK : RIGHT_MASK), UserInputMapper::ChannelType::BUTTON);
}

View file

@ -58,12 +58,11 @@ public:
SixenseManager();
static SixenseManager& getInstance();
// Plugin functions
virtual bool isSupported() const override;
virtual bool isJointController() const override { return true; }
const QString& getName() const override { return NAME; }
const QString& getID() const override { return HYDRA_ID_STRING; }
virtual void activate() override;
virtual void deactivate() override;
@ -77,15 +76,15 @@ public:
virtual void update(float deltaTime, bool jointsCaptured) override;
virtual void focusOutEvent() override;
bool getInvertButtons() const { return _invertButtons; }
void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; }
UserInputMapper::Input makeInput(unsigned int button, int index);
UserInputMapper::Input makeInput(JoystickAxisChannel axis, int index);
UserInputMapper::Input makeInput(JointChannel joint);
virtual void saveSettings() const override;
virtual void loadSettings() override;
public slots:
void setFilter(bool filter);
void setSixenseFilter(bool filter);
private:
void handleButtonEvent(unsigned int buttons, int index);
@ -99,7 +98,7 @@ private:
// these are calibration results
glm::vec3 _avatarPosition; // in hydra-frame
glm::quat _avatarRotation; // in hydra-frame
float _armLength;
float _reachLength;
// these are measured values used to compute the calibration results
quint64 _lockExpiry;
@ -107,9 +106,8 @@ private:
glm::vec3 _averageRight;
glm::vec3 _reachLeft;
glm::vec3 _reachRight;
glm::vec3 _reachUp;
glm::vec3 _reachForward;
float _lastDistance;
bool _useSixenseFilter = true;
#ifdef __APPLE__
QLibrary* _sixenseLibrary;
@ -117,9 +115,8 @@ private:
bool _hydrasConnected;
bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
static const QString NAME;
static const QString HYDRA_ID_STRING;
};
#endif // hifi_SixenseManager_h

View file

@ -9,6 +9,8 @@
PluginContainer* Plugin::CONTAINER{ nullptr };
QString Plugin::UNKNOWN_PLUGIN_ID("unknown");
void Plugin::setContainer(PluginContainer* container) {
CONTAINER = container;
}

View file

@ -7,6 +7,8 @@
//
#pragma once
#include <assert.h>
#include <QString>
#include <QObject>
@ -14,7 +16,12 @@
class Plugin : public QObject {
public:
/// \return human-readable name
virtual const QString& getName() const = 0;
/// \return string ID (not necessarily human-readable)
virtual const QString& getID() const { assert(false); return UNKNOWN_PLUGIN_ID; }
virtual bool isSupported() const;
static void setContainer(PluginContainer* container);
@ -37,6 +44,11 @@ public:
*/
virtual void idle();
virtual void saveSettings() const {}
virtual void loadSettings() {}
protected:
static PluginContainer* CONTAINER;
static QString UNKNOWN_PLUGIN_ID;
};

View file

@ -8,6 +8,8 @@
#include "PluginManager.h"
#include <mutex>
#include "Forward.h"
PluginManager* PluginManager::getInstance() {
static PluginManager _manager;
return &_manager;
@ -16,6 +18,7 @@ PluginManager* PluginManager::getInstance() {
// TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class
extern DisplayPluginList getDisplayPlugins();
extern InputPluginList getInputPlugins();
extern void saveInputPluginSettings(const InputPluginList& plugins);
const DisplayPluginList& PluginManager::getDisplayPlugins() {
static DisplayPluginList displayPlugins;
@ -35,3 +38,6 @@ const InputPluginList& PluginManager::getInputPlugins() {
return inputPlugins;
}
void PluginManager::saveSettings() {
saveInputPluginSettings(getInputPlugins());
}

View file

@ -15,4 +15,5 @@ public:
const DisplayPluginList& getDisplayPlugins();
const InputPluginList& getInputPlugins();
void saveSettings();
};

View file

@ -0,0 +1,83 @@
//
// SettingHandle.h
//
//
// Created by AndrewMeadows 2015.10.05
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "SettingHandle.h"
#include <math.h>
void Settings::getFloatValueIfValid(const QString& name, float& f) {
const QVariant badDefaultValue = NAN;
bool ok = true;
float tempFloat = value(name, badDefaultValue).toFloat(&ok);
if (ok && !isnan(tempFloat)) {
f = tempFloat;
}
}
void Settings::getBoolValue(const QString& name, bool& b) {
const QVariant defaultValue = false;
b = value(name, defaultValue).toBool();
}
void Settings::setVec3Value(const QString& name, const glm::vec3& v) {
beginGroup(name);
{
setValue(QString("x"), v.x);
setValue(QString("y"), v.y);
setValue(QString("z"), v.z);
}
endGroup();
}
void Settings::getVec3ValueIfValid(const QString& name, glm::vec3& v) {
beginGroup(name);
{
bool ok = true;
const QVariant badDefaultValue = NAN;
float x = value(QString("x"), badDefaultValue).toFloat(&ok);
float y = value(QString("y"), badDefaultValue).toFloat(&ok);
float z = value(QString("z"), badDefaultValue).toFloat(&ok);
if (ok && (!isnan(x) && !isnan(y) && !isnan(z))) {
v = glm::vec3(x, y, z);
}
}
endGroup();
}
void Settings::setQuatValue(const QString& name, const glm::quat& q) {
beginGroup(name);
{
setValue(QString("x"), q.x);
setValue(QString("y"), q.y);
setValue(QString("z"), q.z);
setValue(QString("w"), q.w);
}
endGroup();
}
void Settings::getQuatValueIfValid(const QString& name, glm::quat& q) {
beginGroup(name);
{
bool ok = true;
const QVariant badDefaultValue = NAN;
float x = value(QString("x"), badDefaultValue).toFloat(&ok);
float y = value(QString("y"), badDefaultValue).toFloat(&ok);
float z = value(QString("z"), badDefaultValue).toFloat(&ok);
float w = value(QString("w"), badDefaultValue).toFloat(&ok);
if (ok && (!isnan(x) && !isnan(y) && !isnan(z) && !isnan(w))) {
q = glm::quat(w, x, y, z);
}
}
endGroup();
}

View file

@ -18,11 +18,22 @@
#include <QString>
#include <QVariant>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include "SettingInterface.h"
// TODO: remove
class Settings : public QSettings {
public:
void getFloatValueIfValid(const QString& name, float& f);
void getBoolValue(const QString& name, bool& b);
void setVec3Value(const QString& name, const glm::vec3& v);
void getVec3ValueIfValid(const QString& name, glm::vec3& v);
void setQuatValue(const QString& name, const glm::quat& q);
void getQuatValueIfValid(const QString& name, glm::quat& q);
};
namespace Setting {
@ -65,4 +76,4 @@ namespace Setting {
}
}
#endif // hifi_SettingHandle_h
#endif // hifi_SettingHandle_h