diff --git a/interface/interface_en.ts b/interface/interface_en.ts
new file mode 100644
index 0000000000..48b395339e
--- /dev/null
+++ b/interface/interface_en.ts
@@ -0,0 +1,274 @@
+
+
+
+
+ Application
+
+
+ Export Voxels
+
+
+
+
+ Sparse Voxel Octree Files (*.svo)
+
+
+
+
+ Open Script
+
+
+
+
+ JavaScript Files (*.js)
+
+
+
+
+ ChatWindow
+
+
+
+ Chat
+
+
+
+
+
+ Connecting to XMPP...
+
+
+
+
+
+ online now:
+
+
+
+
+ day
+
+ %n day
+ %n days
+
+
+
+
+ hour
+
+ %n hour
+ %n hours
+
+
+
+
+ minute
+
+ %n minute
+ %n minutes
+
+
+
+ second
+
+ %n second
+ %n seconds
+
+
+
+
+ %1 online now:
+
+
+
+
+ Dialog
+
+
+
+
+
+ Update Required
+
+
+
+
+
+ Download
+
+
+
+
+
+ Skip Version
+
+
+
+
+
+ Close
+
+
+
+
+ Menu
+
+
+ Open .ini config file
+
+
+
+
+
+ Text files (*.ini)
+
+
+
+
+ Save .ini config file
+
+
+
+
+ PreferencesDialog
+
+
+
+ Cancel
+
+
+
+
+
+ Save all changes
+
+
+
+
+
+
+
+ Avatar
+
+
+
+
+
+ <html><head/><body><p>Avatar display name <span style=" color:#909090;">(optional)</span></p></body></html>
+
+
+
+
+
+ Not showing a name
+
+
+
+
+
+ Head
+
+
+
+
+
+ Body
+
+
+
+
+
+ Advanced Tuning
+
+
+
+
+
+ It's not recomended that you play with these settings unless you've looked into exactly what they do.
+
+
+
+
+
+ Vertical field of view
+
+
+
+
+
+ Lean scale (applies to Faceshift users)
+
+
+
+
+
+ Avatar scale <span style=" color:#909090;">(default is 1.0)</span>
+
+
+
+
+
+ Pupil dillation
+
+
+
+
+
+ Audio Jitter Buffer Samples (0 for automatic)
+
+
+
+
+
+ Faceshift eye detection
+
+
+
+
+
+ Voxels
+
+
+
+
+
+ Maximum voxels
+
+
+
+
+
+ Max voxels sent each second
+
+
+
+
+ QObject
+
+
+
+ Import Voxels
+
+
+
+
+ Loading ...
+
+
+
+
+ Place voxels
+
+
+
+
+ <b>Import</b> %1 as voxels
+
+
+
+
+ Cancel
+
+
+
+
diff --git a/interface/resources/resources.qrc b/interface/resources/resources.qrc
index 35c0e40270..0dc5a27651 100644
--- a/interface/resources/resources.qrc
+++ b/interface/resources/resources.qrc
@@ -1,5 +1,6 @@
-
+
+ styles/search.svg
images/close.svg
images/kill-script.svg
images/reload.svg
diff --git a/interface/resources/styles/avatar.svg b/interface/resources/styles/avatar.svg
new file mode 100644
index 0000000000..f9382edee4
--- /dev/null
+++ b/interface/resources/styles/avatar.svg
@@ -0,0 +1,27 @@
+
+
+
+
diff --git a/interface/resources/styles/close.svg b/interface/resources/styles/close.svg
new file mode 100644
index 0000000000..8fe4bf4bdb
--- /dev/null
+++ b/interface/resources/styles/close.svg
@@ -0,0 +1,14 @@
+
+
+
+
diff --git a/interface/resources/styles/down.svg b/interface/resources/styles/down.svg
new file mode 100644
index 0000000000..983ccd9597
--- /dev/null
+++ b/interface/resources/styles/down.svg
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/interface/resources/styles/global.qss b/interface/resources/styles/global.qss
new file mode 100644
index 0000000000..2554f3b2c9
--- /dev/null
+++ b/interface/resources/styles/global.qss
@@ -0,0 +1,113 @@
+* {
+ padding: 0;
+ margin: 0;
+}
+
+FramelessDialog {
+ font-family: Helvetica, Arial, sans-serif;
+ font-size: 16px;
+}
+
+QLineEdit {
+ background-color: rgba(255, 255, 255, 1);
+ border-style: solid;
+ border-width: 1px;
+ border-color: #ccc;
+ padding: 8px;
+ font-size: 16px;
+ color: rgb(51, 51, 51);
+}
+
+QLabel p {
+ color: #0e7077;
+ font-size: 23px;
+}
+
+QPushButton {
+ border-width: 0;
+ border-radius: 9px;
+ font-family: Arial;
+ font-size: 18px;
+ color: #ffffff;
+ padding: 10px 0px;
+}
+
+QSpinBox, QDoubleSpinBox {
+ padding: 5px;
+ border-width: 1;
+ font-size: 16px;
+ color: rgb(51, 51, 51);
+}
+
+QDoubleSpinBox::up-arrow,
+QSpinBox::up-arrow {
+ background-image: url(styles/up.svg);
+ background-repeat: no-repeat;
+ background-position: center center;
+}
+
+QDoubleSpinBox::down-arrow,
+QSpinBox::down-arrow {
+ background-image: url(styles/down.svg);
+ background-repeat: no-repeat;
+ background-position: center center;
+}
+
+QDoubleSpinBox::up-button,
+QSpinBox::up-button,
+QDoubleSpinBox::down-button,
+QSpinBox::down-button {
+ width: 26px;
+ height: 13px;
+
+ background-color: #f2f2f2;
+ border-color: #ccc;
+ border-style: solid;
+ border-width: 1px;
+}
+
+QDoubleSpinBox::up-button,
+QSpinBox::up-button {
+
+ margin-top:2px;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+}
+
+QDoubleSpinBox::down-button,
+QSpinBox::down-button {
+ margin-bottom:3px;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+}
+
+QSlider {
+ width: 125px;
+ height: 18px;
+}
+
+QSlider::groove:horizontal {
+ border: none;
+ background-image: url(styles/slider-bg.svg);
+ background-repeat: no-repeat;
+ background-position: center center;
+}
+
+QSlider::handle:horizontal {
+ width: 18px;
+ height: 18px;
+ background-image: url(styles/slider-handle.svg);
+ background-repeat: no-repeat;
+ background-position: center center;
+}
+
+QPushButton#closeButton {
+ border-color: #ccc;
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 0;
+ background-color: #fff;
+ background-image: url(styles/close.svg);
+ background-repeat: no-repeat;
+ background-position: center center;
+}
diff --git a/interface/resources/styles/preferences.qss b/interface/resources/styles/preferences.qss
new file mode 100644
index 0000000000..643fd13a77
--- /dev/null
+++ b/interface/resources/styles/preferences.qss
@@ -0,0 +1,21 @@
+QLabel#avatarLabel {
+ background-image: url(styles/avatar.svg);
+ background-repeat: no-repeat;
+ background-position: left center;
+}
+
+QLabel#advancedTuningLabel {
+ background-image: url(styles/wrench.svg);
+ background-repeat: no-repeat;
+ background-position: left center;
+}
+
+QPushButton#buttonBrowseHead,
+QPushButton#buttonBrowseBody {
+ background-image: url(styles/search.svg);
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-color: #fff;
+ border-radius: 0;
+ padding: 0;
+}
diff --git a/interface/resources/styles/slider-bg.svg b/interface/resources/styles/slider-bg.svg
new file mode 100644
index 0000000000..36c6478026
--- /dev/null
+++ b/interface/resources/styles/slider-bg.svg
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/interface/resources/styles/slider-handle.svg b/interface/resources/styles/slider-handle.svg
new file mode 100644
index 0000000000..5d87e8599c
--- /dev/null
+++ b/interface/resources/styles/slider-handle.svg
@@ -0,0 +1,10 @@
+
+
+
+
diff --git a/interface/resources/styles/up.svg b/interface/resources/styles/up.svg
new file mode 100644
index 0000000000..d122c4801e
--- /dev/null
+++ b/interface/resources/styles/up.svg
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/interface/resources/styles/wrench.svg b/interface/resources/styles/wrench.svg
new file mode 100644
index 0000000000..5019f92b18
--- /dev/null
+++ b/interface/resources/styles/wrench.svg
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp
index 80007da485..c68afdbf5f 100644
--- a/interface/src/Menu.cpp
+++ b/interface/src/Menu.cpp
@@ -86,7 +86,8 @@ Menu::Menu() :
_lastAvatarDetailDrop(usecTimestampNow()),
_fpsAverage(FIVE_SECONDS_OF_FRAMES),
_fastFPSAverage(ONE_SECOND_OF_FRAMES),
- _loginAction(NULL)
+ _loginAction(NULL),
+ _preferencesDialog(NULL)
{
Application *appInstance = Application::getInstance();
@@ -771,164 +772,12 @@ void Menu::loginForCurrentDomain() {
}
void Menu::editPreferences() {
- Application* applicationInstance = Application::getInstance();
- ModelsBrowser headBrowser(Head);
- ModelsBrowser skeletonBrowser(Skeleton);
-
- const QString BROWSE_BUTTON_TEXT = "Browse";
-
- QDialog dialog(applicationInstance->getWindow());
- dialog.setWindowTitle("Interface Preferences");
-
- QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom);
- dialog.setLayout(layout);
-
- QFormLayout* form = new QFormLayout();
- layout->addLayout(form, 1);
-
-
- QHBoxLayout headModelLayout;
- QString faceURLString = applicationInstance->getAvatar()->getHead()->getFaceModel().getURL().toString();
- QLineEdit headURLEdit(faceURLString);
- QPushButton headBrowseButton(BROWSE_BUTTON_TEXT);
- connect(&headBrowseButton, SIGNAL(clicked()), &headBrowser, SLOT(browse()));
- connect(&headBrowser, SIGNAL(selected(QString)), &headURLEdit, SLOT(setText(QString)));
- headURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH);
- headURLEdit.setPlaceholderText(DEFAULT_HEAD_MODEL_URL.toString());
- headModelLayout.addWidget(&headURLEdit);
- headModelLayout.addWidget(&headBrowseButton);
- form->addRow("Head URL:", &headModelLayout);
-
- QHBoxLayout skeletonModelLayout;
- QString skeletonURLString = applicationInstance->getAvatar()->getSkeletonModel().getURL().toString();
- QLineEdit skeletonURLEdit(skeletonURLString);
- QPushButton SkeletonBrowseButton(BROWSE_BUTTON_TEXT);
- connect(&SkeletonBrowseButton, SIGNAL(clicked()), &skeletonBrowser, SLOT(browse()));
- connect(&skeletonBrowser, SIGNAL(selected(QString)), &skeletonURLEdit, SLOT(setText(QString)));
- skeletonURLEdit.setMinimumWidth(QLINE_MINIMUM_WIDTH);
- skeletonURLEdit.setPlaceholderText(DEFAULT_BODY_MODEL_URL.toString());
- skeletonModelLayout.addWidget(&skeletonURLEdit);
- skeletonModelLayout.addWidget(&SkeletonBrowseButton);
- form->addRow("Skeleton URL:", &skeletonModelLayout);
-
-
- QString displayNameString = applicationInstance->getAvatar()->getDisplayName();
- QLineEdit* displayNameEdit = new QLineEdit(displayNameString);
- displayNameEdit->setMinimumWidth(QLINE_MINIMUM_WIDTH);
- form->addRow("Display name:", displayNameEdit);
-
- QSlider* pupilDilation = new QSlider(Qt::Horizontal);
- pupilDilation->setValue(applicationInstance->getAvatar()->getHead()->getPupilDilation() * pupilDilation->maximum());
- form->addRow("Pupil Dilation:", pupilDilation);
-
- QSlider* faceshiftEyeDeflection = new QSlider(Qt::Horizontal);
- faceshiftEyeDeflection->setValue(_faceshiftEyeDeflection * faceshiftEyeDeflection->maximum());
- form->addRow("Faceshift Eye Deflection:", faceshiftEyeDeflection);
-
- QSpinBox* fieldOfView = new QSpinBox();
- fieldOfView->setMaximum(180.f);
- fieldOfView->setMinimum(1.f);
- fieldOfView->setValue(_fieldOfView);
- form->addRow("Vertical Field of View (Degrees):", fieldOfView);
-
- QDoubleSpinBox* leanScale = new QDoubleSpinBox();
- leanScale->setValue(applicationInstance->getAvatar()->getLeanScale());
- form->addRow("Lean Scale:", leanScale);
-
- QDoubleSpinBox* avatarScale = new QDoubleSpinBox();
- avatarScale->setValue(applicationInstance->getAvatar()->getScale());
- form->addRow("Avatar Scale:", avatarScale);
-
- QSpinBox* audioJitterBufferSamples = new QSpinBox();
- audioJitterBufferSamples->setMaximum(10000);
- audioJitterBufferSamples->setMinimum(-10000);
- audioJitterBufferSamples->setValue(_audioJitterBufferSamples);
- form->addRow("Audio Jitter Buffer Samples (0 for automatic):", audioJitterBufferSamples);
-
- QSpinBox* maxVoxels = new QSpinBox();
- const int MAX_MAX_VOXELS = 5000000;
- const int MIN_MAX_VOXELS = 0;
- const int STEP_MAX_VOXELS = 50000;
- maxVoxels->setMaximum(MAX_MAX_VOXELS);
- maxVoxels->setMinimum(MIN_MAX_VOXELS);
- maxVoxels->setSingleStep(STEP_MAX_VOXELS);
- maxVoxels->setValue(_maxVoxels);
- form->addRow("Maximum Voxels:", maxVoxels);
-
- QSpinBox* maxVoxelsPPS = new QSpinBox();
- const int MAX_MAX_VOXELS_PPS = 6000;
- const int MIN_MAX_VOXELS_PPS = 60;
- const int STEP_MAX_VOXELS_PPS = 10;
- maxVoxelsPPS->setMaximum(MAX_MAX_VOXELS_PPS);
- maxVoxelsPPS->setMinimum(MIN_MAX_VOXELS_PPS);
- maxVoxelsPPS->setSingleStep(STEP_MAX_VOXELS_PPS);
- maxVoxelsPPS->setValue(_maxVoxelPacketsPerSecond);
- form->addRow("Maximum Voxels Packets Per Second:", maxVoxelsPPS);
-
- QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
- dialog.connect(buttons, SIGNAL(accepted()), SLOT(accept()));
- dialog.connect(buttons, SIGNAL(rejected()), SLOT(reject()));
- layout->addWidget(buttons);
-
- int ret = dialog.exec();
- if (ret == QDialog::Accepted) {
- bool shouldDispatchIdentityPacket = false;
-
- if (headURLEdit.text() != faceURLString) {
- // change the faceModelURL in the profile, it will also update this user's BlendFace
- if (headURLEdit.text().isEmpty()) {
- applicationInstance->getAvatar()->setFaceModelURL(QUrl(headURLEdit.placeholderText()));
- } else {
- applicationInstance->getAvatar()->setFaceModelURL(QUrl(headURLEdit.text()));
- }
- shouldDispatchIdentityPacket = true;
- }
-
- if (skeletonURLEdit.text() != skeletonURLString) {
- // change the skeletonModelURL in the profile, it will also update this user's Body
- if (skeletonURLEdit.text().isEmpty()) {
- applicationInstance->getAvatar()->setSkeletonModelURL(QUrl(skeletonURLEdit.placeholderText()));
- } else {
- applicationInstance->getAvatar()->setSkeletonModelURL(QUrl(skeletonURLEdit.text()));
- }
- shouldDispatchIdentityPacket = true;
- }
-
- QString displayNameStr(displayNameEdit->text());
-
- if (displayNameStr != displayNameString) {
- applicationInstance->getAvatar()->setDisplayName(displayNameStr);
- shouldDispatchIdentityPacket = true;
- }
-
- if (shouldDispatchIdentityPacket) {
- applicationInstance->getAvatar()->sendIdentityPacket();
- }
-
- applicationInstance->getAvatar()->getHead()->setPupilDilation(pupilDilation->value() / (float)pupilDilation->maximum());
-
- _maxVoxels = maxVoxels->value();
- applicationInstance->getVoxels()->setMaxVoxels(_maxVoxels);
-
- _maxVoxelPacketsPerSecond = maxVoxelsPPS->value();
-
- applicationInstance->getAvatar()->setLeanScale(leanScale->value());
- applicationInstance->getAvatar()->setClampedTargetScale(avatarScale->value());
-
- _audioJitterBufferSamples = audioJitterBufferSamples->value();
-
- if (_audioJitterBufferSamples != 0) {
- applicationInstance->getAudio()->setJitterBufferSamples(_audioJitterBufferSamples);
- }
-
- _fieldOfView = fieldOfView->value();
- applicationInstance->resizeGL(applicationInstance->getGLWidget()->width(), applicationInstance->getGLWidget()->height());
-
- _faceshiftEyeDeflection = faceshiftEyeDeflection->value() / (float)faceshiftEyeDeflection->maximum();
+ if (!_preferencesDialog) {
+ _preferencesDialog = new PreferencesDialog(Application::getInstance()->getWindow());
+ _preferencesDialog->show();
+ } else {
+ _preferencesDialog->close();
}
- QMetaObject::invokeMethod(applicationInstance->getAudio(), "reset", Qt::QueuedConnection);
-
- sendFakeEnterEvent();
}
void Menu::goToDomain(const QString newDomain) {
diff --git a/interface/src/Menu.h b/interface/src/Menu.h
index fb71efa5e5..e827e43014 100644
--- a/interface/src/Menu.h
+++ b/interface/src/Menu.h
@@ -22,6 +22,7 @@
#include
#include "location/LocationManager.h"
+#include "ui/PreferencesDialog.h"
#include "ui/ChatWindow.h"
const float ADJUST_LOD_DOWN_FPS = 40.0;
@@ -71,10 +72,13 @@ public:
void triggerOption(const QString& menuOption);
QAction* getActionForOption(const QString& menuOption);
-
+
float getAudioJitterBufferSamples() const { return _audioJitterBufferSamples; }
+ void setAudioJitterBufferSamples(float audioJitterBufferSamples) { _audioJitterBufferSamples = audioJitterBufferSamples; }
float getFieldOfView() const { return _fieldOfView; }
+ void setFieldOfView(float fieldOfView) { _fieldOfView = fieldOfView; }
float getFaceshiftEyeDeflection() const { return _faceshiftEyeDeflection; }
+ void setFaceshiftEyeDeflection(float faceshiftEyeDeflection) { _faceshiftEyeDeflection = faceshiftEyeDeflection; }
BandwidthDialog* getBandwidthDialog() const { return _bandwidthDialog; }
FrustumDrawMode getFrustumDrawMode() const { return _frustumDrawMode; }
ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; }
@@ -97,6 +101,7 @@ public:
// User Tweakable PPS from Voxel Server
int getMaxVoxelPacketsPerSecond() const { return _maxVoxelPacketsPerSecond; }
+ void setMaxVoxelPacketsPerSecond(int maxVoxelPacketsPerSecond) { _maxVoxelPacketsPerSecond = maxVoxelPacketsPerSecond; }
QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
const QString& actionName,
@@ -222,6 +227,7 @@ private:
SimpleMovingAverage _fpsAverage;
SimpleMovingAverage _fastFPSAverage;
QAction* _loginAction;
+ QPointer _preferencesDialog;
QAction* _chatAction;
};
diff --git a/interface/src/ui/FramelessDialog.cpp b/interface/src/ui/FramelessDialog.cpp
new file mode 100644
index 0000000000..18e3bca89a
--- /dev/null
+++ b/interface/src/ui/FramelessDialog.cpp
@@ -0,0 +1,100 @@
+//
+// FramelessDialog.cpp
+// interface/src/ui
+//
+// Created by Stojce Slavkovski on 2/20/14.
+// Copyright 2014 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 "Application.h"
+#include "FramelessDialog.h"
+
+const int RESIZE_HANDLE_WIDTH = 7;
+
+FramelessDialog::FramelessDialog(QWidget *parent, Qt::WindowFlags flags) :
+QDialog(parent, flags | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint) {
+ setAttribute(Qt::WA_DeleteOnClose);
+
+ // handle rezize and move events
+ parentWidget()->installEventFilter(this);
+
+ // handle minimize, restore and focus events
+ Application::getInstance()->installEventFilter(this);
+}
+
+bool FramelessDialog::eventFilter(QObject* sender, QEvent* event) {
+ switch (event->type()) {
+ case QEvent::Move:
+ if (sender == parentWidget()) {
+ // move to upper left corner on app move
+ move(parentWidget()->geometry().topLeft());
+ }
+ break;
+ case QEvent::Resize:
+ if (sender == parentWidget()) {
+ // keep full app height on resizing the app
+ setFixedHeight(parentWidget()->size().height());
+ }
+ break;
+ case QEvent::WindowStateChange:
+ if (parentWidget()->isMinimized()) {
+ setHidden(true);
+ } else {
+ setHidden(false);
+ }
+ break;
+ case QEvent::ApplicationDeactivate:
+ // hide on minimize and focus lost
+ setHidden(true);
+ break;
+ case QEvent::ApplicationActivate:
+ setHidden(false);
+ break;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+void FramelessDialog::setStyleSheetFile(const QString& fileName) {
+ QFile globalStyleSheet(Application::resourcesPath() + "styles/global.qss");
+ QFile styleSheet(Application::resourcesPath() + fileName);
+ if (styleSheet.open(QIODevice::ReadOnly) && globalStyleSheet.open(QIODevice::ReadOnly) ) {
+ QDir::setCurrent(Application::resourcesPath());
+ setStyleSheet(globalStyleSheet.readAll() + styleSheet.readAll());
+ }
+}
+
+void FramelessDialog::showEvent(QShowEvent* event) {
+ // move to upper left corner
+ move(parentWidget()->geometry().topLeft());
+
+ // keep full app height
+ setFixedHeight(parentWidget()->size().height());
+
+ // resize parrent if width is smaller than this dialog
+ if (parentWidget()->size().width() < size().width()) {
+ parentWidget()->resize(size().width(), parentWidget()->size().height());
+ }
+}
+void FramelessDialog::mousePressEvent(QMouseEvent* mouseEvent) {
+ if (abs(mouseEvent->pos().x() - size().width()) < RESIZE_HANDLE_WIDTH && mouseEvent->button() == Qt::LeftButton) {
+ _isResizing = true;
+ QApplication::setOverrideCursor(Qt::SizeHorCursor);
+ }
+}
+
+void FramelessDialog::mouseReleaseEvent(QMouseEvent* mouseEvent) {
+ QApplication::restoreOverrideCursor();
+ _isResizing = false;
+}
+
+void FramelessDialog::mouseMoveEvent(QMouseEvent* mouseEvent) {
+ if (_isResizing) {
+ resize(mouseEvent->pos().x(), size().height());
+ }
+}
diff --git a/interface/src/ui/FramelessDialog.h b/interface/src/ui/FramelessDialog.h
new file mode 100644
index 0000000000..db9f6dfd6c
--- /dev/null
+++ b/interface/src/ui/FramelessDialog.h
@@ -0,0 +1,38 @@
+//
+// FramelessDialog.h
+// interface/src/ui
+//
+// Created by Stojce Slavkovski on 2/20/14.
+// Copyright 2014 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
+//
+
+
+#ifndef hifi_FramelessDialog_h
+#define hifi_FramelessDialog_h
+
+#include
+
+class FramelessDialog : public QDialog {
+ Q_OBJECT
+
+public:
+ FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0);
+ void setStyleSheetFile(const QString& fileName);
+
+protected:
+ virtual void mouseMoveEvent(QMouseEvent* mouseEvent);
+ virtual void mousePressEvent(QMouseEvent* mouseEvent);
+ virtual void mouseReleaseEvent(QMouseEvent* mouseEvent);
+ virtual void showEvent(QShowEvent* event);
+
+ bool eventFilter(QObject* sender, QEvent* event);
+
+private:
+ bool _isResizing;
+
+};
+
+#endif // hifi_FramelessDialog_h
diff --git a/interface/src/ui/ModelsBrowser.cpp b/interface/src/ui/ModelsBrowser.cpp
index 6c421863c8..77e056bdd3 100644
--- a/interface/src/ui/ModelsBrowser.cpp
+++ b/interface/src/ui/ModelsBrowser.cpp
@@ -65,7 +65,7 @@ static const QString propertiesIds[MODEL_METADATA_COUNT] = {
};
ModelsBrowser::ModelsBrowser(ModelType modelsType, QWidget* parent) :
- QWidget(parent),
+ QWidget(parent, Qt::WindowStaysOnTopHint),
_handler(new ModelHandler(modelsType))
{
connect(_handler, SIGNAL(doneDownloading()), SLOT(resizeView()));
diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp
new file mode 100644
index 0000000000..d1c9b4f6ca
--- /dev/null
+++ b/interface/src/ui/PreferencesDialog.cpp
@@ -0,0 +1,163 @@
+//
+// PreferencesDialog.cpp
+// interface/src/ui
+//
+// Created by Stojce Slavkovski on 2/20/14.
+// Copyright 2014 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 "Application.h"
+#include "Menu.h"
+#include "PreferencesDialog.h"
+#include "ModelsBrowser.h"
+
+const int SCROLL_PANEL_BOTTOM_MARGIN = 30;
+const int OK_BUTTON_RIGHT_MARGIN = 30;
+const int BUTTONS_TOP_MARGIN = 24;
+
+PreferencesDialog::PreferencesDialog(QWidget* parent, Qt::WindowFlags flags) : FramelessDialog(parent, flags) {
+
+ ui.setupUi(this);
+ setStyleSheetFile("styles/preferences.qss");
+ loadPreferences();
+ connect(ui.closeButton, &QPushButton::clicked, this, &QDialog::close);
+
+ connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &PreferencesDialog::openHeadModelBrowser);
+ connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &PreferencesDialog::openBodyModelBrowser);
+}
+
+void PreferencesDialog::accept() {
+ savePreferences();
+ close();
+}
+
+void PreferencesDialog::setHeadUrl(QString modelUrl) {
+ ui.faceURLEdit->setText(modelUrl);
+ setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
+}
+
+void PreferencesDialog::setSkeletonUrl(QString modelUrl) {
+ ui.skeletonURLEdit->setText(modelUrl);
+ setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
+}
+
+void PreferencesDialog::openHeadModelBrowser() {
+ setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
+ ModelsBrowser modelBrowser(Head);
+ connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setHeadUrl);
+ modelBrowser.browse();
+}
+
+void PreferencesDialog::openBodyModelBrowser() {
+ setWindowFlags(windowFlags() & ~Qt::WindowStaysOnTopHint);
+ ModelsBrowser modelBrowser(Skeleton);
+ connect(&modelBrowser, &ModelsBrowser::selected, this, &PreferencesDialog::setSkeletonUrl);
+ modelBrowser.browse();
+}
+
+void PreferencesDialog::resizeEvent(QResizeEvent *resizeEvent) {
+
+ // keep buttons panel at the bottom
+ ui.buttonsPanel->setGeometry(0, size().height() - ui.buttonsPanel->height(), size().width(), ui.buttonsPanel->height());
+
+ // set width and height of srcollarea to match bottom panel and width
+ ui.scrollArea->setGeometry(ui.scrollArea->geometry().x(), ui.scrollArea->geometry().y(),
+ size().width(),
+ size().height() - ui.buttonsPanel->height() -
+ SCROLL_PANEL_BOTTOM_MARGIN - ui.scrollArea->geometry().y());
+
+ // move Save button to left position
+ ui.defaultButton->move(size().width() - OK_BUTTON_RIGHT_MARGIN - ui.defaultButton->size().width(), BUTTONS_TOP_MARGIN);
+
+ // move Save button to left position
+ ui.cancelButton->move(ui.defaultButton->pos().x() - ui.cancelButton->size().width(), BUTTONS_TOP_MARGIN);
+
+ // move close button
+ ui.closeButton->move(size().width() - OK_BUTTON_RIGHT_MARGIN - ui.closeButton->size().width(), ui.closeButton->pos().y());
+}
+
+void PreferencesDialog::loadPreferences() {
+
+ MyAvatar* myAvatar = Application::getInstance()->getAvatar();
+ Menu* menuInstance = Menu::getInstance();
+
+ _displayNameString = myAvatar->getDisplayName();
+ ui.displayNameEdit->setText(_displayNameString);
+
+ _faceURLString = myAvatar->getHead()->getFaceModel().getURL().toString();
+ ui.faceURLEdit->setText(_faceURLString);
+
+ _skeletonURLString = myAvatar->getSkeletonModel().getURL().toString();
+ ui.skeletonURLEdit->setText(_skeletonURLString);
+
+ ui.pupilDilationSlider->setValue(myAvatar->getHead()->getPupilDilation() *
+ ui.pupilDilationSlider->maximum());
+
+ ui.faceshiftEyeDeflectionSider->setValue(menuInstance->getFaceshiftEyeDeflection() *
+ ui.faceshiftEyeDeflectionSider->maximum());
+
+ ui.audioJitterSpin->setValue(menuInstance->getAudioJitterBufferSamples());
+
+ ui.fieldOfViewSpin->setValue(menuInstance->getFieldOfView());
+
+ ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
+
+ ui.avatarScaleSpin->setValue(myAvatar->getScale());
+
+ ui.maxVoxelsSpin->setValue(menuInstance->getMaxVoxels());
+
+ ui.maxVoxelsPPSSpin->setValue(menuInstance->getMaxVoxelPacketsPerSecond());
+}
+
+void PreferencesDialog::savePreferences() {
+
+ MyAvatar* myAvatar = Application::getInstance()->getAvatar();
+ bool shouldDispatchIdentityPacket = false;
+
+ QString displayNameStr(ui.displayNameEdit->text());
+ if (displayNameStr != _displayNameString) {
+ myAvatar->setDisplayName(displayNameStr);
+ shouldDispatchIdentityPacket = true;
+ }
+
+ QUrl faceModelURL(ui.faceURLEdit->text());
+ if (faceModelURL.toString() != _faceURLString) {
+ // change the faceModelURL in the profile, it will also update this user's BlendFace
+ myAvatar->setFaceModelURL(faceModelURL);
+ shouldDispatchIdentityPacket = true;
+ }
+
+ QUrl skeletonModelURL(ui.skeletonURLEdit->text());
+ if (skeletonModelURL.toString() != _skeletonURLString) {
+ // change the skeletonModelURL in the profile, it will also update this user's Body
+ myAvatar->setSkeletonModelURL(skeletonModelURL);
+ shouldDispatchIdentityPacket = true;
+ }
+
+ if (shouldDispatchIdentityPacket) {
+ myAvatar->sendIdentityPacket();
+ }
+
+ myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
+ myAvatar->setLeanScale(ui.leanScaleSpin->value());
+ myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value());
+
+ Application::getInstance()->getVoxels()->setMaxVoxels(ui.maxVoxelsSpin->value());
+ Application::getInstance()->resizeGL(Application::getInstance()->getGLWidget()->width(),
+ Application::getInstance()->getGLWidget()->height());
+
+ Menu::getInstance()->setFieldOfView(ui.fieldOfViewSpin->value());
+
+ Menu::getInstance()->setFaceshiftEyeDeflection(ui.faceshiftEyeDeflectionSider->value() /
+ (float)ui.faceshiftEyeDeflectionSider->maximum());
+ Menu::getInstance()->setMaxVoxelPacketsPerSecond(ui.maxVoxelsPPSSpin->value());
+
+ Menu::getInstance()->setAudioJitterBufferSamples(ui.audioJitterSpin->value());
+
+ Application::getInstance()->resizeGL(Application::getInstance()->getGLWidget()->width(),
+ Application::getInstance()->getGLWidget()->height());
+}
diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h
new file mode 100644
index 0000000000..c9514e584a
--- /dev/null
+++ b/interface/src/ui/PreferencesDialog.h
@@ -0,0 +1,47 @@
+//
+// PreferencesDialog.h
+// interface/src/ui
+//
+// Created by Stojce Slavkovski on 2/20/14.
+// Copyright 2014 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
+//
+
+#ifndef hifi_PreferencesDialog_h
+#define hifi_PreferencesDialog_h
+
+#include "FramelessDialog.h"
+#include "ui_preferencesDialog.h"
+
+#include
+
+class PreferencesDialog : public FramelessDialog {
+ Q_OBJECT
+
+public:
+ PreferencesDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0);
+
+protected:
+ void resizeEvent(QResizeEvent* resizeEvent);
+
+private:
+ void loadPreferences();
+ void savePreferences();
+ void openHeadModelBrowser();
+ void openBodyModelBrowser();
+
+ Ui_PreferencesDialog ui;
+ QString _faceURLString;
+ QString _skeletonURLString;
+ QString _displayNameString;
+
+private slots:
+ void accept();
+ void setHeadUrl(QString modelUrl);
+ void setSkeletonUrl(QString modelUrl);
+
+};
+
+#endif // hifi_PreferencesDialog_h
diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui
new file mode 100644
index 0000000000..a151a499c6
--- /dev/null
+++ b/interface/ui/preferencesDialog.ui
@@ -0,0 +1,1375 @@
+
+
+ PreferencesDialog
+
+
+
+ 0
+ 0
+ 638
+ 652
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 610
+ 0
+
+
+
+ 0.950000000000000
+
+
+
+
+ 0
+ 560
+ 611
+ 97
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 97
+
+
+
+
+ Arial
+
+
+
+ background-color: #0e7077
+
+
+
+
+ 310
+ 24
+ 91
+ 50
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 50
+
+
+
+
+ Arial
+ 18
+ 50
+ false
+
+
+
+
+
+
+ Cancel
+
+
+
+
+
+ 400
+ 24
+ 188
+ 50
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 188
+ 49
+
+
+
+
+ Arial
+ 18
+
+
+
+ background-color: #fff;
+color: #0e7077
+
+
+ Save all changes
+
+
+ true
+
+
+
+
+
+
+ 0
+ 30
+ 615
+ 491
+
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Plain
+
+
+ 0
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 615
+ 833
+
+
+
+
+ 0
+
+
+ 30
+
+
+ 0
+
+
+ 30
+
+
+ 30
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ Arial
+ 24
+
+
+
+ color: #0e7077
+
+
+ Avatar
+
+
+ 25
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 30
+
+
+
+
+ Arial
+ 16
+
+
+
+ color: #0e7077
+
+
+ <html><head/><body><p>Avatar display name <span style=" color:#909090;">(optional)</span></p></body></html>
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+ displayNameEdit
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 280
+ 0
+
+
+
+
+ Arial
+
+
+
+ Qt::LeftToRight
+
+
+
+
+
+ Not showing a name
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 30
+
+
+
+
+ Arial
+ 16
+
+
+
+ color: #0e7077
+
+
+ Head
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+ 0
+
+
+ faceURLEdit
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ Arial
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 30
+ 30
+
+
+
+
+ 30
+ 30
+
+
+
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 30
+
+
+
+
+ Arial
+ 16
+
+
+
+ color: #0e7077
+
+
+ Body
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+ skeletonURLEdit
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ Arial
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 30
+ 30
+
+
+
+
+ 30
+ 30
+
+
+
+
+
+
+
+
+
+
+ 30
+ 30
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 0
+ 35
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ Arial
+ 24
+
+
+
+ color: #0e7077
+
+
+ Advanced Tuning
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
+ 25
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ Arial
+ 16
+
+
+
+ true
+
+
+ color: rgb(51, 51, 51);
+
+
+ It's not recomended that you play with these settings unless you've looked into exactly what they do.
+
+
+ false
+
+
+ true
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 40
+
+
+
+
+ Arial
+ 20
+ 50
+ false
+
+
+
+ color: #0e7077
+
+
+ Avatar
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ -
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 10
+
+
-
+
+
+
+ Arial
+
+
+
+
+
+
+ Vertical field of view
+
+
+ 15
+
+
+ fieldOfViewSpin
+
+
+
+ -
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 95
+ 36
+
+
+
+
+ 95
+ 36
+
+
+
+
+ Arial
+
+
+
+ 1
+
+
+ 180
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 10
+
+
+ 10
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 25
+
+
+
+
+ Arial
+
+
+
+ color: rgb(51, 51, 51)
+
+
+ Lean scale (applies to Faceshift users)
+
+
+ 15
+
+
+ leanScaleSpin
+
+
+
+ -
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+ QSizePolicy::Expanding
+
+
+
+ 40
+ 10
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 95
+ 36
+
+
+
+
+ 70
+ 16777215
+
+
+
+
+ Arial
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 10
+
+
-
+
+
+
+ Arial
+
+
+
+ color: rgb(51, 51, 51)
+
+
+ Avatar scale <span style=" color:#909090;">(default is 1.0)</span>
+
+
+ 15
+
+
+ avatarScaleSpin
+
+
+
+ -
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 95
+ 36
+
+
+
+
+ 70
+ 16777215
+
+
+
+
+ Arial
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 10
+
+
-
+
+
+
+ Arial
+
+
+
+ color: rgb(51, 51, 51)
+
+
+ Pupil dillation
+
+
+ 15
+
+
+ pupilDilationSlider
+
+
+
+ -
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 125
+ 0
+
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 10
+
+
-
+
+
+
+ Arial
+
+
+
+ color: rgb(51, 51, 51)
+
+
+ Audio Jitter Buffer Samples (0 for automatic)
+
+
+ 15
+
+
+ audioJitterSpin
+
+
+
+ -
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 95
+ 36
+
+
+
+
+ 70
+ 16777215
+
+
+
+
+ Arial
+
+
+
+ -10000
+
+
+ 10000
+
+
+ 1
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 10
+
+
-
+
+
+
+ Arial
+
+
+
+ color: rgb(51, 51, 51)
+
+
+ Faceshift eye detection
+
+
+ 15
+
+
+ faceshiftEyeDeflectionSider
+
+
+
+ -
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 125
+ 0
+
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 40
+
+
+
+
+ Arial
+ 20
+ 50
+ false
+
+
+
+ color: #0e7077
+
+
+ Voxels
+
+
+ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft
+
+
+
+ -
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 10
+
+
-
+
+
+
+ Arial
+
+
+
+ color: rgb(51, 51, 51)
+
+
+ Maximum voxels
+
+
+ 15
+
+
+ maxVoxelsSpin
+
+
+
+ -
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 125
+ 36
+
+
+
+
+ Arial
+
+
+
+ 5000000
+
+
+ 50000
+
+
+
+
+
+ -
+
+
+ 0
+
+
+ 10
+
+
+ 0
+
+
+ 10
+
+
-
+
+
+
+ Arial
+
+
+
+ Max voxels sent each second
+
+
+ 15
+
+
+ maxVoxelsPPSSpin
+
+
+
+ -
+
+
+
+ Arial
+
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 95
+ 36
+
+
+
+
+ 70
+ 16777215
+
+
+
+
+ Arial
+
+
+
+ 60
+
+
+ 6000
+
+
+ 10
+
+
+
+
+
+
+
+
+
+
+
+ 540
+ 24
+ 31
+ 31
+
+
+
+
+ PreferAntialias
+
+
+
+
+
+
+
+
+
+ FramelessDialog
+ 1
+
+
+
+
+
+ cancelButton
+ clicked()
+ PreferencesDialog
+ close()
+
+
+ 495
+ 749
+
+
+ 528
+ 0
+
+
+
+
+ defaultButton
+ clicked()
+ PreferencesDialog
+ accept()
+
+
+ 504
+ 749
+
+
+ 20
+ 20
+
+
+
+
+