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

This commit is contained in:
samcake 2015-12-08 09:21:45 -08:00
commit 4b03001c61
9 changed files with 132 additions and 53 deletions

View file

@ -20,6 +20,9 @@ var leapHands = (function () {
hasHandAndWristJoints, hasHandAndWristJoints,
handToWristOffset = [], // For avatars without a wrist joint we control an estimate of a proper hand joint position handToWristOffset = [], // For avatars without a wrist joint we control an estimate of a proper hand joint position
HAND_OFFSET = 0.4, // Relative distance of wrist to hand versus wrist to index finger knuckle HAND_OFFSET = 0.4, // Relative distance of wrist to hand versus wrist to index finger knuckle
handAnimationStateHandlers,
handAnimationStateFunctions,
handAnimationStateProperties,
hands, hands,
wrists, wrists,
NUM_HANDS = 2, // 0 = left; 1 = right NUM_HANDS = 2, // 0 = left; 1 = right
@ -37,7 +40,14 @@ var leapHands = (function () {
avatarScale, avatarScale,
avatarFaceModelURL, avatarFaceModelURL,
avatarSkeletonModelURL, avatarSkeletonModelURL,
settingsTimer; settingsTimer,
HMD_CAMERA_TO_AVATAR_ROTATION = [
Quat.angleAxis(180.0, { x: 0, y: 0, z: 1 }),
Quat.angleAxis(-180.0, { x: 0, y: 0, z: 1 })
],
DESKTOP_CAMERA_TO_AVATAR_ROTATION =
Quat.multiply(Quat.angleAxis(180.0, { x: 0, y: 1, z: 0 }), Quat.angleAxis(90.0, { x: 0, y: 0, z: 1 })),
LEAP_THUMB_ROOT_ADJUST = [Quat.fromPitchYawRollDegrees(0, 0, 20), Quat.fromPitchYawRollDegrees(0, 0, -20)];
function printSkeletonJointNames() { function printSkeletonJointNames() {
var jointNames, var jointNames,
@ -125,6 +135,26 @@ var leapHands = (function () {
*/ */
} }
function animateLeftHand() {
var ROTATION_AND_POSITION = 0;
return {
leftHandType: ROTATION_AND_POSITION,
leftHandPosition: hands[0].position,
leftHandRotation: hands[0].rotation
};
}
function animateRightHand() {
var ROTATION_AND_POSITION = 0;
return {
rightHandType: ROTATION_AND_POSITION,
rightHandPosition: hands[1].position,
rightHandRotation: hands[1].rotation
};
}
function finishCalibration() { function finishCalibration() {
var avatarPosition, var avatarPosition,
handPosition, handPosition,
@ -166,10 +196,8 @@ var leapHands = (function () {
MyAvatar.clearJointData("LeftHand"); MyAvatar.clearJointData("LeftHand");
MyAvatar.clearJointData("LeftForeArm"); MyAvatar.clearJointData("LeftForeArm");
MyAvatar.clearJointData("LeftArm");
MyAvatar.clearJointData("RightHand"); MyAvatar.clearJointData("RightHand");
MyAvatar.clearJointData("RightForeArm"); MyAvatar.clearJointData("RightForeArm");
MyAvatar.clearJointData("RightArm");
calibrationStatus = CALIBRATED; calibrationStatus = CALIBRATED;
print("Leap Motion: Calibrated"); print("Leap Motion: Calibrated");
@ -193,12 +221,10 @@ var leapHands = (function () {
} }
// Set avatar arms vertical, forearms horizontal, as "zero" position for calibration // Set avatar arms vertical, forearms horizontal, as "zero" position for calibration
MyAvatar.setJointRotation("LeftArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 0.0)); MyAvatar.setJointRotation("LeftForeArm", Quat.fromPitchYawRollDegrees(0.0, 0.0, 90.0));
MyAvatar.setJointRotation("LeftForeArm", Quat.fromPitchYawRollDegrees(0.0, 90.0, 90.0)); MyAvatar.setJointRotation("LeftHand", Quat.fromPitchYawRollDegrees(0.0, 90.0, 0.0));
MyAvatar.setJointRotation("LeftHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0)); MyAvatar.setJointRotation("RightForeArm", Quat.fromPitchYawRollDegrees(0.0, 0.0, -90.0));
MyAvatar.setJointRotation("RightArm", Quat.fromPitchYawRollDegrees(90.0, 0.0, 0.0)); MyAvatar.setJointRotation("RightHand", Quat.fromPitchYawRollDegrees(0.0, -90.0, 0.0));
MyAvatar.setJointRotation("RightForeArm", Quat.fromPitchYawRollDegrees(0.0, -90.0, -90.0));
MyAvatar.setJointRotation("RightHand", Quat.fromPitchYawRollRadians(0.0, 0.0, 0.0));
// Wait for arms to assume their positions before calculating // Wait for arms to assume their positions before calculating
Script.setTimeout(finishCalibration, CALIBRATION_TIME); Script.setTimeout(finishCalibration, CALIBRATION_TIME);
@ -319,6 +345,13 @@ var leapHands = (function () {
] ]
]; ];
handAnimationStateHandlers = [null, null];
handAnimationStateFunctions = [animateLeftHand, animateRightHand];
handAnimationStateProperties = [
["leftHandType", "leftHandPosition", "leftHandRotation"],
["rightHandType", "rightHandPosition", "rightHandPosition"]
];
setIsOnHMD(); setIsOnHMD();
settingsTimer = Script.setInterval(checkSettings, 2000); settingsTimer = Script.setInterval(checkSettings, 2000);
@ -348,6 +381,12 @@ var leapHands = (function () {
return; return;
} }
// Hand animation handlers ...
if (handAnimationStateHandlers[h] === null) {
handAnimationStateHandlers[h] = MyAvatar.addAnimationStateHandler(handAnimationStateFunctions[h],
handAnimationStateProperties[h]);
}
// Hand position ... // Hand position ...
handOffset = hands[h].controller.getAbsTranslation(); handOffset = hands[h].controller.getAbsTranslation();
handRotation = hands[h].controller.getAbsRotation(); handRotation = hands[h].controller.getAbsRotation();
@ -362,37 +401,41 @@ var leapHands = (function () {
// Hand offset in camera coordinates ... // Hand offset in camera coordinates ...
handOffset = { handOffset = {
x: hands[h].zeroPosition.x - handOffset.x, x: -handOffset.x,
y: hands[h].zeroPosition.y - handOffset.z, y: -handOffset.z,
z: hands[h].zeroPosition.z + handOffset.y z: -handOffset.y - hands[h].zeroPosition.z
}; };
handOffset.z = -handOffset.z;
// Hand offset in world coordinates ... // Hand offset in world coordinates ...
cameraOrientation = Camera.getOrientation(); cameraOrientation = Camera.getOrientation();
handOffset = Vec3.sum(Camera.getPosition(), Vec3.multiplyQbyV(cameraOrientation, handOffset)); handOffset = Vec3.sum(Camera.getPosition(), Vec3.multiplyQbyV(cameraOrientation, handOffset));
// Hand offset in avatar coordinates ... // Hand offset in avatar coordinates ...
inverseAvatarOrientation = Quat.inverse(MyAvatar.orientation); inverseAvatarOrientation = Quat.inverse(MyAvatar.orientation);
handOffset = Vec3.subtract(handOffset, MyAvatar.position); handOffset = Vec3.subtract(handOffset, MyAvatar.position);
handOffset = Vec3.multiplyQbyV(inverseAvatarOrientation, handOffset); handOffset = Vec3.multiplyQbyV(inverseAvatarOrientation, handOffset);
handOffset.z = -handOffset.z; handOffset.z = -handOffset.z;
handOffset.x = -handOffset.x; handOffset.x = -handOffset.x;
// Hand rotation in camera coordinates ... // Hand rotation in camera coordinates ...
handRotation = { handRotation = {
x: -handRotation.x, x: -handRotation.y,
y: -handRotation.z, y: -handRotation.z,
z: -handRotation.y, z: -handRotation.x,
w: handRotation.w w: handRotation.w
}; };
// Hand rotation in avatar coordinates ... // Hand rotation in avatar coordinates ...
handRotation = Quat.multiply(Quat.angleAxis(180.0, { x: 0, y: 1, z: 0 }), handRotation); handRotation = Quat.multiply(HMD_CAMERA_TO_AVATAR_ROTATION[h], handRotation);
cameraOrientation.x = -cameraOrientation.x; cameraOrientation = {
cameraOrientation.z = -cameraOrientation.z; x: cameraOrientation.z,
handRotation = Quat.multiply(cameraOrientation, handRotation); y: cameraOrientation.y,
handRotation = Quat.multiply(inverseAvatarOrientation, handRotation); z: cameraOrientation.x,
w: cameraOrientation.w
};
cameraOrientation = Quat.multiply(cameraOrientation, Quat.inverse(MyAvatar.orientation));
handRotation = Quat.multiply(handRotation, cameraOrientation); // Works!!!
} else { } else {
@ -411,18 +454,19 @@ var leapHands = (function () {
// Hand rotation in camera coordinates ... // Hand rotation in camera coordinates ...
handRotation = { handRotation = {
x: -handRotation.x, x: handRotation.z,
y: -handRotation.z, y: handRotation.y,
z: -handRotation.y, z: handRotation.x,
w: handRotation.w w: handRotation.w
}; };
// Hand rotation in avatar coordinates ... // Hand rotation in avatar coordinates ...
handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 1, y: 0, z: 0 }), handRotation); handRotation = Quat.multiply(DESKTOP_CAMERA_TO_AVATAR_ROTATION, handRotation);
} }
// Set hand position and orientation ... // Set hand position and orientation for animation state handler ...
MyAvatar.setJointModelPositionAndOrientation(hands[h].jointName, handOffset, handRotation, true); hands[h].position = handOffset;
hands[h].rotation = handRotation;
// Set finger joints ... // Set finger joints ...
for (i = 0; i < NUM_FINGERS; i += 1) { for (i = 0; i < NUM_FINGERS; i += 1) {
@ -436,6 +480,10 @@ var leapHands = (function () {
z: side * -locRotation.x, z: side * -locRotation.x,
w: locRotation.w w: locRotation.w
}; };
if (j === 0) {
// Adjust avatar thumb root joint rotation to make avatar hands look better
locRotation = Quat.multiply(LEAP_THUMB_ROOT_ADJUST[h], locRotation);
}
} else { } else {
locRotation = { locRotation = {
x: -locRotation.x, x: -locRotation.x,
@ -458,14 +506,9 @@ var leapHands = (function () {
hands[h].inactiveCount += 1; hands[h].inactiveCount += 1;
if (hands[h].inactiveCount === MAX_HAND_INACTIVE_COUNT) { if (hands[h].inactiveCount === MAX_HAND_INACTIVE_COUNT) {
if (h === 0) { if (handAnimationStateHandlers[h] !== null) {
MyAvatar.clearJointData("LeftHand"); MyAvatar.removeAnimationStateHandler(handAnimationStateHandlers[h]);
MyAvatar.clearJointData("LeftForeArm"); handAnimationStateHandlers[h] = null;
MyAvatar.clearJointData("LeftArm");
} else {
MyAvatar.clearJointData("RightHand");
MyAvatar.clearJointData("RightForeArm");
MyAvatar.clearJointData("RightArm");
} }
} }
} }
@ -483,6 +526,9 @@ var leapHands = (function () {
for (h = 0; h < NUM_HANDS; h += 1) { for (h = 0; h < NUM_HANDS; h += 1) {
Controller.releaseInputController(hands[h].controller); Controller.releaseInputController(hands[h].controller);
Controller.releaseInputController(wrists[h].controller); Controller.releaseInputController(wrists[h].controller);
if (handAnimationStateHandlers[h] !== null) {
MyAvatar.removeAnimationStateHandler(handAnimationStateHandlers[h]);
}
for (i = 0; i < NUM_FINGERS; i += 1) { for (i = 0; i < NUM_FINGERS; i += 1) {
for (j = 0; j < NUM_FINGER_JOINTS; j += 1) { for (j = 0; j < NUM_FINGER_JOINTS; j += 1) {
if (fingers[h][i][j].controller !== null) { if (fingers[h][i][j].controller !== null) {

View file

@ -1077,6 +1077,11 @@ void Application::initializeUi() {
} }
void Application::paintGL() { void Application::paintGL() {
// paintGL uses a queued connection, so we can get messages from the queue even after we've quit
// and the plugins have shutdown
if (_aboutToQuit) {
return;
}
_frameCount++; _frameCount++;
// update fps moving average // update fps moving average
@ -4071,7 +4076,7 @@ bool Application::canAcceptURL(const QString& urlString) {
QString lowerPath = url.path().toLower(); QString lowerPath = url.path().toLower();
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
if (lowerPath.endsWith(i.key())) { if (lowerPath.endsWith(i.key(), Qt::CaseInsensitive)) {
return true; return true;
} }
} }
@ -4091,7 +4096,7 @@ bool Application::acceptURL(const QString& urlString, bool defaultUpload) {
QString lowerPath = url.path().toLower(); QString lowerPath = url.path().toLower();
while (i.hasNext()) { while (i.hasNext()) {
i.next(); i.next();
if (lowerPath.endsWith(i.key())) { if (lowerPath.endsWith(i.key(), Qt::CaseInsensitive)) {
AcceptURLMethod method = i.value(); AcceptURLMethod method = i.value();
return (this->*method)(urlString); return (this->*method)(urlString);
} }
@ -4191,7 +4196,7 @@ bool Application::askToUploadAsset(const QString& filename) {
messageBox.setDefaultButton(QMessageBox::Ok); messageBox.setDefaultButton(QMessageBox::Ok);
// Option to drop model in world for models // Option to drop model in world for models
if (filename.endsWith(FBX_EXTENSION) || filename.endsWith(OBJ_EXTENSION)) { if (filename.endsWith(FBX_EXTENSION, Qt::CaseInsensitive) || filename.endsWith(OBJ_EXTENSION, Qt::CaseInsensitive)) {
auto checkBox = new QCheckBox(&messageBox); auto checkBox = new QCheckBox(&messageBox);
checkBox->setText("Add to scene"); checkBox->setText("Add to scene");
messageBox.setCheckBox(checkBox); messageBox.setCheckBox(checkBox);
@ -4226,7 +4231,8 @@ void Application::modelUploadFinished(AssetUpload* upload, const QString& hash)
auto filename = QFileInfo(upload->getFilename()).fileName(); auto filename = QFileInfo(upload->getFilename()).fileName();
if ((upload->getError() == AssetUpload::NoError) && if ((upload->getError() == AssetUpload::NoError) &&
(filename.endsWith(FBX_EXTENSION) || filename.endsWith(OBJ_EXTENSION))) { (upload->getExtension().endsWith(FBX_EXTENSION, Qt::CaseInsensitive) ||
upload->getExtension().endsWith(OBJ_EXTENSION, Qt::CaseInsensitive))) {
auto entities = DependencyManager::get<EntityScriptingInterface>(); auto entities = DependencyManager::get<EntityScriptingInterface>();

View file

@ -65,11 +65,6 @@ std::shared_ptr<Avatar> AvatarActionHold::getTarget(glm::quat& rotation, glm::ve
} }
} }
if (!isRightHand) {
static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
palmRotation *= yFlip; // Match right hand frame of reference
}
rotation = palmRotation * _relativeRotation; rotation = palmRotation * _relativeRotation;
position = palmPosition + rotation * _relativePosition; position = palmPosition + rotation * _relativePosition;
}); });
@ -218,14 +213,20 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
ok = true; ok = true;
kinematic = EntityActionInterface::extractBooleanArgument("hold", arguments, "kinematic", ok, false); kinematic = EntityActionInterface::extractBooleanArgument("hold", arguments, "kinematic", ok, false);
if (!ok) { if (!ok) {
_kinematic = false; kinematic = _kinematic;
} }
ok = true; ok = true;
kinematicSetVelocity = EntityActionInterface::extractBooleanArgument("hold", arguments, kinematicSetVelocity = EntityActionInterface::extractBooleanArgument("hold", arguments,
"kinematicSetVelocity", ok, false); "kinematicSetVelocity", ok, false);
if (!ok) { if (!ok) {
_kinematicSetVelocity = false; kinematicSetVelocity = _kinematicSetVelocity;
}
ok = true;
ignoreIK = EntityActionInterface::extractBooleanArgument("hold", arguments, "ignoreIK", ok, false);
if (!ok) {
ignoreIK = _ignoreIK;
} }
if (somethingChanged || if (somethingChanged ||

View file

@ -50,7 +50,7 @@ private:
bool _kinematic { false }; bool _kinematic { false };
bool _kinematicSetVelocity { false }; bool _kinematicSetVelocity { false };
bool _previousSet { false }; bool _previousSet { false };
bool _ignoreIK { true }; bool _ignoreIK { false };
glm::vec3 _previousPositionalTarget; glm::vec3 _previousPositionalTarget;
glm::quat _previousRotationalTarget; glm::quat _previousRotationalTarget;

View file

@ -33,8 +33,8 @@
const int PREFERENCES_HEIGHT_PADDING = 20; const int PREFERENCES_HEIGHT_PADDING = 20;
PreferencesDialog::PreferencesDialog(QWidget* parent) : PreferencesDialog::PreferencesDialog(QWidget* parent) :
QDialog(parent) { QDialog(parent)
{
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
ui.setupUi(this); ui.setupUi(this);
@ -48,10 +48,8 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) :
connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, qApp, &Application::loadDefaultScripts); connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, qApp, &Application::loadDefaultScripts);
connect(ui.buttonChangeAppearance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); connect(ui.buttonChangeAppearance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser);
connect(ui.appearanceDescription, &QLineEdit::textChanged, this, [this](const QString& url) { connect(ui.appearanceDescription, &QLineEdit::editingFinished, this, &PreferencesDialog::changeFullAvatarURL);
DependencyManager::get<AvatarManager>()->getMyAvatar()->useFullAvatarURL(url, "");
this->fullAvatarURLChanged(url, "");
});
connect(qApp, &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged); connect(qApp, &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged);
// move dialog to left side // move dialog to left side
@ -61,6 +59,11 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) :
UIUtil::scaleWidgetFontSizes(this); UIUtil::scaleWidgetFontSizes(this);
} }
void PreferencesDialog::changeFullAvatarURL() {
DependencyManager::get<AvatarManager>()->getMyAvatar()->useFullAvatarURL(ui.appearanceDescription->text(), "");
this->fullAvatarURLChanged(ui.appearanceDescription->text(), "");
}
void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) {
ui.appearanceDescription->setText(newValue); ui.appearanceDescription->setText(newValue);
const QString APPEARANCE_LABEL_TEXT("Appearance: "); const QString APPEARANCE_LABEL_TEXT("Appearance: ");
@ -69,9 +72,17 @@ void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QStr
void PreferencesDialog::accept() { void PreferencesDialog::accept() {
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar(); MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
// if there is an attempted change to the full avatar URL, apply it now
if (QUrl(ui.appearanceDescription->text()) != myAvatar->getFullAvatarURLFromPreferences()) {
changeFullAvatarURL();
}
_lastGoodAvatarURL = myAvatar->getFullAvatarURLFromPreferences(); _lastGoodAvatarURL = myAvatar->getFullAvatarURLFromPreferences();
_lastGoodAvatarName = myAvatar->getFullAvatarModelName(); _lastGoodAvatarName = myAvatar->getFullAvatarModelName();
savePreferences(); savePreferences();
close(); close();
delete _marketplaceWindow; delete _marketplaceWindow;
_marketplaceWindow = NULL; _marketplaceWindow = NULL;

View file

@ -49,6 +49,7 @@ private slots:
void openFullAvatarModelBrowser(); void openFullAvatarModelBrowser();
void openSnapshotLocationBrowser(); void openSnapshotLocationBrowser();
void openScriptsLocationBrowser(); void openScriptsLocationBrowser();
void changeFullAvatarURL();
void fullAvatarURLChanged(const QString& newValue, const QString& modelName); void fullAvatarURLChanged(const QString& newValue, const QString& modelName);
}; };

View file

@ -30,6 +30,12 @@ class PresentThread : public QThread, public Dependency {
using Lock = std::unique_lock<Mutex>; using Lock = std::unique_lock<Mutex>;
public: public:
PresentThread() {
connect(qApp, &QCoreApplication::aboutToQuit, [this]{
_shutdown = true;
});
}
~PresentThread() { ~PresentThread() {
_shutdown = true; _shutdown = true;
wait(); wait();
@ -99,6 +105,10 @@ public:
_context->doneCurrent(); _context->doneCurrent();
} }
_context->makeCurrent();
if (_activePlugin) {
_activePlugin->uncustomizeContext();
}
_context->doneCurrent(); _context->doneCurrent();
_context->moveToThread(qApp->thread()); _context->moveToThread(qApp->thread());
} }

View file

@ -337,6 +337,9 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
// a timer with a small interval is used to get better performance. // a timer with a small interval is used to get better performance.
_updateTimer.setInterval(MIN_TIMER_MS); _updateTimer.setInterval(MIN_TIMER_MS);
connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick); connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
QObject::connect(qApp, &QCoreApplication::aboutToQuit, [this]{
disconnect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
});
_updateTimer.start(); _updateTimer.start();
_qmlComponent = new QQmlComponent(_qmlEngine); _qmlComponent = new QQmlComponent(_qmlEngine);

View file

@ -63,6 +63,7 @@ void AssetUpload::start() {
// file opened, read the data and grab the extension // file opened, read the data and grab the extension
_extension = QFileInfo(_filename).suffix(); _extension = QFileInfo(_filename).suffix();
_extension = _extension.toLower();
_data = file.readAll(); _data = file.readAll();
} else { } else {