diff --git a/BUILD.md b/BUILD.md index d6be0b61fb..db81ecb30d 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,13 +1,13 @@ # General Build Information -*Last Updated on May 17, 2020* +*Last Updated on June 27, 2020* ### OS Specific Build Guides * [Build Windows](BUILD_WIN.md) - complete instructions for Windows. * [Build Linux](BUILD_LINUX.md) - additional instructions for Linux. * [Build OSX](BUILD_OSX.md) - additional instructions for OS X. -* [Build Android](BUILD_ANDROID.md) - additional instructions for Android +* [Build Android](BUILD_ANDROID.md) - additional instructions for Android. ### Dependencies - [git](https://git-scm.com/downloads): >= 1.6 @@ -78,11 +78,11 @@ Where /path/to/directory is the path to a directory where you wish the build fil BUILD_NUMBER // The type of release. - RELEASE_TYPE=PRODUCTION|PR - RELEASE_BUILD=PRODUCTION|PR + RELEASE_TYPE=PRODUCTION|PR|DEV // TODO: What do these do? PRODUCTION_BUILD=0|1 + PR_BUILD=0|1 STABLE_BUILD=0|1 // TODO: What do these do? @@ -150,4 +150,4 @@ The following build options can be used when running CMake #### Devices You can support external input/output devices such as Leap Motion, MIDI, and more by adding each individual SDK in the visible building path. Refer to the readme file available in each device folder in [interface/external/](interface/external) for the detailed explanation of the requirements to use the device. - \ No newline at end of file + diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index a6ab382781..4c4fcbf2dd 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -370,16 +370,18 @@ void EntityServer::entityFilterAdded(EntityItemID id, bool success) { void EntityServer::nodeAdded(SharedNodePointer node) { EntityTreePointer tree = std::static_pointer_cast(_tree); - tree->knowAvatarID(node->getUUID()); + if (tree) { + tree->knowAvatarID(node->getUUID()); + } OctreeServer::nodeAdded(node); } void EntityServer::nodeKilled(SharedNodePointer node) { EntityTreePointer tree = std::static_pointer_cast(_tree); - tree->withWriteLock([&] { + if (tree) { tree->deleteDescendantsOfAvatar(node->getUUID()); - }); - tree->forgetAvatarID(node->getUUID()); + tree->forgetAvatarID(node->getUUID()); + } OctreeServer::nodeKilled(node); } diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 284dd344e7..3ae92651b8 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -247,7 +247,7 @@ "name": "standard_permissions", "type": "table", "label": "Domain-Wide User Permissions", - "help": "Indicate which types of users can have which domain-wide permissions.", + "help": "Indicate which types of users can have which domain-wide permissions.", "caption": "Standard Permissions", "can_add_new_rows": false, "groups": [ @@ -256,7 +256,7 @@ "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 11 } ], @@ -337,7 +337,7 @@ }, { "name": "id_can_get_and_set_private_user_data", - "label": "Can Get and Set Private User Data", + "label": "Get and Set Private User Data", "type": "checkbox", "editable": true, "default": false @@ -392,7 +392,7 @@ "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 11 } ], @@ -498,7 +498,7 @@ }, { "name": "id_can_get_and_set_private_user_data", - "label": "Can Get and Set Private User Data", + "label": "Get and Set Private User Data", "type": "checkbox", "editable": true, "default": false @@ -520,7 +520,7 @@ "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 11 } ], @@ -623,7 +623,7 @@ }, { "name": "id_can_get_and_set_private_user_data", - "label": "Can Get and Set Private User Data", + "label": "Get and Set Private User Data", "type": "checkbox", "editable": true, "default": false @@ -641,7 +641,7 @@ "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 11 } ], @@ -722,7 +722,7 @@ }, { "name": "id_can_get_and_set_private_user_data", - "label": "Can Get and Set Private User Data", + "label": "Get and Set Private User Data", "type": "checkbox", "editable": true, "default": false @@ -740,7 +740,7 @@ "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 11 } ], @@ -821,7 +821,7 @@ }, { "name": "id_can_get_and_set_private_user_data", - "label": "Can Get and Set Private User Data", + "label": "Get and Set Private User Data", "type": "checkbox", "editable": true, "default": false @@ -839,7 +839,7 @@ "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 11 } ], @@ -920,7 +920,7 @@ }, { "name": "id_can_get_and_set_private_user_data", - "label": "Can Get and Set Private User Data", + "label": "Get and Set Private User Data", "type": "checkbox", "editable": true, "default": false @@ -938,7 +938,7 @@ "span": 1 }, { - "label": "Permissions ?", + "label": "Permissions ?", "span": 11 } ], @@ -1019,7 +1019,7 @@ }, { "name": "id_can_get_and_set_private_user_data", - "label": "Can Get and Set Private User Data", + "label": "Get and Set Private User Data", "type": "checkbox", "editable": true, "default": false diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 05ddcd5bd3..fccd6b50c5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3857,6 +3857,11 @@ void Application::showHelp() { //InfoView::show(INFO_HELP_PATH, false, queryString.toString()); } +void Application::gotoTutorial() { + const QString TUTORIAL_ADDRESS = "file:///~/serverless/tutorial.json"; + DependencyManager::get()->handleLookupString(TUTORIAL_ADDRESS); +} + void Application::resizeEvent(QResizeEvent* event) { resizeGL(); } @@ -4065,7 +4070,7 @@ std::map Application::prepareServerlessDomainContents(QUrl dom bool success = tmpTree->readFromByteArray(domainURL.toString(), data); if (success) { tmpTree->reaverageOctreeElements(); - tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), 0, 0, 0); + tmpTree->sendEntities(&_entityEditSender, getEntities()->getTree(), "domain", 0, 0, 0); } std::map namedPaths = tmpTree->getNamedPaths(); @@ -5545,8 +5550,8 @@ bool Application::importEntities(const QString& urlOrFilename, const bool isObse return success; } -QVector Application::pasteEntities(float x, float y, float z) { - return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), x, y, z); +QVector Application::pasteEntities(const QString& entityHostType, float x, float y, float z) { + return _entityClipboard->sendEntities(&_entityEditSender, getEntities()->getTree(), entityHostType, x, y, z); } void Application::init() { diff --git a/interface/src/Application.h b/interface/src/Application.h index 684ff6bdaa..3d4e6873a8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -375,7 +375,7 @@ signals: void awayStateWhenFocusLostInVRChanged(bool enabled); public slots: - QVector pasteEntities(float x, float y, float z); + QVector pasteEntities(const QString& entityHostType, float x, float y, float z); bool exportEntities(const QString& filename, const QVector& entityIDs, const glm::vec3* givenOffset = nullptr); bool exportEntities(const QString& filename, float x, float y, float z, float scale); bool importEntities(const QString& url, const bool isObservable = true, const qint64 callerId = -1); @@ -425,6 +425,7 @@ public slots: #endif static void showHelp(); + static void gotoTutorial(); void cycleCamera(); void cameraModeChanged(); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index a1bb670837..0ed5f67ea0 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -816,6 +816,8 @@ Menu::Menu() { addActionToQMenuAndActionHash(helpMenu, "Controls Reference", 0, qApp, SLOT(showHelp())); + addActionToQMenuAndActionHash(helpMenu, "Tutorial", 0, qApp, SLOT(gotoTutorial())); + helpMenu->addSeparator(); // Help > Release Notes diff --git a/interface/src/scripting/ClipboardScriptingInterface.cpp b/interface/src/scripting/ClipboardScriptingInterface.cpp index c0a6b64421..af7ac8165b 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.cpp +++ b/interface/src/scripting/ClipboardScriptingInterface.cpp @@ -60,10 +60,11 @@ bool ClipboardScriptingInterface::importEntities( return retVal; } -QVector ClipboardScriptingInterface::pasteEntities(glm::vec3 position) { +QVector ClipboardScriptingInterface::pasteEntities(glm::vec3 position, const QString& entityHostType) { QVector retVal; BLOCKING_INVOKE_METHOD(qApp, "pasteEntities", Q_RETURN_ARG(QVector, retVal), + Q_ARG(const QString&, entityHostType), Q_ARG(float, position.x), Q_ARG(float, position.y), Q_ARG(float, position.z)); diff --git a/interface/src/scripting/ClipboardScriptingInterface.h b/interface/src/scripting/ClipboardScriptingInterface.h index 9e72d9ea15..9660b2158b 100644 --- a/interface/src/scripting/ClipboardScriptingInterface.h +++ b/interface/src/scripting/ClipboardScriptingInterface.h @@ -117,10 +117,11 @@ public: * Pastes the contents of the clipboard into the domain. * @function Clipboard.pasteEntities * @param {Vec3} position - The position to paste the clipboard contents at. + * @param {Entities.EntityHostType} [entityHostType="domain"] - The type of entities to create. * @returns {Uuid[]} The IDs of the new entities that were created as a result of the paste operation. If entities couldn't * be created then an empty array is returned. */ - Q_INVOKABLE QVector pasteEntities(glm::vec3 position); + Q_INVOKABLE QVector pasteEntities(glm::vec3 position, const QString& entityHostType = "domain"); }; #endif // hifi_ClipboardScriptingInterface_h diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index 621323575f..2fd52ee036 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -26,6 +26,9 @@ static const int MAX_TARGET_MARKERS = 30; static const float JOINT_CHAIN_INTERP_TIME = 0.5f; +static QTime debounceJointWarningsClock; +static const int JOINT_WARNING_DEBOUNCE_TIME = 30000; // 30 seconds + static void lookupJointInfo(const AnimInverseKinematics::JointChainInfo& jointChainInfo, int indexA, int indexB, const AnimInverseKinematics::JointInfo** jointInfoA, @@ -91,6 +94,7 @@ AnimInverseKinematics::IKTargetVar::IKTargetVar(const IKTargetVar& orig) : } AnimInverseKinematics::AnimInverseKinematics(const QString& id) : AnimNode(AnimNode::Type::InverseKinematics, id) { + debounceJointWarningsClock.start(); } AnimInverseKinematics::~AnimInverseKinematics() { @@ -158,6 +162,14 @@ void AnimInverseKinematics::setTargetVars(const QString& jointName, const QStrin } } +bool debounceJointWarnings() { + if (debounceJointWarningsClock.elapsed() >= JOINT_WARNING_DEBOUNCE_TIME) { + debounceJointWarningsClock.restart(); + return true; + } + return false; +} + void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector& targets, const AnimPoseVec& underPoses) { _hipsTargetIndex = -1; @@ -172,7 +184,7 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std:: if (jointIndex >= 0) { // this targetVar has a valid joint --> cache the indices targetVar.jointIndex = jointIndex; - } else { + } else if (debounceJointWarnings()) { qCWarning(animation) << "AnimInverseKinematics could not find jointName" << targetVar.jointName << "in skeleton"; } } diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index f34eb85230..bc56781924 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -199,7 +199,7 @@ float importanceSample3DDimension(float startDim) { return dimension; } -ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties, +ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createParticle(const Transform& baseTransform, const particle::Properties& particleProperties, const ShapeType& shapeType, const GeometryResource::Pointer& geometryResource, const TriangleInfo& triangleInfo) { CpuParticle particle; @@ -217,7 +217,7 @@ ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createPa const auto& polarFinish = particleProperties.polar.finish; particle.seed = randFloatInRange(-1.0f, 1.0f); - particle.expiration = now + (uint64_t)(particleProperties.lifespan * USECS_PER_SECOND); + particle.expiration = (uint64_t)(particleProperties.lifespan * USECS_PER_SECOND); particle.relativePosition = glm::vec3(0.0f); particle.basePosition = baseTransform.getTranslation(); @@ -403,7 +403,7 @@ void ParticleEffectEntityRenderer::stepSimulation() { computeTriangles(geometryResource->getHFMModel()); } // emit particle - _cpuParticles.push_back(createParticle(now, modelTransform, particleProperties, shapeType, geometryResource, _triangleInfo)); + _cpuParticles.push_back(createParticle(modelTransform, particleProperties, shapeType, geometryResource, _triangleInfo)); _timeUntilNextEmit = emitInterval; if (emitInterval < timeRemaining) { timeRemaining -= emitInterval; @@ -415,7 +415,7 @@ void ParticleEffectEntityRenderer::stepSimulation() { } // Kill any particles that have expired or are over the max size - while (_cpuParticles.size() > particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration <= now)) { + while (_cpuParticles.size() > particleProperties.maxParticles || (!_cpuParticles.empty() && _cpuParticles.front().expiration == 0)) { _cpuParticles.pop_front(); } @@ -428,6 +428,7 @@ void ParticleEffectEntityRenderer::stepSimulation() { } particle.basePosition = modelTransform.getTranslation(); } + particle.expiration = particle.expiration >= interval ? particle.expiration - interval : 0; particle.integrate(deltaTime); } _prevEmitterShouldTrail = particleProperties.emission.shouldTrail; diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index cc907f2b1d..8a3d8120f5 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -88,7 +88,7 @@ private: glm::mat4 transform; } _triangleInfo; - static CpuParticle createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties, + static CpuParticle createParticle(const Transform& baseTransform, const particle::Properties& particleProperties, const ShapeType& shapeType, const GeometryResource::Pointer& geometryResource, const TriangleInfo& triangleInfo); void stepSimulation(); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 1ce19033e5..61c01b9633 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2233,15 +2233,24 @@ void EntityTree::fixupNeedsParentFixups() { } entity->postParentFixup(); - } else if (getIsServer() || _avatarIDs.contains(entity->getParentID())) { - // this is a child of an avatar, which the entity server will never have - // a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves. - if (!_childrenOfAvatars.contains(entity->getParentID())) { - _childrenOfAvatars[entity->getParentID()] = QSet(); + } else { + bool needsUpdate = getIsServer(); + if (!needsUpdate) { + std::lock_guard lock(_avatarIDsLock); + needsUpdate = _avatarIDs.contains(entity->getParentID()); + } + + if (needsUpdate) { + std::lock_guard lock(_childrenOfAvatarsLock); + // this is a child of an avatar, which the entity server will never have + // a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves. + if (!_childrenOfAvatars.contains(entity->getParentID())) { + _childrenOfAvatars[entity->getParentID()] = QSet(); + } + _childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID(); + doMove = true; + iter.remove(); // and pull it out of the list } - _childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID(); - doMove = true; - iter.remove(); // and pull it out of the list } if (queryAACubeSuccess && doMove) { @@ -2261,8 +2270,19 @@ void EntityTree::fixupNeedsParentFixups() { } } -void EntityTree::deleteDescendantsOfAvatar(QUuid avatarID) { - QHash>::const_iterator itr = _childrenOfAvatars.constFind(avatarID); +void EntityTree::knowAvatarID(const QUuid& avatarID) { + std::lock_guard lock(_avatarIDsLock); + _avatarIDs += avatarID; +} + +void EntityTree::forgetAvatarID(const QUuid& avatarID) { + std::lock_guard lock(_avatarIDsLock); + _avatarIDs -= avatarID; +} + +void EntityTree::deleteDescendantsOfAvatar(const QUuid& avatarID) { + std::lock_guard lock(_childrenOfAvatarsLock); + auto itr = _childrenOfAvatars.find(avatarID); if (itr != _childrenOfAvatars.end()) { if (!itr.value().empty()) { std::vector ids; @@ -2280,8 +2300,10 @@ void EntityTree::deleteDescendantsOfAvatar(QUuid avatarID) { void EntityTree::removeFromChildrenOfAvatars(EntityItemPointer entity) { QUuid avatarID = entity->getParentID(); - if (_childrenOfAvatars.contains(avatarID)) { - _childrenOfAvatars[avatarID].remove(entity->getID()); + std::lock_guard lock(_childrenOfAvatarsLock); + auto itr = _childrenOfAvatars.find(avatarID); + if (itr != _childrenOfAvatars.end()) { + itr.value().remove(entity->getID()); } } @@ -2657,11 +2679,12 @@ QByteArray EntityTree::remapActionDataIDs(QByteArray actionData, QHash EntityTree::sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree, - float x, float y, float z) { + const QString& entityHostType, float x, float y, float z) { SendEntitiesOperationArgs args; args.ourTree = this; args.otherTree = localTree; args.root = glm::vec3(x, y, z); + args.entityHostType = entityHostType; // If this is called repeatedly (e.g., multiple pastes with the same data), the new elements will clash unless we // use new identifiers. We need to keep a map so that we can map parent identifiers correctly. QHash map; @@ -2751,6 +2774,11 @@ bool EntityTree::sendEntitiesOperation(const OctreeElementPointer& element, void EntityItemID newID = getMapped(oldID); EntityItemProperties properties = item->getProperties(); + properties.setEntityHostTypeFromString(args->entityHostType); + if (properties.getEntityHostType() == entity::HostType::AVATAR) { + properties.setOwningAvatarID(AVATAR_SELF_ID); + } + EntityItemID oldParentID = properties.getParentID(); if (oldParentID.isInvalidID()) { // no parent properties.setPosition(properties.getPosition() + args->root); diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 2d5119d626..656673421a 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -40,6 +40,7 @@ public: class SendEntitiesOperationArgs { public: glm::vec3 root; + QString entityHostType; EntityTree* ourTree; EntityTreePointer otherTree; QHash* map; @@ -177,7 +178,7 @@ public: static QByteArray remapActionDataIDs(QByteArray actionData, QHash& map); QVector sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree, - float x, float y, float z); + const QString& entityHostType, float x, float y, float z); void entityChanged(EntityItemPointer entity); @@ -239,9 +240,9 @@ public: Q_INVOKABLE int getJointIndex(const QUuid& entityID, const QString& name) const; Q_INVOKABLE QStringList getJointNames(const QUuid& entityID) const; - void knowAvatarID(QUuid avatarID) { _avatarIDs += avatarID; } - void forgetAvatarID(QUuid avatarID) { _avatarIDs -= avatarID; } - void deleteDescendantsOfAvatar(QUuid avatarID); + void knowAvatarID(const QUuid& avatarID); + void forgetAvatarID(const QUuid& avatarID); + void deleteDescendantsOfAvatar(const QUuid& avatarID); void removeFromChildrenOfAvatars(EntityItemPointer entity); void addToNeedsParentFixupList(EntityItemPointer entity); @@ -364,8 +365,10 @@ protected: QVector _needsParentFixup; // entites with a parentID but no (yet) known parent instance mutable QReadWriteLock _needsParentFixupLock; + std::mutex _avatarIDsLock; // we maintain a list of avatarIDs to notice when an entity is a child of one. QSet _avatarIDs; // IDs of avatars connected to entity server + std::mutex _childrenOfAvatarsLock; QHash> _childrenOfAvatars; // which entities are children of which avatars float _maxTmpEntityLifetime { DEFAULT_MAX_TMP_ENTITY_LIFETIME }; diff --git a/libraries/fbx/src/GLTFSerializer.cpp b/libraries/fbx/src/GLTFSerializer.cpp index a7af5518a9..8234f2b17d 100755 --- a/libraries/fbx/src/GLTFSerializer.cpp +++ b/libraries/fbx/src/GLTFSerializer.cpp @@ -1055,6 +1055,11 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& int indicesAccessorIdx = primitive.indices; + if (indicesAccessorIdx > _file.accessors.size()) { + qWarning(modelformat) << "Indices accessor index is out of bounds for model " << _url; + continue; + } + GLTFAccessor& indicesAccessor = _file.accessors[indicesAccessorIdx]; // Buffers @@ -1093,6 +1098,11 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& foreach(auto &key, keys) { int accessorIdx = primitive.attributes.values[key]; + if (accessorIdx > _file.accessors.size()) { + qWarning(modelformat) << "Accessor index is out of bounds for model " << _url; + continue; + } + GLTFAccessor& accessor = _file.accessors[accessorIdx]; if (key == "POSITION") { @@ -1239,6 +1249,11 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& int v2_index = (indices[n + 1] * 3); int v3_index = (indices[n + 2] * 3); + if (v1_index + 2 >= vertices.size() || v2_index + 2 >= vertices.size() || v3_index + 2 >= vertices.size()) { + qWarning(modelformat) << "Indices out of range for model " << _url; + break; + } + glm::vec3 v1 = glm::vec3(vertices[v1_index], vertices[v1_index + 1], vertices[v1_index + 2]); glm::vec3 v2 = glm::vec3(vertices[v2_index], vertices[v2_index + 1], vertices[v2_index + 2]); glm::vec3 v3 = glm::vec3(vertices[v3_index], vertices[v3_index + 1], vertices[v3_index + 2]); @@ -1333,7 +1348,7 @@ bool GLTFSerializer::buildGeometry(HFMModel& hfmModel, const hifi::VariantHash& } if (validatedIndices.size() == 0) { - qWarning(modelformat) << "Indices out of range for model " << _url; + qWarning(modelformat) << "No valid indices for model " << _url; continue; } diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index 8bdb777f96..148c4f8580 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -249,8 +249,9 @@ public slots: * Takes you to a specified metaverse address. * @function location.handleLookupString * @param {string} address - The address to go to: a "hifi://" address, an IP address (e.g., - * "127.0.0.1" or "localhost"), a domain name, a named path on a domain (starts with - * "/"), a position or position and orientation, or a user (starts with "@"). + * "127.0.0.1" or "localhost"), a file:/// address, a domain name, a named path + * on a domain (starts with "/"), a position or position and orientation, or a user (starts with + * "@"). * @param {boolean} [fromSuggestions=false] - Set to true if the address is obtained from the "Goto" dialog. * Helps ensure that user's location history is correctly maintained. */ diff --git a/libraries/shared/src/NumericalConstants.h b/libraries/shared/src/NumericalConstants.h index 8377c48960..b7fecfa1e4 100644 --- a/libraries/shared/src/NumericalConstants.h +++ b/libraries/shared/src/NumericalConstants.h @@ -28,8 +28,8 @@ const float ARCSECONDS_PER_ARCMINUTE = 60.0f; const float ARCSECONDS_PER_DEGREE = ARCMINUTES_PER_DEGREE * ARCSECONDS_PER_ARCMINUTE; const float EPSILON = 0.000001f; //smallish positive number - used as margin of error for some computations -const float SQUARE_ROOT_OF_2 = (float)sqrt(2.0f); -const float SQUARE_ROOT_OF_3 = (float)sqrt(3.0f); +const float SQUARE_ROOT_OF_2 = 1.414214f; +const float SQUARE_ROOT_OF_3 = 1.732051f; const float METERS_PER_DECIMETER = 0.1f; const float METERS_PER_CENTIMETER = 0.01f; const float METERS_PER_MILLIMETER = 0.001f; diff --git a/scripts/communityModules/chat/FloofChat.html b/scripts/communityScripts/chat/FloofChat.html similarity index 80% rename from scripts/communityModules/chat/FloofChat.html rename to scripts/communityScripts/chat/FloofChat.html index a1e84e132f..7baac63455 100644 --- a/scripts/communityModules/chat/FloofChat.html +++ b/scripts/communityScripts/chat/FloofChat.html @@ -12,6 +12,7 @@ + @@ -28,11 +29,19 @@
+ +
+ +
@@ -46,6 +55,7 @@