Merge branch 'master' of github.com:highfidelity/hifi into bug16645

This commit is contained in:
NissimHadar 2018-07-18 08:49:40 -07:00
commit 6cecfd4d24
9 changed files with 479 additions and 414 deletions

View file

@ -23,6 +23,7 @@
#include <QtCore/QFile> #include <QtCore/QFile>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QJsonDocument> #include <QtCore/QJsonDocument>
#include <QtCore/QSaveFile>
#include <QtCore/QString> #include <QtCore/QString>
#include <QtGui/QImageReader> #include <QtGui/QImageReader>
#include <QtCore/QVector> #include <QtCore/QVector>
@ -1042,7 +1043,7 @@ bool AssetServer::loadMappingsFromFile() {
bool AssetServer::writeMappingsToFile() { bool AssetServer::writeMappingsToFile() {
auto mapFilePath = _resourcesDirectory.absoluteFilePath(MAP_FILE_NAME); auto mapFilePath = _resourcesDirectory.absoluteFilePath(MAP_FILE_NAME);
QFile mapFile { mapFilePath }; QSaveFile mapFile { mapFilePath };
if (mapFile.open(QIODevice::WriteOnly)) { if (mapFile.open(QIODevice::WriteOnly)) {
QJsonObject root; QJsonObject root;
@ -1053,8 +1054,12 @@ bool AssetServer::writeMappingsToFile() {
QJsonDocument jsonDocument { root }; QJsonDocument jsonDocument { root };
if (mapFile.write(jsonDocument.toJson()) != -1) { if (mapFile.write(jsonDocument.toJson()) != -1) {
qCDebug(asset_server) << "Wrote JSON mappings to file at" << mapFilePath; if (mapFile.commit()) {
return true; qCDebug(asset_server) << "Wrote JSON mappings to file at" << mapFilePath;
return true;
} else {
qCWarning(asset_server) << "Failed to commit JSON mappings to file at" << mapFilePath;
}
} else { } else {
qCWarning(asset_server) << "Failed to write JSON mappings to file at" << mapFilePath; qCWarning(asset_server) << "Failed to write JSON mappings to file at" << mapFilePath;
} }

View file

@ -262,6 +262,26 @@ void MyAvatar::setDominantHand(const QString& hand) {
} }
} }
void MyAvatar::requestDisableHandTouch() {
std::lock_guard<std::mutex> guard(_disableHandTouchMutex);
_disableHandTouchCount++;
emit shouldDisableHandTouchChanged(_disableHandTouchCount > 0);
}
void MyAvatar::requestEnableHandTouch() {
std::lock_guard<std::mutex> guard(_disableHandTouchMutex);
_disableHandTouchCount = std::max(_disableHandTouchCount - 1, 0);
emit shouldDisableHandTouchChanged(_disableHandTouchCount > 0);
}
void MyAvatar::disableHandTouchForID(const QUuid& entityID) {
emit disableHandTouchForIDChanged(entityID, true);
}
void MyAvatar::enableHandTouchForID(const QUuid& entityID) {
emit disableHandTouchForIDChanged(entityID, false);
}
void MyAvatar::registerMetaTypes(ScriptEnginePointer engine) { void MyAvatar::registerMetaTypes(ScriptEnginePointer engine) {
QScriptValue value = engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); QScriptValue value = engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
engine->globalObject().setProperty("MyAvatar", value); engine->globalObject().setProperty("MyAvatar", value);

View file

@ -505,6 +505,28 @@ public:
* @returns {boolean} * @returns {boolean}
*/ */
Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; } Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; }
/**jsdoc
* Request to enable hand touch effect globally
* @function MyAvatar.requestEnableHandTouch
*/
Q_INVOKABLE void requestEnableHandTouch();
/**jsdoc
* Request to disable hand touch effect globally
* @function MyAvatar.requestDisableHandTouch
*/
Q_INVOKABLE void requestDisableHandTouch();
/**jsdoc
* Disables hand touch effect on a specific entity
* @function MyAvatar.disableHandTouchForID
* @param {Uuid} entityID - ID of the entity that will disable hand touch effect
*/
Q_INVOKABLE void disableHandTouchForID(const QUuid& entityID);
/**jsdoc
* Enables hand touch effect on a specific entity
* @function MyAvatar.enableHandTouchForID
* @param {Uuid} entityID - ID of the entity that will enable hand touch effect
*/
Q_INVOKABLE void enableHandTouchForID(const QUuid& entityID);
bool useAdvancedMovementControls() const { return _useAdvancedMovementControls.get(); } bool useAdvancedMovementControls() const { return _useAdvancedMovementControls.get(); }
void setUseAdvancedMovementControls(bool useAdvancedMovementControls) void setUseAdvancedMovementControls(bool useAdvancedMovementControls)
@ -1392,6 +1414,23 @@ signals:
*/ */
void scaleChanged(); void scaleChanged();
/**jsdoc
* Triggered when hand touch is globally enabled or disabled
* @function MyAvatar.shouldDisableHandTouchChanged
* @param {boolean} shouldDisable
* @returns {Signal}
*/
void shouldDisableHandTouchChanged(bool shouldDisable);
/**jsdoc
* Triggered when hand touch is enabled or disabled for an specific entity
* @function MyAvatar.disableHandTouchForIDChanged
* @param {Uuid} entityID - ID of the entity that will enable hand touch effect
* @param {boolean} disable
* @returns {Signal}
*/
void disableHandTouchForIDChanged(const QUuid& entityID, bool disable);
private slots: private slots:
void leaveDomain(); void leaveDomain();
@ -1628,6 +1667,7 @@ private:
// all poses are in sensor-frame // all poses are in sensor-frame
std::map<controller::Action, controller::Pose> _controllerPoseMap; std::map<controller::Action, controller::Pose> _controllerPoseMap;
mutable std::mutex _controllerPoseMapMutex; mutable std::mutex _controllerPoseMapMutex;
mutable std::mutex _disableHandTouchMutex;
bool _centerOfGravityModelEnabled { true }; bool _centerOfGravityModelEnabled { true };
bool _hmdLeanRecenterEnabled { true }; bool _hmdLeanRecenterEnabled { true };
@ -1668,6 +1708,7 @@ private:
bool _shouldLoadScripts { false }; bool _shouldLoadScripts { false };
bool _haveReceivedHeightLimitsFromDomain { false }; bool _haveReceivedHeightLimitsFromDomain { false };
int _disableHandTouchCount { 0 };
}; };
QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode);

View file

@ -21,14 +21,17 @@
#include <QtCore/qpair.h> #include <QtCore/qpair.h>
#include <QtCore/qlist.h> #include <QtCore/qlist.h>
#include <QtNetwork/QNetworkAccessManager> #include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest> #include <QtNetwork/QNetworkRequest>
#include <qfile.h> #include <qfile.h>
#include <qfileinfo.h>
#include <shared/NsightHelpers.h> #include <shared/NsightHelpers.h>
#include <NetworkAccessManager.h> #include <NetworkAccessManager.h>
#include <ResourceManager.h> #include <ResourceManager.h>
#include <PathUtils.h>
#include "FBXReader.h" #include "FBXReader.h"
@ -786,13 +789,18 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) {
QVector<glm::vec3> raw_vertices; QVector<glm::vec3> raw_vertices;
QVector<glm::vec3> raw_normals; QVector<glm::vec3> raw_normals;
addArrayOfType(indicesBuffer.blob, bool success = addArrayOfType(indicesBuffer.blob,
indicesBufferview.byteOffset + indicesAccBoffset, indicesBufferview.byteOffset + indicesAccBoffset,
indicesBufferview.byteLength, indicesAccessor.count,
part.triangleIndices, part.triangleIndices,
indicesAccessor.type, indicesAccessor.type,
indicesAccessor.componentType); indicesAccessor.componentType);
if (!success) {
qWarning(modelformat) << "There was a problem reading glTF INDICES data for model " << _url;
continue;
}
QList<QString> keys = primitive.attributes.values.keys(); QList<QString> keys = primitive.attributes.values.keys();
foreach(auto &key, keys) { foreach(auto &key, keys) {
@ -805,44 +813,60 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) {
int accBoffset = accessor.defined["byteOffset"] ? accessor.byteOffset : 0; int accBoffset = accessor.defined["byteOffset"] ? accessor.byteOffset : 0;
if (key == "POSITION") { if (key == "POSITION") {
QVector<float> vertices; QVector<float> vertices;
addArrayOfType(buffer.blob, success = addArrayOfType(buffer.blob,
bufferview.byteOffset + accBoffset, bufferview.byteOffset + accBoffset,
bufferview.byteLength, vertices, accessor.count, vertices,
accessor.type, accessor.type,
accessor.componentType); accessor.componentType);
if (!success) {
qWarning(modelformat) << "There was a problem reading glTF POSITION data for model " << _url;
continue;
}
for (int n = 0; n < vertices.size(); n = n + 3) { for (int n = 0; n < vertices.size(); n = n + 3) {
mesh.vertices.push_back(glm::vec3(vertices[n], vertices[n + 1], vertices[n + 2])); mesh.vertices.push_back(glm::vec3(vertices[n], vertices[n + 1], vertices[n + 2]));
} }
} else if (key == "NORMAL") { } else if (key == "NORMAL") {
QVector<float> normals; QVector<float> normals;
addArrayOfType(buffer.blob, success = addArrayOfType(buffer.blob,
bufferview.byteOffset + accBoffset, bufferview.byteOffset + accBoffset,
bufferview.byteLength, accessor.count,
normals, normals,
accessor.type, accessor.type,
accessor.componentType); accessor.componentType);
if (!success) {
qWarning(modelformat) << "There was a problem reading glTF NORMAL data for model " << _url;
continue;
}
for (int n = 0; n < normals.size(); n = n + 3) { for (int n = 0; n < normals.size(); n = n + 3) {
mesh.normals.push_back(glm::vec3(normals[n], normals[n + 1], normals[n + 2])); mesh.normals.push_back(glm::vec3(normals[n], normals[n + 1], normals[n + 2]));
} }
} else if (key == "TEXCOORD_0") { } else if (key == "TEXCOORD_0") {
QVector<float> texcoords; QVector<float> texcoords;
addArrayOfType(buffer.blob, success = addArrayOfType(buffer.blob,
bufferview.byteOffset + accBoffset, bufferview.byteOffset + accBoffset,
bufferview.byteLength, accessor.count,
texcoords, texcoords,
accessor.type, accessor.type,
accessor.componentType); accessor.componentType);
if (!success) {
qWarning(modelformat) << "There was a problem reading glTF TEXCOORD_0 data for model " << _url;
continue;
}
for (int n = 0; n < texcoords.size(); n = n + 2) { for (int n = 0; n < texcoords.size(); n = n + 2) {
mesh.texCoords.push_back(glm::vec2(texcoords[n], texcoords[n + 1])); mesh.texCoords.push_back(glm::vec2(texcoords[n], texcoords[n + 1]));
} }
} else if (key == "TEXCOORD_1") { } else if (key == "TEXCOORD_1") {
QVector<float> texcoords; QVector<float> texcoords;
addArrayOfType(buffer.blob, success = addArrayOfType(buffer.blob,
bufferview.byteOffset + accBoffset, bufferview.byteOffset + accBoffset,
bufferview.byteLength, accessor.count,
texcoords, texcoords,
accessor.type, accessor.type,
accessor.componentType); accessor.componentType);
if (!success) {
qWarning(modelformat) << "There was a problem reading glTF TEXCOORD_1 data for model " << _url;
continue;
}
for (int n = 0; n < texcoords.size(); n = n + 2) { for (int n = 0; n < texcoords.size(); n = n + 2) {
mesh.texCoords1.push_back(glm::vec2(texcoords[n], texcoords[n + 1])); mesh.texCoords1.push_back(glm::vec2(texcoords[n], texcoords[n + 1]));
} }
@ -888,8 +912,16 @@ bool GLTFReader::buildGeometry(FBXGeometry& geometry, const QUrl& url) {
FBXGeometry* GLTFReader::readGLTF(QByteArray& model, const QVariantHash& mapping, FBXGeometry* GLTFReader::readGLTF(QByteArray& model, const QVariantHash& mapping,
const QUrl& url, bool loadLightmaps, float lightmapLevel) { const QUrl& url, bool loadLightmaps, float lightmapLevel) {
_url = url; _url = url;
// Normalize url for local files
QUrl normalizeUrl = DependencyManager::get<ResourceManager>()->normalizeURL(url);
if (normalizeUrl.scheme().isEmpty() || (normalizeUrl.scheme() == "file")) {
QString localFileName = PathUtils::expandToLocalDataAbsolutePath(normalizeUrl).toLocalFile();
_url = QUrl(QFileInfo(localFileName).absoluteFilePath());
}
parseGLTF(model); parseGLTF(model);
//_file.dump(); //_file.dump();
FBXGeometry* geometryPtr = new FBXGeometry(); FBXGeometry* geometryPtr = new FBXGeometry();
@ -904,6 +936,7 @@ FBXGeometry* GLTFReader::readGLTF(QByteArray& model, const QVariantHash& mapping
bool GLTFReader::readBinary(const QString& url, QByteArray& outdata) { bool GLTFReader::readBinary(const QString& url, QByteArray& outdata) {
QUrl binaryUrl = _url.resolved(QUrl(url).fileName()); QUrl binaryUrl = _url.resolved(QUrl(url).fileName());
qCDebug(modelformat) << "binaryUrl: " << binaryUrl << " OriginalUrl: " << _url; qCDebug(modelformat) << "binaryUrl: " << binaryUrl << " OriginalUrl: " << _url;
bool success; bool success;
std::tie<bool, QByteArray>(success, outdata) = requestData(binaryUrl); std::tie<bool, QByteArray>(success, outdata) = requestData(binaryUrl);
@ -1018,13 +1051,12 @@ void GLTFReader::setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& materia
fbxmat.opacityTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); fbxmat.opacityTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
fbxmat.albedoTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]); fbxmat.albedoTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
fbxmat.useAlbedoMap = true; fbxmat.useAlbedoMap = true;
fbxmat.metallicTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.baseColorTexture]);
fbxmat.useMetallicMap = true;
} }
if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) { if (material.pbrMetallicRoughness.defined["metallicRoughnessTexture"]) {
fbxmat.roughnessTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]); fbxmat.roughnessTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
fbxmat.useRoughnessMap = true; fbxmat.useRoughnessMap = true;
fbxmat.metallicTexture = getFBXTexture(_file.textures[material.pbrMetallicRoughness.metallicRoughnessTexture]);
fbxmat.useMetallicMap = true;
} }
if (material.pbrMetallicRoughness.defined["roughnessFactor"]) { if (material.pbrMetallicRoughness.defined["roughnessFactor"]) {
fbxmat._material->setRoughness(material.pbrMetallicRoughness.roughnessFactor); fbxmat._material->setRoughness(material.pbrMetallicRoughness.roughnessFactor);
@ -1043,7 +1075,7 @@ void GLTFReader::setFBXMaterial(FBXMaterial& fbxmat, const GLTFMaterial& materia
} }
template<typename T, typename L> template<typename T, typename L>
bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int byteLength, bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int count,
QVector<L>& outarray, int accessorType) { QVector<L>& outarray, int accessorType) {
QDataStream blobstream(bin); QDataStream blobstream(bin);
@ -1051,142 +1083,77 @@ bool GLTFReader::readArray(const QByteArray& bin, int byteOffset, int byteLength
blobstream.setVersion(QDataStream::Qt_5_9); blobstream.setVersion(QDataStream::Qt_5_9);
blobstream.setFloatingPointPrecision(QDataStream::FloatingPointPrecision::SinglePrecision); blobstream.setFloatingPointPrecision(QDataStream::FloatingPointPrecision::SinglePrecision);
int vsize = byteLength / sizeof(T); qCDebug(modelformat) << "size1: " << count;
qCDebug(modelformat) << "size1: " << vsize;
int dataskipped = blobstream.skipRawData(byteOffset); int dataskipped = blobstream.skipRawData(byteOffset);
qCDebug(modelformat) << "dataskipped: " << dataskipped; qCDebug(modelformat) << "dataskipped: " << dataskipped;
int bufferCount = 0;
while (outarray.size() < vsize) { switch (accessorType) {
case GLTFAccessorType::SCALAR:
T value1, value2, value3, value4, bufferCount = 1;
value5, value6, value7, value8, break;
value9, value10, value11, value12, case GLTFAccessorType::VEC2:
value13, value14, value15, value16; bufferCount = 2;
break;
if (accessorType == GLTFAccessorType::SCALAR) { case GLTFAccessorType::VEC3:
bufferCount = 3;
blobstream >> value1; break;
case GLTFAccessorType::VEC4:
outarray.push_back(value1); bufferCount = 4;
} else if (accessorType == GLTFAccessorType::VEC2) { break;
case GLTFAccessorType::MAT2:
blobstream >> value1; bufferCount = 4;
blobstream >> value2; break;
case GLTFAccessorType::MAT3:
outarray.push_back(value1); bufferCount = 9;
outarray.push_back(value2); break;
} else if (accessorType == GLTFAccessorType::VEC3) { case GLTFAccessorType::MAT4:
bufferCount = 16;
blobstream >> value1; break;
blobstream >> value2; default:
blobstream >> value3; qWarning(modelformat) << "Unknown accessorType: " << accessorType;
blobstream.unsetDevice();
outarray.push_back(value1); return false;
outarray.push_back(value2); }
outarray.push_back(value3); for (int i = 0; i < count; i++) {
} else if (accessorType == GLTFAccessorType::VEC4 || accessorType == GLTFAccessorType::MAT2) { for (int j = 0; j < bufferCount; j++) {
if (!blobstream.atEnd()) {
blobstream >> value1; T value;
blobstream >> value2; blobstream >> value;
blobstream >> value3; outarray.push_back(value);
blobstream >> value4; } else {
blobstream.unsetDevice();
outarray.push_back(value1); return false;
outarray.push_back(value2); }
outarray.push_back(value3);
outarray.push_back(value4);
} else if (accessorType == GLTFAccessorType::MAT3) {
blobstream >> value1;
blobstream >> value2;
blobstream >> value3;
blobstream >> value4;
blobstream >> value5;
blobstream >> value6;
blobstream >> value7;
blobstream >> value8;
blobstream >> value9;
outarray.push_back(value1);
outarray.push_back(value2);
outarray.push_back(value3);
outarray.push_back(value4);
outarray.push_back(value5);
outarray.push_back(value6);
outarray.push_back(value7);
outarray.push_back(value8);
outarray.push_back(value9);
} else if (accessorType == GLTFAccessorType::MAT4) {
blobstream >> value1;
blobstream >> value2;
blobstream >> value3;
blobstream >> value4;
blobstream >> value5;
blobstream >> value6;
blobstream >> value7;
blobstream >> value8;
blobstream >> value9;
blobstream >> value10;
blobstream >> value11;
blobstream >> value12;
blobstream >> value13;
blobstream >> value14;
blobstream >> value15;
blobstream >> value16;
outarray.push_back(value1);
outarray.push_back(value2);
outarray.push_back(value3);
outarray.push_back(value4);
outarray.push_back(value5);
outarray.push_back(value6);
outarray.push_back(value7);
outarray.push_back(value8);
outarray.push_back(value9);
outarray.push_back(value10);
outarray.push_back(value11);
outarray.push_back(value12);
outarray.push_back(value13);
outarray.push_back(value14);
outarray.push_back(value15);
outarray.push_back(value16);
} }
} }
blobstream.unsetDevice(); blobstream.unsetDevice();
return true; return true;
} }
template<typename T> template<typename T>
bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int byteLength, bool GLTFReader::addArrayOfType(const QByteArray& bin, int byteOffset, int count,
QVector<T>& outarray, int accessorType, int componentType) { QVector<T>& outarray, int accessorType, int componentType) {
switch (componentType) { switch (componentType) {
case GLTFAccessorComponentType::BYTE: {} case GLTFAccessorComponentType::BYTE: {}
case GLTFAccessorComponentType::UNSIGNED_BYTE: { case GLTFAccessorComponentType::UNSIGNED_BYTE: {
readArray<uchar>(bin, byteOffset, byteLength, outarray, accessorType); return readArray<uchar>(bin, byteOffset, count, outarray, accessorType);
break;
} }
case GLTFAccessorComponentType::SHORT: { case GLTFAccessorComponentType::SHORT: {
readArray<short>(bin, byteOffset, byteLength, outarray, accessorType); return readArray<short>(bin, byteOffset, count, outarray, accessorType);
break;
} }
case GLTFAccessorComponentType::UNSIGNED_INT: { case GLTFAccessorComponentType::UNSIGNED_INT: {
readArray<quint32>(bin, byteOffset, byteLength, outarray, accessorType); return readArray<uint>(bin, byteOffset, count, outarray, accessorType);
break;
} }
case GLTFAccessorComponentType::UNSIGNED_SHORT: { case GLTFAccessorComponentType::UNSIGNED_SHORT: {
readArray<ushort>(bin, byteOffset, byteLength, outarray, accessorType); return readArray<ushort>(bin, byteOffset, count, outarray, accessorType);
break;
} }
case GLTFAccessorComponentType::FLOAT: { case GLTFAccessorComponentType::FLOAT: {
readArray<float>(bin, byteOffset, byteLength, outarray, accessorType); return readArray<float>(bin, byteOffset, count, outarray, accessorType);
break;
} }
} }
return true; return false;
} }
void GLTFReader::retriangulate(const QVector<int>& inIndices, const QVector<glm::vec3>& in_vertices, void GLTFReader::retriangulate(const QVector<int>& inIndices, const QVector<glm::vec3>& in_vertices,

View file

@ -762,11 +762,11 @@ private:
bool readBinary(const QString& url, QByteArray& outdata); bool readBinary(const QString& url, QByteArray& outdata);
template<typename T, typename L> template<typename T, typename L>
bool readArray(const QByteArray& bin, int byteOffset, int byteLength, bool readArray(const QByteArray& bin, int byteOffset, int count,
QVector<L>& outarray, int accessorType); QVector<L>& outarray, int accessorType);
template<typename T> template<typename T>
bool addArrayOfType(const QByteArray& bin, int byteOffset, int byteLength, bool addArrayOfType(const QByteArray& bin, int byteOffset, int count,
QVector<T>& outarray, int accessorType, int componentType); QVector<T>& outarray, int accessorType, int componentType);
void retriangulate(const QVector<int>& in_indices, const QVector<glm::vec3>& in_vertices, void retriangulate(const QVector<int>& in_indices, const QVector<glm::vec3>& in_vertices,

View file

@ -14,64 +14,64 @@
/* global Script, Overlays, Controller, Vec3, MyAvatar, Entities /* global Script, Overlays, Controller, Vec3, MyAvatar, Entities
*/ */
(function() { (function () {
var MSECONDS_AFTER_LOAD = 2000;
var handTouchEnabled = true;
var MSECONDS_AFTER_LOAD = 2000;
var updateFingerWithIndex = 0; var updateFingerWithIndex = 0;
var untouchableEntities = [];
// Keys to access finger data
// Keys to access finger data
var fingerKeys = ["pinky", "ring", "middle", "index", "thumb"]; var fingerKeys = ["pinky", "ring", "middle", "index", "thumb"];
// Additionally close the hands to achieve a grabbing effect // Additionally close the hands to achieve a grabbing effect
var grabPercent = { left: 0, right: 0 }; var grabPercent = { left: 0, right: 0 };
var Palm = function() { var Palm = function() {
this.position = {x: 0, y: 0, z: 0}; this.position = {x: 0, y: 0, z: 0};
this.perpendicular = {x: 0, y: 0, z: 0}; this.perpendicular = {x: 0, y: 0, z: 0};
this.distance = 0; this.distance = 0;
this.fingers = { this.fingers = {
pinky: {x: 0, y: 0, z: 0}, pinky: {x: 0, y: 0, z: 0},
middle: {x: 0, y: 0, z: 0}, middle: {x: 0, y: 0, z: 0},
ring: {x: 0, y: 0, z: 0}, ring: {x: 0, y: 0, z: 0},
thumb: {x: 0, y: 0, z: 0}, thumb: {x: 0, y: 0, z: 0},
index: {x: 0, y: 0, z: 0} index: {x: 0, y: 0, z: 0}
}; };
this.set = false; this.set = false;
}; };
var palmData = { var palmData = {
left: new Palm(), left: new Palm(),
right: new Palm() right: new Palm()
}; };
var handJointNames = {left: "LeftHand", right: "RightHand"}; var handJointNames = {left: "LeftHand", right: "RightHand"};
// Store which fingers are touching - if all false restate the default poses // Store which fingers are touching - if all false restate the default poses
var isTouching = { var isTouching = {
left: { left: {
pinky: false, pinky: false,
middle: false, middle: false,
ring: false, ring: false,
thumb: false, thumb: false,
index: false index: false
}, right: { }, right: {
pinky: false, pinky: false,
middle: false, middle: false,
ring: false, ring: false,
thumb: false, thumb: false,
index: false index: false
} }
}; };
// frame count for transition to default pose // frame count for transition to default pose
var countToDefault = { var countToDefault = {
left: 0, left: 0,
right: 0 right: 0
}; };
// joint data for open pose // joint data for open pose
var dataOpen = { var dataOpen = {
left: { left: {
@ -128,7 +128,7 @@
] ]
} }
}; };
// joint data for close pose // joint data for close pose
var dataClose = { var dataClose = {
left: { left: {
@ -185,78 +185,78 @@
] ]
} }
}; };
// snapshot for the default pose // snapshot for the default pose
var dataDefault = { var dataDefault = {
left: { left: {
pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
set: false set: false
}, },
right: { right: {
pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
set: false set: false
} }
}; };
// joint data for the current frame // joint data for the current frame
var dataCurrent = { var dataCurrent = {
left: { left: {
pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}]
}, },
right: { right: {
pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}]
} }
}; };
// interpolated values on joint data to smooth movement // interpolated values on joint data to smooth movement
var dataDelta = { var dataDelta = {
left: { left: {
pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}]
}, },
right: { right: {
pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], pinky: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], middle: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], ring: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}], thumb: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}],
index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}] index: [{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0},{x: 0, y: 0, z: 0, w: 0}]
} }
}; };
// Acquire an updated value per hand every 5 frames when finger is touching (faster in) // Acquire an updated value per hand every 5 frames when finger is touching (faster in)
var touchAnimationSteps = 5; var touchAnimationSteps = 5;
// Acquire an updated value per hand every 20 frames when finger is returning to default position (slower out) // Acquire an updated value per hand every 20 frames when finger is returning to default position (slower out)
var defaultAnimationSteps = 10; var defaultAnimationSteps = 10;
// Debugging info // Debugging info
var showSphere = false; var showSphere = false;
var showLines = false; var showLines = false;
// This get setup on creation // This get setup on creation
var linesCreated = false; var linesCreated = false;
var sphereCreated = false; var sphereCreated = false;
// Register object with API Debugger // Register object with API Debugger
var varsToDebug = { var varsToDebug = {
scriptLoaded: false, scriptLoaded: false,
toggleDebugSphere: function() { toggleDebugSphere: function() {
@ -275,17 +275,17 @@
}, },
fingerPercent: { fingerPercent: {
left: { left: {
pinky: 0.38, pinky: 0.38,
middle: 0.38, middle: 0.38,
ring: 0.38, ring: 0.38,
thumb: 0.38, thumb: 0.38,
index: 0.38 index: 0.38
} , } ,
right: { right: {
pinky: 0.38, pinky: 0.38,
middle: 0.38, middle: 0.38,
ring: 0.38, ring: 0.38,
thumb: 0.38, thumb: 0.38,
index: 0.38 index: 0.38
} }
}, },
@ -300,12 +300,11 @@
palmData: { palmData: {
left: new Palm(), left: new Palm(),
right: new Palm() right: new Palm()
}, },
offset: {x: 0, y: 0, z: 0}, offset: {x: 0, y: 0, z: 0},
avatarLoaded: false avatarLoaded: false
}; };
// Add/Subtract the joint data - per finger joint // Add/Subtract the joint data - per finger joint
function addVals(val1, val2, sign) { function addVals(val1, val2, sign) {
var val = []; var val = [];
@ -321,7 +320,7 @@
} }
return val; return val;
} }
// Multiply/Divide the joint data - per finger joint // Multiply/Divide the joint data - per finger joint
function multiplyValsBy(val1, num) { function multiplyValsBy(val1, num) {
var val = []; var val = [];
@ -334,7 +333,7 @@
} }
return val; return val;
} }
// Calculate the finger lengths by adding its joint lengths // Calculate the finger lengths by adding its joint lengths
function getJointDistances(jointNamesArray) { function getJointDistances(jointNamesArray) {
var result = {distances: [], totalDistance: 0}; var result = {distances: [], totalDistance: 0};
@ -349,13 +348,12 @@
} }
return result; return result;
} }
function dataRelativeToWorld(side, dataIn, dataOut) {
function dataRelativeToWorld(side, dataIn, dataOut) {
var handJoint = handJointNames[side]; var handJoint = handJointNames[side];
var jointIndex = MyAvatar.getJointIndex(handJoint); var jointIndex = MyAvatar.getJointIndex(handJoint);
var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex); var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex);
dataOut.position = MyAvatar.jointToWorldPoint(dataIn.position, jointIndex); dataOut.position = MyAvatar.jointToWorldPoint(dataIn.position, jointIndex);
var localPerpendicular = side === "right" ? {x: 0.2, y: 0, z: 1} : {x: -0.2, y: 0, z: 1}; var localPerpendicular = side === "right" ? {x: 0.2, y: 0, z: 1} : {x: -0.2, y: 0, z: 1};
dataOut.perpendicular = Vec3.normalize( dataOut.perpendicular = Vec3.normalize(
@ -365,15 +363,14 @@
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
var finger = fingerKeys[i]; var finger = fingerKeys[i];
dataOut.fingers[finger] = MyAvatar.jointToWorldPoint(dataIn.fingers[finger], jointIndex); dataOut.fingers[finger] = MyAvatar.jointToWorldPoint(dataIn.fingers[finger], jointIndex);
} }
} }
function dataRelativeToHandJoint(side, dataIn, dataOut) {
function dataRelativeToHandJoint(side, dataIn, dataOut) {
var handJoint = handJointNames[side]; var handJoint = handJointNames[side];
var jointIndex = MyAvatar.getJointIndex(handJoint); var jointIndex = MyAvatar.getJointIndex(handJoint);
var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex); var worldPosHand = MyAvatar.jointToWorldPoint({x: 0, y: 0, z: 0}, jointIndex);
dataOut.position = MyAvatar.worldToJointPoint(dataIn.position, jointIndex); dataOut.position = MyAvatar.worldToJointPoint(dataIn.position, jointIndex);
dataOut.perpendicular = MyAvatar.worldToJointPoint(Vec3.sum(worldPosHand, dataIn.perpendicular), jointIndex); dataOut.perpendicular = MyAvatar.worldToJointPoint(Vec3.sum(worldPosHand, dataIn.perpendicular), jointIndex);
dataOut.distance = dataIn.distance; dataOut.distance = dataIn.distance;
@ -382,46 +379,44 @@
dataOut.fingers[finger] = MyAvatar.worldToJointPoint(dataIn.fingers[finger], jointIndex); dataOut.fingers[finger] = MyAvatar.worldToJointPoint(dataIn.fingers[finger], jointIndex);
} }
} }
// Calculate touch field; Sphere at the center of the palm, // Calculate touch field; Sphere at the center of the palm,
// perpendicular vector from the palm plane and origin of the the finger rays // perpendicular vector from the palm plane and origin of the the finger rays
function estimatePalmData(side) { function estimatePalmData(side) {
// Return data object // Return data object
var data = new Palm(); var data = new Palm();
var jointOffset = { x: 0, y: 0, z: 0 }; var jointOffset = { x: 0, y: 0, z: 0 };
var upperSide = side[0].toUpperCase() + side.substring(1); var upperSide = side[0].toUpperCase() + side.substring(1);
var jointIndexHand = MyAvatar.getJointIndex(upperSide + "Hand"); var jointIndexHand = MyAvatar.getJointIndex(upperSide + "Hand");
// Store position of the hand joint // Store position of the hand joint
var worldPosHand = MyAvatar.jointToWorldPoint(jointOffset, jointIndexHand); var worldPosHand = MyAvatar.jointToWorldPoint(jointOffset, jointIndexHand);
var minusWorldPosHand = {x: -worldPosHand.x, y: -worldPosHand.y, z: -worldPosHand.z}; var minusWorldPosHand = {x: -worldPosHand.x, y: -worldPosHand.y, z: -worldPosHand.z};
// Data for finger rays // Data for finger rays
var directions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; var directions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined};
var positions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined}; var positions = {pinky: undefined, middle: undefined, ring: undefined, thumb: undefined, index: undefined};
var thumbLength = 0; var thumbLength = 0;
var weightCount = 0; var weightCount = 0;
// Calculate palm center // Calculate palm center
var handJointWeight = 1; var handJointWeight = 1;
var fingerJointWeight = 2; var fingerJointWeight = 2;
var palmCenter = {x: 0, y: 0, z: 0}; var palmCenter = {x: 0, y: 0, z: 0};
palmCenter = Vec3.sum(worldPosHand, palmCenter); palmCenter = Vec3.sum(worldPosHand, palmCenter);
weightCount += handJointWeight; weightCount += handJointWeight;
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
var finger = fingerKeys[i]; var finger = fingerKeys[i];
var jointSuffixes = 4; // Get 4 joint names with suffix numbers (0, 1, 2, 3) var jointSuffixes = 4; // Get 4 joint names with suffix numbers (0, 1, 2, 3)
var jointNames = getJointNames(side, finger, jointSuffixes); var jointNames = getJointNames(side, finger, jointSuffixes);
var fingerLength = getJointDistances(jointNames).totalDistance; var fingerLength = getJointDistances(jointNames).totalDistance;
var jointIndex = MyAvatar.getJointIndex(jointNames[0]); var jointIndex = MyAvatar.getJointIndex(jointNames[0]);
positions[finger] = MyAvatar.jointToWorldPoint(jointOffset, jointIndex); positions[finger] = MyAvatar.jointToWorldPoint(jointOffset, jointIndex);
directions[finger] = Vec3.normalize(Vec3.sum(positions[finger], minusWorldPosHand)); directions[finger] = Vec3.normalize(Vec3.sum(positions[finger], minusWorldPosHand));
@ -429,66 +424,63 @@
if (finger !== "thumb") { if (finger !== "thumb") {
// finger joints have double the weight than the hand joint // finger joints have double the weight than the hand joint
// This would better position the palm estimation // This would better position the palm estimation
palmCenter = Vec3.sum(Vec3.multiply(fingerJointWeight, positions[finger]), palmCenter); palmCenter = Vec3.sum(Vec3.multiply(fingerJointWeight, positions[finger]), palmCenter);
weightCount += fingerJointWeight; weightCount += fingerJointWeight;
} else { } else {
thumbLength = fingerLength; thumbLength = fingerLength;
} }
} }
// perpendicular change direction depending on the side // perpendicular change direction depending on the side
data.perpendicular = (side === "right") ? data.perpendicular = (side === "right") ?
Vec3.normalize(Vec3.cross(directions.index, directions.pinky)): Vec3.normalize(Vec3.cross(directions.index, directions.pinky)):
Vec3.normalize(Vec3.cross(directions.pinky, directions.index)); Vec3.normalize(Vec3.cross(directions.pinky, directions.index));
data.position = Vec3.multiply(1.0/weightCount, palmCenter); data.position = Vec3.multiply(1.0/weightCount, palmCenter);
if (side === "right") { if (side === "right") {
varsToDebug.offset = MyAvatar.worldToJointPoint(worldPosHand, jointIndexHand); varsToDebug.offset = MyAvatar.worldToJointPoint(worldPosHand, jointIndexHand);
} }
var palmDistanceMultiplier = 1.55; // 1.55 based on test/error for the sphere radius that best fits the hand var palmDistanceMultiplier = 1.55; // 1.55 based on test/error for the sphere radius that best fits the hand
data.distance = palmDistanceMultiplier*Vec3.distance(data.position, positions.index); data.distance = palmDistanceMultiplier*Vec3.distance(data.position, positions.index);
// move back thumb ray origin // move back thumb ray origin
var thumbBackMultiplier = 0.2; var thumbBackMultiplier = 0.2;
data.fingers.thumb = Vec3.sum( data.fingers.thumb = Vec3.sum(
data.fingers.thumb, Vec3.multiply( -thumbBackMultiplier * thumbLength, data.perpendicular)); data.fingers.thumb, Vec3.multiply( -thumbBackMultiplier * thumbLength, data.perpendicular));
// return getDataRelativeToHandJoint(side, data); // return getDataRelativeToHandJoint(side, data);
dataRelativeToHandJoint(side, data, palmData[side]); dataRelativeToHandJoint(side, data, palmData[side]);
palmData[side].set = true; palmData[side].set = true;
// return palmData[side];
} }
// Register GlobalDebugger for API Debugger // Register GlobalDebugger for API Debugger
Script.registerValue("GlobalDebugger", varsToDebug); Script.registerValue("GlobalDebugger", varsToDebug);
// store the rays for the fingers - only for debug purposes // store the rays for the fingers - only for debug purposes
var fingerRays = { var fingerRays = {
left: { left: {
pinky: undefined, pinky: undefined,
middle: undefined, middle: undefined,
ring: undefined, ring: undefined,
thumb: undefined, thumb: undefined,
index: undefined index: undefined
}, },
right: { right: {
pinky: undefined, pinky: undefined,
middle: undefined, middle: undefined,
ring: undefined, ring: undefined,
thumb: undefined, thumb: undefined,
index: undefined index: undefined
} }
}; };
// Create debug overlays - finger rays + palm rays + spheres // Create debug overlays - finger rays + palm rays + spheres
var palmRay, sphereHand; var palmRay, sphereHand;
function createDebugLines() { function createDebugLines() {
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
fingerRays.left[fingerKeys[i]] = Overlays.addOverlay("line3d", { fingerRays.left[fingerKeys[i]] = Overlays.addOverlay("line3d", {
color: { red: 0, green: 0, blue: 255 }, color: { red: 0, green: 0, blue: 255 },
@ -503,7 +495,7 @@
visible: showLines visible: showLines
}); });
} }
palmRay = { palmRay = {
left: Overlays.addOverlay("line3d", { left: Overlays.addOverlay("line3d", {
color: { red: 255, green: 0, blue: 0 }, color: { red: 255, green: 0, blue: 0 },
@ -520,9 +512,8 @@
}; };
linesCreated = true; linesCreated = true;
} }
function createDebugSphere() { function createDebugSphere() {
sphereHand = { sphereHand = {
right: Overlays.addOverlay("sphere", { right: Overlays.addOverlay("sphere", {
position: MyAvatar.position, position: MyAvatar.position,
@ -536,10 +527,10 @@
scale: { x: 0.01, y: 0.01, z: 0.01 }, scale: { x: 0.01, y: 0.01, z: 0.01 },
visible: showSphere visible: showSphere
}) })
}; };
sphereCreated = true; sphereCreated = true;
} }
function acquireDefaultPose(side) { function acquireDefaultPose(side) {
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
var finger = fingerKeys[i]; var finger = fingerKeys[i];
@ -553,86 +544,87 @@
} }
dataDefault[side].set = true; dataDefault[side].set = true;
} }
var rayPicks = { var rayPicks = {
left: { left: {
pinky: undefined, pinky: undefined,
middle: undefined, middle: undefined,
ring: undefined, ring: undefined,
thumb: undefined, thumb: undefined,
index: undefined index: undefined
}, },
right: { right: {
pinky: undefined, pinky: undefined,
middle: undefined, middle: undefined,
ring: undefined, ring: undefined,
thumb: undefined, thumb: undefined,
index: undefined index: undefined
} }
}; };
var dataFailed = { var dataFailed = {
left: { left: {
pinky: 0, pinky: 0,
middle: 0, middle: 0,
ring: 0, ring: 0,
thumb: 0, thumb: 0,
index: 0 index: 0
}, },
right: { right: {
pinky: 0, pinky: 0,
middle: 0, middle: 0,
ring: 0, ring: 0,
thumb: 0, thumb: 0,
index: 0 index: 0
} }
}; };
function clearRayPicks(side) { function clearRayPicks(side) {
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
var finger = fingerKeys[i]; var finger = fingerKeys[i];
if (rayPicks[side][finger] !== undefined) { if (rayPicks[side][finger] !== undefined) {
RayPick.removeRayPick(rayPicks[side][finger]); RayPick.removeRayPick(rayPicks[side][finger]);
rayPicks[side][finger] = undefined; rayPicks[side][finger] = undefined;
} }
} }
} }
function createRayPicks(side) { function createRayPicks(side) {
var data = palmData[side]; var data = palmData[side];
clearRayPicks(side); clearRayPicks(side);
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
var finger = fingerKeys[i]; var finger = fingerKeys[i];
var LOOKUP_DISTANCE_MULTIPLIER = 1.5; var LOOKUP_DISTANCE_MULTIPLIER = 1.5;
var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance;
var checkOffset = { var checkOffset = {
x: data.perpendicular.x * dist, x: data.perpendicular.x * dist,
y: data.perpendicular.y * dist, y: data.perpendicular.y * dist,
z: data.perpendicular.z * dist z: data.perpendicular.z * dist
}; };
var checkPoint = Vec3.sum(data.position, Vec3.multiply(2, checkOffset)); var checkPoint = Vec3.sum(data.position, Vec3.multiply(2, checkOffset));
var sensorToWorldScale = MyAvatar.getSensorToWorldScale(); var sensorToWorldScale = MyAvatar.getSensorToWorldScale();
var origin = data.fingers[finger]; var origin = data.fingers[finger];
var direction = Vec3.normalize(Vec3.subtract(checkPoint, origin)); var direction = Vec3.normalize(Vec3.subtract(checkPoint, origin));
origin = Vec3.multiply(1/sensorToWorldScale, origin); origin = Vec3.multiply(1/sensorToWorldScale, origin);
rayPicks[side][finger] = RayPick.createRayPick( rayPicks[side][finger] = RayPick.createRayPick(
{ {
"enabled": false, "enabled": false,
"joint": handJointNames[side], "joint": handJointNames[side],
"posOffset": origin, "posOffset": origin,
"dirOffset": direction, "dirOffset": direction,
"filter": RayPick.PICK_ENTITIES "filter": RayPick.PICK_ENTITIES
} }
); );
RayPick.setPrecisionPicking(rayPicks[side][finger], true); RayPick.setPrecisionPicking(rayPicks[side][finger], true);
} }
} }
function activateNextRay(side, index) { function activateNextRay(side, index) {
var nextIndex = (index < fingerKeys.length-1) ? index + 1 : 0; var nextIndex = (index < fingerKeys.length-1) ? index + 1 : 0;
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
@ -641,46 +633,44 @@
RayPick.enableRayPick(rayPicks[side][finger]); RayPick.enableRayPick(rayPicks[side][finger]);
} else { } else {
RayPick.disableRayPick(rayPicks[side][finger]); RayPick.disableRayPick(rayPicks[side][finger]);
} }
} }
} }
function updateSphereHand(side) {
function updateSphereHand(side) {
var data = new Palm(); var data = new Palm();
dataRelativeToWorld(side, palmData[side], data); dataRelativeToWorld(side, palmData[side], data);
varsToDebug.palmData[side] = palmData[side]; varsToDebug.palmData[side] = palmData[side];
var palmPoint = data.position; var palmPoint = data.position;
var LOOKUP_DISTANCE_MULTIPLIER = 1.5; var LOOKUP_DISTANCE_MULTIPLIER = 1.5;
var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance;
// Situate the debugging overlays // Situate the debugging overlays
var checkOffset = {
var checkOffset = { x: data.perpendicular.x * dist,
x: data.perpendicular.x * dist, y: data.perpendicular.y * dist,
y: data.perpendicular.y * dist, z: data.perpendicular.z * dist
z: data.perpendicular.z * dist
}; };
var spherePos = Vec3.sum(palmPoint, checkOffset); var spherePos = Vec3.sum(palmPoint, checkOffset);
var checkPoint = Vec3.sum(palmPoint, Vec3.multiply(2, checkOffset)); var checkPoint = Vec3.sum(palmPoint, Vec3.multiply(2, checkOffset));
if (showLines) { if (showLines) {
Overlays.editOverlay(palmRay[side], { Overlays.editOverlay(palmRay[side], {
start: palmPoint, start: palmPoint,
end: checkPoint, end: checkPoint,
visible: showLines visible: showLines
}); });
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
Overlays.editOverlay(fingerRays[side][fingerKeys[i]], { Overlays.editOverlay(fingerRays[side][fingerKeys[i]], {
start: data.fingers[fingerKeys[i]], start: data.fingers[fingerKeys[i]],
end: checkPoint, end: checkPoint,
visible: showLines visible: showLines
}); });
} }
} }
if (showSphere) { if (showSphere) {
Overlays.editOverlay(sphereHand[side], { Overlays.editOverlay(sphereHand[side], {
position: spherePos, position: spherePos,
@ -690,16 +680,16 @@
z: 2*dist z: 2*dist
}, },
visible: showSphere visible: showSphere
}); });
} }
// Update the intersection of only one finger at a time // Update the intersection of only one finger at a time
var finger = fingerKeys[updateFingerWithIndex];
var finger = fingerKeys[updateFingerWithIndex]; var nearbyEntities = Entities.findEntities(spherePos, dist);
// Filter the entities that are allowed to be touched
var touchableEntities = nearbyEntities.filter(function (id) {
var grabbables = Entities.findEntities(spherePos, dist); return untouchableEntities.indexOf(id) == -1;
});
var intersection; var intersection;
if (rayPicks[side][finger] !== undefined) { if (rayPicks[side][finger] !== undefined) {
intersection = RayPick.getPrevRayPickResult(rayPicks[side][finger]); intersection = RayPick.getPrevRayPickResult(rayPicks[side][finger]);
@ -708,11 +698,10 @@
var animationSteps = defaultAnimationSteps; var animationSteps = defaultAnimationSteps;
var newFingerData = dataDefault[side][finger]; var newFingerData = dataDefault[side][finger];
var isAbleToGrab = false; var isAbleToGrab = false;
if (grabbables.length > 0) { if (touchableEntities.length > 0) {
RayPick.setIncludeItems(rayPicks[side][finger], touchableEntities);
RayPick.setIncludeItems(rayPicks[side][finger], grabbables);
if (intersection === undefined) { if (intersection === undefined) {
return; return;
} }
@ -725,28 +714,27 @@
// Store if this finger is touching something // Store if this finger is touching something
isTouching[side][finger] = isAbleToGrab; isTouching[side][finger] = isAbleToGrab;
if (isAbleToGrab) { if (isAbleToGrab) {
// update the open/close percentage for this finger // update the open/close percentage for this finger
var FINGER_REACT_MULTIPLIER = 2.8; var FINGER_REACT_MULTIPLIER = 2.8;
percent = intersection.distance/(FINGER_REACT_MULTIPLIER*dist); percent = intersection.distance/(FINGER_REACT_MULTIPLIER*dist);
var THUMB_FACTOR = 0.2; var THUMB_FACTOR = 0.2;
var FINGER_FACTOR = 0.05; var FINGER_FACTOR = 0.05;
// Amount of grab coefficient added to the fingers - thumb is higher // Amount of grab coefficient added to the fingers - thumb is higher
var grabMultiplier = finger === "thumb" ? THUMB_FACTOR : FINGER_FACTOR; var grabMultiplier = finger === "thumb" ? THUMB_FACTOR : FINGER_FACTOR;
percent += grabMultiplier * grabPercent[side]; percent += grabMultiplier * grabPercent[side];
// Calculate new interpolation data // Calculate new interpolation data
var totalDistance = addVals(dataClose[side][finger], dataOpen[side][finger], -1); var totalDistance = addVals(dataClose[side][finger], dataOpen[side][finger], -1);
// Assign close/open ratio to finger to simulate touch // Assign close/open ratio to finger to simulate touch
newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1); newFingerData = addVals(dataOpen[side][finger], multiplyValsBy(totalDistance, percent), 1);
animationSteps = touchAnimationSteps; animationSteps = touchAnimationSteps;
} }
varsToDebug.fingerPercent[side][finger] = percent; varsToDebug.fingerPercent[side][finger] = percent;
} }
if (!isAbleToGrab) { if (!isAbleToGrab) {
dataFailed[side][finger] = dataFailed[side][finger] === 0 ? 1 : 2; dataFailed[side][finger] = dataFailed[side][finger] === 0 ? 1 : 2;
} else { } else {
@ -755,13 +743,12 @@
// If it only fails once it will not update increments // If it only fails once it will not update increments
if (dataFailed[side][finger] !== 1) { if (dataFailed[side][finger] !== 1) {
// Calculate animation increments // Calculate animation increments
dataDelta[side][finger] = dataDelta[side][finger] =
multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps); multiplyValsBy(addVals(newFingerData, dataCurrent[side][finger], -1), 1.0/animationSteps);
} }
} }
// Recreate the finger joint names // Recreate the finger joint names
function getJointNames(side, finger, count) { function getJointNames(side, finger, count) {
var names = []; var names = [];
for (var i = 1; i < count+1; i++) { for (var i = 1; i < count+1; i++) {
@ -772,30 +759,34 @@
} }
// Capture the controller values // Capture the controller values
var leftTriggerPress = function (value) { var leftTriggerPress = function (value) {
varsToDebug.triggerValues.leftTriggerValue = value; varsToDebug.triggerValues.leftTriggerValue = value;
// the value for the trigger increments the hand-close percentage // the value for the trigger increments the hand-close percentage
grabPercent.left = value; grabPercent.left = value;
}; };
var leftTriggerClick = function (value) { var leftTriggerClick = function (value) {
varsToDebug.triggerValues.leftTriggerClicked = value; varsToDebug.triggerValues.leftTriggerClicked = value;
}; };
var rightTriggerPress = function (value) { var rightTriggerPress = function (value) {
varsToDebug.triggerValues.rightTriggerValue = value; varsToDebug.triggerValues.rightTriggerValue = value;
// the value for the trigger increments the hand-close percentage // the value for the trigger increments the hand-close percentage
grabPercent.right = value; grabPercent.right = value;
}; };
var rightTriggerClick = function (value) { var rightTriggerClick = function (value) {
varsToDebug.triggerValues.rightTriggerClicked = value; varsToDebug.triggerValues.rightTriggerClicked = value;
}; };
var leftSecondaryPress = function (value) { var leftSecondaryPress = function (value) {
varsToDebug.triggerValues.leftSecondaryValue = value; varsToDebug.triggerValues.leftSecondaryValue = value;
}; };
var rightSecondaryPress = function (value) { var rightSecondaryPress = function (value) {
varsToDebug.triggerValues.rightSecondaryValue = value; varsToDebug.triggerValues.rightSecondaryValue = value;
}; };
var MAPPING_NAME = "com.highfidelity.handTouch"; var MAPPING_NAME = "com.highfidelity.handTouch";
var mapping = Controller.newMapping(MAPPING_NAME); var mapping = Controller.newMapping(MAPPING_NAME);
mapping.from([Controller.Standard.RT]).peek().to(rightTriggerPress); mapping.from([Controller.Standard.RT]).peek().to(rightTriggerPress);
@ -809,16 +800,17 @@
mapping.from([Controller.Standard.RightGrip]).peek().to(rightSecondaryPress); mapping.from([Controller.Standard.RightGrip]).peek().to(rightSecondaryPress);
Controller.enableMapping(MAPPING_NAME); Controller.enableMapping(MAPPING_NAME);
if (showLines && !linesCreated) { if (showLines && !linesCreated) {
createDebugLines(); createDebugLines();
linesCreated = true; linesCreated = true;
} }
if (showSphere && !sphereCreated) { if (showSphere && !sphereCreated) {
createDebugSphere(); createDebugSphere();
sphereCreated = true; sphereCreated = true;
} }
function getTouching(side) { function getTouching(side) {
var animating = false; var animating = false;
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
@ -827,19 +819,70 @@
} }
return animating; // return false only if none of the fingers are touching return animating; // return false only if none of the fingers are touching
} }
function reEstimatePalmData() { function reEstimatePalmData() {
["right", "left"].forEach(function(side) { ["right", "left"].forEach(function(side) {
estimatePalmData(side); estimatePalmData(side);
}); });
} }
function recreateRayPicks() { function recreateRayPicks() {
["right", "left"].forEach(function(side) { ["right", "left"].forEach(function(side) {
createRayPicks(side); createRayPicks(side);
}); });
} }
function cleanUp() {
["right", "left"].forEach(function (side) {
if (linesCreated) {
Overlays.deleteOverlay(palmRay[side]);
}
if (sphereCreated) {
Overlays.deleteOverlay(sphereHand[side]);
}
clearRayPicks(side);
for (var i = 0; i < fingerKeys.length; i++) {
var finger = fingerKeys[i];
var jointSuffixes = 3; // We need to clear the joints 0, 1 and 2 joints
var names = getJointNames(side, finger, jointSuffixes);
for (var j = 0; j < names.length; j++) {
var index = MyAvatar.getJointIndex(names[j]);
MyAvatar.clearJointData(index);
}
if (linesCreated) {
Overlays.deleteOverlay(fingerRays[side][finger]);
}
}
});
}
MyAvatar.shouldDisableHandTouchChanged.connect(function (shouldDisable) {
if (shouldDisable) {
if (handTouchEnabled) {
cleanUp();
}
} else {
if (!handTouchEnabled) {
reEstimatePalmData();
recreateRayPicks();
}
}
handTouchEnabled = !shouldDisable;
});
MyAvatar.disableHandTouchForIDChanged.connect(function (entityID, disable) {
var entityIndex = untouchableEntities.indexOf(entityID);
if (disable) {
if (entityIndex == -1) {
untouchableEntities.push(entityID);
}
} else {
if (entityIndex != -1) {
untouchableEntities.splice(entityIndex, 1);
}
}
});
MyAvatar.onLoadComplete.connect(function () { MyAvatar.onLoadComplete.connect(function () {
// Sometimes the rig is not ready when this signal is trigger // Sometimes the rig is not ready when this signal is trigger
console.log("avatar loaded"); console.log("avatar loaded");
@ -848,78 +891,55 @@
recreateRayPicks(); recreateRayPicks();
}, MSECONDS_AFTER_LOAD); }, MSECONDS_AFTER_LOAD);
}); });
MyAvatar.sensorToWorldScaleChanged.connect(function() { MyAvatar.sensorToWorldScaleChanged.connect(function() {
reEstimatePalmData(); reEstimatePalmData();
}); });
Script.scriptEnding.connect(function () {
["right", "left"].forEach(function(side) {
if (linesCreated) {
Overlays.deleteOverlay(palmRay[side]);
}
if (sphereCreated) {
Overlays.deleteOverlay(sphereHand[side]);
}
clearRayPicks(side);
for (var i = 0; i < fingerKeys.length; i++) {
var finger = fingerKeys[i]; Script.scriptEnding.connect(function () {
var jointSuffixes = 3; // We need to clear the joints 0, 1 and 2 joints cleanUp();
var names = getJointNames(side, finger, jointSuffixes);
for (var j = 0; j < names.length; j++) {
var index = MyAvatar.getJointIndex(names[j]);
MyAvatar.clearJointData(index);
}
if (linesCreated) {
Overlays.deleteOverlay(fingerRays[side][finger]);
}
}
});
}); });
Script.update.connect(function() { Script.update.connect(function () {
if (!handTouchEnabled) {
return;
}
// index of the finger that needs to be updated this frame // index of the finger that needs to be updated this frame
updateFingerWithIndex = (updateFingerWithIndex < fingerKeys.length-1) ? updateFingerWithIndex + 1 : 0; updateFingerWithIndex = (updateFingerWithIndex < fingerKeys.length-1) ? updateFingerWithIndex + 1 : 0;
["right", "left"].forEach(function(side) { ["right", "left"].forEach(function(side) {
if (!palmData[side].set) { if (!palmData[side].set) {
reEstimatePalmData(); reEstimatePalmData();
recreateRayPicks(); recreateRayPicks();
} }
// recalculate the base data // recalculate the base data
updateSphereHand(side); updateSphereHand(side);
activateNextRay(side, updateFingerWithIndex); activateNextRay(side, updateFingerWithIndex);
// this vars manage the transition to default pose // this vars manage the transition to default pose
var isHandTouching = getTouching(side); var isHandTouching = getTouching(side);
countToDefault[side] = isHandTouching ? 0 : countToDefault[side] + 1; countToDefault[side] = isHandTouching ? 0 : countToDefault[side] + 1;
for (var i = 0; i < fingerKeys.length; i++) { for (var i = 0; i < fingerKeys.length; i++) {
var finger = fingerKeys[i]; var finger = fingerKeys[i];
var jointSuffixes = 3; // We need to update rotation of the 0, 1 and 2 joints var jointSuffixes = 3; // We need to update rotation of the 0, 1 and 2 joints
var names = getJointNames(side, finger, jointSuffixes); var names = getJointNames(side, finger, jointSuffixes);
// Add the animation increments // Add the animation increments
dataCurrent[side][finger] = addVals(dataCurrent[side][finger], dataDelta[side][finger], 1);
dataCurrent[side][finger] = addVals(dataCurrent[side][finger], dataDelta[side][finger], 1);
// update every finger joint // update every finger joint
for (var j = 0; j < names.length; j++) { for (var j = 0; j < names.length; j++) {
var index = MyAvatar.getJointIndex(names[j]); var index = MyAvatar.getJointIndex(names[j]);
// if no finger is touching restate the default poses // if no finger is touching restate the default poses
if (isHandTouching || (dataDefault[side].set && if (isHandTouching || (dataDefault[side].set &&
countToDefault[side] < fingerKeys.length*touchAnimationSteps)) { countToDefault[side] < fingerKeys.length*touchAnimationSteps)) {
var quatRot = dataCurrent[side][finger][j]; var quatRot = dataCurrent[side][finger][j];
MyAvatar.setJointRotation(index, quatRot); MyAvatar.setJointRotation(index, quatRot);
} else { } else {
MyAvatar.clearJointData(index); MyAvatar.clearJointData(index);
} }

View file

@ -63,6 +63,15 @@ var createToolsWindow = new CreateWindow(
false false
); );
/**
* @description Returns true in case we should use the tablet version of the CreateApp
* @returns boolean
*/
var shouldUseEditTabletApp = function() {
return HMD.active || (!HMD.active && !Settings.getValue("desktopTabletBecomesToolbar", true));
};
var selectionDisplay = SelectionDisplay; var selectionDisplay = SelectionDisplay;
var selectionManager = SelectionManager; var selectionManager = SelectionManager;
@ -88,11 +97,12 @@ var cameraManager = new CameraManager();
var grid = new Grid(); var grid = new Grid();
var gridTool = new GridTool({ var gridTool = new GridTool({
horizontalGrid: grid, horizontalGrid: grid,
createToolsWindow: createToolsWindow createToolsWindow: createToolsWindow,
shouldUseEditTabletApp: shouldUseEditTabletApp
}); });
gridTool.setVisible(false); gridTool.setVisible(false);
var entityListTool = new EntityListTool(); var entityListTool = new EntityListTool(shouldUseEditTabletApp);
selectionManager.addEventListener(function () { selectionManager.addEventListener(function () {
selectionDisplay.updateHandles(); selectionDisplay.updateHandles();
@ -578,7 +588,8 @@ var toolBar = (function () {
}); });
createButton = activeButton; createButton = activeButton;
tablet.screenChanged.connect(function (type, url) { tablet.screenChanged.connect(function (type, url) {
var isGoingToHomescreenOnDesktop = (!HMD.active && (url === 'hifi/tablet/TabletHome.qml' || url === '')); var isGoingToHomescreenOnDesktop = (!shouldUseEditTabletApp() &&
(url === 'hifi/tablet/TabletHome.qml' || url === ''));
if (isActive && (type !== "QML" || url !== "hifi/tablet/Edit.qml") && !isGoingToHomescreenOnDesktop) { if (isActive && (type !== "QML" || url !== "hifi/tablet/Edit.qml") && !isGoingToHomescreenOnDesktop) {
that.setActive(false); that.setActive(false);
} }
@ -605,7 +616,7 @@ var toolBar = (function () {
}); });
function createNewEntityDialogButtonCallback(entityType) { function createNewEntityDialogButtonCallback(entityType) {
return function() { return function() {
if (HMD.active) { if (shouldUseEditTabletApp()) {
// tablet version of new-model dialog // tablet version of new-model dialog
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
tablet.pushOntoStack("hifi/tablet/New" + entityType + "Dialog.qml"); tablet.pushOntoStack("hifi/tablet/New" + entityType + "Dialog.qml");
@ -837,7 +848,7 @@ var toolBar = (function () {
selectionDisplay.triggerMapping.disable(); selectionDisplay.triggerMapping.disable();
tablet.landscape = false; tablet.landscape = false;
} else { } else {
if (HMD.active) { if (shouldUseEditTabletApp()) {
tablet.loadQMLSource("hifi/tablet/Edit.qml", true); tablet.loadQMLSource("hifi/tablet/Edit.qml", true);
} else { } else {
// make other apps inactive while in desktop mode // make other apps inactive while in desktop mode
@ -1989,8 +2000,8 @@ var PropertiesTool = function (opts) {
that.setVisible = function (newVisible) { that.setVisible = function (newVisible) {
visible = newVisible; visible = newVisible;
webView.setVisible(HMD.active && visible); webView.setVisible(shouldUseEditTabletApp() && visible);
createToolsWindow.setVisible(!HMD.active && visible); createToolsWindow.setVisible(!shouldUseEditTabletApp() && visible);
}; };
that.setVisible(false); that.setVisible(false);
@ -2416,7 +2427,7 @@ function selectParticleEntity(entityID) {
// Switch to particle explorer // Switch to particle explorer
var selectTabMethod = { method: 'selectTab', params: { id: 'particle' } }; var selectTabMethod = { method: 'selectTab', params: { id: 'particle' } };
if (HMD.active) { if (shouldUseEditTabletApp()) {
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
tablet.sendToQml(selectTabMethod); tablet.sendToQml(selectTabMethod);
} else { } else {

View file

@ -11,7 +11,7 @@
/* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages, /* global EntityListTool, Tablet, selectionManager, Entities, Camera, MyAvatar, Vec3, Menu, Messages,
cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible */ cameraManager, MENU_EASE_ON_FOCUS, deleteSelectedEntities, toggleSelectedEntitiesLocked, toggleSelectedEntitiesVisible */
EntityListTool = function() { EntityListTool = function(shouldUseEditTabletApp) {
var that = {}; var that = {};
var CreateWindow = Script.require('../modules/createWindow.js'); var CreateWindow = Script.require('../modules/createWindow.js');
@ -55,8 +55,8 @@ EntityListTool = function() {
that.setVisible = function(newVisible) { that.setVisible = function(newVisible) {
visible = newVisible; visible = newVisible;
webView.setVisible(HMD.active && visible); webView.setVisible(shouldUseEditTabletApp() && visible);
entityListWindow.setVisible(!HMD.active && visible); entityListWindow.setVisible(!shouldUseEditTabletApp() && visible);
}; };
that.setVisible(false); that.setVisible(false);

View file

@ -1,6 +1,6 @@
var GRID_CONTROLS_HTML_URL = Script.resolvePath('../html/gridControls.html'); var GRID_CONTROLS_HTML_URL = Script.resolvePath('../html/gridControls.html');
Grid = function(opts) { Grid = function() {
var that = {}; var that = {};
var gridColor = { red: 0, green: 0, blue: 0 }; var gridColor = { red: 0, green: 0, blue: 0 };
var gridAlpha = 0.6; var gridAlpha = 0.6;
@ -247,6 +247,7 @@ GridTool = function(opts) {
var horizontalGrid = opts.horizontalGrid; var horizontalGrid = opts.horizontalGrid;
var verticalGrid = opts.verticalGrid; var verticalGrid = opts.verticalGrid;
var createToolsWindow = opts.createToolsWindow; var createToolsWindow = opts.createToolsWindow;
var shouldUseEditTabletApp = opts.shouldUseEditTabletApp;
var listeners = []; var listeners = [];
var webView = null; var webView = null;
@ -299,7 +300,7 @@ GridTool = function(opts) {
}; };
that.setVisible = function(visible) { that.setVisible = function(visible) {
webView.setVisible(HMD.active && visible); webView.setVisible(shouldUseEditTabletApp() && visible);
}; };
return that; return that;