void ModelEntityItem::setAnimationSettings(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 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); } // old settings used frameIndex if (settingsMap.contains("frameIndex")) { float currentFrame = settingsMap["frameIndex"].toFloat(); #ifdef WANT_DEBUG if (isAnimatingSomething()) { qCDebug(entities) << "ModelEntityItem::setAnimationSettings() calling setAnimationFrameIndex()..."; qCDebug(entities) << " model URL:" << getModelURL(); qCDebug(entities) << " animation URL:" << getAnimationURL(); qCDebug(entities) << " settings:" << value; qCDebug(entities) << " settingsMap[frameIndex]:" << settingsMap["frameIndex"]; qCDebug(entities" currentFrame: %20.5f", currentFrame); } #endif setAnimationCurrentFrame(currentFrame); } if (settingsMap.contains("running")) { bool running = settingsMap["running"].toBool(); if (running != getAnimationIsPlaying()) { 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); } _dirtyFlags |= Simulation::DIRTY_UPDATEABLE; }
int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { int bytesRead = 0; const unsigned char* dataAt = data; READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL); if (args.bitstreamVersion < VERSION_ENTITIES_HAS_COLLISION_MODEL) { setCompoundShapeURL(""); } else if (args.bitstreamVersion == VERSION_ENTITIES_HAS_COLLISION_MODEL) { READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); } else { READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL); } READ_ENTITY_PROPERTY(PROP_ANIMATION_URL, QString, setAnimationURL); // 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, setAnimationFPS); READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex); READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying); if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) { if (animationIsPlaying != getAnimationIsPlaying()) { setAnimationIsPlaying(animationIsPlaying); } } if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) { setAnimationFPS(animationFPS); } if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) { setAnimationFrameIndex(animationFrameIndex); } READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); return bytesRead; }
int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData) { int bytesRead = 0; const unsigned char* dataAt = data; READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor); // 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, setAnimationFPS); READ_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex); READ_ENTITY_PROPERTY(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying); if (propertyFlags.getHasProperty(PROP_ANIMATION_PLAYING)) { if (animationIsPlaying != getAnimationIsPlaying()) { setAnimationIsPlaying(animationIsPlaying); } } if (propertyFlags.getHasProperty(PROP_ANIMATION_FPS)) { setAnimationFPS(animationFPS); } if (propertyFlags.getHasProperty(PROP_ANIMATION_FRAME_INDEX)) { setAnimationFrameIndex(animationFrameIndex); } READ_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings); READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, updateShapeType); READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles); READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan); READ_ENTITY_PROPERTY(PROP_EMIT_RATE, float, setEmitRate); READ_ENTITY_PROPERTY(PROP_EMIT_DIRECTION, glm::vec3, setEmitDirection); READ_ENTITY_PROPERTY(PROP_EMIT_STRENGTH, float, setEmitStrength); READ_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, float, setLocalGravity); READ_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, float, setParticleRadius); READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures); return bytesRead; }
void ParticleEffectEntityItem::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(); #ifdef WANT_DEBUG if (isAnimatingSomething()) { qCDebug(entities) << "ParticleEffectEntityItem::setAnimationSettings() calling setAnimationFrameIndex()..."; qCDebug(entities) << " settings:" << value; qCDebug(entities) << " settingsMap[frameIndex]:" << settingsMap["frameIndex"]; qCDebug(entities, " frameIndex: %20.5f", frameIndex); } #endif setAnimationFrameIndex(frameIndex); } if (settingsMap.contains("running")) { bool running = settingsMap["running"].toBool(); if (running != getAnimationIsPlaying()) { 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; _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; }
int ModelEntityItem::oldVersionReadEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { int bytesRead = 0; if (bytesLeftToRead >= expectedBytes()) { int clockSkew = args.sourceNode ? args.sourceNode->getClockSkewUsec() : 0; const unsigned char* dataAt = data; // id // this old bitstream format had 32bit IDs. They are obsolete and need to be replaced with our new UUID // format. We can simply read and ignore the old ID since they should not be repeated. This code should only // run on loading from an old file. quint32 oldID; memcpy(&oldID, dataAt, sizeof(oldID)); dataAt += sizeof(oldID); bytesRead += sizeof(oldID); _id = QUuid::createUuid(); // _lastUpdated memcpy(&_lastUpdated, dataAt, sizeof(_lastUpdated)); dataAt += sizeof(_lastUpdated); bytesRead += sizeof(_lastUpdated); _lastUpdated -= clockSkew; // _lastEdited memcpy(&_lastEdited, dataAt, sizeof(_lastEdited)); dataAt += sizeof(_lastEdited); bytesRead += sizeof(_lastEdited); _lastEdited -= clockSkew; _created = _lastEdited; // NOTE: old models didn't have age or created time, assume their last edit was a create QString ageAsString = formatSecondsElapsed(getAge()); qDebug() << "Loading old model file, _created = _lastEdited =" << _created << " age=" << getAge() << "seconds - " << ageAsString << "old ID=" << oldID << "new ID=" << _id; // radius float radius; memcpy(&radius, dataAt, sizeof(radius)); dataAt += sizeof(radius); bytesRead += sizeof(radius); setRadius(radius); // position memcpy(&_position, dataAt, sizeof(_position)); dataAt += sizeof(_position); bytesRead += sizeof(_position); // color memcpy(&_color, dataAt, sizeof(_color)); dataAt += sizeof(_color); bytesRead += sizeof(_color); // TODO: how to handle this? Presumable, this would only ever be true if the model file was saved with // a model being in a shouldBeDeleted state. Which seems unlikely. But if it happens, maybe we should delete the entity after loading? // shouldBeDeleted bool shouldBeDeleted = false; memcpy(&shouldBeDeleted, dataAt, sizeof(shouldBeDeleted)); dataAt += sizeof(shouldBeDeleted); bytesRead += sizeof(shouldBeDeleted); if (shouldBeDeleted) { qDebug() << "UNEXPECTED - read shouldBeDeleted=TRUE from an old format file"; } // modelURL uint16_t modelURLLength; memcpy(&modelURLLength, dataAt, sizeof(modelURLLength)); dataAt += sizeof(modelURLLength); bytesRead += sizeof(modelURLLength); QString modelURLString((const char*)dataAt); setModelURL(modelURLString); dataAt += modelURLLength; bytesRead += modelURLLength; // rotation int bytes = unpackOrientationQuatFromBytes(dataAt, _rotation); dataAt += bytes; bytesRead += bytes; if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ANIMATION) { // animationURL uint16_t animationURLLength; memcpy(&animationURLLength, dataAt, sizeof(animationURLLength)); dataAt += sizeof(animationURLLength); bytesRead += sizeof(animationURLLength); QString animationURLString((const char*)dataAt); setAnimationURL(animationURLString); dataAt += animationURLLength; bytesRead += animationURLLength; // animationIsPlaying bool animationIsPlaying; memcpy(&animationIsPlaying, dataAt, sizeof(animationIsPlaying)); dataAt += sizeof(animationIsPlaying); bytesRead += sizeof(animationIsPlaying); setAnimationIsPlaying(animationIsPlaying); // animationFrameIndex float animationFrameIndex; memcpy(&animationFrameIndex, dataAt, sizeof(animationFrameIndex)); dataAt += sizeof(animationFrameIndex); bytesRead += sizeof(animationFrameIndex); setAnimationFrameIndex(animationFrameIndex); // animationFPS float animationFPS; memcpy(&animationFPS, dataAt, sizeof(animationFPS)); dataAt += sizeof(animationFPS); bytesRead += sizeof(animationFPS); setAnimationFPS(animationFPS); } } return bytesRead; }