From 061f182fab4a8f72e046021cec93a3a41ac22f82 Mon Sep 17 00:00:00 2001 From: Mika Impola Date: Wed, 21 May 2014 00:02:59 +0300 Subject: [PATCH 01/28] Initialise lisencing manager after we have enabled Visage. --- interface/src/devices/Visage.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 119d89654a..70cdaf2b01 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -41,14 +41,8 @@ Visage::Visage() : _headOrigin(DEFAULT_HEAD_ORIGIN) { #ifdef HAVE_VISAGE -#ifdef WIN32 - QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage"; -#else - QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage/license.vlc"; -#endif - initializeLicenseManager(licensePath.data()); - _tracker = new VisageTracker2(Application::resourcesPath().toLatin1() + "visage/tracker.cfg"); - _data = new FaceData(); + _tracker = NULL; + _data = NULL; #endif } @@ -179,6 +173,19 @@ void Visage::setEnabled(bool enabled) { return; } if ((_enabled = enabled)) { + if(_tracker == NULL && _data == NULL){ + + #ifdef WIN32 + QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage"; + #else + QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage/license.vlc"; + #endif + + initializeLicenseManager(licensePath.data()); + _tracker = new VisageTracker2(Application::resourcesPath().toLatin1() + "visage/tracker.cfg"); + _data = new FaceData(); + } + _tracker->trackFromCam(); } else { _tracker->stop(); From de7c05cb2dda4936f7af3245e485d072486936de Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 21 May 2014 15:30:50 -0700 Subject: [PATCH 02/28] More animation controls. --- interface/src/avatar/MyAvatar.cpp | 19 ++++++++++++++++--- interface/src/avatar/MyAvatar.h | 4 ++-- interface/src/renderer/Model.cpp | 24 +++++++++++++++++------- interface/src/renderer/Model.h | 12 ++++++++++++ interface/src/ui/AnimationsDialog.cpp | 27 +++++++++++++++++++++++++++ interface/src/ui/AnimationsDialog.h | 6 ++++++ 6 files changed, 80 insertions(+), 12 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index be88a80b90..3f40bbc8ed 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -441,10 +441,12 @@ void MyAvatar::removeAnimationHandle(const AnimationHandlePointer& handle) { _animationHandles.removeOne(handle); } -void MyAvatar::startAnimation(const QString& url, float fps, float priority, bool loop, const QStringList& maskedJoints) { +void MyAvatar::startAnimation(const QString& url, float fps, float priority, + bool loop, bool hold, int firstFrame, int lastFrame, const QStringList& maskedJoints) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "startAnimation", Q_ARG(const QString&, url), - Q_ARG(float, fps), Q_ARG(float, priority), Q_ARG(bool, loop), Q_ARG(const QStringList&, maskedJoints)); + QMetaObject::invokeMethod(this, "startAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps), + Q_ARG(float, priority), Q_ARG(bool, loop), Q_ARG(bool, hold), Q_ARG(int, firstFrame), + Q_ARG(int, lastFrame), Q_ARG(const QStringList&, maskedJoints)); return; } AnimationHandlePointer handle = _skeletonModel.createAnimationHandle(); @@ -452,6 +454,9 @@ void MyAvatar::startAnimation(const QString& url, float fps, float priority, boo handle->setFPS(fps); handle->setPriority(priority); handle->setLoop(loop); + handle->setHold(hold); + handle->setFirstFrame(firstFrame); + handle->setLastFrame(lastFrame); handle->setMaskedJoints(maskedJoints); handle->start(); } @@ -514,6 +519,10 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("url", pointer->getURL()); settings->setValue("fps", pointer->getFPS()); settings->setValue("priority", pointer->getPriority()); + settings->setValue("loop", pointer->getLoop()); + settings->setValue("hold", pointer->getHold()); + settings->setValue("firstFrame", pointer->getFirstFrame()); + settings->setValue("lastFrame", pointer->getLastFrame()); settings->setValue("maskedJoints", pointer->getMaskedJoints()); } settings->endArray(); @@ -581,6 +590,10 @@ void MyAvatar::loadData(QSettings* settings) { handle->setURL(settings->value("url").toUrl()); handle->setFPS(loadSetting(settings, "fps", 30.0f)); handle->setPriority(loadSetting(settings, "priority", 1.0f)); + handle->setLoop(settings->value("loop", true).toBool()); + handle->setHold(settings->value("hold", false).toBool()); + handle->setFirstFrame(settings->value("firstFrame", 0).toInt()); + handle->setLastFrame(settings->value("lastFrame", INT_MAX).toInt()); handle->setMaskedJoints(settings->value("maskedJoints").toStringList()); } settings->endArray(); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9d6f22264f..fcbb2103d1 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -67,8 +67,8 @@ public: void removeAnimationHandle(const AnimationHandlePointer& handle); /// Allows scripts to run animations. - Q_INVOKABLE void startAnimation(const QString& url, float fps = 30.0f, - float priority = 1.0f, bool loop = false, const QStringList& maskedJoints = QStringList()); + Q_INVOKABLE void startAnimation(const QString& url, float fps = 30.0f, float priority = 1.0f, bool loop = false, + bool hold = false, int firstFrame = 0, int lastFrame = INT_MAX, const QStringList& maskedJoints = QStringList()); /// Stops an animation as identified by a URL. Q_INVOKABLE void stopAnimation(const QString& url); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 900d7ff951..5b81de2c1f 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1694,7 +1694,7 @@ void AnimationHandle::setRunning(bool running) { if (!_model->_runningAnimations.contains(_self)) { insertSorted(_model->_runningAnimations, _self); } - _frameIndex = 0.0f; + _frameIndex = _firstFrame; } else { _model->_runningAnimations.removeOne(_self); @@ -1706,7 +1706,10 @@ AnimationHandle::AnimationHandle(Model* model) : _model(model), _fps(30.0f), _priority(1.0f), + _firstFrame(0), + _lastFrame(INT_MAX), _loop(false), + _hold(false), _running(false) { } @@ -1737,10 +1740,11 @@ void AnimationHandle::simulate(float deltaTime) { stop(); return; } - int ceilFrameIndex = (int)glm::ceil(_frameIndex); - if (!_loop && ceilFrameIndex >= animationGeometry.animationFrames.size()) { + int lastFrameIndex = qMin(_lastFrame, animationGeometry.animationFrames.size() - 1); + int firstFrameIndex = qMin(_firstFrame, lastFrameIndex); + if ((!_loop && _frameIndex >= lastFrameIndex) || firstFrameIndex == lastFrameIndex) { // passed the end; apply the last frame - const FBXAnimationFrame& frame = animationGeometry.animationFrames.last(); + const FBXAnimationFrame& frame = animationGeometry.animationFrames.at(lastFrameIndex); for (int i = 0; i < _jointMappings.size(); i++) { int mapping = _jointMappings.at(i); if (mapping != -1) { @@ -1750,14 +1754,20 @@ void AnimationHandle::simulate(float deltaTime) { } } } - stop(); + if (!_hold) { + stop(); + } return; } + int frameCount = lastFrameIndex - firstFrameIndex + 1; + _frameIndex = firstFrameIndex + glm::mod(qMax(_frameIndex - firstFrameIndex, 0.0f), (float)frameCount); + qDebug() << _frameIndex; + // blend between the closest two frames const FBXAnimationFrame& ceilFrame = animationGeometry.animationFrames.at( - ceilFrameIndex % animationGeometry.animationFrames.size()); + firstFrameIndex + ((int)glm::ceil(_frameIndex) - firstFrameIndex) % frameCount); const FBXAnimationFrame& floorFrame = animationGeometry.animationFrames.at( - (int)glm::floor(_frameIndex) % animationGeometry.animationFrames.size()); + firstFrameIndex + ((int)glm::floor(_frameIndex) - firstFrameIndex) % frameCount); float frameFraction = glm::fract(_frameIndex); for (int i = 0; i < _jointMappings.size(); i++) { int mapping = _jointMappings.at(i); diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 59ec50cac1..979dc6c601 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -393,6 +393,15 @@ public: void setLoop(bool loop) { _loop = loop; } bool getLoop() const { return _loop; } + void setHold(bool hold) { _hold = hold; } + bool getHold() const { return _hold; } + + void setFirstFrame(int firstFrame) { _firstFrame = firstFrame; } + int getFirstFrame() const { return _firstFrame; } + + void setLastFrame(int lastFrame) { _lastFrame = lastFrame; } + int getLastFrame() const { return _lastFrame; } + void setMaskedJoints(const QStringList& maskedJoints); const QStringList& getMaskedJoints() const { return _maskedJoints; } @@ -416,7 +425,10 @@ private: QUrl _url; float _fps; float _priority; + int _firstFrame; + int _lastFrame; bool _loop; + bool _hold; QStringList _maskedJoints; bool _running; QVector _jointMappings; diff --git a/interface/src/ui/AnimationsDialog.cpp b/interface/src/ui/AnimationsDialog.cpp index 29837f67be..f30c98cce7 100644 --- a/interface/src/ui/AnimationsDialog.cpp +++ b/interface/src/ui/AnimationsDialog.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include #include @@ -107,6 +108,24 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo maskedJointBox->addWidget(_chooseMaskedJoints = new QPushButton("Choose")); connect(_chooseMaskedJoints, SIGNAL(clicked(bool)), SLOT(chooseMaskedJoints())); + layout->addRow("Loop:", _loop = new QCheckBox()); + _loop->setChecked(handle->getLoop()); + connect(_loop, SIGNAL(toggled(bool)), SLOT(updateHandle())); + + layout->addRow("Hold:", _hold = new QCheckBox()); + _hold->setChecked(handle->getHold()); + connect(_hold, SIGNAL(toggled(bool)), SLOT(updateHandle())); + + layout->addRow("First Frame:", _firstFrame = new QSpinBox()); + _firstFrame->setMaximum(INT_MAX); + _firstFrame->setValue(handle->getFirstFrame()); + connect(_firstFrame, SIGNAL(valueChanged(int)), SLOT(updateHandle())); + + layout->addRow("Last Frame:", _lastFrame = new QSpinBox()); + _lastFrame->setMaximum(INT_MAX); + _lastFrame->setValue(handle->getLastFrame()); + connect(_lastFrame, SIGNAL(valueChanged(int)), SLOT(updateHandle())); + QPushButton* remove = new QPushButton("Delete"); layout->addRow(remove); connect(remove, SIGNAL(clicked(bool)), SLOT(removeHandle())); @@ -149,7 +168,15 @@ void AnimationPanel::updateHandle() { _handle->setURL(_url->text()); _handle->setFPS(_fps->value()); _handle->setPriority(_priority->value()); + _handle->setLoop(_loop->isChecked()); + _handle->setHold(_hold->isChecked()); + _handle->setFirstFrame(_firstFrame->value()); + _handle->setLastFrame(_lastFrame->value()); _handle->setMaskedJoints(_maskedJoints->text().split(QRegExp("\\s*,\\s*"))); + + if ((_loop->isChecked() || _hold->isChecked()) && !_handle->isRunning()) { + _handle->start(); + } } void AnimationPanel::removeHandle() { diff --git a/interface/src/ui/AnimationsDialog.h b/interface/src/ui/AnimationsDialog.h index 7693a1da97..8b0f6cd257 100644 --- a/interface/src/ui/AnimationsDialog.h +++ b/interface/src/ui/AnimationsDialog.h @@ -17,9 +17,11 @@ #include "avatar/MyAvatar.h" +class QCheckBox; class QDoubleSpinner; class QLineEdit; class QPushButton; +class QSpinBox; class QVBoxLayout; /// Allows users to edit the avatar animations. @@ -64,6 +66,10 @@ private: QLineEdit* _url; QDoubleSpinBox* _fps; QDoubleSpinBox* _priority; + QCheckBox* _loop; + QCheckBox* _hold; + QSpinBox* _firstFrame; + QSpinBox* _lastFrame; QLineEdit* _maskedJoints; QPushButton* _chooseMaskedJoints; bool _applying; From 2eee9a32ac4d38da9b18dd5433a38ec36a8dc944 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 21 May 2014 15:39:12 -0700 Subject: [PATCH 03/28] Removed debugging line. --- interface/src/renderer/Model.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 5b81de2c1f..5d0f571b5b 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1761,7 +1761,6 @@ void AnimationHandle::simulate(float deltaTime) { } int frameCount = lastFrameIndex - firstFrameIndex + 1; _frameIndex = firstFrameIndex + glm::mod(qMax(_frameIndex - firstFrameIndex, 0.0f), (float)frameCount); - qDebug() << _frameIndex; // blend between the closest two frames const FBXAnimationFrame& ceilFrame = animationGeometry.animationFrames.at( From 4036f929c956c8a5124de81699d58d073430f20d Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 22 May 2014 10:31:30 -0700 Subject: [PATCH 04/28] Stopped access violation when erasing particles. --- .../src/particles/ParticleTreeRenderer.cpp | 4 +++- libraries/particles/src/ParticleTreeElement.cpp | 17 ++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/src/particles/ParticleTreeRenderer.cpp b/interface/src/particles/ParticleTreeRenderer.cpp index 38ef9c8516..781fc2bfc8 100644 --- a/interface/src/particles/ParticleTreeRenderer.cpp +++ b/interface/src/particles/ParticleTreeRenderer.cpp @@ -127,5 +127,7 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg } void ParticleTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { - static_cast(_tree)->processEraseMessage(dataByteArray, sourceNode); + if (_tree->tryLockForWrite()) { + static_cast(_tree)->processEraseMessage(dataByteArray, sourceNode); + } } diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index b6e59eb0ab..2a617380fc 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -20,8 +20,9 @@ ParticleTreeElement::ParticleTreeElement(unsigned char* octalCode) : OctreeEleme ParticleTreeElement::~ParticleTreeElement() { _voxelMemoryUsage -= sizeof(ParticleTreeElement); - delete _particles; + QList* tmpParticles = _particles; _particles = NULL; + delete tmpParticles; } // This will be called primarily on addChildAt(), which means we're adding a child of our @@ -277,12 +278,14 @@ const Particle* ParticleTreeElement::getParticleWithID(uint32_t id) const { bool ParticleTreeElement::removeParticleWithID(uint32_t id) { bool foundParticle = false; - uint16_t numberOfParticles = _particles->size(); - for (uint16_t i = 0; i < numberOfParticles; i++) { - if ((*_particles)[i].getID() == id) { - foundParticle = true; - _particles->removeAt(i); - break; + if (_particles) { + uint16_t numberOfParticles = _particles->size(); + for (uint16_t i = 0; i < numberOfParticles; i++) { + if ((*_particles)[i].getID() == id) { + foundParticle = true; + _particles->removeAt(i); + break; + } } } return foundParticle; From ea1359c10f237cbab2bd2b53dc3759f036c316cf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 22 May 2014 11:11:22 -0700 Subject: [PATCH 05/28] Clean up log --- interface/src/Application.cpp | 4 ++-- libraries/voxels/src/LocalVoxelsList.cpp | 8 ++------ libraries/voxels/src/Tags.cpp | 2 +- libraries/voxels/src/VoxelTree.cpp | 2 +- libraries/voxels/src/VoxelTreeCommands.cpp | 1 - 5 files changed, 6 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 2b552de0ee..fd09e530c1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1476,10 +1476,10 @@ void Application::importVoxels() { } if (!_voxelImporter->exec()) { - qDebug() << "[DEBUG] Import succeeded." << endl; + qDebug() << "Import succeeded." << endl; _importSucceded = true; } else { - qDebug() << "[DEBUG] Import failed." << endl; + qDebug() << "Import failed." << endl; if (_sharedVoxelSystem.getTree() == _voxelImporter->getVoxelTree()) { _sharedVoxelSystem.killLocalVoxels(); _sharedVoxelSystem.changeTree(&_clipboard); diff --git a/libraries/voxels/src/LocalVoxelsList.cpp b/libraries/voxels/src/LocalVoxelsList.cpp index 4324306161..55becb0976 100644 --- a/libraries/voxels/src/LocalVoxelsList.cpp +++ b/libraries/voxels/src/LocalVoxelsList.cpp @@ -40,18 +40,17 @@ void LocalVoxelsList::addPersistantTree(QString treeName, VoxelTree* tree) { StrongVoxelTreePointer treePtr(tree, doNothing); _persistantTrees.push_back(treePtr); _trees.insert(treeName, treePtr); - qDebug() << "[DEBUG] LocalVoxelsList : added persistant tree (" << treeName << ")"; } void LocalVoxelsList::insert(QString treeName, StrongVoxelTreePointer& tree) { // If the key don't already exist or the value is null if (!_trees.contains(treeName) || !_trees.value(treeName)) { _trees.insert(treeName, tree); - qDebug() << "[DEBUG] LocalVoxelsList : added local tree (" << treeName << ")"; + qDebug() << "LocalVoxelsList : added local tree (" << treeName << ")"; } else { // if not we replace the tree created by the user with the existing one tree = _trees.value(treeName); - qDebug() << "[DEBUG] LocalVoxelsList : local tree already exist (" << treeName << ")"; + qDebug() << "[WARNING] LocalVoxelsList : local tree already exist (" << treeName << ")"; } } @@ -59,9 +58,6 @@ void LocalVoxelsList::remove(QString treeName) { // if the tree is not used anymore (no strong pointer) if (!_trees.value(treeName)) { // then remove it from the list - qDebug() << "[DEBUG] LocalVoxelsList : removed unused tree (" << treeName << ")"; _trees.remove(treeName); - } else { - qDebug() << "[DEBUG] LocalVoxelsList : tree still in use (" << treeName << ")"; } } diff --git a/libraries/voxels/src/Tags.cpp b/libraries/voxels/src/Tags.cpp index 8f8228faae..d3c534735e 100644 --- a/libraries/voxels/src/Tags.cpp +++ b/libraries/voxels/src/Tags.cpp @@ -186,7 +186,7 @@ int retrieveData(std::string filename, std::stringstream &ss) { return ret; } - std::cerr << "[DEBUG] Schematic compression type not recognize : " << type << std::endl; + std::cerr << "[ERROR] Schematic compression type not recognize : " << type << std::endl; return 1; } diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 6372d7fd6d..5fe3fbdf05 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -359,7 +359,7 @@ bool VoxelTree::readFromSchematicFile(const char *fileName) { for (int x = 0; x < schematics.getWidth(); ++x) { if (_stopImport) { - qDebug("[DEBUG] Canceled import at %d voxels.", count); + qDebug("Canceled import at %d voxels.", count); _stopImport = false; return true; } diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index 39e08d3bc2..4ddc280749 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -107,7 +107,6 @@ DeleteVoxelCommand::DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, Voxe _voxel.blue = element->getColor()[2]; } else { _voxel.s = 0.0f; - qDebug() << "No element for delete."; } _tree->unlock(); } From b0c3655076ce3bf1b482c9da55fb728ebf7a7f59 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 22 May 2014 11:40:36 -0700 Subject: [PATCH 06/28] Fix for bad bounding shape for multi-root models. --- interface/src/renderer/Model.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 900d7ff951..2b50b6d19c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -682,7 +682,6 @@ void Model::computeBoundingShape(const FBXGeometry& geometry) { shapeIsSet.fill(false, numJoints); int numShapesSet = 0; int lastNumShapesSet = -1; - glm::vec3 rootOffset(0.0f); while (numShapesSet < numJoints && numShapesSet != lastNumShapesSet) { lastNumShapesSet = numShapesSet; for (int i = 0; i < numJoints; i++) { @@ -692,9 +691,11 @@ void Model::computeBoundingShape(const FBXGeometry& geometry) { if (parentIndex == -1) { glm::mat4 baseTransform = glm::scale(_scale) * glm::translate(_offset); glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation; - transforms[i] = baseTransform * geometry.offset * glm::translate(joint.translation) + glm::mat4 rootTransform = baseTransform * geometry.offset * glm::translate(joint.translation) * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; - rootOffset = extractTranslation(transforms[i]); + // remove the tranlsation part before we save the root transform + transforms[i] = glm::translate(- extractTranslation(rootTransform)) * rootTransform; + finalRotations[i] = combinedRotation; ++numShapesSet; shapeIsSet[i] = true; @@ -715,7 +716,7 @@ void Model::computeBoundingShape(const FBXGeometry& geometry) { for (int i = 0; i < _jointShapes.size(); i++) { const FBXJoint& joint = geometry.joints[i]; glm::vec3 jointToShapeOffset = uniformScale * (finalRotations[i] * joint.shapePosition); - glm::vec3 localPosition = extractTranslation(transforms[i]) + jointToShapeOffset- rootOffset; + glm::vec3 localPosition = extractTranslation(transforms[i]) + jointToShapeOffset; Shape* shape = _jointShapes[i]; shape->setPosition(localPosition); shape->setRotation(finalRotations[i] * joint.shapeRotation); @@ -1078,12 +1079,10 @@ void Model::updateJointState(int index) { if (joint.parentIndex == -1) { glm::mat4 baseTransform = glm::mat4_cast(_rotation) * glm::scale(_scale) * glm::translate(_offset); - glm::quat combinedRotation = joint.preRotation * state.rotation * joint.postRotation; state.transform = baseTransform * geometry.offset * glm::translate(state.translation) * joint.preTransform * glm::mat4_cast(combinedRotation) * joint.postTransform; state.combinedRotation = _rotation * combinedRotation; - } else { const JointState& parentState = _jointStates.at(joint.parentIndex); if (index == geometry.leanJointIndex) { From b9e73a6ef73b790476f5c48b60322b72bba0accd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 22 May 2014 12:23:01 -0700 Subject: [PATCH 07/28] added delete support to edit models --- examples/editModels.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/examples/editModels.js b/examples/editModels.js index a73cf72987..ceaec136c5 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -632,10 +632,23 @@ function mouseMoveEvent(event) { Models.editModel(selectedModelID, selectedModelProperties); } +function setupModelMenus() { + // add our menuitems + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Models", isSeparator: true, beforeItem: "Physics" }); + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Delete Model", shortcutKeyEvent: { text: "backspace" }, afterItem: "Models" }); +} + +function cleanupModelMenus() { + // delete our menuitems + Menu.removeSeparator("Edit", "Models"); + Menu.removeMenuItem("Edit", "Delete Model"); +} + function scriptEnding() { leftController.cleanup(); rightController.cleanup(); toolBar.cleanup(); + cleanupModelMenus(); } Script.scriptEnding.connect(scriptEnding); @@ -644,5 +657,22 @@ Script.update.connect(checkController); Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseMoveEvent.connect(mouseMoveEvent); +setupModelMenus(); +Menu.menuItemEvent.connect(function(menuItem){ + print("menuItemEvent() in JS... menuItem=" + menuItem); + if (menuItem == "Delete Model") { + if (leftController.grabbing) { + print(" Delete Model.... controller.modelID="+ leftController.modelID); + Models.deleteModel(leftController.modelID); + leftController.grabbing = false; + } else if (rightController.grabbing) { + print(" Delete Model.... controller.modelID="+ rightController.modelID); + Models.deleteModel(rightController.modelID); + rightController.grabbing = false; + } else { + print(" Delete Model.... not holding..."); + } + } +}); From 66b9d582a80e9a4ad69dbb835f78b173c945c4dd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 22 May 2014 12:43:23 -0700 Subject: [PATCH 08/28] fix broken mouse edit --- examples/editModels.js | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index ceaec136c5..717b7824bb 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -40,6 +40,16 @@ var modelURLs = [ var toolBar; +function isLocked(properties) { + // special case to lock the ground plane model in hq. + if (location.hostname == "hq.highfidelity.io" && + properties.modelURL == "https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/Terrain_Reduce_forAlpha.fbx") { + return true; + } + return false; +} + + function controller(wichSide) { this.side = wichSide; this.palm = 2 * wichSide; @@ -117,7 +127,7 @@ function controller(wichSide) { this.grab = function (modelID, properties) { - if (this.isLocked(properties)) { + if (isLocked(properties)) { print("Model locked " + modelID.id); } else { print("Grabbing " + modelID.id); @@ -150,15 +160,6 @@ function controller(wichSide) { } } - this.isLocked = function (properties) { - // special case to lock the ground plane model in hq. - if (location.hostname == "hq.highfidelity.io" && - properties.modelURL == "https://s3-us-west-1.amazonaws.com/highfidelity-public/ozan/Terrain_Reduce_forAlpha.fbx") { - return true; - } - return false; - } - this.checkModel = function (properties) { // special case to lock the ground plane model in hq. if (this.isLocked(properties)) { @@ -293,6 +294,7 @@ function controller(wichSide) { if (this.pressing) { Vec3.print("Looking at: ", this.palmPosition); var foundModels = Models.findModels(this.palmPosition, LASER_LENGTH_FACTOR); + for (var i = 0; i < foundModels.length; i++) { if (!foundModels[i].isKnownID) { @@ -305,7 +307,9 @@ function controller(wichSide) { } var properties = Models.getModelProperties(foundModels[i]); - if (this.isLocked(properties)) { + print("foundModels["+i+"].modelURL=" + properties.modelURL); + + if (isLocked(properties)) { print("Model locked " + properties.id); } else { print("Checking properties: " + properties.id + " " + properties.isKnownID); @@ -486,7 +490,7 @@ function mousePressEvent(event) { } var properties = Models.getModelProperties(foundModels[i]); - if (this.isLocked(properties)) { + if (isLocked(properties)) { print("Model locked " + properties.id); } else { print("Checking properties: " + properties.id + " " + properties.isKnownID); From 5013c8c2fab31353f6e49dc44c9a73d0da243d1a Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 22 May 2014 12:45:36 -0700 Subject: [PATCH 09/28] Fixed script editor crash when script calls Script.stop(). Also made the processEraseMessage wait until it can lock to ensure particles are deleted. --- .../src/particles/ParticleTreeRenderer.cpp | 3 ++- interface/src/ui/ScriptEditorWidget.cpp | 10 ++++++++++ interface/src/ui/ScriptEditorWidget.h | 1 + libraries/shared/src/SharedUtil.cpp | 18 +++++++++--------- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/interface/src/particles/ParticleTreeRenderer.cpp b/interface/src/particles/ParticleTreeRenderer.cpp index 781fc2bfc8..c89adab65d 100644 --- a/interface/src/particles/ParticleTreeRenderer.cpp +++ b/interface/src/particles/ParticleTreeRenderer.cpp @@ -127,7 +127,8 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element, RenderArgs* arg } void ParticleTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) { - if (_tree->tryLockForWrite()) { + if (_tree){ + _tree->lockForWrite(); static_cast(_tree)->processEraseMessage(dataByteArray, sourceNode); } } diff --git a/interface/src/ui/ScriptEditorWidget.cpp b/interface/src/ui/ScriptEditorWidget.cpp index 07c6e72226..be5577e0e8 100644 --- a/interface/src/ui/ScriptEditorWidget.cpp +++ b/interface/src/ui/ScriptEditorWidget.cpp @@ -57,6 +57,11 @@ void ScriptEditorWidget::onScriptModified() { } } +void ScriptEditorWidget::onScriptEnding() { + // signals will automatically be disonnected when the _scriptEngine is deleted later + _scriptEngine = NULL; +} + bool ScriptEditorWidget::isModified() { return _scriptEditorWidgetUI->scriptEdit->document()->isModified(); } @@ -69,11 +74,13 @@ bool ScriptEditorWidget::setRunning(bool run) { if (run && !save()) { return false; } + // Clean-up old connections. if (_scriptEngine != NULL) { disconnect(_scriptEngine, &ScriptEngine::runningStateChanged, this, &ScriptEditorWidget::runningStateChanged); disconnect(_scriptEngine, &ScriptEngine::errorMessage, this, &ScriptEditorWidget::onScriptError); disconnect(_scriptEngine, &ScriptEngine::printedMessage, this, &ScriptEditorWidget::onScriptPrint); + disconnect(_scriptEngine, &ScriptEngine::scriptEnding, this, &ScriptEditorWidget::onScriptEnding); } if (run) { @@ -83,6 +90,7 @@ bool ScriptEditorWidget::setRunning(bool run) { // Make new connections. connect(_scriptEngine, &ScriptEngine::errorMessage, this, &ScriptEditorWidget::onScriptError); connect(_scriptEngine, &ScriptEngine::printedMessage, this, &ScriptEditorWidget::onScriptPrint); + connect(_scriptEngine, &ScriptEngine::scriptEnding, this, &ScriptEditorWidget::onScriptEnding); } else { Application::getInstance()->stopScript(_currentScript); _scriptEngine = NULL; @@ -125,6 +133,7 @@ void ScriptEditorWidget::loadFile(const QString& scriptPath) { disconnect(_scriptEngine, &ScriptEngine::runningStateChanged, this, &ScriptEditorWidget::runningStateChanged); disconnect(_scriptEngine, &ScriptEngine::errorMessage, this, &ScriptEditorWidget::onScriptError); disconnect(_scriptEngine, &ScriptEngine::printedMessage, this, &ScriptEditorWidget::onScriptPrint); + disconnect(_scriptEngine, &ScriptEngine::scriptEnding, this, &ScriptEditorWidget::onScriptEnding); } } else { QNetworkAccessManager* networkManager = new QNetworkAccessManager(this); @@ -144,6 +153,7 @@ void ScriptEditorWidget::loadFile(const QString& scriptPath) { connect(_scriptEngine, &ScriptEngine::runningStateChanged, this, &ScriptEditorWidget::runningStateChanged); connect(_scriptEngine, &ScriptEngine::errorMessage, this, &ScriptEditorWidget::onScriptError); connect(_scriptEngine, &ScriptEngine::printedMessage, this, &ScriptEditorWidget::onScriptPrint); + connect(_scriptEngine, &ScriptEngine::scriptEnding, this, &ScriptEditorWidget::onScriptEnding); } } diff --git a/interface/src/ui/ScriptEditorWidget.h b/interface/src/ui/ScriptEditorWidget.h index 1a96661cf7..3e95ea322b 100644 --- a/interface/src/ui/ScriptEditorWidget.h +++ b/interface/src/ui/ScriptEditorWidget.h @@ -46,6 +46,7 @@ private slots: void onScriptError(const QString& message); void onScriptPrint(const QString& message); void onScriptModified(); + void onScriptEnding(); private: Ui::ScriptEditorWidget* _scriptEditorWidgetUI; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 1136d49dd4..f29e8e3345 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -276,7 +276,7 @@ unsigned char* pointToOctalCode(float x, float y, float z, float s) { unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, unsigned char g, unsigned char b ) { // special case for size 1, the root node - if (s >= 1.0) { + if (s >= 1.0f) { unsigned char* voxelOut = new unsigned char; *voxelOut = 0; return voxelOut; @@ -289,7 +289,7 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, // voxel of size S. unsigned int voxelSizeInOctets = 1; while (sTest > s) { - sTest /= 2.0; + sTest /= 2.0f; voxelSizeInOctets++; } @@ -314,11 +314,11 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, if (x >= xTest) { // byte = (byte << 1) | true; - xTest += sTest/2.0; + xTest += sTest/2.0f; } else { // byte = (byte << 1) | false; - xTest -= sTest/2.0; + xTest -= sTest/2.0f; } bitInByteNDX++; // If we've reached the last bit of the byte, then we want to copy this byte @@ -333,11 +333,11 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, if (y >= yTest) { // byte = (byte << 1) | true; - yTest += sTest/2.0; + yTest += sTest/2.0f; } else { // byte = (byte << 1) | false; - yTest -= sTest/2.0; + yTest -= sTest/2.0f; } bitInByteNDX++; // If we've reached the last bit of the byte, then we want to copy this byte @@ -352,11 +352,11 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, if (z >= zTest) { // byte = (byte << 1) | true; - zTest += sTest/2.0; + zTest += sTest/2.0f; } else { // byte = (byte << 1) | false; - zTest -= sTest/2.0; + zTest -= sTest/2.0f; } bitInByteNDX++; // If we've reached the last bit of the byte, then we want to copy this byte @@ -369,7 +369,7 @@ unsigned char* pointToVoxel(float x, float y, float z, float s, unsigned char r, } octetsDone++; - sTest /= 2.0; + sTest /= 2.0f; } // If we've got here, and we didn't fill the last byte, we need to zero pad this From b5056dcd3a1ca5586e2270b37a7f4dffc3df7ec8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 22 May 2014 13:01:02 -0700 Subject: [PATCH 10/28] fix broken mouse edit --- examples/editModels.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/editModels.js b/examples/editModels.js index 717b7824bb..5319d75bb9 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -162,7 +162,7 @@ function controller(wichSide) { this.checkModel = function (properties) { // special case to lock the ground plane model in hq. - if (this.isLocked(properties)) { + if (isLocked(properties)) { return { valid: false }; } From a48c6b82e2a5e70b5f37be97c1bc8efe910d6022 Mon Sep 17 00:00:00 2001 From: barnold1953 Date: Thu, 22 May 2014 14:17:26 -0700 Subject: [PATCH 11/28] Fixed my mistake by unlocking the lock. --- interface/src/particles/ParticleTreeRenderer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/particles/ParticleTreeRenderer.cpp b/interface/src/particles/ParticleTreeRenderer.cpp index c89adab65d..d9683405e2 100644 --- a/interface/src/particles/ParticleTreeRenderer.cpp +++ b/interface/src/particles/ParticleTreeRenderer.cpp @@ -130,5 +130,6 @@ void ParticleTreeRenderer::processEraseMessage(const QByteArray& dataByteArray, if (_tree){ _tree->lockForWrite(); static_cast(_tree)->processEraseMessage(dataByteArray, sourceNode); + _tree->unlock(); } } From 01e8d775f23ae5166ebb83d2f1a84c0fb979879e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 22 May 2014 14:24:19 -0700 Subject: [PATCH 12/28] change node auth URL to data.highfidelity.io --- interface/src/ModelUploader.cpp | 1 - interface/src/ui/LoginDialog.cpp | 2 +- interface/ui/loginDialog.ui | 4 ++-- libraries/networking/src/LimitedNodeList.cpp | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/interface/src/ModelUploader.cpp b/interface/src/ModelUploader.cpp index ec7fcee6f2..81bca0fc5a 100644 --- a/interface/src/ModelUploader.cpp +++ b/interface/src/ModelUploader.cpp @@ -50,7 +50,6 @@ static const QString JOINT_FIELD = "joint"; static const QString FREE_JOINT_FIELD = "freeJoint"; static const QString S3_URL = "http://public.highfidelity.io"; -static const QString DATA_SERVER_URL = "https://data-web.highfidelity.io"; static const QString MODEL_URL = "/api/v1/models"; static const QString SETTING_NAME = "LastModelUploadLocation"; diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 40029b6785..57e02689c1 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -21,7 +21,7 @@ #include "LoginDialog.h" -const QString FORGOT_PASSWORD_URL = "https://data-web.highfidelity.io/password/new"; +const QString FORGOT_PASSWORD_URL = "https://data.highfidelity.io/password/new"; LoginDialog::LoginDialog(QWidget* parent) : FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP), diff --git a/interface/ui/loginDialog.ui b/interface/ui/loginDialog.ui index d54b3c833f..73d466b68a 100644 --- a/interface/ui/loginDialog.ui +++ b/interface/ui/loginDialog.ui @@ -136,7 +136,7 @@ <style type="text/css"> a { text-decoration: none; color: #267077;} </style> -Invalid username or password. <a href="https://data-web.highfidelity.io/password/new">Recover?</a> +Invalid username or password. <a href="https://data.highfidelity.io/password/new">Recover?</a> Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter @@ -458,7 +458,7 @@ border-radius: 4px; padding-top: 1px; <style type="text/css"> a { text-decoration: none; color: #267077;} </style> -<a href="https://data-web.highfidelity.io/password/new">Recover password?</a> +<a href="https://data.highfidelity.io/password/new">Recover password?</a> true diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index b5a23f6b99..c0d7941edf 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -33,7 +33,7 @@ const char SOLO_NODE_TYPES[2] = { NodeType::AudioMixer }; -const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data-web.highfidelity.io"); +const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data.highfidelity.io"); LimitedNodeList* LimitedNodeList::_sharedInstance = NULL; From 519f5539d97a9f9be76f89812175e3ff9db23f0f Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 22 May 2014 14:37:34 -0700 Subject: [PATCH 13/28] also support deleting mouse selected model --- examples/editModels.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index 5319d75bb9..55c79cbc1d 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -666,13 +666,17 @@ Menu.menuItemEvent.connect(function(menuItem){ print("menuItemEvent() in JS... menuItem=" + menuItem); if (menuItem == "Delete Model") { if (leftController.grabbing) { - print(" Delete Model.... controller.modelID="+ leftController.modelID); + print(" Delete Model.... leftController.modelID="+ leftController.modelID); Models.deleteModel(leftController.modelID); leftController.grabbing = false; } else if (rightController.grabbing) { - print(" Delete Model.... controller.modelID="+ rightController.modelID); + print(" Delete Model.... rightController.modelID="+ rightController.modelID); Models.deleteModel(rightController.modelID); rightController.grabbing = false; + } else if (modelSelected) { + print(" Delete Model.... selectedModelID="+ selectedModelID); + Models.deleteModel(selectedModelID); + modelSelected = false; } else { print(" Delete Model.... not holding..."); } From d4af39a9f5aded75fc429fe7e89e110529a6c1a3 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 22 May 2014 14:41:46 -0700 Subject: [PATCH 14/28] Working on handling animation priorities to prevent Hydra move/restore from interfering with scripted animations. --- interface/src/avatar/MyAvatar.cpp | 4 +- interface/src/avatar/SkeletonModel.cpp | 29 ++++++----- interface/src/renderer/Model.cpp | 66 ++++++++++++++++---------- interface/src/renderer/Model.h | 16 +++---- interface/src/ui/AnimationsDialog.cpp | 4 ++ interface/src/ui/AnimationsDialog.h | 2 + 6 files changed, 75 insertions(+), 46 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c8d1747505..b2a3ecbedb 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -714,14 +714,14 @@ glm::vec3 MyAvatar::getUprightHeadPosition() const { void MyAvatar::setJointData(int index, const glm::quat& rotation) { Avatar::setJointData(index, rotation); if (QThread::currentThread() == thread()) { - _skeletonModel.setJointState(index, true, rotation); + _skeletonModel.setJointState(index, true, rotation, 2.0f); } } void MyAvatar::clearJointData(int index) { Avatar::clearJointData(index); if (QThread::currentThread() == thread()) { - _skeletonModel.setJointState(index, false); + _skeletonModel.setJointState(index, false, glm::quat(), 2.0f); } } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 09871ad38b..429ab1cf30 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -21,6 +21,8 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar) : _owningAvatar(owningAvatar) { } +const float PALM_PRIORITY = 3.0f; + void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { setTranslation(_owningAvatar->getPosition()); setRotation(_owningAvatar->getOrientation() * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f))); @@ -43,7 +45,7 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { } int jointIndex = geometry.humanIKJointIndices.at(humanIKJointIndex); if (jointIndex != -1) { - setJointRotation(jointIndex, _rotation * prioVR->getJointRotations().at(i), true); + setJointRotation(jointIndex, _rotation * prioVR->getJointRotations().at(i), true, PALM_PRIORITY); } } return; @@ -58,16 +60,16 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { if (leftPalmIndex == -1) { // palms are not yet set, use mouse if (_owningAvatar->getHandState() == HAND_STATE_NULL) { - restoreRightHandPosition(HAND_RESTORATION_RATE); + restoreRightHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else { applyHandPosition(geometry.rightHandJointIndex, _owningAvatar->getHandPosition()); } - restoreLeftHandPosition(HAND_RESTORATION_RATE); + restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else if (leftPalmIndex == rightPalmIndex) { // right hand only applyPalmData(geometry.rightHandJointIndex, hand->getPalms()[leftPalmIndex]); - restoreLeftHandPosition(HAND_RESTORATION_RATE); + restoreLeftHandPosition(HAND_RESTORATION_RATE, PALM_PRIORITY); } else { applyPalmData(geometry.leftHandJointIndex, hand->getPalms()[leftPalmIndex]); @@ -132,7 +134,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) if (jointIndex == -1) { return; } - setJointPosition(jointIndex, position); + setJointPosition(jointIndex, position, glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); const FBXGeometry& geometry = _geometry->getFBXGeometry(); glm::vec3 handPosition, elbowPosition; @@ -148,7 +150,8 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) // align hand with forearm float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; - applyRotationDelta(jointIndex, rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector)); + applyRotationDelta(jointIndex, rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), + forearmVector), true, PALM_PRIORITY); } void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { @@ -183,12 +186,14 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { } else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); setJointPosition(parentJointIndex, palm.getPosition() + forearmVector * - geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale)); - setJointRotation(parentJointIndex, palmRotation, true); + geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), + glm::quat(), false, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); + setJointRotation(parentJointIndex, palmRotation, true, PALM_PRIORITY); _jointStates[jointIndex].rotation = glm::quat(); } else { - setJointPosition(jointIndex, palm.getPosition(), palmRotation, true); + setJointPosition(jointIndex, palm.getPosition(), palmRotation, + true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY); } } @@ -335,11 +340,11 @@ void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, c glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f); glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition); - setJointRotation(shoulderJointIndex, shoulderRotation, true); + setJointRotation(shoulderJointIndex, shoulderRotation, true, PALM_PRIORITY); setJointRotation(elbowJointIndex, rotationBetween(shoulderRotation * forwardVector, - wristPosition - elbowPosition) * shoulderRotation, true); + wristPosition - elbowPosition) * shoulderRotation, true, PALM_PRIORITY); - setJointRotation(jointIndex, rotation, true); + setJointRotation(jointIndex, rotation, true, PALM_PRIORITY); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 5d0f571b5b..db7e0a7c6d 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -118,7 +118,7 @@ QVector Model::createJointStates(const FBXGeometry& geometry) JointState state; state.translation = joint.translation; state.rotation = joint.rotation; - state.animationDisabled = false; + state.animationPriority = 0.0f; jointStates.append(state); } @@ -473,9 +473,18 @@ bool Model::getJointState(int index, glm::quat& rotation) const { glm::abs(rotation.w - defaultRotation.w) >= EPSILON; } -void Model::setJointState(int index, bool valid, const glm::quat& rotation) { +void Model::setJointState(int index, bool valid, const glm::quat& rotation, float priority) { if (index != -1 && index < _jointStates.size()) { - _jointStates[index].rotation = valid ? rotation : _geometry->getFBXGeometry().joints.at(index).rotation; + JointState& state = _jointStates[index]; + if (priority >= state.animationPriority) { + if (valid) { + state.rotation = rotation; + state.animationPriority = priority; + } else if (priority == state.animationPriority) { + state.rotation = _geometry->getFBXGeometry().joints.at(index).rotation; + state.animationPriority = 0.0f; + } + } } } @@ -535,8 +544,8 @@ bool Model::getRightHandRotation(glm::quat& rotation) const { return getJointRotation(getRightHandJointIndex(), rotation); } -bool Model::restoreLeftHandPosition(float percent) { - return restoreJointPosition(getLeftHandJointIndex(), percent); +bool Model::restoreLeftHandPosition(float percent, float priority) { + return restoreJointPosition(getLeftHandJointIndex(), percent, priority); } bool Model::getLeftShoulderPosition(glm::vec3& position) const { @@ -547,8 +556,8 @@ float Model::getLeftArmLength() const { return getLimbLength(getLeftHandJointIndex()); } -bool Model::restoreRightHandPosition(float percent) { - return restoreJointPosition(getRightHandJointIndex(), percent); +bool Model::restoreRightHandPosition(float percent, float priority) { + return restoreJointPosition(getRightHandJointIndex(), percent, priority); } bool Model::getRightShoulderPosition(glm::vec3& position) const { @@ -1115,7 +1124,7 @@ void Model::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint } bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation, bool useRotation, - int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment) { + int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } @@ -1138,7 +1147,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat endRotation; if (useRotation) { getJointRotation(jointIndex, endRotation, true); - applyRotationDelta(jointIndex, rotation * glm::inverse(endRotation)); + applyRotationDelta(jointIndex, rotation * glm::inverse(endRotation), priority); getJointRotation(jointIndex, endRotation, true); } @@ -1182,7 +1191,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const 1.0f / (combinedWeight + 1.0f)); } } - applyRotationDelta(index, combinedDelta); + applyRotationDelta(index, combinedDelta, priority); glm::quat actualDelta = state.combinedRotation * glm::inverse(oldCombinedRotation); endPosition = actualDelta * jointVector + jointPosition; if (useRotation) { @@ -1200,15 +1209,17 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const return true; } -bool Model::setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind) { +bool Model::setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } JointState& state = _jointStates[jointIndex]; - state.rotation = state.rotation * glm::inverse(state.combinedRotation) * rotation * - glm::inverse(fromBind ? _geometry->getFBXGeometry().joints.at(jointIndex).inverseBindRotation : - _geometry->getFBXGeometry().joints.at(jointIndex).inverseDefaultRotation); - state.animationDisabled = true; + if (priority >= state.animationPriority) { + state.rotation = state.rotation * glm::inverse(state.combinedRotation) * rotation * + glm::inverse(fromBind ? _geometry->getFBXGeometry().joints.at(jointIndex).inverseBindRotation : + _geometry->getFBXGeometry().joints.at(jointIndex).inverseDefaultRotation); + state.animationPriority = priority; + } return true; } @@ -1229,7 +1240,7 @@ void Model::setJointTranslation(int jointIndex, const glm::vec3& translation) { state.translation = glm::vec3(glm::inverse(parentTransform) * glm::vec4(translation, 1.0f)) - preTranslation; } -bool Model::restoreJointPosition(int jointIndex, float percent) { +bool Model::restoreJointPosition(int jointIndex, float percent, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } @@ -1238,10 +1249,12 @@ bool Model::restoreJointPosition(int jointIndex, float percent) { foreach (int index, freeLineage) { JointState& state = _jointStates[index]; - const FBXJoint& joint = geometry.joints.at(index); - state.rotation = safeMix(state.rotation, joint.rotation, percent); - state.translation = glm::mix(state.translation, joint.translation, percent); - state.animationDisabled = false; + if (priority == state.animationPriority) { + const FBXJoint& joint = geometry.joints.at(index); + state.rotation = safeMix(state.rotation, joint.rotation, percent); + state.translation = glm::mix(state.translation, joint.translation, percent); + state.animationPriority = 0.0f; + } } return true; } @@ -1260,8 +1273,12 @@ float Model::getLimbLength(int jointIndex) const { return length; } -void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain) { +void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority) { JointState& state = _jointStates[jointIndex]; + if (priority < state.animationPriority) { + return; + } + state.animationPriority = priority; const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex]; if (!constrain || (joint.rotationMin == glm::vec3(-PI, -PI, -PI) && joint.rotationMax == glm::vec3(PI, PI, PI))) { @@ -1275,7 +1292,6 @@ void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool cons glm::quat newRotation = glm::quat(glm::clamp(eulers, joint.rotationMin, joint.rotationMax)); state.combinedRotation = state.combinedRotation * glm::inverse(state.rotation) * newRotation; state.rotation = newRotation; - state.animationDisabled = true; } const int BALL_SUBDIVISIONS = 10; @@ -1749,8 +1765,9 @@ void AnimationHandle::simulate(float deltaTime) { int mapping = _jointMappings.at(i); if (mapping != -1) { Model::JointState& state = _model->_jointStates[mapping]; - if (!state.animationDisabled) { + if (_priority >= state.animationPriority) { state.rotation = frame.rotations.at(i); + state.animationPriority = _priority; } } } @@ -1772,8 +1789,9 @@ void AnimationHandle::simulate(float deltaTime) { int mapping = _jointMappings.at(i); if (mapping != -1) { Model::JointState& state = _model->_jointStates[mapping]; - if (!state.animationDisabled) { + if (_priority >= state.animationPriority) { state.rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction); + state.animationPriority = _priority; } } } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 979dc6c601..23bde4846b 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -113,7 +113,7 @@ public: bool getJointState(int index, glm::quat& rotation) const; /// Sets the joint state at the specified index. - void setJointState(int index, bool valid, const glm::quat& rotation = glm::quat()); + void setJointState(int index, bool valid, const glm::quat& rotation = glm::quat(), float priority = 1.0f); /// Returns the index of the left hand joint, or -1 if not found. int getLeftHandJointIndex() const { return isActive() ? _geometry->getFBXGeometry().leftHandJointIndex : -1; } @@ -166,7 +166,7 @@ public: /// Restores some percentage of the default position of the left hand. /// \param percent the percentage of the default position to restore /// \return whether or not the left hand joint was found - bool restoreLeftHandPosition(float percent = 1.0f); + bool restoreLeftHandPosition(float percent = 1.0f, float priority = 1.0f); /// Gets the position of the left shoulder. /// \return whether or not the left shoulder joint was found @@ -178,7 +178,7 @@ public: /// Restores some percentage of the default position of the right hand. /// \param percent the percentage of the default position to restore /// \return whether or not the right hand joint was found - bool restoreRightHandPosition(float percent = 1.0f); + bool restoreRightHandPosition(float percent = 1.0f, float priority = 1.0f); /// Gets the position of the right shoulder. /// \return whether or not the right shoulder joint was found @@ -254,7 +254,7 @@ protected: glm::quat rotation; // rotation relative to parent glm::mat4 transform; // rotation to world frame + translation in model frame glm::quat combinedRotation; // rotation from joint local to world frame - bool animationDisabled; // if true, animations do not affect this joint + float animationPriority; // the priority of the animation affecting this joint }; bool _shapesAreDirty; @@ -290,8 +290,8 @@ protected: bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(), bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, - const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f)); - bool setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind = false); + const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f); + bool setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind = false, float priority = 1.0f); void setJointTranslation(int jointIndex, const glm::vec3& translation); @@ -299,13 +299,13 @@ protected: /// \param percent the percentage of the default position to apply (i.e., 0.25f to slerp one fourth of the way to /// the original position /// \return true if the joint was found - bool restoreJointPosition(int jointIndex, float percent = 1.0f); + bool restoreJointPosition(int jointIndex, float percent = 1.0f, float priority = 0.0f); /// Computes and returns the extended length of the limb terminating at the specified joint and starting at the joint's /// first free ancestor. float getLimbLength(int jointIndex) const; - void applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain = true); + void applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain = true, float priority = 1.0f); void computeBoundingShape(const FBXGeometry& geometry); diff --git a/interface/src/ui/AnimationsDialog.cpp b/interface/src/ui/AnimationsDialog.cpp index f30c98cce7..205a215b10 100644 --- a/interface/src/ui/AnimationsDialog.cpp +++ b/interface/src/ui/AnimationsDialog.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include #include @@ -80,6 +81,9 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); setLayout(layout); + layout->addRow("Role:", _role = new QComboBox()); + _role->setEditable(true); + QHBoxLayout* urlBox = new QHBoxLayout(); layout->addRow("URL:", urlBox); urlBox->addWidget(_url = new QLineEdit(handle->getURL().toString()), 1); diff --git a/interface/src/ui/AnimationsDialog.h b/interface/src/ui/AnimationsDialog.h index 8b0f6cd257..edda665d10 100644 --- a/interface/src/ui/AnimationsDialog.h +++ b/interface/src/ui/AnimationsDialog.h @@ -18,6 +18,7 @@ #include "avatar/MyAvatar.h" class QCheckBox; +class QComboBox; class QDoubleSpinner; class QLineEdit; class QPushButton; @@ -63,6 +64,7 @@ private: AnimationsDialog* _dialog; AnimationHandlePointer _handle; + QComboBox* _role; QLineEdit* _url; QDoubleSpinBox* _fps; QDoubleSpinBox* _priority; From 79f09605d561a342371f857b4fb66d249f017bbb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 22 May 2014 14:55:43 -0700 Subject: [PATCH 15/28] show credit balance in window title --- interface/src/Application.cpp | 26 ++++++++++++++++--- libraries/networking/src/AccountManager.cpp | 20 ++++++++++++++ libraries/networking/src/AccountManager.h | 5 +++- .../networking/src/DataServerAccountInfo.cpp | 20 +++++++++++++- .../networking/src/DataServerAccountInfo.h | 9 +++++++ 5 files changed, 75 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fd09e530c1..c6704bcd80 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -237,12 +237,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(&nodeList->getDomainHandler(), SIGNAL(connectedToDomain(const QString&)), SLOT(connectedToDomain(const QString&))); // update our location every 5 seconds in the data-server, assuming that we are authenticated with one - const float DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5.0f * 1000.0f; + const qint64 DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS = 5 * 1000; QTimer* locationUpdateTimer = new QTimer(this); connect(locationUpdateTimer, &QTimer::timeout, this, &Application::updateLocationInServer); locationUpdateTimer->start(DATA_SERVER_LOCATION_CHANGE_UPDATE_MSECS); - + connect(nodeList, &NodeList::nodeAdded, this, &Application::nodeAdded); connect(nodeList, &NodeList::nodeKilled, this, &Application::nodeKilled); connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), SLOT(nodeKilled(SharedNodePointer))); @@ -251,9 +251,18 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle); connect(nodeList, SIGNAL(uuidChanged(const QUuid&)), _myAvatar, SLOT(setSessionUUID(const QUuid&))); connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset); - + // connect to appropriate slots on AccountManager AccountManager& accountManager = AccountManager::getInstance(); + + const qint64 BALANCE_UPDATE_INTERVAL_MSECS = 5 * 1000; + + QTimer* balanceUpdateTimer = new QTimer(this); + connect(balanceUpdateTimer, &QTimer::timeout, &accountManager, &AccountManager::updateBalance); + balanceUpdateTimer->start(BALANCE_UPDATE_INTERVAL_MSECS); + + connect(&accountManager, &AccountManager::balanceChanged, this, &Application::updateWindowTitle); + connect(&accountManager, &AccountManager::authRequired, Menu::getInstance(), &Menu::loginForCurrentDomain); connect(&accountManager, &AccountManager::usernameChanged, this, &Application::updateWindowTitle); @@ -3095,6 +3104,17 @@ void Application::updateWindowTitle(){ QString title = QString() + (!username.isEmpty() ? username + " @ " : QString()) + nodeList->getDomainHandler().getHostname() + buildVersion; qDebug("Application title set to: %s", title.toStdString().c_str()); + + AccountManager& accountManager = AccountManager::getInstance(); + if (accountManager.getAccountInfo().hasBalance()) { + float creditBalance = accountManager.getAccountInfo().getBalance() * pow(10.0f, -8.0f); + + QString creditBalanceString; + creditBalanceString.sprintf("%.8f", creditBalance); + + title += " - ₵" + creditBalanceString; + } + _window->setWindowTitle(title); } diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index aad2cfb386..7d27332a57 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -61,6 +61,8 @@ AccountManager::AccountManager() : qRegisterMetaType("QNetworkAccessManager::Operation"); qRegisterMetaType("JSONCallbackParameters"); + + connect(&_accountInfo, &DataServerAccountInfo::balanceChanged, this, &AccountManager::accountInfoBalanceChanged); } const QString DOUBLE_SLASH_SUBSTITUTE = "slashslash"; @@ -69,6 +71,9 @@ void AccountManager::logout() { // a logout means we want to delete the DataServerAccountInfo we currently have for this URL, in-memory and in file _accountInfo = DataServerAccountInfo(); + emit balanceChanged(0); + connect(&_accountInfo, &DataServerAccountInfo::balanceChanged, this, &AccountManager::accountInfoBalanceChanged); + QSettings settings; settings.beginGroup(ACCOUNTS_GROUP); @@ -82,6 +87,21 @@ void AccountManager::logout() { emit usernameChanged(QString()); } +void AccountManager::updateBalance() { + if (hasValidAccessToken()) { + // ask our auth endpoint for our balance + JSONCallbackParameters callbackParameters; + callbackParameters.jsonCallbackReceiver = &_accountInfo; + callbackParameters.jsonCallbackMethod = "setBalanceFromJSON"; + + authenticatedRequest("/api/v1/wallets/mine", QNetworkAccessManager::GetOperation, callbackParameters); + } +} + +void AccountManager::accountInfoBalanceChanged(qint64 newBalance) { + emit balanceChanged(newBalance); +} + void AccountManager::setAuthURL(const QUrl& authURL) { if (_authURL != authURL) { _authURL = authURL; diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index 6bdf5d76d8..f32ff75f51 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -34,7 +34,7 @@ public: QString updateSlot; }; -class AccountManager : public QObject { +class AccountManager: public QObject { Q_OBJECT public: static AccountManager& getInstance(); @@ -63,6 +63,8 @@ public slots: void requestFinished(); void requestError(QNetworkReply::NetworkError error); void logout(); + void updateBalance(); + void accountInfoBalanceChanged(qint64 newBalance); signals: void authRequired(); void authEndpointChanged(); @@ -71,6 +73,7 @@ signals: void loginComplete(const QUrl& authURL); void loginFailed(); void logoutComplete(); + void balanceChanged(qint64 newBalance); private slots: void processReply(); private: diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index 0fdb5ff4b1..ac664bca7c 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -17,7 +17,9 @@ DataServerAccountInfo::DataServerAccountInfo() : _accessToken(), _username(), _xmppPassword(), - _discourseApiKey() + _discourseApiKey(), + _balance(0), + _hasBalance(false) { } @@ -75,6 +77,22 @@ void DataServerAccountInfo::setDiscourseApiKey(const QString& discourseApiKey) { } } +void DataServerAccountInfo::setBalance(quint64 balance) { + if (!_hasBalance || _balance != balance) { + _balance = balance; + _hasBalance = true; + + emit balanceChanged(_balance); + } +} + +void DataServerAccountInfo::setBalanceFromJSON(const QJsonObject& jsonObject) { + if (jsonObject["status"].toString() == "success") { + qint64 balanceInSatoshis = jsonObject["data"].toObject()["wallet"].toObject()["balance"].toInt(); + setBalance(balanceInSatoshis); + } +} + QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info) { out << info._accessToken << info._username << info._xmppPassword << info._discourseApiKey; return out; diff --git a/libraries/networking/src/DataServerAccountInfo.h b/libraries/networking/src/DataServerAccountInfo.h index a7d1fa9cb0..f3fe2401fe 100644 --- a/libraries/networking/src/DataServerAccountInfo.h +++ b/libraries/networking/src/DataServerAccountInfo.h @@ -34,9 +34,16 @@ public: const QString& getDiscourseApiKey() const { return _discourseApiKey; } void setDiscourseApiKey(const QString& discourseApiKey); + + quint64 getBalance() const { return _balance; } + void setBalance(quint64 balance); + bool hasBalance() const { return _hasBalance; } + Q_INVOKABLE void setBalanceFromJSON(const QJsonObject& jsonObject); friend QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info); friend QDataStream& operator>>(QDataStream &in, DataServerAccountInfo& info); +signals: + qint64 balanceChanged(qint64 newBalance); private: void swap(DataServerAccountInfo& otherInfo); @@ -44,6 +51,8 @@ private: QString _username; QString _xmppPassword; QString _discourseApiKey; + quint64 _balance; + bool _hasBalance; }; #endif // hifi_DataServerAccountInfo_h From 083543419d411110027545e9c269c8b7a3ae9b98 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 22 May 2014 15:00:36 -0700 Subject: [PATCH 16/28] More priority bits. --- interface/src/avatar/MyAvatar.cpp | 6 ++++-- interface/src/renderer/Model.cpp | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b2a3ecbedb..06f36afe52 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -711,17 +711,19 @@ glm::vec3 MyAvatar::getUprightHeadPosition() const { return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f); } +const float JOINT_PRIORITY = 2.0f; + void MyAvatar::setJointData(int index, const glm::quat& rotation) { Avatar::setJointData(index, rotation); if (QThread::currentThread() == thread()) { - _skeletonModel.setJointState(index, true, rotation, 2.0f); + _skeletonModel.setJointState(index, true, rotation, JOINT_PRIORITY); } } void MyAvatar::clearJointData(int index) { Avatar::clearJointData(index); if (QThread::currentThread() == thread()) { - _skeletonModel.setJointState(index, false, glm::quat(), 2.0f); + _skeletonModel.setJointState(index, false, glm::quat(), JOINT_PRIORITY); } } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 835c8fd901..636f66fa16 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1681,7 +1681,7 @@ void AnimationHandle::setURL(const QUrl& url) { static void insertSorted(QList& handles, const AnimationHandlePointer& handle) { for (QList::iterator it = handles.begin(); it != handles.end(); it++) { - if (handle->getPriority() < (*it)->getPriority()) { + if (handle->getPriority() > (*it)->getPriority()) { handles.insert(it, handle); return; } @@ -1713,6 +1713,15 @@ void AnimationHandle::setRunning(bool running) { } else { _model->_runningAnimations.removeOne(_self); + for (int i = 0; i < _jointMappings.size(); i++) { + int mapping = _jointMappings.at(i); + if (mapping != -1) { + Model::JointState& state = _model->_jointStates[mapping]; + if (_priority == state.animationPriority) { + state.animationPriority = 0.0f; + } + } + } } } From 164d3c5fb3aea2ff3c523efc19260ebb569115b9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 22 May 2014 15:06:16 -0700 Subject: [PATCH 17/28] make sure balance is cleared on logout and re-launch --- interface/src/Application.cpp | 2 +- libraries/networking/src/DataServerAccountInfo.cpp | 8 +++++++- libraries/networking/src/DataServerAccountInfo.h | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c6704bcd80..07309fab85 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3103,7 +3103,6 @@ void Application::updateWindowTitle(){ QString username = AccountManager::getInstance().getAccountInfo().getUsername(); QString title = QString() + (!username.isEmpty() ? username + " @ " : QString()) + nodeList->getDomainHandler().getHostname() + buildVersion; - qDebug("Application title set to: %s", title.toStdString().c_str()); AccountManager& accountManager = AccountManager::getInstance(); if (accountManager.getAccountInfo().hasBalance()) { @@ -3115,6 +3114,7 @@ void Application::updateWindowTitle(){ title += " - ₵" + creditBalanceString; } + qDebug("Application title set to: %s", title.toStdString().c_str()); _window->setWindowTitle(title); } diff --git a/libraries/networking/src/DataServerAccountInfo.cpp b/libraries/networking/src/DataServerAccountInfo.cpp index ac664bca7c..b3607200fe 100644 --- a/libraries/networking/src/DataServerAccountInfo.cpp +++ b/libraries/networking/src/DataServerAccountInfo.cpp @@ -27,7 +27,9 @@ DataServerAccountInfo::DataServerAccountInfo() : DataServerAccountInfo::DataServerAccountInfo(const QJsonObject& jsonObject) : _accessToken(jsonObject), _username(), - _xmppPassword() + _xmppPassword(), + _balance(0), + _hasBalance(false) { QJsonObject userJSONObject = jsonObject["user"].toObject(); setUsername(userJSONObject["username"].toString()); @@ -40,6 +42,8 @@ DataServerAccountInfo::DataServerAccountInfo(const DataServerAccountInfo& otherI _username = otherInfo._username; _xmppPassword = otherInfo._xmppPassword; _discourseApiKey = otherInfo._discourseApiKey; + _balance = otherInfo._balance; + _hasBalance = otherInfo._hasBalance; } DataServerAccountInfo& DataServerAccountInfo::operator=(const DataServerAccountInfo& otherInfo) { @@ -55,6 +59,8 @@ void DataServerAccountInfo::swap(DataServerAccountInfo& otherInfo) { swap(_username, otherInfo._username); swap(_xmppPassword, otherInfo._xmppPassword); swap(_discourseApiKey, otherInfo._discourseApiKey); + swap(_balance, otherInfo._balance); + swap(_hasBalance, otherInfo._hasBalance); } void DataServerAccountInfo::setUsername(const QString& username) { diff --git a/libraries/networking/src/DataServerAccountInfo.h b/libraries/networking/src/DataServerAccountInfo.h index f3fe2401fe..fd135f922b 100644 --- a/libraries/networking/src/DataServerAccountInfo.h +++ b/libraries/networking/src/DataServerAccountInfo.h @@ -38,6 +38,7 @@ public: quint64 getBalance() const { return _balance; } void setBalance(quint64 balance); bool hasBalance() const { return _hasBalance; } + void setHasBalance(bool hasBalance) { _hasBalance = hasBalance; } Q_INVOKABLE void setBalanceFromJSON(const QJsonObject& jsonObject); friend QDataStream& operator<<(QDataStream &out, const DataServerAccountInfo& info); From 40c59a35890eba2c7b3424f81d667dd0fce0aa2f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 22 May 2014 15:10:41 -0700 Subject: [PATCH 18/28] fix rate of payment for assignments --- domain-server/src/DomainServer.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9ad36e6956..20e34744db 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -731,10 +731,11 @@ void DomainServer::setupPendingAssignmentCredits() { qint64 elapsedMsecsSinceLastPayment = nodeData->getPaymentIntervalTimer().elapsed(); nodeData->getPaymentIntervalTimer().restart(); - const float CREDITS_PER_HOUR = 3; + const float CREDITS_PER_HOUR = 0.10; const float CREDITS_PER_MSEC = CREDITS_PER_HOUR / (60 * 60 * 1000); + const int SATOSHIS_PER_MSEC = CREDITS_PER_MSEC * powf(10, 8); - float pendingCredits = elapsedMsecsSinceLastPayment * CREDITS_PER_MSEC; + float pendingCredits = elapsedMsecsSinceLastPayment * SATOSHIS_PER_MSEC; if (existingTransaction) { existingTransaction->incrementAmount(pendingCredits); From fc9d850c40399bcdf20e6fcbcc6a24357dda83c1 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 22 May 2014 15:33:06 -0700 Subject: [PATCH 19/28] output when pay-for-assignments is on --- domain-server/src/DomainServer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 20e34744db..cd8e66a2b5 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -218,6 +218,8 @@ bool DomainServer::optionallySetupAssignmentPayment() { } } + qDebug() << "Assignments will be paid for via" << qPrintable(_oauthProviderURL.toString()); + // assume that the fact we are authing against HF data server means we will pay for assignments // setup a timer to send transactions to pay assigned nodes every 30 seconds QTimer* creditSetupTimer = new QTimer(this); From 8458477b9f7d47d4b2dd2ca806e5c265b648cf89 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 22 May 2014 16:15:34 -0700 Subject: [PATCH 20/28] Fixed a compile warning, provide means to start/stop animations. --- interface/src/AudioReflector.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 6 ++++-- interface/src/renderer/Model.cpp | 19 +++++++++++++++-- interface/src/renderer/Model.h | 18 ++++++++++++++-- interface/src/ui/AnimationsDialog.cpp | 30 ++++++++++++++++++++++----- interface/src/ui/AnimationsDialog.h | 4 ++++ 6 files changed, 67 insertions(+), 12 deletions(-) diff --git a/interface/src/AudioReflector.cpp b/interface/src/AudioReflector.cpp index e66735c403..52d23b4fee 100644 --- a/interface/src/AudioReflector.cpp +++ b/interface/src/AudioReflector.cpp @@ -17,7 +17,7 @@ const float MINIMUM_ATTENUATION_TO_REFLECT = 1.0f / 256.0f; const float DEFAULT_DISTANCE_SCALING_FACTOR = 2.0f; const float MAXIMUM_DELAY_MS = 1000.0 * 20.0f; // stop reflecting after path is this long const int DEFAULT_DIFFUSION_FANOUT = 5; -const int ABSOLUTE_MAXIMUM_BOUNCE_COUNT = 10; +const unsigned int ABSOLUTE_MAXIMUM_BOUNCE_COUNT = 10; const float DEFAULT_LOCAL_ATTENUATION_FACTOR = 0.125; const float DEFAULT_COMB_FILTER_WINDOW = 0.05f; //ms delay differential to avoid diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 06f36afe52..25eb071c8a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -430,8 +430,6 @@ void MyAvatar::setGravity(const glm::vec3& gravity) { AnimationHandlePointer MyAvatar::addAnimationHandle() { AnimationHandlePointer handle = _skeletonModel.createAnimationHandle(); - handle->setLoop(true); - handle->start(); _animationHandles.append(handle); return handle; } @@ -516,11 +514,13 @@ void MyAvatar::saveData(QSettings* settings) { for (int i = 0; i < _animationHandles.size(); i++) { settings->setArrayIndex(i); const AnimationHandlePointer& pointer = _animationHandles.at(i); + settings->setValue("role", pointer->getRole()); settings->setValue("url", pointer->getURL()); settings->setValue("fps", pointer->getFPS()); settings->setValue("priority", pointer->getPriority()); settings->setValue("loop", pointer->getLoop()); settings->setValue("hold", pointer->getHold()); + settings->setValue("startAutomatically", pointer->getStartAutomatically()); settings->setValue("firstFrame", pointer->getFirstFrame()); settings->setValue("lastFrame", pointer->getLastFrame()); settings->setValue("maskedJoints", pointer->getMaskedJoints()); @@ -587,11 +587,13 @@ void MyAvatar::loadData(QSettings* settings) { for (int i = 0; i < animationCount; i++) { settings->setArrayIndex(i); const AnimationHandlePointer& handle = _animationHandles.at(i); + handle->setRole(settings->value("role", "idle").toString()); handle->setURL(settings->value("url").toUrl()); handle->setFPS(loadSetting(settings, "fps", 30.0f)); handle->setPriority(loadSetting(settings, "priority", 1.0f)); handle->setLoop(settings->value("loop", true).toBool()); handle->setHold(settings->value("hold", false).toBool()); + handle->setStartAutomatically(settings->value("startAutomatically", true).toBool()); handle->setFirstFrame(settings->value("firstFrame", 0).toInt()); handle->setLastFrame(settings->value("lastFrame", INT_MAX).toInt()); handle->setMaskedJoints(settings->value("maskedJoints").toStringList()); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 636f66fa16..3005921d39 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1699,12 +1699,25 @@ void AnimationHandle::setPriority(float priority) { } } +void AnimationHandle::setStartAutomatically(bool startAutomatically) { + if ((_startAutomatically = startAutomatically) && !_running) { + start(); + } +} + void AnimationHandle::setMaskedJoints(const QStringList& maskedJoints) { _maskedJoints = maskedJoints; _jointMappings.clear(); } void AnimationHandle::setRunning(bool running) { + if (_running == running) { + if (running) { + // move back to the beginning + _frameIndex = _firstFrame; + } + return; + } if ((_running = running)) { if (!_model->_runningAnimations.contains(_self)) { insertSorted(_model->_runningAnimations, _self); @@ -1723,6 +1736,7 @@ void AnimationHandle::setRunning(bool running) { } } } + emit runningChanged(_running); } AnimationHandle::AnimationHandle(Model* model) : @@ -1730,10 +1744,11 @@ AnimationHandle::AnimationHandle(Model* model) : _model(model), _fps(30.0f), _priority(1.0f), - _firstFrame(0), - _lastFrame(INT_MAX), _loop(false), _hold(false), + _startAutomatically(false), + _firstFrame(0), + _lastFrame(INT_MAX), _running(false) { } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 23bde4846b..a0806ee238 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -381,6 +381,9 @@ class AnimationHandle : public QObject { public: + void setRole(const QString& role) { _role = role; } + const QString& getRole() const { return _role; } + void setURL(const QUrl& url); const QUrl& getURL() const { return _url; } @@ -396,6 +399,9 @@ public: void setHold(bool hold) { _hold = hold; } bool getHold() const { return _hold; } + void setStartAutomatically(bool startAutomatically); + bool getStartAutomatically() const { return _startAutomatically; } + void setFirstFrame(int firstFrame) { _firstFrame = firstFrame; } int getFirstFrame() const { return _firstFrame; } @@ -407,7 +413,13 @@ public: void setRunning(bool running); bool isRunning() const { return _running; } + +signals: + void runningChanged(bool running); + +public slots: + void start() { setRunning(true); } void stop() { setRunning(false); } @@ -422,13 +434,15 @@ private: Model* _model; WeakAnimationHandlePointer _self; AnimationPointer _animation; + QString _role; QUrl _url; float _fps; float _priority; - int _firstFrame; - int _lastFrame; bool _loop; bool _hold; + bool _startAutomatically; + int _firstFrame; + int _lastFrame; QStringList _maskedJoints; bool _running; QVector _jointMappings; diff --git a/interface/src/ui/AnimationsDialog.cpp b/interface/src/ui/AnimationsDialog.cpp index 205a215b10..9f62abc270 100644 --- a/interface/src/ui/AnimationsDialog.cpp +++ b/interface/src/ui/AnimationsDialog.cpp @@ -82,7 +82,11 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo setLayout(layout); layout->addRow("Role:", _role = new QComboBox()); + _role->addItem("idle"); + _role->addItem("sit"); _role->setEditable(true); + _role->setCurrentText(handle->getRole()); + connect(_role, SIGNAL(currentTextChanged(const QString&)), SLOT(updateHandle())); QHBoxLayout* urlBox = new QHBoxLayout(); layout->addRow("URL:", urlBox); @@ -120,6 +124,10 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo _hold->setChecked(handle->getHold()); connect(_hold, SIGNAL(toggled(bool)), SLOT(updateHandle())); + layout->addRow("Start Automatically:", _startAutomatically = new QCheckBox()); + _startAutomatically->setChecked(handle->getStartAutomatically()); + connect(_startAutomatically, SIGNAL(toggled(bool)), SLOT(updateHandle())); + layout->addRow("First Frame:", _firstFrame = new QSpinBox()); _firstFrame->setMaximum(INT_MAX); _firstFrame->setValue(handle->getFirstFrame()); @@ -130,9 +138,18 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo _lastFrame->setValue(handle->getLastFrame()); connect(_lastFrame, SIGNAL(valueChanged(int)), SLOT(updateHandle())); + QHBoxLayout* buttons = new QHBoxLayout(); + layout->addRow(buttons); + buttons->addWidget(_start = new QPushButton("Start")); + _handle->connect(_start, SIGNAL(clicked(bool)), SLOT(start())); + buttons->addWidget(_stop = new QPushButton("Stop")); + _handle->connect(_stop, SIGNAL(clicked(bool)), SLOT(stop())); QPushButton* remove = new QPushButton("Delete"); - layout->addRow(remove); + buttons->addWidget(remove); connect(remove, SIGNAL(clicked(bool)), SLOT(removeHandle())); + + connect(_handle.data(), SIGNAL(runningChanged(bool)), SLOT(updateStartStop())); + updateStartStop(); } void AnimationPanel::chooseURL() { @@ -168,19 +185,22 @@ void AnimationPanel::chooseMaskedJoints() { } } +void AnimationPanel::updateStartStop() { + _start->setEnabled(!_handle->isRunning()); + _stop->setEnabled(_handle->isRunning()); +} + void AnimationPanel::updateHandle() { + _handle->setRole(_role->currentText()); _handle->setURL(_url->text()); _handle->setFPS(_fps->value()); _handle->setPriority(_priority->value()); _handle->setLoop(_loop->isChecked()); _handle->setHold(_hold->isChecked()); + _handle->setStartAutomatically(_startAutomatically->isChecked()); _handle->setFirstFrame(_firstFrame->value()); _handle->setLastFrame(_lastFrame->value()); _handle->setMaskedJoints(_maskedJoints->text().split(QRegExp("\\s*,\\s*"))); - - if ((_loop->isChecked() || _hold->isChecked()) && !_handle->isRunning()) { - _handle->start(); - } } void AnimationPanel::removeHandle() { diff --git a/interface/src/ui/AnimationsDialog.h b/interface/src/ui/AnimationsDialog.h index edda665d10..6f7a2f3784 100644 --- a/interface/src/ui/AnimationsDialog.h +++ b/interface/src/ui/AnimationsDialog.h @@ -57,6 +57,7 @@ private slots: void chooseURL(); void chooseMaskedJoints(); + void updateStartStop(); void updateHandle(); void removeHandle(); @@ -70,10 +71,13 @@ private: QDoubleSpinBox* _priority; QCheckBox* _loop; QCheckBox* _hold; + QCheckBox* _startAutomatically; QSpinBox* _firstFrame; QSpinBox* _lastFrame; QLineEdit* _maskedJoints; QPushButton* _chooseMaskedJoints; + QPushButton* _start; + QPushButton* _stop; bool _applying; }; From 2a50b5451f56c4c6ff2fc5d121d56471453599fe Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 22 May 2014 16:41:51 -0700 Subject: [PATCH 21/28] Script commands to start/stop animations by role. --- interface/src/avatar/MyAvatar.cpp | 42 ++++++++++++++++++++++++++++++- interface/src/avatar/MyAvatar.h | 9 +++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 25eb071c8a..042d2cdc7c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -459,6 +459,47 @@ void MyAvatar::startAnimation(const QString& url, float fps, float priority, handle->start(); } +void MyAvatar::startAnimationByRole(const QString& role, const QString& url, float fps, float priority, + bool loop, bool hold, int firstFrame, int lastFrame, const QStringList& maskedJoints) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "startAnimationByRole", Q_ARG(const QString&, role), Q_ARG(const QString&, url), + Q_ARG(float, fps), Q_ARG(float, priority), Q_ARG(bool, loop), Q_ARG(bool, hold), Q_ARG(int, firstFrame), + Q_ARG(int, lastFrame), Q_ARG(const QStringList&, maskedJoints)); + return; + } + // check for a configured animation for the role + foreach (const AnimationHandlePointer& handle, _animationHandles) { + if (handle->getRole() == role) { + handle->start(); + return; + } + } + // no joy; use the parameters provided + AnimationHandlePointer handle = _skeletonModel.createAnimationHandle(); + handle->setRole(role); + handle->setURL(url); + handle->setFPS(fps); + handle->setPriority(priority); + handle->setLoop(loop); + handle->setHold(hold); + handle->setFirstFrame(firstFrame); + handle->setLastFrame(lastFrame); + handle->setMaskedJoints(maskedJoints); + handle->start(); +} + +void MyAvatar::stopAnimationByRole(const QString& role) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "stopAnimationByRole", Q_ARG(const QString&, role)); + return; + } + foreach (const AnimationHandlePointer& handle, _skeletonModel.getRunningAnimations()) { + if (handle->getRole() == role) { + handle->stop(); + } + } +} + void MyAvatar::stopAnimation(const QString& url) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "stopAnimation", Q_ARG(const QString&, url)); @@ -467,7 +508,6 @@ void MyAvatar::stopAnimation(const QString& url) { foreach (const AnimationHandlePointer& handle, _skeletonModel.getRunningAnimations()) { if (handle->getURL() == url) { handle->stop(); - return; } } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fcbb2103d1..a8eb3babd0 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -73,6 +73,15 @@ public: /// Stops an animation as identified by a URL. Q_INVOKABLE void stopAnimation(const QString& url); + /// Starts an animation by its role, using the provided URL and parameters if the avatar doesn't have a custom + /// animation for the role. + Q_INVOKABLE void startAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f, + float priority = 1.0f, bool loop = false, bool hold = false, int firstFrame = 0, + int lastFrame = INT_MAX, const QStringList& maskedJoints = QStringList()); + + /// Stops an animation identified by its role. + Q_INVOKABLE void stopAnimationByRole(const QString& role); + // get/set avatar data void saveData(QSettings* settings); void loadData(QSettings* settings); From a32dfdb7bbb51d8196bc7b7a9d1da89ee02c56d3 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 22 May 2014 17:05:28 -0700 Subject: [PATCH 22/28] We should let people "start" even if the animation is already playing (to start again from the beginning). Fixed an issue with competing priorities. --- interface/src/renderer/Model.cpp | 38 +++++++++++++++++---------- interface/src/renderer/Model.h | 3 ++- interface/src/ui/AnimationsDialog.cpp | 9 ++----- interface/src/ui/AnimationsDialog.h | 1 - 4 files changed, 28 insertions(+), 23 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 3005921d39..5d94a9a7d0 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1690,12 +1690,19 @@ static void insertSorted(QList& handles, const Animation } void AnimationHandle::setPriority(float priority) { - if (_priority != priority) { - _priority = priority; - if (_running) { - _model->_runningAnimations.removeOne(_self); - insertSorted(_model->_runningAnimations, _self); + if (_priority == priority) { + return; + } + if (_running) { + _model->_runningAnimations.removeOne(_self); + if (priority < _priority) { + lowerPriority(priority); } + _priority = priority; + insertSorted(_model->_runningAnimations, _self); + + } else { + _priority = priority; } } @@ -1726,15 +1733,7 @@ void AnimationHandle::setRunning(bool running) { } else { _model->_runningAnimations.removeOne(_self); - for (int i = 0; i < _jointMappings.size(); i++) { - int mapping = _jointMappings.at(i); - if (mapping != -1) { - Model::JointState& state = _model->_jointStates[mapping]; - if (_priority == state.animationPriority) { - state.animationPriority = 0.0f; - } - } - } + lowerPriority(0.0f); } emit runningChanged(_running); } @@ -1820,3 +1819,14 @@ void AnimationHandle::simulate(float deltaTime) { } } +void AnimationHandle::lowerPriority(float newPriority) { + for (int i = 0; i < _jointMappings.size(); i++) { + int mapping = _jointMappings.at(i); + if (mapping != -1) { + Model::JointState& state = _model->_jointStates[mapping]; + if (_priority == state.animationPriority) { + state.animationPriority = newPriority; + } + } + } +} diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index a0806ee238..c2aeec7183 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -430,7 +430,8 @@ private: AnimationHandle(Model* model); void simulate(float deltaTime); - + void lowerPriority(float newPriority); + Model* _model; WeakAnimationHandlePointer _self; AnimationPointer _animation; diff --git a/interface/src/ui/AnimationsDialog.cpp b/interface/src/ui/AnimationsDialog.cpp index 9f62abc270..2456b589da 100644 --- a/interface/src/ui/AnimationsDialog.cpp +++ b/interface/src/ui/AnimationsDialog.cpp @@ -148,8 +148,8 @@ AnimationPanel::AnimationPanel(AnimationsDialog* dialog, const AnimationHandlePo buttons->addWidget(remove); connect(remove, SIGNAL(clicked(bool)), SLOT(removeHandle())); - connect(_handle.data(), SIGNAL(runningChanged(bool)), SLOT(updateStartStop())); - updateStartStop(); + _stop->connect(_handle.data(), SIGNAL(runningChanged(bool)), SLOT(setEnabled(bool))); + _stop->setEnabled(_handle->isRunning()); } void AnimationPanel::chooseURL() { @@ -185,11 +185,6 @@ void AnimationPanel::chooseMaskedJoints() { } } -void AnimationPanel::updateStartStop() { - _start->setEnabled(!_handle->isRunning()); - _stop->setEnabled(_handle->isRunning()); -} - void AnimationPanel::updateHandle() { _handle->setRole(_role->currentText()); _handle->setURL(_url->text()); diff --git a/interface/src/ui/AnimationsDialog.h b/interface/src/ui/AnimationsDialog.h index 6f7a2f3784..dd3865741e 100644 --- a/interface/src/ui/AnimationsDialog.h +++ b/interface/src/ui/AnimationsDialog.h @@ -57,7 +57,6 @@ private slots: void chooseURL(); void chooseMaskedJoints(); - void updateStartStop(); void updateHandle(); void removeHandle(); From 6d500d64d12bb4d75cb817208e7f13e086ec6deb Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 22 May 2014 17:12:22 -0700 Subject: [PATCH 23/28] fix floats that aren't actually floats --- domain-server/src/DomainServer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index cd8e66a2b5..f979de64c0 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -733,9 +733,9 @@ void DomainServer::setupPendingAssignmentCredits() { qint64 elapsedMsecsSinceLastPayment = nodeData->getPaymentIntervalTimer().elapsed(); nodeData->getPaymentIntervalTimer().restart(); - const float CREDITS_PER_HOUR = 0.10; + const float CREDITS_PER_HOUR = 0.10f; const float CREDITS_PER_MSEC = CREDITS_PER_HOUR / (60 * 60 * 1000); - const int SATOSHIS_PER_MSEC = CREDITS_PER_MSEC * powf(10, 8); + const int SATOSHIS_PER_MSEC = CREDITS_PER_MSEC * powf(10.0f, 8.0f); float pendingCredits = elapsedMsecsSinceLastPayment * SATOSHIS_PER_MSEC; From 4f81bac742a2bf54db72e78f8cc1760c00d6438d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 22 May 2014 17:16:42 -0700 Subject: [PATCH 24/28] add back a missing space in AccountManager --- libraries/networking/src/AccountManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index f32ff75f51..628b084ea8 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -34,7 +34,7 @@ public: QString updateSlot; }; -class AccountManager: public QObject { +class AccountManager : public QObject { Q_OBJECT public: static AccountManager& getInstance(); From 2681312b54757fd2ef0b938b81d34149ce53cb3f Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 23 May 2014 00:09:15 -0700 Subject: [PATCH 25/28] Velocity damped hand positions --- examples/hydraMove.js | 2 +- interface/src/devices/SixenseManager.cpp | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/examples/hydraMove.js b/examples/hydraMove.js index 60823ffb36..bd462f5e38 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -50,7 +50,7 @@ var JOYSTICK_PITCH_MAG = PITCH_MAG * 0.5; var LEFT_PALM = 0; -var LEFT_BUTTON_4 = 5; +var LEFT_BUTTON_4 = 4; var LEFT_BUTTON_FWD = 5; var RIGHT_PALM = 2; var RIGHT_BUTTON_4 = 10; diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 547642a1be..d2784961bd 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -120,7 +120,6 @@ void SixenseManager::update(float deltaTime) { // Rotation of Palm glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]); rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * _orbRotation * rotation; - palm->setRawRotation(rotation); // Compute current velocity from position change glm::vec3 rawVelocity; @@ -130,8 +129,13 @@ void SixenseManager::update(float deltaTime) { rawVelocity = glm::vec3(0.0f); } palm->setRawVelocity(rawVelocity); // meters/sec - palm->setRawPosition(position); - + + // Use a velocity sensitive filter to damp small motions and preserve large ones with + // no latency. + float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); + palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter)); + palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter)); + // use the velocity to determine whether there's any movement (if the hand isn't new) const float MOVEMENT_DISTANCE_THRESHOLD = 0.003f; _amountMoved += rawVelocity * deltaTime; From f7f4c48b9b9578860460118c281ef2857695911d Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Fri, 23 May 2014 08:40:41 -0600 Subject: [PATCH 26/28] Revert "Initialise lisencing manager after we have enabled Visage." This reverts commit 061f182fab4a8f72e046021cec93a3a41ac22f82. --- interface/src/devices/Visage.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/interface/src/devices/Visage.cpp b/interface/src/devices/Visage.cpp index 70cdaf2b01..119d89654a 100644 --- a/interface/src/devices/Visage.cpp +++ b/interface/src/devices/Visage.cpp @@ -41,8 +41,14 @@ Visage::Visage() : _headOrigin(DEFAULT_HEAD_ORIGIN) { #ifdef HAVE_VISAGE - _tracker = NULL; - _data = NULL; +#ifdef WIN32 + QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage"; +#else + QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage/license.vlc"; +#endif + initializeLicenseManager(licensePath.data()); + _tracker = new VisageTracker2(Application::resourcesPath().toLatin1() + "visage/tracker.cfg"); + _data = new FaceData(); #endif } @@ -173,19 +179,6 @@ void Visage::setEnabled(bool enabled) { return; } if ((_enabled = enabled)) { - if(_tracker == NULL && _data == NULL){ - - #ifdef WIN32 - QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage"; - #else - QByteArray licensePath = Application::resourcesPath().toLatin1() + "visage/license.vlc"; - #endif - - initializeLicenseManager(licensePath.data()); - _tracker = new VisageTracker2(Application::resourcesPath().toLatin1() + "visage/tracker.cfg"); - _data = new FaceData(); - } - _tracker->trackFromCam(); } else { _tracker->stop(); From 4d6e8a2c9e5746e230d43dba53552312203f3348 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 23 May 2014 09:42:36 -0700 Subject: [PATCH 27/28] Or rather, replaceMatchingPriorities. --- interface/src/renderer/Model.cpp | 6 +++--- interface/src/renderer/Model.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 5d94a9a7d0..d18abce677 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1696,7 +1696,7 @@ void AnimationHandle::setPriority(float priority) { if (_running) { _model->_runningAnimations.removeOne(_self); if (priority < _priority) { - lowerPriority(priority); + replaceMatchingPriorities(priority); } _priority = priority; insertSorted(_model->_runningAnimations, _self); @@ -1733,7 +1733,7 @@ void AnimationHandle::setRunning(bool running) { } else { _model->_runningAnimations.removeOne(_self); - lowerPriority(0.0f); + replaceMatchingPriorities(0.0f); } emit runningChanged(_running); } @@ -1819,7 +1819,7 @@ void AnimationHandle::simulate(float deltaTime) { } } -void AnimationHandle::lowerPriority(float newPriority) { +void AnimationHandle::replaceMatchingPriorities(float newPriority) { for (int i = 0; i < _jointMappings.size(); i++) { int mapping = _jointMappings.at(i); if (mapping != -1) { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index c2aeec7183..1a6642dfc6 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -430,7 +430,7 @@ private: AnimationHandle(Model* model); void simulate(float deltaTime); - void lowerPriority(float newPriority); + void replaceMatchingPriorities(float newPriority); Model* _model; WeakAnimationHandlePointer _self; From 6998dfae3cd731f0bfa997c4ec08e3341d2e276d Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 23 May 2014 09:57:47 -0700 Subject: [PATCH 28/28] add visual indicator of thrust direction --- examples/hydraMove.js | 60 ++++++++++++++++++++++++ interface/src/devices/SixenseManager.cpp | 2 +- 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/examples/hydraMove.js b/examples/hydraMove.js index bd462f5e38..ed6a5a4f44 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -26,6 +26,7 @@ var THRUST_INCREASE_RATE = 1.05; var MAX_THRUST_MULTIPLIER = 75.0; var thrustMultiplier = INITIAL_THRUST_MULTPLIER; var grabDelta = { x: 0, y: 0, z: 0}; +var grabStartPosition = { x: 0, y: 0, z: 0}; var grabDeltaVelocity = { x: 0, y: 0, z: 0}; var grabStartRotation = { x: 0, y: 0, z: 0, w: 1}; var grabCurrentRotation = { x: 0, y: 0, z: 0, w: 1}; @@ -63,6 +64,63 @@ function printVector(text, v, decimals) { } var debug = false; +var RED_COLOR = { red: 255, green: 0, blue: 0 }; +var GRAY_COLOR = { red: 25, green: 25, blue: 25 }; +var defaultPosition = { x: 0, y: 0, z: 0}; +var RADIUS = 0.05; +var greenSphere = -1; +var redSphere = -1; + +function createDebugOverlay() { + + if (greenSphere == -1) { + greenSphere = Overlays.addOverlay("sphere", { + position: defaultPosition, + size: RADIUS, + color: GRAY_COLOR, + alpha: 1, + visible: true, + solid: true, + anchor: "MyAvatar" + }); + redSphere = Overlays.addOverlay("sphere", { + position: defaultPosition, + size: RADIUS, + color: RED_COLOR, + alpha: 1, + visible: true, + solid: true, + anchor: "MyAvatar" + }); + } +} + +function destroyDebugOverlay() { + if (greenSphere != -1) { + Overlays.deleteOverlay(greenSphere); + Overlays.deleteOverlay(redSphere); + greenSphere = -1; + redSphere = -1; + } +} + +function displayDebug() { + if (!(grabbingWithRightHand || grabbingWithLeftHand)) { + if (greenSphere != -1) { + destroyDebugOverlay(); + } + } else { + // update debug indicator + if (greenSphere == -1) { + createDebugOverlay(); + } + + var displayOffset = { x:0, y:0.5, z:-0.5 }; + + Overlays.editOverlay(greenSphere, { position: Vec3.sum(grabStartPosition, displayOffset) } ); + Overlays.editOverlay(redSphere, { position: Vec3.sum(Vec3.sum(grabStartPosition, grabDelta), displayOffset), size: RADIUS + (0.25 * Vec3.length(grabDelta)) } ); + } +} function getJoystickPosition(palm) { // returns CONTROLLER_ID position in avatar local frame @@ -220,6 +278,8 @@ function flyWithHydra(deltaTime) { MyAvatar.headPitch = newPitch; } handleGrabBehavior(deltaTime); + displayDebug(); + } Script.update.connect(flyWithHydra); diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index d2784961bd..8cd3cc059e 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -135,7 +135,7 @@ void SixenseManager::update(float deltaTime) { float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter)); palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter)); - + // use the velocity to determine whether there's any movement (if the hand isn't new) const float MOVEMENT_DISTANCE_THRESHOLD = 0.003f; _amountMoved += rawVelocity * deltaTime;