364 lines · 12.0 KB · Text
RawDownload
////  ZoneEntityItem.cpp//  libraries/entities/src////  Created by Brad Hefta-Gaub on 12/4/13.//  Copyright 2013 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 "ZoneEntityItem.h" #include <glm/gtx/transform.hpp>#include <QDebug> #include <ByteCountCoding.h> #include "EntitiesLogging.h"#include "EntityItemProperties.h"#include "EntityTree.h"#include "EntityTreeElement.h"#include "EntityEditFilters.h" bool ZoneEntityItem::_zonesArePickable = false;bool ZoneEntityItem::_drawZoneBoundaries = false;  const ShapeType ZoneEntityItem::DEFAULT_SHAPE_TYPE = SHAPE_TYPE_BOX;const QString ZoneEntityItem::DEFAULT_COMPOUND_SHAPE_URL = "";const bool ZoneEntityItem::DEFAULT_FLYING_ALLOWED = true;const bool ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED = true;const QString ZoneEntityItem::DEFAULT_FILTER_URL = ""; EntityItemPointer ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {    std::shared_ptr<ZoneEntityItem> entity(new ZoneEntityItem(entityID), [](ZoneEntityItem* ptr) { ptr->deleteLater(); });    entity->setProperties(properties);    return entity;} ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {    _type = EntityTypes::Zone;     _shapeType = DEFAULT_SHAPE_TYPE;    _compoundShapeURL = DEFAULT_COMPOUND_SHAPE_URL;    _visuallyReady = false;} EntityItemProperties ZoneEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {    EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class @Zone_ENTITY_COPY_TO@     return properties;} bool ZoneEntityItem::setSubClassProperties(const EntityItemProperties& properties) {    bool somethingChanged = false; @Zone_ENTITY_SET_FROM@     somethingChanged |= _keyLightPropertiesChanged || _ambientLightPropertiesChanged || _skyboxPropertiesChanged ||                        _hazePropertiesChanged || _bloomPropertiesChanged || _tonemappingPropertiesChanged ||                        _ambientOcclusionPropertiesChanged || _normalMapAttenuationPropertiesChanged;     return somethingChanged;} EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {    EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); @Zone_REQUESTED_PROPS@     return requestedProperties;} void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,                                        EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData,                                        EntityPropertyFlags& requestedProperties,                                        EntityPropertyFlags& propertyFlags,                                        EntityPropertyFlags& propertiesDidntFit,                                        int& propertyCount,                                        OctreeElement::AppendState& appendState) const {     bool successPropertyFits = true; @Zone_ENTITY_APPEND@ } int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,                                                ReadBitstreamToTreeParams& args,                                                EntityPropertyFlags& propertyFlags, bool overwriteLocalData,                                                bool& somethingChanged) {    int bytesRead = 0;    const unsigned char* dataAt = data; @Zone_ENTITY_READ@     return bytesRead;} void ZoneEntityItem::debugDump() const {    qCDebug(entities) << "ZoneEntityItem id:" << getEntityItemID() << "---------------------------------------------";    qCDebug(entities) << "    name:" << _name;    qCDebug(entities) << "    position:" << debugTreeVector(getWorldPosition());    qCDebug(entities) << "    dimensions:" << debugTreeVector(getScaledDimensions());    qCDebug(entities) << "    editedAgo:" << debugTime(getLastEdited(), usecTimestampNow());    qCDebug(entities) << "    pointer:" << this; @Zone_ENTITY_DEBUG@ } void ZoneEntityItem::setShapeType(ShapeType type) {    switch(type) {        case SHAPE_TYPE_NONE:        case SHAPE_TYPE_CAPSULE_X:        case SHAPE_TYPE_CAPSULE_Y:        case SHAPE_TYPE_CAPSULE_Z:        case SHAPE_TYPE_HULL:        case SHAPE_TYPE_PLANE:        case SHAPE_TYPE_SIMPLE_HULL:        case SHAPE_TYPE_SIMPLE_COMPOUND:        case SHAPE_TYPE_STATIC_MESH:        case SHAPE_TYPE_CIRCLE:            // these types are unsupported for ZoneEntity            type = DEFAULT_SHAPE_TYPE;            break;        default:            break;    }     ShapeType oldShapeType;    withWriteLock([&] {        oldShapeType = _shapeType;        _shapeType = type;    });     if (type == SHAPE_TYPE_COMPOUND) {        if (type != oldShapeType) {            fetchCollisionGeometryResource();        }    } else {        _shapeResource.reset();    }} ShapeType ZoneEntityItem::getShapeType() const {    return resultWithReadLock<ShapeType>([&] {        return _shapeType;    });} void ZoneEntityItem::setCompoundShapeURL(const QString& url) {    QString oldCompoundShapeURL;    ShapeType shapeType;    withWriteLock([&] {        oldCompoundShapeURL = _compoundShapeURL;        _compoundShapeURL = url;        shapeType = _shapeType;    });    if (oldCompoundShapeURL != url) {        if (shapeType == SHAPE_TYPE_COMPOUND) {            fetchCollisionGeometryResource();        } else {            _shapeResource.reset();        }    }} bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,                         const glm::vec3& viewFrustumPos, OctreeElementPointer& element, float& distance,                         BoxFace& face, glm::vec3& surfaceNormal,                         QVariantMap& extraInfo, bool precisionPicking) const {    return _zonesArePickable;} bool ZoneEntityItem::findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,                         const glm::vec3& acceleration, const glm::vec3& viewFrustumPos, OctreeElementPointer& element,                         float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal,                         QVariantMap& extraInfo, bool precisionPicking) const {    return _zonesArePickable;} bool ZoneEntityItem::contains(const glm::vec3& point) const {    GeometryResource::Pointer resource = _shapeResource;    if (getShapeType() == SHAPE_TYPE_COMPOUND && resource) {        if (resource->isLoaded()) {            const HFMModel& hfmModel = resource->getHFMModel();             Extents meshExtents = hfmModel.getMeshExtents();            glm::vec3 meshExtentsDiagonal = meshExtents.maximum - meshExtents.minimum;            glm::vec3 offset = -meshExtents.minimum - (meshExtentsDiagonal * getRegistrationPoint());            glm::vec3 scale(getScaledDimensions() / meshExtentsDiagonal);             glm::mat4 hfmToEntityMatrix = glm::scale(scale) * glm::translate(offset);            glm::mat4 entityToWorldMatrix = getTransform().getMatrix();            glm::mat4 worldToHFMMatrix = glm::inverse(entityToWorldMatrix * hfmToEntityMatrix);             return hfmModel.convexHullContains(glm::vec3(worldToHFMMatrix * glm::vec4(point, 1.0f)));        }    }    return EntityItem::contains(point);} void ZoneEntityItem::setFilterURL(const QString& url) {    withWriteLock([&] {        _filterURL = url;    });    if (DependencyManager::isSet<EntityEditFilters>()) {        auto entityEditFilters = DependencyManager::get<EntityEditFilters>();        qCDebug(entities) << "adding filter " << url << "for zone" << getEntityItemID();        entityEditFilters->addFilter(getEntityItemID(), url);    }} QString ZoneEntityItem::getFilterURL() const {    return resultWithReadLock<QString>([&] {        return _filterURL;    });} QString ZoneEntityItem::getCompoundShapeURL() const {    return resultWithReadLock<QString>([&] {        return _compoundShapeURL;    });} void ZoneEntityItem::resetRenderingPropertiesChanged() {    withWriteLock([&] {        _keyLightPropertiesChanged = false;        _ambientLightPropertiesChanged = false;        _skyboxPropertiesChanged = false;        _hazePropertiesChanged = false;        _bloomPropertiesChanged = false;        _tonemappingPropertiesChanged = false;        _ambientOcclusionPropertiesChanged = false;        _normalMapAttenuationPropertiesChanged = false;    });} void ZoneEntityItem::setSkyboxMode(const uint8_t value) {    if (value < COMPONENT_MODE_ITEM_COUNT && value != _skyboxMode) {        _skyboxMode = value;        _skyboxPropertiesChanged = true;    }} uint8_t ZoneEntityItem::getSkyboxMode() const {    return _skyboxMode;} void ZoneEntityItem::setKeyLightMode(const uint8_t value) {    if (value < COMPONENT_MODE_ITEM_COUNT && value != _keyLightMode) {        _keyLightMode = value;        _keyLightPropertiesChanged = true;    }} uint8_t ZoneEntityItem::getKeyLightMode() const {    return _keyLightMode;} void ZoneEntityItem::setAmbientLightMode(const uint8_t value) {    if (value < COMPONENT_MODE_ITEM_COUNT && value != _ambientLightMode) {        _ambientLightMode = value;        _ambientLightPropertiesChanged = true;    }} uint8_t ZoneEntityItem::getAmbientLightMode() const {    return _ambientLightMode;} void ZoneEntityItem::setHazeMode(const uint8_t value) {    if (value < COMPONENT_MODE_ITEM_COUNT && value != _hazeMode) {        _hazeMode = value;        _hazePropertiesChanged = true;    }} uint8_t ZoneEntityItem::getHazeMode() const {    return _hazeMode;} void ZoneEntityItem::setBloomMode(const uint8_t value) {    if (value < COMPONENT_MODE_ITEM_COUNT && value != _bloomMode) {        _bloomMode = value;        _bloomPropertiesChanged = true;    }} uint8_t ZoneEntityItem::getBloomMode() const {    return _bloomMode;} void ZoneEntityItem::setTonemappingMode(const uint8_t value) {    if (value < COMPONENT_MODE_ITEM_COUNT && value != _tonemappingMode) {        _tonemappingMode = value;        _tonemappingPropertiesChanged = true;    }} uint8_t ZoneEntityItem::getTonemappingMode() const {    return _tonemappingMode;} void ZoneEntityItem::setAmbientOcclusionMode(const uint8_t value) {    if (value < COMPONENT_MODE_ITEM_COUNT && value != _ambientOcclusionMode) {        _ambientOcclusionMode = value;        _ambientOcclusionPropertiesChanged = true;    }} uint8_t ZoneEntityItem::getAmbientOcclusionMode() const {    return _ambientOcclusionMode;} void ZoneEntityItem::setNormalMapAttenuationMode(const uint8_t value) {    if (value < COMPONENT_MODE_ITEM_COUNT && value != _normalMapAttenuationMode) {        _normalMapAttenuationMode = value;        _normalMapAttenuationPropertiesChanged = true;    }} uint8_t ZoneEntityItem::getNormalMapAttenuationMode() const {    return _normalMapAttenuationMode;} void ZoneEntityItem::setUserData(const QString& value) {    bool changed = false;    withWriteLock([&] {        changed = _userData != value;        _needsRenderUpdate |= changed;    });    if (changed) {        EntityItem::setUserData(value);    }} void ZoneEntityItem::fetchCollisionGeometryResource() {    QUrl hullURL(getCompoundShapeURL());    if (hullURL.isEmpty()) {        _shapeResource.reset();    } else {        _shapeResource = DependencyManager::get<ModelCache>()->getCollisionGeometryResource(hullURL);    }} bool ZoneEntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const {    // currently the only property filter we handle in ZoneEntityItem is value of avatarPriority     static const QString AVATAR_PRIORITY_PROPERTY = "avatarPriority";     // If set match zones of interest to avatar mixer:    if (jsonFilters.contains(AVATAR_PRIORITY_PROPERTY) && jsonFilters[AVATAR_PRIORITY_PROPERTY].toBool()        && _avatarPriority != COMPONENT_MODE_INHERIT) {        return true;    }     // Chain to base:    return EntityItem::matchesJSONFilters(jsonFilters);}