mirror of
https://github.com/AleziaKurdis/overte.git
synced 2025-08-08 07:46:54 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into propertyRangeAudit
This commit is contained in:
commit
eff9d11437
104 changed files with 3455 additions and 1949 deletions
|
@ -276,6 +276,7 @@ void AssignmentClientMonitor::checkSpares() {
|
|||
|
||||
// Spawn or kill children, as needed. If --min or --max weren't specified, allow the child count
|
||||
// to drift up or down as far as needed.
|
||||
|
||||
if (spareCount < 1 || totalCount < _minAssignmentClientForks) {
|
||||
if (!_maxAssignmentClientForks || totalCount < _maxAssignmentClientForks) {
|
||||
spawnChildClient();
|
||||
|
@ -307,7 +308,7 @@ void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer<ReceivedMes
|
|||
AssignmentClientChildData* childData = nullptr;
|
||||
|
||||
if (!matchingNode) {
|
||||
// The parent only expects to be talking with prorams running on this same machine.
|
||||
// The parent only expects to be talking with programs running on this same machine.
|
||||
if (senderSockAddr.getAddress() == QHostAddress::LocalHost ||
|
||||
senderSockAddr.getAddress() == QHostAddress::LocalHostIPv6) {
|
||||
|
||||
|
@ -316,9 +317,9 @@ void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer<ReceivedMes
|
|||
matchingNode = DependencyManager::get<LimitedNodeList>()->addOrUpdateNode(senderID, NodeType::Unassigned,
|
||||
senderSockAddr, senderSockAddr);
|
||||
|
||||
auto childData = std::unique_ptr<AssignmentClientChildData>
|
||||
auto newChildData = std::unique_ptr<AssignmentClientChildData>
|
||||
{ new AssignmentClientChildData(Assignment::Type::AllTypes) };
|
||||
matchingNode->setLinkedData(std::move(childData));
|
||||
matchingNode->setLinkedData(std::move(newChildData));
|
||||
} else {
|
||||
// tell unknown assignment-client child to exit.
|
||||
qDebug() << "Asking unknown child at" << senderSockAddr << "to exit.";
|
||||
|
@ -329,9 +330,8 @@ void AssignmentClientMonitor::handleChildStatusPacket(QSharedPointer<ReceivedMes
|
|||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
childData = dynamic_cast<AssignmentClientChildData*>(matchingNode->getLinkedData());
|
||||
}
|
||||
childData = dynamic_cast<AssignmentClientChildData*>(matchingNode->getLinkedData());
|
||||
|
||||
if (childData) {
|
||||
// update our records about how to reach this child
|
||||
|
|
|
@ -915,59 +915,52 @@ void AssetServer::handleAssetUpload(QSharedPointer<ReceivedMessage> message, Sha
|
|||
void AssetServer::sendStatsPacket() {
|
||||
QJsonObject serverStats;
|
||||
|
||||
auto stats = DependencyManager::get<NodeList>()->sampleStatsForAllConnections();
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->eachNode([&](auto& node) {
|
||||
auto& stats = node->getConnectionStats();
|
||||
|
||||
for (const auto& stat : stats) {
|
||||
QJsonObject nodeStats;
|
||||
auto endTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(stat.second.endTime);
|
||||
auto endTimeMs = std::chrono::duration_cast<std::chrono::milliseconds>(stats.endTime);
|
||||
QDateTime date = QDateTime::fromMSecsSinceEpoch(endTimeMs.count());
|
||||
|
||||
static const float USEC_PER_SEC = 1000000.0f;
|
||||
static const float MEGABITS_PER_BYTE = 8.0f / 1000000.0f; // Bytes => Mbits
|
||||
float elapsed = (float)(stat.second.endTime - stat.second.startTime).count() / USEC_PER_SEC; // sec
|
||||
float elapsed = (float)(stats.endTime - stats.startTime).count() / USEC_PER_SEC; // sec
|
||||
float megabitsPerSecPerByte = MEGABITS_PER_BYTE / elapsed; // Bytes => Mb/s
|
||||
|
||||
QJsonObject connectionStats;
|
||||
connectionStats["1. Last Heard"] = date.toString();
|
||||
connectionStats["2. Est. Max (P/s)"] = stat.second.estimatedBandwith;
|
||||
connectionStats["3. RTT (ms)"] = stat.second.rtt;
|
||||
connectionStats["4. CW (P)"] = stat.second.congestionWindowSize;
|
||||
connectionStats["5. Period (us)"] = stat.second.packetSendPeriod;
|
||||
connectionStats["6. Up (Mb/s)"] = stat.second.sentBytes * megabitsPerSecPerByte;
|
||||
connectionStats["7. Down (Mb/s)"] = stat.second.receivedBytes * megabitsPerSecPerByte;
|
||||
connectionStats["2. Est. Max (P/s)"] = stats.estimatedBandwith;
|
||||
connectionStats["3. RTT (ms)"] = stats.rtt;
|
||||
connectionStats["4. CW (P)"] = stats.congestionWindowSize;
|
||||
connectionStats["5. Period (us)"] = stats.packetSendPeriod;
|
||||
connectionStats["6. Up (Mb/s)"] = stats.sentBytes * megabitsPerSecPerByte;
|
||||
connectionStats["7. Down (Mb/s)"] = stats.receivedBytes * megabitsPerSecPerByte;
|
||||
nodeStats["Connection Stats"] = connectionStats;
|
||||
|
||||
using Events = udt::ConnectionStats::Stats::Event;
|
||||
const auto& events = stat.second.events;
|
||||
const auto& events = stats.events;
|
||||
|
||||
QJsonObject upstreamStats;
|
||||
upstreamStats["1. Sent (P/s)"] = stat.second.sendRate;
|
||||
upstreamStats["2. Sent Packets"] = stat.second.sentPackets;
|
||||
upstreamStats["1. Sent (P/s)"] = stats.sendRate;
|
||||
upstreamStats["2. Sent Packets"] = (int)stats.sentPackets;
|
||||
upstreamStats["3. Recvd ACK"] = events[Events::ReceivedACK];
|
||||
upstreamStats["4. Procd ACK"] = events[Events::ProcessedACK];
|
||||
upstreamStats["5. Retransmitted"] = events[Events::Retransmission];
|
||||
upstreamStats["5. Retransmitted"] = (int)stats.retransmittedPackets;
|
||||
nodeStats["Upstream Stats"] = upstreamStats;
|
||||
|
||||
QJsonObject downstreamStats;
|
||||
downstreamStats["1. Recvd (P/s)"] = stat.second.receiveRate;
|
||||
downstreamStats["2. Recvd Packets"] = stat.second.receivedPackets;
|
||||
downstreamStats["1. Recvd (P/s)"] = stats.receiveRate;
|
||||
downstreamStats["2. Recvd Packets"] = (int)stats.receivedPackets;
|
||||
downstreamStats["3. Sent ACK"] = events[Events::SentACK];
|
||||
downstreamStats["4. Duplicates"] = events[Events::Duplicate];
|
||||
downstreamStats["4. Duplicates"] = (int)stats.duplicatePackets;
|
||||
nodeStats["Downstream Stats"] = downstreamStats;
|
||||
|
||||
QString uuid;
|
||||
auto nodelist = DependencyManager::get<NodeList>();
|
||||
if (stat.first == nodelist->getDomainHandler().getSockAddr()) {
|
||||
uuid = uuidStringWithoutCurlyBraces(nodelist->getDomainHandler().getUUID());
|
||||
nodeStats[USERNAME_UUID_REPLACEMENT_STATS_KEY] = "DomainServer";
|
||||
} else {
|
||||
auto node = nodelist->findNodeWithAddr(stat.first);
|
||||
uuid = uuidStringWithoutCurlyBraces(node ? node->getUUID() : QUuid());
|
||||
nodeStats[USERNAME_UUID_REPLACEMENT_STATS_KEY] = uuid;
|
||||
}
|
||||
QString uuid = uuidStringWithoutCurlyBraces(node->getUUID());
|
||||
nodeStats[USERNAME_UUID_REPLACEMENT_STATS_KEY] = uuid;
|
||||
|
||||
serverStats[uuid] = nodeStats;
|
||||
}
|
||||
});
|
||||
|
||||
// send off the stats packets
|
||||
ThreadedAssignment::addPacketStatsAndSendStatsPacket(serverStats);
|
||||
|
|
|
@ -338,7 +338,7 @@ void AudioMixer::sendStatsPacket() {
|
|||
QJsonObject nodeStats;
|
||||
QString uuidString = uuidStringWithoutCurlyBraces(node->getUUID());
|
||||
|
||||
nodeStats["outbound_kbps"] = node->getOutboundBandwidth();
|
||||
nodeStats["outbound_kbps"] = node->getOutboundKbps();
|
||||
nodeStats[USERNAME_UUID_REPLACEMENT_STATS_KEY] = uuidString;
|
||||
|
||||
nodeStats["jitter"] = clientData->getAudioStreamStats();
|
||||
|
|
|
@ -839,8 +839,8 @@ void AvatarMixer::sendStatsPacket() {
|
|||
// add the key to ask the domain-server for a username replacement, if it has it
|
||||
avatarStats[USERNAME_UUID_REPLACEMENT_STATS_KEY] = uuidStringWithoutCurlyBraces(node->getUUID());
|
||||
|
||||
avatarStats[NODE_OUTBOUND_KBPS_STAT_KEY] = node->getOutboundBandwidth();
|
||||
avatarStats[NODE_INBOUND_KBPS_STAT_KEY] = node->getInboundBandwidth();
|
||||
avatarStats[NODE_OUTBOUND_KBPS_STAT_KEY] = node->getOutboundKbps();
|
||||
avatarStats[NODE_INBOUND_KBPS_STAT_KEY] = node->getInboundKbps();
|
||||
|
||||
AvatarMixerClientData* clientData = static_cast<AvatarMixerClientData*>(node->getLinkedData());
|
||||
if (clientData) {
|
||||
|
|
|
@ -146,7 +146,8 @@ void AvatarMixerClientData::processSetTraitsMessage(ReceivedMessage& message,
|
|||
break;
|
||||
}
|
||||
|
||||
if (traitType == AvatarTraits::AvatarEntity) {
|
||||
if (traitType == AvatarTraits::AvatarEntity ||
|
||||
traitType == AvatarTraits::Grab) {
|
||||
auto& instanceVersionRef = _lastReceivedTraitVersions.getInstanceValueRef(traitType, instanceID);
|
||||
|
||||
if (packetTraitVersion > instanceVersionRef) {
|
||||
|
|
|
@ -75,8 +75,8 @@ void MessagesMixer::sendStatsPacket() {
|
|||
DependencyManager::get<NodeList>()->eachNode([&](const SharedNodePointer& node) {
|
||||
QJsonObject clientStats;
|
||||
clientStats[USERNAME_UUID_REPLACEMENT_STATS_KEY] = uuidStringWithoutCurlyBraces(node->getUUID());
|
||||
clientStats["outbound_kbps"] = node->getOutboundBandwidth();
|
||||
clientStats["inbound_kbps"] = node->getInboundBandwidth();
|
||||
clientStats["outbound_kbps"] = node->getOutboundKbps();
|
||||
clientStats["inbound_kbps"] = node->getInboundKbps();
|
||||
messagesMixerObject[uuidStringWithoutCurlyBraces(node->getUUID())] = clientStats;
|
||||
});
|
||||
|
||||
|
|
|
@ -192,13 +192,13 @@ Item {
|
|||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio In Audio: " + root.audioAudioInboundPPS + " pps, " +
|
||||
"Silent: " + root.audioSilentInboundPPS + " pps";
|
||||
text: "Audio Mixer Out: " + root.audioMixerOutKbps + " kbps, " +
|
||||
root.audioMixerOutPps + "pps";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio Mixer Out: " + root.audioMixerOutKbps + " kbps, " +
|
||||
root.audioMixerOutPps + "pps";
|
||||
text: "Audio In Audio: " + root.audioAudioInboundPPS + " pps, " +
|
||||
"Silent: " + root.audioSilentInboundPPS + " pps";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
|
|
|
@ -210,13 +210,13 @@ Item {
|
|||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio In Audio: " + root.audioAudioInboundPPS + " pps, " +
|
||||
"Silent: " + root.audioSilentInboundPPS + " pps";
|
||||
text: "Audio Mixer Out: " + root.audioMixerOutKbps + " kbps, " +
|
||||
root.audioMixerOutPps + "pps";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio Mixer Out: " + root.audioMixerOutKbps + " kbps, " +
|
||||
root.audioMixerOutPps + "pps";
|
||||
text: "Audio In Audio: " + root.audioAudioInboundPPS + " pps, " +
|
||||
"Silent: " + root.audioSilentInboundPPS + " pps";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
|
|
|
@ -869,7 +869,7 @@ Flickable {
|
|||
id: outOfRangeDataStrategyComboBox
|
||||
|
||||
height: 25
|
||||
width: 100
|
||||
width: 150
|
||||
|
||||
editable: true
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
|
|
|
@ -208,6 +208,8 @@
|
|||
#include "InterfaceParentFinder.h"
|
||||
#include "ui/OctreeStatsProvider.h"
|
||||
|
||||
#include "avatar/GrabManager.h"
|
||||
|
||||
#include <GPUIdent.h>
|
||||
#include <gl/GLHelpers.h>
|
||||
#include <src/scripting/GooglePolyScriptingInterface.h>
|
||||
|
@ -859,7 +861,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<LODManager>();
|
||||
DependencyManager::set<StandAloneJSConsole>();
|
||||
DependencyManager::set<DialogsManager>();
|
||||
DependencyManager::set<BandwidthRecorder>();
|
||||
DependencyManager::set<ResourceCacheSharedItems>();
|
||||
DependencyManager::set<DesktopScriptingInterface>();
|
||||
DependencyManager::set<EntityScriptingInterface>(true);
|
||||
|
@ -919,6 +920,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) {
|
|||
DependencyManager::set<ResourceRequestObserver>();
|
||||
DependencyManager::set<Keyboard>();
|
||||
DependencyManager::set<KeyboardScriptingInterface>();
|
||||
DependencyManager::set<GrabManager>();
|
||||
|
||||
return previousSessionCrashed;
|
||||
}
|
||||
|
@ -1078,6 +1080,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->startThread();
|
||||
nodeList->setFlagTimeForConnectionStep(true);
|
||||
|
||||
// move the AddressManager to the NodeList thread so that domain resets due to domain changes always occur
|
||||
// before we tell MyAvatar to go to a new location in the new domain
|
||||
|
@ -1573,13 +1576,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
|
||||
connect(this, SIGNAL(aboutToQuit()), this, SLOT(onAboutToQuit()));
|
||||
|
||||
// hook up bandwidth estimator
|
||||
QSharedPointer<BandwidthRecorder> bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
||||
connect(nodeList.data(), &LimitedNodeList::dataSent,
|
||||
bandwidthRecorder.data(), &BandwidthRecorder::updateOutboundData);
|
||||
connect(nodeList.data(), &LimitedNodeList::dataReceived,
|
||||
bandwidthRecorder.data(), &BandwidthRecorder::updateInboundData);
|
||||
|
||||
// FIXME -- I'm a little concerned about this.
|
||||
connect(myAvatar->getSkeletonModel().get(), &SkeletonModel::skeletonLoaded,
|
||||
this, &Application::checkSkeleton, Qt::QueuedConnection);
|
||||
|
@ -2045,15 +2041,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
properties["deadlock_watchdog_maxElapsed"] = (int)DeadlockWatchdogThread::_maxElapsed;
|
||||
properties["deadlock_watchdog_maxElapsedAverage"] = (int)DeadlockWatchdogThread::_maxElapsedAverage;
|
||||
|
||||
auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
||||
properties["packet_rate_in"] = bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond();
|
||||
properties["packet_rate_out"] = bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond();
|
||||
properties["kbps_in"] = bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond();
|
||||
properties["kbps_out"] = bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond();
|
||||
|
||||
properties["atp_in_kbps"] = bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer);
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
properties["packet_rate_in"] = nodeList->getInboundPPS();
|
||||
properties["packet_rate_out"] = nodeList->getOutboundPPS();
|
||||
properties["kbps_in"] = nodeList->getInboundKbps();
|
||||
properties["kbps_out"] = nodeList->getOutboundKbps();
|
||||
|
||||
SharedNodePointer entityServerNode = nodeList->soloNodeOfType(NodeType::EntityServer);
|
||||
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||
SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
||||
|
@ -2064,6 +2057,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
properties["avatar_ping"] = avatarMixerNode ? avatarMixerNode->getPingMs() : -1;
|
||||
properties["asset_ping"] = assetServerNode ? assetServerNode->getPingMs() : -1;
|
||||
properties["messages_ping"] = messagesMixerNode ? messagesMixerNode->getPingMs() : -1;
|
||||
properties["atp_in_kbps"] = messagesMixerNode ? assetServerNode->getInboundKbps() : 0.0f;
|
||||
|
||||
auto loadingRequests = ResourceCache::getLoadingRequests();
|
||||
|
||||
|
@ -6084,6 +6078,9 @@ void Application::update(float deltaTime) {
|
|||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||
updateDialogs(deltaTime); // update various stats dialogs if present
|
||||
|
||||
auto grabManager = DependencyManager::get<GrabManager>();
|
||||
grabManager->simulateGrabs();
|
||||
|
||||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||
|
||||
{
|
||||
|
|
|
@ -58,6 +58,16 @@ AvatarActionHold::~AvatarActionHold() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void AvatarActionHold::removeFromOwner() {
|
||||
auto avatarManager = DependencyManager::get<AvatarManager>();
|
||||
if (avatarManager) {
|
||||
auto myAvatar = avatarManager->getMyAvatar();
|
||||
if (myAvatar) {
|
||||
myAvatar->removeHoldAction(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool AvatarActionHold::getAvatarRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation) {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
MyCharacterController* controller = myAvatar ? myAvatar->getCharacterController() : nullptr;
|
||||
|
@ -143,7 +153,7 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::
|
|||
ownerEntity->setTransitingWithAvatar(_isTransitingWithAvatar);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (holdingAvatar->isMyAvatar()) {
|
||||
std::shared_ptr<MyAvatar> myAvatar = avatarManager->getMyAvatar();
|
||||
|
||||
|
@ -226,7 +236,7 @@ bool AvatarActionHold::getTarget(float deltaTimeStep, glm::quat& rotation, glm::
|
|||
}
|
||||
|
||||
rotation = palmRotation * _relativeRotation;
|
||||
position = palmPosition + rotation * _relativePosition;
|
||||
position = palmPosition + palmRotation * _relativePosition;
|
||||
|
||||
// update linearVelocity based on offset via _relativePosition;
|
||||
linearVelocity = linearVelocity + glm::cross(angularVelocity, position - palmPosition);
|
||||
|
@ -369,8 +379,12 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
|||
hand = _hand;
|
||||
}
|
||||
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
holderID = myAvatar->getSessionUUID();
|
||||
ok = true;
|
||||
holderID = EntityDynamicInterface::extractStringArgument("hold", arguments, "holderID", ok, false);
|
||||
if (!ok) {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
holderID = myAvatar->getSessionUUID();
|
||||
}
|
||||
|
||||
ok = true;
|
||||
kinematic = EntityDynamicInterface::extractBooleanArgument("hold", arguments, "kinematic", ok, false);
|
||||
|
@ -417,13 +431,13 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
|||
_kinematicSetVelocity = kinematicSetVelocity;
|
||||
_ignoreIK = ignoreIK;
|
||||
_active = true;
|
||||
|
||||
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setDynamicDataDirty(true);
|
||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
||||
ownerEntity->setDynamicDataNeedsTransmit(true);
|
||||
ownerEntity->setTransitingWithAvatar(myAvatar->getTransit()->isActive());
|
||||
}
|
||||
});
|
||||
|
|
|
@ -26,6 +26,8 @@ public:
|
|||
AvatarActionHold(const QUuid& id, EntityItemPointer ownerEntity);
|
||||
virtual ~AvatarActionHold();
|
||||
|
||||
virtual void removeFromOwner() override;
|
||||
|
||||
virtual bool updateArguments(QVariantMap arguments) override;
|
||||
virtual QVariantMap getArguments() override;
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
|
||||
#include <shared/QtHelpers.h>
|
||||
#include <AvatarData.h>
|
||||
#include <PerfStat.h>
|
||||
|
@ -529,6 +528,7 @@ void AvatarManager::handleChangedMotionStates(const VectorOfMotionStates& motion
|
|||
}
|
||||
|
||||
void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents) {
|
||||
bool playedCollisionSound { false };
|
||||
for (Collision collision : collisionEvents) {
|
||||
// TODO: The plan is to handle MOTIONSTATE_TYPE_AVATAR, and then MOTIONSTATE_TYPE_MYAVATAR. As it is, other
|
||||
// people's avatars will have an id that doesn't match any entities, and one's own avatar will have
|
||||
|
@ -536,43 +536,47 @@ void AvatarManager::handleCollisionEvents(const CollisionEvents& collisionEvents
|
|||
// my avatar. (Other user machines will make a similar analysis and inject sound for their collisions.)
|
||||
if (collision.idA.isNull() || collision.idB.isNull()) {
|
||||
auto myAvatar = getMyAvatar();
|
||||
auto collisionSound = myAvatar->getCollisionSound();
|
||||
if (collisionSound) {
|
||||
const auto characterController = myAvatar->getCharacterController();
|
||||
const float avatarVelocityChange = (characterController ? glm::length(characterController->getVelocityChange()) : 0.0f);
|
||||
const float velocityChange = glm::length(collision.velocityChange) + avatarVelocityChange;
|
||||
const float MIN_AVATAR_COLLISION_ACCELERATION = 2.4f; // walking speed
|
||||
const bool isSound = (collision.type == CONTACT_EVENT_TYPE_START) && (velocityChange > MIN_AVATAR_COLLISION_ACCELERATION);
|
||||
myAvatar->collisionWithEntity(collision);
|
||||
|
||||
if (!isSound) {
|
||||
return; // No sense iterating for others. We only have one avatar.
|
||||
if (!playedCollisionSound) {
|
||||
playedCollisionSound = true;
|
||||
auto collisionSound = myAvatar->getCollisionSound();
|
||||
if (collisionSound) {
|
||||
const auto characterController = myAvatar->getCharacterController();
|
||||
const float avatarVelocityChange =
|
||||
(characterController ? glm::length(characterController->getVelocityChange()) : 0.0f);
|
||||
const float velocityChange = glm::length(collision.velocityChange) + avatarVelocityChange;
|
||||
const float MIN_AVATAR_COLLISION_ACCELERATION = 2.4f; // walking speed
|
||||
const bool isSound =
|
||||
(collision.type == CONTACT_EVENT_TYPE_START) && (velocityChange > MIN_AVATAR_COLLISION_ACCELERATION);
|
||||
|
||||
if (!isSound) {
|
||||
return; // No sense iterating for others. We only have one avatar.
|
||||
}
|
||||
// Your avatar sound is personal to you, so let's say the "mass" part of the kinetic energy is already accounted for.
|
||||
const float energy = velocityChange * velocityChange;
|
||||
const float COLLISION_ENERGY_AT_FULL_VOLUME = 10.0f;
|
||||
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
|
||||
|
||||
// For general entity collisionSoundURL, playSound supports changing the pitch for the sound based on the size of the object,
|
||||
// but most avatars are roughly the same size, so let's not be so fancy yet.
|
||||
const float AVATAR_STRETCH_FACTOR = 1.0f;
|
||||
|
||||
_collisionInjectors.remove_if(
|
||||
[](const AudioInjectorPointer& injector) { return !injector || injector->isFinished(); });
|
||||
|
||||
static const int MAX_INJECTOR_COUNT = 3;
|
||||
if (_collisionInjectors.size() < MAX_INJECTOR_COUNT) {
|
||||
AudioInjectorOptions options;
|
||||
options.stereo = collisionSound->isStereo();
|
||||
options.position = myAvatar->getWorldPosition();
|
||||
options.volume = energyFactorOfFull;
|
||||
options.pitch = 1.0f / AVATAR_STRETCH_FACTOR;
|
||||
|
||||
auto injector = AudioInjector::playSoundAndDelete(collisionSound, options);
|
||||
_collisionInjectors.emplace_back(injector);
|
||||
}
|
||||
}
|
||||
// Your avatar sound is personal to you, so let's say the "mass" part of the kinetic energy is already accounted for.
|
||||
const float energy = velocityChange * velocityChange;
|
||||
const float COLLISION_ENERGY_AT_FULL_VOLUME = 10.0f;
|
||||
const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME);
|
||||
|
||||
// For general entity collisionSoundURL, playSound supports changing the pitch for the sound based on the size of the object,
|
||||
// but most avatars are roughly the same size, so let's not be so fancy yet.
|
||||
const float AVATAR_STRETCH_FACTOR = 1.0f;
|
||||
|
||||
_collisionInjectors.remove_if([](const AudioInjectorPointer& injector) {
|
||||
return !injector || injector->isFinished();
|
||||
});
|
||||
|
||||
static const int MAX_INJECTOR_COUNT = 3;
|
||||
if (_collisionInjectors.size() < MAX_INJECTOR_COUNT) {
|
||||
AudioInjectorOptions options;
|
||||
options.stereo = collisionSound->isStereo();
|
||||
options.position = myAvatar->getWorldPosition();
|
||||
options.volume = energyFactorOfFull;
|
||||
options.pitch = 1.0f / AVATAR_STRETCH_FACTOR;
|
||||
|
||||
auto injector = AudioInjector::playSoundAndDelete(collisionSound, options);
|
||||
_collisionInjectors.emplace_back(injector);
|
||||
}
|
||||
myAvatar->collisionWithEntity(collision);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -887,3 +891,13 @@ QVariantMap AvatarManager::getPalData(const QStringList& specificAvatarIdentifie
|
|||
doc.insert("data", palData);
|
||||
return doc.toVariantMap();
|
||||
}
|
||||
|
||||
void AvatarManager::accumulateGrabPositions(std::map<QUuid, GrabLocationAccumulator>& grabAccumulators) {
|
||||
auto avatarMap = getHashCopy();
|
||||
AvatarHash::iterator itr = avatarMap.begin();
|
||||
while (itr != avatarMap.end()) {
|
||||
const auto& avatar = std::static_pointer_cast<Avatar>(*itr);
|
||||
avatar->accumulateGrabPositions(grabAccumulators);
|
||||
itr++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,6 +198,8 @@ public:
|
|||
void handleProcessedPhysicsTransaction(PhysicsEngine::Transaction& transaction);
|
||||
void removeDeadAvatarEntities(const SetOfEntities& deadEntities);
|
||||
|
||||
void accumulateGrabPositions(std::map<QUuid, GrabLocationAccumulator>& grabAccumulators);
|
||||
|
||||
public slots:
|
||||
/**jsdoc
|
||||
* @function AvatarManager.updateAvatarRenderStatus
|
||||
|
@ -215,7 +217,7 @@ private:
|
|||
void simulateAvatarFades(float deltaTime);
|
||||
|
||||
AvatarSharedPointer newSharedAvatar() override;
|
||||
|
||||
|
||||
// called only from the AvatarHashMap thread - cannot be called while this thread holds the
|
||||
// hash lock, since handleRemovedAvatar needs a write lock on the entity tree and the entity tree
|
||||
// frequently grabs a read lock on the hash to get a given avatar by ID
|
||||
|
|
39
interface/src/avatar/GrabManager.cpp
Normal file
39
interface/src/avatar/GrabManager.cpp
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// GrabManager.cpp
|
||||
// interface/src/avatar/
|
||||
//
|
||||
// Created by Seth Alves on 2018-12-4.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
|
||||
#include "GrabManager.h"
|
||||
|
||||
void GrabManager::simulateGrabs() {
|
||||
QSharedPointer<AvatarManager> avatarManager = DependencyManager::get<AvatarManager>();
|
||||
|
||||
// Update grabbed objects
|
||||
auto entityTreeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
auto entityTree = entityTreeRenderer->getTree();
|
||||
entityTree->withReadLock([&] {
|
||||
PROFILE_RANGE(simulation, "Grabs");
|
||||
|
||||
std::map<QUuid, GrabLocationAccumulator> grabAccumulators;
|
||||
avatarManager->accumulateGrabPositions(grabAccumulators);
|
||||
|
||||
for (auto& accumulatedLocation : grabAccumulators) {
|
||||
QUuid grabbedThingID = accumulatedLocation.first;
|
||||
GrabLocationAccumulator& acc = accumulatedLocation.second;
|
||||
bool success;
|
||||
SpatiallyNestablePointer grabbedThing = SpatiallyNestable::findByID(grabbedThingID, success);
|
||||
if (success && grabbedThing) {
|
||||
glm::vec3 finalPosition = acc.finalizePosition();
|
||||
glm::quat finalOrientation = acc.finalizeOrientation();
|
||||
grabbedThing->setTransform(createMatFromQuatAndPos(finalOrientation, finalPosition));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
23
interface/src/avatar/GrabManager.h
Normal file
23
interface/src/avatar/GrabManager.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// GrabManager.h
|
||||
// interface/src/avatar/
|
||||
//
|
||||
// Created by Seth Alves on 2018-12-4.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <AvatarData.h>
|
||||
#include <EntityTreeRenderer.h>
|
||||
#include "AvatarManager.h"
|
||||
|
||||
class GrabManager : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
void simulateGrabs();
|
||||
|
||||
};
|
|
@ -746,7 +746,7 @@ void MyAvatar::updateChildCauterization(SpatiallyNestablePointer object, bool ca
|
|||
void MyAvatar::simulate(float deltaTime) {
|
||||
PerformanceTimer perfTimer("simulate");
|
||||
animateScaleChanges(deltaTime);
|
||||
|
||||
|
||||
setFlyingEnabled(getFlyingEnabled());
|
||||
|
||||
if (_cauterizationNeedsUpdate) {
|
||||
|
@ -820,6 +820,7 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
// and all of its joints, now update our attachements.
|
||||
Avatar::simulateAttachments(deltaTime);
|
||||
relayJointDataToChildren();
|
||||
updateGrabs();
|
||||
|
||||
if (!_skeletonModel->hasSkeleton()) {
|
||||
// All the simulation that can be done has been done
|
||||
|
@ -874,47 +875,12 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
zoneAllowsFlying = zone->getFlyingAllowed();
|
||||
collisionlessAllowed = zone->getGhostingAllowed();
|
||||
}
|
||||
auto now = usecTimestampNow();
|
||||
EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
|
||||
MovingEntitiesOperator moveOperator;
|
||||
bool force = false;
|
||||
bool iShouldTellServer = true;
|
||||
forEachDescendant([&](SpatiallyNestablePointer object) {
|
||||
// if the queryBox has changed, tell the entity-server
|
||||
if (object->getNestableType() == NestableType::Entity && object->updateQueryAACube()) {
|
||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(object);
|
||||
bool success;
|
||||
AACube newCube = entity->getQueryAACube(success);
|
||||
if (success) {
|
||||
moveOperator.addEntityToMoveList(entity, newCube);
|
||||
}
|
||||
// send an edit packet to update the entity-server about the queryAABox
|
||||
if (packetSender && entity->isDomainEntity()) {
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
properties.setQueryAACubeDirty();
|
||||
properties.setLastEdited(now);
|
||||
|
||||
packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree,
|
||||
entity->getID(), properties);
|
||||
entity->setLastBroadcast(usecTimestampNow());
|
||||
|
||||
entity->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||
EntityItemPointer entityDescendant = std::dynamic_pointer_cast<EntityItem>(descendant);
|
||||
if (entityDescendant && entityDescendant->isDomainEntity() && descendant->updateQueryAACube()) {
|
||||
EntityItemProperties descendantProperties;
|
||||
descendantProperties.setQueryAACube(descendant->getQueryAACube());
|
||||
descendantProperties.setLastEdited(now);
|
||||
packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree,
|
||||
entityDescendant->getID(), descendantProperties);
|
||||
entityDescendant->setLastBroadcast(now); // for debug/physics status icons
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
entityTree->updateEntityQueryAACube(object, packetSender, force, iShouldTellServer);
|
||||
});
|
||||
// also update the position of children in our local octree
|
||||
if (moveOperator.hasMovingEntities()) {
|
||||
PerformanceTimer perfTimer("recurseTreeWithOperator");
|
||||
entityTree->recurseTreeWithOperator(&moveOperator);
|
||||
}
|
||||
});
|
||||
bool isPhysicsEnabled = qApp->isPhysicsEnabled();
|
||||
_characterController.setFlyingAllowed((zoneAllowsFlying && _enableFlying) || !isPhysicsEnabled);
|
||||
|
@ -1565,35 +1531,74 @@ ScriptAvatarData* MyAvatar::getTargetAvatar() const {
|
|||
}
|
||||
}
|
||||
|
||||
void MyAvatar::updateLookAtTargetAvatar() {
|
||||
//
|
||||
// Look at the avatar whose eyes are closest to the ray in direction of my avatar's head
|
||||
// And set the correctedLookAt for all (nearby) avatars that are looking at me.
|
||||
_lookAtTargetAvatar.reset();
|
||||
_targetAvatarPosition = glm::vec3(0.0f);
|
||||
static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myPosition, const glm::vec3& otherForward, const glm::vec3& otherPosition,
|
||||
bool otherIsTalking, bool lookingAtOtherAlready) {
|
||||
const float DISTANCE_FACTOR = 3.14f;
|
||||
const float MY_ANGLE_FACTOR = 1.0f;
|
||||
const float OTHER_ANGLE_FACTOR = 1.0f;
|
||||
const float OTHER_IS_TALKING_TERM = otherIsTalking ? 1.0f : 0.0f;
|
||||
const float LOOKING_AT_OTHER_ALREADY_TERM = lookingAtOtherAlready ? -0.2f : 0.0f;
|
||||
|
||||
glm::vec3 lookForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD;
|
||||
glm::vec3 cameraPosition = qApp->getCamera().getPosition();
|
||||
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f; // meters
|
||||
const float MAX_MY_ANGLE = PI / 8.0f; // 22.5 degrees, Don't look too far away from the head facing.
|
||||
const float MAX_OTHER_ANGLE = (3.0f * PI) / 4.0f; // 135 degrees, Don't stare at the back of another avatars head.
|
||||
|
||||
float smallestAngleTo = glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES) / 2.0f;
|
||||
const float KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR = 1.3f;
|
||||
const float GREATEST_LOOKING_AT_DISTANCE = 10.0f;
|
||||
glm::vec3 d = otherPosition - myPosition;
|
||||
float distance = glm::length(d);
|
||||
glm::vec3 dUnit = d / distance;
|
||||
float myAngle = acosf(glm::dot(myForward, dUnit));
|
||||
float otherAngle = acosf(glm::dot(otherForward, -dUnit));
|
||||
|
||||
AvatarHash hash = DependencyManager::get<AvatarManager>()->getHashCopy();
|
||||
if (distance > GREATEST_LOOKING_AT_DISTANCE || myAngle > MAX_MY_ANGLE || otherAngle > MAX_OTHER_ANGLE) {
|
||||
return FLT_MAX;
|
||||
} else {
|
||||
return (DISTANCE_FACTOR * distance +
|
||||
MY_ANGLE_FACTOR * myAngle +
|
||||
OTHER_ANGLE_FACTOR * otherAngle +
|
||||
OTHER_IS_TALKING_TERM +
|
||||
LOOKING_AT_OTHER_ALREADY_TERM);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const AvatarSharedPointer& avatarPointer, hash) {
|
||||
auto avatar = static_pointer_cast<Avatar>(avatarPointer);
|
||||
bool isCurrentTarget = avatar->getIsLookAtTarget();
|
||||
float distanceTo = glm::length(avatar->getHead()->getEyePosition() - cameraPosition);
|
||||
avatar->setIsLookAtTarget(false);
|
||||
if (!avatar->isMyAvatar() && avatar->isInitialized() &&
|
||||
(distanceTo < GREATEST_LOOKING_AT_DISTANCE * getModelScale())) {
|
||||
float radius = glm::length(avatar->getHead()->getEyePosition() - avatar->getHead()->getRightEyePosition());
|
||||
float angleTo = coneSphereAngle(getHead()->getEyePosition(), lookForward, avatar->getHead()->getEyePosition(), radius);
|
||||
if (angleTo < (smallestAngleTo * (isCurrentTarget ? KEEP_LOOKING_AT_CURRENT_ANGLE_FACTOR : 1.0f))) {
|
||||
_lookAtTargetAvatar = avatarPointer;
|
||||
_targetAvatarPosition = avatarPointer->getWorldPosition();
|
||||
void MyAvatar::computeMyLookAtTarget(const AvatarHash& hash) {
|
||||
glm::vec3 myForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FORWARD;
|
||||
glm::vec3 myPosition = getHead()->getEyePosition();
|
||||
CameraMode mode = qApp->getCamera().getMode();
|
||||
if (mode == CAMERA_MODE_FIRST_PERSON) {
|
||||
myPosition = qApp->getCamera().getPosition();
|
||||
}
|
||||
|
||||
float bestCost = FLT_MAX;
|
||||
std::shared_ptr<Avatar> bestAvatar;
|
||||
|
||||
foreach (const AvatarSharedPointer& avatarData, hash) {
|
||||
std::shared_ptr<Avatar> avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||
if (!avatar->isMyAvatar() && avatar->isInitialized()) {
|
||||
glm::vec3 otherForward = avatar->getHead()->getForwardDirection();
|
||||
glm::vec3 otherPosition = avatar->getHead()->getEyePosition();
|
||||
const float TIME_WITHOUT_TALKING_THRESHOLD = 1.0f;
|
||||
bool otherIsTalking = avatar->getHead()->getTimeWithoutTalking() <= TIME_WITHOUT_TALKING_THRESHOLD;
|
||||
bool lookingAtOtherAlready = _lookAtTargetAvatar.lock().get() == avatar.get();
|
||||
float cost = lookAtCostFunction(myForward, myPosition, otherForward, otherPosition, otherIsTalking, lookingAtOtherAlready);
|
||||
if (cost < bestCost) {
|
||||
bestCost = cost;
|
||||
bestAvatar = avatar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestAvatar) {
|
||||
_lookAtTargetAvatar = bestAvatar;
|
||||
_targetAvatarPosition = bestAvatar->getWorldPosition();
|
||||
} else {
|
||||
_lookAtTargetAvatar.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::snapOtherAvatarLookAtTargetsToMe(const AvatarHash& hash) {
|
||||
foreach (const AvatarSharedPointer& avatarData, hash) {
|
||||
std::shared_ptr<Avatar> avatar = std::static_pointer_cast<Avatar>(avatarData);
|
||||
if (!avatar->isMyAvatar() && avatar->isInitialized()) {
|
||||
if (_lookAtSnappingEnabled && avatar->getLookAtSnappingEnabled() && isLookingAtMe(avatar)) {
|
||||
|
||||
// Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face.
|
||||
|
@ -1648,10 +1653,19 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
|||
avatar->getHead()->clearCorrectedLookAtPosition();
|
||||
}
|
||||
}
|
||||
auto avatarPointer = _lookAtTargetAvatar.lock();
|
||||
if (avatarPointer) {
|
||||
static_pointer_cast<Avatar>(avatarPointer)->setIsLookAtTarget(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::updateLookAtTargetAvatar() {
|
||||
|
||||
// The AvatarManager is a mutable class shared by many threads. We make a thread-safe deep copy of it,
|
||||
// to avoid having to hold a lock while we iterate over all the avatars within.
|
||||
AvatarHash hash = DependencyManager::get<AvatarManager>()->getHashCopy();
|
||||
|
||||
// determine what the best look at target for my avatar should be.
|
||||
computeMyLookAtTarget(hash);
|
||||
|
||||
// snap look at position for avatars that are looking at me.
|
||||
snapOtherAvatarLookAtTargetsToMe(hash);
|
||||
}
|
||||
|
||||
void MyAvatar::clearLookAtTargetAvatar() {
|
||||
|
@ -4746,3 +4760,50 @@ SpatialParentTree* MyAvatar::getParentTree() const {
|
|||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||
return entityTree.get();
|
||||
}
|
||||
|
||||
const QUuid MyAvatar::grab(const QUuid& targetID, int parentJointIndex,
|
||||
glm::vec3 positionalOffset, glm::quat rotationalOffset) {
|
||||
auto grabID = QUuid::createUuid();
|
||||
// create a temporary grab object to get grabData
|
||||
|
||||
QString hand = "none";
|
||||
if (parentJointIndex == CONTROLLER_RIGHTHAND_INDEX ||
|
||||
parentJointIndex == CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX ||
|
||||
parentJointIndex == FARGRAB_RIGHTHAND_INDEX ||
|
||||
parentJointIndex == getJointIndex("RightHand")) {
|
||||
hand = "right";
|
||||
} else if (parentJointIndex == CONTROLLER_LEFTHAND_INDEX ||
|
||||
parentJointIndex == CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX ||
|
||||
parentJointIndex == FARGRAB_LEFTHAND_INDEX ||
|
||||
parentJointIndex == getJointIndex("LeftHand")) {
|
||||
hand = "left";
|
||||
}
|
||||
|
||||
Grab tmpGrab(DependencyManager::get<NodeList>()->getSessionUUID(),
|
||||
targetID, parentJointIndex, hand, positionalOffset, rotationalOffset);
|
||||
QByteArray grabData = tmpGrab.toByteArray();
|
||||
bool dataChanged = updateAvatarGrabData(grabID, grabData);
|
||||
|
||||
if (dataChanged && _clientTraitsHandler) {
|
||||
// indicate that the changed data should be sent to the mixer
|
||||
_clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::Grab, grabID);
|
||||
}
|
||||
|
||||
return grabID;
|
||||
}
|
||||
|
||||
void MyAvatar::releaseGrab(const QUuid& grabID) {
|
||||
bool tellHandler { false };
|
||||
|
||||
_avatarGrabsLock.withWriteLock([&] {
|
||||
if (_avatarGrabData.remove(grabID)) {
|
||||
_deletedAvatarGrabs.insert(grabID);
|
||||
tellHandler = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (tellHandler && _clientTraitsHandler) {
|
||||
// indicate the deletion of the data to the mixer
|
||||
_clientTraitsHandler->markInstancedTraitDeleted(AvatarTraits::Grab, grabID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -832,6 +832,8 @@ public:
|
|||
|
||||
AvatarWeakPointer getLookAtTargetAvatar() const { return _lookAtTargetAvatar; }
|
||||
void updateLookAtTargetAvatar();
|
||||
void computeMyLookAtTarget(const AvatarHash& hash);
|
||||
void snapOtherAvatarLookAtTargetsToMe(const AvatarHash& hash);
|
||||
void clearLookAtTargetAvatar();
|
||||
|
||||
virtual void setJointRotations(const QVector<glm::quat>& jointRotations) override;
|
||||
|
@ -1170,6 +1172,25 @@ public:
|
|||
|
||||
glm::vec3 getNextPosition() { return _goToPending ? _goToPosition : getWorldPosition(); }
|
||||
|
||||
/**jsdoc
|
||||
* Create a new grab.
|
||||
* @function MyAvatar.grab
|
||||
* @param {Uuid} targetID - id of grabbed thing
|
||||
* @param {number} parentJointIndex - avatar joint being used to grab
|
||||
* @param {Vec3} offset - target's positional offset from joint
|
||||
* @param {Quat} rotationalOffset - target's rotational offset from joint
|
||||
* @returns {Uuid} id of the new grab
|
||||
*/
|
||||
Q_INVOKABLE const QUuid grab(const QUuid& targetID, int parentJointIndex,
|
||||
glm::vec3 positionalOffset, glm::quat rotationalOffset);
|
||||
|
||||
/**jsdoc
|
||||
* Release (delete) a grab.
|
||||
* @function MyAvatar.releaseGrab
|
||||
* @param {Uuid} grabID - id of grabbed thing
|
||||
*/
|
||||
Q_INVOKABLE void releaseGrab(const QUuid& grabID);
|
||||
|
||||
public slots:
|
||||
|
||||
/**jsdoc
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
|
||||
#include <gl/Context.h>
|
||||
|
||||
#include "BandwidthRecorder.h"
|
||||
#include "Menu.h"
|
||||
#include "Util.h"
|
||||
#include "SequenceNumberStats.h"
|
||||
|
@ -166,20 +165,25 @@ void Stats::updateStats(bool force) {
|
|||
STAT_UPDATE(collisionPicksUpdated, updatedPicks[PickQuery::Collision]);
|
||||
}
|
||||
|
||||
auto bandwidthRecorder = DependencyManager::get<BandwidthRecorder>();
|
||||
STAT_UPDATE(packetInCount, (int)bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond());
|
||||
STAT_UPDATE(packetOutCount, (int)bandwidthRecorder->getCachedTotalAverageOutputPacketsPerSecond());
|
||||
STAT_UPDATE_FLOAT(mbpsIn, (float)bandwidthRecorder->getCachedTotalAverageInputKilobitsPerSecond() / 1000.0f, 0.01f);
|
||||
STAT_UPDATE_FLOAT(mbpsOut, (float)bandwidthRecorder->getCachedTotalAverageOutputKilobitsPerSecond() / 1000.0f, 0.01f);
|
||||
STAT_UPDATE(packetInCount, nodeList->getInboundPPS());
|
||||
STAT_UPDATE(packetOutCount, nodeList->getOutboundPPS());
|
||||
STAT_UPDATE_FLOAT(mbpsIn, nodeList->getInboundKbps() / 1000.0f, 0.01f);
|
||||
STAT_UPDATE_FLOAT(mbpsOut, nodeList->getOutboundKbps() / 1000.0f, 0.01f);
|
||||
|
||||
STAT_UPDATE_FLOAT(assetMbpsIn, (float)bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AssetServer) / 1000.0f, 0.01f);
|
||||
STAT_UPDATE_FLOAT(assetMbpsOut, (float)bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AssetServer) / 1000.0f, 0.01f);
|
||||
|
||||
// Second column: ping
|
||||
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||
SharedNodePointer avatarMixerNode = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
||||
SharedNodePointer assetServerNode = nodeList->soloNodeOfType(NodeType::AssetServer);
|
||||
SharedNodePointer messageMixerNode = nodeList->soloNodeOfType(NodeType::MessagesMixer);
|
||||
|
||||
if (assetServerNode) {
|
||||
STAT_UPDATE_FLOAT(assetMbpsIn, assetServerNode->getInboundKbps() / 1000.0f, 0.01f);
|
||||
STAT_UPDATE_FLOAT(assetMbpsOut, assetServerNode->getOutboundKbps() / 1000.0f, 0.01f);
|
||||
} else {
|
||||
STAT_UPDATE_FLOAT(assetMbpsIn, 0.0f, 0.01f);
|
||||
STAT_UPDATE_FLOAT(assetMbpsOut, 0.0f, 0.01f);
|
||||
}
|
||||
|
||||
// Second column: ping
|
||||
STAT_UPDATE(audioPing, audioMixerNode ? audioMixerNode->getPingMs() : -1);
|
||||
const int mixerLossRate = (int)roundf(_audioStats->data()->getMixerStream()->lossRateWindow() * 100.0f);
|
||||
const int clientLossRate = (int)roundf(_audioStats->data()->getClientStream()->lossRateWindow() * 100.0f);
|
||||
|
@ -198,7 +202,7 @@ void Stats::updateStats(bool force) {
|
|||
// TODO: this should also support entities
|
||||
if (node->getType() == NodeType::EntityServer) {
|
||||
totalPingOctree += node->getPingMs();
|
||||
totalEntityKbps += node->getInboundBandwidth();
|
||||
totalEntityKbps += node->getInboundKbps();
|
||||
octreeServerCount++;
|
||||
if (pingOctreeMax < node->getPingMs()) {
|
||||
pingOctreeMax = node->getPingMs();
|
||||
|
@ -218,10 +222,10 @@ void Stats::updateStats(bool force) {
|
|||
if (_expanded || force) {
|
||||
SharedNodePointer avatarMixer = nodeList->soloNodeOfType(NodeType::AvatarMixer);
|
||||
if (avatarMixer) {
|
||||
STAT_UPDATE(avatarMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AvatarMixer)));
|
||||
STAT_UPDATE(avatarMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer)));
|
||||
STAT_UPDATE(avatarMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer)));
|
||||
STAT_UPDATE(avatarMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer)));
|
||||
STAT_UPDATE(avatarMixerInKbps, (int)roundf(avatarMixer->getInboundKbps()));
|
||||
STAT_UPDATE(avatarMixerInPps, avatarMixer->getInboundPPS());
|
||||
STAT_UPDATE(avatarMixerOutKbps, (int)roundf(avatarMixer->getOutboundKbps()));
|
||||
STAT_UPDATE(avatarMixerOutPps, avatarMixer->getOutboundPPS());
|
||||
} else {
|
||||
STAT_UPDATE(avatarMixerInKbps, -1);
|
||||
STAT_UPDATE(avatarMixerInPps, -1);
|
||||
|
@ -233,17 +237,15 @@ void Stats::updateStats(bool force) {
|
|||
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||
auto audioClient = DependencyManager::get<AudioClient>().data();
|
||||
if (audioMixerNode || force) {
|
||||
STAT_UPDATE(audioMixerKbps, (int)roundf(
|
||||
bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) +
|
||||
bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerPps, (int)roundf(
|
||||
bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) +
|
||||
bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerKbps, (int)roundf(audioMixerNode->getInboundKbps() +
|
||||
audioMixerNode->getOutboundKbps()));
|
||||
STAT_UPDATE(audioMixerPps, audioMixerNode->getInboundPPS() +
|
||||
audioMixerNode->getOutboundPPS());
|
||||
|
||||
STAT_UPDATE(audioMixerInKbps, (int)roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerInPps, (int)roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerOutKbps, (int)roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerOutPps, (int)roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerInKbps, (int)roundf(audioMixerNode->getInboundKbps()));
|
||||
STAT_UPDATE(audioMixerInPps, audioMixerNode->getInboundPPS());
|
||||
STAT_UPDATE(audioMixerOutKbps, (int)roundf(audioMixerNode->getOutboundKbps()));
|
||||
STAT_UPDATE(audioMixerOutPps, audioMixerNode->getOutboundPPS());
|
||||
STAT_UPDATE(audioAudioInboundPPS, (int)audioClient->getAudioInboundPPS());
|
||||
STAT_UPDATE(audioSilentInboundPPS, (int)audioClient->getSilentInboundPPS());
|
||||
STAT_UPDATE(audioOutboundPPS, (int)audioClient->getAudioOutboundPPS());
|
||||
|
|
|
@ -123,7 +123,7 @@ void Text3DOverlay::render(RenderArgs* args) {
|
|||
glm::vec4 textColor = { toGlm(_color), getTextAlpha() };
|
||||
|
||||
// FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase.
|
||||
_textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), true);
|
||||
_textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f));
|
||||
}
|
||||
|
||||
const render::ShapeKey Text3DOverlay::getShapeKey() {
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <shared/Camera.h>
|
||||
#include <SoftAttachmentModel.h>
|
||||
#include <render/TransitionStage.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include "ModelEntityItem.h"
|
||||
#include "RenderableModelEntityItem.h"
|
||||
|
||||
|
@ -295,6 +296,7 @@ void Avatar::setTargetScale(float targetScale) {
|
|||
if (_targetScale != newValue) {
|
||||
_targetScale = newValue;
|
||||
_scaleChanged = usecTimestampNow();
|
||||
_avatarScaleChanged = _scaleChanged;
|
||||
_isAnimatingScale = true;
|
||||
|
||||
emit targetScaleChanged(targetScale);
|
||||
|
@ -481,6 +483,111 @@ void Avatar::removeAvatarEntitiesFromTree() {
|
|||
}
|
||||
}
|
||||
|
||||
void Avatar::updateGrabs() {
|
||||
|
||||
// update the Grabs according to any changes in _avatarGrabData
|
||||
_avatarGrabsLock.withWriteLock([&] {
|
||||
if (_avatarGrabDataChanged) {
|
||||
foreach (auto grabID, _avatarGrabData.keys()) {
|
||||
AvatarGrabMap::iterator grabItr = _avatarGrabs.find(grabID);
|
||||
if (grabItr == _avatarGrabs.end()) {
|
||||
GrabPointer grab = std::make_shared<Grab>();
|
||||
grab->fromByteArray(_avatarGrabData.value(grabID));
|
||||
_avatarGrabs[grabID] = grab;
|
||||
_changedAvatarGrabs.insert(grabID);
|
||||
} else {
|
||||
GrabPointer grab = grabItr.value();
|
||||
bool changed = grab->fromByteArray(_avatarGrabData.value(grabID));
|
||||
if (changed) {
|
||||
_changedAvatarGrabs.insert(grabID);
|
||||
}
|
||||
}
|
||||
}
|
||||
_avatarGrabDataChanged = false;
|
||||
}
|
||||
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
auto entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
EntityEditPacketSender* packetSender = treeRenderer ? treeRenderer->getPacketSender() : nullptr;
|
||||
auto sessionID = DependencyManager::get<NodeList>()->getSessionUUID();
|
||||
|
||||
QMutableSetIterator<QUuid> delItr(_deletedAvatarGrabs);
|
||||
while (delItr.hasNext()) {
|
||||
QUuid grabID = delItr.next();
|
||||
GrabPointer grab = _avatarGrabs[grabID];
|
||||
if (!grab) {
|
||||
delItr.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
bool success;
|
||||
SpatiallyNestablePointer target = SpatiallyNestable::findByID(grab->getTargetID(), success);
|
||||
|
||||
// only clear this entry from the _deletedAvatarGrabs if we found the entity.
|
||||
if (success && target) {
|
||||
bool iShouldTellServer = target->getEditSenderID() == sessionID;
|
||||
|
||||
EntityItemPointer entity = std::dynamic_pointer_cast<EntityItem>(target);
|
||||
if (entity && entity->isAvatarEntity() && (entity->getOwningAvatarID() == sessionID ||
|
||||
entity->getOwningAvatarID() == AVATAR_SELF_ID)) {
|
||||
// this is our own avatar-entity, so we always tell the server about the release
|
||||
iShouldTellServer = true;
|
||||
}
|
||||
|
||||
target->removeGrab(grab);
|
||||
delItr.remove();
|
||||
// in case this is the last grab on an entity, we need to shrink the queryAACube and tell the server
|
||||
// about the final position.
|
||||
if (entityTree) {
|
||||
bool force = true;
|
||||
entityTree->withWriteLock([&] {
|
||||
entityTree->updateEntityQueryAACube(target, packetSender, force, iShouldTellServer);
|
||||
});
|
||||
}
|
||||
}
|
||||
_avatarGrabs.remove(grabID);
|
||||
_changedAvatarGrabs.remove(grabID);
|
||||
}
|
||||
|
||||
QMutableSetIterator<QUuid> changeItr(_changedAvatarGrabs);
|
||||
while (changeItr.hasNext()) {
|
||||
QUuid grabID = changeItr.next();
|
||||
GrabPointer& grab = _avatarGrabs[grabID];
|
||||
|
||||
bool success;
|
||||
SpatiallyNestablePointer target = SpatiallyNestable::findByID(grab->getTargetID(), success);
|
||||
|
||||
if (success && target) {
|
||||
target->addGrab(grab);
|
||||
// only clear this entry from the _changedAvatarGrabs if we found the entity.
|
||||
changeItr.remove();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Avatar::accumulateGrabPositions(std::map<QUuid, GrabLocationAccumulator>& grabAccumulators) {
|
||||
// relay avatar's joint position to grabbed target in a way that allows for averaging
|
||||
_avatarGrabsLock.withReadLock([&] {
|
||||
foreach (auto grabID, _avatarGrabs.keys()) {
|
||||
const GrabPointer& grab = _avatarGrabs.value(grabID);
|
||||
|
||||
if (!grab || !grab->getActionID().isNull()) {
|
||||
continue; // the accumulated value isn't used, in this case.
|
||||
}
|
||||
|
||||
glm::vec3 jointTranslation = getAbsoluteJointTranslationInObjectFrame(grab->getParentJointIndex());
|
||||
glm::quat jointRotation = getAbsoluteJointRotationInObjectFrame(grab->getParentJointIndex());
|
||||
glm::mat4 jointMat = createMatFromQuatAndPos(jointRotation, jointTranslation);
|
||||
glm::mat4 offsetMat = createMatFromQuatAndPos(grab->getRotationalOffset(), grab->getPositionalOffset());
|
||||
glm::mat4 avatarMat = getTransform().getMatrix();
|
||||
glm::mat4 worldTransform = avatarMat * jointMat * offsetMat;
|
||||
GrabLocationAccumulator& grabLocationAccumulator = grabAccumulators[grab->getTargetID()];
|
||||
grabLocationAccumulator.accumulate(extractTranslation(worldTransform), extractRotation(worldTransform));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Avatar::relayJointDataToChildren() {
|
||||
forEachChild([&](SpatiallyNestablePointer child) {
|
||||
if (child->getNestableType() == NestableType::Entity) {
|
||||
|
@ -551,7 +658,7 @@ void Avatar::simulate(float deltaTime, bool inView) {
|
|||
if (!hasParent()) {
|
||||
setLocalPosition(_globalPosition);
|
||||
}
|
||||
|
||||
|
||||
_simulationRate.increment();
|
||||
if (inView) {
|
||||
_simulationInViewRate.increment();
|
||||
|
@ -617,6 +724,11 @@ void Avatar::simulate(float deltaTime, bool inView) {
|
|||
updateAvatarEntities();
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_RANGE(simulation, "grabs");
|
||||
updateGrabs();
|
||||
}
|
||||
|
||||
updateFadingStatus();
|
||||
}
|
||||
|
||||
|
@ -1295,6 +1407,9 @@ glm::quat Avatar::getAbsoluteJointRotationInObjectFrame(int index) const {
|
|||
}
|
||||
|
||||
switch (index) {
|
||||
case NO_JOINT_INDEX: {
|
||||
return glm::quat();
|
||||
}
|
||||
case SENSOR_TO_WORLD_MATRIX_INDEX: {
|
||||
glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix();
|
||||
glm::mat4 avatarMatrix = getLocalTransform().getMatrix();
|
||||
|
@ -1344,6 +1459,9 @@ glm::vec3 Avatar::getAbsoluteJointTranslationInObjectFrame(int index) const {
|
|||
}
|
||||
|
||||
switch (index) {
|
||||
case NO_JOINT_INDEX: {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
case SENSOR_TO_WORLD_MATRIX_INDEX: {
|
||||
glm::mat4 sensorToWorldMatrix = getSensorToWorldMatrix();
|
||||
glm::mat4 avatarMatrix = getLocalTransform().getMatrix();
|
||||
|
|
|
@ -156,9 +156,6 @@ public:
|
|||
|
||||
virtual void postUpdate(float deltaTime, const render::ScenePointer& scene);
|
||||
|
||||
//setters
|
||||
void setIsLookAtTarget(const bool isLookAtTarget) { _isLookAtTarget = isLookAtTarget; }
|
||||
bool getIsLookAtTarget() const { return _isLookAtTarget; }
|
||||
//getters
|
||||
bool isInitialized() const { return _initialized; }
|
||||
SkeletonModelPointer getSkeletonModel() { return _skeletonModel; }
|
||||
|
@ -440,6 +437,8 @@ public:
|
|||
std::shared_ptr<AvatarTransit> getTransit() { return std::make_shared<AvatarTransit>(_transit); };
|
||||
AvatarTransit::Status updateTransit(float deltaTime, const glm::vec3& avatarPosition, float avatarScale, const AvatarTransit::TransitConfig& config);
|
||||
|
||||
void accumulateGrabPositions(std::map<QUuid, GrabLocationAccumulator>& grabAccumulators);
|
||||
|
||||
signals:
|
||||
void targetScaleChanged(float targetScale);
|
||||
|
||||
|
@ -542,6 +541,7 @@ protected:
|
|||
|
||||
// protected methods...
|
||||
bool isLookingAtMe(AvatarSharedPointer avatar) const;
|
||||
void updateGrabs();
|
||||
void relayJointDataToChildren();
|
||||
|
||||
void fade(render::Transaction& transaction, render::Transition::Type type);
|
||||
|
@ -592,7 +592,6 @@ protected:
|
|||
int _rightPointerGeometryID { 0 };
|
||||
int _nameRectGeometryID { 0 };
|
||||
bool _initialized { false };
|
||||
bool _isLookAtTarget { false };
|
||||
bool _isAnimatingScale { false };
|
||||
bool _mustFadeIn { false };
|
||||
bool _isFading { false };
|
||||
|
@ -628,6 +627,8 @@ protected:
|
|||
|
||||
static void metaBlendshapeOperator(render::ItemID renderItemID, int blendshapeNumber, const QVector<BlendshapeOffset>& blendshapeOffsets,
|
||||
const QVector<int>& blendedMeshSizes, const render::ItemIDs& subItemIDs);
|
||||
|
||||
AvatarGrabMap _avatarGrabs;
|
||||
};
|
||||
|
||||
#endif // hifi_Avatar_h
|
||||
|
|
|
@ -1893,42 +1893,96 @@ qint64 AvatarData::packTrait(AvatarTraits::TraitType traitType, ExtendedIODevice
|
|||
return bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
qint64 AvatarData::packAvatarEntityTraitInstance(AvatarTraits::TraitType traitType,
|
||||
AvatarTraits::TraitInstanceID traitInstanceID,
|
||||
ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion) {
|
||||
qint64 bytesWritten = 0;
|
||||
|
||||
// grab a read lock on the avatar entities and check for entity data for the given ID
|
||||
QByteArray entityBinaryData;
|
||||
|
||||
_avatarEntitiesLock.withReadLock([this, &entityBinaryData, &traitInstanceID] {
|
||||
if (_avatarEntityData.contains(traitInstanceID)) {
|
||||
entityBinaryData = _avatarEntityData[traitInstanceID];
|
||||
}
|
||||
});
|
||||
|
||||
if (entityBinaryData.size() > AvatarTraits::MAXIMUM_TRAIT_SIZE) {
|
||||
qWarning() << "Refusing to pack instanced trait" << traitType << "of size" << entityBinaryData.size()
|
||||
<< "bytes since it exceeds the maximum size " << AvatarTraits::MAXIMUM_TRAIT_SIZE << "bytes";
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytesWritten += destination.writePrimitive(traitType);
|
||||
|
||||
if (traitVersion > AvatarTraits::DEFAULT_TRAIT_VERSION) {
|
||||
bytesWritten += destination.writePrimitive(traitVersion);
|
||||
}
|
||||
|
||||
bytesWritten += destination.write(traitInstanceID.toRfc4122());
|
||||
|
||||
if (!entityBinaryData.isNull()) {
|
||||
AvatarTraits::TraitWireSize entityBinarySize = entityBinaryData.size();
|
||||
|
||||
bytesWritten += destination.writePrimitive(entityBinarySize);
|
||||
bytesWritten += destination.write(entityBinaryData);
|
||||
} else {
|
||||
bytesWritten += destination.writePrimitive(AvatarTraits::DELETED_TRAIT_SIZE);
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
qint64 AvatarData::packGrabTraitInstance(AvatarTraits::TraitType traitType,
|
||||
AvatarTraits::TraitInstanceID traitInstanceID,
|
||||
ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion) {
|
||||
qint64 bytesWritten = 0;
|
||||
|
||||
// grab a read lock on the avatar grabs and check for grab data for the given ID
|
||||
QByteArray grabBinaryData;
|
||||
|
||||
_avatarGrabsLock.withReadLock([this, &grabBinaryData, &traitInstanceID] {
|
||||
if (_avatarGrabData.contains(traitInstanceID)) {
|
||||
grabBinaryData = _avatarGrabData[traitInstanceID];
|
||||
}
|
||||
});
|
||||
|
||||
if (grabBinaryData.size() > AvatarTraits::MAXIMUM_TRAIT_SIZE) {
|
||||
qWarning() << "Refusing to pack instanced trait" << traitType << "of size" << grabBinaryData.size()
|
||||
<< "bytes since it exceeds the maximum size " << AvatarTraits::MAXIMUM_TRAIT_SIZE << "bytes";
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytesWritten += destination.writePrimitive(traitType);
|
||||
|
||||
if (traitVersion > AvatarTraits::DEFAULT_TRAIT_VERSION) {
|
||||
bytesWritten += destination.writePrimitive(traitVersion);
|
||||
}
|
||||
|
||||
bytesWritten += destination.write(traitInstanceID.toRfc4122());
|
||||
|
||||
if (!grabBinaryData.isNull()) {
|
||||
AvatarTraits::TraitWireSize grabBinarySize = grabBinaryData.size();
|
||||
|
||||
bytesWritten += destination.writePrimitive(grabBinarySize);
|
||||
bytesWritten += destination.write(grabBinaryData);
|
||||
} else {
|
||||
bytesWritten += destination.writePrimitive(AvatarTraits::DELETED_TRAIT_SIZE);
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
qint64 AvatarData::packTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID traitInstanceID,
|
||||
ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion) {
|
||||
qint64 bytesWritten = 0;
|
||||
|
||||
if (traitType == AvatarTraits::AvatarEntity) {
|
||||
// grab a read lock on the avatar entities and check for entity data for the given ID
|
||||
QByteArray entityBinaryData;
|
||||
|
||||
_avatarEntitiesLock.withReadLock([this, &entityBinaryData, &traitInstanceID] {
|
||||
if (_avatarEntityData.contains(traitInstanceID)) {
|
||||
entityBinaryData = _avatarEntityData[traitInstanceID];
|
||||
}
|
||||
});
|
||||
|
||||
if (entityBinaryData.size() > AvatarTraits::MAXIMUM_TRAIT_SIZE) {
|
||||
qWarning() << "Refusing to pack instanced trait" << traitType << "of size" << entityBinaryData.size()
|
||||
<< "bytes since it exceeds the maximum size " << AvatarTraits::MAXIMUM_TRAIT_SIZE << "bytes";
|
||||
return 0;
|
||||
}
|
||||
|
||||
bytesWritten += destination.writePrimitive(traitType);
|
||||
|
||||
if (traitVersion > AvatarTraits::DEFAULT_TRAIT_VERSION) {
|
||||
bytesWritten += destination.writePrimitive(traitVersion);
|
||||
}
|
||||
|
||||
bytesWritten += destination.write(traitInstanceID.toRfc4122());
|
||||
|
||||
if (!entityBinaryData.isNull()) {
|
||||
AvatarTraits::TraitWireSize entityBinarySize = entityBinaryData.size();
|
||||
|
||||
bytesWritten += destination.writePrimitive(entityBinarySize);
|
||||
bytesWritten += destination.write(entityBinaryData);
|
||||
} else {
|
||||
bytesWritten += destination.writePrimitive(AvatarTraits::DELETED_TRAIT_SIZE);
|
||||
}
|
||||
packAvatarEntityTraitInstance(traitType, traitInstanceID, destination, traitVersion);
|
||||
} else if (traitType == AvatarTraits::Grab) {
|
||||
packGrabTraitInstance(traitType, traitInstanceID, destination, traitVersion);
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
|
@ -1940,6 +1994,9 @@ void AvatarData::prepareResetTraitInstances() {
|
|||
foreach (auto entityID, _avatarEntityData.keys()) {
|
||||
_clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::AvatarEntity, entityID);
|
||||
}
|
||||
foreach (auto grabID, _avatarGrabData.keys()) {
|
||||
_clientTraitsHandler->markInstancedTraitUpdated(AvatarTraits::Grab, grabID);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1956,12 +2013,16 @@ void AvatarData::processTraitInstance(AvatarTraits::TraitType traitType,
|
|||
AvatarTraits::TraitInstanceID instanceID, QByteArray traitBinaryData) {
|
||||
if (traitType == AvatarTraits::AvatarEntity) {
|
||||
updateAvatarEntity(instanceID, traitBinaryData);
|
||||
} else if (traitType == AvatarTraits::Grab) {
|
||||
updateAvatarGrabData(instanceID, traitBinaryData);
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarData::processDeletedTraitInstance(AvatarTraits::TraitType traitType, AvatarTraits::TraitInstanceID instanceID) {
|
||||
if (traitType == AvatarTraits::AvatarEntity) {
|
||||
clearAvatarEntity(instanceID);
|
||||
} else if (traitType == AvatarTraits::Grab) {
|
||||
clearAvatarGrabData(instanceID);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2909,3 +2970,38 @@ AABox AvatarData::getDefaultBubbleBox() const {
|
|||
bubbleBox.translate(_globalPosition);
|
||||
return bubbleBox;
|
||||
}
|
||||
|
||||
bool AvatarData::updateAvatarGrabData(const QUuid& grabID, const QByteArray& grabData) {
|
||||
bool changed { false };
|
||||
_avatarGrabsLock.withWriteLock([&] {
|
||||
AvatarGrabDataMap::iterator itr = _avatarGrabData.find(grabID);
|
||||
if (itr == _avatarGrabData.end()) {
|
||||
// create a new one
|
||||
if (_avatarGrabData.size() < MAX_NUM_AVATAR_GRABS) {
|
||||
_avatarGrabData.insert(grabID, grabData);
|
||||
_avatarGrabDataChanged = true;
|
||||
changed = true;
|
||||
} else {
|
||||
qCWarning(avatars) << "Can't create more grabs on avatar, limit reached.";
|
||||
}
|
||||
} else {
|
||||
// update an existing one
|
||||
if (itr.value() != grabData) {
|
||||
itr.value() = grabData;
|
||||
_avatarGrabDataChanged = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void AvatarData::clearAvatarGrabData(const QUuid& grabID) {
|
||||
_avatarGrabsLock.withWriteLock([&] {
|
||||
if (_avatarGrabData.remove(grabID)) {
|
||||
_avatarGrabDataChanged = true;
|
||||
_deletedAvatarGrabs.insert(grabID);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -54,15 +54,21 @@
|
|||
#include "AvatarTraits.h"
|
||||
#include "HeadData.h"
|
||||
#include "PathUtils.h"
|
||||
#include "Grab.h"
|
||||
|
||||
#include <graphics/Material.h>
|
||||
|
||||
using AvatarSharedPointer = std::shared_ptr<AvatarData>;
|
||||
using AvatarWeakPointer = std::weak_ptr<AvatarData>;
|
||||
using AvatarHash = QHash<QUuid, AvatarSharedPointer>;
|
||||
|
||||
using AvatarEntityMap = QMap<QUuid, QByteArray>;
|
||||
using AvatarEntityIDs = QSet<QUuid>;
|
||||
|
||||
using AvatarGrabDataMap = QMap<QUuid, QByteArray>;
|
||||
using AvatarGrabIDs = QSet<QUuid>;
|
||||
using AvatarGrabMap = QMap<QUuid, GrabPointer>;
|
||||
|
||||
using AvatarDataSequenceNumber = uint16_t;
|
||||
|
||||
// avatar motion behaviors
|
||||
|
@ -1342,6 +1348,13 @@ protected:
|
|||
bool hasParent() const { return !getParentID().isNull(); }
|
||||
bool hasFaceTracker() const { return _headData ? _headData->_isFaceTrackerConnected : false; }
|
||||
|
||||
qint64 packAvatarEntityTraitInstance(AvatarTraits::TraitType traitType,
|
||||
AvatarTraits::TraitInstanceID traitInstanceID,
|
||||
ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion);
|
||||
qint64 packGrabTraitInstance(AvatarTraits::TraitType traitType,
|
||||
AvatarTraits::TraitInstanceID traitInstanceID,
|
||||
ExtendedIODevice& destination, AvatarTraits::TraitVersion traitVersion);
|
||||
|
||||
// isReplicated will be true on downstream Avatar Mixers and their clients, but false on the upstream "master"
|
||||
// Audio Mixer that the replicated avatar is connected to.
|
||||
bool _isReplicated{ false };
|
||||
|
@ -1452,6 +1465,12 @@ protected:
|
|||
AvatarEntityMap _avatarEntityData;
|
||||
bool _avatarEntityDataChanged { false };
|
||||
|
||||
mutable ReadWriteLockable _avatarGrabsLock;
|
||||
AvatarGrabDataMap _avatarGrabData;
|
||||
bool _avatarGrabDataChanged { false }; // by network
|
||||
AvatarGrabIDs _changedAvatarGrabs; // updated grab IDs -- changes needed to entities or physics
|
||||
AvatarGrabIDs _deletedAvatarGrabs; // deleted grab IDs -- changes needed to entities or physics
|
||||
|
||||
// used to transform any sensor into world space, including the _hmdSensorMat, or hand controllers.
|
||||
ThreadSafeValueCache<glm::mat4> _sensorToWorldMatrixCache { glm::mat4() };
|
||||
ThreadSafeValueCache<glm::mat4> _controllerLeftHandMatrixCache { glm::mat4() };
|
||||
|
@ -1511,6 +1530,9 @@ protected:
|
|||
f(index);
|
||||
}
|
||||
|
||||
bool updateAvatarGrabData(const QUuid& grabID, const QByteArray& grabData);
|
||||
void clearAvatarGrabData(const QUuid& grabID);
|
||||
|
||||
private:
|
||||
friend void avatarStateFromFrame(const QByteArray& frameData, AvatarData* _avatar);
|
||||
static QUrl _defaultFullAvatarModelUrl;
|
||||
|
@ -1614,6 +1636,7 @@ QScriptValue AvatarEntityMapToScriptValue(QScriptEngine* engine, const AvatarEnt
|
|||
void AvatarEntityMapFromScriptValue(const QScriptValue& object, AvatarEntityMap& value);
|
||||
|
||||
// faux joint indexes (-1 means invalid)
|
||||
const int NO_JOINT_INDEX = 65535; // -1
|
||||
const int SENSOR_TO_WORLD_MATRIX_INDEX = 65534; // -2
|
||||
const int CONTROLLER_RIGHTHAND_INDEX = 65533; // -3
|
||||
const int CONTROLLER_LEFTHAND_INDEX = 65532; // -4
|
||||
|
@ -1626,5 +1649,6 @@ const int FARGRAB_MOUSE_INDEX = 65526; // -10
|
|||
|
||||
const int LOWEST_PSEUDO_JOINT_INDEX = 65526;
|
||||
|
||||
const int MAX_NUM_AVATAR_GRABS = 6;
|
||||
|
||||
#endif // hifi_AvatarData_h
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace AvatarTraits {
|
|||
SkeletonModelURL,
|
||||
FirstInstancedTrait,
|
||||
AvatarEntity = FirstInstancedTrait,
|
||||
Grab,
|
||||
TotalTraitTypes
|
||||
};
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <ScriptEngine.h>
|
||||
#include <EntitySimulation.h>
|
||||
#include <ZoneRenderer.h>
|
||||
#include <PhysicalEntitySimulation.h>
|
||||
|
||||
#include "EntitiesRendererLogging.h"
|
||||
#include "RenderableEntityItem.h"
|
||||
|
@ -1250,3 +1251,11 @@ void EntityTreeRenderer::onEntityChanged(const EntityItemID& id) {
|
|||
_changedEntities.insert(id);
|
||||
});
|
||||
}
|
||||
|
||||
EntityEditPacketSender* EntityTreeRenderer::getPacketSender() {
|
||||
EntityTreePointer tree = getTree();
|
||||
EntitySimulationPointer simulation = tree ? tree->getSimulation() : nullptr;
|
||||
PhysicalEntitySimulationPointer peSimulation = std::static_pointer_cast<PhysicalEntitySimulation>(simulation);
|
||||
EntityEditPacketSender* packetSender = peSimulation ? peSimulation->getPacketSender() : nullptr;
|
||||
return packetSender;
|
||||
}
|
||||
|
|
|
@ -120,6 +120,8 @@ public:
|
|||
static void setGetAvatarUpOperator(std::function<glm::vec3()> getAvatarUpOperator) { _getAvatarUpOperator = getAvatarUpOperator; }
|
||||
static glm::vec3 getAvatarUp() { return _getAvatarUpOperator(); }
|
||||
|
||||
EntityEditPacketSender* getPacketSender();
|
||||
|
||||
signals:
|
||||
void enterEntity(const EntityItemID& entityItemID);
|
||||
void leaveEntity(const EntityItemID& entityItemID);
|
||||
|
|
|
@ -37,7 +37,7 @@ void LineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointe
|
|||
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_lineVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
glm::vec4 lineColor(toGlm(entity->getColor()), entity->getLocalRenderAlpha());
|
||||
glm::vec4 lineColor(toGlm(entity->getColor()), 1.0f);
|
||||
geometryCache->updateVertices(_lineVerticesID, _linePoints, lineColor);
|
||||
}
|
||||
|
||||
|
|
|
@ -131,21 +131,6 @@ bool ShapeEntityRenderer::isTransparent() const {
|
|||
return Parent::isTransparent();
|
||||
}
|
||||
|
||||
ItemKey ShapeEntityRenderer::getKey() {
|
||||
ItemKey::Builder builder;
|
||||
builder.withTypeShape().withTypeMeta().withTagBits(getTagMask());
|
||||
|
||||
withReadLock([&] {
|
||||
if (isTransparent()) {
|
||||
builder.withTransparent();
|
||||
} else if (_canCastShadow) {
|
||||
builder.withShadowCaster();
|
||||
}
|
||||
});
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
bool ShapeEntityRenderer::useMaterialPipeline() const {
|
||||
bool proceduralReady = resultWithReadLock<bool>([&] {
|
||||
return _procedural.isReady();
|
||||
|
|
|
@ -25,7 +25,6 @@ public:
|
|||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
|
||||
protected:
|
||||
ItemKey getKey() override;
|
||||
ShapeKey getShapeKey() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -27,7 +27,10 @@ static const int FIXED_FONT_POINT_SIZE = 40;
|
|||
TextEntityRenderer::TextEntityRenderer(const EntityItemPointer& entity) :
|
||||
Parent(entity),
|
||||
_textRenderer(TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE / 2.0f)) {
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
_geometryID = geometryCache->allocateID();
|
||||
}
|
||||
}
|
||||
|
||||
TextEntityRenderer::~TextEntityRenderer() {
|
||||
|
@ -37,6 +40,18 @@ TextEntityRenderer::~TextEntityRenderer() {
|
|||
}
|
||||
}
|
||||
|
||||
bool TextEntityRenderer::isTransparent() const {
|
||||
return Parent::isTransparent() || _textAlpha < 1.0f || _backgroundAlpha < 1.0f;
|
||||
}
|
||||
|
||||
ShapeKey TextEntityRenderer::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
if (_text != entity->getText()) {
|
||||
return true;
|
||||
|
@ -50,10 +65,18 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
|
|||
return true;
|
||||
}
|
||||
|
||||
if (_textAlpha != entity->getTextAlpha()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_backgroundColor != toGlm(entity->getBackgroundColor())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_backgroundAlpha != entity->getBackgroundAlpha()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_dimensions != entity->getScaledDimensions()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -61,6 +84,23 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint
|
|||
if (_billboardMode != entity->getBillboardMode()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_leftMargin != entity->getLeftMargin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_rightMargin != entity->getRightMargin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_topMargin != entity->getTopMargin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_bottomMargin != entity->getBottomMargin()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -76,14 +116,19 @@ void TextEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen
|
|||
}
|
||||
|
||||
void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
_textColor = toGlm(entity->getTextColor());
|
||||
_backgroundColor = toGlm(entity->getBackgroundColor());
|
||||
_billboardMode = entity->getBillboardMode();
|
||||
_lineHeight = entity->getLineHeight();
|
||||
_text = entity->getText();
|
||||
_lineHeight = entity->getLineHeight();
|
||||
_textColor = toGlm(entity->getTextColor());
|
||||
_textAlpha = entity->getTextAlpha();
|
||||
_backgroundColor = toGlm(entity->getBackgroundColor());
|
||||
_backgroundAlpha = entity->getBackgroundAlpha();
|
||||
_billboardMode = entity->getBillboardMode();
|
||||
_leftMargin = entity->getLeftMargin();
|
||||
_rightMargin = entity->getRightMargin();
|
||||
_topMargin = entity->getTopMargin();
|
||||
_bottomMargin = entity->getBottomMargin();
|
||||
}
|
||||
|
||||
|
||||
void TextEntityRenderer::doRender(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableTextEntityItem::render");
|
||||
|
||||
|
@ -93,17 +138,16 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
modelTransform = _renderTransform;
|
||||
dimensions = _dimensions;
|
||||
});
|
||||
static const float SLIGHTLY_BEHIND = -0.005f;
|
||||
|
||||
float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f;
|
||||
bool transparent = fadeRatio < 1.0f;
|
||||
glm::vec4 textColor = glm::vec4(_textColor, fadeRatio);
|
||||
glm::vec4 backgroundColor = glm::vec4(_backgroundColor, fadeRatio);
|
||||
glm::vec4 textColor = glm::vec4(_textColor, fadeRatio * _textAlpha);
|
||||
glm::vec4 backgroundColor = glm::vec4(_backgroundColor, fadeRatio * _backgroundAlpha);
|
||||
|
||||
// Render background
|
||||
static const float SLIGHTLY_BEHIND = -0.005f;
|
||||
glm::vec3 minCorner = glm::vec3(0.0f, -dimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 maxCorner = glm::vec3(dimensions.x, 0.0f, SLIGHTLY_BEHIND);
|
||||
|
||||
|
||||
// Batch render calls
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
@ -135,18 +179,15 @@ void TextEntityRenderer::doRender(RenderArgs* args) {
|
|||
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (!_geometryID) {
|
||||
_geometryID = geometryCache->allocateID();
|
||||
}
|
||||
geometryCache->bindSimpleProgram(batch, false, transparent, false, false, false);
|
||||
geometryCache->bindSimpleProgram(batch, false, backgroundColor.a < 1.0f, false, false, false);
|
||||
geometryCache->renderQuad(batch, minCorner, maxCorner, backgroundColor, _geometryID);
|
||||
|
||||
// FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase.
|
||||
float scale = _lineHeight / _textRenderer->getFontSize();
|
||||
transformToTopLeft.setScale(scale); // Scale to have the correct line height
|
||||
batch.setModelTransform(transformToTopLeft);
|
||||
|
||||
float leftMargin = 0.1f * _lineHeight, topMargin = 0.1f * _lineHeight;
|
||||
glm::vec2 bounds = glm::vec2(dimensions.x - 2.0f * leftMargin,
|
||||
dimensions.y - 2.0f * topMargin);
|
||||
_textRenderer->draw(batch, leftMargin / scale, -topMargin / scale, _text, textColor, bounds / scale);
|
||||
glm::vec2 bounds = glm::vec2(dimensions.x - (_leftMargin + _rightMargin),
|
||||
dimensions.y - (_topMargin + _bottomMargin));
|
||||
_textRenderer->draw(batch, _leftMargin / scale, -_topMargin / scale, _text, textColor, bounds / scale);
|
||||
}
|
||||
|
|
|
@ -25,19 +25,33 @@ class TextEntityRenderer : public TypedEntityRenderer<TextEntityItem> {
|
|||
public:
|
||||
TextEntityRenderer(const EntityItemPointer& entity);
|
||||
~TextEntityRenderer();
|
||||
|
||||
bool isTransparent() const override;
|
||||
ShapeKey getShapeKey() override;
|
||||
|
||||
private:
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
int _geometryID{ 0 };
|
||||
std::shared_ptr<TextRenderer3D> _textRenderer;
|
||||
BillboardMode _billboardMode;
|
||||
glm::vec3 _dimensions;
|
||||
glm::vec3 _textColor;
|
||||
glm::vec3 _backgroundColor;
|
||||
|
||||
QString _text;
|
||||
float _lineHeight;
|
||||
glm::vec3 _textColor;
|
||||
float _textAlpha;
|
||||
glm::vec3 _backgroundColor;
|
||||
float _backgroundAlpha;
|
||||
|
||||
float _leftMargin;
|
||||
float _rightMargin;
|
||||
float _topMargin;
|
||||
float _bottomMargin;
|
||||
|
||||
BillboardMode _billboardMode;
|
||||
glm::vec3 _dimensions;
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -50,6 +50,8 @@ public:
|
|||
const QUuid& getID() const { return _id; }
|
||||
EntityDynamicType getType() const { return _type; }
|
||||
|
||||
virtual void removeFromOwner() { }
|
||||
|
||||
virtual void remapIDs(QHash<EntityItemID, EntityItemID>& map) = 0;
|
||||
|
||||
virtual bool isAction() const { return false; }
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include <SharedUtil.h> // usecTimestampNow()
|
||||
#include <LogHandler.h>
|
||||
#include <Extents.h>
|
||||
#include <QVariantGLM.h>
|
||||
#include <Grab.h>
|
||||
|
||||
#include "EntityScriptingInterface.h"
|
||||
#include "EntitiesLogging.h"
|
||||
|
@ -38,6 +40,7 @@
|
|||
#include "EntitySimulation.h"
|
||||
#include "EntityDynamicFactoryInterface.h"
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE(EntityItemPointer);
|
||||
int entityItemPointernMetaTypeId = qRegisterMetaType<EntityItemPointer>();
|
||||
|
||||
|
@ -70,33 +73,60 @@ EntityItem::~EntityItem() {
|
|||
EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties;
|
||||
|
||||
// Core
|
||||
requestedProperties += PROP_SIMULATION_OWNER;
|
||||
requestedProperties += PROP_VISIBLE;
|
||||
requestedProperties += PROP_NAME;
|
||||
requestedProperties += PROP_LOCKED;
|
||||
requestedProperties += PROP_USER_DATA;
|
||||
requestedProperties += PROP_HREF;
|
||||
requestedProperties += PROP_DESCRIPTION;
|
||||
requestedProperties += PROP_POSITION;
|
||||
requestedProperties += PROP_DIMENSIONS;
|
||||
requestedProperties += PROP_ROTATION;
|
||||
requestedProperties += PROP_REGISTRATION_POINT;
|
||||
// TODO: handle PROP_CREATED?
|
||||
requestedProperties += PROP_LAST_EDITED_BY;
|
||||
requestedProperties += PROP_ENTITY_HOST_TYPE;
|
||||
requestedProperties += PROP_OWNING_AVATAR_ID;
|
||||
requestedProperties += PROP_PARENT_ID;
|
||||
requestedProperties += PROP_PARENT_JOINT_INDEX;
|
||||
requestedProperties += PROP_QUERY_AA_CUBE;
|
||||
requestedProperties += PROP_CAN_CAST_SHADOW;
|
||||
// requestedProperties += PROP_VISIBLE_IN_SECONDARY_CAMERA; // not sent over wire
|
||||
withReadLock([&] {
|
||||
requestedProperties += _grabProperties.getEntityProperties(params);
|
||||
});
|
||||
|
||||
// Physics
|
||||
requestedProperties += PROP_DENSITY;
|
||||
requestedProperties += PROP_VELOCITY;
|
||||
requestedProperties += PROP_ANGULAR_VELOCITY;
|
||||
requestedProperties += PROP_ACCELERATION;
|
||||
|
||||
requestedProperties += PROP_DIMENSIONS;
|
||||
requestedProperties += PROP_DENSITY;
|
||||
requestedProperties += PROP_GRAVITY;
|
||||
requestedProperties += PROP_ACCELERATION;
|
||||
requestedProperties += PROP_DAMPING;
|
||||
requestedProperties += PROP_ANGULAR_DAMPING;
|
||||
requestedProperties += PROP_RESTITUTION;
|
||||
requestedProperties += PROP_FRICTION;
|
||||
requestedProperties += PROP_LIFETIME;
|
||||
requestedProperties += PROP_SCRIPT;
|
||||
requestedProperties += PROP_SCRIPT_TIMESTAMP;
|
||||
requestedProperties += PROP_SERVER_SCRIPTS;
|
||||
requestedProperties += PROP_COLLISION_SOUND_URL;
|
||||
requestedProperties += PROP_REGISTRATION_POINT;
|
||||
requestedProperties += PROP_ANGULAR_DAMPING;
|
||||
requestedProperties += PROP_VISIBLE;
|
||||
requestedProperties += PROP_CAN_CAST_SHADOW;
|
||||
requestedProperties += PROP_COLLISIONLESS;
|
||||
requestedProperties += PROP_COLLISION_MASK;
|
||||
requestedProperties += PROP_DYNAMIC;
|
||||
requestedProperties += PROP_LOCKED;
|
||||
requestedProperties += PROP_USER_DATA;
|
||||
requestedProperties += PROP_COLLISION_SOUND_URL;
|
||||
requestedProperties += PROP_ACTION_DATA;
|
||||
|
||||
// Cloning
|
||||
requestedProperties += PROP_CLONEABLE;
|
||||
requestedProperties += PROP_CLONE_LIFETIME;
|
||||
requestedProperties += PROP_CLONE_LIMIT;
|
||||
requestedProperties += PROP_CLONE_DYNAMIC;
|
||||
requestedProperties += PROP_CLONE_AVATAR_ENTITY;
|
||||
requestedProperties += PROP_CLONE_ORIGIN_ID;
|
||||
|
||||
// Scripts
|
||||
requestedProperties += PROP_SCRIPT;
|
||||
requestedProperties += PROP_SCRIPT_TIMESTAMP;
|
||||
requestedProperties += PROP_SERVER_SCRIPTS;
|
||||
|
||||
// Certifiable properties
|
||||
requestedProperties += PROP_ITEM_NAME;
|
||||
|
@ -111,30 +141,6 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param
|
|||
requestedProperties += PROP_CERTIFICATE_ID;
|
||||
requestedProperties += PROP_STATIC_CERTIFICATE_VERSION;
|
||||
|
||||
requestedProperties += PROP_NAME;
|
||||
requestedProperties += PROP_HREF;
|
||||
requestedProperties += PROP_DESCRIPTION;
|
||||
requestedProperties += PROP_ACTION_DATA;
|
||||
requestedProperties += PROP_PARENT_ID;
|
||||
requestedProperties += PROP_PARENT_JOINT_INDEX;
|
||||
requestedProperties += PROP_QUERY_AA_CUBE;
|
||||
|
||||
requestedProperties += PROP_ENTITY_HOST_TYPE;
|
||||
requestedProperties += PROP_OWNING_AVATAR_ID;
|
||||
|
||||
requestedProperties += PROP_LAST_EDITED_BY;
|
||||
|
||||
requestedProperties += PROP_CLONEABLE;
|
||||
requestedProperties += PROP_CLONE_LIFETIME;
|
||||
requestedProperties += PROP_CLONE_LIMIT;
|
||||
requestedProperties += PROP_CLONE_DYNAMIC;
|
||||
requestedProperties += PROP_CLONE_AVATAR_ENTITY;
|
||||
requestedProperties += PROP_CLONE_ORIGIN_ID;
|
||||
|
||||
withReadLock([&] {
|
||||
requestedProperties += _grabProperties.getEntityProperties(params);
|
||||
});
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -240,36 +246,72 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
|
||||
propertyFlags -= PROP_LAST_ITEM; // clear the last item for now, we may or may not set it as the actual item
|
||||
|
||||
// NOTE: When we enable partial packing of entity properties, we'll want to pack simulationOwner, transform, and velocity properties near each other
|
||||
// since they will commonly be transmitted together. simulationOwner must always go first, to avoid race conditions of simulation ownership bids
|
||||
// These items would go here once supported....
|
||||
// PROP_PAGED_PROPERTY,
|
||||
// PROP_CUSTOM_PROPERTIES_INCLUDED,
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SIMULATION_OWNER, _simulationOwner.toByteArray());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, getName());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, getUserData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_HREF, getHref());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, getDescription());
|
||||
APPEND_ENTITY_PROPERTY(PROP_POSITION, getLocalPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getUnscaledDimensions());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ROTATION, getLocalOrientation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint());
|
||||
// TODO: handle created?
|
||||
APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, getLastEditedBy());
|
||||
// APPEND_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, getEntityHostType()); // not sent over wire
|
||||
// APPEND_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, getOwningAvatarID()); // not sent over wire
|
||||
// convert AVATAR_SELF_ID to actual sessionUUID.
|
||||
QUuid actualParentID = getParentID();
|
||||
if (actualParentID == AVATAR_SELF_ID) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
actualParentID = nodeList->getSessionUUID();
|
||||
}
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, actualParentID);
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, getQueryAACube());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow());
|
||||
// APPEND_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, getIsVisibleInSecondaryCamera()); // not sent over wire
|
||||
withReadLock([&] {
|
||||
_grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties,
|
||||
propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
});
|
||||
|
||||
// Physics
|
||||
APPEND_ENTITY_PROPERTY(PROP_DENSITY, getDensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VELOCITY, getLocalVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getLocalAngularVelocity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getUnscaledDimensions());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DENSITY, getDensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAVITY, getGravity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DAMPING, getDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_RESTITUTION, getRestitution());
|
||||
APPEND_ENTITY_PROPERTY(PROP_FRICTION, getFriction());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFETIME, getLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, getScriptTimestamp());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, getServerScripts());
|
||||
APPEND_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, getRegistrationPoint());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, getAngularDamping());
|
||||
APPEND_ENTITY_PROPERTY(PROP_VISIBLE, getVisible());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, getCanCastShadow());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISIONLESS, getCollisionless());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_MASK, getCollisionMask());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DYNAMIC, getDynamic());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LOCKED, getLocked());
|
||||
APPEND_ENTITY_PROPERTY(PROP_USER_DATA, getUserData());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, getCollisionSoundURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getDynamicData());
|
||||
|
||||
// Cloning
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONEABLE, getCloneable());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_LIFETIME, getCloneLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_LIMIT, getCloneLimit());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_DYNAMIC, getCloneDynamic());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_AVATAR_ENTITY, getCloneAvatarEntity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_ORIGIN_ID, getCloneOriginID());
|
||||
|
||||
// Scripts
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT, getScript());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, getScriptTimestamp());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, getServerScripts());
|
||||
|
||||
// Certifiable Properties
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, getMarketplaceID());
|
||||
|
@ -284,36 +326,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet
|
|||
APPEND_ENTITY_PROPERTY(PROP_CERTIFICATE_ID, getCertificateID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STATIC_CERTIFICATE_VERSION, getStaticCertificateVersion());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, getName());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, getCollisionSoundURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_HREF, getHref());
|
||||
APPEND_ENTITY_PROPERTY(PROP_DESCRIPTION, getDescription());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, getDynamicData());
|
||||
|
||||
// convert AVATAR_SELF_ID to actual sessionUUID.
|
||||
QUuid actualParentID = getParentID();
|
||||
if (actualParentID == AVATAR_SELF_ID) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
actualParentID = nodeList->getSessionUUID();
|
||||
}
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_ID, actualParentID);
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, getParentJointIndex());
|
||||
APPEND_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, getQueryAACube());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, getLastEditedBy());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONEABLE, getCloneable());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_LIFETIME, getCloneLifetime());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_LIMIT, getCloneLimit());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_DYNAMIC, getCloneDynamic());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_AVATAR_ENTITY, getCloneAvatarEntity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CLONE_ORIGIN_ID, getCloneOriginID());
|
||||
|
||||
withReadLock([&] {
|
||||
_grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties,
|
||||
propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
});
|
||||
|
||||
appendSubclassData(packetData, params, entityTreeElementExtraEncodeData,
|
||||
requestedProperties,
|
||||
propertyFlags,
|
||||
|
@ -673,7 +685,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||
bool weOwnSimulation = _simulationOwner.matchesValidID(myNodeID);
|
||||
|
||||
// pack SimulationOwner, transform, and velocity properties near each other
|
||||
// NOTE: the server is authoritative for changes to simOwnerID so we always unpack ownership data
|
||||
// even when we would otherwise ignore the rest of the packet.
|
||||
|
||||
|
@ -766,6 +777,14 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
return otherOverwrites && simulationChanged && (valueChanged || filterRejection);
|
||||
};
|
||||
|
||||
// Core
|
||||
// PROP_SIMULATION_OWNER handled above
|
||||
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
|
||||
READ_ENTITY_PROPERTY(PROP_NAME, QString, setName);
|
||||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked);
|
||||
READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData);
|
||||
READ_ENTITY_PROPERTY(PROP_HREF, QString, setHref);
|
||||
READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription);
|
||||
{ // When we own the simulation we don't accept updates to the entity's transform/velocities
|
||||
// we also want to ignore any duplicate packets that have the same "recently updated" values
|
||||
// as a packet we've already recieved. This is because we want multiple edits of the same
|
||||
|
@ -778,30 +797,68 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
// Note: duplicate packets are expected and not wrong. They may be sent for any number of
|
||||
// reasons and the contract is that the client handles them in an idempotent manner.
|
||||
auto customUpdatePositionFromNetwork = [this, shouldUpdate, lastEdited](glm::vec3 value){
|
||||
auto customUpdatePositionFromNetwork = [this, shouldUpdate, lastEdited](glm::vec3 value) {
|
||||
if (shouldUpdate(_lastUpdatedPositionTimestamp, value != _lastUpdatedPositionValue)) {
|
||||
setPosition(value);
|
||||
_lastUpdatedPositionTimestamp = lastEdited;
|
||||
_lastUpdatedPositionValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
auto customUpdateRotationFromNetwork = [this, shouldUpdate, lastEdited](glm::quat value){
|
||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, customUpdatePositionFromNetwork);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, setUnscaledDimensions);
|
||||
{ // See comment above
|
||||
auto customUpdateRotationFromNetwork = [this, shouldUpdate, lastEdited](glm::quat value) {
|
||||
if (shouldUpdate(_lastUpdatedRotationTimestamp, value != _lastUpdatedRotationValue)) {
|
||||
setRotation(value);
|
||||
_lastUpdatedRotationTimestamp = lastEdited;
|
||||
_lastUpdatedRotationValue = value;
|
||||
}
|
||||
};
|
||||
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, customUpdateRotationFromNetwork);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
||||
// READ_ENTITY_PROPERTY(PROP_CREATED, quint64, setCreated); // not sent over wire
|
||||
READ_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy);
|
||||
// READ_ENTITY_PROPERTY(PROP_ENTITY_HOST_TYPE, entity::HostType, setEntityHostType); // not sent over wire
|
||||
// READ_ENTITY_PROPERTY(PROP_OWNING_AVATAR_ID, QUuuid, setOwningAvatarID); // not sent over wire
|
||||
{ // parentID and parentJointIndex are protected by simulation ownership
|
||||
bool oldOverwrite = overwriteLocalData;
|
||||
overwriteLocalData = overwriteLocalData && !weOwnSimulation;
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
||||
overwriteLocalData = oldOverwrite;
|
||||
}
|
||||
{ // See comment above
|
||||
auto customUpdateQueryAACubeFromNetwork = [this, shouldUpdate, lastEdited](AACube value) {
|
||||
if (shouldUpdate(_lastUpdatedQueryAACubeTimestamp, value != _lastUpdatedQueryAACubeValue)) {
|
||||
setQueryAACube(value);
|
||||
_lastUpdatedQueryAACubeTimestamp = lastEdited;
|
||||
_lastUpdatedQueryAACubeValue = value;
|
||||
}
|
||||
};
|
||||
READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, customUpdateQueryAACubeFromNetwork);
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow);
|
||||
// READ_ENTITY_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, bool, setIsVisibleInSecondaryCamera); // not sent over wire
|
||||
withWriteLock([&] {
|
||||
int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData,
|
||||
somethingChanged);
|
||||
bytesRead += bytesFromGrab;
|
||||
dataAt += bytesFromGrab;
|
||||
});
|
||||
|
||||
auto customUpdateVelocityFromNetwork = [this, shouldUpdate, lastEdited](glm::vec3 value){
|
||||
if (shouldUpdate(_lastUpdatedVelocityTimestamp, value != _lastUpdatedVelocityValue)) {
|
||||
READ_ENTITY_PROPERTY(PROP_DENSITY, float, setDensity);
|
||||
{
|
||||
auto customUpdateVelocityFromNetwork = [this, shouldUpdate, lastEdited](glm::vec3 value) {
|
||||
if (shouldUpdate(_lastUpdatedVelocityTimestamp, value != _lastUpdatedVelocityValue)) {
|
||||
setVelocity(value);
|
||||
_lastUpdatedVelocityTimestamp = lastEdited;
|
||||
_lastUpdatedVelocityValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, customUpdateVelocityFromNetwork);
|
||||
auto customUpdateAngularVelocityFromNetwork = [this, shouldUpdate, lastEdited](glm::vec3 value){
|
||||
if (shouldUpdate(_lastUpdatedAngularVelocityTimestamp, value != _lastUpdatedAngularVelocityValue)) {
|
||||
setAngularVelocity(value);
|
||||
|
@ -809,7 +866,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
_lastUpdatedAngularVelocityValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, customUpdateAngularVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, setGravity);
|
||||
auto customSetAcceleration = [this, shouldUpdate, lastEdited](glm::vec3 value){
|
||||
if (shouldUpdate(_lastUpdatedAccelerationTimestamp, value != _lastUpdatedAccelerationValue)) {
|
||||
setAcceleration(value);
|
||||
|
@ -817,48 +875,40 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
_lastUpdatedAccelerationValue = value;
|
||||
}
|
||||
};
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, customUpdatePositionFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, customUpdateRotationFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, customUpdateVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, customUpdateAngularVelocityFromNetwork);
|
||||
READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, customSetAcceleration);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, setUnscaledDimensions);
|
||||
READ_ENTITY_PROPERTY(PROP_DENSITY, float, setDensity);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, setGravity);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_DAMPING, float, setDamping);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, setAngularDamping);
|
||||
READ_ENTITY_PROPERTY(PROP_RESTITUTION, float, setRestitution);
|
||||
READ_ENTITY_PROPERTY(PROP_FRICTION, float, setFriction);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, setLifetime);
|
||||
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
|
||||
READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
|
||||
|
||||
{
|
||||
// We use this scope to work around an issue stopping server script changes
|
||||
// from being received by an entity script server running a script that continously updates an entity.
|
||||
|
||||
// Basically, we'll allow recent changes to the server scripts even if there are local changes to other properties
|
||||
// that have been made more recently.
|
||||
|
||||
bool overwriteLocalData = !ignoreServerPacket || (lastEditedFromBufferAdjusted > _serverScriptsChangedTimestamp);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, QString, setServerScripts);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, setAngularDamping);
|
||||
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible);
|
||||
READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISIONLESS, bool, setCollisionless);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint16_t, setCollisionMask);
|
||||
READ_ENTITY_PROPERTY(PROP_DYNAMIC, bool, setDynamic);
|
||||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked);
|
||||
READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setDynamicData);
|
||||
|
||||
// Cloning
|
||||
READ_ENTITY_PROPERTY(PROP_CLONEABLE, bool, setCloneable);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_LIFETIME, float, setCloneLifetime);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_LIMIT, float, setCloneLimit);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_DYNAMIC, bool, setCloneDynamic);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_AVATAR_ENTITY, bool, setCloneAvatarEntity);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_ORIGIN_ID, QUuid, setCloneOriginID);
|
||||
|
||||
// Scripts
|
||||
READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript);
|
||||
READ_ENTITY_PROPERTY(PROP_SCRIPT_TIMESTAMP, quint64, setScriptTimestamp);
|
||||
{
|
||||
// We use this scope to work around an issue stopping server script changes
|
||||
// from being received by an entity script server running a script that continously updates an entity.
|
||||
// Basically, we'll allow recent changes to the server scripts even if there are local changes to other properties
|
||||
// that have been made more recently.
|
||||
bool overwriteLocalData = !ignoreServerPacket || (lastEditedFromBufferAdjusted > _serverScriptsChangedTimestamp);
|
||||
READ_ENTITY_PROPERTY(PROP_SERVER_SCRIPTS, QString, setServerScripts);
|
||||
}
|
||||
|
||||
// Certifiable props
|
||||
READ_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_NAME, QString, setItemName);
|
||||
READ_ENTITY_PROPERTY(PROP_ITEM_DESCRIPTION, QString, setItemDescription);
|
||||
|
@ -871,49 +921,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
READ_ENTITY_PROPERTY(PROP_CERTIFICATE_ID, QString, setCertificateID);
|
||||
READ_ENTITY_PROPERTY(PROP_STATIC_CERTIFICATE_VERSION, quint32, setStaticCertificateVersion);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_NAME, QString, setName);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||
READ_ENTITY_PROPERTY(PROP_HREF, QString, setHref);
|
||||
READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription);
|
||||
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setDynamicData);
|
||||
|
||||
{ // parentID and parentJointIndex are also protected by simulation ownership
|
||||
bool oldOverwrite = overwriteLocalData;
|
||||
overwriteLocalData = overwriteLocalData && !weOwnSimulation;
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_ID, QUuid, setParentID);
|
||||
READ_ENTITY_PROPERTY(PROP_PARENT_JOINT_INDEX, quint16, setParentJointIndex);
|
||||
overwriteLocalData = oldOverwrite;
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
auto customUpdateQueryAACubeFromNetwork = [this, shouldUpdate, lastEdited](AACube value){
|
||||
if (shouldUpdate(_lastUpdatedQueryAACubeTimestamp, value != _lastUpdatedQueryAACubeValue)) {
|
||||
setQueryAACube(value);
|
||||
_lastUpdatedQueryAACubeTimestamp = lastEdited;
|
||||
_lastUpdatedQueryAACubeValue = value;
|
||||
}
|
||||
};
|
||||
READ_ENTITY_PROPERTY(PROP_QUERY_AA_CUBE, AACube, customUpdateQueryAACubeFromNetwork);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_LAST_EDITED_BY, QUuid, setLastEditedBy);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_CLONEABLE, bool, setCloneable);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_LIFETIME, float, setCloneLifetime);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_LIMIT, float, setCloneLimit);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_DYNAMIC, bool, setCloneDynamic);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_AVATAR_ENTITY, bool, setCloneAvatarEntity);
|
||||
READ_ENTITY_PROPERTY(PROP_CLONE_ORIGIN_ID, QUuid, setCloneOriginID);
|
||||
|
||||
withWriteLock([&] {
|
||||
int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData,
|
||||
somethingChanged);
|
||||
bytesRead += bytesFromGrab;
|
||||
dataAt += bytesFromGrab;
|
||||
});
|
||||
|
||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
propertyFlags, overwriteLocalData, somethingChanged);
|
||||
|
||||
|
@ -1282,34 +1289,60 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire
|
|||
|
||||
properties._type = getType();
|
||||
|
||||
// Core
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(simulationOwner, getSimulationOwner);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(visible, getVisible);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(name, getName);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(href, getHref);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(description, getDescription);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(position, getLocalPosition);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getUnscaledDimensions);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotation, getLocalOrientation);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(created, getCreated);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lastEditedBy, getLastEditedBy);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(entityHostType, getEntityHostType);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(owningAvatarID, getOwningAvatarID);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(queryAACube, getQueryAACube);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow);
|
||||
// COPY_ENTITY_PROPERTY_TO_PROPERTIES(isVisibleInSecondaryCamera, getIsVisibleInSecondaryCamera); // not sent over wire
|
||||
withReadLock([&] {
|
||||
_grabProperties.getProperties(properties);
|
||||
});
|
||||
|
||||
// Physics
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(density, getDensity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(velocity, getLocalVelocity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getLocalAngularVelocity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(gravity, getGravity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(acceleration, getAcceleration);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(damping, getDamping);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularDamping, getAngularDamping);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(restitution, getRestitution);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(friction, getFriction);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(created, getCreated);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifetime, getLifetime);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(script, getScript);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptTimestamp, getScriptTimestamp);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(serverScripts, getServerScripts);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(registrationPoint, getRegistrationPoint);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularVelocity, getLocalAngularVelocity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(angularDamping, getAngularDamping);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRenderAlpha, getLocalRenderAlpha);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(visible, getVisible);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(canCastShadow, getCanCastShadow);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionless, getCollisionless);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionMask, getCollisionMask);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(dynamic, getDynamic);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionSoundURL, getCollisionSoundURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getDynamicData);
|
||||
|
||||
// Cloning
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneable, getCloneable);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneLifetime, getCloneLifetime);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneLimit, getCloneLimit);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneDynamic, getCloneDynamic);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneAvatarEntity, getCloneAvatarEntity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneOriginID, getCloneOriginID);
|
||||
|
||||
// Scripts
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(script, getScript);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(scriptTimestamp, getScriptTimestamp);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(serverScripts, getServerScripts);
|
||||
|
||||
// Certifiable Properties
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(itemName, getItemName);
|
||||
|
@ -1324,31 +1357,13 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(certificateID, getCertificateID);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(staticCertificateVersion, getStaticCertificateVersion);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(name, getName);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(href, getHref);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(description, getDescription);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(actionData, getDynamicData);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentID, getParentID);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentJointIndex, getParentJointIndex);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(queryAACube, getQueryAACube);
|
||||
// Script local data
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localPosition, getLocalPosition);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(localRotation, getLocalOrientation);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(entityHostType, getEntityHostType);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(owningAvatarID, getOwningAvatarID);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lastEditedBy, getLastEditedBy);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneable, getCloneable);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneLifetime, getCloneLifetime);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneLimit, getCloneLimit);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneDynamic, getCloneDynamic);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneAvatarEntity, getCloneAvatarEntity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cloneOriginID, getCloneOriginID);
|
||||
|
||||
withReadLock([&] {
|
||||
_grabProperties.getProperties(properties);
|
||||
});
|
||||
// FIXME: are these needed?
|
||||
//COPY_ENTITY_PROPERTY_TO_PROPERTIES(localVelocity, getLocalVelocity);
|
||||
//COPY_ENTITY_PROPERTY_TO_PROPERTIES(localAngularVelocity, getLocalAngularVelocity);
|
||||
//COPY_ENTITY_PROPERTY_TO_PROPERTIES(localDimensions, getLocalDimensions);
|
||||
|
||||
properties._defaultSettings = false;
|
||||
|
||||
|
@ -1418,42 +1433,61 @@ bool EntityItem::stillWaitingToTakeOwnership(uint64_t timestamp) const {
|
|||
bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = false;
|
||||
|
||||
// these affect transform and velocity properties
|
||||
// Core
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulationOwner, setSimulationOwner);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(href, setHref);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(description, setDescription);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, setPosition);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setUnscaledDimensions);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, setRotation);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(created, setCreated);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(entityHostType, setEntityHostType);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(owningAvatarID, setOwningAvatarID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, setParentID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isVisibleInSecondaryCamera, setIsVisibleInSecondaryCamera);
|
||||
withWriteLock([&] {
|
||||
bool grabPropertiesChanged = _grabProperties.setProperties(properties);
|
||||
somethingChanged |= grabPropertiesChanged;
|
||||
});
|
||||
|
||||
// Physics
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(density, setDensity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, setVelocity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, setAngularVelocity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(acceleration, setAcceleration);
|
||||
|
||||
// these (along with "position" above) affect tree structure
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setUnscaledDimensions);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint);
|
||||
|
||||
// these (along with all properties above) affect the simulation
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(density, setDensity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, setGravity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(acceleration, setAcceleration);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, setDamping);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, setAngularDamping);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(restitution, setRestitution);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(friction, setFriction);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, setLifetime);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionless, setCollisionless);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionMask, setCollisionMask);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(dynamic, setDynamic);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(created, setCreated);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, setLifetime);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setDynamicData);
|
||||
|
||||
// non-simulation properties below
|
||||
// Cloning
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneable, setCloneable);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneLifetime, setCloneLifetime);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneLimit, setCloneLimit);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneDynamic, setCloneDynamic);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneAvatarEntity, setCloneAvatarEntity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneOriginID, setCloneOriginID);
|
||||
|
||||
// Scripts
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(scriptTimestamp, setScriptTimestamp);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(serverScripts, setServerScripts);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(canCastShadow, setCanCastShadow);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isVisibleInSecondaryCamera, setIsVisibleInSecondaryCamera);
|
||||
|
||||
// Certifiable Properties
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(itemName, setItemName);
|
||||
|
@ -1468,31 +1502,6 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(certificateID, setCertificateID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(staticCertificateVersion, setStaticCertificateVersion);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(href, setHref);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(description, setDescription);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(actionData, setDynamicData);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentID, setParentID);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentJointIndex, setParentJointIndex);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(queryAACube, setQueryAACube);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(entityHostType, setEntityHostType);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(owningAvatarID, setOwningAvatarID);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lastEditedBy, setLastEditedBy);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneable, setCloneable);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneLifetime, setCloneLifetime);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneLimit, setCloneLimit);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneDynamic, setCloneDynamic);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneAvatarEntity, setCloneAvatarEntity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cloneOriginID, setCloneOriginID);
|
||||
|
||||
withWriteLock([&] {
|
||||
bool grabPropertiesChanged = _grabProperties.setProperties(properties);
|
||||
somethingChanged |= grabPropertiesChanged;
|
||||
});
|
||||
|
||||
if (updateQueryAACube()) {
|
||||
somethingChanged = true;
|
||||
}
|
||||
|
@ -1647,7 +1656,10 @@ AACube EntityItem::getQueryAACube(bool& success) const {
|
|||
}
|
||||
|
||||
bool EntityItem::shouldPuffQueryAACube() const {
|
||||
return hasActions() || isChildOfMyAvatar() || isMovingRelativeToParent();
|
||||
bool hasGrabs = _grabsLock.resultWithReadLock<bool>([&] {
|
||||
return _grabs.count() > 0;
|
||||
});
|
||||
return hasActions() || isChildOfMyAvatar() || isMovingRelativeToParent() || hasGrabs;
|
||||
}
|
||||
|
||||
// TODO: get rid of all users of this function...
|
||||
|
@ -2091,6 +2103,35 @@ bool EntityItem::addAction(EntitySimulationPointer simulation, EntityDynamicPoin
|
|||
return result;
|
||||
}
|
||||
|
||||
void EntityItem::enableNoBootstrap() {
|
||||
if (!(bool)(_flags & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) {
|
||||
_flags |= Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING;
|
||||
_flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
|
||||
forEachDescendant([&](SpatiallyNestablePointer child) {
|
||||
if (child->getNestableType() == NestableType::Entity) {
|
||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(child);
|
||||
entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP);
|
||||
entity->markSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::disableNoBootstrap() {
|
||||
if (!stillHasGrabActions()) {
|
||||
_flags &= ~Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING;
|
||||
_flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
|
||||
forEachDescendant([&](SpatiallyNestablePointer child) {
|
||||
if (child->getNestableType() == NestableType::Entity) {
|
||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(child);
|
||||
entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP);
|
||||
entity->clearSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityDynamicPointer action) {
|
||||
assert(action);
|
||||
assert(simulation);
|
||||
|
@ -2112,17 +2153,7 @@ bool EntityItem::addActionInternal(EntitySimulationPointer simulation, EntityDyn
|
|||
|
||||
auto actionType = action->getType();
|
||||
if (actionType == DYNAMIC_TYPE_HOLD || actionType == DYNAMIC_TYPE_FAR_GRAB) {
|
||||
if (!(bool)(_flags & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) {
|
||||
_flags |= Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING;
|
||||
_flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
|
||||
forEachDescendant([&](SpatiallyNestablePointer child) {
|
||||
if (child->getNestableType() == NestableType::Entity) {
|
||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(child);
|
||||
entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP);
|
||||
entity->markSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING);
|
||||
}
|
||||
});
|
||||
}
|
||||
enableNoBootstrap();
|
||||
}
|
||||
} else {
|
||||
qCDebug(entities) << "EntityItem::addActionInternal -- serializeActions failed";
|
||||
|
@ -2203,16 +2234,8 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi
|
|||
action->setIsMine(false);
|
||||
_objectActions.remove(actionID);
|
||||
|
||||
if ((removedActionType == DYNAMIC_TYPE_HOLD || removedActionType == DYNAMIC_TYPE_FAR_GRAB) && !stillHasGrabActions()) {
|
||||
_flags &= ~Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING;
|
||||
_flags |= Simulation::DIRTY_COLLISION_GROUP; // may need to not collide with own avatar
|
||||
forEachDescendant([&](SpatiallyNestablePointer child) {
|
||||
if (child->getNestableType() == NestableType::Entity) {
|
||||
EntityItemPointer entity = std::static_pointer_cast<EntityItem>(child);
|
||||
entity->markDirtyFlags(Simulation::DIRTY_COLLISION_GROUP);
|
||||
entity->clearSpecialFlags(Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING);
|
||||
}
|
||||
});
|
||||
if (removedActionType == DYNAMIC_TYPE_HOLD || removedActionType == DYNAMIC_TYPE_FAR_GRAB) {
|
||||
disableNoBootstrap();
|
||||
} else {
|
||||
// NO-OP: we assume SPECIAL_FLAGS_NO_BOOTSTRAPPING bits and collision group are correct
|
||||
// because they should have been set correctly when the action was added
|
||||
|
@ -2449,6 +2472,14 @@ bool EntityItem::shouldSuppressLocationEdits() const {
|
|||
i++;
|
||||
}
|
||||
|
||||
i = _grabActions.begin();
|
||||
while (i != _grabActions.end()) {
|
||||
if (i.value()->shouldSuppressLocationEdits()) {
|
||||
return true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// if any of the ancestors are MyAvatar, suppress
|
||||
return isChildOfMyAvatar();
|
||||
}
|
||||
|
@ -2456,13 +2487,22 @@ bool EntityItem::shouldSuppressLocationEdits() const {
|
|||
QList<EntityDynamicPointer> EntityItem::getActionsOfType(EntityDynamicType typeToGet) const {
|
||||
QList<EntityDynamicPointer> result;
|
||||
|
||||
QHash<QUuid, EntityDynamicPointer>::const_iterator i = _objectActions.begin();
|
||||
while (i != _objectActions.end()) {
|
||||
for (QHash<QUuid, EntityDynamicPointer>::const_iterator i = _objectActions.begin();
|
||||
i != _objectActions.end();
|
||||
i++) {
|
||||
EntityDynamicPointer action = i.value();
|
||||
if (action->getType() == typeToGet && action->isActive()) {
|
||||
result += action;
|
||||
}
|
||||
}
|
||||
|
||||
for (QHash<QUuid, EntityDynamicPointer>::const_iterator i = _grabActions.begin();
|
||||
i != _grabActions.end();
|
||||
i++) {
|
||||
EntityDynamicPointer action = i.value();
|
||||
if (action->getType() == typeToGet && action->isActive()) {
|
||||
result += action;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -2653,20 +2693,6 @@ void EntityItem::setDescription(const QString& value) {
|
|||
});
|
||||
}
|
||||
|
||||
float EntityItem::getLocalRenderAlpha() const {
|
||||
float result;
|
||||
withReadLock([&] {
|
||||
result = _localRenderAlpha;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void EntityItem::setLocalRenderAlpha(float localRenderAlpha) {
|
||||
withWriteLock([&] {
|
||||
_localRenderAlpha = localRenderAlpha;
|
||||
});
|
||||
}
|
||||
|
||||
glm::vec3 EntityItem::getGravity() const {
|
||||
glm::vec3 result;
|
||||
withReadLock([&] {
|
||||
|
@ -3282,4 +3308,67 @@ void EntityItem::prepareForSimulationOwnershipBid(EntityItemProperties& properti
|
|||
|
||||
bool EntityItem::isWearable() const {
|
||||
return isVisible() && (getParentID() == DependencyManager::get<NodeList>()->getSessionUUID() || getParentID() == AVATAR_SELF_ID);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::addGrab(GrabPointer grab) {
|
||||
enableNoBootstrap();
|
||||
SpatiallyNestable::addGrab(grab);
|
||||
|
||||
if (getDynamic() && getParentID().isNull()) {
|
||||
EntityTreePointer entityTree = getTree();
|
||||
assert(entityTree);
|
||||
EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||
assert(simulation);
|
||||
|
||||
auto actionFactory = DependencyManager::get<EntityDynamicFactoryInterface>();
|
||||
QUuid actionID = QUuid::createUuid();
|
||||
|
||||
EntityDynamicType dynamicType;
|
||||
QVariantMap arguments;
|
||||
int grabParentJointIndex =grab->getParentJointIndex();
|
||||
if (grabParentJointIndex == FARGRAB_RIGHTHAND_INDEX || grabParentJointIndex == FARGRAB_LEFTHAND_INDEX) {
|
||||
// add a far-grab action
|
||||
dynamicType = DYNAMIC_TYPE_FAR_GRAB;
|
||||
arguments["otherID"] = grab->getOwnerID();
|
||||
arguments["otherJointIndex"] = grabParentJointIndex;
|
||||
arguments["targetPosition"] = vec3ToQMap(grab->getPositionalOffset());
|
||||
arguments["targetRotation"] = quatToQMap(grab->getRotationalOffset());
|
||||
arguments["linearTimeScale"] = 0.05;
|
||||
arguments["angularTimeScale"] = 0.05;
|
||||
} else {
|
||||
// add a near-grab action
|
||||
dynamicType = DYNAMIC_TYPE_HOLD;
|
||||
arguments["holderID"] = grab->getOwnerID();
|
||||
arguments["hand"] = grab->getHand();
|
||||
arguments["timeScale"] = 0.05;
|
||||
arguments["relativePosition"] = vec3ToQMap(grab->getPositionalOffset());
|
||||
arguments["relativeRotation"] = quatToQMap(grab->getRotationalOffset());
|
||||
arguments["kinematic"] = _grabProperties.getGrabKinematic();
|
||||
arguments["kinematicSetVelocity"] = true;
|
||||
arguments["ignoreIK"] = _grabProperties.getGrabFollowsController();
|
||||
}
|
||||
EntityDynamicPointer action = actionFactory->factory(dynamicType, actionID, getThisPointer(), arguments);
|
||||
grab->setActionID(actionID);
|
||||
_grabActions[actionID] = action;
|
||||
simulation->addDynamic(action);
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::removeGrab(GrabPointer grab) {
|
||||
SpatiallyNestable::removeGrab(grab);
|
||||
|
||||
QUuid actionID = grab->getActionID();
|
||||
if (!actionID.isNull()) {
|
||||
EntityDynamicPointer action = _grabActions.value(actionID);
|
||||
if (action) {
|
||||
_grabActions.remove(actionID);
|
||||
EntityTreePointer entityTree = getTree();
|
||||
EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||
if (simulation) {
|
||||
action->removeFromSimulation(simulation);
|
||||
action->removeFromOwner();
|
||||
}
|
||||
}
|
||||
}
|
||||
disableNoBootstrap();
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ typedef std::shared_ptr<EntityDynamicInterface> EntityDynamicPointer;
|
|||
typedef std::shared_ptr<EntityTreeElement> EntityTreeElementPointer;
|
||||
using EntityTreeElementExtraEncodeDataPointer = std::shared_ptr<EntityTreeElementExtraEncodeData>;
|
||||
|
||||
|
||||
#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0;
|
||||
#define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() override { };
|
||||
|
||||
|
@ -207,9 +206,6 @@ public:
|
|||
glm::vec3 getUnscaledDimensions() const;
|
||||
virtual void setUnscaledDimensions(const glm::vec3& value);
|
||||
|
||||
float getLocalRenderAlpha() const;
|
||||
void setLocalRenderAlpha(float localRenderAlpha);
|
||||
|
||||
void setDensity(float density);
|
||||
float computeMass() const;
|
||||
void setMass(float mass);
|
||||
|
@ -554,6 +550,9 @@ public:
|
|||
|
||||
void prepareForSimulationOwnershipBid(EntityItemProperties& properties, uint64_t now, uint8_t priority);
|
||||
|
||||
virtual void addGrab(GrabPointer grab) override;
|
||||
virtual void removeGrab(GrabPointer grab) override;
|
||||
|
||||
signals:
|
||||
void requestRenderUpdate();
|
||||
void spaceUpdate(std::pair<int32_t, glm::vec4> data);
|
||||
|
@ -592,7 +591,6 @@ protected:
|
|||
mutable bool _recalcMinAACube { true };
|
||||
mutable bool _recalcMaxAACube { true };
|
||||
|
||||
float _localRenderAlpha { ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA };
|
||||
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
|
||||
// rather than in all of the derived classes. If we ever collapse these classes to one we could do it a
|
||||
|
@ -668,6 +666,9 @@ protected:
|
|||
bool _simulated { false }; // set by EntitySimulation
|
||||
bool _visuallyReady { true };
|
||||
|
||||
void enableNoBootstrap();
|
||||
void disableNoBootstrap();
|
||||
|
||||
bool addActionInternal(EntitySimulationPointer simulation, EntityDynamicPointer action);
|
||||
bool removeActionInternal(const QUuid& actionID, EntitySimulationPointer simulation = nullptr);
|
||||
void deserializeActionsInternal();
|
||||
|
@ -734,6 +735,8 @@ protected:
|
|||
|
||||
GrabPropertyGroup _grabProperties;
|
||||
|
||||
QHash<QUuid, EntityDynamicPointer> _grabActions;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, graphics::MultiMaterial> _materials;
|
||||
std::mutex _materialsLock;
|
||||
|
|
|
@ -141,141 +141,58 @@ public:
|
|||
// type _foo { value };
|
||||
// bool _fooChanged { false };
|
||||
|
||||
// Core Properties
|
||||
DEFINE_PROPERTY_REF(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner, SimulationOwner());
|
||||
DEFINE_PROPERTY(PROP_VISIBLE, Visible, visible, bool, ENTITY_ITEM_DEFAULT_VISIBLE);
|
||||
DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW);
|
||||
DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString, ENTITY_ITEM_DEFAULT_NAME);
|
||||
DEFINE_PROPERTY(PROP_LOCKED, Locked, locked, bool, ENTITY_ITEM_DEFAULT_LOCKED);
|
||||
DEFINE_PROPERTY_REF(PROP_USER_DATA, UserData, userData, QString, ENTITY_ITEM_DEFAULT_USER_DATA);
|
||||
DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_DESCRIPTION, Description, description, QString, "");
|
||||
DEFINE_PROPERTY_REF_WITH_SETTER(PROP_POSITION, Position, position, glm::vec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_DIMENSIONS, Dimensions, dimensions, glm::vec3, ENTITY_ITEM_DEFAULT_DIMENSIONS);
|
||||
DEFINE_PROPERTY_REF(PROP_ROTATION, Rotation, rotation, glm::quat, ENTITY_ITEM_DEFAULT_ROTATION);
|
||||
DEFINE_PROPERTY(PROP_DENSITY, Density, density, float, ENTITY_ITEM_DEFAULT_DENSITY);
|
||||
DEFINE_PROPERTY_REF(PROP_VELOCITY, Velocity, velocity, glm::vec3, ENTITY_ITEM_DEFAULT_VELOCITY);
|
||||
DEFINE_PROPERTY_REF(PROP_GRAVITY, Gravity, gravity, glm::vec3, ENTITY_ITEM_DEFAULT_GRAVITY);
|
||||
DEFINE_PROPERTY_REF(PROP_ACCELERATION, Acceleration, acceleration, glm::vec3, ENTITY_ITEM_DEFAULT_ACCELERATION);
|
||||
DEFINE_PROPERTY(PROP_DAMPING, Damping, damping, float, ENTITY_ITEM_DEFAULT_DAMPING);
|
||||
DEFINE_PROPERTY(PROP_RESTITUTION, Restitution, restitution, float, ENTITY_ITEM_DEFAULT_RESTITUTION);
|
||||
DEFINE_PROPERTY(PROP_FRICTION, Friction, friction, float, ENTITY_ITEM_DEFAULT_FRICTION);
|
||||
DEFINE_PROPERTY(PROP_LIFETIME, Lifetime, lifetime, float, ENTITY_ITEM_DEFAULT_LIFETIME);
|
||||
DEFINE_PROPERTY(PROP_CREATED, Created, created, quint64, UNKNOWN_CREATED_TIME);
|
||||
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString, ENTITY_ITEM_DEFAULT_SCRIPT);
|
||||
DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP);
|
||||
DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, u8vec3Color, particle::DEFAULT_COLOR);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, u8vec3Color, particle::DEFAULT_COLOR_SPREAD);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, glm::vec3, particle::DEFAULT_COLOR_UNINITIALIZED);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_FINISH, ColorFinish, colorFinish, glm::vec3, particle::DEFAULT_COLOR_UNINITIALIZED);
|
||||
DEFINE_PROPERTY(PROP_ALPHA, Alpha, alpha, float, particle::DEFAULT_ALPHA);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float, particle::DEFAULT_ALPHA_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_START, AlphaStart, alphaStart, float, particle::DEFAULT_ALPHA_START);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float, particle::DEFAULT_ALPHA_FINISH);
|
||||
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3, ENTITY_ITEM_DEFAULT_REGISTRATION_POINT);
|
||||
DEFINE_PROPERTY_REF(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY);
|
||||
DEFINE_PROPERTY(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING);
|
||||
DEFINE_PROPERTY(PROP_COLLISIONLESS, Collisionless, collisionless, bool, ENTITY_ITEM_DEFAULT_COLLISIONLESS);
|
||||
DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint16_t, ENTITY_COLLISION_MASK_DEFAULT);
|
||||
DEFINE_PROPERTY(PROP_DYNAMIC, Dynamic, dynamic, bool, ENTITY_ITEM_DEFAULT_DYNAMIC);
|
||||
DEFINE_PROPERTY(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool, LightEntityItem::DEFAULT_IS_SPOTLIGHT);
|
||||
DEFINE_PROPERTY(PROP_INTENSITY, Intensity, intensity, float, LightEntityItem::DEFAULT_INTENSITY);
|
||||
DEFINE_PROPERTY(PROP_FALLOFF_RADIUS, FalloffRadius, falloffRadius, float, LightEntityItem::DEFAULT_FALLOFF_RADIUS);
|
||||
DEFINE_PROPERTY(PROP_EXPONENT, Exponent, exponent, float, LightEntityItem::DEFAULT_EXPONENT);
|
||||
DEFINE_PROPERTY(PROP_CUTOFF, Cutoff, cutoff, float, LightEntityItem::DEFAULT_CUTOFF);
|
||||
DEFINE_PROPERTY(PROP_LOCKED, Locked, locked, bool, ENTITY_ITEM_DEFAULT_LOCKED);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_USER_DATA, UserData, userData, QString, ENTITY_ITEM_DEFAULT_USER_DATA);
|
||||
DEFINE_PROPERTY_REF(PROP_SIMULATION_OWNER, SimulationOwner, simulationOwner, SimulationOwner, SimulationOwner());
|
||||
DEFINE_PROPERTY_REF(PROP_TEXT, Text, text, QString, TextEntityItem::DEFAULT_TEXT);
|
||||
DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float, TextEntityItem::DEFAULT_LINE_HEIGHT);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, u8vec3Color, TextEntityItem::DEFAULT_TEXT_COLOR);
|
||||
DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, u8vec3Color, TextEntityItem::DEFAULT_BACKGROUND_COLOR);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType, SHAPE_TYPE_NONE);
|
||||
DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32, particle::DEFAULT_MAX_PARTICLES);
|
||||
DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float, particle::DEFAULT_LIFESPAN);
|
||||
DEFINE_PROPERTY(PROP_EMITTING_PARTICLES, IsEmitting, isEmitting, bool, true);
|
||||
DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float, particle::DEFAULT_EMIT_RATE);
|
||||
DEFINE_PROPERTY(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, float, particle::DEFAULT_EMIT_SPEED);
|
||||
DEFINE_PROPERTY(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, float, particle::DEFAULT_SPEED_SPREAD);
|
||||
DEFINE_PROPERTY_REF(PROP_EMIT_ORIENTATION, EmitOrientation, emitOrientation, glm::quat, particle::DEFAULT_EMIT_ORIENTATION);
|
||||
DEFINE_PROPERTY_REF(PROP_EMIT_DIMENSIONS, EmitDimensions, emitDimensions, glm::vec3, particle::DEFAULT_EMIT_DIMENSIONS);
|
||||
DEFINE_PROPERTY(PROP_EMIT_RADIUS_START, EmitRadiusStart, emitRadiusStart, float, particle::DEFAULT_EMIT_RADIUS_START);
|
||||
DEFINE_PROPERTY(PROP_POLAR_START, PolarStart, polarStart, float, particle::DEFAULT_POLAR_START);
|
||||
DEFINE_PROPERTY(PROP_POLAR_FINISH, PolarFinish, polarFinish, float, particle::DEFAULT_POLAR_FINISH);
|
||||
DEFINE_PROPERTY(PROP_AZIMUTH_START, AzimuthStart, azimuthStart, float, particle::DEFAULT_AZIMUTH_START);
|
||||
DEFINE_PROPERTY(PROP_AZIMUTH_FINISH, AzimuthFinish, azimuthFinish, float, particle::DEFAULT_AZIMUTH_FINISH);
|
||||
DEFINE_PROPERTY_REF(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3, particle::DEFAULT_EMIT_ACCELERATION);
|
||||
DEFINE_PROPERTY_REF(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3, particle::DEFAULT_ACCELERATION_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float, particle::DEFAULT_PARTICLE_RADIUS);
|
||||
DEFINE_PROPERTY(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float, particle::DEFAULT_RADIUS_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_RADIUS_START, RadiusStart, radiusStart, float, particle::DEFAULT_RADIUS_START);
|
||||
DEFINE_PROPERTY(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float, particle::DEFAULT_RADIUS_FINISH);
|
||||
DEFINE_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool, particle::DEFAULT_EMITTER_SHOULD_TRAIL);
|
||||
DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup);
|
||||
DEFINE_PROPERTY_GROUP(AmbientLight, ambientLight, AmbientLightPropertyGroup);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray, PolyVoxEntityItem::DEFAULT_VOXEL_DATA);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t, PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE);
|
||||
DEFINE_PROPERTY_REF(PROP_NAME, Name, name, QString, ENTITY_ITEM_DEFAULT_NAME);
|
||||
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_KEY_LIGHT_MODE, KeyLightMode, keyLightMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_AMBIENT_LIGHT_MODE, AmbientLightMode, ambientLightMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_HAZE_MODE, HazeMode, hazeMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
|
||||
DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup);
|
||||
DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup);
|
||||
DEFINE_PROPERTY_GROUP(Bloom, bloom, BloomPropertyGroup);
|
||||
DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup);
|
||||
DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString, "");
|
||||
DEFINE_PROPERTY(PROP_LINE_WIDTH, LineWidth, lineWidth, float, LineEntityItem::DEFAULT_LINE_WIDTH);
|
||||
DEFINE_PROPERTY_REF(LINE_POINTS, LinePoints, linePoints, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_DESCRIPTION, Description, description, QString, "");
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE);
|
||||
DEFINE_PROPERTY_REF(PROP_ACTION_DATA, ActionData, actionData, QByteArray, QByteArray());
|
||||
DEFINE_PROPERTY(PROP_NORMALS, Normals, normals, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector<float>, QVector<float>());
|
||||
DEFINE_PROPERTY(PROP_IS_UV_MODE_STRETCH, IsUVModeStretch, isUVModeStretch, bool, true);
|
||||
DEFINE_PROPERTY_REF(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_X_N_NEIGHBOR_ID, XNNeighborID, xNNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Y_N_NEIGHBOR_ID, YNNeighborID, yNNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Z_N_NEIGHBOR_ID, ZNNeighborID, zNNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY(PROP_CREATED, Created, created, quint64, UNKNOWN_CREATED_TIME);
|
||||
DEFINE_PROPERTY_REF(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid, ENTITY_ITEM_DEFAULT_LAST_EDITED_BY);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_ENTITY_HOST_TYPE, EntityHostType, entityHostType, entity::HostType, entity::HostType::DOMAIN);
|
||||
DEFINE_PROPERTY_REF(PROP_OWNING_AVATAR_ID, OwningAvatarID, owningAvatarID, QUuid, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_ID, ParentID, parentID, QUuid, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, quint16, -1);
|
||||
DEFINE_PROPERTY_REF(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube, AACube());
|
||||
DEFINE_PROPERTY_REF(PROP_SHAPE, Shape, shape, QString, "Sphere");
|
||||
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_URL, MaterialURL, materialURL, QString, "");
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_MATERIAL_MAPPING_MODE, MaterialMappingMode, materialMappingMode, MaterialMappingMode, UV);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, quint16, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_MATERIAL_NAME, ParentMaterialName, parentMaterialName, QString, "0");
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glm::vec2, glm::vec2(0.0f));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glm::vec2, glm::vec2(1.0f));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_DATA, MaterialData, materialData, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_REPEAT, MaterialRepeat, materialRepeat, bool, true);
|
||||
|
||||
DEFINE_PROPERTY(PROP_CAN_CAST_SHADOW, CanCastShadow, canCastShadow, bool, ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW);
|
||||
DEFINE_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool, ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA);
|
||||
DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup);
|
||||
|
||||
DEFINE_PROPERTY(PROP_PARTICLE_SPIN, ParticleSpin, particleSpin, float, particle::DEFAULT_PARTICLE_SPIN);
|
||||
DEFINE_PROPERTY(PROP_SPIN_SPREAD, SpinSpread, spinSpread, float, particle::DEFAULT_SPIN_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_SPIN_START, SpinStart, spinStart, float, particle::DEFAULT_SPIN_START);
|
||||
DEFINE_PROPERTY(PROP_SPIN_FINISH, SpinFinish, spinFinish, float, particle::DEFAULT_SPIN_FINISH);
|
||||
DEFINE_PROPERTY(PROP_PARTICLE_ROTATE_WITH_ENTITY, RotateWithEntity, rotateWithEntity, bool, particle::DEFAULT_ROTATE_WITH_ENTITY);
|
||||
// Physics
|
||||
DEFINE_PROPERTY(PROP_DENSITY, Density, density, float, ENTITY_ITEM_DEFAULT_DENSITY);
|
||||
DEFINE_PROPERTY_REF(PROP_VELOCITY, Velocity, velocity, glm::vec3, ENTITY_ITEM_DEFAULT_VELOCITY);
|
||||
DEFINE_PROPERTY_REF(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY);
|
||||
DEFINE_PROPERTY_REF(PROP_GRAVITY, Gravity, gravity, glm::vec3, ENTITY_ITEM_DEFAULT_GRAVITY);
|
||||
DEFINE_PROPERTY_REF(PROP_ACCELERATION, Acceleration, acceleration, glm::vec3, ENTITY_ITEM_DEFAULT_ACCELERATION);
|
||||
DEFINE_PROPERTY(PROP_DAMPING, Damping, damping, float, ENTITY_ITEM_DEFAULT_DAMPING);
|
||||
DEFINE_PROPERTY(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING);
|
||||
DEFINE_PROPERTY(PROP_RESTITUTION, Restitution, restitution, float, ENTITY_ITEM_DEFAULT_RESTITUTION);
|
||||
DEFINE_PROPERTY(PROP_FRICTION, Friction, friction, float, ENTITY_ITEM_DEFAULT_FRICTION);
|
||||
DEFINE_PROPERTY(PROP_LIFETIME, Lifetime, lifetime, float, ENTITY_ITEM_DEFAULT_LIFETIME);
|
||||
DEFINE_PROPERTY(PROP_COLLISIONLESS, Collisionless, collisionless, bool, ENTITY_ITEM_DEFAULT_COLLISIONLESS);
|
||||
DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint16_t, ENTITY_COLLISION_MASK_DEFAULT);
|
||||
DEFINE_PROPERTY(PROP_DYNAMIC, Dynamic, dynamic, bool, ENTITY_ITEM_DEFAULT_DYNAMIC);
|
||||
DEFINE_PROPERTY_REF(PROP_COLLISION_SOUND_URL, CollisionSoundURL, collisionSoundURL, QString, ENTITY_ITEM_DEFAULT_COLLISION_SOUND_URL);
|
||||
DEFINE_PROPERTY_REF(PROP_ACTION_DATA, ActionData, actionData, QByteArray, QByteArray());
|
||||
|
||||
DEFINE_PROPERTY_REF(PROP_IMAGE_URL, ImageURL, imageURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_EMISSIVE, Emissive, emissive, bool, false);
|
||||
DEFINE_PROPERTY_REF(PROP_KEEP_ASPECT_RATIO, KeepAspectRatio, keepAspectRatio, bool, true);
|
||||
DEFINE_PROPERTY_REF(PROP_SUB_IMAGE, SubImage, subImage, QRect, QRect());
|
||||
// Cloning
|
||||
DEFINE_PROPERTY(PROP_CLONEABLE, Cloneable, cloneable, bool, ENTITY_ITEM_DEFAULT_CLONEABLE);
|
||||
DEFINE_PROPERTY(PROP_CLONE_LIFETIME, CloneLifetime, cloneLifetime, float, ENTITY_ITEM_DEFAULT_CLONE_LIFETIME);
|
||||
DEFINE_PROPERTY(PROP_CLONE_LIMIT, CloneLimit, cloneLimit, float, ENTITY_ITEM_DEFAULT_CLONE_LIMIT);
|
||||
DEFINE_PROPERTY(PROP_CLONE_DYNAMIC, CloneDynamic, cloneDynamic, bool, ENTITY_ITEM_DEFAULT_CLONE_DYNAMIC);
|
||||
DEFINE_PROPERTY(PROP_CLONE_AVATAR_ENTITY, CloneAvatarEntity, cloneAvatarEntity, bool, ENTITY_ITEM_DEFAULT_CLONE_AVATAR_ENTITY);
|
||||
DEFINE_PROPERTY_REF(PROP_CLONE_ORIGIN_ID, CloneOriginID, cloneOriginID, QUuid, ENTITY_ITEM_DEFAULT_CLONE_ORIGIN_ID);
|
||||
|
||||
DEFINE_PROPERTY_REF(PROP_GRID_FOLLOW_CAMERA, FollowCamera, followCamera, bool, true);
|
||||
DEFINE_PROPERTY(PROP_MAJOR_GRID_EVERY, MajorGridEvery, majorGridEvery, uint32_t, GridEntityItem::DEFAULT_MAJOR_GRID_EVERY);
|
||||
DEFINE_PROPERTY(PROP_MINOR_GRID_EVERY, MinorGridEvery, minorGridEvery, float, GridEntityItem::DEFAULT_MINOR_GRID_EVERY);
|
||||
// Scripts
|
||||
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString, ENTITY_ITEM_DEFAULT_SCRIPT);
|
||||
DEFINE_PROPERTY(PROP_SCRIPT_TIMESTAMP, ScriptTimestamp, scriptTimestamp, quint64, ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP);
|
||||
DEFINE_PROPERTY_REF(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString, ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS);
|
||||
|
||||
// Certifiable Properties - related to Proof of Purchase certificates
|
||||
DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME);
|
||||
|
@ -297,33 +214,139 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_DIMENSIONS, LocalDimensions, localDimensions, glm::vec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
|
||||
// Common
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_SHAPE_TYPE, ShapeType, shapeType, ShapeType, SHAPE_TYPE_NONE);
|
||||
DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, u8vec3Color, particle::DEFAULT_COLOR);
|
||||
DEFINE_PROPERTY(PROP_ALPHA, Alpha, alpha, float, particle::DEFAULT_ALPHA);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXTURES, Textures, textures, QString, "");
|
||||
|
||||
// Particles
|
||||
DEFINE_PROPERTY(PROP_MAX_PARTICLES, MaxParticles, maxParticles, quint32, particle::DEFAULT_MAX_PARTICLES);
|
||||
DEFINE_PROPERTY(PROP_LIFESPAN, Lifespan, lifespan, float, particle::DEFAULT_LIFESPAN);
|
||||
DEFINE_PROPERTY(PROP_EMITTING_PARTICLES, IsEmitting, isEmitting, bool, true);
|
||||
DEFINE_PROPERTY(PROP_EMIT_RATE, EmitRate, emitRate, float, particle::DEFAULT_EMIT_RATE);
|
||||
DEFINE_PROPERTY(PROP_EMIT_SPEED, EmitSpeed, emitSpeed, float, particle::DEFAULT_EMIT_SPEED);
|
||||
DEFINE_PROPERTY(PROP_SPEED_SPREAD, SpeedSpread, speedSpread, float, particle::DEFAULT_SPEED_SPREAD);
|
||||
DEFINE_PROPERTY_REF(PROP_EMIT_ORIENTATION, EmitOrientation, emitOrientation, glm::quat, particle::DEFAULT_EMIT_ORIENTATION);
|
||||
DEFINE_PROPERTY_REF(PROP_EMIT_DIMENSIONS, EmitDimensions, emitDimensions, glm::vec3, particle::DEFAULT_EMIT_DIMENSIONS);
|
||||
DEFINE_PROPERTY(PROP_EMIT_RADIUS_START, EmitRadiusStart, emitRadiusStart, float, particle::DEFAULT_EMIT_RADIUS_START);
|
||||
DEFINE_PROPERTY(PROP_POLAR_START, PolarStart, polarStart, float, particle::DEFAULT_POLAR_START);
|
||||
DEFINE_PROPERTY(PROP_POLAR_FINISH, PolarFinish, polarFinish, float, particle::DEFAULT_POLAR_FINISH);
|
||||
DEFINE_PROPERTY(PROP_AZIMUTH_START, AzimuthStart, azimuthStart, float, particle::DEFAULT_AZIMUTH_START);
|
||||
DEFINE_PROPERTY(PROP_AZIMUTH_FINISH, AzimuthFinish, azimuthFinish, float, particle::DEFAULT_AZIMUTH_FINISH);
|
||||
DEFINE_PROPERTY_REF(PROP_EMIT_ACCELERATION, EmitAcceleration, emitAcceleration, glm::vec3, particle::DEFAULT_EMIT_ACCELERATION);
|
||||
DEFINE_PROPERTY_REF(PROP_ACCELERATION_SPREAD, AccelerationSpread, accelerationSpread, glm::vec3, particle::DEFAULT_ACCELERATION_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float, particle::DEFAULT_PARTICLE_RADIUS);
|
||||
DEFINE_PROPERTY(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float, particle::DEFAULT_RADIUS_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_RADIUS_START, RadiusStart, radiusStart, float, particle::DEFAULT_RADIUS_START);
|
||||
DEFINE_PROPERTY(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float, particle::DEFAULT_RADIUS_FINISH);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_SPREAD, ColorSpread, colorSpread, u8vec3Color, particle::DEFAULT_COLOR_SPREAD);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_START, ColorStart, colorStart, glm::vec3, particle::DEFAULT_COLOR_UNINITIALIZED);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR_FINISH, ColorFinish, colorFinish, glm::vec3, particle::DEFAULT_COLOR_UNINITIALIZED);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float, particle::DEFAULT_ALPHA_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_START, AlphaStart, alphaStart, float, particle::DEFAULT_ALPHA_START);
|
||||
DEFINE_PROPERTY(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float, particle::DEFAULT_ALPHA_FINISH);
|
||||
DEFINE_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, EmitterShouldTrail, emitterShouldTrail, bool, particle::DEFAULT_EMITTER_SHOULD_TRAIL);
|
||||
DEFINE_PROPERTY(PROP_PARTICLE_SPIN, ParticleSpin, particleSpin, float, particle::DEFAULT_PARTICLE_SPIN);
|
||||
DEFINE_PROPERTY(PROP_SPIN_SPREAD, SpinSpread, spinSpread, float, particle::DEFAULT_SPIN_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_SPIN_START, SpinStart, spinStart, float, particle::DEFAULT_SPIN_START);
|
||||
DEFINE_PROPERTY(PROP_SPIN_FINISH, SpinFinish, spinFinish, float, particle::DEFAULT_SPIN_FINISH);
|
||||
DEFINE_PROPERTY(PROP_PARTICLE_ROTATE_WITH_ENTITY, RotateWithEntity, rotateWithEntity, bool, particle::DEFAULT_ROTATE_WITH_ENTITY);
|
||||
|
||||
// Model
|
||||
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector<bool>, QVector<bool>());
|
||||
DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector<glm::quat>, QVector<glm::quat>());
|
||||
DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector<bool>, QVector<bool>());
|
||||
DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool, ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS);
|
||||
DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup);
|
||||
|
||||
// Light
|
||||
DEFINE_PROPERTY(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool, LightEntityItem::DEFAULT_IS_SPOTLIGHT);
|
||||
DEFINE_PROPERTY(PROP_INTENSITY, Intensity, intensity, float, LightEntityItem::DEFAULT_INTENSITY);
|
||||
DEFINE_PROPERTY(PROP_EXPONENT, Exponent, exponent, float, LightEntityItem::DEFAULT_EXPONENT);
|
||||
DEFINE_PROPERTY(PROP_CUTOFF, Cutoff, cutoff, float, LightEntityItem::DEFAULT_CUTOFF);
|
||||
DEFINE_PROPERTY(PROP_FALLOFF_RADIUS, FalloffRadius, falloffRadius, float, LightEntityItem::DEFAULT_FALLOFF_RADIUS);
|
||||
|
||||
// Text
|
||||
DEFINE_PROPERTY_REF(PROP_TEXT, Text, text, QString, TextEntityItem::DEFAULT_TEXT);
|
||||
DEFINE_PROPERTY(PROP_LINE_HEIGHT, LineHeight, lineHeight, float, TextEntityItem::DEFAULT_LINE_HEIGHT);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXT_COLOR, TextColor, textColor, u8vec3Color, TextEntityItem::DEFAULT_TEXT_COLOR);
|
||||
DEFINE_PROPERTY_REF(PROP_TEXT_ALPHA, TextAlpha, textAlpha, float, TextEntityItem::DEFAULT_TEXT_ALPHA);
|
||||
DEFINE_PROPERTY_REF(PROP_BACKGROUND_COLOR, BackgroundColor, backgroundColor, u8vec3Color, TextEntityItem::DEFAULT_BACKGROUND_COLOR);
|
||||
DEFINE_PROPERTY_REF(PROP_BACKGROUND_ALPHA, BackgroundAlpha, backgroundAlpha, float, TextEntityItem::DEFAULT_TEXT_ALPHA);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_BILLBOARD_MODE, BillboardMode, billboardMode, BillboardMode, BillboardMode::NONE);
|
||||
DEFINE_PROPERTY_REF(PROP_LEFT_MARGIN, LeftMargin, leftMargin, float, TextEntityItem::DEFAULT_MARGIN);
|
||||
DEFINE_PROPERTY_REF(PROP_RIGHT_MARGIN, RightMargin, rightMargin, float, TextEntityItem::DEFAULT_MARGIN);
|
||||
DEFINE_PROPERTY_REF(PROP_TOP_MARGIN, TopMargin, topMargin, float, TextEntityItem::DEFAULT_MARGIN);
|
||||
DEFINE_PROPERTY_REF(PROP_BOTTOM_MARGIN, BottomMargin, bottomMargin, float, TextEntityItem::DEFAULT_MARGIN);
|
||||
|
||||
// Zone
|
||||
DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup);
|
||||
DEFINE_PROPERTY_GROUP(AmbientLight, ambientLight, AmbientLightPropertyGroup);
|
||||
DEFINE_PROPERTY_GROUP(Skybox, skybox, SkyboxPropertyGroup);
|
||||
DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup);
|
||||
DEFINE_PROPERTY_GROUP(Bloom, bloom, BloomPropertyGroup);
|
||||
DEFINE_PROPERTY(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool, ZoneEntityItem::DEFAULT_FLYING_ALLOWED);
|
||||
DEFINE_PROPERTY(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool, ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED);
|
||||
DEFINE_PROPERTY(PROP_FILTER_URL, FilterURL, filterURL, QString, ZoneEntityItem::DEFAULT_FILTER_URL);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_KEY_LIGHT_MODE, KeyLightMode, keyLightMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_SKYBOX_MODE, SkyboxMode, skyboxMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_AMBIENT_LIGHT_MODE, AmbientLightMode, ambientLightMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_HAZE_MODE, HazeMode, hazeMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_BLOOM_MODE, BloomMode, bloomMode, uint32_t, (uint32_t)COMPONENT_MODE_INHERIT);
|
||||
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_ENTITY_HOST_TYPE, EntityHostType, entityHostType, entity::HostType, entity::HostType::DOMAIN);
|
||||
DEFINE_PROPERTY_REF(PROP_OWNING_AVATAR_ID, OwningAvatarID, owningAvatarID, QUuid, UNKNOWN_ENTITY_ID);
|
||||
// Polyvox
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_DATA, VoxelData, voxelData, QByteArray, PolyVoxEntityItem::DEFAULT_VOXEL_DATA);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t, PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE);
|
||||
DEFINE_PROPERTY_REF(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_X_N_NEIGHBOR_ID, XNNeighborID, xNNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Y_N_NEIGHBOR_ID, YNNeighborID, yNNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Z_N_NEIGHBOR_ID, ZNNeighborID, zNNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID, UNKNOWN_ENTITY_ID);
|
||||
|
||||
// Web
|
||||
DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_DPI, DPI, dpi, uint16_t, ENTITY_ITEM_DEFAULT_DPI);
|
||||
|
||||
DEFINE_PROPERTY_REF(PROP_LAST_EDITED_BY, LastEditedBy, lastEditedBy, QUuid, ENTITY_ITEM_DEFAULT_LAST_EDITED_BY);
|
||||
// Polyline
|
||||
DEFINE_PROPERTY_REF(PROP_LINE_POINTS, LinePoints, linePoints, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector<float>, QVector<float>());
|
||||
DEFINE_PROPERTY(PROP_STROKE_NORMALS, Normals, normals, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_IS_UV_MODE_STRETCH, IsUVModeStretch, isUVModeStretch, bool, true);
|
||||
|
||||
DEFINE_PROPERTY_REF(PROP_SERVER_SCRIPTS, ServerScripts, serverScripts, QString, ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS);
|
||||
DEFINE_PROPERTY(PROP_RELAY_PARENT_JOINTS, RelayParentJoints, relayParentJoints, bool, ENTITY_ITEM_DEFAULT_RELAY_PARENT_JOINTS);
|
||||
// Shape
|
||||
DEFINE_PROPERTY_REF(PROP_SHAPE, Shape, shape, QString, "Sphere");
|
||||
|
||||
DEFINE_PROPERTY(PROP_CLONEABLE, Cloneable, cloneable, bool, ENTITY_ITEM_DEFAULT_CLONEABLE);
|
||||
DEFINE_PROPERTY(PROP_CLONE_LIFETIME, CloneLifetime, cloneLifetime, float, ENTITY_ITEM_DEFAULT_CLONE_LIFETIME);
|
||||
DEFINE_PROPERTY(PROP_CLONE_LIMIT, CloneLimit, cloneLimit, float, ENTITY_ITEM_DEFAULT_CLONE_LIMIT);
|
||||
DEFINE_PROPERTY(PROP_CLONE_DYNAMIC, CloneDynamic, cloneDynamic, bool, ENTITY_ITEM_DEFAULT_CLONE_DYNAMIC);
|
||||
DEFINE_PROPERTY(PROP_CLONE_AVATAR_ENTITY, CloneAvatarEntity, cloneAvatarEntity, bool, ENTITY_ITEM_DEFAULT_CLONE_AVATAR_ENTITY);
|
||||
DEFINE_PROPERTY_REF(PROP_CLONE_ORIGIN_ID, CloneOriginID, cloneOriginID, QUuid, ENTITY_ITEM_DEFAULT_CLONE_ORIGIN_ID);
|
||||
// Material
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_URL, MaterialURL, materialURL, QString, "");
|
||||
DEFINE_PROPERTY_REF_ENUM(PROP_MATERIAL_MAPPING_MODE, MaterialMappingMode, materialMappingMode, MaterialMappingMode, UV);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, quint16, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_MATERIAL_NAME, ParentMaterialName, parentMaterialName, QString, "0");
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glm::vec2, glm::vec2(0.0f));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glm::vec2, glm::vec2(1.0f));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_DATA, MaterialData, materialData, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_REPEAT, MaterialRepeat, materialRepeat, bool, true);
|
||||
|
||||
DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup);
|
||||
// Image
|
||||
DEFINE_PROPERTY_REF(PROP_IMAGE_URL, ImageURL, imageURL, QString, "");
|
||||
DEFINE_PROPERTY_REF(PROP_EMISSIVE, Emissive, emissive, bool, false);
|
||||
DEFINE_PROPERTY_REF(PROP_KEEP_ASPECT_RATIO, KeepAspectRatio, keepAspectRatio, bool, true);
|
||||
DEFINE_PROPERTY_REF(PROP_SUB_IMAGE, SubImage, subImage, QRect, QRect());
|
||||
|
||||
// Grid
|
||||
DEFINE_PROPERTY_REF(PROP_GRID_FOLLOW_CAMERA, FollowCamera, followCamera, bool, true);
|
||||
DEFINE_PROPERTY(PROP_MAJOR_GRID_EVERY, MajorGridEvery, majorGridEvery, uint32_t, GridEntityItem::DEFAULT_MAJOR_GRID_EVERY);
|
||||
DEFINE_PROPERTY(PROP_MINOR_GRID_EVERY, MinorGridEvery, minorGridEvery, float, GridEntityItem::DEFAULT_MINOR_GRID_EVERY);
|
||||
|
||||
static QString getComponentModeAsString(uint32_t mode);
|
||||
|
||||
|
@ -339,9 +362,6 @@ public:
|
|||
bool containsPositionChange() const { return _positionChanged; }
|
||||
bool containsDimensionsChange() const { return _dimensionsChanged; }
|
||||
|
||||
float getLocalRenderAlpha() const { return _localRenderAlpha; }
|
||||
void setLocalRenderAlpha(float value) { _localRenderAlpha = value; _localRenderAlphaChanged = true; }
|
||||
|
||||
static OctreeElement::AppendState encodeEntityEditPacket(PacketType command, EntityItemID id, const EntityItemProperties& properties,
|
||||
QByteArray& buffer, EntityPropertyFlags requestedProperties, EntityPropertyFlags& didntFitProperties);
|
||||
|
||||
|
@ -352,8 +372,6 @@ public:
|
|||
static bool decodeEntityEditPacket(const unsigned char* data, int bytesToRead, int& processedBytes,
|
||||
EntityItemID& entityID, EntityItemProperties& properties);
|
||||
|
||||
bool localRenderAlphaChanged() const { return _localRenderAlphaChanged; }
|
||||
|
||||
void clearID() { _id = UNKNOWN_ENTITY_ID; _idSet = false; }
|
||||
void markAllChanged();
|
||||
|
||||
|
@ -374,9 +392,12 @@ public:
|
|||
|
||||
void setQueryAACubeDirty() { _queryAACubeChanged = true; }
|
||||
|
||||
void setLocationDirty() { _positionChanged = true; _rotationChanged = true; }
|
||||
|
||||
void setCreated(QDateTime& v);
|
||||
|
||||
bool hasTransformOrVelocityChanges() const;
|
||||
void clearTransformOrVelocityChanges();
|
||||
bool hasMiscPhysicsChanges() const;
|
||||
|
||||
bool hasSimulationRestrictedChanges() const;
|
||||
|
@ -441,8 +462,6 @@ private:
|
|||
EntityTypes::EntityType _type;
|
||||
void setType(const QString& typeName) { _type = EntityTypes::getEntityTypeFromName(typeName); }
|
||||
|
||||
float _localRenderAlpha;
|
||||
bool _localRenderAlphaChanged;
|
||||
bool _defaultSettings;
|
||||
bool _dimensionsInitialized = true; // Only false if creating an entity locally with no dimensions properties
|
||||
|
||||
|
@ -479,6 +498,8 @@ void EntityPropertyInfoFromScriptValue(const QScriptValue& object, EntityPropert
|
|||
inline void EntityItemProperties::setPosition(const glm::vec3& value)
|
||||
{ _position = glm::clamp(value, (float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE); _positionChanged = true; }
|
||||
|
||||
QDebug& operator<<(QDebug& dbg, const EntityPropertyFlags& f);
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
||||
debug << "EntityItemProperties[" << "\n";
|
||||
|
||||
|
|
|
@ -44,7 +44,6 @@ const QString ENTITY_ITEM_DEFAULT_CERTIFICATE_ID = QString("");
|
|||
const quint32 ENTITY_ITEM_DEFAULT_STATIC_CERTIFICATE_VERSION = 0;
|
||||
|
||||
const float ENTITY_ITEM_DEFAULT_ALPHA = 1.0f;
|
||||
const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f;
|
||||
const bool ENTITY_ITEM_DEFAULT_VISIBLE = true;
|
||||
const bool ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA = true;
|
||||
const bool ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW { true };
|
||||
|
|
|
@ -414,24 +414,28 @@ inline QRect QRect_convertFromScriptValue(const QScriptValue& v, bool& isValid)
|
|||
{ \
|
||||
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P); \
|
||||
_propertyInfos[#n] = propertyInfo; \
|
||||
_enumsToPropertyStrings[P] = #n; \
|
||||
}
|
||||
|
||||
#define ADD_PROPERTY_TO_MAP_WITH_RANGE(P, N, n, T, M, X) \
|
||||
{ \
|
||||
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
|
||||
_propertyInfos[#n] = propertyInfo; \
|
||||
_enumsToPropertyStrings[P] = #n; \
|
||||
}
|
||||
|
||||
#define ADD_GROUP_PROPERTY_TO_MAP(P, G, g, N, n) \
|
||||
{ \
|
||||
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P); \
|
||||
_propertyInfos[#g "." #n] = propertyInfo; \
|
||||
_enumsToPropertyStrings[P] = #g "." #n; \
|
||||
}
|
||||
|
||||
#define ADD_GROUP_PROPERTY_TO_MAP_WITH_RANGE(P, G, g, N, n, M, X) \
|
||||
{ \
|
||||
EntityPropertyInfo propertyInfo = EntityPropertyInfo(P, M, X); \
|
||||
_propertyInfos[#g "." #n] = propertyInfo; \
|
||||
_enumsToPropertyStrings[P] = #g "." #n; \
|
||||
}
|
||||
|
||||
#define DEFINE_CORE(N, n, T, V) \
|
||||
|
|
|
@ -1,208 +0,0 @@
|
|||
|
||||
#include "EntityPropertyFlags.h"
|
||||
|
||||
|
||||
QDebug& operator<<(QDebug& dbg, const EntityPropertyFlags& f) {
|
||||
QString result = "[ ";
|
||||
|
||||
result = f.getHasProperty(PROP_PAGED_PROPERTY) ? result + "pagedProperty " : result;
|
||||
result = f.getHasProperty(PROP_CUSTOM_PROPERTIES_INCLUDED) ? result + "customPropertiesIncluded " : result;
|
||||
result = f.getHasProperty(PROP_VISIBLE) ? result + "visible " : result;
|
||||
result = f.getHasProperty(PROP_CAN_CAST_SHADOW) ? result + "canCastShadow " : result;
|
||||
result = f.getHasProperty(PROP_POSITION) ? result + "position " : result;
|
||||
result = f.getHasProperty(PROP_DIMENSIONS) ? result + "dimensions " : result;
|
||||
result = f.getHasProperty(PROP_ROTATION) ? result + "rotation " : result;
|
||||
result = f.getHasProperty(PROP_DENSITY) ? result + "density " : result;
|
||||
result = f.getHasProperty(PROP_VELOCITY) ? result + "velocity " : result;
|
||||
result = f.getHasProperty(PROP_GRAVITY) ? result + "gravity " : result;
|
||||
result = f.getHasProperty(PROP_DAMPING) ? result + "damping " : result;
|
||||
result = f.getHasProperty(PROP_LIFETIME) ? result + "lifetime " : result;
|
||||
result = f.getHasProperty(PROP_SCRIPT) ? result + "script " : result;
|
||||
result = f.getHasProperty(PROP_COLOR) ? result + "color " : result;
|
||||
result = f.getHasProperty(PROP_MODEL_URL) ? result + "modelUrl " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_URL) ? result + "animationUrl " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_FPS) ? result + "animationFps " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_FRAME_INDEX) ? result + "animationFrameIndex " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_PLAYING) ? result + "animationPlaying " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_ALLOW_TRANSLATION) ? result + "animationAllowTranslation " : result;
|
||||
result = f.getHasProperty(PROP_RELAY_PARENT_JOINTS) ? result + "relayParentJoints " : result;
|
||||
result = f.getHasProperty(PROP_REGISTRATION_POINT) ? result + "registrationPoint " : result;
|
||||
result = f.getHasProperty(PROP_ANGULAR_VELOCITY) ? result + "angularVelocity " : result;
|
||||
result = f.getHasProperty(PROP_ANGULAR_DAMPING) ? result + "angularDamping " : result;
|
||||
result = f.getHasProperty(PROP_COLLISIONLESS) ? result + "collisionless " : result;
|
||||
result = f.getHasProperty(PROP_DYNAMIC) ? result + "dynamic " : result;
|
||||
result = f.getHasProperty(PROP_IS_SPOTLIGHT) ? result + "isSpotlight " : result;
|
||||
result = f.getHasProperty(PROP_DIFFUSE_COLOR) ? result + "diffuseColor " : result;
|
||||
result = f.getHasProperty(PROP_AMBIENT_COLOR_UNUSED) ? result + "ambientColorUnused " : result;
|
||||
result = f.getHasProperty(PROP_SPECULAR_COLOR_UNUSED) ? result + "specularColorUnused " : result;
|
||||
result = f.getHasProperty(PROP_INTENSITY) ? result + "intensity " : result;
|
||||
result = f.getHasProperty(PROP_LINEAR_ATTENUATION_UNUSED) ? result + "linearAttenuationUnused " : result;
|
||||
result = f.getHasProperty(PROP_QUADRATIC_ATTENUATION_UNUSED) ? result + "quadraticAttenuationUnused " : result;
|
||||
result = f.getHasProperty(PROP_EXPONENT) ? result + "exponent " : result;
|
||||
result = f.getHasProperty(PROP_CUTOFF) ? result + "cutoff " : result;
|
||||
result = f.getHasProperty(PROP_LOCKED) ? result + "locked " : result;
|
||||
result = f.getHasProperty(PROP_TEXTURES) ? result + "textures " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_SETTINGS_UNUSED) ? result + "animationSettingsUnused " : result;
|
||||
result = f.getHasProperty(PROP_USER_DATA) ? result + "userData " : result;
|
||||
result = f.getHasProperty(PROP_SHAPE_TYPE) ? result + "shapeType " : result;
|
||||
result = f.getHasProperty(PROP_MAX_PARTICLES) ? result + "maxParticles " : result;
|
||||
result = f.getHasProperty(PROP_LIFESPAN) ? result + "lifespan " : result;
|
||||
result = f.getHasProperty(PROP_EMIT_RATE) ? result + "emitRate " : result;
|
||||
result = f.getHasProperty(PROP_EMIT_SPEED) ? result + "emitSpeed " : result;
|
||||
result = f.getHasProperty(PROP_EMIT_STRENGTH) ? result + "emitStrength " : result;
|
||||
result = f.getHasProperty(PROP_EMIT_ACCELERATION) ? result + "emitAcceleration " : result;
|
||||
result = f.getHasProperty(PROP_PARTICLE_RADIUS) ? result + "particleRadius " : result;
|
||||
result = f.getHasProperty(PROP_COMPOUND_SHAPE_URL) ? result + "compoundShapeUrl " : result;
|
||||
result = f.getHasProperty(PROP_MARKETPLACE_ID) ? result + "marketplaceID " : result;
|
||||
result = f.getHasProperty(PROP_ACCELERATION) ? result + "acceleration " : result;
|
||||
result = f.getHasProperty(PROP_SIMULATION_OWNER) ? result + "simulationOwner " : result;
|
||||
result = f.getHasProperty(PROP_NAME) ? result + "name " : result;
|
||||
result = f.getHasProperty(PROP_COLLISION_SOUND_URL) ? result + "collisionSoundUrl " : result;
|
||||
result = f.getHasProperty(PROP_RESTITUTION) ? result + "restitution " : result;
|
||||
result = f.getHasProperty(PROP_FRICTION) ? result + "friction " : result;
|
||||
result = f.getHasProperty(PROP_VOXEL_VOLUME_SIZE) ? result + "voxelVolumeSize " : result;
|
||||
result = f.getHasProperty(PROP_VOXEL_DATA) ? result + "voxelData " : result;
|
||||
result = f.getHasProperty(PROP_VOXEL_SURFACE_STYLE) ? result + "voxelSurfaceStyle " : result;
|
||||
result = f.getHasProperty(PROP_LINE_WIDTH) ? result + "lineWidth " : result;
|
||||
result = f.getHasProperty(PROP_LINE_POINTS) ? result + "linePoints " : result;
|
||||
result = f.getHasProperty(PROP_HREF) ? result + "href " : result;
|
||||
result = f.getHasProperty(PROP_DESCRIPTION) ? result + "description " : result;
|
||||
result = f.getHasProperty(PROP_BILLBOARD_MODE) ? result + "billboardMode " : result;
|
||||
result = f.getHasProperty(PROP_SCRIPT_TIMESTAMP) ? result + "scriptTimestamp " : result;
|
||||
result = f.getHasProperty(PROP_ACTION_DATA) ? result + "actionData " : result;
|
||||
result = f.getHasProperty(PROP_X_TEXTURE_URL) ? result + "xTextureUrl " : result;
|
||||
result = f.getHasProperty(PROP_Y_TEXTURE_URL) ? result + "yTextureUrl " : result;
|
||||
result = f.getHasProperty(PROP_Z_TEXTURE_URL) ? result + "zTextureUrl " : result;
|
||||
result = f.getHasProperty(PROP_NORMALS) ? result + "normals " : result;
|
||||
result = f.getHasProperty(PROP_STROKE_COLORS) ? result + "strokeColors " : result;
|
||||
result = f.getHasProperty(PROP_STROKE_WIDTHS) ? result + "strokeWidths " : result;
|
||||
result = f.getHasProperty(PROP_IS_UV_MODE_STRETCH) ? result + "isUvModeStretch " : result;
|
||||
result = f.getHasProperty(PROP_SPEED_SPREAD) ? result + "speedSpread " : result;
|
||||
result = f.getHasProperty(PROP_ACCELERATION_SPREAD) ? result + "accelerationSpread " : result;
|
||||
result = f.getHasProperty(PROP_X_N_NEIGHBOR_ID) ? result + "xNNeighborID " : result;
|
||||
result = f.getHasProperty(PROP_Y_N_NEIGHBOR_ID) ? result + "yNNeighborID " : result;
|
||||
result = f.getHasProperty(PROP_Z_N_NEIGHBOR_ID) ? result + "zNNeighborID " : result;
|
||||
result = f.getHasProperty(PROP_X_P_NEIGHBOR_ID) ? result + "xPNeighborID " : result;
|
||||
result = f.getHasProperty(PROP_Y_P_NEIGHBOR_ID) ? result + "yPNeighborID " : result;
|
||||
result = f.getHasProperty(PROP_Z_P_NEIGHBOR_ID) ? result + "zPNeighborID " : result;
|
||||
result = f.getHasProperty(PROP_RADIUS_SPREAD) ? result + "radiusSpread " : result;
|
||||
result = f.getHasProperty(PROP_RADIUS_START) ? result + "radiusStart " : result;
|
||||
result = f.getHasProperty(PROP_RADIUS_FINISH) ? result + "radiusFinish " : result;
|
||||
result = f.getHasProperty(PROP_ALPHA) ? result + "alpha " : result;
|
||||
result = f.getHasProperty(PROP_COLOR_SPREAD) ? result + "colorSpread " : result;
|
||||
result = f.getHasProperty(PROP_COLOR_START) ? result + "colorStart " : result;
|
||||
result = f.getHasProperty(PROP_COLOR_FINISH) ? result + "colorFinish " : result;
|
||||
result = f.getHasProperty(PROP_ALPHA_SPREAD) ? result + "alphaSpread " : result;
|
||||
result = f.getHasProperty(PROP_ALPHA_START) ? result + "alphaStart " : result;
|
||||
result = f.getHasProperty(PROP_ALPHA_FINISH) ? result + "alphaFinish " : result;
|
||||
result = f.getHasProperty(PROP_EMIT_ORIENTATION) ? result + "emitOrientation " : result;
|
||||
result = f.getHasProperty(PROP_EMIT_DIMENSIONS) ? result + "emitDimensions " : result;
|
||||
result = f.getHasProperty(PROP_EMIT_RADIUS_START) ? result + "emitRadiusStart " : result;
|
||||
result = f.getHasProperty(PROP_POLAR_START) ? result + "polarStart " : result;
|
||||
result = f.getHasProperty(PROP_POLAR_FINISH) ? result + "polarFinish " : result;
|
||||
result = f.getHasProperty(PROP_AZIMUTH_START) ? result + "azimuthStart " : result;
|
||||
result = f.getHasProperty(PROP_AZIMUTH_FINISH) ? result + "azimuthFinish " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_LOOP) ? result + "animationLoop " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_FIRST_FRAME) ? result + "animationFirstFrame " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_LAST_FRAME) ? result + "animationLastFrame " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_HOLD) ? result + "animationHold " : result;
|
||||
result = f.getHasProperty(PROP_ANIMATION_START_AUTOMATICALLY) ? result + "animationStartAutomatically " : result;
|
||||
result = f.getHasProperty(PROP_EMITTER_SHOULD_TRAIL) ? result + "emitterShouldTrail " : result;
|
||||
result = f.getHasProperty(PROP_PARENT_ID) ? result + "parentID " : result;
|
||||
result = f.getHasProperty(PROP_PARENT_JOINT_INDEX) ? result + "parentJointIndex " : result;
|
||||
result = f.getHasProperty(PROP_LOCAL_POSITION) ? result + "localPosition " : result;
|
||||
result = f.getHasProperty(PROP_LOCAL_ROTATION) ? result + "localRotation " : result;
|
||||
result = f.getHasProperty(PROP_QUERY_AA_CUBE) ? result + "queryAaCube " : result;
|
||||
result = f.getHasProperty(PROP_JOINT_ROTATIONS_SET) ? result + "jointRotationsSet " : result;
|
||||
result = f.getHasProperty(PROP_JOINT_ROTATIONS) ? result + "jointRotations " : result;
|
||||
result = f.getHasProperty(PROP_JOINT_TRANSLATIONS_SET) ? result + "jointTranslationsSet " : result;
|
||||
result = f.getHasProperty(PROP_JOINT_TRANSLATIONS) ? result + "jointTranslations " : result;
|
||||
result = f.getHasProperty(PROP_COLLISION_MASK) ? result + "collisionMask " : result;
|
||||
result = f.getHasProperty(PROP_FALLOFF_RADIUS) ? result + "falloffRadius " : result;
|
||||
result = f.getHasProperty(PROP_FLYING_ALLOWED) ? result + "flyingAllowed " : result;
|
||||
result = f.getHasProperty(PROP_GHOSTING_ALLOWED) ? result + "ghostingAllowed " : result;
|
||||
result = f.getHasProperty(PROP_ENTITY_HOST_TYPE) ? result + "entityHostType " : result;
|
||||
result = f.getHasProperty(PROP_OWNING_AVATAR_ID) ? result + "owningAvatarID " : result;
|
||||
result = f.getHasProperty(PROP_SHAPE) ? result + "shape " : result;
|
||||
result = f.getHasProperty(PROP_DPI) ? result + "dpi " : result;
|
||||
result = f.getHasProperty(PROP_LOCAL_VELOCITY) ? result + "localVelocity " : result;
|
||||
result = f.getHasProperty(PROP_LOCAL_ANGULAR_VELOCITY) ? result + "localAngularVelocity " : result;
|
||||
result = f.getHasProperty(PROP_LAST_EDITED_BY) ? result + "lastEditedBy " : result;
|
||||
result = f.getHasProperty(PROP_SERVER_SCRIPTS) ? result + "serverScripts " : result;
|
||||
result = f.getHasProperty(PROP_FILTER_URL) ? result + "filterUrl " : result;
|
||||
result = f.getHasProperty(PROP_ITEM_NAME) ? result + "itemName " : result;
|
||||
result = f.getHasProperty(PROP_ITEM_DESCRIPTION) ? result + "itemDescription " : result;
|
||||
result = f.getHasProperty(PROP_ITEM_CATEGORIES) ? result + "itemCategories " : result;
|
||||
result = f.getHasProperty(PROP_ITEM_ARTIST) ? result + "itemArtist " : result;
|
||||
result = f.getHasProperty(PROP_ITEM_LICENSE) ? result + "itemLicense " : result;
|
||||
result = f.getHasProperty(PROP_LIMITED_RUN) ? result + "limitedRun " : result;
|
||||
result = f.getHasProperty(PROP_EDITION_NUMBER) ? result + "editionNumber " : result;
|
||||
result = f.getHasProperty(PROP_ENTITY_INSTANCE_NUMBER) ? result + "entityInstanceNumber " : result;
|
||||
result = f.getHasProperty(PROP_CERTIFICATE_ID) ? result + "certificateID " : result;
|
||||
result = f.getHasProperty(PROP_STATIC_CERTIFICATE_VERSION) ? result + "staticCertificateVersion " : result;
|
||||
result = f.getHasProperty(PROP_CLONEABLE) ? result + "cloneable " : result;
|
||||
result = f.getHasProperty(PROP_CLONE_LIFETIME) ? result + "cloneLifetime " : result;
|
||||
result = f.getHasProperty(PROP_CLONE_LIMIT) ? result + "cloneLimit " : result;
|
||||
result = f.getHasProperty(PROP_CLONE_DYNAMIC) ? result + "cloneDynamic " : result;
|
||||
result = f.getHasProperty(PROP_CLONE_AVATAR_ENTITY) ? result + "cloneAvatarEntity " : result;
|
||||
result = f.getHasProperty(PROP_CLONE_ORIGIN_ID) ? result + "cloneOriginID " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_MODE) ? result + "hazeMode " : result;
|
||||
result = f.getHasProperty(PROP_KEYLIGHT_COLOR) ? result + "keylightColor " : result;
|
||||
result = f.getHasProperty(PROP_KEYLIGHT_INTENSITY) ? result + "keylightIntensity " : result;
|
||||
result = f.getHasProperty(PROP_KEYLIGHT_DIRECTION) ? result + "keylightDirection " : result;
|
||||
result = f.getHasProperty(PROP_KEYLIGHT_CAST_SHADOW) ? result + "keylightCastShadow " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_RANGE) ? result + "hazeRange " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_COLOR) ? result + "hazeColor " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_GLARE_COLOR) ? result + "hazeGlareColor " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_ENABLE_GLARE) ? result + "hazeEnableGlare " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_GLARE_ANGLE) ? result + "hazeGlareAngle " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_ALTITUDE_EFFECT) ? result + "hazeAltitudeEffect " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_CEILING) ? result + "hazeCeiling " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_BASE_REF) ? result + "hazeBaseRef " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_BACKGROUND_BLEND) ? result + "hazeBackgroundBlend " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_ATTENUATE_KEYLIGHT) ? result + "hazeAttenuateKeylight " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_KEYLIGHT_RANGE) ? result + "hazeKeylightRange " : result;
|
||||
result = f.getHasProperty(PROP_HAZE_KEYLIGHT_ALTITUDE) ? result + "hazeKeylightAltitude " : result;
|
||||
result = f.getHasProperty(PROP_KEY_LIGHT_MODE) ? result + "keyLightMode " : result;
|
||||
result = f.getHasProperty(PROP_AMBIENT_LIGHT_MODE) ? result + "ambientLightMode " : result;
|
||||
result = f.getHasProperty(PROP_SKYBOX_MODE) ? result + "skyboxMode " : result;
|
||||
result = f.getHasProperty(PROP_LOCAL_DIMENSIONS) ? result + "localDimensions " : result;
|
||||
result = f.getHasProperty(PROP_MATERIAL_URL) ? result + "materialUrl " : result;
|
||||
result = f.getHasProperty(PROP_MATERIAL_MAPPING_MODE) ? result + "materialMappingMode " : result;
|
||||
result = f.getHasProperty(PROP_MATERIAL_PRIORITY) ? result + "materialPriority " : result;
|
||||
result = f.getHasProperty(PROP_PARENT_MATERIAL_NAME) ? result + "parentMaterialName " : result;
|
||||
result = f.getHasProperty(PROP_MATERIAL_MAPPING_POS) ? result + "materialMappingPos " : result;
|
||||
result = f.getHasProperty(PROP_MATERIAL_MAPPING_SCALE) ? result + "materialMappingScale " : result;
|
||||
result = f.getHasProperty(PROP_MATERIAL_MAPPING_ROT) ? result + "materialMappingRot " : result;
|
||||
result = f.getHasProperty(PROP_MATERIAL_DATA) ? result + "materialData " : result;
|
||||
result = f.getHasProperty(PROP_MATERIAL_REPEAT) ? result + "materialRepeat " : result;
|
||||
result = f.getHasProperty(PROP_VISIBLE_IN_SECONDARY_CAMERA) ? result + "visibleInSecondaryCamera " : result;
|
||||
result = f.getHasProperty(PROP_PARTICLE_SPIN) ? result + "particleSpin " : result;
|
||||
result = f.getHasProperty(PROP_SPIN_START) ? result + "spinStart " : result;
|
||||
result = f.getHasProperty(PROP_SPIN_FINISH) ? result + "spinFinish " : result;
|
||||
result = f.getHasProperty(PROP_SPIN_SPREAD) ? result + "spinSpread " : result;
|
||||
result = f.getHasProperty(PROP_PARTICLE_ROTATE_WITH_ENTITY) ? result + "particleRotateWithEntity " : result;
|
||||
result = f.getHasProperty(PROP_BLOOM_INTENSITY) ? result + "bloomIntensity " : result;
|
||||
result = f.getHasProperty(PROP_BLOOM_THRESHOLD) ? result + "bloomThreshold " : result;
|
||||
result = f.getHasProperty(PROP_BLOOM_SIZE) ? result + "bloomSize " : result;
|
||||
result = f.getHasProperty(PROP_GRAB_GRABBABLE) ? result + "grab.Grabbable " : result;
|
||||
result = f.getHasProperty(PROP_GRAB_KINEMATIC) ? result + "grab.Kinematic " : result;
|
||||
result = f.getHasProperty(PROP_GRAB_FOLLOWS_CONTROLLER) ? result + "grab.FollowsController " : result;
|
||||
result = f.getHasProperty(PROP_GRAB_TRIGGERABLE) ? result + "grab.Triggerable " : result;
|
||||
result = f.getHasProperty(PROP_GRAB_EQUIPPABLE) ? result + "grab.Equippable " : result;
|
||||
result =
|
||||
f.getHasProperty(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET) ? result + "grab.LeftEquippablePositionOffset " : result;
|
||||
result =
|
||||
f.getHasProperty(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET) ? result + "grab.LeftEquippableRotationOffset " : result;
|
||||
result =
|
||||
f.getHasProperty(PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET) ? result + "grab.RightEquippablePositionOffset " : result;
|
||||
result =
|
||||
f.getHasProperty(PROP_GRAB_RIGHT_EQUIPPABLE_ROTATION_OFFSET) ? result + "grab.RightEquippableRotationOffset " : result;
|
||||
result = f.getHasProperty(PROP_GRAB_EQUIPPABLE_INDICATOR_URL) ? result + "grab.EquippableIndicatorURL " : result;
|
||||
result = f.getHasProperty(PROP_GRAB_EQUIPPABLE_INDICATOR_SCALE) ? result + "grab.EquippableIndicatorScale " : result;
|
||||
result = f.getHasProperty(PROP_GRAB_EQUIPPABLE_INDICATOR_OFFSET) ? result + "grab.EquippableIndicatorOffset " : result;
|
||||
|
||||
result += "]";
|
||||
dbg.nospace() << result;
|
||||
return dbg;
|
||||
}
|
|
@ -18,255 +18,34 @@ enum EntityPropertyList {
|
|||
PROP_PAGED_PROPERTY,
|
||||
PROP_CUSTOM_PROPERTIES_INCLUDED,
|
||||
|
||||
// these properties are supported by the EntityItem base class
|
||||
// Core properties
|
||||
PROP_SIMULATION_OWNER,
|
||||
PROP_VISIBLE,
|
||||
PROP_CAN_CAST_SHADOW,
|
||||
PROP_NAME,
|
||||
PROP_LOCKED,
|
||||
PROP_USER_DATA,
|
||||
PROP_HREF,
|
||||
PROP_DESCRIPTION,
|
||||
PROP_POSITION,
|
||||
PROP_DIMENSIONS,
|
||||
PROP_ROTATION,
|
||||
PROP_DENSITY,
|
||||
PROP_VELOCITY,
|
||||
PROP_GRAVITY,
|
||||
PROP_DAMPING,
|
||||
PROP_LIFETIME,
|
||||
PROP_SCRIPT,
|
||||
|
||||
// these properties are supported by some derived classes
|
||||
PROP_COLOR,
|
||||
|
||||
// these are used by models only
|
||||
PROP_MODEL_URL,
|
||||
PROP_ANIMATION_URL,
|
||||
PROP_ANIMATION_FPS,
|
||||
PROP_ANIMATION_FRAME_INDEX,
|
||||
PROP_ANIMATION_PLAYING,
|
||||
PROP_ANIMATION_ALLOW_TRANSLATION,
|
||||
PROP_RELAY_PARENT_JOINTS,
|
||||
|
||||
// these properties are supported by the EntityItem base class
|
||||
PROP_REGISTRATION_POINT,
|
||||
PROP_ANGULAR_VELOCITY,
|
||||
PROP_ANGULAR_DAMPING,
|
||||
PROP_COLLISIONLESS,
|
||||
PROP_DYNAMIC, // 24
|
||||
|
||||
// property used by Light entity
|
||||
PROP_IS_SPOTLIGHT,
|
||||
PROP_DIFFUSE_COLOR,
|
||||
PROP_AMBIENT_COLOR_UNUSED, // FIXME - No longer used, can remove and bump protocol
|
||||
PROP_SPECULAR_COLOR_UNUSED, // FIXME - No longer used, can remove and bump protocol
|
||||
PROP_INTENSITY, // Previously PROP_CONSTANT_ATTENUATION
|
||||
PROP_LINEAR_ATTENUATION_UNUSED,
|
||||
PROP_QUADRATIC_ATTENUATION_UNUSED,
|
||||
PROP_EXPONENT,
|
||||
PROP_CUTOFF,
|
||||
|
||||
// available to all entities
|
||||
PROP_LOCKED, // 34
|
||||
|
||||
PROP_TEXTURES, // used by Model entities
|
||||
PROP_ANIMATION_SETTINGS_UNUSED, // FIXME - No longer used, can remove and bump protocol
|
||||
PROP_USER_DATA, // all entities -- 37
|
||||
PROP_SHAPE_TYPE, // used by Model + zones entities
|
||||
|
||||
// used by ParticleEffect entities
|
||||
PROP_MAX_PARTICLES, // 39
|
||||
PROP_LIFESPAN, // 40 -- used by all entities
|
||||
PROP_EMIT_RATE,
|
||||
PROP_EMIT_SPEED,
|
||||
PROP_EMIT_STRENGTH,
|
||||
PROP_EMIT_ACCELERATION, // FIXME - doesn't seem to get set in mark all changed????
|
||||
PROP_PARTICLE_RADIUS, // 45!!
|
||||
|
||||
PROP_COMPOUND_SHAPE_URL, // used by Model + zones entities
|
||||
PROP_MARKETPLACE_ID, // all entities
|
||||
PROP_ACCELERATION, // all entities
|
||||
PROP_SIMULATION_OWNER, // formerly known as PROP_SIMULATOR_ID
|
||||
PROP_NAME, // all entities -- 50
|
||||
PROP_COLLISION_SOUND_URL,
|
||||
PROP_RESTITUTION,
|
||||
PROP_FRICTION, // 53
|
||||
|
||||
PROP_VOXEL_VOLUME_SIZE,
|
||||
PROP_VOXEL_DATA,
|
||||
PROP_VOXEL_SURFACE_STYLE,
|
||||
|
||||
//for lines
|
||||
PROP_LINE_WIDTH,
|
||||
PROP_LINE_POINTS,
|
||||
|
||||
// used by hyperlinks
|
||||
PROP_HREF,
|
||||
PROP_DESCRIPTION, // 61
|
||||
|
||||
PROP_BILLBOARD_MODE,
|
||||
PROP_SCRIPT_TIMESTAMP,
|
||||
|
||||
PROP_ACTION_DATA,
|
||||
|
||||
PROP_X_TEXTURE_URL, // used by PolyVox
|
||||
PROP_Y_TEXTURE_URL, // used by PolyVox
|
||||
PROP_Z_TEXTURE_URL, // used by PolyVox
|
||||
|
||||
// Used by PolyLine entity
|
||||
PROP_NORMALS,
|
||||
PROP_STROKE_COLORS,
|
||||
PROP_STROKE_WIDTHS,
|
||||
PROP_IS_UV_MODE_STRETCH,
|
||||
|
||||
// used by particles
|
||||
PROP_SPEED_SPREAD,
|
||||
PROP_ACCELERATION_SPREAD,
|
||||
|
||||
PROP_X_N_NEIGHBOR_ID, // used by PolyVox
|
||||
PROP_Y_N_NEIGHBOR_ID, // used by PolyVox
|
||||
PROP_Z_N_NEIGHBOR_ID, // used by PolyVox
|
||||
PROP_X_P_NEIGHBOR_ID, // used by PolyVox
|
||||
PROP_Y_P_NEIGHBOR_ID, // used by PolyVox
|
||||
PROP_Z_P_NEIGHBOR_ID, // used by PolyVox
|
||||
|
||||
// Used by particles
|
||||
PROP_RADIUS_SPREAD,
|
||||
PROP_RADIUS_START,
|
||||
PROP_RADIUS_FINISH,
|
||||
|
||||
PROP_ALPHA, // Supported by some derived classes
|
||||
|
||||
//Used by particles
|
||||
PROP_COLOR_SPREAD,
|
||||
PROP_COLOR_START,
|
||||
PROP_COLOR_FINISH,
|
||||
PROP_ALPHA_SPREAD,
|
||||
PROP_ALPHA_START,
|
||||
PROP_ALPHA_FINISH,
|
||||
PROP_EMIT_ORIENTATION,
|
||||
PROP_EMIT_DIMENSIONS,
|
||||
PROP_EMIT_RADIUS_START,
|
||||
PROP_POLAR_START,
|
||||
PROP_POLAR_FINISH,
|
||||
PROP_AZIMUTH_START,
|
||||
PROP_AZIMUTH_FINISH,
|
||||
|
||||
PROP_ANIMATION_LOOP,
|
||||
PROP_ANIMATION_FIRST_FRAME,
|
||||
PROP_ANIMATION_LAST_FRAME,
|
||||
PROP_ANIMATION_HOLD,
|
||||
PROP_ANIMATION_START_AUTOMATICALLY,
|
||||
|
||||
PROP_EMITTER_SHOULD_TRAIL,
|
||||
|
||||
PROP_CREATED,
|
||||
PROP_LAST_EDITED_BY,
|
||||
PROP_ENTITY_HOST_TYPE, // not sent over wire
|
||||
PROP_OWNING_AVATAR_ID, // not sent over wire
|
||||
PROP_PARENT_ID,
|
||||
PROP_PARENT_JOINT_INDEX,
|
||||
|
||||
PROP_LOCAL_POSITION, // only used to convert values to and from scripts
|
||||
PROP_LOCAL_ROTATION, // only used to convert values to and from scripts
|
||||
|
||||
PROP_QUERY_AA_CUBE, // how the EntityTree considers the size and position on an entity
|
||||
|
||||
// ModelEntity joint state
|
||||
PROP_JOINT_ROTATIONS_SET,
|
||||
PROP_JOINT_ROTATIONS,
|
||||
PROP_JOINT_TRANSLATIONS_SET,
|
||||
PROP_JOINT_TRANSLATIONS,
|
||||
|
||||
PROP_COLLISION_MASK, // one byte of collision group flags
|
||||
|
||||
PROP_FALLOFF_RADIUS, // for Light entity
|
||||
|
||||
PROP_FLYING_ALLOWED, // can avatars in a zone fly?
|
||||
PROP_GHOSTING_ALLOWED, // can avatars in a zone turn off physics?
|
||||
|
||||
PROP_ENTITY_HOST_TYPE, // doesn't go over wire
|
||||
PROP_OWNING_AVATAR_ID, // doesn't go over wire
|
||||
|
||||
PROP_SHAPE,
|
||||
PROP_DPI,
|
||||
|
||||
PROP_LOCAL_VELOCITY, // only used to convert values to and from scripts
|
||||
PROP_LOCAL_ANGULAR_VELOCITY, // only used to convert values to and from scripts
|
||||
|
||||
PROP_LAST_EDITED_BY,
|
||||
|
||||
PROP_SERVER_SCRIPTS,
|
||||
|
||||
PROP_FILTER_URL,
|
||||
|
||||
// Certificable Properties
|
||||
PROP_ITEM_NAME,
|
||||
PROP_ITEM_DESCRIPTION,
|
||||
PROP_ITEM_CATEGORIES,
|
||||
PROP_ITEM_ARTIST,
|
||||
PROP_ITEM_LICENSE,
|
||||
PROP_LIMITED_RUN,
|
||||
// PROP_MARKETPLACE_ID is above
|
||||
PROP_EDITION_NUMBER,
|
||||
PROP_ENTITY_INSTANCE_NUMBER,
|
||||
PROP_CERTIFICATE_ID,
|
||||
PROP_STATIC_CERTIFICATE_VERSION,
|
||||
|
||||
PROP_CLONEABLE,
|
||||
PROP_CLONE_LIFETIME,
|
||||
PROP_CLONE_LIMIT,
|
||||
PROP_CLONE_DYNAMIC,
|
||||
PROP_CLONE_AVATAR_ENTITY,
|
||||
PROP_CLONE_ORIGIN_ID,
|
||||
|
||||
PROP_HAZE_MODE,
|
||||
|
||||
PROP_KEYLIGHT_COLOR,
|
||||
PROP_KEYLIGHT_INTENSITY,
|
||||
PROP_KEYLIGHT_DIRECTION,
|
||||
PROP_KEYLIGHT_CAST_SHADOW,
|
||||
|
||||
PROP_HAZE_RANGE,
|
||||
PROP_HAZE_COLOR,
|
||||
PROP_HAZE_GLARE_COLOR,
|
||||
PROP_HAZE_ENABLE_GLARE,
|
||||
PROP_HAZE_GLARE_ANGLE,
|
||||
|
||||
PROP_HAZE_ALTITUDE_EFFECT,
|
||||
PROP_HAZE_CEILING,
|
||||
PROP_HAZE_BASE_REF,
|
||||
|
||||
PROP_HAZE_BACKGROUND_BLEND,
|
||||
|
||||
PROP_HAZE_ATTENUATE_KEYLIGHT,
|
||||
PROP_HAZE_KEYLIGHT_RANGE,
|
||||
PROP_HAZE_KEYLIGHT_ALTITUDE,
|
||||
|
||||
PROP_KEY_LIGHT_MODE,
|
||||
PROP_AMBIENT_LIGHT_MODE,
|
||||
PROP_SKYBOX_MODE,
|
||||
|
||||
PROP_LOCAL_DIMENSIONS, // only used to convert values to and from scripts
|
||||
|
||||
PROP_MATERIAL_URL,
|
||||
PROP_MATERIAL_MAPPING_MODE,
|
||||
PROP_MATERIAL_PRIORITY,
|
||||
PROP_PARENT_MATERIAL_NAME,
|
||||
PROP_MATERIAL_MAPPING_POS,
|
||||
PROP_MATERIAL_MAPPING_SCALE,
|
||||
PROP_MATERIAL_MAPPING_ROT,
|
||||
PROP_MATERIAL_DATA,
|
||||
|
||||
PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over the wire, only used locally
|
||||
|
||||
PROP_PARTICLE_SPIN,
|
||||
PROP_SPIN_START,
|
||||
PROP_SPIN_FINISH,
|
||||
PROP_SPIN_SPREAD,
|
||||
PROP_PARTICLE_ROTATE_WITH_ENTITY,
|
||||
|
||||
PROP_BLOOM_MODE,
|
||||
PROP_BLOOM_INTENSITY,
|
||||
PROP_BLOOM_THRESHOLD,
|
||||
PROP_BLOOM_SIZE,
|
||||
|
||||
PROP_QUERY_AA_CUBE,
|
||||
PROP_CAN_CAST_SHADOW,
|
||||
PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over wire
|
||||
// Grab
|
||||
PROP_GRAB_GRABBABLE,
|
||||
PROP_GRAB_KINEMATIC,
|
||||
PROP_GRAB_FOLLOWS_CONTROLLER,
|
||||
PROP_GRAB_TRIGGERABLE,
|
||||
PROP_GRAB_EQUIPPABLE,
|
||||
PROP_GRAB_DELEGATE_TO_PARENT,
|
||||
PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET,
|
||||
PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET,
|
||||
PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET,
|
||||
|
@ -275,54 +54,268 @@ enum EntityPropertyList {
|
|||
PROP_GRAB_EQUIPPABLE_INDICATOR_SCALE,
|
||||
PROP_GRAB_EQUIPPABLE_INDICATOR_OFFSET,
|
||||
|
||||
PROP_MATERIAL_REPEAT,
|
||||
// Physics
|
||||
PROP_DENSITY,
|
||||
PROP_VELOCITY,
|
||||
PROP_ANGULAR_VELOCITY,
|
||||
PROP_GRAVITY,
|
||||
PROP_ACCELERATION,
|
||||
PROP_DAMPING,
|
||||
PROP_ANGULAR_DAMPING,
|
||||
PROP_RESTITUTION,
|
||||
PROP_FRICTION,
|
||||
PROP_LIFETIME,
|
||||
PROP_COLLISIONLESS,
|
||||
PROP_COLLISION_MASK,
|
||||
PROP_DYNAMIC,
|
||||
PROP_COLLISION_SOUND_URL,
|
||||
PROP_ACTION_DATA,
|
||||
|
||||
PROP_EMISSIVE,
|
||||
PROP_SUB_IMAGE,
|
||||
// Cloning
|
||||
PROP_CLONEABLE,
|
||||
PROP_CLONE_LIFETIME,
|
||||
PROP_CLONE_LIMIT,
|
||||
PROP_CLONE_DYNAMIC,
|
||||
PROP_CLONE_AVATAR_ENTITY,
|
||||
PROP_CLONE_ORIGIN_ID,
|
||||
|
||||
// Scripts
|
||||
PROP_SCRIPT,
|
||||
PROP_SCRIPT_TIMESTAMP,
|
||||
PROP_SERVER_SCRIPTS,
|
||||
|
||||
// Certifiable Properties
|
||||
PROP_ITEM_NAME,
|
||||
PROP_ITEM_DESCRIPTION,
|
||||
PROP_ITEM_CATEGORIES,
|
||||
PROP_ITEM_ARTIST,
|
||||
PROP_ITEM_LICENSE,
|
||||
PROP_LIMITED_RUN,
|
||||
PROP_MARKETPLACE_ID,
|
||||
PROP_EDITION_NUMBER,
|
||||
PROP_ENTITY_INSTANCE_NUMBER,
|
||||
PROP_CERTIFICATE_ID,
|
||||
PROP_STATIC_CERTIFICATE_VERSION,
|
||||
|
||||
// Used to convert values to and from scripts
|
||||
PROP_LOCAL_POSITION,
|
||||
PROP_LOCAL_ROTATION,
|
||||
PROP_LOCAL_VELOCITY,
|
||||
PROP_LOCAL_ANGULAR_VELOCITY,
|
||||
PROP_LOCAL_DIMENSIONS,
|
||||
|
||||
// These properties are used by multiple subtypes but aren't in the base EntityItem
|
||||
PROP_SHAPE_TYPE,
|
||||
PROP_COMPOUND_SHAPE_URL,
|
||||
PROP_COLOR,
|
||||
PROP_ALPHA,
|
||||
PROP_TEXTURES,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
// ATTENTION: add new shared EntityItem properties to the list ABOVE this line
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// We need as many of these as the number of unique properties of a derived EntityItem class
|
||||
PROP_DERIVED_0,
|
||||
PROP_DERIVED_1,
|
||||
PROP_DERIVED_2,
|
||||
PROP_DERIVED_3,
|
||||
PROP_DERIVED_4,
|
||||
PROP_DERIVED_5,
|
||||
PROP_DERIVED_6,
|
||||
PROP_DERIVED_7,
|
||||
PROP_DERIVED_8,
|
||||
PROP_DERIVED_9,
|
||||
PROP_DERIVED_10,
|
||||
PROP_DERIVED_11,
|
||||
PROP_DERIVED_12,
|
||||
PROP_DERIVED_13,
|
||||
PROP_DERIVED_14,
|
||||
PROP_DERIVED_15,
|
||||
PROP_DERIVED_16,
|
||||
PROP_DERIVED_17,
|
||||
PROP_DERIVED_18,
|
||||
PROP_DERIVED_19,
|
||||
PROP_DERIVED_20,
|
||||
PROP_DERIVED_21,
|
||||
PROP_DERIVED_22,
|
||||
PROP_DERIVED_23,
|
||||
PROP_DERIVED_24,
|
||||
PROP_DERIVED_25,
|
||||
PROP_DERIVED_26,
|
||||
PROP_DERIVED_27,
|
||||
PROP_DERIVED_28,
|
||||
PROP_DERIVED_29,
|
||||
PROP_DERIVED_30,
|
||||
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// WARNING! Do not add props here unless you intentionally mean to reuse PROP_ indexes
|
||||
// WARNING! Do not add props here unless you intentionally mean to reuse PROP_DERIVED_X indexes
|
||||
//
|
||||
// These properties of TextEntity piggy back off of properties of ModelEntities, the type doesn't matter
|
||||
// since the derived class knows how to interpret it's own properties and knows the types it expects
|
||||
PROP_TEXT_COLOR = PROP_COLOR,
|
||||
PROP_TEXT = PROP_MODEL_URL,
|
||||
PROP_LINE_HEIGHT = PROP_ANIMATION_URL,
|
||||
PROP_BACKGROUND_COLOR = PROP_ANIMATION_FPS,
|
||||
PROP_COLLISION_MODEL_URL_OLD_VERSION = PROP_ANIMATION_FPS + 1,
|
||||
|
||||
// Aliases/Piggyback properties for Zones. These properties intentionally reuse the enum values for
|
||||
// other properties which will never overlap with each other. We do this so that we don't have to expand
|
||||
// These properties intentionally reuse the enum values for other properties which will never overlap with each other. We do this so that we don't have to expand
|
||||
// the size of the properties bitflags mask
|
||||
PROP_SKYBOX_COLOR = PROP_ANIMATION_URL,
|
||||
PROP_SKYBOX_URL = PROP_ANIMATION_FPS,
|
||||
//
|
||||
// Only add properties here that are only used by one subclass. Otherwise, they should go above to prevent collisions
|
||||
|
||||
PROP_AMBIENT_LIGHT_INTENSITY = PROP_CUTOFF,
|
||||
PROP_AMBIENT_LIGHT_URL = PROP_ANIMATION_PLAYING,
|
||||
// Particles
|
||||
PROP_MAX_PARTICLES = PROP_DERIVED_0,
|
||||
PROP_LIFESPAN = PROP_DERIVED_1,
|
||||
PROP_EMITTING_PARTICLES = PROP_DERIVED_2,
|
||||
PROP_EMIT_RATE = PROP_DERIVED_3,
|
||||
PROP_EMIT_SPEED = PROP_DERIVED_4,
|
||||
PROP_SPEED_SPREAD = PROP_DERIVED_5,
|
||||
PROP_EMIT_ORIENTATION = PROP_DERIVED_6,
|
||||
PROP_EMIT_DIMENSIONS = PROP_DERIVED_7,
|
||||
PROP_ACCELERATION_SPREAD = PROP_DERIVED_8,
|
||||
PROP_POLAR_START = PROP_DERIVED_9,
|
||||
PROP_POLAR_FINISH = PROP_DERIVED_10,
|
||||
PROP_AZIMUTH_START = PROP_DERIVED_11,
|
||||
PROP_AZIMUTH_FINISH = PROP_DERIVED_12,
|
||||
PROP_EMIT_RADIUS_START = PROP_DERIVED_13,
|
||||
PROP_EMIT_ACCELERATION = PROP_DERIVED_14,
|
||||
PROP_PARTICLE_RADIUS = PROP_DERIVED_15,
|
||||
PROP_RADIUS_SPREAD = PROP_DERIVED_16,
|
||||
PROP_RADIUS_START = PROP_DERIVED_17,
|
||||
PROP_RADIUS_FINISH = PROP_DERIVED_18,
|
||||
PROP_COLOR_SPREAD = PROP_DERIVED_19,
|
||||
PROP_COLOR_START = PROP_DERIVED_20,
|
||||
PROP_COLOR_FINISH = PROP_DERIVED_21,
|
||||
PROP_ALPHA_SPREAD = PROP_DERIVED_22,
|
||||
PROP_ALPHA_START = PROP_DERIVED_23,
|
||||
PROP_ALPHA_FINISH = PROP_DERIVED_24,
|
||||
PROP_EMITTER_SHOULD_TRAIL = PROP_DERIVED_25,
|
||||
PROP_PARTICLE_SPIN = PROP_DERIVED_26,
|
||||
PROP_SPIN_START = PROP_DERIVED_27,
|
||||
PROP_SPIN_FINISH = PROP_DERIVED_28,
|
||||
PROP_SPIN_SPREAD = PROP_DERIVED_29,
|
||||
PROP_PARTICLE_ROTATE_WITH_ENTITY = PROP_DERIVED_30,
|
||||
|
||||
// Aliases/Piggyback properties for Web. These properties intentionally reuse the enum values for
|
||||
// other properties which will never overlap with each other.
|
||||
PROP_SOURCE_URL = PROP_MODEL_URL,
|
||||
// Model
|
||||
PROP_MODEL_URL = PROP_DERIVED_0,
|
||||
PROP_JOINT_ROTATIONS_SET = PROP_DERIVED_1,
|
||||
PROP_JOINT_ROTATIONS = PROP_DERIVED_2,
|
||||
PROP_JOINT_TRANSLATIONS_SET = PROP_DERIVED_3,
|
||||
PROP_JOINT_TRANSLATIONS = PROP_DERIVED_4,
|
||||
PROP_RELAY_PARENT_JOINTS = PROP_DERIVED_5,
|
||||
// Animation
|
||||
PROP_ANIMATION_URL = PROP_DERIVED_6,
|
||||
PROP_ANIMATION_ALLOW_TRANSLATION = PROP_DERIVED_7,
|
||||
PROP_ANIMATION_FPS = PROP_DERIVED_8,
|
||||
PROP_ANIMATION_FRAME_INDEX = PROP_DERIVED_9,
|
||||
PROP_ANIMATION_PLAYING = PROP_DERIVED_10,
|
||||
PROP_ANIMATION_LOOP = PROP_DERIVED_11,
|
||||
PROP_ANIMATION_FIRST_FRAME = PROP_DERIVED_12,
|
||||
PROP_ANIMATION_LAST_FRAME = PROP_DERIVED_13,
|
||||
PROP_ANIMATION_HOLD = PROP_DERIVED_14,
|
||||
|
||||
// Aliases/Piggyback properties for Particle Emmitter. These properties intentionally reuse the enum values for
|
||||
// other properties which will never overlap with each other.
|
||||
PROP_EMITTING_PARTICLES = PROP_ANIMATION_PLAYING,
|
||||
// Light
|
||||
PROP_IS_SPOTLIGHT = PROP_DERIVED_0,
|
||||
PROP_INTENSITY = PROP_DERIVED_1,
|
||||
PROP_EXPONENT = PROP_DERIVED_2,
|
||||
PROP_CUTOFF = PROP_DERIVED_3,
|
||||
PROP_FALLOFF_RADIUS = PROP_DERIVED_4,
|
||||
|
||||
// Aliases/Piggyback properties for Image. These properties intentionally reuse the enum values for
|
||||
// other properties which will never overlap with each other.
|
||||
PROP_IMAGE_URL = PROP_MODEL_URL,
|
||||
PROP_KEEP_ASPECT_RATIO = PROP_ANIMATION_PLAYING,
|
||||
// Text
|
||||
PROP_TEXT = PROP_DERIVED_0,
|
||||
PROP_LINE_HEIGHT = PROP_DERIVED_1,
|
||||
PROP_TEXT_COLOR = PROP_DERIVED_2,
|
||||
PROP_TEXT_ALPHA = PROP_DERIVED_3,
|
||||
PROP_BACKGROUND_COLOR = PROP_DERIVED_4,
|
||||
PROP_BACKGROUND_ALPHA = PROP_DERIVED_5,
|
||||
PROP_BILLBOARD_MODE = PROP_DERIVED_6,
|
||||
PROP_LEFT_MARGIN = PROP_DERIVED_7,
|
||||
PROP_RIGHT_MARGIN = PROP_DERIVED_8,
|
||||
PROP_TOP_MARGIN = PROP_DERIVED_9,
|
||||
PROP_BOTTOM_MARGIN = PROP_DERIVED_10,
|
||||
|
||||
// Aliases/Piggyback properties for Grid. These properties intentionally reuse the enum values for
|
||||
// other properties which will never overlap with each other.
|
||||
PROP_GRID_FOLLOW_CAMERA = PROP_ANIMATION_PLAYING,
|
||||
PROP_MAJOR_GRID_EVERY = PROP_ANIMATION_URL,
|
||||
PROP_MINOR_GRID_EVERY = PROP_ANIMATION_FPS,
|
||||
// Zone
|
||||
// Keylight
|
||||
PROP_KEYLIGHT_COLOR = PROP_DERIVED_0,
|
||||
PROP_KEYLIGHT_INTENSITY = PROP_DERIVED_1,
|
||||
PROP_KEYLIGHT_DIRECTION = PROP_DERIVED_2,
|
||||
PROP_KEYLIGHT_CAST_SHADOW = PROP_DERIVED_3,
|
||||
// Ambient light
|
||||
PROP_AMBIENT_LIGHT_INTENSITY = PROP_DERIVED_4,
|
||||
PROP_AMBIENT_LIGHT_URL = PROP_DERIVED_5,
|
||||
// Skybox
|
||||
PROP_SKYBOX_COLOR = PROP_DERIVED_6,
|
||||
PROP_SKYBOX_URL = PROP_DERIVED_7,
|
||||
// Haze
|
||||
PROP_HAZE_RANGE = PROP_DERIVED_8,
|
||||
PROP_HAZE_COLOR = PROP_DERIVED_9,
|
||||
PROP_HAZE_GLARE_COLOR = PROP_DERIVED_10,
|
||||
PROP_HAZE_ENABLE_GLARE = PROP_DERIVED_11,
|
||||
PROP_HAZE_GLARE_ANGLE = PROP_DERIVED_12,
|
||||
PROP_HAZE_ALTITUDE_EFFECT = PROP_DERIVED_13,
|
||||
PROP_HAZE_CEILING = PROP_DERIVED_14,
|
||||
PROP_HAZE_BASE_REF = PROP_DERIVED_15,
|
||||
PROP_HAZE_BACKGROUND_BLEND = PROP_DERIVED_16,
|
||||
PROP_HAZE_ATTENUATE_KEYLIGHT = PROP_DERIVED_17,
|
||||
PROP_HAZE_KEYLIGHT_RANGE = PROP_DERIVED_18,
|
||||
PROP_HAZE_KEYLIGHT_ALTITUDE = PROP_DERIVED_19,
|
||||
// Bloom
|
||||
PROP_BLOOM_INTENSITY = PROP_DERIVED_20,
|
||||
PROP_BLOOM_THRESHOLD = PROP_DERIVED_21,
|
||||
PROP_BLOOM_SIZE = PROP_DERIVED_22,
|
||||
PROP_FLYING_ALLOWED = PROP_DERIVED_23,
|
||||
PROP_GHOSTING_ALLOWED = PROP_DERIVED_24,
|
||||
PROP_FILTER_URL = PROP_DERIVED_25,
|
||||
PROP_KEY_LIGHT_MODE = PROP_DERIVED_26,
|
||||
PROP_AMBIENT_LIGHT_MODE = PROP_DERIVED_27,
|
||||
PROP_SKYBOX_MODE = PROP_DERIVED_28,
|
||||
PROP_HAZE_MODE = PROP_DERIVED_29,
|
||||
PROP_BLOOM_MODE = PROP_DERIVED_30,
|
||||
|
||||
// Polyvox
|
||||
PROP_VOXEL_VOLUME_SIZE = PROP_DERIVED_0,
|
||||
PROP_VOXEL_DATA = PROP_DERIVED_1,
|
||||
PROP_VOXEL_SURFACE_STYLE = PROP_DERIVED_2,
|
||||
PROP_X_TEXTURE_URL = PROP_DERIVED_3,
|
||||
PROP_Y_TEXTURE_URL = PROP_DERIVED_4,
|
||||
PROP_Z_TEXTURE_URL = PROP_DERIVED_5,
|
||||
PROP_X_N_NEIGHBOR_ID = PROP_DERIVED_6,
|
||||
PROP_Y_N_NEIGHBOR_ID = PROP_DERIVED_7,
|
||||
PROP_Z_N_NEIGHBOR_ID = PROP_DERIVED_8,
|
||||
PROP_X_P_NEIGHBOR_ID = PROP_DERIVED_9,
|
||||
PROP_Y_P_NEIGHBOR_ID = PROP_DERIVED_10,
|
||||
PROP_Z_P_NEIGHBOR_ID = PROP_DERIVED_11,
|
||||
|
||||
// Web
|
||||
PROP_SOURCE_URL = PROP_DERIVED_0,
|
||||
PROP_DPI = PROP_DERIVED_1,
|
||||
|
||||
// Polyline
|
||||
PROP_LINE_POINTS = PROP_DERIVED_0,
|
||||
PROP_STROKE_WIDTHS = PROP_DERIVED_1,
|
||||
PROP_STROKE_NORMALS = PROP_DERIVED_2,
|
||||
PROP_STROKE_COLORS = PROP_DERIVED_3,
|
||||
PROP_IS_UV_MODE_STRETCH = PROP_DERIVED_4,
|
||||
|
||||
// Shape
|
||||
PROP_SHAPE = PROP_DERIVED_0,
|
||||
|
||||
// Material
|
||||
PROP_MATERIAL_URL = PROP_DERIVED_0,
|
||||
PROP_MATERIAL_MAPPING_MODE = PROP_DERIVED_1,
|
||||
PROP_MATERIAL_PRIORITY = PROP_DERIVED_2,
|
||||
PROP_PARENT_MATERIAL_NAME = PROP_DERIVED_3,
|
||||
PROP_MATERIAL_MAPPING_POS = PROP_DERIVED_4,
|
||||
PROP_MATERIAL_MAPPING_SCALE = PROP_DERIVED_5,
|
||||
PROP_MATERIAL_MAPPING_ROT = PROP_DERIVED_6,
|
||||
PROP_MATERIAL_DATA = PROP_DERIVED_7,
|
||||
PROP_MATERIAL_REPEAT = PROP_DERIVED_8,
|
||||
|
||||
// Image
|
||||
PROP_IMAGE_URL = PROP_DERIVED_0,
|
||||
PROP_EMISSIVE = PROP_DERIVED_1,
|
||||
PROP_KEEP_ASPECT_RATIO = PROP_DERIVED_2,
|
||||
PROP_SUB_IMAGE = PROP_DERIVED_3,
|
||||
|
||||
// Grid
|
||||
PROP_GRID_FOLLOW_CAMERA = PROP_DERIVED_0,
|
||||
PROP_MAJOR_GRID_EVERY = PROP_DERIVED_1,
|
||||
PROP_MINOR_GRID_EVERY = PROP_DERIVED_2,
|
||||
|
||||
// WARNING!!! DO NOT ADD PROPS_xxx here unless you really really meant to.... Add them UP above
|
||||
};
|
||||
|
@ -333,10 +326,4 @@ typedef PropertyFlags<EntityPropertyList> EntityPropertyFlags;
|
|||
// one greater than the last item property due to the enum's auto-incrementing.
|
||||
extern EntityPropertyList PROP_LAST_ITEM;
|
||||
|
||||
QString EntityPropertyFlagsToString(EntityPropertyFlags propertiesFlags);
|
||||
|
||||
|
||||
QDebug& operator<<(QDebug& dbg, const EntityPropertyFlags& f);
|
||||
|
||||
|
||||
#endif // hifi_EntityPropertyFlags_h
|
||||
|
|
|
@ -816,6 +816,10 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties&
|
|||
|
||||
QString previousUserdata;
|
||||
if (entity) {
|
||||
if (properties.hasTransformOrVelocityChanges() && entity->hasGrabs()) {
|
||||
// if an entity is grabbed, the grab will override any position changes
|
||||
properties.clearTransformOrVelocityChanges();
|
||||
}
|
||||
if (properties.hasSimulationRestrictedChanges()) {
|
||||
if (_bidOnSimulationOwnership) {
|
||||
// flag for simulation ownership, or upgrade existing ownership priority
|
||||
|
@ -2275,3 +2279,126 @@ const EntityPropertyInfo EntityScriptingInterface::getPropertyInfo(const QScript
|
|||
EntityItemProperties::getPropertyInfo(name, propertyInfo);
|
||||
return propertyInfo;
|
||||
}
|
||||
|
||||
glm::vec3 EntityScriptingInterface::worldToLocalPosition(glm::vec3 worldPosition, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::vec3 localPosition = SpatiallyNestable::worldToLocal(worldPosition, parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return localPosition;
|
||||
} else {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glm::quat EntityScriptingInterface::worldToLocalRotation(glm::quat worldRotation, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::quat localRotation = SpatiallyNestable::worldToLocal(worldRotation, parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return localRotation;
|
||||
} else {
|
||||
return glm::quat();
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 EntityScriptingInterface::worldToLocalVelocity(glm::vec3 worldVelocity, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::vec3 localVelocity = SpatiallyNestable::worldToLocalVelocity(worldVelocity, parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return localVelocity;
|
||||
} else {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 EntityScriptingInterface::worldToLocalAngularVelocity(glm::vec3 worldAngularVelocity, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::vec3 localAngularVelocity = SpatiallyNestable::worldToLocalAngularVelocity(worldAngularVelocity, parentID,
|
||||
parentJointIndex, scalesWithParent,
|
||||
success);
|
||||
if (success) {
|
||||
return localAngularVelocity;
|
||||
} else {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 EntityScriptingInterface::worldToLocalDimensions(glm::vec3 worldDimensions, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
|
||||
bool success;
|
||||
glm::vec3 localDimensions = SpatiallyNestable::worldToLocalDimensions(worldDimensions, parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return localDimensions;
|
||||
} else {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 EntityScriptingInterface::localToWorldPosition(glm::vec3 localPosition, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::vec3 worldPosition = SpatiallyNestable::localToWorld(localPosition, parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return worldPosition;
|
||||
} else {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glm::quat EntityScriptingInterface::localToWorldRotation(glm::quat localRotation, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::quat worldRotation = SpatiallyNestable::localToWorld(localRotation, parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return worldRotation;
|
||||
} else {
|
||||
return glm::quat();
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 EntityScriptingInterface::localToWorldVelocity(glm::vec3 localVelocity, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::vec3 worldVelocity = SpatiallyNestable::localToWorldVelocity(localVelocity, parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return worldVelocity;
|
||||
} else {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 EntityScriptingInterface::localToWorldAngularVelocity(glm::vec3 localAngularVelocity, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::vec3 worldAngularVelocity = SpatiallyNestable::localToWorldAngularVelocity(localAngularVelocity,
|
||||
parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return worldAngularVelocity;
|
||||
} else {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 EntityScriptingInterface::localToWorldDimensions(glm::vec3 localDimensions, const QUuid& parentID,
|
||||
int parentJointIndex, bool scalesWithParent) {
|
||||
bool success;
|
||||
glm::vec3 worldDimensions = SpatiallyNestable::localToWorldDimensions(localDimensions, parentID, parentJointIndex,
|
||||
scalesWithParent, success);
|
||||
if (success) {
|
||||
return worldDimensions;
|
||||
} else {
|
||||
return glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1573,6 +1573,109 @@ public slots:
|
|||
* print("Scale: " + JSON.stringify(Mat4.extractScale(transform))); // { x: 1, y: 1, z: 1 } */
|
||||
Q_INVOKABLE glm::mat4 getEntityLocalTransform(const QUuid& entityID);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* @function Entities.worldToLocalPosition
|
||||
* @param {Vec3} worldPosition
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 worldToLocalPosition(glm::vec3 worldPosition, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.worldToLocalRotation
|
||||
* @param {Quat} worldRotation
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Quat}
|
||||
*/
|
||||
Q_INVOKABLE glm::quat worldToLocalRotation(glm::quat worldRotation, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.worldToLocalVelocity
|
||||
* @param {Vec3} worldVelocity
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 worldToLocalVelocity(glm::vec3 worldVelocity, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.worldToLocalAngularVelocity
|
||||
* @param {Vec3} worldAngularVelocity
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 worldToLocalAngularVelocity(glm::vec3 worldAngularVelocity, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.worldToLocalDimensions
|
||||
* @param {Vec3} worldDimensions
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 worldToLocalDimensions(glm::vec3 worldDimensions, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.localToWorldPosition
|
||||
* @param {Vec3} localPosition
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 localToWorldPosition(glm::vec3 localPosition, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.localToWorldRotation
|
||||
* @param {Quat} localRotation
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Quat}
|
||||
*/
|
||||
Q_INVOKABLE glm::quat localToWorldRotation(glm::quat localRotation, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.localToWorldVelocity
|
||||
* @param {Vec3} localVelocity
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 localToWorldVelocity(glm::vec3 localVelocity, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.localToWorldAngularVelocity
|
||||
* @param {Vec3} localAngularVelocity
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 localToWorldAngularVelocity(glm::vec3 localAngularVelocity, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
/**jsdoc
|
||||
* @function Entities.localToWorldDimensions
|
||||
* @param {Vec3} localDimensions
|
||||
* @param {Uuid} parentID
|
||||
* @param {number} parentJointIndex
|
||||
* @param {boolean} scalesWithparent
|
||||
* @returns {Vec3}
|
||||
*/
|
||||
Q_INVOKABLE glm::vec3 localToWorldDimensions(glm::vec3 localDimensions, const QUuid& parentID,
|
||||
int parentJointIndex = -1, bool scalesWithParent = false);
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* Get the static certificate for an entity. The static certificate contains static properties of the item which cannot
|
||||
* be altered.
|
||||
|
|
|
@ -2586,6 +2586,8 @@ void convertGrabUserDataToProperties(EntityItemProperties& properties) {
|
|||
grabProperties.setEquippable(equippable.toBool());
|
||||
}
|
||||
|
||||
grabProperties.setGrabDelegateToParent(true);
|
||||
|
||||
if (grabbableKey["spatialKey"].isObject()) {
|
||||
QJsonObject spatialKey = grabbableKey["spatialKey"].toObject();
|
||||
grabProperties.setEquippable(true);
|
||||
|
@ -2956,3 +2958,50 @@ bool EntityTree::removeMaterialFromOverlay(const QUuid& overlayID, graphics::Mat
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EntityTree::updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||
MovingEntitiesOperator& moveOperator, bool force, bool tellServer) {
|
||||
// if the queryBox has changed, tell the entity-server
|
||||
EntityItemPointer entity = std::dynamic_pointer_cast<EntityItem>(object);
|
||||
if (entity && (entity->updateQueryAACube() || force)) {
|
||||
bool success;
|
||||
AACube newCube = entity->getQueryAACube(success);
|
||||
if (success) {
|
||||
moveOperator.addEntityToMoveList(entity, newCube);
|
||||
}
|
||||
// send an edit packet to update the entity-server about the queryAABox. We do this for domain-hosted
|
||||
// entities as well as for avatar-entities; the packet-sender will route the update accordingly
|
||||
if (tellServer && packetSender && (entity->isDomainEntity() || entity->isAvatarEntity())) {
|
||||
quint64 now = usecTimestampNow();
|
||||
EntityItemProperties properties = entity->getProperties();
|
||||
properties.setQueryAACubeDirty();
|
||||
properties.setLocationDirty();
|
||||
properties.setLastEdited(now);
|
||||
|
||||
packetSender->queueEditEntityMessage(PacketType::EntityEdit, getThisPointer(), entity->getID(), properties);
|
||||
entity->setLastBroadcast(now); // for debug/physics status icons
|
||||
}
|
||||
|
||||
entity->markDirtyFlags(Simulation::DIRTY_POSITION);
|
||||
entityChanged(entity);
|
||||
}
|
||||
|
||||
object->forEachDescendant([&](SpatiallyNestablePointer descendant) {
|
||||
updateEntityQueryAACubeWorker(descendant, packetSender, moveOperator, force, tellServer);
|
||||
});
|
||||
}
|
||||
|
||||
void EntityTree::updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||
bool force, bool tellServer) {
|
||||
// This is used when something other than a script or physics moves an entity. We need to put it in the
|
||||
// correct place in our local octree, update its and its children's queryAACubes, and send an edit
|
||||
// packet to the entity-server.
|
||||
MovingEntitiesOperator moveOperator;
|
||||
|
||||
updateEntityQueryAACubeWorker(object, packetSender, moveOperator, force, tellServer);
|
||||
|
||||
if (moveOperator.hasMovingEntities()) {
|
||||
PerformanceTimer perfTimer("recurseTreeWithOperator");
|
||||
recurseTreeWithOperator(&moveOperator);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -277,6 +277,9 @@ public:
|
|||
|
||||
std::map<QString, QString> getNamedPaths() const { return _namedPaths; }
|
||||
|
||||
void updateEntityQueryAACube(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||
bool force, bool tellServer);
|
||||
|
||||
signals:
|
||||
void deletingEntity(const EntityItemID& entityID);
|
||||
void deletingEntityPointer(EntityItem* entityID);
|
||||
|
@ -392,6 +395,9 @@ private:
|
|||
bool _serverlessDomain { false };
|
||||
|
||||
std::map<QString, QString> _namedPaths;
|
||||
|
||||
void updateEntityQueryAACubeWorker(SpatiallyNestablePointer object, EntityEditPacketSender* packetSender,
|
||||
MovingEntitiesOperator& moveOperator, bool force, bool tellServer);
|
||||
};
|
||||
|
||||
void convertGrabUserDataToProperties(EntityItemProperties& properties);
|
||||
|
|
|
@ -24,6 +24,8 @@ void GrabPropertyGroup::copyToScriptValue(const EntityPropertyFlags& desiredProp
|
|||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_FOLLOWS_CONTROLLER, Grab, grab, GrabFollowsController, grabFollowsController);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_TRIGGERABLE, Grab, grab, Triggerable, triggerable);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_EQUIPPABLE, Grab, grab, Equippable, equippable);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_DELEGATE_TO_PARENT, Grab, grab,
|
||||
GrabDelegateToParent, grabDelegateToParent);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET, Grab, grab,
|
||||
EquippableLeftPosition, equippableLeftPosition);
|
||||
COPY_GROUP_PROPERTY_TO_QSCRIPTVALUE(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET, Grab, grab,
|
||||
|
@ -141,6 +143,7 @@ bool GrabPropertyGroup::appendToEditPacket(OctreePacketData* packetData,
|
|||
APPEND_ENTITY_PROPERTY(PROP_GRAB_FOLLOWS_CONTROLLER, getGrabFollowsController());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_TRIGGERABLE, getTriggerable());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_EQUIPPABLE, getEquippable());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_DELEGATE_TO_PARENT, getGrabDelegateToParent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET, getEquippableLeftPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET, getEquippableLeftRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET, getEquippableRightPosition());
|
||||
|
@ -164,6 +167,7 @@ bool GrabPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags,
|
|||
READ_ENTITY_PROPERTY(PROP_GRAB_FOLLOWS_CONTROLLER, bool, setGrabFollowsController);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_TRIGGERABLE, bool, setTriggerable);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_EQUIPPABLE, bool, setEquippable);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_DELEGATE_TO_PARENT, bool, setGrabDelegateToParent);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET, glm::vec3, setEquippableLeftPosition);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET, glm::quat, setEquippableLeftRotation);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET, glm::vec3, setEquippableRightPosition);
|
||||
|
@ -177,6 +181,7 @@ bool GrabPropertyGroup::decodeFromEditPacket(EntityPropertyFlags& propertyFlags,
|
|||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_GRAB_FOLLOWS_CONTROLLER, GrabFollowsController);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_GRAB_TRIGGERABLE, Triggerable);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_GRAB_EQUIPPABLE, Equippable);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_GRAB_DELEGATE_TO_PARENT, GrabDelegateToParent);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET, EquippableLeftPosition);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET, EquippableLeftRotation);
|
||||
DECODE_GROUP_PROPERTY_HAS_CHANGED(PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET, EquippableRightPosition);
|
||||
|
@ -215,6 +220,7 @@ EntityPropertyFlags GrabPropertyGroup::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_GRAB_FOLLOWS_CONTROLLER, grabFollowsController);
|
||||
CHECK_PROPERTY_CHANGE(PROP_GRAB_TRIGGERABLE, triggerable);
|
||||
CHECK_PROPERTY_CHANGE(PROP_GRAB_EQUIPPABLE, equippable);
|
||||
CHECK_PROPERTY_CHANGE(PROP_GRAB_DELEGATE_TO_PARENT, grabDelegateToParent);
|
||||
CHECK_PROPERTY_CHANGE(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET, equippableLeftPosition);
|
||||
CHECK_PROPERTY_CHANGE(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET, equippableLeftRotation);
|
||||
CHECK_PROPERTY_CHANGE(PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET, equippableRightPosition);
|
||||
|
@ -273,6 +279,7 @@ EntityPropertyFlags GrabPropertyGroup::getEntityProperties(EncodeBitstreamParams
|
|||
requestedProperties += PROP_GRAB_FOLLOWS_CONTROLLER;
|
||||
requestedProperties += PROP_GRAB_TRIGGERABLE;
|
||||
requestedProperties += PROP_GRAB_EQUIPPABLE;
|
||||
requestedProperties += PROP_GRAB_DELEGATE_TO_PARENT;
|
||||
requestedProperties += PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET;
|
||||
requestedProperties += PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET;
|
||||
requestedProperties += PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET;
|
||||
|
@ -299,6 +306,7 @@ void GrabPropertyGroup::appendSubclassData(OctreePacketData* packetData, EncodeB
|
|||
APPEND_ENTITY_PROPERTY(PROP_GRAB_FOLLOWS_CONTROLLER, getGrabFollowsController());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_TRIGGERABLE, getTriggerable());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_EQUIPPABLE, getEquippable());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_DELEGATE_TO_PARENT, getGrabDelegateToParent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET, getEquippableLeftPosition());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET, getEquippableLeftRotation());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET, getEquippableRightPosition());
|
||||
|
@ -321,6 +329,7 @@ int GrabPropertyGroup::readEntitySubclassDataFromBuffer(const unsigned char* dat
|
|||
READ_ENTITY_PROPERTY(PROP_GRAB_FOLLOWS_CONTROLLER, bool, setGrabFollowsController);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_TRIGGERABLE, bool, setTriggerable);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_EQUIPPABLE, bool, setEquippable);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_DELEGATE_TO_PARENT, bool, setGrabDelegateToParent);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET, glm::vec3, setEquippableLeftPosition);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET, glm::quat, setEquippableLeftRotation);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAB_RIGHT_EQUIPPABLE_POSITION_OFFSET, glm::vec3, setEquippableRightPosition);
|
||||
|
|
|
@ -31,6 +31,7 @@ static const bool INITIAL_KINEMATIC { true };
|
|||
static const bool INITIAL_FOLLOWS_CONTROLLER { true };
|
||||
static const bool INITIAL_TRIGGERABLE { false };
|
||||
static const bool INITIAL_EQUIPPABLE { false };
|
||||
static const bool INITIAL_GRAB_DELEGATE_TO_PARENT { true };
|
||||
static const glm::vec3 INITIAL_LEFT_EQUIPPABLE_POSITION { glm::vec3(0.0f) };
|
||||
static const glm::quat INITIAL_LEFT_EQUIPPABLE_ROTATION { glm::quat() };
|
||||
static const glm::vec3 INITIAL_RIGHT_EQUIPPABLE_POSITION { glm::vec3(0.0f) };
|
||||
|
@ -123,6 +124,8 @@ public:
|
|||
INITIAL_FOLLOWS_CONTROLLER);
|
||||
DEFINE_PROPERTY(PROP_GRAB_TRIGGERABLE, Triggerable, triggerable, bool, INITIAL_TRIGGERABLE);
|
||||
DEFINE_PROPERTY(PROP_GRAB_EQUIPPABLE, Equippable, equippable, bool, INITIAL_EQUIPPABLE);
|
||||
DEFINE_PROPERTY(PROP_GRAB_DELEGATE_TO_PARENT, GrabDelegateToParent, grabDelegateToParent, bool,
|
||||
INITIAL_GRAB_DELEGATE_TO_PARENT);
|
||||
DEFINE_PROPERTY_REF(PROP_GRAB_LEFT_EQUIPPABLE_POSITION_OFFSET, EquippableLeftPosition, equippableLeftPosition,
|
||||
glm::vec3, INITIAL_LEFT_EQUIPPABLE_POSITION);
|
||||
DEFINE_PROPERTY_REF(PROP_GRAB_LEFT_EQUIPPABLE_ROTATION_OFFSET, EquippableLeftRotation, equippableLeftRotation,
|
||||
|
|
|
@ -30,30 +30,30 @@ void ImageEntityItem::setUnscaledDimensions(const glm::vec3& value) {
|
|||
EntityItemProperties ImageEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(imageURL, getImageURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emissive, getEmissive);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(keepAspectRatio, getKeepAspectRatio);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(subImage, getSubImage);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool ImageEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(imageURL, setImageURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emissive, setEmissive);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(keepAspectRatio, setKeepAspectRatio);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(subImage, setSubImage);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
|
@ -75,30 +75,30 @@ int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_IMAGE_URL, QString, setImageURL);
|
||||
READ_ENTITY_PROPERTY(PROP_EMISSIVE, bool, setEmissive);
|
||||
READ_ENTITY_PROPERTY(PROP_KEEP_ASPECT_RATIO, bool, setKeepAspectRatio);
|
||||
READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode);
|
||||
READ_ENTITY_PROPERTY(PROP_SUB_IMAGE, QRect, setSubImage);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_ALPHA;
|
||||
|
||||
requestedProperties += PROP_IMAGE_URL;
|
||||
requestedProperties += PROP_EMISSIVE;
|
||||
requestedProperties += PROP_KEEP_ASPECT_RATIO;
|
||||
requestedProperties += PROP_BILLBOARD_MODE;
|
||||
requestedProperties += PROP_SUB_IMAGE;
|
||||
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_ALPHA;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -112,14 +112,14 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, getImageURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMISSIVE, getEmissive());
|
||||
APPEND_ENTITY_PROPERTY(PROP_KEEP_ASPECT_RATIO, getKeepAspectRatio());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SUB_IMAGE, getSubImage());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
|
||||
}
|
||||
|
||||
bool ImageEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
|
|
@ -73,8 +73,8 @@ void LightEntityItem::dimensionsChanged() {
|
|||
EntityItemProperties LightEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isSpotlight, getIsSpotlight);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isSpotlight, getIsSpotlight);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(intensity, getIntensity);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(exponent, getExponent);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(cutoff, getCutoff);
|
||||
|
@ -157,8 +157,8 @@ bool LightEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
bool LightEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = EntityItem::setSubClassProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isSpotlight, setIsSpotlight);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isSpotlight, setIsSpotlight);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(intensity, setIntensity);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(exponent, setExponent);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(cutoff, setCutoff);
|
||||
|
@ -176,8 +176,8 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, bool, setIsSpotlight);
|
||||
READ_ENTITY_PROPERTY(PROP_INTENSITY, float, setIntensity);
|
||||
READ_ENTITY_PROPERTY(PROP_EXPONENT, float, setExponent);
|
||||
READ_ENTITY_PROPERTY(PROP_CUTOFF, float, setCutoff);
|
||||
|
@ -189,8 +189,8 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
|
||||
EntityPropertyFlags LightEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_IS_SPOTLIGHT;
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_IS_SPOTLIGHT;
|
||||
requestedProperties += PROP_INTENSITY;
|
||||
requestedProperties += PROP_EXPONENT;
|
||||
requestedProperties += PROP_CUTOFF;
|
||||
|
@ -207,8 +207,8 @@ void LightEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_SPOTLIGHT, getIsSpotlight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_INTENSITY, getIntensity());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EXPONENT, getExponent());
|
||||
APPEND_ENTITY_PROPERTY(PROP_CUTOFF, getCutoff());
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "EntityTreeElement.h"
|
||||
#include "OctreeConstants.h"
|
||||
|
||||
const float LineEntityItem::DEFAULT_LINE_WIDTH = 2.0f;
|
||||
const int LineEntityItem::MAX_POINTS_PER_LINE = 70;
|
||||
|
||||
|
||||
|
@ -42,7 +41,6 @@ EntityItemProperties LineEntityItem::getProperties(const EntityPropertyFlags& de
|
|||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineWidth, getLineWidth);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(linePoints, getLinePoints);
|
||||
|
||||
return properties;
|
||||
|
@ -53,7 +51,6 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineWidth, setLineWidth);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
|
||||
|
||||
if (somethingChanged) {
|
||||
|
@ -115,7 +112,6 @@ int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_WIDTH, float, setLineWidth);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
|
||||
return bytesRead;
|
||||
|
@ -125,7 +121,6 @@ int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
EntityPropertyFlags LineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_LINE_WIDTH;
|
||||
requestedProperties += PROP_LINE_POINTS;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -141,7 +136,6 @@ void LineEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, getLineWidth());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints());
|
||||
}
|
||||
|
||||
|
@ -166,20 +160,6 @@ void LineEntityItem::setColor(const glm::u8vec3& value) {
|
|||
});
|
||||
}
|
||||
|
||||
void LineEntityItem::setLineWidth(float lineWidth) {
|
||||
withWriteLock([&] {
|
||||
_lineWidth = lineWidth;
|
||||
});
|
||||
}
|
||||
|
||||
float LineEntityItem::getLineWidth() const {
|
||||
float result;
|
||||
withReadLock([&] {
|
||||
result = _lineWidth;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<glm::vec3> LineEntityItem::getLinePoints() const {
|
||||
QVector<glm::vec3> result;
|
||||
withReadLock([&] {
|
||||
|
|
|
@ -44,9 +44,6 @@ class LineEntityItem : public EntityItem {
|
|||
glm::u8vec3 getColor() const;
|
||||
void setColor(const glm::u8vec3& value);
|
||||
|
||||
void setLineWidth(float lineWidth);
|
||||
float getLineWidth() const;
|
||||
|
||||
bool setLinePoints(const QVector<glm::vec3>& points);
|
||||
bool appendPoint(const glm::vec3& point);
|
||||
|
||||
|
@ -69,12 +66,10 @@ class LineEntityItem : public EntityItem {
|
|||
bool pointsChanged() const { return _pointsChanged; }
|
||||
void resetPointsChanged();
|
||||
virtual void debugDump() const override;
|
||||
static const float DEFAULT_LINE_WIDTH;
|
||||
static const int MAX_POINTS_PER_LINE;
|
||||
|
||||
private:
|
||||
glm::u8vec3 _color;
|
||||
float _lineWidth { DEFAULT_LINE_WIDTH };
|
||||
QVector<glm::vec3> _points;
|
||||
bool _pointsChanged { true };
|
||||
};
|
||||
|
|
|
@ -55,11 +55,13 @@ void ModelEntityItem::setTextures(const QString& textures) {
|
|||
|
||||
EntityItemProperties ModelEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointRotationsSet, getJointRotationsSet);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointRotations, getJointRotations);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(jointTranslationsSet, getJointTranslationsSet);
|
||||
|
@ -75,11 +77,12 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
bool somethingChanged = false;
|
||||
somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointRotationsSet, setJointRotationsSet);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointRotations, setJointRotations);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(jointTranslationsSet, setJointTranslationsSet);
|
||||
|
@ -116,11 +119,12 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
const unsigned char* dataAt = data;
|
||||
bool animationPropertiesChanged = false;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL);
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_MODEL_URL, QString, setModelURL);
|
||||
READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, QVector<bool>, setJointRotationsSet);
|
||||
READ_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, QVector<glm::quat>, setJointRotations);
|
||||
READ_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, QVector<bool>, setJointTranslationsSet);
|
||||
|
@ -151,11 +155,12 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_MODEL_URL;
|
||||
requestedProperties += PROP_COMPOUND_SHAPE_URL;
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
requestedProperties += PROP_SHAPE_TYPE;
|
||||
requestedProperties += PROP_COMPOUND_SHAPE_URL;
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
|
||||
requestedProperties += PROP_MODEL_URL;
|
||||
requestedProperties += PROP_JOINT_ROTATIONS_SET;
|
||||
requestedProperties += PROP_JOINT_ROTATIONS;
|
||||
requestedProperties += PROP_JOINT_TRANSLATIONS_SET;
|
||||
|
@ -176,11 +181,12 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS_SET, getJointRotationsSet());
|
||||
APPEND_ENTITY_PROPERTY(PROP_JOINT_ROTATIONS, getJointRotations());
|
||||
APPEND_ENTITY_PROPERTY(PROP_JOINT_TRANSLATIONS_SET, getJointTranslationsSet());
|
||||
|
|
|
@ -410,6 +410,10 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(const EntityPropert
|
|||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(maxParticles, getMaxParticles);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lifespan, getLifespan);
|
||||
|
||||
|
@ -434,17 +438,14 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(const EntityPropert
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(radiusStart, getRadiusStart);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(radiusFinish, getRadiusFinish);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(colorSpread, getColorSpread);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(colorStart, getColorStart);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(colorFinish, getColorFinish);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaSpread, getAlphaSpread);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaStart, getAlphaStart);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaFinish, getAlphaFinish);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitterShouldTrail, getEmitterShouldTrail);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleSpin, getParticleSpin);
|
||||
|
@ -460,6 +461,10 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
|
|||
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(maxParticles, setMaxParticles);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifespan, setLifespan);
|
||||
|
||||
|
@ -484,17 +489,14 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(radiusStart, setRadiusStart);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(radiusFinish, setRadiusFinish);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(colorSpread, setColorSpread);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(colorStart, setColorStart);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(colorFinish, setColorFinish);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaSpread, setAlphaSpread);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaStart, setAlphaStart);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaFinish, setAlphaFinish);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitterShouldTrail, setEmitterShouldTrail);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleSpin, setParticleSpin);
|
||||
|
@ -531,6 +533,10 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_MAX_PARTICLES, quint32, setMaxParticles);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFESPAN, float, setLifespan);
|
||||
|
||||
|
@ -555,17 +561,14 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
READ_ENTITY_PROPERTY(PROP_RADIUS_START, float, setRadiusStart);
|
||||
READ_ENTITY_PROPERTY(PROP_RADIUS_FINISH, float, setRadiusFinish);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, u8vec3Color, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_SPREAD, u8vec3Color, setColorSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_START, vec3Color, setColorStart);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR_FINISH, vec3Color, setColorFinish);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, float, setAlphaSpread);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_START, float, setAlphaStart);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA_FINISH, float, setAlphaFinish);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
READ_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_PARTICLE_SPIN, float, setParticleSpin);
|
||||
|
@ -581,6 +584,10 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea
|
|||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
|
||||
requestedProperties += PROP_SHAPE_TYPE;
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_ALPHA;
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
|
||||
requestedProperties += PROP_MAX_PARTICLES;
|
||||
requestedProperties += PROP_LIFESPAN;
|
||||
|
||||
|
@ -605,17 +612,14 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea
|
|||
requestedProperties += PROP_RADIUS_START;
|
||||
requestedProperties += PROP_RADIUS_FINISH;
|
||||
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_COLOR_SPREAD;
|
||||
requestedProperties += PROP_COLOR_START;
|
||||
requestedProperties += PROP_COLOR_FINISH;
|
||||
|
||||
requestedProperties += PROP_ALPHA;
|
||||
requestedProperties += PROP_ALPHA_SPREAD;
|
||||
requestedProperties += PROP_ALPHA_START;
|
||||
requestedProperties += PROP_ALPHA_FINISH;
|
||||
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
requestedProperties += PROP_EMITTER_SHOULD_TRAIL;
|
||||
|
||||
requestedProperties += PROP_PARTICLE_SPIN;
|
||||
|
@ -637,10 +641,14 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
|
|||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_MAX_PARTICLES, getMaxParticles());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LIFESPAN, getLifespan());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, getIsEmitting());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMITTING_PARTICLES, getIsEmitting());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_RATE, getEmitRate());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMIT_SPEED, getEmitSpeed());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SPEED_SPREAD, getSpeedSpread());
|
||||
|
@ -661,17 +669,14 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
|
|||
APPEND_ENTITY_PROPERTY(PROP_RADIUS_START, getRadiusStart());
|
||||
APPEND_ENTITY_PROPERTY(PROP_RADIUS_FINISH, getRadiusFinish());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR_SPREAD, getColorSpread());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR_START, getColorStart());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR_FINISH, getColorFinish());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, getAlphaSpread());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, getAlphaStart());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, getAlphaFinish());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, getEmitterShouldTrail());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_PARTICLE_SPIN, getParticleSpin());
|
||||
|
|
|
@ -41,13 +41,12 @@ EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags
|
|||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineWidth, getLineWidth);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(linePoints, getLinePoints);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(linePoints, getLinePoints);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeWidths, getStrokeWidths);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(normals, getNormals);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeColors, getStrokeColors);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeWidths, getStrokeWidths);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isUVModeStretch, getIsUVModeStretch);
|
||||
return properties;
|
||||
}
|
||||
|
@ -58,13 +57,12 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineWidth, setLineWidth);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeWidths, setStrokeWidths);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(normals, setNormals);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeColors, setStrokeColors);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeWidths, setStrokeWidths);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isUVModeStretch, setIsUVModeStretch);
|
||||
|
||||
if (somethingChanged) {
|
||||
|
@ -203,13 +201,12 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
|
|||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_WIDTH, float, setLineWidth);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_NORMALS, QVector<glm::vec3>, setNormals);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_COLORS, QVector<glm::vec3>, setStrokeColors);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXTURES, QString, setTextures);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_NORMALS, QVector<glm::vec3>, setNormals);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_COLORS, QVector<glm::vec3>, setStrokeColors);
|
||||
READ_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, bool, setIsUVModeStretch);
|
||||
|
||||
return bytesRead;
|
||||
|
@ -218,13 +215,12 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
|
|||
EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_LINE_WIDTH;
|
||||
requestedProperties += PROP_LINE_POINTS;
|
||||
|
||||
requestedProperties += PROP_NORMALS;
|
||||
requestedProperties += PROP_STROKE_COLORS;
|
||||
requestedProperties += PROP_STROKE_WIDTHS;
|
||||
requestedProperties += PROP_TEXTURES;
|
||||
|
||||
requestedProperties += PROP_LINE_POINTS;
|
||||
requestedProperties += PROP_STROKE_WIDTHS;
|
||||
requestedProperties += PROP_STROKE_NORMALS;
|
||||
requestedProperties += PROP_STROKE_COLORS;
|
||||
requestedProperties += PROP_IS_UV_MODE_STRETCH;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -241,13 +237,12 @@ void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, Encode
|
|||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_WIDTH, getLineWidth());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_NORMALS, getNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, getStrokeColors());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, getStrokeWidths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, getTextures());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, getStrokeWidths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_NORMALS, getNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, getStrokeColors());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, getIsUVModeStretch());
|
||||
}
|
||||
|
||||
|
|
|
@ -44,9 +44,6 @@ class PolyLineEntityItem : public EntityItem {
|
|||
glm::u8vec3 getColor() const;
|
||||
void setColor(const glm::u8vec3& value);
|
||||
|
||||
void setLineWidth(float lineWidth){ _lineWidth = lineWidth; }
|
||||
float getLineWidth() const{ return _lineWidth; }
|
||||
|
||||
bool setLinePoints(const QVector<glm::vec3>& points);
|
||||
bool appendPoint(const glm::vec3& point);
|
||||
QVector<glm::vec3> getLinePoints() const;
|
||||
|
@ -99,7 +96,6 @@ private:
|
|||
|
||||
protected:
|
||||
glm::u8vec3 _color;
|
||||
float _lineWidth { DEFAULT_LINE_WIDTH };
|
||||
bool _pointsChanged { true };
|
||||
bool _normalsChanged { true };
|
||||
bool _strokeColorsChanged { true };
|
||||
|
|
|
@ -118,10 +118,10 @@ ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem(
|
|||
EntityItemProperties ShapeEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
properties.setShape(entity::stringFromShape(getShape()));
|
||||
properties._shapeChanged = false;
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
|
||||
properties.setShape(entity::stringFromShape(getShape()));
|
||||
properties._shapeChanged = false;
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
@ -158,9 +158,9 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) {
|
|||
bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -183,18 +183,18 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE, QString, setShape);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, glm::u8vec3, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE, QString, setShape);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_SHAPE;
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_ALPHA;
|
||||
requestedProperties += PROP_SHAPE;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -207,9 +207,9 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape()));
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA, getAlpha());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape()));
|
||||
}
|
||||
|
||||
void ShapeEntityItem::setColor(const glm::u8vec3& value) {
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
const QString TextEntityItem::DEFAULT_TEXT("");
|
||||
const float TextEntityItem::DEFAULT_LINE_HEIGHT = 0.1f;
|
||||
const glm::u8vec3 TextEntityItem::DEFAULT_TEXT_COLOR = { 255, 255, 255 };
|
||||
const float TextEntityItem::DEFAULT_TEXT_ALPHA = 1.0f;
|
||||
const glm::u8vec3 TextEntityItem::DEFAULT_BACKGROUND_COLOR = { 0, 0, 0};
|
||||
const float TextEntityItem::DEFAULT_MARGIN = 0.0f;
|
||||
|
||||
EntityItemPointer TextEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity(new TextEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
|
@ -50,8 +52,14 @@ EntityItemProperties TextEntityItem::getProperties(const EntityPropertyFlags& de
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(text, getText);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(lineHeight, getLineHeight);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textColor, getTextColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textAlpha, getTextAlpha);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundColor, getBackgroundColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(backgroundAlpha, getBackgroundAlpha);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(billboardMode, getBillboardMode);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(leftMargin, getLeftMargin);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(rightMargin, getRightMargin);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(topMargin, getTopMargin);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(bottomMargin, getBottomMargin);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -62,8 +70,14 @@ bool TextEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(text, setText);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(lineHeight, setLineHeight);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textColor, setTextColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textAlpha, setTextAlpha);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundColor, setBackgroundColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundAlpha, setBackgroundAlpha);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(billboardMode, setBillboardMode);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(leftMargin, setLeftMargin);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(rightMargin, setRightMargin);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(topMargin, setTopMargin);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(bottomMargin, setBottomMargin);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -90,8 +104,14 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
READ_ENTITY_PROPERTY(PROP_TEXT, QString, setText);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_HEIGHT, float, setLineHeight);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXT_COLOR, glm::u8vec3, setTextColor);
|
||||
READ_ENTITY_PROPERTY(PROP_TEXT_ALPHA, float, setTextAlpha);
|
||||
READ_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, glm::u8vec3, setBackgroundColor);
|
||||
READ_ENTITY_PROPERTY(PROP_BACKGROUND_ALPHA, float, setBackgroundAlpha);
|
||||
READ_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, BillboardMode, setBillboardMode);
|
||||
READ_ENTITY_PROPERTY(PROP_LEFT_MARGIN, float, setLeftMargin);
|
||||
READ_ENTITY_PROPERTY(PROP_RIGHT_MARGIN, float, setRightMargin);
|
||||
READ_ENTITY_PROPERTY(PROP_TOP_MARGIN, float, setTopMargin);
|
||||
READ_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, float, setBottomMargin);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -101,8 +121,14 @@ EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& p
|
|||
requestedProperties += PROP_TEXT;
|
||||
requestedProperties += PROP_LINE_HEIGHT;
|
||||
requestedProperties += PROP_TEXT_COLOR;
|
||||
requestedProperties += PROP_TEXT_ALPHA;
|
||||
requestedProperties += PROP_BACKGROUND_COLOR;
|
||||
requestedProperties += PROP_BACKGROUND_ALPHA;
|
||||
requestedProperties += PROP_BILLBOARD_MODE;
|
||||
requestedProperties += PROP_LEFT_MARGIN;
|
||||
requestedProperties += PROP_RIGHT_MARGIN;
|
||||
requestedProperties += PROP_TOP_MARGIN;
|
||||
requestedProperties += PROP_BOTTOM_MARGIN;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -119,8 +145,14 @@ void TextEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
APPEND_ENTITY_PROPERTY(PROP_TEXT, getText());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, getLineHeight());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_COLOR, getTextColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXT_ALPHA, getTextAlpha());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_COLOR, getBackgroundColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_ALPHA, getBackgroundAlpha());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BILLBOARD_MODE, (uint32_t)getBillboardMode());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LEFT_MARGIN, getLeftMargin());
|
||||
APPEND_ENTITY_PROPERTY(PROP_RIGHT_MARGIN, getRightMargin());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TOP_MARGIN, getTopMargin());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BOTTOM_MARGIN, getBottomMargin());
|
||||
|
||||
}
|
||||
|
||||
|
@ -216,6 +248,18 @@ glm::u8vec3 TextEntityItem::getTextColor() const {
|
|||
});
|
||||
}
|
||||
|
||||
void TextEntityItem::setTextAlpha(float value) {
|
||||
withWriteLock([&] {
|
||||
_textAlpha = value;
|
||||
});
|
||||
}
|
||||
|
||||
float TextEntityItem::getTextAlpha() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _textAlpha;
|
||||
});
|
||||
}
|
||||
|
||||
void TextEntityItem::setBackgroundColor(const glm::u8vec3& value) {
|
||||
withWriteLock([&] {
|
||||
_backgroundColor = value;
|
||||
|
@ -228,6 +272,18 @@ glm::u8vec3 TextEntityItem::getBackgroundColor() const {
|
|||
});
|
||||
}
|
||||
|
||||
void TextEntityItem::setBackgroundAlpha(float value) {
|
||||
withWriteLock([&] {
|
||||
_backgroundAlpha = value;
|
||||
});
|
||||
}
|
||||
|
||||
float TextEntityItem::getBackgroundAlpha() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _backgroundAlpha;
|
||||
});
|
||||
}
|
||||
|
||||
BillboardMode TextEntityItem::getBillboardMode() const {
|
||||
BillboardMode result;
|
||||
withReadLock([&] {
|
||||
|
@ -242,3 +298,50 @@ void TextEntityItem::setBillboardMode(BillboardMode value) {
|
|||
});
|
||||
}
|
||||
|
||||
void TextEntityItem::setLeftMargin(float value) {
|
||||
withWriteLock([&] {
|
||||
_leftMargin = value;
|
||||
});
|
||||
}
|
||||
|
||||
float TextEntityItem::getLeftMargin() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _leftMargin;
|
||||
});
|
||||
}
|
||||
|
||||
void TextEntityItem::setRightMargin(float value) {
|
||||
withWriteLock([&] {
|
||||
_rightMargin = value;
|
||||
});
|
||||
}
|
||||
|
||||
float TextEntityItem::getRightMargin() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _rightMargin;
|
||||
});
|
||||
}
|
||||
|
||||
void TextEntityItem::setTopMargin(float value) {
|
||||
withWriteLock([&] {
|
||||
_topMargin = value;
|
||||
});
|
||||
}
|
||||
|
||||
float TextEntityItem::getTopMargin() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _topMargin;
|
||||
});
|
||||
}
|
||||
|
||||
void TextEntityItem::setBottomMargin(float value) {
|
||||
withWriteLock([&] {
|
||||
_bottomMargin = value;
|
||||
});
|
||||
}
|
||||
|
||||
float TextEntityItem::getBottomMargin() const {
|
||||
return resultWithReadLock<float>([&] {
|
||||
return _bottomMargin;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -67,19 +67,45 @@ public:
|
|||
glm::u8vec3 getTextColor() const;
|
||||
void setTextColor(const glm::u8vec3& value);
|
||||
|
||||
static const float DEFAULT_TEXT_ALPHA;
|
||||
float getTextAlpha() const;
|
||||
void setTextAlpha(float value);
|
||||
|
||||
static const glm::u8vec3 DEFAULT_BACKGROUND_COLOR;
|
||||
glm::u8vec3 getBackgroundColor() const;
|
||||
void setBackgroundColor(const glm::u8vec3& value);
|
||||
|
||||
float getBackgroundAlpha() const;
|
||||
void setBackgroundAlpha(float value);
|
||||
|
||||
BillboardMode getBillboardMode() const;
|
||||
void setBillboardMode(BillboardMode value);
|
||||
|
||||
static const float DEFAULT_MARGIN;
|
||||
float getLeftMargin() const;
|
||||
void setLeftMargin(float value);
|
||||
|
||||
float getRightMargin() const;
|
||||
void setRightMargin(float value);
|
||||
|
||||
float getTopMargin() const;
|
||||
void setTopMargin(float value);
|
||||
|
||||
float getBottomMargin() const;
|
||||
void setBottomMargin(float value);
|
||||
|
||||
private:
|
||||
QString _text;
|
||||
float _lineHeight;
|
||||
glm::u8vec3 _textColor;
|
||||
float _textAlpha;
|
||||
glm::u8vec3 _backgroundColor;
|
||||
float _backgroundAlpha;
|
||||
BillboardMode _billboardMode;
|
||||
float _leftMargin;
|
||||
float _rightMargin;
|
||||
float _topMargin;
|
||||
float _bottomMargin;
|
||||
};
|
||||
|
||||
#endif // hifi_TextEntityItem_h
|
||||
|
|
|
@ -48,6 +48,9 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(en
|
|||
EntityItemProperties ZoneEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
|
||||
|
||||
// Contain QString properties, must be synchronized
|
||||
withReadLock([&] {
|
||||
_keyLightProperties.getProperties(properties);
|
||||
|
@ -57,9 +60,6 @@ EntityItemProperties ZoneEntityItem::getProperties(const EntityPropertyFlags& de
|
|||
_hazeProperties.getProperties(properties);
|
||||
_bloomProperties.getProperties(properties);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(flyingAllowed, getFlyingAllowed);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(ghostingAllowed, getGhostingAllowed);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(filterURL, getFilterURL);
|
||||
|
@ -94,6 +94,9 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = EntityItem::setSubClassProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
|
||||
|
||||
// Contains a QString property, must be synchronized
|
||||
withWriteLock([&] {
|
||||
_keyLightPropertiesChanged = _keyLightProperties.setProperties(properties);
|
||||
|
@ -103,9 +106,6 @@ bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& propertie
|
|||
_hazePropertiesChanged = _hazeProperties.setProperties(properties);
|
||||
_bloomPropertiesChanged = _bloomProperties.setProperties(properties);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, setShapeType);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(flyingAllowed, setFlyingAllowed);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ghostingAllowed, setGhostingAllowed);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(filterURL, setFilterURL);
|
||||
|
@ -129,6 +129,9 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
|
||||
{
|
||||
int bytesFromKeylight;
|
||||
withWriteLock([&] {
|
||||
|
@ -178,9 +181,6 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
dataAt += bytesFromBloom;
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
READ_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, bool, setFlyingAllowed);
|
||||
READ_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed);
|
||||
READ_ENTITY_PROPERTY(PROP_FILTER_URL, QString, setFilterURL);
|
||||
|
@ -197,15 +197,15 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
|
||||
requestedProperties += PROP_SHAPE_TYPE;
|
||||
requestedProperties += PROP_COMPOUND_SHAPE_URL;
|
||||
|
||||
requestedProperties += _keyLightProperties.getEntityProperties(params);
|
||||
requestedProperties += _ambientLightProperties.getEntityProperties(params);
|
||||
requestedProperties += _skyboxProperties.getEntityProperties(params);
|
||||
requestedProperties += _hazeProperties.getEntityProperties(params);
|
||||
requestedProperties += _bloomProperties.getEntityProperties(params);
|
||||
|
||||
requestedProperties += PROP_SHAPE_TYPE;
|
||||
requestedProperties += PROP_COMPOUND_SHAPE_URL;
|
||||
|
||||
requestedProperties += PROP_FLYING_ALLOWED;
|
||||
requestedProperties += PROP_GHOSTING_ALLOWED;
|
||||
requestedProperties += PROP_FILTER_URL;
|
||||
|
@ -229,6 +229,9 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
|
||||
|
||||
withReadLock([&] {
|
||||
_keyLightProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
|
||||
propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
|
@ -242,9 +245,6 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
_bloomProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
|
||||
propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, getFlyingAllowed());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, getGhostingAllowed());
|
||||
APPEND_ENTITY_PROPERTY(PROP_FILTER_URL, getFilterURL());
|
||||
|
|
|
@ -1,190 +0,0 @@
|
|||
//
|
||||
// BandwidthMeter.cpp
|
||||
// interface/src/ui
|
||||
//
|
||||
// Created by Seth Alves on 2015-1-30
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Based on code by Tobias Schwinger
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "BandwidthRecorder.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
BandwidthRecorder::Channel::Channel() {
|
||||
}
|
||||
|
||||
float BandwidthRecorder::Channel::getAverageInputPacketsPerSecond() const {
|
||||
float averageTimeBetweenPackets = _input.getEventDeltaAverage();
|
||||
if (averageTimeBetweenPackets > 0.0f) {
|
||||
return (1.0f / averageTimeBetweenPackets);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::Channel::getAverageOutputPacketsPerSecond() const {
|
||||
float averageTimeBetweenPackets = _output.getEventDeltaAverage();
|
||||
if (averageTimeBetweenPackets > 0.0f) {
|
||||
return (1.0f / averageTimeBetweenPackets);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::Channel::getAverageInputKilobitsPerSecond() const {
|
||||
return (_input.getAverageSampleValuePerSecond() * (8.0f / 1000));
|
||||
}
|
||||
|
||||
float BandwidthRecorder::Channel::getAverageOutputKilobitsPerSecond() const {
|
||||
return (_output.getAverageSampleValuePerSecond() * (8.0f / 1000));
|
||||
}
|
||||
|
||||
|
||||
void BandwidthRecorder::Channel::updateInputAverage(const float sample) {
|
||||
_input.updateAverage(sample);
|
||||
}
|
||||
|
||||
void BandwidthRecorder::Channel::updateOutputAverage(const float sample) {
|
||||
_output.updateAverage(sample);
|
||||
}
|
||||
|
||||
BandwidthRecorder::BandwidthRecorder() {
|
||||
for (uint i=0; i<CHANNEL_COUNT; i++) {
|
||||
_channels[ i ] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
BandwidthRecorder::~BandwidthRecorder() {
|
||||
for (uint i=0; i<CHANNEL_COUNT; i++) {
|
||||
delete _channels[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
void BandwidthRecorder::updateInboundData(const quint8 channelType, const int sample) {
|
||||
if (! _channels[channelType]) {
|
||||
_channels[channelType] = new Channel();
|
||||
}
|
||||
_channels[channelType]->updateInputAverage(sample);
|
||||
}
|
||||
|
||||
void BandwidthRecorder::updateOutboundData(const quint8 channelType, const int sample) {
|
||||
if (! _channels[channelType]) {
|
||||
_channels[channelType] = new Channel();
|
||||
}
|
||||
_channels[channelType]->updateOutputAverage(sample);
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getAverageInputPacketsPerSecond(const quint8 channelType) const {
|
||||
if (! _channels[channelType]) {
|
||||
return 0.0f;
|
||||
}
|
||||
return _channels[channelType]->getAverageInputPacketsPerSecond();
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getAverageOutputPacketsPerSecond(const quint8 channelType) const {
|
||||
if (! _channels[channelType]) {
|
||||
return 0.0f;
|
||||
}
|
||||
return _channels[channelType]->getAverageOutputPacketsPerSecond();
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getAverageInputKilobitsPerSecond(const quint8 channelType) const {
|
||||
if (! _channels[channelType]) {
|
||||
return 0.0f;
|
||||
}
|
||||
return _channels[channelType]->getAverageInputKilobitsPerSecond();
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getAverageOutputKilobitsPerSecond(const quint8 channelType) const {
|
||||
if (! _channels[channelType]) {
|
||||
return 0.0f;
|
||||
}
|
||||
return _channels[channelType]->getAverageOutputKilobitsPerSecond();
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getTotalAverageInputPacketsPerSecond() const {
|
||||
float result = 0.0f;
|
||||
for (uint i=0; i<CHANNEL_COUNT; i++) {
|
||||
if (_channels[i]) {
|
||||
result += _channels[i]->getAverageInputPacketsPerSecond();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getTotalAverageOutputPacketsPerSecond() const {
|
||||
float result = 0.0f;
|
||||
for (uint i=0; i<CHANNEL_COUNT; i++) {
|
||||
if (_channels[i]) {
|
||||
result += _channels[i]->getAverageOutputPacketsPerSecond();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getTotalAverageInputKilobitsPerSecond() const {
|
||||
float result = 0.0f;
|
||||
for (uint i=0; i<CHANNEL_COUNT; i++) {
|
||||
if (_channels[i]) {
|
||||
result += _channels[i]->getAverageInputKilobitsPerSecond();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getTotalAverageOutputKilobitsPerSecond() const {
|
||||
float result = 0.0f;
|
||||
for (uint i=0; i<CHANNEL_COUNT; i++) {
|
||||
if (_channels[i]) {
|
||||
result += _channels[i]->getAverageOutputKilobitsPerSecond();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getCachedTotalAverageInputPacketsPerSecond() const {
|
||||
static qint64 lastCalculated = 0;
|
||||
static float cachedValue = 0.0f;
|
||||
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
||||
if (now - lastCalculated > 1000.0f) {
|
||||
lastCalculated = now;
|
||||
cachedValue = getTotalAverageInputPacketsPerSecond();
|
||||
}
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getCachedTotalAverageOutputPacketsPerSecond() const {
|
||||
static qint64 lastCalculated = 0;
|
||||
static float cachedValue = 0.0f;
|
||||
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
||||
if (now - lastCalculated > 1000.0f) {
|
||||
lastCalculated = now;
|
||||
cachedValue = getTotalAverageOutputPacketsPerSecond();
|
||||
}
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getCachedTotalAverageInputKilobitsPerSecond() const {
|
||||
static qint64 lastCalculated = 0;
|
||||
static float cachedValue = 0.0f;
|
||||
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
||||
if (now - lastCalculated > 1000.0f) {
|
||||
lastCalculated = now;
|
||||
cachedValue = getTotalAverageInputKilobitsPerSecond();
|
||||
}
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
float BandwidthRecorder::getCachedTotalAverageOutputKilobitsPerSecond() const {
|
||||
static qint64 lastCalculated = 0;
|
||||
static float cachedValue = 0.0f;
|
||||
qint64 now = QDateTime::currentMSecsSinceEpoch();
|
||||
if (now - lastCalculated > 1000.0f) {
|
||||
lastCalculated = now;
|
||||
cachedValue = getTotalAverageOutputKilobitsPerSecond();
|
||||
}
|
||||
return cachedValue;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
//
|
||||
// BandwidthRecorder.h
|
||||
//
|
||||
// Created by Seth Alves on 2015-1-30
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Based on code by Tobias Schwinger
|
||||
//
|
||||
// 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_BandwidthRecorder_h
|
||||
#define hifi_BandwidthRecorder_h
|
||||
|
||||
#include <QObject>
|
||||
#include <QElapsedTimer>
|
||||
#include "DependencyManager.h"
|
||||
#include "SimpleMovingAverage.h"
|
||||
|
||||
|
||||
class BandwidthRecorder : public QObject, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
BandwidthRecorder();
|
||||
~BandwidthRecorder();
|
||||
|
||||
// keep track of data rate in two directions as well as units and style to use during display
|
||||
class Channel {
|
||||
public:
|
||||
Channel();
|
||||
float getAverageInputPacketsPerSecond() const;
|
||||
float getAverageOutputPacketsPerSecond() const;
|
||||
float getAverageInputKilobitsPerSecond() const;
|
||||
float getAverageOutputKilobitsPerSecond() const;
|
||||
|
||||
void updateInputAverage(const float sample);
|
||||
void updateOutputAverage(const float sample);
|
||||
|
||||
private:
|
||||
SimpleMovingAverage _input;
|
||||
SimpleMovingAverage _output;
|
||||
};
|
||||
|
||||
float getAverageInputPacketsPerSecond(const quint8 channelType) const;
|
||||
float getAverageOutputPacketsPerSecond(const quint8 channelType) const;
|
||||
float getAverageInputKilobitsPerSecond(const quint8 channelType) const;
|
||||
float getAverageOutputKilobitsPerSecond(const quint8 channelType) const;
|
||||
|
||||
float getTotalAverageInputPacketsPerSecond() const;
|
||||
float getTotalAverageOutputPacketsPerSecond() const;
|
||||
float getTotalAverageInputKilobitsPerSecond() const;
|
||||
float getTotalAverageOutputKilobitsPerSecond() const;
|
||||
|
||||
float getCachedTotalAverageInputPacketsPerSecond() const;
|
||||
float getCachedTotalAverageOutputPacketsPerSecond() const;
|
||||
float getCachedTotalAverageInputKilobitsPerSecond() const;
|
||||
float getCachedTotalAverageOutputKilobitsPerSecond() const;
|
||||
|
||||
|
||||
private:
|
||||
// one for each possible Node type
|
||||
static const unsigned int CHANNEL_COUNT = 256;
|
||||
Channel* _channels[CHANNEL_COUNT];
|
||||
|
||||
|
||||
public slots:
|
||||
void updateInboundData(const quint8 channelType, const int bytes);
|
||||
void updateOutboundData(const quint8 channelType, const int bytes);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -83,6 +83,11 @@ LimitedNodeList::LimitedNodeList(int socketListenPort, int dtlsListenPort) :
|
|||
connect(silentNodeTimer, &QTimer::timeout, this, &LimitedNodeList::removeSilentNodes);
|
||||
silentNodeTimer->start(NODE_SILENCE_THRESHOLD_MSECS);
|
||||
|
||||
const int CONNECTION_STATS_SAMPLE_INTERVAL_MSECS = 1000;
|
||||
QTimer* statsSampleTimer = new QTimer(this);
|
||||
connect(statsSampleTimer, &QTimer::timeout, this, &LimitedNodeList::sampleConnectionStats);
|
||||
statsSampleTimer->start(CONNECTION_STATS_SAMPLE_INTERVAL_MSECS);
|
||||
|
||||
// check the local socket right now
|
||||
updateLocalSocket();
|
||||
|
||||
|
@ -295,17 +300,14 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
|||
});
|
||||
|
||||
if (sendingNodeType != NodeType::Unassigned) {
|
||||
emit dataReceived(sendingNodeType, packet.getPayloadSize());
|
||||
return true;
|
||||
} else {
|
||||
HIFI_FCDEBUG(networking(), "Replicated packet of type" << headerType
|
||||
<< "received from unknown upstream" << packet.getSenderSockAddr());
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
emit dataReceived(NodeType::Unassigned, packet.getPayloadSize());
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
@ -319,7 +321,7 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
|||
SharedNodePointer matchingNode = nodeWithLocalID(sourceLocalID);
|
||||
sourceNode = matchingNode.data();
|
||||
}
|
||||
|
||||
|
||||
QUuid sourceID = sourceNode ? sourceNode->getUUID() : QUuid();
|
||||
|
||||
if (!sourceNode &&
|
||||
|
@ -328,8 +330,6 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
|||
packet.getSenderSockAddr() == getDomainSockAddr() &&
|
||||
PacketTypeEnum::getDomainSourcedPackets().contains(headerType)) {
|
||||
// This is a packet sourced by the domain server
|
||||
|
||||
emit dataReceived(NodeType::Unassigned, packet.getPayloadSize());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -367,8 +367,6 @@ bool LimitedNodeList::packetSourceAndHashMatchAndTrackBandwidth(const udt::Packe
|
|||
// from this sending node
|
||||
sourceNode->setLastHeardMicrostamp(usecTimestampNow());
|
||||
|
||||
emit dataReceived(sourceNode->getType(), packet.getPayloadSize());
|
||||
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
@ -407,9 +405,6 @@ qint64 LimitedNodeList::sendUnreliablePacket(const NLPacket& packet, const Node&
|
|||
return 0;
|
||||
}
|
||||
|
||||
emit dataSent(destinationNode.getType(), packet.getDataSize());
|
||||
destinationNode.recordBytesSent(packet.getDataSize());
|
||||
|
||||
return sendUnreliablePacket(packet, *destinationNode.getActiveSocket(), destinationNode.getAuthenticateHash());
|
||||
}
|
||||
|
||||
|
@ -430,9 +425,6 @@ qint64 LimitedNodeList::sendPacket(std::unique_ptr<NLPacket> packet, const Node&
|
|||
auto activeSocket = destinationNode.getActiveSocket();
|
||||
|
||||
if (activeSocket) {
|
||||
emit dataSent(destinationNode.getType(), packet->getDataSize());
|
||||
destinationNode.recordBytesSent(packet->getDataSize());
|
||||
|
||||
return sendPacket(std::move(packet), *activeSocket, destinationNode.getAuthenticateHash());
|
||||
} else {
|
||||
qCDebug(networking) << "LimitedNodeList::sendPacket called without active socket for node" << destinationNode << "- not sending";
|
||||
|
@ -470,8 +462,6 @@ qint64 LimitedNodeList::sendUnreliableUnorderedPacketList(NLPacketList& packetLi
|
|||
bytesSent += sendPacket(packetList.takeFront<NLPacket>(), *activeSocket,
|
||||
connectionHash);
|
||||
}
|
||||
|
||||
emit dataSent(destinationNode.getType(), bytesSent);
|
||||
return bytesSent;
|
||||
} else {
|
||||
qCDebug(networking) << "LimitedNodeList::sendPacketList called without active socket for node" << destinationNode
|
||||
|
@ -887,10 +877,56 @@ void LimitedNodeList::removeSilentNodes() {
|
|||
}
|
||||
}
|
||||
|
||||
void LimitedNodeList::sampleConnectionStats() {
|
||||
uint32_t packetsIn { 0 };
|
||||
uint32_t packetsOut { 0 };
|
||||
uint64_t bytesIn { 0 };
|
||||
uint64_t bytesOut { 0 };
|
||||
int elapsedSum { 0 };
|
||||
int elapsedCount { 0 };
|
||||
|
||||
auto allStats = _nodeSocket.sampleStatsForAllConnections();
|
||||
for (const auto& stats : allStats) {
|
||||
auto node = findNodeWithAddr(stats.first);
|
||||
if (node && node->getActiveSocket() &&
|
||||
*node->getActiveSocket() == stats.first) {
|
||||
node->updateStats(stats.second);
|
||||
}
|
||||
|
||||
packetsIn += stats.second.receivedPackets;
|
||||
packetsIn += stats.second.receivedUnreliablePackets;
|
||||
packetsOut += stats.second.sentPackets;
|
||||
packetsOut += stats.second.sentUnreliablePackets;
|
||||
bytesIn += stats.second.receivedBytes;
|
||||
bytesIn += stats.second.receivedUnreliableBytes;
|
||||
bytesOut += stats.second.sentBytes;
|
||||
bytesOut += stats.second.sentUnreliableBytes;
|
||||
elapsedSum += (stats.second.endTime - stats.second.startTime).count();
|
||||
elapsedCount++;
|
||||
}
|
||||
|
||||
if (elapsedCount > 0) {
|
||||
float elapsedAvg = (float)elapsedSum / elapsedCount;
|
||||
float factor = USECS_PER_SECOND / elapsedAvg;
|
||||
|
||||
float kilobitsReceived = (float)bytesIn * BITS_IN_BYTE / BYTES_PER_KILOBYTE;
|
||||
float kilobitsSent = (float)bytesOut * BITS_IN_BYTE / BYTES_PER_KILOBYTE;
|
||||
|
||||
_inboundPPS = packetsIn * factor;
|
||||
_outboundPPS = packetsOut * factor;
|
||||
_inboundKbps = kilobitsReceived * factor;
|
||||
_outboundKbps = kilobitsSent * factor;
|
||||
} else {
|
||||
_inboundPPS = 0;
|
||||
_outboundPPS = 0;
|
||||
_inboundKbps = 0.0f;
|
||||
_outboundKbps = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t RFC_5389_MAGIC_COOKIE = 0x2112A442;
|
||||
const int NUM_BYTES_STUN_HEADER = 20;
|
||||
|
||||
|
||||
void LimitedNodeList::makeSTUNRequestPacket(char* stunRequestPacket) {
|
||||
int packetIndex = 0;
|
||||
|
||||
|
@ -1261,6 +1297,10 @@ void LimitedNodeList::flagTimeForConnectionStep(ConnectionStep connectionStep) {
|
|||
}
|
||||
|
||||
void LimitedNodeList::flagTimeForConnectionStep(ConnectionStep connectionStep, quint64 timestamp) {
|
||||
if (!_flagTimeForConnectionStep) {
|
||||
// this is only true in interface
|
||||
return;
|
||||
}
|
||||
if (connectionStep == ConnectionStep::LookupAddress) {
|
||||
QWriteLocker writeLock(&_connectionTimeLock);
|
||||
|
||||
|
|
|
@ -122,7 +122,7 @@ public:
|
|||
bool getThisNodeCanWriteAssets() const { return _permissions.can(NodePermissions::Permission::canWriteToAssetServer); }
|
||||
bool getThisNodeCanKick() const { return _permissions.can(NodePermissions::Permission::canKick); }
|
||||
bool getThisNodeCanReplaceContent() const { return _permissions.can(NodePermissions::Permission::canReplaceDomainContent); }
|
||||
|
||||
|
||||
quint16 getSocketLocalPort() const { return _nodeSocket.localPort(); }
|
||||
Q_INVOKABLE void setSocketLocalPort(quint16 socketLocalPort);
|
||||
|
||||
|
@ -204,9 +204,9 @@ public:
|
|||
// This allows multiple threads (i.e. a thread pool) to share a lock
|
||||
// without deadlocking when a dying node attempts to acquire a write lock
|
||||
template<typename NestedNodeLambda>
|
||||
void nestedEach(NestedNodeLambda functor,
|
||||
int* lockWaitOut = nullptr,
|
||||
int* nodeTransformOut = nullptr,
|
||||
void nestedEach(NestedNodeLambda functor,
|
||||
int* lockWaitOut = nullptr,
|
||||
int* nodeTransformOut = nullptr,
|
||||
int* functorOut = nullptr) {
|
||||
auto start = usecTimestampNow();
|
||||
{
|
||||
|
@ -310,12 +310,20 @@ public:
|
|||
void setAuthenticatePackets(bool useAuthentication) { _useAuthentication = useAuthentication; }
|
||||
bool getAuthenticatePackets() const { return _useAuthentication; }
|
||||
|
||||
void setFlagTimeForConnectionStep(bool flag) { _flagTimeForConnectionStep = flag; }
|
||||
bool isFlagTimeForConnectionStep() { return _flagTimeForConnectionStep; }
|
||||
|
||||
static void makeSTUNRequestPacket(char* stunRequestPacket);
|
||||
|
||||
#if (PR_BUILD || DEV_BUILD)
|
||||
void sendFakedHandshakeRequestToNode(SharedNodePointer node);
|
||||
#endif
|
||||
|
||||
int getInboundPPS() const { return _inboundPPS; }
|
||||
int getOutboundPPS() const { return _outboundPPS; }
|
||||
float getInboundKbps() const { return _inboundKbps; }
|
||||
float getOutboundKbps() const { return _outboundKbps; }
|
||||
|
||||
public slots:
|
||||
void reset();
|
||||
void eraseAllNodes();
|
||||
|
@ -329,10 +337,10 @@ public slots:
|
|||
|
||||
bool killNodeWithUUID(const QUuid& nodeUUID, ConnectionID newConnectionID = NULL_CONNECTION_ID);
|
||||
|
||||
signals:
|
||||
void dataSent(quint8 channelType, int bytes);
|
||||
void dataReceived(quint8 channelType, int bytes);
|
||||
private slots:
|
||||
void sampleConnectionStats();
|
||||
|
||||
signals:
|
||||
// QUuid might be zero for non-sourced packet types.
|
||||
void packetVersionMismatch(PacketType type, const HifiSockAddr& senderSockAddr, const QUuid& senderUUID);
|
||||
|
||||
|
@ -369,8 +377,6 @@ protected:
|
|||
|
||||
qint64 sendPacket(std::unique_ptr<NLPacket> packet, const Node& destinationNode,
|
||||
const HifiSockAddr& overridenSockAddr);
|
||||
qint64 writePacket(const NLPacket& packet, const HifiSockAddr& destinationSockAddr,
|
||||
const QUuid& connectionSecret = QUuid());
|
||||
void collectPacketStats(const NLPacket& packet);
|
||||
void fillPacketHeader(const NLPacket& packet, HMACAuth* hmacAuth = nullptr);
|
||||
|
||||
|
@ -440,6 +446,12 @@ private:
|
|||
using LocalIDMapping = tbb::concurrent_unordered_map<Node::LocalID, SharedNodePointer>;
|
||||
LocalIDMapping _localIDMap;
|
||||
Node::LocalID _sessionLocalID { 0 };
|
||||
bool _flagTimeForConnectionStep { false }; // only keep track in interface
|
||||
|
||||
int _inboundPPS { 0 };
|
||||
int _outboundPPS { 0 };
|
||||
float _inboundKbps { 0.0f };
|
||||
float _outboundKbps { 0.0f };
|
||||
};
|
||||
|
||||
#endif // hifi_LimitedNodeList_h
|
||||
|
|
|
@ -228,19 +228,3 @@ QDebug operator<<(QDebug debug, const NetworkPeer &peer) {
|
|||
<< "- local:" << peer.getLocalSocket();
|
||||
return debug;
|
||||
}
|
||||
|
||||
void NetworkPeer::recordBytesSent(int count) const {
|
||||
_bandwidthRecorder.updateOutboundData(0, count);
|
||||
}
|
||||
|
||||
void NetworkPeer::recordBytesReceived(int count) const {
|
||||
_bandwidthRecorder.updateInboundData(0, count);
|
||||
}
|
||||
|
||||
float NetworkPeer::getOutboundBandwidth() const {
|
||||
return _bandwidthRecorder.getAverageOutputKilobitsPerSecond(0);
|
||||
}
|
||||
|
||||
float NetworkPeer::getInboundBandwidth() const {
|
||||
return _bandwidthRecorder.getAverageInputKilobitsPerSecond(0);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
#include "BandwidthRecorder.h"
|
||||
#include "HifiSockAddr.h"
|
||||
#include "UUID.h"
|
||||
|
||||
|
@ -78,12 +77,6 @@ public:
|
|||
void incrementConnectionAttempts() { ++_connectionAttempts; }
|
||||
void resetConnectionAttempts() { _connectionAttempts = 0; }
|
||||
|
||||
void recordBytesSent(int count) const;
|
||||
void recordBytesReceived(int count) const;
|
||||
|
||||
float getOutboundBandwidth() const; // in kbps
|
||||
float getInboundBandwidth() const; // in kbps
|
||||
|
||||
// Typically the LimitedNodeList removes nodes after they are "silent"
|
||||
// meaning that we have not received any packets (including simple keepalive pings) from them for a set interval.
|
||||
// The _isForcedNeverSilent flag tells the LimitedNodeList that a Node should never be killed by removeSilentNodes()
|
||||
|
@ -114,8 +107,6 @@ protected:
|
|||
HifiSockAddr _symmetricSocket;
|
||||
HifiSockAddr* _activeSocket;
|
||||
|
||||
mutable BandwidthRecorder _bandwidthRecorder;
|
||||
|
||||
quint64 _wakeTimestamp;
|
||||
std::atomic_ullong _lastHeardMicrostamp;
|
||||
|
||||
|
|
|
@ -219,3 +219,37 @@ void Node::setConnectionSecret(const QUuid& connectionSecret) {
|
|||
_connectionSecret = connectionSecret;
|
||||
_authenticateHash->setKey(_connectionSecret);
|
||||
}
|
||||
|
||||
void Node::updateStats(Stats stats) {
|
||||
_stats = stats;
|
||||
}
|
||||
|
||||
const Node::Stats& Node::getConnectionStats() const {
|
||||
return _stats;
|
||||
}
|
||||
|
||||
float Node::getInboundKbps() const {
|
||||
float bitsReceived = (_stats.receivedBytes + _stats.receivedUnreliableBytes) * BITS_IN_BYTE;
|
||||
auto elapsed = _stats.endTime - _stats.startTime;
|
||||
auto bps = (bitsReceived * USECS_PER_SECOND) / elapsed.count();
|
||||
return bps / BYTES_PER_KILOBYTE;
|
||||
}
|
||||
|
||||
float Node::getOutboundKbps() const {
|
||||
float bitsSent = (_stats.sentBytes + _stats.sentUnreliableBytes) * BITS_IN_BYTE;
|
||||
auto elapsed = _stats.endTime - _stats.startTime;
|
||||
auto bps = (bitsSent * USECS_PER_SECOND) / elapsed.count();
|
||||
return bps / BYTES_PER_KILOBYTE;
|
||||
}
|
||||
|
||||
int Node::getInboundPPS() const {
|
||||
float packetsReceived = _stats.receivedPackets + _stats.receivedUnreliablePackets;
|
||||
auto elapsed = _stats.endTime - _stats.startTime;
|
||||
return (packetsReceived * USECS_PER_SECOND) / elapsed.count();
|
||||
}
|
||||
|
||||
int Node::getOutboundPPS() const {
|
||||
float packetsSent = _stats.sentPackets + _stats.sentUnreliablePackets;
|
||||
auto elapsed = _stats.endTime - _stats.startTime;
|
||||
return (packetsSent * USECS_PER_SECOND) / elapsed.count();
|
||||
}
|
||||
|
|
|
@ -35,10 +35,13 @@
|
|||
#include "MovingPercentile.h"
|
||||
#include "NodePermissions.h"
|
||||
#include "HMACAuth.h"
|
||||
#include "udt/ConnectionStats.h"
|
||||
#include "NumericalConstants.h"
|
||||
|
||||
class Node : public NetworkPeer {
|
||||
Q_OBJECT
|
||||
public:
|
||||
using Stats = udt::ConnectionStats::Stats;
|
||||
|
||||
Node(const QUuid& uuid, NodeType_t type,
|
||||
const HifiSockAddr& publicSocket, const HifiSockAddr& localSocket,
|
||||
|
@ -94,6 +97,14 @@ public:
|
|||
friend QDataStream& operator<<(QDataStream& out, const Node& node);
|
||||
friend QDataStream& operator>>(QDataStream& in, Node& node);
|
||||
|
||||
void updateStats(Stats stats);
|
||||
const Stats& getConnectionStats() const;
|
||||
|
||||
int getInboundPPS() const;
|
||||
int getOutboundPPS() const;
|
||||
float getInboundKbps() const;
|
||||
float getOutboundKbps() const;
|
||||
|
||||
private:
|
||||
// privatize copy and assignment operator to disallow Node copying
|
||||
Node(const Node &otherNode);
|
||||
|
@ -115,6 +126,8 @@ private:
|
|||
IgnoredNodeIDs _ignoredNodeIDs;
|
||||
mutable QReadWriteLock _ignoredNodeIDSetLock;
|
||||
std::vector<QString> _replicatedUsernames { };
|
||||
|
||||
Stats _stats;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Node*)
|
||||
|
|
|
@ -284,10 +284,6 @@ void PacketReceiver::handleVerifiedMessage(QSharedPointer<ReceivedMessage> recei
|
|||
connectionType = _directlyConnectedObjects.contains(listener.object) ? Qt::DirectConnection : Qt::AutoConnection;
|
||||
}
|
||||
|
||||
if (matchingNode) {
|
||||
matchingNode->recordBytesReceived(receivedMessage->getSize());
|
||||
}
|
||||
|
||||
QMetaMethod metaMethod = listener.method;
|
||||
|
||||
static const QByteArray QSHAREDPOINTER_NODE_NORMALIZED = QMetaObject::normalizedType("QSharedPointer<Node>");
|
||||
|
|
|
@ -139,11 +139,10 @@ void UserActivityLogger::connectedDevice(QString typeOfDevice, QString deviceNam
|
|||
"NullDisplayPlugin",
|
||||
"3D TV - Side by Side Stereo",
|
||||
"3D TV - Interleaved",
|
||||
|
||||
"Keyboard/Mouse"
|
||||
};
|
||||
|
||||
if (DEVICE_BLACKLIST.contains(deviceName)) {
|
||||
if (DEVICE_BLACKLIST.contains(deviceName) || deviceName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -192,12 +192,21 @@ void Connection::recordSentPackets(int wireSize, int payloadSize,
|
|||
_congestionControl->onPacketSent(wireSize, seqNum, timePoint);
|
||||
}
|
||||
|
||||
void Connection::recordRetransmission(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) {
|
||||
_stats.record(ConnectionStats::Stats::Retransmission);
|
||||
void Connection::recordRetransmission(int wireSize, int payloadSize,
|
||||
SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint) {
|
||||
_stats.recordRetransmittedPackets(payloadSize, wireSize);
|
||||
|
||||
_congestionControl->onPacketReSent(wireSize, seqNum, timePoint);
|
||||
}
|
||||
|
||||
void Connection::recordSentUnreliablePackets(int wireSize, int payloadSize) {
|
||||
_stats.recordUnreliableSentPackets(payloadSize, wireSize);
|
||||
}
|
||||
|
||||
void Connection::recordReceivedUnreliablePackets(int wireSize, int payloadSize) {
|
||||
_stats.recordUnreliableReceivedPackets(payloadSize, wireSize);
|
||||
}
|
||||
|
||||
void Connection::sendACK() {
|
||||
SequenceNumber nextACKNumber = nextACK();
|
||||
|
||||
|
@ -212,7 +221,7 @@ void Connection::sendACK() {
|
|||
// have the socket send off our packet
|
||||
_parentSocket->writeBasePacket(*_ackPacket, _destination);
|
||||
|
||||
_stats.record(ConnectionStats::Stats::SentACK);
|
||||
_stats.recordSentACK(_ackPacket->getWireSize());
|
||||
}
|
||||
|
||||
SequenceNumber Connection::nextACK() const {
|
||||
|
@ -270,7 +279,7 @@ bool Connection::processReceivedSequenceNumber(SequenceNumber sequenceNumber, in
|
|||
sendACK();
|
||||
|
||||
if (wasDuplicate) {
|
||||
_stats.record(ConnectionStats::Stats::Duplicate);
|
||||
_stats.recordDuplicatePackets(payloadSize, packetSize);
|
||||
} else {
|
||||
_stats.recordReceivedPackets(payloadSize, packetSize);
|
||||
}
|
||||
|
@ -318,7 +327,7 @@ void Connection::processACK(ControlPacketPointer controlPacket) {
|
|||
controlPacket->readPrimitive(&ack);
|
||||
|
||||
// update the total count of received ACKs
|
||||
_stats.record(ConnectionStats::Stats::ReceivedACK);
|
||||
_stats.recordReceivedACK(controlPacket->getWireSize());
|
||||
|
||||
// validate that this isn't a BS ACK
|
||||
if (ack > getSendQueue().getCurrentSequenceNumber()) {
|
||||
|
|
|
@ -73,6 +73,9 @@ public:
|
|||
void setMaxBandwidth(int maxBandwidth);
|
||||
|
||||
void sendHandshakeRequest();
|
||||
|
||||
void recordSentUnreliablePackets(int wireSize, int payloadSize);
|
||||
void recordReceivedUnreliablePackets(int wireSize, int payloadSize);
|
||||
|
||||
signals:
|
||||
void packetSent();
|
||||
|
@ -80,7 +83,8 @@ signals:
|
|||
|
||||
private slots:
|
||||
void recordSentPackets(int wireSize, int payloadSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint);
|
||||
void recordRetransmission(int wireSize, SequenceNumber sequenceNumber, p_high_resolution_clock::time_point timePoint);
|
||||
void recordRetransmission(int wireSize, int payloadSize, SequenceNumber sequenceNumber, p_high_resolution_clock::time_point timePoint);
|
||||
|
||||
void queueInactive();
|
||||
void queueTimeout();
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@ using namespace std::chrono;
|
|||
ConnectionStats::ConnectionStats() {
|
||||
auto now = duration_cast<microseconds>(system_clock::now().time_since_epoch());
|
||||
_currentSample.startTime = now;
|
||||
_total.startTime = now;
|
||||
}
|
||||
|
||||
ConnectionStats::Stats ConnectionStats::sample() {
|
||||
|
@ -35,79 +34,60 @@ ConnectionStats::Stats ConnectionStats::sample() {
|
|||
|
||||
void ConnectionStats::record(Stats::Event event) {
|
||||
++_currentSample.events[(int) event];
|
||||
++_total.events[(int) event];
|
||||
}
|
||||
|
||||
void ConnectionStats::recordSentACK(int size) {
|
||||
record(Stats::SentACK);
|
||||
recordSentPackets(0, size);
|
||||
}
|
||||
|
||||
void ConnectionStats::recordReceivedACK(int size) {
|
||||
record(Stats::ReceivedACK);
|
||||
recordReceivedPackets(0, size);
|
||||
}
|
||||
|
||||
void ConnectionStats::recordSentPackets(int payload, int total) {
|
||||
++_currentSample.sentPackets;
|
||||
++_total.sentPackets;
|
||||
|
||||
_currentSample.sentUtilBytes += payload;
|
||||
_total.sentUtilBytes += payload;
|
||||
|
||||
_currentSample.sentBytes += total;
|
||||
_total.sentBytes += total;
|
||||
}
|
||||
|
||||
void ConnectionStats::recordReceivedPackets(int payload, int total) {
|
||||
++_currentSample.receivedPackets;
|
||||
++_total.receivedPackets;
|
||||
|
||||
_currentSample.receivedUtilBytes += payload;
|
||||
_total.receivedUtilBytes += payload;
|
||||
|
||||
_currentSample.receivedBytes += total;
|
||||
_total.receivedBytes += total;
|
||||
}
|
||||
|
||||
void ConnectionStats::recordRetransmittedPackets(int payload, int total) {
|
||||
++_currentSample.retransmittedPackets;
|
||||
_currentSample.retransmittedUtilBytes += payload;
|
||||
_currentSample.retransmittedBytes += total;
|
||||
}
|
||||
|
||||
void ConnectionStats::recordDuplicatePackets(int payload, int total) {
|
||||
++_currentSample.duplicatePackets;
|
||||
_currentSample.duplicateUtilBytes += payload;
|
||||
_currentSample.duplicateBytes += total;
|
||||
}
|
||||
|
||||
void ConnectionStats::recordUnreliableSentPackets(int payload, int total) {
|
||||
++_currentSample.sentUnreliablePackets;
|
||||
++_total.sentUnreliablePackets;
|
||||
|
||||
_currentSample.sentUnreliableUtilBytes += payload;
|
||||
_total.sentUnreliableUtilBytes += payload;
|
||||
|
||||
_currentSample.sentUnreliableBytes += total;
|
||||
_total.sentUnreliableBytes += total;
|
||||
}
|
||||
|
||||
void ConnectionStats::recordUnreliableReceivedPackets(int payload, int total) {
|
||||
++_currentSample.receivedUnreliablePackets;
|
||||
++_total.receivedUnreliablePackets;
|
||||
|
||||
_currentSample.receivedUnreliableUtilBytes += payload;
|
||||
_total.receivedUnreliableUtilBytes += payload;
|
||||
|
||||
_currentSample.sentUnreliableBytes += total;
|
||||
_total.receivedUnreliableBytes += total;
|
||||
}
|
||||
|
||||
static const double EWMA_CURRENT_SAMPLE_WEIGHT = 0.125;
|
||||
static const double EWMA_PREVIOUS_SAMPLES_WEIGHT = 1.0 - EWMA_CURRENT_SAMPLE_WEIGHT;
|
||||
|
||||
void ConnectionStats::recordSendRate(int sample) {
|
||||
_currentSample.sendRate = sample;
|
||||
_total.sendRate = (int)((_total.sendRate * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT));
|
||||
}
|
||||
|
||||
void ConnectionStats::recordReceiveRate(int sample) {
|
||||
_currentSample.receiveRate = sample;
|
||||
_total.receiveRate = (int)((_total.receiveRate * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT));
|
||||
}
|
||||
|
||||
void ConnectionStats::recordRTT(int sample) {
|
||||
_currentSample.rtt = sample;
|
||||
_total.rtt = (int)((_total.rtt * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT));
|
||||
_currentSample.receivedUnreliableBytes += total;
|
||||
}
|
||||
|
||||
void ConnectionStats::recordCongestionWindowSize(int sample) {
|
||||
_currentSample.congestionWindowSize = sample;
|
||||
_total.congestionWindowSize = (int)((_total.congestionWindowSize * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT));
|
||||
}
|
||||
|
||||
void ConnectionStats::recordPacketSendPeriod(int sample) {
|
||||
_currentSample.packetSendPeriod = sample;
|
||||
_total.packetSendPeriod = (int)((_total.packetSendPeriod * EWMA_PREVIOUS_SAMPLES_WEIGHT) + (sample * EWMA_CURRENT_SAMPLE_WEIGHT));
|
||||
}
|
||||
|
||||
QDebug& operator<<(QDebug&& debug, const udt::ConnectionStats::Stats& stats) {
|
||||
|
@ -117,13 +97,13 @@ QDebug& operator<<(QDebug&& debug, const udt::ConnectionStats::Stats& stats) {
|
|||
HIFI_LOG_EVENT(SentACK)
|
||||
HIFI_LOG_EVENT(ReceivedACK)
|
||||
HIFI_LOG_EVENT(ProcessedACK)
|
||||
HIFI_LOG_EVENT(Retransmission)
|
||||
HIFI_LOG_EVENT(Duplicate)
|
||||
;
|
||||
#undef HIFI_LOG_EVENT
|
||||
|
||||
debug << " Sent packets: " << stats.sentPackets;
|
||||
debug << "\n Retransmitted packets: " << stats.retransmittedPackets;
|
||||
debug << "\n Received packets: " << stats.receivedPackets;
|
||||
debug << "\n Duplicate packets: " << stats.duplicatePackets;
|
||||
debug << "\n Sent util bytes: " << stats.sentUtilBytes;
|
||||
debug << "\n Sent bytes: " << stats.sentBytes;
|
||||
debug << "\n Received bytes: " << stats.receivedBytes << "\n";
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include <chrono>
|
||||
#include <array>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace udt {
|
||||
|
||||
|
@ -24,8 +25,6 @@ public:
|
|||
SentACK,
|
||||
ReceivedACK,
|
||||
ProcessedACK,
|
||||
Retransmission,
|
||||
Duplicate,
|
||||
|
||||
NumEvents
|
||||
};
|
||||
|
@ -40,19 +39,27 @@ public:
|
|||
Events events;
|
||||
|
||||
// packet counts and sizes
|
||||
int sentPackets { 0 };
|
||||
int receivedPackets { 0 };
|
||||
int sentUtilBytes { 0 };
|
||||
int receivedUtilBytes { 0 };
|
||||
int sentBytes { 0 };
|
||||
int receivedBytes { 0 };
|
||||
uint32_t sentPackets { 0 };
|
||||
uint32_t receivedPackets { 0 };
|
||||
uint32_t retransmittedPackets { 0 };
|
||||
uint32_t duplicatePackets { 0 };
|
||||
|
||||
uint64_t sentUtilBytes { 0 };
|
||||
uint64_t receivedUtilBytes { 0 };
|
||||
uint64_t retransmittedUtilBytes { 0 };
|
||||
uint64_t duplicateUtilBytes { 0 };
|
||||
|
||||
uint64_t sentBytes { 0 };
|
||||
uint64_t receivedBytes { 0 };
|
||||
uint64_t retransmittedBytes { 0 };
|
||||
uint64_t duplicateBytes { 0 };
|
||||
|
||||
int sentUnreliablePackets { 0 };
|
||||
int receivedUnreliablePackets { 0 };
|
||||
int sentUnreliableUtilBytes { 0 };
|
||||
int receivedUnreliableUtilBytes { 0 };
|
||||
int sentUnreliableBytes { 0 };
|
||||
int receivedUnreliableBytes { 0 };
|
||||
uint32_t sentUnreliablePackets { 0 };
|
||||
uint32_t receivedUnreliablePackets { 0 };
|
||||
uint64_t sentUnreliableUtilBytes { 0 };
|
||||
uint64_t receivedUnreliableUtilBytes { 0 };
|
||||
uint64_t sentUnreliableBytes { 0 };
|
||||
uint64_t receivedUnreliableBytes { 0 };
|
||||
|
||||
// the following stats are trailing averages in the result, not totals
|
||||
int sendRate { 0 };
|
||||
|
@ -69,25 +76,26 @@ public:
|
|||
ConnectionStats();
|
||||
|
||||
Stats sample();
|
||||
Stats getTotalStats();
|
||||
|
||||
void record(Stats::Event event);
|
||||
|
||||
|
||||
void recordSentACK(int size);
|
||||
void recordReceivedACK(int size);
|
||||
|
||||
void recordSentPackets(int payload, int total);
|
||||
void recordReceivedPackets(int payload, int total);
|
||||
|
||||
void recordRetransmittedPackets(int payload, int total);
|
||||
void recordDuplicatePackets(int payload, int total);
|
||||
|
||||
void recordUnreliableSentPackets(int payload, int total);
|
||||
void recordUnreliableReceivedPackets(int payload, int total);
|
||||
|
||||
void recordSendRate(int sample);
|
||||
void recordReceiveRate(int sample);
|
||||
void recordRTT(int sample);
|
||||
|
||||
void recordCongestionWindowSize(int sample);
|
||||
void recordPacketSendPeriod(int sample);
|
||||
|
||||
private:
|
||||
Stats _currentSample;
|
||||
Stats _total;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -33,14 +33,14 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
case PacketType::EntityPhysics:
|
||||
return static_cast<PacketVersion>(EntityVersion::GridEntities);
|
||||
return static_cast<PacketVersion>(EntityVersion::MorePropertiesCleanup);
|
||||
case PacketType::EntityQuery:
|
||||
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
|
||||
case PacketType::AvatarIdentity:
|
||||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
case PacketType::KillAvatar:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::JointTransScaled);
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::GrabTraits);
|
||||
case PacketType::MessagesData:
|
||||
return static_cast<PacketVersion>(MessageDataVersion::TextOrBinaryData);
|
||||
// ICE packets
|
||||
|
|
|
@ -249,7 +249,10 @@ enum class EntityVersion : PacketVersion {
|
|||
EntityHostTypes,
|
||||
CleanupProperties,
|
||||
ImageEntities,
|
||||
GridEntities
|
||||
GridEntities,
|
||||
MissingTextProperties,
|
||||
GrabTraits,
|
||||
MorePropertiesCleanup
|
||||
};
|
||||
|
||||
enum class EntityScriptCallMethodVersion : PacketVersion {
|
||||
|
@ -302,7 +305,8 @@ enum class AvatarMixerPacketVersion : PacketVersion {
|
|||
MigrateSkeletonURLToTraits,
|
||||
MigrateAvatarEntitiesToTraits,
|
||||
FarGrabJointsRedux,
|
||||
JointTransScaled
|
||||
JointTransScaled,
|
||||
GrabTraits
|
||||
};
|
||||
|
||||
enum class DomainConnectRequestVersion : PacketVersion {
|
||||
|
|
|
@ -404,6 +404,7 @@ bool SendQueue::maybeResendPacket() {
|
|||
Packet::ObfuscationLevel level = (Packet::ObfuscationLevel)(entry.first < 2 ? 0 : (entry.first - 2) % 4);
|
||||
|
||||
auto wireSize = resendPacket.getWireSize();
|
||||
auto payloadSize = resendPacket.getPayloadSize();
|
||||
auto sequenceNumber = it->first;
|
||||
|
||||
if (level != Packet::NoObfuscation) {
|
||||
|
@ -439,7 +440,8 @@ bool SendQueue::maybeResendPacket() {
|
|||
sentLocker.unlock();
|
||||
}
|
||||
|
||||
emit packetRetransmitted(wireSize, sequenceNumber, p_high_resolution_clock::now());
|
||||
emit packetRetransmitted(wireSize, payloadSize, sequenceNumber,
|
||||
p_high_resolution_clock::now());
|
||||
|
||||
// Signal that we did resend a packet
|
||||
return true;
|
||||
|
|
|
@ -78,7 +78,7 @@ public slots:
|
|||
|
||||
signals:
|
||||
void packetSent(int wireSize, int payloadSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint);
|
||||
void packetRetransmitted(int wireSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint);
|
||||
void packetRetransmitted(int wireSize, int payloadSize, SequenceNumber seqNum, p_high_resolution_clock::time_point timePoint);
|
||||
|
||||
void queueInactive();
|
||||
|
||||
|
|
|
@ -129,6 +129,12 @@ qint64 Socket::writePacket(const Packet& packet, const HifiSockAddr& sockAddr) {
|
|||
sequenceNumber = ++_unreliableSequenceNumbers[sockAddr];
|
||||
}
|
||||
|
||||
auto connection = findOrCreateConnection(sockAddr, true);
|
||||
if (connection) {
|
||||
connection->recordSentUnreliablePackets(packet.getWireSize(),
|
||||
packet.getPayloadSize());
|
||||
}
|
||||
|
||||
// write the correct sequence number to the Packet here
|
||||
packet.writeSequenceNumber(sequenceNumber);
|
||||
|
||||
|
@ -392,9 +398,10 @@ void Socket::readPendingDatagrams() {
|
|||
|
||||
// call our verification operator to see if this packet is verified
|
||||
if (!_packetFilterOperator || _packetFilterOperator(*packet)) {
|
||||
auto connection = findOrCreateConnection(senderSockAddr, true);
|
||||
|
||||
if (packet->isReliable()) {
|
||||
// if this was a reliable packet then signal the matching connection with the sequence number
|
||||
auto connection = findOrCreateConnection(senderSockAddr, true);
|
||||
|
||||
if (!connection || !connection->processReceivedSequenceNumber(packet->getSequenceNumber(),
|
||||
packet->getDataSize(),
|
||||
|
@ -406,6 +413,9 @@ void Socket::readPendingDatagrams() {
|
|||
#endif
|
||||
continue;
|
||||
}
|
||||
} else if (connection) {
|
||||
connection->recordReceivedUnreliablePackets(packet->getWireSize(),
|
||||
packet->getPayloadSize());
|
||||
}
|
||||
|
||||
if (packet->isPartOfMessage()) {
|
||||
|
|
|
@ -9,13 +9,15 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "OctreeEntitiesFileParser.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <cctype>
|
||||
|
||||
#include <QUuid>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "OctreeEntitiesFileParser.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
|
|
|
@ -33,36 +33,53 @@ ObjectActionTractor::ObjectActionTractor(const QUuid& id, EntityItemPointer owne
|
|||
_rotationalTargetSet(true),
|
||||
_linearVelocityTarget(0.0f)
|
||||
{
|
||||
#if WANT_DEBUG
|
||||
#if WANT_DEBUG
|
||||
qCDebug(physics) << "ObjectActionTractor::ObjectActionTractor";
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
ObjectActionTractor::~ObjectActionTractor() {
|
||||
#if WANT_DEBUG
|
||||
#if WANT_DEBUG
|
||||
qCDebug(physics) << "ObjectActionTractor::~ObjectActionTractor";
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ObjectActionTractor::getTarget(float deltaTimeStep, glm::quat& rotation, glm::vec3& position,
|
||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity,
|
||||
float& linearTimeScale, float& angularTimeScale) {
|
||||
bool success { true };
|
||||
EntityItemPointer other = std::dynamic_pointer_cast<EntityItem>(getOther());
|
||||
withReadLock([&]{
|
||||
glm::vec3& linearVelocity, glm::vec3& angularVelocity,
|
||||
float& linearTimeScale, float& angularTimeScale) {
|
||||
SpatiallyNestablePointer other = getOther();
|
||||
return resultWithReadLock<bool>([&]{
|
||||
linearTimeScale = _linearTimeScale;
|
||||
angularTimeScale = _angularTimeScale;
|
||||
|
||||
if (!_otherID.isNull()) {
|
||||
if (other && other->isReadyToComputeShape()) {
|
||||
rotation = _desiredRotationalTarget * other->getWorldOrientation();
|
||||
position = other->getWorldOrientation() * _desiredPositionalTarget + other->getWorldPosition();
|
||||
bool otherIsReady { true };
|
||||
if (other && other->getNestableType() == NestableType::Entity) {
|
||||
EntityItemPointer otherEntity = std::static_pointer_cast<EntityItem>(other);
|
||||
otherIsReady = otherEntity->isReadyToComputeShape();
|
||||
}
|
||||
if (other && otherIsReady) {
|
||||
bool success;
|
||||
glm::vec3 otherWorldPosition = other->getWorldPosition(_otherJointIndex, success);
|
||||
if (!success) {
|
||||
linearTimeScale = FLT_MAX;
|
||||
angularTimeScale = FLT_MAX;
|
||||
return false;
|
||||
}
|
||||
glm::quat otherWorldOrientation = other->getWorldOrientation(_otherJointIndex, success);
|
||||
if (!success) {
|
||||
linearTimeScale = FLT_MAX;
|
||||
angularTimeScale = FLT_MAX;
|
||||
return false;
|
||||
}
|
||||
rotation = otherWorldOrientation * _desiredRotationalTarget;
|
||||
position = otherWorldOrientation * _desiredPositionalTarget + otherWorldPosition;
|
||||
} else {
|
||||
// we should have an "other" but can't find it, or its collision shape isn't loaded,
|
||||
// so disable the tractor.
|
||||
linearTimeScale = FLT_MAX;
|
||||
angularTimeScale = FLT_MAX;
|
||||
success = false;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
rotation = _desiredRotationalTarget;
|
||||
|
@ -70,8 +87,8 @@ bool ObjectActionTractor::getTarget(float deltaTimeStep, glm::quat& rotation, gl
|
|||
}
|
||||
linearVelocity = glm::vec3();
|
||||
angularVelocity = glm::vec3();
|
||||
return true;
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
||||
|
@ -108,9 +125,9 @@ bool ObjectActionTractor::prepareForTractorUpdate(btScalar deltaTimeStep) {
|
|||
float linearTimeScale;
|
||||
float angularTimeScale;
|
||||
bool success = tractorAction->getTarget(deltaTimeStep,
|
||||
rotationForAction, positionForAction,
|
||||
linearVelocityForAction, angularVelocityForAction,
|
||||
linearTimeScale, angularTimeScale);
|
||||
rotationForAction, positionForAction,
|
||||
linearVelocityForAction, angularVelocityForAction,
|
||||
linearTimeScale, angularTimeScale);
|
||||
if (success) {
|
||||
if (angularTimeScale < MAX_TRACTOR_TIMESCALE) {
|
||||
angularTractorCount++;
|
||||
|
@ -239,7 +256,7 @@ bool ObjectActionTractor::updateArguments(QVariantMap arguments) {
|
|||
glm::quat rotationalTarget;
|
||||
float angularTimeScale;
|
||||
QUuid otherID;
|
||||
|
||||
int otherJointIndex;
|
||||
|
||||
bool needUpdate = false;
|
||||
bool somethingChanged = ObjectDynamic::updateArguments(arguments);
|
||||
|
@ -274,18 +291,25 @@ bool ObjectActionTractor::updateArguments(QVariantMap arguments) {
|
|||
}
|
||||
|
||||
ok = true;
|
||||
otherID = QUuid(EntityDynamicInterface::extractStringArgument("tractor action",
|
||||
arguments, "otherID", ok, false));
|
||||
otherID = QUuid(EntityDynamicInterface::extractStringArgument("tractor action", arguments, "otherID", ok, false));
|
||||
if (!ok) {
|
||||
otherID = _otherID;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
otherJointIndex = EntityDynamicInterface::extractIntegerArgument("tractor action", arguments,
|
||||
"otherJointIndex", ok, false);
|
||||
if (!ok) {
|
||||
otherJointIndex = _otherJointIndex;
|
||||
}
|
||||
|
||||
if (somethingChanged ||
|
||||
positionalTarget != _desiredPositionalTarget ||
|
||||
linearTimeScale != _linearTimeScale ||
|
||||
rotationalTarget != _desiredRotationalTarget ||
|
||||
angularTimeScale != _angularTimeScale ||
|
||||
otherID != _otherID) {
|
||||
otherID != _otherID ||
|
||||
otherJointIndex != _otherJointIndex) {
|
||||
// something changed
|
||||
needUpdate = true;
|
||||
}
|
||||
|
@ -298,6 +322,7 @@ bool ObjectActionTractor::updateArguments(QVariantMap arguments) {
|
|||
_desiredRotationalTarget = rotationalTarget;
|
||||
_angularTimeScale = glm::max(MIN_TIMESCALE, glm::abs(angularTimeScale));
|
||||
_otherID = otherID;
|
||||
_otherJointIndex = otherJointIndex;
|
||||
_active = true;
|
||||
|
||||
auto ownerEntity = _ownerEntity.lock();
|
||||
|
@ -313,20 +338,22 @@ bool ObjectActionTractor::updateArguments(QVariantMap arguments) {
|
|||
}
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"tractor"</code> {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and
|
||||
* The <code>"tractor"</code> {@link Entities.ActionType|ActionType} moves and rotates an entity to a target position and
|
||||
* orientation, optionally relative to another entity.
|
||||
* It has arguments in addition to the common {@link Entities.ActionArguments|ActionArguments}.
|
||||
*
|
||||
* @typedef {object} Entities.ActionArguments-Tractor
|
||||
* @property {Vec3} targetPosition=0,0,0 - The target position.
|
||||
* @property {Quat} targetRotation=0,0,0,1 - The target rotation.
|
||||
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
|
||||
* @property {Uuid} otherID=null - If an entity ID, the <code>targetPosition</code> and <code>targetRotation</code> are
|
||||
* relative to this entity's position and rotation.
|
||||
* @property {Uuid} otherJointIndex=null - If an entity JointIndex, the <code>targetPosition</code> and
|
||||
* <code>targetRotation</code> are relative to this entity's joint's position and rotation.
|
||||
* @property {number} linearTimeScale=3.4e+38 - Controls how long it takes for the entity's position to catch up with the
|
||||
* target position. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
|
||||
* target position. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the action
|
||||
* is applied using an exponential decay.
|
||||
* @property {number} angularTimeScale=3.4e+38 - Controls how long it takes for the entity's orientation to catch up with the
|
||||
* target orientation. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the
|
||||
* target orientation. The value is the time for the action to catch up to 1/e = 0.368 of the target value, where the
|
||||
* action is applied using an exponential decay.
|
||||
*/
|
||||
QVariantMap ObjectActionTractor::getArguments() {
|
||||
|
@ -339,6 +366,7 @@ QVariantMap ObjectActionTractor::getArguments() {
|
|||
arguments["angularTimeScale"] = _angularTimeScale;
|
||||
|
||||
arguments["otherID"] = _otherID;
|
||||
arguments["otherJointIndex"] = _otherJointIndex;
|
||||
});
|
||||
return arguments;
|
||||
}
|
||||
|
@ -354,6 +382,7 @@ void ObjectActionTractor::serializeParameters(QDataStream& dataStream) const {
|
|||
dataStream << localTimeToServerTime(_expires);
|
||||
dataStream << _tag;
|
||||
dataStream << _otherID;
|
||||
dataStream << _otherJointIndex;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -387,6 +416,7 @@ void ObjectActionTractor::deserializeParameters(QByteArray serializedArguments,
|
|||
dataStream >> _tag;
|
||||
|
||||
dataStream >> _otherID;
|
||||
dataStream >> _otherJointIndex;
|
||||
|
||||
_active = true;
|
||||
});
|
||||
|
|
|
@ -66,6 +66,7 @@ protected:
|
|||
EntityItemID _otherID;
|
||||
SpatiallyNestableWeakPointer _other;
|
||||
SpatiallyNestablePointer getOther();
|
||||
int _otherJointIndex { -1 };
|
||||
|
||||
private:
|
||||
qint64 getEntityServerClockSkew() const;
|
||||
|
|
|
@ -67,11 +67,11 @@ float TextRenderer3D::getFontSize() const {
|
|||
}
|
||||
|
||||
void TextRenderer3D::draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color,
|
||||
const glm::vec2& bounds, bool layered) {
|
||||
const glm::vec2& bounds) {
|
||||
// The font does all the OpenGL work
|
||||
if (_font) {
|
||||
_color = color;
|
||||
_font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds, layered);
|
||||
_font->drawString(batch, _drawInfo, str, _color, _effectType, { x, y }, bounds);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
float getFontSize() const; // Pixel size
|
||||
|
||||
void draw(gpu::Batch& batch, float x, float y, const QString& str, const glm::vec4& color = glm::vec4(1.0f),
|
||||
const glm::vec2& bounds = glm::vec2(-1.0f), bool layered = false);
|
||||
const glm::vec2& bounds = glm::vec2(-1.0f));
|
||||
|
||||
private:
|
||||
TextRenderer3D(const char* family, float pointSize, int weight = -1, bool italic = false,
|
||||
|
|
|
@ -49,7 +49,7 @@ void main(void) {
|
|||
vec3 orthogonal = cross(v1, v2) * _lineData.width;
|
||||
|
||||
// Deteremine which end to emit based on the vertex id (even / odd)
|
||||
vec4 eye = (0 == gl_VertexID % 2) ? p1eye : p2eye;
|
||||
vec4 eye = mix(p2eye, p1eye, float(gl_VertexID % 2 == 0));
|
||||
|
||||
// Add or subtract the orthogonal vector based on a different vertex ID
|
||||
// calculation
|
||||
|
|
|
@ -222,7 +222,6 @@ void Font::setupGPU() {
|
|||
// Setup render pipeline
|
||||
{
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D);
|
||||
gpu::ShaderPointer programTransparent = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent);
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
|
@ -232,13 +231,14 @@ void Font::setupGPU() {
|
|||
PrepareStencil::testMaskDrawShape(*state);
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
|
||||
gpu::ShaderPointer programTransparent = gpu::Shader::createProgram(shader::render_utils::program::sdf_text3D_transparent);
|
||||
auto transparentState = std::make_shared<gpu::State>();
|
||||
transparentState->setCullMode(gpu::State::CULL_BACK);
|
||||
transparentState->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
transparentState->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
PrepareStencil::testMaskDrawShape(*transparentState);
|
||||
PrepareStencil::testMask(*transparentState);
|
||||
_transparentPipeline = gpu::Pipeline::create(programTransparent, transparentState);
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
|
|||
break;
|
||||
}
|
||||
}
|
||||
if ((bounds.y != -1) && (advance.y - _fontSize < -origin.y - bounds.y)) {
|
||||
if ((bounds.y != -1) && (advance.y - _fontSize < origin.y - bounds.y)) {
|
||||
// We are out of the y bound, stop drawing
|
||||
break;
|
||||
}
|
||||
|
@ -343,7 +343,7 @@ void Font::buildVertices(Font::DrawInfo& drawInfo, const QString& str, const glm
|
|||
}
|
||||
|
||||
void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString& str, const glm::vec4& color,
|
||||
EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds, bool layered) {
|
||||
EffectType effectType, const glm::vec2& origin, const glm::vec2& bounds) {
|
||||
if (str == "") {
|
||||
return;
|
||||
}
|
||||
|
@ -370,7 +370,7 @@ void Font::drawString(gpu::Batch& batch, Font::DrawInfo& drawInfo, const QString
|
|||
}
|
||||
// need the gamma corrected color here
|
||||
|
||||
batch.setPipeline((color.a < 1.0f || layered) ? _transparentPipeline : _pipeline);
|
||||
batch.setPipeline((color.a < 1.0f) ? _transparentPipeline : _pipeline);
|
||||
batch.setInputFormat(_format);
|
||||
batch.setInputBuffer(0, drawInfo.verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||
batch.setResourceTexture(render_utils::slot::texture::TextFont, _texture);
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
// Render string to batch
|
||||
void drawString(gpu::Batch& batch, DrawInfo& drawInfo, const QString& str,
|
||||
const glm::vec4& color, EffectType effectType,
|
||||
const glm::vec2& origin, const glm::vec2& bound, bool layered = false);
|
||||
const glm::vec2& origin, const glm::vec2& bound);
|
||||
|
||||
static Pointer load(const QString& family);
|
||||
|
||||
|
|
|
@ -480,7 +480,7 @@ void AABox::embiggen(const glm::vec3& scale) {
|
|||
}
|
||||
|
||||
void AABox::setScaleStayCentered(const glm::vec3& scale) {
|
||||
_corner += -0.5f * scale;
|
||||
_corner -= 0.5f * (scale - _scale);
|
||||
_scale = scale;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,9 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <limits>
|
||||
#include "GLMHelpers.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include "NumericalConstants.h"
|
||||
|
||||
const vec3 Vectors::UNIT_X{ 1.0f, 0.0f, 0.0f };
|
||||
|
|
70
libraries/shared/src/Grab.cpp
Normal file
70
libraries/shared/src/Grab.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// Grab.cpp
|
||||
// libraries/avatars/src
|
||||
//
|
||||
// Created by Seth Alves on 2018-9-1.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "Grab.h"
|
||||
|
||||
QByteArray Grab::toByteArray() {
|
||||
QByteArray ba;
|
||||
QDataStream dataStream(&ba, QIODevice::WriteOnly);
|
||||
const int dataEncodingVersion = 1;
|
||||
dataStream << dataEncodingVersion << _ownerID << _targetID << _parentJointIndex
|
||||
<< _hand << _positionalOffset << _rotationalOffset;
|
||||
return ba;
|
||||
}
|
||||
|
||||
bool Grab::fromByteArray(const QByteArray& grabData) {
|
||||
QDataStream dataStream(grabData);
|
||||
|
||||
int dataEncodingVersion;
|
||||
QUuid newOwnerID { QUuid() };
|
||||
QUuid newTargetID { QUuid() };
|
||||
int newParentJointIndex { -1 };
|
||||
QString newHand { "none" };
|
||||
glm::vec3 newPositionalOffset { glm::vec3(0.0f) };
|
||||
glm::quat newRotationalOffset { glm::quat() };
|
||||
|
||||
dataStream >> dataEncodingVersion;
|
||||
assert(dataEncodingVersion == 1);
|
||||
dataStream >> newOwnerID;
|
||||
dataStream >> newTargetID;
|
||||
dataStream >> newParentJointIndex;
|
||||
dataStream >> newHand;
|
||||
dataStream >> newPositionalOffset;
|
||||
dataStream >> newRotationalOffset;
|
||||
|
||||
bool somethingChanged { false };
|
||||
if (_ownerID != newOwnerID) {
|
||||
_ownerID = newOwnerID;
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (_targetID != newTargetID) {
|
||||
_targetID = newTargetID;
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (_parentJointIndex != newParentJointIndex) {
|
||||
_parentJointIndex = newParentJointIndex;
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (_hand != newHand) {
|
||||
_hand = newHand;
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (_positionalOffset != newPositionalOffset) {
|
||||
_positionalOffset = newPositionalOffset;
|
||||
somethingChanged = true;
|
||||
}
|
||||
if (_rotationalOffset != newRotationalOffset) {
|
||||
_rotationalOffset = newRotationalOffset;
|
||||
somethingChanged = true;
|
||||
}
|
||||
|
||||
return somethingChanged;
|
||||
}
|
99
libraries/shared/src/Grab.h
Normal file
99
libraries/shared/src/Grab.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
//
|
||||
// Grab.h
|
||||
// libraries/avatars/src
|
||||
//
|
||||
// Created by Seth Alves on 2018-9-1.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// 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_Grab_h
|
||||
#define hifi_Grab_h
|
||||
|
||||
#include <QUuid>
|
||||
#include <QByteArray>
|
||||
#include "GLMHelpers.h"
|
||||
#include "StreamUtils.h"
|
||||
|
||||
class Grab;
|
||||
using GrabPointer = std::shared_ptr<Grab>;
|
||||
using GrabWeakPointer = std::weak_ptr<Grab>;
|
||||
|
||||
class GrabLocationAccumulator {
|
||||
public:
|
||||
void accumulate(glm::vec3 position, glm::quat orientation) {
|
||||
_position += position;
|
||||
_orientation = orientation; // XXX
|
||||
count++;
|
||||
}
|
||||
|
||||
glm::vec3 finalizePosition() { return count > 0 ? _position * (1.0f / count) : glm::vec3(0.0f); }
|
||||
glm::quat finalizeOrientation() { return _orientation; } // XXX
|
||||
|
||||
protected:
|
||||
glm::vec3 _position;
|
||||
glm::quat _orientation;
|
||||
int count { 0 };
|
||||
};
|
||||
|
||||
class Grab {
|
||||
public:
|
||||
Grab() {};
|
||||
Grab(const QUuid& newOwnerID, const QUuid& newTargetID, int newParentJointIndex, const QString& newHand,
|
||||
glm::vec3 newPositionalOffset, glm::quat newRotationalOffset) :
|
||||
_ownerID(newOwnerID),
|
||||
_targetID(newTargetID),
|
||||
_parentJointIndex(newParentJointIndex),
|
||||
_hand(newHand),
|
||||
_positionalOffset(newPositionalOffset),
|
||||
_rotationalOffset(newRotationalOffset) {}
|
||||
|
||||
QByteArray toByteArray();
|
||||
bool fromByteArray(const QByteArray& grabData);
|
||||
|
||||
Grab& operator=(const GrabPointer& other) {
|
||||
_ownerID = other->_ownerID;
|
||||
_targetID = other->_targetID;
|
||||
_parentJointIndex = other->_parentJointIndex;
|
||||
_hand = other->_hand;
|
||||
_positionalOffset = other->_positionalOffset;
|
||||
_rotationalOffset = other->_rotationalOffset;
|
||||
_actionID = other->_actionID;
|
||||
return *this;
|
||||
}
|
||||
|
||||
QUuid getActionID() const { return _actionID; }
|
||||
void setActionID(const QUuid& actionID) { _actionID = actionID; }
|
||||
|
||||
QUuid getOwnerID() const { return _ownerID; }
|
||||
void setOwnerID(QUuid ownerID) { _ownerID = ownerID; }
|
||||
|
||||
QUuid getTargetID() const { return _targetID; }
|
||||
void setTargetID(QUuid targetID) { _targetID = targetID; }
|
||||
|
||||
int getParentJointIndex() const { return _parentJointIndex; }
|
||||
void setParentJointIndex(int parentJointIndex) { _parentJointIndex = parentJointIndex; }
|
||||
|
||||
QString getHand() const { return _hand; }
|
||||
void setHand(QString hand) { _hand = hand; }
|
||||
|
||||
glm::vec3 getPositionalOffset() const { return _positionalOffset; }
|
||||
void setPositionalOffset(glm::vec3 positionalOffset) { _positionalOffset = positionalOffset; }
|
||||
|
||||
glm::quat getRotationalOffset() const { return _rotationalOffset; }
|
||||
void setRotationalOffset(glm::quat rotationalOffset) { _rotationalOffset = rotationalOffset; }
|
||||
|
||||
protected:
|
||||
QUuid _actionID; // if an action is created in bullet for this grab, this is the ID
|
||||
QUuid _ownerID; // avatar ID of grabber
|
||||
QUuid _targetID; // SpatiallyNestable ID of grabbed
|
||||
int _parentJointIndex { -1 }; // which avatar joint is being used to grab
|
||||
QString _hand; // "left" or "right"
|
||||
glm::vec3 _positionalOffset; // relative to joint
|
||||
glm::quat _rotationalOffset; // relative to joint
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Grab_h
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// ResourceAccessMonitor.h
|
||||
// libraries/networking/src
|
||||
// ResourceRequestObserver.cpp
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Kerry Ivan Kurian on 9/27/18.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
|
@ -9,12 +9,12 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QString>
|
||||
#include <QUrl>
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
void ResourceRequestObserver::update(const QUrl& requestUrl,
|
||||
const qint64 callerId,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
// ResourceRequestObserver.h
|
||||
// libraries/commerce/src
|
||||
// libraries/shared/src
|
||||
//
|
||||
// Created by Kerry Ivan Kurian on 9/27/18.
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
|
|
|
@ -481,27 +481,29 @@ void SpatiallyNestable::setWorldTransform(const glm::vec3& position, const glm::
|
|||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
bool success = true;
|
||||
Transform parentTransform = getParentTransform(success);
|
||||
_transformLock.withWriteLock([&] {
|
||||
Transform myWorldTransform;
|
||||
Transform::mult(myWorldTransform, parentTransform, _transform);
|
||||
if (myWorldTransform.getRotation() != orientation) {
|
||||
changed = true;
|
||||
myWorldTransform.setRotation(orientation);
|
||||
}
|
||||
if (myWorldTransform.getTranslation() != position) {
|
||||
changed = true;
|
||||
myWorldTransform.setTranslation(position);
|
||||
}
|
||||
if (success) {
|
||||
bool changed = false;
|
||||
_transformLock.withWriteLock([&] {
|
||||
Transform myWorldTransform;
|
||||
Transform::mult(myWorldTransform, parentTransform, _transform);
|
||||
if (myWorldTransform.getRotation() != orientation) {
|
||||
changed = true;
|
||||
myWorldTransform.setRotation(orientation);
|
||||
}
|
||||
if (myWorldTransform.getTranslation() != position) {
|
||||
changed = true;
|
||||
myWorldTransform.setTranslation(position);
|
||||
}
|
||||
if (changed) {
|
||||
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
||||
_translationChanged = usecTimestampNow();
|
||||
}
|
||||
});
|
||||
if (changed) {
|
||||
Transform::inverseMult(_transform, parentTransform, myWorldTransform);
|
||||
_translationChanged = usecTimestampNow();
|
||||
locationChanged(false);
|
||||
}
|
||||
});
|
||||
if (success && changed) {
|
||||
locationChanged(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -788,19 +790,21 @@ void SpatiallyNestable::setTransform(const Transform& transform, bool& success)
|
|||
return;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
Transform parentTransform = getParentTransform(success);
|
||||
_transformLock.withWriteLock([&] {
|
||||
Transform beforeTransform = _transform;
|
||||
Transform::inverseMult(_transform, parentTransform, transform);
|
||||
if (_transform != beforeTransform) {
|
||||
changed = true;
|
||||
_translationChanged = usecTimestampNow();
|
||||
_rotationChanged = usecTimestampNow();
|
||||
if (success) {
|
||||
bool changed = false;
|
||||
_transformLock.withWriteLock([&] {
|
||||
Transform beforeTransform = _transform;
|
||||
Transform::inverseMult(_transform, parentTransform, transform);
|
||||
if (_transform != beforeTransform) {
|
||||
changed = true;
|
||||
_translationChanged = usecTimestampNow();
|
||||
_rotationChanged = usecTimestampNow();
|
||||
}
|
||||
});
|
||||
if (changed) {
|
||||
locationChanged();
|
||||
}
|
||||
});
|
||||
if (success && changed) {
|
||||
locationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1369,3 +1373,43 @@ bool SpatiallyNestable::isParentPathComplete(int depth) const {
|
|||
|
||||
return parent->isParentPathComplete(depth + 1);
|
||||
}
|
||||
|
||||
void SpatiallyNestable::addGrab(GrabPointer grab) {
|
||||
_grabsLock.withWriteLock([&] {
|
||||
_grabs.insert(grab);
|
||||
});
|
||||
}
|
||||
|
||||
void SpatiallyNestable::removeGrab(GrabPointer grab) {
|
||||
_grabsLock.withWriteLock([&] {
|
||||
_grabs.remove(grab);
|
||||
});
|
||||
}
|
||||
|
||||
bool SpatiallyNestable::hasGrabs() {
|
||||
bool result { false };
|
||||
_grabsLock.withReadLock([&] {
|
||||
result = !_grabs.isEmpty();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
QUuid SpatiallyNestable::getEditSenderID() {
|
||||
// if more than one avatar is grabbing something, decide which one should tell the enity-server about it
|
||||
QUuid editSenderID;
|
||||
bool editSenderIDSet { false };
|
||||
_grabsLock.withReadLock([&] {
|
||||
foreach (const GrabPointer &grab, _grabs) {
|
||||
QUuid ownerID = grab->getOwnerID();
|
||||
if (!editSenderIDSet) {
|
||||
editSenderID = ownerID;
|
||||
editSenderIDSet = true;
|
||||
} else {
|
||||
if (ownerID < editSenderID) {
|
||||
editSenderID = ownerID;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return editSenderID;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "AACube.h"
|
||||
#include "SpatialParentFinder.h"
|
||||
#include "shared/ReadWriteLockable.h"
|
||||
#include "Grab.h"
|
||||
|
||||
class SpatiallyNestable;
|
||||
using SpatiallyNestableWeakPointer = std::weak_ptr<SpatiallyNestable>;
|
||||
|
@ -213,6 +214,11 @@ public:
|
|||
virtual void dimensionsChanged() { _queryAACubeSet = false; } // called when a this object's dimensions have changed
|
||||
virtual void parentDeleted() { } // called on children of a deleted parent
|
||||
|
||||
virtual void addGrab(GrabPointer grab);
|
||||
virtual void removeGrab(GrabPointer grab);
|
||||
bool hasGrabs();
|
||||
virtual QUuid getEditSenderID();
|
||||
|
||||
protected:
|
||||
QUuid _id;
|
||||
mutable SpatiallyNestableWeakPointer _parent;
|
||||
|
@ -232,6 +238,9 @@ protected:
|
|||
quint64 _translationChanged { 0 };
|
||||
quint64 _rotationChanged { 0 };
|
||||
|
||||
mutable ReadWriteLockable _grabsLock;
|
||||
QSet<GrabPointer> _grabs;
|
||||
|
||||
private:
|
||||
SpatiallyNestable() = delete;
|
||||
const NestableType _nestableType; // EntityItem or an AvatarData
|
||||
|
|
|
@ -40,7 +40,8 @@ function updateOverlay(entityID, queryAACube) {
|
|||
blue: 255
|
||||
},
|
||||
alpha: 1,
|
||||
solid: false
|
||||
solid: false,
|
||||
grabbable: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -60,4 +61,4 @@ function cleanup() {
|
|||
}
|
||||
}
|
||||
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
|
|
|
@ -42,52 +42,6 @@ function jointToWorldPointTest_update(deltaTime) {
|
|||
Entities.editEntity(jointToWorldPointTest_sphereEntity, newProperties);
|
||||
}
|
||||
|
||||
//jointToWorldDirection
|
||||
// create line in world space
|
||||
// each frame calculate world space direction of players head z axis
|
||||
// update line to match
|
||||
var jointToWorldDirectionTest_lineEntity;
|
||||
function jointToWorldDirectionTest() {
|
||||
var jointIndex = MyAvatar.getJointIndex("Head");
|
||||
var avatarPos = MyAvatar.getJointPosition(jointIndex);
|
||||
|
||||
var jointDir = { x: 1, y: 0, z: 1 };
|
||||
var worldDir = MyAvatar.jointToWorldDirection(jointDir, jointIndex);
|
||||
print(worldDir.x);
|
||||
print(worldDir.y);
|
||||
print(worldDir.z);
|
||||
jointToWorldDirectionTest_lineEntity = Entities.addEntity({
|
||||
type: "Line",
|
||||
color: {red: 250, green: 0, blue: 0},
|
||||
dimensions: {x: 5, y: 5, z: 5},
|
||||
lifetime: 10.0,
|
||||
linePoints: [{
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}, worldDir
|
||||
],
|
||||
position : avatarPos,
|
||||
});
|
||||
}
|
||||
function jointToWorldDirection_update(deltaTime) {
|
||||
var jointIndex = MyAvatar.getJointIndex("Head");
|
||||
var avatarPos = MyAvatar.getJointPosition(jointIndex);
|
||||
var jointDir = { x: 1, y: 0, z: 0 };
|
||||
var worldDir = MyAvatar.jointToWorldDirection(jointDir, jointIndex);
|
||||
var newProperties = {
|
||||
linePoints: [{
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}, worldDir
|
||||
],
|
||||
position : avatarPos
|
||||
};
|
||||
|
||||
Entities.editEntity(jointToWorldDirectionTest_lineEntity, newProperties);
|
||||
}
|
||||
|
||||
//jointToWorldRotation
|
||||
// create box in world space
|
||||
// each frame calculate world space rotation of players head
|
||||
|
|
|
@ -49,53 +49,6 @@ function worldToJointPointTest() {
|
|||
Entities.addEntity(worldSphereProps);
|
||||
}
|
||||
|
||||
//worldToJointDirection
|
||||
// create line and attach to avatars head
|
||||
// each frame calculate direction of world x axis in joint space of players head
|
||||
// update arrow orientation to match
|
||||
var worldToJointDirectionTest_lineEntity;
|
||||
function worldToJointDirectionTest() {
|
||||
var jointIndex = MyAvatar.getJointIndex("Head");
|
||||
|
||||
var jointPosition_WorldSpace = MyAvatar.getJointPosition(jointIndex);
|
||||
var jointOffset_WorldSpace = { x: 0, y: 0, z: 0 };
|
||||
var jointPosition_WorldSpaceOffset = Vec3.sum(jointPosition_WorldSpace, jointOffset_WorldSpace);
|
||||
var jointPosition_JointSpaceOffset = MyAvatar.worldToJointPoint(jointPosition_WorldSpaceOffset, jointIndex);
|
||||
|
||||
var worldDir = { x: 1, y: 0, z: 0 };
|
||||
var avatarDir = MyAvatar.worldToJointDirection(worldDir, jointIndex);
|
||||
|
||||
worldToJointDirectionTest_lineEntity = Entities.addEntity({
|
||||
type: "Line",
|
||||
color: {red: 200, green: 250, blue: 0},
|
||||
dimensions: {x: 5, y: 5, z: 5},
|
||||
lifetime: 10.0,
|
||||
linePoints: [{
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}, avatarDir
|
||||
],
|
||||
localPosition : jointOffset_WorldSpace,
|
||||
parentID : AVATAR_SELF_ID,
|
||||
parentJointIndex : jointIndex
|
||||
});
|
||||
}
|
||||
|
||||
function worldToJointDirectionTest_update(deltaTime) {
|
||||
var jointIndex = MyAvatar.getJointIndex("Head");
|
||||
var worldDir = { x: 1, y: 0, z: 0 };
|
||||
var avatarDir = MyAvatar.worldToJointDirection(worldDir, jointIndex);
|
||||
var newProperties = { linePoints: [{
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
}, avatarDir
|
||||
]};
|
||||
|
||||
Entities.editEntity(worldToJointDirectionTest_lineEntity, newProperties);
|
||||
}
|
||||
|
||||
//worldToJointRotation
|
||||
// create box and parent to some player joint
|
||||
// convert world identity rotation to joint space rotation
|
||||
|
|
497
scripts/system/controllers/controllerModules/farGrabEntity.js
Normal file
497
scripts/system/controllers/controllerModules/farGrabEntity.js
Normal file
|
@ -0,0 +1,497 @@
|
|||
"use strict";
|
||||
|
||||
// farGrabEntity.js
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* jslint bitwise: true */
|
||||
|
||||
/* global Script, Controller, RIGHT_HAND, LEFT_HAND, Mat4, MyAvatar, Vec3, Quat, getEnabledModuleByName, makeRunningValues,
|
||||
Entities, enableDispatcherModule, disableDispatcherModule, entityIsGrabbable, makeDispatcherModuleParameters, MSECS_PER_SEC,
|
||||
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC,
|
||||
projectOntoEntityXYPlane, ContextOverlay, HMD, Picks, makeLaserLockInfo, makeLaserParams, AddressManager,
|
||||
getEntityParents, Selection, DISPATCHER_HOVERING_LIST, unhighlightTargetEntity, Messages, findGroupParent,
|
||||
worldPositionToRegistrationFrameMatrix, DISPATCHER_PROPERTIES
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
(function() {
|
||||
var MARGIN = 25;
|
||||
|
||||
function TargetObject(entityID, entityProps) {
|
||||
this.entityID = entityID;
|
||||
this.entityProps = entityProps;
|
||||
this.targetEntityID = null;
|
||||
this.targetEntityProps = null;
|
||||
|
||||
this.getTargetEntity = function() {
|
||||
var parentPropsLength = this.parentProps.length;
|
||||
if (parentPropsLength !== 0) {
|
||||
var targetEntity = {
|
||||
id: this.parentProps[parentPropsLength - 1].id,
|
||||
props: this.parentProps[parentPropsLength - 1]};
|
||||
this.targetEntityID = targetEntity.id;
|
||||
this.targetEntityProps = targetEntity.props;
|
||||
return targetEntity;
|
||||
}
|
||||
this.targetEntityID = this.entityID;
|
||||
this.targetEntityProps = this.entityProps;
|
||||
return {
|
||||
id: this.entityID,
|
||||
props: this.entityProps};
|
||||
};
|
||||
}
|
||||
|
||||
function FarGrabEntity(hand) {
|
||||
this.hand = hand;
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
this.targetObject = null;
|
||||
this.previouslyUnhooked = {};
|
||||
this.potentialEntityWithContextOverlay = false;
|
||||
this.entityWithContextOverlay = false;
|
||||
this.contextOverlayTimer = false;
|
||||
this.reticleMinX = MARGIN;
|
||||
this.reticleMaxX = 0;
|
||||
this.reticleMinY = MARGIN;
|
||||
this.reticleMaxY = 0;
|
||||
this.endedGrab = 0;
|
||||
this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms
|
||||
|
||||
var FAR_GRAB_JOINTS = [65527, 65528]; // FARGRAB_LEFTHAND_INDEX, FARGRAB_RIGHTHAND_INDEX
|
||||
|
||||
var DISTANCE_HOLDING_RADIUS_FACTOR = 3.5; // multiplied by distance between hand and object
|
||||
var DISTANCE_HOLDING_ACTION_TIMEFRAME = 0.1; // how quickly objects move to their new position
|
||||
var DISTANCE_HOLDING_UNITY_MASS = 1200; // The mass at which the distance holding action timeframe is unmodified
|
||||
var DISTANCE_HOLDING_UNITY_DISTANCE = 6; // The distance at which the distance holding action timeframe is unmodified
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
540,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100,
|
||||
makeLaserParams(this.hand, false));
|
||||
|
||||
|
||||
this.handToController = function() {
|
||||
return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
};
|
||||
|
||||
this.distanceGrabTimescale = function(mass, distance) {
|
||||
var timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME * mass /
|
||||
DISTANCE_HOLDING_UNITY_MASS * distance /
|
||||
DISTANCE_HOLDING_UNITY_DISTANCE;
|
||||
if (timeScale < DISTANCE_HOLDING_ACTION_TIMEFRAME) {
|
||||
timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME;
|
||||
}
|
||||
return timeScale;
|
||||
};
|
||||
|
||||
this.getMass = function(dimensions, density) {
|
||||
return (dimensions.x * dimensions.y * dimensions.z) * density;
|
||||
};
|
||||
|
||||
this.startFarGrabEntity = function (controllerData, targetProps) {
|
||||
var controllerLocation = controllerData.controllerLocations[this.hand];
|
||||
var worldControllerPosition = controllerLocation.position;
|
||||
var worldControllerRotation = controllerLocation.orientation;
|
||||
// transform the position into room space
|
||||
var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix());
|
||||
var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition);
|
||||
|
||||
var now = Date.now();
|
||||
|
||||
// add the action and initialize some variables
|
||||
this.currentObjectPosition = targetProps.position;
|
||||
this.currentObjectRotation = targetProps.rotation;
|
||||
this.currentObjectTime = now;
|
||||
|
||||
this.grabRadius = this.grabbedDistance;
|
||||
this.grabRadialVelocity = 0.0;
|
||||
|
||||
// offset between controller vector at the grab radius and the entity position
|
||||
var targetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation));
|
||||
targetPosition = Vec3.sum(targetPosition, worldControllerPosition);
|
||||
this.offsetPosition = Vec3.subtract(this.currentObjectPosition, targetPosition);
|
||||
|
||||
// compute a constant based on the initial conditions which we use below to exaggerate hand motion
|
||||
// onto the held object
|
||||
this.radiusScalar = Math.log(this.grabRadius + 1.0);
|
||||
if (this.radiusScalar < 1.0) {
|
||||
this.radiusScalar = 1.0;
|
||||
}
|
||||
|
||||
// compute the mass for the purpose of energy and how quickly to move object
|
||||
this.mass = this.getMass(targetProps.dimensions, targetProps.density);
|
||||
|
||||
// Debounce haptic pules. Can occur as near grab controller module vacillates between being ready or not due to
|
||||
// changing positions and floating point rounding.
|
||||
if (Date.now() - this.endedGrab > this.MIN_HAPTIC_PULSE_INTERVAL) {
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
}
|
||||
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
var message = {
|
||||
hand: this.hand,
|
||||
entityID: this.targetEntityID
|
||||
};
|
||||
|
||||
Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message));
|
||||
|
||||
var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position);
|
||||
MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal);
|
||||
MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], { x: 0, y: 0, z: 0, w: 1 });
|
||||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(targetProps.id, "startDistanceGrab", args);
|
||||
|
||||
this.targetEntityID = targetProps.id;
|
||||
|
||||
|
||||
if (this.grabID) {
|
||||
MyAvatar.releaseGrab(this.grabID);
|
||||
}
|
||||
var farJointIndex = FAR_GRAB_JOINTS[this.hand];
|
||||
this.grabID = MyAvatar.grab(targetProps.id, farJointIndex,
|
||||
Entities.worldToLocalPosition(targetProps.position, MyAvatar.SELF_ID, farJointIndex),
|
||||
Entities.worldToLocalRotation(targetProps.rotation, MyAvatar.SELF_ID, farJointIndex));
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'grab',
|
||||
grabbedEntity: targetProps.id,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
this.grabbing = true;
|
||||
|
||||
this.previousRoomControllerPosition = roomControllerPosition;
|
||||
};
|
||||
|
||||
this.continueDistanceHolding = function(controllerData) {
|
||||
var controllerLocation = controllerData.controllerLocations[this.hand];
|
||||
var worldControllerPosition = controllerLocation.position;
|
||||
var worldControllerRotation = controllerLocation.orientation;
|
||||
|
||||
// also transform the position into room space
|
||||
var worldToSensorMat = Mat4.inverse(MyAvatar.getSensorToWorldMatrix());
|
||||
var roomControllerPosition = Mat4.transformPoint(worldToSensorMat, worldControllerPosition);
|
||||
|
||||
var targetProps = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES);
|
||||
var now = Date.now();
|
||||
var deltaObjectTime = (now - this.currentObjectTime) / MSECS_PER_SEC; // convert to seconds
|
||||
this.currentObjectTime = now;
|
||||
|
||||
// the action was set up when this.distanceHolding was called. update the targets.
|
||||
var radius = Vec3.distance(this.currentObjectPosition, worldControllerPosition) *
|
||||
this.radiusScalar * DISTANCE_HOLDING_RADIUS_FACTOR;
|
||||
if (radius < 1.0) {
|
||||
radius = 1.0;
|
||||
}
|
||||
|
||||
var roomHandDelta = Vec3.subtract(roomControllerPosition, this.previousRoomControllerPosition);
|
||||
var worldHandDelta = Mat4.transformVector(MyAvatar.getSensorToWorldMatrix(), roomHandDelta);
|
||||
var handMoved = Vec3.multiply(worldHandDelta, radius);
|
||||
this.currentObjectPosition = Vec3.sum(this.currentObjectPosition, handMoved);
|
||||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "continueDistanceGrab", args);
|
||||
|
||||
// Update radialVelocity
|
||||
var lastVelocity = Vec3.multiply(worldHandDelta, 1.0 / deltaObjectTime);
|
||||
var delta = Vec3.normalize(Vec3.subtract(targetProps.position, worldControllerPosition));
|
||||
var newRadialVelocity = Vec3.dot(lastVelocity, delta);
|
||||
|
||||
var VELOCITY_AVERAGING_TIME = 0.016;
|
||||
var blendFactor = deltaObjectTime / VELOCITY_AVERAGING_TIME;
|
||||
if (blendFactor < 0.0) {
|
||||
blendFactor = 0.0;
|
||||
} else if (blendFactor > 1.0) {
|
||||
blendFactor = 1.0;
|
||||
}
|
||||
this.grabRadialVelocity = blendFactor * newRadialVelocity + (1.0 - blendFactor) * this.grabRadialVelocity;
|
||||
|
||||
var RADIAL_GRAB_AMPLIFIER = 10.0;
|
||||
if (Math.abs(this.grabRadialVelocity) > 0.0) {
|
||||
this.grabRadius = this.grabRadius + (this.grabRadialVelocity * deltaObjectTime *
|
||||
this.grabRadius * RADIAL_GRAB_AMPLIFIER);
|
||||
}
|
||||
|
||||
// don't let grabRadius go all the way to zero, because it can't come back from that
|
||||
var MINIMUM_GRAB_RADIUS = 0.1;
|
||||
if (this.grabRadius < MINIMUM_GRAB_RADIUS) {
|
||||
this.grabRadius = MINIMUM_GRAB_RADIUS;
|
||||
}
|
||||
var newTargetPosition = Vec3.multiply(this.grabRadius, Quat.getUp(worldControllerRotation));
|
||||
newTargetPosition = Vec3.sum(newTargetPosition, worldControllerPosition);
|
||||
newTargetPosition = Vec3.sum(newTargetPosition, this.offsetPosition);
|
||||
|
||||
// MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], MyAvatar.worldToJointPoint(newTargetPosition));
|
||||
|
||||
// var newTargetPosLocal = Mat4.transformPoint(MyAvatar.getSensorToWorldMatrix(), newTargetPosition);
|
||||
var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition);
|
||||
MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal);
|
||||
MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], { x: 0, y: 0, z: 0, w: 1 });
|
||||
|
||||
this.previousRoomControllerPosition = roomControllerPosition;
|
||||
};
|
||||
|
||||
this.endFarGrabEntity = function (controllerData) {
|
||||
if (this.grabID) {
|
||||
MyAvatar.releaseGrab(this.grabID);
|
||||
this.grabID = null;
|
||||
}
|
||||
|
||||
this.endedGrab = Date.now();
|
||||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args);
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
unhighlightTargetEntity(this.targetEntityID);
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
this.potentialEntityWithContextOverlay = false;
|
||||
MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]);
|
||||
};
|
||||
|
||||
this.updateRecommendedArea = function() {
|
||||
var dims = Controller.getViewportDimensions();
|
||||
this.reticleMaxX = dims.x - MARGIN;
|
||||
this.reticleMaxY = dims.y - MARGIN;
|
||||
};
|
||||
|
||||
this.calculateNewReticlePosition = function(intersection) {
|
||||
this.updateRecommendedArea();
|
||||
var point2d = HMD.overlayFromWorldPoint(intersection);
|
||||
point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX));
|
||||
point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY));
|
||||
return point2d;
|
||||
};
|
||||
|
||||
this.notPointingAtEntity = function(controllerData) {
|
||||
var intersection = controllerData.rayPicks[this.hand];
|
||||
var entityProperty = Entities.getEntityProperties(intersection.objectID, DISPATCHER_PROPERTIES);
|
||||
var entityType = entityProperty.type;
|
||||
var hudRayPick = controllerData.hudRayPicks[this.hand];
|
||||
var point2d = this.calculateNewReticlePosition(hudRayPick.intersection);
|
||||
if ((intersection.type === Picks.INTERSECTED_ENTITY && entityType === "Web") ||
|
||||
intersection.type === Picks.INTERSECTED_OVERLAY || Window.isPointOnDesktopWindow(point2d)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.destroyContextOverlay = function(controllerData) {
|
||||
if (this.entityWithContextOverlay) {
|
||||
ContextOverlay.destroyContextOverlay(this.entityWithContextOverlay);
|
||||
this.entityWithContextOverlay = false;
|
||||
this.potentialEntityWithContextOverlay = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.targetIsNull = function() {
|
||||
var properties = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES);
|
||||
if (Object.keys(properties).length === 0 && this.distanceHolding) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
this.getTargetProps = function (controllerData) {
|
||||
var targetEntity = controllerData.rayPicks[this.hand].objectID;
|
||||
if (targetEntity) {
|
||||
var gtProps = Entities.getEntityProperties(targetEntity, DISPATCHER_PROPERTIES);
|
||||
if (entityIsGrabbable(gtProps)) {
|
||||
// if we've attempted to grab a child, roll up to the root of the tree
|
||||
var groupRootProps = findGroupParent(controllerData, gtProps);
|
||||
if (entityIsGrabbable(groupRootProps)) {
|
||||
return groupRootProps;
|
||||
}
|
||||
return gtProps;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData) {
|
||||
if (HMD.active) {
|
||||
if (this.notPointingAtEntity(controllerData)) {
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
this.distanceHolding = false;
|
||||
|
||||
if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) {
|
||||
return makeRunningValues(true, [], []);
|
||||
} else {
|
||||
this.destroyContextOverlay();
|
||||
}
|
||||
}
|
||||
return makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
this.run = function (controllerData) {
|
||||
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) {
|
||||
this.endFarGrabEntity(controllerData);
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
this.intersectionDistance = controllerData.rayPicks[this.hand].distance;
|
||||
|
||||
// gather up the readiness of the near-grab modules
|
||||
var nearGrabNames = [
|
||||
this.hand === RIGHT_HAND ? "RightScaleAvatar" : "LeftScaleAvatar",
|
||||
this.hand === RIGHT_HAND ? "RightFarTriggerEntity" : "LeftFarTriggerEntity",
|
||||
this.hand === RIGHT_HAND ? "RightNearGrabEntity" : "LeftNearGrabEntity"
|
||||
];
|
||||
if (!this.grabbing) {
|
||||
nearGrabNames.push(this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay");
|
||||
nearGrabNames.push(this.hand === RIGHT_HAND ? "RightNearTabletHighlight" : "LeftNearTabletHighlight");
|
||||
}
|
||||
|
||||
var nearGrabReadiness = [];
|
||||
for (var i = 0; i < nearGrabNames.length; i++) {
|
||||
var nearGrabModule = getEnabledModuleByName(nearGrabNames[i]);
|
||||
var ready = nearGrabModule ? nearGrabModule.isReady(controllerData) : makeRunningValues(false, [], []);
|
||||
nearGrabReadiness.push(ready);
|
||||
}
|
||||
|
||||
if (this.targetEntityID) {
|
||||
// if we are doing a distance grab and the object gets close enough to the controller,
|
||||
// stop the far-grab so the near-grab or equip can take over.
|
||||
for (var k = 0; k < nearGrabReadiness.length; k++) {
|
||||
if (nearGrabReadiness[k].active && (nearGrabReadiness[k].targets[0] === this.targetEntityID)) {
|
||||
this.endFarGrabEntity(controllerData);
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
}
|
||||
|
||||
this.continueDistanceHolding(controllerData);
|
||||
} else {
|
||||
// if we are doing a distance search and this controller moves into a position
|
||||
// where it could near-grab something, stop searching.
|
||||
for (var j = 0; j < nearGrabReadiness.length; j++) {
|
||||
if (nearGrabReadiness[j].active) {
|
||||
this.endFarGrabEntity(controllerData);
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
}
|
||||
|
||||
var rayPickInfo = controllerData.rayPicks[this.hand];
|
||||
if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) {
|
||||
if (controllerData.triggerClicks[this.hand]) {
|
||||
var entityID = rayPickInfo.objectID;
|
||||
var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES);
|
||||
if (targetProps.href !== "") {
|
||||
AddressManager.handleLookupString(targetProps.href);
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
this.targetObject = new TargetObject(entityID, targetProps);
|
||||
this.targetObject.parentProps = getEntityParents(targetProps);
|
||||
|
||||
if (this.contextOverlayTimer) {
|
||||
Script.clearTimeout(this.contextOverlayTimer);
|
||||
}
|
||||
this.contextOverlayTimer = false;
|
||||
if (entityID === this.entityWithContextOverlay) {
|
||||
this.destroyContextOverlay();
|
||||
} else {
|
||||
Selection.removeFromSelectedItemsList("contextOverlayHighlightList", "entity", entityID);
|
||||
}
|
||||
|
||||
var targetEntity = this.targetObject.getTargetEntity();
|
||||
entityID = targetEntity.id;
|
||||
targetProps = targetEntity.props;
|
||||
|
||||
if (entityIsGrabbable(targetProps) || entityIsGrabbable(this.targetObject.entityProps)) {
|
||||
|
||||
this.targetEntityID = entityID;
|
||||
this.grabbedDistance = rayPickInfo.distance;
|
||||
this.distanceHolding = true;
|
||||
this.startFarGrabEntity(controllerData, targetProps);
|
||||
}
|
||||
} else if (!this.entityWithContextOverlay) {
|
||||
var _this = this;
|
||||
|
||||
if (_this.potentialEntityWithContextOverlay !== rayPickInfo.objectID) {
|
||||
if (_this.contextOverlayTimer) {
|
||||
Script.clearTimeout(_this.contextOverlayTimer);
|
||||
}
|
||||
_this.contextOverlayTimer = false;
|
||||
_this.potentialEntityWithContextOverlay = rayPickInfo.objectID;
|
||||
}
|
||||
|
||||
if (!_this.contextOverlayTimer) {
|
||||
_this.contextOverlayTimer = Script.setTimeout(function () {
|
||||
if (!_this.entityWithContextOverlay &&
|
||||
_this.contextOverlayTimer &&
|
||||
_this.potentialEntityWithContextOverlay === rayPickInfo.objectID) {
|
||||
var cotProps = Entities.getEntityProperties(rayPickInfo.objectID,
|
||||
DISPATCHER_PROPERTIES);
|
||||
var pointerEvent = {
|
||||
type: "Move",
|
||||
id: _this.hand + 1, // 0 is reserved for hardware mouse
|
||||
pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID,
|
||||
rayPickInfo.intersection, cotProps),
|
||||
pos3D: rayPickInfo.intersection,
|
||||
normal: rayPickInfo.surfaceNormal,
|
||||
direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal),
|
||||
button: "Secondary"
|
||||
};
|
||||
if (ContextOverlay.createOrDestroyContextOverlay(rayPickInfo.objectID, pointerEvent)) {
|
||||
_this.entityWithContextOverlay = rayPickInfo.objectID;
|
||||
}
|
||||
}
|
||||
_this.contextOverlayTimer = false;
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return this.exitIfDisabled(controllerData);
|
||||
};
|
||||
|
||||
this.exitIfDisabled = function(controllerData) {
|
||||
var moduleName = this.hand === RIGHT_HAND ? "RightDisableModules" : "LeftDisableModules";
|
||||
var disableModule = getEnabledModuleByName(moduleName);
|
||||
if (disableModule) {
|
||||
if (disableModule.disableModules) {
|
||||
this.endFarGrabEntity(controllerData);
|
||||
Selection.removeFromSelectedItemsList(DISPATCHER_HOVERING_LIST, "entity", this.highlightedEntity);
|
||||
this.highlightedEntity = null;
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
}
|
||||
var grabbedThing = this.distanceHolding ? this.targetObject.entityID : null;
|
||||
var offset = this.calculateOffset(controllerData);
|
||||
var laserLockInfo = makeLaserLockInfo(grabbedThing, false, this.hand, offset);
|
||||
return makeRunningValues(true, [], [], laserLockInfo);
|
||||
};
|
||||
|
||||
this.calculateOffset = function(controllerData) {
|
||||
if (this.distanceHolding) {
|
||||
var targetProps = Entities.getEntityProperties(this.targetObject.entityID,
|
||||
[ "position", "rotation", "registrationPoint", "dimensions" ]);
|
||||
return worldPositionToRegistrationFrameMatrix(targetProps, controllerData.rayPicks[this.hand].intersection);
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
}
|
||||
|
||||
var leftFarGrabEntity = new FarGrabEntity(LEFT_HAND);
|
||||
var rightFarGrabEntity = new FarGrabEntity(RIGHT_HAND);
|
||||
|
||||
enableDispatcherModule("LeftFarGrabEntity", leftFarGrabEntity);
|
||||
enableDispatcherModule("RightFarGrabEntity", rightFarGrabEntity);
|
||||
|
||||
function cleanup() {
|
||||
disableDispatcherModule("LeftFarGrabEntity");
|
||||
disableDispatcherModule("RightFarGrabEntity");
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
|
@ -8,10 +8,10 @@
|
|||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND,
|
||||
getControllerJointIndex, getGrabbableData, enableDispatcherModule, disableDispatcherModule,
|
||||
propsArePhysical, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, entityIsGrabbable,
|
||||
Quat, Vec3, MSECS_PER_SEC, getControllerWorldLocation, makeDispatcherModuleParameters, makeRunningValues,
|
||||
MSECS_PER_SEC, makeDispatcherModuleParameters, makeRunningValues,
|
||||
TRIGGER_OFF_VALUE, NEAR_GRAB_RADIUS, findGroupParent, entityIsCloneable, propsAreCloneDynamic, cloneEntity,
|
||||
HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, unhighlightTargetEntity, Uuid,
|
||||
DISPATCHER_PROPERTIES
|
||||
DISPATCHER_PROPERTIES, HMD
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -65,25 +65,14 @@ Script.include("/~/system/libraries/cloneEntityUtils.js");
|
|||
this.grabFollowsController = grabbableData.grabFollowsController;
|
||||
this.kinematicGrab = grabbableData.grabKinematic;
|
||||
|
||||
var handRotation;
|
||||
var handPosition;
|
||||
if (this.grabFollowsController) {
|
||||
var controllerID =
|
||||
(this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand;
|
||||
var controllerLocation = getControllerWorldLocation(controllerID, false);
|
||||
handRotation = controllerLocation.orientation;
|
||||
handPosition = controllerLocation.position;
|
||||
var handJointIndex;
|
||||
if (HMD.mounted && HMD.isHandControllerAvailable() && grabbableData.grabFollowsController) {
|
||||
handJointIndex = getControllerJointIndex(this.hand);
|
||||
} else {
|
||||
handRotation = this.getHandRotation();
|
||||
handPosition = this.getHandPosition();
|
||||
handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||
}
|
||||
|
||||
var objectRotation = targetProps.rotation;
|
||||
this.offsetRotation = Quat.multiply(Quat.inverse(handRotation), objectRotation);
|
||||
|
||||
var currentObjectPosition = targetProps.position;
|
||||
var offset = Vec3.subtract(currentObjectPosition, handPosition);
|
||||
this.offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, this.offsetRotation)), offset);
|
||||
this.offsetPosition = Entities.worldToLocalPosition(targetProps.position, MyAvatar.SELF_ID, handJointIndex);
|
||||
this.offsetRotation = Entities.worldToLocalRotation(targetProps.rotation, MyAvatar.SELF_ID, handJointIndex);
|
||||
|
||||
var now = Date.now();
|
||||
this.actionTimeout = now + (ACTION_TTL * MSECS_PER_SEC);
|
||||
|
|
225
scripts/system/controllers/controllerModules/nearGrabEntity.js
Normal file
225
scripts/system/controllers/controllerModules/nearGrabEntity.js
Normal file
|
@ -0,0 +1,225 @@
|
|||
"use strict";
|
||||
|
||||
// nearGrabEntity.js
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
/* global Script, Entities, MyAvatar, Controller, RIGHT_HAND, LEFT_HAND, getControllerJointIndex, enableDispatcherModule,
|
||||
disableDispatcherModule, Messages, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, TRIGGER_OFF_VALUE,
|
||||
makeDispatcherModuleParameters, entityIsGrabbable, makeRunningValues, NEAR_GRAB_RADIUS, findGroupParent, Vec3, cloneEntity,
|
||||
entityIsCloneable, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, BUMPER_ON_VALUE, distanceBetweenPointAndEntityBoundingBox,
|
||||
getGrabbableData, getEnabledModuleByName, DISPATCHER_PROPERTIES, HMD, NEAR_GRAB_DISTANCE
|
||||
*/
|
||||
|
||||
Script.include("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
Script.include("/~/system/libraries/cloneEntityUtils.js");
|
||||
Script.include("/~/system/libraries/controllers.js");
|
||||
|
||||
(function() {
|
||||
|
||||
function NearGrabEntity(hand) {
|
||||
this.hand = hand;
|
||||
this.targetEntityID = null;
|
||||
this.grabbing = false;
|
||||
this.cloneAllowed = true;
|
||||
this.grabID = null;
|
||||
|
||||
this.parameters = makeDispatcherModuleParameters(
|
||||
500,
|
||||
this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"],
|
||||
[],
|
||||
100);
|
||||
|
||||
this.startGrab = function (targetProps) {
|
||||
if (this.grabID) {
|
||||
MyAvatar.releaseGrab(this.grabID);
|
||||
}
|
||||
|
||||
var grabData = getGrabbableData(targetProps);
|
||||
|
||||
var handJointIndex;
|
||||
if (HMD.mounted && HMD.isHandControllerAvailable() && grabData.grabFollowsController) {
|
||||
handJointIndex = getControllerJointIndex(this.hand);
|
||||
} else {
|
||||
handJointIndex = MyAvatar.getJointIndex(this.hand === RIGHT_HAND ? "RightHand" : "LeftHand");
|
||||
}
|
||||
|
||||
this.targetEntityID = targetProps.id;
|
||||
|
||||
var relativePosition = Entities.worldToLocalPosition(targetProps.position, MyAvatar.SELF_ID, handJointIndex);
|
||||
var relativeRotation = Entities.worldToLocalRotation(targetProps.rotation, MyAvatar.SELF_ID, handJointIndex);
|
||||
this.grabID = MyAvatar.grab(targetProps.id, handJointIndex, relativePosition, relativeRotation);
|
||||
};
|
||||
|
||||
this.startNearGrabEntity = function (targetProps) {
|
||||
Controller.triggerHapticPulse(HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, this.hand);
|
||||
|
||||
this.startGrab(targetProps);
|
||||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(targetProps.id, "startNearGrab", args);
|
||||
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'grab',
|
||||
grabbedEntity: targetProps.id,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
|
||||
this.grabbing = true;
|
||||
};
|
||||
|
||||
this.endGrab = function () {
|
||||
if (this.grabID) {
|
||||
MyAvatar.releaseGrab(this.grabID);
|
||||
this.grabID = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.endNearGrabEntity = function () {
|
||||
this.endGrab();
|
||||
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "releaseGrab", args);
|
||||
Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({
|
||||
action: 'release',
|
||||
grabbedEntity: this.targetEntityID,
|
||||
joint: this.hand === RIGHT_HAND ? "RightHand" : "LeftHand"
|
||||
}));
|
||||
};
|
||||
|
||||
this.getTargetProps = function (controllerData) {
|
||||
// nearbyEntityProperties is already sorted by length from controller
|
||||
var nearbyEntityProperties = controllerData.nearbyEntityProperties[this.hand];
|
||||
var sensorScaleFactor = MyAvatar.sensorToWorldScale;
|
||||
var nearGrabDistance = NEAR_GRAB_DISTANCE * sensorScaleFactor;
|
||||
var nearGrabRadius = NEAR_GRAB_RADIUS * sensorScaleFactor;
|
||||
for (var i = 0; i < nearbyEntityProperties.length; i++) {
|
||||
var props = nearbyEntityProperties[i];
|
||||
var grabPosition = controllerData.controllerLocations[this.hand].position; // Is offset from hand position.
|
||||
var dist = distanceBetweenPointAndEntityBoundingBox(grabPosition, props);
|
||||
var distance = Vec3.distance(grabPosition, props.position);
|
||||
if ((dist > nearGrabDistance) ||
|
||||
(distance > nearGrabRadius)) { // Only smallish entities can be near grabbed.
|
||||
continue;
|
||||
}
|
||||
if (entityIsGrabbable(props) || entityIsCloneable(props)) {
|
||||
if (!entityIsCloneable(props)) {
|
||||
// if we've attempted to grab a non-cloneable child, roll up to the root of the tree
|
||||
var groupRootProps = findGroupParent(controllerData, props);
|
||||
if (entityIsGrabbable(groupRootProps)) {
|
||||
return groupRootProps;
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
this.isReady = function (controllerData, deltaTime) {
|
||||
this.targetEntityID = null;
|
||||
this.grabbing = false;
|
||||
|
||||
if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE &&
|
||||
controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) {
|
||||
this.cloneAllowed = true;
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
var scaleModuleName = this.hand === RIGHT_HAND ? "RightScaleEntity" : "LeftScaleEntity";
|
||||
var scaleModule = getEnabledModuleByName(scaleModuleName);
|
||||
if (scaleModule.grabbedThingID || scaleModule.isReady(controllerData).active) {
|
||||
// we're rescaling -- don't start a grab.
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
var targetProps = this.getTargetProps(controllerData);
|
||||
if (targetProps) {
|
||||
this.targetEntityID = targetProps.id;
|
||||
return makeRunningValues(true, [this.targetEntityID], []);
|
||||
} else {
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
};
|
||||
|
||||
this.run = function (controllerData, deltaTime) {
|
||||
|
||||
if (this.grabbing) {
|
||||
if (controllerData.triggerClicks[this.hand] < TRIGGER_OFF_VALUE &&
|
||||
controllerData.secondaryValues[this.hand] < TRIGGER_OFF_VALUE) {
|
||||
this.endNearGrabEntity();
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
|
||||
var props = controllerData.nearbyEntityPropertiesByID[this.targetEntityID];
|
||||
if (!props) {
|
||||
props = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES);
|
||||
if (!props) {
|
||||
// entity was deleted
|
||||
this.grabbing = false;
|
||||
this.targetEntityID = null;
|
||||
return makeRunningValues(false, [], []);
|
||||
}
|
||||
}
|
||||
|
||||
var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID];
|
||||
Entities.callEntityMethod(this.targetEntityID, "continueNearGrab", args);
|
||||
} else {
|
||||
// still searching
|
||||
var readiness = this.isReady(controllerData);
|
||||
if (!readiness.active) {
|
||||
return readiness;
|
||||
}
|
||||
if (controllerData.triggerClicks[this.hand] || controllerData.secondaryValues[this.hand] > BUMPER_ON_VALUE) {
|
||||
// switch to grab
|
||||
var targetProps = this.getTargetProps(controllerData);
|
||||
var targetCloneable = entityIsCloneable(targetProps);
|
||||
|
||||
if (targetCloneable) {
|
||||
if (this.cloneAllowed) {
|
||||
var cloneID = cloneEntity(targetProps);
|
||||
if (cloneID !== null) {
|
||||
var cloneProps = Entities.getEntityProperties(cloneID, DISPATCHER_PROPERTIES);
|
||||
cloneProps.id = cloneID;
|
||||
this.grabbing = true;
|
||||
this.targetEntityID = cloneID;
|
||||
this.startNearGrabEntity(cloneProps);
|
||||
this.cloneAllowed = false; // prevent another clone call until inputs released
|
||||
}
|
||||
}
|
||||
} else if (targetProps) {
|
||||
this.grabbing = true;
|
||||
this.startNearGrabEntity(targetProps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return makeRunningValues(true, [this.targetEntityID], []);
|
||||
};
|
||||
|
||||
this.cleanup = function () {
|
||||
if (this.targetEntityID) {
|
||||
this.endNearGrabEntity();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var leftNearGrabEntity = new NearGrabEntity(LEFT_HAND);
|
||||
var rightNearGrabEntity = new NearGrabEntity(RIGHT_HAND);
|
||||
|
||||
enableDispatcherModule("LeftNearGrabEntity", leftNearGrabEntity);
|
||||
enableDispatcherModule("RightNearGrabEntity", rightNearGrabEntity);
|
||||
|
||||
function cleanup() {
|
||||
leftNearGrabEntity.cleanup();
|
||||
rightNearGrabEntity.cleanup();
|
||||
disableDispatcherModule("LeftNearGrabEntity");
|
||||
disableDispatcherModule("RightNearGrabEntity");
|
||||
}
|
||||
Script.scriptEnding.connect(cleanup);
|
||||
}());
|
|
@ -7,7 +7,7 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
/* global Script, Vec3, MyAvatar, Entities, RIGHT_HAND */
|
||||
/* global Script, Vec3, MyAvatar, Entities, RIGHT_HAND, entityIsGrabbable */
|
||||
|
||||
(function() {
|
||||
var dispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js");
|
||||
|
@ -62,14 +62,19 @@
|
|||
var otherHandTargetProps = otherModule.getTargetProps(controllerData);
|
||||
if (thisHandTargetProps && otherHandTargetProps) {
|
||||
if (thisHandTargetProps.id === otherHandTargetProps.id) {
|
||||
if (!entityIsGrabbable(thisHandTargetProps)) {
|
||||
return dispatcherUtils.makeRunningValues(false, [], []);
|
||||
}
|
||||
this.grabbedThingID = thisHandTargetProps.id;
|
||||
this.scalingStartDistance = Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position,
|
||||
controllerData.controllerLocations[this.otherHand()].position));
|
||||
this.scalingStartDistance =
|
||||
Vec3.length(Vec3.subtract(controllerData.controllerLocations[this.hand].position,
|
||||
controllerData.controllerLocations[this.otherHand()].position));
|
||||
this.scalingStartDimensions = thisHandTargetProps.dimensions;
|
||||
return dispatcherUtils.makeRunningValues(true, [], []);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.grabbedThingID = false;
|
||||
return dispatcherUtils.makeRunningValues(false, [], []);
|
||||
};
|
||||
|
||||
|
@ -82,10 +87,11 @@
|
|||
controllerData.controllerLocations[this.otherHand()].position));
|
||||
var currentRescale = scalingCurrentDistance / this.scalingStartDistance;
|
||||
var newDimensions = Vec3.multiply(currentRescale, this.scalingStartDimensions);
|
||||
Entities.editEntity(this.grabbedThingID, { dimensions: newDimensions });
|
||||
Entities.editEntity(this.grabbedThingID, { localDimensions: newDimensions });
|
||||
}
|
||||
return dispatcherUtils.makeRunningValues(true, [], []);
|
||||
}
|
||||
this.grabbedThingID = false;
|
||||
return dispatcherUtils.makeRunningValues(false, [], []);
|
||||
};
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue