mirror of
https://github.com/overte-org/overte.git
synced 2025-07-24 01:23:55 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into bug/delete-avatar-entity
This commit is contained in:
commit
7fe47e4e2f
21 changed files with 263 additions and 92 deletions
|
@ -65,7 +65,8 @@ Rectangle {
|
||||||
onClicked: {
|
onClicked: {
|
||||||
newModelDialog.keyboardEnabled = HMD.active
|
newModelDialog.keyboardEnabled = HMD.active
|
||||||
parent.focus = true;
|
parent.focus = true;
|
||||||
parent.forceActiveFocus()
|
parent.forceActiveFocus();
|
||||||
|
modelURL.cursorPosition = modelURL.positionAt(mouseX, mouseY, TextInput.CursorBetweenCharaters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1470,6 +1470,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
|
|
||||||
properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
|
properties["throttled"] = _displayPlugin ? _displayPlugin->isThrottled() : false;
|
||||||
|
|
||||||
|
QJsonObject bytesDownloaded;
|
||||||
|
bytesDownloaded["atp"] = statTracker->getStat(STAT_ATP_RESOURCE_TOTAL_BYTES).toInt();
|
||||||
|
bytesDownloaded["http"] = statTracker->getStat(STAT_HTTP_RESOURCE_TOTAL_BYTES).toInt();
|
||||||
|
bytesDownloaded["file"] = statTracker->getStat(STAT_FILE_RESOURCE_TOTAL_BYTES).toInt();
|
||||||
|
bytesDownloaded["total"] = bytesDownloaded["atp"].toInt() + bytesDownloaded["http"].toInt()
|
||||||
|
+ bytesDownloaded["file"].toInt();
|
||||||
|
properties["bytesDownloaded"] = bytesDownloaded;
|
||||||
|
|
||||||
auto myAvatar = getMyAvatar();
|
auto myAvatar = getMyAvatar();
|
||||||
glm::vec3 avatarPosition = myAvatar->getPosition();
|
glm::vec3 avatarPosition = myAvatar->getPosition();
|
||||||
properties["avatar_has_moved"] = lastAvatarPosition != avatarPosition;
|
properties["avatar_has_moved"] = lastAvatarPosition != avatarPosition;
|
||||||
|
@ -2116,6 +2124,7 @@ void Application::initializeUi() {
|
||||||
surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
|
surfaceContext->setContextProperty("ApplicationCompositor", &getApplicationCompositor());
|
||||||
|
|
||||||
surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
surfaceContext->setContextProperty("AvatarInputs", AvatarInputs::getInstance());
|
||||||
|
surfaceContext->setContextProperty("HoverOverlay", DependencyManager::get<HoverOverlayInterface>().data());
|
||||||
|
|
||||||
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) {
|
||||||
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
surfaceContext->setContextProperty("Steam", new SteamScriptingInterface(engine, steamClient.get()));
|
||||||
|
@ -5818,6 +5827,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
||||||
auto entityScriptServerLog = DependencyManager::get<EntityScriptServerLogClient>();
|
auto entityScriptServerLog = DependencyManager::get<EntityScriptServerLogClient>();
|
||||||
scriptEngine->registerGlobalObject("EntityScriptServerLog", entityScriptServerLog.data());
|
scriptEngine->registerGlobalObject("EntityScriptServerLog", entityScriptServerLog.data());
|
||||||
scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance());
|
scriptEngine->registerGlobalObject("AvatarInputs", AvatarInputs::getInstance());
|
||||||
|
scriptEngine->registerGlobalObject("HoverOverlay", DependencyManager::get<HoverOverlayInterface>().data());
|
||||||
|
|
||||||
qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
qScriptRegisterMetaType(scriptEngine, OverlayIDtoScriptValue, OverlayIDfromScriptValue);
|
||||||
|
|
||||||
|
|
|
@ -1075,9 +1075,6 @@ void MyAvatar::loadData() {
|
||||||
|
|
||||||
getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f));
|
getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f));
|
||||||
|
|
||||||
_targetScale = loadSetting(settings, "scale", 1.0f);
|
|
||||||
setScale(glm::vec3(_targetScale));
|
|
||||||
|
|
||||||
_prefOverrideAnimGraphUrl.set(QUrl(settings.value("animGraphURL", "").toString()));
|
_prefOverrideAnimGraphUrl.set(QUrl(settings.value("animGraphURL", "").toString()));
|
||||||
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl();
|
_fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl();
|
||||||
_fullAvatarModelName = settings.value("fullAvatarModelName", DEFAULT_FULL_AVATAR_MODEL_NAME).toString();
|
_fullAvatarModelName = settings.value("fullAvatarModelName", DEFAULT_FULL_AVATAR_MODEL_NAME).toString();
|
||||||
|
@ -2282,17 +2279,27 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings
|
||||||
if (_domainMinimumScale > _domainMaximumScale) {
|
if (_domainMinimumScale > _domainMaximumScale) {
|
||||||
std::swap(_domainMinimumScale, _domainMaximumScale);
|
std::swap(_domainMinimumScale, _domainMaximumScale);
|
||||||
}
|
}
|
||||||
|
// Set avatar current scale
|
||||||
|
Settings settings;
|
||||||
|
settings.beginGroup("Avatar");
|
||||||
|
_targetScale = loadSetting(settings, "scale", 1.0f);
|
||||||
|
|
||||||
qCDebug(interfaceapp, "This domain requires a minimum avatar scale of %f and a maximum avatar scale of %f",
|
qCDebug(interfaceapp) << "This domain requires a minimum avatar scale of " << _domainMinimumScale
|
||||||
(double)_domainMinimumScale, (double)_domainMaximumScale);
|
<< " and a maximum avatar scale of " << _domainMaximumScale
|
||||||
|
<< ". Current avatar scale is " << _targetScale;
|
||||||
|
|
||||||
// debug to log if this avatar's scale in this domain will be clamped
|
// debug to log if this avatar's scale in this domain will be clamped
|
||||||
auto clampedScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale);
|
float clampedScale = glm::clamp(_targetScale, _domainMinimumScale, _domainMaximumScale);
|
||||||
|
|
||||||
if (_targetScale != clampedScale) {
|
if (_targetScale != clampedScale) {
|
||||||
qCDebug(interfaceapp, "Avatar scale will be clamped to %f because %f is not allowed by current domain",
|
qCDebug(interfaceapp) << "Current avatar scale is clamped to " << clampedScale
|
||||||
(double)clampedScale, (double)_targetScale);
|
<< " because " << _targetScale << " is not allowed by current domain";
|
||||||
|
// The current scale of avatar should not be more than domain's max_avatar_scale and not less than domain's min_avatar_scale .
|
||||||
|
_targetScale = clampedScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setScale(glm::vec3(_targetScale));
|
||||||
|
settings.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::clearScaleRestriction() {
|
void MyAvatar::clearScaleRestriction() {
|
||||||
|
|
|
@ -464,12 +464,12 @@ void EntityTreeRenderer::connectSignalsToSlots(EntityScriptingInterface* entityS
|
||||||
connect(this, &EntityTreeRenderer::clickReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickReleaseOnEntity);
|
connect(this, &EntityTreeRenderer::clickReleaseOnEntity, entityScriptingInterface, &EntityScriptingInterface::clickReleaseOnEntity);
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::hoverEnterEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
|
connect(this, &EntityTreeRenderer::hoverEnterEntity, entityScriptingInterface, &EntityScriptingInterface::hoverEnterEntity);
|
||||||
connect(this, &EntityTreeRenderer::hoverEnterEntity, hoverOverlayInterface, &HoverOverlayInterface::createHoverOverlay);
|
connect(this, SIGNAL(hoverEnterEntity(const EntityItemID&, const PointerEvent&)), hoverOverlayInterface, SLOT(createHoverOverlay(const EntityItemID&, const PointerEvent&)));
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::hoverOverEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
connect(this, &EntityTreeRenderer::hoverOverEntity, entityScriptingInterface, &EntityScriptingInterface::hoverOverEntity);
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::hoverLeaveEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
connect(this, &EntityTreeRenderer::hoverLeaveEntity, entityScriptingInterface, &EntityScriptingInterface::hoverLeaveEntity);
|
||||||
connect(this, &EntityTreeRenderer::hoverLeaveEntity, hoverOverlayInterface, &HoverOverlayInterface::destroyHoverOverlay);
|
connect(this, SIGNAL(hoverLeaveEntity(const EntityItemID&, const PointerEvent&)), hoverOverlayInterface, SLOT(destroyHoverOverlay(const EntityItemID&, const PointerEvent&)));
|
||||||
|
|
||||||
connect(this, &EntityTreeRenderer::enterEntity, entityScriptingInterface, &EntityScriptingInterface::enterEntity);
|
connect(this, &EntityTreeRenderer::enterEntity, entityScriptingInterface, &EntityScriptingInterface::enterEntity);
|
||||||
connect(this, &EntityTreeRenderer::leaveEntity, entityScriptingInterface, &EntityScriptingInterface::leaveEntity);
|
connect(this, &EntityTreeRenderer::leaveEntity, entityScriptingInterface, &EntityScriptingInterface::leaveEntity);
|
||||||
|
|
|
@ -46,10 +46,8 @@ bool AddEntityOperator::preRecursion(const OctreeElementPointer& element) {
|
||||||
|
|
||||||
// If this element is the best fit for the new entity properties, then add/or update it
|
// If this element is the best fit for the new entity properties, then add/or update it
|
||||||
if (entityTreeElement->bestFitBounds(_newEntityBox)) {
|
if (entityTreeElement->bestFitBounds(_newEntityBox)) {
|
||||||
|
_tree->addEntityMapEntry(_newEntity);
|
||||||
entityTreeElement->addEntityItem(_newEntity);
|
entityTreeElement->addEntityItem(_newEntity);
|
||||||
_tree->setContainingElement(_newEntity->getEntityItemID(), entityTreeElement);
|
|
||||||
|
|
||||||
_foundNew = true;
|
_foundNew = true;
|
||||||
keepSearching = false;
|
keepSearching = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -96,7 +96,7 @@ bool DeleteEntityOperator::preRecursion(const OctreeElementPointer& element) {
|
||||||
bool entityDeleted = entityTreeElement->removeEntityItem(theEntity); // remove it from the element
|
bool entityDeleted = entityTreeElement->removeEntityItem(theEntity); // remove it from the element
|
||||||
assert(entityDeleted);
|
assert(entityDeleted);
|
||||||
(void)entityDeleted; // quite warning
|
(void)entityDeleted; // quite warning
|
||||||
_tree->setContainingElement(details.entity->getEntityItemID(), NULL); // update or id to element lookup
|
_tree->clearEntityMapEntry(details.entity->getEntityItemID());
|
||||||
_foundCount++;
|
_foundCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,8 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) :
|
||||||
|
|
||||||
EntityItem::~EntityItem() {
|
EntityItem::~EntityItem() {
|
||||||
// clear out any left-over actions
|
// clear out any left-over actions
|
||||||
EntityTreePointer entityTree = _element ? _element->getTree() : nullptr;
|
EntityTreeElementPointer element = _element; // use local copy of _element for logic below
|
||||||
|
EntityTreePointer entityTree = element ? element->getTree() : nullptr;
|
||||||
EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||||
if (simulation) {
|
if (simulation) {
|
||||||
clearActions(simulation);
|
clearActions(simulation);
|
||||||
|
@ -880,8 +881,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
// Tracking for editing roundtrips here. We will tell our EntityTree that we just got incoming data about
|
// Tracking for editing roundtrips here. We will tell our EntityTree that we just got incoming data about
|
||||||
// and entity that was edited at some time in the past. The tree will determine how it wants to track this
|
// and entity that was edited at some time in the past. The tree will determine how it wants to track this
|
||||||
// information.
|
// information.
|
||||||
if (_element && _element->getTree()) {
|
EntityTreeElementPointer element = _element; // use local copy of _element for logic below
|
||||||
_element->getTree()->trackIncomingEntityLastEdited(lastEditedFromBufferAdjusted, bytesRead);
|
if (element && element->getTree()) {
|
||||||
|
element->getTree()->trackIncomingEntityLastEdited(lastEditedFromBufferAdjusted, bytesRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2056,7 +2058,8 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi
|
||||||
_previouslyDeletedActions.insert(actionID, usecTimestampNow());
|
_previouslyDeletedActions.insert(actionID, usecTimestampNow());
|
||||||
if (_objectActions.contains(actionID)) {
|
if (_objectActions.contains(actionID)) {
|
||||||
if (!simulation) {
|
if (!simulation) {
|
||||||
EntityTreePointer entityTree = _element ? _element->getTree() : nullptr;
|
EntityTreeElementPointer element = _element; // use local copy of _element for logic below
|
||||||
|
EntityTreePointer entityTree = element ? element->getTree() : nullptr;
|
||||||
simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,13 +90,17 @@ void EntityTree::eraseAllOctreeElements(bool createNewRoot) {
|
||||||
if (_simulation) {
|
if (_simulation) {
|
||||||
_simulation->clearEntities();
|
_simulation->clearEntities();
|
||||||
}
|
}
|
||||||
{
|
QHash<EntityItemID, EntityItemPointer> localMap;
|
||||||
QWriteLocker locker(&_entityToElementLock);
|
localMap.swap(_entityMap);
|
||||||
foreach(EntityTreeElementPointer element, _entityToElementMap) {
|
this->withWriteLock([&] {
|
||||||
|
foreach(EntityItemPointer entity, localMap) {
|
||||||
|
EntityTreeElementPointer element = entity->getElement();
|
||||||
|
if (element) {
|
||||||
element->cleanupEntities();
|
element->cleanupEntities();
|
||||||
}
|
}
|
||||||
_entityToElementMap.clear();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
localMap.clear();
|
||||||
Octree::eraseAllOctreeElements(createNewRoot);
|
Octree::eraseAllOctreeElements(createNewRoot);
|
||||||
|
|
||||||
resetClientEditStats();
|
resetClientEditStats();
|
||||||
|
@ -136,29 +140,24 @@ void EntityTree::postAddEntity(EntityItemPointer entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
|
bool EntityTree::updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
|
||||||
EntityTreeElementPointer containingElement = getContainingElement(entityID);
|
EntityItemPointer entity;
|
||||||
|
{
|
||||||
|
QReadLocker locker(&_entityMapLock);
|
||||||
|
entity = _entityMap.value(entityID);
|
||||||
|
}
|
||||||
|
if (!entity) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return updateEntity(entity, properties, senderNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperties& origProperties,
|
||||||
|
const SharedNodePointer& senderNode) {
|
||||||
|
EntityTreeElementPointer containingElement = entity->getElement();
|
||||||
if (!containingElement) {
|
if (!containingElement) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
|
|
||||||
if (!existingEntity) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return updateEntityWithElement(existingEntity, properties, containingElement, senderNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EntityTree::updateEntity(EntityItemPointer entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode) {
|
|
||||||
EntityTreeElementPointer containingElement = getContainingElement(entity->getEntityItemID());
|
|
||||||
if (!containingElement) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return updateEntityWithElement(entity, properties, containingElement, senderNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& origProperties,
|
|
||||||
EntityTreeElementPointer containingElement, const SharedNodePointer& senderNode) {
|
|
||||||
EntityItemProperties properties = origProperties;
|
EntityItemProperties properties = origProperties;
|
||||||
|
|
||||||
bool allowLockChange;
|
bool allowLockChange;
|
||||||
|
@ -190,7 +189,7 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
||||||
bool success;
|
bool success;
|
||||||
AACube queryCube = entity->getQueryAACube(success);
|
AACube queryCube = entity->getQueryAACube(success);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
qCDebug(entities) << "Warning -- failed to get query-cube for" << entity->getID();
|
qCWarning(entities) << "failed to get query-cube for" << entity->getID();
|
||||||
}
|
}
|
||||||
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, queryCube);
|
UpdateEntityOperator theOperator(getThisPointer(), containingElement, entity, queryCube);
|
||||||
recurseTreeWithOperator(&theOperator);
|
recurseTreeWithOperator(&theOperator);
|
||||||
|
@ -331,9 +330,8 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this final containingElement check should eventually be removed (or wrapped in an #ifdef DEBUG).
|
// TODO: this final containingElement check should eventually be removed (or wrapped in an #ifdef DEBUG).
|
||||||
containingElement = getContainingElement(entity->getEntityItemID());
|
if (!entity->getElement()) {
|
||||||
if (!containingElement) {
|
qCWarning(entities) << "EntityTree::updateEntity() we no longer have a containing element for entityID="
|
||||||
qCDebug(entities) << "UNEXPECTED!!!! after updateEntity() we no longer have a containing element??? entityID="
|
|
||||||
<< entity->getEntityItemID();
|
<< entity->getEntityItemID();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -366,7 +364,7 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti
|
||||||
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
// You should not call this on existing entities that are already part of the tree! Call updateEntity()
|
||||||
EntityTreeElementPointer containingElement = getContainingElement(entityID);
|
EntityTreeElementPointer containingElement = getContainingElement(entityID);
|
||||||
if (containingElement) {
|
if (containingElement) {
|
||||||
qCDebug(entities) << "UNEXPECTED!!! ----- don't call addEntity() on existing entity items. entityID=" << entityID
|
qCWarning(entities) << "EntityTree::addEntity() on existing entity item with entityID=" << entityID
|
||||||
<< "containingElement=" << containingElement.get();
|
<< "containingElement=" << containingElement.get();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -422,7 +420,7 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign
|
||||||
EntityTreeElementPointer containingElement = getContainingElement(entityID);
|
EntityTreeElementPointer containingElement = getContainingElement(entityID);
|
||||||
if (!containingElement) {
|
if (!containingElement) {
|
||||||
if (!ignoreWarnings) {
|
if (!ignoreWarnings) {
|
||||||
qCDebug(entities) << "UNEXPECTED!!!! EntityTree::deleteEntity() entityID doesn't exist!!! entityID=" << entityID;
|
qCWarning(entities) << "EntityTree::deleteEntity() on non-existent entityID=" << entityID;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -430,8 +428,7 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign
|
||||||
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
|
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
|
||||||
if (!existingEntity) {
|
if (!existingEntity) {
|
||||||
if (!ignoreWarnings) {
|
if (!ignoreWarnings) {
|
||||||
qCDebug(entities) << "UNEXPECTED!!!! don't call EntityTree::deleteEntity() on entity items that don't exist. "
|
qCWarning(entities) << "EntityTree::deleteEntity() on non-existant entity item with entityID=" << entityID;
|
||||||
"entityID=" << entityID;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -478,7 +475,7 @@ void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool i
|
||||||
EntityTreeElementPointer containingElement = getContainingElement(entityID);
|
EntityTreeElementPointer containingElement = getContainingElement(entityID);
|
||||||
if (!containingElement) {
|
if (!containingElement) {
|
||||||
if (!ignoreWarnings) {
|
if (!ignoreWarnings) {
|
||||||
qCDebug(entities) << "UNEXPECTED!!!! EntityTree::deleteEntities() entityID doesn't exist!!! entityID=" << entityID;
|
qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entityID=" << entityID;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -486,8 +483,7 @@ void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool i
|
||||||
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
|
EntityItemPointer existingEntity = containingElement->getEntityWithEntityItemID(entityID);
|
||||||
if (!existingEntity) {
|
if (!existingEntity) {
|
||||||
if (!ignoreWarnings) {
|
if (!ignoreWarnings) {
|
||||||
qCDebug(entities) << "UNEXPECTED!!!! don't call EntityTree::deleteEntities() on entity items that don't exist. "
|
qCWarning(entities) << "EntityTree::deleteEntities() on non-existent entity item with entityID=" << entityID;
|
||||||
"entityID=" << entityID;
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -975,7 +971,7 @@ int EntityTree::processEditPacketData(ReceivedMessage& message, const unsigned c
|
||||||
const SharedNodePointer& senderNode) {
|
const SharedNodePointer& senderNode) {
|
||||||
|
|
||||||
if (!getIsServer()) {
|
if (!getIsServer()) {
|
||||||
qCDebug(entities) << "UNEXPECTED!!! processEditPacketData() should only be called on a server tree.";
|
qCWarning(entities) << "EntityTree::processEditPacketData() should only be called on a server tree.";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1502,27 +1498,43 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityTreeElementPointer EntityTree::getContainingElement(const EntityItemID& entityItemID) /*const*/ {
|
EntityTreeElementPointer EntityTree::getContainingElement(const EntityItemID& entityItemID) /*const*/ {
|
||||||
QReadLocker locker(&_entityToElementLock);
|
EntityItemPointer entity;
|
||||||
EntityTreeElementPointer element = _entityToElementMap.value(entityItemID);
|
{
|
||||||
return element;
|
QReadLocker locker(&_entityMapLock);
|
||||||
|
entity = _entityMap.value(entityItemID);
|
||||||
|
}
|
||||||
|
if (entity) {
|
||||||
|
return entity->getElement();
|
||||||
|
}
|
||||||
|
return EntityTreeElementPointer(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element) {
|
void EntityTree::addEntityMapEntry(EntityItemPointer entity) {
|
||||||
QWriteLocker locker(&_entityToElementLock);
|
EntityItemID id = entity->getEntityItemID();
|
||||||
if (element) {
|
QWriteLocker locker(&_entityMapLock);
|
||||||
_entityToElementMap[entityItemID] = element;
|
EntityItemPointer otherEntity = _entityMap.value(id);
|
||||||
} else {
|
if (otherEntity) {
|
||||||
_entityToElementMap.remove(entityItemID);
|
qCWarning(entities) << "EntityTree::addEntityMapEntry() found pre-existing id " << id;
|
||||||
|
assert(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
_entityMap.insert(id, entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EntityTree::clearEntityMapEntry(const EntityItemID& id) {
|
||||||
|
QWriteLocker locker(&_entityMapLock);
|
||||||
|
_entityMap.remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::debugDumpMap() {
|
void EntityTree::debugDumpMap() {
|
||||||
|
// QHash's are implicitly shared, so we make a shared copy and use that instead.
|
||||||
|
// This way we might be able to avoid both a lock and a true copy.
|
||||||
|
QHash<EntityItemID, EntityItemPointer> localMap(_entityMap);
|
||||||
qCDebug(entities) << "EntityTree::debugDumpMap() --------------------------";
|
qCDebug(entities) << "EntityTree::debugDumpMap() --------------------------";
|
||||||
QReadLocker locker(&_entityToElementLock);
|
QHashIterator<EntityItemID, EntityItemPointer> i(localMap);
|
||||||
QHashIterator<EntityItemID, EntityTreeElementPointer> i(_entityToElementMap);
|
|
||||||
while (i.hasNext()) {
|
while (i.hasNext()) {
|
||||||
i.next();
|
i.next();
|
||||||
qCDebug(entities) << i.key() << ": " << i.value().get();
|
qCDebug(entities) << i.key() << ": " << i.value()->getElement().get();
|
||||||
}
|
}
|
||||||
qCDebug(entities) << "-----------------------------------------------------";
|
qCDebug(entities) << "-----------------------------------------------------";
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,9 +119,6 @@ public:
|
||||||
// use this method if you only know the entityID
|
// use this method if you only know the entityID
|
||||||
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
bool updateEntity(const EntityItemID& entityID, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
||||||
|
|
||||||
// use this method if you have a pointer to the entity (avoid an extra entity lookup)
|
|
||||||
bool updateEntity(EntityItemPointer entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
|
||||||
|
|
||||||
// check if the avatar is a child of this entity, If so set the avatar parentID to null
|
// check if the avatar is a child of this entity, If so set the avatar parentID to null
|
||||||
void unhookChildAvatar(const EntityItemID entityID);
|
void unhookChildAvatar(const EntityItemID entityID);
|
||||||
void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = true);
|
void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = true);
|
||||||
|
@ -183,7 +180,8 @@ public:
|
||||||
int processEraseMessageDetails(const QByteArray& buffer, const SharedNodePointer& sourceNode);
|
int processEraseMessageDetails(const QByteArray& buffer, const SharedNodePointer& sourceNode);
|
||||||
|
|
||||||
EntityTreeElementPointer getContainingElement(const EntityItemID& entityItemID) /*const*/;
|
EntityTreeElementPointer getContainingElement(const EntityItemID& entityItemID) /*const*/;
|
||||||
void setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element);
|
void addEntityMapEntry(EntityItemPointer entity);
|
||||||
|
void clearEntityMapEntry(const EntityItemID& id);
|
||||||
void debugDumpMap();
|
void debugDumpMap();
|
||||||
virtual void dumpTree() override;
|
virtual void dumpTree() override;
|
||||||
virtual void pruneTree() override;
|
virtual void pruneTree() override;
|
||||||
|
@ -275,8 +273,7 @@ signals:
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void processRemovedEntities(const DeleteEntityOperator& theOperator);
|
void processRemovedEntities(const DeleteEntityOperator& theOperator);
|
||||||
bool updateEntityWithElement(EntityItemPointer entity, const EntityItemProperties& properties,
|
bool updateEntity(EntityItemPointer entity, const EntityItemProperties& properties,
|
||||||
EntityTreeElementPointer containingElement,
|
|
||||||
const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
||||||
static bool findNearPointOperation(const OctreeElementPointer& element, void* extraData);
|
static bool findNearPointOperation(const OctreeElementPointer& element, void* extraData);
|
||||||
static bool findInSphereOperation(const OctreeElementPointer& element, void* extraData);
|
static bool findInSphereOperation(const OctreeElementPointer& element, void* extraData);
|
||||||
|
@ -309,8 +306,8 @@ protected:
|
||||||
_deletedEntityItemIDs << id;
|
_deletedEntityItemIDs << id;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutable QReadWriteLock _entityToElementLock;
|
mutable QReadWriteLock _entityMapLock;
|
||||||
QHash<EntityItemID, EntityTreeElementPointer> _entityToElementMap;
|
QHash<EntityItemID, EntityItemPointer> _entityMap;
|
||||||
|
|
||||||
EntitySimulationPointer _simulation;
|
EntitySimulationPointer _simulation;
|
||||||
|
|
||||||
|
|
|
@ -885,10 +885,10 @@ EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemI
|
||||||
void EntityTreeElement::cleanupEntities() {
|
void EntityTreeElement::cleanupEntities() {
|
||||||
withWriteLock([&] {
|
withWriteLock([&] {
|
||||||
foreach(EntityItemPointer entity, _entityItems) {
|
foreach(EntityItemPointer entity, _entityItems) {
|
||||||
|
// NOTE: only EntityTreeElement should ever be changing the value of entity->_element
|
||||||
// NOTE: We explicitly don't delete the EntityItem here because since we only
|
// NOTE: We explicitly don't delete the EntityItem here because since we only
|
||||||
// access it by smart pointers, when we remove it from the _entityItems
|
// access it by smart pointers, when we remove it from the _entityItems
|
||||||
// we know that it will be deleted.
|
// we know that it will be deleted.
|
||||||
//delete entity;
|
|
||||||
entity->_element = NULL;
|
entity->_element = NULL;
|
||||||
}
|
}
|
||||||
_entityItems.clear();
|
_entityItems.clear();
|
||||||
|
@ -903,6 +903,7 @@ bool EntityTreeElement::removeEntityWithEntityItemID(const EntityItemID& id) {
|
||||||
EntityItemPointer& entity = _entityItems[i];
|
EntityItemPointer& entity = _entityItems[i];
|
||||||
if (entity->getEntityItemID() == id) {
|
if (entity->getEntityItemID() == id) {
|
||||||
foundEntity = true;
|
foundEntity = true;
|
||||||
|
// NOTE: only EntityTreeElement should ever be changing the value of entity->_element
|
||||||
entity->_element = NULL;
|
entity->_element = NULL;
|
||||||
_entityItems.removeAt(i);
|
_entityItems.removeAt(i);
|
||||||
break;
|
break;
|
||||||
|
@ -918,6 +919,7 @@ bool EntityTreeElement::removeEntityItem(EntityItemPointer entity) {
|
||||||
numEntries = _entityItems.removeAll(entity);
|
numEntries = _entityItems.removeAll(entity);
|
||||||
});
|
});
|
||||||
if (numEntries > 0) {
|
if (numEntries > 0) {
|
||||||
|
// NOTE: only EntityTreeElement should ever be changing the value of entity->_element
|
||||||
assert(entity->_element.get() == this);
|
assert(entity->_element.get() == this);
|
||||||
entity->_element = NULL;
|
entity->_element = NULL;
|
||||||
return true;
|
return true;
|
||||||
|
@ -1001,7 +1003,6 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
||||||
if (currentContainingElement.get() != this) {
|
if (currentContainingElement.get() != this) {
|
||||||
currentContainingElement->removeEntityItem(entityItem);
|
currentContainingElement->removeEntityItem(entityItem);
|
||||||
addEntityItem(entityItem);
|
addEntityItem(entityItem);
|
||||||
_myTree->setContainingElement(entityItemID, getThisPointer());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1032,9 +1033,9 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
||||||
|
|
||||||
// don't add if we've recently deleted....
|
// don't add if we've recently deleted....
|
||||||
if (!_myTree->isDeletedEntity(entityItem->getID())) {
|
if (!_myTree->isDeletedEntity(entityItem->getID())) {
|
||||||
|
_myTree->addEntityMapEntry(entityItem);
|
||||||
addEntityItem(entityItem); // add this new entity to this elements entities
|
addEntityItem(entityItem); // add this new entity to this elements entities
|
||||||
entityItemID = entityItem->getEntityItemID();
|
entityItemID = entityItem->getEntityItemID();
|
||||||
_myTree->setContainingElement(entityItemID, getThisPointer());
|
|
||||||
_myTree->postAddEntity(entityItem);
|
_myTree->postAddEntity(entityItem);
|
||||||
if (entityItem->getCreated() == UNKNOWN_CREATED_TIME) {
|
if (entityItem->getCreated() == UNKNOWN_CREATED_TIME) {
|
||||||
entityItem->recordCreationTime();
|
entityItem->recordCreationTime();
|
||||||
|
|
|
@ -24,7 +24,15 @@ void HoverOverlayInterface::createHoverOverlay(const EntityItemID& entityItemID,
|
||||||
setCurrentHoveredEntity(entityItemID);
|
setCurrentHoveredEntity(entityItemID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HoverOverlayInterface::createHoverOverlay(const EntityItemID& entityItemID) {
|
||||||
|
HoverOverlayInterface::createHoverOverlay(entityItemID, PointerEvent());
|
||||||
|
}
|
||||||
|
|
||||||
void HoverOverlayInterface::destroyHoverOverlay(const EntityItemID& entityItemID, const PointerEvent& event) {
|
void HoverOverlayInterface::destroyHoverOverlay(const EntityItemID& entityItemID, const PointerEvent& event) {
|
||||||
qCDebug(hover_overlay) << "Destroying Hover Overlay on top of entity with ID: " << entityItemID;
|
qCDebug(hover_overlay) << "Destroying Hover Overlay on top of entity with ID: " << entityItemID;
|
||||||
setCurrentHoveredEntity(QUuid());
|
setCurrentHoveredEntity(QUuid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HoverOverlayInterface::destroyHoverOverlay(const EntityItemID& entityItemID) {
|
||||||
|
HoverOverlayInterface::destroyHoverOverlay(entityItemID, PointerEvent());
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,9 @@
|
||||||
#include "EntityTree.h"
|
#include "EntityTree.h"
|
||||||
#include "HoverOverlayLogging.h"
|
#include "HoverOverlayLogging.h"
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @namespace HoverOverlay
|
||||||
|
*/
|
||||||
class HoverOverlayInterface : public QObject, public Dependency {
|
class HoverOverlayInterface : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -34,7 +37,9 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void createHoverOverlay(const EntityItemID& entityItemID, const PointerEvent& event);
|
void createHoverOverlay(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||||
|
void createHoverOverlay(const EntityItemID& entityItemID);
|
||||||
void destroyHoverOverlay(const EntityItemID& entityItemID, const PointerEvent& event);
|
void destroyHoverOverlay(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||||
|
void destroyHoverOverlay(const EntityItemID& entityItemID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _verboseLogging { true };
|
bool _verboseLogging { true };
|
||||||
|
|
|
@ -51,7 +51,7 @@ MovingEntitiesOperator::~MovingEntitiesOperator() {
|
||||||
|
|
||||||
|
|
||||||
void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const AACube& newCube) {
|
void MovingEntitiesOperator::addEntityToMoveList(EntityItemPointer entity, const AACube& newCube) {
|
||||||
EntityTreeElementPointer oldContainingElement = _tree->getContainingElement(entity->getEntityItemID());
|
EntityTreeElementPointer oldContainingElement = entity->getElement();
|
||||||
AABox newCubeClamped = newCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE);
|
AABox newCubeClamped = newCube.clamp((float)-HALF_TREE_SCALE, (float)HALF_TREE_SCALE);
|
||||||
|
|
||||||
if (_wantDebug) {
|
if (_wantDebug) {
|
||||||
|
@ -193,7 +193,6 @@ bool MovingEntitiesOperator::preRecursion(const OctreeElementPointer& element) {
|
||||||
|
|
||||||
// If this element is the best fit for the new bounds of this entity then add the entity to the element
|
// If this element is the best fit for the new bounds of this entity then add the entity to the element
|
||||||
if (!details.newFound && entityTreeElement->bestFitBounds(details.newCube)) {
|
if (!details.newFound && entityTreeElement->bestFitBounds(details.newCube)) {
|
||||||
EntityItemID entityItemID = details.entity->getEntityItemID();
|
|
||||||
// remove from the old before adding
|
// remove from the old before adding
|
||||||
EntityTreeElementPointer oldElement = details.entity->getElement();
|
EntityTreeElementPointer oldElement = details.entity->getElement();
|
||||||
if (oldElement != entityTreeElement) {
|
if (oldElement != entityTreeElement) {
|
||||||
|
@ -201,7 +200,6 @@ bool MovingEntitiesOperator::preRecursion(const OctreeElementPointer& element) {
|
||||||
oldElement->removeEntityItem(details.entity);
|
oldElement->removeEntityItem(details.entity);
|
||||||
}
|
}
|
||||||
entityTreeElement->addEntityItem(details.entity);
|
entityTreeElement->addEntityItem(details.entity);
|
||||||
_tree->setContainingElement(entityItemID, entityTreeElement);
|
|
||||||
}
|
}
|
||||||
_foundNewCount++;
|
_foundNewCount++;
|
||||||
//details.newFound = true; // TODO: would be nice to add this optimization
|
//details.newFound = true; // TODO: would be nice to add this optimization
|
||||||
|
|
|
@ -138,8 +138,8 @@ bool UpdateEntityOperator::preRecursion(const OctreeElementPointer& element) {
|
||||||
qCDebug(entities) << " _foundNew=" << _foundNew;
|
qCDebug(entities) << " _foundNew=" << _foundNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we haven't yet found the old entity, and this subTreeContains our old
|
// If we haven't yet found the old element, and this subTreeContains our old element,
|
||||||
// entity, then we need to keep searching.
|
// then we need to keep searching.
|
||||||
if (!_foundOld && subtreeContainsOld) {
|
if (!_foundOld && subtreeContainsOld) {
|
||||||
|
|
||||||
if (_wantDebug) {
|
if (_wantDebug) {
|
||||||
|
@ -169,7 +169,6 @@ bool UpdateEntityOperator::preRecursion(const OctreeElementPointer& element) {
|
||||||
// NOTE: we know we haven't yet added it to its new element because _removeOld is true
|
// NOTE: we know we haven't yet added it to its new element because _removeOld is true
|
||||||
EntityTreeElementPointer oldElement = _existingEntity->getElement();
|
EntityTreeElementPointer oldElement = _existingEntity->getElement();
|
||||||
oldElement->removeEntityItem(_existingEntity);
|
oldElement->removeEntityItem(_existingEntity);
|
||||||
_tree->setContainingElement(_entityItemID, NULL);
|
|
||||||
|
|
||||||
if (oldElement != _containingElement) {
|
if (oldElement != _containingElement) {
|
||||||
qCDebug(entities) << "WARNING entity moved during UpdateEntityOperator recursion";
|
qCDebug(entities) << "WARNING entity moved during UpdateEntityOperator recursion";
|
||||||
|
@ -187,8 +186,8 @@ bool UpdateEntityOperator::preRecursion(const OctreeElementPointer& element) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we haven't yet found the new entity, and this subTreeContains our new
|
// If we haven't yet found the new element, and this subTreeContains our new element,
|
||||||
// entity, then we need to keep searching.
|
// then we need to keep searching.
|
||||||
if (!_foundNew && subtreeContainsNew) {
|
if (!_foundNew && subtreeContainsNew) {
|
||||||
|
|
||||||
if (_wantDebug) {
|
if (_wantDebug) {
|
||||||
|
@ -221,7 +220,6 @@ bool UpdateEntityOperator::preRecursion(const OctreeElementPointer& element) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entityTreeElement->addEntityItem(_existingEntity);
|
entityTreeElement->addEntityItem(_existingEntity);
|
||||||
_tree->setContainingElement(_entityItemID, entityTreeElement);
|
|
||||||
}
|
}
|
||||||
_foundNew = true; // we found the new element
|
_foundNew = true; // we found the new element
|
||||||
_removeOld = false; // and it has already been removed from the old
|
_removeOld = false; // and it has already been removed from the old
|
||||||
|
|
|
@ -188,6 +188,9 @@ void AssetResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytes
|
||||||
|
|
||||||
auto now = p_high_resolution_clock::now();
|
auto now = p_high_resolution_clock::now();
|
||||||
|
|
||||||
|
// Recording ATP bytes downloaded in stats
|
||||||
|
DependencyManager::get<StatTracker>()->updateStat(STAT_ATP_RESOURCE_TOTAL_BYTES, bytesReceived);
|
||||||
|
|
||||||
// if we haven't received the full asset check if it is time to output progress to log
|
// if we haven't received the full asset check if it is time to output progress to log
|
||||||
// we do so every X seconds to assist with ATP download tracking
|
// we do so every X seconds to assist with ATP download tracking
|
||||||
|
|
||||||
|
@ -201,6 +204,5 @@ void AssetResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytes
|
||||||
|
|
||||||
_lastProgressDebug = now;
|
_lastProgressDebug = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
void FileResourceRequest::doSend() {
|
void FileResourceRequest::doSend() {
|
||||||
auto statTracker = DependencyManager::get<StatTracker>();
|
auto statTracker = DependencyManager::get<StatTracker>();
|
||||||
statTracker->incrementStat(STAT_FILE_REQUEST_STARTED);
|
statTracker->incrementStat(STAT_FILE_REQUEST_STARTED);
|
||||||
|
int fileSize = 0;
|
||||||
QString filename = _url.toLocalFile();
|
QString filename = _url.toLocalFile();
|
||||||
|
|
||||||
// sometimes on windows, we see the toLocalFile() return null,
|
// sometimes on windows, we see the toLocalFile() return null,
|
||||||
|
@ -53,6 +53,7 @@ void FileResourceRequest::doSend() {
|
||||||
}
|
}
|
||||||
|
|
||||||
_result = ResourceRequest::Success;
|
_result = ResourceRequest::Success;
|
||||||
|
fileSize = file.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -68,6 +69,8 @@ void FileResourceRequest::doSend() {
|
||||||
|
|
||||||
if (_result == ResourceRequest::Success) {
|
if (_result == ResourceRequest::Success) {
|
||||||
statTracker->incrementStat(STAT_FILE_REQUEST_SUCCESS);
|
statTracker->incrementStat(STAT_FILE_REQUEST_SUCCESS);
|
||||||
|
// Recording FILE bytes downloaded in stats
|
||||||
|
statTracker->updateStat(STAT_FILE_RESOURCE_TOTAL_BYTES,fileSize);
|
||||||
} else {
|
} else {
|
||||||
statTracker->incrementStat(STAT_FILE_REQUEST_FAILED);
|
statTracker->incrementStat(STAT_FILE_REQUEST_FAILED);
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,6 +201,11 @@ void HTTPResourceRequest::onDownloadProgress(qint64 bytesReceived, qint64 bytesT
|
||||||
_sendTimer->start();
|
_sendTimer->start();
|
||||||
|
|
||||||
emit progress(bytesReceived, bytesTotal);
|
emit progress(bytesReceived, bytesTotal);
|
||||||
|
|
||||||
|
// Recording HTTP bytes downloaded in stats
|
||||||
|
DependencyManager::get<StatTracker>()->updateStat(STAT_HTTP_RESOURCE_TOTAL_BYTES, bytesReceived);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HTTPResourceRequest::onTimeout() {
|
void HTTPResourceRequest::onTimeout() {
|
||||||
|
|
|
@ -33,6 +33,9 @@ const QString STAT_HTTP_REQUEST_CACHE = "CacheHTTPRequest";
|
||||||
const QString STAT_ATP_MAPPING_REQUEST_STARTED = "StartedATPMappingRequest";
|
const QString STAT_ATP_MAPPING_REQUEST_STARTED = "StartedATPMappingRequest";
|
||||||
const QString STAT_ATP_MAPPING_REQUEST_FAILED = "FailedATPMappingRequest";
|
const QString STAT_ATP_MAPPING_REQUEST_FAILED = "FailedATPMappingRequest";
|
||||||
const QString STAT_ATP_MAPPING_REQUEST_SUCCESS = "SuccessfulATPMappingRequest";
|
const QString STAT_ATP_MAPPING_REQUEST_SUCCESS = "SuccessfulATPMappingRequest";
|
||||||
|
const QString STAT_HTTP_RESOURCE_TOTAL_BYTES = "HTTPBytesDownloaded";
|
||||||
|
const QString STAT_ATP_RESOURCE_TOTAL_BYTES = "ATPBytesDownloaded";
|
||||||
|
const QString STAT_FILE_RESOURCE_TOTAL_BYTES = "FILEBytesDownloaded";
|
||||||
|
|
||||||
class ResourceRequest : public QObject {
|
class ResourceRequest : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
104
scripts/developer/tests/entityLookupCostMeasurement.js
Normal file
104
scripts/developer/tests/entityLookupCostMeasurement.js
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
// Creates a large number of entities on the cardinal planes of the octree (all
|
||||||
|
// objects will live in the root octree element). Measures how long it takes
|
||||||
|
// to update the properties of the first and last entity. The difference
|
||||||
|
// between the two measurements shows how the cost of lookup changes as a
|
||||||
|
// function of the number of entities. For best results run this in an
|
||||||
|
// otherwise empty domain.
|
||||||
|
|
||||||
|
var firstId;
|
||||||
|
var lastId;
|
||||||
|
var NUM_ENTITIES_ON_SIDE = 25;
|
||||||
|
|
||||||
|
// create the objects
|
||||||
|
createObjects = function () {
|
||||||
|
var STRIDE = 0.75;
|
||||||
|
var WIDTH = 0.5;
|
||||||
|
var DIMENSIONS = { x: WIDTH, y: WIDTH, z: WIDTH };
|
||||||
|
var LIFETIME = 20;
|
||||||
|
|
||||||
|
var properties = {
|
||||||
|
name: "",
|
||||||
|
type : "Box",
|
||||||
|
dimensions : DIMENSIONS,
|
||||||
|
position : { x: 0, y: 0, z: 0},
|
||||||
|
lifetime : LIFETIME,
|
||||||
|
color : { red:255, green: 64, blue: 255 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// xy
|
||||||
|
var planeName = "xy";
|
||||||
|
for (var i = 0; i < NUM_ENTITIES_ON_SIDE; ++i) {
|
||||||
|
for (var j = 0; j < NUM_ENTITIES_ON_SIDE; ++j) {
|
||||||
|
properties.name = "Box-" + planeName + "-" + i + "." + j;
|
||||||
|
properties.position = { x: i * STRIDE, y: j * STRIDE, z: 0 };
|
||||||
|
var red = i * 255 / NUM_ENTITIES_ON_SIDE;
|
||||||
|
var green = j * 255 / NUM_ENTITIES_ON_SIDE;
|
||||||
|
var blue = 0;
|
||||||
|
properties.color = { red: red, green: green, blue: blue };
|
||||||
|
if (i == 0 && j == 0) {
|
||||||
|
firstId = Entities.addEntity(properties);
|
||||||
|
} else {
|
||||||
|
Entities.addEntity(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// yz
|
||||||
|
var planeName = "yz";
|
||||||
|
for (var i = 0; i < NUM_ENTITIES_ON_SIDE; ++i) {
|
||||||
|
for (var j = 0; j < NUM_ENTITIES_ON_SIDE; ++j) {
|
||||||
|
properties.name = "Box-" + planeName + "-" + i + "." + j;
|
||||||
|
properties.position = { x: 0, y: i * STRIDE, z: j * STRIDE };
|
||||||
|
var red = 0;
|
||||||
|
var green = i * 255 / NUM_ENTITIES_ON_SIDE;
|
||||||
|
var blue = j * 255 / NUM_ENTITIES_ON_SIDE;
|
||||||
|
properties.color = { red: red, green: green, blue: blue };
|
||||||
|
Entities.addEntity(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// zx
|
||||||
|
var planeName = "zx";
|
||||||
|
for (var i = 0; i < NUM_ENTITIES_ON_SIDE; ++i) {
|
||||||
|
for (var j = 0; j < NUM_ENTITIES_ON_SIDE; ++j) {
|
||||||
|
properties.name = "Box-" + planeName + "-" + i + "." + j;
|
||||||
|
properties.position = { x: j * STRIDE, y: 0, z: i * STRIDE };
|
||||||
|
var red = j * 255 / NUM_ENTITIES_ON_SIDE;
|
||||||
|
var green = 0;
|
||||||
|
var blue = i * 255 / NUM_ENTITIES_ON_SIDE;
|
||||||
|
properties.color = { red: red, green: green, blue: blue };
|
||||||
|
lastId = Entities.addEntity(properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
createObjects();
|
||||||
|
|
||||||
|
// measure the time it takes to edit the first and last entities many times
|
||||||
|
// (requires a lookup by entityId each time)
|
||||||
|
changeProperties = function (id) {
|
||||||
|
var newProperties = { color : { red: 255, green: 255, blue: 255 } };
|
||||||
|
Entities.editEntity(id, newProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
// first
|
||||||
|
var NUM_CHANGES = 10000;
|
||||||
|
var firstStart = Date.now();
|
||||||
|
for (var k = 0; k < NUM_CHANGES; ++k) {
|
||||||
|
changeProperties(firstId);
|
||||||
|
}
|
||||||
|
var firstEnd = Date.now();
|
||||||
|
var firstDt = firstEnd - firstStart;
|
||||||
|
|
||||||
|
// last
|
||||||
|
var lastStart = Date.now();
|
||||||
|
for (var k = 0; k < NUM_CHANGES; ++k) {
|
||||||
|
changeProperties(lastId);
|
||||||
|
}
|
||||||
|
var lastEnd = Date.now();
|
||||||
|
var lastDt = lastEnd - lastStart;
|
||||||
|
|
||||||
|
// print the results
|
||||||
|
var numEntities = 3 * NUM_ENTITIES_ON_SIDE * NUM_ENTITIES_ON_SIDE;
|
||||||
|
print("numEntities = " + numEntities + " numEdits = " + NUM_CHANGES + " firstDt = " + firstDt + " lastDt = " + lastDt);
|
||||||
|
|
|
@ -187,6 +187,8 @@ var DEFAULT_GRABBABLE_DATA = {
|
||||||
var USE_BLACKLIST = true;
|
var USE_BLACKLIST = true;
|
||||||
var blacklist = [];
|
var blacklist = [];
|
||||||
|
|
||||||
|
var entitiesWithHoverOverlays = [];
|
||||||
|
|
||||||
var FORBIDDEN_GRAB_NAMES = ["Grab Debug Entity", "grab pointer"];
|
var FORBIDDEN_GRAB_NAMES = ["Grab Debug Entity", "grab pointer"];
|
||||||
var FORBIDDEN_GRAB_TYPES = ["Unknown", "Light", "PolyLine", "Zone"];
|
var FORBIDDEN_GRAB_TYPES = ["Unknown", "Light", "PolyLine", "Zone"];
|
||||||
|
|
||||||
|
@ -2201,6 +2203,15 @@ function MyController(hand) {
|
||||||
entityPropertiesCache.addEntity(rayPickInfo.entityID);
|
entityPropertiesCache.addEntity(rayPickInfo.entityID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rayPickInfo.entityID && entitiesWithHoverOverlays.indexOf(rayPickInfo.entityID) == -1) {
|
||||||
|
entitiesWithHoverOverlays.forEach(function (element) {
|
||||||
|
HoverOverlay.destroyHoverOverlay(element);
|
||||||
|
});
|
||||||
|
entitiesWithHoverOverlays = [];
|
||||||
|
HoverOverlay.createHoverOverlay(rayPickInfo.entityID);
|
||||||
|
entitiesWithHoverOverlays.push(rayPickInfo.entityID);
|
||||||
|
}
|
||||||
|
|
||||||
var candidateHotSpotEntities = Entities.findEntities(handPosition, MAX_EQUIP_HOTSPOT_RADIUS);
|
var candidateHotSpotEntities = Entities.findEntities(handPosition, MAX_EQUIP_HOTSPOT_RADIUS);
|
||||||
entityPropertiesCache.addEntities(candidateHotSpotEntities);
|
entityPropertiesCache.addEntities(candidateHotSpotEntities);
|
||||||
|
|
||||||
|
@ -3763,6 +3774,11 @@ function MyController(hand) {
|
||||||
this.release = function() {
|
this.release = function() {
|
||||||
this.turnOffVisualizations();
|
this.turnOffVisualizations();
|
||||||
|
|
||||||
|
entitiesWithHoverOverlays.forEach(function (element) {
|
||||||
|
HoverOverlay.destroyHoverOverlay(element);
|
||||||
|
});
|
||||||
|
entitiesWithHoverOverlays = [];
|
||||||
|
|
||||||
if (this.grabbedThingID !== null) {
|
if (this.grabbedThingID !== null) {
|
||||||
|
|
||||||
Messages.sendMessage('Hifi-Teleport-Ignore-Remove', this.grabbedThingID);
|
Messages.sendMessage('Hifi-Teleport-Ignore-Remove', this.grabbedThingID);
|
||||||
|
|
|
@ -76,7 +76,7 @@ function calcSpawnInfo(hand, tabletHeight) {
|
||||||
var TABLET_RAKE_ANGLE = 30;
|
var TABLET_RAKE_ANGLE = 30;
|
||||||
rotation = Quat.multiply(Quat.angleAxis(TABLET_RAKE_ANGLE, Vec3.multiplyQbyV(lookAt, Vec3.UNIT_X)), lookAt);
|
rotation = Quat.multiply(Quat.angleAxis(TABLET_RAKE_ANGLE, Vec3.multiplyQbyV(lookAt, Vec3.UNIT_X)), lookAt);
|
||||||
|
|
||||||
var RELATIVE_SPAWN_OFFSET = { x: 0, y: 0.4, z: 0.05 };
|
var RELATIVE_SPAWN_OFFSET = { x: 0, y: 0.6, z: 0.1 };
|
||||||
position = Vec3.sum(position, Vec3.multiplyQbyV(rotation, Vec3.multiply(tabletHeight, RELATIVE_SPAWN_OFFSET)));
|
position = Vec3.sum(position, Vec3.multiplyQbyV(rotation, Vec3.multiply(tabletHeight, RELATIVE_SPAWN_OFFSET)));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue