Merge branch 'master' of github.com:highfidelity/hifi into qt-launcher

This commit is contained in:
danteruiz 2019-10-25 10:15:39 -07:00
commit bc207638a5
42 changed files with 748 additions and 219 deletions

View file

@ -6,8 +6,8 @@ if (WIN32)
include(ExternalProject)
ExternalProject_Add(
${EXTERNAL_NAME}
URL https://public.highfidelity.com/dependencies/qtaudio_wasapi12.zip
URL_MD5 9e2eef41165f85344808f754b48bf08d
URL https://public.highfidelity.com/dependencies/qtaudio_wasapi13.zip
URL_MD5 aa56a45f19c18caee13d29a40d1d7d28
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""

View file

@ -1,4 +1,4 @@
Source: hifi-deps
Version: 0.1
Version: 0.3
Description: Collected dependencies for High Fidelity applications
Build-Depends: bullet3, draco, etc2comp, glm, nvtt, openexr (!android), openssl (windows), tbb (!android&!osx), zlib, webrtc (!android)

View file

@ -265,7 +265,7 @@ endif()
if platform.system() == 'Windows':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-windows3.tar.gz'
elif platform.system() == 'Darwin':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos3.tar.gz'
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-macos.tar.gz?versionId=bLAgnoJ8IMKpqv8NFDcAu8hsyQy3Rwwz'
elif platform.system() == 'Linux':
if platform.linux_distribution()[1][:3] == '16.':
url = 'https://hifi-public.s3.amazonaws.com/dependencies/vcpkg/qt5-install-5.12.3-ubuntu-16.04-with-symbols.tar.gz'

View file

@ -133,15 +133,12 @@ Item {
ListElement {
text: "Low World Detail"
worldDetailQualityValue: 0.25
}
ListElement {
text: "Medium World Detail"
worldDetailQualityValue: 0.5
}
ListElement {
text: "Full World Detail"
worldDetailQualityValue: 0.75
}
}
@ -158,14 +155,7 @@ Item {
currentIndex: -1
function refreshWorldDetailDropdown() {
var currentWorldDetailQuality = LODManager.worldDetailQuality;
if (currentWorldDetailQuality <= 0.25) {
worldDetailDropdown.currentIndex = 0;
} else if (currentWorldDetailQuality <= 0.5) {
worldDetailDropdown.currentIndex = 1;
} else {
worldDetailDropdown.currentIndex = 2;
}
worldDetailDropdown.currentIndex = LODManager.worldDetailQuality;
}
Component.onCompleted: {
@ -173,7 +163,7 @@ Item {
}
onCurrentIndexChanged: {
LODManager.worldDetailQuality = model.get(currentIndex).worldDetailQualityValue;
LODManager.worldDetailQuality = currentIndex;
worldDetailDropdown.displayText = model.get(currentIndex).text;
}
}

View file

@ -258,13 +258,12 @@ Flickable {
Layout.preferredHeight: contentItem.height
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
interactive: false
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
clip: true
model: AudioScriptingInterface.devices.input
delegate: Item {
width: parent.width
height: inputDeviceCheckbox.height
width: parent.width
height: model.type != "hmd" ? inputDeviceCheckbox.height + simplifiedUI.margins.settings.spacingBetweenRadiobuttons : 0
visible: model.type != "hmd"
SimplifiedControls.RadioButton {
id: inputDeviceCheckbox
anchors.left: parent.left
@ -354,13 +353,12 @@ Flickable {
Layout.preferredHeight: contentItem.height
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
interactive: false
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
clip: true
model: AudioScriptingInterface.devices.output
delegate: Item {
width: parent.width
height: outputDeviceCheckbox.height
height: model.type != "hmd" ? outputDeviceCheckbox.height +simplifiedUI.margins.settings.spacingBetweenRadiobuttons : 0
visible: model.type != "hmd"
SimplifiedControls.RadioButton {
id: outputDeviceCheckbox
anchors.left: parent.left

View file

@ -259,13 +259,13 @@ Flickable {
Layout.preferredHeight: contentItem.height
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
interactive: false
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
clip: true
model: AudioScriptingInterface.devices.input
delegate: Item {
width: parent.width
height: inputDeviceCheckbox.height
width: parent.width
height: model.type != "desktop" ? inputDeviceCheckbox.height + simplifiedUI.margins.settings.spacingBetweenRadiobuttons : 0
visible: model.type != "desktop"
SimplifiedControls.RadioButton {
id: inputDeviceCheckbox
anchors.left: parent.left
@ -355,13 +355,12 @@ Flickable {
Layout.preferredHeight: contentItem.height
Layout.topMargin: simplifiedUI.margins.settings.settingsGroupTopMargin
interactive: false
spacing: simplifiedUI.margins.settings.spacingBetweenRadiobuttons
clip: true
model: AudioScriptingInterface.devices.output
delegate: Item {
width: parent.width
height: outputDeviceCheckbox.height
height: model.type != "desktop" ? outputDeviceCheckbox.height + simplifiedUI.margins.settings.spacingBetweenRadiobuttons : 0
visible: model.type != "desktop"
SimplifiedControls.RadioButton {
id: outputDeviceCheckbox
anchors.left: parent.left

View file

@ -429,7 +429,7 @@ Rectangle {
SimplifiedControls.TextField {
id: goToTextField
readonly property string shortPlaceholderText: "Jump to..."
readonly property string longPlaceholderText: "Type the name of a location to quickly jump there..."
readonly property string longPlaceholderText: "Quickly jump to a location by typing '/LocationName'"
anchors.centerIn: parent
width: Math.min(parent.width, 445)
height: 35

View file

@ -0,0 +1,10 @@
{
"DataVersion": 3,
"Paths": {
"/": "/0, 0, 0/0,0,0,0"
},
"Entities": [
],
"Id": "{5807d519-eb7d-496d-b22a-0820811291c9}",
"Version": 120
}

View file

@ -5845,14 +5845,14 @@ void Application::pushPostUpdateLambda(void* key, const std::function<void()>& f
// to everyone.
// The principal result is to call updateLookAtTargetAvatar() and then setLookAtPosition().
// Note that it is called BEFORE we update position or joints based on sensors, etc.
void Application::updateMyAvatarLookAtPosition() {
void Application::updateMyAvatarLookAtPosition(float deltaTime) {
PerformanceTimer perfTimer("lookAt");
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");
auto myAvatar = getMyAvatar();
FaceTracker* faceTracker = getActiveFaceTracker();
myAvatar->updateLookAtPosition(faceTracker, _myCamera);
myAvatar->updateEyesLookAtPosition(faceTracker, _myCamera, deltaTime);
}
void Application::updateThreads(float deltaTime) {
@ -6636,7 +6636,7 @@ void Application::update(float deltaTime) {
{
PROFILE_RANGE(simulation, "MyAvatar");
PerformanceTimer perfTimer("MyAvatar");
qApp->updateMyAvatarLookAtPosition();
qApp->updateMyAvatarLookAtPosition(deltaTime);
avatarManager->updateMyAvatar(deltaTime);
}
}
@ -7516,6 +7516,7 @@ void Application::registerScriptEngineWithApplicationServices(const ScriptEngine
scriptEngine->registerGlobalObject("AvatarManager", DependencyManager::get<AvatarManager>().data());
scriptEngine->registerGlobalObject("LODManager", DependencyManager::get<LODManager>().data());
qScriptRegisterMetaType(scriptEngine.data(), worldDetailQualityToScriptValue, worldDetailQualityFromScriptValue);
scriptEngine->registerGlobalObject("Keyboard", DependencyManager::get<KeyboardScriptingInterface>().data());
scriptEngine->registerGlobalObject("Performance", new PerformanceScriptingInterface());

View file

@ -292,7 +292,7 @@ public:
virtual void pushPostUpdateLambda(void* key, const std::function<void()>& func) override;
void updateMyAvatarLookAtPosition();
void updateMyAvatarLookAtPosition(float deltaTime);
float getGameLoopRate() const { return _gameLoopCounter.rate(); }

View file

@ -19,11 +19,8 @@
#include "ui/DialogsManager.h"
#include "InterfaceLogging.h"
const float LODManager::DEFAULT_DESKTOP_LOD_DOWN_FPS = LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS;
const float LODManager::DEFAULT_HMD_LOD_DOWN_FPS = LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS;
Setting::Handle<float> desktopLODDecreaseFPS("desktopLODDecreaseFPS", LODManager::DEFAULT_DESKTOP_LOD_DOWN_FPS);
Setting::Handle<float> hmdLODDecreaseFPS("hmdLODDecreaseFPS", LODManager::DEFAULT_HMD_LOD_DOWN_FPS);
Setting::Handle<int> desktopWorldDetailQuality("desktopWorldDetailQuality", (int)DEFAULT_WORLD_DETAIL_QUALITY);
Setting::Handle<int> hmdWorldDetailQuality("hmdWorldDetailQuality", (int)DEFAULT_WORLD_DETAIL_QUALITY);
LODManager::LODManager() {
}
@ -326,19 +323,21 @@ QString LODManager::getLODFeedbackText() {
}
void LODManager::loadSettings() {
setDesktopLODTargetFPS(desktopLODDecreaseFPS.get());
Setting::Handle<bool> firstRun { Settings::firstRun, true };
auto desktopQuality = static_cast<WorldDetailQuality>(desktopWorldDetailQuality.get());
auto hmdQuality = static_cast<WorldDetailQuality>(hmdWorldDetailQuality.get());
Setting::Handle<bool> firstRun{ Settings::firstRun, true };
if (qApp->property(hifi::properties::OCULUS_STORE).toBool() && firstRun.get()) {
const float LOD_HIGH_QUALITY_LEVEL = 0.75f;
setHMDLODTargetFPS(LOD_HIGH_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS);
} else {
setHMDLODTargetFPS(hmdLODDecreaseFPS.get());
hmdQuality = WORLD_DETAIL_HIGH;
}
setWorldDetailQuality(desktopQuality, false);
setWorldDetailQuality(hmdQuality, true);
}
void LODManager::saveSettings() {
desktopLODDecreaseFPS.set(getDesktopLODTargetFPS());
hmdLODDecreaseFPS.set(getHMDLODTargetFPS());
desktopWorldDetailQuality.set((int)_desktopWorldDetailQuality);
hmdWorldDetailQuality.set((int)_hmdWorldDetailQuality);
}
const float MIN_DECREASE_FPS = 0.5f;
@ -393,54 +392,33 @@ float LODManager::getLODTargetFPS() const {
}
}
void LODManager::setWorldDetailQuality(float quality) {
static const float MIN_FPS = 10;
static const float LOW = 0.25f;
bool isLowestValue = quality == LOW;
bool isHMDMode = qApp->isHMDMode();
float maxFPS = isHMDMode ? LOD_MAX_LIKELY_HMD_FPS : LOD_MAX_LIKELY_DESKTOP_FPS;
float desiredFPS = maxFPS;
if (!isLowestValue) {
float calculatedFPS = (maxFPS - (maxFPS * quality));
desiredFPS = calculatedFPS < MIN_FPS ? MIN_FPS : calculatedFPS;
}
void LODManager::setWorldDetailQuality(WorldDetailQuality quality, bool isHMDMode) {
float desiredFPS = isHMDMode ? QUALITY_TO_FPS_HMD[quality] : QUALITY_TO_FPS_DESKTOP[quality];
if (isHMDMode) {
_hmdWorldDetailQuality = quality;
setHMDLODTargetFPS(desiredFPS);
} else {
_desktopWorldDetailQuality = quality;
setDesktopLODTargetFPS(desiredFPS);
}
}
void LODManager::setWorldDetailQuality(WorldDetailQuality quality) {
setWorldDetailQuality(quality, qApp->isHMDMode());
emit worldDetailQualityChanged();
}
float LODManager::getWorldDetailQuality() const {
WorldDetailQuality LODManager::getWorldDetailQuality() const {
return qApp->isHMDMode() ? _hmdWorldDetailQuality : _desktopWorldDetailQuality;
}
static const float LOW = 0.25f;
static const float MEDIUM = 0.5f;
static const float HIGH = 0.75f;
QScriptValue worldDetailQualityToScriptValue(QScriptEngine* engine, const WorldDetailQuality& worldDetailQuality) {
return worldDetailQuality;
}
bool inHMD = qApp->isHMDMode();
float targetFPS = 0.0f;
if (inHMD) {
targetFPS = getHMDLODTargetFPS();
} else {
targetFPS = getDesktopLODTargetFPS();
}
float maxFPS = inHMD ? LOD_MAX_LIKELY_HMD_FPS : LOD_MAX_LIKELY_DESKTOP_FPS;
float percentage = 1.0f - targetFPS / maxFPS;
if (percentage <= LOW) {
return LOW;
} else if (percentage <= MEDIUM) {
return MEDIUM;
}
return HIGH;
void worldDetailQualityFromScriptValue(const QScriptValue& object, WorldDetailQuality& worldDetailQuality) {
worldDetailQuality =
static_cast<WorldDetailQuality>(std::min(std::max(object.toInt32(), (int)WORLD_DETAIL_LOW), (int)WORLD_DETAIL_HIGH));
}
void LODManager::setLODQualityLevel(float quality) {

View file

@ -23,26 +23,52 @@
#include <render/Args.h>
/**jsdoc
* <p>The world detail quality rendered.</p>
* <table>
* <thead>
* <tr><th>Value</th><th>Description</th></tr>
* </thead>
* <tbody>
* <tr><td><code>0</code></td><td>Low world detail quality.</td></tr>
* <tr><td><code>1</code></td><td>Medium world detail quality.</td></tr>
* <tr><td><code>2</code></td><td>High world detail quality.</td></tr>
* </tbody>
* </table>
* @typedef {number} LODManager.WorldDetailQuality
*/
enum WorldDetailQuality {
WORLD_DETAIL_LOW = 0,
WORLD_DETAIL_MEDIUM,
WORLD_DETAIL_HIGH
};
Q_DECLARE_METATYPE(WorldDetailQuality);
#ifdef Q_OS_ANDROID
const float LOD_DEFAULT_QUALITY_LEVEL = 0.2f; // default quality level setting is High (lower framerate)
#else
const float LOD_DEFAULT_QUALITY_LEVEL = 0.5f; // default quality level setting is Mid
#endif
const float LOD_MAX_LIKELY_DESKTOP_FPS = 60.0f; // this is essentially, V-synch fps
#ifdef Q_OS_ANDROID
const float LOD_MAX_LIKELY_HMD_FPS = 36.0f; // this is essentially, V-synch fps
const WorldDetailQuality DEFAULT_WORLD_DETAIL_QUALITY = WORLD_DETAIL_LOW;
const std::vector<float> QUALITY_TO_FPS_DESKTOP = { 60.0f, 30.0f, 15.0f };
const std::vector<float> QUALITY_TO_FPS_HMD = { 25.0f, 16.0f, 10.0f };
#else
const float LOD_MAX_LIKELY_HMD_FPS = 90.0f; // this is essentially, V-synch fps
const WorldDetailQuality DEFAULT_WORLD_DETAIL_QUALITY = WORLD_DETAIL_MEDIUM;
const std::vector<float> QUALITY_TO_FPS_DESKTOP = { 60.0f, 30.0f, 15.0f };
const std::vector<float> QUALITY_TO_FPS_HMD = { 90.0f, 45.0f, 22.5f };
#endif
const float LOD_OFFSET_FPS = 5.0f; // offset of FPS to add for computing the target framerate
class AABox;
/**jsdoc
* The LOD class manages your Level of Detail functions within Interface.
* @namespace LODManager
*
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
@ -51,12 +77,12 @@ class AABox;
* @property {number} engineRunTime <em>Read-only.</em>
* @property {number} gpuTime <em>Read-only.</em>
*/
class LODManager : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
Q_PROPERTY(float worldDetailQuality READ getWorldDetailQuality WRITE setWorldDetailQuality NOTIFY worldDetailQualityChanged)
Q_PROPERTY(WorldDetailQuality worldDetailQuality READ getWorldDetailQuality WRITE setWorldDetailQuality
NOTIFY worldDetailQualityChanged)
Q_PROPERTY(float lodQualityLevel READ getLODQualityLevel WRITE setLODQualityLevel NOTIFY lodQualityLevelChanged)
@ -193,8 +219,8 @@ public:
float getSmoothRenderTime() const { return _smoothRenderTime; };
float getSmoothRenderFPS() const { return (_smoothRenderTime > 0.0f ? (float)MSECS_PER_SECOND / _smoothRenderTime : 0.0f); };
void setWorldDetailQuality(float quality);
float getWorldDetailQuality() const;
void setWorldDetailQuality(WorldDetailQuality quality);
WorldDetailQuality getWorldDetailQuality() const;
void setLODQualityLevel(float quality);
float getLODQualityLevel() const;
@ -220,9 +246,6 @@ public:
float getPidOd() const;
float getPidO() const;
static const float DEFAULT_DESKTOP_LOD_DOWN_FPS;
static const float DEFAULT_HMD_LOD_DOWN_FPS;
signals:
/**jsdoc
@ -244,6 +267,8 @@ signals:
private:
LODManager();
void setWorldDetailQuality(WorldDetailQuality quality, bool isHMDMode);
std::mutex _automaticLODLock;
bool _automaticLODAdjust = true;
@ -258,8 +283,11 @@ private:
float _lodQualityLevel{ LOD_DEFAULT_QUALITY_LEVEL };
float _desktopTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_DESKTOP_FPS };
float _hmdTargetFPS { LOD_OFFSET_FPS + LOD_DEFAULT_QUALITY_LEVEL * LOD_MAX_LIKELY_HMD_FPS };
WorldDetailQuality _desktopWorldDetailQuality { DEFAULT_WORLD_DETAIL_QUALITY };
WorldDetailQuality _hmdWorldDetailQuality { DEFAULT_WORLD_DETAIL_QUALITY };
float _desktopTargetFPS { QUALITY_TO_FPS_DESKTOP[_desktopWorldDetailQuality] };
float _hmdTargetFPS { QUALITY_TO_FPS_HMD[_hmdWorldDetailQuality] };
float _lodHalfAngle = getHalfAngleFromVisibilityDistance(DEFAULT_VISIBILITY_DISTANCE_FOR_UNIT_ELEMENT);
int _boundaryLevelAdjust = 0;
@ -269,4 +297,7 @@ private:
glm::vec4 _pidOutputs{ 0.0f };
};
QScriptValue worldDetailQualityToScriptValue(QScriptEngine* engine, const WorldDetailQuality& worldDetailQuality);
void worldDetailQualityFromScriptValue(const QScriptValue& object, WorldDetailQuality& worldDetailQuality);
#endif // hifi_LODManager_h

View file

@ -92,7 +92,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
RenderScriptingInterface::getInstance()->setShadowsEnabled(true);
qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.75f);
DependencyManager::get<LODManager>()->setWorldDetailQuality(WORLD_DETAIL_HIGH);
break;
case PerformancePreset::MID:
@ -104,7 +104,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
RenderScriptingInterface::getInstance()->setShadowsEnabled(false);
qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::INTERACTIVE);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.5f);
DependencyManager::get<LODManager>()->setWorldDetailQuality(WORLD_DETAIL_MEDIUM);
break;
case PerformancePreset::LOW:
@ -114,7 +114,7 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP
RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommandedPpiScale);
DependencyManager::get<LODManager>()->setWorldDetailQuality(0.25f);
DependencyManager::get<LODManager>()->setWorldDetailQuality(WORLD_DETAIL_LOW);
break;
case PerformancePreset::UNKNOWN:

View file

@ -906,6 +906,25 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
updateViewBoom();
}
// Head's look at blending needs updating
// before we perform rig animations and IK.
{
PerformanceTimer perfTimer("lookat");
CameraMode mode = qApp->getCamera().getMode();
if (_scriptControlsHeadLookAt || mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON ||
mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) {
if (!_pointAtActive || !_isPointTargetValid) {
updateHeadLookAt(deltaTime);
} else {
resetHeadLookAt();
}
} else if (_headLookAtActive) {
resetHeadLookAt();
_headLookAtActive = false;
}
}
// update sensorToWorldMatrix for camera and hand controllers
// before we perform rig animations and IK.
updateSensorToWorldMatrix();
@ -957,18 +976,6 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
head->setPosition(headPosition);
head->setScale(getModelScale());
head->simulate(deltaTime);
CameraMode mode = qApp->getCamera().getMode();
if (_scriptControlsHeadLookAt || mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON ||
mode == CAMERA_MODE_LOOK_AT || mode == CAMERA_MODE_SELFIE) {
if (!_pointAtActive || !_isPointTargetValid) {
updateHeadLookAt(deltaTime);
} else {
resetHeadLookAt();
}
} else if (_headLookAtActive){
resetHeadLookAt();
_headLookAtActive = false;
}
}
// Record avatars movements.
@ -2151,7 +2158,7 @@ static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myP
const float DISTANCE_FACTOR = 3.14f;
const float MY_ANGLE_FACTOR = 1.0f;
const float OTHER_ANGLE_FACTOR = 1.0f;
const float OTHER_IS_TALKING_TERM = otherIsTalking ? 1.0f : 0.0f;
const float OTHER_IS_TALKING_TERM = otherIsTalking ? -1.0f : 0.0f;
const float LOOKING_AT_OTHER_ALREADY_TERM = lookingAtOtherAlready ? -0.2f : 0.0f;
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; // meters
@ -2177,6 +2184,9 @@ static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myP
void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) {
glm::vec3 myForward = _lookAtYaw * IDENTITY_FORWARD;
if (_skeletonModel->isLoaded()) {
myForward = getHeadJointFrontVector();
}
glm::vec3 myPosition = getHead()->getEyePosition();
CameraMode mode = qApp->getCamera().getMode();
if (mode == CAMERA_MODE_FIRST_PERSON_LOOK_AT || mode == CAMERA_MODE_FIRST_PERSON) {
@ -2189,7 +2199,7 @@ void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) {
foreach (const AvatarSharedPointer& avatarData, hash) {
std::shared_ptr<Avatar> avatar = std::static_pointer_cast<Avatar>(avatarData);
if (!avatar->isMyAvatar() && avatar->isInitialized()) {
glm::vec3 otherForward = avatar->getHead()->getForwardDirection();
glm::vec3 otherForward = avatar->getHeadJointFrontVector();
glm::vec3 otherPosition = avatar->getHead()->getEyePosition();
const float TIME_WITHOUT_TALKING_THRESHOLD = 1.0f;
bool otherIsTalking = avatar->getHead()->getTimeWithoutTalking() <= TIME_WITHOUT_TALKING_THRESHOLD;
@ -2277,7 +2287,9 @@ void MyAvatar::updateLookAtTargetAvatar() {
AvatarHash hash = DependencyManager::get<AvatarManager>()->getHashCopy();
// determine what the best look at target for my avatar should be.
computeMyLookAtTarget(hash);
if (!_scriptControlsEyesLookAt) {
computeMyLookAtTarget(hash);
}
// snap look at position for avatars that are looking at me.
snapOtherAvatarLookAtTargetsToMe(hash);
@ -6612,7 +6624,7 @@ bool MyAvatar::getIsJointOverridden(int jointIndex) const {
return _skeletonModel->getIsJointOverridden(jointIndex);
}
void MyAvatar::updateLookAtPosition(FaceTracker* faceTracker, Camera& myCamera) {
void MyAvatar::updateEyesLookAtPosition(FaceTracker* faceTracker, Camera& myCamera, float deltaTime) {
updateLookAtTargetAvatar();
@ -6642,6 +6654,13 @@ void MyAvatar::updateLookAtPosition(FaceTracker* faceTracker, Camera& myCamera)
} else {
lookAtSpot = myHead->getEyePosition() + glm::normalize(leftVec) * 1000.0f;
}
} else if (_scriptControlsEyesLookAt) {
if (_scriptEyesControlTimer < MAX_LOOK_AT_TIME_SCRIPT_CONTROL) {
_scriptEyesControlTimer += deltaTime;
lookAtSpot = _eyesLookAtTarget.get();
} else {
_scriptControlsEyesLookAt = false;
}
} else {
controller::Pose leftEyePose = getControllerPoseInAvatarFrame(controller::Action::LEFT_EYE);
controller::Pose rightEyePose = getControllerPoseInAvatarFrame(controller::Action::RIGHT_EYE);
@ -6704,8 +6723,9 @@ void MyAvatar::updateLookAtPosition(FaceTracker* faceTracker, Camera& myCamera)
if (headPose.isValid()) {
lookAtSpot = transformPoint(headPose.getMatrix(), glm::vec3(0.0f, 0.0f, TREE_SCALE));
} else {
lookAtSpot = myHead->getEyePosition() +
(getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE));
lookAtSpot = _shouldTurnToFaceCamera ?
myHead->getLookAtPosition() :
myHead->getEyePosition() + getHeadJointFrontVector() * (float)TREE_SCALE;
}
}
@ -6725,7 +6745,7 @@ void MyAvatar::updateLookAtPosition(FaceTracker* faceTracker, Camera& myCamera)
}
}
}
_eyesLookAtTarget.set(lookAtSpot);
getHead()->setLookAtPosition(lookAtSpot);
}
@ -6808,6 +6828,17 @@ void MyAvatar::setHeadLookAt(const glm::vec3& lookAtTarget) {
_lookAtScriptTarget = lookAtTarget;
}
void MyAvatar::setEyesLookAt(const glm::vec3& lookAtTarget) {
if (QThread::currentThread() != thread()) {
BLOCKING_INVOKE_METHOD(this, "setEyesLookAt",
Q_ARG(const glm::vec3&, lookAtTarget));
return;
}
_eyesLookAtTarget.set(lookAtTarget);
_scriptEyesControlTimer = 0.0f;
_scriptControlsEyesLookAt = true;
}
glm::vec3 MyAvatar::getLookAtPivotPoint() {
glm::vec3 avatarUp = getWorldOrientation() * Vectors::UP;
glm::vec3 yAxisEyePosition = getWorldPosition() + avatarUp * glm::dot(avatarUp, _skeletonModel->getDefaultEyeModelPosition());
@ -6900,4 +6931,3 @@ void MyAvatar::resetPointAt() {
POINT_BLEND_LINEAR_ALPHA_NAME, POINT_ALPHA_BLENDING);
}
}

View file

@ -1765,10 +1765,26 @@ public:
/**jsdoc
* Returns the current head look at target point in world coordinates.
* @function MyAvatar.getHeadLookAt
* @returns {Vec3} Default position between your avatar's eyes in world coordinates.
* @returns {Vec3} The head's look at target in world coordinates.
*/
Q_INVOKABLE glm::vec3 getHeadLookAt() { return _lookAtCameraTarget; }
/**jsdoc
* Force the avatar's eyes to look to the specified location.
* Once this method is called, API calls will have full control of the eyes for a limited time.
* If this method is not called for two seconds, the engine will regain control of the eyes.
* @function MyAvatar.setEyesLookAt
* @param {Vec3} lookAtTarget - The target point in world coordinates.
*/
Q_INVOKABLE void setEyesLookAt(const glm::vec3& lookAtTarget);
/**jsdoc
* Returns the current eyes look at target point in world coordinates.
* @function MyAvatar.getEyesLookAt
* @returns {Vec3} The eyes's look at target in world coordinates.
*/
Q_INVOKABLE glm::vec3 getEyesLookAt() { return _eyesLookAtTarget.get(); }
/**jsdoc
* Aims the pointing directional blending towards the provided target point.
* The "point" reaction should be triggered before using this method.
@ -1906,7 +1922,7 @@ public:
bool getFlowActive() const;
bool getNetworkGraphActive() const;
void updateLookAtPosition(FaceTracker* faceTracker, Camera& myCamera);
void updateEyesLookAtPosition(FaceTracker* faceTracker, Camera& myCamera, float deltaTime);
// sets the reaction enabled and triggered parameters of the passed in params
// also clears internal reaction triggers
@ -2666,6 +2682,9 @@ private:
eyeContactTarget _eyeContactTarget;
float _eyeContactTargetTimer { 0.0f };
ThreadSafeValueCache<glm::vec3> _eyesLookAtTarget { glm::vec3() };
bool _scriptControlsEyesLookAt{ false };
float _scriptEyesControlTimer{ 0.0f };
glm::vec3 _trackedHeadPosition;

View file

@ -44,7 +44,8 @@ enum AudioDeviceRole {
SelectedDesktopRole,
SelectedHMDRole,
PeakRole,
InfoRole
InfoRole,
TypeRole
};
QHash<int, QByteArray> AudioDeviceList::_roles {
@ -52,7 +53,8 @@ QHash<int, QByteArray> AudioDeviceList::_roles {
{ SelectedDesktopRole, "selectedDesktop" },
{ SelectedHMDRole, "selectedHMD" },
{ PeakRole, "peak" },
{ InfoRole, "info" }
{ InfoRole, "info" },
{ TypeRole, "type"}
};
static QString getTargetDevice(bool hmd, QAudio::Mode mode) {
@ -60,12 +62,6 @@ static QString getTargetDevice(bool hmd, QAudio::Mode mode) {
auto& setting = getSetting(hmd, mode);
if (setting.isSet()) {
deviceName = setting.get();
} else if (hmd) {
if (mode == QAudio::AudioInput) {
deviceName = qApp->getActiveDisplayPlugin()->getPreferredAudioInDevice();
} else { // if (_mode == QAudio::AudioOutput)
deviceName = qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice();
}
} else {
deviceName = HifiAudioDeviceInfo::DEFAULT_DEVICE_NAME;
}
@ -144,6 +140,8 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const {
return _devices.at(index.row())->selectedHMD;
} else if (role == InfoRole) {
return QVariant::fromValue<HifiAudioDeviceInfo>(_devices.at(index.row())->info);
} else if (role == TypeRole) {
return _devices.at(index.row())->type;
} else {
return QVariant();
}
@ -166,8 +164,8 @@ void AudioDeviceList::resetDevice(bool contextIsHMD) {
QString deviceName = getTargetDevice(contextIsHMD, _mode);
// FIXME can't use blocking connections here, so we can't determine whether the switch succeeded or not
// We need to have the AudioClient emit signals on switch success / failure
QMetaObject::invokeMethod(client, "switchAudioDevice",
Q_ARG(QAudio::Mode, _mode), Q_ARG(QString, deviceName));
QMetaObject::invokeMethod(client, "switchAudioDevice",
Q_ARG(QAudio::Mode, _mode), Q_ARG(QString, deviceName), Q_ARG(bool, contextIsHMD));
#if 0
bool switchResult = false;
@ -265,13 +263,20 @@ void AudioDeviceList::onDevicesChanged(const QList<HifiAudioDeviceInfo>& devices
bool hmdIsSelected = false;
bool desktopIsSelected = false;
foreach(const HifiAudioDeviceInfo& deviceInfo, devices) {
for (bool isHMD : {false, true}) {
auto& backupSelectedDeviceName = isHMD ? _backupSelectedHMDDeviceName : _backupSelectedDesktopDeviceName;
if (deviceInfo.deviceName() == backupSelectedDeviceName) {
HifiAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
selectedDevice = deviceInfo;
backupSelectedDeviceName.clear();
if (!_backupSelectedDesktopDeviceName.isEmpty() && !_backupSelectedHMDDeviceName.isEmpty()) {
foreach(const HifiAudioDeviceInfo& deviceInfo, devices) {
for (bool isHMD : {false, true}) {
auto& backupSelectedDeviceName = isHMD ? _backupSelectedHMDDeviceName : _backupSelectedDesktopDeviceName;
if (deviceInfo.deviceName() == backupSelectedDeviceName) {
if (isHMD && deviceInfo.getDeviceType() != HifiAudioDeviceInfo::desktop) {
_selectedHMDDevice= deviceInfo;
backupSelectedDeviceName.clear();
} else if (!isHMD && deviceInfo.getDeviceType() != HifiAudioDeviceInfo::hmd) {
_selectedDesktopDevice = deviceInfo;
backupSelectedDeviceName.clear();
}
}
}
}
}
@ -281,10 +286,18 @@ void AudioDeviceList::onDevicesChanged(const QList<HifiAudioDeviceInfo>& devices
device.info = deviceInfo;
if (deviceInfo.isDefault()) {
if (deviceInfo.getMode() == QAudio::AudioInput) {
device.display = "Computer's default microphone (recommended)";
} else {
device.display = "Computer's default audio (recommended)";
if (deviceInfo.getDeviceType() == HifiAudioDeviceInfo::desktop) {
if (deviceInfo.getMode() == QAudio::AudioInput) {
device.display = "Computer's default microphone (recommended)";
} else {
device.display = "Computer's default audio (recommended)";
}
} else if (deviceInfo.getDeviceType() == HifiAudioDeviceInfo::hmd) {
if (deviceInfo.getMode() == QAudio::AudioInput) {
device.display = "Headset's default mic (recommended)";
} else {
device.display = "Headset's default audio (recommended)";
}
}
} else {
device.display = device.info.deviceName()
@ -292,6 +305,19 @@ void AudioDeviceList::onDevicesChanged(const QList<HifiAudioDeviceInfo>& devices
.remove("Device")
.replace(" )", ")");
}
switch (deviceInfo.getDeviceType()) {
case HifiAudioDeviceInfo::hmd:
device.type = "hmd";
break;
case HifiAudioDeviceInfo::desktop:
device.type = "desktop";
break;
case HifiAudioDeviceInfo::both:
device.type = "both";
break;
}
for (bool isHMD : {false, true}) {
HifiAudioDeviceInfo& selectedDevice = isHMD ? _selectedHMDDevice : _selectedDesktopDevice;
@ -302,8 +328,14 @@ void AudioDeviceList::onDevicesChanged(const QList<HifiAudioDeviceInfo>& devices
}
else {
//no selected device for context. fallback to saved
const QString& savedDeviceName = isHMD ? _hmdSavedDeviceName : _desktopSavedDeviceName;
isSelected = (device.info.deviceName() == savedDeviceName);
QString& savedDeviceName = isHMD ? _hmdSavedDeviceName : _desktopSavedDeviceName;
if (device.info.deviceName() == savedDeviceName) {
if ((isHMD && device.info.getDeviceType() != HifiAudioDeviceInfo::desktop) ||
(!isHMD && device.info.getDeviceType() != HifiAudioDeviceInfo::hmd)) {
isSelected = true;
}
}
}
if (isSelected) {

View file

@ -29,6 +29,7 @@ public:
QString display;
bool selectedDesktop { false };
bool selectedHMD { false };
QString type;
};
class AudioDeviceList : public QAbstractListModel {

View file

@ -18,15 +18,23 @@
#include "DependencyManager.h"
/**jsdoc
* The Keyboard API provides facilities to use 3D Physical keyboard.
* The <code>Keyboard</code> API provides facilities to use an in-world, virtual keyboard. When enabled, this keyboard is
* displayed instead of the 2D keyboard that raises at the bottom of the tablet or Web entities when a text input field has
* focus and you're in HMD mode.
*
* @namespace Keyboard
*
* @hifi-interface
* @hifi-client-entity
* @hifi-avatar
*
* @property {bool} raised - <code>true</code> If the keyboard is visible <code>false</code> otherwise
* @property {bool} password - <code>true</code> Will show * instead of characters in the text display <code>false</code> otherwise
* @property {boolean} raised - <code>true</code> if the virtual keyboard is visible, <code>false</code> if it isn't.
* @property {boolean} password - <code>true</code> if <code>"*"</code>s are displayed on the virtual keyboard's display
* instead of the characters typed, <code>false</code> if the actual characters are displayed.
* @property {boolean} use3DKeyboard - <code>true</code> if user settings have "Use Virtual Keyboard" enabled,
* <code>false</code> if it's disabled. <em>Read-only.</em>
* @property {boolean} preferMalletsOverLasers - <code>true</code> if user settings for the virtual keyboard have "Mallets"
* selected, <code>false</code> if "Lasers" is selected. <em>Read-only.</em>
*/
class KeyboardScriptingInterface : public QObject, public Dependency {
@ -39,14 +47,61 @@ class KeyboardScriptingInterface : public QObject, public Dependency {
public:
KeyboardScriptingInterface() = default;
~KeyboardScriptingInterface() = default;
/**jsdoc
* Loads a JSON file that defines the virtual keyboard's layout. The default JSON file used is
* {@link https://github.com/highfidelity/hifi/blob/master/interface/resources/config/keyboard.json|https://github.com/highfidelity/hifi/.../keyboard.json}.
* @function Keyboard.loadKeyboardFile
* @param {string} path - The keyboard JSON file.
*/
Q_INVOKABLE void loadKeyboardFile(const QString& string);
/**jsdoc
* Enables the left mallet so that it is displayed when in HMD mode.
* @function Keyboard.enableLeftMallet
*/
Q_INVOKABLE void enableLeftMallet();
/**jsdoc
* Enables the right mallet so that it is displayed when in HMD mode.
* @function Keyboard.enableRightMallet
*/
Q_INVOKABLE void enableRightMallet();
/**jsdoc
* Disables the left mallet so that it is not displayed when in HMD mode.
* @function Keyboard.disableLeftMallet
*/
Q_INVOKABLE void disableLeftMallet();
/**jsdoc
* Disables the right mallet so that it is not displayed when in HMD mode.
* @function Keyboard.disableRightMallet
*/
Q_INVOKABLE void disableRightMallet();
/**jsdoc
* Configures the virtual keyboard to recognize a ray pointer as the left hand's laser.
* @function Keyboard.setLeftHandLaser
* @param {number} leftHandLaser - The ID of a ray pointer created by {@link Pointers.createPointer}.
*/
Q_INVOKABLE void setLeftHandLaser(unsigned int leftHandLaser);
/**jsdoc
* Configures the virtual keyboard to recognize a ray pointer as the right hand's laser.
* @function Keyboard.setRightHandLaser
* @param {number} rightHandLaser - The ID of a ray pointer created by {@link Pointers.createPointer}.
*/
Q_INVOKABLE void setRightHandLaser(unsigned int rightHandLaser);
/**jsdoc
* Checks whether an entity is part of the virtual keyboard.
* @function Keyboard.containsID
* @param {Uuid} entityID - The entity ID.
* @returns {boolean} <code>true</code> if the entity is part of the virtual keyboard, <code>false</code> if it isn't.
*/
Q_INVOKABLE bool containsID(const QUuid& overlayID) const;
private:
bool getPreferMalletsOverLasers() const;
bool isRaised() const;

View file

@ -41,7 +41,8 @@ void MenuScriptingInterface::removeMenu(const QString& menu) {
bool MenuScriptingInterface::menuExists(const QString& menu) {
if (QThread::currentThread() == qApp->thread()) {
return Menu::getInstance()->menuExists(menu);
Menu* menuInstance = Menu::getInstance();
return menuInstance && menuInstance->menuExists(menu);
}
bool result { false };
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "menuExists",
@ -84,7 +85,8 @@ void MenuScriptingInterface::removeMenuItem(const QString& menu, const QString&
bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString& menuitem) {
if (QThread::currentThread() == qApp->thread()) {
return Menu::getInstance()->menuItemExists(menu, menuitem);
Menu* menuInstance = Menu::getInstance();
return menuInstance && menuInstance->menuItemExists(menu, menuitem);
}
bool result { false };
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "menuItemExists",
@ -96,7 +98,8 @@ bool MenuScriptingInterface::menuItemExists(const QString& menu, const QString&
bool MenuScriptingInterface::isOptionChecked(const QString& menuOption) {
if (QThread::currentThread() == qApp->thread()) {
return Menu::getInstance()->isOptionChecked(menuOption);
Menu* menuInstance = Menu::getInstance();
return menuInstance && menuInstance->isOptionChecked(menuOption);
}
bool result { false };
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isOptionChecked",
@ -113,7 +116,8 @@ void MenuScriptingInterface::setIsOptionChecked(const QString& menuOption, bool
bool MenuScriptingInterface::isMenuEnabled(const QString& menuOption) {
if (QThread::currentThread() == qApp->thread()) {
return Menu::getInstance()->isOptionChecked(menuOption);
Menu* menuInstance = Menu::getInstance();
return menuInstance && menuInstance->isMenuEnabled(menuOption);
}
bool result { false };
BLOCKING_INVOKE_METHOD(Menu::getInstance(), "isMenuEnabled",

View file

@ -58,18 +58,19 @@ void setupPreferences() {
static const QString GRAPHICS_QUALITY { "Graphics Quality" };
{
auto getter = []()->float {
return DependencyManager::get<LODManager>()->getWorldDetailQuality();
return (int)DependencyManager::get<LODManager>()->getWorldDetailQuality();
};
auto setter = [](float value) {
DependencyManager::get<LODManager>()->setWorldDetailQuality(value);
auto setter = [](int value) {
DependencyManager::get<LODManager>()->setWorldDetailQuality(static_cast<WorldDetailQuality>(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 wodButtons = new RadioButtonsPreference(GRAPHICS_QUALITY, "World Detail", getter, setter);
QStringList items;
items << "Low World Detail" << "Medium World Detail" << "High World Detail";
wodButtons->setHeading("World Detail");
wodButtons->setItems(items);
preferences->addPreference(wodButtons);
auto getterShadow = []()->bool {
auto menu = Menu::getInstance();

View file

@ -6,6 +6,7 @@ setup_hifi_library(Network Multimedia ${PLATFORM_QT_COMPONENTS})
link_hifi_libraries(audio plugins)
include_hifi_library_headers(shared)
include_hifi_library_headers(networking)
include_hifi_library_headers(gpu)
if (ANDROID)
else ()

View file

@ -39,6 +39,7 @@
#include <QtMultimedia/QAudioInput>
#include <QtMultimedia/QAudioOutput>
#include <shared/QtHelpers.h>
#include <ThreadHelpers.h>
#include <NodeList.h>
#include <plugins/CodecPlugin.h>
@ -47,6 +48,7 @@
#include <SettingHandle.h>
#include <SharedUtil.h>
#include <Transform.h>
#include <plugins/DisplayPlugin.h>
#include "AudioClientLogging.h"
#include "AudioLogging.h"
@ -81,20 +83,50 @@ Mutex _recordMutex;
HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode);
static QString getHmdAudioDeviceName(QAudio::Mode mode) {
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getAllDisplayPlugins()) {
if (displayPlugin && displayPlugin->isHmd()) {
if (mode == QAudio::AudioInput) {
return displayPlugin->getPreferredAudioInDevice();
} else {
return displayPlugin->getPreferredAudioOutDevice();
}
break;
}
}
return QString();
}
// thread-safe
QList<HifiAudioDeviceInfo> getAvailableDevices(QAudio::Mode mode) {
//get hmd device name prior to locking device mutex. in case of shutdown, this thread will be locked and audio client
//cannot properly shut down.
QString hmdDeviceName = getHmdAudioDeviceName(mode);
// NOTE: availableDevices() clobbers the Qt internal device list
Lock lock(_deviceMutex);
auto devices = QAudioDeviceInfo::availableDevices(mode);
QList<HifiAudioDeviceInfo> newDevices;
for (auto& device : devices) {
newDevices.push_back(HifiAudioDeviceInfo(device, false, mode));
}
newDevices.push_front(defaultAudioDeviceForMode(mode));
if (!hmdDeviceName.isNull() && !hmdDeviceName.isEmpty()) {
HifiAudioDeviceInfo hmdDevice;
foreach(auto device, newDevices) {
if (device.getDevice().deviceName() == hmdDeviceName) {
hmdDevice = HifiAudioDeviceInfo(device.getDevice(), true, mode, HifiAudioDeviceInfo::hmd);
break;
}
}
if (!hmdDevice.getDevice().isNull()) {
newDevices.push_front(hmdDevice);
}
}
return newDevices;
}
@ -110,8 +142,8 @@ void AudioClient::checkDevices() {
auto inputDevices = getAvailableDevices(QAudio::AudioInput);
auto outputDevices = getAvailableDevices(QAudio::AudioOutput);
QMetaObject::invokeMethod(this, "changeDefault", Q_ARG(HifiAudioDeviceInfo, inputDevices.first()), Q_ARG(QAudio::Mode, QAudio::AudioInput));
QMetaObject::invokeMethod(this, "changeDefault", Q_ARG(HifiAudioDeviceInfo, outputDevices.first()), Q_ARG(QAudio::Mode, QAudio::AudioOutput));
checkDefaultChanges(inputDevices);
checkDefaultChanges(outputDevices);
Lock lock(_deviceMutex);
if (inputDevices != _inputDevices) {
@ -125,6 +157,14 @@ void AudioClient::checkDevices() {
}
}
void AudioClient::checkDefaultChanges(QList<HifiAudioDeviceInfo>& devices) {
foreach(auto device, devices) {
if (device.isDefault()) {
QMetaObject::invokeMethod(this, "changeDefault", Q_ARG(HifiAudioDeviceInfo, device), Q_ARG(QAudio::Mode, device.getMode()));
}
}
}
HifiAudioDeviceInfo AudioClient::getActiveAudioDevice(QAudio::Mode mode) const {
Lock lock(_deviceMutex);
@ -386,12 +426,14 @@ void AudioClient::setAudioPaused(bool pause) {
}
}
HifiAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName) {
HifiAudioDeviceInfo getNamedAudioDeviceForMode(QAudio::Mode mode, const QString& deviceName, bool isHmd=false) {
HifiAudioDeviceInfo result;
foreach (HifiAudioDeviceInfo audioDevice, getAvailableDevices(mode)) {
if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) {
result = audioDevice;
break;
if ((!isHmd && audioDevice.getDeviceType() != HifiAudioDeviceInfo::hmd) || (isHmd && audioDevice.getDeviceType() != HifiAudioDeviceInfo::desktop)) {
result = audioDevice;
break;
}
}
}
return result;
@ -477,7 +519,7 @@ HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
// find a device in the list that matches the name we have and return it
foreach(QAudioDeviceInfo audioDevice, devices){
if (audioDevice.deviceName() == CFStringGetCStringPtr(deviceName, kCFStringEncodingMacRoman)) {
return HifiAudioDeviceInfo(audioDevice, true, mode);
return HifiAudioDeviceInfo(audioDevice, true, mode, HifiAudioDeviceInfo::desktop);
}
}
}
@ -532,7 +574,7 @@ HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
HifiAudioDeviceInfo foundDevice;
foreach(QAudioDeviceInfo audioDevice, devices) {
if (audioDevice.deviceName().trimmed() == deviceName.trimmed()) {
foundDevice=HifiAudioDeviceInfo(audioDevice,true,mode);
foundDevice = HifiAudioDeviceInfo(audioDevice, true, mode, HifiAudioDeviceInfo::desktop);
break;
}
}
@ -558,8 +600,8 @@ HifiAudioDeviceInfo defaultAudioDeviceForMode(QAudio::Mode mode) {
}
#endif
// fallback for failed lookup is the default device
return (mode == QAudio::AudioInput) ? HifiAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice(), true,mode) :
HifiAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice(), true, mode);
return (mode == QAudio::AudioInput) ? HifiAudioDeviceInfo(QAudioDeviceInfo::defaultInputDevice(), true, mode, HifiAudioDeviceInfo::desktop) :
HifiAudioDeviceInfo(QAudioDeviceInfo::defaultOutputDevice(), true, mode, HifiAudioDeviceInfo::desktop);
}
bool AudioClient::getNamedAudioDeviceForModeExists(QAudio::Mode mode, const QString& deviceName) {
@ -763,6 +805,7 @@ void AudioClient::stop() {
// Destruction of the pointers will occur when the parent object (this) is destroyed)
{
Lock lock(_checkDevicesMutex);
_checkDevicesTimer->stop();
_checkDevicesTimer = nullptr;
}
{
@ -948,13 +991,18 @@ void AudioClient::selectAudioFormat(const QString& selectedCodecName) {
void AudioClient::changeDefault(HifiAudioDeviceInfo newDefault, QAudio::Mode mode) {
HifiAudioDeviceInfo currentDevice = mode == QAudio::AudioInput ? _inputDeviceInfo : _outputDeviceInfo;
if (currentDevice.isDefault() && currentDevice.getDevice() != newDefault.getDevice()) {
if (currentDevice.isDefault() && currentDevice.getDeviceType() == newDefault.getDeviceType() && currentDevice.getDevice() != newDefault.getDevice()) {
switchAudioDevice(mode, newDefault);
}
}
bool AudioClient::switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo& deviceInfo) {
auto device = deviceInfo;
if (deviceInfo.getDevice().isNull()) {
qCDebug(audioclient) << __FUNCTION__ << " switching to null device :"
<< deviceInfo.deviceName() << " : " << deviceInfo.getDevice().deviceName();
}
if (mode == QAudio::AudioInput) {
return switchInputToAudioDevice(device);
} else {
@ -962,8 +1010,8 @@ bool AudioClient::switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo
}
}
bool AudioClient::switchAudioDevice(QAudio::Mode mode, const QString& deviceName) {
return switchAudioDevice(mode, getNamedAudioDeviceForMode(mode, deviceName));
bool AudioClient::switchAudioDevice(QAudio::Mode mode, const QString& deviceName, bool isHmd) {
return switchAudioDevice(mode, getNamedAudioDeviceForMode(mode, deviceName, isHmd));
}
void AudioClient::configureReverb() {
@ -1771,7 +1819,8 @@ void AudioClient::outputFormatChanged() {
bool AudioClient::switchInputToAudioDevice(const HifiAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) {
Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread");
qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << _inputDeviceInfo.deviceName() <<"----"<<inputDeviceInfo.getDevice().deviceName() << "]";
qCDebug(audioclient) << __FUNCTION__ << "_inputDeviceInfo: [" << _inputDeviceInfo.deviceName() << ":" << _inputDeviceInfo.getDevice().deviceName()
<< "-- inputDeviceInfo:" << inputDeviceInfo.deviceName() << ":" << inputDeviceInfo.getDevice().deviceName() << "]";
bool supportedFormat = false;
// NOTE: device start() uses the Qt internal device list
@ -1823,8 +1872,9 @@ bool AudioClient::switchInputToAudioDevice(const HifiAudioDeviceInfo inputDevice
}
if (!inputDeviceInfo.getDevice().isNull()) {
qCDebug(audioclient) << "The audio input device " << inputDeviceInfo.deviceName() << "is available.";
qCDebug(audioclient) << "The audio input device" << inputDeviceInfo.deviceName() << ":" << inputDeviceInfo.getDevice().deviceName() << "is available.";
//do not update UI that we're changing devices if default or same device
bool doEmit = _inputDeviceInfo.deviceName() != inputDeviceInfo.deviceName();
_inputDeviceInfo = inputDeviceInfo;
if (doEmit) {
@ -1959,9 +2009,9 @@ void AudioClient::setHeadsetPluggedIn(bool pluggedIn) {
bool aecEnabled = enableAEC.get();
if ((pluggedIn || !aecEnabled) && _inputDeviceInfo.deviceName() != VOICE_RECOGNITION) {
switchAudioDevice(QAudio::AudioInput, VOICE_RECOGNITION);
switchAudioDevice(QAudio::AudioInput, VOICE_RECOGNITION, false);
} else if (!pluggedIn && aecEnabled && _inputDeviceInfo.deviceName() != VOICE_COMMUNICATION) {
switchAudioDevice(QAudio::AudioInput, VOICE_COMMUNICATION);
switchAudioDevice(QAudio::AudioInput, VOICE_COMMUNICATION, false);
}
}
_isHeadsetPluggedIn = pluggedIn;
@ -2006,8 +2056,9 @@ void AudioClient::noteAwakening() {
bool AudioClient::switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) {
Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread");
qCDebug(audioclient) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]";
qCDebug(audioclient) << __FUNCTION__ << "_outputdeviceInfo: [" << _outputDeviceInfo.deviceName() << ":" << _outputDeviceInfo.getDevice().deviceName()
<< "-- outputDeviceInfo:" << outputDeviceInfo.deviceName() << ":" << outputDeviceInfo.getDevice().deviceName() << "]";
bool supportedFormat = false;
// NOTE: device start() uses the Qt internal device list
@ -2063,7 +2114,9 @@ bool AudioClient::switchOutputToAudioDevice(const HifiAudioDeviceInfo outputDevi
}
if (!outputDeviceInfo.getDevice().isNull()) {
qCDebug(audioclient) << "The audio output device " << outputDeviceInfo.deviceName() << "is available.";
qCDebug(audioclient) << "The audio output device" << outputDeviceInfo.deviceName() << ":" << outputDeviceInfo.getDevice().deviceName() << "is available.";
//do not update UI that we're changing devices if default or same device
bool doEmit = _outputDeviceInfo.deviceName() != outputDeviceInfo.deviceName();
_outputDeviceInfo = outputDeviceInfo;
if (doEmit) {

View file

@ -238,10 +238,11 @@ public slots:
bool shouldLoopbackInjectors() override { return _shouldEchoToServer; }
Q_INVOKABLE void changeDefault(HifiAudioDeviceInfo newDefault, QAudio::Mode mode);
void checkDefaultChanges(QList<HifiAudioDeviceInfo>& devices);
// calling with a null QAudioDevice will use the system default
bool switchAudioDevice(QAudio::Mode mode, const HifiAudioDeviceInfo& deviceInfo = HifiAudioDeviceInfo());
bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName);
bool switchAudioDevice(QAudio::Mode mode, const QString& deviceName, bool isHmd);
// Qt opensles plugin is not able to detect when the headset is plugged in
void setHeadsetPluggedIn(bool pluggedIn);

View file

@ -22,15 +22,14 @@ HifiAudioDeviceInfo& HifiAudioDeviceInfo::operator=(const HifiAudioDeviceInfo& o
_audioDeviceInfo = other.getDevice();
_mode = other.getMode();
_isDefault = other.isDefault();
_deviceType = other.getDeviceType();
return *this;
}
bool HifiAudioDeviceInfo::operator==(const HifiAudioDeviceInfo& rhs) const {
//Does the QAudioDeviceinfo match as well as is this the default device or
return getDevice() == rhs.getDevice() && isDefault() == rhs.isDefault();
}
bool HifiAudioDeviceInfo::operator!=(const HifiAudioDeviceInfo& rhs) const {
return getDevice() != rhs.getDevice() || isDefault() != rhs.isDefault();
}
}

View file

@ -23,19 +23,27 @@ class HifiAudioDeviceInfo : public QObject {
Q_OBJECT
public:
enum DeviceType {
desktop,
hmd,
both
};
HifiAudioDeviceInfo() : QObject() {}
HifiAudioDeviceInfo(const HifiAudioDeviceInfo &deviceInfo) : QObject(){
_audioDeviceInfo = deviceInfo.getDevice();
_mode = deviceInfo.getMode();
_isDefault = deviceInfo.isDefault();
_deviceType = deviceInfo.getDeviceType();
}
HifiAudioDeviceInfo(QAudioDeviceInfo deviceInfo, bool isDefault, QAudio::Mode mode) :
HifiAudioDeviceInfo(QAudioDeviceInfo deviceInfo, bool isDefault, QAudio::Mode mode, DeviceType devType=both) :
_audioDeviceInfo(deviceInfo),
_isDefault(isDefault),
_mode(mode){
_mode(mode),
_deviceType(devType){
}
void setMode(QAudio::Mode mode) { _mode = mode; }
void setIsDefault() { _isDefault = true; }
void setDevice(QAudioDeviceInfo devInfo);
@ -52,7 +60,7 @@ public:
QAudioDeviceInfo getDevice() const { return _audioDeviceInfo; }
bool isDefault() const { return _isDefault; }
QAudio::Mode getMode() const { return _mode; }
DeviceType getDeviceType() const { return _deviceType; }
HifiAudioDeviceInfo& operator=(const HifiAudioDeviceInfo& other);
bool operator==(const HifiAudioDeviceInfo& rhs) const;
bool operator!=(const HifiAudioDeviceInfo& rhs) const;
@ -61,6 +69,7 @@ private:
QAudioDeviceInfo _audioDeviceInfo;
bool _isDefault { false };
QAudio::Mode _mode { QAudio::AudioInput };
DeviceType _deviceType{ both };
public:
static const QString DEFAULT_DEVICE_NAME;

View file

@ -165,9 +165,6 @@ AvatarTransit::Status AvatarTransit::update(float deltaTime, const glm::vec3& av
_status = Status::ENDED;
}
if (previousStatus != _status) {
qDebug(avatars_renderer) << "AvatarTransit " << avatarTransitStatusToStringMap[(int)previousStatus] << "->" << avatarTransitStatusToStringMap[_status];
}
return _status;
}

View file

@ -96,10 +96,16 @@ void Head::simulate(float deltaTime) {
// no blinking when brows are raised; blink less with increasing loudness
const float BASE_BLINK_RATE = 15.0f / 60.0f;
const float ROOT_LOUDNESS_TO_BLINK_INTERVAL = 0.25f;
if (forceBlink || (_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) *
if (_forceBlinkToRetarget || forceBlink ||
(_browAudioLift < EPSILON && shouldDo(glm::max(1.0f, sqrt(fabs(_averageLoudness - _longTermAverageLoudness)) *
ROOT_LOUDNESS_TO_BLINK_INTERVAL) / BASE_BLINK_RATE, deltaTime))) {
float randSpeedVariability = randFloat();
float eyeBlinkVelocity = BLINK_SPEED + randSpeedVariability * BLINK_SPEED_VARIABILITY;
if (_forceBlinkToRetarget) {
// Slow down by half the blink if reseting eye target
eyeBlinkVelocity = 0.5f * eyeBlinkVelocity;
_forceBlinkToRetarget = false;
}
_leftEyeBlinkVelocity = eyeBlinkVelocity;
_rightEyeBlinkVelocity = eyeBlinkVelocity;
if (randFloat() < 0.5f) {
@ -114,13 +120,12 @@ void Head::simulate(float deltaTime) {
if (_leftEyeBlink == FULLY_CLOSED) {
_leftEyeBlinkVelocity = -BLINK_SPEED;
updateEyeLookAt();
} else if (_leftEyeBlink == FULLY_OPEN) {
_leftEyeBlinkVelocity = 0.0f;
}
if (_rightEyeBlink == FULLY_CLOSED) {
_rightEyeBlinkVelocity = -BLINK_SPEED;
} else if (_rightEyeBlink == FULLY_OPEN) {
_rightEyeBlinkVelocity = 0.0f;
}
@ -350,3 +355,24 @@ float Head::getFinalPitch() const {
float Head::getFinalRoll() const {
return glm::clamp(_baseRoll + _deltaRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL);
}
void Head::setLookAtPosition(const glm::vec3& lookAtPosition) {
if (_isEyeLookAtUpdated && _requestLookAtPosition != lookAtPosition) {
_lookAtPositionChanged = usecTimestampNow();
glm::vec3 oldAvatarLookAtVector = _requestLookAtPosition - _owningAvatar->getWorldPosition();
glm::vec3 newAvatarLookAtVector = lookAtPosition - _owningAvatar->getWorldPosition();
const float MIN_BLINK_ANGLE = 0.35f; // 20 degrees
_forceBlinkToRetarget = angleBetween(oldAvatarLookAtVector, newAvatarLookAtVector) > MIN_BLINK_ANGLE;
if (_forceBlinkToRetarget) {
_isEyeLookAtUpdated = false;
} else {
_lookAtPosition = lookAtPosition;
}
}
_requestLookAtPosition = lookAtPosition;
}
void Head::updateEyeLookAt() {
_lookAtPosition = _requestLookAtPosition;
_isEyeLookAtUpdated = true;
}

View file

@ -79,6 +79,9 @@ public:
float getTimeWithoutTalking() const { return _timeWithoutTalking; }
virtual void setLookAtPosition(const glm::vec3& lookAtPosition) override;
void updateEyeLookAt();
protected:
// disallow copies of the Head, copy of owning Avatar is disallowed too
Head(const Head&);
@ -123,6 +126,10 @@ protected:
int _leftEyeLookAtID;
int _rightEyeLookAtID;
glm::vec3 _requestLookAtPosition;
bool _forceBlinkToRetarget { false };
bool _isEyeLookAtUpdated { false };
// private methods
void calculateMouthShapes(float timeRatio);
void applyEyelidOffset(glm::quat headOrientation);

View file

@ -3214,3 +3214,12 @@ void AvatarData::clearAvatarGrabData(const QUuid& grabID) {
}
});
}
glm::vec3 AvatarData::getHeadJointFrontVector() const {
int headJointIndex = getJointIndex("Head");
glm::quat headJointRotation = Quaternions::Y_180 * getAbsoluteJointRotationInObjectFrame(headJointIndex);// getAbsoluteJointRotationInRigFrame(headJointIndex, headJointRotation);
headJointRotation = getWorldOrientation() * headJointRotation;
float headYaw = safeEulerAngles(headJointRotation).y;
glm::quat headYawRotation = glm::angleAxis(headYaw, Vectors::UP);
return headYawRotation * IDENTITY_FORWARD;
}

View file

@ -1484,6 +1484,7 @@ public:
std::vector<AvatarSkeletonTrait::UnpackedJointData> getSkeletonData() const;
void sendSkeletonData() const;
QVector<JointData> getJointData() const;
glm::vec3 getHeadJointFrontVector() const;
signals:

View file

@ -64,7 +64,7 @@ public:
void setBlendshapeCoefficients(const QVector<float>& blendshapeCoefficients) { _blendshapeCoefficients = blendshapeCoefficients; }
const glm::vec3& getLookAtPosition() const { return _lookAtPosition; }
void setLookAtPosition(const glm::vec3& lookAtPosition) {
virtual void setLookAtPosition(const glm::vec3& lookAtPosition) {
if (_lookAtPosition != lookAtPosition) {
_lookAtPositionChanged = usecTimestampNow();
}

View file

@ -13,6 +13,7 @@
#include <QtCore/QDir>
#include <QtCore/QDebug>
#include <QtCore/QPluginLoader>
#include <shared/QtHelpers.h>
//#define HIFI_PLUGINMANAGER_DEBUG
#if defined(HIFI_PLUGINMANAGER_DEBUG)
@ -21,6 +22,7 @@
#include <DependencyManager.h>
#include <UserActivityLogger.h>
#include <QThreadPool>
#include "RuntimePlugin.h"
#include "CodecPlugin.h"
@ -221,7 +223,17 @@ const OculusPlatformPluginPointer PluginManager::getOculusPlatformPlugin() {
return oculusPlatformPlugin;
}
const DisplayPluginList& PluginManager::getDisplayPlugins() {
DisplayPluginList PluginManager::getAllDisplayPlugins() {
if (thread() != QThread::currentThread()) {
DisplayPluginList list;
QMetaObject::invokeMethod(this, "getAllDisplayPlugins", Qt::BlockingQueuedConnection, Q_RETURN_ARG(DisplayPluginList, list));
return list;
} else {
return _displayPlugins;
}
}
const DisplayPluginList& PluginManager::getDisplayPlugins() {
static std::once_flag once;
static auto deviceAddedCallback = [](QString deviceName) {
qCDebug(plugins) << "Added device: " << deviceName;

View file

@ -51,6 +51,7 @@ public:
using PluginFilter = std::function<bool(const QJsonObject&)>;
void setPluginFilter(PluginFilter pluginFilter) { _pluginFilter = pluginFilter; }
Q_INVOKABLE DisplayPluginList getAllDisplayPlugins();
signals:
void inputDeviceRunningChanged(const QString& pluginName, bool isRunning, const QStringList& runningDevices);

View file

@ -377,7 +377,7 @@ function displayInitialLaunchWindow() {
initialLaunchWindow.fromQml.connect(onMessageFromInitialLaunchWindow);
Window.location = "file:///~/serverless/tutorial.json";
Window.location = "file:///~/serverless/empty.json";
}
var SECOND_LAUNCH_QML_PATH = Script.resolvePath("simplifiedFTUE/SecondLaunchWindow.qml");
@ -405,7 +405,7 @@ function displaySecondLaunchWindow() {
secondLaunchWindow.fromQml.connect(onMessageFromSecondLaunchWindow);
Window.location = "file:///~/serverless/tutorial.json";
Window.location = "file:///~/serverless/empty.json";
}
function closeInitialLaunchWindow() {

View file

@ -61,17 +61,21 @@ Item {
Rectangle {
width: 5
height: 5
color: "red"
ColorAnimation on color { loops: Animation.Infinite; from: "red"; to: "yellow"; duration: 1000 }
color: "blue"
ColorAnimation on color { loops: Animation.Infinite; from: "blue"; to: "yellow"; duration: 1000 }
}
WebEngineView {
id: root
url: "https://google.com/"
x: 6; y: 6;
width: parent.width * 0.8
height: parent.height * 0.8
url: "https://www.webrtc-experiment.com/Pluginfree-Screen-Sharing/#19583796789766627"
// url: "https://vimeo.com/108650530"
// url: "https://www.youtube.com/watch?v=7EWQOeQf32U&autoplay=1&loop=1"
// x: 6; y: 6;
anchors.fill: parent
// width: parent.width * 0.8
// height: parent.height * 0.8
}
}

View file

@ -39,7 +39,7 @@ void MacQml::init() {
_surface->load(url, callback);
_surface->resize(_window->size());
_surface->resume();
_window->installEventFilter(_surface.get());
}
void MacQml::draw() {

View file

@ -9,7 +9,7 @@ public:
QmlPtr _surface;
GLuint _fbo{ 0 };
MacQml(const QWindow* window) : Parent(window) {}
MacQml(QWindow* window) : Parent(window) {}
void update() override;
void init() override;
void draw() override;

View file

@ -24,7 +24,7 @@ public:
std::array<std::array<QmlInfo, DIVISIONS_Y>, DIVISIONS_X> _surfaces;
GLuint _fbo{ 0 };
StressWeb(const QWindow* window) : Parent(window) {}
StressWeb(QWindow* window) : Parent(window) {}
static QString getSourceUrl(bool video);
void buildSurface(QmlInfo& qmlInfo, bool video);
void destroySurface(QmlInfo& qmlInfo);

View file

@ -8,8 +8,8 @@
class TestCase {
public:
using QmlPtr = QSharedPointer<hifi::qml::OffscreenSurface>;
using Builder = std::function<TestCase*(const QWindow*)>;
TestCase(const QWindow* window) : _window(window) {}
using Builder = std::function<TestCase*(QWindow*)>;
TestCase(QWindow* window) : _window(window) {}
virtual void init();
virtual void destroy();
virtual void update();
@ -18,6 +18,6 @@ public:
protected:
QOpenGLFunctions_4_1_Core _glf;
const QWindow* _window;
QWindow* _window;
std::function<void(uint32_t, void*)> _discardLamdba;
};

View file

@ -205,12 +205,22 @@ void TestWindow::resizeEvent(QResizeEvent* ev) {
int main(int argc, char** argv) {
#ifdef Q_OS_MAC
auto format = getDefaultOpenGLSurfaceFormat();
format.setVersion(4, 1);
// Deal with some weirdness in the chromium context sharing on Mac.
// The primary share context needs to be 3.2, so that the Chromium will
// succeed in it's creation of it's command stub contexts.
format.setVersion(3, 2);
// This appears to resolve the issues with corrupted fonts on OSX. No
// idea why.
qputenv("QT_ENABLE_GLYPH_CACHE_WORKAROUND", "true");
// https://i.kym-cdn.com/entries/icons/original/000/008/342/ihave.jpg
QSurfaceFormat::setDefaultFormat(format);
#endif
QGuiApplication app(argc, argv);
TestCase::Builder builder = [](const QWindow* window)->TestCase*{ return new MacQml(window); };
TestCase::Builder builder = [](QWindow* window)->TestCase*{ return new MacQml(window); };
TestWindow window(builder);
return app.exec();
}

View file

@ -1,8 +1,10 @@
# General
This document describes the process to build Qt 5.12.3.
Note that there are three patches. The first (to qfloat16.h) is needed to compile QT 5.12.3 on Visual Studio 2017 due to a bug in Visual Studio (*bitset* will not compile. Note that there is a change in CMakeLists.txt to support this.
The second patch is to OpenSL ES audio.
The third is a patch to QScriptEngine to prevent crashes in QScriptEnginePrivate::reportAdditionalMemoryCost, during garbage collection. See https://bugreports.qt.io/browse/QTBUG-76176
Note that there are several patches.
* The first (to qfloat16.h) is needed to compile QT 5.12.3 on Visual Studio 2017 due to a bug in Visual Studio (*bitset* will not compile. Note that there is a change in CMakeLists.txt to support this.
* The second patch is to OpenSL ES audio and allow audio echo cancelllation on Android.
* The third is a patch to QScriptEngine to prevent crashes in QScriptEnginePrivate::reportAdditionalMemoryCost, during garbage collection. See https://bugreports.qt.io/browse/QTBUG-76176
* The fourth is a patch which fixes video playback on WebEngineViews on mac. See https://bugreports.qt.io/browse/QTBUG-70967
## Requirements
### Windows
1. Visual Studio 2017
@ -222,6 +224,7 @@ git clone --recursive git://code.qt.io/qt/qt5.git -b 5.12.3 --single-branch
`cd qt5`
`git apply --ignore-space-change --ignore-whitespace patches/aec.patch`
`git apply --ignore-space-change --ignore-whitespace patches/qtscript-crash-fix.patch`
`git apply --ignore-space-change --ignore-whitespace patches/mac-web-video.patch`
`cd ..`
#### Configuring
`mkdir qt5-install`

View file

@ -0,0 +1,247 @@
Submodule qtwebengine contains modified content
diff --git a/qtwebengine/src/core/stream_video_node.cpp b/qtwebengine/src/core/stream_video_node.cpp
index 29922f86..baa39d3b 100644
--- a/qtwebengine/src/core/stream_video_node.cpp
+++ b/qtwebengine/src/core/stream_video_node.cpp
@@ -62,38 +62,45 @@ protected:
const char *vertexShader() const override {
// Keep in sync with cc::VertexShaderVideoTransform
static const char *shader =
- "attribute highp vec4 a_position;\n"
- "attribute mediump vec2 a_texCoord;\n"
- "uniform highp mat4 matrix;\n"
- "uniform highp mat4 texMatrix;\n"
- "varying mediump vec2 v_texCoord;\n"
- "void main() {\n"
- " gl_Position = matrix * a_position;\n"
- " v_texCoord = vec4(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0)).xy;\n"
- "}";
+ R"SHADER(#version 150 core
+in vec4 a_position;
+in vec2 a_texCoord;
+uniform mat4 matrix;
+uniform mat4 texMatrix;
+out vec2 v_texCoord;
+void main() {
+ gl_Position = matrix * a_position;
+ v_texCoord = vec4(texMatrix * vec4(a_texCoord.x, 1.0 - a_texCoord.y, 0.0, 1.0)).xy;
+}
+ )SHADER";
return shader;
}
const char *fragmentShader() const override {
// Keep in sync with cc::FragmentShaderRGBATexAlpha
static const char *shaderExternal =
- "#extension GL_OES_EGL_image_external : require\n"
- "varying mediump vec2 v_texCoord;\n"
- "uniform samplerExternalOES s_texture;\n"
- "uniform lowp float alpha;\n"
- "void main() {\n"
- " lowp vec4 texColor = texture2D(s_texture, v_texCoord);\n"
- " gl_FragColor = texColor * alpha;\n"
- "}";
+ R"SHADER(#version 150 core
+#extension GL_OES_EGL_image_external : require
+in vec2 v_texCoord;
+uniform samplerExternalOES s_texture;
+uniform float alpha;
+out vec4 fragColor;
+void main() {
+ vec4 texColor = texture(s_texture, v_texCoord);
+ fragColor = texColor * alpha;
+}
+ )SHADER";
static const char *shader2DRect =
- "#extension GL_ARB_texture_rectangle : require\n"
- "varying mediump vec2 v_texCoord;\n"
- "uniform sampler2DRect s_texture;\n"
- "uniform lowp float alpha;\n"
- "void main() {\n"
- " lowp vec4 texColor = texture2DRect(s_texture, v_texCoord);\n"
- " gl_FragColor = texColor * alpha;\n"
- "}";
+ R"SHADER(#version 150 core
+in vec2 v_texCoord;
+uniform sampler2D s_texture;
+uniform float alpha;
+out vec4 fragColor;
+void main() {
+ vec4 texColor = texture(s_texture, v_texCoord);
+ fragColor = texColor * alpha;
+}
+ )SHADER";
if (m_target == ExternalTarget)
return shaderExternal;
else
diff --git a/qtwebengine/src/core/yuv_video_node.cpp b/qtwebengine/src/core/yuv_video_node.cpp
index 4a436d95..dc4b6ff9 100644
--- a/qtwebengine/src/core/yuv_video_node.cpp
+++ b/qtwebengine/src/core/yuv_video_node.cpp
@@ -59,39 +59,41 @@ public:
YUVVideoMaterialShader(const gfx::ColorSpace &colorSpace)
{
static const char *shaderHead =
- "varying mediump vec2 v_yaTexCoord;\n"
- "varying mediump vec2 v_uvTexCoord;\n"
- "uniform sampler2D y_texture;\n"
- "uniform sampler2D u_texture;\n"
- "uniform sampler2D v_texture;\n"
- "uniform mediump float alpha;\n"
- "uniform mediump vec4 ya_clamp_rect;\n"
- "uniform mediump vec4 uv_clamp_rect;\n";
- static const char *shader =
- "void main() {\n"
- " mediump vec2 ya_clamped =\n"
- " max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));\n"
- " mediump float y_raw = texture2D(y_texture, ya_clamped).x;\n"
- " mediump vec2 uv_clamped =\n"
- " max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));\n"
- " mediump float u_unsigned = texture2D(u_texture, uv_clamped).x;\n"
- " mediump float v_unsigned = texture2D(v_texture, uv_clamped).x;\n"
- " mediump vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);\n"
- " mediump vec3 rgb = DoColorConversion(yuv);\n"
- " gl_FragColor = vec4(rgb, 1.0) * alpha;\n"
- "}";
+ R"SHADER(#version 150 core
+in vec2 v_yaTexCoord;
+in vec2 v_uvTexCoord;
+uniform sampler2D y_texture;
+uniform sampler2D u_texture;
+uniform sampler2D v_texture;
+uniform float alpha;
+uniform vec4 ya_clamp_rect;
+uniform vec4 uv_clamp_rect;
+out vec4 fragColor;
+ )SHADER";
+
+ static const char *shader = R"SHADER(
+void main() {
+ vec2 ya_clamped =
+ max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));
+ float y_raw = texture(y_texture, ya_clamped).x;
+ vec2 uv_clamped =
+ max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));
+ float u_unsigned = texture(u_texture, uv_clamped).x;
+ float v_unsigned = texture(v_texture, uv_clamped).x;
+ vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);
+ vec3 rgb = DoColorConversion(yuv);
+ fragColor = vec4(rgb, 1.0) * alpha;
+}
+ )SHADER";
+
// Invalid or unspecified color spaces should be treated as REC709.
gfx::ColorSpace src = colorSpace.IsValid() ? colorSpace : gfx::ColorSpace::CreateREC709();
gfx::ColorSpace dst = gfx::ColorSpace::CreateSRGB();
std::unique_ptr<gfx::ColorTransform> transform =
gfx::ColorTransform::NewColorTransform(src, dst, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
- QByteArray header(shaderHead);
- if (QOpenGLContext::currentContext()->isOpenGLES())
- header = QByteArray("precision mediump float;\n") + header;
-
m_csShader = QByteArray::fromStdString(transform->GetShaderSource());
- m_fragmentShader = header + m_csShader + QByteArray(shader);
+ m_fragmentShader = QByteArray(shaderHead) + m_csShader + QByteArray(shader);
}
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
@@ -108,20 +110,22 @@ protected:
const char *vertexShader() const override {
// Keep in sync with logic in VertexShader in components/viz/service/display/shader.cc
const char *shader =
- "attribute highp vec4 a_position;\n"
- "attribute mediump vec2 a_texCoord;\n"
- "uniform highp mat4 matrix;\n"
- "varying mediump vec2 v_yaTexCoord;\n"
- "varying mediump vec2 v_uvTexCoord;\n"
- "uniform mediump vec2 yaTexScale;\n"
- "uniform mediump vec2 yaTexOffset;\n"
- "uniform mediump vec2 uvTexScale;\n"
- "uniform mediump vec2 uvTexOffset;\n"
- "void main() {\n"
- " gl_Position = matrix * a_position;\n"
- " v_yaTexCoord = a_texCoord * yaTexScale + yaTexOffset;\n"
- " v_uvTexCoord = a_texCoord * uvTexScale + uvTexOffset;\n"
- "}";
+ R"SHADER(#version 150 core
+in vec4 a_position;
+in vec2 a_texCoord;
+uniform mat4 matrix;
+out vec2 v_yaTexCoord;
+out vec2 v_uvTexCoord;
+uniform vec2 yaTexScale;
+uniform vec2 yaTexOffset;
+uniform vec2 uvTexScale;
+uniform vec2 uvTexOffset;
+void main() {
+ gl_Position = matrix * a_position;
+ v_yaTexCoord = a_texCoord * yaTexScale + yaTexOffset;
+ v_uvTexCoord = a_texCoord * uvTexScale + uvTexOffset;
+}
+ )SHADER";
return shader;
}
@@ -168,33 +172,35 @@ public:
YUVAVideoMaterialShader(const gfx::ColorSpace &colorSpace) : YUVVideoMaterialShader(colorSpace)
{
static const char *shaderHead =
- "varying mediump vec2 v_yaTexCoord;\n"
- "varying mediump vec2 v_uvTexCoord;\n"
- "uniform sampler2D y_texture;\n"
- "uniform sampler2D u_texture;\n"
- "uniform sampler2D v_texture;\n"
- "uniform sampler2D a_texture;\n"
- "uniform mediump float alpha;\n"
- "uniform mediump vec4 ya_clamp_rect;\n"
- "uniform mediump vec4 uv_clamp_rect;\n";
+ R"SHADER(#version 150 core
+in vec2 v_yaTexCoord;
+in vec2 v_uvTexCoord;
+uniform sampler2D y_texture;
+uniform sampler2D u_texture;
+uniform sampler2D v_texture;
+uniform sampler2D a_texture;
+uniform float alpha;
+uniform vec4 ya_clamp_rect;
+uniform vec4 uv_clamp_rect;
+out vec4 fragColor;
+ )SHADER";
static const char *shader =
- "void main() {\n"
- " mediump vec2 ya_clamped =\n"
- " max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));\n"
- " mediump float y_raw = texture2D(y_texture, ya_clamped).x;\n"
- " mediump vec2 uv_clamped =\n"
- " max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));\n"
- " mediump float u_unsigned = texture2D(u_texture, uv_clamped).x;\n"
- " mediump float v_unsigned = texture2D(v_texture, uv_clamped).x;\n"
- " mediump float a_raw = texture2D(a_texture, ya_clamped).x;\n"
- " mediump vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);\n"
- " mediump vec3 rgb = DoColorConversion(yuv);\n"
- " gl_FragColor = vec4(rgb, 1.0) * (alpha * a_raw);\n"
- "}";
- QByteArray header(shaderHead);
- if (QOpenGLContext::currentContext()->isOpenGLES())
- header = QByteArray("precision mediump float;\n") + header;
- m_fragmentShader = header + m_csShader + QByteArray(shader);
+ R"SHADER(
+void main() {
+ vec2 ya_clamped =
+ max(ya_clamp_rect.xy, min(ya_clamp_rect.zw, v_yaTexCoord));
+ float y_raw = texture(y_texture, ya_clamped).x;
+ vec2 uv_clamped =
+ max(uv_clamp_rect.xy, min(uv_clamp_rect.zw, v_uvTexCoord));
+ float u_unsigned = texture(u_texture, uv_clamped).x;
+ float v_unsigned = texture(v_texture, uv_clamped).x;
+ float a_raw = texture(a_texture, ya_clamped).x;
+ vec3 yuv = vec3(y_raw, u_unsigned, v_unsigned);
+ vec3 rgb = DoColorConversion(yuv);
+ fragColor = vec4(rgb, 1.0) * (alpha * a_raw);
+}
+ )SHADER";
+ m_fragmentShader = QByteArray(shaderHead) + m_csShader + QByteArray(shader);
}
void updateState(const RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;