261 lines · 8.7 KB · Text
RawDownload
////  AnimationPropertyGroup.cpp//  libraries/entities/src////  Created by Brad Hefta-Gaub on 12/4/13.//  Copyright 2013 High Fidelity, Inc.//  Copyright 2023 Overte e.V.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//  SPDX-License-Identifier: Apache-2.0// #include "AnimationPropertyGroup.h" #include <QJsonDocument>#include <OctreePacketData.h> #include "EntityItemProperties.h" const float AnimationPropertyGroup::MAXIMUM_POSSIBLE_FRAME = 100000.0f; bool operator==(const AnimationPropertyGroup& a, const AnimationPropertyGroup& b) {    return        (a._currentFrame == b._currentFrame) &&        (a._running == b._running) &&        (a._loop == b._loop) &&        (a._hold == b._hold) &&        (a._firstFrame == b._firstFrame) &&        (a._lastFrame == b._lastFrame) &&        (a._fps == b._fps) &&        (a._allowTranslation == b._allowTranslation) &&        (a._url == b._url) &&        (a._smoothFrames == b._smoothFrames);}  /*@jsdoc * An animation is configured by the following properties: * @typedef {object} Entities.AnimationProperties * @property {string} url="" - The URL of the glTF or FBX file that has the animation. glTF files may be in JSON or binary *     format (".gltf" or ".glb" URLs respectively). *     <p><strong>Warning:</strong> glTF animations currently do not always animate correctly.</p> * @property {boolean} allowTranslation=true - <code>true</code> to enable translations contained in the animation to be *     played, <code>false</code> to disable translations. * @property {number} fps=30 - The speed in frames/s that the animation is played at. * @property {number} firstFrame=0 - The first frame to play in the animation. * @property {number} lastFrame=100000 - The last frame to play in the animation. * @property {number} currentFrame=0 - The current frame being played in the animation. * @property {boolean} running=false - <code>true</code> if the animation should play, <code>false</code> if it shouldn't. * @property {boolean} loop=true - <code>true</code> if the animation is continuously repeated in a loop, <code>false</code> if *     it isn't. * @property {boolean} hold=false - <code>true</code> if the rotations and translations of the last frame played are *     maintained when the animation stops playing, <code>false</code> if they aren't. * @property {boolean} smoothFrames=true - <code>true</code> if the frames of the animation should be linearly interpolated to *     create smoother movement, <code>false</code> if the frames should not be interpolated. */ void AnimationPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProperties, ScriptValue& properties, ScriptEngine* engine,        bool skipDefaults, EntityItemProperties& defaultEntityProperties, bool returnNothingOnEmptyPropertyFlags, AvatarEntityOwnership ownership) const {     auto nodeList = DependencyManager::get<NodeList>(); @Animation_GROUP_COPY_TO_SCRIPT@ } void AnimationPropertyGroup::copyFromScriptValue(const ScriptValue& object, const QSet<QString> &namesSet, bool& _defaultSettings) { @Animation_GROUP_COPY_FROM_SCRIPT@     // legacy property support    COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationURL, QString, setUrl, getUrl);    COPY_PROPERTY_FROM_QSCRIPTVALUE_NOCHECK(animationSettings, QString, setFromOldAnimationSettings);    COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFPS, float, setFps, getFps);    COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationIsPlaying, bool, setRunning, getRunning);    COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(animationFrameIndex, float, setCurrentFrame, getCurrentFrame); } void AnimationPropertyGroup::merge(const AnimationPropertyGroup& other) { @Animation_GROUP_MERGE@ } void AnimationPropertyGroup::debugDump() const { @Animation_GROUP_DEBUG_DUMP@ } void AnimationPropertyGroup::listChangedProperties(QList<QString>& out) { @Animation_GROUP_LIST_CHANGED@ } bool AnimationPropertyGroup::appendToEditPacket(OctreePacketData* packetData,                                    EntityPropertyFlags& requestedProperties,                                    EntityPropertyFlags& propertyFlags,                                    EntityPropertyFlags& propertiesDidntFit,                                    int& propertyCount,                                    OctreeElement::AppendState& appendState) const {     bool successPropertyFits = true; @Animation_GROUP_APPEND@     return successPropertyFits;} bool AnimationPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags, const unsigned char*& dataAt , int& processedBytes) {     int bytesRead = 0;    bool overwriteLocalData = true;    bool somethingChanged = false; @Animation_GROUP_READ@ @Animation_GROUP_DECODE_CHANGED@     processedBytes += bytesRead;     return somethingChanged;} void AnimationPropertyGroup::markAllChanged() { @Animation_GROUP_MARK_CHANGED@ } EntityPropertyFlags AnimationPropertyGroup::getChangedProperties() const {    EntityPropertyFlags changedProperties; @Animation_GROUP_CHANGED_PROPERTIES@     return changedProperties;} void AnimationPropertyGroup::getProperties(EntityItemProperties& properties) const { @Animation_GROUP_COPY_TO@ } bool AnimationPropertyGroup::setProperties(const EntityItemProperties& properties) {    bool somethingChanged = false; @Animation_GROUP_SET_FROM@     return somethingChanged;} EntityPropertyFlags AnimationPropertyGroup::getEntityProperties(EncodeBitstreamParams& params) const {    EntityPropertyFlags requestedProperties; @Animation_REQUESTED_PROPS@     return requestedProperties;} int AnimationPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,                                            ReadBitstreamToTreeParams& args,                                            EntityPropertyFlags& propertyFlags, bool overwriteLocalData,                                            bool& somethingChanged) {     int bytesRead = 0;    const unsigned char* dataAt = data; @Animation_GROUP_READ@     return bytesRead;} void AnimationPropertyGroup::addPropertyMap(QHash<QString, EntityPropertyInfo>& _propertyInfos,                                            QHash<EntityPropertyList, QString>& _enumsToPropertyStrings) { @Animation_GROUP_ADD_TO_MAP@ } void AnimationPropertyGroup::setFromOldAnimationSettings(const QString& value) {    // the animations setting is a JSON string that may contain various animation settings.    // if it includes fps, currentFrame, or running, those values will be parsed out and    // will over ride the regular animation settings     bool allowTranslation = getAllowTranslation();    float fps = getFps();    float currentFrame = getCurrentFrame();    bool running = getRunning();    bool loop = getLoop();    float firstFrame = getFirstFrame();    float lastFrame = getLastFrame();    bool hold = getHold();     QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());    QJsonObject settingsAsJsonObject = settingsAsJson.object();    QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();     if (settingsMap.contains("allowTranslation")) {        allowTranslation = settingsMap["allowTranslation"].toBool();    }     if (settingsMap.contains("fps")) {        fps = settingsMap["fps"].toFloat();    }     // old settings had frameIndex    if (settingsMap.contains("frameIndex")) {        currentFrame = settingsMap["frameIndex"].toFloat();    }     if (settingsMap.contains("running")) {        running = settingsMap["running"].toBool();    }     if (settingsMap.contains("firstFrame")) {        firstFrame = settingsMap["firstFrame"].toFloat();    }     if (settingsMap.contains("loop")) {        loop = settingsMap["loop"].toBool();    }     if (settingsMap.contains("lastFrame")) {        lastFrame = settingsMap["lastFrame"].toFloat();    }     if (settingsMap.contains("hold")) {        hold = settingsMap["hold"].toBool();    }     setAllowTranslation(allowTranslation);    setFps(fps);    setCurrentFrame(currentFrame);    setRunning(running);    setLoop(loop);    setFirstFrame(firstFrame);    setLastFrame(lastFrame);    setHold(hold);} float AnimationPropertyGroup::getNumFrames() const {    return _lastFrame - _firstFrame + 1.0f;} float AnimationPropertyGroup::computeLoopedFrame(float frame) const {    float numFrames = getNumFrames();    if (numFrames > 1.0f) {        frame = getFirstFrame() + fmodf(frame - getFirstFrame(), numFrames);    } else {        frame = getFirstFrame();    }    return frame;} bool AnimationPropertyGroup::isValidAndRunning() const {    return getRunning() && (getFps() > 0.0f) && (getNumFrames() > 1.0f) && !(getUrl().isEmpty());}