Ejemplo n.º 1
0
void setupPreferences() {
    auto preferences = DependencyManager::get<Preferences>();
    auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
    static const QString AVATAR_BASICS { "Avatar Basics" };
    {
        auto getter = [myAvatar]()->QString { return myAvatar->getDisplayName(); };
        auto setter = [myAvatar](const QString& value) { myAvatar->setDisplayName(value); };
        auto preference = new EditPreference(AVATAR_BASICS, "Avatar display name (optional)", getter, setter);
        preference->setPlaceholderText("Not showing a name");
        preferences->addPreference(preference);
    }

    {
        auto getter = [myAvatar]()->QString { return myAvatar->getCollisionSoundURL(); };
        auto setter = [myAvatar](const QString& value) { myAvatar->setCollisionSoundURL(value); };
        auto preference = new EditPreference(AVATAR_BASICS, "Avatar collision sound URL (optional)", getter, setter);
        preference->setPlaceholderText("Enter the URL of a sound to play when you bump into something");
        preferences->addPreference(preference);
    }

    {
        auto getter = [myAvatar]()->QString { return myAvatar->getFullAvatarURLFromPreferences().toString(); };
        auto setter = [myAvatar](const QString& value) { myAvatar->useFullAvatarURL(value, ""); qApp->clearAvatarOverrideUrl(); };
        auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance", getter, setter);
        preferences->addPreference(preference);
    }

    // Graphics quality
    static const QString GRAPHICS_QUALITY { "Graphics Quality" };
    {
        auto getter = []()->float {
            return DependencyManager::get<LODManager>()->getWorldDetailQuality();
        };

        auto setter = [](float value) {
            DependencyManager::get<LODManager>()->setWorldDetailQuality(value);
        };

        auto wodSlider = new SliderPreference(GRAPHICS_QUALITY, "World Detail", getter, setter);
        wodSlider->setMin(0.25f);
        wodSlider->setMax(0.75f);
        wodSlider->setStep(0.25f);
        preferences->addPreference(wodSlider);

        auto getterShadow = []()->bool {
            auto menu = Menu::getInstance();
            return menu->isOptionChecked(MenuOption::Shadows);
        };
        auto setterShadow = [](bool value) {
            auto menu = Menu::getInstance();
            menu->setIsOptionChecked(MenuOption::Shadows, value);
        };
        preferences->addPreference(new CheckPreference(GRAPHICS_QUALITY, "Show Shadows", getterShadow, setterShadow));
    }

    // UI
    static const QString UI_CATEGORY { "User Interface" };
    {
        auto getter = []()->bool { return qApp->getSettingConstrainToolbarPosition(); };
        auto setter = [](bool value) { qApp->setSettingConstrainToolbarPosition(value); };
        preferences->addPreference(new CheckPreference(UI_CATEGORY, "Constrain Toolbar Position to Horizontal Center", getter, setter));
    }

    {
        auto getter = []()->float { return qApp->getDesktopTabletScale(); };
        auto setter = [](float value) { qApp->setDesktopTabletScale(value); };
        auto preference = new SpinnerPreference(UI_CATEGORY, "Desktop Tablet Scale %", getter, setter);
        preference->setMin(20);
        preference->setMax(500);
        preferences->addPreference(preference);
    }

    {
        auto getter = []()->float { return qApp->getHMDTabletScale(); };
        auto setter = [](float value) { qApp->setHMDTabletScale(value); };
        auto preference = new SpinnerPreference(UI_CATEGORY, "VR Tablet Scale %", getter, setter);
        preference->setMin(20);
        preference->setMax(500);
        preferences->addPreference(preference);
    }

    {
        static const QString RETICLE_ICON_NAME = { Cursor::Manager::getIconName(Cursor::Icon::RETICLE) };
        auto getter = []()->bool { return qApp->getPreferredCursor() == RETICLE_ICON_NAME; };
        auto setter = [](bool value) { qApp->setPreferredCursor(value ? RETICLE_ICON_NAME : QString()); };
        preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter));
    }

    {
        auto getter = []()->bool { return qApp->getMiniTabletEnabled(); };
        auto setter = [](bool value) { qApp->setMiniTabletEnabled(value); };
        preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use mini tablet", getter, setter));
    }

    {
        auto getter = []()->int { return DependencyManager::get<Keyboard>()->getUse3DKeyboard(); };
        auto setter = [](int value) { DependencyManager::get<Keyboard>()->setUse3DKeyboard(value); };
        preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use Virtual Keyboard", getter, setter));
    }

    {
        auto getter = []()->bool { return DependencyManager::get<Keyboard>()->getPreferMalletsOverLasers() ? 1 : 0; };
        auto setter = [](bool value) { return DependencyManager::get<Keyboard>()->setPreferMalletsOverLasers((bool)value); };
        auto preference = new RadioButtonsPreference(UI_CATEGORY, "Keyboard laser / mallets", getter, setter);
        QStringList items;
        items << "Lasers" << "Mallets";
        preference->setItems(items);
        preference->setIndented(true);
        preferences->addPreference(preference);
    }


    {
        auto getter = []()->int { return qApp->getPreferStylusOverLaser() ? 1 : 0; };
        auto setter = [](int value) { qApp->setPreferStylusOverLaser((bool)value); };
        auto preference = new RadioButtonsPreference(UI_CATEGORY, "Tablet stylys / laser", getter, setter);
        QStringList items;
        items << "Lasers" << "Stylus";
        preference->setHeading("Tablet Input Mechanism");
        preference->setItems(items);
        preferences->addPreference(preference);
    }

    static const QString VIEW_CATEGORY{ "View" };
    {
        auto getter = [myAvatar]()->float { return myAvatar->getRealWorldFieldOfView(); };
        auto setter = [myAvatar](float value) { myAvatar->setRealWorldFieldOfView(value); };
        auto preference = new SpinnerPreference(VIEW_CATEGORY, "Real world vertical field of view (angular size of monitor)", getter, setter);
        preference->setMin(1);
        preference->setMax(180);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return qApp->getFieldOfView(); };
        auto setter = [](float value) { qApp->setFieldOfView(value); };
        auto preference = new SpinnerPreference(VIEW_CATEGORY, "Vertical field of view", getter, setter);
        preference->setMin(1);
        preference->setMax(180);
        preference->setStep(1);
        preferences->addPreference(preference);
    }

    /*
    // FIXME: Remove setting completely or make available through JavaScript API?
    {
        auto getter = []()->bool { return qApp->getPreferAvatarFingerOverStylus(); };
        auto setter = [](bool value) { qApp->setPreferAvatarFingerOverStylus(value); };
        preferences->addPreference(new CheckPreference(UI_CATEGORY, "Prefer Avatar Finger Over Stylus", getter, setter));
        }*/

    // Snapshots
    static const QString SNAPSHOTS { "Snapshots" };
    {
        auto getter = []()->QString { return DependencyManager::get<Snapshot>()->_snapshotsLocation.get(); };
        auto setter = [](const QString& value) { DependencyManager::get<Snapshot>()->_snapshotsLocation.set(value); emit DependencyManager::get<Snapshot>()->snapshotLocationSet(value); };
        auto preference = new BrowsePreference(SNAPSHOTS, "Put my snapshots here", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return SnapshotAnimated::snapshotAnimatedDuration.get(); };
        auto setter = [](float value) { SnapshotAnimated::snapshotAnimatedDuration.set(value); };
        auto preference = new SpinnerPreference(SNAPSHOTS, "Animated Snapshot Duration", getter, setter);
        preference->setMin(1);
        preference->setMax(5);
        preference->setStep(1);
        preferences->addPreference(preference);
    }

    {
        auto getter = []()->bool { return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); };
        auto setter = [](bool value) { Menu::getInstance()->setIsOptionChecked(MenuOption::DisableActivityLogger, !value); };
        preferences->addPreference(new CheckPreference("Privacy", "Send data - High Fidelity uses information provided by your "
                                "client to improve the product through the logging of errors, tracking of usage patterns, "
                                "installation and system details, and crash events. By allowing High Fidelity to collect "
                                "this information you are helping to improve the product. ", getter, setter));
    }
    
    static const QString AVATAR_TUNING { "Avatar Tuning" };
    {
        auto getter = [myAvatar]()->QString { return myAvatar->getDominantHand(); };
        auto setter = [myAvatar](const QString& value) { myAvatar->setDominantHand(value); };
        preferences->addPreference(new PrimaryHandPreference(AVATAR_TUNING, "Dominant Hand", getter, setter));
    }
    {
        auto getter = [myAvatar]()->float { return myAvatar->getTargetScale(); };
        auto setter = [myAvatar](float value) { myAvatar->setTargetScale(value); };
        auto preference = new SpinnerSliderPreference(AVATAR_TUNING, "Avatar Scale", getter, setter);
        preference->setMin(0.25);
        preference->setMax(4);
        preference->setStep(0.05f);
        preference->setDecimals(2);
        preferences->addPreference(preference);
        
        // When the Interface is first loaded, this section setupPreferences(); is loaded - 
        // causing the myAvatar->getDomainMinScale() and myAvatar->getDomainMaxScale() to get set to incorrect values
        // which can't be changed across domain switches. Having these values loaded up when you load the Dialog each time
        // is a way around this, therefore they're not specified here but in the QML.
    }

    {
        auto getter = [myAvatar]()->QString { return myAvatar->getAnimGraphOverrideUrl().toString(); };
        auto setter = [myAvatar](const QString& value) { myAvatar->setAnimGraphOverrideUrl(QUrl(value)); };
        auto preference = new EditPreference(AVATAR_TUNING, "Avatar animation JSON", getter, setter);
        preference->setPlaceholderText("default");
        preferences->addPreference(preference);
    }

    {
        auto getter = [myAvatar]()->bool { return myAvatar->getCollisionsEnabled(); };
        auto setter = [myAvatar](bool value) { myAvatar->setCollisionsEnabled(value); };
        auto preference = new CheckPreference(AVATAR_TUNING, "Enable Avatar collisions", getter, setter);
        preferences->addPreference(preference);
    }

    static const QString FACE_TRACKING{ "Face Tracking" };
    {
        auto getter = []()->float { return DependencyManager::get<DdeFaceTracker>()->getEyeClosingThreshold(); };
        auto setter = [](float value) { DependencyManager::get<DdeFaceTracker>()->setEyeClosingThreshold(value); };
        preferences->addPreference(new SliderPreference(FACE_TRACKING, "Eye Closing Threshold", getter, setter));
    }
    {
        auto getter = []()->float { return FaceTracker::getEyeDeflection(); };
        auto setter = [](float value) { FaceTracker::setEyeDeflection(value); };
        preferences->addPreference(new SliderPreference(FACE_TRACKING, "Eye Deflection", getter, setter));
    }

    static const QString VR_MOVEMENT{ "VR Movement" };
    {
        auto getter = [myAvatar]()->bool { return myAvatar->getAllowTeleporting(); };
        auto setter = [myAvatar](bool value) { myAvatar->setAllowTeleporting(value); };
        auto preference = new CheckPreference(VR_MOVEMENT, "Teleporting", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = [myAvatar]()->bool { return myAvatar->useAdvancedMovementControls(); };
        auto setter = [myAvatar](bool value) { myAvatar->setUseAdvancedMovementControls(value); };
        auto preference = new CheckPreference(VR_MOVEMENT, "Walking", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = [myAvatar]()->bool { return myAvatar->getFlyingHMDPref(); };
        auto setter = [myAvatar](bool value) { myAvatar->setFlyingHMDPref(value); };
        auto preference = new CheckPreference(VR_MOVEMENT, "Jumping and flying", getter, setter);
        preference->setIndented(true);
        preferences->addPreference(preference);
    }
    {
        auto getter = [myAvatar]()->int { return myAvatar->getSnapTurn() ? 0 : 1; };
        auto setter = [myAvatar](int value) { myAvatar->setSnapTurn(value == 0); };
        auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Snap turn / Smooth turn", getter, setter);
        QStringList items;
        items << "Snap turn" << "Smooth turn";
        preference->setHeading("Rotation mode");
        preference->setItems(items);
        preferences->addPreference(preference);
    }
    {
        auto getter = [myAvatar]()->bool { return myAvatar->getShowPlayArea(); };
        auto setter = [myAvatar](bool value) { myAvatar->setShowPlayArea(value); };
        auto preference = new CheckPreference(VR_MOVEMENT, "Show room boundaries while teleporting", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = [myAvatar]()->int {
            switch (myAvatar->getUserRecenterModel()) {
                case MyAvatar::SitStandModelType::Auto:
                    default:
                    return 0;
                case MyAvatar::SitStandModelType::ForceSit:
                    return 1;
                case MyAvatar::SitStandModelType::ForceStand:
                    return 2;
                case MyAvatar::SitStandModelType::DisableHMDLean:
                    return 3;
            }
        };
        auto setter = [myAvatar](int value) {
            switch (value) {
                case 0:
                default:
                    myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::Auto);
                    break;
                case 1:
                    myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::ForceSit);
                    break;
                case 2:
                    myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::ForceStand);
                    break;
                case 3:
                    myAvatar->setUserRecenterModel(MyAvatar::SitStandModelType::DisableHMDLean);
                    break;
            }
        };
        auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Auto / Force Sit / Force Stand / Disable Recenter", getter, setter);
        QStringList items;
        items << "Auto - turns on avatar leaning when standing in real world" << "Seated - disables all avatar leaning while sitting in real world" << "Standing - enables avatar leaning while sitting in real world" << "Disabled - allows avatar sitting on the floor [Experimental]";
        preference->setHeading("Avatar leaning behavior");
        preference->setItems(items);
        preferences->addPreference(preference);
    }
    {
        auto getter = [=]()->float { return myAvatar->getUserHeight(); };
        auto setter = [=](float value) { myAvatar->setUserHeight(value); };
        auto preference = new SpinnerPreference(VR_MOVEMENT, "User real-world height (meters)", getter, setter);
        preference->setMin(1.0f);
        preference->setMax(2.2f);
        preference->setDecimals(3);
        preference->setStep(0.001f);
        preferences->addPreference(preference);
    }

    static const QString AVATAR_CAMERA{ "Mouse Sensitivity" };
    {
        auto getter = [myAvatar]()->float { return myAvatar->getPitchSpeed(); };
        auto setter = [myAvatar](float value) { myAvatar->setPitchSpeed(value); };
        auto preference = new SpinnerSliderPreference(AVATAR_CAMERA, "Y input:", getter, setter);
        preference->setMin(1.0f);
        preference->setMax(360.0f);
        preference->setStep(1);
        preference->setDecimals(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = [myAvatar]()->float { return myAvatar->getYawSpeed(); };
        auto setter = [myAvatar](float value) { myAvatar->setYawSpeed(value); };
        auto preference = new SpinnerSliderPreference(AVATAR_CAMERA, "X input:", getter, setter);
        preference->setMin(1.0f);
        preference->setMax(360.0f);
        preference->setStep(1);
        preference->setDecimals(1);
        preferences->addPreference(preference);
    }

    static const QString AUDIO_BUFFERS("Audio Buffers");
    {
        auto getter = []()->bool { return !DependencyManager::get<AudioClient>()->getReceivedAudioStream().dynamicJitterBufferEnabled(); };
        auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setDynamicJitterBufferEnabled(!value); };
        auto preference = new CheckPreference(AUDIO_BUFFERS, "Disable dynamic jitter buffer", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getStaticJitterBufferFrames(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setStaticJitterBufferFrames(value); };
        auto preference = new SpinnerPreference(AUDIO_BUFFERS, "Static jitter buffer frames", getter, setter);
        preference->setMin(0);
        preference->setMax(2000);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->bool { return !DependencyManager::get<AudioClient>()->getOutputStarveDetectionEnabled(); };
        auto setter = [](bool value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionEnabled(!value); };
        auto preference = new CheckPreference(AUDIO_BUFFERS, "Disable output starve detection", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputBufferSize(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputBufferSize(value); };
        auto preference = new SpinnerPreference(AUDIO_BUFFERS, "Output buffer initial frames", getter, setter);
        preference->setMin(AudioClient::MIN_BUFFER_FRAMES);
        preference->setMax(AudioClient::MAX_BUFFER_FRAMES);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
#if DEV_BUILD || PR_BUILD
    {
        auto getter = []()->bool { return DependencyManager::get<AudioClient>()->isSimulatingJitter(); };
        auto setter = [](bool value) { return DependencyManager::get<AudioClient>()->setIsSimulatingJitter(value); };
        auto preference = new CheckPreference(AUDIO_BUFFERS, "Packet jitter simulator", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getGateThreshold(); };
        auto setter = [](float value) { return DependencyManager::get<AudioClient>()->setGateThreshold(value); };
        auto preference = new SpinnerPreference(AUDIO_BUFFERS, "Packet throttle threshold", getter, setter);
        preference->setMin(1);
        preference->setMax(200);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
#endif

    {
        static const QString NETWORKING("Networking");

        QWeakPointer<NodeList> nodeListWeak = DependencyManager::get<NodeList>();
        {
            static const int MIN_PORT_NUMBER { 0 };
            static const int MAX_PORT_NUMBER { 65535 };
            auto getter = [nodeListWeak] {
                auto nodeList = nodeListWeak.lock();
                if (nodeList) {
                    return static_cast<int>(nodeList->getSocketLocalPort());
                } else {
                    return -1;
                }
            };
            auto setter = [nodeListWeak](int preset) {
                auto nodeList = nodeListWeak.lock();
                if (nodeList) {
                    nodeList->setSocketLocalPort(static_cast<quint16>(preset));
                }
            };
            auto preference = new IntSpinnerPreference(NETWORKING, "Listening Port", getter, setter);
            preference->setMin(MIN_PORT_NUMBER);
            preference->setMax(MAX_PORT_NUMBER);
            preferences->addPreference(preference);
        }

        {
            auto getter = []()->float { return qApp->getMaxOctreePacketsPerSecond(); };
            auto setter = [](float value) { qApp->setMaxOctreePacketsPerSecond(value); };
            auto preference = new SpinnerPreference(NETWORKING, "Max entities packets sent each second", getter, setter);
            preference->setMin(60);
            preference->setMax(6000);
            preference->setStep(10);
            preferences->addPreference(preference);
        }

    }
}
Ejemplo n.º 2
0
void setupPreferences() {
    auto preferences = DependencyManager::get<Preferences>();

    MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
    static const QString AVATAR_BASICS { "Avatar Basics" };
    {
        auto getter = [=]()->QString { return myAvatar->getDisplayName(); };
        auto setter = [=](const QString& value) { myAvatar->setDisplayName(value); };
        auto preference = new EditPreference(AVATAR_BASICS, "Avatar display name (optional)", getter, setter);
        preference->setPlaceholderText("Not showing a name");
        preferences->addPreference(preference);
    }

    {
        auto getter = [=]()->QString { return myAvatar->getCollisionSoundURL(); };
        auto setter = [=](const QString& value) { myAvatar->setCollisionSoundURL(value); };
        auto preference = new EditPreference(AVATAR_BASICS, "Avatar collision sound URL (optional)", getter, setter);
        preference->setPlaceholderText("Enter the URL of a sound to play when you bump into something");
        preferences->addPreference(preference);
    }

    {
        auto getter = [=]()->QString { return myAvatar->getFullAvatarURLFromPreferences().toString(); };
        auto setter = [=](const QString& value) { myAvatar->useFullAvatarURL(value, ""); };
        auto preference = new AvatarPreference(AVATAR_BASICS, "Appearance", getter, setter);
        preferences->addPreference(preference);
    }

    {
        auto getter = [=]()->bool { return myAvatar->getSnapTurn(); };
        auto setter = [=](bool value) { myAvatar->setSnapTurn(value); };
        preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Snap turn when in HMD", getter, setter));
    }
    {
        auto getter = [=]()->bool { return myAvatar->getClearOverlayWhenMoving(); };
        auto setter = [=](bool value) { myAvatar->setClearOverlayWhenMoving(value); };
        preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Clear overlays when moving", getter, setter));
    }

    // Snapshots
    static const QString SNAPSHOTS { "Snapshots" };
    {
        auto getter = []()->QString { return Snapshot::snapshotsLocation.get(); };
        auto setter = [](const QString& value) { Snapshot::snapshotsLocation.set(value); };
        auto preference = new BrowsePreference(SNAPSHOTS, "Put my snapshots here", getter, setter);
        preferences->addPreference(preference);
    }

    // Scripts
    {
        auto getter = []()->QString { return DependencyManager::get<ScriptEngines>()->getScriptsLocation(); };
        auto setter = [](const QString& value) { DependencyManager::get<ScriptEngines>()->setScriptsLocation(value); };
        preferences->addPreference(new BrowsePreference("Scripts", "Load scripts from this directory", getter, setter));
    }

    preferences->addPreference(new ButtonPreference("Scripts", "Load Default Scripts", [] {
        DependencyManager::get<ScriptEngines>()->loadDefaultScripts();
    }));

    {
        auto getter = []()->bool { return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); };
        auto setter = [](bool value) { Menu::getInstance()->setIsOptionChecked(MenuOption::DisableActivityLogger, !value); };
        preferences->addPreference(new CheckPreference("Privacy", "Send data", getter, setter));
    }
    
    static const QString LOD_TUNING("Level of Detail Tuning");
    {
        auto getter = []()->float { return DependencyManager::get<LODManager>()->getDesktopLODDecreaseFPS(); };
        auto setter = [](float value) { DependencyManager::get<LODManager>()->setDesktopLODDecreaseFPS(value); };
        auto preference = new SpinnerPreference(LOD_TUNING, "Minimum desktop FPS", getter, setter);
        preference->setMin(0);
        preference->setMax(120);
        preference->setStep(1);
        preferences->addPreference(preference);
    }

    {
        auto getter = []()->float { return DependencyManager::get<LODManager>()->getHMDLODDecreaseFPS(); };
        auto setter = [](float value) { DependencyManager::get<LODManager>()->setHMDLODDecreaseFPS(value); };
        auto preference = new SpinnerPreference(LOD_TUNING, "Minimum HMD FPS", getter, setter);
        preference->setMin(0);
        preference->setMax(120);
        preference->setStep(1);
        preferences->addPreference(preference);
    }

    static const QString AVATAR_TUNING { "Avatar Tuning" };
    {
        auto getter = [=]()->float { return myAvatar->getRealWorldFieldOfView(); };
        auto setter = [=](float value) { myAvatar->setRealWorldFieldOfView(value); };
        auto preference = new SpinnerPreference(AVATAR_TUNING, "Real world vertical field of view (angular size of monitor)", getter, setter);
        preference->setMin(1);
        preference->setMax(180);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return qApp->getFieldOfView(); };
        auto setter = [](float value) { qApp->setFieldOfView(value); };
        auto preference = new SpinnerPreference(AVATAR_TUNING, "Vertical field of view", getter, setter);
        preference->setMin(1);
        preference->setMax(180);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = [=]()->float { return myAvatar->getUniformScale(); };
        auto setter = [=](float value) { myAvatar->setTargetScaleVerbose(value); }; // The hell?
        auto preference = new SpinnerPreference(AVATAR_TUNING, "Avatar scale (default is 1.0)", getter, setter);
        preference->setMin(0.01f);
        preference->setMax(99.9f);
        preference->setDecimals(2);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<DdeFaceTracker>()->getEyeClosingThreshold(); };
        auto setter = [](float value) { DependencyManager::get<DdeFaceTracker>()->setEyeClosingThreshold(value); };
        preferences->addPreference(new SliderPreference(AVATAR_TUNING, "Camera binary eyelid threshold", getter, setter));
    }
    {
        auto getter = []()->float { return FaceTracker::getEyeDeflection(); };
        auto setter = [](float value) { FaceTracker::setEyeDeflection(value); };
        preferences->addPreference(new SliderPreference(AVATAR_TUNING, "Face tracker eye deflection", getter, setter));
    }
    {
        auto getter = []()->QString { return DependencyManager::get<Faceshift>()->getHostname(); };
        auto setter = [](const QString& value) { DependencyManager::get<Faceshift>()->setHostname(value); };
        auto preference = new EditPreference(AVATAR_TUNING, "Faceshift hostname", getter, setter);
        preference->setPlaceholderText("localhost");
        preferences->addPreference(preference);
    }
    {
        auto getter = [=]()->QString { return myAvatar->getAnimGraphOverrideUrl().toString(); };
        auto setter = [=](const QString& value) { myAvatar->setAnimGraphOverrideUrl(QUrl(value)); };
        auto preference = new EditPreference(AVATAR_TUNING, "Avatar animation JSON", getter, setter);
        preference->setPlaceholderText("default");
        preferences->addPreference(preference);
    }

    static const QString AVATAR_CAMERA { "Avatar Camera" };
    {
        auto getter = [=]()->float { return myAvatar->getPitchSpeed(); };
        auto setter = [=](float value) { myAvatar->setPitchSpeed(value); };
        auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera pitch speed (degrees/second)", getter, setter);
        preference->setMin(1.0f);
        preference->setMax(360.0f);
        preferences->addPreference(preference);
    }
    {
        auto getter = [=]()->float { return myAvatar->getYawSpeed(); };
        auto setter = [=](float value) { myAvatar->setYawSpeed(value); };
        auto preference = new SpinnerPreference(AVATAR_CAMERA, "Camera yaw speed (degrees/second)", getter, setter);
        preference->setMin(1.0f);
        preference->setMax(360.0f);
        preferences->addPreference(preference);
    }

    static const QString AUDIO("Audio");
    {
        auto getter = []()->bool { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getDynamicJitterBuffers(); };
        auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setDynamicJitterBuffers(value); };
        preferences->addPreference(new CheckPreference(AUDIO, "Enable dynamic jitter buffers", getter, setter));
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getDesiredJitterBufferFrames(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setStaticDesiredJitterBufferFrames(value); };
        
        auto preference = new SpinnerPreference(AUDIO, "Static jitter buffer frames", getter, setter);
        preference->setMin(0);
        preference->setMax(10000);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getMaxFramesOverDesired(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setMaxFramesOverDesired(value); };
        auto preference = new SpinnerPreference(AUDIO, "Max frames over desired", getter, setter);
        preference->setMax(10000);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->bool { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getUseStDevForJitterCalc(); };
        auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setUseStDevForJitterCalc(value); };
        preferences->addPreference(new CheckPreference(AUDIO, "Use standard deviation for dynamic jitter calc", getter, setter));
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowStarveThreshold(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowStarveThreshold(value); };
        auto preference = new SpinnerPreference(AUDIO, "Window A starve threshold", getter, setter);
        preference->setMax(10000);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowSecondsForDesiredCalcOnTooManyStarves(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowSecondsForDesiredCalcOnTooManyStarves(value); };
        auto preference = new SpinnerPreference(AUDIO, "Window A (raise desired on N starves) seconds", getter, setter);
        preference->setMax(10000);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getWindowSecondsForDesiredReduction(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setWindowSecondsForDesiredReduction(value); };
        auto preference = new SpinnerPreference(AUDIO, "Window B (desired ceiling) seconds", getter, setter);
        preference->setMax(10000);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->bool { return DependencyManager::get<AudioClient>()->getReceivedAudioStream().getRepetitionWithFade(); };
        auto setter = [](bool value) { DependencyManager::get<AudioClient>()->getReceivedAudioStream().setRepetitionWithFade(value); };
        preferences->addPreference(new CheckPreference(AUDIO, "Repetition with fade", getter, setter));
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputBufferSize(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputBufferSize(value); };
        auto preference = new SpinnerPreference(AUDIO, "Output buffer initial size (frames)", getter, setter);
        preference->setMin(1);
        preference->setMax(20);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->bool { return DependencyManager::get<AudioClient>()->getOutputStarveDetectionEnabled(); };
        auto setter = [](bool value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionEnabled(value); };
        auto preference = new CheckPreference(AUDIO, "Output starve detection (automatic buffer size increase)", getter, setter);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputStarveDetectionThreshold(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionThreshold(value); };
        auto preference = new SpinnerPreference(AUDIO, "Output starve detection threshold", getter, setter);
        preference->setMin(1);
        preference->setMax(500);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getOutputStarveDetectionPeriod(); };
        auto setter = [](float value) { DependencyManager::get<AudioClient>()->setOutputStarveDetectionPeriod(value); };
        auto preference = new SpinnerPreference(AUDIO, "Output starve detection period (ms)", getter, setter);
        preference->setMin(1);
        preference->setMax((float)999999999);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
#if DEV_BUILD || PR_BUILD
    {
        auto getter = []()->float { return DependencyManager::get<AudioClient>()->getGateThreshold(); };
        auto setter = [](float value) { return DependencyManager::get<AudioClient>()->setGateThreshold(value); };
        auto preference = new SpinnerPreference(AUDIO, "Debug gate threshold", getter, setter);
        preference->setMin(1);
        preference->setMax((float)100);
        preference->setStep(1);
        preferences->addPreference(preference);
    }
#endif

    {
        auto getter = []()->float { return qApp->getMaxOctreePacketsPerSecond(); };
        auto setter = [](float value) { qApp->setMaxOctreePacketsPerSecond(value); };
        auto preference = new SpinnerPreference("Octree", "Max packets sent each second", getter, setter);
        preference->setMin(60);
        preference->setMax(6000);
        preference->setStep(10);
        preferences->addPreference(preference);
    }


    {
        auto getter = []()->float { return qApp->getApplicationCompositor().getHmdUIAngularSize(); };
        auto setter = [](float value) { qApp->getApplicationCompositor().setHmdUIAngularSize(value); };
        auto preference = new SpinnerPreference("HMD", "UI horizontal angular size (degrees)", getter, setter);
        preference->setMin(30);
        preference->setMax(160);
        preference->setStep(1);
        preferences->addPreference(preference);
    }


    {
        auto getter = []()->float { return controller::InputDevice::getReticleMoveSpeed(); };
        auto setter = [](float value) { controller::InputDevice::setReticleMoveSpeed(value); };
        auto preference = new SpinnerPreference("Sixense Controllers", "Reticle movement speed", getter, setter);
        preference->setMin(0);
        preference->setMax(100);
        preference->setStep(1);
        preferences->addPreference(preference);
    }

    {
        static const QString RENDER("Graphics");
        auto renderConfig = qApp->getRenderEngine()->getConfiguration();

        auto ambientOcclusionConfig = renderConfig->getConfig<AmbientOcclusionEffect>();
        {
            auto getter = [ambientOcclusionConfig]()->QString { return ambientOcclusionConfig->getPreset(); };
            auto setter = [ambientOcclusionConfig](QString preset) { ambientOcclusionConfig->setPreset(preset); };
            auto preference = new ComboBoxPreference(RENDER, "Ambient occlusion", getter, setter);
            preference->setItems(ambientOcclusionConfig->getPresetList());
            preferences->addPreference(preference);
        }

        auto shadowConfig = renderConfig->getConfig<RenderShadowTask>();
        {
            auto getter = [shadowConfig]()->QString { return shadowConfig->getPreset(); };
            auto setter = [shadowConfig](QString preset) { shadowConfig->setPreset(preset); };
            auto preference = new ComboBoxPreference(RENDER, "Shadows", getter, setter);
            preference->setItems(shadowConfig->getPresetList());
            preferences->addPreference(preference);
        }
    }
    {
        static const QString RENDER("Networking");

        auto nodelist = DependencyManager::get<NodeList>();
        {
            static const int MIN_PORT_NUMBER { 0 };
            static const int MAX_PORT_NUMBER { 65535 };
            auto getter = [nodelist] { return static_cast<int>(nodelist->getSocketLocalPort()); };
            auto setter = [nodelist](int preset) { nodelist->setSocketLocalPort(static_cast<quint16>(preset)); };
            auto preference = new IntSpinnerPreference(RENDER, "Listening Port", getter, setter);
            preference->setMin(MIN_PORT_NUMBER);
            preference->setMax(MAX_PORT_NUMBER);
            preferences->addPreference(preference);
        }
    }
}