From 4c64c111444383aaa8d282fd7cb5a000430d27ad Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 26 Mar 2014 16:58:47 -0700 Subject: [PATCH 01/39] making some type casts abide by coding standard --- interface/src/avatar/Hand.cpp | 4 ++-- interface/src/avatar/SkeletonModel.cpp | 2 +- interface/src/renderer/FBXReader.cpp | 6 +++--- interface/src/renderer/GeometryCache.cpp | 6 +++--- interface/src/ui/BandwidthMeter.cpp | 8 ++++---- interface/src/ui/Oscilloscope.cpp | 4 ++-- libraries/metavoxels/src/MetavoxelData.cpp | 2 +- libraries/shared/src/qtimespan.cpp | 4 ++-- tests/physics/src/ShapeColliderTests.cpp | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 77586dd7ae..8c202ae1b1 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -167,7 +167,7 @@ void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) { averagePenetration += collision->_penetration; averageContactPoint += collision->_contactPoint; } - averagePenetration /= float(handCollisions.size()); + averagePenetration /= (float)handCollisions.size(); if (isMyHand) { // our hand against other avatar // for now we resolve it to test shapes/collisions @@ -176,7 +176,7 @@ void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) { } else { // someone else's hand against MyAvatar // TODO: submit collision info to MyAvatar which should lean accordingly - averageContactPoint /= float(handCollisions.size()); + averageContactPoint /= (float)handCollisions.size(); } } } diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 9e4740df15..b0eac98913 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -129,7 +129,7 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin direction += fingerVector / length; } fingerVector = glm::inverse(palmRotation) * fingerVector * -sign; - IndexValue indexValue = { int(i), atan2f(fingerVector.z, fingerVector.x) }; + IndexValue indexValue = { (int)i, atan2f(fingerVector.z, fingerVector.x) }; fingerIndices.append(indexValue); } qSort(fingerIndices.begin(), fingerIndices.end()); diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index 53f4e04b0b..c264fe70a2 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -1588,7 +1588,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) int numVertices = extracted.mesh.vertices.size(); jointShapeInfo.numVertices = numVertices; if (numVertices > 0) { - averageVertex /= float(jointShapeInfo.numVertices); + averageVertex /= (float)jointShapeInfo.numVertices; float averageRadius = 0.f; foreach (const glm::vec3& vertex, extracted.mesh.vertices) { averageRadius += glm::distance(vertex, averageVertex); @@ -1619,7 +1619,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else { // collide the joint like a sphere if (jointShapeInfo.numVertices > 0) { - jointShapeInfo.averageVertex /= float(jointShapeInfo.numVertices); + jointShapeInfo.averageVertex /= (float)jointShapeInfo.numVertices; joint.shapePosition = jointShapeInfo.averageVertex; } else { joint.shapePosition = glm::vec3(0.f); @@ -1629,7 +1629,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) && jointShapeInfo.numVertices > 0) { // the bone projection algorithm was not able to compute the joint radius // so we use an alternative measure - jointShapeInfo.averageRadius /= float(jointShapeInfo.numVertices); + jointShapeInfo.averageRadius /= (float)jointShapeInfo.numVertices; joint.boneRadius = jointShapeInfo.averageRadius; } } diff --git a/interface/src/renderer/GeometryCache.cpp b/interface/src/renderer/GeometryCache.cpp index c4a0d15baa..b835e91a12 100644 --- a/interface/src/renderer/GeometryCache.cpp +++ b/interface/src/renderer/GeometryCache.cpp @@ -31,11 +31,11 @@ void GeometryCache::renderHemisphere(int slices, int stacks) { GLfloat* vertexData = new GLfloat[vertices * 3]; GLfloat* vertex = vertexData; for (int i = 0; i < stacks - 1; i++) { - float phi = PI_OVER_TWO * float(i) / float(stacks - 1); + float phi = PI_OVER_TWO * (float)i / (float)(stacks - 1); float z = sinf(phi), radius = cosf(phi); for (int j = 0; j < slices; j++) { - float theta = TWO_PI * float(j) / float(slices); + float theta = TWO_PI * (float)j / (float)slices; *(vertex++) = sinf(theta) * radius; *(vertex++) = cosf(theta) * radius; @@ -181,7 +181,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) { float y = (float)i / (stacks - 1); for (int j = 0; j <= slices; j++) { - float theta = 3.f * PI_OVER_TWO + PI * float(j) / float(slices); + float theta = 3.f * PI_OVER_TWO + PI * (float)j / (float)slices; //normals *(vertex++) = sinf(theta); diff --git a/interface/src/ui/BandwidthMeter.cpp b/interface/src/ui/BandwidthMeter.cpp index dfc142fb95..64ff74b846 100644 --- a/interface/src/ui/BandwidthMeter.cpp +++ b/interface/src/ui/BandwidthMeter.cpp @@ -160,7 +160,7 @@ void BandwidthMeter::render(int screenWidth, int screenHeight) { // Center of coordinate system -> upper left of bar glPushMatrix(); - glTranslatef(float(barX), float(y), 0.0f); + glTranslatef((float)barX, (float)y, 0.0f); // Render captions setColorRGBA(COLOR_TEXT); @@ -202,7 +202,7 @@ void BandwidthMeter::render(int screenWidth, int screenHeight) { // Render scale indicators setColorRGBA(COLOR_INDICATOR); for (int j = NUMBER_OF_MARKERS; --j > 0;) { - renderVerticalLine(int(barWidth * j / NUMBER_OF_MARKERS), 0, h); + renderVerticalLine((barWidth * j) / NUMBER_OF_MARKERS, 0, h); } // Render bars @@ -210,8 +210,8 @@ void BandwidthMeter::render(int screenWidth, int screenHeight) { for (size_t i = 0; i < N_CHANNELS; ++i) { ChannelIndex chIdx = ChannelIndex(i); - int wIn = int(barWidth * inputStream(chIdx).getValue() * UNIT_SCALE / scaleMax); - int wOut = int(barWidth * outputStream(chIdx).getValue() * UNIT_SCALE / scaleMax); + int wIn = (int)(barWidth * inputStream(chIdx).getValue() * UNIT_SCALE / scaleMax); + int wOut = (int)(barWidth * outputStream(chIdx).getValue() * UNIT_SCALE / scaleMax); setColorRGBA(channelInfo(chIdx).colorRGBA); diff --git a/interface/src/ui/Oscilloscope.cpp b/interface/src/ui/Oscilloscope.cpp index 90d2d49926..a47586b436 100644 --- a/interface/src/ui/Oscilloscope.cpp +++ b/interface/src/ui/Oscilloscope.cpp @@ -127,7 +127,7 @@ void Oscilloscope::render(int x, int y) { } // fetch low pass factor (and convert to fix point) / downsample factor - int lowPassFixPt = -int(std::numeric_limits::min()) * _lowPassCoeff; + int lowPassFixPt = -(int)(std::numeric_limits::min()) * _lowPassCoeff; unsigned downsample = _downsampleRatio; // keep half of the buffer for writing and ensure an even vertex count unsigned usedWidth = min(_width, MAX_SAMPLES_PER_CHANNEL / (downsample * 2)) & ~1u; @@ -141,7 +141,7 @@ void Oscilloscope::render(int x, int y) { short const* inPtr = _samples + _writePos[ch]; short* outPtr = _vertices + MAX_COORDS_PER_CHANNEL * ch; int sample = 0, x = usedWidth; - for (int i = int(usedSamples); --i >= 0 ;) { + for (int i = (int)usedSamples; --i >= 0 ;) { if (inPtr == basePtr) { // handle boundary, reading the circular sample buffer inPtr = endPtr; diff --git a/libraries/metavoxels/src/MetavoxelData.cpp b/libraries/metavoxels/src/MetavoxelData.cpp index 397e10d45f..cab5a73076 100644 --- a/libraries/metavoxels/src/MetavoxelData.cpp +++ b/libraries/metavoxels/src/MetavoxelData.cpp @@ -1096,7 +1096,7 @@ QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngin QScriptValue minimum = infoValue.property(guide->_minimumHandle); MetavoxelInfo info = { glm::vec3(minimum.property(0).toNumber(), minimum.property(1).toNumber(), minimum.property(2).toNumber()), - float(infoValue.property(guide->_sizeHandle).toNumber()), guide->_visitation->info.inputValues, + (float)infoValue.property(guide->_sizeHandle).toNumber(), guide->_visitation->info.inputValues, guide->_visitation->info.outputValues, infoValue.property(guide->_isLeafHandle).toBool() }; // extract and convert the values provided by the script diff --git a/libraries/shared/src/qtimespan.cpp b/libraries/shared/src/qtimespan.cpp index 2ddddb30f3..f3482cfb14 100644 --- a/libraries/shared/src/qtimespan.cpp +++ b/libraries/shared/src/qtimespan.cpp @@ -1594,7 +1594,7 @@ void QTimeSpan::setFromMonths(qreal months) { Q_ASSERT_X(hasValidReference(), "setFromMonths", "Can not set interval from time unit month if there is no reference date."); - int fullMonths = int(months); + int fullMonths = (int)months; qreal fractionalMonth = months - fullMonths; QDateTime endDate = d->reference; @@ -1631,7 +1631,7 @@ void QTimeSpan::setFromYears(qreal years) { Q_ASSERT_X(hasValidReference(), "setFromYears", "Can not set interval from time unit year if there is no reference date."); - int fullYears = int(years); + int fullYears = (int)years; qreal fractionalYear = years - fullYears; QDateTime endDate = d->reference; diff --git a/tests/physics/src/ShapeColliderTests.cpp b/tests/physics/src/ShapeColliderTests.cpp index 6d7e9a6db1..f19f6d6f95 100644 --- a/tests/physics/src/ShapeColliderTests.cpp +++ b/tests/physics/src/ShapeColliderTests.cpp @@ -189,7 +189,7 @@ void ShapeColliderTests::sphereMissesCapsule() { float delta = 1.3f * (totalRadius + halfHeightB) / (numberOfSteps - 1); for (int i = 0; i < numberOfSteps; ++i) { // translate sphereA into world-frame - glm::vec3 localPosition = localStartPosition + (float(i) * delta) * yAxis; + glm::vec3 localPosition = localStartPosition + ((float)i * delta) * yAxis; sphereA.setPosition(rotation * localPosition + translation); // sphereA agains capsuleB From b6f2150d2e7a4bc02b3fc79dca875d02d2deb54e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 27 Mar 2014 10:37:07 -0700 Subject: [PATCH 02/39] HeadData::_yaw and friends change to _baseYaw --- interface/src/avatar/Head.cpp | 10 +++++----- interface/src/avatar/MyAvatar.cpp | 22 +++++++++++----------- libraries/avatars/src/AvatarData.cpp | 6 +++--- libraries/avatars/src/AvatarData.h | 4 ++-- libraries/avatars/src/HeadData.cpp | 20 ++++++++++---------- libraries/avatars/src/HeadData.h | 24 ++++++++++++------------ 6 files changed, 43 insertions(+), 43 deletions(-) diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index fc18eed885..0653a702cb 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -50,7 +50,7 @@ void Head::init() { } void Head::reset() { - _yaw = _pitch = _roll = 0.0f; + _baseYaw = _basePitch = _baseRoll = 0.0f; _leanForward = _leanSideways = 0.0f; _faceModel.reset(); } @@ -185,7 +185,7 @@ glm::quat Head::getTweakedOrientation() const { glm::quat Head::getCameraOrientation () const { Avatar* owningAvatar = static_cast(_owningAvatar); - return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_pitch, 0.f, 0.0f))); + return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.f, 0.0f))); } glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const { @@ -198,15 +198,15 @@ glm::vec3 Head::getScalePivot() const { } float Head::getTweakedYaw() const { - return glm::clamp(_yaw + _yawTweak, MIN_HEAD_YAW, MAX_HEAD_YAW); + return glm::clamp(_baseYaw + _yawTweak, MIN_HEAD_YAW, MAX_HEAD_YAW); } float Head::getTweakedPitch() const { - return glm::clamp(_pitch + _pitchTweak, MIN_HEAD_PITCH, MAX_HEAD_PITCH); + return glm::clamp(_basePitch + _pitchTweak, MIN_HEAD_PITCH, MAX_HEAD_PITCH); } float Head::getTweakedRoll() const { - return glm::clamp(_roll + _rollTweak, MIN_HEAD_ROLL, MAX_HEAD_ROLL); + return glm::clamp(_baseRoll + _rollTweak, MIN_HEAD_ROLL, MAX_HEAD_ROLL); } void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 618cda1199..5c4dbd88a4 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -117,9 +117,9 @@ void MyAvatar::update(float deltaTime) { OculusManager::getEulerAngles(yaw, pitch, roll); // but these euler angles are stored in degrees - head->setYaw(yaw * DEGREES_PER_RADIAN); - head->setPitch(pitch * DEGREES_PER_RADIAN); - head->setRoll(roll * DEGREES_PER_RADIAN); + head->setBaseYaw(yaw * DEGREES_PER_RADIAN); + head->setBasePitch(pitch * DEGREES_PER_RADIAN); + head->setBaseRoll(roll * DEGREES_PER_RADIAN); } // Get audio loudness data from audio input device @@ -229,7 +229,7 @@ void MyAvatar::simulate(float deltaTime) { if (!Application::getInstance()->getFaceshift()->isActive() && OculusManager::isConnected() && fabsf(forwardAcceleration) > OCULUS_ACCELERATION_PULL_THRESHOLD && - fabs(getHead()->getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) { + fabs(getHead()->getBaseYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) { // if we're wearing the oculus // and this acceleration is above the pull threshold @@ -239,7 +239,7 @@ void MyAvatar::simulate(float deltaTime) { _bodyYaw = getAbsoluteHeadYaw(); // set the head yaw to zero for this draw - getHead()->setYaw(0); + getHead()->setBaseYaw(0); // correct the oculus yaw offset OculusManager::updateYawOffset(); @@ -505,7 +505,7 @@ void MyAvatar::saveData(QSettings* settings) { settings->setValue("bodyPitch", _bodyPitch); settings->setValue("bodyRoll", _bodyRoll); - settings->setValue("headPitch", getHead()->getPitch()); + settings->setValue("headPitch", getHead()->getBasePitch()); settings->setValue("position_x", _position.x); settings->setValue("position_y", _position.y); @@ -531,7 +531,7 @@ void MyAvatar::loadData(QSettings* settings) { _bodyPitch = loadSetting(settings, "bodyPitch", 0.0f); _bodyRoll = loadSetting(settings, "bodyRoll", 0.0f); - getHead()->setPitch(loadSetting(settings, "headPitch", 0.0f)); + getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f)); _position.x = loadSetting(settings, "position_x", 0.0f); _position.y = loadSetting(settings, "position_y", 0.0f); @@ -574,9 +574,9 @@ void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) { setOrientation(orientation); // then vertically - float oldPitch = getHead()->getPitch(); - getHead()->setPitch(oldPitch - deltaY * ANGULAR_SCALE); - rotation = glm::angleAxis(glm::radians((getHead()->getPitch() - oldPitch)), orientation * IDENTITY_RIGHT); + float oldPitch = getHead()->getBasePitch(); + getHead()->setBasePitch(oldPitch - deltaY * ANGULAR_SCALE); + rotation = glm::angleAxis(glm::radians((getHead()->getBasePitch() - oldPitch)), orientation * IDENTITY_RIGHT); setPosition(position + rotation * (getPosition() - position)); } @@ -682,7 +682,7 @@ void MyAvatar::updateThrust(float deltaTime) { _thrust -= _driveKeys[DOWN] * _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up; _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; - getHead()->setPitch(getHead()->getPitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); + getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); // If thrust keys are being held down, slowly increase thrust to allow reaching great speeds if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) { diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index bb0fcd27e6..0899d67cb1 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -288,9 +288,9 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) { } return maxAvailableSize; } - _headData->setYaw(headYaw); - _headData->setPitch(headPitch); - _headData->setRoll(headRoll); + _headData->setBaseYaw(headYaw); + _headData->setBasePitch(headPitch); + _headData->setBaseRoll(headRoll); } // 6 bytes // Head lean (relative to pelvis) diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index a89639d68d..2ea20c1041 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -128,8 +128,8 @@ public: void setHeadOrientation(const glm::quat& orientation) { _headData->setOrientation(orientation); } // access to Head().set/getMousePitch (degrees) - float getHeadPitch() const { return _headData->getPitch(); } - void setHeadPitch(float value) { _headData->setPitch(value); }; + float getHeadPitch() const { return _headData->getBasePitch(); } + void setHeadPitch(float value) { _headData->setBasePitch(value); }; // access to Head().set/getAverageLoudness float getAudioLoudness() const { return _headData->getAudioLoudness(); } diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index cf48aeabfa..da1bdca23b 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -14,9 +14,9 @@ #include "HeadData.h" HeadData::HeadData(AvatarData* owningAvatar) : - _yaw(0.0f), - _pitch(0.0f), - _roll(0.0f), + _baseYaw(0.0f), + _basePitch(0.0f), + _baseRoll(0.0f), _leanSideways(0.0f), _leanForward(0.0f), _lookAtPosition(0.0f, 0.0f, 0.0f), @@ -32,7 +32,7 @@ HeadData::HeadData(AvatarData* owningAvatar) : } glm::quat HeadData::getOrientation() const { - return _owningAvatar->getOrientation() * glm::quat(glm::radians(glm::vec3(_pitch, _yaw, _roll))); + return _owningAvatar->getOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, _baseYaw, _baseRoll))); } void HeadData::setOrientation(const glm::quat& orientation) { @@ -44,21 +44,21 @@ void HeadData::setOrientation(const glm::quat& orientation) { // the rest goes to the head glm::vec3 eulers = glm::degrees(safeEulerAngles(glm::inverse(bodyOrientation) * orientation)); - _pitch = eulers.x; - _yaw = eulers.y; - _roll = eulers.z; + _basePitch = eulers.x; + _baseYaw = eulers.y; + _baseRoll = eulers.z; } void HeadData::addYaw(float yaw) { - setYaw(_yaw + yaw); + setBaseYaw(_baseYaw + yaw); } void HeadData::addPitch(float pitch) { - setPitch(_pitch + pitch); + setBasePitch(_basePitch + pitch); } void HeadData::addRoll(float roll) { - setRoll(_roll + roll); + setBaseRoll(_baseRoll + roll); } diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index b199ff19d2..8016d8b674 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -36,15 +36,15 @@ public: void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; } float getLeanForward() const { return _leanForward; } void setLeanForward(float leanForward) { _leanForward = leanForward; } - float getYaw() const { return _yaw; } - void setYaw(float yaw) { _yaw = glm::clamp(yaw, MIN_HEAD_YAW, MAX_HEAD_YAW); } - float getPitch() const { return _pitch; } - void setPitch(float pitch) { _pitch = glm::clamp(pitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH); } - float getRoll() const { return _roll; } - void setRoll(float roll) { _roll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); } - virtual float getTweakedYaw() const { return _yaw; } - virtual float getTweakedPitch() const { return _pitch; } - virtual float getTweakedRoll() const { return _roll; } + float getBaseYaw() const { return _baseYaw; } + void setBaseYaw(float yaw) { _baseYaw = glm::clamp(yaw, MIN_HEAD_YAW, MAX_HEAD_YAW); } + float getBasePitch() const { return _basePitch; } + void setBasePitch(float pitch) { _basePitch = glm::clamp(pitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH); } + float getBaseRoll() const { return _baseRoll; } + void setBaseRoll(float roll) { _baseRoll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); } + virtual float getTweakedYaw() const { return _baseYaw; } + virtual float getTweakedPitch() const { return _basePitch; } + virtual float getTweakedRoll() const { return _baseRoll; } glm::quat getOrientation() const; void setOrientation(const glm::quat& orientation); @@ -73,9 +73,9 @@ public: protected: // degrees - float _yaw; - float _pitch; - float _roll; + float _baseYaw; + float _basePitch; + float _baseRoll; float _leanSideways; float _leanForward; From c354e980a804c174fcfdd0c4b46259391a2bf98e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 27 Mar 2014 11:03:42 -0700 Subject: [PATCH 03/39] getTweakedOrientation() to getFinalOrientation() --- interface/src/Audio.cpp | 2 +- interface/src/avatar/FaceModel.cpp | 2 +- interface/src/avatar/Head.cpp | 2 +- interface/src/avatar/Head.h | 6 +++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 67f2e2caec..2f0b3df277 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -522,7 +522,7 @@ void Audio::handleAudioInput() { if (audioMixer && audioMixer->getActiveSocket()) { MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar(); glm::vec3 headPosition = interfaceAvatar->getHead()->getPosition(); - glm::quat headOrientation = interfaceAvatar->getHead()->getTweakedOrientation(); + glm::quat headOrientation = interfaceAvatar->getHead()->getFinalOrientation(); // we need the amount of bytes in the buffer + 1 for type // + 12 for 3 floats for position + float for bearing + 1 attenuation byte diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 19faa0da42..b7eba1e98e 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -60,7 +60,7 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ // likewise with the eye joints glm::mat4 inverse = glm::inverse(parentState.transform * glm::translate(state.translation) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)); - glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getTweakedOrientation() * IDENTITY_FRONT, 0.0f)); + glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientation() * IDENTITY_FRONT, 0.0f)); glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + _owningHead->getSaccade() - _translation, 1.0f)); glm::quat between = rotationBetween(front, lookAt); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 0653a702cb..c72e53b1a0 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -178,7 +178,7 @@ void Head::setScale (float scale) { _scale = scale; } -glm::quat Head::getTweakedOrientation() const { +glm::quat Head::getFinalOrientation() const { return _owningAvatar->getOrientation() * glm::quat(glm::radians( glm::vec3(getTweakedPitch(), getTweakedYaw(), getTweakedRoll() ))); } diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 733323abc5..311d5e887a 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -45,8 +45,12 @@ public: void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; } void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; } - glm::quat getTweakedOrientation() const; + /// \return orientationBody * orientationBase+Delta + glm::quat getFinalOrientation() const; + + /// \return orientationBody * orientationBasePitch glm::quat getCameraOrientation () const; + const glm::vec3& getAngularVelocity() const { return _angularVelocity; } void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; } From ca9f0c01c1ce1698bdc9d7f506b76fabedfd2b2a Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 27 Mar 2014 11:08:55 -0700 Subject: [PATCH 04/39] Couple of quick fixes: reset the skeleton joints when space is pressed as a last resort to fix broken IK, don't render display names at the origin if we don't have a skeleton model. --- interface/src/avatar/Avatar.cpp | 10 +++++++--- interface/src/avatar/MyAvatar.cpp | 1 + interface/src/renderer/Model.cpp | 7 +++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index de9b33d9c7..94e1416e68 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -397,9 +397,13 @@ void Avatar::renderDisplayName() { glPushMatrix(); glm::vec3 textPosition; - getSkeletonModel().getNeckPosition(textPosition); - textPosition += getBodyUpDirection() * getHeadHeight() * 1.1f; - + if (getSkeletonModel().getNeckPosition(textPosition)) { + textPosition += getBodyUpDirection() * getHeadHeight() * 1.1f; + } else { + const float HEAD_PROPORTION = 0.75f; + textPosition = _position + getBodyUpDirection() * (getBillboardSize() * HEAD_PROPORTION); + } + glTranslatef(textPosition.x, textPosition.y, textPosition.z); // we need "always facing camera": we must remove the camera rotation from the stack diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 618cda1199..350b4fb2be 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -79,6 +79,7 @@ void MyAvatar::reset() { // TODO? resurrect headMouse stuff? //_headMouseX = _glWidget->width() / 2; //_headMouseY = _glWidget->height() / 2; + _skeletonModel.reset(); getHead()->reset(); getHand()->reset(); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index df5560a4b1..36ac6bec99 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -130,9 +130,16 @@ void Model::init() { } void Model::reset() { + if (_jointStates.isEmpty()) { + return; + } foreach (Model* attachment, _attachments) { attachment->reset(); } + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + for (int i = 0; i < _jointStates.size(); i++) { + _jointStates[i].rotation = geometry.joints.at(i).rotation; + } } void Model::clearShapes() { From 7949be0319f991c45c51c9b2a7c3b402b43a0fcf Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 27 Mar 2014 11:14:26 -0700 Subject: [PATCH 05/39] PitchTweak and friends become DeltaPitch --- interface/src/avatar/FaceModel.cpp | 6 +++--- interface/src/avatar/Head.cpp | 20 ++++++++++---------- interface/src/avatar/Head.h | 24 ++++++++++++------------ interface/src/avatar/MyAvatar.cpp | 12 ++++++------ libraries/avatars/src/AvatarData.cpp | 6 +++--- libraries/avatars/src/HeadData.h | 6 +++--- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index b7eba1e98e..19120d10be 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -50,9 +50,9 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX glm::mat3 axes = glm::mat3_cast(_rotation); glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) * joint.preTransform * glm::mat4_cast(joint.preRotation))); - state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getTweakedRoll(), glm::normalize(inverse * axes[2])) - * glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getTweakedYaw(), glm::normalize(inverse * axes[1])) - * glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getTweakedPitch(), glm::normalize(inverse * axes[0])) + state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2])) + * glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1])) + * glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0])) * joint.rotation; } diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index c72e53b1a0..d432830252 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -36,9 +36,9 @@ Head::Head(Avatar* owningAvatar) : _leftEyeBlinkVelocity(0.0f), _rightEyeBlinkVelocity(0.0f), _timeWithoutTalking(0.0f), - _pitchTweak(0.f), - _yawTweak(0.f), - _rollTweak(0.f), + _deltaPitch(0.f), + _deltaYaw(0.f), + _deltaRoll(0.f), _isCameraMoving(false), _faceModel(this) { @@ -180,7 +180,7 @@ void Head::setScale (float scale) { glm::quat Head::getFinalOrientation() const { return _owningAvatar->getOrientation() * glm::quat(glm::radians( - glm::vec3(getTweakedPitch(), getTweakedYaw(), getTweakedRoll() ))); + glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() ))); } glm::quat Head::getCameraOrientation () const { @@ -197,16 +197,16 @@ glm::vec3 Head::getScalePivot() const { return _faceModel.isActive() ? _faceModel.getTranslation() : _position; } -float Head::getTweakedYaw() const { - return glm::clamp(_baseYaw + _yawTweak, MIN_HEAD_YAW, MAX_HEAD_YAW); +float Head::getFinalYaw() const { + return glm::clamp(_baseYaw + _deltaYaw, MIN_HEAD_YAW, MAX_HEAD_YAW); } -float Head::getTweakedPitch() const { - return glm::clamp(_basePitch + _pitchTweak, MIN_HEAD_PITCH, MAX_HEAD_PITCH); +float Head::getFinalPitch() const { + return glm::clamp(_basePitch + _deltaPitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH); } -float Head::getTweakedRoll() const { - return glm::clamp(_baseRoll + _rollTweak, MIN_HEAD_ROLL, MAX_HEAD_ROLL); +float Head::getFinalRoll() const { + return glm::clamp(_baseRoll + _deltaRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); } void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 311d5e887a..915cf1e268 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -74,18 +74,18 @@ public: /// Returns the point about which scaling occurs. glm::vec3 getScalePivot() const; - void setPitchTweak(float pitch) { _pitchTweak = pitch; } - float getPitchTweak() const { return _pitchTweak; } + void setDeltaPitch(float pitch) { _deltaPitch = pitch; } + float getDeltaPitch() const { return _deltaPitch; } - void setYawTweak(float yaw) { _yawTweak = yaw; } - float getYawTweak() const { return _yawTweak; } + void setDeltaYaw(float yaw) { _deltaYaw = yaw; } + float getDeltaYaw() const { return _deltaYaw; } - void setRollTweak(float roll) { _rollTweak = roll; } - float getRollTweak() const { return _rollTweak; } + void setDeltaRoll(float roll) { _deltaRoll = roll; } + float getDeltaRoll() const { return _deltaRoll; } - virtual float getTweakedPitch() const; - virtual float getTweakedYaw() const; - virtual float getTweakedRoll() const; + virtual float getFinalPitch() const; + virtual float getFinalYaw() const; + virtual float getFinalRoll() const; private: // disallow copies of the Head, copy of owning Avatar is disallowed too @@ -111,9 +111,9 @@ private: float _timeWithoutTalking; // tweaked angles affect the rendered head, but not the camera - float _pitchTweak; - float _yawTweak; - float _rollTweak; + float _deltaPitch; + float _deltaYaw; + float _deltaRoll; bool _isCameraMoving; FaceModel _faceModel; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5c4dbd88a4..c1c8a9a616 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -364,9 +364,9 @@ void MyAvatar::updateFromGyros(float deltaTime) { // restore rotation, lean to neutral positions const float RESTORE_PERIOD = 0.25f; // seconds float restorePercentage = glm::clamp(deltaTime/RESTORE_PERIOD, 0.f, 1.f); - head->setPitchTweak(glm::mix(head->getPitchTweak(), 0.0f, restorePercentage)); - head->setYawTweak(glm::mix(head->getYawTweak(), 0.0f, restorePercentage)); - head->setRollTweak(glm::mix(head->getRollTweak(), 0.0f, restorePercentage)); + head->setDeltaPitch(glm::mix(head->getDeltaPitch(), 0.0f, restorePercentage)); + head->setDeltaYaw(glm::mix(head->getDeltaYaw(), 0.0f, restorePercentage)); + head->setDeltaRoll(glm::mix(head->getDeltaRoll(), 0.0f, restorePercentage)); head->setLeanSideways(glm::mix(head->getLeanSideways(), 0.0f, restorePercentage)); head->setLeanForward(glm::mix(head->getLeanForward(), 0.0f, restorePercentage)); return; @@ -377,9 +377,9 @@ void MyAvatar::updateFromGyros(float deltaTime) { const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f; const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f; const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f; - head->setPitchTweak(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); - head->setYawTweak(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); - head->setRollTweak(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); + head->setDeltaPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY); + head->setDeltaYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY); + head->setDeltaRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY); // Update torso lean distance based on accelerometer data const float TORSO_LENGTH = 0.5f; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 0899d67cb1..31639b6836 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -93,9 +93,9 @@ QByteArray AvatarData::toByteArray() { destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _targetScale); // Head rotation (NOTE: This needs to become a quaternion to save two bytes) - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedYaw()); - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedPitch()); - destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedRoll()); + destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getFinalYaw()); + destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getFinalPitch()); + destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getFinalRoll()); // Head lean X,Z (head lateral and fwd/back motion relative to torso) memcpy(destinationBuffer, &_headData->_leanSideways, sizeof(_headData->_leanSideways)); diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index 8016d8b674..a907c5b694 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -42,9 +42,9 @@ public: void setBasePitch(float pitch) { _basePitch = glm::clamp(pitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH); } float getBaseRoll() const { return _baseRoll; } void setBaseRoll(float roll) { _baseRoll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); } - virtual float getTweakedYaw() const { return _baseYaw; } - virtual float getTweakedPitch() const { return _basePitch; } - virtual float getTweakedRoll() const { return _baseRoll; } + virtual float getFinalYaw() const { return _baseYaw; } + virtual float getFinalPitch() const { return _basePitch; } + virtual float getFinalRoll() const { return _baseRoll; } glm::quat getOrientation() const; void setOrientation(const glm::quat& orientation); From a978f533e11f1dcf54f354c34f05f14ae8166206 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 27 Mar 2014 11:24:03 -0700 Subject: [PATCH 06/39] update a comment --- interface/src/avatar/Head.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index 915cf1e268..dc96aa318f 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -110,7 +110,7 @@ private: float _rightEyeBlinkVelocity; float _timeWithoutTalking; - // tweaked angles affect the rendered head, but not the camera + // delta angles for local head rotation float _deltaPitch; float _deltaYaw; float _deltaRoll; From 21eef6c15ee86dd6ce33f96308487724ddfab0c4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 27 Mar 2014 13:10:03 -0700 Subject: [PATCH 07/39] make sure VoxelServer and ParticleServer are in Agent interest list --- assignment-client/src/Agent.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 25dcfcdd95..b5199e87e8 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -138,7 +138,11 @@ void Agent::run() { ThreadedAssignment::commonInit(AGENT_LOGGING_NAME, NodeType::Agent); NodeList* nodeList = NodeList::getInstance(); - nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() << NodeType::AudioMixer << NodeType::AvatarMixer); + nodeList->addSetOfNodeTypesToNodeInterestSet(NodeSet() + << NodeType::AudioMixer + << NodeType::AvatarMixer + << NodeType::VoxelServer + << NodeType::ParticleServer); // figure out the URL for the script for this agent assignment QString scriptURLString("http://%1:8080/assignment/%2"); From 7cc72307456b15e06691b4132be05e441a2a2058 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 27 Mar 2014 13:18:45 -0700 Subject: [PATCH 08/39] Adjust the shadow shader to prevent seeing shadows on the opposite sides of objects. Closes #2544. --- interface/resources/shaders/shadow_map.frag | 5 ++-- interface/resources/shaders/shadow_map.vert | 30 +++++++++++++++++++++ interface/src/voxels/VoxelSystem.cpp | 15 ++++------- 3 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 interface/resources/shaders/shadow_map.vert diff --git a/interface/resources/shaders/shadow_map.frag b/interface/resources/shaders/shadow_map.frag index 4bd8b8b768..810fc6a947 100644 --- a/interface/resources/shaders/shadow_map.frag +++ b/interface/resources/shaders/shadow_map.frag @@ -10,7 +10,8 @@ uniform sampler2DShadow shadowMap; +varying vec4 shadowColor; + void main(void) { - gl_FragColor = gl_Color * mix(vec4(0.8, 0.8, 0.8, 1.0), vec4(1.0, 1.0, 1.0, 1.0), - shadow2D(shadowMap, gl_TexCoord[0].stp)); + gl_FragColor = gl_Color * mix(shadowColor, vec4(1.0, 1.0, 1.0, 1.0), shadow2D(shadowMap, gl_TexCoord[0].stp)); } diff --git a/interface/resources/shaders/shadow_map.vert b/interface/resources/shaders/shadow_map.vert new file mode 100644 index 0000000000..a15cd070b9 --- /dev/null +++ b/interface/resources/shaders/shadow_map.vert @@ -0,0 +1,30 @@ +#version 120 + +// +// shadow_map.vert +// vertex shader +// +// Created by Andrzej Kapolka on 3/27/14. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +varying vec4 shadowColor; + +void main(void) { + // the shadow color depends on the light product + vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + float lightProduct = dot(normal, gl_LightSource[0].position); + shadowColor = mix(vec4(1.0, 1.0, 1.0, 1.0), vec4(0.8, 0.8, 0.8, 1.0), step(0.0, lightProduct)); + + // standard diffuse lighting + gl_FrontColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient + + gl_LightSource[0].diffuse * max(0.0, lightProduct)); + + // generate the shadow texture coordinate using the eye position + vec4 eyePosition = gl_ModelViewMatrix * gl_Vertex; + gl_TexCoord[0] = vec4(dot(gl_EyePlaneS[0], eyePosition), dot(gl_EyePlaneT[0], eyePosition), + dot(gl_EyePlaneR[0], eyePosition), 1.0); + + // use the fixed function transform + gl_Position = ftransform(); +} diff --git a/interface/src/voxels/VoxelSystem.cpp b/interface/src/voxels/VoxelSystem.cpp index 4db5af3c04..5c68485436 100644 --- a/interface/src/voxels/VoxelSystem.cpp +++ b/interface/src/voxels/VoxelSystem.cpp @@ -506,8 +506,10 @@ void VoxelSystem::initVoxelMemory() { _perlinModulateProgram.setUniformValue("permutationNormalTexture", 0); _perlinModulateProgram.release(); - _shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() - + "shaders/shadow_map.frag"); + _shadowMapProgram.addShaderFromSourceFile(QGLShader::Vertex, + Application::resourcesPath() + "shaders/shadow_map.vert"); + _shadowMapProgram.addShaderFromSourceFile(QGLShader::Fragment, + Application::resourcesPath() + "shaders/shadow_map.frag"); _shadowMapProgram.link(); _shadowMapProgram.bind(); @@ -1471,10 +1473,6 @@ void VoxelSystem::applyScaleAndBindProgram(bool texture) { if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { _shadowMapProgram.bind(); glBindTexture(GL_TEXTURE_2D, Application::getInstance()->getTextureCache()->getShadowDepthTextureID()); - glEnable(GL_TEXTURE_GEN_S); - glEnable(GL_TEXTURE_GEN_T); - glEnable(GL_TEXTURE_GEN_R); - glEnable(GL_TEXTURE_2D); glTexGenfv(GL_S, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[0]); glTexGenfv(GL_T, GL_EYE_PLANE, (const GLfloat*)&Application::getInstance()->getShadowMatrix()[1]); @@ -1496,10 +1494,7 @@ void VoxelSystem::removeScaleAndReleaseProgram(bool texture) { if (Menu::getInstance()->isOptionChecked(MenuOption::Shadows)) { _shadowMapProgram.release(); glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_GEN_S); - glDisable(GL_TEXTURE_GEN_T); - glDisable(GL_TEXTURE_GEN_R); - glDisable(GL_TEXTURE_2D); + } else if (texture) { _perlinModulateProgram.release(); From bda96ef935f00abc36ccbb89e3f0a134be61805c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 27 Mar 2014 13:35:22 -0700 Subject: [PATCH 09/39] added back use of nodeWithUUID() instead of sharedpointer --- .../src/octree/OctreeSendThread.cpp | 25 ++++++++-- .../src/octree/OctreeSendThread.h | 3 +- assignment-client/src/octree/OctreeServer.cpp | 46 +++++++++++++------ assignment-client/src/octree/OctreeServer.h | 4 ++ libraries/shared/src/NodeList.cpp | 18 ++++++-- libraries/shared/src/NodeList.h | 2 +- 6 files changed, 73 insertions(+), 25 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 382d8aa528..023f3f3d2c 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -21,8 +21,9 @@ quint64 endSceneSleepTime = 0; OctreeSendThread::OctreeSendThread(OctreeServer* myServer, SharedNodePointer node) : _myServer(myServer), - _node(node), + _nodeUUID(node->getUUID()), _packetData(), + _nodeMissingCount(0), _processLock(), _isShuttingDown(false) { @@ -43,7 +44,6 @@ OctreeSendThread::~OctreeSendThread() { } qDebug() << qPrintable(safeServerName) << "server [" << _myServer << "]: client disconnected " "- ending sending thread [" << this << "]"; - _node.clear(); OctreeServer::clientDisconnected(); } @@ -72,13 +72,28 @@ bool OctreeSendThread::process() { // don't do any send processing until the initial load of the octree is complete... if (_myServer->isInitialLoadComplete()) { - if (!_node.isNull()) { - OctreeQueryNode* nodeData = static_cast(_node->getLinkedData()); + SharedNodePointer node = NodeList::getInstance()->nodeWithUUID(_nodeUUID, false); + if (node) { + _nodeMissingCount = 0; + OctreeQueryNode* nodeData = static_cast(node->getLinkedData()); // Sometimes the node data has not yet been linked, in which case we can't really do anything if (nodeData && !nodeData->isShuttingDown()) { bool viewFrustumChanged = nodeData->updateCurrentViewFrustum(); - packetDistributor(_node, nodeData, viewFrustumChanged); + packetDistributor(node, nodeData, viewFrustumChanged); + } + } else { + _nodeMissingCount++; + const int MANY_FAILED_LOCKS = 1; + if (_nodeMissingCount >= MANY_FAILED_LOCKS) { + + QString safeServerName("Octree"); + if (_myServer) { + safeServerName = _myServer->getMyServerName(); + } + + qDebug() << qPrintable(safeServerName) << "server: sending thread [" << this << "]" + << "failed to get nodeWithUUID() " << _nodeUUID <<". Failed:" << _nodeMissingCount << "times"; } } } diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index 4e18ee9b2a..4b1b6d8c92 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -38,14 +38,15 @@ protected: virtual bool process(); private: - SharedNodePointer _node; OctreeServer* _myServer; + QUuid _nodeUUID; int handlePacketSend(const SharedNodePointer& node, OctreeQueryNode* nodeData, int& trueBytesSent, int& truePacketsSent); int packetDistributor(const SharedNodePointer& node, OctreeQueryNode* nodeData, bool viewFrustumChanged); OctreePacketData _packetData; + int _nodeMissingCount; QMutex _processLock; // don't allow us to have our nodeData, or our thread to be deleted while we're processing bool _isShuttingDown; }; diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index fa087cced2..fd3f9e6cb7 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1160,7 +1160,6 @@ QString OctreeServer::getStatusLink() { } void OctreeServer::sendStatsPacket() { - // TODO: we have too many stats to fit in a single MTU... so for now, we break it into multiple JSON objects and // send them separately. What we really should do is change the NodeList::sendStatsToDomainServer() to handle the // the following features: @@ -1241,59 +1240,78 @@ QMap OctreeServer::_threadsDidPacketDistributor; QMap OctreeServer::_threadsDidHandlePacketSend; QMap OctreeServer::_threadsDidCallWriteDatagram; +QMutex OctreeServer::_threadsDidProcessMutex; +QMutex OctreeServer::_threadsDidPacketDistributorMutex; +QMutex OctreeServer::_threadsDidHandlePacketSendMutex; +QMutex OctreeServer::_threadsDidCallWriteDatagramMutex; + void OctreeServer::didProcess(OctreeSendThread* thread) { + QMutexLocker locker(&_threadsDidProcessMutex); _threadsDidProcess[thread] = usecTimestampNow(); } void OctreeServer::didPacketDistributor(OctreeSendThread* thread) { + QMutexLocker locker(&_threadsDidPacketDistributorMutex); _threadsDidPacketDistributor[thread] = usecTimestampNow(); } void OctreeServer::didHandlePacketSend(OctreeSendThread* thread) { + QMutexLocker locker(&_threadsDidHandlePacketSendMutex); _threadsDidHandlePacketSend[thread] = usecTimestampNow(); } void OctreeServer::didCallWriteDatagram(OctreeSendThread* thread) { + QMutexLocker locker(&_threadsDidCallWriteDatagramMutex); _threadsDidCallWriteDatagram[thread] = usecTimestampNow(); } void OctreeServer::stopTrackingThread(OctreeSendThread* thread) { + QMutexLocker lockerA(&_threadsDidProcessMutex); + QMutexLocker lockerB(&_threadsDidPacketDistributorMutex); + QMutexLocker lockerC(&_threadsDidHandlePacketSendMutex); + QMutexLocker lockerD(&_threadsDidCallWriteDatagramMutex); + _threadsDidProcess.remove(thread); _threadsDidPacketDistributor.remove(thread); _threadsDidHandlePacketSend.remove(thread); + _threadsDidCallWriteDatagram.remove(thread); } -int howManyThreadsDidSomething(QMap& something, quint64 since) { - if (since == 0) { - return something.size(); - } +int howManyThreadsDidSomething(QMutex& mutex, QMap& something, quint64 since) { int count = 0; - QMap::const_iterator i = something.constBegin(); - while (i != something.constEnd()) { - if (i.value() > since) { - count++; + if (mutex.tryLock()) { + if (since == 0) { + count = something.size(); + } else { + QMap::const_iterator i = something.constBegin(); + while (i != something.constEnd()) { + if (i.value() > since) { + count++; + } + ++i; + } } - ++i; + mutex.unlock(); } return count; } int OctreeServer::howManyThreadsDidProcess(quint64 since) { - return howManyThreadsDidSomething(_threadsDidProcess, since); + return howManyThreadsDidSomething(_threadsDidProcessMutex, _threadsDidProcess, since); } int OctreeServer::howManyThreadsDidPacketDistributor(quint64 since) { - return howManyThreadsDidSomething(_threadsDidPacketDistributor, since); + return howManyThreadsDidSomething(_threadsDidPacketDistributorMutex, _threadsDidPacketDistributor, since); } int OctreeServer::howManyThreadsDidHandlePacketSend(quint64 since) { - return howManyThreadsDidSomething(_threadsDidHandlePacketSend, since); + return howManyThreadsDidSomething(_threadsDidHandlePacketSendMutex, _threadsDidHandlePacketSend, since); } int OctreeServer::howManyThreadsDidCallWriteDatagram(quint64 since) { - return howManyThreadsDidSomething(_threadsDidCallWriteDatagram, since); + return howManyThreadsDidSomething(_threadsDidCallWriteDatagramMutex, _threadsDidCallWriteDatagram, since); } diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index 3dac42709f..63d43b6634 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -211,6 +211,10 @@ protected: static QMap _threadsDidHandlePacketSend; static QMap _threadsDidCallWriteDatagram; + static QMutex _threadsDidProcessMutex; + static QMutex _threadsDidPacketDistributorMutex; + static QMutex _threadsDidHandlePacketSendMutex; + static QMutex _threadsDidCallWriteDatagramMutex; }; #endif // __octree_server__OctreeServer__ diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index dc5a419295..761ea40d55 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -357,10 +357,20 @@ int NodeList::findNodeAndUpdateWithDataFromPacket(const QByteArray& packet) { return 0; } -SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID) { - QMutexLocker locker(&_nodeHashMutex); - return _nodeHash.value(nodeUUID); -} +SharedNodePointer NodeList::nodeWithUUID(const QUuid& nodeUUID, bool blockingLock) { + const int WAIT_TIME = 10; // wait up to 10ms in the try lock case + SharedNodePointer node; + // if caller wants us to block and guarantee the correct answer, then honor that request + if (blockingLock) { + // this will block till we can get access + QMutexLocker locker(&_nodeHashMutex); + node = _nodeHash.value(nodeUUID); + } else if (_nodeHashMutex.tryLock(WAIT_TIME)) { // some callers are willing to get wrong answers but not block + node = _nodeHash.value(nodeUUID); + _nodeHashMutex.unlock(); + } + return node; + } SharedNodePointer NodeList::sendingNodeForPacket(const QByteArray& packet) { QUuid nodeUUID = uuidFromPacketHeader(packet); diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index f10e01f3f4..d05d6a2fbc 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -103,7 +103,7 @@ public: QByteArray constructPingReplyPacket(const QByteArray& pingPacket); void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node); - SharedNodePointer nodeWithUUID(const QUuid& nodeUUID); + SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true); SharedNodePointer sendingNodeForPacket(const QByteArray& packet); SharedNodePointer addOrUpdateNode(const QUuid& uuid, char nodeType, From 563725e7810259e49f47a5b6cca883a14bdea5d7 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 27 Mar 2014 13:44:34 -0700 Subject: [PATCH 10/39] Use the "correct" shadow strategy: include only ambient term when in shadow. --- interface/resources/shaders/shadow_map.frag | 2 +- interface/resources/shaders/shadow_map.vert | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/interface/resources/shaders/shadow_map.frag b/interface/resources/shaders/shadow_map.frag index 810fc6a947..b683ed5af2 100644 --- a/interface/resources/shaders/shadow_map.frag +++ b/interface/resources/shaders/shadow_map.frag @@ -13,5 +13,5 @@ uniform sampler2DShadow shadowMap; varying vec4 shadowColor; void main(void) { - gl_FragColor = gl_Color * mix(shadowColor, vec4(1.0, 1.0, 1.0, 1.0), shadow2D(shadowMap, gl_TexCoord[0].stp)); + gl_FragColor = mix(shadowColor, gl_Color, shadow2D(shadowMap, gl_TexCoord[0].stp)); } diff --git a/interface/resources/shaders/shadow_map.vert b/interface/resources/shaders/shadow_map.vert index a15cd070b9..6809ca6e2b 100644 --- a/interface/resources/shaders/shadow_map.vert +++ b/interface/resources/shaders/shadow_map.vert @@ -11,14 +11,12 @@ varying vec4 shadowColor; void main(void) { - // the shadow color depends on the light product - vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); - float lightProduct = dot(normal, gl_LightSource[0].position); - shadowColor = mix(vec4(1.0, 1.0, 1.0, 1.0), vec4(0.8, 0.8, 0.8, 1.0), step(0.0, lightProduct)); + // the shadow color includes only the ambient terms + shadowColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient); - // standard diffuse lighting - gl_FrontColor = gl_Color * (gl_LightModel.ambient + gl_LightSource[0].ambient + - gl_LightSource[0].diffuse * max(0.0, lightProduct)); + // the normal color includes diffuse + vec4 normal = normalize(gl_ModelViewMatrix * vec4(gl_Normal, 0.0)); + gl_FrontColor = shadowColor + gl_Color * (gl_LightSource[0].diffuse * max(0.0, dot(normal, gl_LightSource[0].position))); // generate the shadow texture coordinate using the eye position vec4 eyePosition = gl_ModelViewMatrix * gl_Vertex; From 9078d9a0f245a4a7218936adc0dc421d1a32a770 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 27 Mar 2014 14:14:31 -0700 Subject: [PATCH 11/39] Fix for avatar LOD's getting into a degenerate state. Don't persist the avatar LOD, since we adjust it more rapidly. --- interface/interface_en.ts | 8 ++++---- interface/src/Menu.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index da8827d89d..aa7b1951ea 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 79b0a23ce5..efb5f04c43 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -393,8 +393,6 @@ void Menu::loadSettings(QSettings* settings) { _maxVoxels = loadSetting(settings, "maxVoxels", DEFAULT_MAX_VOXELS_PER_SYSTEM); _maxVoxelPacketsPerSecond = loadSetting(settings, "maxVoxelsPPS", DEFAULT_MAX_VOXEL_PPS); _voxelSizeScale = loadSetting(settings, "voxelSizeScale", DEFAULT_OCTREE_SIZE_SCALE); - _avatarLODDistanceMultiplier = loadSetting(settings, "avatarLODDistanceMultiplier", - DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER); _boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0); settings->beginGroup("View Frustum Offset Camera"); @@ -434,7 +432,6 @@ void Menu::saveSettings(QSettings* settings) { settings->setValue("maxVoxels", _maxVoxels); settings->setValue("maxVoxelsPPS", _maxVoxelPacketsPerSecond); settings->setValue("voxelSizeScale", _voxelSizeScale); - settings->setValue("avatarLODDistanceMultiplier", _avatarLODDistanceMultiplier); settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust); settings->beginGroup("View Frustum Offset Camera"); settings->setValue("viewFrustumOffsetYaw", _viewFrustumOffset.yaw); @@ -1203,7 +1200,10 @@ void Menu::autoAdjustLOD(float currentFPS) { if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) { // attempt to lower the detail in proportion to the fps difference float targetFps = (ADJUST_LOD_DOWN_FPS + ADJUST_LOD_UP_FPS) * 0.5f; - _avatarLODDistanceMultiplier *= (targetFps / _fastFPSAverage.getAverage()); + float averageFps = _fastFPSAverage.getAverage(); + const float MAXIMUM_MULTIPLIER_SCALE = 2.0f; + _avatarLODDistanceMultiplier *= (averageFps < EPSILON) ? MAXIMUM_MULTIPLIER_SCALE : + qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps); _lastAvatarDetailDrop = now; } } else if (_fastFPSAverage.getAverage() > ADJUST_LOD_UP_FPS) { From eab4b4bc5d945ed2ef73db745970ea599971c2b0 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 27 Mar 2014 14:47:46 -0700 Subject: [PATCH 12/39] Make sure we process the model root nodes in alphabetic order. --- interface/src/renderer/FBXReader.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/src/renderer/FBXReader.cpp b/interface/src/renderer/FBXReader.cpp index 53f4e04b0b..6846f79825 100644 --- a/interface/src/renderer/FBXReader.cpp +++ b/interface/src/renderer/FBXReader.cpp @@ -1259,7 +1259,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) remainingModels.insert(model.key()); } while (!remainingModels.isEmpty()) { - QString topID = getTopModelID(parentMap, models, *remainingModels.constBegin()); + QString first = *remainingModels.constBegin(); + foreach (const QString& id, remainingModels) { + if (id < first) { + first = id; + } + } + QString topID = getTopModelID(parentMap, models, first); appendModelIDs(parentMap.value(topID), childMap, models, remainingModels, modelIDs); } From 077df3906fbc491fd740e2bc99674772a2e26037 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 27 Mar 2014 15:02:26 -0700 Subject: [PATCH 13/39] Make sure we reset our LOD adjustments before we switch back from throttling the renderer. --- interface/interface_en.ts | 4 ++-- interface/src/Application.cpp | 2 ++ interface/src/Menu.cpp | 6 ++++++ interface/src/Menu.h | 1 + 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index aa7b1951ea..8ca6f7d269 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -14,12 +14,12 @@ - + Open Script - + JavaScript Files (*.js) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index edeb454f11..5b08997b7c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1636,6 +1636,8 @@ void Application::updateLOD() { // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) { Menu::getInstance()->autoAdjustLOD(_fps); + } else { + Menu::getInstance()->resetLODAdjust(); } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index efb5f04c43..e1764374ea 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1249,6 +1249,12 @@ void Menu::autoAdjustLOD(float currentFPS) { } } +void Menu::resetLODAdjust() { + _fpsAverage.reset(); + _fastFPSAverage.reset(); + _lastAvatarDetailDrop = _lastAdjust = usecTimestampNow(); +} + void Menu::setVoxelSizeScale(float sizeScale) { _voxelSizeScale = sizeScale; } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index cab5645304..6b41430eaf 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -85,6 +85,7 @@ public: // User Tweakable LOD Items QString getLODFeedbackText(); void autoAdjustLOD(float currentFPS); + void resetLODAdjust(); void setVoxelSizeScale(float sizeScale); float getVoxelSizeScale() const { return _voxelSizeScale; } float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; } From c540427b9e25a6aac8185455550daab7052a08f3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 27 Mar 2014 15:03:46 -0700 Subject: [PATCH 14/39] tweaks to _processLock to reduce time it's locked --- .../src/octree/OctreeSendThread.cpp | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 023f3f3d2c..4105b21eb8 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -48,26 +48,28 @@ OctreeSendThread::~OctreeSendThread() { } void OctreeSendThread::setIsShuttingDown() { - QMutexLocker locker(&_processLock); // this will cause us to wait till the process loop is complete _isShuttingDown = true; OctreeServer::stopTrackingThread(this); + + // this will cause us to wait till the process loop is complete, we do this after we change _isShuttingDown + QMutexLocker locker(&_processLock); } bool OctreeSendThread::process() { + if (_isShuttingDown) { + return false; // exit early if we're shutting down + } + OctreeServer::didProcess(this); float lockWaitElapsedUsec = OctreeServer::SKIP_TIME; quint64 lockWaitStart = usecTimestampNow(); - QMutexLocker locker(&_processLock); + _processLock.lock(); quint64 lockWaitEnd = usecTimestampNow(); lockWaitElapsedUsec = (float)(lockWaitEnd - lockWaitStart); OctreeServer::trackProcessWaitTime(lockWaitElapsedUsec); - if (_isShuttingDown) { - return false; // exit early if we're shutting down - } - quint64 start = usecTimestampNow(); // don't do any send processing until the initial load of the octree is complete... @@ -98,6 +100,12 @@ bool OctreeSendThread::process() { } } + _processLock.unlock(); + + if (_isShuttingDown) { + return false; // exit early if we're shutting down + } + // Only sleep if we're still running and we got the lock last time we tried, otherwise try to get the lock asap if (isStillRunning()) { // dynamically sleep until we need to fire off the next set of octree elements From 796d20168e1d3105ed0a887fce3bb9b20f8395a6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 27 Mar 2014 15:30:30 -0700 Subject: [PATCH 15/39] splitting lean input from lean perturbations --- interface/src/avatar/Avatar.cpp | 19 ----------- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/Head.cpp | 21 +++++++++++- interface/src/avatar/Head.h | 17 ++++++++-- interface/src/avatar/MyAvatar.cpp | 45 ++++++++++++++++---------- interface/src/avatar/MyAvatar.h | 4 +++ interface/src/avatar/SkeletonModel.cpp | 10 ++++-- libraries/avatars/src/HeadData.cpp | 7 ---- libraries/avatars/src/HeadData.h | 5 --- 9 files changed, 75 insertions(+), 55 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index de9b33d9c7..75b0a4c66a 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -758,25 +758,6 @@ bool Avatar::collisionWouldMoveAvatar(CollisionInfo& collision) const { return false; } -void Avatar::applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { - // compute lean angles - glm::vec3 leverAxis = contactPoint - getPosition(); - float leverLength = glm::length(leverAxis); - if (leverLength > EPSILON) { - glm::quat bodyRotation = getOrientation(); - glm::vec3 xAxis = bodyRotation * glm::vec3(1.f, 0.f, 0.f); - glm::vec3 zAxis = bodyRotation * glm::vec3(0.f, 0.f, 1.f); - - leverAxis = leverAxis / leverLength; - glm::vec3 effectivePenetration = penetration - glm::dot(penetration, leverAxis) * leverAxis; - // we use the small-angle approximation for sine below to compute the length of - // the opposite side of a narrow right triangle - float sideways = - glm::dot(effectivePenetration, xAxis) / leverLength; - float forward = glm::dot(effectivePenetration, zAxis) / leverLength; - getHead()->addLean(sideways, forward); - } -} - float Avatar::getBoundingRadius() const { // TODO: also use head model when computing the avatar's bounding radius return _skeletonModel.getBoundingRadius(); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 685705bfc4..f2ee400ba2 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -145,7 +145,7 @@ public: /// \return true if we expect the avatar would move as a result of the collision bool collisionWouldMoveAvatar(CollisionInfo& collision) const; - void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration); + virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { } /// \return bounding radius of avatar virtual float getBoundingRadius() const; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index d432830252..ffa0975ccb 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -39,6 +39,8 @@ Head::Head(Avatar* owningAvatar) : _deltaPitch(0.f), _deltaYaw(0.f), _deltaRoll(0.f), + _deltaLeanSideways(0.f), + _deltaLeanForward(0.f), _isCameraMoving(false), _faceModel(this) { @@ -56,7 +58,6 @@ void Head::reset() { } void Head::simulate(float deltaTime, bool isMine, bool billboard) { - // Update audio trailing average for rendering facial animations Faceshift* faceshift = Application::getInstance()->getFaceshift(); Visage* visage = Application::getInstance()->getVisage(); @@ -165,6 +166,19 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) { _eyePosition = calculateAverageEyePosition(); } +void Head::relaxLean(float deltaTime) { + // restore rotation, lean to neutral positions + const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds + float relaxationFactor = 1.f - glm::min(deltaTime / LEAN_RELAXATION_PERIOD, 1.f); + _deltaYaw *= relaxationFactor; + _deltaPitch *= relaxationFactor; + _deltaRoll *= relaxationFactor; + _leanSideways *= relaxationFactor; + _leanForward *= relaxationFactor; + _deltaLeanSideways *= relaxationFactor; + _deltaLeanForward *= relaxationFactor; +} + void Head::render(float alpha, bool forShadowMap) { if (_faceModel.render(alpha, forShadowMap) && _renderLookatVectors) { renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition); @@ -209,6 +223,11 @@ float Head::getFinalRoll() const { return glm::clamp(_baseRoll + _deltaRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); } +void Head::addLeanDeltas(float sideways, float forward) { + _deltaLeanSideways += sideways; + _deltaLeanForward += forward; +} + void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) { Application::getInstance()->getGlowEffect()->begin(); diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index dc96aa318f..8a03cfc7ad 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -44,6 +44,8 @@ public: void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; } void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; } void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; } + void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; } + void setLeanForward(float leanForward) { _leanForward = leanForward; } /// \return orientationBody * orientationBase+Delta glm::quat getFinalOrientation() const; @@ -61,6 +63,10 @@ public: glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } glm::vec3 getUpDirection() const { return getOrientation() * IDENTITY_UP; } glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; } + float getLeanSideways() const { return _leanSideways; } + float getLeanForward() const { return _leanForward; } + float getFinalLeanSideways() const { return _leanSideways + _deltaLeanSideways; } + float getFinalLeanForward() const { return _leanForward + _deltaLeanForward; } glm::quat getEyeRotation(const glm::vec3& eyePosition) const; @@ -71,7 +77,7 @@ public: float getAverageLoudness() const { return _averageLoudness; } glm::vec3 calculateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; } - /// Returns the point about which scaling occurs. + /// \return the point about which scaling occurs. glm::vec3 getScalePivot() const; void setDeltaPitch(float pitch) { _deltaPitch = pitch; } @@ -86,6 +92,9 @@ public: virtual float getFinalPitch() const; virtual float getFinalYaw() const; virtual float getFinalRoll() const; + + void relaxLean(float deltaTime); + void addLeanDeltas(float sideways, float forward); private: // disallow copies of the Head, copy of owning Avatar is disallowed too @@ -110,11 +119,15 @@ private: float _rightEyeBlinkVelocity; float _timeWithoutTalking; - // delta angles for local head rotation + // delta angles for local head rotation (driven by hardware input) float _deltaPitch; float _deltaYaw; float _deltaRoll; + // delta lean angles for lean perturbations (driven by collisions) + float _deltaLeanSideways; + float _deltaLeanForward; + bool _isCameraMoving; FaceModel _faceModel; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c1c8a9a616..e18735e3e5 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -93,7 +93,13 @@ void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) { } void MyAvatar::update(float deltaTime) { + Head* head = getHead(); + head->relaxLean(deltaTime); updateFromGyros(deltaTime); + if (Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) { + // Faceshift drive is enabled, set the avatar drive based on the head position + moveWithLean(); + } // Update head mouse from faceshift if active Faceshift* faceshift = Application::getInstance()->getFaceshift(); @@ -111,7 +117,6 @@ void MyAvatar::update(float deltaTime) { //_headMouseY = glm::clamp(_headMouseY, 0, _glWidget->height()); } - Head* head = getHead(); if (OculusManager::isConnected()) { float yaw, pitch, roll; // these angles will be in radians OculusManager::getEulerAngles(yaw, pitch, roll); @@ -360,17 +365,7 @@ void MyAvatar::updateFromGyros(float deltaTime) { } } } - } else { - // restore rotation, lean to neutral positions - const float RESTORE_PERIOD = 0.25f; // seconds - float restorePercentage = glm::clamp(deltaTime/RESTORE_PERIOD, 0.f, 1.f); - head->setDeltaPitch(glm::mix(head->getDeltaPitch(), 0.0f, restorePercentage)); - head->setDeltaYaw(glm::mix(head->getDeltaYaw(), 0.0f, restorePercentage)); - head->setDeltaRoll(glm::mix(head->getDeltaRoll(), 0.0f, restorePercentage)); - head->setLeanSideways(glm::mix(head->getLeanSideways(), 0.0f, restorePercentage)); - head->setLeanForward(glm::mix(head->getLeanForward(), 0.0f, restorePercentage)); - return; - } + } // Set the rotation of the avatar's head (as seen by others, not affecting view frustum) // to be scaled. Pitch is greater to emphasize nodding behavior / synchrony. @@ -389,13 +384,11 @@ void MyAvatar::updateFromGyros(float deltaTime) { -MAX_LEAN, MAX_LEAN)); head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); +} - // if Faceshift drive is enabled, set the avatar drive based on the head position - if (!Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) { - return; - } - +void MyAvatar::moveWithLean() { // Move with Lean by applying thrust proportional to leaning + Head* head = getHead(); glm::quat orientation = head->getCameraOrientation(); glm::vec3 front = orientation * IDENTITY_FRONT; glm::vec3 right = orientation * IDENTITY_RIGHT; @@ -1152,3 +1145,21 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { } } + +void MyAvatar::applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { + glm::vec3 leverAxis = contactPoint - getPosition(); + float leverLength = glm::length(leverAxis); + if (leverLength > EPSILON) { + // compute lean perturbation angles + glm::quat bodyRotation = getOrientation(); + glm::vec3 xAxis = bodyRotation * glm::vec3(1.f, 0.f, 0.f); + glm::vec3 zAxis = bodyRotation * glm::vec3(0.f, 0.f, 1.f); + + leverAxis = leverAxis / leverLength; + glm::vec3 effectivePenetration = penetration - glm::dot(penetration, leverAxis) * leverAxis; + // use the small-angle approximation for sine + float sideways = - glm::dot(effectivePenetration, xAxis) / leverLength; + float forward = glm::dot(effectivePenetration, zAxis) / leverLength; + getHead()->addLeanDeltas(sideways, forward); + } +} diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index cbb625aa2f..38edc5356e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -34,6 +34,7 @@ public: void update(float deltaTime); void simulate(float deltaTime); void updateFromGyros(float deltaTime); + void moveWithLean(); void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE); void renderBody(RenderMode renderMode); @@ -87,6 +88,9 @@ public: virtual void clearJointData(int index); virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + + void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration); + public slots: void goHome(); void increaseSize(); diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index b4746a39d2..3c5f5cae6a 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -72,11 +72,15 @@ void SkeletonModel::getHandShapes(int jointIndex, QVector& shapes) const FBXGeometry& geometry = _geometry->getFBXGeometry(); for (int i = 0; i < _jointStates.size(); i++) { const FBXJoint& joint = geometry.joints[i]; + int parentIndex = joint.parentIndex; if (i == jointIndex) { // this shape is the hand shapes.push_back(_shapes[i]); + if (parentIndex != -1) { + // also add the forearm + shapes.push_back(_shapes[parentIndex]); + } } else { - int parentIndex = joint.parentIndex; while (parentIndex != -1) { if (parentIndex == jointIndex) { // this shape is a child of the hand @@ -199,8 +203,8 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const glm::mat3 axes = glm::mat3_cast(_rotation); glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) * joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation))); - state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getLeanSideways(), - glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getLeanForward(), + state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(), + glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(), glm::normalize(inverse * axes[0])) * joint.rotation; } diff --git a/libraries/avatars/src/HeadData.cpp b/libraries/avatars/src/HeadData.cpp index da1bdca23b..e74ac043fb 100644 --- a/libraries/avatars/src/HeadData.cpp +++ b/libraries/avatars/src/HeadData.cpp @@ -61,10 +61,3 @@ void HeadData::addRoll(float roll) { setBaseRoll(_baseRoll + roll); } - -void HeadData::addLean(float sideways, float forwards) { - // Add lean as impulse - _leanSideways += sideways; - _leanForward += forwards; -} - diff --git a/libraries/avatars/src/HeadData.h b/libraries/avatars/src/HeadData.h index a907c5b694..c60627e3f9 100644 --- a/libraries/avatars/src/HeadData.h +++ b/libraries/avatars/src/HeadData.h @@ -32,10 +32,6 @@ public: virtual ~HeadData() { }; // degrees - float getLeanSideways() const { return _leanSideways; } - void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; } - float getLeanForward() const { return _leanForward; } - void setLeanForward(float leanForward) { _leanForward = leanForward; } float getBaseYaw() const { return _baseYaw; } void setBaseYaw(float yaw) { _baseYaw = glm::clamp(yaw, MIN_HEAD_YAW, MAX_HEAD_YAW); } float getBasePitch() const { return _basePitch; } @@ -64,7 +60,6 @@ public: void addYaw(float yaw); void addPitch(float pitch); void addRoll(float roll); - void addLean(float sideways, float forwards); const glm::vec3& getLookAtPosition() const { return _lookAtPosition; } void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; } From aee15e0496863a0b638cef385814e59cf417f3bb Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 27 Mar 2014 15:38:21 -0700 Subject: [PATCH 16/39] Don't render display name/chat message for own avatar in first person mode. --- interface/src/avatar/Avatar.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 94e1416e68..9e9210a5b8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -246,7 +246,8 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { const float DISPLAYNAME_DISTANCE = 10.0f; setShowDisplayName(renderMode == NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE); - if (renderMode != NORMAL_RENDER_MODE) { + if (renderMode != NORMAL_RENDER_MODE || (isMyAvatar() && + Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON)) { return; } renderDisplayName(); From 361276d13389a0227f7ed411ec71fa066eb574ae Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Thu, 27 Mar 2014 16:19:21 -0700 Subject: [PATCH 17/39] Use a spherical estimate of the shadowed region to avoid growing and shrinking it as we turn around. Also, might as well render shadows for the billboards. --- interface/interface_en.ts | 4 ++-- interface/src/Application.cpp | 29 ++++++++++++++++++----------- interface/src/avatar/Avatar.cpp | 4 +--- 3 files changed, 21 insertions(+), 16 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 8ca6f7d269..c1d16e878f 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -14,12 +14,12 @@ - + Open Script - + JavaScript Files (*.js) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5b08997b7c..c6fc522fca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2189,19 +2189,26 @@ void Application::updateShadowMap() { (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); loadViewFrustum(_myCamera, _viewFrustum); glm::vec3 points[] = { - inverseRotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale)), - inverseRotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale)), - inverseRotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale)), - inverseRotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale)), - inverseRotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale)), - inverseRotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale)), - inverseRotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale)), - inverseRotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale)) }; - glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX), maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX); + glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale), + glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale), + glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale), + glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale), + glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale), + glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale), + glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale), + glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) }; + glm::vec3 center; for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) { - minima = glm::min(minima, points[i]); - maxima = glm::max(maxima, points[i]); + center += points[i]; } + center /= (float)(sizeof(points) / sizeof(points[0])); + float radius = 0.0f; + for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) { + radius = qMax(radius, glm::distance(points[i], center)); + } + center = inverseRotation * center; + glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius); + glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius); // stretch out our extents in z so that we get all of the avatars minima.z -= _viewFrustum.getFarClip() * 0.5f; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 9e9210a5b8..0b77d3e759 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -313,9 +313,7 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { void Avatar::renderBody(RenderMode renderMode) { if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { // render the billboard until both models are loaded - if (renderMode != SHADOW_RENDER_MODE) { - renderBillboard(); - } + renderBillboard(); return; } _skeletonModel.render(1.0f, renderMode == SHADOW_RENDER_MODE); From 5c7ac6d3a1964870675063d2a38cf494fed9c03a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 27 Mar 2014 17:41:55 -0700 Subject: [PATCH 18/39] hack the NodeList to take the socket on which pinged as active socket --- libraries/shared/src/NodeList.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 761ea40d55..d4ede7ee66 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -294,6 +294,10 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr matchingNode->setLastHeardMicrostamp(usecTimestampNow()); QByteArray replyPacket = constructPingReplyPacket(packet); writeDatagram(replyPacket, matchingNode, senderSockAddr); + + // HACK for hacker dojo network demo + matchingNode->setPublicSocket(senderSockAddr); + matchingNode->activatePublicSocket(); } break; @@ -829,13 +833,13 @@ SharedNodePointer NodeList::updateSocketsForNode(const QUuid& uuid, // check if we need to change this node's public or local sockets if (publicSocket != matchingNode->getPublicSocket()) { - matchingNode->setPublicSocket(publicSocket); - qDebug() << "Public socket change for node" << *matchingNode; +// matchingNode->setPublicSocket(publicSocket); +// qDebug() << "Public socket change for node" << *matchingNode; } if (localSocket != matchingNode->getLocalSocket()) { - matchingNode->setLocalSocket(localSocket); - qDebug() << "Local socket change for node" << *matchingNode; +// matchingNode->setLocalSocket(localSocket); +// qDebug() << "Local socket change for node" << *matchingNode; } } From 1c47b8a3e15336a188e82e50efc5484ceb8901b3 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 27 Mar 2014 21:29:01 -0700 Subject: [PATCH 19/39] Revert "hack the NodeList to take the socket on which pinged as active socket" This reverts commit 5c7ac6d3a1964870675063d2a38cf494fed9c03a. --- libraries/shared/src/NodeList.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index d4ede7ee66..761ea40d55 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -294,10 +294,6 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr matchingNode->setLastHeardMicrostamp(usecTimestampNow()); QByteArray replyPacket = constructPingReplyPacket(packet); writeDatagram(replyPacket, matchingNode, senderSockAddr); - - // HACK for hacker dojo network demo - matchingNode->setPublicSocket(senderSockAddr); - matchingNode->activatePublicSocket(); } break; @@ -833,13 +829,13 @@ SharedNodePointer NodeList::updateSocketsForNode(const QUuid& uuid, // check if we need to change this node's public or local sockets if (publicSocket != matchingNode->getPublicSocket()) { -// matchingNode->setPublicSocket(publicSocket); -// qDebug() << "Public socket change for node" << *matchingNode; + matchingNode->setPublicSocket(publicSocket); + qDebug() << "Public socket change for node" << *matchingNode; } if (localSocket != matchingNode->getLocalSocket()) { -// matchingNode->setLocalSocket(localSocket); -// qDebug() << "Local socket change for node" << *matchingNode; + matchingNode->setLocalSocket(localSocket); + qDebug() << "Local socket change for node" << *matchingNode; } } From 18a293c020f8bda43569c47478ad2a7fd1e7f094 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 28 Mar 2014 08:58:49 -0700 Subject: [PATCH 20/39] add a symmetric socket to the Node class --- libraries/shared/src/Node.cpp | 1 + libraries/shared/src/Node.h | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index dadf39f790..d300cd7ba0 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -51,6 +51,7 @@ Node::Node(const QUuid& uuid, char type, const HifiSockAddr& publicSocket, const _lastHeardMicrostamp(usecTimestampNow()), _publicSocket(publicSocket), _localSocket(localSocket), + _symmetricSocket(), _activeSocket(NULL), _connectionSecret(), _bytesReceivedMovingAverage(NULL), diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index 43ec5baf81..1c9ee97477 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -70,7 +70,9 @@ public: void setPublicSocket(const HifiSockAddr& publicSocket); const HifiSockAddr& getLocalSocket() const { return _localSocket; } void setLocalSocket(const HifiSockAddr& localSocket); - + const HifiSockAddr& getSymmetricSocket() const { return _symmetricSocket; } + void setSymmetricSocket(const HifiSockAddr& symmetricSocket) { _symmetricSocket = symmetricSocket; } + const HifiSockAddr* getActiveSocket() const { return _activeSocket; } void activatePublicSocket(); @@ -110,6 +112,7 @@ private: quint64 _lastHeardMicrostamp; HifiSockAddr _publicSocket; HifiSockAddr _localSocket; + HifiSockAddr _symmetricSocket; HifiSockAddr* _activeSocket; QUuid _connectionSecret; SimpleMovingAverage* _bytesReceivedMovingAverage; From f80b415497e6c1402ed46217280702fae0129f1b Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 28 Mar 2014 09:07:30 -0700 Subject: [PATCH 21/39] handle activation and setting of symmetric socket --- libraries/shared/src/Node.cpp | 14 ++++++++++++++ libraries/shared/src/Node.h | 3 ++- libraries/shared/src/NodeList.cpp | 12 ++++++++++++ libraries/shared/src/NodeList.h | 1 + 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/Node.cpp b/libraries/shared/src/Node.cpp index d300cd7ba0..a4491fb707 100644 --- a/libraries/shared/src/Node.cpp +++ b/libraries/shared/src/Node.cpp @@ -85,6 +85,15 @@ void Node::setLocalSocket(const HifiSockAddr& localSocket) { _localSocket = localSocket; } +void Node::setSymmetricSocket(const HifiSockAddr& symmetricSocket) { + if (_activeSocket == &_symmetricSocket) { + // if the active socket was the symmetric socket then reset it to NULL + _activeSocket = NULL; + } + + _symmetricSocket = symmetricSocket; +} + void Node::activateLocalSocket() { qDebug() << "Activating local socket for node" << *this; _activeSocket = &_localSocket; @@ -95,6 +104,11 @@ void Node::activatePublicSocket() { _activeSocket = &_publicSocket; } +void Node::activateSymmetricSocket() { + qDebug() << "Activating symmetric socket for node" << *this; + _activeSocket = &_symmetricSocket; +} + void Node::recordBytesReceived(int bytesReceived) { if (!_bytesReceivedMovingAverage) { _bytesReceivedMovingAverage = new SimpleMovingAverage(100); diff --git a/libraries/shared/src/Node.h b/libraries/shared/src/Node.h index 1c9ee97477..79d75629a6 100644 --- a/libraries/shared/src/Node.h +++ b/libraries/shared/src/Node.h @@ -71,12 +71,13 @@ public: const HifiSockAddr& getLocalSocket() const { return _localSocket; } void setLocalSocket(const HifiSockAddr& localSocket); const HifiSockAddr& getSymmetricSocket() const { return _symmetricSocket; } - void setSymmetricSocket(const HifiSockAddr& symmetricSocket) { _symmetricSocket = symmetricSocket; } + void setSymmetricSocket(const HifiSockAddr& symmetricSocket); const HifiSockAddr* getActiveSocket() const { return _activeSocket; } void activatePublicSocket(); void activateLocalSocket(); + void activateSymmetricSocket(); const QUuid& getConnectionSecret() const { return _connectionSecret; } void setConnectionSecret(const QUuid& connectionSecret) { _connectionSecret = connectionSecret; } diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 761ea40d55..bcd40a8de4 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -294,6 +294,15 @@ void NodeList::processNodeData(const HifiSockAddr& senderSockAddr, const QByteAr matchingNode->setLastHeardMicrostamp(usecTimestampNow()); QByteArray replyPacket = constructPingReplyPacket(packet); writeDatagram(replyPacket, matchingNode, senderSockAddr); + + // If we don't have a symmetric socket for this node and this socket doesn't match + // what we have for public and local then set it as the symmetric. + // This allows a server on a reachable port to communicate with nodes on symmetric NATs + if (matchingNode->getSymmetricSocket().isNull()) { + if (senderSockAddr != matchingNode->getLocalSocket() && senderSockAddr != matchingNode->getPublicSocket()) { + matchingNode->setSymmetricSocket(senderSockAddr); + } + } } break; @@ -879,6 +888,9 @@ void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, con sendingNode->activateLocalSocket(); } else if (pingType == PingType::Public && !sendingNode->getActiveSocket()) { sendingNode->activatePublicSocket(); + } else if (pingType == PingType::Symmetric && !sendingNode->getActiveSocket()) { + + } } diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index d05d6a2fbc..182c72b670 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -58,6 +58,7 @@ namespace PingType { const PingType_t Agnostic = 0; const PingType_t Local = 1; const PingType_t Public = 2; + const PingType_t Symmetric = 3; } class NodeList : public QObject { From 8b1b2d8d9901a07fa9483ef7a30fe743b70b5f91 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 28 Mar 2014 09:11:20 -0700 Subject: [PATCH 22/39] send a symmetric ping packet if appropriate when pinging nodes --- libraries/shared/src/NodeList.cpp | 9 +++++++-- libraries/shared/src/NodeList.h | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index bcd40a8de4..879377a2fd 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -791,7 +791,7 @@ QByteArray NodeList::constructPingReplyPacket(const QByteArray& pingPacket) { return replyPacket; } -void NodeList::pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node) { +void NodeList::pingPunchForInactiveNode(const SharedNodePointer& node) { // send the ping packet to the local and public sockets for this node QByteArray localPingPacket = constructPingPacket(PingType::Local); @@ -799,6 +799,11 @@ void NodeList::pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& QByteArray publicPingPacket = constructPingPacket(PingType::Public); writeDatagram(publicPingPacket, node, node->getPublicSocket()); + + if (!node->getSymmetricSocket().isNull()) { + QByteArray symmetricPingPacket = constructPingPacket(PingType::Symmetric); + writeDatagram(symmetricPingPacket, node, node->getSymmetricSocket()); + } } SharedNodePointer NodeList::addOrUpdateNode(const QUuid& uuid, char nodeType, @@ -869,7 +874,7 @@ void NodeList::pingInactiveNodes() { foreach (const SharedNodePointer& node, getNodeHash()) { if (!node->getActiveSocket()) { // we don't have an active link to this node, ping it to set that up - pingPublicAndLocalSocketsForInactiveNode(node); + pingPunchForInactiveNode(node); } } } diff --git a/libraries/shared/src/NodeList.h b/libraries/shared/src/NodeList.h index 182c72b670..34078b6a94 100644 --- a/libraries/shared/src/NodeList.h +++ b/libraries/shared/src/NodeList.h @@ -102,7 +102,7 @@ public: QByteArray constructPingPacket(PingType_t pingType = PingType::Agnostic); QByteArray constructPingReplyPacket(const QByteArray& pingPacket); - void pingPublicAndLocalSocketsForInactiveNode(const SharedNodePointer& node); + void pingPunchForInactiveNode(const SharedNodePointer& node); SharedNodePointer nodeWithUUID(const QUuid& nodeUUID, bool blockingLock = true); SharedNodePointer sendingNodeForPacket(const QByteArray& packet); From 65f912249db51230b6250fb814dd15da90eaefaa Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 17 Mar 2014 14:52:56 +0200 Subject: [PATCH 23/39] Moved user names in the char 1 pixel to the bottom. --- interface/src/ui/ChatWindow.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 55f32c5c7c..21f9b5285f 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -191,7 +191,10 @@ void ChatWindow::participantsChanged() { userLabel->setStyleSheet("background-color: palette(light);" "border-radius: 5px;" "color: #267077;" - "padding: 2px;" + "padding-top: 3px;" + "padding-right: 2px;" + "padding-bottom: 2px;" + "padding-left: 2px;" "border: 1px solid palette(shadow);" "font-weight: bold"); ui->usersWidget->layout()->addWidget(userLabel); From a48ca6523685007b1e5bd5ad1b9bf14335f17a43 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 17 Mar 2014 15:49:30 +0200 Subject: [PATCH 24/39] Enabled going to the clicked user in the chat. --- interface/interface_en.ts | 8 ++-- interface/src/Menu.cpp | 10 +++-- interface/src/Menu.h | 1 + interface/src/ui/ChatWindow.cpp | 70 +++++++++++++++++++-------------- 4 files changed, 52 insertions(+), 37 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index c1d16e878f..5d17756094 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -45,7 +45,7 @@ - + day %n day @@ -53,7 +53,7 @@ - + hour %n hour @@ -61,7 +61,7 @@ - + minute %n minute @@ -76,7 +76,7 @@ - + %1 online now: diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e1764374ea..47c6d040be 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -923,12 +923,16 @@ void Menu::goTo() { gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height()); int dialogReturn = gotoDialog.exec(); - if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) { + goToUser(dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty(), + gotoDialog.textValue()); +} + +void Menu::goToUser(bool go, const QString& user) { + if (go) { LocationManager* manager = &LocationManager::getInstance(); - manager->goTo(gotoDialog.textValue()); + manager->goTo(user); connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision); } - sendFakeEnterEvent(); } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 6b41430eaf..41bd1b85fd 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -122,6 +122,7 @@ public slots: void importSettings(); void exportSettings(); void goTo(); + void goToUser(bool go, const QString& user); void pasteToVoxel(); void toggleLoginMenuItem(); diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 21f9b5285f..2ea2b080a0 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "Application.h" @@ -90,27 +89,33 @@ void ChatWindow::showEvent(QShowEvent* event) { } bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { - Q_UNUSED(sender); - - if (event->type() != QEvent::KeyPress) { - return false; - } - QKeyEvent* keyEvent = static_cast(event); - if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) && - (keyEvent->modifiers() & Qt::ShiftModifier) == 0) { - QString messageText = ui->messagePlainTextEdit->document()->toPlainText().trimmed(); - if (!messageText.isEmpty()) { -#ifdef HAVE_QXMPP - const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); - QXmppMessage message; - message.setTo(publicChatRoom->jid()); - message.setType(QXmppMessage::GroupChat); - message.setBody(messageText); - XmppClient::getInstance().getXMPPClient().sendPacket(message); -#endif - ui->messagePlainTextEdit->document()->clear(); + if (sender == ui->messagePlainTextEdit) { + if (event->type() != QEvent::KeyPress) { + return false; } - return true; + QKeyEvent* keyEvent = static_cast(event); + if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) && + (keyEvent->modifiers() & Qt::ShiftModifier) == 0) { + QString messageText = ui->messagePlainTextEdit->document()->toPlainText().trimmed(); + if (!messageText.isEmpty()) { + #ifdef HAVE_QXMPP + const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom(); + QXmppMessage message; + message.setTo(publicChatRoom->jid()); + message.setType(QXmppMessage::GroupChat); + message.setBody(messageText); + XmppClient::getInstance().getXMPPClient().sendPacket(message); + #endif + ui->messagePlainTextEdit->document()->clear(); + } + return true; + } + } else { + if (event->type() != QEvent::MouseButtonRelease) { + return false; + } + QString user = sender->property("user").toString(); + Menu::getInstance()->goToUser(true, user); } return false; } @@ -187,16 +192,21 @@ void ChatWindow::participantsChanged() { delete item; } foreach (const QString& participant, participants) { - QLabel* userLabel = new QLabel(getParticipantName(participant)); + QString participantName = getParticipantName(participant); + QLabel* userLabel = new QLabel(); + userLabel->setText(participantName); userLabel->setStyleSheet("background-color: palette(light);" - "border-radius: 5px;" - "color: #267077;" - "padding-top: 3px;" - "padding-right: 2px;" - "padding-bottom: 2px;" - "padding-left: 2px;" - "border: 1px solid palette(shadow);" - "font-weight: bold"); + "border-radius: 5px;" + "color: #267077;" + "padding-top: 3px;" + "padding-right: 2px;" + "padding-bottom: 2px;" + "padding-left: 2px;" + "border: 1px solid palette(shadow);" + "font-weight: bold"); + userLabel->setProperty("user", participantName); + userLabel->setCursor(Qt::PointingHandCursor); + userLabel->installEventFilter(this); ui->usersWidget->layout()->addWidget(userLabel); } } From d764ef79ed8461cc531bccc8e285fcca3e63980b Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 17 Mar 2014 18:05:16 +0200 Subject: [PATCH 25/39] Gave more space to the user in sent messages so that resizing of the column for messages occurs for really long user names. --- interface/interface_en.ts | 14 +++++++------- interface/src/ui/ChatWindow.cpp | 15 ++++++++++----- interface/ui/chatWindow.ui | 32 ++++++++++++++++---------------- 3 files changed, 33 insertions(+), 28 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 5d17756094..e2f9720777 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -28,24 +28,24 @@ ChatWindow - + Chat - + Connecting to XMPP... - + online now: - + day %n day @@ -53,7 +53,7 @@ - + hour %n hour @@ -61,7 +61,7 @@ - + minute %n minute @@ -76,7 +76,7 @@ - + %1 online now: diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 2ea2b080a0..ab31037f43 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -6,7 +6,7 @@ // Copyright (c) 2014 High Fidelity, Inc. All rights reserved. // -#include +#include #include #include #include @@ -38,6 +38,9 @@ ChatWindow::ChatWindow() : FlowLayout* flowLayout = new FlowLayout(0, 4, 4); ui->usersWidget->setLayout(flowLayout); + ui->messagesGridLayout->setColumnStretch(0, 1); + ui->messagesGridLayout->setColumnStretch(1, 3); + ui->messagePlainTextEdit->installEventFilter(this); ui->closeButton->hide(); @@ -143,8 +146,9 @@ void ChatWindow::addTimeStamp() { timeLabel->setStyleSheet("color: palette(shadow);" "background-color: palette(highlight);" "padding: 4px;"); + timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); timeLabel->setAlignment(Qt::AlignHCenter); - ui->messagesFormLayout->addRow(timeLabel); + ui->messagesGridLayout->addWidget(timeLabel, ui->messagesGridLayout->rowCount(), 0, 1, 2); numMessagesAfterLastTimeStamp = 0; } } @@ -217,7 +221,7 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { } QLabel* userLabel = new QLabel(getParticipantName(message.from())); - userLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + userLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); userLabel->setStyleSheet("padding: 2px; font-weight: bold"); userLabel->setAlignment(Qt::AlignTop); @@ -228,8 +232,9 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { messageLabel->setStyleSheet("padding: 2px; margin-right: 20px"); messageLabel->setAlignment(Qt::AlignTop); - ui->messagesFormLayout->addRow(userLabel, messageLabel); - ui->messagesFormLayout->parentWidget()->updateGeometry(); + ui->messagesGridLayout->addWidget(userLabel, ui->messagesGridLayout->rowCount(), 0, Qt::AlignTop | Qt::AlignRight); + ui->messagesGridLayout->addWidget(messageLabel, ui->messagesGridLayout->rowCount() - 1, 1); + ui->messagesGridLayout->parentWidget()->updateGeometry(); Application::processEvents(); QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar(); verticalScrollBar->setSliderPosition(verticalScrollBar->maximum()); diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 1106fca3cd..e549feaded 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -122,34 +122,34 @@ 0 0 - 358 - 464 + 382 + 16 + + + 0 + 0 + + margin-top: 0px; - - - QFormLayout::AllNonFixedFieldsGrow - - - 0 - - - 0 - + - 4 + 0 - 4 + 0 - 4 + 0 - 4 + 0 + + + 0 From 5073439007f22c3384377effef47b2866c6665a6 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 24 Mar 2014 16:55:29 +0200 Subject: [PATCH 26/39] Highlighted the user's own chat messages. --- interface/src/ui/ChatWindow.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index ab31037f43..2c2c64ac0c 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -200,14 +200,14 @@ void ChatWindow::participantsChanged() { QLabel* userLabel = new QLabel(); userLabel->setText(participantName); userLabel->setStyleSheet("background-color: palette(light);" - "border-radius: 5px;" - "color: #267077;" - "padding-top: 3px;" - "padding-right: 2px;" - "padding-bottom: 2px;" - "padding-left: 2px;" - "border: 1px solid palette(shadow);" - "font-weight: bold"); + "border-radius: 5px;" + "color: #267077;" + "padding-top: 3px;" + "padding-right: 2px;" + "padding-bottom: 2px;" + "padding-left: 2px;" + "border: 1px solid palette(shadow);" + "font-weight: bold"); userLabel->setProperty("user", participantName); userLabel->setCursor(Qt::PointingHandCursor); userLabel->installEventFilter(this); @@ -232,6 +232,11 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { messageLabel->setStyleSheet("padding: 2px; margin-right: 20px"); messageLabel->setAlignment(Qt::AlignTop); + if (getParticipantName(message.from()) == AccountManager::getInstance().getUsername()) { + userLabel->setStyleSheet(userLabel->styleSheet() + "; color: palette(highlight)"); + messageLabel->setStyleSheet(messageLabel->styleSheet() + "; color: palette(highlight)"); + } + ui->messagesGridLayout->addWidget(userLabel, ui->messagesGridLayout->rowCount(), 0, Qt::AlignTop | Qt::AlignRight); ui->messagesGridLayout->addWidget(messageLabel, ui->messagesGridLayout->rowCount() - 1, 1); ui->messagesGridLayout->parentWidget()->updateGeometry(); From e27f1914139edbb0eaffc64fd75787745379264b Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Mon, 24 Mar 2014 17:37:34 +0200 Subject: [PATCH 27/39] Changed the dock widget for the chat so that it replicates the agreed upon design. --- interface/interface_en.ts | 20 +- interface/src/ui/ChatWindow.cpp | 15 +- interface/ui/chatWindow.ui | 315 ++++++++++++++++---------------- 3 files changed, 177 insertions(+), 173 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index e2f9720777..5031083497 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -27,25 +27,25 @@ ChatWindow - - + + Chat - - + + Connecting to XMPP... - - + + online now: - + day %n day @@ -53,7 +53,7 @@ - + hour %n hour @@ -61,7 +61,7 @@ - + minute %n minute @@ -76,7 +76,7 @@ - + %1 online now: diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 2c2c64ac0c..f0da355532 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -30,10 +30,10 @@ ChatWindow::ChatWindow() : ui(new Ui::ChatWindow), numMessagesAfterLastTimeStamp(0) { - QWidget* widget = new QWidget(); - setWidget(widget); - - ui->setupUi(widget); + ui->setupUi(this); + + // remove the title bar (see the Qt docs on setTitleBarWidget) + setTitleBarWidget(new QWidget()); FlowLayout* flowLayout = new FlowLayout(0, 4, 4); ui->usersWidget->setLayout(flowLayout); @@ -42,8 +42,6 @@ ChatWindow::ChatWindow() : ui->messagesGridLayout->setColumnStretch(1, 3); ui->messagePlainTextEdit->installEventFilter(this); - - ui->closeButton->hide(); #ifdef HAVE_QXMPP const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient(); @@ -78,15 +76,16 @@ ChatWindow::~ChatWindow() { } void ChatWindow::keyPressEvent(QKeyEvent* event) { - QWidget::keyPressEvent(event); + QDockWidget::keyPressEvent(event); if (event->key() == Qt::Key_Escape) { hide(); } } void ChatWindow::showEvent(QShowEvent* event) { - QWidget::showEvent(event); + QDockWidget::showEvent(event); if (!event->spontaneous()) { + activateWindow(); ui->messagePlainTextEdit->setFocus(); } } diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index e549feaded..32ae426484 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -1,7 +1,7 @@ ChatWindow - + 0 @@ -13,180 +13,185 @@ 400 - 0 + 238 - - Chat - font-family: Helvetica, Arial, sans-serif; - - - 0 - - - 8 - - - 8 - - - 8 - - - 8 - - - - - - 0 - 0 - - - - Connecting to XMPP... - - - Qt::AlignCenter - - - - - - - + + QDockWidget::NoDockWidgetFeatures + + + Chat + + + + + 0 + + + 8 + + + 8 + + + 8 + + + 8 + + + + + + 0 + 0 + + + + Connecting to XMPP... + + + Qt::AlignCenter + + + + + + + + + + 0 + 0 + + + + font-weight: bold; color: palette(shadow); margin-bottom: 4px; + + + online now: + + + + + + + + 0 + 0 + + + + + 16 + 16 + + + + Qt::NoFocus + + + + + + + :/images/close.svg:/images/close.svg + + + true + + + + + + + + + + + + margin-top: 12px; + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 382 + 16 + + - + 0 0 - font-weight: bold; color: palette(shadow); margin-bottom: 4px; - - - online now: + margin-top: 0px; + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + - - - - - - 0 - 0 - - - - - 16 - 16 - - - - Qt::NoFocus - - - - - - - :/images/close.svg:/images/close.svg - - - true - - - - - - - - - - - - margin-top: 12px; - - - Qt::ScrollBarAlwaysOff - - - true - - - - - 0 - 0 - 382 - 16 - - + + + + - + 0 0 - - margin-top: 0px; + + + 0 + 60 + + + + border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContents + + + true - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - - 0 - 0 - - - - - 0 - 60 - - - - border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - QAbstractScrollArea::AdjustToContents - - - true - - - - + + + messagePlainTextEdit From 4374e28e9cc23258682bdc8bb6b40cfb2e215906 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Tue, 25 Mar 2014 23:41:56 +0200 Subject: [PATCH 28/39] Changed the highlighting of own messages to occupy the whole row. --- interface/src/ui/ChatWindow.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index f0da355532..ae49e82b17 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -220,23 +220,23 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { } QLabel* userLabel = new QLabel(getParticipantName(message.from())); - userLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + userLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); userLabel->setStyleSheet("padding: 2px; font-weight: bold"); - userLabel->setAlignment(Qt::AlignTop); + userLabel->setAlignment(Qt::AlignTop | Qt::AlignRight); QLabel* messageLabel = new QLabel(message.body().replace(regexLinks, "\\1")); messageLabel->setWordWrap(true); messageLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); messageLabel->setOpenExternalLinks(true); - messageLabel->setStyleSheet("padding: 2px; margin-right: 20px"); - messageLabel->setAlignment(Qt::AlignTop); + messageLabel->setStyleSheet("padding-bottom: 2px; padding-right: 2px; padding-top: 2px; padding-right: 20px"); + messageLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); if (getParticipantName(message.from()) == AccountManager::getInstance().getUsername()) { - userLabel->setStyleSheet(userLabel->styleSheet() + "; color: palette(highlight)"); - messageLabel->setStyleSheet(messageLabel->styleSheet() + "; color: palette(highlight)"); + userLabel->setStyleSheet(userLabel->styleSheet() + "; background-color: #e1e8ea"); + messageLabel->setStyleSheet(messageLabel->styleSheet() + "; background-color: #e1e8ea"); } - ui->messagesGridLayout->addWidget(userLabel, ui->messagesGridLayout->rowCount(), 0, Qt::AlignTop | Qt::AlignRight); + ui->messagesGridLayout->addWidget(userLabel, ui->messagesGridLayout->rowCount(), 0); ui->messagesGridLayout->addWidget(messageLabel, ui->messagesGridLayout->rowCount() - 1, 1); ui->messagesGridLayout->parentWidget()->updateGeometry(); Application::processEvents(); From 3907c563df14c25c150d93dab5156f2347c622da Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Wed, 26 Mar 2014 23:44:31 +0200 Subject: [PATCH 29/39] Put the chat window above the 3D view and animated its showing. --- interface/interface_en.ts | 20 ++++++++++---------- interface/src/Menu.cpp | 24 ++++++++++++++++++------ interface/ui/chatWindow.ui | 3 +++ 3 files changed, 31 insertions(+), 16 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 5031083497..56fdd669ed 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -27,20 +27,20 @@ ChatWindow - - + + Chat - - + + Connecting to XMPP... - - + + online now: @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 47c6d040be..229b2e9611 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -1103,13 +1105,23 @@ void Menu::showMetavoxelEditor() { } void Menu::showChat() { + QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_chatWindow) { - Application::getInstance()->getWindow()->addDockWidget(Qt::RightDockWidgetArea, _chatWindow = new ChatWindow()); - - } else { - if (!_chatWindow->toggleViewAction()->isChecked()) { - _chatWindow->toggleViewAction()->trigger(); - } + mainWindow->addDockWidget(Qt::NoDockWidgetArea, _chatWindow = new ChatWindow()); + } + if (!_chatWindow->toggleViewAction()->isChecked()) { + int width = _chatWindow->width(); + int y = qMax((mainWindow->height() - _chatWindow->height()) / 2, 0); + _chatWindow->move(mainWindow->width(), y); + _chatWindow->resize(0, _chatWindow->height()); + _chatWindow->toggleViewAction()->trigger(); + + QPropertyAnimation* slideAnimation = new QPropertyAnimation(_chatWindow, "geometry", _chatWindow); + slideAnimation->setStartValue(_chatWindow->geometry()); + slideAnimation->setEndValue(QRect(mainWindow->width() - width, _chatWindow->y(), + width, _chatWindow->height())); + slideAnimation->setDuration(250); + slideAnimation->start(QAbstractAnimation::DeleteWhenStopped); } } diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index 32ae426484..60a0c6badd 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -22,6 +22,9 @@ QDockWidget::NoDockWidgetFeatures + + Qt::NoDockWidgetArea + Chat From 6fd1bf7edb9941a9f9a0b3ba2721a48d5fb82dbe Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Fri, 28 Mar 2014 18:44:06 +0200 Subject: [PATCH 30/39] Simplified the new goToUser function. --- interface/interface_en.ts | 8 +++---- interface/src/Menu.cpp | 41 +++++++++++---------------------- interface/src/Menu.h | 2 +- interface/src/ui/ChatWindow.cpp | 2 +- 4 files changed, 20 insertions(+), 33 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 56fdd669ed..519e2b61c1 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -113,18 +113,18 @@ Menu - + Open .ini config file - - + + Text files (*.ini) - + Save .ini config file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 229b2e9611..e217424cbe 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -20,8 +20,6 @@ #include #include #include -#include -#include #include #include #include @@ -925,19 +923,18 @@ void Menu::goTo() { gotoDialog.resize(gotoDialog.parentWidget()->size().width() * DIALOG_RATIO_OF_WINDOW, gotoDialog.size().height()); int dialogReturn = gotoDialog.exec(); - goToUser(dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty(), - gotoDialog.textValue()); -} - -void Menu::goToUser(bool go, const QString& user) { - if (go) { - LocationManager* manager = &LocationManager::getInstance(); - manager->goTo(user); - connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision); + if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) { + goToUser(gotoDialog.textValue()); } sendFakeEnterEvent(); } +void Menu::goToUser(const QString& user) { + LocationManager* manager = &LocationManager::getInstance(); + manager->goTo(user); + connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision); +} + void Menu::multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData) { QMessageBox msgBox; msgBox.setText("Both user and location exists with same name"); @@ -1105,23 +1102,13 @@ void Menu::showMetavoxelEditor() { } void Menu::showChat() { - QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_chatWindow) { - mainWindow->addDockWidget(Qt::NoDockWidgetArea, _chatWindow = new ChatWindow()); - } - if (!_chatWindow->toggleViewAction()->isChecked()) { - int width = _chatWindow->width(); - int y = qMax((mainWindow->height() - _chatWindow->height()) / 2, 0); - _chatWindow->move(mainWindow->width(), y); - _chatWindow->resize(0, _chatWindow->height()); - _chatWindow->toggleViewAction()->trigger(); - - QPropertyAnimation* slideAnimation = new QPropertyAnimation(_chatWindow, "geometry", _chatWindow); - slideAnimation->setStartValue(_chatWindow->geometry()); - slideAnimation->setEndValue(QRect(mainWindow->width() - width, _chatWindow->y(), - width, _chatWindow->height())); - slideAnimation->setDuration(250); - slideAnimation->start(QAbstractAnimation::DeleteWhenStopped); + Application::getInstance()->getWindow()->addDockWidget(Qt::RightDockWidgetArea, _chatWindow = new ChatWindow()); + + } else { + if (!_chatWindow->toggleViewAction()->isChecked()) { + _chatWindow->toggleViewAction()->trigger(); + } } } diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 41bd1b85fd..c7c4c6ecea 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -122,7 +122,7 @@ public slots: void importSettings(); void exportSettings(); void goTo(); - void goToUser(bool go, const QString& user); + void goToUser(const QString& user); void pasteToVoxel(); void toggleLoginMenuItem(); diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index ae49e82b17..76e9c4ec2d 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -117,7 +117,7 @@ bool ChatWindow::eventFilter(QObject* sender, QEvent* event) { return false; } QString user = sender->property("user").toString(); - Menu::getInstance()->goToUser(true, user); + Menu::getInstance()->goToUser(user); } return false; } From 0c289076098f4a86a4676f5b6379b53a10fe8618 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 28 Mar 2014 10:08:00 -0700 Subject: [PATCH 31/39] fix the hydraMove script to pull you based on head orientation, not body --- examples/hydraMove.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/hydraMove.js b/examples/hydraMove.js index 92c594df9e..6268a38ba3 100644 --- a/examples/hydraMove.js +++ b/examples/hydraMove.js @@ -162,11 +162,11 @@ function flyWithHydra(deltaTime) { if (thrustMultiplier < MAX_THRUST_MULTIPLIER) { thrustMultiplier *= 1 + (deltaTime * THRUST_INCREASE_RATE); } - var currentOrientation = MyAvatar.orientation; + var headOrientation = MyAvatar.headOrientation; - var front = Quat.getFront(currentOrientation); - var right = Quat.getRight(currentOrientation); - var up = Quat.getUp(currentOrientation); + var front = Quat.getFront(headOrientation); + var right = Quat.getRight(headOrientation); + var up = Quat.getUp(headOrientation); var thrustFront = Vec3.multiply(front, MyAvatar.scale * THRUST_MAG_HAND_JETS * thrustJoystickPosition.y * thrustMultiplier * deltaTime); From 9b43508098cd68db7757f5ad7404975b1f7aaad7 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Fri, 28 Mar 2014 19:26:16 +0200 Subject: [PATCH 32/39] Restored code that Git had somehow deleted. --- interface/src/Menu.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index e217424cbe..7748c466c7 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1102,13 +1102,23 @@ void Menu::showMetavoxelEditor() { } void Menu::showChat() { + QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_chatWindow) { - Application::getInstance()->getWindow()->addDockWidget(Qt::RightDockWidgetArea, _chatWindow = new ChatWindow()); - - } else { - if (!_chatWindow->toggleViewAction()->isChecked()) { - _chatWindow->toggleViewAction()->trigger(); - } + mainWindow->addDockWidget(Qt::NoDockWidgetArea, _chatWindow = new ChatWindow()); + } + if (!_chatWindow->toggleViewAction()->isChecked()) { + int width = _chatWindow->width(); + int y = qMax((mainWindow->height() - _chatWindow->height()) / 2, 0); + _chatWindow->move(mainWindow->width(), y); + _chatWindow->resize(0, _chatWindow->height()); + _chatWindow->toggleViewAction()->trigger(); + + QPropertyAnimation* slideAnimation = new QPropertyAnimation(_chatWindow, "geometry", _chatWindow); + slideAnimation->setStartValue(_chatWindow->geometry()); + slideAnimation->setEndValue(QRect(mainWindow->width() - width, _chatWindow->y(), + width, _chatWindow->height())); + slideAnimation->setDuration(250); + slideAnimation->start(QAbstractAnimation::DeleteWhenStopped); } } From eb35b636518a72f2367a788d7c779495472a2e14 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 28 Mar 2014 10:48:44 -0700 Subject: [PATCH 33/39] use a shared pointer for more elegant cleanup at assignment conclusion --- assignment-client/src/AssignmentClient.cpp | 26 +++++++++++---------- assignment-client/src/AssignmentClient.h | 2 +- assignment-client/src/AssignmentThread.cpp | 16 +++++++++++++ assignment-client/src/AssignmentThread.h | 23 ++++++++++++++++++ libraries/shared/src/ThreadedAssignment.cpp | 9 +++---- libraries/shared/src/ThreadedAssignment.h | 4 +++- 6 files changed, 60 insertions(+), 20 deletions(-) create mode 100644 assignment-client/src/AssignmentThread.cpp create mode 100644 assignment-client/src/AssignmentThread.h diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp index 970b6518ec..aa20f2ff29 100644 --- a/assignment-client/src/AssignmentClient.cpp +++ b/assignment-client/src/AssignmentClient.cpp @@ -18,6 +18,7 @@ #include #include "AssignmentFactory.h" +#include "AssignmentThread.h" #include "AssignmentClient.h" @@ -28,7 +29,7 @@ int hifiSockAddrMeta = qRegisterMetaType("HifiSockAddr"); AssignmentClient::AssignmentClient(int &argc, char **argv) : QCoreApplication(argc, argv), - _currentAssignment(NULL) + _currentAssignment() { setOrganizationName("High Fidelity"); setOrganizationDomain("highfidelity.io"); @@ -124,7 +125,7 @@ void AssignmentClient::readPendingDatagrams() { if (nodeList->packetVersionAndHashMatch(receivedPacket)) { if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) { // construct the deployed assignment from the packet data - _currentAssignment = AssignmentFactory::unpackAssignment(receivedPacket); + _currentAssignment = SharedAssignmentPointer(AssignmentFactory::unpackAssignment(receivedPacket)); if (_currentAssignment) { qDebug() << "Received an assignment -" << *_currentAssignment; @@ -137,14 +138,13 @@ void AssignmentClient::readPendingDatagrams() { qDebug() << "Destination IP for assignment is" << nodeList->getDomainInfo().getIP().toString(); // start the deployed assignment - QThread* workerThread = new QThread(this); + AssignmentThread* workerThread = new AssignmentThread(_currentAssignment, this); - connect(workerThread, SIGNAL(started()), _currentAssignment, SLOT(run())); - - connect(_currentAssignment, SIGNAL(finished()), this, SLOT(assignmentCompleted())); - connect(_currentAssignment, SIGNAL(finished()), workerThread, SLOT(quit())); - connect(_currentAssignment, SIGNAL(finished()), _currentAssignment, SLOT(deleteLater())); - connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater())); + connect(workerThread, &QThread::started, _currentAssignment.data(), &ThreadedAssignment::run); + connect(_currentAssignment.data(), &ThreadedAssignment::finished, workerThread, &QThread::quit); + connect(_currentAssignment.data(), &ThreadedAssignment::finished, + this, &AssignmentClient::assignmentCompleted); + connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater); _currentAssignment->moveToThread(workerThread); @@ -153,7 +153,7 @@ void AssignmentClient::readPendingDatagrams() { // let the assignment handle the incoming datagrams for its duration disconnect(&nodeList->getNodeSocket(), 0, this, 0); - connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _currentAssignment, + connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _currentAssignment.data(), &ThreadedAssignment::readPendingDatagrams); // Starts an event loop, and emits workerThread->started() @@ -202,10 +202,12 @@ void AssignmentClient::assignmentCompleted() { NodeList* nodeList = NodeList::getInstance(); // have us handle incoming NodeList datagrams again - disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment, 0); + disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment.data(), 0); connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams); - _currentAssignment = NULL; + // clear our current assignment shared pointer now that we're done with it + // if the assignment thread is still around it has its own shared pointer to the assignment + _currentAssignment.clear(); // reset our NodeList by switching back to unassigned and clearing the list nodeList->setOwnerType(NodeType::Unassigned); diff --git a/assignment-client/src/AssignmentClient.h b/assignment-client/src/AssignmentClient.h index 29187fa3d6..c267c6238b 100644 --- a/assignment-client/src/AssignmentClient.h +++ b/assignment-client/src/AssignmentClient.h @@ -24,7 +24,7 @@ private slots: void handleAuthenticationRequest(); private: Assignment _requestAssignment; - ThreadedAssignment* _currentAssignment; + SharedAssignmentPointer _currentAssignment; }; #endif /* defined(__hifi__AssignmentClient__) */ diff --git a/assignment-client/src/AssignmentThread.cpp b/assignment-client/src/AssignmentThread.cpp new file mode 100644 index 0000000000..dfe093aa7b --- /dev/null +++ b/assignment-client/src/AssignmentThread.cpp @@ -0,0 +1,16 @@ +// +// AssignmentThread.cpp +// hifi +// +// Created by Stephen Birarda on 2014-03-28. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#include "AssignmentThread.h" + +AssignmentThread::AssignmentThread(const SharedAssignmentPointer& assignment, QObject* parent) : + QThread(parent), + _assignment(assignment) +{ + +} \ No newline at end of file diff --git a/assignment-client/src/AssignmentThread.h b/assignment-client/src/AssignmentThread.h new file mode 100644 index 0000000000..b55ac10676 --- /dev/null +++ b/assignment-client/src/AssignmentThread.h @@ -0,0 +1,23 @@ +// +// AssignmentThread.h +// hifi +// +// Created by Stephen Birarda on 2014-03-28. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// + +#ifndef __hifi__AssignmentThread__ +#define __hifi__AssignmentThread__ + +#include + +#include + +class AssignmentThread : public QThread { +public: + AssignmentThread(const SharedAssignmentPointer& assignment, QObject* parent); +private: + SharedAssignmentPointer _assignment; +}; + +#endif /* defined(__hifi__AssignmentThread__) */ diff --git a/libraries/shared/src/ThreadedAssignment.cpp b/libraries/shared/src/ThreadedAssignment.cpp index be49b18055..fdf2d91c36 100644 --- a/libraries/shared/src/ThreadedAssignment.cpp +++ b/libraries/shared/src/ThreadedAssignment.cpp @@ -20,18 +20,15 @@ ThreadedAssignment::ThreadedAssignment(const QByteArray& packet) : } -void ThreadedAssignment::deleteLater() { - // move the NodeList back to the QCoreApplication instance's thread - NodeList::getInstance()->moveToThread(QCoreApplication::instance()->thread()); - QObject::deleteLater(); -} - void ThreadedAssignment::setFinished(bool isFinished) { _isFinished = isFinished; if (_isFinished) { aboutToFinish(); emit finished(); + + // move the NodeList back to the QCoreApplication instance's thread + NodeList::getInstance()->moveToThread(QCoreApplication::instance()->thread()); } } diff --git a/libraries/shared/src/ThreadedAssignment.h b/libraries/shared/src/ThreadedAssignment.h index 5b78eed56d..f9652dd98d 100644 --- a/libraries/shared/src/ThreadedAssignment.h +++ b/libraries/shared/src/ThreadedAssignment.h @@ -9,6 +9,8 @@ #ifndef __hifi__ThreadedAssignment__ #define __hifi__ThreadedAssignment__ +#include + #include "Assignment.h" class ThreadedAssignment : public Assignment { @@ -22,7 +24,6 @@ public: public slots: /// threaded run of assignment virtual void run() = 0; - virtual void deleteLater(); virtual void readPendingDatagrams() = 0; virtual void sendStatsPacket(); @@ -36,5 +37,6 @@ signals: void finished(); }; +typedef QSharedPointer SharedAssignmentPointer; #endif /* defined(__hifi__ThreadedAssignment__) */ From f9cee2ccfa3b8156564a608b7b7bbf47eeecd3b8 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Fri, 28 Mar 2014 22:21:55 +0200 Subject: [PATCH 34/39] Fixed a typo that resulted in a wrong padding of a widget. --- interface/src/ui/ChatWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/ChatWindow.cpp b/interface/src/ui/ChatWindow.cpp index 76e9c4ec2d..6963c208c5 100644 --- a/interface/src/ui/ChatWindow.cpp +++ b/interface/src/ui/ChatWindow.cpp @@ -228,7 +228,7 @@ void ChatWindow::messageReceived(const QXmppMessage& message) { messageLabel->setWordWrap(true); messageLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); messageLabel->setOpenExternalLinks(true); - messageLabel->setStyleSheet("padding-bottom: 2px; padding-right: 2px; padding-top: 2px; padding-right: 20px"); + messageLabel->setStyleSheet("padding-bottom: 2px; padding-left: 2px; padding-top: 2px; padding-right: 20px"); messageLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft); if (getParticipantName(message.from()) == AccountManager::getInstance().getUsername()) { From 4d16547362be06bbafbc2664b24bd1b703034b69 Mon Sep 17 00:00:00 2001 From: Grayson Stebbins Date: Fri, 28 Mar 2014 14:50:26 -0700 Subject: [PATCH 35/39] Note about shortcut for domain dialog (set your domain via Cmnd+D/Cntrl+D) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8a6725ed8..ab1212f656 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Running Interface When you launch interface, you will automatically connect to our default domain: "root.highfidelity.io". If you don't see anything, make sure your preferences are pointing to -root.highfidelity.io, if you still have no luck it's possible our servers are +root.highfidelity.io (set your domain via Cmnd+D/Cntrl+D), if you still have no luck it's possible our servers are simply down; if you're experiencing a major bug, let us know by adding an issue to this repository. Make sure to include details about your computer and how to reproduce the bug. From 6880160bc00492ed907ebce06af713ead53ba6b2 Mon Sep 17 00:00:00 2001 From: James Brotchie Date: Mon, 31 Mar 2014 22:08:38 +1000 Subject: [PATCH 36/39] Remember most recently opened script location. Previously when running a script from a file you were always taken back to your desktop directory. Now you will be taken to the location of your most recently opened script. --- interface/interface_en.ts | 8 ++++---- interface/src/Application.cpp | 15 ++++++++++++--- interface/src/Application.h | 2 ++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/interface/interface_en.ts b/interface/interface_en.ts index 519e2b61c1..7c5d1ecbcf 100644 --- a/interface/interface_en.ts +++ b/interface/interface_en.ts @@ -4,22 +4,22 @@ Application - + Export Voxels - + Sparse Voxel Octree Files (*.svo) - + Open Script - + JavaScript Files (*.js) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c6fc522fca..d91e686844 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -169,6 +169,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _bytesPerSecond(0), _recentMaxPackets(0), _resetRecentMaxPacketsSoon(true), + _previousScriptLocation(), _logger(new FileLogger(this)) { // read the ApplicationInfo.ini file for Name/Version/Domain information @@ -3610,12 +3611,20 @@ void Application::loadScript(const QString& scriptName) { } void Application::loadDialog() { - // shut down and stop any existing script - QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); - QString suggestedName = desktopLocation.append("/script.js"); + QString suggestedName; + + if (_previousScriptLocation.isEmpty()) { + QString desktopLocation = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation); + suggestedName = desktopLocation.append("/script.js"); + } else { + suggestedName = _previousScriptLocation; + } QString fileNameString = QFileDialog::getOpenFileName(_glWidget, tr("Open Script"), suggestedName, tr("JavaScript Files (*.js)")); + if (!fileNameString.isEmpty()) { + _previousScriptLocation = fileNameString; + } loadScript(fileNameString); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 15778f2a17..bab7578ca4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -483,6 +483,8 @@ private: ControllerScriptingInterface _controllerScriptingInterface; QPointer _logDialog; + QString _previousScriptLocation; + FileLogger* _logger; void checkVersion(); From 59bc0ffb9dc652a87d191946f736fd6ff65a79da Mon Sep 17 00:00:00 2001 From: James Brotchie Date: Mon, 31 Mar 2014 23:33:17 +1000 Subject: [PATCH 37/39] Update BUILD.md Not sure about anybody else but I needed glm 0.9.5.2 the compile without errors. 0.9.5.0 (as suggested in the current BUILD.md) failed because the precision template parameter was undefined. --- BUILD.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/BUILD.md b/BUILD.md index 8f871c3cea..6464f14d08 100644 --- a/BUILD.md +++ b/BUILD.md @@ -3,7 +3,7 @@ Dependencies * [cmake](http://www.cmake.org/cmake/resources/software.html) ~> 2.8.11 * [Qt](http://qt-project.org/downloads) ~> 5.2.0 * [zLib](http://www.zlib.net/) ~> 1.2.8 -* [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.0 +* [glm](http://glm.g-truc.net/0.9.5/index.html) ~> 0.9.5.2 * [qxmpp](https://code.google.com/p/qxmpp/) ~> 0.7.6 #####Linux only @@ -142,4 +142,4 @@ If you need to debug Interface, you can run interface from within Visual Studio ####Debugging Interface * In the Solution Explorer, right click interface and click Set as StartUp Project * Set the "Working Directory" for the Interface debugging sessions to the Debug output directory so that your application can load resources. Do this: right click interface and click Properties, choose Debugging from Configuration Properties, set Working Directory to .\Debug -* Now you can run and debug interface through Visual Studio \ No newline at end of file +* Now you can run and debug interface through Visual Studio From da116608a036ca8bb5792a8537a18552d744c860 Mon Sep 17 00:00:00 2001 From: James Brotchie Date: Tue, 1 Apr 2014 07:38:22 +1000 Subject: [PATCH 38/39] Hitting enter no longer shows chat window when chat is disabled. When chat is disabled (QXMPP library not available or XMPP disconnected) hitting enter would show the chat window, even when the Tools -> Chat menu item is grayed out! --- interface/src/Menu.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7748c466c7..ec20401fef 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -1102,6 +1102,11 @@ void Menu::showMetavoxelEditor() { } void Menu::showChat() { + if (!_chatAction->isEnabled()) { + // Don't do anything if chat is disabled (No + // QXMPP library or xmpp is disconnected). + return; + } QMainWindow* mainWindow = Application::getInstance()->getWindow(); if (!_chatWindow) { mainWindow->addDockWidget(Qt::NoDockWidgetArea, _chatWindow = new ChatWindow()); From 135d97d0a7500134e39e1b283ed274a0eafb6f74 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 31 Mar 2014 15:59:54 -0700 Subject: [PATCH 39/39] add a pretty important missing line for symmetric socket activation --- libraries/shared/src/NodeList.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/shared/src/NodeList.cpp b/libraries/shared/src/NodeList.cpp index 879377a2fd..b725914bfd 100644 --- a/libraries/shared/src/NodeList.cpp +++ b/libraries/shared/src/NodeList.cpp @@ -894,8 +894,7 @@ void NodeList::activateSocketFromNodeCommunication(const QByteArray& packet, con } else if (pingType == PingType::Public && !sendingNode->getActiveSocket()) { sendingNode->activatePublicSocket(); } else if (pingType == PingType::Symmetric && !sendingNode->getActiveSocket()) { - - + sendingNode->activateSymmetricSocket(); } }