Merge branch 'master' of https://github.com/highfidelity/hifi into particleExplorerOptionalPropFix

This commit is contained in:
David Back 2018-06-29 10:34:17 -07:00
commit 328bf37f64
27 changed files with 191 additions and 167 deletions

View file

@ -228,7 +228,7 @@ Java_io_highfidelity_hifiinterface_fragment_LoginFragment_nativeLogin(JNIEnv *en
env->ReleaseStringUTFChars(username_, c_username); env->ReleaseStringUTFChars(username_, c_username);
env->ReleaseStringUTFChars(password_, c_password); env->ReleaseStringUTFChars(password_, c_password);
auto accountManager = AndroidHelper::instance().getAccountManager(); auto accountManager = DependencyManager::get<AccountManager>();
__loginCompletedListener = QAndroidJniObject(instance); __loginCompletedListener = QAndroidJniObject(instance);
__usernameChangedListener = QAndroidJniObject(usernameChangedListener); __usernameChangedListener = QAndroidJniObject(usernameChangedListener);
@ -270,18 +270,18 @@ Java_io_highfidelity_hifiinterface_SplashActivity_registerLoadCompleteListener(J
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_io_highfidelity_hifiinterface_MainActivity_nativeIsLoggedIn(JNIEnv *env, jobject instance) { Java_io_highfidelity_hifiinterface_MainActivity_nativeIsLoggedIn(JNIEnv *env, jobject instance) {
return AndroidHelper::instance().getAccountManager()->isLoggedIn(); return DependencyManager::get<AccountManager>()->isLoggedIn();
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_io_highfidelity_hifiinterface_MainActivity_nativeLogout(JNIEnv *env, jobject instance) { Java_io_highfidelity_hifiinterface_MainActivity_nativeLogout(JNIEnv *env, jobject instance) {
AndroidHelper::instance().getAccountManager()->logout(); DependencyManager::get<AccountManager>()->logout();
} }
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
Java_io_highfidelity_hifiinterface_MainActivity_nativeGetDisplayName(JNIEnv *env, Java_io_highfidelity_hifiinterface_MainActivity_nativeGetDisplayName(JNIEnv *env,
jobject instance) { jobject instance) {
QString username = AndroidHelper::instance().getAccountManager()->getAccountInfo().getUsername(); QString username = DependencyManager::get<AccountManager>()->getAccountInfo().getUsername();
return env->NewStringUTF(username.toLatin1().data()); return env->NewStringUTF(username.toLatin1().data());
} }

View file

@ -129,12 +129,10 @@ Rectangle {
id: stereoMic id: stereoMic
spacing: muteMic.spacing; spacing: muteMic.spacing;
text: qsTr("Enable stereo input"); text: qsTr("Enable stereo input");
checked: AudioScriptingInterface.isStereoInput(); checked: AudioScriptingInterface.isStereoInput;
onClicked: { onClicked: {
var success = AudioScriptingInterface.setStereoInput(checked); AudioScriptingInterface.isStereoInput = checked;
if (!success) { checked = Qt.binding(function() { return AudioScriptingInterface.isStereoInput; }); // restore binding
checked = !checked;
}
} }
} }
} }

View file

@ -17,7 +17,7 @@ PreferencesDialog {
id: root id: root
objectName: "GeneralPreferencesDialog" objectName: "GeneralPreferencesDialog"
title: "General Settings" title: "General Settings"
showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"] showCategories: ["User Interface", "Mouse Sensitivity", "HMD", "Snapshots", "Privacy"]
property var settings: Settings { property var settings: Settings {
category: root.objectName category: root.objectName
property alias x: root.x property alias x: root.x

View file

@ -32,6 +32,6 @@ StackView {
TabletPreferencesDialog { TabletPreferencesDialog {
id: root id: root
objectName: "TabletGeneralPreferences" objectName: "TabletGeneralPreferences"
showCategories: ["User Interface", "HMD", "Snapshots", "Privacy"] showCategories: ["User Interface", "Mouse Sensitivity", "HMD", "Snapshots", "Privacy"]
} }
} }

View file

@ -10,31 +10,11 @@
// //
#include "AndroidHelper.h" #include "AndroidHelper.h"
#include <QDebug> #include <QDebug>
#include <AccountManager.h>
AndroidHelper::AndroidHelper() { AndroidHelper::AndroidHelper() {
} }
AndroidHelper::~AndroidHelper() { AndroidHelper::~AndroidHelper() {
workerThread.quit();
workerThread.wait();
}
void AndroidHelper::init() {
workerThread.start();
_accountManager = QSharedPointer<AccountManager>(new AccountManager, &QObject::deleteLater);
_accountManager->setIsAgent(true);
_accountManager->setAuthURL(NetworkingConstants::METAVERSE_SERVER_URL());
_accountManager->setSessionID(DependencyManager::get<AccountManager>()->getSessionID());
connect(_accountManager.data(), &AccountManager::loginComplete, [](const QUrl& authURL) {
DependencyManager::get<AccountManager>()->setAccountInfo(AndroidHelper::instance().getAccountManager()->getAccountInfo());
DependencyManager::get<AccountManager>()->setAuthURL(authURL);
});
connect(_accountManager.data(), &AccountManager::logoutComplete, [] () {
DependencyManager::get<AccountManager>()->logout();
});
_accountManager->moveToThread(&workerThread);
} }
void AndroidHelper::requestActivity(const QString &activityName, const bool backToScene) { void AndroidHelper::requestActivity(const QString &activityName, const bool backToScene) {

View file

@ -13,8 +13,6 @@
#define hifi_Android_Helper_h #define hifi_Android_Helper_h
#include <QObject> #include <QObject>
#include <QThread>
#include <AccountManager.h>
class AndroidHelper : public QObject { class AndroidHelper : public QObject {
Q_OBJECT Q_OBJECT
@ -23,7 +21,6 @@ public:
static AndroidHelper instance; static AndroidHelper instance;
return instance; return instance;
} }
void init();
void requestActivity(const QString &activityName, const bool backToScene); void requestActivity(const QString &activityName, const bool backToScene);
void notifyLoadComplete(); void notifyLoadComplete();
void notifyEnterForeground(); void notifyEnterForeground();
@ -31,7 +28,6 @@ public:
void performHapticFeedback(int duration); void performHapticFeedback(int duration);
QSharedPointer<AccountManager> getAccountManager() { return _accountManager; }
AndroidHelper(AndroidHelper const&) = delete; AndroidHelper(AndroidHelper const&) = delete;
void operator=(AndroidHelper const&) = delete; void operator=(AndroidHelper const&) = delete;
@ -49,8 +45,6 @@ signals:
private: private:
AndroidHelper(); AndroidHelper();
~AndroidHelper(); ~AndroidHelper();
QSharedPointer<AccountManager> _accountManager;
QThread workerThread;
}; };
#endif #endif

View file

@ -2259,7 +2259,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID()); qCDebug(interfaceapp) << "Metaverse session ID is" << uuidStringWithoutCurlyBraces(accountManager->getSessionID());
#if defined(Q_OS_ANDROID) #if defined(Q_OS_ANDROID)
AndroidHelper::instance().init();
connect(&AndroidHelper::instance(), &AndroidHelper::enterBackground, this, &Application::enterBackground); connect(&AndroidHelper::instance(), &AndroidHelper::enterBackground, this, &Application::enterBackground);
connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground); connect(&AndroidHelper::instance(), &AndroidHelper::enterForeground, this, &Application::enterForeground);
AndroidHelper::instance().notifyLoadComplete(); AndroidHelper::instance().notifyLoadComplete();

View file

@ -36,13 +36,13 @@
#include <SettingHandle.h> #include <SettingHandle.h>
#include <UsersScriptingInterface.h> #include <UsersScriptingInterface.h>
#include <UUID.h> #include <UUID.h>
#include <avatars-renderer/OtherAvatar.h>
#include <shared/ConicalViewFrustum.h> #include <shared/ConicalViewFrustum.h>
#include "Application.h" #include "Application.h"
#include "InterfaceLogging.h" #include "InterfaceLogging.h"
#include "Menu.h" #include "Menu.h"
#include "MyAvatar.h" #include "MyAvatar.h"
#include "OtherAvatar.h"
#include "SceneScriptingInterface.h" #include "SceneScriptingInterface.h"
// 50 times per second - target is 45hz, but this helps account for any small deviations // 50 times per second - target is 45hz, but this helps account for any small deviations
@ -192,6 +192,15 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
while (!sortedAvatars.empty()) { while (!sortedAvatars.empty()) {
const SortableAvatar& sortData = sortedAvatars.top(); const SortableAvatar& sortData = sortedAvatars.top();
const auto avatar = std::static_pointer_cast<Avatar>(sortData.getAvatar()); const auto avatar = std::static_pointer_cast<Avatar>(sortData.getAvatar());
const auto otherAvatar = std::static_pointer_cast<OtherAvatar>(sortData.getAvatar());
// if the geometry is loaded then turn off the orb
if (avatar->getSkeletonModel()->isLoaded()) {
// remove the orb if it is there
otherAvatar->removeOrb();
} else {
otherAvatar->updateOrbPosition();
}
bool ignoring = DependencyManager::get<NodeList>()->isPersonalMutingNode(avatar->getID()); bool ignoring = DependencyManager::get<NodeList>()->isPersonalMutingNode(avatar->getID());
if (ignoring) { if (ignoring) {

View file

@ -1098,7 +1098,6 @@ void MyAvatar::saveData() {
settings.setValue("displayName", _displayName); settings.setValue("displayName", _displayName);
settings.setValue("collisionSoundURL", _collisionSoundURL); settings.setValue("collisionSoundURL", _collisionSoundURL);
settings.setValue("useSnapTurn", _useSnapTurn); settings.setValue("useSnapTurn", _useSnapTurn);
settings.setValue("clearOverlayWhenMoving", _clearOverlayWhenMoving);
settings.setValue("userHeight", getUserHeight()); settings.setValue("userHeight", getUserHeight());
settings.setValue("enabledFlying", getFlyingEnabled()); settings.setValue("enabledFlying", getFlyingEnabled());
@ -1254,7 +1253,6 @@ void MyAvatar::loadData() {
setDisplayName(settings.value("displayName").toString()); setDisplayName(settings.value("displayName").toString());
setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString()); setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString());
setSnapTurn(settings.value("useSnapTurn", _useSnapTurn).toBool()); setSnapTurn(settings.value("useSnapTurn", _useSnapTurn).toBool());
setClearOverlayWhenMoving(settings.value("clearOverlayWhenMoving", _clearOverlayWhenMoving).toBool());
setDominantHand(settings.value("dominantHand", _dominantHand).toString().toLower()); setDominantHand(settings.value("dominantHand", _dominantHand).toString().toLower());
setUserHeight(settings.value("userHeight", DEFAULT_AVATAR_HEIGHT).toDouble()); setUserHeight(settings.value("userHeight", DEFAULT_AVATAR_HEIGHT).toDouble());
settings.endGroup(); settings.endGroup();

View file

@ -250,7 +250,7 @@ public:
Q_ENUM(DriveKeys) Q_ENUM(DriveKeys)
explicit MyAvatar(QThread* thread); explicit MyAvatar(QThread* thread);
~MyAvatar(); virtual ~MyAvatar();
void instantiableAvatar() override {}; void instantiableAvatar() override {};
void registerMetaTypes(ScriptEnginePointer engine); void registerMetaTypes(ScriptEnginePointer engine);
@ -469,16 +469,6 @@ public:
* @param {boolean} on * @param {boolean} on
*/ */
Q_INVOKABLE void setSnapTurn(bool on) { _useSnapTurn = on; } Q_INVOKABLE void setSnapTurn(bool on) { _useSnapTurn = on; }
/**jsdoc
* @function MyAvatar.getClearOverlayWhenMoving
* @returns {boolean}
*/
Q_INVOKABLE bool getClearOverlayWhenMoving() const { return _clearOverlayWhenMoving; }
/**jsdoc
* @function MyAvatar.setClearOverlayWhenMoving
* @param {boolean} on
*/
Q_INVOKABLE void setClearOverlayWhenMoving(bool on) { _clearOverlayWhenMoving = on; }
/**jsdoc /**jsdoc
@ -1496,7 +1486,6 @@ private:
ThreadSafeValueCache<QUrl> _prefOverrideAnimGraphUrl; ThreadSafeValueCache<QUrl> _prefOverrideAnimGraphUrl;
QUrl _fstAnimGraphOverrideUrl; QUrl _fstAnimGraphOverrideUrl;
bool _useSnapTurn { true }; bool _useSnapTurn { true };
bool _clearOverlayWhenMoving { true };
QString _dominantHand { DOMINANT_RIGHT_HAND }; QString _dominantHand { DOMINANT_RIGHT_HAND };
const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // degrees const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // degrees

View file

@ -0,0 +1,60 @@
//
// Created by Bradley Austin Davis on 2017/04/27
// Copyright 2013-2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "OtherAvatar.h"
#include "Application.h"
OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) {
// give the pointer to our head to inherited _headData variable from AvatarData
_headData = new Head(this);
_skeletonModel = std::make_shared<SkeletonModel>(this, nullptr);
_skeletonModel->setLoadingPriority(OTHERAVATAR_LOADING_PRIORITY);
connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished);
connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady);
connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset);
// add the purple orb
createOrb();
}
OtherAvatar::~OtherAvatar() {
removeOrb();
}
void OtherAvatar::removeOrb() {
if (qApp->getOverlays().isAddedOverlay(_otherAvatarOrbMeshPlaceholderID)) {
qApp->getOverlays().deleteOverlay(_otherAvatarOrbMeshPlaceholderID);
}
}
void OtherAvatar::updateOrbPosition() {
if (_otherAvatarOrbMeshPlaceholder != nullptr) {
_otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition());
}
}
void OtherAvatar::createOrb() {
if (_otherAvatarOrbMeshPlaceholderID == UNKNOWN_OVERLAY_ID ||
!qApp->getOverlays().isAddedOverlay(_otherAvatarOrbMeshPlaceholderID)) {
_otherAvatarOrbMeshPlaceholder = std::make_shared<Sphere3DOverlay>();
_otherAvatarOrbMeshPlaceholder->setAlpha(1.0f);
_otherAvatarOrbMeshPlaceholder->setColor({ 0xFF, 0x00, 0xFF });
_otherAvatarOrbMeshPlaceholder->setIsSolid(false);
_otherAvatarOrbMeshPlaceholder->setPulseMin(0.5);
_otherAvatarOrbMeshPlaceholder->setPulseMax(1.0);
_otherAvatarOrbMeshPlaceholder->setColorPulse(1.0);
_otherAvatarOrbMeshPlaceholder->setIgnoreRayIntersection(true);
_otherAvatarOrbMeshPlaceholder->setDrawInFront(false);
_otherAvatarOrbMeshPlaceholderID = qApp->getOverlays().addOverlay(_otherAvatarOrbMeshPlaceholder);
// Position focus
_otherAvatarOrbMeshPlaceholder->setWorldOrientation(glm::quat(0.0f, 0.0f, 0.0f, 1.0));
_otherAvatarOrbMeshPlaceholder->setWorldPosition(getHead()->getPosition());
_otherAvatarOrbMeshPlaceholder->setDimensions(glm::vec3(0.5f, 0.5f, 0.5f));
_otherAvatarOrbMeshPlaceholder->setVisible(true);
}
}

View file

@ -0,0 +1,32 @@
//
// Created by Bradley Austin Davis on 2017/04/27
// Copyright 2013-2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_OtherAvatar_h
#define hifi_OtherAvatar_h
#include <avatars-renderer/Avatar.h>
#include "ui/overlays/Overlays.h"
#include "ui/overlays/Sphere3DOverlay.h"
#include "InterfaceLogging.h"
class OtherAvatar : public Avatar {
public:
explicit OtherAvatar(QThread* thread);
virtual ~OtherAvatar();
virtual void instantiableAvatar() override { };
virtual void createOrb() override;
void updateOrbPosition();
void removeOrb();
protected:
std::shared_ptr<Sphere3DOverlay> _otherAvatarOrbMeshPlaceholder { nullptr };
OverlayID _otherAvatarOrbMeshPlaceholderID { UNKNOWN_OVERLAY_ID };
};
#endif // hifi_OtherAvatar_h

View file

@ -35,5 +35,8 @@ QVariant SettingsScriptingInterface::getValue(const QString& setting, const QVar
} }
void SettingsScriptingInterface::setValue(const QString& setting, const QVariant& value) { void SettingsScriptingInterface::setValue(const QString& setting, const QVariant& value) {
Setting::Handle<QVariant>(setting).set(value); // Make a deep-copy of the string.
// Dangling pointers can occur with QStrings that are implicitly shared from a QScriptEngine.
QString deepCopy = QString::fromUtf16(setting.utf16());
Setting::Handle<QVariant>(deepCopy).set(value);
} }

View file

@ -88,38 +88,24 @@ void OverlayConductor::update(float dt) {
_hmdMode = false; _hmdMode = false;
} }
bool isAtRest = updateAvatarIsAtRest();
bool isMoving = !isAtRest;
bool shouldRecenter = false; bool shouldRecenter = false;
if (_flags & SuppressedByMove) { if (_suppressedByHead) {
if (!isMoving) { if (updateAvatarIsAtRest()) {
_flags &= ~SuppressedByMove; _suppressedByHead = false;
shouldRecenter = true;
}
} else {
if (myAvatar->getClearOverlayWhenMoving() && isMoving) {
_flags |= SuppressedByMove;
}
}
if (_flags & SuppressedByHead) {
if (isAtRest) {
_flags &= ~SuppressedByHead;
shouldRecenter = true; shouldRecenter = true;
} }
} else { } else {
if (_hmdMode && headOutsideOverlay()) { if (_hmdMode && headOutsideOverlay()) {
_flags |= SuppressedByHead; _suppressedByHead = true;
} }
} }
bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && (0 == (_flags & SuppressMask)); bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && !_suppressedByHead;
if (targetVisible != currentVisible) { if (targetVisible != currentVisible) {
offscreenUi->setPinned(!targetVisible); offscreenUi->setPinned(!targetVisible);
} }
if (shouldRecenter && !_flags) { if (shouldRecenter && !_suppressedByHead) {
centerUI(); centerUI();
} }
} }

View file

@ -25,13 +25,7 @@ private:
bool headOutsideOverlay() const; bool headOutsideOverlay() const;
bool updateAvatarIsAtRest(); bool updateAvatarIsAtRest();
enum SupressionFlags { bool _suppressedByHead { false };
SuppressedByMove = 0x01,
SuppressedByHead = 0x02,
SuppressMask = 0x03,
};
uint8_t _flags { SuppressedByMove };
bool _hmdMode { false }; bool _hmdMode { false };
// used by updateAvatarIsAtRest // used by updateAvatarIsAtRest

View file

@ -161,12 +161,6 @@ void setupPreferences() {
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter)); preferences->addPreference(new CheckPreference(UI_CATEGORY, "Use reticle cursor instead of arrow", getter, setter));
} }
{
auto getter = [=]()->bool { return myAvatar->getClearOverlayWhenMoving(); };
auto setter = [=](bool value) { myAvatar->setClearOverlayWhenMoving(value); };
preferences->addPreference(new CheckPreference(UI_CATEGORY, "Clear overlays when moving", getter, setter));
}
static const QString VIEW_CATEGORY{ "View" }; static const QString VIEW_CATEGORY{ "View" };
{ {
auto getter = [=]()->float { return myAvatar->getRealWorldFieldOfView(); }; auto getter = [=]()->float { return myAvatar->getRealWorldFieldOfView(); };

View file

@ -1426,6 +1426,8 @@ bool AudioClient::setIsStereoInput(bool isStereoInput) {
// restart the input device // restart the input device
switchInputToAudioDevice(_inputDeviceInfo); switchInputToAudioDevice(_inputDeviceInfo);
emit isStereoInputChanged(_isStereoInput);
} }
return stereoInputChanged; return stereoInputChanged;
@ -1463,6 +1465,8 @@ void AudioClient::outputFormatChanged() {
} }
bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) { bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInfo, bool isShutdownRequest) {
Q_ASSERT_X(QThread::currentThread() == thread(), Q_FUNC_INFO, "Function invoked on wrong thread");
qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << inputDeviceInfo.deviceName() << "]"; qCDebug(audioclient) << __FUNCTION__ << "inputDeviceInfo: [" << inputDeviceInfo.deviceName() << "]";
bool supportedFormat = false; bool supportedFormat = false;
@ -1663,6 +1667,8 @@ void AudioClient::outputNotify() {
} }
bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceInfo, bool isShutdownRequest) { bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo 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) << "AudioClient::switchOutputToAudioDevice() outputDeviceInfo: [" << outputDeviceInfo.deviceName() << "]";
bool supportedFormat = false; bool supportedFormat = false;
@ -2021,7 +2027,7 @@ void AudioClient::setAvatarBoundingBoxParameters(glm::vec3 corner, glm::vec3 sca
void AudioClient::startThread() { void AudioClient::startThread() {
moveToNewNamedThread(this, "Audio Thread", [this] { start(); }); moveToNewNamedThread(this, "Audio Thread", [this] { start(); }, QThread::TimeCriticalPriority);
} }
void AudioClient::setInputVolume(float volume, bool emitSignal) { void AudioClient::setInputVolume(float volume, bool emitSignal) {

View file

@ -44,6 +44,9 @@ public slots:
virtual bool setIsStereoInput(bool stereo) = 0; virtual bool setIsStereoInput(bool stereo) = 0;
virtual bool isStereoInput() = 0; virtual bool isStereoInput() = 0;
signals:
void isStereoInputChanged(bool isStereo);
}; };
Q_DECLARE_METATYPE(AbstractAudioInterface*) Q_DECLARE_METATYPE(AbstractAudioInterface*)

View file

@ -1338,6 +1338,9 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const {
} }
void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
if (!isMyAvatar()) {
createOrb();
}
AvatarData::setSkeletonModelURL(skeletonModelURL); AvatarData::setSkeletonModelURL(skeletonModelURL);
if (QThread::currentThread() == thread()) { if (QThread::currentThread() == thread()) {
_skeletonModel->setURL(_skeletonModelURL); _skeletonModel->setURL(_skeletonModelURL);

View file

@ -23,7 +23,6 @@
#include <graphics-scripting/Forward.h> #include <graphics-scripting/Forward.h>
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include "Head.h" #include "Head.h"
#include "SkeletonModel.h" #include "SkeletonModel.h"
#include "Rig.h" #include "Rig.h"
@ -41,7 +40,6 @@ static const float SCALING_RATIO = .05f;
extern const float CHAT_MESSAGE_SCALE; extern const float CHAT_MESSAGE_SCALE;
extern const float CHAT_MESSAGE_HEIGHT; extern const float CHAT_MESSAGE_HEIGHT;
enum ScreenTintLayer { enum ScreenTintLayer {
SCREEN_TINT_BEFORE_LANDSCAPE = 0, SCREEN_TINT_BEFORE_LANDSCAPE = 0,
SCREEN_TINT_BEFORE_AVATARS, SCREEN_TINT_BEFORE_AVATARS,
@ -69,7 +67,7 @@ public:
static void setShowNamesAboveHeads(bool show); static void setShowNamesAboveHeads(bool show);
explicit Avatar(QThread* thread); explicit Avatar(QThread* thread);
~Avatar(); virtual ~Avatar();
virtual void instantiableAvatar() = 0; virtual void instantiableAvatar() = 0;
@ -109,6 +107,7 @@ public:
float getLODDistance() const; float getLODDistance() const;
virtual bool isMyAvatar() const override { return false; } virtual bool isMyAvatar() const override { return false; }
virtual void createOrb() { }
virtual QVector<glm::quat> getJointRotations() const override; virtual QVector<glm::quat> getJointRotations() const override;
using AvatarData::getJointRotation; using AvatarData::getJointRotation;
@ -167,8 +166,8 @@ public:
virtual int parseDataFromBuffer(const QByteArray& buffer) override; virtual int parseDataFromBuffer(const QByteArray& buffer) override;
static void renderJointConnectingCone( gpu::Batch& batch, glm::vec3 position1, glm::vec3 position2, static void renderJointConnectingCone(gpu::Batch& batch, glm::vec3 position1, glm::vec3 position2,
float radius1, float radius2, const glm::vec4& color); float radius1, float radius2, const glm::vec4& color);
virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { } virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { }
@ -235,7 +234,7 @@ public:
/// Scales a world space position vector relative to the avatar position and scale /// Scales a world space position vector relative to the avatar position and scale
/// \param vector position to be scaled. Will store the result /// \param vector position to be scaled. Will store the result
void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const; void scaleVectorRelativeToPosition(glm::vec3& positionToScale) const;
void slamPosition(const glm::vec3& position); void slamPosition(const glm::vec3& position);
virtual void updateAttitude(const glm::quat& orientation) override; virtual void updateAttitude(const glm::quat& orientation) override;
@ -254,7 +253,6 @@ public:
void setPositionViaScript(const glm::vec3& position) override; void setPositionViaScript(const glm::vec3& position) override;
void setOrientationViaScript(const glm::quat& orientation) override; void setOrientationViaScript(const glm::quat& orientation) override;
/**jsdoc /**jsdoc
* @function MyAvatar.getParentID * @function MyAvatar.getParentID
* @returns {Uuid} * @returns {Uuid}
@ -283,7 +281,6 @@ public:
// This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript. // This calls through to the SpatiallyNestable versions, but is here to expose these to JavaScript.
Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override; Q_INVOKABLE virtual void setParentJointIndex(quint16 parentJointIndex) override;
/**jsdoc /**jsdoc
* Returns an array of joints, where each joint is an object containing name, index, and parentIndex fields. * Returns an array of joints, where each joint is an object containing name, index, and parentIndex fields.
* @function MyAvatar.getSkeleton * @function MyAvatar.getSkeleton
@ -349,7 +346,6 @@ public:
// not all subclasses of AvatarData have access to this data. // not all subclasses of AvatarData have access to this data.
virtual bool canMeasureEyeHeight() const override { return true; } virtual bool canMeasureEyeHeight() const override { return true; }
virtual float getModelScale() const { return _modelScale; } virtual float getModelScale() const { return _modelScale; }
virtual void setModelScale(float scale) { _modelScale = scale; } virtual void setModelScale(float scale) { _modelScale = scale; }
virtual glm::vec3 scaleForChildren() const override { return glm::vec3(getModelScale()); } virtual glm::vec3 scaleForChildren() const override { return glm::vec3(getModelScale()); }

View file

@ -1,19 +0,0 @@
//
// Created by Bradley Austin Davis on 2017/04/27
// Copyright 2013-2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "OtherAvatar.h"
OtherAvatar::OtherAvatar(QThread* thread) : Avatar(thread) {
// give the pointer to our head to inherited _headData variable from AvatarData
_headData = new Head(this);
_skeletonModel = std::make_shared<SkeletonModel>(this, nullptr);
_skeletonModel->setLoadingPriority(OTHERAVATAR_LOADING_PRIORITY);
connect(_skeletonModel.get(), &Model::setURLFinished, this, &Avatar::setModelURLFinished);
connect(_skeletonModel.get(), &Model::rigReady, this, &Avatar::rigReady);
connect(_skeletonModel.get(), &Model::rigReset, this, &Avatar::rigReset);
}

View file

@ -1,20 +0,0 @@
//
// Created by Bradley Austin Davis on 2017/04/27
// Copyright 2013-2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_OtherAvatar_h
#define hifi_OtherAvatar_h
#include "Avatar.h"
class OtherAvatar : public Avatar {
public:
explicit OtherAvatar(QThread* thread);
virtual void instantiableAvatar() override {};
};
#endif // hifi_OtherAvatar_h

View file

@ -23,6 +23,21 @@ void registerAudioMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, soundSharedPointerToScriptValue, soundSharedPointerFromScriptValue); qScriptRegisterMetaType(engine, soundSharedPointerToScriptValue, soundSharedPointerFromScriptValue);
} }
void AudioScriptingInterface::setLocalAudioInterface(AbstractAudioInterface* audioInterface) {
if (_localAudioInterface) {
disconnect(_localAudioInterface, &AbstractAudioInterface::isStereoInputChanged,
this, &AudioScriptingInterface::isStereoInputChanged);
}
_localAudioInterface = audioInterface;
if (_localAudioInterface) {
connect(_localAudioInterface, &AbstractAudioInterface::isStereoInputChanged,
this, &AudioScriptingInterface::isStereoInputChanged);
}
}
ScriptAudioInjector* AudioScriptingInterface::playSystemSound(SharedSoundPointer sound, const QVector3D& position) { ScriptAudioInjector* AudioScriptingInterface::playSystemSound(SharedSoundPointer sound, const QVector3D& position) {
AudioInjectorOptions options; AudioInjectorOptions options;
options.position = glm::vec3(position.x(), position.y(), position.z()); options.position = glm::vec3(position.x(), position.y(), position.z());
@ -61,11 +76,10 @@ ScriptAudioInjector* AudioScriptingInterface::playSound(SharedSoundPointer sound
} }
bool AudioScriptingInterface::setStereoInput(bool stereo) { bool AudioScriptingInterface::setStereoInput(bool stereo) {
bool stereoInputChanged = false;
if (_localAudioInterface) { if (_localAudioInterface) {
stereoInputChanged = _localAudioInterface->setIsStereoInput(stereo); QMetaObject::invokeMethod(_localAudioInterface, "setIsStereoInput", Q_ARG(bool, stereo));
} }
return stereoInputChanged; return true;
} }
bool AudioScriptingInterface::isStereoInput() { bool AudioScriptingInterface::isStereoInput() {

View file

@ -23,9 +23,11 @@ class AudioScriptingInterface : public QObject, public Dependency {
Q_OBJECT Q_OBJECT
SINGLETON_DEPENDENCY SINGLETON_DEPENDENCY
Q_PROPERTY(bool isStereoInput READ isStereoInput WRITE setStereoInput NOTIFY isStereoInputChanged)
public: public:
virtual ~AudioScriptingInterface() {} virtual ~AudioScriptingInterface() {}
void setLocalAudioInterface(AbstractAudioInterface* audioInterface) { _localAudioInterface = audioInterface; } void setLocalAudioInterface(AbstractAudioInterface* audioInterface);
protected: protected:
AudioScriptingInterface() {} AudioScriptingInterface() {}
@ -114,6 +116,13 @@ signals:
*/ */
void inputReceived(const QByteArray& inputSamples); void inputReceived(const QByteArray& inputSamples);
/**jsdoc
* @function Audio.isStereoInputChanged
* @param {boolean} isStereo
* @returns {Signal}
*/
void isStereoInputChanged(bool isStereo);
private: private:
AbstractAudioInterface* _localAudioInterface { nullptr }; AbstractAudioInterface* _localAudioInterface { nullptr };
}; };

View file

@ -1639,22 +1639,24 @@ QVariantMap ScriptEngine::fetchModuleSource(const QString& modulePath, const boo
loader->start(MAX_RETRIES); loader->start(MAX_RETRIES);
if (!loader->isFinished()) { if (!loader->isFinished()) {
QTimer monitor; // This lambda can get called AFTER this local scope has completed.
QEventLoop loop; // This is why we pass smart ptrs to the lambda instead of references to local variables.
QObject::connect(loader, &BatchLoader::finished, this, [&monitor, &loop]{ auto monitor = std::make_shared<QTimer>();
monitor.stop(); auto loop = std::make_shared<QEventLoop>();
loop.quit(); QObject::connect(loader, &BatchLoader::finished, this, [monitor, loop] {
monitor->stop();
loop->quit();
}); });
// this helps detect the case where stop() is invoked during the download // this helps detect the case where stop() is invoked during the download
// but not seen in time to abort processing in onload()... // but not seen in time to abort processing in onload()...
connect(&monitor, &QTimer::timeout, this, [this, &loop]{ connect(monitor.get(), &QTimer::timeout, this, [this, loop] {
if (isStopping()) { if (isStopping()) {
loop.exit(-1); loop->exit(-1);
} }
}); });
monitor.start(500); monitor->start(500);
loop.exec(); loop->exec();
} }
loader->deleteLater(); loader->deleteLater();
return req; return req;

View file

@ -44,6 +44,11 @@ void Space::processResets(const Transaction::Resets& transactions) {
for (auto& reset : transactions) { for (auto& reset : transactions) {
// Access the true item // Access the true item
auto proxyID = std::get<0>(reset); auto proxyID = std::get<0>(reset);
// Guard against proxyID being past the end of the list.
if (proxyID < 0 || proxyID >= (int32_t)_proxies.size() || proxyID >= (int32_t)_owners.size()) {
continue;
}
auto& item = _proxies[proxyID]; auto& item = _proxies[proxyID];
// Reset the item with a new payload // Reset the item with a new payload

View file

@ -17,7 +17,6 @@ var SNAPSHOT_DELAY = 500; // 500ms
var FINISH_SOUND_DELAY = 350; var FINISH_SOUND_DELAY = 350;
var resetOverlays; var resetOverlays;
var reticleVisible; var reticleVisible;
var clearOverlayWhenMoving;
var buttonName = "SNAP"; var buttonName = "SNAP";
var buttonConnected = false; var buttonConnected = false;
@ -286,6 +285,7 @@ function printToPolaroid(image_url) {
var polaroid_url = image_url; var polaroid_url = image_url;
var model_pos = Vec3.sum(MyAvatar.position, Vec3.multiply(1.25, Quat.getForward(MyAvatar.orientation))); var model_pos = Vec3.sum(MyAvatar.position, Vec3.multiply(1.25, Quat.getForward(MyAvatar.orientation)));
model_pos.y += 0.2; // Print a bit closer to the head
var model_q1 = MyAvatar.orientation; var model_q1 = MyAvatar.orientation;
var model_q2 = Quat.angleAxis(90, Quat.getRight(model_q1)); var model_q2 = Quat.angleAxis(90, Quat.getRight(model_q1));
@ -295,11 +295,11 @@ function printToPolaroid(image_url) {
"type": 'Model', "type": 'Model',
"shapeType": 'box', "shapeType": 'box',
"name": "New Snapshot", "name": "Snapshot by " + MyAvatar.sessionDisplayName,
"description": "Printed from Snaps", "description": "Printed from SNAP app",
"modelURL": POLAROID_MODEL_URL, "modelURL": POLAROID_MODEL_URL,
"dimensions": { "x": 0.5667, "y": 0.0212, "z": 0.4176 }, "dimensions": { "x": 0.5667, "y": 0.042, "z": 0.4176 },
"position": model_pos, "position": model_pos,
"rotation": model_rot, "rotation": model_rot,
@ -307,9 +307,9 @@ function printToPolaroid(image_url) {
"density": 200, "density": 200,
"restitution": 0.15, "restitution": 0.15,
"gravity": { "x": 0, "y": -4.5, "z": 0 }, "gravity": { "x": 0, "y": -2.5, "z": 0 },
"velocity": { "x": 0, "y": 3.5, "z": 0 }, "velocity": { "x": 0, "y": 1.95, "z": 0 },
"angularVelocity": { "x": -1.0, "y": 0, "z": -1.3 }, "angularVelocity": { "x": -1.0, "y": 0, "z": -1.3 },
"dynamic": true, "dynamic": true,
@ -438,11 +438,6 @@ function takeSnapshot() {
isUploadingPrintableStill = true; isUploadingPrintableStill = true;
updatePrintPermissions(); updatePrintPermissions();
// Raising the desktop for the share dialog at end will interact badly with clearOverlayWhenMoving.
// Turn it off now, before we start futzing with things (and possibly moving).
clearOverlayWhenMoving = MyAvatar.getClearOverlayWhenMoving(); // Do not use Settings. MyAvatar keeps a separate copy.
MyAvatar.setClearOverlayWhenMoving(false);
// We will record snapshots based on the starting location. That could change, e.g., when recording a .gif. // We will record snapshots based on the starting location. That could change, e.g., when recording a .gif.
// Even the domainID could change (e.g., if the user falls into a teleporter while recording). // Even the domainID could change (e.g., if the user falls into a teleporter while recording).
href = location.href; href = location.href;
@ -544,9 +539,6 @@ function stillSnapshotTaken(pathStillSnapshot, notify) {
// last element in data array tells dialog whether we can share or not // last element in data array tells dialog whether we can share or not
Settings.setValue("previousStillSnapPath", pathStillSnapshot); Settings.setValue("previousStillSnapPath", pathStillSnapshot);
if (clearOverlayWhenMoving) {
MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog
}
HMD.openTablet(); HMD.openTablet();
isDomainOpen(domainID, function (canShare) { isDomainOpen(domainID, function (canShare) {
@ -590,9 +582,6 @@ function processingGifStarted(pathStillSnapshot) {
} }
Settings.setValue("previousStillSnapPath", pathStillSnapshot); Settings.setValue("previousStillSnapPath", pathStillSnapshot);
if (clearOverlayWhenMoving) {
MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog
}
HMD.openTablet(); HMD.openTablet();
isDomainOpen(domainID, function (canShare) { isDomainOpen(domainID, function (canShare) {