From b590cd5b8928766d14f6e2cf4bb8b020a6f21a52 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 28 Nov 2017 17:51:06 -0800 Subject: [PATCH 01/49] avatar-entities which are children of an avatar will scale with the avatar --- interface/src/Application.cpp | 4 +- interface/src/Util.cpp | 2 +- interface/src/ui/overlays/Base3DOverlay.cpp | 10 +- interface/src/ui/overlays/Line3DOverlay.cpp | 8 +- .../src/avatars-renderer/Avatar.h | 1 + .../src/EntityTreeRenderer.cpp | 2 +- .../src/RenderableLightEntityItem.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 22 ++-- .../src/RenderableModelEntityItem.h | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 12 +- .../src/RenderableShapeEntityItem.cpp | 4 +- .../src/RenderableTextEntityItem.cpp | 4 +- .../src/RenderableWebEntityItem.cpp | 4 +- .../src/RenderableZoneEntityItem.cpp | 4 +- libraries/entities/src/EntityItem.cpp | 65 +++++++--- libraries/entities/src/EntityItem.h | 11 +- .../entities/src/EntityItemProperties.cpp | 21 ++++ libraries/entities/src/EntityItemProperties.h | 2 + libraries/entities/src/EntityPropertyFlags.h | 2 + .../entities/src/EntityScriptingInterface.cpp | 64 ++++++++-- libraries/entities/src/EntityTreeElement.cpp | 4 +- libraries/entities/src/LightEntityItem.cpp | 14 +-- libraries/entities/src/LightEntityItem.h | 2 +- libraries/entities/src/LineEntityItem.cpp | 6 +- libraries/entities/src/ModelEntityItem.cpp | 2 +- .../entities/src/ParticleEffectEntityItem.cpp | 4 +- libraries/entities/src/PolyLineEntityItem.cpp | 4 +- libraries/entities/src/PolyVoxEntityItem.cpp | 6 +- libraries/entities/src/ShapeEntityItem.cpp | 14 +-- libraries/entities/src/ShapeEntityItem.h | 2 +- libraries/entities/src/TextEntityItem.cpp | 6 +- libraries/entities/src/TextEntityItem.h | 2 +- libraries/entities/src/WebEntityItem.cpp | 6 +- libraries/entities/src/WebEntityItem.h | 2 +- libraries/entities/src/ZoneEntityItem.cpp | 2 +- libraries/shared/src/SpatiallyNestable.cpp | 119 ++++++++++++++++-- libraries/shared/src/SpatiallyNestable.h | 28 +++-- 37 files changed, 336 insertions(+), 133 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d7fcbf6467..45ede258b7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4238,7 +4238,7 @@ void Application::init() { getEntities()->init(); getEntities()->setEntityLoadingPriorityFunction([this](const EntityItem& item) { - auto dims = item.getDimensions(); + auto dims = item.getScaledDimensions(); auto maxSize = glm::compMax(dims); if (maxSize <= 0.0f) { @@ -4590,7 +4590,7 @@ void Application::setKeyboardFocusEntity(const EntityItemID& entityItemID) { _lastAcceptedKeyPress = usecTimestampNow(); setKeyboardFocusHighlight(entity->getWorldPosition(), entity->getWorldOrientation(), - entity->getDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); + entity->getScaledDimensions() * FOCUS_HIGHLIGHT_EXPANSION_FACTOR); } } } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index aad7768b99..e5e94da68a 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -407,7 +407,7 @@ void shapeInfoCalculator(const ShapeEntityItem * const shapeEntity, ShapeInfo &s ShapeInfo::PointList points; pointCollection.push_back(points); - GeometryCache::computeSimpleHullPointListForShape((int)shapeEntity->getShape(), shapeEntity->getDimensions(), pointCollection.back()); + GeometryCache::computeSimpleHullPointListForShape((int)shapeEntity->getShape(), shapeEntity->getScaledDimensions(), pointCollection.back()); shapeInfo.setPointCollection(pointCollection); } diff --git a/interface/src/ui/overlays/Base3DOverlay.cpp b/interface/src/ui/overlays/Base3DOverlay.cpp index 3e29395eba..884a174041 100644 --- a/interface/src/ui/overlays/Base3DOverlay.cpp +++ b/interface/src/ui/overlays/Base3DOverlay.cpp @@ -42,7 +42,7 @@ Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) : setTransform(base3DOverlay->getTransform()); } -QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& properties) { +QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& properties, bool scalesWithParent) { // the position and rotation in _transform are relative to the parent (aka local). The versions coming from // scripts are in world-frame, unless localPosition or localRotation are used. Patch up the properties // so that "position" and "rotation" are relative-to-parent values. @@ -56,7 +56,7 @@ QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& propert result["position"] = result["localPosition"]; } else if (result["position"].isValid()) { glm::vec3 localPosition = SpatiallyNestable::worldToLocal(vec3FromVariant(result["position"]), - parentID, parentJointIndex, success); + parentID, parentJointIndex, scalesWithParent, success); if (success) { result["position"] = vec3toVariant(localPosition); } @@ -66,7 +66,7 @@ QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& propert result["orientation"] = result["localOrientation"]; } else if (result["orientation"].isValid()) { glm::quat localOrientation = SpatiallyNestable::worldToLocal(quatFromVariant(result["orientation"]), - parentID, parentJointIndex, success); + parentID, parentJointIndex, scalesWithParent, success); if (success) { result["orientation"] = quatToVariant(localOrientation); } @@ -118,7 +118,7 @@ void Base3DOverlay::setProperties(const QVariantMap& originalProperties) { } } - properties = convertOverlayLocationFromScriptSemantics(properties); + properties = convertOverlayLocationFromScriptSemantics(properties, getScalesWithParent()); Overlay::setProperties(properties); bool needRenderItemUpdate = false; @@ -310,4 +310,4 @@ SpatialParentTree* Base3DOverlay::getParentTree() const { void Base3DOverlay::setVisible(bool visible) { Parent::setVisible(visible); notifyRenderVariableChange(); -} \ No newline at end of file +} diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index 66a6772aa5..2fa9f7c7d3 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -56,12 +56,12 @@ glm::vec3 Line3DOverlay::getEnd() const { if (_endParentID != QUuid()) { glm::vec3 localOffset = _direction * _length; bool success; - worldEnd = localToWorld(localOffset, _endParentID, _endParentJointIndex, success); + worldEnd = localToWorld(localOffset, _endParentID, _endParentJointIndex, getScalesWithParent(), success); return worldEnd; } localEnd = getLocalEnd(); - worldEnd = localToWorld(localEnd, getParentID(), getParentJointIndex(), success); + worldEnd = localToWorld(localEnd, getParentID(), getParentJointIndex(), getScalesWithParent(), success); if (!success) { qDebug() << "Line3DOverlay::getEnd failed"; } @@ -79,10 +79,10 @@ void Line3DOverlay::setEnd(const glm::vec3& end) { glm::vec3 offset; if (_endParentID != QUuid()) { - offset = worldToLocal(end, _endParentID, _endParentJointIndex, success); + offset = worldToLocal(end, _endParentID, _endParentJointIndex, getScalesWithParent(), success); } else { localStart = getLocalStart(); - localEnd = worldToLocal(end, getParentID(), getParentJointIndex(), success); + localEnd = worldToLocal(end, getParentID(), getParentJointIndex(), getScalesWithParent(), success); offset = localEnd - localStart; } if (!success) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index a723a8e1b0..959cb6912b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -264,6 +264,7 @@ public: virtual float getModelScale() const { return _modelScale; } virtual void setModelScale(float scale) { _modelScale = scale; } + virtual glm::vec3 scaleForChildren() const override { return glm::vec3(getModelScale()); } virtual void setAvatarEntityDataChanged(bool value) override; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5f7899ae74..77c538619c 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -610,7 +610,7 @@ static glm::vec2 projectOntoEntityXYPlane(EntityItemPointer entity, const PickRa glm::vec3 entityPosition = entity->getWorldPosition(); glm::quat entityRotation = entity->getWorldOrientation(); - glm::vec3 entityDimensions = entity->getDimensions(); + glm::vec3 entityDimensions = entity->getScaledDimensions(); glm::vec3 entityRegistrationPoint = entity->getRegistrationPoint(); // project the intersection point onto the local xy plane of the object. diff --git a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp index 696d7ab8db..fc33ebc498 100644 --- a/libraries/entities-renderer/src/RenderableLightEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLightEntityItem.cpp @@ -37,7 +37,7 @@ void LightEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPoint lightPayload.editBound() = render::Item::Bound(); } - glm::vec3 dimensions = entity->getDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); float largestDiameter = glm::compMax(dimensions); light->setMaximumRadius(largestDiameter / 2.0f); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 06b81ff428..3921432a43 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -74,11 +74,11 @@ RenderableModelEntityItem::RenderableModelEntityItem(const EntityItemID& entityI RenderableModelEntityItem::~RenderableModelEntityItem() { } -void RenderableModelEntityItem::setDimensions(const glm::vec3& value) { +void RenderableModelEntityItem::setUnscaledDimensions(const glm::vec3& value) { glm::vec3 newDimensions = glm::max(value, glm::vec3(0.0f)); // can never have negative dimensions - if (getDimensions() != newDimensions) { + if (getUnscaledDimensions() != newDimensions) { _dimensionsInitialized = true; - ModelEntityItem::setDimensions(value); + ModelEntityItem::setUnscaledDimensions(value); } } @@ -120,11 +120,11 @@ void RenderableModelEntityItem::doInitialModelSimulation() { // translation/rotation/scale/registration. The first two are straightforward, but the latter two have guards to // make sure they don't happen after they've already been set. Here we reset those guards. This doesn't cause the // entity values to change -- it just allows the model to match once it comes in. - model->setScaleToFit(false, getDimensions()); + model->setScaleToFit(false, getScaledDimensions()); model->setSnapModelToRegistrationPoint(false, getRegistrationPoint()); // now recalculate the bounds and registration - model->setScaleToFit(true, getDimensions()); + model->setScaleToFit(true, getScaledDimensions()); model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); model->setRotation(getWorldOrientation()); model->setTranslation(getWorldPosition()); @@ -165,7 +165,7 @@ bool RenderableModelEntityItem::needsUpdateModelBounds() const { return true; } - if (model->getScaleToFitDimensions() != getDimensions()) { + if (model->getScaleToFitDimensions() != getScaledDimensions()) { return true; } @@ -205,17 +205,17 @@ void RenderableModelEntityItem::updateModelBounds() { updateRenderItems = true; } - if (model->getScaleToFitDimensions() != getDimensions() || + if (model->getScaleToFitDimensions() != getScaledDimensions() || model->getRegistrationPoint() != getRegistrationPoint()) { // The machinery for updateModelBounds will give existing models the opportunity to fix their // translation/rotation/scale/registration. The first two are straightforward, but the latter two // have guards to make sure they don't happen after they've already been set. Here we reset those guards. // This doesn't cause the entity values to change -- it just allows the model to match once it comes in. - model->setScaleToFit(false, getDimensions()); + model->setScaleToFit(false, getScaledDimensions()); model->setSnapModelToRegistrationPoint(false, getRegistrationPoint()); // now recalculate the bounds and registration - model->setScaleToFit(true, getDimensions()); + model->setScaleToFit(true, getScaledDimensions()); model->setSnapModelToRegistrationPoint(true, getRegistrationPoint()); updateRenderItems = true; model->scaleToFit(); @@ -368,7 +368,7 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { const uint32_t QUAD_STRIDE = 4; ShapeType type = getShapeType(); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); auto model = getModel(); if (type == SHAPE_TYPE_COMPOUND) { updateModelBounds(); @@ -1163,7 +1163,7 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return true; } - if (model->getScaleToFitDimensions() != entity->getDimensions() || + if (model->getScaleToFitDimensions() != entity->getScaledDimensions() || model->getRegistrationPoint() != entity->getRegistrationPoint()) { return true; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 0272bed575..34c0a8f81d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -60,7 +60,7 @@ public: RenderableModelEntityItem(const EntityItemID& entityItemID, bool dimensionsInitialized); virtual ~RenderableModelEntityItem(); - virtual void setDimensions(const glm::vec3& value) override; + virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; void doInitialModelSimulation(); diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 356bf3a69c..496f8b7323 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -213,7 +213,7 @@ void RenderablePolyVoxEntityItem::setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxel glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const { glm::vec3 result; withReadLock([&] { - glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units + glm::vec3 scale = getScaledDimensions() / _voxelVolumeSize; // meters / voxel-units if (isEdged(_voxelSurfaceStyle)) { result = scale / -2.0f; } @@ -228,7 +228,7 @@ glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { voxelVolumeSize = _voxelVolumeSize; }); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 scale = dimensions / voxelVolumeSize; // meters / voxel-units bool success; // TODO -- Does this actually have to happen in world space? glm::vec3 center = getCenterPosition(success); // this handles registrationPoint changes @@ -393,7 +393,7 @@ bool RenderablePolyVoxEntityItem::setSphere(const vec3& centerWorldCoords, float glm::mat4 vtwMatrix = voxelToWorldMatrix(); glm::mat4 wtvMatrix = glm::inverse(vtwMatrix); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 voxelSize = dimensions / _voxelVolumeSize; float smallestDimensionSize = voxelSize.x; smallestDimensionSize = glm::min(smallestDimensionSize, voxelSize.y); @@ -454,7 +454,7 @@ bool RenderablePolyVoxEntityItem::setCapsule(const vec3& startWorldCoords, const glm::mat4 vtwMatrix = voxelToWorldMatrix(); glm::mat4 wtvMatrix = glm::inverse(vtwMatrix); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 voxelSize = dimensions / _voxelVolumeSize; float smallestDimensionSize = voxelSize.x; smallestDimensionSize = glm::min(smallestDimensionSize, voxelSize.y); @@ -580,7 +580,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o // the PolyVox ray intersection code requires a near and far point. // set ray cast length to long enough to cover all of the voxel space float distanceToEntity = glm::distance(origin, getWorldPosition()); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); float largestDimension = glm::compMax(dimensions) * 2.0f; glm::vec3 farPoint = origin + normDirection * (distanceToEntity + largestDimension); @@ -668,7 +668,7 @@ bool RenderablePolyVoxEntityItem::isReadyToComputeShape() const { void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { ShapeType shapeType = getShapeType(); if (shapeType == SHAPE_TYPE_NONE) { - info.setParams(getShapeType(), 0.5f * getDimensions()); + info.setParams(getShapeType(), 0.5f * getScaledDimensions()); return; } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 3524709395..cbee221399 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -63,7 +63,7 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return true; } - if (_dimensions != entity->getDimensions()) { + if (_dimensions != entity->getScaledDimensions()) { return true; } @@ -82,7 +82,7 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _shape = entity->getShape(); _position = entity->getWorldPosition(); - _dimensions = entity->getDimensions(); + _dimensions = entity->getScaledDimensions(); _orientation = entity->getWorldOrientation(); _renderTransform = getModelTransform(); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index 6c0f4447ae..968c181940 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -54,7 +54,7 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint return true; } - if (_dimensions != entity->getDimensions()) { + if (_dimensions != entity->getScaledDimensions()) { return true; } @@ -67,7 +67,7 @@ bool TextEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint void TextEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) { _textColor = toGlm(entity->getTextColorX()); _backgroundColor = toGlm(entity->getBackgroundColorX()); - _dimensions = entity->getDimensions(); + _dimensions = entity->getScaledDimensions(); _faceCamera = entity->getFaceCamera(); _lineHeight = entity->getLineHeight(); _text = entity->getText(); diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index cdd260e73c..05a2228607 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -144,7 +144,7 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene glm::vec2 windowSize = getWindowSize(entity); _webSurface->resize(QSize(windowSize.x, windowSize.y)); _renderTransform = getModelTransform(); - _renderTransform.postScale(entity->getDimensions()); + _renderTransform.postScale(entity->getScaledDimensions()); }); } @@ -274,7 +274,7 @@ void WebEntityRenderer::destroyWebSurface() { } glm::vec2 WebEntityRenderer::getWindowSize(const TypedEntityPointer& entity) const { - glm::vec2 dims = glm::vec2(entity->getDimensions()); + glm::vec2 dims = glm::vec2(entity->getScaledDimensions()); dims *= METERS_TO_INCHES * _lastDPI; // ensure no side is never larger then MAX_WINDOW_SIZE diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 7a5c50df50..784945f0bb 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -206,7 +206,7 @@ void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scen entity->resetRenderingPropertiesChanged(); _lastPosition = entity->getWorldPosition(); _lastRotation = entity->getWorldOrientation(); - _lastDimensions = entity->getDimensions(); + _lastDimensions = entity->getScaledDimensions(); _keyLightProperties = entity->getKeyLightProperties(); _skyboxProperties = entity->getSkyboxProperties(); @@ -278,7 +278,7 @@ bool ZoneEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoint if (entity->getWorldPosition() != _lastPosition) { return true; } - if (entity->getDimensions() != _lastDimensions) { + if (entity->getScaledDimensions() != _lastDimensions) { return true; } if (entity->getWorldOrientation() != _lastRotation) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index c8e7ce6c11..d244f6d557 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -49,6 +49,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : { setLocalVelocity(ENTITY_ITEM_DEFAULT_VELOCITY); setLocalAngularVelocity(ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY); + setUnscaledDimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS); // explicitly set transform parts to set dirty flags used by batch rendering locationChanged(); dimensionsChanged(); @@ -241,7 +242,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, getLocalAngularVelocity()); APPEND_ENTITY_PROPERTY(PROP_ACCELERATION, getAcceleration()); - APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getDimensions()); + APPEND_ENTITY_PROPERTY(PROP_DIMENSIONS, getUnscaledDimensions()); APPEND_ENTITY_PROPERTY(PROP_DENSITY, getDensity()); APPEND_ENTITY_PROPERTY(PROP_GRAVITY, getGravity()); APPEND_ENTITY_PROPERTY(PROP_DAMPING, getDamping()); @@ -776,7 +777,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, customSetAcceleration); } - READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, setDimensions); + READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, setUnscaledDimensions); READ_ENTITY_PROPERTY(PROP_DENSITY, float, setDensity); READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, setGravity); @@ -894,7 +895,7 @@ void EntityItem::debugDump() const { qCDebug(entities) << "EntityItem id:" << getEntityItemID(); qCDebug(entities, " edited ago:%f", (double)getEditedAgo()); qCDebug(entities, " position:%f,%f,%f", (double)position.x, (double)position.y, (double)position.z); - qCDebug(entities) << " dimensions:" << getDimensions(); + qCDebug(entities) << " dimensions:" << getScaledDimensions(); } // adjust any internal timestamps to fix clock skew for this server @@ -919,7 +920,7 @@ void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, qint64 clockSk } float EntityItem::computeMass() const { - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); return getDensity() * _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z; } @@ -938,7 +939,7 @@ void EntityItem::setMass(float mass) { // we must protect the density range to help maintain stability of physics simulation // therefore this method might not accept the mass that is supplied. - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); float volume = _volumeMultiplier * dimensions.x * dimensions.y * dimensions.z; // compute new density @@ -1172,7 +1173,7 @@ bool EntityItem::wantTerseEditLogging() const { glm::mat4 EntityItem::getEntityToWorldMatrix() const { glm::mat4 translation = glm::translate(getWorldPosition()); glm::mat4 rotation = glm::mat4_cast(getWorldOrientation()); - glm::mat4 scale = glm::scale(getDimensions()); + glm::mat4 scale = glm::scale(getScaledDimensions()); glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()); return translation * rotation * scale * registration; } @@ -1212,7 +1213,7 @@ EntityItemProperties EntityItem::getProperties(EntityPropertyFlags desiredProper COPY_ENTITY_PROPERTY_TO_PROPERTIES(simulationOwner, getSimulationOwner); COPY_ENTITY_PROPERTY_TO_PROPERTIES(position, getLocalPosition); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getDimensions); // NOTE: radius is obsolete + COPY_ENTITY_PROPERTY_TO_PROPERTIES(dimensions, getUnscaledDimensions); COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotation, getLocalOrientation); COPY_ENTITY_PROPERTY_TO_PROPERTIES(density, getDensity); COPY_ENTITY_PROPERTY_TO_PROPERTIES(velocity, getLocalVelocity); @@ -1319,7 +1320,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(acceleration, setAcceleration); // these (along with "position" above) affect tree structure - SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setDimensions); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, setUnscaledDimensions); SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint); // these (along with all properties above) affect the simulation @@ -1421,7 +1422,7 @@ void EntityItem::recordCreationTime() { const Transform EntityItem::getTransformToCenter(bool& success) const { Transform result = getTransform(success); if (getRegistrationPoint() != ENTITY_ITEM_HALF_VEC3) { // If it is not already centered, translate to center - result.postTranslate((ENTITY_ITEM_HALF_VEC3 - getRegistrationPoint()) * getDimensions()); // Position to center + result.postTranslate((ENTITY_ITEM_HALF_VEC3 - getRegistrationPoint()) * getScaledDimensions()); // Position to center } return result; } @@ -1437,7 +1438,7 @@ AACube EntityItem::getMaximumAACube(bool& success) const { // we want to compute the furthestExtent that an entity can extend out from its "position" // to do this we compute the max of these two vec3s: registration and 1-registration // and then scale by dimensions - glm::vec3 maxExtents = getDimensions() * glm::max(_registrationPoint, glm::vec3(1.0f) - _registrationPoint); + glm::vec3 maxExtents = getScaledDimensions() * glm::max(_registrationPoint, glm::vec3(1.0f) - _registrationPoint); // there exists a sphere that contains maxExtents for all rotations float radius = glm::length(maxExtents); @@ -1462,7 +1463,7 @@ AACube EntityItem::getMinimumAACube(bool& success) const { glm::vec3 position = getWorldPosition(success); if (success) { _recalcMinAACube = false; - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 unrotatedMinRelativeToEntity = - (dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint); Extents extents = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; @@ -1492,7 +1493,7 @@ AABox EntityItem::getAABox(bool& success) const { glm::vec3 position = getWorldPosition(success); if (success) { _recalcAABox = false; - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 unrotatedMinRelativeToEntity = - (dimensions * _registrationPoint); glm::vec3 unrotatedMaxRelativeToEntity = dimensions * (glm::vec3(1.0f, 1.0f, 1.0f) - _registrationPoint); Extents extents = { unrotatedMinRelativeToEntity, unrotatedMaxRelativeToEntity }; @@ -1532,12 +1533,12 @@ bool EntityItem::shouldPuffQueryAACube() const { // ... cornerToCornerLength = sqrt(3 x maxDimension ^ 2) // ... radius = sqrt(3 x maxDimension ^ 2) / 2.0f; float EntityItem::getRadius() const { - return 0.5f * glm::length(getDimensions()); + return 0.5f * glm::length(getScaledDimensions()); } void EntityItem::adjustShapeInfoByRegistration(ShapeInfo& info) const { if (_registrationPoint != ENTITY_ITEM_DEFAULT_REGISTRATION_POINT) { - glm::mat4 scale = glm::scale(getDimensions()); + glm::mat4 scale = glm::scale(getScaledDimensions()); glm::mat4 registration = scale * glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint()); glm::vec3 regTransVec = glm::vec3(registration[3]); // extract position component from matrix info.setOffset(regTransVec); @@ -1558,12 +1559,12 @@ bool EntityItem::contains(const glm::vec3& point) const { } void EntityItem::computeShapeInfo(ShapeInfo& info) { - info.setParams(getShapeType(), 0.5f * getDimensions()); + info.setParams(getShapeType(), 0.5f * getScaledDimensions()); adjustShapeInfoByRegistration(info); } float EntityItem::getVolumeEstimate() const { - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); return dimensions.x * dimensions.y * dimensions.z; } @@ -1617,11 +1618,25 @@ void EntityItem::setParentID(const QUuid& value) { } } -void EntityItem::setDimensions(const glm::vec3& value) { +glm::vec3 EntityItem::getScaledDimensions() const { + glm::vec3 scale = getSNScale(); + return glm::vec3(_unscaledDimensions.x * scale.x, + _unscaledDimensions.y * scale.y, + _unscaledDimensions.z * scale.z); +} + +void EntityItem::setScaledDimensions(const glm::vec3& value) { + glm::vec3 parentScale = getSNScale(); + setUnscaledDimensions(glm::vec3(value.x / parentScale.x, + value.y / parentScale.y, + value.z / parentScale.z)); +} + +void EntityItem::setUnscaledDimensions(const glm::vec3& value) { glm::vec3 newDimensions = glm::max(value, glm::vec3(0.0f)); // can never have negative dimensions - if (getDimensions() != newDimensions) { + if (getUnscaledDimensions() != newDimensions) { withWriteLock([&] { - _dimensions = newDimensions; + _unscaledDimensions = newDimensions; }); locationChanged(); dimensionsChanged(); @@ -2292,6 +2307,16 @@ void EntityItem::dimensionsChanged() { somethingChangedNotification(); } +bool EntityItem::getScalesWithParent() const { + // keep this logic the same as in EntityItemProperties::getScalesWithParent + if (getClientOnly()) { + QUuid ancestorID = findAncestorOfType(NestableType::Avatar); + return !ancestorID.isNull(); + } else { + return false; + } +} + void EntityItem::globalizeProperties(EntityItemProperties& properties, const QString& messageTemplate, const glm::vec3& offset) const { // TODO -- combine this with convertLocationToScriptSemantics bool success; @@ -2299,7 +2324,7 @@ void EntityItem::globalizeProperties(EntityItemProperties& properties, const QSt if (success) { properties.setPosition(globalPosition + offset); properties.setRotation(getWorldOrientation()); - properties.setDimensions(getDimensions()); + properties.setDimensions(getScaledDimensions()); // Should we do velocities and accelerations, too? This could end up being quite involved, which is why the method exists. } else { properties.setPosition(getQueryAACube().calcCenter() + offset); // best we can do diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 882b8e6812..985dbdcaae 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -180,8 +180,11 @@ public: void setDescription(const QString& value); /// Dimensions in meters (0.0 - TREE_SCALE) - inline const glm::vec3 getDimensions() const { return _dimensions; } - virtual void setDimensions(const glm::vec3& value); + glm::vec3 getScaledDimensions() const; + virtual void setScaledDimensions(const glm::vec3& value); + + inline const glm::vec3 getUnscaledDimensions() const { return _unscaledDimensions; } + virtual void setUnscaledDimensions(const glm::vec3& value); float getLocalRenderAlpha() const; void setLocalRenderAlpha(float localRenderAlpha); @@ -454,6 +457,8 @@ public: virtual void locationChanged(bool tellPhysics = true) override; + virtual bool getScalesWithParent() const override; + using ChangeHandlerCallback = std::function; using ChangeHandlerId = QUuid; ChangeHandlerId registerChangeHandler(const ChangeHandlerCallback& handler); @@ -474,7 +479,7 @@ protected: virtual void dimensionsChanged() override; - glm::vec3 _dimensions { ENTITY_ITEM_DEFAULT_DIMENSIONS }; + glm::vec3 _unscaledDimensions { ENTITY_ITEM_DEFAULT_DIMENSIONS }; EntityTypes::EntityType _type { EntityTypes::Unknown }; quint64 _lastSimulated { 0 }; // last time this entity called simulate(), this includes velocity, angular velocity, // and physics changes diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 5ab4bdee01..8f57db772a 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -365,6 +365,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_LOCAL_ROTATION, localRotation); CHECK_PROPERTY_CHANGE(PROP_LOCAL_VELOCITY, localVelocity); CHECK_PROPERTY_CHANGE(PROP_LOCAL_ANGULAR_VELOCITY, localAngularVelocity); + CHECK_PROPERTY_CHANGE(PROP_LOCAL_DIMENSIONS, localDimensions); CHECK_PROPERTY_CHANGE(PROP_FLYING_ALLOWED, flyingAllowed); CHECK_PROPERTY_CHANGE(PROP_GHOSTING_ALLOWED, ghostingAllowed); @@ -627,6 +628,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ROTATION, localRotation); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_VELOCITY, localVelocity); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_ANGULAR_VELOCITY, localAngularVelocity); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCAL_DIMENSIONS, localDimensions); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_CLIENT_ONLY, clientOnly); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_OWNING_AVATAR_ID, owningAvatarID); @@ -803,6 +805,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(localRotation, glmQuat, setLocalRotation); COPY_PROPERTY_FROM_QSCRIPTVALUE(localVelocity, glmVec3, setLocalVelocity); COPY_PROPERTY_FROM_QSCRIPTVALUE(localAngularVelocity, glmVec3, setLocalAngularVelocity); + COPY_PROPERTY_FROM_QSCRIPTVALUE(localDimensions, glmVec3, setLocalDimensions); COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotationsSet, qVectorBool, setJointRotationsSet); COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotations, qVectorQuat, setJointRotations); @@ -950,6 +953,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(localRotation); COPY_PROPERTY_IF_CHANGED(localVelocity); COPY_PROPERTY_IF_CHANGED(localAngularVelocity); + COPY_PROPERTY_IF_CHANGED(localDimensions); COPY_PROPERTY_IF_CHANGED(jointRotationsSet); COPY_PROPERTY_IF_CHANGED(jointRotations); @@ -1128,6 +1132,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glm::quat); ADD_PROPERTY_TO_MAP(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3); + ADD_PROPERTY_TO_MAP(PROP_LOCAL_DIMENSIONS, LocalDimensions, localDimensions, glm::vec3); ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector); ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector); @@ -2460,9 +2465,25 @@ bool EntityItemProperties::transformChanged() const { localPositionChanged() || localRotationChanged(); } +bool EntityItemProperties::getScalesWithParent() const { + // keep this logic the same as in EntityItem::getScalesWithParent + bool scalesWithParent { false }; + if (parentIDChanged()) { + bool success; + SpatiallyNestablePointer parent = SpatiallyNestable::findByID(getParentID(), success); + if (success && parent) { + bool avatarAncestor = (parent->getNestableType() == NestableType::Avatar || + parent->hasAncestorOfType(NestableType::Avatar)); + scalesWithParent = getClientOnly() && avatarAncestor; + } + } + return scalesWithParent; +} + bool EntityItemProperties::parentRelatedPropertyChanged() const { return positionChanged() || rotationChanged() || localPositionChanged() || localRotationChanged() || + localDimensionsChanged() || parentIDChanged() || parentJointIndexChanged(); } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index ec192d7c9f..a1118e8441 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -88,6 +88,7 @@ public: EntityPropertyFlags getChangedProperties() const; bool transformChanged() const; + bool getScalesWithParent() const; bool parentRelatedPropertyChanged() const; bool queryAACubeRelatedPropertyChanged() const; @@ -226,6 +227,7 @@ public: DEFINE_PROPERTY_REF(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glmQuat, ENTITY_ITEM_DEFAULT_ROTATION); DEFINE_PROPERTY_REF(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glmVec3, ENTITY_ITEM_ZERO_VEC3); DEFINE_PROPERTY_REF(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glmVec3, ENTITY_ITEM_ZERO_VEC3); + DEFINE_PROPERTY_REF(PROP_LOCAL_DIMENSIONS, LocalDimensions, localDimensions, glmVec3, ENTITY_ITEM_ZERO_VEC3); DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector, QVector()); DEFINE_PROPERTY_REF(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector, QVector()); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 35d40b669a..c44f8091e0 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -219,6 +219,8 @@ enum EntityPropertyList { PROP_HAZE_KEYLIGHT_RANGE, PROP_HAZE_KEYLIGHT_ALTITUDE, + PROP_LOCAL_DIMENSIONS, // only used to convert values to and from scripts + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 35941c09d3..25eb126704 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -117,7 +117,8 @@ void EntityScriptingInterface::setEntityTree(EntityTreePointer elementTree) { } } -EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties& entitySideProperties) { +EntityItemProperties convertPropertiesToScriptSemantics(const EntityItemProperties& entitySideProperties, + bool scalesWithParent) { // In EntityTree code, properties.position and properties.rotation are relative to the parent. In javascript, // they are in world-space. The local versions are put into localPosition and localRotation and position and // rotation are converted from local to world space. @@ -126,35 +127,48 @@ EntityItemProperties convertLocationToScriptSemantics(const EntityItemProperties scriptSideProperties.setLocalRotation(entitySideProperties.getRotation()); scriptSideProperties.setLocalVelocity(entitySideProperties.getLocalVelocity()); scriptSideProperties.setLocalAngularVelocity(entitySideProperties.getLocalAngularVelocity()); + scriptSideProperties.setLocalDimensions(entitySideProperties.getDimensions()); bool success; glm::vec3 worldPosition = SpatiallyNestable::localToWorld(entitySideProperties.getPosition(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), + scalesWithParent, success); glm::quat worldRotation = SpatiallyNestable::localToWorld(entitySideProperties.getRotation(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), + scalesWithParent, success); glm::vec3 worldVelocity = SpatiallyNestable::localToWorldVelocity(entitySideProperties.getVelocity(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), + scalesWithParent, success); glm::vec3 worldAngularVelocity = SpatiallyNestable::localToWorldAngularVelocity(entitySideProperties.getAngularVelocity(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), + scalesWithParent, success); + glm::vec3 worldDimensions = SpatiallyNestable::localToWorldDimensions(entitySideProperties.getDimensions(), + entitySideProperties.getParentID(), + entitySideProperties.getParentJointIndex(), + scalesWithParent, + success); + scriptSideProperties.setPosition(worldPosition); scriptSideProperties.setRotation(worldRotation); scriptSideProperties.setVelocity(worldVelocity); scriptSideProperties.setAngularVelocity(worldAngularVelocity); + scriptSideProperties.setDimensions(worldDimensions); return scriptSideProperties; } -EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperties& scriptSideProperties) { +EntityItemProperties convertPropertiesFromScriptSemantics(const EntityItemProperties& scriptSideProperties, + bool scalesWithParent) { // convert position and rotation properties from world-space to local, unless localPosition and localRotation // are set. If they are set, they overwrite position and rotation. EntityItemProperties entitySideProperties = scriptSideProperties; @@ -168,7 +182,7 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti glm::vec3 localPosition = SpatiallyNestable::worldToLocal(entitySideProperties.getPosition(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), - success); + scalesWithParent, success); entitySideProperties.setPosition(localPosition); } @@ -178,7 +192,7 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti glm::quat localRotation = SpatiallyNestable::worldToLocal(entitySideProperties.getRotation(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), - success); + scalesWithParent, success); entitySideProperties.setRotation(localRotation); } @@ -188,7 +202,7 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti glm::vec3 localVelocity = SpatiallyNestable::worldToLocalVelocity(entitySideProperties.getVelocity(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), - success); + scalesWithParent, success); entitySideProperties.setVelocity(localVelocity); } @@ -199,10 +213,20 @@ EntityItemProperties convertLocationFromScriptSemantics(const EntityItemProperti SpatiallyNestable::worldToLocalAngularVelocity(entitySideProperties.getAngularVelocity(), entitySideProperties.getParentID(), entitySideProperties.getParentJointIndex(), - success); + scalesWithParent, success); entitySideProperties.setAngularVelocity(localAngularVelocity); } + if (scriptSideProperties.localDimensionsChanged()) { + entitySideProperties.setDimensions(scriptSideProperties.getLocalDimensions()); + } else if (scriptSideProperties.dimensionsChanged()) { + glm::vec3 localDimensions = SpatiallyNestable::worldToLocalDimensions(entitySideProperties.getDimensions(), + entitySideProperties.getParentID(), + entitySideProperties.getParentJointIndex(), + scalesWithParent, success); + entitySideProperties.setDimensions(localDimensions); + } + return entitySideProperties; } @@ -212,9 +236,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties _activityTracking.addedEntityCount++; - EntityItemProperties propertiesWithSimID = convertLocationFromScriptSemantics(properties); - propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); - + EntityItemProperties propertiesWithSimID = properties; if (clientOnly) { auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); @@ -222,6 +244,11 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties propertiesWithSimID.setOwningAvatarID(myNodeID); } + bool scalesWithParent = propertiesWithSimID.getScalesWithParent(); + + propertiesWithSimID = convertPropertiesFromScriptSemantics(propertiesWithSimID, scalesWithParent); + propertiesWithSimID.setDimensionsInitialized(properties.dimensionsChanged()); + auto dimensions = propertiesWithSimID.getDimensions(); float volume = dimensions.x * dimensions.y * dimensions.z; auto density = propertiesWithSimID.getDensity(); @@ -295,15 +322,20 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identity, EntityPropertyFlags desiredProperties) { PROFILE_RANGE(script_entities, __FUNCTION__); + bool scalesWithParent { false }; EntityItemProperties results; if (_entityTree) { _entityTree->withReadLock([&] { EntityItemPointer entity = _entityTree->findEntityByEntityItemID(EntityItemID(identity)); if (entity) { + scalesWithParent = entity->getScalesWithParent(); if (desiredProperties.getHasProperty(PROP_POSITION) || desiredProperties.getHasProperty(PROP_ROTATION) || desiredProperties.getHasProperty(PROP_LOCAL_POSITION) || - desiredProperties.getHasProperty(PROP_LOCAL_ROTATION)) { + desiredProperties.getHasProperty(PROP_LOCAL_ROTATION) || + desiredProperties.getHasProperty(PROP_LOCAL_VELOCITY) || + desiredProperties.getHasProperty(PROP_LOCAL_ANGULAR_VELOCITY) || + desiredProperties.getHasProperty(PROP_LOCAL_DIMENSIONS)) { // if we are explicitly getting position or rotation, we need parent information to make sense of them. desiredProperties.setHasProperty(PROP_PARENT_ID); desiredProperties.setHasProperty(PROP_PARENT_JOINT_INDEX); @@ -316,6 +348,9 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit desiredProperties = entity->getEntityProperties(params); desiredProperties.setHasProperty(PROP_LOCAL_POSITION); desiredProperties.setHasProperty(PROP_LOCAL_ROTATION); + desiredProperties.setHasProperty(PROP_LOCAL_VELOCITY); + desiredProperties.setHasProperty(PROP_LOCAL_ANGULAR_VELOCITY); + desiredProperties.setHasProperty(PROP_LOCAL_DIMENSIONS); } results = entity->getProperties(desiredProperties); @@ -323,7 +358,7 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit }); } - return convertLocationToScriptSemantics(results); + return convertPropertiesToScriptSemantics(results, scalesWithParent); } QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& scriptSideProperties) { @@ -390,10 +425,13 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& if (!scriptSideProperties.localRotationChanged() && !scriptSideProperties.rotationChanged()) { properties.setRotation(entity->getWorldOrientation()); } + if (!scriptSideProperties.localDimensionsChanged() && !scriptSideProperties.dimensionsChanged()) { + properties.setDimensions(entity->getScaledDimensions()); + } } - properties = convertLocationFromScriptSemantics(properties); properties.setClientOnly(entity->getClientOnly()); properties.setOwningAvatarID(entity->getOwningAvatarID()); + properties = convertPropertiesFromScriptSemantics(properties, properties.getScalesWithParent()); float cost = calculateCost(density * volume, oldVelocity, newVelocity); cost *= costMultiplier; @@ -529,7 +567,7 @@ void EntityScriptingInterface::deleteEntity(QUuid id) { return; } - auto dimensions = entity->getDimensions(); + auto dimensions = entity->getScaledDimensions(); float volume = dimensions.x * dimensions.y * dimensions.z; auto density = entity->getDensity(); auto velocity = entity->getWorldVelocity().length(); diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index 7e2958583d..926975f735 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -667,7 +667,7 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con glm::mat4 entityToWorldMatrix = translation * rotation; glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - glm::vec3 dimensions = entity->getDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); glm::vec3 registrationPoint = entity->getRegistrationPoint(); glm::vec3 corner = -(dimensions * registrationPoint); @@ -763,7 +763,7 @@ void EntityTreeElement::getEntities(const glm::vec3& searchPosition, float searc glm::vec3 penetration; if (!success || entityBox.findSpherePenetration(searchPosition, searchRadius, penetration)) { - glm::vec3 dimensions = entity->getDimensions(); + glm::vec3 dimensions = entity->getScaledDimensions(); // FIXME - consider allowing the entity to determine penetration so that // entities could presumably dull actuall hull testing if they wanted to diff --git a/libraries/entities/src/LightEntityItem.cpp b/libraries/entities/src/LightEntityItem.cpp index f4944603f1..45f36a1744 100644 --- a/libraries/entities/src/LightEntityItem.cpp +++ b/libraries/entities/src/LightEntityItem.cpp @@ -41,16 +41,16 @@ LightEntityItem::LightEntityItem(const EntityItemID& entityItemID) : EntityItem( _color[RED_INDEX] = _color[GREEN_INDEX] = _color[BLUE_INDEX] = 0; } -void LightEntityItem::setDimensions(const glm::vec3& value) { +void LightEntityItem::setUnscaledDimensions(const glm::vec3& value) { if (_isSpotlight) { // If we are a spotlight, treat the z value as our radius or length, and // recalculate the x/y dimensions to properly encapsulate the spotlight. const float length = value.z; const float width = length * glm::sin(glm::radians(_cutoff)); - EntityItem::setDimensions(glm::vec3(width, width, length)); + EntityItem::setUnscaledDimensions(glm::vec3(width, width, length)); } else { float maxDimension = glm::compMax(value); - EntityItem::setDimensions(glm::vec3(maxDimension, maxDimension, maxDimension)); + EntityItem::setUnscaledDimensions(glm::vec3(maxDimension, maxDimension, maxDimension)); } } @@ -98,7 +98,7 @@ void LightEntityItem::setIsSpotlight(bool value) { return; } - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 newDimensions; if (value) { const float length = dimensions.z; @@ -112,7 +112,7 @@ void LightEntityItem::setIsSpotlight(bool value) { _isSpotlight = value; _lightPropertiesChanged = true; }); - setDimensions(newDimensions); + setScaledDimensions(newDimensions); } void LightEntityItem::setCutoff(float value) { @@ -128,9 +128,9 @@ void LightEntityItem::setCutoff(float value) { if (getIsSpotlight()) { // If we are a spotlight, adjusting the cutoff will affect the area we encapsulate, // so update the dimensions to reflect this. - const float length = getDimensions().z; + const float length = getScaledDimensions().z; const float width = length * glm::sin(glm::radians(_cutoff)); - setDimensions(glm::vec3(width, width, length)); + setScaledDimensions(glm::vec3(width, width, length)); } withWriteLock([&] { diff --git a/libraries/entities/src/LightEntityItem.h b/libraries/entities/src/LightEntityItem.h index edc7376079..870b283c26 100644 --- a/libraries/entities/src/LightEntityItem.h +++ b/libraries/entities/src/LightEntityItem.h @@ -29,7 +29,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensions(const glm::vec3& value) override; + virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual bool setProperties(const EntityItemProperties& properties) override; virtual bool setSubClassProperties(const EntityItemProperties& properties) override; diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index 02d16f2537..00196d7b23 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -80,7 +80,7 @@ bool LineEntityItem::appendPoint(const glm::vec3& point) { qCDebug(entities) << "MAX POINTS REACHED!"; return false; } - glm::vec3 halfBox = getDimensions() * 0.5f; + glm::vec3 halfBox = getScaledDimensions() * 0.5f; if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { qCDebug(entities) << "Point is outside entity's bounding box"; return false; @@ -96,7 +96,7 @@ bool LineEntityItem::setLinePoints(const QVector& points) { if (points.size() > MAX_POINTS_PER_LINE) { return false; } - glm::vec3 halfBox = getDimensions() * 0.5f; + glm::vec3 halfBox = getScaledDimensions() * 0.5f; for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { @@ -157,7 +157,7 @@ void LineEntityItem::debugDump() const { qCDebug(entities) << " LINE EntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 313721ff54..5ec86e2f76 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -190,7 +190,7 @@ void ModelEntityItem::debugDump() const { qCDebug(entities) << "ModelEntityItem id:" << getEntityItemID(); qCDebug(entities) << " edited ago:" << getEditedAgo(); qCDebug(entities) << " position:" << getWorldPosition(); - qCDebug(entities) << " dimensions:" << getDimensions(); + qCDebug(entities) << " dimensions:" << getScaledDimensions(); qCDebug(entities) << " model URL:" << getModelURL(); qCDebug(entities) << " compound shape URL:" << getCompoundShapeURL(); } diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index bc0c093518..c20572a491 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -353,7 +353,7 @@ void ParticleEffectEntityItem::computeAndUpdateDimensions() { float maxDistanceValue = glm::compMax(maxDistance); //times 2 because dimensions are diameters not radii glm::vec3 dims(2.0f * maxDistanceValue); - EntityItem::setDimensions(dims); + EntityItem::setScaledDimensions(dims); } @@ -593,7 +593,7 @@ void ParticleEffectEntityItem::debugDump() const { _particleProperties.color.gradient.target.green << "," << _particleProperties.color.gradient.target.blue; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index e69fb2e100..498d13058e 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -191,7 +191,7 @@ void PolyLineEntityItem::calculateScaleAndRegistrationPoint() { } // if Polyline has only one or fewer points, use default dimension settings - setDimensions(newScale); + setScaledDimensions(newScale); EntityItem::setRegistrationPoint(newRegistrationPoint); } @@ -257,7 +257,7 @@ void PolyLineEntityItem::debugDump() const { qCDebug(entities) << " QUAD EntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index b08d94ca7e..84ce83d3a1 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -229,7 +229,7 @@ void PolyVoxEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qCDebug(entities) << " POLYVOX EntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); } @@ -377,7 +377,7 @@ EntityItemID PolyVoxEntityItem::getZPNeighborID() const { glm::vec3 PolyVoxEntityItem::getSurfacePositionAdjustment() const { glm::vec3 result; withReadLock([&] { - glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units + glm::vec3 scale = getScaledDimensions() / _voxelVolumeSize; // meters / voxel-units if (isEdged()) { result = scale / -2.0f; } @@ -392,7 +392,7 @@ glm::mat4 PolyVoxEntityItem::voxelToLocalMatrix() const { voxelVolumeSize = _voxelVolumeSize; }); - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec3 scale = dimensions / voxelVolumeSize; // meters / voxel-units bool success; // TODO -- Does this actually have to happen in world space? glm::vec3 center = getCenterPosition(success); // this handles registrationPoint changes diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 15704ebc17..f564c89d21 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -106,11 +106,11 @@ void ShapeEntityItem::setShape(const entity::Shape& shape) { break; case entity::Shape::Circle: // Circle is implicitly flat so we enforce flat dimensions - setDimensions(getDimensions()); + setUnscaledDimensions(getUnscaledDimensions()); break; case entity::Shape::Quad: // Quad is implicitly flat so we enforce flat dimensions - setDimensions(getDimensions()); + setUnscaledDimensions(getUnscaledDimensions()); break; default: _type = EntityTypes::Shape; @@ -204,15 +204,15 @@ void ShapeEntityItem::setColor(const QColor& value) { setAlpha(value.alpha()); } -void ShapeEntityItem::setDimensions(const glm::vec3& value) { +void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { const float MAX_FLAT_DIMENSION = 0.0001f; if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { // enforce flatness in Y glm::vec3 newDimensions = value; newDimensions.y = MAX_FLAT_DIMENSION; - EntityItem::setDimensions(newDimensions); + EntityItem::setUnscaledDimensions(newDimensions); } else { - EntityItem::setDimensions(value); + EntityItem::setUnscaledDimensions(value); } } @@ -256,7 +256,7 @@ void ShapeEntityItem::debugDump() const { qCDebug(entities) << " collisionShapeType:" << ShapeInfo::getNameForShapeType(getShapeType()); qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2]; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); qCDebug(entities) << "SHAPE EntityItem Ptr:" << this; } @@ -266,7 +266,7 @@ void ShapeEntityItem::computeShapeInfo(ShapeInfo& info) { // This will be called whenever DIRTY_SHAPE flag (set by dimension change, etc) // is set. - const glm::vec3 entityDimensions = getDimensions(); + const glm::vec3 entityDimensions = getScaledDimensions(); switch (_shape){ case entity::Shape::Quad: diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 20e36c88e6..c5df17db54 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -80,7 +80,7 @@ public: const rgbColor& getColor() const { return _color; } void setColor(const rgbColor& value); - void setDimensions(const glm::vec3& value) override; + void setUnscaledDimensions(const glm::vec3& value) override; xColor getXColor() const; void setColor(const xColor& value); diff --git a/libraries/entities/src/TextEntityItem.cpp b/libraries/entities/src/TextEntityItem.cpp index 67e83ab3fd..639da69a17 100644 --- a/libraries/entities/src/TextEntityItem.cpp +++ b/libraries/entities/src/TextEntityItem.cpp @@ -41,9 +41,9 @@ TextEntityItem::TextEntityItem(const EntityItemID& entityItemID) : EntityItem(en const float TEXT_ENTITY_ITEM_FIXED_DEPTH = 0.01f; -void TextEntityItem::setDimensions(const glm::vec3& value) { +void TextEntityItem::setUnscaledDimensions(const glm::vec3& value) { // NOTE: Text Entities always have a "depth" of 1cm. - EntityItem::setDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH)); + EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH)); } EntityItemProperties TextEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { @@ -132,7 +132,7 @@ bool TextEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const { - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * diff --git a/libraries/entities/src/TextEntityItem.h b/libraries/entities/src/TextEntityItem.h index 8db929fa47..520a935e55 100644 --- a/libraries/entities/src/TextEntityItem.h +++ b/libraries/entities/src/TextEntityItem.h @@ -23,7 +23,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensions(const glm::vec3& value) override; + virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; } // methods for getting/setting all properties of an entity diff --git a/libraries/entities/src/WebEntityItem.cpp b/libraries/entities/src/WebEntityItem.cpp index 5ee630d8ed..54db6e7c3b 100644 --- a/libraries/entities/src/WebEntityItem.cpp +++ b/libraries/entities/src/WebEntityItem.cpp @@ -36,9 +36,9 @@ WebEntityItem::WebEntityItem(const EntityItemID& entityItemID) : EntityItem(enti const float WEB_ENTITY_ITEM_FIXED_DEPTH = 0.01f; -void WebEntityItem::setDimensions(const glm::vec3& value) { +void WebEntityItem::setUnscaledDimensions(const glm::vec3& value) { // NOTE: Web Entities always have a "depth" of 1cm. - EntityItem::setDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH)); + EntityItem::setUnscaledDimensions(glm::vec3(value.x, value.y, WEB_ENTITY_ITEM_FIXED_DEPTH)); } EntityItemProperties WebEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { @@ -109,7 +109,7 @@ bool WebEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const g bool& keepSearching, OctreeElementPointer& element, float& distance, BoxFace& face, glm::vec3& surfaceNormal, void** intersectedObject, bool precisionPicking) const { - glm::vec3 dimensions = getDimensions(); + glm::vec3 dimensions = getScaledDimensions(); glm::vec2 xyDimensions(dimensions.x, dimensions.y); glm::quat rotation = getWorldOrientation(); glm::vec3 position = getWorldPosition() + rotation * (dimensions * (ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint())); diff --git a/libraries/entities/src/WebEntityItem.h b/libraries/entities/src/WebEntityItem.h index 9e84a3a776..f5066beebc 100644 --- a/libraries/entities/src/WebEntityItem.h +++ b/libraries/entities/src/WebEntityItem.h @@ -22,7 +22,7 @@ public: ALLOW_INSTANTIATION // This class can be instantiated /// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately - virtual void setDimensions(const glm::vec3& value) override; + virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual ShapeType getShapeType() const override { return SHAPE_TYPE_BOX; } // methods for getting/setting all properties of an entity diff --git a/libraries/entities/src/ZoneEntityItem.cpp b/libraries/entities/src/ZoneEntityItem.cpp index 0ed523202b..fbfbc71a85 100644 --- a/libraries/entities/src/ZoneEntityItem.cpp +++ b/libraries/entities/src/ZoneEntityItem.cpp @@ -242,7 +242,7 @@ void ZoneEntityItem::debugDump() const { quint64 now = usecTimestampNow(); qCDebug(entities) << " ZoneEntityItem id:" << getEntityItemID() << "---------------------------------------------"; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); qCDebug(entities) << " _backgroundMode:" << EntityItemProperties::getBackgroundModeString(_backgroundMode); qCDebug(entities) << " _hazeMode:" << EntityItemProperties::getHazeModeString(_hazeMode); diff --git a/libraries/shared/src/SpatiallyNestable.cpp b/libraries/shared/src/SpatiallyNestable.cpp index 2114cbf944..20a5a76b73 100644 --- a/libraries/shared/src/SpatiallyNestable.cpp +++ b/libraries/shared/src/SpatiallyNestable.cpp @@ -19,7 +19,7 @@ #include "SharedLogging.h" const float defaultAACubeSize = 1.0f; -const int maxParentingChain = 30; +const int MAX_PARENTING_CHAIN_SIZE = 30; SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) : _nestableType(nestableType), @@ -28,6 +28,7 @@ SpatiallyNestable::SpatiallyNestable(NestableType nestableType, QUuid id) : // set flags in _transform _transform.setTranslation(glm::vec3(0.0f)); _transform.setRotation(glm::quat()); + _transform.setScale(1.0f); _scaleChanged = usecTimestampNow(); _translationChanged = usecTimestampNow(); _rotationChanged = usecTimestampNow(); @@ -85,6 +86,9 @@ Transform SpatiallyNestable::getParentTransform(bool& success, int depth) const } if (parent) { result = parent->getTransform(_parentJointIndex, success, depth + 1); + if (getScalesWithParent()) { + result.setScale(parent->scaleForChildren()); + } } return result; } @@ -165,7 +169,7 @@ void SpatiallyNestable::setParentJointIndex(quint16 parentJointIndex) { glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, - bool& success) { + bool scalesWithParent, bool& success) { QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { success = false; @@ -189,6 +193,9 @@ glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } } success = true; @@ -199,7 +206,7 @@ glm::vec3 SpatiallyNestable::worldToLocal(const glm::vec3& position, glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, - bool& success) { + bool scalesWithParent, bool& success) { QSharedPointer parentFinder = DependencyManager::get(); if (!parentFinder) { success = false; @@ -223,6 +230,9 @@ glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, if (!success) { return glm::quat(); } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } } success = true; @@ -231,7 +241,7 @@ glm::quat SpatiallyNestable::worldToLocal(const glm::quat& orientation, } glm::vec3 SpatiallyNestable::worldToLocalVelocity(const glm::vec3& velocity, const QUuid& parentID, - int parentJointIndex, bool& success) { + int parentJointIndex, bool scalesWithParent, bool& success) { SpatiallyNestablePointer parent = SpatiallyNestable::findByID(parentID, success); if (!success || !parent) { return velocity; @@ -240,6 +250,9 @@ glm::vec3 SpatiallyNestable::worldToLocalVelocity(const glm::vec3& velocity, con if (!success) { return velocity; } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } glm::vec3 parentVelocity = parent->getWorldVelocity(success); if (!success) { return velocity; @@ -249,7 +262,7 @@ glm::vec3 SpatiallyNestable::worldToLocalVelocity(const glm::vec3& velocity, con } glm::vec3 SpatiallyNestable::worldToLocalAngularVelocity(const glm::vec3& angularVelocity, const QUuid& parentID, - int parentJointIndex, bool& success) { + int parentJointIndex, bool scalesWithParent, bool& success) { SpatiallyNestablePointer parent = SpatiallyNestable::findByID(parentID, success); if (!success || !parent) { return angularVelocity; @@ -258,12 +271,50 @@ glm::vec3 SpatiallyNestable::worldToLocalAngularVelocity(const glm::vec3& angula if (!success) { return angularVelocity; } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } return glm::inverse(parentTransform.getRotation()) * angularVelocity; } + +glm::vec3 SpatiallyNestable::worldToLocalDimensions(const glm::vec3& dimensions, + const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success) { + if (!scalesWithParent) { + success = true; + return dimensions; + } + + QSharedPointer parentFinder = DependencyManager::get(); + if (!parentFinder) { + success = false; + return dimensions; + } + + Transform parentTransform; + auto parentWP = parentFinder->find(parentID, success); + if (!success) { + return dimensions; + } + + auto parent = parentWP.lock(); + if (!parentID.isNull() && !parent) { + success = false; + return dimensions; + } + + success = true; + if (parent) { + return dimensions / parent->scaleForChildren(); + } + return dimensions; +} + glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success) { Transform result; QSharedPointer parentFinder = DependencyManager::get(); @@ -289,6 +340,9 @@ glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, if (!success) { return glm::vec3(0.0f); } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } } success = true; @@ -300,6 +354,7 @@ glm::vec3 SpatiallyNestable::localToWorld(const glm::vec3& position, glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success) { Transform result; QSharedPointer parentFinder = DependencyManager::get(); @@ -325,7 +380,9 @@ glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, if (!success) { return glm::quat(); } - parentTransform.setScale(1.0f); + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } } success = true; @@ -336,7 +393,7 @@ glm::quat SpatiallyNestable::localToWorld(const glm::quat& orientation, } glm::vec3 SpatiallyNestable::localToWorldVelocity(const glm::vec3& velocity, const QUuid& parentID, - int parentJointIndex, bool& success) { + int parentJointIndex, bool scalesWithParent, bool& success) { SpatiallyNestablePointer parent = SpatiallyNestable::findByID(parentID, success); if (!success || !parent) { return velocity; @@ -345,6 +402,9 @@ glm::vec3 SpatiallyNestable::localToWorldVelocity(const glm::vec3& velocity, con if (!success) { return velocity; } + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } glm::vec3 parentVelocity = parent->getWorldVelocity(success); if (!success) { return velocity; @@ -354,7 +414,7 @@ glm::vec3 SpatiallyNestable::localToWorldVelocity(const glm::vec3& velocity, con } glm::vec3 SpatiallyNestable::localToWorldAngularVelocity(const glm::vec3& angularVelocity, const QUuid& parentID, - int parentJointIndex, bool& success) { + int parentJointIndex, bool scalesWithParent, bool& success) { SpatiallyNestablePointer parent = SpatiallyNestable::findByID(parentID, success); if (!success || !parent) { return angularVelocity; @@ -363,10 +423,47 @@ glm::vec3 SpatiallyNestable::localToWorldAngularVelocity(const glm::vec3& angula if (!success) { return angularVelocity; } - + if (scalesWithParent) { + parentTransform.setScale(parent->scaleForChildren()); + } return parentTransform.getRotation() * angularVelocity; } + +glm::vec3 SpatiallyNestable::localToWorldDimensions(const glm::vec3& dimensions, + const QUuid& parentID, int parentJointIndex, bool scalesWithParent, + bool& success) { + if (!scalesWithParent) { + success = true; + return dimensions; + } + + Transform result; + QSharedPointer parentFinder = DependencyManager::get(); + if (!parentFinder) { + success = false; + return dimensions; + } + + Transform parentTransform; + auto parentWP = parentFinder->find(parentID, success); + if (!success) { + return dimensions; + } + + auto parent = parentWP.lock(); + if (!parentID.isNull() && !parent) { + success = false; + return dimensions; + } + + success = true; + if (parent) { + return dimensions * parent->scaleForChildren(); + } + return dimensions; +} + glm::vec3 SpatiallyNestable::getWorldPosition(bool& success) const { return getTransform(success).getTranslation(); } @@ -615,10 +712,10 @@ const Transform SpatiallyNestable::getTransform(int jointIndex, bool& success, i // cause this object's parent to query its parent, etc) and multiplies this object's local transform onto it. Transform jointInWorldFrame; - if (depth > maxParentingChain) { + if (depth > MAX_PARENTING_CHAIN_SIZE) { success = false; // someone created a loop. break it... - qCDebug(shared) << "Parenting loop detected."; + qCDebug(shared) << "Parenting loop detected: " << getID(); SpatiallyNestablePointer _this = getThisPointer(); _this->setParentID(QUuid()); bool setPositionSuccess; diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 9cd38f9ce9..2a315e9230 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -50,19 +50,28 @@ public: virtual quint16 getParentJointIndex() const { return _parentJointIndex; } virtual void setParentJointIndex(quint16 parentJointIndex); - static glm::vec3 worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, bool& success); - static glm::quat worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success); + static glm::vec3 worldToLocal(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); + static glm::quat worldToLocal(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); static glm::vec3 worldToLocalVelocity(const glm::vec3& velocity, const QUuid& parentID, - int parentJointIndex, bool& success); + int parentJointIndex, bool scalesWithParent, bool& success); static glm::vec3 worldToLocalAngularVelocity(const glm::vec3& angularVelocity, const QUuid& parentID, - int parentJointIndex, bool& success); + int parentJointIndex, bool scalesWithParent, bool& success); + static glm::vec3 worldToLocalDimensions(const glm::vec3& dimensions, const QUuid& parentID, + int parentJointIndex, bool scalesWithParent, bool& success); - static glm::vec3 localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, bool& success); - static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, bool& success); + static glm::vec3 localToWorld(const glm::vec3& position, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); + static glm::quat localToWorld(const glm::quat& orientation, const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); static glm::vec3 localToWorldVelocity(const glm::vec3& velocity, - const QUuid& parentID, int parentJointIndex, bool& success); + const QUuid& parentID, int parentJointIndex, bool scalesWithParent, bool& success); static glm::vec3 localToWorldAngularVelocity(const glm::vec3& angularVelocity, - const QUuid& parentID, int parentJointIndex, bool& success); + const QUuid& parentID, int parentJointIndex, + bool scalesWithParent, bool& success); + static glm::vec3 localToWorldDimensions(const glm::vec3& dimensions, const QUuid& parentID, + int parentJointIndex, bool scalesWithParent, bool& success); static QString nestableTypeToString(NestableType nestableType); @@ -140,6 +149,9 @@ public: virtual glm::vec3 getLocalSNScale() const; virtual void setLocalSNScale(const glm::vec3& scale); + virtual bool getScalesWithParent() const { return false; } + virtual glm::vec3 scaleForChildren() const { return glm::vec3(1.0f); } + QList getChildren() const; bool hasChildren() const; From 7bb44f413948cc4d45c5c3fedd590c317a01772d Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Mon, 4 Dec 2017 16:46:58 -0800 Subject: [PATCH 02/49] Created poly scripting interface template --- interface/src/Application.cpp | 3 ++ .../GooglePolyScriptingInterface.cpp | 21 ++++++++++++++ .../scripting/GooglePolyScriptingInterface.h | 28 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 interface/src/scripting/GooglePolyScriptingInterface.cpp create mode 100644 interface/src/scripting/GooglePolyScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d7fcbf6467..38ec8ea05b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -191,6 +191,7 @@ #include #include #include +#include #include #include @@ -698,6 +699,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(nullptr, qApp->getOcteeSceneStats()); DependencyManager::set(); DependencyManager::set(); @@ -5900,6 +5902,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LimitlessSpeechRecognition", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("GooglePoly", DependencyManager::get().data()); if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine.data(), steamClient.get())); diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp new file mode 100644 index 0000000000..bad9b39972 --- /dev/null +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -0,0 +1,21 @@ +// +// GooglePolyScriptingInterface.cpp +// interface/src/scripting +// +// Created by Elisa Lupin-Jimenez on 12/3/2017. +// Copyright 2017 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 "GooglePolyScriptingInterface.h" +#include "ScriptEngineLogging.h" + +GooglePolyScriptingInterface::GooglePolyScriptingInterface() { + +} + +void GooglePolyScriptingInterface::testPrint() { + qCDebug(scriptengine) << "Google Poly interface exists"; +} \ No newline at end of file diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h new file mode 100644 index 0000000000..04afef8a58 --- /dev/null +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -0,0 +1,28 @@ +// +// GooglePolyScriptingInterface.h +// interface/src/scripting +// +// Created by Elisa Lupin-Jimenez on 12/3/2017. +// Copyright 2017 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_GooglePolyScriptingInterface_h +#define hifi_GooglePolyScriptingInterface_h + +#include +#include + +class GooglePolyScriptingInterface : public QObject, public Dependency { + Q_OBJECT +public: + GooglePolyScriptingInterface(); + +public slots: + void testPrint(); + +}; + +#endif // hifi_GooglePolyScriptingInterface_h \ No newline at end of file From d6e1a9defe9e411acb7780c07b7d85ceb8c81ae8 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Mon, 4 Dec 2017 16:46:58 -0800 Subject: [PATCH 03/49] Created poly scripting interface template --- interface/src/Application.cpp | 3 ++ .../GooglePolyScriptingInterface.cpp | 21 ++++++++++++++ .../scripting/GooglePolyScriptingInterface.h | 28 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 interface/src/scripting/GooglePolyScriptingInterface.cpp create mode 100644 interface/src/scripting/GooglePolyScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d7fcbf6467..38ec8ea05b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -191,6 +191,7 @@ #include #include #include +#include #include #include @@ -698,6 +699,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(nullptr, qApp->getOcteeSceneStats()); DependencyManager::set(); DependencyManager::set(); @@ -5900,6 +5902,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LimitlessSpeechRecognition", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("GooglePoly", DependencyManager::get().data()); if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine.data(), steamClient.get())); diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp new file mode 100644 index 0000000000..bad9b39972 --- /dev/null +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -0,0 +1,21 @@ +// +// GooglePolyScriptingInterface.cpp +// interface/src/scripting +// +// Created by Elisa Lupin-Jimenez on 12/3/2017. +// Copyright 2017 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 "GooglePolyScriptingInterface.h" +#include "ScriptEngineLogging.h" + +GooglePolyScriptingInterface::GooglePolyScriptingInterface() { + +} + +void GooglePolyScriptingInterface::testPrint() { + qCDebug(scriptengine) << "Google Poly interface exists"; +} \ No newline at end of file diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h new file mode 100644 index 0000000000..04afef8a58 --- /dev/null +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -0,0 +1,28 @@ +// +// GooglePolyScriptingInterface.h +// interface/src/scripting +// +// Created by Elisa Lupin-Jimenez on 12/3/2017. +// Copyright 2017 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_GooglePolyScriptingInterface_h +#define hifi_GooglePolyScriptingInterface_h + +#include +#include + +class GooglePolyScriptingInterface : public QObject, public Dependency { + Q_OBJECT +public: + GooglePolyScriptingInterface(); + +public slots: + void testPrint(); + +}; + +#endif // hifi_GooglePolyScriptingInterface_h \ No newline at end of file From 26cb275b897caea78565ee2921f0c3f1d8487652 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 5 Dec 2017 11:11:56 -0800 Subject: [PATCH 04/49] adjust wearables with saved offsets after WEAR IT --- scripts/system/marketplaces/marketplaces.js | 57 ++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index 646e5452df..8cd56211d4 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -8,7 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Tablet, Script, HMD, UserActivityLogger, Entities */ +/* global Tablet, Script, HMD, UserActivityLogger, Entities, Account, Wallet, ContextOverlay, Settings, Camera, Vec3, + Quat, MyAvatar, Clipboard, Menu */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function () { // BEGIN LOCAL_SCOPE @@ -188,6 +189,41 @@ function rezEntity(itemHref, isWearable) { var success = Clipboard.importEntities(itemHref); + var wearableLocalPosition = null; + var wearableLocalRotation = null; + var wearableLocalDimensions = null; + var wearableDimensions = null; + + if (isWearable) { + var wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.transforms"); + if (!wearableTransforms) { + // TODO delete this clause + wearableTransforms = Settings.getValue("io.highfidelity.avatarStore.checkOut.tranforms"); + } + var certPos = itemHref.search("certificate_id="); // TODO how do I parse a URL from here? + if (certPos >= 0) { + certPos += 15; // length of "certificate_id=" + var certURLEncoded = itemHref.substring(certPos); + var certB64Encoded = decodeURIComponent(certURLEncoded); + for (var key in wearableTransforms) { + if (wearableTransforms.hasOwnProperty(key)) { + var certificateTransforms = wearableTransforms[key].certificateTransforms; + if (certificateTransforms) { + for (var certID in certificateTransforms) { + if (certificateTransforms.hasOwnProperty(certID) && + certID == certB64Encoded) { + var certificateTransform = certificateTransforms[certID]; + wearableLocalPosition = certificateTransform.localPosition; + wearableLocalRotation = certificateTransform.localRotation; + wearableLocalDimensions = certificateTransform.localDimensions; + wearableDimensions = certificateTransform.dimensions; + } + } + } + } + } + } + } if (success) { var VERY_LARGE = 10000; @@ -257,6 +293,24 @@ } } + if (isWearable) { + // apply the relative offsets saved during checkout + var offsets = {}; + if (wearableLocalPosition) { + offsets.localPosition = wearableLocalPosition; + } + if (wearableLocalRotation) { + offsets.localRotation = wearableLocalRotation; + } + if (wearableLocalDimensions) { + offsets.localDimensions = wearableLocalDimensions; + } else if (wearableDimensions) { + offsets.dimensions = wearableDimensions; + } + // we currently assume a wearable is a single entity + Entities.editEntity(pastedEntityIDs[0], offsets); + } + if (isActive) { selectionManager.setSelections(pastedEntityIDs); } @@ -399,6 +453,7 @@ referrer: "purchases" }); openWallet(); + break; case 'checkout_walletNotSetUp': wireEventBridge(true); tablet.sendToQml({ From c4e5c53eeef89f91e4a1606a76a63fd4a1445dad Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 5 Dec 2017 11:17:31 -0800 Subject: [PATCH 05/49] jshint cleanups --- scripts/system/marketplaces/marketplaces.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index d35aeebb6b..d0530dc775 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -9,7 +9,7 @@ // /* global Tablet, Script, HMD, UserActivityLogger, Entities, Account, Wallet, ContextOverlay, Settings, Camera, Vec3, - Quat, MyAvatar, Clipboard, Menu */ + Quat, MyAvatar, Clipboard, Menu, Grid, Uuid, GlobalServices, openLoginWindow */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ (function () { // BEGIN LOCAL_SCOPE @@ -338,10 +338,6 @@ // we currently assume a wearable is a single entity Entities.editEntity(pastedEntityIDs[0], offsets); } - - if (isActive) { - selectionManager.setSelections(pastedEntityIDs); - } } else { Window.notifyEditError("Can't import entities: entities would be out of bounds."); } From 3642d6cfdfb72f25df66ce1339c6ec39888ead1a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 5 Dec 2017 11:26:36 -0800 Subject: [PATCH 06/49] fix includes --- scripts/system/marketplaces/marketplaces.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index d0530dc775..c591c088c8 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -14,8 +14,9 @@ (function () { // BEGIN LOCAL_SCOPE - Script.include("../libraries/WebTablet.js"); - Script.include("../libraries/gridTool.js"); + Script.include("/~/system/libraries/accountUtils.js"); + Script.include("/~/system/libraries/WebTablet.js"); + Script.include("/~/system/libraries/gridTool.js"); var METAVERSE_SERVER_URL = Account.metaverseServerURL; var MARKETPLACE_URL = METAVERSE_SERVER_URL + "/marketplace"; From 4ed689672ea2a9b0783b0eb516ac8facb9d2d73b Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 6 Dec 2017 16:07:29 -0800 Subject: [PATCH 07/49] can fetch poly asset list synchronously --- .../GooglePolyScriptingInterface.cpp | 179 +++++++++++++++++- .../scripting/GooglePolyScriptingInterface.h | 12 ++ 2 files changed, 189 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index bad9b39972..99e2d699d0 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -9,13 +9,188 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + #include "GooglePolyScriptingInterface.h" #include "ScriptEngineLogging.h" -GooglePolyScriptingInterface::GooglePolyScriptingInterface() { +QString listPolyUrl = "https://poly.googleapis.com/v1/assets?"; +QString getPolyUrl = "https://poly.googleapis.com/v1/assets/model?"; +GooglePolyScriptingInterface::GooglePolyScriptingInterface() { + // nothing to be implemented } void GooglePolyScriptingInterface::testPrint() { qCDebug(scriptengine) << "Google Poly interface exists"; -} \ No newline at end of file +} + +void GooglePolyScriptingInterface::setAPIKey(QString key) { + authCode = key; +} + +void GooglePolyScriptingInterface::getAssetList() { + authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; + //authCode = "broke"; + QUrl url(listPolyUrl + "key=" + authCode); + QByteArray jsonString = getHTTPRequest(url); + qCDebug(scriptengine) << "the list: " << jsonString; + QJsonObject json = makeJSONObject(&jsonString, true); + +} + +// FIXME: synchronous = not good code +QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { + QNetworkAccessManager manager; + QNetworkReply *response = manager.get(QNetworkRequest(url)); + QEventLoop event; + connect(response, SIGNAL(finished()), &event, SLOT(quit())); + event.exec(); + + return response->readAll(); + +} + +QJsonObject GooglePolyScriptingInterface::makeJSONObject(QByteArray* response, bool isList) { + //QString firstItem = QString::fromUtf8(response->readAll()); + QJsonDocument doc = QJsonDocument::fromJson(*response); + qCDebug(scriptengine) << "json doc is empty: " << doc.isEmpty(); + QJsonObject obj = doc.object(); + qCDebug(scriptengine) << "json obj: " << obj; + qCDebug(scriptengine) << "json list: " << obj.keys(); + if (obj.keys().first() == "error") { + qCDebug(scriptengine) << "Invalid API key"; + return obj; + } + qCDebug(scriptengine) << "total size: " << obj.value("totalSize").toString(); + qCDebug(scriptengine) << "in assets: " << obj.value("assets"); + return obj; +} + +/*void GooglePolyScriptingInterface::getAssetList() { + authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; + QUrl url(listPolyUrl + "key=" + authCode); + QByteArray reply = getHTTPRequest(url); + qCDebug(scriptengine) << "the list: " << test; +} + +// FIXME: synchronous = not good code +QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { + QNetworkAccessManager manager; + QNetworkReply *response = manager.get(QNetworkRequest(url)); + QEventLoop event; + connect(response, SIGNAL(finished()), &event, SLOT(quit())); + event.exec(); + return response->readAll(); +} + +*/ + +/* useful for constructing the url? + + QUrl url("http://gdata.youtube.com/feeds/api/standardfeeds/"); + QString method = "most_popular"; + url.setPath(QString("%1%2").arg(url.path()).arg(method)); + + QMap params; + params["alt"] = "json"; + params["v"] = "2"; + + foreach(QString param, params.keys()) { + url.addQueryItem(param, params[param].toString()); + } + +*/ + +/* NONE OF THESE HTTP GET METHODS WORK D: +https://stackoverflow.com/questions/28267477/getting-a-page-content-with-qt kinda used rn + +this correctly returns the asset list but is apparently synchronous and not a good way to do it +https://stackoverflow.com/questions/24965972/qt-getting-source-html-code-of-a-web-page-hosted-on-the-internet +void GooglePolyScriptingInterface::getAssetList() { + authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; + QUrl url(listPolyUrl + "key=" + authCode); + QNetworkAccessManager manager; + QNetworkReply *response = manager.get(QNetworkRequest(url)); + QEventLoop event; + connect(response, SIGNAL(finished()), &event, SLOT(quit())); + event.exec(); + QString firstItem = response->readAll(); + //QJsonArray arr; + //QJsonObject jsonObject = QJsonDocument::fromJson(response->readAll()).object(); + //QString firstItem = jsonObject["assets"].toString(); + qCDebug(scriptengine) << "first item: " << firstItem; + //qCDebug(scriptengine) << "api key: " << authCode; + //return arr; +} + +this didn't work either https://stackoverflow.com/a/24966317 + QScopedPointer manager(new QNetworkAccessManager); + QNetworkReply* response = manager->get(QNetworkRequest(url)); + QObject::connect(manager, &QNetworkAccessManager::finished, [manager, response] { + response->deleteLater(); + manager->deleteLater(); + if (response->error() != QNetworkReply::NoError) return; + QString contentType = + response->header(QNetworkRequest::ContentTypeHeader).toString(); + if (!contentType.contains("charset=utf-8")) { + qWarning() << "Content charsets other than utf-8 are not implemented yet."; + return; + } + QString html = QString::fromUtf8(response->readAll()); + // do something with the data + }) && manager.take(); + + +or this :( https://stackoverflow.com/questions/39518749/make-get-request-to-web-service-get-json-response-and-update-gui-in-qt + qCDebug(scriptengine) << "gonna get assets with " << url; + QNetworkAccessManager manager; + QNetworkReply* reply = manager.get(QNetworkRequest(url)); + QObject::connect(&manager, &QNetworkAccessManager::finished, + [reply]{ + qCDebug(scriptengine) << "boo radley"; + if (reply->error() != QNetworkReply::NoError) { + qCDebug(scriptengine) << "Poly API failed to respond"; + //manager.clearAccessCache(); + } else { + QJsonObject jsonObject = QJsonDocument::fromJson(reply->readAll()).object(); + QString firstItem = jsonObject["assets"].toString(); + qCDebug(scriptengine) << "first item: " << firstItem; + } + reply->deleteLater(); + }); + +or this :(( http://blog.mathieu-leplatre.info/access-a-json-webservice-with-qt-c.html + //QJsonArray arr; + //QJsonObject jsonObject = QJsonDocument::fromJson(response->readAll()).object(); + //QString firstItem = jsonObject["assets"].toString(); + qCDebug(scriptengine) << "first item: " << firstItem; + //qCDebug(scriptengine) << "api key: " << authCode; + //return arr; + QNetworkAccessManager manager; + QNetworkReply* response = manager.get(QNetworkRequest(url)); + QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onResult(QNetworkReply*))); + + return ""; + } + + void GooglePolyScriptingInterface::onResult(QNetworkReply* reply) { + if (reply->error() != QNetworkReply::NoError) { + qCDebug(scriptengine) << "Poly API failed to respond"; + return; + } + QString firstItem = reply->readAll(); + + qCDebug(scriptengine) << "first item: " << firstItem; + } + +*/ \ No newline at end of file diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 04afef8a58..37b7395914 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -22,6 +22,18 @@ public: public slots: void testPrint(); + void setAPIKey(QString key); + + //QJsonArray GooglePolyScriptingInterface::getAssetList(); + void getAssetList(); + +private: + QByteArray getHTTPRequest(QUrl url); + QJsonObject makeJSONObject(QByteArray* response, bool isList); + //void onResult(QNetworkReply* reply); + + QString authCode; + }; From 1d5875c45b92f6683d25b902f55dab93ef5ceff1 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 6 Dec 2017 17:40:39 -0800 Subject: [PATCH 08/49] removed key --- .../scripting/GooglePolyScriptingInterface.cpp | 15 ++++++++++----- .../src/scripting/GooglePolyScriptingInterface.h | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 20e83fd14e..78cf6e1fc7 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -39,12 +39,11 @@ void GooglePolyScriptingInterface::setAPIKey(QString key) { } void GooglePolyScriptingInterface::getAssetList() { - authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; //authCode = "broke"; QUrl url(listPolyUrl + "key=" + authCode); QByteArray jsonString = getHTTPRequest(url); qCDebug(scriptengine) << "the list: " << jsonString; - QJsonObject json = makeJSONObject(&jsonString, true); + QJsonObject json = makeJSON(&jsonString, true).toJsonObject; } @@ -60,7 +59,8 @@ QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { } -QJsonObject GooglePolyScriptingInterface::makeJSONObject(QByteArray* response, bool isList) { +// since the list is a QJsonArray and a single model is a QJsonObject +QVariant GooglePolyScriptingInterface::makeJSON(QByteArray* response, bool isList) { //QString firstItem = QString::fromUtf8(response->readAll()); QJsonDocument doc = QJsonDocument::fromJson(*response); qCDebug(scriptengine) << "json doc is empty: " << doc.isEmpty(); @@ -71,8 +71,13 @@ QJsonObject GooglePolyScriptingInterface::makeJSONObject(QByteArray* response, b qCDebug(scriptengine) << "Invalid API key"; return obj; } - qCDebug(scriptengine) << "total size: " << obj.value("totalSize").toString(); - qCDebug(scriptengine) << "in assets: " << obj.value("assets"); + qCDebug(scriptengine) << "total size: " << obj.value("totalSize"); + qCDebug(scriptengine) << "the assets: " << obj.value("assets"); + QJsonArray arr = obj.value("assets").toArray(); + qCDebug(scriptengine) << "in array: " << arr; + QJsonObject first = arr.takeAt(0).toObject(); + qCDebug(scriptengine) << "first asset: " << first; + qCDebug(scriptengine) << "first asset description: " << first.value("description"); return obj; } diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 37b7395914..707eabc0af 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -29,7 +29,7 @@ public slots: private: QByteArray getHTTPRequest(QUrl url); - QJsonObject makeJSONObject(QByteArray* response, bool isList); + QVariant makeJSON(QByteArray* response, bool isList); //void onResult(QNetworkReply* reply); QString authCode; From 4659d22021b9b201e505673a2847c176b668c971 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 7 Dec 2017 21:32:18 -0800 Subject: [PATCH 09/49] work around a crash when closing CREATE --- scripts/system/libraries/gridTool.js | 4 +++- scripts/system/marketplaces/marketplaces.js | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/system/libraries/gridTool.js b/scripts/system/libraries/gridTool.js index 2c417a9dde..19d4417a12 100644 --- a/scripts/system/libraries/gridTool.js +++ b/scripts/system/libraries/gridTool.js @@ -242,7 +242,9 @@ GridTool = function(opts) { horizontalGrid.addListener(function(data) { webView.emitScriptEvent(JSON.stringify(data)); - selectionDisplay.updateHandles(); + if (selectionDisplay) { + selectionDisplay.updateHandles(); + } }); webView.webEventReceived.connect(function(data) { diff --git a/scripts/system/marketplaces/marketplaces.js b/scripts/system/marketplaces/marketplaces.js index c9c439e57d..19b45be015 100644 --- a/scripts/system/marketplaces/marketplaces.js +++ b/scripts/system/marketplaces/marketplaces.js @@ -12,6 +12,8 @@ Quat, MyAvatar, Clipboard, Menu, Grid, Uuid, GlobalServices, openLoginWindow */ /* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ +var selectionDisplay = null; // for gridTool.js to ignore + (function () { // BEGIN LOCAL_SCOPE Script.include("/~/system/libraries/accountUtils.js"); From dc999401d598a4e04ca826f9ccf257be88463701 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Mon, 4 Dec 2017 16:46:58 -0800 Subject: [PATCH 10/49] Created poly scripting interface template --- interface/src/Application.cpp | 3 ++ .../GooglePolyScriptingInterface.cpp | 21 ++++++++++++++ .../scripting/GooglePolyScriptingInterface.h | 28 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 interface/src/scripting/GooglePolyScriptingInterface.cpp create mode 100644 interface/src/scripting/GooglePolyScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0176acf108..a5ba4f86bd 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -191,6 +191,7 @@ #include #include #include +#include #include #include @@ -698,6 +699,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); + DependencyManager::set(); DependencyManager::set(nullptr, qApp->getOcteeSceneStats()); DependencyManager::set(); DependencyManager::set(); @@ -5900,6 +5902,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe scriptEngine->registerGlobalObject("Users", DependencyManager::get().data()); scriptEngine->registerGlobalObject("LimitlessSpeechRecognition", DependencyManager::get().data()); + scriptEngine->registerGlobalObject("GooglePoly", DependencyManager::get().data()); if (auto steamClient = PluginManager::getInstance()->getSteamClientPlugin()) { scriptEngine->registerGlobalObject("Steam", new SteamScriptingInterface(scriptEngine.data(), steamClient.get())); diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp new file mode 100644 index 0000000000..bad9b39972 --- /dev/null +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -0,0 +1,21 @@ +// +// GooglePolyScriptingInterface.cpp +// interface/src/scripting +// +// Created by Elisa Lupin-Jimenez on 12/3/2017. +// Copyright 2017 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 "GooglePolyScriptingInterface.h" +#include "ScriptEngineLogging.h" + +GooglePolyScriptingInterface::GooglePolyScriptingInterface() { + +} + +void GooglePolyScriptingInterface::testPrint() { + qCDebug(scriptengine) << "Google Poly interface exists"; +} \ No newline at end of file diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h new file mode 100644 index 0000000000..04afef8a58 --- /dev/null +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -0,0 +1,28 @@ +// +// GooglePolyScriptingInterface.h +// interface/src/scripting +// +// Created by Elisa Lupin-Jimenez on 12/3/2017. +// Copyright 2017 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_GooglePolyScriptingInterface_h +#define hifi_GooglePolyScriptingInterface_h + +#include +#include + +class GooglePolyScriptingInterface : public QObject, public Dependency { + Q_OBJECT +public: + GooglePolyScriptingInterface(); + +public slots: + void testPrint(); + +}; + +#endif // hifi_GooglePolyScriptingInterface_h \ No newline at end of file From 392f290dd62e1ba986af78bb6020dc83710184a0 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 6 Dec 2017 16:07:29 -0800 Subject: [PATCH 11/49] can fetch poly asset list synchronously --- .../GooglePolyScriptingInterface.cpp | 179 +++++++++++++++++- .../scripting/GooglePolyScriptingInterface.h | 12 ++ 2 files changed, 189 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index bad9b39972..99e2d699d0 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -9,13 +9,188 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + #include "GooglePolyScriptingInterface.h" #include "ScriptEngineLogging.h" -GooglePolyScriptingInterface::GooglePolyScriptingInterface() { +QString listPolyUrl = "https://poly.googleapis.com/v1/assets?"; +QString getPolyUrl = "https://poly.googleapis.com/v1/assets/model?"; +GooglePolyScriptingInterface::GooglePolyScriptingInterface() { + // nothing to be implemented } void GooglePolyScriptingInterface::testPrint() { qCDebug(scriptengine) << "Google Poly interface exists"; -} \ No newline at end of file +} + +void GooglePolyScriptingInterface::setAPIKey(QString key) { + authCode = key; +} + +void GooglePolyScriptingInterface::getAssetList() { + authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; + //authCode = "broke"; + QUrl url(listPolyUrl + "key=" + authCode); + QByteArray jsonString = getHTTPRequest(url); + qCDebug(scriptengine) << "the list: " << jsonString; + QJsonObject json = makeJSONObject(&jsonString, true); + +} + +// FIXME: synchronous = not good code +QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { + QNetworkAccessManager manager; + QNetworkReply *response = manager.get(QNetworkRequest(url)); + QEventLoop event; + connect(response, SIGNAL(finished()), &event, SLOT(quit())); + event.exec(); + + return response->readAll(); + +} + +QJsonObject GooglePolyScriptingInterface::makeJSONObject(QByteArray* response, bool isList) { + //QString firstItem = QString::fromUtf8(response->readAll()); + QJsonDocument doc = QJsonDocument::fromJson(*response); + qCDebug(scriptengine) << "json doc is empty: " << doc.isEmpty(); + QJsonObject obj = doc.object(); + qCDebug(scriptengine) << "json obj: " << obj; + qCDebug(scriptengine) << "json list: " << obj.keys(); + if (obj.keys().first() == "error") { + qCDebug(scriptengine) << "Invalid API key"; + return obj; + } + qCDebug(scriptengine) << "total size: " << obj.value("totalSize").toString(); + qCDebug(scriptengine) << "in assets: " << obj.value("assets"); + return obj; +} + +/*void GooglePolyScriptingInterface::getAssetList() { + authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; + QUrl url(listPolyUrl + "key=" + authCode); + QByteArray reply = getHTTPRequest(url); + qCDebug(scriptengine) << "the list: " << test; +} + +// FIXME: synchronous = not good code +QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { + QNetworkAccessManager manager; + QNetworkReply *response = manager.get(QNetworkRequest(url)); + QEventLoop event; + connect(response, SIGNAL(finished()), &event, SLOT(quit())); + event.exec(); + return response->readAll(); +} + +*/ + +/* useful for constructing the url? + + QUrl url("http://gdata.youtube.com/feeds/api/standardfeeds/"); + QString method = "most_popular"; + url.setPath(QString("%1%2").arg(url.path()).arg(method)); + + QMap params; + params["alt"] = "json"; + params["v"] = "2"; + + foreach(QString param, params.keys()) { + url.addQueryItem(param, params[param].toString()); + } + +*/ + +/* NONE OF THESE HTTP GET METHODS WORK D: +https://stackoverflow.com/questions/28267477/getting-a-page-content-with-qt kinda used rn + +this correctly returns the asset list but is apparently synchronous and not a good way to do it +https://stackoverflow.com/questions/24965972/qt-getting-source-html-code-of-a-web-page-hosted-on-the-internet +void GooglePolyScriptingInterface::getAssetList() { + authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; + QUrl url(listPolyUrl + "key=" + authCode); + QNetworkAccessManager manager; + QNetworkReply *response = manager.get(QNetworkRequest(url)); + QEventLoop event; + connect(response, SIGNAL(finished()), &event, SLOT(quit())); + event.exec(); + QString firstItem = response->readAll(); + //QJsonArray arr; + //QJsonObject jsonObject = QJsonDocument::fromJson(response->readAll()).object(); + //QString firstItem = jsonObject["assets"].toString(); + qCDebug(scriptengine) << "first item: " << firstItem; + //qCDebug(scriptengine) << "api key: " << authCode; + //return arr; +} + +this didn't work either https://stackoverflow.com/a/24966317 + QScopedPointer manager(new QNetworkAccessManager); + QNetworkReply* response = manager->get(QNetworkRequest(url)); + QObject::connect(manager, &QNetworkAccessManager::finished, [manager, response] { + response->deleteLater(); + manager->deleteLater(); + if (response->error() != QNetworkReply::NoError) return; + QString contentType = + response->header(QNetworkRequest::ContentTypeHeader).toString(); + if (!contentType.contains("charset=utf-8")) { + qWarning() << "Content charsets other than utf-8 are not implemented yet."; + return; + } + QString html = QString::fromUtf8(response->readAll()); + // do something with the data + }) && manager.take(); + + +or this :( https://stackoverflow.com/questions/39518749/make-get-request-to-web-service-get-json-response-and-update-gui-in-qt + qCDebug(scriptengine) << "gonna get assets with " << url; + QNetworkAccessManager manager; + QNetworkReply* reply = manager.get(QNetworkRequest(url)); + QObject::connect(&manager, &QNetworkAccessManager::finished, + [reply]{ + qCDebug(scriptengine) << "boo radley"; + if (reply->error() != QNetworkReply::NoError) { + qCDebug(scriptengine) << "Poly API failed to respond"; + //manager.clearAccessCache(); + } else { + QJsonObject jsonObject = QJsonDocument::fromJson(reply->readAll()).object(); + QString firstItem = jsonObject["assets"].toString(); + qCDebug(scriptengine) << "first item: " << firstItem; + } + reply->deleteLater(); + }); + +or this :(( http://blog.mathieu-leplatre.info/access-a-json-webservice-with-qt-c.html + //QJsonArray arr; + //QJsonObject jsonObject = QJsonDocument::fromJson(response->readAll()).object(); + //QString firstItem = jsonObject["assets"].toString(); + qCDebug(scriptengine) << "first item: " << firstItem; + //qCDebug(scriptengine) << "api key: " << authCode; + //return arr; + QNetworkAccessManager manager; + QNetworkReply* response = manager.get(QNetworkRequest(url)); + QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onResult(QNetworkReply*))); + + return ""; + } + + void GooglePolyScriptingInterface::onResult(QNetworkReply* reply) { + if (reply->error() != QNetworkReply::NoError) { + qCDebug(scriptengine) << "Poly API failed to respond"; + return; + } + QString firstItem = reply->readAll(); + + qCDebug(scriptengine) << "first item: " << firstItem; + } + +*/ \ No newline at end of file diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 04afef8a58..37b7395914 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -22,6 +22,18 @@ public: public slots: void testPrint(); + void setAPIKey(QString key); + + //QJsonArray GooglePolyScriptingInterface::getAssetList(); + void getAssetList(); + +private: + QByteArray getHTTPRequest(QUrl url); + QJsonObject makeJSONObject(QByteArray* response, bool isList); + //void onResult(QNetworkReply* reply); + + QString authCode; + }; From f7be67b5b2277056097fb97e6ae0060306eb1e8e Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 6 Dec 2017 17:40:39 -0800 Subject: [PATCH 12/49] removed key --- .../scripting/GooglePolyScriptingInterface.cpp | 15 ++++++++++----- .../src/scripting/GooglePolyScriptingInterface.h | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 99e2d699d0..b353b4b3b4 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -39,12 +39,11 @@ void GooglePolyScriptingInterface::setAPIKey(QString key) { } void GooglePolyScriptingInterface::getAssetList() { - authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; //authCode = "broke"; QUrl url(listPolyUrl + "key=" + authCode); QByteArray jsonString = getHTTPRequest(url); qCDebug(scriptengine) << "the list: " << jsonString; - QJsonObject json = makeJSONObject(&jsonString, true); + QJsonObject json = makeJSON(&jsonString, true).toJsonObject; } @@ -60,7 +59,8 @@ QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { } -QJsonObject GooglePolyScriptingInterface::makeJSONObject(QByteArray* response, bool isList) { +// since the list is a QJsonArray and a single model is a QJsonObject +QVariant GooglePolyScriptingInterface::makeJSON(QByteArray* response, bool isList) { //QString firstItem = QString::fromUtf8(response->readAll()); QJsonDocument doc = QJsonDocument::fromJson(*response); qCDebug(scriptengine) << "json doc is empty: " << doc.isEmpty(); @@ -71,8 +71,13 @@ QJsonObject GooglePolyScriptingInterface::makeJSONObject(QByteArray* response, b qCDebug(scriptengine) << "Invalid API key"; return obj; } - qCDebug(scriptengine) << "total size: " << obj.value("totalSize").toString(); - qCDebug(scriptengine) << "in assets: " << obj.value("assets"); + qCDebug(scriptengine) << "total size: " << obj.value("totalSize"); + qCDebug(scriptengine) << "the assets: " << obj.value("assets"); + QJsonArray arr = obj.value("assets").toArray(); + qCDebug(scriptengine) << "in array: " << arr; + QJsonObject first = arr.takeAt(0).toObject(); + qCDebug(scriptengine) << "first asset: " << first; + qCDebug(scriptengine) << "first asset description: " << first.value("description"); return obj; } diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 37b7395914..707eabc0af 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -29,7 +29,7 @@ public slots: private: QByteArray getHTTPRequest(QUrl url); - QJsonObject makeJSONObject(QByteArray* response, bool isList); + QVariant makeJSON(QByteArray* response, bool isList); //void onResult(QNetworkReply* reply); QString authCode; From e49181c3a22505900cedc39a1b5da2b22fbd1cc9 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 13 Dec 2017 17:45:57 -0800 Subject: [PATCH 13/49] added getAssetList() and getFBX() --- .../GooglePolyScriptingInterface.cpp | 113 ++++++++++++++---- .../scripting/GooglePolyScriptingInterface.h | 12 +- 2 files changed, 99 insertions(+), 26 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index b353b4b3b4..8b48f1d115 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -10,6 +10,7 @@ // #include +#include #include #include #include @@ -18,7 +19,9 @@ #include //#include #include +#include #include +#include #include "GooglePolyScriptingInterface.h" #include "ScriptEngineLogging.h" @@ -26,28 +29,81 @@ QString listPolyUrl = "https://poly.googleapis.com/v1/assets?"; QString getPolyUrl = "https://poly.googleapis.com/v1/assets/model?"; +//authCode = "broke"; + +QStringList validFormats = QStringList() << "BLOCKS" << "FBX" << "GLTF" << "GLTF2" << "OBJ" << "TILT" << ""; +QStringList validCategories = QStringList() << "animals" << "architecture" << "art" << "food" << + "nature" << "objects" << "people" << "scenes" << "technology" << "transport" << ""; + GooglePolyScriptingInterface::GooglePolyScriptingInterface() { // nothing to be implemented } -void GooglePolyScriptingInterface::testPrint() { - qCDebug(scriptengine) << "Google Poly interface exists"; +QJsonArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { + QUrl url = formatURLQuery(keyword, category, format); + if (!url.isEmpty()) { + QByteArray jsonString = getHTTPRequest(url); + QJsonArray json = parseJSON(&jsonString, 0).toJsonArray(); + qCDebug(scriptengine) << "first asset name: " << json.at(0).toObject().value("displayName"); + return json; + } else { + qCDebug(scriptengine) << "Invalid filters were specified."; + return QJsonArray(); + } +} + +QString GooglePolyScriptingInterface::getFBX(QString keyword, QString category) { + QUrl url = formatURLQuery(keyword, category, "FBX"); + qCDebug(scriptengine) << "google url: " << url; + if (!url.isEmpty()) { + QByteArray jsonString = getHTTPRequest(url); + qCDebug(scriptengine) << "the list: " << jsonString; + QString modelURL = parseJSON(&jsonString, 1).toString(); + + qCDebug(scriptengine) << "the model url: " << modelURL; + return modelURL; + } else { + qCDebug(scriptengine) << "Invalid filters were specified."; + return ""; + } + +} + +void GooglePolyScriptingInterface::testPrint(QString input) { + qCDebug(scriptengine) << "Google message: " << input; } void GooglePolyScriptingInterface::setAPIKey(QString key) { authCode = key; } -void GooglePolyScriptingInterface::getAssetList() { - //authCode = "broke"; - QUrl url(listPolyUrl + "key=" + authCode); - QByteArray jsonString = getHTTPRequest(url); - qCDebug(scriptengine) << "the list: " << jsonString; - QJsonObject json = makeJSON(&jsonString, true).toJsonObject; - +int GooglePolyScriptingInterface::getRandIntInRange(int length) { + QTime time = QTime::currentTime(); + qsrand((uint)time.msec()); + return qrand() % length; } -// FIXME: synchronous = not good code +QUrl GooglePolyScriptingInterface::formatURLQuery(QString keyword, QString category, QString format) { + QString queries; + if (!validFormats.contains(format) || !validCategories.contains(category)) { + return QUrl(""); + } else { + if (!keyword.isEmpty()) { + keyword.replace(" ", "+"); + queries.append("&keywords=" + keyword); + } + if (!category.isEmpty()) { + queries.append("&category=" + category); + } + if (!format.isEmpty()) { + queries.append("&format=" + format); + } + QString urlString = QString(listPolyUrl + "key=" + authCode + queries); + return QUrl(urlString); + } +} + +// FIXME: synchronous QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { QNetworkAccessManager manager; QNetworkReply *response = manager.get(QNetworkRequest(url)); @@ -56,31 +112,46 @@ QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { event.exec(); return response->readAll(); - + } // since the list is a QJsonArray and a single model is a QJsonObject -QVariant GooglePolyScriptingInterface::makeJSON(QByteArray* response, bool isList) { +QVariant GooglePolyScriptingInterface::parseJSON(QByteArray* response, int fileType) { //QString firstItem = QString::fromUtf8(response->readAll()); QJsonDocument doc = QJsonDocument::fromJson(*response); - qCDebug(scriptengine) << "json doc is empty: " << doc.isEmpty(); QJsonObject obj = doc.object(); qCDebug(scriptengine) << "json obj: " << obj; qCDebug(scriptengine) << "json list: " << obj.keys(); if (obj.keys().first() == "error") { qCDebug(scriptengine) << "Invalid API key"; + return QJsonObject(); + } + qCDebug(scriptengine) << "the assets: " << obj.value("assets"); + if (fileType == 0 || fileType == 1) { + QJsonArray arr = obj.value("assets").toArray(); + qCDebug(scriptengine) << "in array: " << arr; + // return model url + if (fileType == 1) { + int random = getRandIntInRange(arr.size()); + QJsonObject json = arr.at(random).toObject(); + qCDebug(scriptengine) << random << "th object: " << json; + qCDebug(scriptengine) << random << "th asset name: " << json.value("displayName"); + // nested JSONs + return json.value("formats").toArray().at(0).toObject().value("root").toObject().value("url"); + } + // return whole asset list + return arr; + // return specific object + } else { return obj; } - qCDebug(scriptengine) << "total size: " << obj.value("totalSize"); - qCDebug(scriptengine) << "the assets: " << obj.value("assets"); - QJsonArray arr = obj.value("assets").toArray(); - qCDebug(scriptengine) << "in array: " << arr; - QJsonObject first = arr.takeAt(0).toObject(); - qCDebug(scriptengine) << "first asset: " << first; - qCDebug(scriptengine) << "first asset description: " << first.value("description"); - return obj; } + + + + + /*void GooglePolyScriptingInterface::getAssetList() { authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; QUrl url(listPolyUrl + "key=" + authCode); diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 707eabc0af..a90557e593 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -21,18 +21,20 @@ public: GooglePolyScriptingInterface(); public slots: - void testPrint(); + void testPrint(QString input); void setAPIKey(QString key); - //QJsonArray GooglePolyScriptingInterface::getAssetList(); - void getAssetList(); + QJsonArray getAssetList(QString keyword, QString category, QString format); + QString getFBX(QString keyword, QString category); private: + QUrl formatURLQuery(QString keyword, QString category, QString format); QByteArray getHTTPRequest(QUrl url); - QVariant makeJSON(QByteArray* response, bool isList); + QVariant parseJSON(QByteArray* response, int fileType); + int getRandIntInRange(int length); //void onResult(QNetworkReply* reply); - QString authCode; + //QString authCode; }; From e7fad0586713bb13074836532fd8a13562235520 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Mon, 18 Dec 2017 14:20:51 -0800 Subject: [PATCH 14/49] enabled fbx, obj, and blocks model url retrieval --- .../GooglePolyScriptingInterface.cpp | 105 +++++++++--------- .../scripting/GooglePolyScriptingInterface.h | 10 +- 2 files changed, 63 insertions(+), 52 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 7ec6cd343d..8080456e0d 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -17,7 +17,6 @@ #include #include #include -//#include #include #include #include @@ -26,10 +25,8 @@ #include "GooglePolyScriptingInterface.h" #include "ScriptEngineLogging.h" -QString listPolyUrl = "https://poly.googleapis.com/v1/assets?"; -QString getPolyUrl = "https://poly.googleapis.com/v1/assets/model?"; - -QString authCode = "broke"; +const QString listPolyUrl = "https://poly.googleapis.com/v1/assets?"; +const QString getPolyUrl = "https://poly.googleapis.com/v1/assets/model?"; QStringList validFormats = QStringList() << "BLOCKS" << "FBX" << "GLTF" << "GLTF2" << "OBJ" << "TILT" << ""; QStringList validCategories = QStringList() << "animals" << "architecture" << "art" << "food" << @@ -42,8 +39,7 @@ GooglePolyScriptingInterface::GooglePolyScriptingInterface() { QJsonArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { QUrl url = formatURLQuery(keyword, category, format); if (!url.isEmpty()) { - QByteArray jsonString = getHTTPRequest(url); - QJsonArray json = parseJSON(&jsonString, 0).toJsonArray(); + QJsonArray json = parseJSON(url, 0).toJsonArray(); qCDebug(scriptengine) << "first asset name: " << json.at(0).toObject().value("displayName"); return json; } else { @@ -54,19 +50,40 @@ QJsonArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString c QString GooglePolyScriptingInterface::getFBX(QString keyword, QString category) { QUrl url = formatURLQuery(keyword, category, "FBX"); - qCDebug(scriptengine) << "google url: " << url; - if (!url.isEmpty()) { - QByteArray jsonString = getHTTPRequest(url); - qCDebug(scriptengine) << "the list: " << jsonString; - QString modelURL = parseJSON(&jsonString, 1).toString(); - - qCDebug(scriptengine) << "the model url: " << modelURL; - return modelURL; - } else { - qCDebug(scriptengine) << "Invalid filters were specified."; - return ""; - } + return getModelURL(url); +} +QString GooglePolyScriptingInterface::getOBJ(QString keyword, QString category) { + QUrl url = formatURLQuery(keyword, category, "OBJ"); + return getModelURL(url); +} + +QString GooglePolyScriptingInterface::getBlocks(QString keyword, QString category) { + QUrl url = formatURLQuery(keyword, category, "BLOCKS"); + qCDebug(scriptengine) << "Google url request: " << url; + return getModelURL(url); +} + +/* +// This method will not work until we support Tilt models +QString GooglePolyScriptingInterface::getTilt(QString keyword, QString category) { + QUrl url = formatURLQuery(keyword, category, "TILT"); + return getModelURL(url); +} +*/ + +// can provide asset name or full URL to model +QString GooglePolyScriptingInterface::getModelInfo(QString name) { + if (name.contains("poly.googleapis")) { + QStringList list = name.split("/"); + name = list[4]; + } + QString urlString = QString(getPolyUrl); + urlString = urlString.replace("model", name) + "key=" + authCode; + qCDebug(scriptengine) << "google get url: " << urlString; + QUrl url(urlString); + QByteArray json = parseJSON(url, 2).toByteArray(); + return json; } void GooglePolyScriptingInterface::testPrint(QString input) { @@ -103,6 +120,16 @@ QUrl GooglePolyScriptingInterface::formatURLQuery(QString keyword, QString categ } } +QString GooglePolyScriptingInterface::getModelURL(QUrl url) { + qCDebug(scriptengine) << "Google url request: " << url; + if (!url.isEmpty()) { + return parseJSON(url, 1).toString(); + } else { + qCDebug(scriptengine) << "Invalid filters were specified."; + return ""; + } +} + // FIXME: synchronous QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { QNetworkAccessManager manager; @@ -115,26 +142,23 @@ QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { } // since the list is a QJsonArray and a single model is a QJsonObject -QVariant GooglePolyScriptingInterface::parseJSON(QByteArray* response, int fileType) { +QVariant GooglePolyScriptingInterface::parseJSON(QUrl url, int fileType) { //QString firstItem = QString::fromUtf8(response->readAll()); - QJsonDocument doc = QJsonDocument::fromJson(*response); + QByteArray jsonString = getHTTPRequest(url); + QJsonDocument doc = QJsonDocument::fromJson(jsonString); QJsonObject obj = doc.object(); - qCDebug(scriptengine) << "json obj: " << obj; - qCDebug(scriptengine) << "json list: " << obj.keys(); if (obj.keys().first() == "error") { - qCDebug(scriptengine) << "Invalid API key"; + QString error = obj.value("error").toObject().value("message").toString(); + qCDebug(scriptengine) << error; return QJsonObject(); } qCDebug(scriptengine) << "the assets: " << obj.value("assets"); if (fileType == 0 || fileType == 1) { QJsonArray arr = obj.value("assets").toArray(); - qCDebug(scriptengine) << "in array: " << arr; // return model url if (fileType == 1) { int random = getRandIntInRange(arr.size()); QJsonObject json = arr.at(random).toObject(); - qCDebug(scriptengine) << random << "th object: " << json; - qCDebug(scriptengine) << random << "th asset name: " << json.value("displayName"); // nested JSONs return json.value("formats").toArray().at(0).toObject().value("root").toObject().value("url"); } @@ -142,17 +166,14 @@ QVariant GooglePolyScriptingInterface::parseJSON(QByteArray* response, int fileT return arr; // return specific object } else { - return obj; + //return obj; + //return doc.toJson(); + return jsonString; } } -/*void GooglePolyScriptingInterface::getAssetList() { - authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; - QUrl url(listPolyUrl + "key=" + authCode); - QByteArray reply = getHTTPRequest(url); - qCDebug(scriptengine) << "the list: " << test; -} +/* // FIXME: synchronous = not good code QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { @@ -164,23 +185,7 @@ QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { return response->readAll(); } -*/ -/* useful for constructing the url? - - QUrl url("http://gdata.youtube.com/feeds/api/standardfeeds/"); - QString method = "most_popular"; - url.setPath(QString("%1%2").arg(url.path()).arg(method)); - - QMap params; - params["alt"] = "json"; - params["v"] = "2"; - - foreach(QString param, params.keys()) { - url.addQueryItem(param, params[param].toString()); - } - -*/ /* NONE OF THESE HTTP GET METHODS WORK D: https://stackoverflow.com/questions/28267477/getting-a-page-content-with-qt kinda used rn diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 1ae7554a9d..acbc27b90c 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -17,6 +17,7 @@ class GooglePolyScriptingInterface : public QObject, public Dependency { Q_OBJECT + public: GooglePolyScriptingInterface(); @@ -26,15 +27,20 @@ public slots: QJsonArray getAssetList(QString keyword, QString category, QString format); QString getFBX(QString keyword, QString category); + QString getOBJ(QString keyword, QString category); + QString getBlocks(QString keyword, QString category); + //QString getTilt(QString keyword, QString category); + QString getModelInfo(QString name); private: QUrl formatURLQuery(QString keyword, QString category, QString format); + QString getModelURL(QUrl url); QByteArray getHTTPRequest(QUrl url); - QVariant parseJSON(QByteArray* response, int fileType); + QVariant parseJSON(QUrl url, int fileType); int getRandIntInRange(int length); //void onResult(QNetworkReply* reply); - //QString authCode; + QString authCode; }; From 1ee8445f433c77d7310bc7cad0e873c79e804318 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Mon, 18 Dec 2017 17:47:21 -0800 Subject: [PATCH 15/49] added gltf import feature, getAssetList() not working --- .../GooglePolyScriptingInterface.cpp | 60 +++++++++++++------ .../scripting/GooglePolyScriptingInterface.h | 5 +- 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 8080456e0d..42c3b825ba 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -36,17 +36,39 @@ GooglePolyScriptingInterface::GooglePolyScriptingInterface() { // nothing to be implemented } -QJsonArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { +void GooglePolyScriptingInterface::setAPIKey(QString key) { + authCode = key; +} + +QByteArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { QUrl url = formatURLQuery(keyword, category, format); if (!url.isEmpty()) { + //QJsonArray json = parseJSON(url, 0).toJsonArray(); + //qCDebug(scriptengine) << "first asset name: " << json.at(0).toObject().value("displayName"); + QByteArray json = parseJSON(url, 0).toJsonDocument().toJson(); + qCDebug(scriptengine) << "asset list as string is: " << json; + return json; + } else { + qCDebug(scriptengine) << "Invalid filters were specified."; + //return QJsonArray(); + return ""; + } +} + +/*QJsonArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { + QUrl url = formatURLQuery(keyword, category, format); + if (!url.isEmpty()) { + //QJsonArray json = parseJSON(url, 0).toJsonArray(); + //qCDebug(scriptengine) << "first asset name: " << json.at(0).toObject().value("displayName"); QJsonArray json = parseJSON(url, 0).toJsonArray(); - qCDebug(scriptengine) << "first asset name: " << json.at(0).toObject().value("displayName"); + qCDebug(scriptengine) << "asset list as array is: " << json; return json; } else { qCDebug(scriptengine) << "Invalid filters were specified."; return QJsonArray(); + //return ""; } -} +}*/ QString GooglePolyScriptingInterface::getFBX(QString keyword, QString category) { QUrl url = formatURLQuery(keyword, category, "FBX"); @@ -60,7 +82,16 @@ QString GooglePolyScriptingInterface::getOBJ(QString keyword, QString category) QString GooglePolyScriptingInterface::getBlocks(QString keyword, QString category) { QUrl url = formatURLQuery(keyword, category, "BLOCKS"); - qCDebug(scriptengine) << "Google url request: " << url; + return getModelURL(url); +} + +QString GooglePolyScriptingInterface::getGLTF(QString keyword, QString category) { + QUrl url = formatURLQuery(keyword, category, "GLTF"); + return getModelURL(url); +} + +QString GooglePolyScriptingInterface::getGLTF2(QString keyword, QString category) { + QUrl url = formatURLQuery(keyword, category, "GLTF2"); return getModelURL(url); } @@ -74,15 +105,15 @@ QString GooglePolyScriptingInterface::getTilt(QString keyword, QString category) // can provide asset name or full URL to model QString GooglePolyScriptingInterface::getModelInfo(QString name) { - if (name.contains("poly.googleapis")) { + if (name.contains("poly.googleapis") || name.contains("poly.google.com")) { QStringList list = name.split("/"); name = list[4]; } QString urlString = QString(getPolyUrl); urlString = urlString.replace("model", name) + "key=" + authCode; - qCDebug(scriptengine) << "google get url: " << urlString; + qCDebug(scriptengine) << "Google URL request: " << urlString; QUrl url(urlString); - QByteArray json = parseJSON(url, 2).toByteArray(); + QString json = parseJSON(url, 2).toString(); return json; } @@ -90,10 +121,6 @@ void GooglePolyScriptingInterface::testPrint(QString input) { qCDebug(scriptengine) << "Google message: " << input; } -void GooglePolyScriptingInterface::setAPIKey(QString key) { - authCode = key; -} - int GooglePolyScriptingInterface::getRandIntInRange(int length) { QTime time = QTime::currentTime(); qsrand((uint)time.msec()); @@ -121,7 +148,7 @@ QUrl GooglePolyScriptingInterface::formatURLQuery(QString keyword, QString categ } QString GooglePolyScriptingInterface::getModelURL(QUrl url) { - qCDebug(scriptengine) << "Google url request: " << url; + qCDebug(scriptengine) << "Google URL request: " << url; if (!url.isEmpty()) { return parseJSON(url, 1).toString(); } else { @@ -150,9 +177,8 @@ QVariant GooglePolyScriptingInterface::parseJSON(QUrl url, int fileType) { if (obj.keys().first() == "error") { QString error = obj.value("error").toObject().value("message").toString(); qCDebug(scriptengine) << error; - return QJsonObject(); + return ""; } - qCDebug(scriptengine) << "the assets: " << obj.value("assets"); if (fileType == 0 || fileType == 1) { QJsonArray arr = obj.value("assets").toArray(); // return model url @@ -163,11 +189,10 @@ QVariant GooglePolyScriptingInterface::parseJSON(QUrl url, int fileType) { return json.value("formats").toArray().at(0).toObject().value("root").toObject().value("url"); } // return whole asset list - return arr; + //return arr; + return QJsonDocument(arr); // return specific object } else { - //return obj; - //return doc.toJson(); return jsonString; } } @@ -269,5 +294,4 @@ or this :(( http://blog.mathieu-leplatre.info/access-a-json-webservice-with-qt-c qCDebug(scriptengine) << "first item: " << firstItem; } -<<<<<<< HEAD */ diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index acbc27b90c..f8b00462f3 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -25,10 +25,13 @@ public slots: void testPrint(QString input); void setAPIKey(QString key); - QJsonArray getAssetList(QString keyword, QString category, QString format); + //QJsonArray getAssetList(QString keyword, QString category, QString format); + QByteArray getAssetList(QString keyword, QString category, QString format); QString getFBX(QString keyword, QString category); QString getOBJ(QString keyword, QString category); QString getBlocks(QString keyword, QString category); + QString getGLTF(QString keyword, QString category); + QString getGLTF2(QString keyword, QString category); //QString getTilt(QString keyword, QString category); QString getModelInfo(QString name); From bd666406f4635168b0dc1f4ce68810a6b580e13d Mon Sep 17 00:00:00 2001 From: Olivier Prat Date: Tue, 19 Dec 2017 14:17:17 +0100 Subject: [PATCH 16/49] Removed glColor reset hack in MeshPartPayload and replaced it by a reset of the color attribute to white in the execution of the setInputFormat command of the various GLBackends --- .../src/RenderablePolyLineEntityItem.cpp | 1 + .../src/RenderableShapeEntityItem.cpp | 5 ++-- .../src/RenderableWebEntityItem.cpp | 1 - libraries/gpu-gl/src/gpu/gl/GLBackend.cpp | 4 +++ libraries/gpu-gl/src/gpu/gl/GLBackend.h | 1 + .../gpu-gl/src/gpu/gl41/GL41BackendInput.cpp | 13 ++++++++ .../gpu-gl/src/gpu/gl45/GL45BackendInput.cpp | 14 +++++++++ libraries/render-utils/src/GeometryCache.cpp | 30 +++++++++++++++++++ libraries/render-utils/src/GeometryCache.h | 6 ++++ .../render-utils/src/MeshPartPayload.cpp | 10 ------- tests/gpu-test/src/TestShapes.cpp | 9 +++--- 11 files changed, 75 insertions(+), 19 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp index fbf85fa8c2..21764dff7f 100644 --- a/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyLineEntityItem.cpp @@ -303,6 +303,7 @@ void PolyLineEntityRenderer::doRender(RenderArgs* args) { batch.setInputBuffer(0, _verticesBuffer, 0, sizeof(Vertex)); #ifndef POLYLINE_ENTITY_USE_FADE_EFFECT + // glColor4f must be called after setInputFormat if it must be taken into account if (_isFading) { batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime)); } else { diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 3524709395..b00ad0259e 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -137,11 +137,10 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { }); if (proceduralRender) { - batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a); if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { - geometryCache->renderWireShape(batch, geometryShape); + geometryCache->renderWireShape(batch, geometryShape, outColor); } else { - geometryCache->renderShape(batch, geometryShape); + geometryCache->renderShape(batch, geometryShape, outColor); } } else { // FIXME, support instanced multi-shape rendering using multidraw indirect diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index cdd260e73c..b253e73b87 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -188,7 +188,6 @@ void WebEntityRenderer::doRender(RenderArgs* args) { }); batch.setResourceTexture(0, _texture); float fadeRatio = _isFading ? Interpolate::calculateFadeRatio(_fadeStartTime) : 1.0f; - batch._glColor4f(1.0f, 1.0f, 1.0f, fadeRatio); DependencyManager::get()->bindWebBrowserProgram(batch, fadeRatio < OPAQUE_ALPHA_THRESHOLD); DependencyManager::get()->renderQuad(batch, topLeft, bottomRight, texMin, texMax, glm::vec4(1.0f, 1.0f, 1.0f, fadeRatio), _geometryId); diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp index 6fb0d7b152..93077e240b 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.cpp @@ -605,6 +605,10 @@ void GLBackend::do_glColor4f(const Batch& batch, size_t paramOffset) { if (_input._colorAttribute != newColor) { _input._colorAttribute = newColor; glVertexAttrib4fv(gpu::Stream::COLOR, &_input._colorAttribute.r); + // Color has been changed and is not white. To prevent colors from bleeding + // between different objects, we need to set the _hadColorAttribute flag + // as if a previous render call had potential colors + _input._hadColorAttribute = (newColor != glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); } (void)CHECK_GL_ERROR(); } diff --git a/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 1908db614d..5558d3ada1 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -253,6 +253,7 @@ protected: struct InputStageState { bool _invalidFormat { true }; + bool _hadColorAttribute{ true }; Stream::FormatPointer _format; std::string _formatKey; diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp index e8ebcbe05c..42bd56e6e4 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp @@ -62,6 +62,8 @@ void GL41Backend::updateInput() { // now we need to bind the buffers and assign the attrib pointers if (_input._format) { + bool hasColorAttribute{ false }; + const Buffers& buffers = _input._buffers; const Offsets& offsets = _input._bufferOffsets; const Offsets& strides = _input._bufferStrides; @@ -98,6 +100,8 @@ void GL41Backend::updateInput() { uintptr_t pointer = (uintptr_t)(attrib._offset + offsets[bufferNum]); GLboolean isNormalized = attrib._element.isNormalized(); + hasColorAttribute = hasColorAttribute || (slot == Stream::COLOR); + for (size_t locNum = 0; locNum < locationCount; ++locNum) { if (attrib._element.isInteger()) { glVertexAttribIPointer(slot + (GLuint)locNum, count, type, stride, @@ -117,6 +121,15 @@ void GL41Backend::updateInput() { } } } + + if (_input._hadColorAttribute && !hasColorAttribute) { + // The previous input stage had a color attribute but this one doesn't so reset + // color to pure white. + const auto white = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + glVertexAttrib4fv(Stream::COLOR, &white.r); + _input._colorAttribute = white; + } + _input._hadColorAttribute = hasColorAttribute; } // everything format related should be in sync now _input._invalidFormat = false; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp index ece62e15f1..4a43fc988c 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendInput.cpp @@ -32,6 +32,8 @@ void GL45Backend::updateInput() { // Assign the vertex format required if (_input._format) { + bool hasColorAttribute{ false }; + _input._attribBindingBuffers.reset(); const Stream::Format::AttributeMap& attributes = _input._format->getAttributes(); @@ -54,6 +56,9 @@ void GL45Backend::updateInput() { GLboolean isNormalized = attrib._element.isNormalized(); GLenum perLocationSize = attrib._element.getLocationSize(); + + hasColorAttribute = hasColorAttribute || (slot == Stream::COLOR); + for (GLuint locNum = 0; locNum < locationCount; ++locNum) { GLuint attriNum = (GLuint)(slot + locNum); newActivation.set(attriNum); @@ -84,6 +89,15 @@ void GL45Backend::updateInput() { glVertexBindingDivisor(bufferChannelNum, frequency); #endif } + + if (_input._hadColorAttribute && !hasColorAttribute) { + // The previous input stage had a color attribute but this one doesn't so reset + // color to pure white. + const auto white = glm::vec4(1.0f, 1.0f, 1.0f, 1.0f); + glVertexAttrib4fv(Stream::COLOR, &white.r); + _input._colorAttribute = white; + } + _input._hadColorAttribute = hasColorAttribute; } // Manage Activation what was and what is expected now diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 76c354bdf8..2616d08600 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -760,6 +760,20 @@ void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) { _shapes[shape].drawWire(batch); } +void GeometryCache::renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { + batch.setInputFormat(getSolidStreamFormat()); + // Color must be set after input format + batch._glColor4f(color.r, color.g, color.b, color.a); + _shapes[shape].draw(batch); +} + +void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { + batch.setInputFormat(getSolidStreamFormat()); + // Color must be set after input format + batch._glColor4f(color.r, color.g, color.b, color.a); + _shapes[shape].drawWire(batch); +} + void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView); @@ -811,6 +825,14 @@ void GeometryCache::renderWireCube(gpu::Batch& batch) { renderWireShape(batch, Cube); } +void GeometryCache::renderCube(gpu::Batch& batch, const glm::vec4& color) { + renderShape(batch, Cube, color); +} + +void GeometryCache::renderWireCube(gpu::Batch& batch, const glm::vec4& color) { + renderWireShape(batch, Cube, color); +} + void GeometryCache::renderSphere(gpu::Batch& batch) { renderShape(batch, Sphere); } @@ -819,6 +841,14 @@ void GeometryCache::renderWireSphere(gpu::Batch& batch) { renderWireShape(batch, Sphere); } +void GeometryCache::renderSphere(gpu::Batch& batch, const glm::vec4& color) { + renderShape(batch, Sphere, color); +} + +void GeometryCache::renderWireSphere(gpu::Batch& batch, const glm::vec4& color) { + renderWireShape(batch, Sphere, color); +} + void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, int majorRows, int majorCols, float majorEdge, int minorRows, int minorCols, float minorEdge, diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index cd8c43f1df..0585cc9e55 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -251,14 +251,20 @@ public: // Dynamic geometry void renderShape(gpu::Batch& batch, Shape shape); void renderWireShape(gpu::Batch& batch, Shape shape); + void renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& color); + void renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color); size_t getShapeTriangleCount(Shape shape); void renderCube(gpu::Batch& batch); void renderWireCube(gpu::Batch& batch); + void renderCube(gpu::Batch& batch, const glm::vec4& color); + void renderWireCube(gpu::Batch& batch, const glm::vec4& color); size_t getCubeTriangleCount(); void renderSphere(gpu::Batch& batch); void renderWireSphere(gpu::Batch& batch); + void renderSphere(gpu::Batch& batch, const glm::vec4& color); + void renderWireSphere(gpu::Batch& batch, const glm::vec4& color); size_t getSphereTriangleCount(); void renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 1ea3e1a705..cf895a73fa 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -122,11 +122,6 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setInputFormat((_drawMesh->getVertexFormat())); batch.setInputStream(0, _drawMesh->getVertexStream()); - - // TODO: Get rid of that extra call - if (!_hasColorAttrib) { - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } } void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, bool enableTextures) const { @@ -526,11 +521,6 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setInputStream(0, _drawMesh->getVertexStream()); } } - - // TODO: Get rid of that extra call - if (!_hasColorAttrib) { - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - } } void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { diff --git a/tests/gpu-test/src/TestShapes.cpp b/tests/gpu-test/src/TestShapes.cpp index 253d89cf61..67a348c002 100644 --- a/tests/gpu-test/src/TestShapes.cpp +++ b/tests/gpu-test/src/TestShapes.cpp @@ -29,19 +29,18 @@ void TestShapes::renderTest(size_t testId, RenderArgs* args) { float seconds = secTimestampNow() - startSecs; seconds /= 4.0f; batch.setModelTransform(Transform()); - batch._glColor4f(0.8f, 0.25f, 0.25f, 1.0f); + const auto color = glm::vec4(0.8f, 0.25f, 0.25f, 1.0f); bool wire = (seconds - floorf(seconds) > 0.5f); int shapeIndex = ((int)seconds) % TYPE_COUNT; if (wire) { - geometryCache->renderWireShape(batch, SHAPE[shapeIndex]); + geometryCache->renderWireShape(batch, SHAPE[shapeIndex], color); } else { - geometryCache->renderShape(batch, SHAPE[shapeIndex]); + geometryCache->renderShape(batch, SHAPE[shapeIndex], color); } batch.setModelTransform(Transform().setScale(1.01f)); - batch._glColor4f(1, 1, 1, 1); - geometryCache->renderWireCube(batch); + geometryCache->renderWireCube(batch, glm::vec4(1,1,1,1)); } From 34d8fe307df1c736f0d5ea77649b6b63990458a5 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 19 Dec 2017 11:25:15 -0800 Subject: [PATCH 17/49] fixed getAssetList() --- .../GooglePolyScriptingInterface.cpp | 20 ++----------------- .../scripting/GooglePolyScriptingInterface.h | 3 +-- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 42c3b825ba..6387295315 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -40,14 +40,13 @@ void GooglePolyScriptingInterface::setAPIKey(QString key) { authCode = key; } -QByteArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { +QString GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { QUrl url = formatURLQuery(keyword, category, format); if (!url.isEmpty()) { //QJsonArray json = parseJSON(url, 0).toJsonArray(); //qCDebug(scriptengine) << "first asset name: " << json.at(0).toObject().value("displayName"); QByteArray json = parseJSON(url, 0).toJsonDocument().toJson(); - qCDebug(scriptengine) << "asset list as string is: " << json; - return json; + return (QString) json; } else { qCDebug(scriptengine) << "Invalid filters were specified."; //return QJsonArray(); @@ -55,21 +54,6 @@ QByteArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString c } } -/*QJsonArray GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { - QUrl url = formatURLQuery(keyword, category, format); - if (!url.isEmpty()) { - //QJsonArray json = parseJSON(url, 0).toJsonArray(); - //qCDebug(scriptengine) << "first asset name: " << json.at(0).toObject().value("displayName"); - QJsonArray json = parseJSON(url, 0).toJsonArray(); - qCDebug(scriptengine) << "asset list as array is: " << json; - return json; - } else { - qCDebug(scriptengine) << "Invalid filters were specified."; - return QJsonArray(); - //return ""; - } -}*/ - QString GooglePolyScriptingInterface::getFBX(QString keyword, QString category) { QUrl url = formatURLQuery(keyword, category, "FBX"); return getModelURL(url); diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index f8b00462f3..7c6d810d13 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -25,8 +25,7 @@ public slots: void testPrint(QString input); void setAPIKey(QString key); - //QJsonArray getAssetList(QString keyword, QString category, QString format); - QByteArray getAssetList(QString keyword, QString category, QString format); + QString getAssetList(QString keyword, QString category, QString format); QString getFBX(QString keyword, QString category); QString getOBJ(QString keyword, QString category); QString getBlocks(QString keyword, QString category); From 1b6c85edb01812db3d349e6911bd167b00a362a7 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 19 Dec 2017 13:22:31 -0800 Subject: [PATCH 18/49] cleaned up code --- .../GooglePolyScriptingInterface.cpp | 111 +----------------- .../scripting/GooglePolyScriptingInterface.h | 2 - 2 files changed, 2 insertions(+), 111 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 6387295315..6f4735f4b1 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -43,13 +43,10 @@ void GooglePolyScriptingInterface::setAPIKey(QString key) { QString GooglePolyScriptingInterface::getAssetList(QString keyword, QString category, QString format) { QUrl url = formatURLQuery(keyword, category, format); if (!url.isEmpty()) { - //QJsonArray json = parseJSON(url, 0).toJsonArray(); - //qCDebug(scriptengine) << "first asset name: " << json.at(0).toObject().value("displayName"); QByteArray json = parseJSON(url, 0).toJsonDocument().toJson(); return (QString) json; } else { qCDebug(scriptengine) << "Invalid filters were specified."; - //return QJsonArray(); return ""; } } @@ -87,7 +84,7 @@ QString GooglePolyScriptingInterface::getTilt(QString keyword, QString category) } */ -// can provide asset name or full URL to model +// Can provide asset name or full URL to model QString GooglePolyScriptingInterface::getModelInfo(QString name) { if (name.contains("poly.googleapis") || name.contains("poly.google.com")) { QStringList list = name.split("/"); @@ -101,10 +98,6 @@ QString GooglePolyScriptingInterface::getModelInfo(QString name) { return json; } -void GooglePolyScriptingInterface::testPrint(QString input) { - qCDebug(scriptengine) << "Google message: " << input; -} - int GooglePolyScriptingInterface::getRandIntInRange(int length) { QTime time = QTime::currentTime(); qsrand((uint)time.msec()); @@ -152,7 +145,7 @@ QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { return response->readAll(); } -// since the list is a QJsonArray and a single model is a QJsonObject +// 0 = asset list, 1 = model from asset list, 2 = specific model QVariant GooglePolyScriptingInterface::parseJSON(QUrl url, int fileType) { //QString firstItem = QString::fromUtf8(response->readAll()); QByteArray jsonString = getHTTPRequest(url); @@ -173,109 +166,9 @@ QVariant GooglePolyScriptingInterface::parseJSON(QUrl url, int fileType) { return json.value("formats").toArray().at(0).toObject().value("root").toObject().value("url"); } // return whole asset list - //return arr; return QJsonDocument(arr); // return specific object } else { return jsonString; } } - - -/* - -// FIXME: synchronous = not good code -QByteArray GooglePolyScriptingInterface::getHTTPRequest(QUrl url) { - QNetworkAccessManager manager; - QNetworkReply *response = manager.get(QNetworkRequest(url)); - QEventLoop event; - connect(response, SIGNAL(finished()), &event, SLOT(quit())); - event.exec(); - return response->readAll(); -} - - - -/* NONE OF THESE HTTP GET METHODS WORK D: -https://stackoverflow.com/questions/28267477/getting-a-page-content-with-qt kinda used rn - -this correctly returns the asset list but is apparently synchronous and not a good way to do it -https://stackoverflow.com/questions/24965972/qt-getting-source-html-code-of-a-web-page-hosted-on-the-internet -void GooglePolyScriptingInterface::getAssetList() { - authCode = "AIzaSyDamk7Vth52j7aU9JVKn3ungFS0kGJYc8A"; - QUrl url(listPolyUrl + "key=" + authCode); - QNetworkAccessManager manager; - QNetworkReply *response = manager.get(QNetworkRequest(url)); - QEventLoop event; - connect(response, SIGNAL(finished()), &event, SLOT(quit())); - event.exec(); - QString firstItem = response->readAll(); - //QJsonArray arr; - //QJsonObject jsonObject = QJsonDocument::fromJson(response->readAll()).object(); - //QString firstItem = jsonObject["assets"].toString(); - qCDebug(scriptengine) << "first item: " << firstItem; - //qCDebug(scriptengine) << "api key: " << authCode; - //return arr; -} - -this didn't work either https://stackoverflow.com/a/24966317 - QScopedPointer manager(new QNetworkAccessManager); - QNetworkReply* response = manager->get(QNetworkRequest(url)); - QObject::connect(manager, &QNetworkAccessManager::finished, [manager, response] { - response->deleteLater(); - manager->deleteLater(); - if (response->error() != QNetworkReply::NoError) return; - QString contentType = - response->header(QNetworkRequest::ContentTypeHeader).toString(); - if (!contentType.contains("charset=utf-8")) { - qWarning() << "Content charsets other than utf-8 are not implemented yet."; - return; - } - QString html = QString::fromUtf8(response->readAll()); - // do something with the data - }) && manager.take(); - - -or this :( https://stackoverflow.com/questions/39518749/make-get-request-to-web-service-get-json-response-and-update-gui-in-qt - qCDebug(scriptengine) << "gonna get assets with " << url; - QNetworkAccessManager manager; - QNetworkReply* reply = manager.get(QNetworkRequest(url)); - QObject::connect(&manager, &QNetworkAccessManager::finished, - [reply]{ - qCDebug(scriptengine) << "boo radley"; - if (reply->error() != QNetworkReply::NoError) { - qCDebug(scriptengine) << "Poly API failed to respond"; - //manager.clearAccessCache(); - } else { - QJsonObject jsonObject = QJsonDocument::fromJson(reply->readAll()).object(); - QString firstItem = jsonObject["assets"].toString(); - qCDebug(scriptengine) << "first item: " << firstItem; - } - reply->deleteLater(); - }); - -or this :(( http://blog.mathieu-leplatre.info/access-a-json-webservice-with-qt-c.html - //QJsonArray arr; - //QJsonObject jsonObject = QJsonDocument::fromJson(response->readAll()).object(); - //QString firstItem = jsonObject["assets"].toString(); - qCDebug(scriptengine) << "first item: " << firstItem; - //qCDebug(scriptengine) << "api key: " << authCode; - //return arr; - QNetworkAccessManager manager; - QNetworkReply* response = manager.get(QNetworkRequest(url)); - QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onResult(QNetworkReply*))); - - return ""; - } - - void GooglePolyScriptingInterface::onResult(QNetworkReply* reply) { - if (reply->error() != QNetworkReply::NoError) { - qCDebug(scriptengine) << "Poly API failed to respond"; - return; - } - QString firstItem = reply->readAll(); - - qCDebug(scriptengine) << "first item: " << firstItem; - } - -*/ diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 7c6d810d13..cdfeddd5fe 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -22,7 +22,6 @@ public: GooglePolyScriptingInterface(); public slots: - void testPrint(QString input); void setAPIKey(QString key); QString getAssetList(QString keyword, QString category, QString format); @@ -40,7 +39,6 @@ private: QByteArray getHTTPRequest(QUrl url); QVariant parseJSON(QUrl url, int fileType); int getRandIntInRange(int length); - //void onResult(QNetworkReply* reply); QString authCode; From 14935e5924c38f71a3185be79bd2ddb9ff793980 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 19 Dec 2017 15:11:24 -0800 Subject: [PATCH 19/49] added const to valid inputs --- interface/src/scripting/GooglePolyScriptingInterface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 6f4735f4b1..c9699a2a68 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -28,8 +28,8 @@ const QString listPolyUrl = "https://poly.googleapis.com/v1/assets?"; const QString getPolyUrl = "https://poly.googleapis.com/v1/assets/model?"; -QStringList validFormats = QStringList() << "BLOCKS" << "FBX" << "GLTF" << "GLTF2" << "OBJ" << "TILT" << ""; -QStringList validCategories = QStringList() << "animals" << "architecture" << "art" << "food" << +const QStringList validFormats = QStringList() << "BLOCKS" << "FBX" << "GLTF" << "GLTF2" << "OBJ" << "TILT" << ""; +const QStringList validCategories = QStringList() << "animals" << "architecture" << "art" << "food" << "nature" << "objects" << "people" << "scenes" << "technology" << "transport" << ""; GooglePolyScriptingInterface::GooglePolyScriptingInterface() { From ca062f923278dbccff1e7cd68e153bdf8cc1d8fe Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 19 Dec 2017 15:41:42 -0800 Subject: [PATCH 20/49] changed qtglobal include --- interface/src/scripting/GooglePolyScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index c9699a2a68..d3b24f79f0 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -10,7 +10,7 @@ // #include -#include +#include #include #include #include From bd06dc6443e68b7d4ad26f0a8b1a90d9b192e398 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 19 Dec 2017 16:57:16 -0800 Subject: [PATCH 21/49] cleaning up modelmeshpartpayload --- interface/src/ui/overlays/ModelOverlay.cpp | 2 - .../src/avatars-renderer/Avatar.cpp | 1 - .../src/RenderableModelEntityItem.cpp | 1 - .../render-utils/src/CauterizedModel.cpp | 14 +- .../render-utils/src/MeshPartPayload.cpp | 122 ++++++------------ libraries/render-utils/src/MeshPartPayload.h | 21 +-- libraries/render-utils/src/Model.cpp | 42 ++++-- libraries/render-utils/src/Model.h | 7 +- 8 files changed, 97 insertions(+), 113 deletions(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index ba8bf8cbef..67fa94f7e5 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -24,7 +24,6 @@ ModelOverlay::ModelOverlay() : _model(std::make_shared(nullptr, this)), _modelTextures(QVariantMap()) { - _model->init(); _model->setLoadingPriority(_loadPriority); _isLoaded = false; } @@ -38,7 +37,6 @@ ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) : _scaleToFit(modelOverlay->_scaleToFit), _loadPriority(modelOverlay->_loadPriority) { - _model->init(); _model->setLoadingPriority(_loadPriority); if (_url.isValid()) { _updateModel = true; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index bb7f141cd9..c532e7659f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -138,7 +138,6 @@ Avatar::~Avatar() { void Avatar::init() { getHead()->init(); - _skeletonModel->init(); _initialized = true; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e578e4858d..485cc93ca2 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1213,7 +1213,6 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce connect(model.get(), &Model::requestRenderUpdate, this, &ModelEntityRenderer::requestRenderUpdate); connect(entity.get(), &RenderableModelEntityItem::requestCollisionGeometryUpdate, this, &ModelEntityRenderer::flagForCollisionGeometryUpdate); model->setLoadingPriority(EntityTreeRenderer::getEntityLoadingPriority(*entity)); - model->init(); entity->setModel(model); withWriteLock([&] { _model = model; }); } diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index c437a8c556..745e995cc4 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -178,6 +178,11 @@ void CauterizedModel::updateRenderItems() { modelTransform.setTranslation(self->getTranslation()); modelTransform.setRotation(self->getRotation()); + bool isWireframe = self->isWireframe(); + bool isVisible = self->isVisible(); + bool isLayeredInFront = self->isLayeredInFront(); + bool isLayeredInHUD = self->isLayeredInHUD(); + render::Transaction transaction; for (int i = 0; i < (int)self->_modelMeshRenderItemIDs.size(); i++) { @@ -186,7 +191,10 @@ void CauterizedModel::updateRenderItems() { auto clusterMatrices(self->getMeshState(meshIndex).clusterMatrices); auto clusterMatricesCauterized(self->getCauterizeMeshState(meshIndex).clusterMatrices); - transaction.updateItem(itemID, [modelTransform, clusterMatrices, clusterMatricesCauterized](CauterizedMeshPartPayload& data) { + bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); + + transaction.updateItem(itemID, [modelTransform, clusterMatrices, clusterMatricesCauterized, invalidatePayloadShapeKey, + isWireframe, isVisible, isLayeredInFront, isLayeredInHUD](CauterizedMeshPartPayload& data) { data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized); Transform renderTransform = modelTransform; @@ -200,6 +208,10 @@ void CauterizedModel::updateRenderItems() { renderTransform = modelTransform.worldTransform(Transform(clusterMatricesCauterized[0])); } data.updateTransformForCauterizedMesh(renderTransform); + + data.setKey(data.evalKey(isVisible, isLayeredInFront, isLayeredInHUD)); + data.setLayer(data.evalLayer(isLayeredInFront, isLayeredInHUD)); + data.setShapeKey(invalidatePayloadShapeKey ? render::ShapeKey::Builder::invalid() : data.evalShapeKey(isWireframe)); }); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 1ea3e1a705..2be9781935 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -339,13 +339,10 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in } updateTransformForSkinnedMesh(renderTransform, transform); - initCache(); + initCache(model); } -void ModelMeshPartPayload::initCache() { - ModelPointer model = _model.lock(); - assert(model && model->isLoaded()); - +void ModelMeshPartPayload::initCache(const ModelPointer& model) { if (_drawMesh) { auto vertexFormat = _drawMesh->getVertexFormat(); _hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR); @@ -355,6 +352,7 @@ void ModelMeshPartPayload::initCache() { const FBXMesh& mesh = geometry.meshes.at(_meshIndex); _isBlendShaped = !mesh.blendshapes.isEmpty(); + _hasTangents = !mesh.tangents.isEmpty(); } auto networkMaterial = model->getGeometry()->getShapeMaterial(_shapeID); @@ -388,94 +386,65 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render _worldBound.transform(boundTransform); } -ItemKey ModelMeshPartPayload::getKey() const { +render::ItemKey ModelMeshPartPayload::evalKey(bool isVisible, bool isLayeredInFront, bool isLayeredInHUD) const { ItemKey::Builder builder; builder.withTypeShape(); - ModelPointer model = _model.lock(); - if (model) { - if (!model->isVisible()) { - builder.withInvisible(); - } + if (!isVisible) { + builder.withInvisible(); + } - if (model->isLayeredInFront() || model->isLayeredInHUD()) { - builder.withLayered(); - } + if (isLayeredInFront || isLayeredInHUD) { + builder.withLayered(); + } - if (_isBlendShaped || _isSkinned) { - builder.withDeformed(); - } + if (_isBlendShaped || _isSkinned) { + builder.withDeformed(); + } - if (_drawMaterial) { - auto matKey = _drawMaterial->getKey(); - if (matKey.isTranslucent()) { - builder.withTransparent(); - } + if (_drawMaterial) { + auto matKey = _drawMaterial->getKey(); + if (matKey.isTranslucent()) { + builder.withTransparent(); } } + return builder.build(); } -int ModelMeshPartPayload::getLayer() const { - ModelPointer model = _model.lock(); - if (model) { - if (model->isLayeredInFront()) { - return Item::LAYER_3D_FRONT; - } else if (model->isLayeredInHUD()) { - return Item::LAYER_3D_HUD; - } - } - return Item::LAYER_3D; +ItemKey ModelMeshPartPayload::getKey() const { + return _itemKey; } -ShapeKey ModelMeshPartPayload::getShapeKey() const { - // guard against partially loaded meshes - ModelPointer model = _model.lock(); - if (!model || !model->isLoaded() || !model->getGeometry()) { - return ShapeKey::Builder::invalid(); - } - - const FBXGeometry& geometry = model->getFBXGeometry(); - const auto& networkMeshes = model->getGeometry()->getMeshes(); - - // guard against partially loaded meshes - if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)model->_meshStates.size()) { - return ShapeKey::Builder::invalid(); - } - - const FBXMesh& mesh = geometry.meshes.at(_meshIndex); - - // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown - // to false to rebuild out mesh groups. - if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) { - model->_needsFixupInScene = true; // trigger remove/add cycle - model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid - return ShapeKey::Builder::invalid(); - } - - - int vertexCount = mesh.vertices.size(); - if (vertexCount == 0) { - // sanity check - return ShapeKey::Builder::invalid(); // FIXME +int ModelMeshPartPayload::evalLayer(bool isLayeredInFront, bool isLayeredInHUD) const { + if (isLayeredInFront) { + return Item::LAYER_3D_FRONT; + } else if (isLayeredInHUD) { + return Item::LAYER_3D_HUD; + } else { + return Item::LAYER_3D; } +} +int ModelMeshPartPayload::getLayer() const { + return _layer; +} +ShapeKey ModelMeshPartPayload::evalShapeKey(bool isWireframe) const { model::MaterialKey drawMaterialKey; if (_drawMaterial) { drawMaterialKey = _drawMaterial->getKey(); } bool isTranslucent = drawMaterialKey.isTranslucent(); - bool hasTangents = drawMaterialKey.isNormalMap() && !mesh.tangents.isEmpty(); + bool hasTangents = drawMaterialKey.isNormalMap() && _hasTangents; bool hasSpecular = drawMaterialKey.isMetallicMap(); bool hasLightmap = drawMaterialKey.isLightmapMap(); bool isUnlit = drawMaterialKey.isUnlit(); bool isSkinned = _isSkinned; - bool wireframe = model->isWireframe(); - if (wireframe) { + if (isWireframe) { isTranslucent = hasTangents = hasSpecular = hasLightmap = isSkinned = false; } @@ -500,12 +469,16 @@ ShapeKey ModelMeshPartPayload::getShapeKey() const { if (isSkinned) { builder.withSkinned(); } - if (wireframe) { + if (isWireframe) { builder.withWireframe(); } return builder.build(); } +ShapeKey ModelMeshPartPayload::getShapeKey() const { + return _shapeKey; +} + void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { if (!_isBlendShaped) { batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); @@ -549,26 +522,9 @@ void ModelMeshPartPayload::render(RenderArgs* args) { return; // bail asap } - if (_state == WAITING_TO_START) { - if (model->isLoaded()) { - _state = STARTED; - model->setRenderItemsNeedUpdate(); - } else { - return; - } - } - - if (_materialNeedsUpdate && model->getGeometry()->areTexturesLoaded()) { - model->setRenderItemsNeedUpdate(); - _materialNeedsUpdate = false; - } - if (!args) { return; } - if (!getShapeKey().isValid()) { - return; - } gpu::Batch& batch = *(args->_batch); auto locations = args->_shapePipeline->locations; diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 971c6fe90b..e56623ae16 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -96,12 +96,17 @@ public: render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; + render::ItemKey evalKey(bool isVisible, bool isLayeredInFront, bool isLayeredInHUD) const; + void setKey(const render::ItemKey& itemKey) { _itemKey = itemKey; } + int evalLayer(bool isLayeredInFront, bool isLayeredInHUD) const; + void setLayer(int layer) { _layer = layer; } + render::ShapeKey evalShapeKey(bool isWireframe) const; + void setShapeKey(const render::ShapeKey& shapeKey) { _shapeKey = shapeKey; }; + // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) override; void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; - void initCache(); - void computeAdjustedLocalBound(const std::vector& clusterMatrices); gpu::BufferPointer _clusterBuffer; @@ -112,16 +117,14 @@ public: bool _isSkinned{ false }; bool _isBlendShaped { false }; - bool _materialNeedsUpdate { true }; + bool _hasTangents { false }; private: + void initCache(const ModelPointer& model); - enum State : uint8_t { - WAITING_TO_START = 0, - STARTED = 1, - }; - - mutable State _state { WAITING_TO_START } ; + render::ItemKey _itemKey { render::ItemKey::Builder::opaqueShape().build() }; + int _layer { render::Item::LAYER_3D }; + render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index c4bc435691..7dff629183 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -210,6 +210,24 @@ int Model::getRenderInfoTextureCount() { return _renderInfoTextureCount; } +bool Model::shouldInvalidatePayloadShapeKey(int meshIndex) { + if (!getGeometry()) { + return true; + } + + const FBXGeometry& geometry = getFBXGeometry(); + const auto& networkMeshes = getGeometry()->getMeshes(); + // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown + // to false to rebuild out mesh groups. + if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)_meshStates.size()) { + _needsFixupInScene = true; // trigger remove/add cycle + invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid + return true; + } + + return false; +} + void Model::updateRenderItems() { if (!_addedToScene) { return; @@ -237,6 +255,11 @@ void Model::updateRenderItems() { Transform modelTransform = self->getTransform(); modelTransform.setScale(glm::vec3(1.0f)); + bool isWireframe = self->isWireframe(); + bool isVisible = self->isVisible(); + bool isLayeredInFront = self->isLayeredInFront(); + bool isLayeredInHUD = self->isLayeredInHUD(); + render::Transaction transaction; for (int i = 0; i < (int) self->_modelMeshRenderItemIDs.size(); i++) { @@ -244,13 +267,20 @@ void Model::updateRenderItems() { auto meshIndex = self->_modelMeshRenderItemShapes[i].meshIndex; auto clusterMatrices(self->getMeshState(meshIndex).clusterMatrices); - transaction.updateItem(itemID, [modelTransform, clusterMatrices](ModelMeshPartPayload& data) { + bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); + + transaction.updateItem(itemID, [modelTransform, clusterMatrices, invalidatePayloadShapeKey, + isWireframe, isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { data.updateClusterBuffer(clusterMatrices); Transform renderTransform = modelTransform; if (clusterMatrices.size() == 1) { renderTransform = modelTransform.worldTransform(Transform(clusterMatrices[0])); } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); + + data.setKey(data.evalKey(isVisible, isLayeredInFront, isLayeredInHUD)); + data.setLayer(data.evalLayer(isLayeredInFront, isLayeredInHUD)); + data.setShapeKey(invalidatePayloadShapeKey ? render::ShapeKey::Builder::invalid() : data.evalShapeKey(isWireframe)); }); } @@ -272,16 +302,6 @@ void Model::setRenderItemsNeedUpdate() { emit requestRenderUpdate(); } -void Model::initJointTransforms() { - if (isLoaded()) { - glm::mat4 modelOffset = glm::scale(_scale) * glm::translate(_offset); - _rig.setModelOffset(modelOffset); - } -} - -void Model::init() { -} - void Model::reset() { if (isLoaded()) { const FBXGeometry& geometry = getFBXGeometry(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 7568a17342..50ccb22131 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -122,7 +122,6 @@ public: void setIsWireframe(bool isWireframe) { _isWireframe = isWireframe; } bool isWireframe() const { return _isWireframe; } - void init(); void reset(); void setSnapModelToRegistrationPoint(bool snapModelToRegistrationPoint, const glm::vec3& registrationPoint); @@ -346,11 +345,7 @@ protected: // hook for derived classes to be notified when setUrl invalidates the current model. virtual void onInvalidate() {}; - -protected: - virtual void deleteGeometry(); - void initJointTransforms(); QVector _blendshapeCoefficients; @@ -419,6 +414,8 @@ protected: bool _isLayeredInFront { false }; bool _isLayeredInHUD { false }; + bool shouldInvalidatePayloadShapeKey(int meshIndex); + private: float _loadingPriority { 0.0f }; From 7de2918b9b9da99fbf03c793ca4e22c32146b400 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 20 Dec 2017 12:44:47 -0800 Subject: [PATCH 22/49] added newline to header --- interface/src/scripting/GooglePolyScriptingInterface.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index cdfeddd5fe..758926aed5 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -44,4 +44,4 @@ private: }; -#endif // hifi_GooglePolyScriptingInterface_h \ No newline at end of file +#endif // hifi_GooglePolyScriptingInterface_h From 7a7b1f7089b27f2fb74ea4d06815d528e32855a3 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 20 Dec 2017 13:58:58 -0800 Subject: [PATCH 23/49] fix web entity crash --- libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index cdd260e73c..ff0d6bea2d 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -124,7 +124,10 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene withWriteLock([&] { // This work must be done on the main thread if (!hasWebSurface()) { - buildWebSurface(entity); + // If we couldn't create a new web surface, exit + if (!buildWebSurface(entity)) { + return; + } } if (_contextPosition != entity->getWorldPosition()) { From 2ba3e337db8a122d9ecfb49c7cec853f1f257547 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 20 Dec 2017 14:18:01 -0800 Subject: [PATCH 24/49] cleanup --- .../render-utils/src/CauterizedModel.cpp | 6 ++--- .../render-utils/src/MeshPartPayload.cpp | 23 +++++++++++-------- libraries/render-utils/src/MeshPartPayload.h | 11 ++++----- libraries/render-utils/src/Model.cpp | 6 ++--- 4 files changed, 24 insertions(+), 22 deletions(-) diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 745e995cc4..52095ee25a 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -209,9 +209,9 @@ void CauterizedModel::updateRenderItems() { } data.updateTransformForCauterizedMesh(renderTransform); - data.setKey(data.evalKey(isVisible, isLayeredInFront, isLayeredInHUD)); - data.setLayer(data.evalLayer(isLayeredInFront, isLayeredInHUD)); - data.setShapeKey(invalidatePayloadShapeKey ? render::ShapeKey::Builder::invalid() : data.evalShapeKey(isWireframe)); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setLayer(isLayeredInFront, isLayeredInHUD); + data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 2be9781935..313cd383f9 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -386,7 +386,7 @@ void ModelMeshPartPayload::updateTransformForSkinnedMesh(const Transform& render _worldBound.transform(boundTransform); } -render::ItemKey ModelMeshPartPayload::evalKey(bool isVisible, bool isLayeredInFront, bool isLayeredInHUD) const { +void ModelMeshPartPayload::setKey(bool isVisible, bool isLayered) { ItemKey::Builder builder; builder.withTypeShape(); @@ -394,7 +394,7 @@ render::ItemKey ModelMeshPartPayload::evalKey(bool isVisible, bool isLayeredInFr builder.withInvisible(); } - if (isLayeredInFront || isLayeredInHUD) { + if (isLayered) { builder.withLayered(); } @@ -409,20 +409,20 @@ render::ItemKey ModelMeshPartPayload::evalKey(bool isVisible, bool isLayeredInFr } } - return builder.build(); + _itemKey = builder.build(); } ItemKey ModelMeshPartPayload::getKey() const { return _itemKey; } -int ModelMeshPartPayload::evalLayer(bool isLayeredInFront, bool isLayeredInHUD) const { +void ModelMeshPartPayload::setLayer(bool isLayeredInFront, bool isLayeredInHUD) { if (isLayeredInFront) { - return Item::LAYER_3D_FRONT; + _layer = Item::LAYER_3D_FRONT; } else if (isLayeredInHUD) { - return Item::LAYER_3D_HUD; + _layer = Item::LAYER_3D_HUD; } else { - return Item::LAYER_3D; + _layer = Item::LAYER_3D; } } @@ -430,7 +430,12 @@ int ModelMeshPartPayload::getLayer() const { return _layer; } -ShapeKey ModelMeshPartPayload::evalShapeKey(bool isWireframe) const { +void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe) { + if (invalidateShapeKey) { + _shapeKey = ShapeKey::Builder::invalid(); + return; + } + model::MaterialKey drawMaterialKey; if (_drawMaterial) { drawMaterialKey = _drawMaterial->getKey(); @@ -472,7 +477,7 @@ ShapeKey ModelMeshPartPayload::evalShapeKey(bool isWireframe) const { if (isWireframe) { builder.withWireframe(); } - return builder.build(); + _shapeKey = builder.build(); } ShapeKey ModelMeshPartPayload::getShapeKey() const { diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index e56623ae16..8715b6a7a0 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -96,12 +96,9 @@ public: render::ShapeKey getShapeKey() const override; // shape interface void render(RenderArgs* args) override; - render::ItemKey evalKey(bool isVisible, bool isLayeredInFront, bool isLayeredInHUD) const; - void setKey(const render::ItemKey& itemKey) { _itemKey = itemKey; } - int evalLayer(bool isLayeredInFront, bool isLayeredInHUD) const; - void setLayer(int layer) { _layer = layer; } - render::ShapeKey evalShapeKey(bool isWireframe) const; - void setShapeKey(const render::ShapeKey& shapeKey) { _shapeKey = shapeKey; }; + void setKey(bool isVisible, bool isLayered); + void setLayer(bool isLayeredInFront, bool isLayeredInHUD); + void setShapeKey(bool invalidateShapeKey, bool isWireframe); // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) override; @@ -123,8 +120,8 @@ private: void initCache(const ModelPointer& model); render::ItemKey _itemKey { render::ItemKey::Builder::opaqueShape().build() }; - int _layer { render::Item::LAYER_3D }; render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; + int _layer { render::Item::LAYER_3D }; }; namespace render { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 7dff629183..7717ceda6f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -278,9 +278,9 @@ void Model::updateRenderItems() { } data.updateTransformForSkinnedMesh(renderTransform, modelTransform); - data.setKey(data.evalKey(isVisible, isLayeredInFront, isLayeredInHUD)); - data.setLayer(data.evalLayer(isLayeredInFront, isLayeredInHUD)); - data.setShapeKey(invalidatePayloadShapeKey ? render::ShapeKey::Builder::invalid() : data.evalShapeKey(isWireframe)); + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setLayer(isLayeredInFront, isLayeredInHUD); + data.setShapeKey(invalidatePayloadShapeKey, isWireframe); }); } From 31e9f26772c5e3d9cde34624b32450863538b363 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 21 Dec 2017 11:34:03 -0800 Subject: [PATCH 25/49] fix use after free of pending message --- libraries/networking/src/udt/Connection.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 2f57523f79..77ed589e0b 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -191,6 +191,8 @@ void Connection::queueReceivedMessagePacket(std::unique_ptr packet) { pendingMessage.enqueuePacket(std::move(packet)); + bool processedLastOrOnly = false; + while (pendingMessage.hasAvailablePackets()) { auto packet = pendingMessage.removeNextPacket(); @@ -201,9 +203,13 @@ void Connection::queueReceivedMessagePacket(std::unique_ptr packet) { // if this was the last or only packet, then we can remove the pending message from our hash if (packetPosition == Packet::PacketPosition::LAST || packetPosition == Packet::PacketPosition::ONLY) { - _pendingReceivedMessages.erase(messageNumber); + processedLastOrOnly = true; } } + + if (processedLastOrOnly) { + _pendingReceivedMessages.erase(messageNumber); + } } void Connection::sync() { From 69c1c65eb8853a6ebd0701c53f6b732d962c138a Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Thu, 21 Dec 2017 12:48:43 -0800 Subject: [PATCH 26/49] get rid of _model completely --- .../render-utils/src/CauterizedMeshPartPayload.cpp | 12 +----------- .../render-utils/src/CauterizedMeshPartPayload.h | 3 +++ libraries/render-utils/src/CauterizedModel.cpp | 4 +++- libraries/render-utils/src/MeshPartPayload.cpp | 14 ++++---------- libraries/render-utils/src/MeshPartPayload.h | 2 +- 5 files changed, 12 insertions(+), 23 deletions(-) diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 3bb2aa2ef9..396cd13508 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -40,17 +40,7 @@ void CauterizedMeshPartPayload::updateTransformForCauterizedMesh(const Transform void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { // Still relying on the raw data from the model - bool useCauterizedMesh = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE && renderMode != RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE); - if (useCauterizedMesh) { - ModelPointer model = _model.lock(); - if (model) { - CauterizedModel* skeleton = static_cast(model.get()); - useCauterizedMesh = useCauterizedMesh && skeleton->getEnableCauterization(); - } else { - useCauterizedMesh = false; - } - } - + bool useCauterizedMesh = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE && renderMode != RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) && _enableCauterization; if (useCauterizedMesh) { if (_cauterizedClusterBuffer) { batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, _cauterizedClusterBuffer); diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.h b/libraries/render-utils/src/CauterizedMeshPartPayload.h index 1c98f5abf3..44eddc6e31 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.h +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.h @@ -21,9 +21,12 @@ public: void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; + void setEnableCauterization(bool enableCauterization) { _enableCauterization = enableCauterization; } + private: gpu::BufferPointer _cauterizedClusterBuffer; Transform _cauterizedTransform; + bool _enableCauterization { false }; }; #endif // hifi_CauterizedMeshPartPayload_h diff --git a/libraries/render-utils/src/CauterizedModel.cpp b/libraries/render-utils/src/CauterizedModel.cpp index 52095ee25a..dbb82ab638 100644 --- a/libraries/render-utils/src/CauterizedModel.cpp +++ b/libraries/render-utils/src/CauterizedModel.cpp @@ -182,6 +182,7 @@ void CauterizedModel::updateRenderItems() { bool isVisible = self->isVisible(); bool isLayeredInFront = self->isLayeredInFront(); bool isLayeredInHUD = self->isLayeredInHUD(); + bool enableCauterization = self->getEnableCauterization(); render::Transaction transaction; for (int i = 0; i < (int)self->_modelMeshRenderItemIDs.size(); i++) { @@ -194,7 +195,7 @@ void CauterizedModel::updateRenderItems() { bool invalidatePayloadShapeKey = self->shouldInvalidatePayloadShapeKey(meshIndex); transaction.updateItem(itemID, [modelTransform, clusterMatrices, clusterMatricesCauterized, invalidatePayloadShapeKey, - isWireframe, isVisible, isLayeredInFront, isLayeredInHUD](CauterizedMeshPartPayload& data) { + isWireframe, isVisible, isLayeredInFront, isLayeredInHUD, enableCauterization](CauterizedMeshPartPayload& data) { data.updateClusterBuffer(clusterMatrices, clusterMatricesCauterized); Transform renderTransform = modelTransform; @@ -209,6 +210,7 @@ void CauterizedModel::updateRenderItems() { } data.updateTransformForCauterizedMesh(renderTransform); + data.setEnableCauterization(enableCauterization); data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); data.setLayer(isLayeredInFront, isLayeredInHUD); data.setShapeKey(invalidatePayloadShapeKey, isWireframe); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index 313cd383f9..61a5175efd 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -325,7 +325,7 @@ ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, in _shapeID(shapeIndex) { assert(model && model->isLoaded()); - _model = model; + _blendedVertexBuffer = model->_blendedVertexBuffers[_meshIndex]; auto& modelMesh = model->getGeometry()->getMeshes().at(_meshIndex); const Model::MeshState& state = model->getMeshState(_meshIndex); @@ -493,10 +493,9 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); batch.setInputFormat((_drawMesh->getVertexFormat())); - ModelPointer model = _model.lock(); - if (model) { - batch.setInputBuffer(0, model->_blendedVertexBuffers[_meshIndex], 0, sizeof(glm::vec3)); - batch.setInputBuffer(1, model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); + if (_blendedVertexBuffer) { + batch.setInputBuffer(0, _blendedVertexBuffer, 0, sizeof(glm::vec3)); + batch.setInputBuffer(1, _blendedVertexBuffer, _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3)); batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2)); } else { batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0); @@ -522,11 +521,6 @@ void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline: void ModelMeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("ModelMeshPartPayload::render"); - ModelPointer model = _model.lock(); - if (!model || !model->isAddedToScene() || !model->isVisible()) { - return; // bail asap - } - if (!args) { return; } diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 8715b6a7a0..fb55883101 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -107,7 +107,6 @@ public: void computeAdjustedLocalBound(const std::vector& clusterMatrices); gpu::BufferPointer _clusterBuffer; - ModelWeakPointer _model; int _meshIndex; int _shapeID; @@ -119,6 +118,7 @@ public: private: void initCache(const ModelPointer& model); + gpu::BufferPointer _blendedVertexBuffer; render::ItemKey _itemKey { render::ItemKey::Builder::opaqueShape().build() }; render::ShapeKey _shapeKey { render::ShapeKey::Builder::invalid() }; int _layer { render::Item::LAYER_3D }; From 18993a8f72784415fc3e1f9129e38aaa58d6a573 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 21 Dec 2017 14:53:47 -0800 Subject: [PATCH 27/49] fix for AvatarData retrieval from SortableAvatar in PriorityQueue --- assignment-client/src/avatars/AvatarMixerSlave.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/avatars/AvatarMixerSlave.cpp b/assignment-client/src/avatars/AvatarMixerSlave.cpp index 47a81ba1fe..fb4b65726a 100644 --- a/assignment-client/src/avatars/AvatarMixerSlave.cpp +++ b/assignment-client/src/avatars/AvatarMixerSlave.cpp @@ -214,7 +214,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) uint64_t getTimestamp() const override { return _lastEncodeTime; } - const AvatarSharedPointer& getAvatar() const { return _avatar; } + AvatarSharedPointer getAvatar() const { return _avatar; } private: AvatarSharedPointer _avatar; @@ -326,7 +326,7 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node) int remainingAvatars = (int)sortedAvatars.size(); while (!sortedAvatars.empty()) { - const auto& avatarData = sortedAvatars.top().getAvatar(); + const auto avatarData = sortedAvatars.top().getAvatar(); sortedAvatars.pop(); remainingAvatars--; From 7bf0cc2f63f2818ae115bcb8ff8104fed6ba8274 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 21 Dec 2017 15:17:18 -0800 Subject: [PATCH 28/49] cleanup other ref returns of shared pointers from sortables --- interface/src/avatar/AvatarManager.cpp | 6 +++--- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 8a294182bd..93caef555f 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -150,7 +150,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { glm::vec3 getPosition() const override { return _avatar->getWorldPosition(); } float getRadius() const override { return std::static_pointer_cast(_avatar)->getBoundingRadius(); } uint64_t getTimestamp() const override { return std::static_pointer_cast(_avatar)->getLastRenderUpdateTime(); } - const AvatarSharedPointer& getAvatar() const { return _avatar; } + AvatarSharedPointer getAvatar() const { return _avatar; } private: AvatarSharedPointer _avatar; }; @@ -185,7 +185,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { render::Transaction transaction; while (!sortedAvatars.empty()) { const SortableAvatar& sortData = sortedAvatars.top(); - const auto& avatar = std::static_pointer_cast(sortData.getAvatar()); + const auto avatar = std::static_pointer_cast(sortData.getAvatar()); bool ignoring = DependencyManager::get()->isPersonalMutingNode(avatar->getID()); if (ignoring) { @@ -239,7 +239,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { sortedAvatars.pop(); while (inView && !sortedAvatars.empty()) { const SortableAvatar& newSortData = sortedAvatars.top(); - const auto& newAvatar = std::static_pointer_cast(newSortData.getAvatar()); + const auto newAvatar = std::static_pointer_cast(newSortData.getAvatar()); inView = newSortData.getPriority() > OUT_OF_VIEW_THRESHOLD; if (inView && newAvatar->hasNewJointData()) { numAVatarsNotUpdated++; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5f7899ae74..a629b2046f 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -349,7 +349,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene float getRadius() const override { return 0.5f * _renderer->getEntity()->getQueryAACube().getScale(); } uint64_t getTimestamp() const override { return _renderer->getUpdateTime(); } - const EntityRendererPointer& getRenderer() const { return _renderer; } + EntityRendererPointer getRenderer() const { return _renderer; } private: EntityRendererPointer _renderer; }; @@ -382,7 +382,7 @@ void EntityTreeRenderer::updateChangedEntities(const render::ScenePointer& scene std::unordered_map::iterator itr; size_t numSorted = sortedRenderables.size(); while (!sortedRenderables.empty() && usecTimestampNow() < expiry) { - const EntityRendererPointer& renderable = sortedRenderables.top().getRenderer(); + const auto renderable = sortedRenderables.top().getRenderer(); renderable->updateInScene(scene, transaction); _renderablesToUpdate.erase(renderable->getEntity()->getID()); sortedRenderables.pop(); From 05b45f2e7ec94ed1ebdf5d216eef215acfbfe3fd Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 21 Dec 2017 15:40:08 -0800 Subject: [PATCH 29/49] adjust example and add clarifying comments to PrioritySortUtil --- libraries/shared/src/PrioritySortUtil.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/libraries/shared/src/PrioritySortUtil.h b/libraries/shared/src/PrioritySortUtil.h index dc6a877bb9..279fa42ea4 100644 --- a/libraries/shared/src/PrioritySortUtil.h +++ b/libraries/shared/src/PrioritySortUtil.h @@ -28,7 +28,7 @@ glm::vec3 getPosition() const override { return _thing->getPosition(); } float getRadius() const override { return 0.5f * _thing->getBoundingRadius(); } uint64_t getTimestamp() const override { return _thing->getLastTime(); } - const Thing& getThing() const { return _thing; } + Thing getThing() const { return _thing; } private: Thing _thing; }; @@ -43,6 +43,13 @@ (3) Loop over your priority queue and do timeboxed work: + NOTE: Be careful using references to members of instances of T from std::priority_queue. + Under the hood std::priority_queue may re-use instances of T. + For example, after a pop() or a push() the top T may have the same memory address + as the top T before the pop() or push() (but point to a swapped instance of T). + This causes a reference to member variable of T to point to a different value + when operations taken on std::priority_queue shuffle around the instances of T. + uint64_t cutoffTime = usecTimestampNow() + TIME_BUDGET; while (!sortedThings.empty()) { const Thing& thing = sortedThings.top(); From 618e5c9032dbb25bad9acbf3e56171781885508b Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 21 Dec 2017 15:46:01 -0800 Subject: [PATCH 30/49] Commerce Data Tracking: Iteration 3 (Purchases) --- interface/resources/qml/hifi/commerce/checkout/Checkout.qml | 6 ++++-- .../networking/src/UserActivityLoggerScriptingInterface.cpp | 6 ++++-- .../networking/src/UserActivityLoggerScriptingInterface.h | 4 ++-- scripts/system/html/js/marketplacesInject.js | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 6b7432b8b2..9a3d9e1e19 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -33,6 +33,7 @@ Rectangle { property string itemName; property string itemId; property string itemHref; + property string itemAuthor; property double balanceAfterPurchase; property bool alreadyOwned: false; property int itemPrice: -1; @@ -81,12 +82,12 @@ Rectangle { if (result.status !== 'success') { failureErrorText.text = result.message; root.activeView = "checkoutFailure"; - UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemPrice, !root.alreadyOwned, result.message); + UserActivityLogger.commercePurchaseFailure(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned, result.message); } else { root.itemHref = result.data.download_url; root.isWearable = result.data.categories.indexOf("Wearables") > -1; root.activeView = "checkoutSuccess"; - UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemPrice, !root.alreadyOwned); + UserActivityLogger.commercePurchaseSuccess(root.itemId, root.itemAuthor, root.itemPrice, !root.alreadyOwned); } } @@ -879,6 +880,7 @@ Rectangle { root.itemPrice = message.params.itemPrice; itemHref = message.params.itemHref; referrer = message.params.referrer; + itemAuthor = message.params.itemAuthor; setBuyText(); break; default: diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp index aec6df4f14..c63170de75 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.cpp @@ -89,17 +89,19 @@ void UserActivityLoggerScriptingInterface::doLogAction(QString action, QJsonObje Q_ARG(QJsonObject, details)); } -void UserActivityLoggerScriptingInterface::commercePurchaseSuccess(QString marketplaceID, int cost, bool firstPurchaseOfThisItem) { +void UserActivityLoggerScriptingInterface::commercePurchaseSuccess(QString marketplaceID, QString contentCreator, int cost, bool firstPurchaseOfThisItem) { QJsonObject payload; payload["marketplaceID"] = marketplaceID; + payload["contentCreator"] = contentCreator; payload["cost"] = cost; payload["firstPurchaseOfThisItem"] = firstPurchaseOfThisItem; doLogAction("commercePurchaseSuccess", payload); } -void UserActivityLoggerScriptingInterface::commercePurchaseFailure(QString marketplaceID, int cost, bool firstPurchaseOfThisItem, QString errorDetails) { +void UserActivityLoggerScriptingInterface::commercePurchaseFailure(QString marketplaceID, QString contentCreator, int cost, bool firstPurchaseOfThisItem, QString errorDetails) { QJsonObject payload; payload["marketplaceID"] = marketplaceID; + payload["contentCreator"] = contentCreator; payload["cost"] = cost; payload["firstPurchaseOfThisItem"] = firstPurchaseOfThisItem; payload["errorDetails"] = errorDetails; diff --git a/libraries/networking/src/UserActivityLoggerScriptingInterface.h b/libraries/networking/src/UserActivityLoggerScriptingInterface.h index 0e08b050d7..71d411056d 100644 --- a/libraries/networking/src/UserActivityLoggerScriptingInterface.h +++ b/libraries/networking/src/UserActivityLoggerScriptingInterface.h @@ -33,8 +33,8 @@ public: Q_INVOKABLE void bubbleToggled(bool newValue); Q_INVOKABLE void bubbleActivated(); Q_INVOKABLE void logAction(QString action, QVariantMap details = QVariantMap{}); - Q_INVOKABLE void commercePurchaseSuccess(QString marketplaceID, int cost, bool firstPurchaseOfThisItem); - Q_INVOKABLE void commercePurchaseFailure(QString marketplaceID, int cost, bool firstPurchaseOfThisItem, QString errorDetails); + Q_INVOKABLE void commercePurchaseSuccess(QString marketplaceID, QString contentCreator, int cost, bool firstPurchaseOfThisItem); + Q_INVOKABLE void commercePurchaseFailure(QString marketplaceID, QString contentCreator, int cost, bool firstPurchaseOfThisItem, QString errorDetails); Q_INVOKABLE void commerceEntityRezzed(QString marketplaceID, QString source, QString type); Q_INVOKABLE void commerceWalletSetupStarted(int timestamp, QString setupAttemptID, int setupFlowVersion, QString referrer, QString currentDomain); Q_INVOKABLE void commerceWalletSetupProgress(int timestamp, QString setupAttemptID, int secondsElapsed, int currentStepNumber, QString currentStepName); diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 698dd93f29..2b016884f1 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -250,7 +250,8 @@ itemName: name, itemPrice: price ? parseInt(price, 10) : 0, itemHref: href, - referrer: referrer + referrer: referrer, + itemAuthor: author })); } From a2f2c233371f4ff997d332a8ae77cda60f1d8aaa Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 20 Dec 2017 15:40:10 -0800 Subject: [PATCH 31/49] Change three lines of code. Fix one thing. Break another. --- libraries/entities/src/EntityItemProperties.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 9f7ba1cc80..6e7fe9c1b2 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2513,7 +2513,8 @@ bool EntityItemProperties::verifySignature(const QString& publicKey, const QByte return false; } - const unsigned char* key = reinterpret_cast(publicKey.toUtf8().constData()); + auto keyByteArray = publicKey.toUtf8(); + auto key = keyByteArray.constData(); int keyLength = publicKey.length(); BIO *bio = BIO_new_mem_buf((void*)key, keyLength); @@ -2531,14 +2532,14 @@ bool EntityItemProperties::verifySignature(const QString& publicKey, const QByte // ECSDA verification prototype: note that type is currently ignored // int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen, // const unsigned char *sig, int siglen, EC_KEY *eckey); - bool answer = ECDSA_verify(0, + int answer = ECDSA_verify(0, digest, digestLength, signature, signatureLength, ec); long error = ERR_get_error(); - if (error != 0) { + if (error != 0 || answer == -1) { const char* error_str = ERR_error_string(error, NULL); qCWarning(entities) << "ERROR while verifying signature! EC error:" << error_str << "\nKey:" << publicKey << "\nutf8 Key Length:" << keyLength @@ -2552,7 +2553,7 @@ bool EntityItemProperties::verifySignature(const QString& publicKey, const QByte if (evp_key) { EVP_PKEY_free(evp_key); } - return answer; + return (answer == 1); } else { if (bio) { BIO_free(bio); From 373ef6c6ce11dceccfee7ae425e4e47aa9eee305 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 21 Dec 2017 13:48:35 -0800 Subject: [PATCH 32/49] Progress? --- interface/src/commerce/Ledger.cpp | 2 +- interface/src/commerce/Wallet.cpp | 9 +++++---- libraries/entities/src/EntityItemProperties.cpp | 8 ++++++-- libraries/entities/src/EntityTree.cpp | 7 ++++--- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index b0d293584c..33c23ccf2f 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -61,7 +61,7 @@ void Ledger::send(const QString& endpoint, const QString& success, const QString void Ledger::signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure) { auto wallet = DependencyManager::get(); - QString signature = key.isEmpty() ? "" : wallet->signWithKey(text, key); + QString signature = wallet->signWithKey(text, key); QJsonObject request; request[propertyName] = QString(text); if (!controlled_failure) { diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 69914e97a4..2f8a470b51 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -547,13 +547,16 @@ QStringList Wallet::listPublicKeys() { // the horror of code pages and so on (changing the bytes) by just returning a base64 // encoded string representing the signature (suitable for http, etc...) QString Wallet::signWithKey(const QByteArray& text, const QString& key) { - qCInfo(commerce) << "Signing text" << text << "with key" << key; EC_KEY* ecPrivateKey = NULL; + + auto keyFilePathString = keyFilePath().toStdString(); if ((ecPrivateKey = readPrivateKey(keyFilePath().toStdString().c_str()))) { unsigned char* sig = new unsigned char[ECDSA_size(ecPrivateKey)]; unsigned int signatureBytes = 0; + qCInfo(commerce) << "Signing text" << text << "with key at" << ecPrivateKey; + QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); @@ -746,12 +749,10 @@ void Wallet::handleChallengeOwnershipPacket(QSharedPointer pack } EC_KEY_free(ec); - QByteArray ba = sig.toLocal8Bit(); - const char *sigChar = ba.data(); QByteArray textByteArray; if (status > -1) { - textByteArray = QByteArray(sigChar, (int) strlen(sigChar)); + textByteArray = sig.toUtf8(); } textByteArraySize = textByteArray.size(); int certIDSize = certID.size(); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 6e7fe9c1b2..9982f4d6a1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -2540,11 +2540,15 @@ bool EntityItemProperties::verifySignature(const QString& publicKey, const QByte ec); long error = ERR_get_error(); if (error != 0 || answer == -1) { - const char* error_str = ERR_error_string(error, NULL); - qCWarning(entities) << "ERROR while verifying signature! EC error:" << error_str + qCWarning(entities) << "ERROR while verifying signature!" << "\nKey:" << publicKey << "\nutf8 Key Length:" << keyLength << "\nDigest:" << digest << "\nDigest Length:" << digestLength << "\nSignature:" << signature << "\nSignature Length:" << signatureLength; + while (error != 0) { + const char* error_str = ERR_error_string(error, NULL); + qCWarning(entities) << "EC error:" << error_str; + error = ERR_get_error(); + } } EC_KEY_free(ec); if (bio) { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index e62399ce95..3d5bf1dd12 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1189,13 +1189,14 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity key = sent.second; } - QString annotatedKey = "-----BEGIN PUBLIC KEY-----\n" + key.insert(64, "\n") + "\n-----END PUBLIC KEY-----"; - bool verificationSuccess = EntityItemProperties::verifySignature(annotatedKey.toUtf8(), actualNonce.toUtf8(), nonce.toUtf8()); + QString annotatedKey = "-----BEGIN PUBLIC KEY-----\n" + key.insert(64, "\n") + "\n-----END PUBLIC KEY-----\n"; + QByteArray hashedActualNonce = QCryptographicHash::hash(QByteArray::fromBase64(actualNonce.toUtf8()), QCryptographicHash::Sha256); + bool verificationSuccess = EntityItemProperties::verifySignature(annotatedKey.toUtf8(), hashedActualNonce, QByteArray::fromBase64(nonce.toUtf8())); if (verificationSuccess) { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded."; } else { - qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed for nonce" << actualNonce << "key" << key << "signature" << nonce; + qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed.\nHashed actual nonce (digest):" << hashedActualNonce << "\nSent nonce (signature)" << nonce << "\nKey" << key; } return verificationSuccess; From 07a1cf434a2484b2493be7ed1d64932642119047 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 21 Dec 2017 15:01:49 -0800 Subject: [PATCH 33/49] IT'S WORKING!!! --- interface/src/commerce/Ledger.cpp | 2 +- interface/src/commerce/Wallet.cpp | 2 +- libraries/entities/src/EntityTree.cpp | 5 +++-- libraries/networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 ++- 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/interface/src/commerce/Ledger.cpp b/interface/src/commerce/Ledger.cpp index 33c23ccf2f..2865392e9a 100644 --- a/interface/src/commerce/Ledger.cpp +++ b/interface/src/commerce/Ledger.cpp @@ -61,7 +61,7 @@ void Ledger::send(const QString& endpoint, const QString& success, const QString void Ledger::signedSend(const QString& propertyName, const QByteArray& text, const QString& key, const QString& endpoint, const QString& success, const QString& fail, const bool controlled_failure) { auto wallet = DependencyManager::get(); - QString signature = wallet->signWithKey(text, key); + QString signature = wallet->signWithKey(text, key); QJsonObject request; request[propertyName] = QString(text); if (!controlled_failure) { diff --git a/interface/src/commerce/Wallet.cpp b/interface/src/commerce/Wallet.cpp index 2f8a470b51..602684756f 100644 --- a/interface/src/commerce/Wallet.cpp +++ b/interface/src/commerce/Wallet.cpp @@ -555,7 +555,7 @@ QString Wallet::signWithKey(const QByteArray& text, const QString& key) { unsigned int signatureBytes = 0; - qCInfo(commerce) << "Signing text" << text << "with key at" << ecPrivateKey; + qCInfo(commerce) << "Hashing and signing plaintext" << text << "with key at address" << ecPrivateKey; QByteArray hashedPlaintext = QCryptographicHash::hash(text, QCryptographicHash::Sha256); diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 3d5bf1dd12..5afea35d1c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1190,13 +1190,14 @@ bool EntityTree::verifyNonce(const QString& certID, const QString& nonce, Entity } QString annotatedKey = "-----BEGIN PUBLIC KEY-----\n" + key.insert(64, "\n") + "\n-----END PUBLIC KEY-----\n"; - QByteArray hashedActualNonce = QCryptographicHash::hash(QByteArray::fromBase64(actualNonce.toUtf8()), QCryptographicHash::Sha256); + QByteArray hashedActualNonce = QCryptographicHash::hash(QByteArray(actualNonce.toUtf8()), QCryptographicHash::Sha256); bool verificationSuccess = EntityItemProperties::verifySignature(annotatedKey.toUtf8(), hashedActualNonce, QByteArray::fromBase64(nonce.toUtf8())); if (verificationSuccess) { qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "succeeded."; } else { - qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed.\nHashed actual nonce (digest):" << hashedActualNonce << "\nSent nonce (signature)" << nonce << "\nKey" << key; + qCDebug(entities) << "Ownership challenge for Cert ID" << certID << "failed. Actual nonce:" << actualNonce << + "\nHashed actual nonce (digest):" << hashedActualNonce << "\nSent nonce (signature)" << nonce << "\nKey" << key; } return verificationSuccess; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 207ddf6bbb..0a75e8c31b 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::HazeEffect); + return static_cast(EntityVersion::OwnershipChallengeFix); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConnectionIdentifier); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index e5cb87c379..640d9962d2 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -199,7 +199,8 @@ QDebug operator<<(QDebug debug, const PacketType& type); enum class EntityVersion : PacketVersion { StrokeColorProperty = 77, HasDynamicOwnershipTests, - HazeEffect + HazeEffect, + OwnershipChallengeFix }; enum class EntityScriptCallMethodVersion : PacketVersion { From 95c7f876bfb4a76b983d927f4578a9b0e2de0644 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 21 Dec 2017 18:34:37 -0800 Subject: [PATCH 34/49] manually force OwnershipChallengeFix to avoid StaticCertJsonVersionOne --- libraries/networking/src/udt/PacketHeaders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 640d9962d2..2c28f54014 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -197,7 +197,7 @@ uint qHash(const PacketType& key, uint seed); QDebug operator<<(QDebug debug, const PacketType& type); enum class EntityVersion : PacketVersion { - StrokeColorProperty = 77, + StrokeColorProperty = 0, HasDynamicOwnershipTests, HazeEffect, OwnershipChallengeFix From 533aa3d91896c4f4d16e65d90c2b9d9f125b94b8 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 22 Dec 2017 09:07:16 -0800 Subject: [PATCH 35/49] code review --- libraries/entities/src/EntityItem.cpp | 8 ++------ libraries/entities/src/ShapeEntityItem.cpp | 4 ++-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index fcf7519bbd..d0dca2d43e 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -1674,16 +1674,12 @@ void EntityItem::setParentID(const QUuid& value) { glm::vec3 EntityItem::getScaledDimensions() const { glm::vec3 scale = getSNScale(); - return glm::vec3(_unscaledDimensions.x * scale.x, - _unscaledDimensions.y * scale.y, - _unscaledDimensions.z * scale.z); + return _unscaledDimensions * scale; } void EntityItem::setScaledDimensions(const glm::vec3& value) { glm::vec3 parentScale = getSNScale(); - setUnscaledDimensions(glm::vec3(value.x / parentScale.x, - value.y / parentScale.y, - value.z / parentScale.z)); + setUnscaledDimensions(value * parentScale); } void EntityItem::setUnscaledDimensions(const glm::vec3& value) { diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index f564c89d21..3750bc3b57 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -206,12 +206,12 @@ void ShapeEntityItem::setColor(const QColor& value) { void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { const float MAX_FLAT_DIMENSION = 0.0001f; - if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { + if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { // enforce flatness in Y glm::vec3 newDimensions = value; newDimensions.y = MAX_FLAT_DIMENSION; EntityItem::setUnscaledDimensions(newDimensions); - } else { + } else { EntityItem::setUnscaledDimensions(value); } } From e316f71b318f1bbafc9c3cc333d0d39886202e75 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 22 Dec 2017 14:53:48 -0800 Subject: [PATCH 36/49] fix grabbing --- libraries/entities/src/EntityItem.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ddc5e9795f..f572acc2d0 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2063,17 +2063,6 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi } EntityDynamicPointer action = _objectActions[actionID]; - - action->setOwnerEntity(nullptr); - action->setIsMine(false); - - if (simulation) { - action->removeFromSimulation(simulation); - } - - bool success = true; - serializeActions(success, _allActionsDataCache); - _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; auto removedActionType = action->getType(); if ((removedActionType == DYNAMIC_TYPE_HOLD || removedActionType == DYNAMIC_TYPE_FAR_GRAB) && !stillHasGrabActions()) { _dirtyFlags &= ~Simulation::NO_BOOTSTRAPPING; @@ -2090,6 +2079,17 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi // because they should have been set correctly when the action was added // and/or when children were linked } + action->setOwnerEntity(nullptr); + action->setIsMine(false); + _objectActions.remove(actionID); + + if (simulation) { + action->removeFromSimulation(simulation); + } + + bool success = true; + serializeActions(success, _allActionsDataCache); + _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; _objectActions.remove(actionID); setDynamicDataNeedsTransmit(true); return success; From 86be684d7ad5519d30acfa329cd605b8849c1a89 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 22 Dec 2017 14:58:32 -0800 Subject: [PATCH 37/49] delete code --- libraries/entities/src/EntityItem.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index f572acc2d0..db390d9fc5 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2090,7 +2090,6 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulationPoi bool success = true; serializeActions(success, _allActionsDataCache); _dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION; - _objectActions.remove(actionID); setDynamicDataNeedsTransmit(true); return success; } From c38ef77b2640f538359e67d0f5e67cfc20d3155e Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 22 Dec 2017 15:04:06 -0800 Subject: [PATCH 38/49] fix model overlays visibility change --- libraries/render-utils/src/Model.cpp | 55 ++++++++++++++++++++-------- libraries/render-utils/src/Model.h | 6 +-- 2 files changed, 43 insertions(+), 18 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 7717ceda6f..6e0f97f57f 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -594,47 +594,72 @@ void Model::calculateTriangleSets() { } } -void Model::setVisibleInScene(bool newValue, const render::ScenePointer& scene) { - if (_isVisible != newValue) { - _isVisible = newValue; +void Model::setVisibleInScene(bool isVisible, const render::ScenePointer& scene) { + if (_isVisible != isVisible) { + _isVisible = isVisible; + + bool isLayeredInFront = _isLayeredInFront; + bool isLayeredInHUD = _isLayeredInHUD; render::Transaction transaction; foreach (auto item, _modelMeshRenderItemsMap.keys()) { - transaction.resetItem(item, _modelMeshRenderItemsMap[item]); + transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.resetItem(item, _collisionRenderItemsMap[item]); + transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + }); } scene->enqueueTransaction(transaction); } } -void Model::setLayeredInFront(bool layered, const render::ScenePointer& scene) { - if (_isLayeredInFront != layered) { - _isLayeredInFront = layered; +void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene) { + if (_isLayeredInFront != isLayeredInFront) { + _isLayeredInFront = isLayeredInFront; + + bool isVisible = _isVisible; + bool isLayeredInHUD = _isLayeredInFront; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.resetItem(item, _modelMeshRenderItemsMap[item]); + transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setLayer(isLayeredInFront, isLayeredInHUD); + }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.resetItem(item, _collisionRenderItemsMap[item]); + transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setLayer(isLayeredInFront, isLayeredInHUD); + }); } scene->enqueueTransaction(transaction); } } -void Model::setLayeredInHUD(bool layered, const render::ScenePointer& scene) { - if (_isLayeredInHUD != layered) { - _isLayeredInHUD = layered; +void Model::setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene) { + if (_isLayeredInHUD != isLayeredInHUD) { + _isLayeredInHUD = isLayeredInHUD; + + bool isVisible = _isVisible; + bool isLayeredInFront = isLayeredInFront; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { - transaction.resetItem(item, _modelMeshRenderItemsMap[item]); + transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setLayer(isLayeredInFront, isLayeredInHUD); + }); } foreach(auto item, _collisionRenderItemsMap.keys()) { - transaction.resetItem(item, _collisionRenderItemsMap[item]); + transaction.updateItem(item, [isVisible, isLayeredInFront, isLayeredInHUD](ModelMeshPartPayload& data) { + data.setKey(isVisible, isLayeredInFront || isLayeredInHUD); + data.setLayer(isLayeredInFront, isLayeredInHUD); + }); } scene->enqueueTransaction(transaction); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 50ccb22131..4df7faac84 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -82,9 +82,9 @@ public: const QUrl& getURL() const { return _url; } // new Scene/Engine rendering support - void setVisibleInScene(bool newValue, const render::ScenePointer& scene); - void setLayeredInFront(bool layered, const render::ScenePointer& scene); - void setLayeredInHUD(bool layered, const render::ScenePointer& scene); + void setVisibleInScene(bool isVisible, const render::ScenePointer& scene); + void setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& scene); + void setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& scene); bool needsFixupInScene() const; bool needsReload() const { return _needsReload; } From 2898fa557e2a93fba6361638aeb82cf99e2d65b8 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Sat, 23 Dec 2017 00:53:11 -0800 Subject: [PATCH 39/49] typo --- libraries/render-utils/src/Model.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6e0f97f57f..b91f4dd405 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -622,7 +622,7 @@ void Model::setLayeredInFront(bool isLayeredInFront, const render::ScenePointer& _isLayeredInFront = isLayeredInFront; bool isVisible = _isVisible; - bool isLayeredInHUD = _isLayeredInFront; + bool isLayeredInHUD = _isLayeredInHUD; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { @@ -646,7 +646,7 @@ void Model::setLayeredInHUD(bool isLayeredInHUD, const render::ScenePointer& sce _isLayeredInHUD = isLayeredInHUD; bool isVisible = _isVisible; - bool isLayeredInFront = isLayeredInFront; + bool isLayeredInFront = _isLayeredInFront; render::Transaction transaction; foreach(auto item, _modelMeshRenderItemsMap.keys()) { From e1b344e36de8aefa0433c5491dfcabb2bb373554 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 26 Dec 2017 10:50:10 -0800 Subject: [PATCH 40/49] handles empty json object return --- interface/src/scripting/GooglePolyScriptingInterface.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index d3b24f79f0..9629ae9b2e 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -151,6 +151,10 @@ QVariant GooglePolyScriptingInterface::parseJSON(QUrl url, int fileType) { QByteArray jsonString = getHTTPRequest(url); QJsonDocument doc = QJsonDocument::fromJson(jsonString); QJsonObject obj = doc.object(); + if (obj.isEmpty()) { + qCDebug(scriptengine) << "Assets with specified filters not found"; + return ""; + } if (obj.keys().first() == "error") { QString error = obj.value("error").toObject().value("message").toString(); qCDebug(scriptengine) << error; From 03f06aadf4a4282bf87372d698c8e30e1fd729d9 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 26 Dec 2017 11:08:10 -0800 Subject: [PATCH 41/49] keyword filters case insensitive now --- interface/src/scripting/GooglePolyScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index 9629ae9b2e..f164d6e825 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -106,7 +106,7 @@ int GooglePolyScriptingInterface::getRandIntInRange(int length) { QUrl GooglePolyScriptingInterface::formatURLQuery(QString keyword, QString category, QString format) { QString queries; - if (!validFormats.contains(format) || !validCategories.contains(category)) { + if (!validFormats.contains(format, Qt::CaseInsensitive) || !validCategories.contains(category, Qt::CaseInsensitive)) { return QUrl(""); } else { if (!keyword.isEmpty()) { From 01c1032540b9ff26b575e1b96ca983f0bcb200a5 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 27 Dec 2017 10:51:58 -0800 Subject: [PATCH 42/49] fixed constant names, added another URL check --- interface/resources/qml/js/Utils.jsc | Bin 6596 -> 0 bytes .../GooglePolyScriptingInterface.cpp | 27 +++++++++--------- .../scripting/GooglePolyScriptingInterface.h | 6 ++-- 3 files changed, 17 insertions(+), 16 deletions(-) delete mode 100644 interface/resources/qml/js/Utils.jsc diff --git a/interface/resources/qml/js/Utils.jsc b/interface/resources/qml/js/Utils.jsc deleted file mode 100644 index ab20e996b9469915ac6a89901da175143e6b5024..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6596 zcmcIoZD?EP6@Kh1ckah_<+cmm)~+s7*+{cEDOm|)Y*uPBiCux$Iwl#JYtNP&7t3}W zIXI&o4oU8EkM2n zXjl7O2dDtRuNCd{@)jY-)d!#zenqKY4sn&W{weu)twmlb!$4JTzv65rm+K1vDC#!F zU$|ZVIZ9zlW+S<`HL;hgR&M8~1sQiLyXg~6*Kx4qHtya=?){4Iz`gR%B^6)FqD(EX zPx0NgjXdr9YAbNP75KOnxYqy<89DFo`<=jA05hh+!CUJc)7q5K-I-U<4BwMhw#!Kold03qHB1qPh=(m57jV zQZO*TlsKpO<^4D&)ji|-UBpF<$-`KmCFTK~acFxKqv8qb`vJ}(jwnv6ynF{ogq(=F zep_Ap)wNGud)4)O>UtbUguEF{VOB&&#)x21=BI^yoeI;=cpet< z8yEavN0<0LF8)1^DU2eDE}X7EzTC=9#(VVvU%?VLXPX@E8u^tC$cdhzrY~ z5|TzSE|9{#2}}z<=It55SzSj%iNA*yHv6nZbjwP_N>*aF82-K7|F|4Z{3((gYY*l1 z1HmPNES&HK!VAmo!G#Z7%nSc2m&=jFSbJz;vopy0hR~Acw-O%(%P$^o0YVGQoxRBc zfA58N%nJ{-l0bHGCbwg^#q(qrrDi+!w<_$cdfT#JQtVa6B|0HZKTvD>SPT8{3FK*i zWU(iZU!oSteUbW{j!MrrowDh%hwMA*Wz%5~+1G_Km+UHco!!3?d2`uawWQAO`Fhz^ zFY9DKQ7^k1!8+Li%B~H>BZmbX7dAVWSkh#gI3&0r zaF0rAW;@0YRTR^~w|fH1=rq7T1!gIn>dAFt!Sy*C45#|hZ zyKMQfPE=zR8BZ12Iu&e;jZ`qZ;(XBNe0X7VdI#CX&hyK$=>L{qIw{h|R_2l4RI7AY z^-G-Fg*Pl@c)U6&I`)6~vWKqD3?b!JxCu1uN`cA?Q-i-75ra?*w4> z7DLeZEXfck*xy13exhOT)~XM$^JKYWuGBjYFUK{J-kQV9*AmCcI=9Ipz3t&zt&~o& zbp5o=j@d0M5iMDXSkX$%t~YJ^dxYvnP2X7@RT0fd+JSJgHI(cgqRD9&=_E-h7ipTL zi!Ra}N%Kz9JRJ@v&Ijf=afs?ImCUopaAUf5Bc(P@)^4QL#!&4B4=hC;lN+q^_W+Q1 zP^n|i{5|@(6kNweRp@!g!IB0$&XzP(9WOq8UKl6|MM0Czbbp-MJtdAmS4|C?43SDf)z9}dNlLtGo5xl*UM-i)V9TyEvOFWw5I(m_-&8|fx011{`>NNH;(6Df(rr#QsN>-}$CJna|wOpzoRcq-Fq`bAH8fghvwNyJ`N_RlpJYiGQZuHu}HZ5Pa zdE8c|q5`8P==g;$uId?L_>-ZdTT7Ja(9^jWIyw}4%`oqUj`vkn%QKo+>hkt%Am^R8 zT%)}GyrqJUtqMAFDsNlV@ Date: Wed, 27 Dec 2017 12:49:16 -0800 Subject: [PATCH 44/49] changed api key variable name --- interface/src/scripting/GooglePolyScriptingInterface.cpp | 6 +++--- interface/src/scripting/GooglePolyScriptingInterface.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/scripting/GooglePolyScriptingInterface.cpp b/interface/src/scripting/GooglePolyScriptingInterface.cpp index f164724d37..8ed5d59d07 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.cpp +++ b/interface/src/scripting/GooglePolyScriptingInterface.cpp @@ -37,7 +37,7 @@ GooglePolyScriptingInterface::GooglePolyScriptingInterface() { } void GooglePolyScriptingInterface::setAPIKey(const QString& key) { - authCode = key; + _authCode = key; } QString GooglePolyScriptingInterface::getAssetList(const QString& keyword, const QString& category, const QString& format) { @@ -94,7 +94,7 @@ QString GooglePolyScriptingInterface::getModelInfo(const QString& input) { } } QString urlString(GET_POLY_URL); - urlString = urlString.replace("model", name) + "key=" + authCode; + urlString = urlString.replace("model", name) + "key=" + _authCode; qCDebug(scriptengine) << "Google URL request: " << urlString; QUrl url(urlString); QString json = parseJSON(url, 2).toString(); @@ -123,7 +123,7 @@ QUrl GooglePolyScriptingInterface::formatURLQuery(const QString& keyword, const if (!format.isEmpty()) { queries.append("&format=" + format); } - QString urlString(LIST_POLY_URL + "key=" + authCode + queries); + QString urlString(LIST_POLY_URL + "key=" + _authCode + queries); return QUrl(urlString); } } diff --git a/interface/src/scripting/GooglePolyScriptingInterface.h b/interface/src/scripting/GooglePolyScriptingInterface.h index 04a60f0614..fdd3597bec 100644 --- a/interface/src/scripting/GooglePolyScriptingInterface.h +++ b/interface/src/scripting/GooglePolyScriptingInterface.h @@ -34,7 +34,7 @@ public slots: QString getModelInfo(const QString& input); private: - QString authCode; + QString _authCode; QUrl formatURLQuery(const QString& keyword, const QString& category, const QString& format); QString getModelURL(const QUrl& url); From 25e76c668bf05eeb8eea01240c80b86b8d1c9958 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 2 Jan 2018 12:22:40 -0800 Subject: [PATCH 45/49] Fix marketplacesInject.js for local Metaverse --- scripts/system/html/js/marketplacesInject.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/system/html/js/marketplacesInject.js b/scripts/system/html/js/marketplacesInject.js index 2b016884f1..4820c4bf1d 100644 --- a/scripts/system/html/js/marketplacesInject.js +++ b/scripts/system/html/js/marketplacesInject.js @@ -30,6 +30,7 @@ var userIsLoggedIn = false; var walletNeedsSetup = false; var metaverseServerURL = "https://metaverse.highfidelity.com"; + var marketplaceBaseURL = "https://highfidelity.com"; function injectCommonCode(isDirectoryPage) { @@ -58,7 +59,7 @@ ); // Footer. - var isInitialHiFiPage = location.href === metaverseServerURL + "/marketplace?"; + var isInitialHiFiPage = location.href === marketplaceBaseURL + "/marketplace?"; $("body").append( '
' + (!isInitialHiFiPage ? '' : '') + @@ -70,7 +71,7 @@ // Footer actions. $("#back-button").on("click", function () { - (document.referrer !== "") ? window.history.back() : window.location = (metaverseServerURL + "/marketplace?"); + (document.referrer !== "") ? window.history.back() : window.location = (marketplaceBaseURL + "/marketplace?"); }); $("#all-markets").on("click", function () { EventBridge.emitWebEvent(GOTO_DIRECTORY); @@ -89,7 +90,7 @@ window.location = "https://clara.io/library?gameCheck=true&public=true"; }); $('#exploreHifiMarketplace').on('click', function () { - window.location = "http://www.highfidelity.com/marketplace"; + window.location = marketplaceBaseURL + "/marketplace"; }); } @@ -658,9 +659,9 @@ var HIFI_ITEM_PAGE = 3; var pageType = DIRECTORY; - if (location.href.indexOf("highfidelity.com/") !== -1) { pageType = HIFI; } + if (location.href.indexOf(marketplaceBaseURL + "/") !== -1) { pageType = HIFI; } if (location.href.indexOf("clara.io/") !== -1) { pageType = CLARA; } - if (location.href.indexOf("highfidelity.com/marketplace/items/") !== -1) { pageType = HIFI_ITEM_PAGE; } + if (location.href.indexOf(marketplaceBaseURL + "/marketplace/items/") !== -1) { pageType = HIFI_ITEM_PAGE; } injectCommonCode(pageType === DIRECTORY); switch (pageType) { @@ -695,6 +696,11 @@ userIsLoggedIn = !!parsedJsonMessage.data.userIsLoggedIn; walletNeedsSetup = !!parsedJsonMessage.data.walletNeedsSetup; metaverseServerURL = parsedJsonMessage.data.metaverseServerURL; + if (metaverseServerURL.indexOf('metaverse.') !== -1) { + marketplaceBaseURL = metaverseServerURL.replace('metaverse.', ''); + } else { + marketplaceBaseURL = metaverseServerURL; + } injectCode(); } } From 47a209dc4c5e4829641902dd2d09a2ac94746fa4 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 2 Jan 2018 13:11:00 -0800 Subject: [PATCH 46/49] Make things slightly better? --- interface/resources/qml/js/Utils.jsc | Bin 0 -> 6596 bytes scripts/system/html/js/marketplacesInject.js | 9 +++------ 2 files changed, 3 insertions(+), 6 deletions(-) create mode 100644 interface/resources/qml/js/Utils.jsc diff --git a/interface/resources/qml/js/Utils.jsc b/interface/resources/qml/js/Utils.jsc new file mode 100644 index 0000000000000000000000000000000000000000..ab20e996b9469915ac6a89901da175143e6b5024 GIT binary patch literal 6596 zcmcIoZD?EP6@Kh1ckah_<+cmm)~+s7*+{cEDOm|)Y*uPBiCux$Iwl#JYtNP&7t3}W zIXI&o4oU8EkM2n zXjl7O2dDtRuNCd{@)jY-)d!#zenqKY4sn&W{weu)twmlb!$4JTzv65rm+K1vDC#!F zU$|ZVIZ9zlW+S<`HL;hgR&M8~1sQiLyXg~6*Kx4qHtya=?){4Iz`gR%B^6)FqD(EX zPx0NgjXdr9YAbNP75KOnxYqy<89DFo`<=jA05hh+!CUJc)7q5K-I-U<4BwMhw#!Kold03qHB1qPh=(m57jV zQZO*TlsKpO<^4D&)ji|-UBpF<$-`KmCFTK~acFxKqv8qb`vJ}(jwnv6ynF{ogq(=F zep_Ap)wNGud)4)O>UtbUguEF{VOB&&#)x21=BI^yoeI;=cpet< z8yEavN0<0LF8)1^DU2eDE}X7EzTC=9#(VVvU%?VLXPX@E8u^tC$cdhzrY~ z5|TzSE|9{#2}}z<=It55SzSj%iNA*yHv6nZbjwP_N>*aF82-K7|F|4Z{3((gYY*l1 z1HmPNES&HK!VAmo!G#Z7%nSc2m&=jFSbJz;vopy0hR~Acw-O%(%P$^o0YVGQoxRBc zfA58N%nJ{-l0bHGCbwg^#q(qrrDi+!w<_$cdfT#JQtVa6B|0HZKTvD>SPT8{3FK*i zWU(iZU!oSteUbW{j!MrrowDh%hwMA*Wz%5~+1G_Km+UHco!!3?d2`uawWQAO`Fhz^ zFY9DKQ7^k1!8+Li%B~H>BZmbX7dAVWSkh#gI3&0r zaF0rAW;@0YRTR^~w|fH1=rq7T1!gIn>dAFt!Sy*C45#|hZ zyKMQfPE=zR8BZ12Iu&e;jZ`qZ;(XBNe0X7VdI#CX&hyK$=>L{qIw{h|R_2l4RI7AY z^-G-Fg*Pl@c)U6&I`)6~vWKqD3?b!JxCu1uN`cA?Q-i-75ra?*w4> z7DLeZEXfck*xy13exhOT)~XM$^JKYWuGBjYFUK{J-kQV9*AmCcI=9Ipz3t&zt&~o& zbp5o=j@d0M5iMDXSkX$%t~YJ^dxYvnP2X7@RT0fd+JSJgHI(cgqRD9&=_E-h7ipTL zi!Ra}N%Kz9JRJ@v&Ijf=afs?ImCUopaAUf5Bc(P@)^4QL#!&4B4=hC;lN+q^_W+Q1 zP^n|i{5|@(6kNweRp@!g!IB0$&XzP(9WOq8UKl6|MM0Czbbp-MJtdAmS4|C?43SDf)z9}dNlLtGo5xl*UM-i)V9TyEvOFWw5I(m_-&8|fx011{`>NNH;(6Df(rr#QsN>-}$CJna|wOpzoRcq-Fq`bAH8fghvwNyJ`N_RlpJYiGQZuHu}HZ5Pa zdE8c|q5`8P==g;$uId?L_>-ZdTT7Ja(9^jWIyw}4%`oqUj`vkn%QKo+>hkt%Am^R8 zT%)}GyrqJUtqMAFDsNlV@ Date: Tue, 2 Jan 2018 15:26:11 -0800 Subject: [PATCH 47/49] Add a link to My Purchases from Wallet Home --- .../qml/hifi/commerce/wallet/WalletHome.qml | 26 +++++++++++++++++-- scripts/system/commerce/wallet.js | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml index 5a5eeeb91f..42ee44d584 100644 --- a/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml +++ b/interface/resources/qml/hifi/commerce/wallet/WalletHome.qml @@ -197,14 +197,36 @@ Item { anchors.topMargin: 26; anchors.left: parent.left; anchors.leftMargin: 20; - anchors.right: parent.right; - anchors.rightMargin: 30; + width: paintedWidth; height: 30; // Text size size: 22; // Style color: hifi.colors.baseGrayHighlight; } + + RalewaySemiBold { + id: myPurchasesLink; + text: 'My Purchases'; + // Anchors + anchors.top: parent.top; + anchors.topMargin: 26; + anchors.right: parent.right; + anchors.rightMargin: 20; + width: paintedWidth; + height: 30; + y: 4; + // Text size + size: 18; + // Style + color: hifi.colors.baseGrayHighlight; + horizontalAlignment: Text.AlignRight; + + onLinkActivated: { + sendSignalToWallet({method: 'goToPurchases_fromWalletHome'}); + } + } + ListModel { id: tempTransactionHistoryModel; } diff --git a/scripts/system/commerce/wallet.js b/scripts/system/commerce/wallet.js index cde44e78c9..b3e3134380 100644 --- a/scripts/system/commerce/wallet.js +++ b/scripts/system/commerce/wallet.js @@ -103,6 +103,7 @@ case 'transactionHistory_linkClicked': tablet.gotoWebScreen(message.marketplaceLink, MARKETPLACES_INJECT_SCRIPT_URL); break; + case 'goToPurchases_fromWalletHome': case 'goToPurchases': tablet.pushOntoStack(MARKETPLACE_PURCHASES_QML_PATH); break; From 63801ce802c71c428b7199fe71bfa35f2c85418a Mon Sep 17 00:00:00 2001 From: milad Date: Tue, 2 Jan 2018 17:15:23 -0800 Subject: [PATCH 48/49] add .jsc, remove duplicate qmlc, and remote Utils.jsc --- .gitignore | 4 ++-- interface/resources/qml/js/Utils.jsc | Bin 6596 -> 0 bytes 2 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 interface/resources/qml/js/Utils.jsc diff --git a/.gitignore b/.gitignore index 665238e7da..76ae194c82 100644 --- a/.gitignore +++ b/.gitignore @@ -20,7 +20,7 @@ android/.gradle android/app/src/main/jniLibs # VSCode -# List taken from Github Global Ignores master@435c4d92 +# List taken from Github Global Ignores master@435c4d92 # https://github.com/github/gitignore/commits/master/Global/VisualStudioCode.gitignore .vscode/* !.vscode/settings.json @@ -66,7 +66,7 @@ gvr-interface/libs/* # ignore files for various dev environments TAGS *.sw[po] -*.qmlc +*.jsc # ignore QML compilation output *.qmlc diff --git a/interface/resources/qml/js/Utils.jsc b/interface/resources/qml/js/Utils.jsc deleted file mode 100644 index ab20e996b9469915ac6a89901da175143e6b5024..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6596 zcmcIoZD?EP6@Kh1ckah_<+cmm)~+s7*+{cEDOm|)Y*uPBiCux$Iwl#JYtNP&7t3}W zIXI&o4oU8EkM2n zXjl7O2dDtRuNCd{@)jY-)d!#zenqKY4sn&W{weu)twmlb!$4JTzv65rm+K1vDC#!F zU$|ZVIZ9zlW+S<`HL;hgR&M8~1sQiLyXg~6*Kx4qHtya=?){4Iz`gR%B^6)FqD(EX zPx0NgjXdr9YAbNP75KOnxYqy<89DFo`<=jA05hh+!CUJc)7q5K-I-U<4BwMhw#!Kold03qHB1qPh=(m57jV zQZO*TlsKpO<^4D&)ji|-UBpF<$-`KmCFTK~acFxKqv8qb`vJ}(jwnv6ynF{ogq(=F zep_Ap)wNGud)4)O>UtbUguEF{VOB&&#)x21=BI^yoeI;=cpet< z8yEavN0<0LF8)1^DU2eDE}X7EzTC=9#(VVvU%?VLXPX@E8u^tC$cdhzrY~ z5|TzSE|9{#2}}z<=It55SzSj%iNA*yHv6nZbjwP_N>*aF82-K7|F|4Z{3((gYY*l1 z1HmPNES&HK!VAmo!G#Z7%nSc2m&=jFSbJz;vopy0hR~Acw-O%(%P$^o0YVGQoxRBc zfA58N%nJ{-l0bHGCbwg^#q(qrrDi+!w<_$cdfT#JQtVa6B|0HZKTvD>SPT8{3FK*i zWU(iZU!oSteUbW{j!MrrowDh%hwMA*Wz%5~+1G_Km+UHco!!3?d2`uawWQAO`Fhz^ zFY9DKQ7^k1!8+Li%B~H>BZmbX7dAVWSkh#gI3&0r zaF0rAW;@0YRTR^~w|fH1=rq7T1!gIn>dAFt!Sy*C45#|hZ zyKMQfPE=zR8BZ12Iu&e;jZ`qZ;(XBNe0X7VdI#CX&hyK$=>L{qIw{h|R_2l4RI7AY z^-G-Fg*Pl@c)U6&I`)6~vWKqD3?b!JxCu1uN`cA?Q-i-75ra?*w4> z7DLeZEXfck*xy13exhOT)~XM$^JKYWuGBjYFUK{J-kQV9*AmCcI=9Ipz3t&zt&~o& zbp5o=j@d0M5iMDXSkX$%t~YJ^dxYvnP2X7@RT0fd+JSJgHI(cgqRD9&=_E-h7ipTL zi!Ra}N%Kz9JRJ@v&Ijf=afs?ImCUopaAUf5Bc(P@)^4QL#!&4B4=hC;lN+q^_W+Q1 zP^n|i{5|@(6kNweRp@!g!IB0$&XzP(9WOq8UKl6|MM0Czbbp-MJtdAmS4|C?43SDf)z9}dNlLtGo5xl*UM-i)V9TyEvOFWw5I(m_-&8|fx011{`>NNH;(6Df(rr#QsN>-}$CJna|wOpzoRcq-Fq`bAH8fghvwNyJ`N_RlpJYiGQZuHu}HZ5Pa zdE8c|q5`8P==g;$uId?L_>-ZdTT7Ja(9^jWIyw}4%`oqUj`vkn%QKo+>hkt%Am^R8 zT%)}GyrqJUtqMAFDsNlV@ Date: Wed, 3 Jan 2018 11:28:39 -0800 Subject: [PATCH 49/49] Fix Security Pic Change dialog after QML security changes --- .../qml/hifi/commerce/wallet/SecurityImageChange.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/commerce/wallet/SecurityImageChange.qml b/interface/resources/qml/hifi/commerce/wallet/SecurityImageChange.qml index b261743434..2ad2b75553 100644 --- a/interface/resources/qml/hifi/commerce/wallet/SecurityImageChange.qml +++ b/interface/resources/qml/hifi/commerce/wallet/SecurityImageChange.qml @@ -66,7 +66,7 @@ Item { source: "image://security/securityImage"; cache: false; onVisibleChanged: { - commerce.getSecurityImage(); + Commerce.getSecurityImage(); } } Item { @@ -194,7 +194,7 @@ Item { securityImageSubmitButton.text = "Submitting..."; securityImageSubmitButton.enabled = false; var securityImagePath = securityImageSelection.getImagePathFromImageID(securityImageSelection.getSelectedImageIndex()) - commerce.chooseSecurityImage(securityImagePath); + Commerce.chooseSecurityImage(securityImagePath); } } }