Merge branch 'master' into vr-edit-a

This commit is contained in:
David Rowe 2017-09-06 13:33:33 +12:00
commit 52bf8ac9a1
19 changed files with 348 additions and 41 deletions

View file

@ -6,7 +6,14 @@
<title>Welcome to Interface</title>
<style>
body {
@font-face {
font-family: 'Raleway Light';
src: url('../fonts/Raleway-Light.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
body {
background: black;
width: 100%;
overflow-x: hidden;
@ -15,6 +22,14 @@
padding: 0;
}
a:link {color:inherit}
a:active {color:inherit}
a:visited {color:inherit}
a:hover {
color:inherit;
cursor: pointer;
}
#left_button {
position: absolute;
left: 70;
@ -38,6 +53,15 @@
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
}
#report_problem {
position: fixed;
top: 10;
right: 10;
font-family: "Raleway Light", sans-serif;
text-decoration: none;
color: #ddd;
}
</style>
<script>
var handControllerImageURL = null;
@ -152,6 +176,7 @@
<a href="#" id="left_button" onmousedown="cycleLeft()"></a>
<a href="#" id="right_button" onmousedown="cycleRight()"></a>
</div>
<a href="mailto:support@highfidelity.com" id="report_problem">Report Problem</a>
</body>
</html>

View file

@ -59,7 +59,7 @@ Rectangle {
}
onWalletAuthenticatedStatusResult: {
if (!isAuthenticated && !passphraseModal.visible) {
if (!isAuthenticated && passphraseModal && !passphraseModal.visible) {
passphraseModal.visible = true;
} else if (isAuthenticated) {
root.activeView = "walletHome";

View file

@ -1,5 +1,6 @@
import QtQuick 2.5
import QtGraphicalEffects 1.0
import QtQuick.Layouts 1.3
import "../../styles-uit"
import "../audio" as HifiAudio
@ -109,15 +110,45 @@ Item {
}
}
RalewaySemiBold {
id: usernameText
text: tabletRoot.username
anchors.verticalCenter: parent.verticalCenter
Item {
width: 150
height: 50
anchors.right: parent.right
anchors.rightMargin: 20
horizontalAlignment: Text.AlignRight
font.pixelSize: 20
color: "#afafaf"
anchors.rightMargin: 30
anchors.verticalCenter: parent.verticalCenter
ColumnLayout {
anchors.fill: parent
RalewaySemiBold {
text: Account.loggedIn ? qsTr("Log out") : qsTr("Log in")
horizontalAlignment: Text.AlignRight
anchors.right: parent.right
font.pixelSize: 20
color: "#afafaf"
}
RalewaySemiBold {
visible: Account.loggedIn
height: Account.loggedIn ? parent.height/2 - parent.spacing/2 : 0
text: Account.loggedIn ? "[" + tabletRoot.usernameShort + "]" : ""
horizontalAlignment: Text.AlignRight
anchors.right: parent.right
font.pixelSize: 20
color: "#afafaf"
}
}
MouseArea {
anchors.fill: parent
onClicked: {
if (!Account.loggedIn) {
DialogsManager.showLoginDialog()
} else {
Account.logOut()
}
}
}
}
}

View file

@ -8,6 +8,7 @@ Item {
id: tabletRoot
objectName: "tabletRoot"
property string username: "Unknown user"
property string usernameShort: "Unknown user"
property var rootMenu;
property var openModal: null;
property var openMessage: null;
@ -157,6 +158,11 @@ Item {
function setUsername(newUsername) {
username = newUsername;
usernameShort = newUsername.substring(0, 8);
if (newUsername.length > 8) {
usernameShort = usernameShort + "..."
}
}
ListModel {

View file

@ -604,6 +604,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
DependencyManager::registerInheritance<SpatialParentFinder, InterfaceParentFinder>();
// Set dependencies
DependencyManager::set<Cursor::Manager>();
DependencyManager::set<AccountManager>(std::bind(&Application::getUserAgent, qApp));
DependencyManager::set<StatTracker>();
DependencyManager::set<ScriptEngines>(ScriptEngine::CLIENT_SCRIPT);
@ -6320,11 +6321,11 @@ bool Application::askToWearAvatarAttachmentUrl(const QString& url) {
bool Application::askToReplaceDomainContent(const QString& url) {
QString methodDetails;
const int MAX_CHARACTERS_PER_LINE = 90;
if (DependencyManager::get<NodeList>()->getThisNodeCanReplaceContent()) {
QUrl originURL { url };
if (originURL.host().endsWith(MARKETPLACE_CDN_HOSTNAME)) {
// Create a confirmation dialog when this call is made
const int MAX_CHARACTERS_PER_LINE = 90;
static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. "
"If you want to save what you have now, create a backup before proceeding. For more information about backing up "
"and restoring content, visit the documentation page at: ", MAX_CHARACTERS_PER_LINE) +
@ -6360,7 +6361,9 @@ bool Application::askToReplaceDomainContent(const QString& url) {
}
} else {
methodDetails = "UserDoesNotHavePermissionToReplaceContent";
OffscreenUi::warning("Unable to replace content", "You do not have permissions to replace domain content",
static const QString warningMessage = simpleWordWrap("The domain owner must enable 'Replace Content' "
"permissions for you in this domain's server settings before you can continue.", MAX_CHARACTERS_PER_LINE);
OffscreenUi::warning("You do not have permissions to replace domain content", warningMessage,
QMessageBox::Ok, QMessageBox::Ok);
}
QJsonObject messageProperties = {

View file

@ -1912,6 +1912,17 @@ void MyAvatar::preDisplaySide(RenderArgs* renderArgs) {
const bool shouldDrawHead = shouldRenderHead(renderArgs);
if (shouldDrawHead != _prevShouldDrawHead) {
_skeletonModel->setEnableCauterization(!shouldDrawHead);
for (int i = 0; i < _attachmentData.size(); i++) {
if (_attachmentData[i].jointName.compare("Head", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("Neck", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("LeftEye", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("RightEye", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("HeadTop_End", Qt::CaseInsensitive) == 0 ||
_attachmentData[i].jointName.compare("Face", Qt::CaseInsensitive) == 0) {
_attachmentModels[i]->setVisibleInScene(shouldDrawHead, qApp->getMain3DScene());
}
}
}
_prevShouldDrawHead = shouldDrawHead;
}

View file

@ -272,6 +272,10 @@ void Wallet::setPassphrase(const QString& passphrase) {
delete _passphrase;
}
_passphrase = new QString(passphrase);
// no matter what, we now need to clear the keys as they
// need to be read using this passphrase
_publicKeys.clear();
}
// encrypt some stuff
@ -383,11 +387,25 @@ bool Wallet::walletIsAuthenticatedWithPassphrase() {
// FIXME: initialize OpenSSL elsewhere soon
initialize();
// this should always be false if we don't have a passphrase
// cached yet
if (!_passphrase || _passphrase->isEmpty()) {
return false;
}
if (_publicKeys.count() > 0) {
// we _must_ be authenticated if the publicKeys are there
return true;
}
// otherwise, we have a passphrase but no keys, so we have to check
auto publicKey = readPublicKey(keyFilePath().toStdString().c_str());
if (publicKey.size() > 0) {
if (auto key = readPrivateKey(keyFilePath().toStdString().c_str())) {
RSA_free(key);
// be sure to add the public key so we don't do this over and over
_publicKeys.push_back(publicKey.toBase64());
return true;
}
}

View file

@ -18,6 +18,8 @@ AccountScriptingInterface* AccountScriptingInterface::getInstance() {
auto accountManager = DependencyManager::get<AccountManager>();
QObject::connect(accountManager.data(), &AccountManager::profileChanged,
&sharedInstance, &AccountScriptingInterface::usernameChanged);
QObject::connect(accountManager.data(), &AccountManager::usernameChanged,
&sharedInstance, &AccountScriptingInterface::onUsernameChanged);
return &sharedInstance;
}
@ -31,6 +33,21 @@ bool AccountScriptingInterface::checkAndSignalForAccessToken() {
return accountManager->checkAndSignalForAccessToken();
}
void AccountScriptingInterface::logOut() {
auto accountManager = DependencyManager::get<AccountManager>();
return accountManager->logout();
}
AccountScriptingInterface::AccountScriptingInterface(QObject *parent): QObject(parent) {
m_loggedIn = isLoggedIn();
emit loggedInChanged(m_loggedIn);
}
void AccountScriptingInterface::onUsernameChanged(QString username) {
m_loggedIn = (username != QString());
emit loggedInChanged(m_loggedIn);
}
QString AccountScriptingInterface::getUsername() {
auto accountManager = DependencyManager::get<AccountManager>();
if (accountManager->isLoggedIn()) {

View file

@ -18,6 +18,7 @@ class AccountScriptingInterface : public QObject {
Q_OBJECT
Q_PROPERTY(QString username READ getUsername NOTIFY usernameChanged)
Q_PROPERTY(bool loggedIn READ loggedIn NOTIFY loggedInChanged)
/**jsdoc
* @namespace Account
@ -32,6 +33,7 @@ signals:
* @return {Signal}
*/
void usernameChanged();
void loggedInChanged(bool loggedIn);
public slots:
static AccountScriptingInterface* getInstance();
@ -50,6 +52,20 @@ public slots:
*/
bool isLoggedIn();
bool checkAndSignalForAccessToken();
void logOut();
public:
AccountScriptingInterface(QObject* parent = nullptr);
bool loggedIn() const {
return m_loggedIn;
}
private slots:
void onUsernameChanged(QString username);
private:
bool m_loggedIn { false };
};
#endif // hifi_AccountScriptingInterface_h

View file

@ -33,7 +33,12 @@ void DialogsManagerScriptingInterface::showAddressBar() {
void DialogsManagerScriptingInterface::hideAddressBar() {
QMetaObject::invokeMethod(DependencyManager::get<DialogsManager>().data(),
"hideAddressBar", Qt::QueuedConnection);
"hideAddressBar", Qt::QueuedConnection);
}
void DialogsManagerScriptingInterface::showLoginDialog() {
QMetaObject::invokeMethod(DependencyManager::get<DialogsManager>().data(),
"showLoginDialog", Qt::QueuedConnection);
}
void DialogsManagerScriptingInterface::showFeed() {

View file

@ -24,6 +24,7 @@ public:
public slots:
void showAddressBar();
void hideAddressBar();
void showLoginDialog();
signals:
void addressBarShown(bool visible);

View file

@ -92,6 +92,7 @@ void EntityMotionState::updateServerPhysicsVariables() {
Transform localTransform;
_entity->getLocalTransformAndVelocities(localTransform, _serverVelocity, _serverAngularVelocity);
_serverVariablesSet = true;
_serverPosition = localTransform.getTranslation();
_serverRotation = localTransform.getRotation();
_serverAcceleration = _entity->getAcceleration();
@ -99,18 +100,19 @@ void EntityMotionState::updateServerPhysicsVariables() {
}
void EntityMotionState::handleDeactivation() {
// copy _server data to entity
bool success;
_entity->setPosition(_serverPosition, success, false);
_entity->setOrientation(_serverRotation, success, false);
_entity->setVelocity(ENTITY_ITEM_ZERO_VEC3);
_entity->setAngularVelocity(ENTITY_ITEM_ZERO_VEC3);
// and also to RigidBody
btTransform worldTrans;
worldTrans.setOrigin(glmToBullet(_serverPosition));
worldTrans.setRotation(glmToBullet(_serverRotation));
_body->setWorldTransform(worldTrans);
// no need to update velocities... should already be zero
if (_serverVariablesSet) {
// copy _server data to entity
Transform localTransform = _entity->getLocalTransform();
localTransform.setTranslation(_serverPosition);
localTransform.setRotation(_serverRotation);
_entity->setLocalTransformAndVelocities(localTransform, ENTITY_ITEM_ZERO_VEC3, ENTITY_ITEM_ZERO_VEC3);
// and also to RigidBody
btTransform worldTrans;
worldTrans.setOrigin(glmToBullet(_entity->getPosition()));
worldTrans.setRotation(glmToBullet(_entity->getRotation()));
_body->setWorldTransform(worldTrans);
// no need to update velocities... should already be zero
}
}
// virtual
@ -339,6 +341,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
// if we've never checked before, our _lastStep will be 0, and we need to initialize our state
if (_lastStep == 0) {
btTransform xform = _body->getWorldTransform();
_serverVariablesSet = true;
_serverPosition = worldToLocal.transform(bulletToGLM(xform.getOrigin()));
_serverRotation = worldToLocal.getRotation() * bulletToGLM(xform.getRotation());
_serverVelocity = worldVelocityToLocal.transform(getBodyLinearVelocityGTSigma());

View file

@ -107,6 +107,7 @@ protected:
// Meanwhile we also keep a raw EntityItem* for internal stuff where the pointer is guaranteed valid.
EntityItem* _entity;
bool _serverVariablesSet { false };
glm::vec3 _serverPosition; // in simulation-frame (not world-frame)
glm::quat _serverRotation;
glm::vec3 _serverVelocity;

View file

@ -731,7 +731,7 @@ void SpatiallyNestable::setScale(float value) {
}
}
const Transform SpatiallyNestable::getLocalTransform() const {
Transform SpatiallyNestable::getLocalTransform() const {
Transform result;
_transformLock.withReadLock([&] {
result =_transform;

View file

@ -121,7 +121,7 @@ public:
virtual glm::vec3 getScale(int jointIndex) const;
// object's parent's frame
virtual const Transform getLocalTransform() const;
virtual Transform getLocalTransform() const;
virtual void setLocalTransform(const Transform& transform);
virtual glm::vec3 getLocalPosition() const;

View file

@ -24,13 +24,6 @@ namespace Cursor {
return _icon;
}
class MouseInstance : public Instance {
Source getType() const override {
return Source::MOUSE;
}
};
QMap<uint16_t, QString> Manager::ICON_NAMES {
{ Icon::SYSTEM, "SYSTEM", },
{ Icon::DEFAULT, "DEFAULT", },
@ -38,7 +31,7 @@ namespace Cursor {
{ Icon::ARROW, "ARROW", },
{ Icon::RETICLE, "RETICLE", },
};
QMap<uint16_t, QString> Manager::ICONS;
static uint16_t _customIconId = Icon::USER_BASE;
Manager::Manager() {
@ -62,8 +55,8 @@ namespace Cursor {
}
Manager& Manager::instance() {
static Manager instance;
return instance;
static QSharedPointer<Manager> instance = DependencyManager::get<Cursor::Manager>();
return *instance;
}
QList<uint16_t> Manager::registeredIcons() const {
@ -76,7 +69,6 @@ namespace Cursor {
Instance* Manager::getCursor(uint8_t index) {
Q_ASSERT(index < getCount());
static MouseInstance mouseInstance;
if (index == 0) {
return &mouseInstance;
}

View file

@ -8,6 +8,7 @@
#pragma once
#include <stdint.h>
#include <DependencyManager.h>
#include <GLMHelpers.h>
@ -39,7 +40,15 @@ namespace Cursor {
uint16_t _icon;
};
class Manager {
class MouseInstance : public Instance {
Source getType() const override {
return Source::MOUSE;
}
};
class Manager : public QObject, public Dependency {
SINGLETON_DEPENDENCY
Manager();
Manager(const Manager& other) = delete;
public:
@ -52,12 +61,13 @@ namespace Cursor {
QList<uint16_t> registeredIcons() const;
const QString& getIconImage(uint16_t icon);
static QMap<uint16_t, QString> ICONS;
static QMap<uint16_t, QString> ICON_NAMES;
static Icon lookupIcon(const QString& name);
static const QString& getIconName(const Icon& icon);
private:
MouseInstance mouseInstance;
float _scale{ 1.0f };
QMap<uint16_t, QString> ICONS;
};
}

View file

@ -134,7 +134,7 @@
if (parseInt(cost) > 0) {
var priceElement = $(this).find('.price')
priceElement.css({ "width": "auto", "padding": "3px 5px", "height": "26px" });
priceElement.text(parseFloat(cost / 100).toFixed(2) + ' HFC');
priceElement.text(cost + ' HFC');
priceElement.css({ "min-width": priceElement.width() + 10 });
}
});

View file

@ -0,0 +1,168 @@
(function () {
var FORCE_DROP_CHANNEL = "Hifi-Hand-Drop";
var proxInterval,
proxTimeout;
var _entityID;
this.preload = function (entityID) {
_entityID = entityID;
Entities.editEntity(_entityID, {
userData: '{"grabbableKey": {"grabbable": true}'
});
};
var particleTrailEntity = null;
function particleTrail() {
var props = {
type: 'ParticleEffect',
name: 'Particle',
parentID: _entityID,
isEmitting: true,
lifespan: 2.0,
maxParticles: 100,
textures: 'https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png',
emitRate: 50,
emitSpeed: 0,
emitterShouldTrail: true,
particleRadius: 0,
radiusSpread: 0,
radiusStart: .2,
radiusFinish: 0.1,
color: {
red: 201,
blue: 201,
green: 34
},
accelerationSpread: {
x: 0,
y: 0,
z: 0
},
alpha: 0,
alphaSpread: 0,
alphaStart: 1,
alphaFinish: 0,
polarStart: 0,
polarFinish: 0,
azimuthStart: -180,
azimuthFinish: 180
};
particleTrailEntity = Entities.addEntity(props);
}
function particleExplode() {
var entPos = Entities.getEntityProperties(_entityID, 'position').position;
var props = {
type: 'ParticleEffect',
name: 'Particle',
parentID: _entityID,
isEmitting: true,
lifespan: 2,
maxParticles: 10,
position: entPos,
textures: 'https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png',
emitRate: 1,
emitSpeed: 0,
emitterShouldTrail: false,
particleRadius: 1,
radiusSpread: 0,
radiusStart: 0,
radiusFinish: 1,
color: {
red: 232,
blue: 232,
green: 26
},
emitAcceleration: {
x: 0,
y: 0,
z: 0
},
alpha: 0,
alphaSpread: 0,
alphaStart: 1,
alphaFinish: .5,
polarStart: 0,
polarFinish: 0,
azimuthStart: -180,
azimuthFinish: 180
};
var explosionParticles = Entities.addEntity(props);
Entities.editEntity(_entityID, {
velocity: Vec3.ZERO,
dynamic: false
});
Script.setTimeout(function () {
Entities.deleteEntity(explosionParticles);
Entities.editEntity(_entityID, {
dynamic: true
})
}, 500);
}
function clearProxCheck() {
if (proxInterval) {
Script.clearInterval(proxInterval);
Entities.deleteEntity(particleTrailEntity);
particleTrailEntity = null;
}
if (proxTimeout) {
Script.clearTimeout(proxTimeout);
}
}
function proxCheck() {
var ballPos = Entities.getEntityProperties(_entityID, ['position']).position;
var isAnyAvatarInRange = AvatarList.isAvatarInRange(ballPos, 1);
if (isAnyAvatarInRange) {
clearProxCheck();
particleExplode();
}
}
this.startDistanceGrab = function (thisEntityID, triggerHandAndAvatarUUIDArray) {
clearProxCheck();
var triggerHand = triggerHandAndAvatarUUIDArray[0];
var avatarUUID = triggerHandAndAvatarUUIDArray[1];
var ballPos = Entities.getEntityProperties(_entityID, ['position']).position;
var MAX_DISTANCE_GRAB = 2; //meter
if (Vec3.distance(ballPos, AvatarList.getAvatar(avatarUUID).position) > MAX_DISTANCE_GRAB) {
Messages.sendMessage(FORCE_DROP_CHANNEL, triggerHand, true);
}
};
this.startNearGrab = function (thisEntityID, triggerHandAndAvatarUUIDArray) {
clearProxCheck();
};
this.releaseGrab = function (thisEntityID) {
if (particleTrailEntity === null) {
particleTrail();
}
Script.setTimeout(function () {
proxInterval = Script.setInterval(proxCheck, 50);
}, 200); // Setting a delay to give it time to leave initial avatar without proc.
proxTimeout = Script.setTimeout(function () {
clearProxCheck();
}, 10000)
};
this.collisionWithEntity = function (thisEntityID, collisionEntityID, collisionInfo) {
clearProxCheck();
};
});