diff --git a/assignment-client/src/avatars/ScriptableAvatar.cpp b/assignment-client/src/avatars/ScriptableAvatar.cpp index c7715d4014..5060891284 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.cpp +++ b/assignment-client/src/avatars/ScriptableAvatar.cpp @@ -35,7 +35,7 @@ void ScriptableAvatar::startAnimation(const QString& url, float fps, float prior return; } _animation = DependencyManager::get()->getAnimation(url); - _animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame); + _animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame, false); _maskedJoints = maskedJoints; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 277f6898d1..22b2cffbcb 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -910,6 +910,8 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { const QVector& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy auto& fbxJoints = _animation->getGeometry().joints; + auto& originalFbxJoints = _model->getFBXGeometry().joints; + bool allowTranslation = entity->getAnimationAllowTranslation(); int frameCount = frames.size(); if (frameCount <= 0) { return; @@ -952,7 +954,9 @@ void ModelEntityRenderer::animate(const TypedEntityPointer& entity) { int index = _jointMapping[j]; if (index >= 0) { glm::mat4 translationMat; - if (index < translations.size()) { + if (!allowTranslation){ + translationMat = glm::translate(originalFbxJoints[index].translation); + } else if (index < translations.size()) { translationMat = glm::translate(translations[index]); } glm::mat4 rotationMat; diff --git a/libraries/entities/src/AnimationPropertyGroup.cpp b/libraries/entities/src/AnimationPropertyGroup.cpp index d3c7e3258d..d6a2937553 100644 --- a/libraries/entities/src/AnimationPropertyGroup.cpp +++ b/libraries/entities/src/AnimationPropertyGroup.cpp @@ -33,6 +33,7 @@ bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, QScriptValue& properties, QScriptEngine* engine, bool skipDefaults, EntityItemProperties& defaultEntityProperties) const { COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_URL, Animation, animation, URL, url); + COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FPS, Animation, animation, FPS, fps); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame); COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_ANIMATION_PLAYING, Animation, animation, Running, running); @@ -46,6 +47,7 @@ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desire void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, bool& _defaultSettings) { COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, url, QString, setURL); + COPY_GROUP_PROPERTY_FROM_QSCRIPTVALUE(animation, allowTranslation, bool, setAllowTranslation); // legacy property support COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationURL, QString, setURL, getURL); @@ -67,6 +69,7 @@ void AnimationPropertyGroup::copyFromScriptValue(const QScriptValue& object, boo void AnimationPropertyGroup::merge(const AnimationPropertyGroup& other) { COPY_PROPERTY_IF_CHANGED(url); + COPY_PROPERTY_IF_CHANGED(allowTranslation); COPY_PROPERTY_IF_CHANGED(fps); COPY_PROPERTY_IF_CHANGED(currentFrame); COPY_PROPERTY_IF_CHANGED(running); @@ -88,6 +91,7 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { float lastFrame = getLastFrame(); bool loop = getLoop(); bool hold = getHold(); + bool allowTranslation = getAllowTranslation(); QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8()); QJsonObject settingsAsJsonObject = settingsAsJson.object(); @@ -122,6 +126,11 @@ void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) { running = settingsMap["hold"].toBool(); } + if (settingsMap.contains("allowTranslation")) { + allowTranslation = settingsMap["allowTranslation"].toBool(); + } + + setAllowTranslation(allowTranslation); setFPS(fps); setCurrentFrame(currentFrame); setRunning(running); @@ -137,6 +146,7 @@ void AnimationPropertyGroup::debugDump() const { qCDebug(entities) << " url:" << getURL() << " has changed:" << urlChanged(); qCDebug(entities) << " fps:" << getFPS() << " has changed:" << fpsChanged(); qCDebug(entities) << "currentFrame:" << getCurrentFrame() << " has changed:" << currentFrameChanged(); + qCDebug(entities) << "allowTranslation:" << getAllowTranslation() << " has changed:" << allowTranslationChanged(); } void AnimationPropertyGroup::listChangedProperties(QList& out) { @@ -149,6 +159,9 @@ void AnimationPropertyGroup::listChangedProperties(QList& out) { if (currentFrameChanged()) { out << "animation-currentFrame"; } + if (allowTranslationChanged()) { + out << "animation-allowTranslation"; + } } @@ -162,6 +175,7 @@ bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData, bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getURL()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, getAllowTranslation()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getRunning()); @@ -181,6 +195,7 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF bool somethingChanged = false; READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL); + READ_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, bool, setAllowTranslation); READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS); READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame); @@ -198,7 +213,8 @@ bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyF DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_FIRST_FRAME, FirstFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_LAST_FRAME, LastFrame); DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_HOLD, Hold); - + DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation); + processedBytes += bytesRead; Q_UNUSED(somethingChanged); @@ -215,6 +231,7 @@ void AnimationPropertyGroup::markAllChanged() { _firstFrameChanged = true; _lastFrameChanged = true; _holdChanged = true; + _allowTranslationChanged = true; } EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const { @@ -228,12 +245,14 @@ EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FIRST_FRAME, firstFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_LAST_FRAME, lastFrame); CHECK_PROPERTY_CHANGE(PROP_ANIMATION_HOLD, hold); + CHECK_PROPERTY_CHANGE(PROP_ANIMATION_ALLOW_TRANSLATION, allowTranslation); return changedProperties; } void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) const { COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, URL, getURL); + COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, AllowTranslation, getAllowTranslation); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, FPS, getFPS); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, CurrentFrame, getCurrentFrame); COPY_ENTITY_GROUP_PROPERTY_TO_PROPERTIES(Animation, Running, getRunning); @@ -247,6 +266,7 @@ bool AnimationPropertyGroup::setProperties(const EntityItemProperties& propertie bool somethingChanged = false; SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, URL, url, setURL); + SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, AllowTranslation, allowTranslation, setAllowTranslation); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, FPS, fps, setFPS); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, CurrentFrame, currentFrame, setCurrentFrame); SET_ENTITY_GROUP_PROPERTY_FROM_PROPERTIES(Animation, Running, running, setRunning); @@ -268,6 +288,7 @@ EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamP requestedProperties += PROP_ANIMATION_FIRST_FRAME; requestedProperties += PROP_ANIMATION_LAST_FRAME; requestedProperties += PROP_ANIMATION_HOLD; + requestedProperties += PROP_ANIMATION_ALLOW_TRANSLATION; return requestedProperties; } @@ -283,6 +304,7 @@ void AnimationPropertyGroup::appendSubclassData(OctreePacketData* packetData, En bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, getURL()); + APPEND_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, getAllowTranslation()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, getFPS()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, getCurrentFrame()); APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, getRunning()); @@ -301,6 +323,7 @@ int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char const unsigned char* dataAt = data; READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setURL); + READ_ENTITY_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, bool, setAllowTranslation); READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, setFPS); READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setCurrentFrame); READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setRunning); diff --git a/libraries/entities/src/AnimationPropertyGroup.h b/libraries/entities/src/AnimationPropertyGroup.h index d21e5c52ce..affa960d66 100644 --- a/libraries/entities/src/AnimationPropertyGroup.h +++ b/libraries/entities/src/AnimationPropertyGroup.h @@ -85,6 +85,7 @@ public: DEFINE_PROPERTY(PROP_ANIMATION_FIRST_FRAME, FirstFrame, firstFrame, float, 0.0f); // was animationSettings.firstFrame DEFINE_PROPERTY(PROP_ANIMATION_LAST_FRAME, LastFrame, lastFrame, float, MAXIMUM_POSSIBLE_FRAME); // was animationSettings.lastFrame DEFINE_PROPERTY(PROP_ANIMATION_HOLD, Hold, hold, bool, false); // was animationSettings.hold + DEFINE_PROPERTY(PROP_ANIMATION_ALLOW_TRANSLATION, AllowTranslation, allowTranslation, bool, true); protected: friend bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 20b541f563..d6de4ec614 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1033,6 +1033,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame); ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold); + ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_ALLOW_TRANSLATION, Animation, animation, AllowTranslation, allowTranslation); ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color); ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index b3cfc143c2..d97be6348f 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -40,6 +40,7 @@ enum EntityPropertyList { PROP_ANIMATION_FPS, PROP_ANIMATION_FRAME_INDEX, PROP_ANIMATION_PLAYING, + PROP_ANIMATION_ALLOW_TRANSLATION, // these properties are supported by the EntityItem base class PROP_REGISTRATION_POINT, diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index de0e4ddee5..b02cf04651 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -330,6 +330,10 @@ void ModelEntityItem::setAnimationSettings(const QString& value) { setAnimationHold(hold); } + if (settingsMap.contains("allowTranslation")) { + bool allowTranslation = settingsMap["allowTranslation"].toBool(); + setAnimationAllowTranslation(allowTranslation); + } _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; } diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 99255198e0..c4b3e82f23 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -83,7 +83,10 @@ public: void setAnimationCurrentFrame(float value); void setAnimationIsPlaying(bool value); - void setAnimationFPS(float value); + void setAnimationFPS(float value); + + void setAnimationAllowTranslation(bool value) { _animationProperties.setAllowTranslation(value); }; + bool getAnimationAllowTranslation() const { return _animationProperties.getAllowTranslation(); }; void setAnimationLoop(bool loop); bool getAnimationLoop() const; diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 3ba2b96dfc..a51778d5ff 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -260,6 +260,7 @@ const PacketVersion VERSION_ENTITIES_HINGE_CONSTRAINT = 69; const PacketVersion VERSION_ENTITIES_BULLET_DYNAMICS = 70; const PacketVersion VERSION_ENTITIES_HAS_SHOULD_HIGHLIGHT = 71; const PacketVersion VERSION_ENTITIES_HAS_HIGHLIGHT_SCRIPTING_INTERFACE = 72; +const PacketVersion VERSION_ENTITIES_ANIMATION_ALLOW_TRANSLATION_PROPERTIES = 73; enum class EntityQueryPacketVersion: PacketVersion { JSONFilter = 18, diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 78b54d26f1..5f66a78679 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -827,10 +827,10 @@ AnimationDetails::AnimationDetails() : } AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, - bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame) : + bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame, bool allowTranslation) : role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold), startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame), - running(running), currentFrame(currentFrame) { + running(running), currentFrame(currentFrame), allowTranslation(allowTranslation) { } @@ -847,6 +847,7 @@ QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const Animatio obj.setProperty("lastFrame", details.lastFrame); obj.setProperty("running", details.running); obj.setProperty("currentFrame", details.currentFrame); + obj.setProperty("allowTranslation", details.allowTranslation); return obj; } diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index f4fc9109ac..ed928a6e7b 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -197,7 +197,7 @@ class AnimationDetails { public: AnimationDetails(); AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop, - bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame); + bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame, bool allowTranslation); QString role; QUrl url; @@ -210,6 +210,7 @@ public: float lastFrame; bool running; float currentFrame; + bool allowTranslation; }; Q_DECLARE_METATYPE(AnimationDetails); QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event); diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index f94d339f84..42a938e78d 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -446,6 +446,10 @@ +
+ + +
@@ -642,10 +646,6 @@
- - - -
Voxel volume size m diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 04eadc98a1..d93baff636 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -611,6 +611,7 @@ function loaded() { var elModelAnimationLastFrame = document.getElementById("property-model-animation-last-frame"); var elModelAnimationLoop = document.getElementById("property-model-animation-loop"); var elModelAnimationHold = document.getElementById("property-model-animation-hold"); + var elModelAnimationAllowTranslation = document.getElementById("property-model-animation-allow-translation"); var elModelTextures = document.getElementById("property-model-textures"); var elModelOriginalTextures = document.getElementById("property-model-original-textures"); @@ -926,6 +927,7 @@ function loaded() { elModelAnimationLastFrame.value = properties.animation.lastFrame; elModelAnimationLoop.checked = properties.animation.loop; elModelAnimationHold.checked = properties.animation.hold; + elModelAnimationAllowTranslation.checked = properties.animation.allowTranslation; elModelTextures.value = properties.textures; setTextareaScrolling(elModelTextures); elModelOriginalTextures.value = properties.originalTextures; @@ -1276,6 +1278,7 @@ function loaded() { elModelAnimationLastFrame.addEventListener('change', createEmitGroupNumberPropertyUpdateFunction('animation', 'lastFrame')); elModelAnimationLoop.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'loop')); elModelAnimationHold.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'hold')); + elModelAnimationAllowTranslation.addEventListener('change', createEmitGroupCheckedPropertyUpdateFunction('animation', 'allowTranslation')); elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures'));