mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 04:43:31 +02:00
cleanup edit message memory management in octree packet sending
This commit is contained in:
parent
d9e10db011
commit
fa71c781f4
8 changed files with 223 additions and 227 deletions
|
@ -18,31 +18,28 @@
|
|||
#include "EntityItem.h"
|
||||
|
||||
|
||||
void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType::Value type,
|
||||
unsigned char* editBuffer, size_t length, int clockSkew) {
|
||||
|
||||
void EntityEditPacketSender::adjustEditPacketForClockSkew(PacketType::Value type, QByteArray& buffer, int clockSkew) {
|
||||
|
||||
if (type == PacketType::EntityAdd || type == PacketType::EntityEdit) {
|
||||
EntityItem::adjustEditPacketForClockSkew(editBuffer, length, clockSkew);
|
||||
EntityItem::adjustEditPacketForClockSkew(buffer, clockSkew);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityEditPacketSender::queueEditEntityMessage(PacketType::Value type, EntityItemID modelID,
|
||||
void EntityEditPacketSender::queueEditEntityMessage(PacketType::Value type, EntityItemID modelID,
|
||||
const EntityItemProperties& properties) {
|
||||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
}
|
||||
|
||||
// use MAX_PACKET_SIZE since it's static and guaranteed to be larger than _maxPacketSize
|
||||
unsigned char bufferOut[MAX_PACKET_SIZE];
|
||||
int sizeOut = 0;
|
||||
QByteArray bufferOut(NLPacket::maxPayloadSize(type), 0);
|
||||
|
||||
if (EntityItemProperties::encodeEntityEditPacket(type, modelID, properties, &bufferOut[0], _maxPacketSize, sizeOut)) {
|
||||
if (EntityItemProperties::encodeEntityEditPacket(type, modelID, properties, bufferOut)) {
|
||||
#ifdef WANT_DEBUG
|
||||
qCDebug(entities) << "calling queueOctreeEditMessage()...";
|
||||
qCDebug(entities) << " id:" << modelID;
|
||||
qCDebug(entities) << " properties:" << properties;
|
||||
#endif
|
||||
queueOctreeEditMessage(type, bufferOut, sizeOut);
|
||||
queueOctreeEditMessage(type, bufferOut);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,10 +47,10 @@ void EntityEditPacketSender::queueEraseEntityMessage(const EntityItemID& entityI
|
|||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
}
|
||||
// use MAX_PACKET_SIZE since it's static and guaranteed to be larger than _maxPacketSize
|
||||
unsigned char bufferOut[MAX_PACKET_SIZE];
|
||||
size_t sizeOut = 0;
|
||||
if (EntityItemProperties::encodeEraseEntityMessage(entityItemID, &bufferOut[0], _maxPacketSize, sizeOut)) {
|
||||
queueOctreeEditMessage(PacketType::EntityErase, bufferOut, sizeOut);
|
||||
|
||||
QByteArray bufferOut(NLPacket::maxPayloadSize(PacketType::EntityErase), 0);
|
||||
|
||||
if (EntityItemProperties::encodeEraseEntityMessage(entityItemID, bufferOut)) {
|
||||
queueOctreeEditMessage(PacketType::EntityErase, bufferOut);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,6 @@ public:
|
|||
|
||||
// My server type is the model server
|
||||
virtual char getMyNodeType() const { return NodeType::EntityServer; }
|
||||
virtual void adjustEditPacketForClockSkew(PacketType::Value type, unsigned char* editBuffer, size_t length, int clockSkew);
|
||||
virtual void adjustEditPacketForClockSkew(PacketType::Value type, QByteArray& buffer, int clockSkew);
|
||||
};
|
||||
#endif // hifi_EntityEditPacketSender_h
|
||||
|
|
|
@ -99,7 +99,7 @@ EntityItem::~EntityItem() {
|
|||
clearActions(simulation);
|
||||
}
|
||||
|
||||
// these pointers MUST be correct at delete, else we probably have a dangling backpointer
|
||||
// these pointers MUST be correct at delete, else we probably have a dangling backpointer
|
||||
// to this EntityItem in the corresponding data structure.
|
||||
assert(!_simulated);
|
||||
assert(!_element);
|
||||
|
@ -142,7 +142,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
return requestedProperties;
|
||||
}
|
||||
|
||||
OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* entityTreeElementExtraEncodeData) const {
|
||||
// ALL this fits...
|
||||
// object ID [16 bytes]
|
||||
|
@ -151,7 +151,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
// ByteCountCoded(last_edited to last_updated delta) [~1-8 bytes]
|
||||
// PropertyFlags<>( everything ) [1-2 bytes]
|
||||
// ~27-35 bytes...
|
||||
|
||||
|
||||
OctreeElement::AppendState appendState = OctreeElement::COMPLETED; // assume the best
|
||||
|
||||
// encode our ID as a byte count coded byte stream
|
||||
|
@ -189,7 +189,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
#ifdef WANT_DEBUG
|
||||
float editedAgo = getEditedAgo();
|
||||
QString agoAsString = formatSecondsElapsed(editedAgo);
|
||||
qCDebug(entities) << "Writing entity " << getEntityItemID() << " to buffer, lastEdited =" << lastEdited
|
||||
qCDebug(entities) << "Writing entity " << getEntityItemID() << " to buffer, lastEdited =" << lastEdited
|
||||
<< " ago=" << editedAgo << "seconds - " << agoAsString;
|
||||
#endif
|
||||
|
||||
|
@ -221,7 +221,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
if (successLastUpdatedFits) {
|
||||
successLastSimulatedFits = packetData->appendRawData(encodedSimulatedDelta);
|
||||
}
|
||||
|
||||
|
||||
if (successLastSimulatedFits) {
|
||||
propertyFlagsOffset = packetData->getUncompressedByteOffset();
|
||||
encodedPropertyFlags = propertyFlags;
|
||||
|
@ -229,7 +229,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
successPropertyFlagsFits = packetData->appendRawData(encodedPropertyFlags);
|
||||
}
|
||||
|
||||
bool headerFits = successIDFits && successTypeFits && successCreatedFits && successLastEditedFits
|
||||
bool headerFits = successIDFits && successTypeFits && successCreatedFits && successLastEditedFits
|
||||
&& successLastUpdatedFits && successPropertyFlagsFits;
|
||||
|
||||
int startOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
|
@ -286,9 +286,9 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
int endOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
encodedPropertyFlags = propertyFlags;
|
||||
int newPropertyFlagsLength = encodedPropertyFlags.length();
|
||||
packetData->updatePriorBytes(propertyFlagsOffset,
|
||||
packetData->updatePriorBytes(propertyFlagsOffset,
|
||||
(const unsigned char*)encodedPropertyFlags.constData(), encodedPropertyFlags.length());
|
||||
|
||||
|
||||
// if the size of the PropertyFlags shrunk, we need to shift everything down to front of packet.
|
||||
if (newPropertyFlagsLength < oldPropertyFlagsLength) {
|
||||
int oldSize = packetData->getUncompressedSize();
|
||||
|
@ -302,13 +302,13 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
} else {
|
||||
assert(newPropertyFlagsLength == oldPropertyFlagsLength); // should not have grown
|
||||
}
|
||||
|
||||
|
||||
packetData->endLevel(entityLevel);
|
||||
} else {
|
||||
packetData->discardLevel(entityLevel);
|
||||
appendState = OctreeElement::NONE; // if we got here, then we didn't include the item
|
||||
}
|
||||
|
||||
|
||||
// If any part of the model items didn't fit, then the element is considered partial
|
||||
if (appendState != OctreeElement::COMPLETED) {
|
||||
// add this item into our list for the next appendElementData() pass
|
||||
|
@ -338,7 +338,7 @@ int EntityItem::expectedBytes() {
|
|||
// clients use this method to unpack FULL updates from entity-server
|
||||
int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) {
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_SPLIT_MTU) {
|
||||
|
||||
|
||||
// NOTE: This shouldn't happen. The only versions of the bit stream that didn't support split mtu buffers should
|
||||
// be handled by the model subclass and shouldn't call this routine.
|
||||
qCDebug(entities) << "EntityItem::readEntityDataFromBuffer()... "
|
||||
|
@ -373,7 +373,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
_id = QUuid::fromRfc4122(encodedID);
|
||||
dataAt += encodedID.size();
|
||||
bytesRead += encodedID.size();
|
||||
|
||||
|
||||
// type
|
||||
QByteArray encodedType = originalDataBuffer.mid(bytesRead); // maximum possible size
|
||||
ByteCountCoded<quint32> typeCoder = encodedType;
|
||||
|
@ -671,7 +671,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||
if (overwriteLocalData) {
|
||||
if (!_simulationOwner.matchesValidID(myNodeID)) {
|
||||
|
||||
|
||||
_lastSimulated = now;
|
||||
}
|
||||
}
|
||||
|
@ -688,8 +688,8 @@ void EntityItem::debugDump() const {
|
|||
}
|
||||
|
||||
// adjust any internal timestamps to fix clock skew for this server
|
||||
void EntityItem::adjustEditPacketForClockSkew(unsigned char* editPacketBuffer, size_t length, int clockSkew) {
|
||||
unsigned char* dataAt = editPacketBuffer;
|
||||
void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, int clockSkew) {
|
||||
unsigned char* dataAt = reinterpret_cast<unsigned char*>(buffer.data());
|
||||
int octets = numberOfThreeBitSectionsInCode(dataAt);
|
||||
int lengthOfOctcode = bytesRequiredForCodeLength(octets);
|
||||
dataAt += lengthOfOctcode;
|
||||
|
@ -734,7 +734,7 @@ void EntityItem::setMass(float mass) {
|
|||
// Setting the mass actually changes the _density (at fixed volume), however
|
||||
// we must protect the density range to help maintain stability of physics simulation
|
||||
// therefore this method might not accept the mass that is supplied.
|
||||
|
||||
|
||||
float volume = _volumeMultiplier * getDimensions().x * getDimensions().y * getDimensions().z;
|
||||
|
||||
// compute new density
|
||||
|
@ -830,7 +830,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) {
|
|||
rotation = glm::normalize(dQ * rotation);
|
||||
dt -= PHYSICS_ENGINE_FIXED_SUBSTEP;
|
||||
}
|
||||
// NOTE: this final partial substep can drift away from a real Bullet simulation however
|
||||
// NOTE: this final partial substep can drift away from a real Bullet simulation however
|
||||
// it only becomes significant for rapidly rotating objects
|
||||
// (e.g. around PI/4 radians per substep, or 7.5 rotations/sec at 60 substeps/sec).
|
||||
glm::quat dQ = computeBulletRotationStep(_angularVelocity, dt);
|
||||
|
@ -866,7 +866,7 @@ void EntityItem::simulateKinematicMotion(float timeElapsed, bool setFlags) {
|
|||
qCDebug(entities) << " newPosition:" << newPosition;
|
||||
qCDebug(entities) << " glm::distance(newPosition, position):" << glm::distance(newPosition, position);
|
||||
#endif
|
||||
|
||||
|
||||
position = newPosition;
|
||||
|
||||
// apply effective acceleration, which will be the same as gravity if the Entity isn't at rest.
|
||||
|
@ -920,7 +920,7 @@ glm::vec3 EntityItem::worldToEntity(const glm::vec3& point) const {
|
|||
}
|
||||
|
||||
bool EntityItem::lifetimeHasExpired() const {
|
||||
return isMortal() && (getAge() > getLifetime());
|
||||
return isMortal() && (getAge() > getLifetime());
|
||||
}
|
||||
|
||||
quint64 EntityItem::getExpiry() const {
|
||||
|
@ -934,7 +934,7 @@ EntityItemProperties EntityItem::getProperties() const {
|
|||
properties._created = _created;
|
||||
|
||||
properties._type = getType();
|
||||
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(simulationOwner, getSimulationOwner);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(position, getPosition);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getDimensions); // NOTE: radius is obsolete
|
||||
|
@ -968,7 +968,7 @@ EntityItemProperties EntityItem::getProperties() const {
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getActionData);
|
||||
|
||||
properties._defaultSettings = false;
|
||||
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -1089,7 +1089,7 @@ void EntityItem::setTranformToCenter(const Transform& transform) {
|
|||
setTransform(transform);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Transform copy = transform;
|
||||
copy.postTranslate(getRegistrationPoint() - ENTITY_ITEM_HALF_VEC3); // Center to position
|
||||
setTransform(copy);
|
||||
|
@ -1104,8 +1104,8 @@ void EntityItem::setDimensions(const glm::vec3& value) {
|
|||
|
||||
/// The maximum bounding cube for the entity, independent of it's rotation.
|
||||
/// This accounts for the registration point (upon which rotation occurs around).
|
||||
///
|
||||
AACube EntityItem::getMaximumAACube() const {
|
||||
///
|
||||
AACube EntityItem::getMaximumAACube() const {
|
||||
// * we know that the position is the center of rotation
|
||||
glm::vec3 centerOfRotation = getPosition(); // also where _registration point is
|
||||
|
||||
|
@ -1115,7 +1115,7 @@ AACube EntityItem::getMaximumAACube() const {
|
|||
glm::vec3 registrationPoint = (getDimensions() * getRegistrationPoint());
|
||||
glm::vec3 registrationRemainder = (getDimensions() * (glm::vec3(1.0f, 1.0f, 1.0f) - getRegistrationPoint()));
|
||||
glm::vec3 furthestExtentFromRegistration = glm::max(registrationPoint, registrationRemainder);
|
||||
|
||||
|
||||
// * we know that if you rotate in any direction you would create a sphere
|
||||
// that has a radius of the length of furthest extent from registration point
|
||||
float radius = glm::length(furthestExtentFromRegistration);
|
||||
|
@ -1130,8 +1130,8 @@ AACube EntityItem::getMaximumAACube() const {
|
|||
|
||||
/// The minimum bounding cube for the entity accounting for it's rotation.
|
||||
/// This accounts for the registration point (upon which rotation occurs around).
|
||||
///
|
||||
AACube EntityItem::getMinimumAACube() const {
|
||||
///
|
||||
AACube EntityItem::getMinimumAACube() const {
|
||||
// _position represents the position of the registration point.
|
||||
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint;
|
||||
|
||||
|
@ -1142,15 +1142,15 @@ AACube EntityItem::getMinimumAACube() const {
|
|||
|
||||
// shift the extents to be relative to the position/registration point
|
||||
rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition());
|
||||
|
||||
|
||||
// the cube that best encompasses extents is...
|
||||
AABox box(rotatedExtentsRelativeToRegistrationPoint);
|
||||
glm::vec3 centerOfBox = box.calcCenter();
|
||||
float longestSide = box.getLargestDimension();
|
||||
float halfLongestSide = longestSide / 2.0f;
|
||||
glm::vec3 cornerOfCube = centerOfBox - glm::vec3(halfLongestSide, halfLongestSide, halfLongestSide);
|
||||
|
||||
|
||||
|
||||
|
||||
// old implementation... not correct!!!
|
||||
return AACube(cornerOfCube, longestSide);
|
||||
}
|
||||
|
@ -1158,15 +1158,15 @@ AACube EntityItem::getMinimumAACube() const {
|
|||
AABox EntityItem::getAABox() const {
|
||||
// _position represents the position of the registration point.
|
||||
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint;
|
||||
|
||||
|
||||
glm::vec3 unrotatedMinRelativeToEntity = - (getDimensions() * _registrationPoint);
|
||||
glm::vec3 unrotatedMaxRelativeToEntity = getDimensions() * registrationRemainder;
|
||||
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
|
||||
Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation());
|
||||
|
||||
|
||||
// shift the extents to be relative to the position/registration point
|
||||
rotatedExtentsRelativeToRegistrationPoint.shiftBy(getPosition());
|
||||
|
||||
|
||||
return AABox(rotatedExtentsRelativeToRegistrationPoint);
|
||||
}
|
||||
|
||||
|
@ -1182,8 +1182,8 @@ AABox EntityItem::getAABox() const {
|
|||
// ... ((radius * 2.0f) ^2) / 3 = maxDimension ^ 2
|
||||
// ... sqrt(((radius * 2.0f) ^2) / 3) = maxDimension
|
||||
// ... sqrt((diameter ^2) / 3) = maxDimension
|
||||
//
|
||||
void EntityItem::setRadius(float value) {
|
||||
//
|
||||
void EntityItem::setRadius(float value) {
|
||||
float diameter = value * 2.0f;
|
||||
float maxDimension = sqrt((diameter * diameter) / 3.0f);
|
||||
setDimensions(glm::vec3(maxDimension, maxDimension, maxDimension));
|
||||
|
@ -1193,7 +1193,7 @@ void EntityItem::setRadius(float value) {
|
|||
// ... radius = cornerToCornerLength / 2.0f
|
||||
// ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2)
|
||||
// ... radius = sqrt(3 x maxDimension ^ 2) / 2.0f;
|
||||
float EntityItem::getRadius() const {
|
||||
float EntityItem::getRadius() const {
|
||||
return 0.5f * glm::length(getDimensions());
|
||||
}
|
||||
|
||||
|
@ -1211,7 +1211,7 @@ void EntityItem::computeShapeInfo(ShapeInfo& info) {
|
|||
info.setParams(getShapeType(), 0.5f * getDimensions());
|
||||
}
|
||||
|
||||
void EntityItem::updatePosition(const glm::vec3& value) {
|
||||
void EntityItem::updatePosition(const glm::vec3& value) {
|
||||
auto delta = glm::distance(getPosition(), value);
|
||||
if (delta > IGNORE_POSITION_DELTA) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_POSITION;
|
||||
|
@ -1222,7 +1222,7 @@ void EntityItem::updatePosition(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||
void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||
auto delta = glm::distance(getDimensions(), value);
|
||||
if (delta > IGNORE_DIMENSIONS_DELTA) {
|
||||
setDimensions(value);
|
||||
|
@ -1233,7 +1233,7 @@ void EntityItem::updateDimensions(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateRotation(const glm::quat& rotation) {
|
||||
void EntityItem::updateRotation(const glm::quat& rotation) {
|
||||
if (getRotation() != rotation) {
|
||||
setRotation(rotation);
|
||||
|
||||
|
@ -1273,7 +1273,7 @@ void EntityItem::updateMass(float mass) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateVelocity(const glm::vec3& value) {
|
||||
void EntityItem::updateVelocity(const glm::vec3& value) {
|
||||
auto delta = glm::distance(_velocity, value);
|
||||
if (delta > IGNORE_LINEAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_LINEAR_VELOCITY;
|
||||
|
@ -1290,7 +1290,7 @@ void EntityItem::updateVelocity(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateDamping(float value) {
|
||||
void EntityItem::updateDamping(float value) {
|
||||
auto clampedDamping = glm::clamp(value, 0.0f, 1.0f);
|
||||
if (fabsf(_damping - clampedDamping) > IGNORE_DAMPING_DELTA) {
|
||||
_damping = clampedDamping;
|
||||
|
@ -1298,7 +1298,7 @@ void EntityItem::updateDamping(float value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateGravity(const glm::vec3& value) {
|
||||
void EntityItem::updateGravity(const glm::vec3& value) {
|
||||
auto delta = glm::distance(_gravity, value);
|
||||
if (delta > IGNORE_GRAVITY_DELTA) {
|
||||
_gravity = value;
|
||||
|
@ -1309,7 +1309,7 @@ void EntityItem::updateGravity(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
||||
void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
||||
auto delta = glm::distance(_angularVelocity, value);
|
||||
if (delta > IGNORE_ANGULAR_VELOCITY_DELTA) {
|
||||
_dirtyFlags |= EntityItem::DIRTY_ANGULAR_VELOCITY;
|
||||
|
@ -1326,7 +1326,7 @@ void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateAngularDamping(float value) {
|
||||
void EntityItem::updateAngularDamping(float value) {
|
||||
auto clampedDamping = glm::clamp(value, 0.0f, 1.0f);
|
||||
if (fabsf(_angularDamping - clampedDamping) > IGNORE_DAMPING_DELTA) {
|
||||
_angularDamping = clampedDamping;
|
||||
|
@ -1334,16 +1334,16 @@ void EntityItem::updateAngularDamping(float value) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateIgnoreForCollisions(bool value) {
|
||||
void EntityItem::updateIgnoreForCollisions(bool value) {
|
||||
if (_ignoreForCollisions != value) {
|
||||
_ignoreForCollisions = value;
|
||||
_ignoreForCollisions = value;
|
||||
_dirtyFlags |= EntityItem::DIRTY_COLLISION_GROUP;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateCollisionsWillMove(bool value) {
|
||||
void EntityItem::updateCollisionsWillMove(bool value) {
|
||||
if (_collisionsWillMove != value) {
|
||||
_collisionsWillMove = value;
|
||||
_collisionsWillMove = value;
|
||||
_dirtyFlags |= EntityItem::DIRTY_MOTION_TYPE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,7 +73,7 @@ const float ACTIVATION_ANGULAR_VELOCITY_DELTA = 0.03f;
|
|||
/// one directly, instead you must only construct one of it's derived classes with additional features.
|
||||
class EntityItem {
|
||||
// These two classes manage lists of EntityItem pointers and must be able to cleanup pointers when an EntityItem is deleted.
|
||||
// To make the cleanup robust each EntityItem has backpointers to its manager classes (which are only ever set/cleared by
|
||||
// To make the cleanup robust each EntityItem has backpointers to its manager classes (which are only ever set/cleared by
|
||||
// the managers themselves, hence they are fiends) whose NULL status can be used to determine which managers still need to
|
||||
// do cleanup.
|
||||
friend class EntityTreeElement;
|
||||
|
@ -161,15 +161,15 @@ public:
|
|||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData)
|
||||
{ return 0; }
|
||||
|
||||
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
virtual bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges) { return false; } // by default entity items don't add to scene
|
||||
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
virtual void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges) { } // by default entity items don't add to scene
|
||||
virtual void render(RenderArgs* args) { } // by default entity items don't know how to render
|
||||
|
||||
static int expectedBytes();
|
||||
|
||||
static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, size_t length, int clockSkew);
|
||||
static void adjustEditPacketForClockSkew(QByteArray& buffer, int clockSkew);
|
||||
|
||||
// perform update
|
||||
virtual void update(const quint64& now) { _lastUpdated = now; }
|
||||
|
@ -190,20 +190,20 @@ public:
|
|||
|
||||
// attributes applicable to all entity types
|
||||
EntityTypes::EntityType getType() const { return _type; }
|
||||
|
||||
|
||||
inline glm::vec3 getCenterPosition() const { return getTransformToCenter().getTranslation(); }
|
||||
void setCenterPosition(const glm::vec3& position);
|
||||
|
||||
|
||||
const Transform getTransformToCenter() const;
|
||||
void setTranformToCenter(const Transform& transform);
|
||||
|
||||
|
||||
inline const Transform& getTransform() const { return _transform; }
|
||||
inline void setTransform(const Transform& transform) { _transform = transform; }
|
||||
|
||||
|
||||
/// Position in meters (0.0 - TREE_SCALE)
|
||||
inline const glm::vec3& getPosition() const { return _transform.getTranslation(); }
|
||||
inline void setPosition(const glm::vec3& value) { _transform.setTranslation(value); }
|
||||
|
||||
|
||||
inline const glm::quat& getRotation() const { return _transform.getRotation(); }
|
||||
inline void setRotation(const glm::quat& rotation) { _transform.setRotation(rotation); }
|
||||
|
||||
|
@ -416,7 +416,7 @@ protected:
|
|||
float _glowLevel;
|
||||
float _localRenderAlpha;
|
||||
float _density = ENTITY_ITEM_DEFAULT_DENSITY; // kg/m^3
|
||||
// NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class
|
||||
// NOTE: _volumeMultiplier is used to allow some mass properties code exist in the EntityItem base class
|
||||
// rather than in all of the derived classes. If we ever collapse these classes to one we could do it a
|
||||
// different way.
|
||||
float _volumeMultiplier = 1.0f;
|
||||
|
|
|
@ -132,7 +132,7 @@ 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();
|
||||
|
@ -140,17 +140,17 @@ void EntityItemProperties::setAnimationSettings(const QString& value) {
|
|||
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;
|
||||
}
|
||||
|
@ -160,20 +160,20 @@ QString EntityItemProperties::getAnimationSettings() const {
|
|||
// 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);
|
||||
|
@ -194,10 +194,10 @@ void EntityItemProperties::debugDump() const {
|
|||
qCDebug(entities) << " _dimensions=" << getDimensions();
|
||||
qCDebug(entities) << " _modelURL=" << _modelURL;
|
||||
qCDebug(entities) << " _compoundShapeURL=" << _compoundShapeURL;
|
||||
|
||||
|
||||
getAtmosphere().debugDump();
|
||||
getSkybox().debugDump();
|
||||
|
||||
|
||||
qCDebug(entities) << " changed properties...";
|
||||
EntityPropertyFlags props = getChangedProperties();
|
||||
props.debugDumpBits();
|
||||
|
@ -287,7 +287,7 @@ void EntityItemProperties::setBackgroundModeFromString(const QString& background
|
|||
|
||||
EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
||||
EntityPropertyFlags changedProperties;
|
||||
|
||||
|
||||
CHECK_PROPERTY_CHANGE(PROP_POSITION, position);
|
||||
CHECK_PROPERTY_CHANGE(PROP_DIMENSIONS, dimensions);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ROTATION, rotation);
|
||||
|
@ -357,18 +357,18 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
changedProperties += _stage.getChangedProperties();
|
||||
changedProperties += _atmosphere.getChangedProperties();
|
||||
changedProperties += _skybox.getChangedProperties();
|
||||
|
||||
|
||||
return changedProperties;
|
||||
}
|
||||
|
||||
QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool skipDefaults) const {
|
||||
QScriptValue properties = engine->newObject();
|
||||
EntityItemProperties defaultEntityProperties;
|
||||
|
||||
|
||||
if (_idSet) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(id, _id.toString());
|
||||
}
|
||||
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(type, EntityTypes::getEntityTypeName(_type));
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(position);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(dimensions);
|
||||
|
@ -435,7 +435,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(name);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(collisionSoundURL);
|
||||
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightColor);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightIntensity);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(keyLightAmbientIntensity);
|
||||
|
@ -465,7 +465,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
sittingPoints.setProperty("length", _sittingPoints.size());
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(sittingPoints, sittingPoints); // gettable, but not settable
|
||||
}
|
||||
|
||||
|
||||
if (!skipDefaults) {
|
||||
AABox aaBox = getAABox();
|
||||
QScriptValue boundingBox = engine->newObject();
|
||||
|
@ -479,16 +479,16 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
boundingBox.setProperty("dimensions", boundingBoxDimensions);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(boundingBox, boundingBox); // gettable, but not settable
|
||||
}
|
||||
|
||||
|
||||
QString textureNamesList = _textureNames.join(",\n");
|
||||
if (!skipDefaults) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER_NO_SKIP(originalTextures, textureNamesList); // gettable, but not settable
|
||||
}
|
||||
|
||||
|
||||
_stage.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
|
||||
_atmosphere.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
|
||||
_skybox.copyToScriptValue(properties, engine, skipDefaults, defaultEntityProperties);
|
||||
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -497,7 +497,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
if (typeScriptValue.isValid()) {
|
||||
setType(typeScriptValue.toVariant().toString());
|
||||
}
|
||||
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(position, glmVec3, setPosition);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(dimensions, glmVec3, setDimensions);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(rotation, glmQuat, setRotation);
|
||||
|
@ -549,7 +549,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(marketplaceID, QString, setMarketplaceID);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(name, QString, setName);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionSoundURL, QString, setCollisionSoundURL);
|
||||
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightColor, xColor, setKeyLightColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightIntensity, float, setKeyLightIntensity);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(keyLightAmbientIntensity, float, setKeyLightAmbientIntensity);
|
||||
|
@ -615,14 +615,13 @@ void EntityItemPropertiesFromScriptValueHonorReadOnly(const QScriptValue &object
|
|||
// TODO: Implement support for script and visible properties.
|
||||
//
|
||||
bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, EntityItemID id, const EntityItemProperties& properties,
|
||||
unsigned char* bufferOut, int sizeIn, int& sizeOut) {
|
||||
OctreePacketData ourDataPacket(false, sizeIn); // create a packetData object to add out packet details too.
|
||||
QByteArray& buffer) {
|
||||
OctreePacketData ourDataPacket(false, buffer.size()); // create a packetData object to add out packet details too.
|
||||
OctreePacketData* packetData = &ourDataPacket; // we want a pointer to this so we can use our APPEND_ENTITY_PROPERTY macro
|
||||
|
||||
|
||||
bool success = true; // assume the best
|
||||
OctreeElement::AppendState appendState = OctreeElement::COMPLETED; // assume the best
|
||||
sizeOut = 0;
|
||||
|
||||
|
||||
// TODO: We need to review how jurisdictions should be handled for entities. (The old Models and Particles code
|
||||
// didn't do anything special for jurisdictions, so we're keeping that same behavior here.)
|
||||
//
|
||||
|
@ -632,35 +631,35 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
glm::vec3 rootPosition(0);
|
||||
float rootScale = 0.5f;
|
||||
unsigned char* octcode = pointToOctalCode(rootPosition.x, rootPosition.y, rootPosition.z, rootScale);
|
||||
|
||||
|
||||
success = packetData->startSubTree(octcode);
|
||||
delete[] octcode;
|
||||
|
||||
|
||||
// assuming we have rome to fit our octalCode, proceed...
|
||||
if (success) {
|
||||
|
||||
|
||||
// Now add our edit content details...
|
||||
|
||||
|
||||
// id
|
||||
// encode our ID as a byte count coded byte stream
|
||||
QByteArray encodedID = id.toRfc4122(); // NUM_BYTES_RFC4122_UUID
|
||||
|
||||
|
||||
// encode our ID as a byte count coded byte stream
|
||||
ByteCountCoded<quint32> tokenCoder;
|
||||
QByteArray encodedToken;
|
||||
|
||||
|
||||
// encode our type as a byte count coded byte stream
|
||||
ByteCountCoded<quint32> typeCoder = (quint32)properties.getType();
|
||||
QByteArray encodedType = typeCoder;
|
||||
|
||||
|
||||
quint64 updateDelta = 0; // this is an edit so by definition, it's update is in sync
|
||||
ByteCountCoded<quint64> updateDeltaCoder = updateDelta;
|
||||
QByteArray encodedUpdateDelta = updateDeltaCoder;
|
||||
|
||||
|
||||
EntityPropertyFlags propertyFlags(PROP_LAST_ITEM);
|
||||
EntityPropertyFlags requestedProperties = properties.getChangedProperties();
|
||||
EntityPropertyFlags propertiesDidntFit = requestedProperties;
|
||||
|
||||
|
||||
// TODO: we need to handle the multi-pass form of this, similar to how we handle entity data
|
||||
//
|
||||
// If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item,
|
||||
|
@ -668,46 +667,46 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
//if (modelTreeElementExtraEncodeData && modelTreeElementExtraEncodeData->includedItems.contains(getEntityItemID())) {
|
||||
// requestedProperties = modelTreeElementExtraEncodeData->includedItems.value(getEntityItemID());
|
||||
//}
|
||||
|
||||
|
||||
LevelDetails entityLevel = packetData->startLevel();
|
||||
|
||||
|
||||
// Last Edited quint64 always first, before any other details, which allows us easy access to adjusting this
|
||||
// timestamp for clock skew
|
||||
quint64 lastEdited = properties.getLastEdited();
|
||||
bool successLastEditedFits = packetData->appendValue(lastEdited);
|
||||
|
||||
|
||||
bool successIDFits = packetData->appendRawData(encodedID);
|
||||
if (successIDFits) {
|
||||
successIDFits = packetData->appendRawData(encodedToken);
|
||||
}
|
||||
bool successTypeFits = packetData->appendRawData(encodedType);
|
||||
|
||||
|
||||
// NOTE: We intentionally do not send "created" times in edit messages. This is because:
|
||||
// 1) if the edit is to an existing entity, the created time can not be changed
|
||||
// 2) if the edit is to a new entity, the created time is the last edited time
|
||||
|
||||
|
||||
// TODO: Should we get rid of this in this in edit packets, since this has to always be 0?
|
||||
bool successLastUpdatedFits = packetData->appendRawData(encodedUpdateDelta);
|
||||
|
||||
|
||||
int propertyFlagsOffset = packetData->getUncompressedByteOffset();
|
||||
QByteArray encodedPropertyFlags = propertyFlags;
|
||||
int oldPropertyFlagsLength = encodedPropertyFlags.length();
|
||||
bool successPropertyFlagsFits = packetData->appendRawData(encodedPropertyFlags);
|
||||
int propertyCount = 0;
|
||||
|
||||
|
||||
bool headerFits = successIDFits && successTypeFits && successLastEditedFits
|
||||
&& successLastUpdatedFits && successPropertyFlagsFits;
|
||||
|
||||
|
||||
int startOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
|
||||
|
||||
if (headerFits) {
|
||||
bool successPropertyFits;
|
||||
propertyFlags -= PROP_LAST_ITEM; // clear the last item for now, we may or may not set it as the actual item
|
||||
|
||||
|
||||
// These items would go here once supported....
|
||||
// PROP_PAGED_PROPERTY,
|
||||
// PROP_CUSTOM_PROPERTIES_INCLUDED,
|
||||
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, properties._simulationOwner.toByteArray());
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, properties.getPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, properties.getDimensions()); // NOTE: PROP_RADIUS obsolete
|
||||
|
@ -733,12 +732,12 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, properties.getUserData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_HREF, properties.getHref());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, properties.getDescription());
|
||||
|
||||
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Web) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_SOURCE_URL, properties.getSourceUrl());
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Text) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight());
|
||||
|
@ -746,7 +745,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, properties.getBackgroundColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_FACE_CAMERA, properties.getFaceCamera());
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, properties.getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
|
||||
|
@ -758,7 +757,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_SETTINGS, properties.getAnimationSettings());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)(properties.getShapeType()));
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Light) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, properties.getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
|
||||
|
@ -766,7 +765,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, properties.getExponent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, properties.getCutoff());
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::ParticleEffect) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, properties.getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, properties.getAnimationFrameIndex());
|
||||
|
@ -781,24 +780,24 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
APPEND_ENTITY_PROPERTY(PROP_LOCAL_GRAVITY, properties.getLocalGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, properties.getParticleRadius());
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Zone) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_COLOR, properties.getKeyLightColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_INTENSITY, properties.getKeyLightIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_AMBIENT_INTENSITY, properties.getKeyLightAmbientIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEYLIGHT_DIRECTION, properties.getKeyLightDirection());
|
||||
|
||||
|
||||
_staticStage.setProperties(properties);
|
||||
_staticStage.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
|
||||
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)properties.getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, properties.getCompoundShapeURL());
|
||||
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, (uint32_t)properties.getBackgroundMode());
|
||||
|
||||
|
||||
_staticAtmosphere.setProperties(properties);
|
||||
_staticAtmosphere.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
|
||||
|
||||
|
||||
_staticSkybox.setProperties(properties);
|
||||
_staticSkybox.appentToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState );
|
||||
}
|
||||
|
@ -808,12 +807,12 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
APPEND_ENTITY_PROPERTY(PROP_VOXEL_DATA, properties.getVoxelData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VOXEL_SURFACE_STYLE, properties.getVoxelSurfaceStyle());
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Line) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, properties.getLineWidth());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, properties.getLinePoints());
|
||||
}
|
||||
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, properties.getMarketplaceID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL());
|
||||
|
@ -821,62 +820,63 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
}
|
||||
if (propertyCount > 0) {
|
||||
int endOfEntityItemData = packetData->getUncompressedByteOffset();
|
||||
|
||||
|
||||
encodedPropertyFlags = propertyFlags;
|
||||
int newPropertyFlagsLength = encodedPropertyFlags.length();
|
||||
packetData->updatePriorBytes(propertyFlagsOffset,
|
||||
(const unsigned char*)encodedPropertyFlags.constData(), encodedPropertyFlags.length());
|
||||
|
||||
|
||||
// if the size of the PropertyFlags shrunk, we need to shift everything down to front of packet.
|
||||
if (newPropertyFlagsLength < oldPropertyFlagsLength) {
|
||||
int oldSize = packetData->getUncompressedSize();
|
||||
|
||||
|
||||
const unsigned char* modelItemData = packetData->getUncompressedData(propertyFlagsOffset + oldPropertyFlagsLength);
|
||||
int modelItemDataLength = endOfEntityItemData - startOfEntityItemData;
|
||||
int newEntityItemDataStart = propertyFlagsOffset + newPropertyFlagsLength;
|
||||
packetData->updatePriorBytes(newEntityItemDataStart, modelItemData, modelItemDataLength);
|
||||
|
||||
|
||||
int newSize = oldSize - (oldPropertyFlagsLength - newPropertyFlagsLength);
|
||||
packetData->setUncompressedSize(newSize);
|
||||
|
||||
|
||||
} else {
|
||||
assert(newPropertyFlagsLength == oldPropertyFlagsLength); // should not have grown
|
||||
}
|
||||
|
||||
|
||||
packetData->endLevel(entityLevel);
|
||||
} else {
|
||||
packetData->discardLevel(entityLevel);
|
||||
appendState = OctreeElement::NONE; // if we got here, then we didn't include the item
|
||||
}
|
||||
|
||||
|
||||
// If any part of the model items didn't fit, then the element is considered partial
|
||||
if (appendState != OctreeElement::COMPLETED) {
|
||||
|
||||
|
||||
// TODO: handle mechanism for handling partial fitting data!
|
||||
// add this item into our list for the next appendElementData() pass
|
||||
//modelTreeElementExtraEncodeData->includedItems.insert(getEntityItemID(), propertiesDidntFit);
|
||||
|
||||
|
||||
// for now, if it's not complete, it's not successful
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (success) {
|
||||
packetData->endSubTree();
|
||||
|
||||
const unsigned char* finalizedData = packetData->getFinalizedData();
|
||||
int finalizedSize = packetData->getFinalizedSize();
|
||||
if (finalizedSize <= sizeIn) {
|
||||
memcpy(bufferOut, finalizedData, finalizedSize);
|
||||
sizeOut = finalizedSize;
|
||||
int finalizedSize = packetData->getFinalizedSize();
|
||||
|
||||
if (finalizedSize <= buffer.size()) {
|
||||
buffer.replace(0, finalizedSize, finalizedData, finalizedSize);
|
||||
buffer.resize(finalizedSize);
|
||||
} else {
|
||||
qCDebug(entities) << "ERROR - encoded edit message doesn't fit in output buffer.";
|
||||
sizeOut = 0;
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
packetData->discardSubTree();
|
||||
sizeOut = 0;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -899,19 +899,19 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType::Value command, Ent
|
|||
bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes,
|
||||
EntityItemID& entityID, EntityItemProperties& properties) {
|
||||
bool valid = false;
|
||||
|
||||
|
||||
const unsigned char* dataAt = data;
|
||||
processedBytes = 0;
|
||||
|
||||
|
||||
// the first part of the data is an octcode, this is a required element of the edit packet format, but we don't
|
||||
// actually use it, we do need to skip it and read to the actual data we care about.
|
||||
int octets = numberOfThreeBitSectionsInCode(data);
|
||||
int bytesToReadOfOctcode = bytesRequiredForCodeLength(octets);
|
||||
|
||||
|
||||
// we don't actually do anything with this octcode...
|
||||
dataAt += bytesToReadOfOctcode;
|
||||
processedBytes += bytesToReadOfOctcode;
|
||||
|
||||
|
||||
// Edit packets have a last edited time stamp immediately following the octcode.
|
||||
// NOTE: the edit times have been set by the editor to match out clock, so we don't need to adjust
|
||||
// these times for clock skew at this point.
|
||||
|
@ -920,20 +920,20 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
dataAt += sizeof(lastEdited);
|
||||
processedBytes += sizeof(lastEdited);
|
||||
properties.setLastEdited(lastEdited);
|
||||
|
||||
|
||||
// NOTE: We intentionally do not send "created" times in edit messages. This is because:
|
||||
// 1) if the edit is to an existing entity, the created time can not be changed
|
||||
// 2) if the edit is to a new entity, the created time is the last edited time
|
||||
|
||||
|
||||
// encoded id
|
||||
QByteArray encodedID((const char*)dataAt, NUM_BYTES_RFC4122_UUID); // maximum possible size
|
||||
QUuid editID = QUuid::fromRfc4122(encodedID);
|
||||
dataAt += encodedID.size();
|
||||
processedBytes += encodedID.size();
|
||||
|
||||
|
||||
entityID = editID;
|
||||
valid = true;
|
||||
|
||||
|
||||
// Entity Type...
|
||||
QByteArray encodedType((const char*)dataAt, (bytesToRead - processedBytes));
|
||||
ByteCountCoded<quint32> typeCoder = encodedType;
|
||||
|
@ -942,22 +942,22 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
encodedType = typeCoder; // determine true bytesToRead
|
||||
dataAt += encodedType.size();
|
||||
processedBytes += encodedType.size();
|
||||
|
||||
|
||||
// Update Delta - when was this item updated relative to last edit... this really should be 0
|
||||
// TODO: Should we get rid of this in this in edit packets, since this has to always be 0?
|
||||
// TODO: do properties need to handle lastupdated???
|
||||
|
||||
|
||||
// last updated is stored as ByteCountCoded delta from lastEdited
|
||||
QByteArray encodedUpdateDelta((const char*)dataAt, (bytesToRead - processedBytes));
|
||||
ByteCountCoded<quint64> updateDeltaCoder = encodedUpdateDelta;
|
||||
encodedUpdateDelta = updateDeltaCoder; // determine true bytesToRead
|
||||
dataAt += encodedUpdateDelta.size();
|
||||
processedBytes += encodedUpdateDelta.size();
|
||||
|
||||
|
||||
// TODO: Do we need this lastUpdated?? We don't seem to use it.
|
||||
//quint64 updateDelta = updateDeltaCoder;
|
||||
//quint64 lastUpdated = lastEdited + updateDelta; // don't adjust for clock skew since we already did that for lastEdited
|
||||
|
||||
|
||||
// Property Flags...
|
||||
QByteArray encodedPropertyFlags((const char*)dataAt, (bytesToRead - processedBytes));
|
||||
EntityPropertyFlags propertyFlags = encodedPropertyFlags;
|
||||
|
@ -989,12 +989,12 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_HREF, QString, setHref);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DESCRIPTION, QString, setDescription);
|
||||
|
||||
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Web) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SOURCE_URL, QString, setSourceUrl);
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Text) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight);
|
||||
|
@ -1002,7 +1002,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_COLOR, xColor, setBackgroundColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FACE_CAMERA, bool, setFaceCamera);
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MODEL_URL, QString, setModelURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
|
@ -1014,7 +1014,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Light) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, xColor, setColor);
|
||||
|
@ -1022,14 +1022,14 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CUTOFF, float, setCutoff);
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::ParticleEffect) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_PLAYING, bool, setAnimationIsPlaying);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_SETTINGS, QString, setAnimationSettings);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MAX_PARTICLES, float, setMaxParticles);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LIFESPAN, float, setLifespan);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMIT_RATE, float, setEmitRate);
|
||||
|
@ -1038,15 +1038,15 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCAL_GRAVITY, float, setLocalGravity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius);
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Zone) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_COLOR, xColor, setKeyLightColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_INTENSITY, float, setKeyLightIntensity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_AMBIENT_INTENSITY, float, setKeyLightAmbientIntensity);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_KEYLIGHT_DIRECTION, glm::vec3, setKeyLightDirection);
|
||||
|
||||
|
||||
properties.getStage().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
|
||||
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode);
|
||||
|
@ -1059,12 +1059,12 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VOXEL_DATA, QByteArray, setVoxelData);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VOXEL_SURFACE_STYLE, uint16_t, setVoxelSurfaceStyle);
|
||||
}
|
||||
|
||||
|
||||
if (properties.getType() == EntityTypes::Line) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_WIDTH, float, setLineWidth);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
}
|
||||
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||
|
@ -1077,28 +1077,28 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
// NOTE: This version will only encode the portion of the edit message immediately following the
|
||||
// header it does not include the send times and sequence number because that is handled by the
|
||||
// edit packet sender...
|
||||
bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityItemID,
|
||||
unsigned char* outputBuffer, size_t maxLength, size_t& outputLength) {
|
||||
|
||||
unsigned char* copyAt = outputBuffer;
|
||||
bool EntityItemProperties::encodeEraseEntityMessage(const EntityItemID& entityItemID, QByteArray& buffer) {
|
||||
|
||||
char* copyAt = buffer.data();
|
||||
uint16_t numberOfIds = 1; // only one entity ID in this message
|
||||
|
||||
if (maxLength < sizeof(numberOfIds) + NUM_BYTES_RFC4122_UUID) {
|
||||
|
||||
int outputLength = 0;
|
||||
|
||||
if (buffer.size() < sizeof(numberOfIds) + NUM_BYTES_RFC4122_UUID) {
|
||||
qCDebug(entities) << "ERROR - encodeEraseEntityMessage() called with buffer that is too small!";
|
||||
outputLength = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(copyAt, &numberOfIds, sizeof(numberOfIds));
|
||||
copyAt += sizeof(numberOfIds);
|
||||
outputLength = sizeof(numberOfIds);
|
||||
|
||||
QUuid entityID = entityItemID;
|
||||
QByteArray encodedEntityID = entityID.toRfc4122();
|
||||
|
||||
memcpy(copyAt, encodedEntityID.constData(), NUM_BYTES_RFC4122_UUID);
|
||||
|
||||
memcpy(copyAt, entityItemID.toRfc4122().constData(), NUM_BYTES_RFC4122_UUID);
|
||||
copyAt += NUM_BYTES_RFC4122_UUID;
|
||||
outputLength += NUM_BYTES_RFC4122_UUID;
|
||||
|
||||
|
||||
buffer.resize(outputLength);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1137,19 +1137,19 @@ void EntityItemProperties::markAllChanged() {
|
|||
_isSpotlightChanged = true;
|
||||
_ignoreForCollisionsChanged = true;
|
||||
_collisionsWillMoveChanged = true;
|
||||
|
||||
|
||||
_intensityChanged = true;
|
||||
_exponentChanged = true;
|
||||
_cutoffChanged = true;
|
||||
_lockedChanged = true;
|
||||
_texturesChanged = true;
|
||||
|
||||
|
||||
_textChanged = true;
|
||||
_lineHeightChanged = true;
|
||||
_textColorChanged = true;
|
||||
_backgroundColorChanged = true;
|
||||
_shapeTypeChanged = true;
|
||||
|
||||
|
||||
_maxParticlesChanged = true;
|
||||
_lifespanChanged = true;
|
||||
_emitRateChanged = true;
|
||||
|
@ -1157,24 +1157,24 @@ void EntityItemProperties::markAllChanged() {
|
|||
_emitStrengthChanged = true;
|
||||
_localGravityChanged = true;
|
||||
_particleRadiusChanged = true;
|
||||
|
||||
|
||||
_marketplaceIDChanged = true;
|
||||
|
||||
|
||||
_keyLightColorChanged = true;
|
||||
_keyLightIntensityChanged = true;
|
||||
_keyLightAmbientIntensityChanged = true;
|
||||
_keyLightDirectionChanged = true;
|
||||
|
||||
|
||||
_backgroundModeChanged = true;
|
||||
_stage.markAllChanged();
|
||||
_atmosphere.markAllChanged();
|
||||
_skybox.markAllChanged();
|
||||
|
||||
|
||||
_sourceUrlChanged = true;
|
||||
_voxelVolumeSizeChanged = true;
|
||||
_voxelDataChanged = true;
|
||||
_voxelSurfaceStyleChanged = true;
|
||||
|
||||
|
||||
_lineWidthChanged = true;
|
||||
_linePointsChanged = true;
|
||||
|
||||
|
@ -1190,40 +1190,40 @@ void EntityItemProperties::markAllChanged() {
|
|||
AACube EntityItemProperties::getMaximumAACube() const {
|
||||
// * we know that the position is the center of rotation
|
||||
glm::vec3 centerOfRotation = _position; // also where _registration point is
|
||||
|
||||
|
||||
// * we know that the registration point is the center of rotation
|
||||
// * we can calculate the length of the furthest extent from the registration point
|
||||
// as the dimensions * max (registrationPoint, (1.0,1.0,1.0) - registrationPoint)
|
||||
glm::vec3 registrationPoint = (_dimensions * _registrationPoint);
|
||||
glm::vec3 registrationRemainder = (_dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint));
|
||||
glm::vec3 furthestExtentFromRegistration = glm::max(registrationPoint, registrationRemainder);
|
||||
|
||||
|
||||
// * we know that if you rotate in any direction you would create a sphere
|
||||
// that has a radius of the length of furthest extent from registration point
|
||||
float radius = glm::length(furthestExtentFromRegistration);
|
||||
|
||||
|
||||
// * we know that the minimum bounding cube of this maximum possible sphere is
|
||||
// (center - radius) to (center + radius)
|
||||
glm::vec3 minimumCorner = centerOfRotation - glm::vec3(radius, radius, radius);
|
||||
float diameter = radius * 2.0f;
|
||||
|
||||
|
||||
return AACube(minimumCorner, diameter);
|
||||
}
|
||||
|
||||
// The minimum bounding box for the entity.
|
||||
AABox EntityItemProperties::getAABox() const {
|
||||
|
||||
|
||||
// _position represents the position of the registration point.
|
||||
glm::vec3 registrationRemainder = glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint;
|
||||
|
||||
|
||||
glm::vec3 unrotatedMinRelativeToEntity = - (_dimensions * _registrationPoint);
|
||||
glm::vec3 unrotatedMaxRelativeToEntity = _dimensions * registrationRemainder;
|
||||
Extents unrotatedExtentsRelativeToRegistrationPoint = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity };
|
||||
Extents rotatedExtentsRelativeToRegistrationPoint = unrotatedExtentsRelativeToRegistrationPoint.getRotated(getRotation());
|
||||
|
||||
|
||||
// shift the extents to be relative to the position/registration point
|
||||
rotatedExtentsRelativeToRegistrationPoint.shiftBy(_position);
|
||||
|
||||
|
||||
return AABox(rotatedExtentsRelativeToRegistrationPoint);
|
||||
}
|
||||
|
||||
|
@ -1233,7 +1233,7 @@ bool EntityItemProperties::hasTerseUpdateChanges() const {
|
|||
}
|
||||
|
||||
bool EntityItemProperties::hasMiscPhysicsChanges() const {
|
||||
return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged
|
||||
return _gravityChanged || _dimensionsChanged || _densityChanged || _frictionChanged
|
||||
|| _restitutionChanged || _dampingChanged || _angularDampingChanged || _registrationPointChanged ||
|
||||
_compoundShapeURLChanged || _collisionsWillMoveChanged || _ignoreForCollisionsChanged;
|
||||
}
|
||||
|
|
|
@ -175,11 +175,9 @@ public:
|
|||
void setLocalRenderAlpha(float value) { _localRenderAlpha = value; _localRenderAlphaChanged = true; }
|
||||
|
||||
static bool encodeEntityEditPacket(PacketType::Value command, EntityItemID id, const EntityItemProperties& properties,
|
||||
unsigned char* bufferOut, int sizeIn, int& sizeOut);
|
||||
|
||||
static bool encodeEraseEntityMessage(const EntityItemID& entityItemID,
|
||||
unsigned char* outputBuffer, size_t maxLength, size_t& outputLength);
|
||||
QByteArray& buffer);
|
||||
|
||||
static bool encodeEraseEntityMessage(const EntityItemID& entityItemID, QByteArray& buffer);
|
||||
|
||||
static bool decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes,
|
||||
EntityItemID& entityID, EntityItemProperties& properties);
|
||||
|
@ -201,7 +199,7 @@ public:
|
|||
QString getSimulatorIDAsString() const { return _simulationOwner.getID().toString().mid(1,36).toUpper(); }
|
||||
|
||||
void setVoxelDataDirty() { _voxelDataChanged = true; }
|
||||
|
||||
|
||||
void setLinePointsDirty() {_linePointsChanged = true; }
|
||||
|
||||
void setCreated(QDateTime& v);
|
||||
|
@ -244,12 +242,12 @@ void EntityItemPropertiesFromScriptValueHonorReadOnly(const QScriptValue &object
|
|||
|
||||
|
||||
// define these inline here so the macros work
|
||||
inline void EntityItemProperties::setPosition(const glm::vec3& value)
|
||||
inline void EntityItemProperties::setPosition(const glm::vec3& value)
|
||||
{ _position = glm::clamp(value, 0.0f, (float)TREE_SCALE); _positionChanged = true; }
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
||||
debug << "EntityItemProperties[" << "\n";
|
||||
|
||||
|
||||
debug << " _type:" << properties.getType() << "\n";
|
||||
|
||||
// TODO: figure out why position and animationSettings don't seem to like the macro approach
|
||||
|
|
|
@ -128,8 +128,8 @@ void OctreeEditPacketSender::processPreServerExistsPackets() {
|
|||
|
||||
// Then "process" all the packable messages...
|
||||
while (!_preServerEdits.empty()) {
|
||||
EditMessageTuple editMessage = std::move(_preServerEdits.front());
|
||||
queueOctreeEditMessage(std::get<0>(editMessage), std::get<1>(editMessage), std::get<2>(editMessage));
|
||||
EditMessagePair& editMessage = _preServerEdits.front();
|
||||
queueOctreeEditMessage(editMessage.first, editMessage.second);
|
||||
_preServerEdits.pop_front();
|
||||
}
|
||||
|
||||
|
@ -194,8 +194,8 @@ void OctreeEditPacketSender::queuePacketToNodes(std::unique_ptr<NLPacket> packet
|
|||
}
|
||||
|
||||
|
||||
// NOTE: editPacketBuffer - is JUST the octcode/color and does not contain the packet header!
|
||||
void OctreeEditPacketSender::queueOctreeEditMessage(PacketType::Value type, unsigned char* editPacketBuffer, size_t length) {
|
||||
// NOTE: editMessage - is JUST the octcode/color and does not contain the packet header
|
||||
void OctreeEditPacketSender::queueOctreeEditMessage(PacketType::Value type, QByteArray& editMessage) {
|
||||
|
||||
if (!_shouldSend) {
|
||||
return; // bail early
|
||||
|
@ -205,9 +205,10 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType::Value type, unsi
|
|||
// jurisdictions for processing
|
||||
if (!serversExist()) {
|
||||
if (_maxPendingMessages > 0) {
|
||||
EditMessageTuple messageTuple { type, editPacketBuffer, length };
|
||||
EditMessagePair messagePair { type, QByteArray(editMessage) };
|
||||
|
||||
_pendingPacketsLock.lock();
|
||||
_preServerEdits.push_back(messageTuple);
|
||||
_preServerEdits.push_back(messagePair);
|
||||
|
||||
// if we've saved MORE than out max, then clear out the oldest packet...
|
||||
int allPendingMessages = _preServerSingleMessagePackets.size() + _preServerEdits.size();
|
||||
|
@ -239,7 +240,8 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType::Value type, unsi
|
|||
_serverJurisdictions->lockForRead();
|
||||
if ((*_serverJurisdictions).find(nodeUUID) != (*_serverJurisdictions).end()) {
|
||||
const JurisdictionMap& map = (*_serverJurisdictions)[nodeUUID];
|
||||
isMyJurisdiction = (map.isMyJurisdiction(editPacketBuffer, CHECK_NODE_ONLY) == JurisdictionMap::WITHIN);
|
||||
isMyJurisdiction = (map.isMyJurisdiction(reinterpret_cast<const unsigned char*>(editMessage.data()),
|
||||
CHECK_NODE_ONLY) == JurisdictionMap::WITHIN);
|
||||
} else {
|
||||
isMyJurisdiction = false;
|
||||
}
|
||||
|
@ -253,7 +255,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType::Value type, unsi
|
|||
} else {
|
||||
// If we're switching type, then we send the last one and start over
|
||||
if ((type != bufferedPacket->readType() && bufferedPacket->getSizeUsed() > 0) ||
|
||||
(length >= bufferedPacket->bytesAvailable())) {
|
||||
(editMessage.size() >= bufferedPacket->bytesAvailable())) {
|
||||
|
||||
// create the new packet and swap it with the packet in _pendingEditPackets
|
||||
auto packetToRelease = initializePacket(type, node->getClockSkewUsec());
|
||||
|
@ -269,10 +271,10 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType::Value type, unsi
|
|||
// We call this virtual function that allows our specific type of EditPacketSender to
|
||||
// fixup the buffer for any clock skew
|
||||
if (node->getClockSkewUsec() != 0) {
|
||||
adjustEditPacketForClockSkew(type, editPacketBuffer, length, node->getClockSkewUsec());
|
||||
adjustEditPacketForClockSkew(type, editMessage, node->getClockSkewUsec());
|
||||
}
|
||||
|
||||
bufferedPacket->write(reinterpret_cast<char*>(editPacketBuffer), length);
|
||||
bufferedPacket->write(editMessage);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
/// Queues a single edit message. Will potentially send a pending multi-command packet. Determines which server
|
||||
/// node or nodes the packet should be sent to. Can be called even before servers are known, in which case up to
|
||||
/// MaxPendingMessages will be buffered and processed when servers are known.
|
||||
void queueOctreeEditMessage(PacketType::Value type, unsigned char* editPacketBuffer, size_t length);
|
||||
void queueOctreeEditMessage(PacketType::Value type, QByteArray& editMessage);
|
||||
|
||||
/// Releases all queued messages even if those messages haven't filled an MTU packet. This will move the packed message
|
||||
/// packets onto the send queue. If running in threaded mode, the caller does not need to do any further processing to
|
||||
|
@ -74,8 +74,7 @@ public:
|
|||
|
||||
// you must override these...
|
||||
virtual char getMyNodeType() const = 0;
|
||||
virtual void adjustEditPacketForClockSkew(PacketType::Value type,
|
||||
unsigned char* editPacketBuffer, size_t length, int clockSkew) { }
|
||||
virtual void adjustEditPacketForClockSkew(PacketType::Value type, QByteArray& buffer, int clockSkew) { }
|
||||
|
||||
void processNackPacket(const QByteArray& packet);
|
||||
|
||||
|
@ -83,7 +82,7 @@ public slots:
|
|||
void nodeKilled(SharedNodePointer node);
|
||||
|
||||
protected:
|
||||
using EditMessageTuple = std::tuple<PacketType::Value, unsigned char*, int>;
|
||||
using EditMessagePair = std::pair<PacketType::Value, QByteArray>;
|
||||
|
||||
bool _shouldSend;
|
||||
void queuePacketToNode(const QUuid& nodeID, std::unique_ptr<NLPacket> packet);
|
||||
|
@ -102,7 +101,7 @@ protected:
|
|||
bool _releaseQueuedMessagesPending;
|
||||
QMutex _pendingPacketsLock;
|
||||
QMutex _packetsQueueLock; // don't let different threads release the queue while another thread is writing to it
|
||||
std::list<EditMessageTuple> _preServerEdits; // these will get packed into other larger packets
|
||||
std::list<EditMessagePair> _preServerEdits; // these will get packed into other larger packets
|
||||
std::list<std::unique_ptr<NLPacket>> _preServerSingleMessagePackets; // these will go out as is
|
||||
|
||||
NodeToJurisdictionMap* _serverJurisdictions;
|
||||
|
|
Loading…
Reference in a new issue