mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-17 03:30:30 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into temp0
This commit is contained in:
commit
420118e9db
16 changed files with 538 additions and 102 deletions
|
@ -22,6 +22,9 @@ EntityPropertyDialogBox = (function () {
|
|||
var dimensionZ;
|
||||
var rescalePercentage;
|
||||
var editModelID = -1;
|
||||
var previousAnimationIsPlaying;
|
||||
var previousAnimationFrameIndex;
|
||||
var previousAnimationSettings;
|
||||
|
||||
that.cleanup = function () {
|
||||
};
|
||||
|
@ -47,10 +50,15 @@ EntityPropertyDialogBox = (function () {
|
|||
array.push({ label: "Animation URL:", value: properties.animationURL });
|
||||
index++;
|
||||
array.push({ label: "Animation is playing:", value: properties.animationIsPlaying });
|
||||
previousAnimationIsPlaying = properties.animationIsPlaying;
|
||||
index++;
|
||||
array.push({ label: "Animation FPS:", value: properties.animationFPS });
|
||||
index++;
|
||||
array.push({ label: "Animation Frame:", value: properties.animationFrameIndex });
|
||||
previousAnimationFrameIndex = properties.animationFrameIndex;
|
||||
index++;
|
||||
array.push({ label: "Animation Settings:", value: properties.animationSettings });
|
||||
previousAnimationSettings = properties.animationSettings;
|
||||
index++;
|
||||
array.push({ label: "Textures:", value: properties.textures });
|
||||
index++;
|
||||
|
@ -237,9 +245,29 @@ EntityPropertyDialogBox = (function () {
|
|||
if (properties.type == "Model") {
|
||||
properties.modelURL = array[index++].value;
|
||||
properties.animationURL = array[index++].value;
|
||||
properties.animationIsPlaying = array[index++].value;
|
||||
|
||||
var newAnimationIsPlaying = array[index++].value;
|
||||
if (previousAnimationIsPlaying != newAnimationIsPlaying) {
|
||||
properties.animationIsPlaying = newAnimationIsPlaying;
|
||||
} else {
|
||||
delete properties.animationIsPlaying;
|
||||
}
|
||||
|
||||
properties.animationFPS = array[index++].value;
|
||||
properties.animationFrameIndex = array[index++].value;
|
||||
|
||||
var newAnimationFrameIndex = array[index++].value;
|
||||
if (previousAnimationFrameIndex != newAnimationFrameIndex) {
|
||||
properties.animationFrameIndex = newAnimationFrameIndex;
|
||||
} else {
|
||||
delete properties.animationFrameIndex;
|
||||
}
|
||||
|
||||
var newAnimationSettings = array[index++].value;
|
||||
if (previousAnimationSettings != newAnimationSettings) {
|
||||
properties.animationSettings = newAnimationSettings;
|
||||
} else {
|
||||
delete properties.animationSettings;
|
||||
}
|
||||
properties.textures = array[index++].value;
|
||||
index++; // skip textureNames label
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ void AnimationHandle::setPriority(float priority) {
|
|||
if (_priority == priority) {
|
||||
return;
|
||||
}
|
||||
if (_running) {
|
||||
if (isRunning()) {
|
||||
_model->_runningAnimations.removeOne(_self);
|
||||
if (priority < _priority) {
|
||||
replaceMatchingPriorities(priority);
|
||||
|
@ -47,7 +47,8 @@ void AnimationHandle::setPriority(float priority) {
|
|||
}
|
||||
|
||||
void AnimationHandle::setStartAutomatically(bool startAutomatically) {
|
||||
if ((_startAutomatically = startAutomatically) && !_running) {
|
||||
_animationLoop.setStartAutomatically(startAutomatically);
|
||||
if (getStartAutomatically() && !isRunning()) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
@ -58,48 +59,59 @@ void AnimationHandle::setMaskedJoints(const QStringList& maskedJoints) {
|
|||
}
|
||||
|
||||
void AnimationHandle::setRunning(bool running) {
|
||||
if (_running == running) {
|
||||
if (isRunning() == running) {
|
||||
// if we're already running, this is the same as a restart
|
||||
if (running) {
|
||||
// move back to the beginning
|
||||
_frameIndex = _firstFrame;
|
||||
setFrameIndex(getFirstFrame());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((_running = running)) {
|
||||
_animationLoop.setRunning(running);
|
||||
if (isRunning()) {
|
||||
if (!_model->_runningAnimations.contains(_self)) {
|
||||
insertSorted(_model->_runningAnimations, _self);
|
||||
}
|
||||
_frameIndex = _firstFrame;
|
||||
|
||||
} else {
|
||||
_model->_runningAnimations.removeOne(_self);
|
||||
replaceMatchingPriorities(0.0f);
|
||||
}
|
||||
emit runningChanged(_running);
|
||||
emit runningChanged(isRunning());
|
||||
}
|
||||
|
||||
AnimationHandle::AnimationHandle(Model* model) :
|
||||
QObject(model),
|
||||
_model(model),
|
||||
_fps(30.0f),
|
||||
_priority(1.0f),
|
||||
_loop(false),
|
||||
_hold(false),
|
||||
_startAutomatically(false),
|
||||
_firstFrame(0.0f),
|
||||
_lastFrame(FLT_MAX),
|
||||
_running(false) {
|
||||
_priority(1.0f)
|
||||
{
|
||||
}
|
||||
|
||||
AnimationDetails AnimationHandle::getAnimationDetails() const {
|
||||
AnimationDetails details(_role, _url, _fps, _priority, _loop, _hold,
|
||||
_startAutomatically, _firstFrame, _lastFrame, _running, _frameIndex);
|
||||
AnimationDetails details(_role, _url, getFPS(), _priority, getLoop(), getHold(),
|
||||
getStartAutomatically(), getFirstFrame(), getLastFrame(), isRunning(), getFrameIndex());
|
||||
return details;
|
||||
}
|
||||
|
||||
void AnimationHandle::setAnimationDetails(const AnimationDetails& details) {
|
||||
setRole(details.role);
|
||||
setURL(details.url);
|
||||
setFPS(details.fps);
|
||||
setPriority(details.priority);
|
||||
setLoop(details.loop);
|
||||
setHold(details.hold);
|
||||
setStartAutomatically(details.startAutomatically);
|
||||
setFirstFrame(details.firstFrame);
|
||||
setLastFrame(details.lastFrame);
|
||||
setRunning(details.running);
|
||||
setFrameIndex(details.frameIndex);
|
||||
|
||||
// NOTE: AnimationDetails doesn't support maskedJoints
|
||||
//setMaskedJoints(const QStringList& maskedJoints);
|
||||
}
|
||||
|
||||
|
||||
void AnimationHandle::simulate(float deltaTime) {
|
||||
_frameIndex += deltaTime * _fps;
|
||||
_animationLoop.simulate(deltaTime);
|
||||
|
||||
// update the joint mappings if necessary/possible
|
||||
if (_jointMappings.isEmpty()) {
|
||||
|
@ -125,26 +137,15 @@ void AnimationHandle::simulate(float deltaTime) {
|
|||
stop();
|
||||
return;
|
||||
}
|
||||
float endFrameIndex = qMin(_lastFrame, animationGeometry.animationFrames.size() - (_loop ? 0.0f : 1.0f));
|
||||
float startFrameIndex = qMin(_firstFrame, endFrameIndex);
|
||||
if ((!_loop && (_frameIndex < startFrameIndex || _frameIndex > endFrameIndex)) || startFrameIndex == endFrameIndex) {
|
||||
// passed the end; apply the last frame
|
||||
applyFrame(glm::clamp(_frameIndex, startFrameIndex, endFrameIndex));
|
||||
if (!_hold) {
|
||||
stop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
// wrap within the the desired range
|
||||
if (_frameIndex < startFrameIndex) {
|
||||
_frameIndex = endFrameIndex - glm::mod(endFrameIndex - _frameIndex, endFrameIndex - startFrameIndex);
|
||||
|
||||
} else if (_frameIndex > endFrameIndex) {
|
||||
_frameIndex = startFrameIndex + glm::mod(_frameIndex - startFrameIndex, endFrameIndex - startFrameIndex);
|
||||
}
|
||||
|
||||
// TODO: When moving the loop/frame calculations to AnimationLoop class, we changed this behavior
|
||||
// see AnimationLoop class for more details. Do we need to support clamping the endFrameIndex to
|
||||
// the max number of frames in the geometry???
|
||||
//
|
||||
// float endFrameIndex = qMin(_lastFrame, animationGeometry.animationFrames.size() - (_loop ? 0.0f : 1.0f));
|
||||
|
||||
// blend between the closest two frames
|
||||
applyFrame(_frameIndex);
|
||||
applyFrame(getFrameIndex());
|
||||
}
|
||||
|
||||
void AnimationHandle::applyFrame(float frameIndex) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <QVector>
|
||||
|
||||
#include <AnimationCache.h>
|
||||
#include <AnimationLoop.h>
|
||||
|
||||
class AnimationHandle;
|
||||
class Model;
|
||||
|
@ -38,38 +39,40 @@ public:
|
|||
|
||||
void setURL(const QUrl& url);
|
||||
const QUrl& getURL() const { return _url; }
|
||||
|
||||
void setFPS(float fps) { _fps = fps; }
|
||||
float getFPS() const { return _fps; }
|
||||
|
||||
void setPriority(float priority);
|
||||
float getPriority() const { return _priority; }
|
||||
|
||||
void setLoop(bool loop) { _loop = loop; }
|
||||
bool getLoop() const { return _loop; }
|
||||
|
||||
void setHold(bool hold) { _hold = hold; }
|
||||
bool getHold() const { return _hold; }
|
||||
|
||||
void setStartAutomatically(bool startAutomatically);
|
||||
bool getStartAutomatically() const { return _startAutomatically; }
|
||||
|
||||
void setFirstFrame(float firstFrame) { _firstFrame = firstFrame; }
|
||||
float getFirstFrame() const { return _firstFrame; }
|
||||
|
||||
void setLastFrame(float lastFrame) { _lastFrame = lastFrame; }
|
||||
float getLastFrame() const { return _lastFrame; }
|
||||
|
||||
|
||||
void setMaskedJoints(const QStringList& maskedJoints);
|
||||
const QStringList& getMaskedJoints() const { return _maskedJoints; }
|
||||
|
||||
void setRunning(bool running);
|
||||
bool isRunning() const { return _running; }
|
||||
|
||||
void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(_frameIndex, _firstFrame, _lastFrame); }
|
||||
float getFrameIndex() const { return _frameIndex; }
|
||||
void setFPS(float fps) { _animationLoop.setFPS(fps); }
|
||||
float getFPS() const { return _animationLoop.getFPS(); }
|
||||
|
||||
void setLoop(bool loop) { _animationLoop.setLoop(loop); }
|
||||
bool getLoop() const { return _animationLoop.getLoop(); }
|
||||
|
||||
void setHold(bool hold) { _animationLoop.setHold(hold); }
|
||||
bool getHold() const { return _animationLoop.getHold(); }
|
||||
|
||||
void setStartAutomatically(bool startAutomatically);
|
||||
bool getStartAutomatically() const { return _animationLoop.getStartAutomatically(); }
|
||||
|
||||
void setFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); }
|
||||
float getFirstFrame() const { return _animationLoop.getFirstFrame(); }
|
||||
|
||||
void setLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); }
|
||||
float getLastFrame() const { return _animationLoop.getLastFrame(); }
|
||||
|
||||
void setRunning(bool running);
|
||||
bool isRunning() const { return _animationLoop.isRunning(); }
|
||||
|
||||
void setFrameIndex(float frameIndex) { _animationLoop.setFrameIndex(frameIndex); }
|
||||
float getFrameIndex() const { return _animationLoop.getFrameIndex(); }
|
||||
|
||||
AnimationDetails getAnimationDetails() const;
|
||||
void setAnimationDetails(const AnimationDetails& details);
|
||||
|
||||
signals:
|
||||
|
||||
|
@ -95,17 +98,12 @@ private:
|
|||
AnimationPointer _animation;
|
||||
QString _role;
|
||||
QUrl _url;
|
||||
float _fps;
|
||||
float _priority;
|
||||
bool _loop;
|
||||
bool _hold;
|
||||
bool _startAutomatically;
|
||||
float _firstFrame;
|
||||
float _lastFrame;
|
||||
|
||||
QStringList _maskedJoints;
|
||||
bool _running;
|
||||
QVector<int> _jointMappings;
|
||||
float _frameIndex;
|
||||
|
||||
AnimationLoop _animationLoop;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -94,5 +94,4 @@ Q_DECLARE_METATYPE(AnimationDetails);
|
|||
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event);
|
||||
void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& event);
|
||||
|
||||
|
||||
#endif // hifi_AnimationCache_h
|
||||
|
|
95
libraries/animation/src/AnimationLoop.cpp
Normal file
95
libraries/animation/src/AnimationLoop.cpp
Normal file
|
@ -0,0 +1,95 @@
|
|||
//
|
||||
// AnimationLoop.cpp
|
||||
// libraries/animation
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 11/12/14.
|
||||
// Copyright (c) 2014 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 "AnimationCache.h"
|
||||
#include "AnimationLoop.h"
|
||||
|
||||
AnimationLoop::AnimationLoop() :
|
||||
_fps(30.0f),
|
||||
_loop(false),
|
||||
_hold(false),
|
||||
_startAutomatically(false),
|
||||
_firstFrame(0.0f),
|
||||
_lastFrame(FLT_MAX),
|
||||
_running(false),
|
||||
_frameIndex(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
AnimationLoop::AnimationLoop(const AnimationDetails& animationDetails) :
|
||||
_fps(animationDetails.fps),
|
||||
_loop(animationDetails.loop),
|
||||
_hold(animationDetails.hold),
|
||||
_startAutomatically(animationDetails.startAutomatically),
|
||||
_firstFrame(animationDetails.firstFrame),
|
||||
_lastFrame(animationDetails.lastFrame),
|
||||
_running(animationDetails.running),
|
||||
_frameIndex(animationDetails.frameIndex)
|
||||
{
|
||||
}
|
||||
|
||||
AnimationLoop::AnimationLoop(float fps, bool loop, bool hold, bool startAutomatically, float firstFrame,
|
||||
float lastFrame, bool running, float frameIndex) :
|
||||
_fps(fps),
|
||||
_loop(loop),
|
||||
_hold(hold),
|
||||
_startAutomatically(startAutomatically),
|
||||
_firstFrame(firstFrame),
|
||||
_lastFrame(lastFrame),
|
||||
_running(running),
|
||||
_frameIndex(frameIndex)
|
||||
{
|
||||
}
|
||||
|
||||
void AnimationLoop::simulate(float deltaTime) {
|
||||
_frameIndex += deltaTime * _fps;
|
||||
|
||||
|
||||
// If we knew the number of frames from the animation, we'd consider using it here
|
||||
// animationGeometry.animationFrames.size()
|
||||
float maxFrame = _lastFrame;
|
||||
float endFrameIndex = qMin(_lastFrame, maxFrame - (_loop ? 0.0f : 1.0f));
|
||||
float startFrameIndex = qMin(_firstFrame, endFrameIndex);
|
||||
if ((!_loop && (_frameIndex < startFrameIndex || _frameIndex > endFrameIndex)) || startFrameIndex == endFrameIndex) {
|
||||
// passed the end; apply the last frame
|
||||
_frameIndex = glm::clamp(_frameIndex, startFrameIndex, endFrameIndex);
|
||||
if (!_hold) {
|
||||
stop();
|
||||
}
|
||||
} else {
|
||||
// wrap within the the desired range
|
||||
if (_frameIndex < startFrameIndex) {
|
||||
_frameIndex = endFrameIndex - glm::mod(endFrameIndex - _frameIndex, endFrameIndex - startFrameIndex);
|
||||
|
||||
} else if (_frameIndex > endFrameIndex) {
|
||||
_frameIndex = startFrameIndex + glm::mod(_frameIndex - startFrameIndex, endFrameIndex - startFrameIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationLoop::setStartAutomatically(bool startAutomatically) {
|
||||
if ((_startAutomatically = startAutomatically) && !isRunning()) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void AnimationLoop::setRunning(bool running) {
|
||||
if (_running == running) {
|
||||
if (running) {
|
||||
// move back to the beginning
|
||||
_frameIndex = _firstFrame;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((_running = running)) {
|
||||
_frameIndex = _firstFrame;
|
||||
}
|
||||
}
|
63
libraries/animation/src/AnimationLoop.h
Normal file
63
libraries/animation/src/AnimationLoop.h
Normal file
|
@ -0,0 +1,63 @@
|
|||
//
|
||||
// AnimationLoop.h
|
||||
// libraries/script-engine/src/
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 11/12/14.
|
||||
// Copyright (c) 2014 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_AnimationLoop_h
|
||||
#define hifi_AnimationLoop_h
|
||||
|
||||
class AnimationDetails;
|
||||
|
||||
class AnimationLoop {
|
||||
public:
|
||||
AnimationLoop();
|
||||
AnimationLoop(const AnimationDetails& animationDetails);
|
||||
AnimationLoop(float fps, bool loop, bool hold, bool startAutomatically, float firstFrame,
|
||||
float lastFrame, bool running, float frameIndex);
|
||||
|
||||
void setFPS(float fps) { _fps = fps; }
|
||||
float getFPS() const { return _fps; }
|
||||
|
||||
void setLoop(bool loop) { _loop = loop; }
|
||||
bool getLoop() const { return _loop; }
|
||||
|
||||
void setHold(bool hold) { _hold = hold; }
|
||||
bool getHold() const { return _hold; }
|
||||
|
||||
void setStartAutomatically(bool startAutomatically);
|
||||
bool getStartAutomatically() const { return _startAutomatically; }
|
||||
|
||||
void setFirstFrame(float firstFrame) { _firstFrame = firstFrame; }
|
||||
float getFirstFrame() const { return _firstFrame; }
|
||||
|
||||
void setLastFrame(float lastFrame) { _lastFrame = lastFrame; }
|
||||
float getLastFrame() const { return _lastFrame; }
|
||||
|
||||
void setRunning(bool running);
|
||||
bool isRunning() const { return _running; }
|
||||
|
||||
void setFrameIndex(float frameIndex) { _frameIndex = glm::clamp(frameIndex, _firstFrame, _lastFrame); }
|
||||
float getFrameIndex() const { return _frameIndex; }
|
||||
|
||||
void start() { setRunning(true); }
|
||||
void stop() { setRunning(false); }
|
||||
void simulate(float deltaTime);
|
||||
|
||||
private:
|
||||
float _fps;
|
||||
bool _loop;
|
||||
bool _hold;
|
||||
bool _startAutomatically;
|
||||
float _firstFrame;
|
||||
float _lastFrame;
|
||||
bool _running;
|
||||
float _frameIndex;
|
||||
};
|
||||
|
||||
#endif // hifi_AnimationLoop_h
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QtCore/QJsonDocument>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
#include <GLMHelpers.h>
|
||||
|
@ -66,6 +67,7 @@ EntityItemProperties::EntityItemProperties() :
|
|||
_animationIsPlaying(ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING),
|
||||
_animationFrameIndex(ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX),
|
||||
_animationFPS(ModelEntityItem::DEFAULT_ANIMATION_FPS),
|
||||
_animationSettings(""),
|
||||
_glowLevel(0.0f),
|
||||
_localRenderAlpha(1.0f),
|
||||
_isSpotlight(false),
|
||||
|
@ -76,6 +78,8 @@ EntityItemProperties::EntityItemProperties() :
|
|||
_animationIsPlayingChanged(false),
|
||||
_animationFrameIndexChanged(false),
|
||||
_animationFPSChanged(false),
|
||||
_animationSettingsChanged(false),
|
||||
|
||||
_glowLevelChanged(false),
|
||||
_localRenderAlphaChanged(false),
|
||||
_isSpotlightChanged(false),
|
||||
|
@ -117,6 +121,58 @@ void EntityItemProperties::setSittingPoints(const QVector<SittingPoint>& sitting
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItemProperties::setAnimationSettings(const QString& value) {
|
||||
// the animations setting is a JSON string that may contain various animation settings.
|
||||
// if it includes fps, frameIndex, or running, those values will be parsed out and
|
||||
// will over ride the regular animation settings
|
||||
|
||||
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
|
||||
QJsonObject settingsAsJsonObject = settingsAsJson.object();
|
||||
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
|
||||
if (settingsMap.contains("fps")) {
|
||||
float fps = settingsMap["fps"].toFloat();
|
||||
setAnimationFPS(fps);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("frameIndex")) {
|
||||
float frameIndex = settingsMap["frameIndex"].toFloat();
|
||||
setAnimationFrameIndex(frameIndex);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("running")) {
|
||||
bool running = settingsMap["running"].toBool();
|
||||
setAnimationIsPlaying(running);
|
||||
}
|
||||
|
||||
_animationSettings = value;
|
||||
_animationSettingsChanged = true;
|
||||
}
|
||||
|
||||
QString EntityItemProperties::getAnimationSettings() const {
|
||||
// the animations setting is a JSON string that may contain various animation settings.
|
||||
// if it includes fps, frameIndex, or running, those values will be parsed out and
|
||||
// will over ride the regular animation settings
|
||||
QString value = _animationSettings;
|
||||
|
||||
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
|
||||
QJsonObject settingsAsJsonObject = settingsAsJson.object();
|
||||
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
|
||||
|
||||
QVariant fpsValue(getAnimationFPS());
|
||||
settingsMap["fps"] = fpsValue;
|
||||
|
||||
QVariant frameIndexValue(getAnimationFrameIndex());
|
||||
settingsMap["frameIndex"] = frameIndexValue;
|
||||
|
||||
QVariant runningValue(getAnimationIsPlaying());
|
||||
settingsMap["running"] = runningValue;
|
||||
|
||||
settingsAsJsonObject = QJsonObject::fromVariantMap(settingsMap);
|
||||
QJsonDocument newDocument(settingsAsJsonObject);
|
||||
QByteArray jsonByteArray = newDocument.toJson(QJsonDocument::Compact);
|
||||
QString jsonByteString(jsonByteArray);
|
||||
return jsonByteString;
|
||||
}
|
||||
|
||||
void EntityItemProperties::debugDump() const {
|
||||
qDebug() << "EntityItemProperties...";
|
||||
|
@ -149,6 +205,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_PLAYING, animationIsPlaying);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FRAME_INDEX, animationFrameIndex);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FPS, animationFPS);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_SETTINGS, animationSettings);
|
||||
CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible);
|
||||
CHECK_PROPERTY_CHANGE(PROP_REGISTRATION_POINT, registrationPoint);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANGULAR_VELOCITY, angularVelocity);
|
||||
|
@ -201,8 +258,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(modelURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationIsPlaying);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationFrameIndex);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationFPS);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationFrameIndex);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(animationSettings,getAnimationSettings());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(glowLevel);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(localRenderAlpha);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(ignoreForCollisions);
|
||||
|
@ -276,6 +334,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(animationIsPlaying, setAnimationIsPlaying);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(animationFPS, setAnimationFPS);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(animationFrameIndex, setAnimationFrameIndex);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(animationSettings, setAnimationSettings);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(glowLevel, setGlowLevel);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localRenderAlpha, setLocalRenderAlpha);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(ignoreForCollisions, setIgnoreForCollisions);
|
||||
|
@ -452,6 +511,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, appendValue, properties.getCutoff());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, properties.getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, properties.getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, properties.getAnimationSettings());
|
||||
}
|
||||
if (propertyCount > 0) {
|
||||
int endOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
|
@ -661,7 +721,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_TEXTURES, setTextures);
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
@ -714,6 +775,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_animationIsPlayingChanged = true;
|
||||
_animationFrameIndexChanged = true;
|
||||
_animationFPSChanged = true;
|
||||
_animationSettingsChanged = true;
|
||||
_glowLevelChanged = true;
|
||||
_localRenderAlphaChanged = true;
|
||||
_isSpotlightChanged = true;
|
||||
|
|
|
@ -80,8 +80,9 @@ enum EntityPropertyList {
|
|||
|
||||
// used by Model entities
|
||||
PROP_TEXTURES,
|
||||
PROP_ANIMATION_SETTINGS,
|
||||
|
||||
PROP_LAST_ITEM = PROP_CUTOFF
|
||||
PROP_LAST_ITEM = PROP_ANIMATION_SETTINGS
|
||||
};
|
||||
|
||||
typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
|
||||
|
@ -178,6 +179,8 @@ public:
|
|||
float getAnimationFrameIndex() const { return _animationFrameIndex; }
|
||||
bool getAnimationIsPlaying() const { return _animationIsPlaying; }
|
||||
float getAnimationFPS() const { return _animationFPS; }
|
||||
QString getAnimationSettings() const;
|
||||
|
||||
float getGlowLevel() const { return _glowLevel; }
|
||||
float getLocalRenderAlpha() const { return _localRenderAlpha; }
|
||||
const QString& getScript() const { return _script; }
|
||||
|
@ -189,6 +192,8 @@ public:
|
|||
void setAnimationFrameIndex(float value) { _animationFrameIndex = value; _animationFrameIndexChanged = true; }
|
||||
void setAnimationIsPlaying(bool value) { _animationIsPlaying = value; _animationIsPlayingChanged = true; }
|
||||
void setAnimationFPS(float value) { _animationFPS = value; _animationFPSChanged = true; }
|
||||
void setAnimationSettings(const QString& value);
|
||||
|
||||
void setGlowLevel(float value) { _glowLevel = value; _glowLevelChanged = true; }
|
||||
void setLocalRenderAlpha(float value) { _localRenderAlpha = value; _localRenderAlphaChanged = true; }
|
||||
void setScript(const QString& value) { _script = value; _scriptChanged = true; }
|
||||
|
@ -342,6 +347,7 @@ private:
|
|||
bool _animationIsPlaying;
|
||||
float _animationFrameIndex;
|
||||
float _animationFPS;
|
||||
QString _animationSettings;
|
||||
float _glowLevel;
|
||||
float _localRenderAlpha;
|
||||
bool _isSpotlight;
|
||||
|
@ -352,6 +358,7 @@ private:
|
|||
bool _animationIsPlayingChanged;
|
||||
bool _animationFrameIndexChanged;
|
||||
bool _animationFPSChanged;
|
||||
bool _animationSettingsChanged;
|
||||
bool _glowLevelChanged;
|
||||
bool _localRenderAlphaChanged;
|
||||
bool _isSpotlightChanged;
|
||||
|
|
|
@ -40,6 +40,18 @@
|
|||
} \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_SETTER(P,T,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
T fromBuffer; \
|
||||
memcpy(&fromBuffer, dataAt, sizeof(fromBuffer)); \
|
||||
dataAt += sizeof(fromBuffer); \
|
||||
bytesRead += sizeof(fromBuffer); \
|
||||
if (overwriteLocalData) { \
|
||||
M(fromBuffer); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
#define READ_ENTITY_PROPERTY_QUAT(P,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
glm::quat fromBuffer; \
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
#include <GLMHelpers.h>
|
||||
|
||||
|
@ -33,7 +35,6 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID, const EntityI
|
|||
{
|
||||
_type = EntityTypes::Model;
|
||||
setProperties(properties, true);
|
||||
_animationFrameIndex = 0.0f;
|
||||
_lastAnimated = usecTimestampNow();
|
||||
_jointMappingCompleted = false;
|
||||
_color[0] = _color[1] = _color[2] = 0;
|
||||
|
@ -50,6 +51,7 @@ EntityItemProperties ModelEntityItem::getProperties() const {
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFPS, getAnimationFPS);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(glowLevel, getGlowLevel);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationSettings, getAnimationSettings);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -64,6 +66,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties, bool
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFPS, setAnimationFPS);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationSettings, setAnimationSettings);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -100,10 +103,29 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_MODEL_URL, setModelURL);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_URL, setAnimationURL);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, _animationFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, _animationFrameIndex);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, _animationIsPlaying);
|
||||
|
||||
// Because we're using AnimationLoop which will reset the frame index if you change it's running state
|
||||
// we want to read these values in the order they appear in the buffer, but call our setters in an
|
||||
// order that allows AnimationLoop to preserve the correct frame rate.
|
||||
float animationFPS = getAnimationFPS();
|
||||
float animationFrameIndex = getAnimationFrameIndex();
|
||||
bool animationIsPlaying = getAnimationIsPlaying();
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FPS, float, animationFPS);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, animationFrameIndex);
|
||||
READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, animationIsPlaying);
|
||||
|
||||
if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) {
|
||||
setAnimationIsPlaying(animationIsPlaying);
|
||||
}
|
||||
if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) {
|
||||
setAnimationFPS(animationFPS);
|
||||
}
|
||||
if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) {
|
||||
setAnimationFrameIndex(animationFrameIndex);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_TEXTURES, setTextures);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_SETTINGS, setAnimationSettings);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -199,19 +221,25 @@ int ModelEntityItem::oldVersionReadEntityDataFromBuffer(const unsigned char* dat
|
|||
bytesRead += animationURLLength;
|
||||
|
||||
// animationIsPlaying
|
||||
memcpy(&_animationIsPlaying, dataAt, sizeof(_animationIsPlaying));
|
||||
dataAt += sizeof(_animationIsPlaying);
|
||||
bytesRead += sizeof(_animationIsPlaying);
|
||||
bool animationIsPlaying;
|
||||
memcpy(&animationIsPlaying, dataAt, sizeof(animationIsPlaying));
|
||||
dataAt += sizeof(animationIsPlaying);
|
||||
bytesRead += sizeof(animationIsPlaying);
|
||||
setAnimationIsPlaying(animationIsPlaying);
|
||||
|
||||
// animationFrameIndex
|
||||
memcpy(&_animationFrameIndex, dataAt, sizeof(_animationFrameIndex));
|
||||
dataAt += sizeof(_animationFrameIndex);
|
||||
bytesRead += sizeof(_animationFrameIndex);
|
||||
float animationFrameIndex;
|
||||
memcpy(&animationFrameIndex, dataAt, sizeof(animationFrameIndex));
|
||||
dataAt += sizeof(animationFrameIndex);
|
||||
bytesRead += sizeof(animationFrameIndex);
|
||||
setAnimationFrameIndex(animationFrameIndex);
|
||||
|
||||
// animationFPS
|
||||
memcpy(&_animationFPS, dataAt, sizeof(_animationFPS));
|
||||
dataAt += sizeof(_animationFPS);
|
||||
bytesRead += sizeof(_animationFPS);
|
||||
float animationFPS;
|
||||
memcpy(&animationFPS, dataAt, sizeof(animationFPS));
|
||||
dataAt += sizeof(animationFPS);
|
||||
bytesRead += sizeof(animationFPS);
|
||||
setAnimationFPS(animationFPS);
|
||||
}
|
||||
}
|
||||
return bytesRead;
|
||||
|
@ -227,6 +255,7 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams&
|
|||
requestedProperties += PROP_ANIMATION_FPS;
|
||||
requestedProperties += PROP_ANIMATION_FRAME_INDEX;
|
||||
requestedProperties += PROP_ANIMATION_PLAYING;
|
||||
requestedProperties += PROP_ANIMATION_SETTINGS;
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
|
||||
return requestedProperties;
|
||||
|
@ -249,6 +278,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, appendValue, getAnimationIsPlaying());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, appendValue, getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, appendValue, getAnimationSettings());
|
||||
}
|
||||
|
||||
|
||||
|
@ -314,7 +344,7 @@ QVector<glm::quat> ModelEntityItem::getAnimationFrame() {
|
|||
int frameCount = frames.size();
|
||||
|
||||
if (frameCount > 0) {
|
||||
int animationFrameIndex = (int)(glm::floor(_animationFrameIndex)) % frameCount;
|
||||
int animationFrameIndex = (int)(glm::floor(getAnimationFrameIndex())) % frameCount;
|
||||
|
||||
if (animationFrameIndex < 0 || animationFrameIndex > frameCount) {
|
||||
animationFrameIndex = 0;
|
||||
|
@ -363,7 +393,7 @@ void ModelEntityItem::update(const quint64& updateTime) {
|
|||
if (getAnimationIsPlaying()) {
|
||||
float deltaTime = (float)(now - _lastAnimated) / (float)USECS_PER_SECOND;
|
||||
_lastAnimated = now;
|
||||
_animationFrameIndex += deltaTime * _animationFPS;
|
||||
_animationLoop.simulate(deltaTime);
|
||||
} else {
|
||||
_lastAnimated = now;
|
||||
}
|
||||
|
@ -377,3 +407,94 @@ void ModelEntityItem::debugDump() const {
|
|||
qDebug() << " model URL:" << getModelURL();
|
||||
}
|
||||
|
||||
void ModelEntityItem::setAnimationSettings(const QString& value) {
|
||||
// the animations setting is a JSON string that may contain various animation settings.
|
||||
// if it includes fps, frameIndex, or running, those values will be parsed out and
|
||||
// will over ride the regular animation settings
|
||||
|
||||
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
|
||||
QJsonObject settingsAsJsonObject = settingsAsJson.object();
|
||||
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
|
||||
if (settingsMap.contains("fps")) {
|
||||
float fps = settingsMap["fps"].toFloat();
|
||||
setAnimationFPS(fps);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("frameIndex")) {
|
||||
float frameIndex = settingsMap["frameIndex"].toFloat();
|
||||
setAnimationFrameIndex(frameIndex);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("running")) {
|
||||
bool running = settingsMap["running"].toBool();
|
||||
setAnimationIsPlaying(running);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("firstFrame")) {
|
||||
float firstFrame = settingsMap["firstFrame"].toFloat();
|
||||
setAnimationFirstFrame(firstFrame);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("lastFrame")) {
|
||||
float lastFrame = settingsMap["lastFrame"].toFloat();
|
||||
setAnimationLastFrame(lastFrame);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("loop")) {
|
||||
bool loop = settingsMap["loop"].toBool();
|
||||
setAnimationLoop(loop);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("hold")) {
|
||||
bool hold = settingsMap["hold"].toBool();
|
||||
setAnimationHold(hold);
|
||||
}
|
||||
|
||||
if (settingsMap.contains("startAutomatically")) {
|
||||
bool startAutomatically = settingsMap["startAutomatically"].toBool();
|
||||
setAnimationStartAutomatically(startAutomatically);
|
||||
}
|
||||
|
||||
_animationSettings = value;
|
||||
}
|
||||
|
||||
QString ModelEntityItem::getAnimationSettings() const {
|
||||
// the animations setting is a JSON string that may contain various animation settings.
|
||||
// if it includes fps, frameIndex, or running, those values will be parsed out and
|
||||
// will over ride the regular animation settings
|
||||
QString value = _animationSettings;
|
||||
|
||||
QJsonDocument settingsAsJson = QJsonDocument::fromJson(value.toUtf8());
|
||||
QJsonObject settingsAsJsonObject = settingsAsJson.object();
|
||||
QVariantMap settingsMap = settingsAsJsonObject.toVariantMap();
|
||||
|
||||
QVariant fpsValue(getAnimationFPS());
|
||||
settingsMap["fps"] = fpsValue;
|
||||
|
||||
QVariant frameIndexValue(getAnimationFrameIndex());
|
||||
settingsMap["frameIndex"] = frameIndexValue;
|
||||
|
||||
QVariant runningValue(getAnimationIsPlaying());
|
||||
settingsMap["running"] = runningValue;
|
||||
|
||||
QVariant firstFrameValue(getAnimationFirstFrame());
|
||||
settingsMap["firstFrame"] = firstFrameValue;
|
||||
|
||||
QVariant lastFrameValue(getAnimationLastFrame());
|
||||
settingsMap["lastFrame"] = lastFrameValue;
|
||||
|
||||
QVariant loopValue(getAnimationLoop());
|
||||
settingsMap["loop"] = loopValue;
|
||||
|
||||
QVariant holdValue(getAnimationHold());
|
||||
settingsMap["hold"] = holdValue;
|
||||
|
||||
QVariant startAutomaticallyValue(getAnimationStartAutomatically());
|
||||
settingsMap["startAutomatically"] = startAutomaticallyValue;
|
||||
|
||||
settingsAsJsonObject = QJsonObject::fromVariantMap(settingsMap);
|
||||
QJsonDocument newDocument(settingsAsJsonObject);
|
||||
QByteArray jsonByteArray = newDocument.toJson(QJsonDocument::Compact);
|
||||
QString jsonByteString(jsonByteArray);
|
||||
return jsonByteString;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#ifndef hifi_ModelEntityItem_h
|
||||
#define hifi_ModelEntityItem_h
|
||||
|
||||
#include <AnimationLoop.h>
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
class ModelEntityItem : public EntityItem {
|
||||
|
@ -73,21 +75,38 @@ public:
|
|||
void setModelURL(const QString& url) { _modelURL = url; }
|
||||
void setAnimationURL(const QString& url) { _animationURL = url; }
|
||||
static const float DEFAULT_ANIMATION_FRAME_INDEX;
|
||||
void setAnimationFrameIndex(float value) { _animationFrameIndex = value; }
|
||||
void setAnimationFrameIndex(float value) { _animationLoop.setFrameIndex(value); }
|
||||
void setAnimationSettings(const QString& value);
|
||||
|
||||
static const bool DEFAULT_ANIMATION_IS_PLAYING;
|
||||
void setAnimationIsPlaying(bool value) { _animationIsPlaying = value; }
|
||||
void setAnimationIsPlaying(bool value) { _animationLoop.setRunning(value); }
|
||||
|
||||
static const float DEFAULT_ANIMATION_FPS;
|
||||
void setAnimationFPS(float value) { _animationFPS = value; }
|
||||
void setAnimationFPS(float value) { _animationLoop.setFPS(value); }
|
||||
|
||||
void setAnimationLoop(bool loop) { _animationLoop.setLoop(loop); }
|
||||
bool getAnimationLoop() const { return _animationLoop.getLoop(); }
|
||||
|
||||
void setAnimationHold(bool hold) { _animationLoop.setHold(hold); }
|
||||
bool getAnimationHold() const { return _animationLoop.getHold(); }
|
||||
|
||||
void setAnimationStartAutomatically(bool startAutomatically) { _animationLoop.setStartAutomatically(startAutomatically); }
|
||||
bool getAnimationStartAutomatically() const { return _animationLoop.getStartAutomatically(); }
|
||||
|
||||
void setAnimationFirstFrame(float firstFrame) { _animationLoop.setFirstFrame(firstFrame); }
|
||||
float getAnimationFirstFrame() const { return _animationLoop.getFirstFrame(); }
|
||||
|
||||
void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); }
|
||||
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
|
||||
|
||||
void mapJoints(const QStringList& modelJointNames);
|
||||
QVector<glm::quat> getAnimationFrame();
|
||||
bool jointsMapped() const { return _jointMappingCompleted; }
|
||||
|
||||
bool getAnimationIsPlaying() const { return _animationIsPlaying; }
|
||||
float getAnimationFrameIndex() const { return _animationFrameIndex; }
|
||||
float getAnimationFPS() const { return _animationFPS; }
|
||||
bool getAnimationIsPlaying() const { return _animationLoop.isRunning(); }
|
||||
float getAnimationFrameIndex() const { return _animationLoop.getFrameIndex(); }
|
||||
float getAnimationFPS() const { return _animationLoop.getFPS(); }
|
||||
QString getAnimationSettings() const;
|
||||
|
||||
static const QString DEFAULT_TEXTURES;
|
||||
const QString& getTextures() const { return _textures; }
|
||||
|
@ -106,9 +125,8 @@ protected:
|
|||
|
||||
quint64 _lastAnimated;
|
||||
QString _animationURL;
|
||||
float _animationFrameIndex; // we keep this as a float and round to int only when we need the exact index
|
||||
bool _animationIsPlaying;
|
||||
float _animationFPS;
|
||||
AnimationLoop _animationLoop;
|
||||
QString _animationSettings;
|
||||
QString _textures;
|
||||
|
||||
// used on client side
|
||||
|
|
|
@ -75,7 +75,7 @@ PacketVersion versionForPacketType(PacketType type) {
|
|||
return 1;
|
||||
case PacketTypeEntityAddOrEdit:
|
||||
case PacketTypeEntityData:
|
||||
return VERSION_ENTITIES_SUPPORT_DIMENSIONS;
|
||||
return VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS;
|
||||
case PacketTypeEntityErase:
|
||||
return 2;
|
||||
case PacketTypeAudioStreamStats:
|
||||
|
|
|
@ -124,6 +124,7 @@ const PacketVersion VERSION_ROOT_ELEMENT_HAS_DATA = 2;
|
|||
const PacketVersion VERSION_ENTITIES_SUPPORT_SPLIT_MTU = 3;
|
||||
const PacketVersion VERSION_ENTITIES_HAS_FILE_BREAKS = VERSION_ENTITIES_SUPPORT_SPLIT_MTU;
|
||||
const PacketVersion VERSION_ENTITIES_SUPPORT_DIMENSIONS = 4;
|
||||
const PacketVersion VERSION_ENTITIES_MODELS_HAVE_ANIMATION_SETTINGS = 5;
|
||||
const PacketVersion VERSION_VOXELS_HAS_FILE_BREAKS = 1;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <GeometryUtil.h>
|
||||
#include <OctalCode.h>
|
||||
#include <LogHandler.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
#include <Shape.h>
|
||||
|
@ -71,6 +72,10 @@ void Octree::recurseTreeWithPostOperation(RecurseOctreeOperation operation, void
|
|||
void Octree::recurseElementWithOperation(OctreeElement* element, RecurseOctreeOperation operation, void* extraData,
|
||||
int recursionCount) {
|
||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
||||
"Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||
|
||||
qDebug() << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
||||
return;
|
||||
}
|
||||
|
@ -89,7 +94,11 @@ void Octree::recurseElementWithOperation(OctreeElement* element, RecurseOctreeOp
|
|||
void Octree::recurseElementWithPostOperation(OctreeElement* element, RecurseOctreeOperation operation, void* extraData,
|
||||
int recursionCount) {
|
||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||
qDebug() << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!\n";
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
||||
"Octree::recurseElementWithPostOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||
|
||||
qDebug() << "Octree::recurseElementWithPostOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -115,6 +124,10 @@ void Octree::recurseElementWithOperationDistanceSorted(OctreeElement* element, R
|
|||
const glm::vec3& point, void* extraData, int recursionCount) {
|
||||
|
||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
||||
"Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||
|
||||
qDebug() << "Octree::recurseElementWithOperationDistanceSorted() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
||||
return;
|
||||
}
|
||||
|
@ -152,7 +165,11 @@ void Octree::recurseTreeWithOperator(RecurseOctreeOperator* operatorObject) {
|
|||
|
||||
bool Octree::recurseElementWithOperator(OctreeElement* element, RecurseOctreeOperator* operatorObject, int recursionCount) {
|
||||
if (recursionCount > DANGEROUSLY_DEEP_RECURSION) {
|
||||
qDebug() << "Octree::recurseElementWithOperation() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
||||
"Octree::recurseElementWithOperator() reached DANGEROUSLY_DEEP_RECURSION, bailing!");
|
||||
|
||||
qDebug() << "Octree::recurseElementWithOperator() reached DANGEROUSLY_DEEP_RECURSION, bailing!";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <QString>
|
||||
#include <QStringList>
|
||||
|
||||
#include <LogHandler.h>
|
||||
#include <PacketHeaders.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
|
@ -854,8 +855,12 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
|
|||
const int MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive
|
||||
const int MIN_RESONABLE_FLIGHT_TIME = 0;
|
||||
if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) {
|
||||
static QString repeatedMessage
|
||||
= LogHandler::getInstance().addRepeatedMessageRegex(
|
||||
"ignoring unreasonable packet... flightTime: -?\\d+ nodeClockSkewUsec: -?\\d+ usecs");
|
||||
|
||||
qDebug() << "ignoring unreasonable packet... flightTime:" << flightTime
|
||||
<< " nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs";;
|
||||
<< "nodeClockSkewUsec:" << nodeClockSkewUsec << "usecs";;
|
||||
return; // ignore any packets that are unreasonable
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,15 @@ struct xColor {
|
|||
unsigned char blue;
|
||||
};
|
||||
|
||||
inline QDebug& operator<<(QDebug& dbg, const xColor& c) {
|
||||
dbg.nospace() << "{type='xColor'"
|
||||
", red=" << c.red <<
|
||||
", green=" << c.green <<
|
||||
", blue=" << c.blue <<
|
||||
"}";
|
||||
return dbg;
|
||||
}
|
||||
|
||||
static const float ZERO = 0.0f;
|
||||
static const float ONE = 1.0f;
|
||||
static const float ONE_HALF = 0.5f;
|
||||
|
|
Loading…
Reference in a new issue