Merge branch 'master' into 20276

This commit is contained in:
David Rowe 2015-01-27 19:08:40 -08:00
commit 7286a9c5fb
112 changed files with 3442 additions and 2151 deletions

View file

@ -7,6 +7,7 @@
* IMPORTANT: OpenSSL 1.0.1g is critical to avoid a security vulnerability.
* [Intel Threading Building Blocks](https://www.threadingbuildingblocks.org/) ~> 4.3
* [Bullet Physics Engine](https://code.google.com/p/bullet/downloads/list) ~> 2.82
* [Gverb](https://github.com/highfidelity/gverb/archive/master.zip) (direct download to latest version)
### OS Specific Build Guides
* [BUILD_WIN.md](BUILD_WIN.md) - additional instructions for Windows.
@ -54,11 +55,11 @@ In the examples below the variable $NAME would be replaced by the name of the de
####QXmpp
You can find QXmpp [here](https://github.com/qxmpp-project/qxmpp). The inclusion of the QXmpp enables text chat in the Interface client.
You can [find QXmpp here](https://github.com/qxmpp-project/qxmpp), 0.7.6 is the version you want. The inclusion of the QXmpp enables text chat in the Interface client.
OS X users who tap our [homebrew formulas repository](https://github.com/highfidelity/homebrew-formulas) can install QXmpp via homebrew - `brew install highfidelity/formulas/qxmpp`.
####Devices
You can support external input/output devices such as Leap Motion, Faceshift, PrioVR, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device.
You can support external input/output devices such as Oculus Rift, Leap Motion, Faceshift, PrioVR, MIDI, Razr Hydra and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device.

View file

@ -38,6 +38,8 @@ Once Qt is installed, you need to manually configure the following:
###External Libraries
As it stands, Hifi/Interface is a 32-bit application, so all libraries should also be 32-bit.
CMake will need to know where the headers and libraries for required external dependencies are.
The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure:
@ -75,7 +77,7 @@ As with the Qt libraries, you will need to make sure that directories containing
###OpenSSL
QT will use OpenSSL if it's available, but it doesn't install it, so you must install it separately.
Qt will use OpenSSL if it's available, but it doesn't install it, so you must install it separately.
Your system may already have several versions of the OpenSSL DLL's (ssleay32.dll, libeay32.dll) lying around, but they may be the wrong version. If these DLL's are in the PATH then QT will try to use them, and if they're the wrong version then you will see the following errors in the console:
@ -89,7 +91,7 @@ Your system may already have several versions of the OpenSSL DLL's (ssleay32.dll
To prevent these problems, install OpenSSL yourself. Download the following binary packages [from this website](http://slproweb.com/products/Win32OpenSSL.html):
* Visual C++ 2008 Redistributables
* Win32 OpenSSL v1.0.1h
* Win32 OpenSSL v1.0.1L
Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version.
@ -133,6 +135,20 @@ This package contains only headers, so there's nothing to add to the PATH.
Be careful with glm. For the folder other libraries would normally call 'include', the folder containing the headers, glm opts to use 'glm'. You will have a glm folder nested inside the top-level glm folder.
###Gverb
1. Go to https://github.com/highfidelity/gverb
Or download the sources directly via this link:
https://github.com/highfidelity/gverb/archive/master.zip
2. Extract the archive
3. Place the directories “include” and “src” in interface/external/gverb
(Normally next to this readme)
4. Clear your build directory, run cmake, build and you should be all set.
###Bullet
Bullet 2.82 source can be [downloaded here](https://code.google.com/p/bullet/downloads/detail?name=bullet-2.82-r2704.zip). Bullet does not come with prebuilt libraries, you need to make those yourself.

View file

@ -9,10 +9,11 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QtCore/QProcess>
#include <QtCore/qsharedmemory.h>
#include <QtCore/QThread>
#include <QtCore/QTimer>
#include <QProcess>
#include <QSettings>
#include <QSharedMemory>
#include <QThread>
#include <QTimer>
#include <AccountManager.h>
#include <AddressManager.h>

View file

@ -13,21 +13,22 @@
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <QtCore/QDir>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
#include <QtCore/QJsonArray>
#include <QtCore/QProcess>
#include <QtCore/qsharedmemory.h>
#include <QtCore/QStandardPaths>
#include <QtCore/QTimer>
#include <QtCore/QUrlQuery>
#include <QDir>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QProcess>
#include <QSharedMemory>
#include <QStandardPaths>
#include <QTimer>
#include <QUrlQuery>
#include <AccountManager.h>
#include <HifiConfigVariantMap.h>
#include <HTTPConnection.h>
#include <LogUtils.h>
#include <PacketHeaders.h>
#include <Settings.h>
#include <SharedUtil.h>
#include <ShutdownEventListener.h>
#include <UUID.h>
@ -1920,10 +1921,8 @@ Headers DomainServer::setupCookieHeadersFromProfileReply(QNetworkReply* profileR
_cookieSessionHash.insert(cookieUUID, sessionData);
// persist the cookie to settings file so we can get it back on DS relaunch
QSettings localSettings;
localSettings.beginGroup(DS_SETTINGS_SESSIONS_GROUP);
QVariant sessionVariant = QVariant::fromValue(sessionData);
localSettings.setValue(cookieUUID.toString(), QVariant::fromValue(sessionData));
QStringList path = QStringList() << DS_SETTINGS_SESSIONS_GROUP << cookieUUID.toString();
SettingHandles::SettingHandle<QVariant>(path).set(QVariant::fromValue(sessionData));
// setup expiry for cookie to 1 month from today
QDateTime cookieExpiry = QDateTime::currentDateTimeUtc().addMonths(1);
@ -1943,11 +1942,12 @@ Headers DomainServer::setupCookieHeadersFromProfileReply(QNetworkReply* profileR
void DomainServer::loadExistingSessionsFromSettings() {
// read data for existing web sessions into memory so existing sessions can be leveraged
QSettings domainServerSettings;
Settings domainServerSettings;
domainServerSettings.beginGroup(DS_SETTINGS_SESSIONS_GROUP);
foreach(const QString& uuidKey, domainServerSettings.childKeys()) {
_cookieSessionHash.insert(QUuid(uuidKey), domainServerSettings.value(uuidKey).value<DomainServerWebSessionData>());
_cookieSessionHash.insert(QUuid(uuidKey),
domainServerSettings.value(uuidKey).value<DomainServerWebSessionData>());
qDebug() << "Pulled web session from settings - cookie UUID is" << uuidKey;
}
}

View file

@ -669,6 +669,10 @@ function mouseClickEvent(event) {
print("Model selected: " + foundEntity.id);
selectionDisplay.select(selectedEntityID, event);
cameraManager.focus(selectionManager.worldPosition,
selectionManager.worldDimensions,
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
}
}
}

View file

@ -38,8 +38,8 @@
#include <QObject>
#include <QWheelEvent>
#include <QScreen>
#include <QSettings>
#include <QShortcut>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QUrl>
#include <QWindow>
@ -73,13 +73,16 @@
#include <PhysicsEngine.h>
#include <ProgramObject.h>
#include <ResourceCache.h>
#include <Settings.h>
#include <SoundCache.h>
#include <TextRenderer.h>
#include <UserActivityLogger.h>
#include <UUID.h>
#include "Application.h"
#include "Audio.h"
#include "InterfaceVersion.h"
#include "LODManager.h"
#include "Menu.h"
#include "ModelUploader.h"
#include "Util.h"
@ -100,7 +103,6 @@
#include "gpu/Batch.h"
#include "gpu/GLBackend.h"
#include "scripting/AccountScriptingInterface.h"
#include "scripting/AudioDeviceScriptingInterface.h"
#include "scripting/ClipboardScriptingInterface.h"
@ -112,9 +114,16 @@
#include "scripting/WindowScriptingInterface.h"
#include "scripting/WebWindowClass.h"
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
#include "SpeechRecognizer.h"
#endif
#include "ui/DataWebDialog.h"
#include "ui/DialogsManager.h"
#include "ui/InfoView.h"
#include "ui/LoginDialog.h"
#include "ui/Snapshot.h"
#include "ui/StandAloneJSConsole.h"
#include "ui/Stats.h"
@ -137,6 +146,12 @@ const QString SKIP_FILENAME = QStandardPaths::writableLocation(QStandardPaths::D
const QString DEFAULT_SCRIPTS_JS_URL = "http://s3.amazonaws.com/hifi-public/scripts/defaultScripts.js";
namespace SettingHandles {
const SettingHandle<bool> firstRun("firstRun", true);
const SettingHandle<QString> lastScriptLocation("LastScriptLocation");
const SettingHandle<QString> scriptsLocation("scriptsLocation");
}
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) {
QString logMessage = LogHandler::getInstance().printMessage((LogMsgType) type, context, message);
@ -183,6 +198,12 @@ bool setupEssentials(int& argc, char** argv) {
auto ddeFaceTracker = DependencyManager::set<DdeFaceTracker>();
auto modelBlender = DependencyManager::set<ModelBlender>();
auto audioToolBox = DependencyManager::set<AudioToolBox>();
auto lodManager = DependencyManager::set<LODManager>();
auto jsConsole = DependencyManager::set<StandAloneJSConsole>();
auto dialogsManager = DependencyManager::set<DialogsManager>();
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
auto speechRecognizer = DependencyManager::set<SpeechRecognizer>();
#endif
return true;
}
@ -276,6 +297,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
auto audioIO = DependencyManager::get<Audio>();
audioIO->moveToThread(audioThread);
connect(audioThread, &QThread::started, audioIO.data(), &Audio::start);
connect(audioIO.data(), SIGNAL(muteToggled()), this, SLOT(audioMuteToggled()));
audioThread->start();
@ -287,7 +309,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(clearDomainOctreeDetails()));
connect(&domainHandler, &DomainHandler::settingsReceived, this, &Application::domainSettingsReceived);
connect(&domainHandler, &DomainHandler::hostnameChanged, Menu::getInstance(), &Menu::clearLoginDialogDisplayedFlag);
connect(&domainHandler, &DomainHandler::hostnameChanged,
DependencyManager::get<AddressManager>().data(), &AddressManager::storeCurrentAddress);
// update our location every 5 seconds in the data-server, assuming that we are authenticated with one
const qint64 DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5 * 1000;
@ -313,7 +336,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
connect(&accountManager, &AccountManager::balanceChanged, this, &Application::updateWindowTitle);
connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain);
auto dialogsManager = DependencyManager::get<DialogsManager>();
connect(&accountManager, &AccountManager::authRequired, dialogsManager.data(), &DialogsManager::showLoginDialog);
connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle);
// once we have a profile in account manager make sure we generate a new keypair
@ -334,9 +358,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
connect(addressManager.data(), &AddressManager::rootPlaceNameChanged, this, &Application::updateWindowTitle);
_settings = new QSettings(this);
_numChangedSettings = 0;
#ifdef _WIN32
WSADATA WsaData;
int wsaresult = WSAStartup(MAKEWORD(2,2), &WsaData);
@ -377,7 +398,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_window->setCentralWidget(glCanvas.data());
restoreSizeAndPosition();
_window->restoreGeometry();
_window->setVisible(true);
glCanvas->setFocusPolicy(Qt::StrongFocus);
@ -411,23 +432,31 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
connect(this, SIGNAL(aboutToQuit()), this, SLOT(aboutToQuit()));
// check first run...
QVariant firstRunValue = _settings->value("firstRun",QVariant(true));
if (firstRunValue.isValid() && firstRunValue.toBool()) {
bool firstRun = SettingHandles::firstRun.get();
if (firstRun) {
qDebug() << "This is a first run...";
// clear the scripts, and set out script to our default scripts
clearScriptsBeforeRunning();
loadScript(DEFAULT_SCRIPTS_JS_URL);
QMutexLocker locker(&_settingsMutex);
_settings->setValue("firstRun",QVariant(false));
SettingHandles::firstRun.set(false);
} else {
// do this as late as possible so that all required subsystems are initialized
loadScripts();
QMutexLocker locker(&_settingsMutex);
_previousScriptLocation = _settings->value("LastScriptLocation", QVariant("")).toString();
_previousScriptLocation = SettingHandles::lastScriptLocation.get();
}
loadSettings();
int SAVE_SETTINGS_INTERVAL = 10 * MSECS_PER_SECOND; // Let's save every seconds for now
connect(&_settingsTimer, &QTimer::timeout, this, &Application::saveSettings);
connect(&_settingsThread, SIGNAL(started), &_settingsTimer, SLOT(start));
connect(&_settingsThread, &QThread::finished, &_settingsTimer, &QTimer::deleteLater);
_settingsTimer.moveToThread(&_settingsThread);
_settingsTimer.setSingleShot(false);
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL);
_settingsThread.start();
_trayIcon->show();
// set the local loopback interface for local sounds from audio scripts
@ -448,12 +477,12 @@ void Application::aboutToQuit() {
}
Application::~Application() {
saveSettings();
_entities.getTree()->setSimulation(NULL);
qInstallMessageHandler(NULL);
saveSettings();
storeSizeAndPosition();
_window->saveGeometry();
int DELAY_TIME = 1000;
UserActivityLogger::getInstance().close(DELAY_TIME);
@ -490,45 +519,6 @@ Application::~Application() {
DependencyManager::destroy<GLCanvas>();
}
void Application::saveSettings() {
Menu::getInstance()->saveSettings();
_rearMirrorTools->saveSettings(_settings);
_settings->sync();
_numChangedSettings = 0;
}
void Application::restoreSizeAndPosition() {
QRect available = desktop()->availableGeometry();
QMutexLocker locker(&_settingsMutex);
_settings->beginGroup("Window");
int x = (int)loadSetting(_settings, "x", 0);
int y = (int)loadSetting(_settings, "y", 0);
_window->move(x, y);
int width = (int)loadSetting(_settings, "width", available.width());
int height = (int)loadSetting(_settings, "height", available.height());
_window->resize(width, height);
_settings->endGroup();
}
void Application::storeSizeAndPosition() {
QMutexLocker locker(&_settingsMutex);
_settings->beginGroup("Window");
_settings->setValue("width", _window->rect().width());
_settings->setValue("height", _window->rect().height());
_settings->setValue("x", _window->pos().x());
_settings->setValue("y", _window->pos().y());
_settings->endGroup();
}
void Application::initializeGL() {
qDebug( "Created Display Window.");
@ -650,7 +640,7 @@ void Application::paintGL() {
_myCamera.update(1.0f / _fps);
}
if (Menu::getInstance()->getShadowsEnabled()) {
if (getShadowsEnabled()) {
updateShadowMap();
}
@ -706,6 +696,24 @@ void Application::paintGL() {
_frameCount++;
}
void Application::runTests() {
runTimingTests();
}
void Application::audioMuteToggled() {
QAction* muteAction = Menu::getInstance()->getActionForOption(MenuOption::MuteAudio);
Q_CHECK_PTR(muteAction);
muteAction->setChecked(DependencyManager::get<Audio>()->isMuted());
}
void Application::aboutApp() {
InfoView::forcedShow(INFO_HELP_PATH);
}
void Application::showEditEntitiesHelp() {
InfoView::forcedShow(INFO_EDIT_ENTITIES_PATH);
}
void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) {
if (OculusManager::isConnected()) {
OculusManager::configureCamera(camera, width, height);
@ -713,7 +721,7 @@ void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height)
TV3DManager::configureCamera(camera, width, height);
} else {
camera.setAspectRatio((float)width / height);
camera.setFieldOfView(Menu::getInstance()->getFieldOfView());
camera.setFieldOfView(_viewFrustum.getFieldOfView());
}
}
@ -1436,10 +1444,6 @@ void Application::idle() {
// After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
idleTimer->start(2);
if (_numChangedSettings > 0) {
saveSettings();
}
}
}
}
@ -1457,7 +1461,7 @@ void Application::checkBandwidthMeterClick() {
// The bandwidth meter is visible, the click didn't get dragged too far and
// we actually hit the bandwidth meter
Menu::getInstance()->bandwidthDetails();
DependencyManager::get<DialogsManager>()->bandwidthDetails();
}
}
@ -1595,6 +1599,20 @@ bool Application::exportEntities(const QString& filename, float x, float y, floa
return true;
}
void Application::loadSettings() {
DependencyManager::get<Audio>()->loadSettings();
DependencyManager::get<LODManager>()->loadSettings();
Menu::getInstance()->loadSettings();
_myAvatar->loadData();
}
void Application::saveSettings() {
DependencyManager::get<Audio>()->saveSettings();
DependencyManager::get<LODManager>()->saveSettings();
Menu::getInstance()->saveSettings();
_myAvatar->saveData();
}
bool Application::importEntities(const QString& filename) {
_entityClipboard.eraseAllOctreeElements();
bool success = _entityClipboard.readFromSVOFile(filename.toLocal8Bit().constData());
@ -1645,8 +1663,6 @@ void Application::init() {
_timerStart.start();
_lastTimeUpdated.start();
Menu::getInstance()->loadSettings();
// when --url in command line, teleport to location
const QString HIFI_URL_COMMAND_LINE_KEY = "--url";
@ -1664,11 +1680,11 @@ void Application::init() {
if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseEnabled)) {
// on OS X we only setup sixense if the user wants it on - this allows running without the hid_init crash
// if hydra support is temporarily not required
Menu::getInstance()->toggleSixense(true);
SixenseManager::getInstance().toggleSixense(true);
}
#else
// setup sixense
Menu::getInstance()->toggleSixense(true);
SixenseManager::getInstance().toggleSixense(true);
#endif
// initialize our face trackers after loading the menu settings
@ -1707,16 +1723,13 @@ void Application::init() {
_metavoxels.init();
auto glCanvas = DependencyManager::get<GLCanvas>();
_rearMirrorTools = new RearMirrorTools(glCanvas.data(), _mirrorViewRect, _settings);
_rearMirrorTools = new RearMirrorTools(glCanvas.data(), _mirrorViewRect);
connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView()));
connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView()));
connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView()));
connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors()));
// save settings when avatar changes
connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings);
// make sure our texture cache knows about window size changes
DependencyManager::get<TextureCache>()->associateWithWidget(glCanvas.data());
@ -1758,9 +1771,9 @@ void Application::updateLOD() {
PerformanceTimer perfTimer("LOD");
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
Menu::getInstance()->autoAdjustLOD(_fps);
DependencyManager::get<LODManager>()->autoAdjustLOD(_fps);
} else {
Menu::getInstance()->resetLODAdjust();
DependencyManager::get<LODManager>()->resetLODAdjust();
}
}
@ -1877,7 +1890,7 @@ void Application::updateMyAvatarLookAtPosition() {
// deflect using Faceshift gaze data
glm::vec3 origin = _myAvatar->getHead()->getEyePosition();
float pitchSign = (_myCamera.getMode() == CAMERA_MODE_MIRROR) ? -1.0f : 1.0f;
float deflection = Menu::getInstance()->getFaceshiftEyeDeflection();
float deflection = DependencyManager::get<Faceshift>()->getEyeDeflection();
if (isLookingAtSomeone) {
deflection *= GAZE_DEFLECTION_REDUCTION_DURING_EYE_CONTACT;
}
@ -1949,14 +1962,15 @@ void Application::updateDialogs(float deltaTime) {
PerformanceTimer perfTimer("updateDialogs");
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
auto dialogsManager = DependencyManager::get<DialogsManager>();
// Update bandwidth dialog, if any
BandwidthDialog* bandwidthDialog = Menu::getInstance()->getBandwidthDialog();
BandwidthDialog* bandwidthDialog = dialogsManager->getBandwidthDialog();
if (bandwidthDialog) {
bandwidthDialog->update();
}
OctreeStatsDialog* octreeStatsDialog = Menu::getInstance()->getOctreeStatsDialog();
QPointer<OctreeStatsDialog> octreeStatsDialog = dialogsManager->getOctreeStatsDialog();
if (octreeStatsDialog) {
octreeStatsDialog->update();
}
@ -2227,8 +2241,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
_octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition());
_octreeQuery.setOctreeSizeScale(Menu::getInstance()->getOctreeSizeScale());
_octreeQuery.setBoundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust());
auto lodManager = DependencyManager::get<LODManager>();
_octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
_octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
unsigned char queryPacket[MAX_PACKET_SIZE];
@ -2280,7 +2295,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
int perServerPPS = 0;
const int SMALL_BUDGET = 10;
int perUnknownServer = SMALL_BUDGET;
int totalPPS = Menu::getInstance()->getMaxOctreePacketsPerSecond();
int totalPPS = _octreeQuery.getMaxOctreePacketsPerSecond();
// determine PPS based on number of servers
if (inViewServers >= 1) {
@ -2401,7 +2416,7 @@ QRect Application::getDesirableApplicationGeometry() {
// If our parent window is on the HMD, then don't use it's geometry, instead use
// the "main screen" geometry.
HMDToolsDialog* hmdTools = Menu::getInstance()->getHMDToolsDialog();
HMDToolsDialog* hmdTools = DependencyManager::get<DialogsManager>()->getHMDToolsDialog();
if (hmdTools && hmdTools->hasHMDScreen()) {
QScreen* hmdScreen = hmdTools->getHMDScreen();
QWindow* appWindow = getWindow()->windowHandle();
@ -2626,15 +2641,15 @@ void Application::setupWorldLight() {
}
bool Application::shouldRenderMesh(float largestDimension, float distanceToCamera) {
return Menu::getInstance()->shouldRenderMesh(largestDimension, distanceToCamera);
return DependencyManager::get<LODManager>()->shouldRenderMesh(largestDimension, distanceToCamera);
}
float Application::getSizeScale() const {
return Menu::getInstance()->getOctreeSizeScale();
return DependencyManager::get<LODManager>()->getOctreeSizeScale();
}
int Application::getBoundaryLevelAdjust() const {
return Menu::getInstance()->getBoundaryLevelAdjust();
return DependencyManager::get<LODManager>()->getBoundaryLevelAdjust();
}
PickRay Application::computePickRay(float x, float y) {
@ -2930,8 +2945,10 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom
}
}
bool Application::getShadowsEnabled() {
return Menu::getInstance()->getShadowsEnabled();
bool Application::getShadowsEnabled() {
Menu* menubar = Menu::getInstance();
return menubar->isOptionChecked(MenuOption::SimpleShadows) ||
menubar->isOptionChecked(MenuOption::CascadedShadows);
}
bool Application::getCascadeShadowsEnabled() {
@ -2976,7 +2993,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
_mirrorCamera.setPosition(_myAvatar->getPosition() +
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale());
} else if (_rearMirrorTools->getZoomLevel() == BODY) {
} else if (SettingHandles::rearViewZoomLevel.get() == BODY) {
_mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees
_mirrorCamera.setPosition(_myAvatar->getChestPosition() +
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale());
@ -3373,45 +3390,45 @@ void Application::packetSent(quint64 length) {
_bandwidthMeter.outputStream(BandwidthMeter::OCTREE).updateValue(length);
}
const QString SETTINGS_KEY = "Settings";
void Application::loadScripts() {
// loads all saved scripts
int size = lockSettings()->beginReadArray("Settings");
unlockSettings();
Settings settings;
int size = settings.beginReadArray(SETTINGS_KEY);
for (int i = 0; i < size; ++i){
lockSettings()->setArrayIndex(i);
QString string = _settings->value("script").toString();
unlockSettings();
settings.setArrayIndex(i);
QString string = settings.value("script").toString();
if (!string.isEmpty()) {
loadScript(string);
}
}
QMutexLocker locker(&_settingsMutex);
_settings->endArray();
settings.endArray();
}
void Application::clearScriptsBeforeRunning() {
// clears all scripts from the settings
QMutexLocker locker(&_settingsMutex);
_settings->remove("Settings");
SettingHandles::SettingHandle<QVariant>(SETTINGS_KEY).remove();
}
void Application::saveScripts() {
// Saves all currently running user-loaded scripts
QMutexLocker locker(&_settingsMutex);
_settings->beginWriteArray("Settings");
QStringList runningScripts = getRunningScripts();
if (runningScripts.isEmpty()) {
return;
}
// Saves all currently running user-loaded scripts
Settings settings;
settings.beginWriteArray(SETTINGS_KEY);
int i = 0;
for (QStringList::const_iterator it = runningScripts.begin(); it != runningScripts.end(); it += 1) {
for (auto it = runningScripts.begin(); it != runningScripts.end(); ++it) {
if (getScriptEngine(*it)->isUserLoaded()) {
_settings->setArrayIndex(i);
_settings->setValue("script", *it);
i += 1;
settings.setArrayIndex(i);
settings.setValue("script", *it);
++i;
}
}
_settings->endArray();
settings.endArray();
}
QScriptValue joystickToScriptValue(QScriptEngine *engine, Joystick* const &in) {
@ -3438,7 +3455,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
scriptEngine->registerGlobalObject("Camera", &_myCamera);
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
scriptEngine->registerGlobalObject("SpeechRecognizer", Menu::getInstance()->getSpeechRecognizer());
scriptEngine->registerGlobalObject("SpeechRecognizer", DependencyManager::get<SpeechRecognizer>().data());
#endif
ClipboardScriptingInterface* clipboardScriptable = new ClipboardScriptingInterface();
@ -3538,7 +3555,6 @@ ScriptEngine* Application::loadScript(const QString& scriptFilename, bool isUser
if (activateMainWindow && !loadScriptFromEditor) {
_window->activateWindow();
}
bumpSettings();
return scriptEngine;
}
@ -3566,7 +3582,6 @@ void Application::scriptFinished(const QString& scriptName) {
_scriptEnginesHash.erase(it);
_runningScriptsWidget->scriptStopped(scriptName);
_runningScriptsWidget->setRunningScripts(getRunningScripts());
bumpSettings();
}
}
@ -3662,7 +3677,6 @@ void Application::openUrl(const QUrl& url) {
}
void Application::updateMyAvatarTransform() {
bumpSettings();
const float SIMULATION_OFFSET_QUANTIZATION = 16.0f; // meters
glm::vec3 avatarPosition = _myAvatar->getPosition();
glm::vec3 physicsWorldOffset = _physicsEngine.getOriginOffset();
@ -3679,7 +3693,6 @@ void Application::updateMyAvatarTransform() {
}
void Application::domainSettingsReceived(const QJsonObject& domainSettingsObject) {
// from the domain-handler, figure out the satoshi cost per voxel and per meter cubed
const QString VOXEL_SETTINGS_KEY = "voxels";
const QString PER_VOXEL_COST_KEY = "per-voxel-credits";
@ -3722,9 +3735,7 @@ QString Application::getPreviousScriptLocation() {
void Application::setPreviousScriptLocation(const QString& previousScriptLocation) {
_previousScriptLocation = previousScriptLocation;
QMutexLocker locker(&_settingsMutex);
_settings->setValue("LastScriptLocation", _previousScriptLocation);
bumpSettings();
SettingHandles::lastScriptLocation.set(_previousScriptLocation);
}
void Application::loadDialog() {
@ -3740,7 +3751,6 @@ void Application::loadDialog() {
}
void Application::loadScriptURLDialog() {
QInputDialog scriptURLDialog(Application::getInstance()->getWindow());
scriptURLDialog.setWindowTitle("Open and Run Script URL");
scriptURLDialog.setLabelText("Script:");
@ -3758,11 +3768,16 @@ void Application::loadScriptURLDialog() {
}
loadScript(newScript);
}
sendFakeEnterEvent();
}
QString Application::getScriptsLocation() const {
return SettingHandles::scriptsLocation.get();
}
void Application::setScriptsLocation(const QString& scriptsLocation) {
SettingHandles::scriptsLocation.set(scriptsLocation);
emit scriptLocationChanged(scriptsLocation);
}
void Application::toggleLogDialog() {
if (! _logDialog) {
@ -3864,7 +3879,8 @@ void Application::takeSnapshot() {
_snapshotShareDialog->show();
}
void Application::setVSyncEnabled(bool vsyncOn) {
void Application::setVSyncEnabled() {
bool vsyncOn = Menu::getInstance()->isOptionChecked(MenuOption::RenderTargetFramerateVSyncOn);
#if defined(Q_OS_WIN)
if (wglewGetExtension("WGL_EXT_swap_control")) {
wglSwapIntervalEXT(vsyncOn);
@ -3888,6 +3904,7 @@ void Application::setVSyncEnabled(bool vsyncOn) {
#else
qDebug("V-Sync is FORCED ON on this system\n");
#endif
vsyncOn = true; // Turns off unused variable warning
}
bool Application::isVSyncOn() const {

View file

@ -19,7 +19,6 @@
#include <QImage>
#include <QPointer>
#include <QSet>
#include <QSettings>
#include <QStringList>
#include <QUndoStack>
@ -34,10 +33,10 @@
#include <PacketHeaders.h>
#include <PhysicsEngine.h>
#include <ScriptEngine.h>
#include <StDev.h>
#include <TextureCache.h>
#include <ViewFrustum.h>
#include "Audio.h"
#include "Bookmarks.h"
#include "Camera.h"
#include "DatagramProcessor.h"
@ -80,7 +79,6 @@
class QGLWidget;
class QKeyEvent;
class QMouseEvent;
class QSettings;
class QSystemTrayIcon;
class QTouchEvent;
class QWheelEvent;
@ -121,6 +119,12 @@ static const quint64 TOO_LONG_SINCE_LAST_SEND_DOWNSTREAM_AUDIO_STATS = 1 * USECS
static const QString INFO_HELP_PATH = "html/interface-welcome-allsvg.html";
static const QString INFO_EDIT_ENTITIES_PATH = "html/edit-entities-commands.html";
class Application;
#if defined(qApp)
#undef qApp
#endif
#define qApp (static_cast<Application*>(QCoreApplication::instance()))
class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface {
Q_OBJECT
@ -128,18 +132,16 @@ class Application : public QApplication, public AbstractViewStateInterface, Abst
friend class DatagramProcessor;
public:
static Application* getInstance() { return static_cast<Application*>(QCoreApplication::instance()); }
static Application* getInstance() { return qApp; } // TODO: replace fully by qApp
static const glm::vec3& getPositionForPath() { return getInstance()->_myAvatar->getPosition(); }
static glm::quat getOrientationForPath() { return getInstance()->_myAvatar->getOrientation(); }
Application(int& argc, char** argv, QElapsedTimer &startup_time);
~Application();
void restoreSizeAndPosition();
void loadScripts();
QString getPreviousScriptLocation();
void setPreviousScriptLocation(const QString& previousScriptLocation);
void storeSizeAndPosition();
void clearScriptsBeforeRunning();
void initializeGL();
void paintGL();
@ -180,6 +182,7 @@ public:
PrioVR* getPrioVR() { return &_prioVR; }
QUndoStack* getUndoStack() { return &_undoStack; }
MainWindow* getWindow() { return _window; }
OctreeQuery& getOctreeQuery() { return _octreeQuery; }
EntityTree* getEntityClipboard() { return &_entityClipboard; }
EntityTreeRenderer* getEntityClipboardRenderer() { return &_entityClipboardRenderer; }
@ -215,12 +218,6 @@ public:
virtual const Transform& getViewTransform() const { return _viewTransform; }
void setViewTransform(const Transform& view);
/// if you need to access the application settings, use lockSettings()/unlockSettings()
QSettings* lockSettings() { _settingsMutex.lock(); return _settings; }
void unlockSettings() { _settingsMutex.unlock(); }
void saveSettings();
NodeToOctreeSceneStats* getOcteeSceneStats() { return &_octreeServerSceneStats; }
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); }
@ -303,6 +300,9 @@ public:
RunningScriptsWidget* getRunningScriptsWidget() { return _runningScriptsWidget; }
Bookmarks* getBookmarks() const { return _bookmarks; }
QString getScriptsLocation() const;
void setScriptsLocation(const QString& scriptsLocation);
signals:
@ -317,6 +317,8 @@ signals:
/// Fired when the import window is closed
void importDone();
void scriptLocationChanged(const QString& newPath);
public slots:
void domainChanged(const QString& domainHostname);
@ -353,13 +355,17 @@ public slots:
void openUrl(const QUrl& url);
void updateMyAvatarTransform();
void bumpSettings() { ++_numChangedSettings; }
void domainSettingsReceived(const QJsonObject& domainSettingsObject);
void setVSyncEnabled(bool vsyncOn);
void setVSyncEnabled();
void resetSensors();
void aboutApp();
void showEditEntitiesHelp();
void loadSettings();
void saveSettings();
private slots:
void clearDomainOctreeDetails();
@ -387,6 +393,10 @@ private slots:
void parseVersionXml();
void manageRunningScriptsWidgetVisibility(bool shown);
void runTests();
void audioMuteToggled();
private:
void resetCamerasOnResizeGL(Camera& camera, int width, int height);
@ -443,10 +453,6 @@ private:
QThread* _nodeThread;
DatagramProcessor _datagramProcessor;
QMutex _settingsMutex;
QSettings* _settings;
int _numChangedSettings;
QUndoStack _undoStack;
UndoStackScriptingInterface _undoStackScriptingInterface;
@ -566,6 +572,7 @@ private:
RunningScriptsWidget* _runningScriptsWidget;
QHash<QString, ScriptEngine*> _scriptEnginesHash;
bool _runningScriptsWidgetWasVisible;
QString _scriptsLocation;
QSystemTrayIcon* _trayIcon;
@ -579,6 +586,9 @@ private:
bool _aboutToQuit;
Bookmarks* _bookmarks;
QThread _settingsThread;
QTimer _settingsTimer;
};
#endif // hifi_Application_h

View file

@ -10,9 +10,10 @@
//
#include <cstring>
#include <math.h>
#include <sys/stat.h>
#include <math.h>
#include <glm/glm.hpp>
#ifdef __APPLE__
#include <CoreAudio/AudioHardware.h>
@ -28,29 +29,35 @@
#include <VersionHelpers.h>
#endif
#include <AudioConstants.h>
#include <QtCore/QBuffer>
#include <QtMultimedia/QAudioInput>
#include <QtMultimedia/QAudioOutput>
#include <glm/glm.hpp>
#include <AudioConstants.h>
#include <AudioInjector.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <PositionalAudioStream.h>
#include <Settings.h>
#include <SharedUtil.h>
#include <UUID.h>
#include "Application.h"
#include "Audio.h"
static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 100;
namespace SettingHandles {
const SettingHandle<bool> audioOutputStarveDetectionEnabled("audioOutputStarveDetectionEnabled",
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_ENABLED);
const SettingHandle<int> audioOutputStarveDetectionThreshold("audioOutputStarveDetectionThreshold",
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_THRESHOLD);
const SettingHandle<int> audioOutputStarveDetectionPeriod("audioOutputStarveDetectionPeriod",
DEFAULT_AUDIO_OUTPUT_STARVE_DETECTION_PERIOD);
const SettingHandle<int> audioOutputBufferSize("audioOutputBufferSize",
DEFAULT_MAX_FRAMES_OVER_DESIRED);
}
Audio::Audio() :
AbstractAudioInterface(),
_audioInput(NULL),
@ -1129,3 +1136,28 @@ void Audio::checkDevices() {
emit deviceChanged();
}
}
void Audio::loadSettings() {
_receivedAudioStream.loadSettings();
setOutputStarveDetectionEnabled(SettingHandles::audioOutputStarveDetectionEnabled.get());
setOutputStarveDetectionThreshold(SettingHandles::audioOutputStarveDetectionThreshold.get());
setOutputStarveDetectionPeriod(SettingHandles::audioOutputStarveDetectionPeriod.get());
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "setOutputBufferSize",
Q_ARG(int, SettingHandles::audioOutputBufferSize.get()));
} else {
setOutputBufferSize(SettingHandles::audioOutputBufferSize.get());
}
}
void Audio::saveSettings() {
_receivedAudioStream.saveSettings();
SettingHandles::audioOutputStarveDetectionEnabled.set(getOutputStarveDetectionEnabled());
SettingHandles::audioOutputStarveDetectionThreshold.set(getOutputStarveDetectionThreshold());
SettingHandles::audioOutputStarveDetectionPeriod.set(getOutputStarveDetectionPeriod());
SettingHandles::audioOutputBufferSize.set(getOutputBufferSize());
}

View file

@ -30,7 +30,6 @@
#include <DependencyManager.h>
#include <StDev.h>
#include "InterfaceConfig.h"
#include "audio/AudioIOStats.h"
#include "audio/AudioNoiseGate.h"
#include "AudioStreamStats.h"
@ -96,14 +95,13 @@ public:
};
const MixedProcessedAudioStream& getReceivedAudioStream() const { return _receivedAudioStream; }
MixedProcessedAudioStream& getReceivedAudioStream() { return _receivedAudioStream; }
float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _inputGate.getMeasuredFloor(), 0.0f); }
float getTimeSinceLastClip() const { return _timeSinceLastClip; }
float getAudioAverageInputLoudness() const { return _lastInputLoudness; }
void setReceivedAudioStreamSettings(const InboundAudioStream::Settings& settings) { _receivedAudioStream.setSettings(settings); }
int getDesiredJitterBufferFrames() const { return _receivedAudioStream.getDesiredJitterBufferFrames(); }
bool isMuted() { return _muted; }
@ -174,6 +172,9 @@ public slots:
void outputNotify();
void loadSettings();
void saveSettings();
signals:
bool muteToggled();
void inputReceived(const QByteArray& inputSamples);

View file

@ -9,10 +9,21 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QAction>
#include <QDebug>
#include <QJsonObject>
#include <QFile>
#include <QInputDialog>
#include <QJsonDocument>
#include <QMessageBox>
#include <QStandardPaths>
#include <AddressManager.h>
#include <Application.h>
#include "MainWindow.h"
#include "Menu.h"
#include "Bookmarks.h"
Bookmarks::Bookmarks() {
@ -71,3 +82,125 @@ void Bookmarks::persistToFile() {
QByteArray data = json.toJson();
saveFile.write(data);
}
void Bookmarks::setupMenus(Menu* menubar, QMenu* menu) {
// Add menus/actions
menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation, 0,
this, SLOT(bookmarkLocation()));
_bookmarksMenu = menu->addMenu(MenuOption::Bookmarks);
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark, 0,
this, SLOT(deleteBookmark()));
// Enable/Disable menus as needed
enableMenuItems(_bookmarks.count() > 0);
// Load bookmarks
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it ) {
QString bookmarkName = it.key();
QString bookmarkAddress = it.value().toString();
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
}
}
void Bookmarks::bookmarkLocation() {
QInputDialog bookmarkLocationDialog(qApp->getWindow());
bookmarkLocationDialog.setWindowTitle("Bookmark Location");
bookmarkLocationDialog.setLabelText("Name:");
bookmarkLocationDialog.setInputMode(QInputDialog::TextInput);
bookmarkLocationDialog.resize(400, 200);
if (bookmarkLocationDialog.exec() == QDialog::Rejected) {
return;
}
QString bookmarkName = bookmarkLocationDialog.textValue().trimmed();
bookmarkName = bookmarkName.replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
if (bookmarkName.length() == 0) {
return;
}
auto addressManager = DependencyManager::get<AddressManager>();
QString bookmarkAddress = addressManager->currentAddress().toString();
Menu* menubar = Menu::getInstance();
if (contains(bookmarkName)) {
QMessageBox duplicateBookmarkMessage;
duplicateBookmarkMessage.setIcon(QMessageBox::Warning);
duplicateBookmarkMessage.setText("The bookmark name you entered already exists in your list.");
duplicateBookmarkMessage.setInformativeText("Would you like to overwrite it?");
duplicateBookmarkMessage.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
duplicateBookmarkMessage.setDefaultButton(QMessageBox::Yes);
if (duplicateBookmarkMessage.exec() == QMessageBox::No) {
return;
}
removeLocationFromMenu(menubar, bookmarkName);
}
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
enableMenuItems(true);
}
void Bookmarks::teleportToBookmark() {
QAction* action = qobject_cast<QAction*>(sender());
QString address = action->data().toString();
DependencyManager::get<AddressManager>()->handleLookupString(address);
}
void Bookmarks::deleteBookmark() {
QStringList bookmarkList;
QList<QAction*> menuItems = _bookmarksMenu->actions();
for (int i = 0; i < menuItems.count(); i += 1) {
bookmarkList.append(menuItems[i]->text());
}
QInputDialog deleteBookmarkDialog(qApp->getWindow());
deleteBookmarkDialog.setWindowTitle("Delete Bookmark");
deleteBookmarkDialog.setLabelText("Select the bookmark to delete");
deleteBookmarkDialog.resize(400, 400);
deleteBookmarkDialog.setOption(QInputDialog::UseListViewForComboBoxItems);
deleteBookmarkDialog.setComboBoxItems(bookmarkList);
deleteBookmarkDialog.setOkButtonText("Delete");
if (deleteBookmarkDialog.exec() == QDialog::Rejected) {
return;
}
QString bookmarkName = deleteBookmarkDialog.textValue().trimmed();
if (bookmarkName.length() == 0) {
return;
}
removeLocationFromMenu(Menu::getInstance(), bookmarkName);
remove(bookmarkName);
if (_bookmarksMenu->actions().count() == 0) {
enableMenuItems(false);
}
}
void Bookmarks::enableMenuItems(bool enabled) {
if (_bookmarksMenu) {
_bookmarksMenu->setEnabled(enabled);
}
if (_deleteBookmarksAction) {
_deleteBookmarksAction->setEnabled(enabled);
}
}
void Bookmarks::addLocationToMenu(Menu* menubar, QString& name, QString& address) {
QAction* teleportAction = new QAction(_bookmarksMenu);
teleportAction->setData(address);
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction,
name, 0, QAction::NoRole);
}
void Bookmarks::removeLocationFromMenu(Menu* menubar, QString& name) {
menubar->removeAction(_bookmarksMenu, name);
}

View file

@ -12,10 +12,13 @@
#ifndef hifi_Bookmarks_h
#define hifi_Bookmarks_h
#include <QJsonObject>
#include <QDebug>
#include <QMap>
#include <QObject>
#include <QPointer>
class QAction;
class QMenu;
class Menu;
class Bookmarks: public QObject {
Q_OBJECT
@ -23,19 +26,32 @@ class Bookmarks: public QObject {
public:
Bookmarks();
void setupMenus(Menu* menubar, QMenu* menu);
private slots:
void bookmarkLocation();
void teleportToBookmark();
void deleteBookmark();
private:
QVariantMap _bookmarks; // { name: address, ... }
QPointer<QMenu> _bookmarksMenu;
QPointer<QAction> _deleteBookmarksAction;
const QString BOOKMARKS_FILENAME = "bookmarks.json";
QString _bookmarksFilename;
void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name.
void remove(const QString& name);
bool contains(const QString& name) const;
QVariantMap* getBookmarks() { return &_bookmarks; };
private:
QVariantMap _bookmarks; // { name: address, ... }
const QString BOOKMARKS_FILENAME = "bookmarks.json";
QString _bookmarksFilename;
void readFromFile();
void persistToFile();
void enableMenuItems(bool enabled);
void addLocationToMenu(Menu* menubar, QString& name, QString& address);
void removeLocationFromMenu(Menu* menubar, QString& name);
};
#endif // hifi_Bookmarks_h

View file

@ -15,6 +15,7 @@
#include <PerfStat.h>
#include "Application.h"
#include "Audio.h"
#include "Menu.h"
#include "DatagramProcessor.h"

View file

@ -0,0 +1,210 @@
//
// LODManager.cpp
//
//
// Created by Clement on 1/16/15.
// 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 <Util.h>
#include "Application.h"
#include "ui/DialogsManager.h"
#include "LODManager.h"
namespace SettingHandles {
const SettingHandle<bool> automaticAvatarLOD("automaticAvatarLOD", true);
const SettingHandle<float> avatarLODDecreaseFPS("avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS);
const SettingHandle<float> avatarLODIncreaseFPS("avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS);
const SettingHandle<float> avatarLODDistanceMultiplier("avatarLODDistanceMultiplier",
DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER);
const SettingHandle<int> boundaryLevelAdjust("boundaryLevelAdjust", 0);
const SettingHandle<float> octreeSizeScale("octreeSizeScale", DEFAULT_OCTREE_SIZE_SCALE);
}
void LODManager::autoAdjustLOD(float currentFPS) {
// NOTE: our first ~100 samples at app startup are completely all over the place, and we don't
// really want to count them in our average, so we will ignore the real frame rates and stuff
// our moving average with simulated good data
const int IGNORE_THESE_SAMPLES = 100;
const float ASSUMED_FPS = 60.0f;
if (_fpsAverage.getSampleCount() < IGNORE_THESE_SAMPLES) {
currentFPS = ASSUMED_FPS;
}
_fpsAverage.updateAverage(currentFPS);
_fastFPSAverage.updateAverage(currentFPS);
quint64 now = usecTimestampNow();
const quint64 ADJUST_AVATAR_LOD_DOWN_DELAY = 1000 * 1000;
if (_automaticAvatarLOD) {
if (_fastFPSAverage.getAverage() < _avatarLODDecreaseFPS) {
if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) {
// attempt to lower the detail in proportion to the fps difference
float targetFps = (_avatarLODDecreaseFPS + _avatarLODIncreaseFPS) * 0.5f;
float averageFps = _fastFPSAverage.getAverage();
const float MAXIMUM_MULTIPLIER_SCALE = 2.0f;
_avatarLODDistanceMultiplier = qMin(MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, _avatarLODDistanceMultiplier *
(averageFps < EPSILON ? MAXIMUM_MULTIPLIER_SCALE :
qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps)));
_lastAvatarDetailDrop = now;
}
} else if (_fastFPSAverage.getAverage() > _avatarLODIncreaseFPS) {
// let the detail level creep slowly upwards
const float DISTANCE_DECREASE_RATE = 0.05f;
_avatarLODDistanceMultiplier = qMax(MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER,
_avatarLODDistanceMultiplier - DISTANCE_DECREASE_RATE);
}
}
bool changed = false;
quint64 elapsed = now - _lastAdjust;
if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS
&& _octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) {
_octreeSizeScale *= ADJUST_LOD_DOWN_BY;
if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) {
_octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE;
}
changed = true;
_lastAdjust = now;
qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
<< "_octreeSizeScale=" << _octreeSizeScale;
}
if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS
&& _octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) {
_octreeSizeScale *= ADJUST_LOD_UP_BY;
if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) {
_octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE;
}
changed = true;
_lastAdjust = now;
qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage()
<< "_octreeSizeScale=" << _octreeSizeScale;
}
if (changed) {
_shouldRenderTableNeedsRebuilding = true;
auto lodToolsDialog = DependencyManager::get<DialogsManager>()->getLodToolsDialog();
if (lodToolsDialog) {
lodToolsDialog->reloadSliders();
}
}
}
void LODManager::resetLODAdjust() {
_fpsAverage.reset();
_fastFPSAverage.reset();
_lastAvatarDetailDrop = _lastAdjust = usecTimestampNow();
}
QString LODManager::getLODFeedbackText() {
// determine granularity feedback
int boundaryLevelAdjust = getBoundaryLevelAdjust();
QString granularityFeedback;
switch (boundaryLevelAdjust) {
case 0: {
granularityFeedback = QString("at standard granularity.");
} break;
case 1: {
granularityFeedback = QString("at half of standard granularity.");
} break;
case 2: {
granularityFeedback = QString("at a third of standard granularity.");
} break;
default: {
granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1);
} break;
}
// distance feedback
float octreeSizeScale = getOctreeSizeScale();
float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE;
QString result;
if (relativeToDefault > 1.01) {
result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback);
} else if (relativeToDefault > 0.99) {
result = QString("the default distance %1").arg(granularityFeedback);
} else {
result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback);
}
return result;
}
// TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells
// I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it.
bool LODManager::shouldRenderMesh(float largestDimension, float distanceToCamera) {
const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it.
float octreeSizeScale = getOctreeSizeScale();
int boundaryLevelAdjust = getBoundaryLevelAdjust();
float maxScale = (float)TREE_SCALE;
float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio;
if (_shouldRenderTableNeedsRebuilding) {
_shouldRenderTable.clear();
float SMALLEST_SCALE_IN_TABLE = 0.001f; // 1mm is plenty small
float scale = maxScale;
float visibleDistanceAtScale = visibleDistanceAtMaxScale;
while (scale > SMALLEST_SCALE_IN_TABLE) {
scale /= 2.0f;
visibleDistanceAtScale /= 2.0f;
_shouldRenderTable[scale] = visibleDistanceAtScale;
}
_shouldRenderTableNeedsRebuilding = false;
}
float closestScale = maxScale;
float visibleDistanceAtClosestScale = visibleDistanceAtMaxScale;
QMap<float, float>::const_iterator lowerBound = _shouldRenderTable.lowerBound(largestDimension);
if (lowerBound != _shouldRenderTable.constEnd()) {
closestScale = lowerBound.key();
visibleDistanceAtClosestScale = lowerBound.value();
}
if (closestScale < largestDimension) {
visibleDistanceAtClosestScale *= 2.0f;
}
return (distanceToCamera <= visibleDistanceAtClosestScale);
}
void LODManager::setOctreeSizeScale(float sizeScale) {
_octreeSizeScale = sizeScale;
_shouldRenderTableNeedsRebuilding = true;
}
void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) {
_boundaryLevelAdjust = boundaryLevelAdjust;
_shouldRenderTableNeedsRebuilding = true;
}
void LODManager::loadSettings() {
setAutomaticAvatarLOD(SettingHandles::automaticAvatarLOD.get());
setAvatarLODDecreaseFPS(SettingHandles::avatarLODDecreaseFPS.get());
setAvatarLODIncreaseFPS(SettingHandles::avatarLODIncreaseFPS.get());
setAvatarLODDistanceMultiplier(SettingHandles::avatarLODDistanceMultiplier.get());
setBoundaryLevelAdjust(SettingHandles::boundaryLevelAdjust.get());
setOctreeSizeScale(SettingHandles::octreeSizeScale.get());
}
void LODManager::saveSettings() {
SettingHandles::automaticAvatarLOD.set(getAutomaticAvatarLOD());
SettingHandles::avatarLODDecreaseFPS.set(getAvatarLODDecreaseFPS());
SettingHandles::avatarLODIncreaseFPS.set(getAvatarLODIncreaseFPS());
SettingHandles::avatarLODDistanceMultiplier.set(getAvatarLODDistanceMultiplier());
SettingHandles::boundaryLevelAdjust.set(getBoundaryLevelAdjust());
SettingHandles::octreeSizeScale.set(getOctreeSizeScale());
}

View file

@ -0,0 +1,91 @@
//
// LODManager.h
//
//
// Created by Clement on 1/16/15.
// 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
//
#ifndef hifi_LODManager_h
#define hifi_LODManager_h
#include <DependencyManager.h>
#include <OctreeConstants.h>
#include <Settings.h>
#include <SharedUtil.h>
#include <SimpleMovingAverage.h>
const float ADJUST_LOD_DOWN_FPS = 40.0;
const float ADJUST_LOD_UP_FPS = 55.0;
const float DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f;
const quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 5;
const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2;
const float ADJUST_LOD_DOWN_BY = 0.9f;
const float ADJUST_LOD_UP_BY = 1.1f;
const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.25f;
const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f;
const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f;
const float DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER = 1.0f;
const int ONE_SECOND_OF_FRAMES = 60;
const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES;
class LODManager : public Dependency {
SINGLETON_DEPENDENCY
public:
void setAutomaticAvatarLOD(bool automaticAvatarLOD) { _automaticAvatarLOD = automaticAvatarLOD; }
bool getAutomaticAvatarLOD() const { return _automaticAvatarLOD; }
void setAvatarLODDecreaseFPS(float avatarLODDecreaseFPS) { _avatarLODDecreaseFPS = avatarLODDecreaseFPS; }
float getAvatarLODDecreaseFPS() const { return _avatarLODDecreaseFPS; }
void setAvatarLODIncreaseFPS(float avatarLODIncreaseFPS) { _avatarLODIncreaseFPS = avatarLODIncreaseFPS; }
float getAvatarLODIncreaseFPS() const { return _avatarLODIncreaseFPS; }
void setAvatarLODDistanceMultiplier(float multiplier) { _avatarLODDistanceMultiplier = multiplier; }
float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; }
// User Tweakable LOD Items
QString getLODFeedbackText();
void setOctreeSizeScale(float sizeScale);
float getOctreeSizeScale() const { return _octreeSizeScale; }
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
void autoAdjustLOD(float currentFPS);
void resetLODAdjust();
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
void loadSettings();
void saveSettings();
private:
LODManager() {}
bool _automaticAvatarLOD = true;
float _avatarLODDecreaseFPS = DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS;
float _avatarLODIncreaseFPS = ADJUST_LOD_UP_FPS;
float _avatarLODDistanceMultiplier = DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER;
float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE;
int _boundaryLevelAdjust = 0;
quint64 _lastAdjust = 0;
quint64 _lastAvatarDetailDrop = 0;
SimpleMovingAverage _fpsAverage = FIVE_SECONDS_OF_FRAMES;
SimpleMovingAverage _fastFPSAverage = ONE_SECOND_OF_FRAMES;
bool _shouldRenderTableNeedsRebuilding = true;
QMap<float, float> _shouldRenderTable;
};
#endif // hifi_LODManager_h

View file

@ -9,9 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "MainWindow.h"
#include "Menu.h"
#include <QApplication>
#include <QDesktopWidget>
#include <QEvent>
#include <QMoveEvent>
#include <QResizeEvent>
@ -19,8 +18,33 @@
#include <QHideEvent>
#include <QWindowStateChangeEvent>
MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent) {
#include <Settings.h>
#include "MainWindow.h"
#include "Menu.h"
#include "Util.h"
namespace SettingHandles {
const SettingHandle<QRect> windowGeometry("WindowGeometry");
}
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) {
}
void MainWindow::restoreGeometry() {
// Did not use setGeometry() on purpose,
// see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application
QRect geometry = SettingHandles::windowGeometry.get(qApp->desktop()->availableGeometry());
move(geometry.topLeft());
resize(geometry.size());
}
void MainWindow::saveGeometry() {
// Did not use geometry() on purpose,
// see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application
QRect geometry(pos(), size());
SettingHandles::windowGeometry.set(geometry);
}
void MainWindow::moveEvent(QMoveEvent* event) {

View file

@ -14,12 +14,15 @@
#include <QMainWindow>
class MainWindow : public QMainWindow
{
class MainWindow : public QMainWindow {
Q_OBJECT
public:
explicit MainWindow(QWidget* parent = NULL);
public slots:
void restoreGeometry();
void saveGeometry();
signals:
void windowGeometryChanged(QRect geometry);
void windowShown(bool shown);

File diff suppressed because it is too large Load diff

View file

@ -19,128 +19,23 @@
#include <QPointer>
#include <QStandardPaths>
#include <EventTypes.h>
#include <MenuItemProperties.h>
#include <OctreeConstants.h>
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
#include "SpeechRecognizer.h"
#endif
#include "devices/Faceshift.h"
#include "devices/SixenseManager.h"
#include "ui/ChatWindow.h"
#include "ui/JSConsole.h"
#include "ui/ScriptEditorWindow.h"
// Make an LOD handler class and move everything overthere
const float ADJUST_LOD_DOWN_FPS = 40.0;
const float ADJUST_LOD_UP_FPS = 55.0;
const float DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f;
const quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 5;
const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2;
const float ADJUST_LOD_DOWN_BY = 0.9f;
const float ADJUST_LOD_UP_BY = 1.1f;
const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.25f;
const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE;
const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f;
const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f;
const float DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER = 1.0f;
const int ONE_SECOND_OF_FRAMES = 60;
const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES;
//////////////////////////////////////////////////////////
const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f;
const QString SETTINGS_ADDRESS_KEY = "address";
class QSettings;
class AddressBarDialog;
class AnimationsDialog;
class AttachmentsDialog;
class CachesSizeDialog;
class BandwidthDialog;
class DataWebDialog;
class HMDToolsDialog;
class LodToolsDialog;
class LoginDialog;
class OctreeStatsDialog;
class PreferencesDialog;
class MetavoxelEditor;
class MetavoxelNetworkSimulator;
class ChatWindow;
class MenuItemProperties;
class Settings;
class Menu : public QMenuBar {
Q_OBJECT
public:
static Menu* getInstance();
void loadSettings();
void saveSettings();
QMenu* getMenu(const QString& menuName);
void triggerOption(const QString& menuOption);
QAction* getActionForOption(const QString& menuOption);
const InboundAudioStream::Settings& getReceivedAudioStreamSettings() const { return _receivedAudioStreamSettings; }
void setReceivedAudioStreamSettings(const InboundAudioStream::Settings& receivedAudioStreamSettings) { _receivedAudioStreamSettings = receivedAudioStreamSettings; }
float getFieldOfView() const { return _fieldOfView; }
void setFieldOfView(float fieldOfView) { _fieldOfView = fieldOfView; bumpSettings(); }
float getRealWorldFieldOfView() const { return _realWorldFieldOfView; }
void setRealWorldFieldOfView(float realWorldFieldOfView) { _realWorldFieldOfView = realWorldFieldOfView; bumpSettings(); }
float getOculusUIAngularSize() const { return _oculusUIAngularSize; }
void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; bumpSettings(); }
float getSixenseReticleMoveSpeed() const { return _sixenseReticleMoveSpeed; }
void setSixenseReticleMoveSpeed(float sixenseReticleMoveSpeed) { _sixenseReticleMoveSpeed = sixenseReticleMoveSpeed; bumpSettings(); }
bool getInvertSixenseButtons() const { return _invertSixenseButtons; }
void setInvertSixenseButtons(bool invertSixenseButtons) { _invertSixenseButtons = invertSixenseButtons; bumpSettings(); }
float getFaceshiftEyeDeflection() const { return _faceshiftEyeDeflection; }
void setFaceshiftEyeDeflection(float faceshiftEyeDeflection) { _faceshiftEyeDeflection = faceshiftEyeDeflection; bumpSettings(); }
const QString& getFaceshiftHostname() const { return _faceshiftHostname; }
void setFaceshiftHostname(const QString& hostname) { _faceshiftHostname = hostname; bumpSettings(); }
QString getSnapshotsLocation() const;
void setSnapshotsLocation(QString snapshotsLocation) { _snapshotsLocation = snapshotsLocation; bumpSettings(); }
const QString& getScriptsLocation() const { return _scriptsLocation; }
void setScriptsLocation(const QString& scriptsLocation);
BandwidthDialog* getBandwidthDialog() const { return _bandwidthDialog; }
OctreeStatsDialog* getOctreeStatsDialog() const { return _octreeStatsDialog; }
LodToolsDialog* getLodToolsDialog() const { return _lodToolsDialog; }
HMDToolsDialog* getHMDToolsDialog() const { return _hmdToolsDialog; }
bool getShadowsEnabled() const;
// User Tweakable LOD Items
QString getLODFeedbackText();
void autoAdjustLOD(float currentFPS);
void resetLODAdjust();
void setOctreeSizeScale(float sizeScale);
float getOctreeSizeScale() const { return _octreeSizeScale; }
void setAutomaticAvatarLOD(bool automaticAvatarLOD) { _automaticAvatarLOD = automaticAvatarLOD; bumpSettings(); }
bool getAutomaticAvatarLOD() const { return _automaticAvatarLOD; }
void setAvatarLODDecreaseFPS(float avatarLODDecreaseFPS) { _avatarLODDecreaseFPS = avatarLODDecreaseFPS; bumpSettings(); }
float getAvatarLODDecreaseFPS() const { return _avatarLODDecreaseFPS; }
void setAvatarLODIncreaseFPS(float avatarLODIncreaseFPS) { _avatarLODIncreaseFPS = avatarLODIncreaseFPS; bumpSettings(); }
float getAvatarLODIncreaseFPS() const { return _avatarLODIncreaseFPS; }
void setAvatarLODDistanceMultiplier(float multiplier) { _avatarLODDistanceMultiplier = multiplier; bumpSettings(); }
float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; }
void setBoundaryLevelAdjust(int boundaryLevelAdjust);
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
bool shouldRenderMesh(float largestDimension, float distanceToCamera);
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
SpeechRecognizer* getSpeechRecognizer() { return &_speechRecognizer; }
#endif
// User Tweakable PPS from Voxel Server
int getMaxOctreePacketsPerSecond() const { return _maxOctreePacketsPerSecond; }
void setMaxOctreePacketsPerSecond(int value) { _maxOctreePacketsPerSecond = value; bumpSettings(); }
QAction* addActionToQMenuAndActionHash(QMenu* destinationMenu,
const QString& actionName,
const QKeySequence& shortcut = 0,
@ -154,35 +49,10 @@ public:
const QKeySequence& shortcut = 0,
QAction::MenuRole role = QAction::NoRole,
int menuItemLocation = UNSPECIFIED_POSITION);
void removeAction(QMenu* menu, const QString& actionName);
const QByteArray& getWalletPrivateKey() const { return _walletPrivateKey; }
signals:
void scriptLocationChanged(const QString& newPath);
public slots:
void clearLoginDialogDisplayedFlag();
void loginForCurrentDomain();
void showLoginForCurrentDomain();
void bandwidthDetails();
void octreeStatsDetails();
void cachesSizeDialog();
void lodTools();
void hmdTools(bool showTools);
void loadSettings(QSettings* settings = NULL);
void saveSettings(QSettings* settings = NULL);
void importSettings();
void exportSettings();
void toggleAddressBar();
void copyAddress();
void copyPath();
void toggleLoginMenuItem();
void toggleSixense(bool shouldEnable);
QMenu* addMenu(const QString& menuName);
void removeMenu(const QString& menuName);
bool menuExists(const QString& menuName);
@ -193,47 +63,21 @@ public slots:
bool menuItemExists(const QString& menuName, const QString& menuitem);
bool isOptionChecked(const QString& menuOption) const;
void setIsOptionChecked(const QString& menuOption, bool isChecked);
private slots:
void aboutApp();
void showEditEntitiesHelp();
void bumpSettings();
void editPreferences();
void editAttachments();
void editAnimations();
void changePrivateKey();
void bookmarkLocation();
void teleportToBookmark();
void deleteBookmark();
void hmdToolsClosed();
void runTests();
void showMetavoxelEditor();
void showMetavoxelNetworkSimulator();
void showScriptEditor();
void showChat();
void toggleConsole();
void toggleToolWindow();
void toggleChat();
void audioMuteToggled();
void displayNameLocationResponse(const QString& errorString);
void changeVSync();
void loadRSSDKFile();
private:
static Menu* _instance;
Menu();
typedef void(*settingsAction)(QSettings*, QAction*);
static void loadAction(QSettings* set, QAction* action);
static void saveAction(QSettings* set, QAction* action);
void scanMenuBar(settingsAction modifySetting, QSettings* set);
void scanMenu(QMenu* menu, settingsAction modifySetting, QSettings* set);
typedef void(*settingsAction)(Settings&, QAction&);
static void loadAction(Settings& settings, QAction& action);
static void saveAction(Settings& settings, QAction& action);
void scanMenuBar(settingsAction modifySetting);
void scanMenu(QMenu& menu, settingsAction modifySetting, Settings& settings);
/// helper method to have separators with labels that are also compatible with OS X
void addDisabledActionAndSeparator(QMenu* destinationMenu, const QString& actionName,
int menuItemLocation = UNSPECIFIED_POSITION);
int menuItemLocation = UNSPECIFIED_POSITION);
QAction* addCheckableActionToQMenuAndActionHash(QMenu* destinationMenu,
const QString& actionName,
const QKeySequence& shortcut = 0,
@ -241,78 +85,17 @@ private:
const QObject* receiver = NULL,
const char* member = NULL,
int menuItemLocation = UNSPECIFIED_POSITION);
QAction* getActionFromName(const QString& menuName, QMenu* menu);
QMenu* getSubMenuFromName(const QString& menuName, QMenu* menu);
QMenu* getMenuParent(const QString& menuName, QString& finalMenuPart);
QAction* getMenuAction(const QString& menuName);
int findPositionOfMenuItem(QMenu* menu, const QString& searchMenuItem);
int positionBeforeSeparatorIfNeeded(QMenu* menu, int requestedPosition);
QMenu* getMenu(const QString& menuName);
QHash<QString, QAction*> _actionHash;
InboundAudioStream::Settings _receivedAudioStreamSettings;
// in Degrees, doesn't apply to HMD like Oculus
float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES;
// The actual FOV set by the user's monitor size and view distance
float _realWorldFieldOfView = DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES;
float _faceshiftEyeDeflection = DEFAULT_FACESHIFT_EYE_DEFLECTION;
QString _faceshiftHostname = DEFAULT_FACESHIFT_HOSTNAME;
QDialog* _jsConsole = nullptr;
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
SpeechRecognizer _speechRecognizer;
#endif
float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE;
float _oculusUIAngularSize = DEFAULT_OCULUS_UI_ANGULAR_SIZE;
float _sixenseReticleMoveSpeed = DEFAULT_SIXENSE_RETICLE_MOVE_SPEED;
bool _invertSixenseButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
bool _hasLoginDialogDisplayed = false;
bool _automaticAvatarLOD = true;
float _avatarLODDecreaseFPS = DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS;
float _avatarLODIncreaseFPS = ADJUST_LOD_UP_FPS;
float _avatarLODDistanceMultiplier = DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER;
int _boundaryLevelAdjust = 0;
int _maxOctreePacketsPerSecond = DEFAULT_MAX_OCTREE_PPS;
quint64 _lastAdjust;
quint64 _lastAvatarDetailDrop;
SimpleMovingAverage _fpsAverage = FIVE_SECONDS_OF_FRAMES;
SimpleMovingAverage _fastFPSAverage = ONE_SECOND_OF_FRAMES;
QPointer<AddressBarDialog> _addressBarDialog;
QPointer<AnimationsDialog> _animationsDialog;
QPointer<AttachmentsDialog> _attachmentsDialog;
QPointer<BandwidthDialog> _bandwidthDialog;
QPointer<CachesSizeDialog> _cachesSizeDialog;
QPointer<HMDToolsDialog> _hmdToolsDialog;
QPointer<LodToolsDialog> _lodToolsDialog;
QPointer<LoginDialog> _loginDialog;
QPointer<OctreeStatsDialog> _octreeStatsDialog;
QPointer<PreferencesDialog> _preferencesDialog;
QPointer<MetavoxelEditor> _MetavoxelEditor;
QPointer<MetavoxelNetworkSimulator> _metavoxelNetworkSimulator;
QPointer<ScriptEditorWindow> _ScriptEditor;
QPointer<ChatWindow> _chatWindow;
QAction* _loginAction = nullptr;
QAction* _chatAction = nullptr;
QString _snapshotsLocation;
QString _scriptsLocation;
QByteArray _walletPrivateKey;
bool _shouldRenderTableNeedsRebuilding = true;
QMap<float, float> _shouldRenderTable;
void loadBookmarks();
QMenu* _bookmarksMenu;
QAction* _deleteBookmarksMenu;
};
namespace MenuOption {
@ -402,7 +185,6 @@ namespace MenuOption {
const QString LodTools = "LOD Tools";
const QString Login = "Login";
const QString Log = "Log";
const QString Logout = "Logout";
const QString LowVelocityFilter = "Low Velocity Filter";
const QString MetavoxelEditor = "Metavoxel Editor...";
const QString Metavoxels = "Metavoxels";
@ -484,10 +266,7 @@ namespace MenuOption {
const QString UploadSkeleton = "Upload Skeleton Model";
const QString UserInterface = "User Interface";
const QString Visage = "Visage";
const QString WalletPrivateKey = "Wallet Private Key...";
const QString Wireframe = "Wireframe";
}
void sendFakeEnterEvent();
#endif // hifi_Menu_h

View file

@ -9,6 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QBuffer>
#include <QCheckBox>
#include <QComboBox>
#include <QDebug>
@ -21,6 +22,7 @@
#include <QHBoxLayout>
#include <QHttpMultiPart>
#include <QImage>
#include <QJsonDocument>
#include <QLineEdit>
#include <QMessageBox>
#include <QProgressBar>
@ -28,12 +30,17 @@
#include <QStandardPaths>
#include <QTemporaryFile>
#include <QTextStream>
#include <QThread>
#include <QVBoxLayout>
#include <QVariant>
#include <AccountManager.h>
#include <GeometryCache.h>
#include <GLMHelpers.h>
#include <ResourceCache.h>
#include <Settings.h>
#include <TextureCache.h>
#include "Application.h"
#include "ModelUploader.h"
@ -53,8 +60,6 @@ static const QString BLENDSHAPE_FIELD = "bs";
static const QString S3_URL = "http://public.highfidelity.io";
static const QString MODEL_URL = "/api/v1/models";
static const QString SETTING_NAME = "LastModelUploadLocation";
static const unsigned long long MAX_SIZE = 50 * 1024 * BYTES_PER_MEGABYTES; // 50 GB (Virtually remove limit)
static const int MAX_TEXTURE_SIZE = 1024;
static const int TIMEOUT = 1000;
@ -63,6 +68,11 @@ static const int MAX_CHECK = 30;
static const int QCOMPRESS_HEADER_POSITION = 0;
static const int QCOMPRESS_HEADER_SIZE = 4;
namespace SettingHandles {
const SettingHandle<QString> lastModelUploadLocation("LastModelUploadLocation",
QStandardPaths::writableLocation(QStandardPaths::DownloadLocation));
}
void ModelUploader::uploadModel(ModelType modelType) {
ModelUploader* uploader = new ModelUploader(modelType);
QThread* thread = new QThread();
@ -107,8 +117,7 @@ ModelUploader::~ModelUploader() {
bool ModelUploader::zip() {
// File Dialog
QSettings* settings = Application::getInstance()->lockSettings();
QString lastLocation = settings->value(SETTING_NAME).toString();
QString lastLocation = SettingHandles::lastModelUploadLocation.get();
if (lastLocation.isEmpty()) {
lastLocation = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
@ -123,11 +132,9 @@ bool ModelUploader::zip() {
lastLocation, "Model files (*.fst *.fbx)");
if (filename == "") {
// If the user canceled we return.
Application::getInstance()->unlockSettings();
return false;
}
settings->setValue(SETTING_NAME, filename);
Application::getInstance()->unlockSettings();
SettingHandles::lastModelUploadLocation.set(filename);
// First we check the FST file (if any)
QFile* fst;

View file

@ -17,6 +17,7 @@
#include <NetworkAccessManager.h>
#include "Application.h"
#include "Menu.h"
#include "ScriptsModel.h"
@ -33,8 +34,8 @@ static const QString KEY_NAME = "Key";
TreeNodeBase::TreeNodeBase(TreeNodeFolder* parent, const QString& name, TreeNodeType type) :
_parent(parent),
_name(name),
_type(type) {
_type(type),
_name(name) {
};
TreeNodeScript::TreeNodeScript(const QString& localPath, const QString& fullPath, ScriptOrigin origin) :
@ -58,10 +59,10 @@ ScriptsModel::ScriptsModel(QObject* parent) :
_localDirectory.setFilter(QDir::Files | QDir::Readable);
_localDirectory.setNameFilters(QStringList("*.js"));
updateScriptsLocation(Menu::getInstance()->getScriptsLocation());
updateScriptsLocation(qApp->getScriptsLocation());
connect(&_fsWatcher, &QFileSystemWatcher::directoryChanged, this, &ScriptsModel::reloadLocalFiles);
connect(Menu::getInstance(), &Menu::scriptLocationChanged, this, &ScriptsModel::updateScriptsLocation);
connect(qApp, &Application::scriptLocationChanged, this, &ScriptsModel::updateScriptsLocation);
reloadLocalFiles();
reloadRemoteFiles();

View file

@ -20,12 +20,13 @@
#include <QWinEventNotifier>
#endif
class SpeechRecognizer : public QObject {
Q_OBJECT
public:
SpeechRecognizer();
~SpeechRecognizer();
#include <DependencyManager.h>
class SpeechRecognizer : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
void handleCommandRecognized(const char* command);
bool getEnabled() const { return _enabled; }
@ -42,6 +43,9 @@ protected:
void reloadCommands();
private:
SpeechRecognizer();
virtual ~SpeechRecognizer();
bool _enabled;
QSet<QString> _commands;
#if defined(Q_OS_MAC)

View file

@ -238,14 +238,6 @@ void runTimingTests() {
qDebug("vec3 assign and dot() usecs: %f, last result:%f", elapsedUsecs / (float) numTests, result);
}
float loadSetting(QSettings* settings, const char* name, float defaultValue) {
float value = settings->value(name, defaultValue).toFloat();
if (glm::isnan(value)) {
value = defaultValue;
}
return value;
}
bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNormalizedDirection,
const glm::vec3& sphereCenter, float sphereRadius, float& distance) {
glm::vec3 relativeOrigin = rayStarting - sphereCenter;

View file

@ -31,8 +31,6 @@ void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistan
void runTimingTests();
float loadSetting(QSettings* settings, const char* name, float defaultValue);
bool rayIntersectsSphere(const glm::vec3& rayStarting, const glm::vec3& rayNormalizedDirection,
const glm::vec3& sphereCenter, float sphereRadius, float& distance);

View file

@ -25,6 +25,7 @@
#include <DeferredLightingEffect.h>
#include <GeometryUtil.h>
#include <GlowEffect.h>
#include <LODManager.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <PathUtils.h>
@ -114,8 +115,8 @@ glm::quat Avatar::getWorldAlignedOrientation () const {
}
float Avatar::getLODDistance() const {
return Menu::getInstance()->getAvatarLODDistanceMultiplier() *
glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale;
return DependencyManager::get<LODManager>()->getAvatarLODDistanceMultiplier() *
glm::distance(qApp->getCamera()->getPosition(), _position) / _scale;
}
void Avatar::simulate(float deltaTime) {

View file

@ -28,6 +28,7 @@
#include <NodeList.h>
#include <PacketHeaders.h>
#include <PerfStat.h>
#include <Settings.h>
#include <ShapeCollider.h>
#include <SharedUtil.h>
#include <TextRenderer.h>
@ -338,7 +339,8 @@ void MyAvatar::updateFromTrackers(float deltaTime) {
head->setDeltaPitch(estimatedRotation.x);
head->setDeltaYaw(estimatedRotation.y);
} else {
float magnifyFieldOfView = Menu::getInstance()->getFieldOfView() / Menu::getInstance()->getRealWorldFieldOfView();
float magnifyFieldOfView = qApp->getViewFrustum()->getFieldOfView() /
qApp->getViewFrustum()->getRealWorldFieldOfView();
head->setDeltaPitch(estimatedRotation.x * magnifyFieldOfView);
head->setDeltaYaw(estimatedRotation.y * magnifyFieldOfView);
}
@ -677,60 +679,70 @@ AnimationDetails MyAvatar::getAnimationDetails(const QString& url) {
return result;
}
void MyAvatar::saveData(QSettings* settings) {
settings->beginGroup("Avatar");
void MyAvatar::saveData() {
Settings settings;
settings.beginGroup("Avatar");
settings->setValue("headPitch", getHead()->getBasePitch());
settings.setValue("headPitch", getHead()->getBasePitch());
settings->setValue("pupilDilation", getHead()->getPupilDilation());
settings.setValue("pupilDilation", getHead()->getPupilDilation());
settings->setValue("leanScale", _leanScale);
settings->setValue("scale", _targetScale);
settings.setValue("leanScale", _leanScale);
settings.setValue("scale", _targetScale);
settings->setValue("faceModelURL", _faceModelURL);
settings->setValue("skeletonModelURL", _skeletonModelURL);
settings.setValue("faceModelURL", _faceModelURL);
settings.setValue("skeletonModelURL", _skeletonModelURL);
settings->beginWriteArray("attachmentData");
settings.beginWriteArray("attachmentData");
for (int i = 0; i < _attachmentData.size(); i++) {
settings->setArrayIndex(i);
settings.setArrayIndex(i);
const AttachmentData& attachment = _attachmentData.at(i);
settings->setValue("modelURL", attachment.modelURL);
settings->setValue("jointName", attachment.jointName);
settings->setValue("translation_x", attachment.translation.x);
settings->setValue("translation_y", attachment.translation.y);
settings->setValue("translation_z", attachment.translation.z);
settings.setValue("modelURL", attachment.modelURL);
settings.setValue("jointName", attachment.jointName);
settings.setValue("translation_x", attachment.translation.x);
settings.setValue("translation_y", attachment.translation.y);
settings.setValue("translation_z", attachment.translation.z);
glm::vec3 eulers = safeEulerAngles(attachment.rotation);
settings->setValue("rotation_x", eulers.x);
settings->setValue("rotation_y", eulers.y);
settings->setValue("rotation_z", eulers.z);
settings->setValue("scale", attachment.scale);
settings.setValue("rotation_x", eulers.x);
settings.setValue("rotation_y", eulers.y);
settings.setValue("rotation_z", eulers.z);
settings.setValue("scale", attachment.scale);
}
settings->endArray();
settings.endArray();
settings->beginWriteArray("animationHandles");
settings.beginWriteArray("animationHandles");
for (int i = 0; i < _animationHandles.size(); i++) {
settings->setArrayIndex(i);
settings.setArrayIndex(i);
const AnimationHandlePointer& pointer = _animationHandles.at(i);
settings->setValue("role", pointer->getRole());
settings->setValue("url", pointer->getURL());
settings->setValue("fps", pointer->getFPS());
settings->setValue("priority", pointer->getPriority());
settings->setValue("loop", pointer->getLoop());
settings->setValue("hold", pointer->getHold());
settings->setValue("startAutomatically", pointer->getStartAutomatically());
settings->setValue("firstFrame", pointer->getFirstFrame());
settings->setValue("lastFrame", pointer->getLastFrame());
settings->setValue("maskedJoints", pointer->getMaskedJoints());
settings.setValue("role", pointer->getRole());
settings.setValue("url", pointer->getURL());
settings.setValue("fps", pointer->getFPS());
settings.setValue("priority", pointer->getPriority());
settings.setValue("loop", pointer->getLoop());
settings.setValue("hold", pointer->getHold());
settings.setValue("startAutomatically", pointer->getStartAutomatically());
settings.setValue("firstFrame", pointer->getFirstFrame());
settings.setValue("lastFrame", pointer->getLastFrame());
settings.setValue("maskedJoints", pointer->getMaskedJoints());
}
settings->endArray();
settings.endArray();
settings->setValue("displayName", _displayName);
settings.setValue("displayName", _displayName);
settings->endGroup();
settings.endGroup();
}
void MyAvatar::loadData(QSettings* settings) {
settings->beginGroup("Avatar");
float loadSetting(QSettings& settings, const char* name, float defaultValue) {
float value = settings.value(name, defaultValue).toFloat();
if (glm::isnan(value)) {
value = defaultValue;
}
return value;
}
void MyAvatar::loadData() {
Settings settings;
settings.beginGroup("Avatar");
getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f));
@ -741,16 +753,16 @@ void MyAvatar::loadData(QSettings* settings) {
setScale(_scale);
Application::getInstance()->getCamera()->setScale(_scale);
setFaceModelURL(settings->value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl());
setSkeletonModelURL(settings->value("skeletonModelURL").toUrl());
setFaceModelURL(settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl());
setSkeletonModelURL(settings.value("skeletonModelURL").toUrl());
QVector<AttachmentData> attachmentData;
int attachmentCount = settings->beginReadArray("attachmentData");
int attachmentCount = settings.beginReadArray("attachmentData");
for (int i = 0; i < attachmentCount; i++) {
settings->setArrayIndex(i);
settings.setArrayIndex(i);
AttachmentData attachment;
attachment.modelURL = settings->value("modelURL").toUrl();
attachment.jointName = settings->value("jointName").toString();
attachment.modelURL = settings.value("modelURL").toUrl();
attachment.jointName = settings.value("jointName").toString();
attachment.translation.x = loadSetting(settings, "translation_x", 0.0f);
attachment.translation.y = loadSetting(settings, "translation_y", 0.0f);
attachment.translation.z = loadSetting(settings, "translation_z", 0.0f);
@ -762,10 +774,10 @@ void MyAvatar::loadData(QSettings* settings) {
attachment.scale = loadSetting(settings, "scale", 1.0f);
attachmentData.append(attachment);
}
settings->endArray();
settings.endArray();
setAttachmentData(attachmentData);
int animationCount = settings->beginReadArray("animationHandles");
int animationCount = settings.beginReadArray("animationHandles");
while (_animationHandles.size() > animationCount) {
_animationHandles.takeLast()->stop();
}
@ -773,65 +785,64 @@ void MyAvatar::loadData(QSettings* settings) {
addAnimationHandle();
}
for (int i = 0; i < animationCount; i++) {
settings->setArrayIndex(i);
settings.setArrayIndex(i);
const AnimationHandlePointer& handle = _animationHandles.at(i);
handle->setRole(settings->value("role", "idle").toString());
handle->setURL(settings->value("url").toUrl());
handle->setRole(settings.value("role", "idle").toString());
handle->setURL(settings.value("url").toUrl());
handle->setFPS(loadSetting(settings, "fps", 30.0f));
handle->setPriority(loadSetting(settings, "priority", 1.0f));
handle->setLoop(settings->value("loop", true).toBool());
handle->setHold(settings->value("hold", false).toBool());
handle->setStartAutomatically(settings->value("startAutomatically", true).toBool());
handle->setFirstFrame(settings->value("firstFrame", 0.0f).toFloat());
handle->setLastFrame(settings->value("lastFrame", INT_MAX).toFloat());
handle->setMaskedJoints(settings->value("maskedJoints").toStringList());
handle->setLoop(settings.value("loop", true).toBool());
handle->setHold(settings.value("hold", false).toBool());
handle->setStartAutomatically(settings.value("startAutomatically", true).toBool());
handle->setFirstFrame(settings.value("firstFrame", 0.0f).toFloat());
handle->setLastFrame(settings.value("lastFrame", INT_MAX).toFloat());
handle->setMaskedJoints(settings.value("maskedJoints").toStringList());
}
settings->endArray();
settings.endArray();
setDisplayName(settings->value("displayName").toString());
setDisplayName(settings.value("displayName").toString());
settings->endGroup();
settings.endGroup();
}
void MyAvatar::saveAttachmentData(const AttachmentData& attachment) const {
QSettings* settings = Application::getInstance()->lockSettings();
settings->beginGroup("savedAttachmentData");
settings->beginGroup(_skeletonModel.getURL().toString());
settings->beginGroup(attachment.modelURL.toString());
settings->setValue("jointName", attachment.jointName);
Settings settings;
settings.beginGroup("savedAttachmentData");
settings.beginGroup(_skeletonModel.getURL().toString());
settings.beginGroup(attachment.modelURL.toString());
settings.setValue("jointName", attachment.jointName);
settings->beginGroup(attachment.jointName);
settings->setValue("translation_x", attachment.translation.x);
settings->setValue("translation_y", attachment.translation.y);
settings->setValue("translation_z", attachment.translation.z);
settings.beginGroup(attachment.jointName);
settings.setValue("translation_x", attachment.translation.x);
settings.setValue("translation_y", attachment.translation.y);
settings.setValue("translation_z", attachment.translation.z);
glm::vec3 eulers = safeEulerAngles(attachment.rotation);
settings->setValue("rotation_x", eulers.x);
settings->setValue("rotation_y", eulers.y);
settings->setValue("rotation_z", eulers.z);
settings->setValue("scale", attachment.scale);
settings.setValue("rotation_x", eulers.x);
settings.setValue("rotation_y", eulers.y);
settings.setValue("rotation_z", eulers.z);
settings.setValue("scale", attachment.scale);
settings->endGroup();
settings->endGroup();
settings->endGroup();
settings->endGroup();
Application::getInstance()->unlockSettings();
settings.endGroup();
settings.endGroup();
settings.endGroup();
settings.endGroup();
}
AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL, const QString& jointName) const {
QSettings* settings = Application::getInstance()->lockSettings();
settings->beginGroup("savedAttachmentData");
settings->beginGroup(_skeletonModel.getURL().toString());
settings->beginGroup(modelURL.toString());
Settings settings;
settings.beginGroup("savedAttachmentData");
settings.beginGroup(_skeletonModel.getURL().toString());
settings.beginGroup(modelURL.toString());
AttachmentData attachment;
attachment.modelURL = modelURL;
if (jointName.isEmpty()) {
attachment.jointName = settings->value("jointName").toString();
attachment.jointName = settings.value("jointName").toString();
} else {
attachment.jointName = jointName;
}
settings->beginGroup(attachment.jointName);
if (settings->contains("translation_x")) {
settings.beginGroup(attachment.jointName);
if (settings.contains("translation_x")) {
attachment.translation.x = loadSetting(settings, "translation_x", 0.0f);
attachment.translation.y = loadSetting(settings, "translation_y", 0.0f);
attachment.translation.z = loadSetting(settings, "translation_z", 0.0f);
@ -845,11 +856,10 @@ AttachmentData MyAvatar::loadAttachmentData(const QUrl& modelURL, const QString&
attachment = AttachmentData();
}
settings->endGroup();
settings->endGroup();
settings->endGroup();
settings->endGroup();
Application::getInstance()->unlockSettings();
settings.endGroup();
settings.endGroup();
settings.endGroup();
settings.endGroup();
return attachment;
}

View file

@ -78,8 +78,8 @@ public:
Q_INVOKABLE AnimationDetails getAnimationDetails(const QString& url);
// get/set avatar data
void saveData(QSettings* settings);
void loadData(QSettings* settings);
void saveData();
void loadData();
void saveAttachmentData(const AttachmentData& attachment) const;
AttachmentData loadAttachmentData(const QUrl& modelURL, const QString& jointName = QString()) const;

View file

@ -11,7 +11,9 @@
#include <QTimer>
#include <GLMHelpers.h>
#include <PerfStat.h>
#include <Settings.h>
#include <SharedUtil.h>
#include "Faceshift.h"
@ -27,6 +29,11 @@ using namespace std;
const quint16 FACESHIFT_PORT = 33433;
float STARTING_FACESHIFT_FRAME_TIME = 0.033f;
namespace SettingHandles {
const SettingHandle<float> faceshiftEyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION);
const SettingHandle<QString> faceshiftHostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME);
}
Faceshift::Faceshift() :
_tcpEnabled(true),
_tcpRetryCount(0),
@ -66,6 +73,9 @@ Faceshift::Faceshift() :
_udpSocket.bind(FACESHIFT_PORT);
#endif
_eyeDeflection = SettingHandles::faceshiftEyeDeflection.get();
_hostname = SettingHandles::faceshiftHostname.get();
}
void Faceshift::init() {
@ -159,7 +169,7 @@ void Faceshift::connectSocket() {
qDebug("Faceshift: Connecting...");
}
_tcpSocket.connectToHost(Menu::getInstance()->getFaceshiftHostname(), FACESHIFT_PORT);
_tcpSocket.connectToHost(_hostname, FACESHIFT_PORT);
_tracking = false;
}
}
@ -309,3 +319,13 @@ void Faceshift::receive(const QByteArray& buffer) {
}
#endif
}
void Faceshift::setEyeDeflection(float faceshiftEyeDeflection) {
_eyeDeflection = faceshiftEyeDeflection;
SettingHandles::faceshiftEyeDeflection.set(_eyeDeflection);
}
void Faceshift::setHostname(const QString& hostname) {
_hostname = hostname;
SettingHandles::faceshiftHostname.set(_hostname);
}

View file

@ -61,6 +61,12 @@ public:
float getMouthSize() const { return getBlendshapeCoefficient(_jawOpenIndex); }
float getMouthSmileLeft() const { return getBlendshapeCoefficient(_mouthSmileLeftIndex); }
float getMouthSmileRight() const { return getBlendshapeCoefficient(_mouthSmileRightIndex); }
float getEyeDeflection() const { return _eyeDeflection; }
void setEyeDeflection(float faceshiftEyeDeflection);
const QString& getHostname() const { return _hostname; }
void setHostname(const QString& hostname);
void update();
void reset();
@ -145,6 +151,9 @@ private:
float _longTermAverageEyeYaw;
bool _longTermAverageInitialized;
float _eyeDeflection = DEFAULT_FACESHIFT_EYE_DEFLECTION;
QString _hostname = DEFAULT_FACESHIFT_HOSTNAME;
};
#endif // hifi_Faceshift_h

View file

@ -8,6 +8,8 @@
// 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 "RealSense.h"
#include "MainWindow.h"
#include "Menu.h"

View file

@ -40,6 +40,7 @@ public:
virtual void update();
public slots:
void loadRSSDKFile();
protected:

View file

@ -301,7 +301,16 @@ const float RANGE_MULT = (MAX_PIXEL_RANGE_MULT - MIN_PIXEL_RANGE_MULT) * 0.01;
//Returns a multiplier to be applied to the cursor range for the controllers
float SixenseManager::getCursorPixelRangeMult() const {
//scales (0,100) to (MINIMUM_PIXEL_RANGE_MULT, MAXIMUM_PIXEL_RANGE_MULT)
return Menu::getInstance()->getSixenseReticleMoveSpeed() * RANGE_MULT + MIN_PIXEL_RANGE_MULT;
return _reticleMoveSpeed * RANGE_MULT + MIN_PIXEL_RANGE_MULT;
}
void SixenseManager::toggleSixense(bool shouldEnable) {
if (shouldEnable && !isInitialized()) {
initialize();
setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
setLowVelocityFilter(Menu::getInstance()->isOptionChecked(MenuOption::LowVelocityFilter));
}
setIsEnabled(shouldEnable);
}
#ifdef HAVE_SIXENSE
@ -459,7 +468,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) {
unsigned int deviceID = index == 0 ? CONTROLLER_0_EVENT : CONTROLLER_1_EVENT;
if (Menu::getInstance()->getInvertSixenseButtons()) {
if (_invertButtons) {
bumperButton = Qt::LeftButton;
triggerButton = Qt::RightButton;
} else {

View file

@ -55,8 +55,13 @@ public:
void update(float deltaTime);
float getCursorPixelRangeMult() const;
public slots:
float getReticleMoveSpeed() const { return _reticleMoveSpeed; }
void setReticleMoveSpeed(float sixenseReticleMoveSpeed) { _reticleMoveSpeed = sixenseReticleMoveSpeed; }
bool getInvertButtons() const { return _invertButtons; }
void setInvertButtons(bool invertSixenseButtons) { _invertButtons = invertSixenseButtons; }
public slots:
void toggleSixense(bool shouldEnable);
void setFilter(bool filter);
void setLowVelocityFilter(bool lowVelocityFilter) { _lowVelocityFilter = lowVelocityFilter; };
@ -102,6 +107,9 @@ private:
bool _lowVelocityFilter;
bool _controllersAtBase;
float _reticleMoveSpeed = DEFAULT_SIXENSE_RETICLE_MOVE_SPEED;
bool _invertButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS;
};
#endif // hifi_SixenseManager_h

View file

@ -8,13 +8,15 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Application.h"
#include <QDebug>
#include <QDir>
#include <QSettings>
#include <QTranslator>
#include <SharedUtil.h>
#include "Application.h"
int main(int argc, const char * argv[]) {
QElapsedTimer startupTime;
startupTime.start();

View file

@ -9,7 +9,7 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Application.h"
#include "Audio.h"
#include "AudioDeviceScriptingInterface.h"

View file

@ -12,11 +12,11 @@
#ifndef hifi_AudioDeviceScriptingInterface_h
#define hifi_AudioDeviceScriptingInterface_h
#include <QDebug>
#include <QObject>
#include <QString>
#include <QVector>
#include "Application.h"
class AudioEffectOptions;
class AudioDeviceScriptingInterface : public QObject {
Q_OBJECT

View file

@ -9,7 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Application.h"
#include <Settings.h>
#include "SettingsScriptingInterface.h"
@ -19,9 +20,7 @@ SettingsScriptingInterface* SettingsScriptingInterface::getInstance() {
}
QVariant SettingsScriptingInterface::getValue(const QString& setting) {
QSettings* settings = Application::getInstance()->lockSettings();
QVariant value = settings->value(setting);
Application::getInstance()->unlockSettings();
QVariant value = SettingHandles::SettingHandle<QVariant>(setting).get();
if (!value.isValid()) {
value = "";
}
@ -29,9 +28,7 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting) {
}
QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVariant& defaultValue) {
QSettings* settings = Application::getInstance()->lockSettings();
QVariant value = settings->value(setting, defaultValue);
Application::getInstance()->unlockSettings();
QVariant value = SettingHandles::SettingHandle<QVariant>(setting, defaultValue).get();
if (!value.isValid()) {
value = "";
}
@ -39,7 +36,5 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVar
}
void SettingsScriptingInterface::setValue(const QString& setting, const QVariant& value) {
QSettings* settings = Application::getInstance()->lockSettings();
settings->setValue(setting, value);
Application::getInstance()->unlockSettings();
SettingHandles::SettingHandle<QVariant>(setting).set(value);
}

View file

@ -15,6 +15,7 @@
#include <QInputDialog>
#include <QMessageBox>
#include <QScriptValue>
#include <QScrollArea>
#include "Application.h"
#include "MainWindow.h"

View file

@ -21,8 +21,8 @@
const QString ADDRESSBAR_GO_BUTTON_ICON = "images/address-bar-submit.svg";
const QString ADDRESSBAR_GO_BUTTON_ACTIVE_ICON = "images/address-bar-submit-active.svg";
AddressBarDialog::AddressBarDialog() :
FramelessDialog(Application::getInstance()->getWindow(), 0, FramelessDialog::POSITION_TOP)
AddressBarDialog::AddressBarDialog(QWidget* parent) :
FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP)
{
setAttribute(Qt::WA_DeleteOnClose, false);
setupUI();

View file

@ -23,7 +23,7 @@ class AddressBarDialog : public FramelessDialog {
Q_OBJECT
public:
AddressBarDialog();
AddressBarDialog(QWidget* parent);
private:
void setupUI();

View file

@ -20,12 +20,18 @@
#include <QScrollArea>
#include <QVBoxLayout>
#include <Settings.h>
#include "AnimationsDialog.h"
#include "Application.h"
#include "MainWindow.h"
AnimationsDialog::AnimationsDialog() :
QDialog(Application::getInstance()->getWindow()) {
namespace SettingHandles {
const SettingHandle<QString> animationDirectory("animation_directory", QString());
}
AnimationsDialog::AnimationsDialog(QWidget* parent) :
QDialog(parent) {
setWindowTitle("Edit Animations");
setAttribute(Qt::WA_DeleteOnClose);
@ -157,14 +163,12 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo
}
void AnimationPanel::chooseURL() {
QString directory = Application::getInstance()->lockSettings()->value("animation_directory").toString();
Application::getInstance()->unlockSettings();
QString directory = SettingHandles::animationDirectory.get();
QString filename = QFileDialog::getOpenFileName(this, "Choose Animation", directory, "Animation files (*.fbx)");
if (filename.isEmpty()) {
return;
}
Application::getInstance()->lockSettings()->setValue("animation_directory", QFileInfo(filename).path());
Application::getInstance()->unlockSettings();
SettingHandles::animationDirectory.set(QFileInfo(filename).path());
_url->setText(QUrl::fromLocalFile(filename).toString());
emit _url->returnPressed();
}

View file

@ -13,6 +13,7 @@
#define hifi_AnimationsDialog_h
#include <QDialog>
#include <QDoubleSpinBox>
#include <QFrame>
#include "avatar/MyAvatar.h"
@ -30,7 +31,7 @@ class AnimationsDialog : public QDialog {
public:
AnimationsDialog();
AnimationsDialog(QWidget* parent = nullptr);
virtual void setVisible(bool visible);

View file

@ -16,6 +16,7 @@
#include <PathUtils.h>
#include <PerfStat.h>
#include "Audio.h"
#include "audio/AudioIOStatsRenderer.h"
#include "audio/AudioScope.h"
#include "audio/AudioToolBox.h"
@ -164,7 +165,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) {
Overlays& overlays = application->getOverlays();
auto glCanvas = DependencyManager::get<GLCanvas>();
_textureFov = glm::radians(Menu::getInstance()->getOculusUIAngularSize());
_textureFov = glm::radians(_oculusUIAngularSize);
_textureAspectRatio = (float)glCanvas->getDeviceWidth() / (float)glCanvas->getDeviceHeight();
//Handle fading and deactivation/activation of UI

View file

@ -20,6 +20,8 @@ const float MAGNIFY_WIDTH = 220.0f;
const float MAGNIFY_HEIGHT = 100.0f;
const float MAGNIFY_MULT = 2.0f;
const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f;
// Handles the drawing of the overlays to the screen
class ApplicationOverlay {
public:
@ -35,6 +37,9 @@ public:
QPoint getPalmClickLocation(const PalmData *palm) const;
bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const;
float getOculusUIAngularSize() const { return _oculusUIAngularSize; }
void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; }
// Converter from one frame of reference to another.
// Frame of reference:
// Screen: Position on the screen (x,y)
@ -80,6 +85,8 @@ private:
VerticesIndices _vbo;
};
float _oculusUIAngularSize = DEFAULT_OCULUS_UI_ANGULAR_SIZE;
void renderReticle(glm::quat orientation, float alpha);
void renderPointers();;
void renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder);

View file

@ -22,8 +22,8 @@
#include "AttachmentsDialog.h"
#include "MainWindow.h"
AttachmentsDialog::AttachmentsDialog() :
QDialog(Application::getInstance()->getWindow()) {
AttachmentsDialog::AttachmentsDialog(QWidget* parent) :
QDialog(parent) {
setWindowTitle("Edit Attachments");
setAttribute(Qt::WA_DeleteOnClose);

View file

@ -27,8 +27,7 @@ class AttachmentsDialog : public QDialog {
Q_OBJECT
public:
AttachmentsDialog();
AttachmentsDialog(QWidget* parent = nullptr);
virtual void setVisible(bool visible);

View file

@ -22,6 +22,7 @@
#include <AddressManager.h>
#include <AccountManager.h>
#include <PathUtils.h>
#include <Settings.h>
#include "Application.h"
#include "ChatMessageArea.h"
@ -41,6 +42,10 @@ const QRegularExpression regexHifiLinks("([#@]\\S+)");
const QString mentionSoundsPath("/mention-sounds/");
const QString mentionRegex("@(\\b%1\\b)");
namespace SettingHandles {
const SettingHandle<QDateTime> usernameMentionTimestamp("MentionTimestamp", QDateTime());
}
ChatWindow::ChatWindow(QWidget* parent) :
QWidget(parent, Qt::Window | Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint |
Qt::WindowCloseButtonHint),
@ -377,12 +382,10 @@ void ChatWindow::messageReceived(const QXmppMessage& message) {
if (message.body().contains(usernameMention)) {
// Don't show messages already seen in icon tray at start-up.
QSettings* settings = Application::getInstance()->lockSettings();
bool showMessage = settings->value("usernameMentionTimestamp").toDateTime() < _lastMessageStamp;
bool showMessage = SettingHandles::usernameMentionTimestamp.get() < _lastMessageStamp;
if (showMessage) {
settings->setValue("usernameMentionTimestamp", _lastMessageStamp);
SettingHandles::usernameMentionTimestamp.set(_lastMessageStamp);
}
Application::getInstance()->unlockSettings();
if (isHidden() && showMessage) {

View file

@ -0,0 +1,215 @@
//
// DialogsManager.cpp
//
//
// Created by Clement on 1/18/15.
// 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 <AccountManager.h>
#include <MainWindow.h>
#include <PathUtils.h>
#include <XmppClient.h>
#include "AddressBarDialog.h"
#include "AnimationsDialog.h"
#include "AttachmentsDialog.h"
#include "BandwidthDialog.h"
#include "CachesSizeDialog.h"
#include "ChatWindow.h"
#include "HMDToolsDialog.h"
#include "LodToolsDialog.h"
#include "LoginDialog.h"
#include "MetavoxelEditor.h"
#include "MetavoxelNetworkSimulator.h"
#include "OctreeStatsDialog.h"
#include "PreferencesDialog.h"
#include "ScriptEditorWindow.h"
#include "DialogsManager.h"
void DialogsManager::toggleAddressBar() {
maybeCreateDialog(_addressBarDialog);
if (!_addressBarDialog->isVisible()) {
_addressBarDialog->show();
}
}
void DialogsManager::toggleLoginDialog() {
maybeCreateDialog(_loginDialog);
_loginDialog->toggleQAction();
}
void DialogsManager::showLoginDialog() {
maybeCreateDialog(_loginDialog);
_loginDialog->showLoginForCurrentDomain();
}
void DialogsManager::octreeStatsDetails() {
if (!_octreeStatsDialog) {
_octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats());
if (_hmdToolsDialog) {
_hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle());
}
connect(_octreeStatsDialog, SIGNAL(closed()), _octreeStatsDialog, SLOT(deleteLater()));
_octreeStatsDialog->show();
}
_octreeStatsDialog->raise();
}
void DialogsManager::cachesSizeDialog() {
qDebug() << "Caches size:" << _cachesSizeDialog.isNull();
if (!_cachesSizeDialog) {
maybeCreateDialog(_cachesSizeDialog);
connect(_cachesSizeDialog, SIGNAL(closed()), _cachesSizeDialog, SLOT(deleteLater()));
_cachesSizeDialog->show();
}
_cachesSizeDialog->raise();
}
void DialogsManager::editPreferences() {
if (!_preferencesDialog) {
maybeCreateDialog(_preferencesDialog);
_preferencesDialog->show();
} else {
_preferencesDialog->close();
}
}
void DialogsManager::editAttachments() {
if (!_attachmentsDialog) {
maybeCreateDialog(_attachmentsDialog);
_attachmentsDialog->show();
} else {
_attachmentsDialog->close();
}
}
void DialogsManager::editAnimations() {
if (!_animationsDialog) {
maybeCreateDialog(_animationsDialog);
_animationsDialog->show();
} else {
_animationsDialog->close();
}
}
void DialogsManager::bandwidthDetails() {
if (! _bandwidthDialog) {
_bandwidthDialog = new BandwidthDialog(qApp->getWindow(), qApp->getBandwidthMeter());
connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater()));
if (_hmdToolsDialog) {
_hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle());
}
_bandwidthDialog->show();
}
_bandwidthDialog->raise();
}
void DialogsManager::lodTools() {
if (!_lodToolsDialog) {
maybeCreateDialog(_lodToolsDialog);
connect(_lodToolsDialog, SIGNAL(closed()), _lodToolsDialog, SLOT(deleteLater()));
_lodToolsDialog->show();
}
_lodToolsDialog->raise();
}
void DialogsManager::toggleToolWindow() {
QMainWindow* toolWindow = qApp->getToolWindow();
toolWindow->setVisible(!toolWindow->isVisible());
}
void DialogsManager::hmdTools(bool showTools) {
if (showTools) {
if (!_hmdToolsDialog) {
maybeCreateDialog(_hmdToolsDialog);
connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed()));
}
_hmdToolsDialog->show();
_hmdToolsDialog->raise();
} else {
hmdToolsClosed();
}
qApp->getWindow()->activateWindow();
}
void DialogsManager::hmdToolsClosed() {
Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false);
_hmdToolsDialog->hide();
}
void DialogsManager::showMetavoxelEditor() {
maybeCreateDialog(_metavoxelEditor);
_metavoxelEditor->raise();
}
void DialogsManager::showMetavoxelNetworkSimulator() {
maybeCreateDialog(_metavoxelNetworkSimulator);
_metavoxelNetworkSimulator->raise();
}
void DialogsManager::showScriptEditor() {
maybeCreateDialog(_scriptEditor);
_scriptEditor->raise();
}
void DialogsManager::setupChat() {
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
connect(&xmppClient, &QXmppClient::connected, this, &DialogsManager::toggleChat);
connect(&xmppClient, &QXmppClient::disconnected, this, &DialogsManager::toggleChat);
QDir::setCurrent(PathUtils::resourcesPath());
// init chat window to listen chat
maybeCreateDialog(_chatWindow);
#endif
}
void DialogsManager::showChat() {
if (AccountManager::getInstance().isLoggedIn()) {
maybeCreateDialog(_chatWindow);
if (_chatWindow->isHidden()) {
_chatWindow->show();
}
_chatWindow->raise();
_chatWindow->activateWindow();
_chatWindow->setFocus();
} else {
qApp->getTrayIcon()->showMessage("Interface",
"You need to login to be able to chat with others on this domain.");
}
}
void DialogsManager::toggleChat() {
#ifdef HAVE_QXMPP
QAction* chatAction = Menu::getInstance()->getActionForOption(MenuOption::Login);
Q_CHECK_PTR(chatAction);
chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected());
if (!chatAction->isEnabled() && _chatWindow && AccountManager::getInstance().isLoggedIn()) {
if (_chatWindow->isHidden()) {
_chatWindow->show();
_chatWindow->raise();
_chatWindow->activateWindow();
_chatWindow->setFocus();
} else {
_chatWindow->hide();
}
}
#endif
}

View file

@ -0,0 +1,105 @@
//
// DialogsManager.h
//
//
// Created by Clement on 1/18/15.
// 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
//
#ifndef hifi_DialogsManager_h
#define hifi_DialogsManager_h
#include <QPointer>
#include <Application.h>
#include <DependencyManager.h>
#include "HMDToolsDialog.h"
class QAction;
class AddressBarDialog;
class AnimationsDialog;
class AttachmentsDialog;
class CachesSizeDialog;
class ChatWindow;
class BandwidthDialog;
class LodToolsDialog;
class LoginDialog;
class MetavoxelEditor;
class MetavoxelNetworkSimulator;
class OctreeStatsDialog;
class PreferencesDialog;
class ScriptEditorWindow;
class DialogsManager : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
QPointer<BandwidthDialog> getBandwidthDialog() const { return _bandwidthDialog; }
QPointer<HMDToolsDialog> getHMDToolsDialog() const { return _hmdToolsDialog; }
QPointer<LodToolsDialog> getLodToolsDialog() const { return _lodToolsDialog; }
QPointer<OctreeStatsDialog> getOctreeStatsDialog() const { return _octreeStatsDialog; }
void setupChat();
public slots:
void toggleAddressBar();
void toggleLoginDialog();
void showLoginDialog();
void octreeStatsDetails();
void cachesSizeDialog();
void editPreferences();
void editAttachments();
void editAnimations();
void bandwidthDetails();
void lodTools();
void hmdTools(bool showTools);
void showMetavoxelEditor();
void showMetavoxelNetworkSimulator();
void showScriptEditor();
void showChat();
private slots:
void toggleToolWindow();
void hmdToolsClosed();
void toggleChat();
private:
DialogsManager() {}
template<typename T>
void maybeCreateDialog(QPointer<T>& member) {
if (!member) {
MainWindow* parent = qApp->getWindow();
Q_CHECK_PTR(parent);
member = new T(parent);
Q_CHECK_PTR(member);
if (_hmdToolsDialog) {
_hmdToolsDialog->watchWindow(member->windowHandle());
}
}
}
QPointer<AddressBarDialog> _addressBarDialog;
QPointer<AnimationsDialog> _animationsDialog;
QPointer<AttachmentsDialog> _attachmentsDialog;
QPointer<BandwidthDialog> _bandwidthDialog;
QPointer<CachesSizeDialog> _cachesSizeDialog;
QPointer<ChatWindow> _chatWindow;
QPointer<HMDToolsDialog> _hmdToolsDialog;
QPointer<LodToolsDialog> _lodToolsDialog;
QPointer<LoginDialog> _loginDialog;
QPointer<MetavoxelEditor> _metavoxelEditor;
QPointer<MetavoxelNetworkSimulator> _metavoxelNetworkSimulator;
QPointer<OctreeStatsDialog> _octreeStatsDialog;
QPointer<PreferencesDialog> _preferencesDialog;
QPointer<ScriptEditorWindow> _scriptEditor;
};
#endif // hifi_DialogsManager_h

View file

@ -19,11 +19,13 @@
#include <QScreen>
#include <QWindow>
#include "MainWindow.h"
#include "Menu.h"
#include "devices/OculusManager.h"
#include "ui/DialogsManager.h"
#include "ui/HMDToolsDialog.h"
#include "devices/OculusManager.h"
HMDToolsDialog::HMDToolsDialog(QWidget* parent) :
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) ,
@ -67,20 +69,21 @@ HMDToolsDialog::HMDToolsDialog(QWidget* parent) :
// watch for our dialog window moving screens. If it does we want to enforce our rules about
// what screens we're allowed on
watchWindow(windowHandle());
auto dialogsManager = DependencyManager::get<DialogsManager>();
if (Application::getInstance()->getRunningScriptsWidget()) {
watchWindow(Application::getInstance()->getRunningScriptsWidget()->windowHandle());
}
if (Application::getInstance()->getToolWindow()) {
watchWindow(Application::getInstance()->getToolWindow()->windowHandle());
}
if (Menu::getInstance()->getBandwidthDialog()) {
watchWindow(Menu::getInstance()->getBandwidthDialog()->windowHandle());
if (dialogsManager->getBandwidthDialog()) {
watchWindow(dialogsManager->getBandwidthDialog()->windowHandle());
}
if (Menu::getInstance()->getOctreeStatsDialog()) {
watchWindow(Menu::getInstance()->getOctreeStatsDialog()->windowHandle());
if (dialogsManager->getOctreeStatsDialog()) {
watchWindow(dialogsManager->getOctreeStatsDialog()->windowHandle());
}
if (Menu::getInstance()->getLodToolsDialog()) {
watchWindow(Menu::getInstance()->getLodToolsDialog()->windowHandle());
if (dialogsManager->getLodToolsDialog()) {
watchWindow(dialogsManager->getLodToolsDialog()->windowHandle());
}
// when the application is about to quit, leave HDM mode

View file

@ -10,18 +10,21 @@
//
#include <QApplication>
#include <QDesktopWidget>
#include <QFileInfo>
#include <QtWebKitWidgets/QWebFrame>
#include <QtWebKit/QWebElement>
#include <QDesktopWidget>
#include <PathUtils.h>
#include <Settings.h>
#include "Application.h"
#include "InfoView.h"
#define SETTINGS_VERSION_KEY "info-version"
#define MAX_DIALOG_HEIGHT_RATIO 0.9
static const float MAX_DIALOG_HEIGHT_RATIO = 0.9f;
namespace SettingHandles {
const SettingHandle<QString> infoVersion("info-version", QString());
}
InfoView::InfoView(bool forced, QString path) :
_forced(forced)
@ -49,20 +52,17 @@ bool InfoView::shouldShow() {
return true;
}
QSettings* settings = Application::getInstance()->lockSettings();
QString lastVersion = settings->value(SETTINGS_VERSION_KEY).toString();
QString lastVersion = SettingHandles::infoVersion.get();
QWebElement versionTag = page()->mainFrame()->findFirstElement("#version");
QString version = versionTag.attribute("value");
if (version != QString::null && (lastVersion == QString::null || lastVersion != version)) {
settings->setValue(SETTINGS_VERSION_KEY, version);
SettingHandles::infoVersion.set(version);
shouldShow = true;
} else {
shouldShow = false;
}
Application::getInstance()->unlockSettings();
return shouldShow;
}
@ -72,7 +72,7 @@ void InfoView::loaded(bool ok) {
return;
}
QDesktopWidget* desktop = Application::getInstance()->desktop();
QDesktopWidget* desktop = qApp->desktop();
QWebFrame* mainFrame = page()->mainFrame();
int height = mainFrame->contentsSize().height() > desktop->height() ?

View file

@ -9,17 +9,19 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QFormLayout>
#include <QDialogButtonBox>
#include <QPalette>
#include <QCheckBox>
#include <QColor>
#include <QDialogButtonBox>
#include <QDoubleSpinBox>
#include <QSlider>
#include <QFormLayout>
#include <QLabel>
#include <QPalette>
#include <QPushButton>
#include <QSlider>
#include <QString>
#include <LODManager.h>
#include "Menu.h"
#include "ui/LodToolsDialog.h"
@ -28,6 +30,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint)
{
this->setWindowTitle("LOD Tools");
auto lodManager = DependencyManager::get<LODManager>();
// Create layouter
QFormLayout* form = new QFormLayout(this);
@ -45,7 +48,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
_lodSize->setTickPosition(QSlider::TicksBelow);
_lodSize->setFixedWidth(SLIDER_WIDTH);
_lodSize->setPageStep(PAGE_STEP_LOD_SIZE);
int sliderValue = Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE;
int sliderValue = lodManager->getOctreeSizeScale() / TREE_SCALE;
_lodSize->setValue(sliderValue);
form->addRow("LOD Size Scale:", _lodSize);
connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int)));
@ -60,7 +63,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
_boundaryLevelAdjust->setTickInterval(STEP_ADJUST);
_boundaryLevelAdjust->setTickPosition(QSlider::TicksBelow);
_boundaryLevelAdjust->setFixedWidth(SLIDER_WIDTH);
sliderValue = Menu::getInstance()->getBoundaryLevelAdjust();
sliderValue = lodManager->getBoundaryLevelAdjust();
_boundaryLevelAdjust->setValue(sliderValue);
form->addRow("Boundary Level Adjust:", _boundaryLevelAdjust);
connect(_boundaryLevelAdjust,SIGNAL(valueChanged(int)),this,SLOT(boundaryLevelValueChanged(int)));
@ -71,22 +74,22 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
const unsigned redish = 0xfff00000;
palette.setColor(QPalette::WindowText, QColor::fromRgb(redish));
_feedback->setPalette(palette);
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
_feedback->setText(lodManager->getLODFeedbackText());
const int FEEDBACK_WIDTH = 350;
_feedback->setFixedWidth(FEEDBACK_WIDTH);
form->addRow("You can see... ", _feedback);
form->addRow("Automatic Avatar LOD Adjustment:", _automaticAvatarLOD = new QCheckBox(this));
_automaticAvatarLOD->setChecked(Menu::getInstance()->getAutomaticAvatarLOD());
_automaticAvatarLOD->setChecked(lodManager->getAutomaticAvatarLOD());
connect(_automaticAvatarLOD, SIGNAL(toggled(bool)), SLOT(updateAvatarLODControls()));
form->addRow("Decrease Avatar LOD Below FPS:", _avatarLODDecreaseFPS = new QDoubleSpinBox(this));
_avatarLODDecreaseFPS->setValue(Menu::getInstance()->getAvatarLODDecreaseFPS());
_avatarLODDecreaseFPS->setValue(lodManager->getAvatarLODDecreaseFPS());
_avatarLODDecreaseFPS->setDecimals(0);
connect(_avatarLODDecreaseFPS, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues()));
form->addRow("Increase Avatar LOD Above FPS:", _avatarLODIncreaseFPS = new QDoubleSpinBox(this));
_avatarLODIncreaseFPS->setValue(Menu::getInstance()->getAvatarLODIncreaseFPS());
_avatarLODIncreaseFPS->setValue(lodManager->getAvatarLODIncreaseFPS());
_avatarLODIncreaseFPS->setDecimals(0);
connect(_avatarLODIncreaseFPS, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues()));
@ -94,7 +97,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
_avatarLOD->setDecimals(3);
_avatarLOD->setRange(1.0 / MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, 1.0 / MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER);
_avatarLOD->setSingleStep(0.001);
_avatarLOD->setValue(1.0 / Menu::getInstance()->getAvatarLODDistanceMultiplier());
_avatarLOD->setValue(1.0 / lodManager->getAvatarLODDistanceMultiplier());
connect(_avatarLOD, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues()));
// Add a button to reset
@ -108,15 +111,17 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) :
}
void LodToolsDialog::reloadSliders() {
_lodSize->setValue(Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE);
_boundaryLevelAdjust->setValue(Menu::getInstance()->getBoundaryLevelAdjust());
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
auto lodManager = DependencyManager::get<LODManager>();
_lodSize->setValue(lodManager->getOctreeSizeScale() / TREE_SCALE);
_boundaryLevelAdjust->setValue(lodManager->getBoundaryLevelAdjust());
_feedback->setText(lodManager->getLODFeedbackText());
}
void LodToolsDialog::updateAvatarLODControls() {
QFormLayout* form = static_cast<QFormLayout*>(layout());
Menu::getInstance()->setAutomaticAvatarLOD(_automaticAvatarLOD->isChecked());
auto lodManager = DependencyManager::get<LODManager>();
lodManager->setAutomaticAvatarLOD(_automaticAvatarLOD->isChecked());
_avatarLODDecreaseFPS->setVisible(_automaticAvatarLOD->isChecked());
form->labelForField(_avatarLODDecreaseFPS)->setVisible(_automaticAvatarLOD->isChecked());
@ -128,7 +133,7 @@ void LodToolsDialog::updateAvatarLODControls() {
form->labelForField(_avatarLOD)->setVisible(!_automaticAvatarLOD->isChecked());
if (!_automaticAvatarLOD->isChecked()) {
_avatarLOD->setValue(1.0 / Menu::getInstance()->getAvatarLODDistanceMultiplier());
_avatarLOD->setValue(1.0 / lodManager->getAvatarLODDistanceMultiplier());
}
if (isVisible()) {
@ -137,25 +142,28 @@ void LodToolsDialog::updateAvatarLODControls() {
}
void LodToolsDialog::updateAvatarLODValues() {
auto lodManager = DependencyManager::get<LODManager>();
if (_automaticAvatarLOD->isChecked()) {
Menu::getInstance()->setAvatarLODDecreaseFPS(_avatarLODDecreaseFPS->value());
Menu::getInstance()->setAvatarLODIncreaseFPS(_avatarLODIncreaseFPS->value());
lodManager->setAvatarLODDecreaseFPS(_avatarLODDecreaseFPS->value());
lodManager->setAvatarLODIncreaseFPS(_avatarLODIncreaseFPS->value());
} else {
Menu::getInstance()->setAvatarLODDistanceMultiplier(1.0 / _avatarLOD->value());
lodManager->setAvatarLODDistanceMultiplier(1.0 / _avatarLOD->value());
}
}
void LodToolsDialog::sizeScaleValueChanged(int value) {
auto lodManager = DependencyManager::get<LODManager>();
float realValue = value * TREE_SCALE;
Menu::getInstance()->setOctreeSizeScale(realValue);
lodManager->setOctreeSizeScale(realValue);
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
_feedback->setText(lodManager->getLODFeedbackText());
}
void LodToolsDialog::boundaryLevelValueChanged(int value) {
Menu::getInstance()->setBoundaryLevelAdjust(value);
_feedback->setText(Menu::getInstance()->getLODFeedbackText());
auto lodManager = DependencyManager::get<LODManager>();
lodManager->setBoundaryLevelAdjust(value);
_feedback->setText(lodManager->getLODFeedbackText());
}
void LodToolsDialog::resetClicked(bool checked) {

View file

@ -29,12 +29,9 @@ LoginDialog::LoginDialog(QWidget* parent) :
_ui(new Ui::LoginDialog) {
_ui->setupUi(this);
_ui->errorLabel->hide();
_ui->emailLineEdit->setFocus();
_ui->logoLabel->setPixmap(QPixmap(PathUtils::resourcesPath() + "images/hifi-logo.svg"));
_ui->loginButton->setIcon(QIcon(PathUtils::resourcesPath() + "images/login.svg"));
_ui->infoLabel->setVisible(false);
_ui->errorLabel->setVisible(false);
reset();
setAttribute(Qt::WA_DeleteOnClose, false);
connect(&AccountManager::getInstance(), &AccountManager::loginComplete,
this, &LoginDialog::handleLoginCompleted);
@ -50,9 +47,21 @@ LoginDialog::~LoginDialog() {
delete _ui;
};
void LoginDialog::handleLoginCompleted(const QUrl& authURL) {
void LoginDialog::reset() {
_ui->errorLabel->hide();
_ui->emailLineEdit->setFocus();
_ui->logoLabel->setPixmap(QPixmap(PathUtils::resourcesPath() + "images/hifi-logo.svg"));
_ui->loginButton->setIcon(QIcon(PathUtils::resourcesPath() + "images/login.svg"));
_ui->infoLabel->setVisible(false);
_ui->errorLabel->setVisible(false);
_ui->emailLineEdit->setText("");
_ui->passwordLineEdit->setText("");
_ui->loginArea->setDisabled(false);
}
void LoginDialog::handleLoginCompleted(const QUrl& authURL) {
reset();
close();
};
@ -87,3 +96,27 @@ void LoginDialog::moveEvent(QMoveEvent* event) {
// Modal dialogs seemed to get repositioned automatically. Combat this by moving the window if needed.
resizeAndPosition();
};
void LoginDialog::toggleQAction() {
AccountManager& accountManager = AccountManager::getInstance();
QAction* loginAction = Menu::getInstance()->getActionForOption(MenuOption::Login);
Q_CHECK_PTR(loginAction);
disconnect(loginAction, 0, 0, 0);
if (accountManager.isLoggedIn()) {
// change the menu item to logout
loginAction->setText("Logout " + accountManager.getAccountInfo().getUsername());
connect(loginAction, &QAction::triggered, &accountManager, &AccountManager::logout);
} else {
// change the menu item to login
loginAction->setText("Login");
connect(loginAction, &QAction::triggered, this, &LoginDialog::showLoginForCurrentDomain);
}
}
void LoginDialog::showLoginForCurrentDomain() {
show();
resizeAndPosition(false);
}

View file

@ -27,6 +27,11 @@ public:
~LoginDialog();
public slots:
void toggleQAction();
void showLoginForCurrentDomain();
protected slots:
void reset();
void handleLoginClicked();
void handleLoginCompleted(const QUrl& authURL);
void handleLoginFailed();
@ -35,8 +40,7 @@ protected:
void moveEvent(QMoveEvent* event);
private:
Ui::LoginDialog* _ui;
Ui::LoginDialog* _ui = nullptr;
};
#endif // hifi_LoginDialog_h

View file

@ -50,8 +50,8 @@ enum GridPlane {
const glm::vec2 INVALID_VECTOR(FLT_MAX, FLT_MAX);
MetavoxelEditor::MetavoxelEditor() :
QWidget(Application::getInstance()->getWindow(), Qt::Tool) {
MetavoxelEditor::MetavoxelEditor(QWidget* parent) :
QWidget(parent, Qt::Tool) {
setWindowTitle("Metavoxel Editor");
setAttribute(Qt::WA_DeleteOnClose);

View file

@ -12,6 +12,7 @@
#ifndef hifi_MetavoxelEditor_h
#define hifi_MetavoxelEditor_h
#include <QFormLayout>
#include <QList>
#include <QWidget>
@ -38,7 +39,7 @@ class MetavoxelEditor : public QWidget {
public:
MetavoxelEditor();
MetavoxelEditor(QWidget* parent = nullptr);
QString getSelectedAttribute() const;

View file

@ -20,8 +20,8 @@
const int BYTES_PER_KILOBYTE = 1024;
MetavoxelNetworkSimulator::MetavoxelNetworkSimulator() :
QWidget(DependencyManager::get<GLCanvas>().data(), Qt::Dialog) {
MetavoxelNetworkSimulator::MetavoxelNetworkSimulator(QWidget* parent) :
QWidget(parent, Qt::Dialog) {
setWindowTitle("Metavoxel Network Simulator");
setAttribute(Qt::WA_DeleteOnClose);

View file

@ -23,7 +23,7 @@ class MetavoxelNetworkSimulator : public QWidget {
public:
MetavoxelNetworkSimulator();
MetavoxelNetworkSimulator(QWidget* parent = nullptr);
private slots:

View file

@ -11,18 +11,22 @@
#include <QFileDialog>
#include <devices/Faceshift.h>
#include <devices/SixenseManager.h>
#include "Application.h"
#include "Audio.h"
#include "MainWindow.h"
#include "Menu.h"
#include "ModelsBrowser.h"
#include "PreferencesDialog.h"
#include "Snapshot.h"
#include "UserActivityLogger.h"
const int PREFERENCES_HEIGHT_PADDING = 20;
PreferencesDialog::PreferencesDialog() :
QDialog(Application::getInstance()->getWindow()) {
PreferencesDialog::PreferencesDialog(QWidget* parent) :
QDialog(parent) {
setAttribute(Qt::WA_DeleteOnClose);
@ -117,51 +121,53 @@ void PreferencesDialog::loadPreferences() {
ui.sendDataCheckBox->setChecked(!menuInstance->isOptionChecked(MenuOption::DisableActivityLogger));
ui.snapshotLocationEdit->setText(menuInstance->getSnapshotsLocation());
ui.snapshotLocationEdit->setText(SettingHandles::snapshotsLocation.get());
ui.scriptsLocationEdit->setText(menuInstance->getScriptsLocation());
ui.scriptsLocationEdit->setText(qApp->getScriptsLocation());
ui.pupilDilationSlider->setValue(myAvatar->getHead()->getPupilDilation() *
ui.pupilDilationSlider->maximum());
ui.faceshiftEyeDeflectionSider->setValue(menuInstance->getFaceshiftEyeDeflection() *
auto faceshift = DependencyManager::get<Faceshift>();
ui.faceshiftEyeDeflectionSider->setValue(faceshift->getEyeDeflection() *
ui.faceshiftEyeDeflectionSider->maximum());
ui.faceshiftHostnameEdit->setText(menuInstance->getFaceshiftHostname());
ui.faceshiftHostnameEdit->setText(faceshift->getHostname());
const InboundAudioStream::Settings& streamSettings = menuInstance->getReceivedAudioStreamSettings();
ui.dynamicJitterBuffersCheckBox->setChecked(streamSettings._dynamicJitterBuffers);
ui.staticDesiredJitterBufferFramesSpin->setValue(streamSettings._staticDesiredJitterBufferFrames);
ui.maxFramesOverDesiredSpin->setValue(streamSettings._maxFramesOverDesired);
ui.useStdevForJitterCalcCheckBox->setChecked(streamSettings._useStDevForJitterCalc);
ui.windowStarveThresholdSpin->setValue(streamSettings._windowStarveThreshold);
ui.windowSecondsForDesiredCalcOnTooManyStarvesSpin->setValue(streamSettings._windowSecondsForDesiredCalcOnTooManyStarves);
ui.windowSecondsForDesiredReductionSpin->setValue(streamSettings._windowSecondsForDesiredReduction);
ui.repetitionWithFadeCheckBox->setChecked(streamSettings._repetitionWithFade);
auto audio = DependencyManager::get<Audio>();
MixedProcessedAudioStream& stream = audio->getReceivedAudioStream();
ui.dynamicJitterBuffersCheckBox->setChecked(stream.getDynamicJitterBuffers());
ui.staticDesiredJitterBufferFramesSpin->setValue(stream.getDesiredJitterBufferFrames());
ui.maxFramesOverDesiredSpin->setValue(stream.getMaxFramesOverDesired());
ui.useStdevForJitterCalcCheckBox->setChecked(stream.getUseStDevForJitterCalc());
ui.windowStarveThresholdSpin->setValue(stream.getWindowStarveThreshold());
ui.windowSecondsForDesiredCalcOnTooManyStarvesSpin->setValue(
stream.getWindowSecondsForDesiredCalcOnTooManyStarves());
ui.windowSecondsForDesiredReductionSpin->setValue(stream.getWindowSecondsForDesiredReduction());
ui.repetitionWithFadeCheckBox->setChecked(stream.getRepetitionWithFade());
ui.outputBufferSizeSpinner->setValue(audio->getOutputBufferSize());
ui.outputStarveDetectionCheckBox->setChecked(audio->getOutputStarveDetectionEnabled());
ui.outputStarveDetectionThresholdSpinner->setValue(audio->getOutputStarveDetectionThreshold());
ui.outputStarveDetectionPeriodSpinner->setValue(audio->getOutputStarveDetectionPeriod());
ui.realWorldFieldOfViewSpin->setValue(menuInstance->getRealWorldFieldOfView());
ui.realWorldFieldOfViewSpin->setValue(qApp->getViewFrustum()->getRealWorldFieldOfView());
ui.fieldOfViewSpin->setValue(menuInstance->getFieldOfView());
ui.fieldOfViewSpin->setValue(qApp->getViewFrustum()->getFieldOfView());
ui.leanScaleSpin->setValue(myAvatar->getLeanScale());
ui.avatarScaleSpin->setValue(myAvatar->getScale());
ui.maxOctreePPSSpin->setValue(menuInstance->getMaxOctreePacketsPerSecond());
ui.maxOctreePPSSpin->setValue(qApp->getOctreeQuery().getMaxOctreePacketsPerSecond());
ui.oculusUIAngularSizeSpin->setValue(menuInstance->getOculusUIAngularSize());
ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationOverlay().getOculusUIAngularSize());
ui.sixenseReticleMoveSpeedSpin->setValue(menuInstance->getSixenseReticleMoveSpeed());
ui.invertSixenseButtonsCheckBox->setChecked(menuInstance->getInvertSixenseButtons());
SixenseManager& sixense = SixenseManager::getInstance();
ui.sixenseReticleMoveSpeedSpin->setValue(sixense.getReticleMoveSpeed());
ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons());
}
@ -213,11 +219,11 @@ void PreferencesDialog::savePreferences() {
}
if (!ui.snapshotLocationEdit->text().isEmpty() && QDir(ui.snapshotLocationEdit->text()).exists()) {
Menu::getInstance()->setSnapshotsLocation(ui.snapshotLocationEdit->text());
SettingHandles::snapshotsLocation.set(ui.snapshotLocationEdit->text());
}
if (!ui.scriptsLocationEdit->text().isEmpty() && QDir(ui.scriptsLocationEdit->text()).exists()) {
Menu::getInstance()->setScriptsLocation(ui.scriptsLocationEdit->text());
qApp->setScriptsLocation(ui.scriptsLocationEdit->text());
}
myAvatar->getHead()->setPupilDilation(ui.pupilDilationSlider->value() / (float)ui.pupilDilationSlider->maximum());
@ -227,36 +233,35 @@ void PreferencesDialog::savePreferences() {
auto glCanvas = DependencyManager::get<GLCanvas>();
Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height());
Menu::getInstance()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value());
qApp->getViewFrustum()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value());
Menu::getInstance()->setFieldOfView(ui.fieldOfViewSpin->value());
Menu::getInstance()->setFaceshiftEyeDeflection(ui.faceshiftEyeDeflectionSider->value() /
(float)ui.faceshiftEyeDeflectionSider->maximum());
qApp->getViewFrustum()->setFieldOfView(ui.fieldOfViewSpin->value());
Menu::getInstance()->setFaceshiftHostname(ui.faceshiftHostnameEdit->text());
auto faceshift = DependencyManager::get<Faceshift>();
faceshift->setEyeDeflection(ui.faceshiftEyeDeflectionSider->value() /
(float)ui.faceshiftEyeDeflectionSider->maximum());
Menu::getInstance()->setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value());
faceshift->setHostname(ui.faceshiftHostnameEdit->text());
qApp->getOctreeQuery().setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value());
Menu::getInstance()->setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value());
Menu::getInstance()->setSixenseReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
Menu::getInstance()->setInvertSixenseButtons(ui.invertSixenseButtonsCheckBox->isChecked());
InboundAudioStream::Settings streamSettings;
streamSettings._dynamicJitterBuffers = ui.dynamicJitterBuffersCheckBox->isChecked();
streamSettings._staticDesiredJitterBufferFrames = ui.staticDesiredJitterBufferFramesSpin->value();
streamSettings._maxFramesOverDesired = ui.maxFramesOverDesiredSpin->value();
streamSettings._useStDevForJitterCalc = ui.useStdevForJitterCalcCheckBox->isChecked();
streamSettings._windowStarveThreshold = ui.windowStarveThresholdSpin->value();
streamSettings._windowSecondsForDesiredCalcOnTooManyStarves = ui.windowSecondsForDesiredCalcOnTooManyStarvesSpin->value();
streamSettings._windowSecondsForDesiredReduction = ui.windowSecondsForDesiredReductionSpin->value();
streamSettings._repetitionWithFade = ui.repetitionWithFadeCheckBox->isChecked();
Menu::getInstance()->setReceivedAudioStreamSettings(streamSettings);
qApp->getApplicationOverlay().setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value());
SixenseManager& sixense = SixenseManager::getInstance();
sixense.setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value());
sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked());
auto audio = DependencyManager::get<Audio>();
MixedProcessedAudioStream& stream = audio->getReceivedAudioStream();
stream.setDynamicJitterBuffers(ui.dynamicJitterBuffersCheckBox->isChecked());
stream.setStaticDesiredJitterBufferFrames(ui.staticDesiredJitterBufferFramesSpin->value());
stream.setMaxFramesOverDesired(ui.maxFramesOverDesiredSpin->value());
stream.setUseStDevForJitterCalc(ui.useStdevForJitterCalcCheckBox->isChecked());
stream.setWindowStarveThreshold(ui.windowStarveThresholdSpin->value());
stream.setWindowSecondsForDesiredCalcOnTooManyStarves(ui.windowSecondsForDesiredCalcOnTooManyStarvesSpin->value());
stream.setWindowSecondsForDesiredReduction(ui.windowSecondsForDesiredReductionSpin->value());
stream.setRepetitionWithFade(ui.repetitionWithFadeCheckBox->isChecked());
QMetaObject::invokeMethod(audio.data(), "setOutputBufferSize", Q_ARG(int, ui.outputBufferSizeSpinner->value()));
@ -265,6 +270,4 @@ void PreferencesDialog::savePreferences() {
audio->setOutputStarveDetectionPeriod(ui.outputStarveDetectionPeriodSpinner->value());
Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height());
Application::getInstance()->bumpSettings();
}

View file

@ -21,7 +21,7 @@ class PreferencesDialog : public QDialog {
Q_OBJECT
public:
PreferencesDialog();
PreferencesDialog(QWidget* parent = nullptr);
protected:
void resizeEvent(QResizeEvent* resizeEvent);

View file

@ -20,24 +20,17 @@
#include "RearMirrorTools.h"
#include "Util.h"
const char SETTINGS_GROUP_NAME[] = "Rear View Tools";
const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel";
const int ICON_SIZE = 24;
const int ICON_PADDING = 5;
RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* settings) :
RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds) :
_parent(parent),
_bounds(bounds),
_windowed(false),
_fullScreen(false)
{
_zoomLevel = HEAD;
_closeTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/close.svg"));
// Disabled for now https://worklist.net/19548
// _resetTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/reset.png"));
_zoomHeadTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/plus.svg"));
_zoomBodyTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/minus.svg"));
@ -46,11 +39,7 @@ RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* se
_resetIconRect = QRect(_bounds.width() - ICON_SIZE - ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE);
_bodyZoomIconRect = QRect(_bounds.width() - ICON_SIZE - ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE);
_headZoomIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.bottom() - ICON_PADDING - ICON_SIZE, ICON_SIZE, ICON_SIZE);
settings->beginGroup(SETTINGS_GROUP_NAME);
_zoomLevel = loadSetting(settings, ZOOM_LEVEL_SETTINGS, 0) == HEAD ? HEAD : BODY;
settings->endGroup();
};
}
void RearMirrorTools::render(bool fullScreen) {
if (fullScreen) {
@ -63,11 +52,9 @@ void RearMirrorTools::render(bool fullScreen) {
if (_windowed) {
displayIcon(_bounds, _closeIconRect, _closeTextureId);
// Disabled for now https://worklist.net/19548
// displayIcon(_bounds, _resetIconRect, _resetTextureId);
displayIcon(_bounds, _headZoomIconRect, _zoomHeadTextureId, _zoomLevel == HEAD);
displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTextureId, _zoomLevel == BODY);
ZoomLevel zoomLevel = (ZoomLevel)SettingHandles::rearViewZoomLevel.get();
displayIcon(_bounds, _headZoomIconRect, _zoomHeadTextureId, zoomLevel == HEAD);
displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTextureId, zoomLevel == BODY);
}
}
}
@ -79,23 +66,14 @@ bool RearMirrorTools::mousePressEvent(int x, int y) {
emit closeView();
return true;
}
/* Disabled for now https://worklist.net/19548
if (_resetIconRect.contains(x, y)) {
emit resetView();
return true;
}
*/
if (_headZoomIconRect.contains(x, y)) {
_zoomLevel = HEAD;
Application::getInstance()->bumpSettings();
SettingHandles::rearViewZoomLevel.set(HEAD);
return true;
}
if (_bodyZoomIconRect.contains(x, y)) {
_zoomLevel = BODY;
Application::getInstance()->bumpSettings();
SettingHandles::rearViewZoomLevel.set(BODY);
return true;
}
@ -116,12 +94,6 @@ bool RearMirrorTools::mousePressEvent(int x, int y) {
return false;
}
void RearMirrorTools::saveSettings(QSettings* settings) {
settings->beginGroup(SETTINGS_GROUP_NAME);
settings->setValue(ZOOM_LEVEL_SETTINGS, _zoomLevel);
settings->endGroup();
}
void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint textureId, bool selected) {
glMatrixMode(GL_PROJECTION);

View file

@ -15,21 +15,27 @@
#include "InterfaceConfig.h"
#include <QGLWidget>
#include <QSettings>
#include <Settings.h>
enum ZoomLevel {
HEAD,
BODY
HEAD = 0,
BODY = 1
};
namespace SettingHandles {
const char SETTINGS_GROUP_NAME[] = "Rear View Tools";
const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel";
const SettingHandle<int> rearViewZoomLevel(QStringList() << SETTINGS_GROUP_NAME << ZOOM_LEVEL_SETTINGS,
ZoomLevel::HEAD);
}
class RearMirrorTools : public QObject {
Q_OBJECT
public:
RearMirrorTools(QGLWidget* parent, QRect& bounds, QSettings* settings);
RearMirrorTools(QGLWidget* parent, QRect& bounds);
void render(bool fullScreen);
bool mousePressEvent(int x, int y);
ZoomLevel getZoomLevel() { return _zoomLevel; }
void saveSettings(QSettings* settings);
signals:
void closeView();
@ -44,7 +50,6 @@ private:
GLuint _resetTextureId;
GLuint _zoomBodyTextureId;
GLuint _zoomHeadTextureId;
ZoomLevel _zoomLevel;
QRect _closeIconRect;
QRect _resetIconRect;

View file

@ -11,6 +11,7 @@
#include "ui_scriptEditorWidget.h"
#include "ScriptEditorWidget.h"
#include "ScriptEditorWindow.h"
#include <QGridLayout>
#include <QFileDialog>

View file

@ -31,7 +31,8 @@
#include "FlowLayout.h"
#include "JSConsole.h"
ScriptEditorWindow::ScriptEditorWindow() :
ScriptEditorWindow::ScriptEditorWindow(QWidget* parent) :
QWidget(parent),
_ScriptEditorWindowUI(new Ui::ScriptEditorWindow),
_loadMenu(new QMenu),
_saveMenu(new QMenu)

View file

@ -22,7 +22,7 @@ class ScriptEditorWindow : public QWidget {
Q_OBJECT
public:
ScriptEditorWindow();
ScriptEditorWindow(QWidget* parent = nullptr);
~ScriptEditorWindow();
void terminateCurrentTab();

View file

@ -10,13 +10,17 @@
//
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QImage>
#include <QTemporaryFile>
#include <AccountManager.h>
#include <Application.h>
#include <FileUtils.h>
#include "Snapshot.h"
#include "Menu.h"
// filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg
// %1 <= username, %2 <= date and time, %3 <= current location
@ -86,7 +90,7 @@ QFile* Snapshot::savedFileForSnapshot(bool isTemporary) {
auto glCanvas = DependencyManager::get<GLCanvas>();
QImage shot = glCanvas->grabFrameBuffer();
Avatar* avatar = Application::getInstance()->getAvatar();
Avatar* avatar = qApp->getAvatar();
glm::vec3 location = avatar->getPosition();
glm::quat orientation = avatar->getHead()->getOrientation();
@ -118,7 +122,7 @@ QFile* Snapshot::savedFileForSnapshot(bool isTemporary) {
const int IMAGE_QUALITY = 100;
if (!isTemporary) {
QString snapshotFullPath = Menu::getInstance()->getSnapshotsLocation();
QString snapshotFullPath = SettingHandles::snapshotsLocation.get();
if (!snapshotFullPath.endsWith(QDir::separator())) {
snapshotFullPath.append(QDir::separator());

View file

@ -12,15 +12,19 @@
#ifndef hifi_Snapshot_h
#define hifi_Snapshot_h
#include "InterfaceConfig.h"
#include <glm/glm.hpp>
#include <qimage.h>
#include <qfile.h>
#include <qtemporaryfile.h>
#include <QGLWidget>
#include <qstring.h>
#include <QString>
#include "avatar/Avatar.h"
#include <Settings.h>
class QFile;
class QTemporaryFile;
namespace SettingHandles {
const SettingHandle<QString> snapshotsLocation("snapshotsLocation",
QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));
}
class SnapshotMetaData {
public:
@ -41,7 +45,6 @@ private:
};
class Snapshot {
public:
static QString saveSnapshot();
static QTemporaryFile* saveTempSnapshot();

View file

@ -0,0 +1,39 @@
//
// StandAloneJSConsole.cpp
//
//
// Created by Clement on 1/17/15.
// 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 <QMainWindow>
#include <QDialog>
#include <QVBoxLayout>
#include <Application.h>
#include <MainWindow.h>
#include "StandAloneJSConsole.h"
void StandAloneJSConsole::toggleConsole() {
QMainWindow* mainWindow = qApp->getWindow();
if (!_jsConsole) {
QDialog* dialog = new QDialog(mainWindow, Qt::WindowStaysOnTopHint);
QVBoxLayout* layout = new QVBoxLayout(dialog);
dialog->setLayout(layout);
dialog->resize(QSize(CONSOLE_WIDTH, CONSOLE_HEIGHT));
layout->setMargin(0);
layout->setSpacing(0);
layout->addWidget(new JSConsole(dialog));
dialog->setWindowOpacity(CONSOLE_WINDOW_OPACITY);
dialog->setWindowTitle(CONSOLE_TITLE);
_jsConsole = dialog;
}
_jsConsole->setVisible(!_jsConsole->isVisible());
}

View file

@ -0,0 +1,35 @@
//
// StandAloneJSConsole.h
//
//
// Created by Clement on 1/17/15.
// 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
//
#ifndef hifi_StandAloneJSConsole_h
#define hifi_StandAloneJSConsole_h
#include <QPointer>
#include <DependencyManager.h>
#include "JSConsole.h"
class QDialog;
class StandAloneJSConsole : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public slots:
void toggleConsole();
private:
StandAloneJSConsole() {}
QPointer<QDialog> _jsConsole;
};
#endif // hifi_StandAloneJSConsole_h

View file

@ -18,6 +18,10 @@
#include <glm/gtx/quaternion.hpp>
#include <glm/gtx/vector_angle.hpp>
#include <Application.h>
#include <GeometryCache.h>
#include <GLCanvas.h>
#include <LODManager.h>
#include <PerfStat.h>
#include "Stats.h"
@ -623,7 +627,7 @@ void Stats::display(
// LOD Details
if (_expanded) {
octreeStats.str("");
QString displayLODDetails = Menu::getInstance()->getLODFeedbackText();
QString displayLODDetails = DependencyManager::get<LODManager>()->getLODFeedbackText();
octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed());
verticalOffset += STATS_PELS_PER_LINE;
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color);

View file

@ -8,12 +8,14 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QScriptValueIterator>
#include <limits>
#include <typeinfo>
#include <Application.h>
#include <devices/OculusManager.h>
#include <Menu.h>
#include <QScriptValueIterator>
#include <LODManager.h>
#include "BillboardOverlay.h"
#include "Circle3DOverlay.h"
@ -83,10 +85,13 @@ void Overlays::update(float deltatime) {
void Overlays::renderHUD() {
QReadLocker lock(&_lock);
auto lodManager = DependencyManager::get<LODManager>();
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(),
RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
foreach(Overlay* thisOverlay, _overlaysHUD) {
if (thisOverlay->is3D()) {
@ -116,9 +121,12 @@ void Overlays::renderWorld(bool drawFront, RenderArgs::RenderMode renderMode, Re
glm::vec3 axis(0.0f, 1.0f, 0.0f);
float myAvatarScale = 1.0f;
auto lodManager = DependencyManager::get<LODManager>();
RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(),
Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(),
renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
lodManager->getOctreeSizeScale(),
lodManager->getBoundaryLevelAdjust(),
renderMode, renderSide,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
foreach(Overlay* thisOverlay, _overlaysWorld) {

View file

@ -11,11 +11,27 @@
#include <glm/glm.hpp>
#include <Settings.h>
#include "InboundAudioStream.h"
#include "PacketHeaders.h"
const int STARVE_HISTORY_CAPACITY = 50;
namespace SettingHandles {
const SettingHandle<bool> dynamicJitterBuffers("dynamicJitterBuffers", DEFAULT_DYNAMIC_JITTER_BUFFERS);
const SettingHandle<int> maxFramesOverDesired("maxFramesOverDesired", DEFAULT_MAX_FRAMES_OVER_DESIRED);
const SettingHandle<int> staticDesiredJitterBufferFrames("staticDesiredJitterBufferFrames",
DEFAULT_STATIC_DESIRED_JITTER_BUFFER_FRAMES);
const SettingHandle<bool> useStDevForJitterCalc("useStDevForJitterCalc", DEFAULT_USE_STDEV_FOR_JITTER_CALC);
const SettingHandle<int> windowStarveThreshold("windowStarveThreshold", DEFAULT_WINDOW_STARVE_THRESHOLD);
const SettingHandle<int> windowSecondsForDesiredCalcOnTooManyStarves("windowSecondsForDesiredCalcOnTooManyStarves",
DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES);
const SettingHandle<int> windowSecondsForDesiredReduction("windowSecondsForDesiredReduction",
DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION);
const SettingHandle<bool> repetitionWithFade("repetitionWithFade", DEFAULT_REPETITION_WITH_FADE);
}
InboundAudioStream::InboundAudioStream(int numFrameSamples, int numFramesCapacity, const Settings& settings) :
_ringBuffer(numFrameSamples, false, numFramesCapacity),
_lastPopSucceeded(false),
@ -500,3 +516,28 @@ float calculateRepeatedFrameFadeFactor(int indexOfRepeat) {
}
return 0.0f;
}
void InboundAudioStream::loadSettings() {
setDynamicJitterBuffers(SettingHandles::dynamicJitterBuffers.get());
setMaxFramesOverDesired(SettingHandles::maxFramesOverDesired.get());
setStaticDesiredJitterBufferFrames(SettingHandles::staticDesiredJitterBufferFrames.get());
setUseStDevForJitterCalc(SettingHandles::useStDevForJitterCalc.get());
setWindowStarveThreshold(SettingHandles::windowStarveThreshold.get());
setWindowSecondsForDesiredCalcOnTooManyStarves(SettingHandles::windowSecondsForDesiredCalcOnTooManyStarves.get());
setWindowSecondsForDesiredReduction(SettingHandles::windowSecondsForDesiredReduction.get());
setRepetitionWithFade(SettingHandles::repetitionWithFade.get());
}
void InboundAudioStream::saveSettings() {
SettingHandles::dynamicJitterBuffers.set(getDynamicJitterBuffers());
SettingHandles::maxFramesOverDesired.set(getMaxFramesOverDesired());
SettingHandles::staticDesiredJitterBufferFrames.set(getDesiredJitterBufferFrames());
SettingHandles::useStDevForJitterCalc.set(getUseStDevForJitterCalc());
SettingHandles::windowStarveThreshold.set(getWindowStarveThreshold());
SettingHandles::windowSecondsForDesiredCalcOnTooManyStarves.set(getWindowSecondsForDesiredCalcOnTooManyStarves());
SettingHandles::windowSecondsForDesiredReduction.set(getWindowSecondsForDesiredReduction());
SettingHandles::repetitionWithFade.set(getRepetitionWithFade());
}

View file

@ -126,6 +126,8 @@ public:
void setWindowSecondsForDesiredReduction(int windowSecondsForDesiredReduction);
void setRepetitionWithFade(bool repetitionWithFade) { _repetitionWithFade = repetitionWithFade; }
void loadSettings();
void saveSettings();
virtual AudioStreamStats getAudioStreamStats() const;
@ -138,7 +140,15 @@ public:
/// returns the desired number of jitter buffer frames using Freddy's method
int getCalculatedJitterBufferFramesUsingMaxGap() const { return _calculatedJitterBufferFramesUsingMaxGap; }
int getWindowSecondsForDesiredReduction() const {
return _timeGapStatsForDesiredReduction.getWindowIntervals(); }
int getWindowSecondsForDesiredCalcOnTooManyStarves() const {
return _timeGapStatsForDesiredCalcOnTooManyStarves.getWindowIntervals(); }
bool getDynamicJitterBuffers() const { return _dynamicJitterBuffers; }
bool getRepetitionWithFade() const { return _repetitionWithFade;}
int getWindowStarveThreshold() const { return _starveThreshold;}
bool getUseStDevForJitterCalc() const { return _useStDevForJitterCalc; }
int getDesiredJitterBufferFrames() const { return _desiredJitterBufferFrames; }
int getMaxFramesOverDesired() const { return _maxFramesOverDesired; }
int getNumFrameSamples() const { return _ringBuffer.getNumFrameSamples(); }
@ -204,7 +214,7 @@ protected:
bool _lastPopSucceeded;
AudioRingBuffer::ConstIterator _lastPopOutput;
bool _dynamicJitterBuffers; // if false, _desiredJitterBufferFrames is locked at 1 (old behavior)
int _staticDesiredJitterBufferFrames;

View file

@ -14,6 +14,7 @@
#include <ByteCountCoding.h>
#include <GLMHelpers.h>
#include <Octree.h>
#include <PhysicsHelpers.h>
#include <RegisteredMetaTypes.h>
#include <SharedUtil.h> // usecTimestampNow()
@ -711,10 +712,22 @@ void EntityItem::simulateKinematicMotion(float timeElapsed) {
} else {
// NOTE: angularSpeed is currently in degrees/sec!!!
// TODO: Andrew to convert to radians/sec
float angle = timeElapsed * glm::radians(angularSpeed);
glm::vec3 axis = _angularVelocity / angularSpeed;
glm::quat dQ = glm::angleAxis(angle, axis);
glm::quat rotation = glm::normalize(dQ * getRotation());
glm::vec3 angularVelocity = glm::radians(_angularVelocity);
// for improved agreement with the way Bullet integrates rotations we use an approximation
// and break the integration into bullet-sized substeps
glm::quat rotation = getRotation();
float dt = timeElapsed;
while (dt > PHYSICS_ENGINE_FIXED_SUBSTEP) {
glm::quat dQ = computeBulletRotationStep(angularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP);
rotation = glm::normalize(dQ * rotation);
dt -= PHYSICS_ENGINE_FIXED_SUBSTEP;
}
// NOTE: this final partial substep can drift away from a real Bullet simulation however
// it only becomes significant for rapidly rotating objects
// (e.g. around PI/4 radians per substep, or 7.5 rotations/sec at 60 substeps/sec).
glm::quat dQ = computeBulletRotationStep(angularVelocity, dt);
rotation = glm::normalize(dQ * rotation);
setRotation(rotation);
}
}

View file

@ -23,6 +23,7 @@ Batch::Batch() :
_resources(),
_data(),
_buffers(),
_textures(),
_streamFormats(),
_transforms()
{
@ -38,6 +39,7 @@ void Batch::clear() {
_resources.clear();
_data.clear();
_buffers.clear();
_textures.clear();
_streamFormats.clear();
_transforms.clear();
}
@ -171,3 +173,14 @@ void Batch::setUniformBuffer(uint32 slot, const BufferView& view) {
}
void Batch::setUniformTexture(uint32 slot, const TexturePointer& texture) {
ADD_COMMAND(setUniformTexture);
_params.push_back(_textures.cache(texture));
_params.push_back(slot);
}
void Batch::setUniformTexture(uint32 slot, const TextureView& view) {
setUniformTexture(slot, view._texture);
}

View file

@ -19,6 +19,7 @@
#include <vector>
#include "Stream.h"
#include "Texture.h"
#if defined(NSIGHT_FOUND)
#include "nvToolsExt.h"
@ -92,6 +93,10 @@ public:
void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size);
void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView
void setUniformTexture(uint32 slot, const TexturePointer& view);
void setUniformTexture(uint32 slot, const TextureView& view); // not a command, just a shortcut from a TextureView
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
@ -148,10 +153,6 @@ public:
void _glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void _glMaterialf(GLenum face, GLenum pname, GLfloat param);
void _glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
enum Command {
COMMAND_draw = 0,
COMMAND_drawIndexed,
@ -167,6 +168,7 @@ public:
COMMAND_setProjectionTransform,
COMMAND_setUniformBuffer,
COMMAND_setUniformTexture,
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
@ -219,10 +221,7 @@ public:
COMMAND_glEnableVertexAttribArray,
COMMAND_glDisableVertexAttribArray,
COMMAND_glColor4f,
COMMAND_glMaterialf,
COMMAND_glMaterialfv,
COMMAND_glColor4f,
NUM_COMMANDS,
};
@ -292,6 +291,7 @@ public:
};
typedef Cache<BufferPointer>::Vector BufferCaches;
typedef Cache<TexturePointer>::Vector TextureCaches;
typedef Cache<Stream::FormatPointer>::Vector StreamFormatCaches;
typedef Cache<Transform>::Vector TransformCaches;
@ -330,6 +330,7 @@ public:
Bytes _data;
BufferCaches _buffers;
TextureCaches _textures;
StreamFormatCaches _streamFormats;
TransformCaches _transforms;

View file

@ -14,6 +14,7 @@
#include <assert.h>
#include "Resource.h"
#include "Texture.h"
namespace gpu {
@ -39,6 +40,17 @@ public:
void syncGPUObject(const Buffer& buffer);
template< typename T >
static void setGPUObject(const Texture& texture, T* to) {
texture.setGPUObject(reinterpret_cast<GPUObject*>(to));
}
template< typename T >
static T* getGPUObject(const Texture& texture) {
return reinterpret_cast<T*>(texture.getGPUObject());
}
void syncGPUObject(const Texture& texture);
protected:
};

View file

@ -93,19 +93,24 @@ static const int DIMENSION_COUNT[NUM_DIMENSIONS] = {
// Provide information on how to use the element
enum Semantic {
RAW = 0, // used as RAW memory
RGB,
RGBA,
BGRA,
XYZ,
XYZW,
POS_XYZ,
POS_XYZW,
QUAT,
DIR_XYZ,
UV,
R8,
INDEX, //used by index buffer of a mesh
PART, // used by part buffer of a mesh
DEPTH, // Depth buffer
DEPTH_STENCIL, // Depth Stencil buffer
SRGB,
SRGBA,
SBGRA,
NUM_SEMANTICS,
};
@ -124,7 +129,7 @@ public:
_dimension(SCALAR),
_type(INT8)
{}
Semantic getSemantic() const { return (Semantic)_semantic; }
Dimension getDimension() const { return (Dimension)_dimension; }
@ -135,13 +140,22 @@ public:
uint32 getSize() const { return DIMENSION_COUNT[_dimension] * TYPE_SIZE[_type]; }
protected:
uint16 getRaw() const { return *((uint16*) (this)); }
bool operator ==(const Element& right) const {
return getRaw() == right.getRaw();
}
bool operator !=(const Element& right) const {
return getRaw() != right.getRaw();
}
protected:
uint8 _semantic;
uint8 _dimension : 4;
uint8 _type : 4;
};
};

View file

@ -1,6 +1,6 @@
//
// GLBackend.cpp
// interface/src/gpu
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 10/27/2014.
// Copyright 2014 High Fidelity, Inc.
@ -8,13 +8,7 @@
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "GLBackend.h"
#include <QDebug>
#include "Batch.h"
using namespace gpu;
#include "GLBackendShared.h"
GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
{
@ -32,6 +26,7 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_setProjectionTransform),
(&::gpu::GLBackend::do_setUniformBuffer),
(&::gpu::GLBackend::do_setUniformTexture),
(&::gpu::GLBackend::do_glEnable),
(&::gpu::GLBackend::do_glDisable),
@ -82,40 +77,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] =
(&::gpu::GLBackend::do_glDisableVertexAttribArray),
(&::gpu::GLBackend::do_glColor4f),
(&::gpu::GLBackend::do_glMaterialf),
(&::gpu::GLBackend::do_glMaterialfv),
};
static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = {
GL_POINTS,
GL_LINES,
GL_LINE_STRIP,
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_QUADS,
};
static const GLenum _elementTypeToGLType[NUM_TYPES]= {
GL_FLOAT,
GL_INT,
GL_UNSIGNED_INT,
GL_HALF_FLOAT,
GL_SHORT,
GL_UNSIGNED_SHORT,
GL_BYTE,
GL_UNSIGNED_BYTE,
GL_FLOAT,
GL_INT,
GL_UNSIGNED_INT,
GL_HALF_FLOAT,
GL_SHORT,
GL_UNSIGNED_SHORT,
GL_BYTE,
GL_UNSIGNED_BYTE
};
GLBackend::GLBackend() :
_input(),
_transform()
@ -174,9 +137,6 @@ void GLBackend::checkGLError() {
}
}
//#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError()
#define CHECK_GL_ERROR()
void GLBackend::do_draw(Batch& batch, uint32 paramOffset) {
updateInput();
updateTransform();
@ -508,6 +468,18 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {
CHECK_GL_ERROR();
}
void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) {
GLuint slot = batch._params[paramOffset + 1]._uint;
TexturePointer uniformTexture = batch._textures.get(batch._params[paramOffset + 0]._uint);
GLuint to = getTextureID(uniformTexture);
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, to);
CHECK_GL_ERROR();
}
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
@ -1077,40 +1049,6 @@ void GLBackend::do_glColor4f(Batch& batch, uint32 paramOffset) {
CHECK_GL_ERROR();
}
void Batch::_glMaterialf(GLenum face, GLenum pname, GLfloat param) {
ADD_COMMAND_GL(glMaterialf);
_params.push_back(param);
_params.push_back(pname);
_params.push_back(face);
DO_IT_NOW(_glMaterialf, 3);
}
void GLBackend::do_glMaterialf(Batch& batch, uint32 paramOffset) {
glMaterialf(
batch._params[paramOffset + 2]._uint,
batch._params[paramOffset + 1]._uint,
batch._params[paramOffset + 0]._float);
CHECK_GL_ERROR();
}
void Batch::_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
ADD_COMMAND_GL(glMaterialfv);
_params.push_back(cacheData(4 * sizeof(float), params));
_params.push_back(pname);
_params.push_back(face);
DO_IT_NOW(_glMaterialfv, 3);
}
void GLBackend::do_glMaterialfv(Batch& batch, uint32 paramOffset) {
glMaterialfv(
batch._params[paramOffset + 2]._uint,
batch._params[paramOffset + 1]._uint,
(const GLfloat*)batch.editData(batch._params[paramOffset + 0]._uint));
CHECK_GL_ERROR();
}
GLBackend::GLBuffer::GLBuffer() :
_stamp(0),
_buffer(0),
@ -1156,3 +1094,4 @@ GLuint GLBackend::getBufferID(const Buffer& buffer) {
GLBackend::syncGPUObject(buffer);
return Backend::getGPUObject<GLBackend::GLBuffer>(buffer)->_buffer;
}

View file

@ -1,6 +1,6 @@
//
// GLBackend.h
// interface/src/gpu
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 10/27/2014.
// Copyright 2014 High Fidelity, Inc.
@ -34,7 +34,7 @@ public:
class GLBuffer {
public:
Stamp _stamp;
Stamp _stamp;
GLuint _buffer;
GLuint _size;
@ -42,9 +42,21 @@ public:
~GLBuffer();
};
static void syncGPUObject(const Buffer& buffer);
static GLuint getBufferID(const Buffer& buffer);
class GLTexture {
public:
Stamp _storageStamp;
Stamp _contentStamp;
GLuint _texture;
GLuint _size;
GLTexture();
~GLTexture();
};
static void syncGPUObject(const Texture& texture);
static GLuint getTextureID(const TexturePointer& texture);
static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
static const int MAX_NUM_INPUT_BUFFERS = 16;
@ -124,6 +136,7 @@ protected:
// Shader Stage
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
void do_setUniformTexture(Batch& batch, uint32 paramOffset);
void updateShader();
struct ShaderStageState {
@ -188,9 +201,6 @@ protected:
void do_glColor4f(Batch& batch, uint32 paramOffset);
void do_glMaterialf(Batch& batch, uint32 paramOffset);
void do_glMaterialfv(Batch& batch, uint32 paramOffset);
typedef void (GLBackend::*CommandCall)(Batch&, uint32);
static CommandCall _commandCalls[Batch::NUM_COMMANDS];

View file

@ -0,0 +1,53 @@
//
// GLBackendShared.h
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 1/22/2014.
// 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_gpu_GLBackend_Shared_h
#define hifi_gpu_GLBackend_Shared_h
#include "GLBackend.h"
#include <QDebug>
#include "Batch.h"
using namespace gpu;
static const GLenum _primitiveToGLmode[NUM_PRIMITIVES] = {
GL_POINTS,
GL_LINES,
GL_LINE_STRIP,
GL_TRIANGLES,
GL_TRIANGLE_STRIP,
GL_QUADS,
};
static const GLenum _elementTypeToGLType[NUM_TYPES]= {
GL_FLOAT,
GL_INT,
GL_UNSIGNED_INT,
GL_HALF_FLOAT,
GL_SHORT,
GL_UNSIGNED_SHORT,
GL_BYTE,
GL_UNSIGNED_BYTE,
GL_FLOAT,
GL_INT,
GL_UNSIGNED_INT,
GL_HALF_FLOAT,
GL_SHORT,
GL_UNSIGNED_SHORT,
GL_BYTE,
GL_UNSIGNED_BYTE
};
#define CHECK_GL_ERROR() ::gpu::GLBackend::checkGLError()
//#define CHECK_GL_ERROR()
#endif

View file

@ -0,0 +1,331 @@
//
// GLBackendTexture.cpp
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 1/19/2015.
// 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 "GLBackendShared.h"
GLBackend::GLTexture::GLTexture() :
_storageStamp(0),
_contentStamp(0),
_texture(0),
_size(0)
{}
GLBackend::GLTexture::~GLTexture() {
if (_texture != 0) {
glDeleteTextures(1, &_texture);
}
}
class GLTexelFormat {
public:
GLenum internalFormat;
GLenum format;
GLenum type;
static GLTexelFormat evalGLTexelFormat(const Element& dstFormat, const Element& srcFormat) {
if (dstFormat != srcFormat) {
GLTexelFormat texel = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
switch(dstFormat.getDimension()) {
case gpu::SCALAR: {
texel.format = GL_RED;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RED;
break;
case gpu::DEPTH:
texel.internalFormat = GL_DEPTH_COMPONENT;
break;
default:
qDebug() << "Unknown combination of texel format";
}
break;
}
case gpu::VEC2: {
texel.format = GL_RG;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RG;
break;
case gpu::DEPTH_STENCIL:
texel.internalFormat = GL_DEPTH_STENCIL;
break;
default:
qDebug() << "Unknown combination of texel format";
}
break;
}
case gpu::VEC3: {
texel.format = GL_RGB;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RGB;
break;
default:
qDebug() << "Unknown combination of texel format";
}
break;
}
case gpu::VEC4: {
texel.format = GL_RGBA;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(srcFormat.getSemantic()) {
case gpu::BGRA:
case gpu::SBGRA:
texel.format = GL_BGRA;
break;
case gpu::RGB:
case gpu::RGBA:
case gpu::SRGB:
case gpu::SRGBA:
default:
break;
};
switch(dstFormat.getSemantic()) {
case gpu::RGB:
texel.internalFormat = GL_RGB;
break;
case gpu::RGBA:
texel.internalFormat = GL_RGBA;
break;
case gpu::SRGB:
texel.internalFormat = GL_SRGB;
break;
case gpu::SRGBA:
texel.internalFormat = GL_SRGB_ALPHA;
break;
default:
qDebug() << "Unknown combination of texel format";
}
break;
}
default:
qDebug() << "Unknown combination of texel format";
}
return texel;
} else {
GLTexelFormat texel = {GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE};
switch(dstFormat.getDimension()) {
case gpu::SCALAR: {
texel.format = GL_RED;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RED;
break;
case gpu::DEPTH:
texel.internalFormat = GL_DEPTH_COMPONENT;
break;
default:
qDebug() << "Unknown combination of texel format";
}
break;
}
case gpu::VEC2: {
texel.format = GL_RG;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RG;
break;
case gpu::DEPTH_STENCIL:
texel.internalFormat = GL_DEPTH_STENCIL;
break;
default:
qDebug() << "Unknown combination of texel format";
}
break;
}
case gpu::VEC3: {
texel.format = GL_RGB;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
case gpu::RGBA:
texel.internalFormat = GL_RGB;
break;
case gpu::SRGB:
case gpu::SRGBA:
texel.internalFormat = GL_SRGB; // standard 2.2 gamma correction color
break;
default:
qDebug() << "Unknown combination of texel format";
}
break;
}
case gpu::VEC4: {
texel.format = GL_RGBA;
texel.type = _elementTypeToGLType[dstFormat.getType()];
switch(dstFormat.getSemantic()) {
case gpu::RGB:
texel.internalFormat = GL_RGB;
break;
case gpu::RGBA:
texel.internalFormat = GL_RGBA;
break;
case gpu::SRGB:
texel.internalFormat = GL_SRGB;
break;
case gpu::SRGBA:
texel.internalFormat = GL_SRGB_ALPHA; // standard 2.2 gamma correction color
break;
default:
qDebug() << "Unknown combination of texel format";
}
break;
}
default:
qDebug() << "Unknown combination of texel format";
}
return texel;
}
}
};
void GLBackend::syncGPUObject(const Texture& texture) {
GLTexture* object = Backend::getGPUObject<GLBackend::GLTexture>(texture);
// If GPU object already created and in sync
bool needUpdate = false;
if (object && (object->_storageStamp == texture.getStamp())) {
// If gpu object info is in sync with sysmem version
if (object->_contentStamp >= texture.getDataStamp()) {
// Then all good, GPU object is ready to be used
return;
} else {
// Need to update the content of the GPU object from the source sysmem of the texture
needUpdate = true;
}
} else if (!texture.isDefined()) {
// NO texture definition yet so let's avoid thinking
return;
}
// need to have a gpu object?
if (!object) {
object = new GLTexture();
glGenTextures(1, &object->_texture);
CHECK_GL_ERROR();
Backend::setGPUObject(texture, object);
}
// GO through the process of allocating the correct storage and/or update the content
switch (texture.getType()) {
case Texture::TEX_2D: {
if (needUpdate) {
if (texture.isStoredMipAvailable(0)) {
GLint boundTex = -1;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex);
Texture::PixelsPointer mip = texture.accessStoredMip(0);
const GLvoid* bytes = mip->_sysmem.read<Resource::Byte>();
Element srcFormat = mip->_format;
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
glBindTexture(GL_TEXTURE_2D, object->_texture);
glTexSubImage2D(GL_TEXTURE_2D, 0,
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
texelFormat.format, texelFormat.type, bytes);
if (texture.isAutogenerateMips()) {
glGenerateMipmap(GL_TEXTURE_2D);
}
glBindTexture(GL_TEXTURE_2D, boundTex);
object->_contentStamp = texture.getDataStamp();
}
} else {
const GLvoid* bytes = 0;
Element srcFormat = texture.getTexelFormat();
if (texture.isStoredMipAvailable(0)) {
Texture::PixelsPointer mip = texture.accessStoredMip(0);
bytes = mip->_sysmem.read<Resource::Byte>();
srcFormat = mip->_format;
object->_contentStamp = texture.getDataStamp();
}
GLint boundTex = -1;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTex);
glBindTexture(GL_TEXTURE_2D, object->_texture);
GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(texture.getTexelFormat(), srcFormat);
glTexImage2D(GL_TEXTURE_2D, 0,
texelFormat.internalFormat, texture.getWidth(), texture.getHeight(), 0,
texelFormat.format, texelFormat.type, bytes);
if (bytes && texture.isAutogenerateMips()) {
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
}
glBindTexture(GL_TEXTURE_2D, boundTex);
object->_storageStamp = texture.getStamp();
object->_size = texture.getSize();
}
break;
}
default:
qDebug() << "GLBackend::syncGPUObject(const Texture&) case for Texture Type " << texture.getType() << " not supported";
}
CHECK_GL_ERROR();
}
GLuint GLBackend::getTextureID(const TexturePointer& texture) {
if (!texture) {
return 0;
}
GLBackend::syncGPUObject(*texture);
GLTexture* object = Backend::getGPUObject<GLBackend::GLTexture>(*texture);
if (object) {
return object->_texture;
} else {
return 0;
}
}

View file

@ -1,6 +1,6 @@
//
// Resource.cpp
// interface/src/gpu
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 10/8/2014.
// Copyright 2014 High Fidelity, Inc.

View file

@ -1,6 +1,6 @@
//
// Resource.h
// interface/src/gpu
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 10/8/2014.
// Copyright 2014 High Fidelity, Inc.
@ -79,18 +79,20 @@ protected:
// Access the byte array.
// The edit version allow to map data.
inline const Byte* readData() const { return _data; }
inline Byte* editData() { _stamp++; return _data; }
const Byte* readData() const { return _data; }
Byte* editData() { _stamp++; return _data; }
template< typename T > const T* read() const { return reinterpret_cast< T* > ( _data ); }
template< typename T > T* edit() { _stamp++; return reinterpret_cast< T* > ( _data ); }
// Access the current version of the sysmem, used to compare if copies are in sync
inline Stamp getStamp() const { return _stamp; }
Stamp getStamp() const { return _stamp; }
static Size allocateMemory(Byte** memAllocated, Size size);
static void deallocateMemory(Byte* memDeallocated, Size size);
bool isAvailable() const { return (_data != 0); }
private:
Stamp _stamp;
Size _size;
@ -136,9 +138,9 @@ public:
protected:
Sysmem* _sysmem;
Sysmem* _sysmem = NULL;
mutable GPUObject* _gpuObject;
mutable GPUObject* _gpuObject = NULL;
// This shouldn't be used by anything else than the Backend class with the proper casting.
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
@ -363,64 +365,6 @@ public:
}
};
// TODO: For now TextureView works with Buffer as a place holder for the Texture.
// The overall logic should be about the same except that the Texture will be a real GL Texture under the hood
class TextureView {
public:
typedef Resource::Size Size;
typedef int Index;
BufferPointer _buffer;
Size _offset;
Size _size;
Element _element;
uint16 _stride;
TextureView() :
_buffer(NULL),
_offset(0),
_size(0),
_element(gpu::VEC3, gpu::UINT8, gpu::RGB),
_stride(1)
{};
TextureView(const Element& element) :
_buffer(NULL),
_offset(0),
_size(0),
_element(element),
_stride(uint16(element.getSize()))
{};
// create the BufferView and own the Buffer
TextureView(Buffer* newBuffer, const Element& element) :
_buffer(newBuffer),
_offset(0),
_size(newBuffer->getSize()),
_element(element),
_stride(uint16(element.getSize()))
{};
TextureView(const BufferPointer& buffer, const Element& element) :
_buffer(buffer),
_offset(0),
_size(buffer->getSize()),
_element(element),
_stride(uint16(element.getSize()))
{};
TextureView(const BufferPointer& buffer, Size offset, Size size, const Element& element) :
_buffer(buffer),
_offset(offset),
_size(size),
_element(element),
_stride(uint16(element.getSize()))
{};
~TextureView() {}
TextureView(const TextureView& view) = default;
TextureView& operator=(const TextureView& view) = default;
};
};
#endif

327
libraries/gpu/src/gpu/Texture.cpp Executable file
View file

@ -0,0 +1,327 @@
//
// Texture.cpp
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 1/17/2015.
// 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 "Texture.h"
#include <math.h>
#include <QDebug>
using namespace gpu;
Texture::Pixels::Pixels(const Element& format, Size size, const Byte* bytes) :
_sysmem(size, bytes),
_format(format) {
}
Texture::Pixels::~Pixels() {
}
void Texture::Storage::assignTexture(Texture* texture) {
_texture = texture;
}
Stamp Texture::Storage::getStamp(uint16 level) const {
PixelsPointer mip = getMip(level);
if (mip) {
return mip->_sysmem.getStamp();
}
return 0;
}
void Texture::Storage::reset() {
_mips.clear();
}
Texture::PixelsPointer Texture::Storage::editMip(uint16 level) {
if (level < _mips.size()) {
return _mips[level];
}
return PixelsPointer();
}
const Texture::PixelsPointer Texture::Storage::getMip(uint16 level) const {
if (level < _mips.size()) {
return _mips[level];
}
return PixelsPointer();
}
bool Texture::Storage::isMipAvailable(uint16 level) const {
PixelsPointer mip = getMip(level);
return (mip && mip->_sysmem.getSize());
}
bool Texture::Storage::allocateMip(uint16 level) {
bool changed = false;
if (level >= _mips.size()) {
_mips.resize(level+1, PixelsPointer());
changed = true;
}
if (!_mips[level]) {
_mips[level] = PixelsPointer(new Pixels());
changed = true;
}
return changed;
}
bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes) {
// Ok we should be able to do that...
allocateMip(level);
_mips[level]->_format = format;
Size allocated = _mips[level]->_sysmem.setData(size, bytes);
return allocated == size;
}
Texture* Texture::create1D(const Element& texelFormat, uint16 width) {
return create(TEX_1D, texelFormat, width, 1, 1, 1, 1);
}
Texture* Texture::create2D(const Element& texelFormat, uint16 width, uint16 height) {
return create(TEX_2D, texelFormat, width, height, 1, 1, 1);
}
Texture* Texture::create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth) {
return create(TEX_3D, texelFormat, width, height, depth, 1, 1);
}
Texture* Texture::createCube(const Element& texelFormat, uint16 width) {
return create(TEX_CUBE, texelFormat, width, width, 1, 1, 1);
}
Texture* Texture::create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices)
{
Texture* tex = new Texture();
tex->_storage.reset(new Storage());
tex->_storage->_texture = tex;
tex->_type = type;
tex->_maxMip = 0;
tex->resize(type, texelFormat, width, height, depth, numSamples, numSlices);
return tex;
}
Texture* Texture::createFromStorage(Storage* storage) {
Texture* tex = new Texture();
tex->_storage.reset(storage);
storage->assignTexture(tex);
return tex;
}
Texture::Texture():
Resource(),
_storage(),
_stamp(0),
_size(0),
_width(1),
_height(1),
_depth(1),
_numSamples(1),
_numSlices(1),
_maxMip(0),
_type(TEX_1D),
_autoGenerateMips(false),
_defined(false)
{
}
Texture::~Texture()
{
}
Texture::Size Texture::resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices) {
if (width && height && depth && numSamples && numSlices) {
bool changed = false;
if ( _type != type) {
_type = type;
changed = true;
}
if (_numSlices != numSlices) {
_numSlices = numSlices;
changed = true;
}
numSamples = evalNumSamplesUsed(numSamples);
if ((_type >= TEX_2D) && (_numSamples != numSamples)) {
_numSamples = numSamples;
changed = true;
}
if (_width != width) {
_width = width;
changed = true;
}
if ((_type >= TEX_2D) && (_height != height)) {
_height = height;
changed = true;
}
if ((_type >= TEX_3D) && (_depth != depth)) {
_depth = depth;
changed = true;
}
// Evaluate the new size with the new format
const int DIM_SIZE[] = {1, 1, 1, 6};
int size = DIM_SIZE[_type] *_width * _height * _depth * _numSamples * texelFormat.getSize();
// If size change then we need to reset
if (changed || (size != getSize())) {
_size = size;
_storage->reset();
_stamp++;
}
// TexelFormat might have change, but it's mostly interpretation
if (texelFormat != _texelFormat) {
_texelFormat = texelFormat;
_stamp++;
}
// Here the Texture has been fully defined from the gpu point of view (size and format)
_defined = true;
} else {
_stamp++;
}
return _size;
}
Texture::Size Texture::resize1D(uint16 width, uint16 numSamples) {
return resize(TEX_1D, getTexelFormat(), width, 1, 1, numSamples, 1);
}
Texture::Size Texture::resize2D(uint16 width, uint16 height, uint16 numSamples) {
return resize(TEX_2D, getTexelFormat(), width, height, 1, numSamples, 1);
}
Texture::Size Texture::resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples) {
return resize(TEX_3D, getTexelFormat(), width, height, depth, numSamples, 1);
}
Texture::Size Texture::resizeCube(uint16 width, uint16 numSamples) {
return resize(TEX_CUBE, getTexelFormat(), width, 1, 1, numSamples, 1);
}
Texture::Size Texture::reformat(const Element& texelFormat) {
return resize(_type, texelFormat, getWidth(), getHeight(), getDepth(), getNumSamples(), getNumSlices());
}
bool Texture::isColorRenderTarget() const {
return (_texelFormat.getSemantic() == gpu::RGBA);
}
bool Texture::isDepthStencilRenderTarget() const {
return (_texelFormat.getSemantic() == gpu::DEPTH) || (_texelFormat.getSemantic() == gpu::DEPTH_STENCIL);
}
uint16 Texture::evalDimNumMips(uint16 size) {
double largerDim = size;
double val = log(largerDim)/log(2.0);
return 1 + (uint16) val;
}
// The number mips that the texture could have if all existed
// = log2(max(width, height, depth))
uint16 Texture::evalNumMips() const {
double largerDim = std::max(std::max(_width, _height), _depth);
double val = log(largerDim)/log(2.0);
return 1 + (uint16) val;
}
uint16 Texture::maxMip() const {
return _maxMip;
}
bool Texture::assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes) {
// Check that level accessed make sense
if (level != 0) {
if (_autoGenerateMips) {
return false;
}
if (level >= evalNumMips()) {
return false;
}
}
// THen check that the mem buffer passed make sense with its format
if (size == evalStoredMipSize(level, format)) {
_storage->assignMipData(level, format, size, bytes);
_stamp++;
return true;
}
return false;
}
uint16 Texture::autoGenerateMips(uint16 maxMip) {
_autoGenerateMips = true;
_maxMip = std::min((uint16) (evalNumMips() - 1), maxMip);
_stamp++;
return _maxMip;
}
uint16 Texture::getStoredMipWidth(uint16 level) const {
PixelsPointer mip = accessStoredMip(level);
if (mip && mip->_sysmem.getSize()) {
return evalMipWidth(level);
}
return 0;
}
uint16 Texture::getStoredMipHeight(uint16 level) const {
PixelsPointer mip = accessStoredMip(level);
if (mip && mip->_sysmem.getSize()) {
return evalMipHeight(level);
}
return 0;
}
uint16 Texture::getStoredMipDepth(uint16 level) const {
PixelsPointer mip = accessStoredMip(level);
if (mip && mip->_sysmem.getSize()) {
return evalMipDepth(level);
}
return 0;
}
uint32 Texture::getStoredMipNumTexels(uint16 level) const {
PixelsPointer mip = accessStoredMip(level);
if (mip && mip->_sysmem.getSize()) {
return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level);
}
return 0;
}
uint32 Texture::getStoredMipSize(uint16 level) const {
PixelsPointer mip = accessStoredMip(level);
if (mip && mip->_sysmem.getSize()) {
return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level) * getTexelFormat().getSize();
}
return 0;
}
uint16 Texture::evalNumSamplesUsed(uint16 numSamplesTried) {
uint16 sample = numSamplesTried;
if (numSamplesTried <= 1)
sample = 1;
else if (numSamplesTried < 4)
sample = 2;
else if (numSamplesTried < 8)
sample = 4;
else if (numSamplesTried < 16)
sample = 8;
else
sample = 8;
return sample;
}

255
libraries/gpu/src/gpu/Texture.h Executable file
View file

@ -0,0 +1,255 @@
//
// Texture.h
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 1/16/2015.
// 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_gpu_Texture_h
#define hifi_gpu_Texture_h
#include "Resource.h"
#include <memory>
namespace gpu {
class Texture : public Resource {
public:
class Pixels {
public:
Pixels() {}
Pixels(const Pixels& pixels) = default;
Pixels(const Element& format, Size size, const Byte* bytes);
~Pixels();
Sysmem _sysmem;
Element _format;
};
typedef QSharedPointer< Pixels > PixelsPointer;
class Storage {
public:
Storage() {}
virtual ~Storage() {}
virtual void reset();
virtual PixelsPointer editMip(uint16 level);
virtual const PixelsPointer getMip(uint16 level) const;
virtual Stamp getStamp(uint16 level) const;
virtual bool allocateMip(uint16 level);
virtual bool assignMipData(uint16 level, const Element& format, Size size, const Byte* bytes);
virtual bool isMipAvailable(uint16 level) const;
protected:
Texture* _texture;
std::vector<PixelsPointer> _mips;
virtual void assignTexture(Texture* tex);
friend class Texture;
};
enum Type {
TEX_1D = 0,
TEX_2D,
TEX_3D,
TEX_CUBE,
};
static Texture* create1D(const Element& texelFormat, uint16 width);
static Texture* create2D(const Element& texelFormat, uint16 width, uint16 height);
static Texture* create3D(const Element& texelFormat, uint16 width, uint16 height, uint16 depth);
static Texture* createCube(const Element& texelFormat, uint16 width);
static Texture* createFromStorage(Storage* storage);
Texture(const Texture& buf); // deep copy of the sysmem texture
Texture& operator=(const Texture& buf); // deep copy of the sysmem texture
~Texture();
const Stamp getStamp() const { return _stamp; }
const Stamp getDataStamp(uint16 level = 0) const { return _storage->getStamp(level); }
// The size in bytes of data stored in the texture
Size getSize() const { return _size; }
// Resize, unless auto mips mode would destroy all the sub mips
Size resize1D(uint16 width, uint16 numSamples);
Size resize2D(uint16 width, uint16 height, uint16 numSamples);
Size resize3D(uint16 width, uint16 height, uint16 depth, uint16 numSamples);
Size resizeCube(uint16 width, uint16 numSamples);
// Reformat, unless auto mips mode would destroy all the sub mips
Size reformat(const Element& texelFormat);
// Size and format
Type getType() const { return _type; }
bool isColorRenderTarget() const;
bool isDepthStencilRenderTarget() const;
const Element& getTexelFormat() const { return _texelFormat; }
bool hasBorder() const { return false; }
uint16 getWidth() const { return _width; }
uint16 getHeight() const { return _height; }
uint16 getDepth() const { return _depth; }
uint32 getRowPitch() const { return getWidth() * getTexelFormat().getSize(); }
uint32 getNumTexels() const { return _width * _height * _depth; }
uint16 getNumSlices() const { return _numSlices; }
uint16 getNumSamples() const { return _numSamples; }
// NumSamples can only have certain values based on the hw
static uint16 evalNumSamplesUsed(uint16 numSamplesTried);
// Mips size evaluation
// The number mips that a dimension could haves
// = 1 + log2(size)
static uint16 evalDimNumMips(uint16 size);
// The number mips that the texture could have if all existed
// = 1 + log2(max(width, height, depth))
uint16 evalNumMips() const;
// Eval the size that the mips level SHOULD have
// not the one stored in the Texture
uint16 evalMipWidth(uint16 level) const { return std::max(_width >> level, 1); }
uint16 evalMipHeight(uint16 level) const { return std::max(_height >> level, 1); }
uint16 evalMipDepth(uint16 level) const { return std::max(_depth >> level, 1); }
uint32 evalMipNumTexels(uint16 level) const { return evalMipWidth(level) * evalMipHeight(level) * evalMipDepth(level); }
uint32 evalMipSize(uint16 level) const { return evalMipNumTexels(level) * getTexelFormat().getSize(); }
uint32 evalStoredMipSize(uint16 level, const Element& format) const { return evalMipNumTexels(level) * format.getSize(); }
uint32 evalTotalSize() const {
uint32 size = 0;
uint16 minMipLevel = 0;
uint16 maxMipLevel = maxMip();
for (uint16 l = minMipLevel; l <= maxMipLevel; l++) {
size += evalMipSize(l);
}
return size * getNumSlices();
}
// max mip is in the range [ 1 if no sub mips, log2(max(width, height, depth))]
// if autoGenerateMip is on => will provide the maxMIp level specified
// else provide the deepest mip level provided through assignMip
uint16 maxMip() const;
// Generate the mips automatically
// But the sysmem version is not available
// Only works for the standard formats
// Specify the maximum Mip level available
// 0 is the default one
// 1 is the first level
// ...
// nbMips - 1 is the last mip level
//
// If -1 then all the mips are generated
//
// Return the totalnumber of mips that will be available
uint16 autoGenerateMips(uint16 maxMip);
bool isAutogenerateMips() const { return _autoGenerateMips; }
// Managing Storage and mips
// Manually allocate the mips down until the specified maxMip
// this is just allocating the sysmem version of it
// in case autoGen is on, this doesn't allocate
// Explicitely assign mip data for a certain level
// If Bytes is NULL then simply allocate the space so mip sysmem can be accessed
bool assignStoredMip(uint16 level, const Element& format, Size size, const Byte* bytes);
// Access the the sub mips
bool isStoredMipAvailable(uint16 level) const { return _storage->isMipAvailable(level); }
const PixelsPointer accessStoredMip(uint16 level) const { return _storage->getMip(level); }
// access sizes for the stored mips
uint16 getStoredMipWidth(uint16 level) const;
uint16 getStoredMipHeight(uint16 level) const;
uint16 getStoredMipDepth(uint16 level) const;
uint32 getStoredMipNumTexels(uint16 level) const;
uint32 getStoredMipSize(uint16 level) const;
bool isDefined() const { return _defined; }
protected:
std::unique_ptr< Storage > _storage;
Stamp _stamp;
uint32 _size;
Element _texelFormat;
uint16 _width;
uint16 _height;
uint16 _depth;
uint16 _numSamples;
uint16 _numSlices;
uint16 _maxMip;
Type _type;
bool _autoGenerateMips;
bool _defined;
static Texture* create(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices);
Texture();
Size resize(Type type, const Element& texelFormat, uint16 width, uint16 height, uint16 depth, uint16 numSamples, uint16 numSlices);
mutable GPUObject* _gpuObject = NULL;
// This shouldn't be used by anything else than the Backend class with the proper casting.
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;
};
typedef QSharedPointer<Texture> TexturePointer;
typedef std::vector< TexturePointer > Textures;
// TODO: For now TextureView works with Buffer as a place holder for the Texture.
// The overall logic should be about the same except that the Texture will be a real GL Texture under the hood
class TextureView {
public:
typedef Resource::Size Size;
TexturePointer _texture = TexturePointer(NULL);
uint16 _subresource = 0;
Element _element = Element(gpu::VEC4, gpu::UINT8, gpu::RGBA);
TextureView() {};
TextureView(const Element& element) :
_element(element)
{};
// create the TextureView and own the Texture
TextureView(Texture* newTexture, const Element& element) :
_texture(newTexture),
_subresource(0),
_element(element)
{};
TextureView(const TexturePointer& texture, const Element& element) :
_texture(texture),
_subresource(0),
_element(element)
{};
~TextureView() {}
TextureView(const TextureView& view) = default;
TextureView& operator=(const TextureView& view) = default;
};
};
#endif

View file

@ -19,11 +19,11 @@
#include <QMetaType>
#include <QPushButton>
#include <QScriptEngine>
#include <QSettings>
#include <QVBoxLayout>
#include <QtDebug>
#include <GLMHelpers.h>
#include <Settings.h>
#include "MetavoxelUtil.h"
#include "ScriptCache.h"
@ -485,6 +485,10 @@ void QColorEditor::selectColor() {
}
}
namespace SettingHandles {
const SettingHandle<QStringList> editorURLs("editorURLs");
}
QUrlEditor::QUrlEditor(QWidget* parent) :
QComboBox(parent) {
@ -492,7 +496,7 @@ QUrlEditor::QUrlEditor(QWidget* parent) :
setInsertPolicy(InsertAtTop);
// populate initial URL list from settings
addItems(QSettings().value("editorURLs").toStringList());
addItems(SettingHandles::editorURLs.get());
connect(this, SIGNAL(activated(const QString&)), SLOT(updateURL(const QString&)));
connect(model(), SIGNAL(rowsInserted(const QModelIndex&,int,int)), SLOT(updateSettings()));
@ -512,7 +516,7 @@ void QUrlEditor::updateSettings() {
for (int i = 0, size = qMin(MAX_STORED_URLS, count()); i < size; i++) {
urls.append(itemText(i));
}
QSettings().setValue("editorURLs", urls);
SettingHandles::editorURLs.set(urls);
}
BaseVec3Editor::BaseVec3Editor(QWidget* parent) : QWidget(parent) {

View file

@ -17,12 +17,12 @@
#include <QItemEditorFactory>
#include <QMessageBox>
#include <QPushButton>
#include <QSettings>
#include <QThread>
#include <glm/gtx/transform.hpp>
#include <GeometryUtil.h>
#include <Settings.h>
#include "MetavoxelData.h"
#include "Spanner.h"
@ -58,6 +58,10 @@ static QItemEditorCreatorBase* heightfieldColorEditorCreator = createHeightfield
const float DEFAULT_PLACEMENT_GRANULARITY = 0.01f;
const float DEFAULT_VOXELIZATION_GRANULARITY = powf(2.0f, -3.0f);
namespace SettingHandles {
const SettingHandle<QString> heightfieldDir("heightDir", QString());
}
Spanner::Spanner() :
_renderer(NULL),
_placementGranularity(DEFAULT_PLACEMENT_GRANULARITY),
@ -610,13 +614,13 @@ static int getHeightfieldSize(int size) {
}
void HeightfieldHeightEditor::select() {
QSettings settings;
QString result = QFileDialog::getOpenFileName(this, "Select Height Image", settings.value("heightDir").toString(),
"Images (*.png *.jpg *.bmp *.raw *.mdr)");
QString result = QFileDialog::getOpenFileName(this, "Select Height Image",
SettingHandles::heightfieldDir.get(),
"Images (*.png *.jpg *.bmp *.raw *.mdr)");
if (result.isNull()) {
return;
}
settings.setValue("heightDir", QFileInfo(result).path());
SettingHandles::heightfieldDir.set(QFileInfo(result).path());
const quint16 CONVERSION_OFFSET = 1;
QString lowerResult = result.toLower();
bool isMDR = lowerResult.endsWith(".mdr");
@ -880,13 +884,13 @@ void HeightfieldColorEditor::setColor(const HeightfieldColorPointer& color) {
}
void HeightfieldColorEditor::select() {
QSettings settings;
QString result = QFileDialog::getOpenFileName(this, "Select Color Image", settings.value("heightDir").toString(),
QString result = QFileDialog::getOpenFileName(this, "Select Color Image",
SettingHandles::heightfieldDir.get(),
"Images (*.png *.jpg *.bmp)");
if (result.isNull()) {
return;
}
settings.setValue("heightDir", QFileInfo(result).path());
SettingHandles::heightfieldDir.get(QFileInfo(result).path());
QImage image;
if (!image.load(result)) {
QMessageBox::warning(this, "Invalid Image", "The selected image could not be read.");

View file

@ -17,6 +17,7 @@
#include <glm/glm.hpp>
#include "gpu/Resource.h"
#include "gpu/Texture.h"
namespace model {
typedef gpu::BufferView UniformBufferView;

View file

@ -21,6 +21,8 @@
#include <QtNetwork/QNetworkRequest>
#include <qthread.h>
#include <Settings.h>
#include "NodeList.h"
#include "PacketHeaders.h"
#include "RSAKeypairGenerator.h"
@ -88,11 +90,9 @@ void AccountManager::logout() {
connect(&_accountInfo, &DataServerAccountInfo::balanceChanged, this, &AccountManager::accountInfoBalanceChanged);
if (_shouldPersistToSettingsFile) {
QSettings settings;
settings.beginGroup(ACCOUNTS_GROUP);
QString keyURLString(_authURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE));
settings.remove(keyURLString);
QStringList path = QStringList() << ACCOUNTS_GROUP << keyURLString;
SettingHandles::SettingHandle<DataServerAccountInfo>(path).remove();
qDebug() << "Removed account info for" << _authURL << "from in-memory accounts and .ini file";
} else {
@ -127,13 +127,13 @@ void AccountManager::setAuthURL(const QUrl& authURL) {
if (_shouldPersistToSettingsFile) {
// check if there are existing access tokens to load from settings
QSettings settings;
Settings settings;
settings.beginGroup(ACCOUNTS_GROUP);
foreach(const QString& key, settings.allKeys()) {
// take a key copy to perform the double slash replacement
QString keyCopy(key);
QUrl keyURL(keyCopy.replace("slashslash", "//"));
QUrl keyURL(keyCopy.replace(DOUBLE_SLASH_SUBSTITUTE, "//"));
if (keyURL == _authURL) {
// pull out the stored access token and store it in memory
@ -337,10 +337,9 @@ void AccountManager::passErrorToCallback(QNetworkReply* requestReply) {
void AccountManager::persistAccountToSettings() {
if (_shouldPersistToSettingsFile) {
// store this access token into the local settings
QSettings localSettings;
localSettings.beginGroup(ACCOUNTS_GROUP);
localSettings.setValue(_authURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE),
QVariant::fromValue(_accountInfo));
QString keyURLString(_authURL.toString().replace("//", DOUBLE_SLASH_SUBSTITUTE));
QStringList path = QStringList() << ACCOUNTS_GROUP << keyURLString;
SettingHandles::SettingHandle<QVariant>(path).set(QVariant::fromValue(_accountInfo));
}
}

View file

@ -9,25 +9,36 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <qdebug.h>
#include <qjsondocument.h>
#include <qregexp.h>
#include <qstringlist.h>
#include <QApplication>
#include <QClipboard>
#include <QDebug>
#include <QJsonDocument>
#include <QRegExp>
#include <QStringList>
#include <GLMHelpers.h>
#include <Settings.h>
#include <UUID.h>
#include "NodeList.h"
#include "AddressManager.h"
const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager";
const QString SETTINGS_CURRENT_ADDRESS_KEY = "address";
namespace SettingHandles {
const SettingHandle<QUrl> currentAddress(QStringList() << ADDRESS_MANAGER_SETTINGS_GROUP
<< "address",
QUrl());
}
AddressManager::AddressManager() :
_rootPlaceName(),
_rootPlaceID(),
_positionGetter(NULL),
_orientationGetter(NULL)
{
connect(qApp, &QCoreApplication::aboutToQuit, this, &AddressManager::storeCurrentAddress);
}
bool AddressManager::isConnected() {
@ -44,25 +55,16 @@ const QUrl AddressManager::currentAddress() const {
return hifiURL;
}
const QString ADDRESS_MANAGER_SETTINGS_GROUP = "AddressManager";
const QString SETTINGS_CURRENT_ADDRESS_KEY = "address";
void AddressManager::loadSettings(const QString& lookupString) {
if (lookupString.isEmpty()) {
QSettings settings;
settings.beginGroup(ADDRESS_MANAGER_SETTINGS_GROUP);
handleLookupString(settings.value(SETTINGS_CURRENT_ADDRESS_KEY).toString());
handleLookupString(SettingHandles::currentAddress.get().toString());
} else {
handleLookupString(lookupString);
}
}
void AddressManager::storeCurrentAddress() {
QSettings settings;
settings.beginGroup(ADDRESS_MANAGER_SETTINGS_GROUP);
settings.setValue(SETTINGS_CURRENT_ADDRESS_KEY, currentAddress());
settings.endGroup();
SettingHandles::currentAddress.set(currentAddress());
}
const QString AddressManager::currentPath(bool withOrientation) const {
@ -430,3 +432,11 @@ void AddressManager::goToUser(const QString& username) {
QNetworkAccessManager::GetOperation,
apiCallbackParameters());
}
void AddressManager::copyAddress() {
QApplication::clipboard()->setText(currentAddress().toString());
}
void AddressManager::copyPath() {
QApplication::clipboard()->setText(currentPath());
}

View file

@ -61,6 +61,9 @@ public slots:
void storeCurrentAddress();
void copyAddress();
void copyPath();
signals:
void lookupResultsFinished();
void lookupResultIsOffline();

View file

@ -23,7 +23,6 @@
#include <QtCore/QElapsedTimer>
#include <QtCore/QMutex>
#include <QtCore/QSet>
#include <QtCore/QSettings>
#include <QtCore/QSharedPointer>
#include <QtNetwork/QHostAddress>
#include <QtNetwork/QUdpSocket>

View file

@ -9,9 +9,9 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QtCore/QSettings>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QSettings>
#include <QString>
#include <QStringList>
#include <QDebug>
#include <PacketHeaders.h>
@ -209,9 +209,9 @@ JurisdictionMap::Area JurisdictionMap::isMyJurisdiction(const unsigned char* nod
bool JurisdictionMap::readFromFile(const char* filename) {
QString settingsFile(filename);
QSettings settings(settingsFile, QSettings::IniFormat);
QString rootCode = settings.value("root","00").toString();
QString settingsFile(filename);
QSettings settings(settingsFile, QSettings::IniFormat);
QString rootCode = settings.value("root","00").toString();
qDebug() << "rootCode=" << rootCode;
_rootOctalCode = hexStringToOctalCode(rootCode);

View file

@ -9,36 +9,29 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <PacketHeaders.h>
//#include <SharedUtil.h>
#include <GLMHelpers.h>
#include <PacketHeaders.h>
#include <Settings.h>
#include "OctreeConstants.h"
#include "OctreeQuery.h"
OctreeQuery::OctreeQuery() :
NodeData(),
_cameraPosition(0,0,0),
_cameraOrientation(),
_cameraFov(0.0f),
_cameraAspectRatio(0.0f),
_cameraNearClip(0.0f),
_cameraFarClip(0.0f),
_wantColor(true),
_wantDelta(true),
_wantLowResMoving(true),
_wantOcclusionCulling(false), // disabled by default
_wantCompression(false), // disabled by default
_maxOctreePPS(DEFAULT_MAX_OCTREE_PPS),
_octreeElementSizeScale(DEFAULT_OCTREE_SIZE_SCALE)
{
namespace SettingHandles {
const SettingHandle<int> maxOctreePacketsPerSecond("maxOctreePPS", DEFAULT_MAX_OCTREE_PPS);
}
OctreeQuery::~OctreeQuery() {
// nothing to do
OctreeQuery::OctreeQuery() {
_maxOctreePPS = SettingHandles::maxOctreePacketsPerSecond.get();
}
void OctreeQuery::setMaxOctreePacketsPerSecond(int maxOctreePPS) {
if (maxOctreePPS != _maxOctreePPS) {
_maxOctreePPS = maxOctreePPS;
SettingHandles::maxOctreePacketsPerSecond.set(_maxOctreePPS);
}
}
int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
unsigned char* bufferStart = destinationBuffer;

View file

@ -45,7 +45,7 @@ class OctreeQuery : public NodeData {
public:
OctreeQuery();
virtual ~OctreeQuery();
virtual ~OctreeQuery() {}
int getBroadcastData(unsigned char* destinationBuffer);
int parseData(const QByteArray& packet);
@ -86,29 +86,29 @@ public slots:
void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; }
void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; }
void setWantCompression(bool wantCompression) { _wantCompression = wantCompression; }
void setMaxOctreePacketsPerSecond(int maxOctreePPS) { _maxOctreePPS = maxOctreePPS; }
void setMaxOctreePacketsPerSecond(int maxOctreePPS);
void setOctreeSizeScale(float octreeSizeScale) { _octreeElementSizeScale = octreeSizeScale; }
void setBoundaryLevelAdjust(int boundaryLevelAdjust) { _boundaryLevelAdjust = boundaryLevelAdjust; }
protected:
// camera details for the avatar
glm::vec3 _cameraPosition;
glm::quat _cameraOrientation;
float _cameraFov;
float _cameraAspectRatio;
float _cameraNearClip;
float _cameraFarClip;
glm::vec3 _cameraEyeOffsetPosition;
glm::vec3 _cameraPosition = glm::vec3(0.0f);
glm::quat _cameraOrientation = glm::quat();
float _cameraFov = 0.0f;
float _cameraAspectRatio = 0.0f;
float _cameraNearClip = 0.0f;
float _cameraFarClip = 0.0f;
glm::vec3 _cameraEyeOffsetPosition = glm::vec3(0.0f);
// octree server sending items
bool _wantColor;
bool _wantDelta;
bool _wantLowResMoving;
bool _wantOcclusionCulling;
bool _wantCompression;
int _maxOctreePPS;
float _octreeElementSizeScale; /// used for LOD calculations
int _boundaryLevelAdjust; /// used for LOD calculations
bool _wantColor = true;
bool _wantDelta = true;
bool _wantLowResMoving = true;
bool _wantOcclusionCulling = false;
bool _wantCompression = false;
int _maxOctreePPS = DEFAULT_MAX_OCTREE_PPS;
float _octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE; /// used for LOD calculations
int _boundaryLevelAdjust = 0; /// used for LOD calculations
private:
// privatize the copy constructor and assignment operator so they cannot be called

View file

@ -17,6 +17,8 @@
#include <QtCore/QDebug>
#include <Settings.h>
#include "GeometryUtil.h"
#include "SharedUtil.h"
#include "ViewFrustum.h"
@ -24,38 +26,34 @@
using namespace std;
ViewFrustum::ViewFrustum() :
_position(0,0,0),
_positionVoxelScale(0,0,0),
_orientation(),
_direction(IDENTITY_FRONT),
_up(IDENTITY_UP),
_right(IDENTITY_RIGHT),
_orthographic(false),
_width(1.0f),
_height(1.0f),
_fieldOfView(0.0),
_aspectRatio(1.0f),
_nearClip(DEFAULT_NEAR_CLIP),
_farClip(DEFAULT_FAR_CLIP),
_focalLength(0.25f),
_keyholeRadius(DEFAULT_KEYHOLE_RADIUS),
_farTopLeft(0,0,0),
_farTopRight(0,0,0),
_farBottomLeft(0,0,0),
_farBottomRight(0,0,0),
_nearTopLeft(0,0,0),
_nearTopRight(0,0,0),
_nearBottomLeft(0,0,0),
_nearBottomRight(0,0,0)
{
namespace SettingHandles {
const SettingHandle<float> fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES);
const SettingHandle<float> realWorldFieldOfView("realWorldFieldOfView", DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES);
}
ViewFrustum::ViewFrustum() {
_fieldOfView = SettingHandles::fieldOfView.get();
_realWorldFieldOfView = SettingHandles::realWorldFieldOfView.get();
}
void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) {
_orientation = orientationAsQuaternion;
_right = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_RIGHT, 0.0f));
_up = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_UP, 0.0f));
_direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f));
_right = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_RIGHT, 0.0f));
_up = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_UP, 0.0f));
_direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f));
}
void ViewFrustum::setFieldOfView(float f) {
if (f != _fieldOfView) {
_fieldOfView = f;
SettingHandles::fieldOfView.set(f);
}
}
void ViewFrustum::setRealWorldFieldOfView(float realWorldFieldOfView) {
if (realWorldFieldOfView != _realWorldFieldOfView) {
_realWorldFieldOfView = realWorldFieldOfView;
SettingHandles::realWorldFieldOfView.set(realWorldFieldOfView);
}
}
// ViewFrustum::calculateViewFrustum()

View file

@ -34,6 +34,8 @@ const float DEFAULT_FAR_CLIP = TREE_SCALE;
class ViewFrustum {
public:
ViewFrustum();
// setters for camera attributes
void setPosition(const glm::vec3& p) { _position = p; _positionVoxelScale = (p / (float)TREE_SCALE); }
void setOrientation(const glm::quat& orientationAsQuaternion);
@ -50,7 +52,8 @@ public:
void setOrthographic(bool orthographic) { _orthographic = orthographic; }
void setWidth(float width) { _width = width; }
void setHeight(float height) { _height = height; }
void setFieldOfView(float f) { _fieldOfView = f; }
void setFieldOfView(float f);
void setRealWorldFieldOfView(float realWorldFieldOfView);
void setAspectRatio(float a) { _aspectRatio = a; }
void setNearClip(float n) { _nearClip = n; }
void setFarClip(float f) { _farClip = f; }
@ -63,6 +66,7 @@ public:
float getWidth() const { return _width; }
float getHeight() const { return _height; }
float getFieldOfView() const { return _fieldOfView; }
float getRealWorldFieldOfView() const { return _realWorldFieldOfView; }
float getAspectRatio() const { return _aspectRatio; }
float getNearClip() const { return _nearClip; }
float getFarClip() const { return _farClip; }
@ -91,8 +95,6 @@ public:
void calculate();
ViewFrustum();
typedef enum {OUTSIDE, INTERSECT, INSIDE} location;
ViewFrustum::location pointInFrustum(const glm::vec3& point) const;
@ -132,47 +134,52 @@ private:
ViewFrustum::location boxInKeyhole(const AABox& box) const;
void calculateOrthographic();
// camera location/orientation attributes
glm::vec3 _position; // the position in TREE_SCALE
glm::vec3 _positionVoxelScale; // the position in voxel scale
glm::quat _orientation;
glm::vec3 _position = glm::vec3(0.0f); // the position in TREE_SCALE
glm::vec3 _positionVoxelScale = glm::vec3(0.0f); // the position in voxel scale
glm::quat _orientation = glm::quat();
// calculated for orientation
glm::vec3 _direction;
glm::vec3 _up;
glm::vec3 _right;
glm::vec3 _direction = IDENTITY_FRONT;
glm::vec3 _up = IDENTITY_UP;
glm::vec3 _right = IDENTITY_RIGHT;
// Lens attributes
bool _orthographic;
float _width;
float _height;
float _fieldOfView; // degrees
float _aspectRatio;
float _nearClip;
float _farClip;
float _focalLength;
glm::vec3 _eyeOffsetPosition;
glm::quat _eyeOffsetOrientation;
bool _orthographic = false;
float _width = 1.0f;
float _height = 1.0f;
float _aspectRatio = 1.0f;
float _nearClip = DEFAULT_NEAR_CLIP;
float _farClip = DEFAULT_FAR_CLIP;
float _focalLength = 0.25f;
glm::vec3 _eyeOffsetPosition = glm::vec3(0.0f);
glm::quat _eyeOffsetOrientation = glm::quat();
// in Degrees, doesn't apply to HMD like Oculus
float _fieldOfView = DEFAULT_FIELD_OF_VIEW_DEGREES;
// The actual FOV set by the user's monitor size and view distance
float _realWorldFieldOfView = DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES;
// keyhole attributes
float _keyholeRadius;
float _keyholeRadius = DEFAULT_KEYHOLE_RADIUS;
AACube _keyholeBoundingCube;
// Calculated values
glm::vec3 _offsetPosition;
glm::vec3 _offsetDirection;
glm::vec3 _offsetUp;
glm::vec3 _offsetRight;
glm::vec3 _farTopLeft;
glm::vec3 _farTopRight;
glm::vec3 _farBottomLeft;
glm::vec3 _farBottomRight;
glm::vec3 _nearTopLeft;
glm::vec3 _nearTopRight;
glm::vec3 _nearBottomLeft;
glm::vec3 _nearBottomRight;
glm::vec3 _offsetPosition = glm::vec3(0.0f);
glm::vec3 _offsetDirection = glm::vec3(0.0f);
glm::vec3 _offsetUp = glm::vec3(0.0f);
glm::vec3 _offsetRight = glm::vec3(0.0f);
glm::vec3 _farTopLeft = glm::vec3(0.0f);
glm::vec3 _farTopRight = glm::vec3(0.0f);
glm::vec3 _farBottomLeft = glm::vec3(0.0f);
glm::vec3 _farBottomRight = glm::vec3(0.0f);
glm::vec3 _nearTopLeft = glm::vec3(0.0f);
glm::vec3 _nearTopRight = glm::vec3(0.0f);
glm::vec3 _nearBottomLeft = glm::vec3(0.0f);
glm::vec3 _nearBottomRight = glm::vec3(0.0f);
enum { TOP_PLANE = 0, BOTTOM_PLANE, LEFT_PLANE, RIGHT_PLANE, NEAR_PLANE, FAR_PLANE };
::Plane _planes[6]; // How will this be used?

View file

@ -15,6 +15,7 @@
#include "BulletUtil.h"
#include "EntityMotionState.h"
#include "PhysicsEngine.h"
#include "PhysicsHelpers.h"
QSet<EntityItem*>* _outgoingEntityList;

View file

@ -14,6 +14,7 @@
#include "BulletUtil.h"
#include "ObjectMotionState.h"
#include "PhysicsEngine.h"
#include "PhysicsHelpers.h"
const float DEFAULT_FRICTION = 0.5f;
const float MAX_FRICTION = 10.0f;
@ -107,6 +108,7 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) {
if (_sentFrame == 0) {
_sentPosition = bulletToGLM(_body->getWorldTransform().getOrigin());
_sentVelocity = bulletToGLM(_body->getLinearVelocity());
_sentRotation = bulletToGLM(_body->getWorldTransform().getRotation());
_sentAngularVelocity = bulletToGLM(_body->getAngularVelocity());
_sentFrame = simulationFrame;
return false;
@ -118,7 +120,8 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) {
glm::vec3 wasAngularVelocity = _sentAngularVelocity;
#endif
float dt = (float)(simulationFrame - _sentFrame) * PHYSICS_ENGINE_FIXED_SUBSTEP;
int numFrames = simulationFrame - _sentFrame;
float dt = (float)(numFrames) * PHYSICS_ENGINE_FIXED_SUBSTEP;
_sentFrame = simulationFrame;
bool isActive = _body->isActive();
@ -170,16 +173,16 @@ bool ObjectMotionState::shouldSendUpdate(uint32_t simulationFrame) {
if (glm::length2(_sentAngularVelocity) > 0.0f) {
// compute rotation error
_sentAngularVelocity *= powf(1.0f - _angularDamping, dt);
float spin = glm::length(_sentAngularVelocity);
const float MIN_SPIN = 1.0e-4f;
if (spin > MIN_SPIN) {
glm::vec3 axis = _sentAngularVelocity / spin;
_sentRotation = glm::normalize(glm::angleAxis(dt * spin, axis) * _sentRotation);
float attenuation = powf(1.0f - _angularDamping, dt);
_sentAngularVelocity *= attenuation;
// Bullet caps the effective rotation velocity inside its rotation integration step, therefore
// we must integrate with the same algorithm and timestep in order achieve similar results.
for (int i = 0; i < numFrames; ++i) {
_sentRotation = glm::normalize(computeBulletRotationStep(_sentAngularVelocity, PHYSICS_ENGINE_FIXED_SUBSTEP) * _sentRotation);
}
}
const float MIN_ROTATION_DOT = 0.98f;
const float MIN_ROTATION_DOT = 0.99f; // 0.99 dot threshold coresponds to about 16 degrees of slop
glm::quat actualRotation = bulletToGLM(worldTrans.getRotation());
#ifdef WANT_DEBUG

View file

@ -11,6 +11,7 @@
#include "PhysicsEngine.h"
#include "ShapeInfoUtil.h"
#include "PhysicsHelpers.h"
#include "ThreadSafeDynamicsWorld.h"
static uint32_t _numSubsteps;
@ -29,23 +30,27 @@ PhysicsEngine::~PhysicsEngine() {
// begin EntitySimulation overrides
void PhysicsEngine::updateEntitiesInternal(const quint64& now) {
// NOTE: the grand order of operations is:
// (1) relay incoming changes
// (2) step simulation
// (3) synchronize outgoing motion states
// (4) send outgoing packets
// this is step (4)
QSet<ObjectMotionState*>::iterator stateItr = _outgoingPackets.begin();
while (stateItr != _outgoingPackets.end()) {
ObjectMotionState* state = *stateItr;
if (state->doesNotNeedToSendUpdate()) {
stateItr = _outgoingPackets.erase(stateItr);
} else if (state->shouldSendUpdate(_numSubsteps)) {
state->sendUpdate(_entityPacketSender, _numSubsteps);
++stateItr;
} else {
++stateItr;
// no need to send updates unless the physics simulation has actually stepped
if (_lastNumSubstepsAtUpdateInternal != _numSubsteps) {
_lastNumSubstepsAtUpdateInternal = _numSubsteps;
// NOTE: the grand order of operations is:
// (1) relay incoming changes
// (2) step simulation
// (3) synchronize outgoing motion states
// (4) send outgoing packets
// this is step (4)
QSet<ObjectMotionState*>::iterator stateItr = _outgoingPackets.begin();
while (stateItr != _outgoingPackets.end()) {
ObjectMotionState* state = *stateItr;
if (state->doesNotNeedToSendUpdate()) {
stateItr = _outgoingPackets.erase(stateItr);
} else if (state->shouldSendUpdate(_numSubsteps)) {
state->sendUpdate(_entityPacketSender, _numSubsteps);
++stateItr;
} else {
++stateItr;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show more