mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 02:03:57 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into 20778-pullFolderFromAndroid
This commit is contained in:
commit
e87d5abbd7
22 changed files with 181 additions and 97 deletions
|
@ -919,6 +919,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<Wallet>();
|
||||
DependencyManager::set<WalletScriptingInterface>();
|
||||
DependencyManager::set<TTSScriptingInterface>();
|
||||
DependencyManager::set<QmlCommerce>();
|
||||
|
||||
DependencyManager::set<FadeEffect>();
|
||||
DependencyManager::set<ResourceRequestObserver>();
|
||||
|
@ -1200,6 +1201,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
connect(&domainHandler, SIGNAL(connectedToDomain(QUrl)), SLOT(updateWindowTitle()));
|
||||
connect(&domainHandler, SIGNAL(disconnectedFromDomain()), SLOT(updateWindowTitle()));
|
||||
connect(&domainHandler, &DomainHandler::disconnectedFromDomain, this, [this]() {
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
if (tabletScriptingInterface) {
|
||||
tabletScriptingInterface->setQmlTabletRoot(SYSTEM_TABLET, nullptr);
|
||||
}
|
||||
getOverlays().deleteOverlay(getTabletScreenID());
|
||||
getOverlays().deleteOverlay(getTabletHomeButtonID());
|
||||
getOverlays().deleteOverlay(getTabletFrameID());
|
||||
|
@ -2598,6 +2603,7 @@ void Application::cleanupBeforeQuit() {
|
|||
DependencyManager::destroy<ContextOverlayInterface>(); // Must be destroyed before TabletScriptingInterface
|
||||
|
||||
// stop QML
|
||||
DependencyManager::destroy<QmlCommerce>();
|
||||
DependencyManager::destroy<TabletScriptingInterface>();
|
||||
DependencyManager::destroy<ToolbarScriptingInterface>();
|
||||
DependencyManager::destroy<OffscreenUi>();
|
||||
|
@ -2886,7 +2892,7 @@ void Application::initializeUi() {
|
|||
Tooltip::registerType();
|
||||
UpdateDialog::registerType();
|
||||
QmlContextCallback commerceCallback = [](QQmlContext* context) {
|
||||
context->setContextProperty("Commerce", new QmlCommerce());
|
||||
context->setContextProperty("Commerce", DependencyManager::get<QmlCommerce>().data());
|
||||
};
|
||||
OffscreenQmlSurface::addWhitelistContextHandler({
|
||||
QUrl{ "hifi/commerce/checkout/Checkout.qml" },
|
||||
|
@ -2911,6 +2917,7 @@ void Application::initializeUi() {
|
|||
QUrl{ "hifi/dialogs/security/SecurityImageChange.qml" },
|
||||
QUrl{ "hifi/dialogs/security/SecurityImageModel.qml" },
|
||||
QUrl{ "hifi/dialogs/security/SecurityImageSelection.qml" },
|
||||
QUrl{ "hifi/tablet/TabletMenu.qml" },
|
||||
}, commerceCallback);
|
||||
QmlContextCallback ttsCallback = [](QQmlContext* context) {
|
||||
context->setContextProperty("TextToSpeech", DependencyManager::get<TTSScriptingInterface>().data());
|
||||
|
@ -8014,8 +8021,7 @@ void Application::openUrl(const QUrl& url) const {
|
|||
if (url.scheme() == URL_SCHEME_HIFI) {
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(url.toString());
|
||||
} else if (url.scheme() == URL_SCHEME_HIFIAPP) {
|
||||
QmlCommerce commerce;
|
||||
commerce.openSystemApp(url.path());
|
||||
DependencyManager::get<QmlCommerce>()->openSystemApp(url.path());
|
||||
} else {
|
||||
// address manager did not handle - ask QDesktopServices to handle
|
||||
QDesktopServices::openUrl(url);
|
||||
|
|
|
@ -767,7 +767,7 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
|
|||
auto headBoneSet = _skeletonModel->getCauterizeBoneSet();
|
||||
forEachChild([&](SpatiallyNestablePointer object) {
|
||||
bool isChildOfHead = headBoneSet.find(object->getParentJointIndex()) != headBoneSet.end();
|
||||
if (isChildOfHead) {
|
||||
if (isChildOfHead && !object->hasGrabs()) {
|
||||
// Cauterize or display children of head per head drawing state.
|
||||
updateChildCauterization(object, !_prevShouldDrawHead);
|
||||
object->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||
|
@ -817,7 +817,9 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
|
|||
// and all of its joints, now update our attachements.
|
||||
Avatar::simulateAttachments(deltaTime);
|
||||
relayJointDataToChildren();
|
||||
updateGrabs();
|
||||
if (updateGrabs()) {
|
||||
_cauterizationNeedsUpdate = true;
|
||||
}
|
||||
|
||||
if (!_skeletonModel->hasSkeleton()) {
|
||||
// All the simulation that can be done has been done
|
||||
|
@ -873,9 +875,13 @@ void MyAvatar::simulate(float deltaTime, bool inView) {
|
|||
collisionlessAllowed = zone->getGhostingAllowed();
|
||||
}
|
||||
EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
|
||||
bool force = false;
|
||||
bool iShouldTellServer = true;
|
||||
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||
// we need to update attached queryAACubes in our own local tree so point-select always works
|
||||
// however we don't want to flood the update pipeline with AvatarEntity updates, so we assume
|
||||
// others have all info required to properly update queryAACube of AvatarEntities on their end
|
||||
EntityItemPointer entity = std::dynamic_pointer_cast<EntityItem>(object);
|
||||
bool iShouldTellServer = !(entity && entity->isAvatarEntity());
|
||||
const bool force = false;
|
||||
entityTree->updateEntityQueryAACube(object, packetSender, force, iShouldTellServer);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -22,7 +22,9 @@
|
|||
#include <ui/TabletScriptingInterface.h>
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
|
||||
QmlCommerce::QmlCommerce() {
|
||||
QmlCommerce::QmlCommerce() :
|
||||
_appsPath(PathUtils::getAppDataPath() + "Apps/")
|
||||
{
|
||||
auto ledger = DependencyManager::get<Ledger>();
|
||||
auto wallet = DependencyManager::get<Wallet>();
|
||||
connect(ledger.data(), &Ledger::buyResult, this, &QmlCommerce::buyResult);
|
||||
|
@ -44,22 +46,18 @@ QmlCommerce::QmlCommerce() {
|
|||
|
||||
auto accountManager = DependencyManager::get<AccountManager>();
|
||||
connect(accountManager.data(), &AccountManager::usernameChanged, this, [&]() { setPassphrase(""); });
|
||||
|
||||
_appsPath = PathUtils::getAppDataPath() + "Apps/";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void QmlCommerce::openSystemApp(const QString& appName) {
|
||||
static QMap<QString, QString> systemApps {
|
||||
static const QMap<QString, QString> systemApps {
|
||||
{"GOTO", "hifi/tablet/TabletAddressDialog.qml"},
|
||||
{"PEOPLE", "hifi/Pal.qml"},
|
||||
{"WALLET", "hifi/commerce/wallet/Wallet.qml"},
|
||||
{"MARKET", "/marketplace.html"}
|
||||
};
|
||||
|
||||
static QMap<QString, QString> systemInject{
|
||||
static const QMap<QString, QString> systemInject{
|
||||
{"MARKET", "/scripts/system/html/js/marketplacesInject.js"}
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
|
||||
#include <QPixmap>
|
||||
|
||||
class QmlCommerce : public QObject {
|
||||
#include <DependencyManager.h>
|
||||
|
||||
class QmlCommerce : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
@ -98,7 +100,7 @@ protected:
|
|||
Q_INVOKABLE void updateItem(const QString& certificateId);
|
||||
|
||||
private:
|
||||
QString _appsPath;
|
||||
const QString _appsPath;
|
||||
};
|
||||
|
||||
#endif // hifi_QmlCommerce_h
|
||||
|
|
|
@ -134,13 +134,6 @@ void Web3DOverlay::destroyWebSurface() {
|
|||
|
||||
QQuickItem* rootItem = _webSurface->getRootItem();
|
||||
|
||||
if (rootItem && rootItem->objectName() == "tabletRoot") {
|
||||
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
|
||||
if (tabletScriptingInterface) {
|
||||
tabletScriptingInterface->setQmlTabletRoot("com.highfidelity.interface.tablet.system", nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Fix for crash in QtWebEngineCore when rapidly switching domains
|
||||
// Call stop on the QWebEngineView before destroying OffscreenQMLSurface.
|
||||
if (rootItem) {
|
||||
|
|
|
@ -1984,11 +1984,10 @@ void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
|
|||
data.rotation = !_sendNetworkNode ? _internalPoseSet._absolutePoses[i].rot() : _networkPoseSet._absolutePoses[i].rot();
|
||||
data.rotationIsDefaultPose = isEqual(data.rotation, defaultAbsRot);
|
||||
|
||||
// translations are in relative frame but scaled so that they are in meters,
|
||||
// instead of model units.
|
||||
// translations are in relative frame.
|
||||
glm::vec3 defaultRelTrans = _animSkeleton->getRelativeDefaultPose(i).trans();
|
||||
glm::vec3 currentRelTrans = _sendNetworkNode ? _networkPoseSet._relativePoses[i].trans() : _internalPoseSet._relativePoses[i].trans();
|
||||
data.translation = geometryToRigScale * currentRelTrans;
|
||||
data.translation = currentRelTrans;
|
||||
data.translationIsDefaultPose = isEqual(currentRelTrans, defaultRelTrans);
|
||||
} else {
|
||||
data.translationIsDefaultPose = true;
|
||||
|
@ -2015,7 +2014,6 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
|||
std::vector<glm::quat> rotations;
|
||||
rotations.reserve(numJoints);
|
||||
const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform));
|
||||
const glm::vec3 rigToGeometryScale(extractScale(_rigToGeometryTransform));
|
||||
|
||||
for (int i = 0; i < numJoints; i++) {
|
||||
const JointData& data = jointDataVec.at(i);
|
||||
|
@ -2041,8 +2039,8 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
|||
if (data.translationIsDefaultPose) {
|
||||
_internalPoseSet._relativePoses[i].trans() = relativeDefaultPoses[i].trans();
|
||||
} else {
|
||||
// JointData translations are in scaled relative-frame so we scale back to regular relative-frame
|
||||
_internalPoseSet._relativePoses[i].trans() = rigToGeometryScale * data.translation;
|
||||
// JointData translations are in relative-frame
|
||||
_internalPoseSet._relativePoses[i].trans() = data.translation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,8 +324,8 @@ void Avatar::removeAvatarEntitiesFromTree() {
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::updateGrabs() {
|
||||
|
||||
bool Avatar::updateGrabs() {
|
||||
bool grabAddedOrRemoved = false;
|
||||
// update the Grabs according to any changes in _avatarGrabData
|
||||
_avatarGrabsLock.withWriteLock([&] {
|
||||
if (_avatarGrabDataChanged) {
|
||||
|
@ -385,6 +385,7 @@ void Avatar::updateGrabs() {
|
|||
entityTree->updateEntityQueryAACube(target, packetSender, force, iShouldTellServer);
|
||||
});
|
||||
}
|
||||
grabAddedOrRemoved = true;
|
||||
}
|
||||
_avatarGrabs.remove(grabID);
|
||||
_changedAvatarGrabs.remove(grabID);
|
||||
|
@ -402,9 +403,11 @@ void Avatar::updateGrabs() {
|
|||
target->addGrab(grab);
|
||||
// only clear this entry from the _changedAvatarGrabs if we found the entity.
|
||||
changeItr.remove();
|
||||
grabAddedOrRemoved = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
return grabAddedOrRemoved;
|
||||
}
|
||||
|
||||
void Avatar::accumulateGrabPositions(std::map<QUuid, GrabLocationAccumulator>& grabAccumulators) {
|
||||
|
|
|
@ -538,7 +538,7 @@ protected:
|
|||
|
||||
// protected methods...
|
||||
bool isLookingAtMe(AvatarSharedPointer avatar) const;
|
||||
void updateGrabs();
|
||||
bool updateGrabs();
|
||||
void relayJointDataToChildren();
|
||||
|
||||
void fade(render::Transaction& transaction, render::Transition::Type type);
|
||||
|
|
|
@ -54,7 +54,8 @@ using namespace std;
|
|||
|
||||
const QString AvatarData::FRAME_NAME = "com.highfidelity.recording.AvatarData";
|
||||
|
||||
static const int TRANSLATION_COMPRESSION_RADIX = 12;
|
||||
static const int TRANSLATION_COMPRESSION_RADIX = 14;
|
||||
static const int FAUX_JOINT_COMPRESSION_RADIX = 12;
|
||||
static const int SENSOR_TO_WORLD_SCALE_RADIX = 10;
|
||||
static const float AUDIO_LOUDNESS_SCALE = 1024.0f;
|
||||
static const float DEFAULT_AVATAR_DENSITY = 1000.0f; // density of water
|
||||
|
@ -73,6 +74,7 @@ size_t AvatarDataPacket::maxJointDataSize(size_t numJoints, bool hasGrabJoints)
|
|||
totalSize += validityBitsSize; // Orientations mask
|
||||
totalSize += numJoints * sizeof(SixByteQuat); // Orientations
|
||||
totalSize += validityBitsSize; // Translations mask
|
||||
totalSize += sizeof(float); // maxTranslationDimension
|
||||
totalSize += numJoints * sizeof(SixByteTrans); // Translations
|
||||
|
||||
size_t NUM_FAUX_JOINT = 2;
|
||||
|
@ -85,6 +87,23 @@ size_t AvatarDataPacket::maxJointDataSize(size_t numJoints, bool hasGrabJoints)
|
|||
return totalSize;
|
||||
}
|
||||
|
||||
size_t AvatarDataPacket::minJointDataSize(size_t numJoints) {
|
||||
const size_t validityBitsSize = calcBitVectorSize((int)numJoints);
|
||||
|
||||
size_t totalSize = sizeof(uint8_t); // numJoints
|
||||
|
||||
totalSize += validityBitsSize; // Orientations mask
|
||||
// assume no valid rotations
|
||||
totalSize += validityBitsSize; // Translations mask
|
||||
totalSize += sizeof(float); // maxTranslationDimension
|
||||
// assume no valid translations
|
||||
|
||||
size_t NUM_FAUX_JOINT = 2;
|
||||
totalSize += NUM_FAUX_JOINT * (sizeof(SixByteQuat) + sizeof(SixByteTrans)); // faux joints
|
||||
|
||||
return totalSize;
|
||||
}
|
||||
|
||||
size_t AvatarDataPacket::maxJointDefaultPoseFlagsSize(size_t numJoints) {
|
||||
const size_t bitVectorSize = calcBitVectorSize((int)numJoints);
|
||||
size_t totalSize = sizeof(uint8_t); // numJoints
|
||||
|
@ -611,13 +630,24 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
assert(numJoints <= 255);
|
||||
const int jointBitVectorSize = calcBitVectorSize(numJoints);
|
||||
|
||||
// Start joints if room for at least the faux joints.
|
||||
IF_AVATAR_SPACE(PACKET_HAS_JOINT_DATA, 1 + 2 * jointBitVectorSize + AvatarDataPacket::FAUX_JOINTS_SIZE) {
|
||||
// include jointData if there is room for the most minimal section. i.e. no translations or rotations.
|
||||
IF_AVATAR_SPACE(PACKET_HAS_JOINT_DATA, AvatarDataPacket::minJointDataSize(numJoints)) {
|
||||
// Allow for faux joints + translation bit-vector:
|
||||
const ptrdiff_t minSizeForJoint = sizeof(AvatarDataPacket::SixByteQuat)
|
||||
+ jointBitVectorSize + AvatarDataPacket::FAUX_JOINTS_SIZE;
|
||||
auto startSection = destinationBuffer;
|
||||
|
||||
// compute maxTranslationDimension before we send any joint data.
|
||||
float maxTranslationDimension = 0.001f;
|
||||
for (int i = sendStatus.rotationsSent; i < numJoints; ++i) {
|
||||
const JointData& data = jointData[i];
|
||||
if (!data.translationIsDefaultPose) {
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.x), maxTranslationDimension);
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.y), maxTranslationDimension);
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.z), maxTranslationDimension);
|
||||
}
|
||||
}
|
||||
|
||||
// joint rotation data
|
||||
*destinationBuffer++ = (uint8_t)numJoints;
|
||||
|
||||
|
@ -684,9 +714,11 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
memset(destinationBuffer, 0, jointBitVectorSize);
|
||||
destinationBuffer += jointBitVectorSize; // Move pointer past the validity bytes
|
||||
|
||||
// write maxTranslationDimension
|
||||
AVATAR_MEMCPY(maxTranslationDimension);
|
||||
|
||||
float minTranslation = (distanceAdjust && cullSmallChanges) ? getDistanceBasedMinTranslationDistance(viewerPosition) : AVATAR_MIN_TRANSLATION;
|
||||
|
||||
float maxTranslationDimension = 0.0;
|
||||
i = sendStatus.translationsSent;
|
||||
for (; i < numJoints; ++i) {
|
||||
const JointData& data = joints[i];
|
||||
|
@ -700,12 +732,8 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
#ifdef WANT_DEBUG
|
||||
translationSentCount++;
|
||||
#endif
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.x), maxTranslationDimension);
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.y), maxTranslationDimension);
|
||||
maxTranslationDimension = glm::max(fabsf(data.translation.z), maxTranslationDimension);
|
||||
|
||||
destinationBuffer +=
|
||||
packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX);
|
||||
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, data.translation / maxTranslationDimension,
|
||||
TRANSLATION_COMPRESSION_RADIX);
|
||||
|
||||
if (sentJoints) {
|
||||
sentJoints[i].translation = data.translation;
|
||||
|
@ -727,12 +755,12 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
Transform controllerLeftHandTransform = Transform(getControllerLeftHandMatrix());
|
||||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerLeftHandTransform.getRotation());
|
||||
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerLeftHandTransform.getTranslation(),
|
||||
TRANSLATION_COMPRESSION_RADIX);
|
||||
FAUX_JOINT_COMPRESSION_RADIX);
|
||||
|
||||
Transform controllerRightHandTransform = Transform(getControllerRightHandMatrix());
|
||||
destinationBuffer += packOrientationQuatToSixBytes(destinationBuffer, controllerRightHandTransform.getRotation());
|
||||
destinationBuffer += packFloatVec3ToSignedTwoByteFixed(destinationBuffer, controllerRightHandTransform.getTranslation(),
|
||||
TRANSLATION_COMPRESSION_RADIX);
|
||||
FAUX_JOINT_COMPRESSION_RADIX);
|
||||
|
||||
IF_AVATAR_SPACE(PACKET_HAS_GRAB_JOINTS, sizeof (AvatarDataPacket::FarGrabJoints)) {
|
||||
// the far-grab joints may range further than 3 meters, so we can't use packFloatVec3ToSignedTwoByteFixed etc
|
||||
|
@ -785,7 +813,7 @@ QByteArray AvatarData::toByteArray(AvatarDataDetail dataDetail, quint64 lastSent
|
|||
outboundDataRateOut->jointDataRate.increment(numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IF_AVATAR_SPACE(PACKET_HAS_JOINT_DEFAULT_POSE_FLAGS, 1 + 2 * jointBitVectorSize) {
|
||||
auto startSection = destinationBuffer;
|
||||
|
||||
|
@ -871,7 +899,7 @@ const unsigned char* unpackFauxJoint(const unsigned char* sourceBuffer, ThreadSa
|
|||
glm::vec3 position;
|
||||
Transform transform;
|
||||
sourceBuffer += unpackOrientationQuatFromSixBytes(sourceBuffer, orientation);
|
||||
sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, position, TRANSLATION_COMPRESSION_RADIX);
|
||||
sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, position, FAUX_JOINT_COMPRESSION_RADIX);
|
||||
transform.setTranslation(position);
|
||||
transform.setRotation(orientation);
|
||||
matrixCache.set(transform.getMatrix());
|
||||
|
@ -1280,6 +1308,12 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
}
|
||||
} // 1 + bytesOfValidity bytes
|
||||
|
||||
// read maxTranslationDimension
|
||||
float maxTranslationDimension;
|
||||
PACKET_READ_CHECK(JointMaxTranslationDimension, sizeof(float));
|
||||
memcpy(&maxTranslationDimension, sourceBuffer, sizeof(float));
|
||||
sourceBuffer += sizeof(float);
|
||||
|
||||
// each joint translation component is stored in 6 bytes.
|
||||
const int COMPRESSED_TRANSLATION_SIZE = 6;
|
||||
PACKET_READ_CHECK(JointTranslation, numValidJointTranslations * COMPRESSED_TRANSLATION_SIZE);
|
||||
|
@ -1288,6 +1322,7 @@ int AvatarData::parseDataFromBuffer(const QByteArray& buffer) {
|
|||
JointData& data = _jointData[i];
|
||||
if (validTranslations[i]) {
|
||||
sourceBuffer += unpackFloatVec3FromSignedTwoByteFixed(sourceBuffer, data.translation, TRANSLATION_COMPRESSION_RADIX);
|
||||
data.translation *= maxTranslationDimension;
|
||||
_hasNewJointData = true;
|
||||
data.translationIsDefaultPose = false;
|
||||
}
|
||||
|
|
|
@ -277,8 +277,8 @@ namespace AvatarDataPacket {
|
|||
uint8_t rotationValidityBits[ceil(numJoints / 8)]; // one bit per joint, if true then a compressed rotation follows.
|
||||
SixByteQuat rotation[numValidRotations]; // encodeded and compressed by packOrientationQuatToSixBytes()
|
||||
uint8_t translationValidityBits[ceil(numJoints / 8)]; // one bit per joint, if true then a compressed translation follows.
|
||||
SixByteTrans translation[numValidTranslations]; // encodeded and compressed by packFloatVec3ToSignedTwoByteFixed()
|
||||
|
||||
float maxTranslationDimension; // used to normalize fixed point translation values.
|
||||
SixByteTrans translation[numValidTranslations]; // normalized and compressed by packFloatVec3ToSignedTwoByteFixed()
|
||||
SixByteQuat leftHandControllerRotation;
|
||||
SixByteTrans leftHandControllerTranslation;
|
||||
SixByteQuat rightHandControllerRotation;
|
||||
|
@ -286,6 +286,7 @@ namespace AvatarDataPacket {
|
|||
};
|
||||
*/
|
||||
size_t maxJointDataSize(size_t numJoints, bool hasGrabJoints);
|
||||
size_t minJointDataSize(size_t numJoints);
|
||||
|
||||
/*
|
||||
struct JointDefaultPoseFlags {
|
||||
|
|
|
@ -841,10 +841,14 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* @property {number} priority=0 - The priority for applying the material to its parent. Only the highest priority material is
|
||||
* applied, with materials of the same priority randomly assigned. Materials that come with the model have a priority of
|
||||
* <code>0</code>.
|
||||
* @property {string|number} parentMaterialName="0" - Selects the submesh or submeshes within the parent to apply the material
|
||||
* to. If in the format <code>"mat::string"</code>, all submeshes with material name <code>"string"</code> are replaced.
|
||||
* Otherwise the property value is parsed as an unsigned integer, specifying the mesh index to modify. Invalid values are
|
||||
* parsed to <code>0</code>.
|
||||
* @property {string} parentMaterialName="0" - Selects the mesh part or parts within the parent to which to apply the material.
|
||||
* If in the format <code>"mat::string"</code>, all mesh parts with material name <code>"string"</code> are replaced.
|
||||
* Otherwise the property value is parsed as an unsigned integer, specifying the mesh part index to modify. If <code>"all"</code>,
|
||||
* all mesh parts will be replaced. If an array (starts with <code>"["</code> and ends with <code>"]"</code>), the string will be
|
||||
* split at each <code>","</code> and each element will be parsed as either a number or a string if it starts with
|
||||
* <code>"mat::"</code>. In other words, <code>"[0,1,mat::string,mat::string2]"</code> will replace mesh parts 0 and 1, and any
|
||||
* mesh parts with material <code>"string"</code> or <code>"string2"</code>. Do not put spaces around the commas. Invalid values
|
||||
* are parsed to <code>0</code>.
|
||||
* @property {string} materialMappingMode="uv" - How the material is mapped to the entity. Either <code>"uv"</code> or
|
||||
* <code>"projected"</code>. In "uv" mode, the material will be evaluated within the UV space of the mesh it is applied to. In
|
||||
* "projected" mode, the 3D transform of the Material Entity will be used to evaluate the texture coordinates for the material.
|
||||
|
|
|
@ -3008,8 +3008,8 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object,
|
|||
// if the queryBox has changed, tell the entity-server
|
||||
EntityItemPointer entity = std::dynamic_pointer_cast<EntityItem>(object);
|
||||
if (entity) {
|
||||
bool tellServerThis = tellServer && (entity->getEntityHostType() != entity::HostType::AVATAR);
|
||||
if ((entity->updateQueryAACube() || force)) {
|
||||
// NOTE: we rely on side-effects of the entity->updateQueryAACube() call in the following if() conditional:
|
||||
if (entity->updateQueryAACube() || force) {
|
||||
bool success;
|
||||
AACube newCube = entity->getQueryAACube(success);
|
||||
if (success) {
|
||||
|
@ -3017,7 +3017,7 @@ void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object,
|
|||
}
|
||||
// send an edit packet to update the entity-server about the queryAABox. We do this for domain-hosted
|
||||
// entities as well as for avatar-entities; the packet-sender will route the update accordingly
|
||||
if (tellServerThis && packetSender && (entity->isDomainEntity() || entity->isAvatarEntity())) {
|
||||
if (tellServer && packetSender && (entity->isDomainEntity() || entity->isAvatarEntity())) {
|
||||
quint64 now = usecTimestampNow();
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
properties.setQueryAACubeDirty();
|
||||
|
|
|
@ -38,10 +38,10 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
|
||||
case PacketType::AvatarIdentity:
|
||||
case PacketType::AvatarData:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::CollisionFlag);
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SendMaxTranslationDimension);
|
||||
case PacketType::BulkAvatarData:
|
||||
case PacketType::KillAvatar:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::FasterAvatarEntities);
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SendMaxTranslationDimension);
|
||||
case PacketType::MessagesData:
|
||||
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
|
||||
// ICE packets
|
||||
|
|
|
@ -312,7 +312,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
|||
GrabTraits,
|
||||
CollisionFlag,
|
||||
AvatarTraitsAck,
|
||||
FasterAvatarEntities
|
||||
FasterAvatarEntities,
|
||||
SendMaxTranslationDimension
|
||||
};
|
||||
|
||||
enum class DomainConnectRequestVersion : PacketVersion {
|
||||
|
|
|
@ -1486,29 +1486,56 @@ bool Model::isRenderable() const {
|
|||
return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty());
|
||||
}
|
||||
|
||||
std::vector<unsigned int> Model::getMeshIDsFromMaterialID(QString parentMaterialName) {
|
||||
// try to find all meshes with materials that match parentMaterialName as a string
|
||||
// if none, return parentMaterialName as a uint
|
||||
std::vector<unsigned int> toReturn;
|
||||
const QString MATERIAL_NAME_PREFIX = "mat::";
|
||||
if (parentMaterialName.startsWith(MATERIAL_NAME_PREFIX)) {
|
||||
parentMaterialName.replace(0, MATERIAL_NAME_PREFIX.size(), QString(""));
|
||||
for (unsigned int i = 0; i < (unsigned int)_modelMeshMaterialNames.size(); i++) {
|
||||
if (_modelMeshMaterialNames[i] == parentMaterialName.toStdString()) {
|
||||
toReturn.push_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::set<unsigned int> Model::getMeshIDsFromMaterialID(QString parentMaterialName) {
|
||||
std::set<unsigned int> toReturn;
|
||||
|
||||
if (toReturn.empty()) {
|
||||
toReturn.push_back(parentMaterialName.toUInt());
|
||||
const QString all("all");
|
||||
if (parentMaterialName == all) {
|
||||
for (unsigned int i = 0; i < (unsigned int)_modelMeshRenderItemIDs.size(); i++) {
|
||||
toReturn.insert(i);
|
||||
}
|
||||
} else if (!parentMaterialName.isEmpty()) {
|
||||
auto parseFunc = [this, &toReturn] (QString& target) {
|
||||
if (target.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// if target starts with "mat::", try to find all meshes with materials that match target as a string
|
||||
// otherwise, return target as a uint
|
||||
const QString MATERIAL_NAME_PREFIX("mat::");
|
||||
if (target.startsWith(MATERIAL_NAME_PREFIX)) {
|
||||
std::string targetStdString = target.replace(0, MATERIAL_NAME_PREFIX.size(), "").toStdString();
|
||||
for (unsigned int i = 0; i < (unsigned int)_modelMeshMaterialNames.size(); i++) {
|
||||
if (_modelMeshMaterialNames[i] == targetStdString) {
|
||||
toReturn.insert(i);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
toReturn.insert(target.toUInt());
|
||||
};
|
||||
|
||||
if (parentMaterialName.length() > 2 && parentMaterialName.startsWith("[") && parentMaterialName.endsWith("]")) {
|
||||
QStringList list = parentMaterialName.split(",", QString::SkipEmptyParts);
|
||||
for (int i = 0; i < list.length(); i++) {
|
||||
auto& target = list[i];
|
||||
if (i == 0) {
|
||||
target = target.replace(0, 1, "");
|
||||
}
|
||||
if (i == list.length() - 1) {
|
||||
target = target.replace(target.length() - 1, 1, "");
|
||||
}
|
||||
parseFunc(target);
|
||||
}
|
||||
} else {
|
||||
parseFunc(parentMaterialName);
|
||||
}
|
||||
}
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
void Model::addMaterial(graphics::MaterialLayer material, const std::string& parentMaterialName) {
|
||||
std::vector<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str()));
|
||||
std::set<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str()));
|
||||
render::Transaction transaction;
|
||||
for (auto shapeID : shapeIDs) {
|
||||
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
||||
|
@ -1531,7 +1558,7 @@ void Model::addMaterial(graphics::MaterialLayer material, const std::string& par
|
|||
}
|
||||
|
||||
void Model::removeMaterial(graphics::MaterialPointer material, const std::string& parentMaterialName) {
|
||||
std::vector<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str()));
|
||||
std::set<unsigned int> shapeIDs = getMeshIDsFromMaterialID(QString(parentMaterialName.c_str()));
|
||||
render::Transaction transaction;
|
||||
for (auto shapeID : shapeIDs) {
|
||||
if (shapeID < _modelMeshRenderItemIDs.size()) {
|
||||
|
|
|
@ -513,7 +513,7 @@ private:
|
|||
|
||||
void calculateTextureInfo();
|
||||
|
||||
std::vector<unsigned int> getMeshIDsFromMaterialID(QString parentMaterialName);
|
||||
std::set<unsigned int> getMeshIDsFromMaterialID(QString parentMaterialName);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(ModelPointer)
|
||||
|
|
|
@ -14,7 +14,7 @@ public:
|
|||
};
|
||||
|
||||
// Used by the avatar mixer to describe a single joint
|
||||
// Translations relative to their parent and are in meters.
|
||||
// Translations relative to their parent joint
|
||||
// Rotations are absolute (i.e. not relative to parent) and are in rig space.
|
||||
class JointData {
|
||||
public:
|
||||
|
|
|
@ -82,15 +82,18 @@ private:
|
|||
}
|
||||
|
||||
#ifdef OCULUS_APP_ID
|
||||
if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
|
||||
if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) {
|
||||
qCWarning(oculusLog) << "Unable to initialize the platform for entitlement check - fail the check" << ovr::getError();
|
||||
return;
|
||||
} else {
|
||||
qCDebug(oculusLog) << "Performing Oculus Platform entitlement check";
|
||||
ovr_Entitlement_GetIsViewerEntitled();
|
||||
static std::once_flag once;
|
||||
std::call_once(once, []() {
|
||||
if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
|
||||
if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) {
|
||||
qCWarning(oculusLog) << "Unable to initialize the platform for entitlement check - fail the check" << ovr::getError();
|
||||
return;
|
||||
} else {
|
||||
qCDebug(oculusLog) << "Performing Oculus Platform entitlement check";
|
||||
ovr_Entitlement_GetIsViewerEntitled();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
#endif
|
||||
|
||||
ovrGraphicsLuid luid;
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
Entities, enableDispatcherModule, disableDispatcherModule, entityIsGrabbable, makeDispatcherModuleParameters, MSECS_PER_SEC,
|
||||
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC,
|
||||
projectOntoEntityXYPlane, ContextOverlay, HMD, Picks, makeLaserLockInfo, makeLaserParams, AddressManager,
|
||||
getEntityParents, Selection, DISPATCHER_HOVERING_LIST, unhighlightTargetEntity, Messages, findGroupParent,
|
||||
getEntityParents, Selection, DISPATCHER_HOVERING_LIST, unhighlightTargetEntity, Messages, findGrabbableGroupParent,
|
||||
worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES
|
||||
*/
|
||||
|
||||
|
@ -308,7 +308,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
var gtProps = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES);
|
||||
if (entityIsGrabbable(gtProps)) {
|
||||
// if we've attempted to grab a child, roll up to the root of the tree
|
||||
var groupRootProps = findGroupParent(controllerData, gtProps);
|
||||
var groupRootProps = findGrabbableGroupParent(controllerData, gtProps);
|
||||
if (entityIsGrabbable(groupRootProps)) {
|
||||
return groupRootProps;
|
||||
}
|
||||
|
|
|
@ -8,9 +8,10 @@
|
|||
|
||||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex, enableDispatcherModule,
|
||||
disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE,
|
||||
makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGroupParent, Vec3, cloneEntity,
|
||||
entityIsCloneable, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, distanceBetweenPointAndEntityBoundingBox,
|
||||
getGrabbableData, getEnabledModuleByName, DISPATCHER_PROPERTIES, HMD, NEAR_GRAB_DISTANCE
|
||||
makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGrabbableGroupParent, Vec3,
|
||||
cloneEntity, entityIsCloneable, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE,
|
||||
distanceBetweenPointAndEntityBoundingBox, getGrabbableData, getEnabledModuleByName, DISPATCHER_PROPERTIES, HMD,
|
||||
NEAR_GRAB_DISTANCE
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -80,9 +81,6 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
this.endNearGrabEntity = function () {
|
||||
this.endGrab();
|
||||
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args);
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
|
@ -90,6 +88,9 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
};
|
||||
|
||||
this.getTargetProps = function (controllerData) {
|
||||
|
@ -110,7 +111,7 @@ Script.include("/~/system/libraries/controllers.js");
|
|||
if (entityIsGrabbable(props) || entityIsCloneable(props)) {
|
||||
if (!entityIsCloneable(props)) {
|
||||
// if we've attempted to grab a non-cloneable child, roll up to the root of the tree
|
||||
var groupRootProps = findGroupParent(controllerData, props);
|
||||
var groupRootProps = findGrabbableGroupParent(controllerData, props);
|
||||
if (entityIsGrabbable(groupRootProps)) {
|
||||
return groupRootProps;
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
makeLaserLockInfo:true,
|
||||
entityHasActions:true,
|
||||
ensureDynamic:true,
|
||||
findGroupParent:true,
|
||||
findGrabbableGroupParent:true,
|
||||
BUMPER_ON_VALUE:true,
|
||||
getEntityParents:true,
|
||||
findHandChildEntities:true,
|
||||
|
@ -451,7 +451,7 @@ ensureDynamic = function (entityID) {
|
|||
}
|
||||
};
|
||||
|
||||
findGroupParent = function (controllerData, targetProps) {
|
||||
findGrabbableGroupParent = function (controllerData, targetProps) {
|
||||
while (targetProps.grab.grabDelegateToParent &&
|
||||
targetProps.parentID &&
|
||||
targetProps.parentID !== Uuid.NULL &&
|
||||
|
@ -460,6 +460,9 @@ findGroupParent = function (controllerData, targetProps) {
|
|||
if (!parentProps) {
|
||||
break;
|
||||
}
|
||||
if (!entityIsGrabbable(parentProps)) {
|
||||
break;
|
||||
}
|
||||
parentProps.id = targetProps.parentID;
|
||||
targetProps = parentProps;
|
||||
controllerData.nearbyEntityPropertiesByID[targetProps.id] = targetProps;
|
||||
|
@ -605,7 +608,7 @@ if (typeof module !== 'undefined') {
|
|||
unhighlightTargetEntity: unhighlightTargetEntity,
|
||||
clearHighlightedEntities: clearHighlightedEntities,
|
||||
makeRunningValues: makeRunningValues,
|
||||
findGroupParent: findGroupParent,
|
||||
findGrabbableGroupParent: findGrabbableGroupParent,
|
||||
LEFT_HAND: LEFT_HAND,
|
||||
RIGHT_HAND: RIGHT_HAND,
|
||||
BUMPER_ON_VALUE: BUMPER_ON_VALUE,
|
||||
|
|
|
@ -379,6 +379,9 @@ function decode_avatar_data_packet(buf)
|
|||
i = i + num_validity_bytes
|
||||
result["valid_translations"] = "Valid Translations: " .. string.format("(%d/%d) {", #indices, num_joints) .. table.concat(indices, ", ") .. "}"
|
||||
|
||||
-- TODO: skip maxTranslationDimension
|
||||
i = i + 4
|
||||
|
||||
-- TODO: skip translations for now
|
||||
i = i + #indices * 6
|
||||
|
||||
|
|
Loading…
Reference in a new issue