From 6274ab4aa7a2bdca59b2152b4a3b41965bcb94ae Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Sat, 31 Aug 2019 09:39:52 -0700 Subject: [PATCH 01/11] 3x3 blend wip --- .../animation/src/AnimBlendDirectional.cpp | 160 ++++++++++++++++++ .../animation/src/AnimBlendDirectional.h | 67 ++++++++ libraries/animation/src/AnimContext.h | 1 + libraries/animation/src/AnimNode.h | 9 + libraries/animation/src/AnimNodeLoader.cpp | 37 ++++ 5 files changed, 274 insertions(+) create mode 100644 libraries/animation/src/AnimBlendDirectional.cpp create mode 100644 libraries/animation/src/AnimBlendDirectional.h diff --git a/libraries/animation/src/AnimBlendDirectional.cpp b/libraries/animation/src/AnimBlendDirectional.cpp new file mode 100644 index 0000000000..36175c30d5 --- /dev/null +++ b/libraries/animation/src/AnimBlendDirectional.cpp @@ -0,0 +1,160 @@ +// +// AnimBlendDirectional.cpp +// +// Created by Anthony J. Thibault on Augest 30 2019. +// Copyright (c) 2019 High Fidelity, Inc. All rights reserved. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "AnimBlendDirectional.h" +#include "GLMHelpers.h" +#include "AnimationLogging.h" +#include "AnimUtil.h" + +AnimBlendDirectional::AnimBlendDirectional(const QString& id, float alpha, const QString& centerId, + const QString& upId, const QString& downId, const QString& leftId, const QString& rightId, + const QString& upLeftId, const QString& upRightId, const QString& downLeftId, const QString& downRightId) : + AnimNode(AnimNode::Type::BlendDirectional, id), + _alpha(alpha), + _upId(upId), + _downId(downId), + _leftId(leftId), + _rightId(rightId), + _upLeftId(upLeftId), + _upRightId(upRightId), + _downLeftId(downLeftId), + _downRightId(downRightId) { + +} + +AnimBlendDirectional::~AnimBlendDirectional() { + +} + +const AnimPoseVec& AnimBlendDirectional::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) { + + _alpha = animVars.lookup(_alphaVar, _alpha); + float parentDebugAlpha = context.getDebugAlpha(_id); + + /* + if (_children.size() == 0) { + for (auto&& pose : _poses) { + pose = AnimPose::identity; + } + } else if (_children.size() == 1) { + _poses = _children[0]->evaluate(animVars, context, dt, triggersOut); + context.setDebugAlpha(_children[0]->getID(), parentDebugAlpha, _children[0]->getType()); + } else if (_children.size() == 2 && _blendType != AnimBlendType_Normal) { + // special case for additive blending + float alpha = glm::clamp(_alpha, 0.0f, 1.0f); + const size_t prevPoseIndex = 0; + const size_t nextPoseIndex = 1; + evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, dt); + + // for animation stack debugging + float weight2 = alpha; + float weight1 = 1.0f - weight2; + context.setDebugAlpha(_children[prevPoseIndex]->getID(), weight1 * parentDebugAlpha, _children[prevPoseIndex]->getType()); + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); + + } else { + float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); + size_t prevPoseIndex = glm::floor(clampedAlpha); + size_t nextPoseIndex = glm::ceil(clampedAlpha); + auto alpha = glm::fract(clampedAlpha); + evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, dt); + + // weights are for animation stack debug purposes only. + float weight1 = 0.0f; + float weight2 = 0.0f; + if (prevPoseIndex == nextPoseIndex) { + weight2 = 1.0f; + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); + } else { + weight2 = alpha; + weight1 = 1.0f - weight2; + context.setDebugAlpha(_children[prevPoseIndex]->getID(), weight1 * parentDebugAlpha, _children[prevPoseIndex]->getType()); + context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); + } + } + processOutputJoints(triggersOut); + */ + + return _poses; +} + +// for AnimDebugDraw rendering +const AnimPoseVec& AnimBlendDirectional::getPosesInternal() const { + return _poses; +} + +/* +void AnimBlendDirectional::evaluateAndBlendChildren(const AnimVariantMap& animVars, const AnimContext& context, AnimVariantMap& triggersOut, float alpha, + size_t prevPoseIndex, size_t nextPoseIndex, float dt) { + if (prevPoseIndex == nextPoseIndex) { + // this can happen if alpha is on an integer boundary + _poses = _children[prevPoseIndex]->evaluate(animVars, context, dt, triggersOut); + } else { + // need to eval and blend between two children. + auto prevPoses = _children[prevPoseIndex]->evaluate(animVars, context, dt, triggersOut); + auto nextPoses = _children[nextPoseIndex]->evaluate(animVars, context, dt, triggersOut); + + if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) { + _poses.resize(prevPoses.size()); + + if (_blendType == AnimBlendType_Normal) { + ::blend(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); + } else if (_blendType == AnimBlendType_AddRelative) { + ::blendAdd(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); + } else if (_blendType == AnimBlendType_AddAbsolute) { + // convert prev from relative to absolute + AnimPoseVec absPrev = prevPoses; + _skeleton->convertRelativePosesToAbsolute(absPrev); + + // rotate the offset rotations from next into the parent relative frame of each joint. + AnimPoseVec relOffsetPoses; + relOffsetPoses.reserve(nextPoses.size()); + for (size_t i = 0; i < nextPoses.size(); ++i) { + + // copy translation and scale from nextPoses + AnimPose pose = nextPoses[i]; + + int parentIndex = _skeleton->getParentIndex((int)i); + if (parentIndex >= 0) { + // but transform nextPoses rot into absPrev parent frame. + pose.rot() = glm::inverse(absPrev[parentIndex].rot()) * pose.rot() * absPrev[parentIndex].rot(); + } + + relOffsetPoses.push_back(pose); + } + + // then blend + ::blendAdd(_poses.size(), &prevPoses[0], &relOffsetPoses[0], alpha, &_poses[0]); + } + } + } +} +*/ + +bool AnimBlendDirectional::lookupChildIds() { + _center = findChildIndexByName(_centerId); + _up = findChildIndexByName(_upId); + _down = findChildIndexByName(_downId); + _left = findChildIndexByName(_leftId); + _right = findChildIndexByName(_rightId); + _upLeft = findChildIndexByName(_upLeftId); + _upRight = findChildIndexByName(_upRightId); + _downLeft = findChildIndexByName(_downLeftId); + _downRight = findChildIndexByName(_downRightId); + + // manditory children + // TODO: currently all are manditory. + if (_center == -1 || _up == -1 || _down == -1 || _left == -1 || _right== -1 || + _upLeft == -1 || _upRight == -1 || _downLeft == -1 || _downRight == -1) { + return false; + } else { + return true; + } +} diff --git a/libraries/animation/src/AnimBlendDirectional.h b/libraries/animation/src/AnimBlendDirectional.h new file mode 100644 index 0000000000..0691168de5 --- /dev/null +++ b/libraries/animation/src/AnimBlendDirectional.h @@ -0,0 +1,67 @@ +// +// AnimBlendDirectonal.h +// +// Created by Anthony J. Thibault on Augest 30 2019. +// Copyright (c) 2019 High Fidelity, Inc. All rights reserved. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_AnimBlendDirectional_h +#define hifi_AnimBlendDirectional_h + +#include "AnimNode.h" + +// blend between up to nine AnimNodes. + +class AnimBlendDirectional : public AnimNode { +public: + friend class AnimTests; + + AnimBlendDirectional(const QString& id, float alpha, const QString& centerId, + const QString& upId, const QString& downId, const QString& leftId, const QString& rightId, + const QString& upLeftId, const QString& upRightId, const QString& downLeftId, const QString& downRightId); + virtual ~AnimBlendDirectional() override; + + virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) override; + + void setAlphaVar(const QString& alphaVar) { _alphaVar = alphaVar; } + + bool lookupChildIds(); + +protected: + // for AnimDebugDraw rendering + virtual const AnimPoseVec& getPosesInternal() const override; + + AnimPoseVec _poses; + + float _alpha; + QString _centerId; + QString _upId; + QString _downId; + QString _leftId; + QString _rightId; + QString _upLeftId; + QString _upRightId; + QString _downLeftId; + QString _downRightId; + + QString _alphaVar; + + int _center; + int _up; + int _down; + int _left; + int _right; + int _upLeft; + int _upRight; + int _downLeft; + int _downRight; + + // no copies + AnimBlendDirectional(const AnimBlendDirectional&) = delete; + AnimBlendDirectional& operator=(const AnimBlendDirectional&) = delete; +}; + +#endif // hifi_AnimBlendDirectional_h diff --git a/libraries/animation/src/AnimContext.h b/libraries/animation/src/AnimContext.h index 2ee8a30980..68b44c8f56 100644 --- a/libraries/animation/src/AnimContext.h +++ b/libraries/animation/src/AnimContext.h @@ -31,6 +31,7 @@ enum class AnimNodeType { TwoBoneIK, SplineIK, PoleVectorConstraint, + BlendDirectional, NumTypes }; diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index a0fb51e891..3dfe9dfe8c 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -99,6 +99,15 @@ public: return result; } + int findChildIndexByName(const QString& id) { + for (int i = 0; i < _children.size(); ++i) { + if (_children[i]->getID() == id) { + return i; + } + } + return -1; + } + const AnimPoseVec& getPoses() const { return getPosesInternal(); } protected: diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 100269c55c..6cb7bb47bd 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -29,6 +29,7 @@ #include "AnimTwoBoneIK.h" #include "AnimSplineIK.h" #include "AnimPoleVectorConstraint.h" +#include "AnimBlendDirectional.h" #include "AnimUtil.h" using NodeLoaderFunc = AnimNode::Pointer (*)(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); @@ -47,6 +48,7 @@ static AnimNode::Pointer loadDefaultPoseNode(const QJsonObject& jsonObj, const Q static AnimNode::Pointer loadTwoBoneIKNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static AnimNode::Pointer loadSplineIKNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static AnimNode::Pointer loadPoleVectorConstraintNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); +static AnimNode::Pointer loadBlendDirectionalNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static const float ANIM_GRAPH_LOAD_PRIORITY = 10.0f; @@ -55,6 +57,7 @@ static const float ANIM_GRAPH_LOAD_PRIORITY = 10.0f; static bool processDoNothing(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { return true; } bool processStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); bool processRandomSwitchStateMachineNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); +bool processBlendDirectionalNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl); static const char* animNodeTypeToString(AnimNode::Type type) { switch (type) { @@ -70,6 +73,7 @@ static const char* animNodeTypeToString(AnimNode::Type type) { case AnimNode::Type::TwoBoneIK: return "twoBoneIK"; case AnimNode::Type::SplineIK: return "splineIK"; case AnimNode::Type::PoleVectorConstraint: return "poleVectorConstraint"; + case AnimNode::Type::BlendDirectional: return "blendDirectional"; case AnimNode::Type::NumTypes: return nullptr; }; return nullptr; @@ -211,6 +215,7 @@ static NodeLoaderFunc animNodeTypeToLoaderFunc(AnimNode::Type type) { case AnimNode::Type::TwoBoneIK: return loadTwoBoneIKNode; case AnimNode::Type::SplineIK: return loadSplineIKNode; case AnimNode::Type::PoleVectorConstraint: return loadPoleVectorConstraintNode; + case AnimNode::Type::BlendDirectional: return loadBlendDirectionalNode; case AnimNode::Type::NumTypes: return nullptr; }; return nullptr; @@ -230,6 +235,7 @@ static NodeProcessFunc animNodeTypeToProcessFunc(AnimNode::Type type) { case AnimNode::Type::TwoBoneIK: return processDoNothing; case AnimNode::Type::SplineIK: return processDoNothing; case AnimNode::Type::PoleVectorConstraint: return processDoNothing; + case AnimNode::Type::BlendDirectional: return processBlendDirectionalNode; case AnimNode::Type::NumTypes: return nullptr; }; return nullptr; @@ -772,6 +778,32 @@ static AnimNode::Pointer loadPoleVectorConstraintNode(const QJsonObject& jsonObj return node; } +static AnimNode::Pointer loadBlendDirectionalNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { + + READ_FLOAT(alpha, jsonObj, id, jsonUrl, nullptr); + READ_OPTIONAL_STRING(alphaVar, jsonObj); + + READ_OPTIONAL_STRING(centerId, jsonObj); + READ_OPTIONAL_STRING(upId, jsonObj); + READ_OPTIONAL_STRING(downId, jsonObj); + READ_OPTIONAL_STRING(leftId, jsonObj); + READ_OPTIONAL_STRING(rightId, jsonObj); + READ_OPTIONAL_STRING(upLeftId, jsonObj); + READ_OPTIONAL_STRING(upRightId, jsonObj); + READ_OPTIONAL_STRING(downLeftId, jsonObj); + READ_OPTIONAL_STRING(downRightId, jsonObj); + + auto node = std::make_shared(id, alpha, centerId, + upId, downId, leftId, rightId, + upLeftId, upRightId, downLeftId, downRightId); + + if (!alphaVar.isEmpty()) { + node->setAlphaVar(alphaVar); + } + + return node; +} + void buildChildMap(std::map& map, AnimNode::Pointer node) { for (int i = 0; i < (int)node->getChildCount(); ++i) { map.insert(std::pair(node->getChild(i)->getID(), i)); @@ -1042,7 +1074,12 @@ bool processRandomSwitchStateMachineNode(AnimNode::Pointer node, const QJsonObje return true; } +bool processBlendDirectionalNode(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& nodeId, const QUrl& jsonUrl) { + auto blendNode = std::static_pointer_cast(node); + assert(blendNode); + return blendNode->lookupChildIds(); +} AnimNodeLoader::AnimNodeLoader(const QUrl& url) : _url(url) From 92df5cccdc6da1693fdb073d66f8fdb17b9c29f7 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Tue, 3 Sep 2019 17:34:30 -0700 Subject: [PATCH 02/11] AnimBlendDirectional node --- .../animation/src/AnimBlendDirectional.cpp | 186 ++++++++---------- .../animation/src/AnimBlendDirectional.h | 14 +- libraries/animation/src/AnimClip.cpp | 6 +- libraries/animation/src/AnimNodeLoader.cpp | 2 +- libraries/animation/src/AnimUtil.cpp | 25 +++ libraries/animation/src/AnimUtil.h | 41 ++++ libraries/animation/src/AnimVariant.cpp | 6 - 7 files changed, 157 insertions(+), 123 deletions(-) diff --git a/libraries/animation/src/AnimBlendDirectional.cpp b/libraries/animation/src/AnimBlendDirectional.cpp index 36175c30d5..c64aad07da 100644 --- a/libraries/animation/src/AnimBlendDirectional.cpp +++ b/libraries/animation/src/AnimBlendDirectional.cpp @@ -13,11 +13,12 @@ #include "AnimationLogging.h" #include "AnimUtil.h" -AnimBlendDirectional::AnimBlendDirectional(const QString& id, float alpha, const QString& centerId, +AnimBlendDirectional::AnimBlendDirectional(const QString& id, glm::vec3 alpha, const QString& centerId, const QString& upId, const QString& downId, const QString& leftId, const QString& rightId, const QString& upLeftId, const QString& upRightId, const QString& downLeftId, const QString& downRightId) : AnimNode(AnimNode::Type::BlendDirectional, id), _alpha(alpha), + _centerId(centerId), _upId(upId), _downId(downId), _leftId(leftId), @@ -35,52 +36,73 @@ AnimBlendDirectional::~AnimBlendDirectional() { const AnimPoseVec& AnimBlendDirectional::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, AnimVariantMap& triggersOut) { - _alpha = animVars.lookup(_alphaVar, _alpha); + // lookupRaw don't transform the vector. + _alpha = animVars.lookupRaw(_alphaVar, _alpha); float parentDebugAlpha = context.getDebugAlpha(_id); - /* - if (_children.size() == 0) { + if (_children.size() == 9) { + + // try to keep the order the same as quadrants, for _childIndices. + // +---+---+ + // | 1 | 0 | + // +---+---+ + // | 2 | 3 | + // +---+---+ + + std::array indices; + glm::vec2 alpha = _alpha; + if (_alpha.x > 0.0f) { + if (_alpha.y > 0.0f) { + // quadrant 0 + indices = { _childIndices[0][2], _childIndices[0][1], _childIndices[1][1], _childIndices[1][2] }; + } else { + // quadrant 3 + indices = { _childIndices[1][2], _childIndices[1][1], _childIndices[2][1], _childIndices[2][2] }; + // shift alpha up so both alpha.x and alpha.y are in the (0, 1) range. + alpha.y += 1.0f; + } + } else { + if (_alpha.y > 0.0f) { + // quadrant 1 + indices = { _childIndices[0][1], _childIndices[0][0], _childIndices[1][0], _childIndices[1][1] }; + // shift alpha right so both alpha.x and alpha.y are in the (0, 1) range. + alpha.x += 1.0f; + } else { + // quadrant 2 + indices = { _childIndices[1][1], _childIndices[1][0], _childIndices[2][0], _childIndices[2][1] }; + // shift alpha up and right so both alpha.x and alpha.y are in the (0, 1) range. + alpha.x += 1.0f; + alpha.y += 1.0f; + } + } + std::array alphas = { + alpha.x * alpha.y, + (1.0f - alpha.x) * alpha.y, + (1.0f - alpha.x) * (1.0f - alpha.y), + alpha.x * (1.0f - alpha.y) + }; + + // evaluate children + std::array poseVecs; + for (int i = 0; i < 4; i++) { + poseVecs[i] = _children[indices[i]]->evaluate(animVars, context, dt, triggersOut); + } + + // blend children + size_t minSize = INT_MAX; + for (int i = 0; i < 4; i++) { + if (poseVecs[i].size() < minSize) { + minSize = poseVecs[i].size(); + } + } + _poses.resize(minSize); + blend4(minSize, &poseVecs[0][0], &poseVecs[1][0], &poseVecs[2][0], &poseVecs[3][0], &alphas[0], &_poses[0]); + + } else { for (auto&& pose : _poses) { pose = AnimPose::identity; } - } else if (_children.size() == 1) { - _poses = _children[0]->evaluate(animVars, context, dt, triggersOut); - context.setDebugAlpha(_children[0]->getID(), parentDebugAlpha, _children[0]->getType()); - } else if (_children.size() == 2 && _blendType != AnimBlendType_Normal) { - // special case for additive blending - float alpha = glm::clamp(_alpha, 0.0f, 1.0f); - const size_t prevPoseIndex = 0; - const size_t nextPoseIndex = 1; - evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, dt); - - // for animation stack debugging - float weight2 = alpha; - float weight1 = 1.0f - weight2; - context.setDebugAlpha(_children[prevPoseIndex]->getID(), weight1 * parentDebugAlpha, _children[prevPoseIndex]->getType()); - context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); - - } else { - float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1)); - size_t prevPoseIndex = glm::floor(clampedAlpha); - size_t nextPoseIndex = glm::ceil(clampedAlpha); - auto alpha = glm::fract(clampedAlpha); - evaluateAndBlendChildren(animVars, context, triggersOut, alpha, prevPoseIndex, nextPoseIndex, dt); - - // weights are for animation stack debug purposes only. - float weight1 = 0.0f; - float weight2 = 0.0f; - if (prevPoseIndex == nextPoseIndex) { - weight2 = 1.0f; - context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); - } else { - weight2 = alpha; - weight1 = 1.0f - weight2; - context.setDebugAlpha(_children[prevPoseIndex]->getID(), weight1 * parentDebugAlpha, _children[prevPoseIndex]->getType()); - context.setDebugAlpha(_children[nextPoseIndex]->getID(), weight2 * parentDebugAlpha, _children[nextPoseIndex]->getType()); - } } - processOutputJoints(triggersOut); - */ return _poses; } @@ -90,71 +112,29 @@ const AnimPoseVec& AnimBlendDirectional::getPosesInternal() const { return _poses; } -/* -void AnimBlendDirectional::evaluateAndBlendChildren(const AnimVariantMap& animVars, const AnimContext& context, AnimVariantMap& triggersOut, float alpha, - size_t prevPoseIndex, size_t nextPoseIndex, float dt) { - if (prevPoseIndex == nextPoseIndex) { - // this can happen if alpha is on an integer boundary - _poses = _children[prevPoseIndex]->evaluate(animVars, context, dt, triggersOut); - } else { - // need to eval and blend between two children. - auto prevPoses = _children[prevPoseIndex]->evaluate(animVars, context, dt, triggersOut); - auto nextPoses = _children[nextPoseIndex]->evaluate(animVars, context, dt, triggersOut); - - if (prevPoses.size() > 0 && prevPoses.size() == nextPoses.size()) { - _poses.resize(prevPoses.size()); - - if (_blendType == AnimBlendType_Normal) { - ::blend(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); - } else if (_blendType == AnimBlendType_AddRelative) { - ::blendAdd(_poses.size(), &prevPoses[0], &nextPoses[0], alpha, &_poses[0]); - } else if (_blendType == AnimBlendType_AddAbsolute) { - // convert prev from relative to absolute - AnimPoseVec absPrev = prevPoses; - _skeleton->convertRelativePosesToAbsolute(absPrev); - - // rotate the offset rotations from next into the parent relative frame of each joint. - AnimPoseVec relOffsetPoses; - relOffsetPoses.reserve(nextPoses.size()); - for (size_t i = 0; i < nextPoses.size(); ++i) { - - // copy translation and scale from nextPoses - AnimPose pose = nextPoses[i]; - - int parentIndex = _skeleton->getParentIndex((int)i); - if (parentIndex >= 0) { - // but transform nextPoses rot into absPrev parent frame. - pose.rot() = glm::inverse(absPrev[parentIndex].rot()) * pose.rot() * absPrev[parentIndex].rot(); - } - - relOffsetPoses.push_back(pose); - } - - // then blend - ::blendAdd(_poses.size(), &prevPoses[0], &relOffsetPoses[0], alpha, &_poses[0]); - } - } - } -} -*/ - bool AnimBlendDirectional::lookupChildIds() { - _center = findChildIndexByName(_centerId); - _up = findChildIndexByName(_upId); - _down = findChildIndexByName(_downId); - _left = findChildIndexByName(_leftId); - _right = findChildIndexByName(_rightId); - _upLeft = findChildIndexByName(_upLeftId); - _upRight = findChildIndexByName(_upRightId); - _downLeft = findChildIndexByName(_downLeftId); - _downRight = findChildIndexByName(_downRightId); + _childIndices[0][0] = findChildIndexByName(_upLeftId); + _childIndices[0][1] = findChildIndexByName(_upId); + _childIndices[0][2] = findChildIndexByName(_upRightId); + + _childIndices[1][0] = findChildIndexByName(_leftId); + _childIndices[1][1] = findChildIndexByName(_centerId); + _childIndices[1][2] = findChildIndexByName(_rightId); + + _childIndices[2][0] = findChildIndexByName(_downLeftId); + _childIndices[2][1] = findChildIndexByName(_downId); + _childIndices[2][2] = findChildIndexByName(_downRightId); // manditory children // TODO: currently all are manditory. - if (_center == -1 || _up == -1 || _down == -1 || _left == -1 || _right== -1 || - _upLeft == -1 || _upRight == -1 || _downLeft == -1 || _downRight == -1) { - return false; - } else { - return true; + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + if (_childIndices[i][j] == -1) { + qDebug(animation) << "Error in AnimBlendDirectional::lookupChildIds() could not find child[" << i << "," << j << "]"; + return false; + } + } } + + return true; } diff --git a/libraries/animation/src/AnimBlendDirectional.h b/libraries/animation/src/AnimBlendDirectional.h index 0691168de5..9053012a79 100644 --- a/libraries/animation/src/AnimBlendDirectional.h +++ b/libraries/animation/src/AnimBlendDirectional.h @@ -19,7 +19,7 @@ class AnimBlendDirectional : public AnimNode { public: friend class AnimTests; - AnimBlendDirectional(const QString& id, float alpha, const QString& centerId, + AnimBlendDirectional(const QString& id, glm::vec3 alpha, const QString& centerId, const QString& upId, const QString& downId, const QString& leftId, const QString& rightId, const QString& upLeftId, const QString& upRightId, const QString& downLeftId, const QString& downRightId); virtual ~AnimBlendDirectional() override; @@ -36,7 +36,7 @@ protected: AnimPoseVec _poses; - float _alpha; + glm::vec3 _alpha; QString _centerId; QString _upId; QString _downId; @@ -49,15 +49,7 @@ protected: QString _alphaVar; - int _center; - int _up; - int _down; - int _left; - int _right; - int _upLeft; - int _upRight; - int _downLeft; - int _downRight; + int _childIndices[3][3]; // no copies AnimBlendDirectional(const AnimBlendDirectional&) = delete; diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 96bc87d738..1a33cc33d2 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -61,7 +61,7 @@ static void bakeRelativeDeltaAnim(std::vector& anim, const AnimPose } } -void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& basePoses, AnimSkeleton::ConstPointer skeleton) { +void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& basePoses, AnimSkeleton::ConstPointer skeleton, const QString& url, int baseFrame) { // invert all the basePoses AnimPoseVec invBasePoses = basePoses; @@ -73,6 +73,7 @@ void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& ba skeleton->convertRelativePosesToAbsolute(absBasePoses); // for each frame of the animation + int frame = 0; for (auto&& animPoses : anim) { ASSERT(animPoses.size() == basePoses.size()); @@ -88,6 +89,7 @@ void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& ba animPoses[i].rot() = absBasePoses[parentIndex].rot() * animPoses[i].rot() * glm::inverse(absBasePoses[parentIndex].rot()); } } + frame++; } } @@ -295,7 +297,7 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const Anim auto baseAnim = copyAndRetargetFromNetworkAnim(_baseNetworkAnim, _skeleton); if (_blendType == AnimBlendType_AddAbsolute) { - bakeAbsoluteDeltaAnim(_anim, baseAnim[(int)_baseFrame], _skeleton); + bakeAbsoluteDeltaAnim(_anim, baseAnim[(int)_baseFrame], _skeleton, _url, _baseFrame); } else { // AnimBlendType_AddRelative bakeRelativeDeltaAnim(_anim, baseAnim[(int)_baseFrame]); diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index 6cb7bb47bd..b9d104c442 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -780,7 +780,7 @@ static AnimNode::Pointer loadPoleVectorConstraintNode(const QJsonObject& jsonObj static AnimNode::Pointer loadBlendDirectionalNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) { - READ_FLOAT(alpha, jsonObj, id, jsonUrl, nullptr); + READ_VEC3(alpha, jsonObj, id, jsonUrl, nullptr); READ_OPTIONAL_STRING(alphaVar, jsonObj); READ_OPTIONAL_STRING(centerId, jsonObj); diff --git a/libraries/animation/src/AnimUtil.cpp b/libraries/animation/src/AnimUtil.cpp index e5f7cf4182..dff7bb194c 100644 --- a/libraries/animation/src/AnimUtil.cpp +++ b/libraries/animation/src/AnimUtil.cpp @@ -26,6 +26,31 @@ void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, A } } +void blend3(size_t numPoses, const AnimPose* a, const AnimPose* b, const AnimPose* c, float* alphas, AnimPose* result) { + for (size_t i = 0; i < numPoses; i++) { + const AnimPose& aPose = a[i]; + const AnimPose& bPose = b[i]; + const AnimPose& cPose = c[i]; + + result[i].scale() = alphas[0] * aPose.scale() + alphas[1] * bPose.scale() + alphas[2] * cPose.scale(); + result[i].rot() = safeLinearCombine3(aPose.rot(), bPose.rot(), cPose.rot(), alphas); + result[i].trans() = alphas[0] * aPose.trans() + alphas[1] * bPose.trans() + alphas[2] * cPose.trans(); + } +} + +void blend4(size_t numPoses, const AnimPose* a, const AnimPose* b, const AnimPose* c, const AnimPose* d, float* alphas, AnimPose* result) { + for (size_t i = 0; i < numPoses; i++) { + const AnimPose& aPose = a[i]; + const AnimPose& bPose = b[i]; + const AnimPose& cPose = c[i]; + const AnimPose& dPose = d[i]; + + result[i].scale() = alphas[0] * aPose.scale() + alphas[1] * bPose.scale() + alphas[2] * cPose.scale() + alphas[3] * dPose.scale(); + result[i].rot() = safeLinearCombine4(aPose.rot(), bPose.rot(), cPose.rot(), dPose.rot(), alphas); + result[i].trans() = alphas[0] * aPose.trans() + alphas[1] * bPose.trans() + alphas[2] * cPose.trans() + alphas[3] * dPose.trans(); + } +} + // additive blend void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result) { diff --git a/libraries/animation/src/AnimUtil.h b/libraries/animation/src/AnimUtil.h index 5d67b27abb..00bddb8b7e 100644 --- a/libraries/animation/src/AnimUtil.h +++ b/libraries/animation/src/AnimUtil.h @@ -16,6 +16,12 @@ // this is where the magic happens void blend(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result); +// blend between three sets of poses +void blend3(size_t numPoses, const AnimPose* a, const AnimPose* b, const AnimPose* c, float* alphas, AnimPose* result); + +// blend between four sets of poses +void blend4(size_t numPoses, const AnimPose* a, const AnimPose* b, const AnimPose* c, const AnimPose* d, float* alphas, AnimPose* result); + // additive blending void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha, AnimPose* result); @@ -34,6 +40,41 @@ inline glm::quat safeLerp(const glm::quat& a, const glm::quat& b, float alpha) { return glm::normalize(glm::lerp(a, bTemp, alpha)); } +inline glm::quat safeLinearCombine3(const glm::quat& a, const glm::quat& b, const glm::quat& c, float* alphas) { + // adjust signs for b & c if necessary + glm::quat bTemp = b; + float dot = glm::dot(a, bTemp); + if (dot < 0.0f) { + bTemp = -bTemp; + } + glm::quat cTemp = c; + dot = glm::dot(a, cTemp); + if (dot < 0.0f) { + cTemp = -cTemp; + } + return glm::normalize(alphas[0] * a + alphas[1] * bTemp + alphas[2] * cTemp); +} + +inline glm::quat safeLinearCombine4(const glm::quat& a, const glm::quat& b, const glm::quat& c, const glm::quat& d, float* alphas) { + // adjust signs for b, c & d if necessary + glm::quat bTemp = b; + float dot = glm::dot(a, bTemp); + if (dot < 0.0f) { + bTemp = -bTemp; + } + glm::quat cTemp = c; + dot = glm::dot(a, cTemp); + if (dot < 0.0f) { + cTemp = -cTemp; + } + glm::quat dTemp = d; + dot = glm::dot(a, dTemp); + if (dot < 0.0f) { + dTemp = -dTemp; + } + return glm::normalize(alphas[0] * a + alphas[1] * bTemp + alphas[2] * cTemp + alphas[3] * dTemp); +} + AnimPose boneLookAt(const glm::vec3& target, const AnimPose& bone); // This will attempt to determine the proper body facing of a characters body diff --git a/libraries/animation/src/AnimVariant.cpp b/libraries/animation/src/AnimVariant.cpp index 930dbed2d9..eb9e595c88 100644 --- a/libraries/animation/src/AnimVariant.cpp +++ b/libraries/animation/src/AnimVariant.cpp @@ -141,32 +141,26 @@ std::map AnimVariantMap::toDebugMap() const { break; case AnimVariant::Type::Vec3: { // To prevent filling up debug stats, don't show vec3 values - /* glm::vec3 value = pair.second.getVec3(); result[pair.first] = QString("(%1, %2, %3)"). arg(QString::number(value.x, 'f', 3)). arg(QString::number(value.y, 'f', 3)). arg(QString::number(value.z, 'f', 3)); - */ break; } case AnimVariant::Type::Quat: { // To prevent filling up the anim stats, don't show quat values - /* glm::quat value = pair.second.getQuat(); result[pair.first] = QString("(%1, %2, %3, %4)"). arg(QString::number(value.x, 'f', 3)). arg(QString::number(value.y, 'f', 3)). arg(QString::number(value.z, 'f', 3)). arg(QString::number(value.w, 'f', 3)); - */ break; } case AnimVariant::Type::String: // To prevent filling up anim stats, don't show string values - /* result[pair.first] = pair.second.getString(); - */ break; default: // invalid AnimVariant::Type From b6f28a6732f58edba952063c01e652a05f2e725a Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 4 Sep 2019 17:06:21 -0700 Subject: [PATCH 03/11] Switch additive animation deltas from a pre multiply to a post multiply. --- libraries/animation/src/AnimBlendLinear.cpp | 8 +++----- libraries/animation/src/AnimClip.cpp | 18 +++++++----------- libraries/animation/src/AnimUtil.cpp | 3 +-- 3 files changed, 11 insertions(+), 18 deletions(-) diff --git a/libraries/animation/src/AnimBlendLinear.cpp b/libraries/animation/src/AnimBlendLinear.cpp index c066dc92eb..d861f07847 100644 --- a/libraries/animation/src/AnimBlendLinear.cpp +++ b/libraries/animation/src/AnimBlendLinear.cpp @@ -110,11 +110,9 @@ void AnimBlendLinear::evaluateAndBlendChildren(const AnimVariantMap& animVars, c // copy translation and scale from nextPoses AnimPose pose = nextPoses[i]; - int parentIndex = _skeleton->getParentIndex((int)i); - if (parentIndex >= 0) { - // but transform nextPoses rot into absPrev parent frame. - pose.rot() = glm::inverse(absPrev[parentIndex].rot()) * pose.rot() * absPrev[parentIndex].rot(); - } + // convert from a rotation that happens in the absolute space of the joint + // into a rotation that happens in the relative space of the joint. + pose.rot() = glm::inverse(absPrev[i].rot()) * pose.rot() * absPrev[i].rot(); relOffsetPoses.push_back(pose); } diff --git a/libraries/animation/src/AnimClip.cpp b/libraries/animation/src/AnimClip.cpp index 1a33cc33d2..3476adc80c 100644 --- a/libraries/animation/src/AnimClip.cpp +++ b/libraries/animation/src/AnimClip.cpp @@ -56,12 +56,12 @@ static void bakeRelativeDeltaAnim(std::vector& anim, const AnimPose // for each joint in animPoses for (size_t i = 0; i < animPoses.size(); ++i) { // convert this relative AnimPose into a delta animation. - animPoses[i] = animPoses[i] * invBasePoses[i]; + animPoses[i] = invBasePoses[i] * animPoses[i]; } } } -void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& basePoses, AnimSkeleton::ConstPointer skeleton, const QString& url, int baseFrame) { +void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& basePoses, AnimSkeleton::ConstPointer skeleton) { // invert all the basePoses AnimPoseVec invBasePoses = basePoses; @@ -73,7 +73,6 @@ void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& ba skeleton->convertRelativePosesToAbsolute(absBasePoses); // for each frame of the animation - int frame = 0; for (auto&& animPoses : anim) { ASSERT(animPoses.size() == basePoses.size()); @@ -81,15 +80,12 @@ void bakeAbsoluteDeltaAnim(std::vector& anim, const AnimPoseVec& ba for (size_t i = 0; i < animPoses.size(); ++i) { // scale and translation are relative frame - animPoses[i] = animPoses[i] * invBasePoses[i]; + animPoses[i] = invBasePoses[i] * animPoses[i]; - // but transform the rotation delta into the absolute frame. - int parentIndex = skeleton->getParentIndex((int)i); - if (parentIndex >= 0) { - animPoses[i].rot() = absBasePoses[parentIndex].rot() * animPoses[i].rot() * glm::inverse(absBasePoses[parentIndex].rot()); - } + // convert from a rotation that happens in the relative space of the joint + // into a rotation that happens in the absolute space of the joint. + animPoses[i].rot() = absBasePoses[i].rot() * animPoses[i].rot() * glm::inverse(absBasePoses[i].rot()); } - frame++; } } @@ -297,7 +293,7 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, const Anim auto baseAnim = copyAndRetargetFromNetworkAnim(_baseNetworkAnim, _skeleton); if (_blendType == AnimBlendType_AddAbsolute) { - bakeAbsoluteDeltaAnim(_anim, baseAnim[(int)_baseFrame], _skeleton, _url, _baseFrame); + bakeAbsoluteDeltaAnim(_anim, baseAnim[(int)_baseFrame], _skeleton); } else { // AnimBlendType_AddRelative bakeRelativeDeltaAnim(_anim, baseAnim[(int)_baseFrame]); diff --git a/libraries/animation/src/AnimUtil.cpp b/libraries/animation/src/AnimUtil.cpp index dff7bb194c..8830cb78b1 100644 --- a/libraries/animation/src/AnimUtil.cpp +++ b/libraries/animation/src/AnimUtil.cpp @@ -68,8 +68,7 @@ void blendAdd(size_t numPoses, const AnimPose* a, const AnimPose* b, float alpha delta = -delta; } delta = glm::lerp(identity, delta, alpha); - result[i].rot() = glm::normalize(delta * aPose.rot()); - + result[i].rot() = glm::normalize(aPose.rot() * delta); result[i].trans() = aPose.trans() + (alpha * bPose.trans()); } } From 29de8a8d9faf37b2309eb3398bca8b89bdf4b809 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 5 Sep 2019 11:11:10 -0700 Subject: [PATCH 04/11] remove ajt comment --- libraries/animation/src/AnimNodeLoader.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/AnimNodeLoader.cpp b/libraries/animation/src/AnimNodeLoader.cpp index b9d104c442..9474c0309f 100644 --- a/libraries/animation/src/AnimNodeLoader.cpp +++ b/libraries/animation/src/AnimNodeLoader.cpp @@ -408,7 +408,6 @@ static AnimNode::Pointer loadClipNode(const QJsonObject& jsonObj, const QString& auto tempUrl = QUrl(url); tempUrl = jsonUrl.resolved(tempUrl); - // AJT: AnimBlendType blendTypeEnum = AnimBlendType_Normal; // default value if (!blendType.isEmpty()) { blendTypeEnum = stringToAnimBlendType(blendType); From c35640f73992a8e373c791b3041332b76821bef0 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 5 Sep 2019 14:54:19 -0700 Subject: [PATCH 05/11] Warning fixes and small bug fix to anim stats --- interface/src/ui/AnimStats.cpp | 2 +- libraries/animation/src/AnimBlendDirectional.cpp | 16 ++++++++++++---- libraries/avatars/src/ClientTraitsHandler.cpp | 3 +++ 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/interface/src/ui/AnimStats.cpp b/interface/src/ui/AnimStats.cpp index 47116ea281..2a355e48d1 100644 --- a/interface/src/ui/AnimStats.cpp +++ b/interface/src/ui/AnimStats.cpp @@ -118,7 +118,7 @@ void AnimStats::updateStats(bool force) { auto prevIter = _prevDebugAlphaMap.find(key); if (prevIter != _prevDebugAlphaMap.end()) { - float prevAlpha = std::get<0>(iter.second); + float prevAlpha = std::get<0>(prevIter->second); if (prevAlpha != alpha) { // change detected: reset timer _animAlphaValueChangedTimers[key] = now; diff --git a/libraries/animation/src/AnimBlendDirectional.cpp b/libraries/animation/src/AnimBlendDirectional.cpp index c64aad07da..d111a6fe08 100644 --- a/libraries/animation/src/AnimBlendDirectional.cpp +++ b/libraries/animation/src/AnimBlendDirectional.cpp @@ -54,22 +54,22 @@ const AnimPoseVec& AnimBlendDirectional::evaluate(const AnimVariantMap& animVars if (_alpha.x > 0.0f) { if (_alpha.y > 0.0f) { // quadrant 0 - indices = { _childIndices[0][2], _childIndices[0][1], _childIndices[1][1], _childIndices[1][2] }; + indices = {{_childIndices[0][2], _childIndices[0][1], _childIndices[1][1], _childIndices[1][2]}}; } else { // quadrant 3 - indices = { _childIndices[1][2], _childIndices[1][1], _childIndices[2][1], _childIndices[2][2] }; + indices = {{_childIndices[1][2], _childIndices[1][1], _childIndices[2][1], _childIndices[2][2]}}; // shift alpha up so both alpha.x and alpha.y are in the (0, 1) range. alpha.y += 1.0f; } } else { if (_alpha.y > 0.0f) { // quadrant 1 - indices = { _childIndices[0][1], _childIndices[0][0], _childIndices[1][0], _childIndices[1][1] }; + indices = {{_childIndices[0][1], _childIndices[0][0], _childIndices[1][0], _childIndices[1][1]}}; // shift alpha right so both alpha.x and alpha.y are in the (0, 1) range. alpha.x += 1.0f; } else { // quadrant 2 - indices = { _childIndices[1][1], _childIndices[1][0], _childIndices[2][0], _childIndices[2][1] }; + indices = {{_childIndices[1][1], _childIndices[1][0], _childIndices[2][0], _childIndices[2][1]}}; // shift alpha up and right so both alpha.x and alpha.y are in the (0, 1) range. alpha.x += 1.0f; alpha.y += 1.0f; @@ -98,6 +98,14 @@ const AnimPoseVec& AnimBlendDirectional::evaluate(const AnimVariantMap& animVars _poses.resize(minSize); blend4(minSize, &poseVecs[0][0], &poseVecs[1][0], &poseVecs[2][0], &poseVecs[3][0], &alphas[0], &_poses[0]); + // animation stack debug stats + for (int i = 0; i < 9; i++) { + context.setDebugAlpha(_children[i]->getID(), 0.0f, _children[i]->getType()); + } + for (int i = 0; i < 4; i++) { + context.setDebugAlpha(_children[indices[i]]->getID(), alphas[i] * parentDebugAlpha, _children[indices[i]]->getType()); + } + } else { for (auto&& pose : _poses) { pose = AnimPose::identity; diff --git a/libraries/avatars/src/ClientTraitsHandler.cpp b/libraries/avatars/src/ClientTraitsHandler.cpp index e133f178df..51f843b83c 100644 --- a/libraries/avatars/src/ClientTraitsHandler.cpp +++ b/libraries/avatars/src/ClientTraitsHandler.cpp @@ -171,6 +171,8 @@ void ClientTraitsHandler::processTraitOverride(QSharedPointer m return; } + // AJT: DON'T CHECK THIS IN, disable model URL overrides. + /* // only accept an override if this is for a trait type we override // and the version matches what we last sent for skeleton if (traitType == AvatarTraits::SkeletonModelURL @@ -192,6 +194,7 @@ void ClientTraitsHandler::processTraitOverride(QSharedPointer m } else { message->seek(message->getPosition() + traitBinarySize); } + */ } } } From aa848df2272add2e3fcd73e8485000454bf43309 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 5 Sep 2019 17:43:07 -0700 Subject: [PATCH 06/11] warning fixes --- libraries/animation/src/AnimBlendDirectional.cpp | 4 ++-- libraries/animation/src/AnimNode.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/animation/src/AnimBlendDirectional.cpp b/libraries/animation/src/AnimBlendDirectional.cpp index d111a6fe08..4e7c67f276 100644 --- a/libraries/animation/src/AnimBlendDirectional.cpp +++ b/libraries/animation/src/AnimBlendDirectional.cpp @@ -75,12 +75,12 @@ const AnimPoseVec& AnimBlendDirectional::evaluate(const AnimVariantMap& animVars alpha.y += 1.0f; } } - std::array alphas = { + std::array alphas = {{ alpha.x * alpha.y, (1.0f - alpha.x) * alpha.y, (1.0f - alpha.x) * (1.0f - alpha.y), alpha.x * (1.0f - alpha.y) - }; + }}; // evaluate children std::array poseVecs; diff --git a/libraries/animation/src/AnimNode.h b/libraries/animation/src/AnimNode.h index 3dfe9dfe8c..3ec671fcd7 100644 --- a/libraries/animation/src/AnimNode.h +++ b/libraries/animation/src/AnimNode.h @@ -100,9 +100,9 @@ public: } int findChildIndexByName(const QString& id) { - for (int i = 0; i < _children.size(); ++i) { + for (size_t i = 0; i < _children.size(); ++i) { if (_children[i]->getID() == id) { - return i; + return (int)i; } } return -1; From 120c678557159bbe8eb293ab98b27b572c43e2b8 Mon Sep 17 00:00:00 2001 From: milad Date: Fri, 6 Sep 2019 10:51:12 -0700 Subject: [PATCH 07/11] added a wearable check for avimojis on startup --- .../emojiApp/simplifiedEmoji.js | 27 +++++++++++++++++-- .../simplifiedEmote/simplifiedEmote.js | 2 +- scripts/simplifiedUI/ui/simplifiedUI.js | 1 + 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index a0fe6cf811..b005966951 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -79,7 +79,6 @@ function pruneOldAvimojis() { }); } - function maybeClearTimeoutDelete() { if (defaultTimeout) { Script.clearTimeout(defaultTimeout); @@ -157,6 +156,7 @@ function handleSelectedEmoji(emojiFilename) { } } + function onDomainChanged() { resetEmojis(); } @@ -167,6 +167,16 @@ function onScaleChanged() { } +function onAddingWearable(id) { + var props = Entities.getEntityProperties(id, ["name"]); + if (props.name.toLowerCase().indexOf("avimoji") > -1) { + Entities.deleteEntity(id); + } else { + return; + } +} + + // #endregion // ************************************* // END ui_handlers @@ -179,7 +189,13 @@ function onScaleChanged() { // what happens when we need to add an emoji over a user +var firstEmojiMadeOnStartup = false; function addEmoji(emojiFilename) { + if (!firstEmojiMadeOnStartup) { + firstEmojiMadeOnStartup = true; + Entities.addingWearable.disconnect(onAddingWearable); + } + if (currentEmoji) { resetEmojis(); } @@ -219,7 +235,8 @@ function createEmoji(emojiFilename) { "billboardMode": "full", "ignorePickIntersection": true, "alpha": 1, - "grab": { "grabbable": false } + "grab": { "grabbable": false }, + "userData": JSON.stringify({ timestamp: Date.now() }) }, "avatar"); maybePlayPop("in"); @@ -389,6 +406,7 @@ var emojiCodeMap; var customEmojiCodeMap; var signalsConnected = false; var _this; +var startupTimeStamp = Date.now(); function startup() { // make a map of just the utf codes to help with accesing emojiCodeMap = emojiList.reduce(function (codeMap, currentEmojiInList, index) { @@ -418,6 +436,7 @@ function startup() { Script.scriptEnding.connect(unload); Window.domainChanged.connect(onDomainChanged); MyAvatar.scaleChanged.connect(onScaleChanged); + Entities.addingWearable.connect(onAddingWearable); signalsConnected = true; function AviMoji() { @@ -457,6 +476,10 @@ function unload() { if (signalsConnected) { Window.domainChanged.disconnect(onDomainChanged); MyAvatar.scaleChanged.disconnect(onScaleChanged); + if (firstEmojiMadeOnStartup) { + Entities.addingWearable.disconnect(onAddingWearable); + } + signalsConnected = false; } } diff --git a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js index abf0dd73e8..f76ef72a33 100644 --- a/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js +++ b/scripts/simplifiedUI/simplifiedEmote/simplifiedEmote.js @@ -543,7 +543,7 @@ function onDisplayModeChanged(isHMDMode) { } -var emojiAPI = Script.require("./emojiApp/simplifiedEmoji.js"); +var emojiAPI = Script.require("./emojiApp/simplifiedEmoji.js?" + Date.now()); var keyPressSignalsConnected = false; var emojiCodeMap; var customEmojiCodeMap; diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index c388c594c9..d63b0294b2 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -590,6 +590,7 @@ var oldShowAudioTools; var oldShowBubbleTools; var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false); function startup() { + maybeRemoveDesktopMenu(); modifyLODSettings(); From 1576a29916bbe1ce2c78e83166584df9c63ff758 Mon Sep 17 00:00:00 2001 From: milad Date: Fri, 6 Sep 2019 10:53:17 -0700 Subject: [PATCH 08/11] toggled flag for discconecting from wearable signal --- .../simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index b005966951..10881b0e98 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -476,7 +476,7 @@ function unload() { if (signalsConnected) { Window.domainChanged.disconnect(onDomainChanged); MyAvatar.scaleChanged.disconnect(onScaleChanged); - if (firstEmojiMadeOnStartup) { + if (!firstEmojiMadeOnStartup) { Entities.addingWearable.disconnect(onAddingWearable); } From 1d8bbc35295a2b43e8b457d63cd2acc061ab937f Mon Sep 17 00:00:00 2001 From: milad Date: Fri, 6 Sep 2019 10:55:35 -0700 Subject: [PATCH 09/11] removed startup time var --- scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index 10881b0e98..39af7ffbec 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -406,7 +406,6 @@ var emojiCodeMap; var customEmojiCodeMap; var signalsConnected = false; var _this; -var startupTimeStamp = Date.now(); function startup() { // make a map of just the utf codes to help with accesing emojiCodeMap = emojiList.reduce(function (codeMap, currentEmojiInList, index) { From b352d53083c72878e43b48c53d6570da6af432e9 Mon Sep 17 00:00:00 2001 From: milad Date: Fri, 6 Sep 2019 11:00:14 -0700 Subject: [PATCH 10/11] removed space made on accident --- scripts/simplifiedUI/ui/simplifiedUI.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index d63b0294b2..c388c594c9 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -590,7 +590,6 @@ var oldShowAudioTools; var oldShowBubbleTools; var keepExistingUIAndScriptsSetting = Settings.getValue("simplifiedUI/keepExistingUIAndScripts", false); function startup() { - maybeRemoveDesktopMenu(); modifyLODSettings(); From bb0b51116a8341ced5e3982cb41abe34d271d51d Mon Sep 17 00:00:00 2001 From: milad Date: Fri, 6 Sep 2019 11:29:29 -0700 Subject: [PATCH 11/11] cr1 --- .../simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js | 5 +---- scripts/simplifiedUI/ui/simplifiedUI.js | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js index 39af7ffbec..1b16843b09 100644 --- a/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js +++ b/scripts/simplifiedUI/simplifiedEmote/emojiApp/simplifiedEmoji.js @@ -171,8 +171,6 @@ function onAddingWearable(id) { var props = Entities.getEntityProperties(id, ["name"]); if (props.name.toLowerCase().indexOf("avimoji") > -1) { Entities.deleteEntity(id); - } else { - return; } } @@ -235,8 +233,7 @@ function createEmoji(emojiFilename) { "billboardMode": "full", "ignorePickIntersection": true, "alpha": 1, - "grab": { "grabbable": false }, - "userData": JSON.stringify({ timestamp: Date.now() }) + "grab": { "grabbable": false } }, "avatar"); maybePlayPop("in"); diff --git a/scripts/simplifiedUI/ui/simplifiedUI.js b/scripts/simplifiedUI/ui/simplifiedUI.js index c388c594c9..affa6896d8 100644 --- a/scripts/simplifiedUI/ui/simplifiedUI.js +++ b/scripts/simplifiedUI/ui/simplifiedUI.js @@ -584,7 +584,7 @@ function restoreLODSettings() { var nametag = Script.require("./simplifiedNametag/simplifiedNametag.js?" + Date.now()); -var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now()) +var si = Script.require("./simplifiedStatusIndicator/simplifiedStatusIndicator.js?" + Date.now()); var emote = Script.require("../simplifiedEmote/simplifiedEmote.js?" + Date.now()); var oldShowAudioTools; var oldShowBubbleTools;