From 3a7290c3ede88e7e402c1547d6133621c19c62fa Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Mon, 8 Jan 2018 12:15:13 -0800 Subject: [PATCH 01/25] starting 2d image entity type --- libraries/entities/src/EntityTypes.h | 1 + libraries/entities/src/FlatImageEntity.cpp | 74 ++++++++++++++++++++++ libraries/entities/src/FlatImageEntity.h | 41 ++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 libraries/entities/src/FlatImageEntity.cpp create mode 100644 libraries/entities/src/FlatImageEntity.h diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 316bf2b813..dac36f28dd 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -49,6 +49,7 @@ public: PolyVox, PolyLine, Shape, + Image, LAST = Shape } EntityType; diff --git a/libraries/entities/src/FlatImageEntity.cpp b/libraries/entities/src/FlatImageEntity.cpp new file mode 100644 index 0000000000..9eb3f64bcb --- /dev/null +++ b/libraries/entities/src/FlatImageEntity.cpp @@ -0,0 +1,74 @@ +// +// FlatImageEntity.cpp +// libraries/entities/src +// +// Created by Elisa Lupin-Jimenez on 1/3/18. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include +#include +#include +#include + +#include "EntitiesLogging.h" +#include "EntityItemProperties.h" +#include "EntityTree.h" +#include "EntityTreeElement.h" +#include "ResourceCache.h" +#include "ShapeEntityItem.h" +#include "FlatImageEntity.h" + +const QString FlatImageEntity::DEFAULT_IMAGE_URL = QString(""); + +EntityItemPointer FlatImageEntity::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + EntityItemPointer entity(new FlatImageEntity(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); + entity->setProperties(properties); + return entity; +} + +FlatImageEntity::FlatImageEntity(const EntityItemID& entityItemID) : EntityItem(entityItemID) { + _type = EntityTypes::Image; +} + +EntityItemProperties FlatImageEntity::getProperties(EntityPropertyFlags desiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class + properties.setShape("Image"); + return properties; +} + +bool FlatImageEntity::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class + + SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape); + + if (somethingChanged) { + bool wantDebug = false; + if (wantDebug) { + uint64_t now = usecTimestampNow(); + int elapsed = now - getLastEdited(); + qCDebug(entities) << "FlatImageEntity::setProperties() AFTER update... edited AGO=" << elapsed << + "now=" << now << " getLastEdited()=" << getLastEdited(); + } + setLastEdited(properties.getLastEdited()); + } + return somethingChanged; +} + +void FlatImageEntity::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const { + + bool successPropertyFits = true; + APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape())); +} + diff --git a/libraries/entities/src/FlatImageEntity.h b/libraries/entities/src/FlatImageEntity.h new file mode 100644 index 0000000000..08c13f8f9f --- /dev/null +++ b/libraries/entities/src/FlatImageEntity.h @@ -0,0 +1,41 @@ +// +// FlatImageEntity.h +// libraries/entities/src +// +// Created by Elisa Lupin-Jimenez on 1/3/18. +// Copyright 2018 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_FlatImageEntity_h +#define hifi_FlatImageEntity_h + +#include "EntityItem.h" + +class FlatImageEntity : public EntityItem { +public: + static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + FlatImageEntity(const EntityItemID& entityItemID); + + ALLOW_INSTANTIATION // This class can be instantiated + + // methods for getting/setting all properties of an entity + virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; + virtual bool setProperties(const EntityItemProperties& properties) override; + + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, + EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, + EntityPropertyFlags& requestedProperties, + EntityPropertyFlags& propertyFlags, + EntityPropertyFlags& propertiesDidntFit, + int& propertyCount, + OctreeElement::AppendState& appendState) const override; + + static const QString DEFAULT_IMAGE_URL; + +}; + +#endif // hifi_FlatImageEntity_h From fdca8ab93eef09e21af8883e20b5072441300b80 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 9 Jan 2018 17:46:24 -0800 Subject: [PATCH 02/25] added image button to edit.js, working on connecting to cpp --- .../resources/qml/hifi/tablet/EditTabView.qml | 12 ++++++ .../entities/src/EntityItemProperties.cpp | 4 ++ libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 3 ++ libraries/entities/src/EntityTypes.cpp | 1 + libraries/entities/src/EntityTypes.h | 2 +- libraries/entities/src/FlatImageEntity.cpp | 43 +++++++++++++++++-- libraries/entities/src/FlatImageEntity.h | 12 ++++++ scripts/system/edit.js | 14 +++++- 9 files changed, 87 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/EditTabView.qml b/interface/resources/qml/hifi/tablet/EditTabView.qml index e94325f399..482469d355 100644 --- a/interface/resources/qml/hifi/tablet/EditTabView.qml +++ b/interface/resources/qml/hifi/tablet/EditTabView.qml @@ -101,6 +101,18 @@ TabView { } } + // for image + NewEntityButton { + icon: "icons/create-icons/25-web-1-01.svg" + text: "IMAGE" + onClicked: { + editRoot.sendToScript({ + method: "newEntityButtonClicked", params: { buttonName: "newImageButton" } + }); + editTabView.currentIndex = 2 + } + } + NewEntityButton { icon: "icons/create-icons/25-web-1-01.svg" text: "WEB" diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index e2a5ddf8b5..a1c51b650f 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1369,6 +1369,10 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_DPI, properties.getDPI()); } + if (properties.getType() == EntityTypes::Image) { + APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, properties.getImageURL()); + } + if (properties.getType() == EntityTypes::Text) { APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight()); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 3e0770f386..5bd6836336 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -194,6 +194,7 @@ public: DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup); DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup); DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString, ""); + DEFINE_PROPERTY_REF(PROP_IMAGE_URL, ImageURL, imageURL, QString, ""); DEFINE_PROPERTY(PROP_LINE_WIDTH, LineWidth, lineWidth, float, LineEntityItem::DEFAULT_LINE_WIDTH); DEFINE_PROPERTY_REF(LINE_POINTS, LinePoints, linePoints, QVector, QVector()); DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 90438ab01c..4768ebed86 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -42,6 +42,9 @@ enum EntityPropertyList { PROP_ANIMATION_ALLOW_TRANSLATION, PROP_RELAY_PARENT_JOINTS, + // for image + PROP_IMAGE_URL, + // these properties are supported by the EntityItem base class PROP_REGISTRATION_POINT, PROP_ANGULAR_VELOCITY, diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index cb17c28fd7..e53b9d02f6 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -89,6 +89,7 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const EntityItemPointer newEntityItem = NULL; EntityTypeFactory factory = NULL; if (entityType >= 0 && entityType <= LAST) { + qCDebug(entities) << "type: " << entityType; factory = _factories[entityType]; } if (factory) { diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index dac36f28dd..8d986c8090 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -48,8 +48,8 @@ public: Line, PolyVox, PolyLine, - Shape, Image, + Shape, LAST = Shape } EntityType; diff --git a/libraries/entities/src/FlatImageEntity.cpp b/libraries/entities/src/FlatImageEntity.cpp index 9eb3f64bcb..66a5702747 100644 --- a/libraries/entities/src/FlatImageEntity.cpp +++ b/libraries/entities/src/FlatImageEntity.cpp @@ -38,14 +38,14 @@ FlatImageEntity::FlatImageEntity(const EntityItemID& entityItemID) : EntityItem( EntityItemProperties FlatImageEntity::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class - properties.setShape("Image"); + properties.setShape("Quad"); return properties; } bool FlatImageEntity::setProperties(const EntityItemProperties& properties) { bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class - SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape); + //SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape); if (somethingChanged) { bool wantDebug = false; @@ -60,6 +60,13 @@ bool FlatImageEntity::setProperties(const EntityItemProperties& properties) { return somethingChanged; } +// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time +EntityPropertyFlags FlatImageEntity::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); + + return requestedProperties; +} + void FlatImageEntity::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, @@ -69,6 +76,36 @@ void FlatImageEntity::appendSubclassData(OctreePacketData* packetData, EncodeBit OctreeElement::AppendState& appendState) const { bool successPropertyFits = true; - APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape())); + // Using "Quad" shape as defined in ShapeEntityItem.cpp + APPEND_ENTITY_PROPERTY(PROP_SHAPE, "Quad"); +} + +int FlatImageEntity::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData, + bool& somethingChanged) { + + int bytesRead = 0; + const unsigned char* dataAt = data; + + return bytesRead; +} + +void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { + const float MAX_FLAT_DIMENSION = 0.0001f; + if (value.y > MAX_FLAT_DIMENSION) { + // enforce flatness in Y + glm::vec3 newDimensions = value; + newDimensions.y = MAX_FLAT_DIMENSION; + EntityItem::setUnscaledDimensions(newDimensions); + } else { + EntityItem::setUnscaledDimensions(value); + } +} + +QString FlatImageEntity::getImageURL() const { + return resultWithReadLock([&] { + return _imageURL; + }); } diff --git a/libraries/entities/src/FlatImageEntity.h b/libraries/entities/src/FlatImageEntity.h index 08c13f8f9f..4dd91b1215 100644 --- a/libraries/entities/src/FlatImageEntity.h +++ b/libraries/entities/src/FlatImageEntity.h @@ -26,6 +26,8 @@ public: virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; + EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; + virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, @@ -34,7 +36,17 @@ public: int& propertyCount, OctreeElement::AppendState& appendState) const override; + int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData, + bool& somethingChanged) override; + + static const QString DEFAULT_IMAGE_URL; + QString getImageURL() const; + +protected: + QString _imageURL; }; diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 863c185cb4..4241468de1 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -251,7 +251,8 @@ var toolBar = (function () { // Align entity with Avatar orientation. properties.rotation = MyAvatar.orientation; - var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Web"]; + // added image here + var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web"]; if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { // Adjust position of entity per bounding box prior to creating it. @@ -286,6 +287,7 @@ var toolBar = (function () { properties.userData = JSON.stringify({ grabbableKey: { grabbable: false } }); } + print("properties.type: " + properties.type); entityID = Entities.addEntity(properties); if (properties.type === "ParticleEffect") { @@ -538,6 +540,16 @@ var toolBar = (function () { }); }); + // for image button + addButton("newImageButton", "web-01.svg", function () { + print("new image message is received"); + createNewEntity({ + type: "Image", + dimensions: DEFAULT_DIMENSIONS, + sourceUrl: "https://highfidelity.com/" + }); + }); + addButton("newWebButton", "web-01.svg", function () { createNewEntity({ type: "Web", From fc0e87d5eaa13cf7c97a1ab2ab8a8eac264576d5 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 10 Jan 2018 17:08:55 -0800 Subject: [PATCH 03/25] more infrastructure links --- .../entities/src/EntityItemProperties.cpp | 9 ++++ .../entities/src/EntityScriptingInterface.cpp | 2 + libraries/entities/src/EntityTree.cpp | 1 + libraries/entities/src/EntityTypes.cpp | 4 +- ...latImageEntity.cpp => ImageEntityItem.cpp} | 42 ++++++++++++------- .../{FlatImageEntity.h => ImageEntityItem.h} | 13 +++--- scripts/system/edit.js | 2 +- 7 files changed, 51 insertions(+), 22 deletions(-) rename libraries/entities/src/{FlatImageEntity.cpp => ImageEntityItem.cpp} (70%) rename libraries/entities/src/{FlatImageEntity.h => ImageEntityItem.h} (85%) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index a1c51b650f..fc8ca18fb6 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -590,6 +590,11 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString()); } + // Image only + if (_type == EntityTypes::Image) { + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL); + } + // Web only if (_type == EntityTypes::Web) { COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOURCE_URL, sourceUrl); @@ -1734,6 +1739,10 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); } + if (properties.getType() == EntityTypes::Image) { + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IMAGE_URL, QString, setImageURL); + } + if (properties.getType() == EntityTypes::Text) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4342f0e683..cab4251d97 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -266,6 +266,8 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties bool success = true; if (_entityTree) { _entityTree->withWriteLock([&] { + propertiesWithSimID.getType(); + qCDebug(entities) << "check 2 type: " << propertiesWithSimID.getType(); EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID); if (entity) { if (propertiesWithSimID.queryAACubeRelatedPropertyChanged()) { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index bf29f3bec9..56c3aa216c 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -514,6 +514,7 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti // construct the instance of the entity EntityTypes::EntityType type = props.getType(); + qCDebug(entities) << "check 3 type: " << type; result = EntityTypes::constructEntityItem(type, entityID, props); if (result) { diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index e53b9d02f6..2e4a0e89a9 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -28,6 +28,7 @@ #include "LineEntityItem.h" #include "PolyVoxEntityItem.h" #include "PolyLineEntityItem.h" +#include "ImageEntityItem.h" #include "ShapeEntityItem.h" QMap EntityTypes::_typeToNameMap; @@ -47,6 +48,7 @@ REGISTER_ENTITY_TYPE(Zone) REGISTER_ENTITY_TYPE(Line) REGISTER_ENTITY_TYPE(PolyVox) REGISTER_ENTITY_TYPE(PolyLine) +REGISTER_ENTITY_TYPE(Image) REGISTER_ENTITY_TYPE(Shape) REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, ShapeEntityItem::boxFactory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, ShapeEntityItem::sphereFactory) @@ -89,7 +91,7 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const EntityItemPointer newEntityItem = NULL; EntityTypeFactory factory = NULL; if (entityType >= 0 && entityType <= LAST) { - qCDebug(entities) << "type: " << entityType; + qCDebug(entities) << "check 4 type: " << entityType; factory = _factories[entityType]; } if (factory) { diff --git a/libraries/entities/src/FlatImageEntity.cpp b/libraries/entities/src/ImageEntityItem.cpp similarity index 70% rename from libraries/entities/src/FlatImageEntity.cpp rename to libraries/entities/src/ImageEntityItem.cpp index 66a5702747..a94374f7b5 100644 --- a/libraries/entities/src/FlatImageEntity.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -1,5 +1,5 @@ // -// FlatImageEntity.cpp +// ImageEntityItem.cpp // libraries/entities/src // // Created by Elisa Lupin-Jimenez on 1/3/18. @@ -22,27 +22,27 @@ #include "EntityTreeElement.h" #include "ResourceCache.h" #include "ShapeEntityItem.h" -#include "FlatImageEntity.h" +#include "ImageEntityItem.h" -const QString FlatImageEntity::DEFAULT_IMAGE_URL = QString(""); +const QString ImageEntityItem::DEFAULT_IMAGE_URL = QString(""); -EntityItemPointer FlatImageEntity::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - EntityItemPointer entity(new FlatImageEntity(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); +EntityItemPointer ImageEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + EntityItemPointer entity(new ImageEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); entity->setProperties(properties); return entity; } -FlatImageEntity::FlatImageEntity(const EntityItemID& entityItemID) : EntityItem(entityItemID) { +ImageEntityItem::ImageEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) { _type = EntityTypes::Image; } -EntityItemProperties FlatImageEntity::getProperties(EntityPropertyFlags desiredProperties) const { +EntityItemProperties ImageEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class properties.setShape("Quad"); return properties; } -bool FlatImageEntity::setProperties(const EntityItemProperties& properties) { +bool ImageEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class //SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape); @@ -52,7 +52,7 @@ bool FlatImageEntity::setProperties(const EntityItemProperties& properties) { if (wantDebug) { uint64_t now = usecTimestampNow(); int elapsed = now - getLastEdited(); - qCDebug(entities) << "FlatImageEntity::setProperties() AFTER update... edited AGO=" << elapsed << + qCDebug(entities) << "ImageEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << "now=" << now << " getLastEdited()=" << getLastEdited(); } setLastEdited(properties.getLastEdited()); @@ -61,13 +61,13 @@ bool FlatImageEntity::setProperties(const EntityItemProperties& properties) { } // TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time -EntityPropertyFlags FlatImageEntity::getEntityProperties(EncodeBitstreamParams& params) const { +EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); return requestedProperties; } -void FlatImageEntity::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, +void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, EntityPropertyFlags& requestedProperties, EntityPropertyFlags& propertyFlags, @@ -80,7 +80,7 @@ void FlatImageEntity::appendSubclassData(OctreePacketData* packetData, EncodeBit APPEND_ENTITY_PROPERTY(PROP_SHAPE, "Quad"); } -int FlatImageEntity::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, +int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) { @@ -91,7 +91,7 @@ int FlatImageEntity::readEntitySubclassDataFromBuffer(const unsigned char* data, return bytesRead; } -void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { +/*void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { const float MAX_FLAT_DIMENSION = 0.0001f; if (value.y > MAX_FLAT_DIMENSION) { // enforce flatness in Y @@ -101,9 +101,23 @@ void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { } else { EntityItem::setUnscaledDimensions(value); } +}*/ + +void ImageEntityItem::setImageURL(const QString& value) { + withWriteLock([&] { + if (_imageURL != value) { + auto newURL = QUrl::fromUserInput(value); + + if (newURL.isValid()) { + _imageURL = newURL.toDisplayString(); + } else { + qCDebug(entities) << "Clearing image entity source URL since" << value << "cannot be parsed to a valid URL."; + } + } + }); } -QString FlatImageEntity::getImageURL() const { +QString ImageEntityItem::getImageURL() const { return resultWithReadLock([&] { return _imageURL; }); diff --git a/libraries/entities/src/FlatImageEntity.h b/libraries/entities/src/ImageEntityItem.h similarity index 85% rename from libraries/entities/src/FlatImageEntity.h rename to libraries/entities/src/ImageEntityItem.h index 4dd91b1215..55e8fc7b36 100644 --- a/libraries/entities/src/FlatImageEntity.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -1,5 +1,5 @@ // -// FlatImageEntity.h +// ImageEntityItem.h // libraries/entities/src // // Created by Elisa Lupin-Jimenez on 1/3/18. @@ -9,16 +9,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifndef hifi_FlatImageEntity_h -#define hifi_FlatImageEntity_h +#ifndef hifi_ImageEntityItem_h +#define hifi_ImageEntityItem_h #include "EntityItem.h" -class FlatImageEntity : public EntityItem { +class ImageEntityItem : public EntityItem { public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); - FlatImageEntity(const EntityItemID& entityItemID); + ImageEntityItem(const EntityItemID& entityItemID); ALLOW_INSTANTIATION // This class can be instantiated @@ -43,6 +43,7 @@ public: static const QString DEFAULT_IMAGE_URL; + virtual void setImageURL(const QString& value); QString getImageURL() const; protected: @@ -50,4 +51,4 @@ protected: }; -#endif // hifi_FlatImageEntity_h +#endif // hifi_ImageEntityItem_h diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 4241468de1..bcd39ab0a5 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -287,7 +287,7 @@ var toolBar = (function () { properties.userData = JSON.stringify({ grabbableKey: { grabbable: false } }); } - print("properties.type: " + properties.type); + print("check 1 type: " + properties.type); entityID = Entities.addEntity(properties); if (properties.type === "ParticleEffect") { From 72d8f90ec1b8950dc06bacff76ff84c114df07f7 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Thu, 11 Jan 2018 14:43:19 -0800 Subject: [PATCH 04/25] not sure why entities don't render with these changes --- libraries/entities/src/EntityItemProperties.h | 1 + libraries/entities/src/EntityTypes.cpp | 2 +- libraries/entities/src/ImageEntityItem.cpp | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 5bd6836336..e121332374 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -67,6 +67,7 @@ class EntityItemProperties { friend class ParticleEffectEntityItem; // TODO: consider removing this friend relationship and use public methods friend class ZoneEntityItem; // TODO: consider removing this friend relationship and use public methods friend class WebEntityItem; // TODO: consider removing this friend relationship and use public methods + friend class ImageEntityItem; friend class LineEntityItem; // TODO: consider removing this friend relationship and use public methods friend class PolyVoxEntityItem; // TODO: consider removing this friend relationship and use public methods friend class PolyLineEntityItem; // TODO: consider removing this friend relationship and use public methods diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 2e4a0e89a9..47ec408374 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -91,7 +91,7 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const EntityItemPointer newEntityItem = NULL; EntityTypeFactory factory = NULL; if (entityType >= 0 && entityType <= LAST) { - qCDebug(entities) << "check 4 type: " << entityType; + qCDebug(entities) << "check 4 type: " << entityType << ", name: " << properties.getName(); factory = _factories[entityType]; } if (factory) { diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index a94374f7b5..2e6432ba19 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -24,7 +24,7 @@ #include "ShapeEntityItem.h" #include "ImageEntityItem.h" -const QString ImageEntityItem::DEFAULT_IMAGE_URL = QString(""); +const QString ImageEntityItem::DEFAULT_IMAGE_URL(""); EntityItemPointer ImageEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { EntityItemPointer entity(new ImageEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); From 3d000d3d011396aee7ae664d8c64f7f2ffaf77d8 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Thu, 11 Jan 2018 16:11:01 -0800 Subject: [PATCH 05/25] changed packet number --- libraries/networking/src/udt/PacketHeaders.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index c48c6bfc0b..1ceb9b8e73 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -31,7 +31,6 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityData: case PacketType::EntityPhysics: return static_cast(EntityVersion::SoftEntities); - case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::RemovedJurisdictions); case PacketType::AvatarIdentity: From 6f76650789ba9454e8d8634098e7519d1a3daa43 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 16 Jan 2018 12:17:39 -0800 Subject: [PATCH 06/25] updated with master --- libraries/entities/src/ImageEntityItem.cpp | 9 +++++++-- libraries/entities/src/ImageEntityItem.h | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 2e6432ba19..41bd55ee85 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -38,6 +38,8 @@ ImageEntityItem::ImageEntityItem(const EntityItemID& entityItemID) : EntityItem( EntityItemProperties ImageEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class + COPY_ENTITY_PROPERTY_TO_PROPERTIES(imageURL, getImageURL); + // Using "Quad" shape as defined in ShapeEntityItem.cpp properties.setShape("Quad"); return properties; } @@ -45,7 +47,7 @@ EntityItemProperties ImageEntityItem::getProperties(EntityPropertyFlags desiredP bool ImageEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class - //SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(imageURL, setImageURL); if (somethingChanged) { bool wantDebug = false; @@ -63,7 +65,7 @@ bool ImageEntityItem::setProperties(const EntityItemProperties& properties) { // TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); - + requestedProperties += PROP_IMAGE_URL; return requestedProperties; } @@ -78,6 +80,7 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit bool successPropertyFits = true; // Using "Quad" shape as defined in ShapeEntityItem.cpp APPEND_ENTITY_PROPERTY(PROP_SHAPE, "Quad"); + APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, _imageURL); } int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, @@ -88,6 +91,8 @@ int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesRead = 0; const unsigned char* dataAt = data; + READ_ENTITY_PROPERTY(PROP_IMAGE_URL, QString, setImageURL); + return bytesRead; } diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index 55e8fc7b36..229b6f190f 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -13,6 +13,7 @@ #define hifi_ImageEntityItem_h #include "EntityItem.h" +#include "ShapeEntityItem.h" class ImageEntityItem : public EntityItem { public: @@ -49,6 +50,9 @@ public: protected: QString _imageURL; + entity::Shape _shape{ entity::Shape::Quad }; + ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_BOX }; + }; #endif // hifi_ImageEntityItem_h From c9c55af66153882bc6fec49cbfd736b2d3308bf8 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 16 Jan 2018 17:37:49 -0800 Subject: [PATCH 07/25] setting up properties page (not complete) --- libraries/entities/src/ImageEntityItem.cpp | 16 +++++++++++++--- libraries/entities/src/ImageEntityItem.h | 4 ++++ scripts/system/html/entityProperties.html | 9 +++++++++ scripts/system/html/js/entityProperties.js | 11 +++++++++++ 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 41bd55ee85..1a6ab1e146 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -79,7 +79,6 @@ void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit bool successPropertyFits = true; // Using "Quad" shape as defined in ShapeEntityItem.cpp - APPEND_ENTITY_PROPERTY(PROP_SHAPE, "Quad"); APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, _imageURL); } @@ -96,7 +95,7 @@ int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, return bytesRead; } -/*void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { +void ImageEntityItem::setUnscaledDimensions(const glm::vec3& value) { const float MAX_FLAT_DIMENSION = 0.0001f; if (value.y > MAX_FLAT_DIMENSION) { // enforce flatness in Y @@ -106,7 +105,7 @@ int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, } else { EntityItem::setUnscaledDimensions(value); } -}*/ +} void ImageEntityItem::setImageURL(const QString& value) { withWriteLock([&] { @@ -128,3 +127,14 @@ QString ImageEntityItem::getImageURL() const { }); } +/*void ImageEntityItem::computeShapeInfo(ShapeInfo& info) { + // This will be called whenever DIRTY_SHAPE flag (set by dimension change, etc) + // is set. + + EntityItem::computeShapeInfo(info); +}*/ + +// This value specifies how the shape should be treated by physics calculations. +ShapeType ImageEntityItem::getShapeType() const { + return _collisionShapeType; +} diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index 229b6f190f..f3f4fbe6c7 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -42,11 +42,15 @@ public: EntityPropertyFlags& propertyFlags, bool overwriteLocalData, bool& somethingChanged) override; + void setUnscaledDimensions(const glm::vec3& value) override; static const QString DEFAULT_IMAGE_URL; virtual void setImageURL(const QString& value); QString getImageURL() const; + //virtual void computeShapeInfo(ShapeInfo& info) override; + virtual ShapeType getShapeType() const override; + protected: QString _imageURL; diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index b93974ee77..6e8178d408 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -714,6 +714,15 @@ +
+ + ImageM + +
+ + +
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 7008d0df66..05a1b2576b 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -133,6 +133,11 @@ function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) { }; } +function createImageURLUpdateFunction(propertyName) { + return function() { + updateProperty(propertyName, this.value); + } +} function createEmitTextPropertyUpdateFunction(propertyName) { return function() { @@ -621,6 +626,8 @@ function loaded() { var elModelTextures = document.getElementById("property-model-textures"); var elModelOriginalTextures = document.getElementById("property-model-original-textures"); + var elImageURL = document.getElementById("property-image-url"); + var elWebSourceURL = document.getElementById("property-web-source-url"); var elWebDPI = document.getElementById("property-web-dpi"); @@ -985,6 +992,8 @@ function loaded() { } else if (properties.type === "Web") { elWebSourceURL.value = properties.sourceUrl; elWebDPI.value = properties.dpi; + } else if (properties.type === "Image") { + elImageURL.value = properties.imageURL; } else if (properties.type === "Text") { elTextText.value = properties.text; elTextLineHeight.value = properties.lineHeight.toFixed(4); @@ -1352,6 +1361,8 @@ function loaded() { elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape')); + elImageURL.addEventListener('change', createImageURLUpdateFunction('imageURL')); + elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); elWebDPI.addEventListener('change', createEmitNumberPropertyUpdateFunction('dpi', 0)); From ecb53192add37a7bb70c88d2c00b6568aab0db7d Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 17 Jan 2018 11:57:40 -0800 Subject: [PATCH 08/25] edit properties reflect image members --- scripts/system/html/css/edit-style.css | 49 +++++++++++++++++++++- scripts/system/html/js/entityProperties.js | 7 ++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 736d42d593..58acc317bd 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -448,7 +448,7 @@ input[type=checkbox]:checked + label:hover { border: 1.5pt solid black; } -.shape-section, .light-section, .model-section, .web-section, .hyperlink-section, .text-section, .zone-section { +.shape-section, .light-section, .model-section, .web-section, .image-section, .hyperlink-section, .text-section, .zone-section { display: table; } @@ -564,6 +564,7 @@ hr { .text-group[collapsed="true"] ~ .text-group, .zone-group[collapsed="true"] ~ .zone-group, +.image-group[collapsed="true"] ~ .image-group, .web-group[collapsed="true"] ~ .web-group, .hyperlink-group[collapsed="true"] ~ .hyperlink-group, .spatial-group[collapsed="true"] ~ .spatial-group, @@ -1466,6 +1467,9 @@ input#reset-to-natural-dimensions { #properties-list.ShapeMenu #text, #properties-list.BoxMenu #text, #properties-list.SphereMenu #text, +#properties-list.ShapeMenu #image, +#properties-list.BoxMenu #image, +#properties-list.SphereMenu #image, #properties-list.ShapeMenu #web, #properties-list.BoxMenu #web, #properties-list.SphereMenu #web { @@ -1497,6 +1501,7 @@ input#reset-to-natural-dimensions { #properties-list.ParticleEffectMenu #shape-list, #properties-list.ParticleEffectMenu #text, #properties-list.ParticleEffectMenu #web, +#properties-list.ParticleEffectMenu #image, #properties-list.ParticleEffectMenu #zone { display: none; } @@ -1527,6 +1532,7 @@ input#reset-to-natural-dimensions { #properties-list.LightMenu #model, #properties-list.LightMenu #zone, #properties-list.LightMenu #text, +#properties-list.LightMenu #image, #properties-list.LightMenu #web { display: none; } @@ -1563,6 +1569,7 @@ input#reset-to-natural-dimensions { #properties-list.ModelMenu #light, #properties-list.ModelMenu #zone, #properties-list.ModelMenu #text, +#properties-list.ModelMenu #image, #properties-list.ModelMenu #web { display: none; } @@ -1599,6 +1606,7 @@ input#reset-to-natural-dimensions { #properties-list.ZoneMenu #light, #properties-list.ZoneMenu #model, #properties-list.ZoneMenu #text, +#properties-list.ZoneMenu #image, #properties-list.ZoneMenu #web { display: none; } @@ -1609,6 +1617,43 @@ input#reset-to-natural-dimensions { } +/* ----- Order of Menu items for Image ----- */ +#properties-list.ImageMenu #general { + order: 1; +} +#properties-list.ImageMenu #image { + order: 2; +} +#properties-list.ImageMenu #collision-info { + order: 3; +} +#properties-list.ImageMenu #physical { + order: 4; +} +#properties-list.ImageMenu #spatial { + order: 5; +} +#properties-list.ImageMenu #behavior { + order: 6; +} +#properties-list.ImageMenu #hyperlink { + order: 7; +} +/* sections to hide */ +#properties-list.ImageMenu #light, +#properties-list.ImageMenu #model, +#properties-list.ImageMenu #zone, +#properties-list.ImageMenu #web, +#properties-list.ImageMenu #text { + display: none; +} +/* items to hide */ +#properties-list.ImageMenu #shape-list, +#properties-list.ImageMenu #base-color-section { + display: none; +} + + /* ----- Order of Menu items for Web ----- */ #properties-list.WebMenu #general { order: 1; @@ -1635,6 +1680,7 @@ input#reset-to-natural-dimensions { #properties-list.WebMenu #light, #properties-list.WebMenu #model, #properties-list.WebMenu #zone, +#properties-list.WebMenu #image, #properties-list.WebMenu #text { display: none; } @@ -1672,6 +1718,7 @@ input#reset-to-natural-dimensions { #properties-list.TextMenu #light, #properties-list.TextMenu #model, #properties-list.TextMenu #zone, +#properties-list.TextMenu #image, #properties-list.TextMenu #web { display: none; } diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 05a1b2576b..54b50de106 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -19,6 +19,7 @@ var ICON_FOR_TYPE = { ParticleEffect: "", Model: "", Web: "q", + Image: "q", // what do? Text: "l", Light: "p", Zone: "o", @@ -134,9 +135,9 @@ function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) { } function createImageURLUpdateFunction(propertyName) { - return function() { + return function () { updateProperty(propertyName, this.value); - } + }; } function createEmitTextPropertyUpdateFunction(propertyName) { @@ -1735,7 +1736,7 @@ function loaded() { } // Dropdowns - // For each dropdown the following replacement is created in place of the oriringal dropdown... + // For each dropdown the following replacement is created in place of the original dropdown... // Structure created: //
//
display textcarat
From dc5f29aa58268a9abdc9b82f6a9bc41828c28832 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 17 Jan 2018 17:57:09 -0800 Subject: [PATCH 09/25] entity item properties hooked up for image --- libraries/entities/src/EntityItemProperties.cpp | 9 +++++++++ scripts/system/edit.js | 2 +- scripts/system/html/js/entityProperties.js | 3 ++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index fc8ca18fb6..3729c75f3d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -350,6 +350,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_MODE, ambientLightMode); CHECK_PROPERTY_CHANGE(PROP_SKYBOX_MODE, skyboxMode); + CHECK_PROPERTY_CHANGE(PROP_IMAGE_URL, imageURL); + CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl); CHECK_PROPERTY_CHANGE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize); CHECK_PROPERTY_CHANGE(PROP_VOXEL_DATA, voxelData); @@ -785,6 +787,8 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientLightMode, AmbientLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(skyboxMode, SkyboxMode); + COPY_PROPERTY_FROM_QSCRIPTVALUE(imageURL, QString, setImageURL); + COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl); COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, glmVec3, setVoxelVolumeSize); COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelData, QByteArray, setVoxelData); @@ -945,6 +949,8 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(ambientLightMode); COPY_PROPERTY_IF_CHANGED(skyboxMode); + COPY_PROPERTY_IF_CHANGED(imageURL); + COPY_PROPERTY_IF_CHANGED(sourceUrl); COPY_PROPERTY_IF_CHANGED(voxelVolumeSize); COPY_PROPERTY_IF_CHANGED(voxelData); @@ -1138,6 +1144,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t); ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString); ADD_PROPERTY_TO_MAP(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString); + ADD_PROPERTY_TO_MAP(PROP_IMAGE_URL, ImageURL, imageURL, QString); ADD_PROPERTY_TO_MAP(PROP_LINE_WIDTH, LineWidth, lineWidth, float); ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString); @@ -2060,6 +2067,8 @@ void EntityItemProperties::markAllChanged() { _skybox.markAllChanged(); _haze.markAllChanged(); + _imageURLChanged = true; + _sourceUrlChanged = true; _voxelVolumeSizeChanged = true; _voxelDataChanged = true; diff --git a/scripts/system/edit.js b/scripts/system/edit.js index bcd39ab0a5..5f976e07d3 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -546,7 +546,7 @@ var toolBar = (function () { createNewEntity({ type: "Image", dimensions: DEFAULT_DIMENSIONS, - sourceUrl: "https://highfidelity.com/" + imageURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg" }); }); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 54b50de106..7c3af548ba 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -19,7 +19,7 @@ var ICON_FOR_TYPE = { ParticleEffect: "", Model: "", Web: "q", - Image: "q", // what do? + Image: "q", // change this when image type icon added Text: "l", Light: "p", Zone: "o", @@ -995,6 +995,7 @@ function loaded() { elWebDPI.value = properties.dpi; } else if (properties.type === "Image") { elImageURL.value = properties.imageURL; + //elImageURL.value = properties.sourceURL; } else if (properties.type === "Text") { elTextText.value = properties.text; elTextLineHeight.value = properties.lineHeight.toFixed(4); From 576d683d3bb62baef14c4ddc2f3696ca71679258 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Thu, 18 Jan 2018 14:40:33 -0800 Subject: [PATCH 10/25] initial changes to incorporate snap model --- libraries/entities/src/EntityScriptingInterface.cpp | 2 -- libraries/entities/src/EntityTree.cpp | 1 - libraries/entities/src/EntityTypes.cpp | 4 +++- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index cab4251d97..4342f0e683 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -266,8 +266,6 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties bool success = true; if (_entityTree) { _entityTree->withWriteLock([&] { - propertiesWithSimID.getType(); - qCDebug(entities) << "check 2 type: " << propertiesWithSimID.getType(); EntityItemPointer entity = _entityTree->addEntity(id, propertiesWithSimID); if (entity) { if (propertiesWithSimID.queryAACubeRelatedPropertyChanged()) { diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 56c3aa216c..bf29f3bec9 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -514,7 +514,6 @@ EntityItemPointer EntityTree::addEntity(const EntityItemID& entityID, const Enti // construct the instance of the entity EntityTypes::EntityType type = props.getType(); - qCDebug(entities) << "check 3 type: " << type; result = EntityTypes::constructEntityItem(type, entityID, props); if (result) { diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 47ec408374..6326df3cc1 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -91,7 +91,9 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const EntityItemPointer newEntityItem = NULL; EntityTypeFactory factory = NULL; if (entityType >= 0 && entityType <= LAST) { - qCDebug(entities) << "check 4 type: " << entityType << ", name: " << properties.getName(); + if (getEntityTypeName(entityType) == "Image") { + entityType = getEntityTypeFromName("Web"); + } factory = _factories[entityType]; } if (factory) { From ceb621a52151d20bfa66dd4eb09779c45f003901 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Mon, 22 Jan 2018 11:36:58 -0800 Subject: [PATCH 11/25] reverted protocol change for images --- libraries/entities/src/EntityItemProperties.cpp | 16 ++++++++-------- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/EntityPropertyFlags.h | 4 ++-- libraries/entities/src/EntityTypes.cpp | 7 ++----- libraries/entities/src/EntityTypes.h | 2 +- libraries/entities/src/ImageEntityItem.cpp | 8 ++++++-- libraries/entities/src/ImageEntityItem.h | 4 ++++ scripts/system/edit.js | 10 +++++++++- 8 files changed, 33 insertions(+), 20 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 3729c75f3d..48ad9601ba 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -350,7 +350,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_MODE, ambientLightMode); CHECK_PROPERTY_CHANGE(PROP_SKYBOX_MODE, skyboxMode); - CHECK_PROPERTY_CHANGE(PROP_IMAGE_URL, imageURL); + //CHECK_PROPERTY_CHANGE(PROP_IMAGE_URL, imageURL); CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl); CHECK_PROPERTY_CHANGE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize); @@ -593,9 +593,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool } // Image only - if (_type == EntityTypes::Image) { + /*if (_type == EntityTypes::Image) { COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL); - } + }*/ // Web only if (_type == EntityTypes::Web) { @@ -1144,7 +1144,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t); ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString); ADD_PROPERTY_TO_MAP(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString); - ADD_PROPERTY_TO_MAP(PROP_IMAGE_URL, ImageURL, imageURL, QString); + //ADD_PROPERTY_TO_MAP(PROP_IMAGE_URL, ImageURL, imageURL, QString); ADD_PROPERTY_TO_MAP(PROP_LINE_WIDTH, LineWidth, lineWidth, float); ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString); @@ -1381,9 +1381,9 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_DPI, properties.getDPI()); } - if (properties.getType() == EntityTypes::Image) { + /*if (properties.getType() == EntityTypes::Image) { APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, properties.getImageURL()); - } + }*/ if (properties.getType() == EntityTypes::Text) { APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText()); @@ -1746,9 +1746,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); } - if (properties.getType() == EntityTypes::Image) { + /*if (properties.getType() == EntityTypes::Image) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IMAGE_URL, QString, setImageURL); - } + }*/ if (properties.getType() == EntityTypes::Text) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index e121332374..14544cd4d1 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -67,7 +67,7 @@ class EntityItemProperties { friend class ParticleEffectEntityItem; // TODO: consider removing this friend relationship and use public methods friend class ZoneEntityItem; // TODO: consider removing this friend relationship and use public methods friend class WebEntityItem; // TODO: consider removing this friend relationship and use public methods - friend class ImageEntityItem; + //friend class ImageEntityItem; friend class LineEntityItem; // TODO: consider removing this friend relationship and use public methods friend class PolyVoxEntityItem; // TODO: consider removing this friend relationship and use public methods friend class PolyLineEntityItem; // TODO: consider removing this friend relationship and use public methods diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 4768ebed86..ec8f4e08c8 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -42,8 +42,8 @@ enum EntityPropertyList { PROP_ANIMATION_ALLOW_TRANSLATION, PROP_RELAY_PARENT_JOINTS, - // for image - PROP_IMAGE_URL, + /*// for image + PROP_IMAGE_URL,*/ // these properties are supported by the EntityItem base class PROP_REGISTRATION_POINT, diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 6326df3cc1..6bf5a176a7 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -28,7 +28,7 @@ #include "LineEntityItem.h" #include "PolyVoxEntityItem.h" #include "PolyLineEntityItem.h" -#include "ImageEntityItem.h" +//#include "ImageEntityItem.h" #include "ShapeEntityItem.h" QMap EntityTypes::_typeToNameMap; @@ -48,7 +48,7 @@ REGISTER_ENTITY_TYPE(Zone) REGISTER_ENTITY_TYPE(Line) REGISTER_ENTITY_TYPE(PolyVox) REGISTER_ENTITY_TYPE(PolyLine) -REGISTER_ENTITY_TYPE(Image) +//REGISTER_ENTITY_TYPE(Image) REGISTER_ENTITY_TYPE(Shape) REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, ShapeEntityItem::boxFactory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, ShapeEntityItem::sphereFactory) @@ -91,9 +91,6 @@ EntityItemPointer EntityTypes::constructEntityItem(EntityType entityType, const EntityItemPointer newEntityItem = NULL; EntityTypeFactory factory = NULL; if (entityType >= 0 && entityType <= LAST) { - if (getEntityTypeName(entityType) == "Image") { - entityType = getEntityTypeFromName("Web"); - } factory = _factories[entityType]; } if (factory) { diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 8d986c8090..6fe4274820 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -48,7 +48,7 @@ public: Line, PolyVox, PolyLine, - Image, + //Image, Shape, LAST = Shape } EntityType; diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index 1a6ab1e146..e30d85257e 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/* NOT IN USE + #include #include @@ -127,14 +129,16 @@ QString ImageEntityItem::getImageURL() const { }); } -/*void ImageEntityItem::computeShapeInfo(ShapeInfo& info) { +void ImageEntityItem::computeShapeInfo(ShapeInfo& info) { // This will be called whenever DIRTY_SHAPE flag (set by dimension change, etc) // is set. EntityItem::computeShapeInfo(info); -}*/ +} // This value specifies how the shape should be treated by physics calculations. ShapeType ImageEntityItem::getShapeType() const { return _collisionShapeType; } + +*/ diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h index f3f4fbe6c7..276d21e6f0 100644 --- a/libraries/entities/src/ImageEntityItem.h +++ b/libraries/entities/src/ImageEntityItem.h @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/* NOT IN USE + #ifndef hifi_ImageEntityItem_h #define hifi_ImageEntityItem_h @@ -60,3 +62,5 @@ protected: }; #endif // hifi_ImageEntityItem_h + +*/ diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 5f976e07d3..1d02fed787 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -540,7 +540,7 @@ var toolBar = (function () { }); }); - // for image button + /*// for image button addButton("newImageButton", "web-01.svg", function () { print("new image message is received"); createNewEntity({ @@ -548,6 +548,14 @@ var toolBar = (function () { dimensions: DEFAULT_DIMENSIONS, imageURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg" }); + });*/ + addButton("newImageButton", "web-01.svg", function () { + createNewEntity({ + type: "Model", + dimensions: DEFAULT_DIMENSIONS, + modelURL: "http://hifi-content.s3.amazonaws.com/alan/dev/Test/snapshot.fbx", + textures: JSON.stringify({ "tex.picture": "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg" }) + }); }); addButton("newWebButton", "web-01.svg", function () { From 308e481e63f5d19db4f8548c3a8689d60a22958f Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Mon, 22 Jan 2018 17:46:12 -0800 Subject: [PATCH 12/25] switch to image property list not working --- scripts/system/edit.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 1d02fed787..6f48e1167a 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -252,7 +252,7 @@ var toolBar = (function () { properties.rotation = MyAvatar.orientation; // added image here - var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web"]; + var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Web"]; if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { // Adjust position of entity per bounding box prior to creating it. @@ -287,7 +287,6 @@ var toolBar = (function () { properties.userData = JSON.stringify({ grabbableKey: { grabbable: false } }); } - print("check 1 type: " + properties.type); entityID = Entities.addEntity(properties); if (properties.type === "ParticleEffect") { @@ -540,20 +539,21 @@ var toolBar = (function () { }); }); - /*// for image button - addButton("newImageButton", "web-01.svg", function () { - print("new image message is received"); - createNewEntity({ - type: "Image", - dimensions: DEFAULT_DIMENSIONS, - imageURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg" - }); - });*/ addButton("newImageButton", "web-01.svg", function () { createNewEntity({ type: "Model", - dimensions: DEFAULT_DIMENSIONS, + // make constant for this later + dimensions: { + x: 4.16, + y: 0.02, + z: 2.58 + }, modelURL: "http://hifi-content.s3.amazonaws.com/alan/dev/Test/snapshot.fbx", + imageURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg", + // will this work? + /*get textures() { + return JSON.stringify({ "tex.picture": this.imageURL }); + }*/ textures: JSON.stringify({ "tex.picture": "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg" }) }); }); From 42151b8fd47f6b32d3662d9d599096ec4d290408 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 23 Jan 2018 14:50:41 -0800 Subject: [PATCH 13/25] creating new image entity opens image property options --- .../entities/src/EntityItemProperties.cpp | 12 +- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/ImageEntityItem.cpp | 2 +- scripts/system/edit.js | 6 +- scripts/system/html/js/entityProperties.js | 123 ++++++++++++++++++ 5 files changed, 136 insertions(+), 9 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 48ad9601ba..7fcfc00ee8 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -592,8 +592,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString()); } - // Image only - /*if (_type == EntityTypes::Image) { + + + /*// Image only + if (_type == EntityTypes::Image) { COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL); }*/ @@ -787,7 +789,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientLightMode, AmbientLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(skyboxMode, SkyboxMode); - COPY_PROPERTY_FROM_QSCRIPTVALUE(imageURL, QString, setImageURL); + //COPY_PROPERTY_FROM_QSCRIPTVALUE(imageURL, QString, setImageURL); COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl); COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, glmVec3, setVoxelVolumeSize); @@ -949,7 +951,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(ambientLightMode); COPY_PROPERTY_IF_CHANGED(skyboxMode); - COPY_PROPERTY_IF_CHANGED(imageURL); + //COPY_PROPERTY_IF_CHANGED(imageURL); COPY_PROPERTY_IF_CHANGED(sourceUrl); COPY_PROPERTY_IF_CHANGED(voxelVolumeSize); @@ -2067,7 +2069,7 @@ void EntityItemProperties::markAllChanged() { _skybox.markAllChanged(); _haze.markAllChanged(); - _imageURLChanged = true; + //_imageURLChanged = true; _sourceUrlChanged = true; _voxelVolumeSizeChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 14544cd4d1..5ca28a12c5 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -195,7 +195,7 @@ public: DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup); DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup); DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString, ""); - DEFINE_PROPERTY_REF(PROP_IMAGE_URL, ImageURL, imageURL, QString, ""); + //DEFINE_PROPERTY_REF(PROP_IMAGE_URL, ImageURL, imageURL, QString, ""); DEFINE_PROPERTY(PROP_LINE_WIDTH, LineWidth, lineWidth, float, LineEntityItem::DEFAULT_LINE_WIDTH); DEFINE_PROPERTY_REF(LINE_POINTS, LinePoints, linePoints, QVector, QVector()); DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString, ""); diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp index e30d85257e..9969a39ed0 100644 --- a/libraries/entities/src/ImageEntityItem.cpp +++ b/libraries/entities/src/ImageEntityItem.cpp @@ -35,7 +35,7 @@ EntityItemPointer ImageEntityItem::factory(const EntityItemID& entityID, const E } ImageEntityItem::ImageEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) { - _type = EntityTypes::Image; + //_type = EntityTypes::Image; } EntityItemProperties ImageEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 6f48e1167a..a5c236a6c9 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -253,6 +253,8 @@ var toolBar = (function () { // added image here var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Web"]; + //var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web"]; + if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { // Adjust position of entity per bounding box prior to creating it. @@ -539,6 +541,7 @@ var toolBar = (function () { }); }); + // for image button addButton("newImageButton", "web-01.svg", function () { createNewEntity({ type: "Model", @@ -548,8 +551,7 @@ var toolBar = (function () { y: 0.02, z: 2.58 }, - modelURL: "http://hifi-content.s3.amazonaws.com/alan/dev/Test/snapshot.fbx", - imageURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg", + modelURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx", // will this work? /*get textures() { return JSON.stringify({ "tex.picture": this.imageURL }); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 7c3af548ba..2b90f8ddfa 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -511,6 +511,10 @@ function loaded() { var elPropertiesList = document.getElementById("properties-list"); var elID = document.getElementById("property-id"); var elType = document.getElementById("property-type"); +<<<<<<< HEAD +======= + debugPrint("the type is: " + JSON.stringify(elType)); +>>>>>>> creating new image entity opens image property options var elTypeIcon = document.getElementById("type-icon"); var elName = document.getElementById("property-name"); var elLocked = document.getElementById("property-locked"); @@ -661,16 +665,28 @@ function loaded() { var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); // Skybox +<<<<<<< HEAD var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit"); var elZoneSkyboxModeDisabled = document.getElementById("property-zone-skybox-mode-disabled"); var elZoneSkyboxModeEnabled = document.getElementById("property-zone-skybox-mode-enabled"); +======= + var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit"); + var elZoneSkyboxModeDisabled = document.getElementById("property-zone-skybox-mode-disabled"); + var elZoneSkyboxModeEnabled = document.getElementById("property-zone-skybox-mode-enabled"); +>>>>>>> creating new image entity opens image property options // Ambient light var elCopySkyboxURLToAmbientURL = document.getElementById("copy-skybox-url-to-ambient-url"); +<<<<<<< HEAD var elZoneAmbientLightModeInherit = document.getElementById("property-zone-ambient-light-mode-inherit"); var elZoneAmbientLightModeDisabled = document.getElementById("property-zone-ambient-light-mode-disabled"); var elZoneAmbientLightModeEnabled = document.getElementById("property-zone-ambient-light-mode-enabled"); +======= + var elZoneAmbientLightModeInherit = document.getElementById("property-zone-ambient-light-mode-inherit"); + var elZoneAmbientLightModeDisabled = document.getElementById("property-zone-ambient-light-mode-disabled"); + var elZoneAmbientLightModeEnabled = document.getElementById("property-zone-ambient-light-mode-enabled"); +>>>>>>> creating new image entity opens image property options var elZoneAmbientLightIntensity = document.getElementById("property-zone-key-ambient-intensity"); var elZoneAmbientLightURL = document.getElementById("property-zone-key-ambient-url"); @@ -787,7 +803,11 @@ function loaded() { } else { properties = data.selections[0].properties; +<<<<<<< HEAD +======= + debugPrint("props: " + JSON.stringify(properties)); +>>>>>>> creating new image entity opens image property options if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null && editor !== null) { saveJSONUserData(true); } @@ -796,6 +816,14 @@ function loaded() { lastEntityID = '"' + properties.id + '"'; elID.value = properties.id; +<<<<<<< HEAD +======= + // image is not yet a separate entity type + if (properties.type === "Model" && properties.modelURL === "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx") { + properties.type = "Image"; + } + +>>>>>>> creating new image entity opens image property options // Create class name for css ruleset filtering elPropertiesList.className = properties.type + 'Menu'; @@ -1024,9 +1052,15 @@ function loaded() { } else if (properties.type === "Zone") { // Key light +<<<<<<< HEAD elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit'); elZoneKeyLightModeDisabled.checked = (properties.keyLightMode === 'disabled'); elZoneKeyLightModeEnabled.checked = (properties.keyLightMode === 'enabled'); +======= + elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit'); + elZoneKeyLightModeDisabled.checked = (properties.keyLightMode === 'disabled'); + elZoneKeyLightModeEnabled.checked = (properties.keyLightMode === 'enabled'); +>>>>>>> creating new image entity opens image property options elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")"; @@ -1038,6 +1072,7 @@ function loaded() { elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2); // Skybox +<<<<<<< HEAD elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit'); elZoneSkyboxModeDisabled.checked = (properties.skyboxMode === 'disabled'); elZoneSkyboxModeEnabled.checked = (properties.skyboxMode === 'enabled'); @@ -1046,14 +1081,30 @@ function loaded() { elZoneAmbientLightModeInherit.checked = (properties.ambientLightMode === 'inherit'); elZoneAmbientLightModeDisabled.checked = (properties.ambientLightMode === 'disabled'); elZoneAmbientLightModeEnabled.checked = (properties.ambientLightMode === 'enabled'); +======= + elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit'); + elZoneSkyboxModeDisabled.checked = (properties.skyboxMode === 'disabled'); + elZoneSkyboxModeEnabled.checked = (properties.skyboxMode === 'enabled'); + + // Ambient light + elZoneAmbientLightModeInherit.checked = (properties.ambientLightMode === 'inherit'); + elZoneAmbientLightModeDisabled.checked = (properties.ambientLightMode === 'disabled'); + elZoneAmbientLightModeEnabled.checked = (properties.ambientLightMode === 'enabled'); +>>>>>>> creating new image entity opens image property options elZoneAmbientLightIntensity.value = properties.ambientLight.ambientIntensity.toFixed(2); elZoneAmbientLightURL.value = properties.ambientLight.ambientURL; // Haze +<<<<<<< HEAD elZoneHazeModeInherit.checked = (properties.hazeMode === 'inherit'); elZoneHazeModeDisabled.checked = (properties.hazeMode === 'disabled'); elZoneHazeModeEnabled.checked = (properties.hazeMode === 'enabled'); +======= + elZoneHazeModeInherit.checked = (properties.hazeMode === 'inherit'); + elZoneHazeModeDisabled.checked = (properties.hazeMode === 'disabled'); + elZoneHazeModeEnabled.checked = (properties.hazeMode === 'enabled'); +>>>>>>> creating new image entity opens image property options elZoneHazeRange.value = properties.haze.hazeRange.toFixed(0); elZoneHazeColor.style.backgroundColor = "rgb(" + @@ -1319,15 +1370,24 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', +<<<<<<< HEAD submit: false, // We don't want to have a submission button +======= +>>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-color-control2').attr('active', 'true'); }, onHide: function(colpick) { $('#property-color-control2').attr('active', 'false'); }, +<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); +======= + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); +>>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); } })); @@ -1343,15 +1403,24 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', +<<<<<<< HEAD submit: false, // We don't want to have a submission button +======= +>>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-light-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-light-color').attr('active', 'false'); }, +<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); +======= + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); +>>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); } })); @@ -1400,15 +1469,24 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', +<<<<<<< HEAD submit: false, // We don't want to have a submission button +======= +>>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-text-text-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-text-text-color').attr('active', 'false'); }, +<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); +======= + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); +>>>>>>> creating new image entity opens image property options $(el).attr('active', 'false'); emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b); } @@ -1424,15 +1502,24 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', +<<<<<<< HEAD submit: false, // We don't want to have a submission button +======= +>>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-text-background-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-text-background-color').attr('active', 'false'); }, +<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); +======= + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); +>>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b); } })); @@ -1449,15 +1536,24 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', +<<<<<<< HEAD submit: false, // We don't want to have a submission button +======= +>>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-zone-key-light-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-key-light-color').attr('active', 'false'); }, +<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); +======= + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); +>>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight'); } })); @@ -1518,15 +1614,24 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', +<<<<<<< HEAD submit: false, // We don't want to have a submission button +======= +>>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-zone-haze-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-haze-color').attr('active', 'false'); }, +<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); +======= + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); +>>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('hazeColor', rgb.r, rgb.g, rgb.b, 'haze'); } })); @@ -1543,15 +1648,24 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', +<<<<<<< HEAD submit: false, // We don't want to have a submission button +======= +>>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-zone-haze-glare-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-haze-glare-color').attr('active', 'false'); }, +<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); +======= + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); +>>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('hazeGlareColor', rgb.r, rgb.g, rgb.b, 'haze'); } })); @@ -1585,15 +1699,24 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', +<<<<<<< HEAD submit: false, // We don't want to have a submission button +======= +>>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-zone-skybox-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-skybox-color').attr('active', 'false'); }, +<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); +======= + onSubmit: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + $(el).colpickHide(); +>>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox'); } })); From fe3bc00baa0cb1bcaaa3090e5ca3e438ba47874a Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 23 Jan 2018 16:45:54 -0800 Subject: [PATCH 14/25] loading and rendering atp and http image files --- scripts/system/html/js/entityProperties.js | 131 ++------------------- 1 file changed, 7 insertions(+), 124 deletions(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 2b90f8ddfa..e7526fa2e0 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -136,7 +136,8 @@ function createEmitGroupNumberPropertyUpdateFunction(group, propertyName) { function createImageURLUpdateFunction(propertyName) { return function () { - updateProperty(propertyName, this.value); + var newTextures = JSON.stringify({ "tex.picture": this.value }); + updateProperty(propertyName, newTextures); }; } @@ -511,10 +512,6 @@ function loaded() { var elPropertiesList = document.getElementById("properties-list"); var elID = document.getElementById("property-id"); var elType = document.getElementById("property-type"); -<<<<<<< HEAD -======= - debugPrint("the type is: " + JSON.stringify(elType)); ->>>>>>> creating new image entity opens image property options var elTypeIcon = document.getElementById("type-icon"); var elName = document.getElementById("property-name"); var elLocked = document.getElementById("property-locked"); @@ -665,28 +662,16 @@ function loaded() { var elZoneKeyLightDirectionY = document.getElementById("property-zone-key-light-direction-y"); // Skybox -<<<<<<< HEAD var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit"); var elZoneSkyboxModeDisabled = document.getElementById("property-zone-skybox-mode-disabled"); var elZoneSkyboxModeEnabled = document.getElementById("property-zone-skybox-mode-enabled"); -======= - var elZoneSkyboxModeInherit = document.getElementById("property-zone-skybox-mode-inherit"); - var elZoneSkyboxModeDisabled = document.getElementById("property-zone-skybox-mode-disabled"); - var elZoneSkyboxModeEnabled = document.getElementById("property-zone-skybox-mode-enabled"); ->>>>>>> creating new image entity opens image property options // Ambient light var elCopySkyboxURLToAmbientURL = document.getElementById("copy-skybox-url-to-ambient-url"); -<<<<<<< HEAD var elZoneAmbientLightModeInherit = document.getElementById("property-zone-ambient-light-mode-inherit"); var elZoneAmbientLightModeDisabled = document.getElementById("property-zone-ambient-light-mode-disabled"); var elZoneAmbientLightModeEnabled = document.getElementById("property-zone-ambient-light-mode-enabled"); -======= - var elZoneAmbientLightModeInherit = document.getElementById("property-zone-ambient-light-mode-inherit"); - var elZoneAmbientLightModeDisabled = document.getElementById("property-zone-ambient-light-mode-disabled"); - var elZoneAmbientLightModeEnabled = document.getElementById("property-zone-ambient-light-mode-enabled"); ->>>>>>> creating new image entity opens image property options var elZoneAmbientLightIntensity = document.getElementById("property-zone-key-ambient-intensity"); var elZoneAmbientLightURL = document.getElementById("property-zone-key-ambient-url"); @@ -803,11 +788,6 @@ function loaded() { } else { properties = data.selections[0].properties; -<<<<<<< HEAD - -======= - debugPrint("props: " + JSON.stringify(properties)); ->>>>>>> creating new image entity opens image property options if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null && editor !== null) { saveJSONUserData(true); } @@ -816,14 +796,11 @@ function loaded() { lastEntityID = '"' + properties.id + '"'; elID.value = properties.id; -<<<<<<< HEAD -======= - // image is not yet a separate entity type + // HTML workaround since image is not yet a separate entity type if (properties.type === "Model" && properties.modelURL === "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx") { properties.type = "Image"; } ->>>>>>> creating new image entity opens image property options // Create class name for css ruleset filtering elPropertiesList.className = properties.type + 'Menu'; @@ -1022,8 +999,9 @@ function loaded() { elWebSourceURL.value = properties.sourceUrl; elWebDPI.value = properties.dpi; } else if (properties.type === "Image") { - elImageURL.value = properties.imageURL; - //elImageURL.value = properties.sourceURL; + var imageLink = JSON.parse(properties.textures)["tex.picture"]; + debugPrint("image url is: " + imageLink); + elImageURL.value = imageLink; } else if (properties.type === "Text") { elTextText.value = properties.text; elTextLineHeight.value = properties.lineHeight.toFixed(4); @@ -1052,15 +1030,9 @@ function loaded() { } else if (properties.type === "Zone") { // Key light -<<<<<<< HEAD elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit'); elZoneKeyLightModeDisabled.checked = (properties.keyLightMode === 'disabled'); elZoneKeyLightModeEnabled.checked = (properties.keyLightMode === 'enabled'); -======= - elZoneKeyLightModeInherit.checked = (properties.keyLightMode === 'inherit'); - elZoneKeyLightModeDisabled.checked = (properties.keyLightMode === 'disabled'); - elZoneKeyLightModeEnabled.checked = (properties.keyLightMode === 'enabled'); ->>>>>>> creating new image entity opens image property options elZoneKeyLightColor.style.backgroundColor = "rgb(" + properties.keyLight.color.red + "," + properties.keyLight.color.green + "," + properties.keyLight.color.blue + ")"; @@ -1072,7 +1044,6 @@ function loaded() { elZoneKeyLightDirectionY.value = properties.keyLight.direction.y.toFixed(2); // Skybox -<<<<<<< HEAD elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit'); elZoneSkyboxModeDisabled.checked = (properties.skyboxMode === 'disabled'); elZoneSkyboxModeEnabled.checked = (properties.skyboxMode === 'enabled'); @@ -1081,30 +1052,14 @@ function loaded() { elZoneAmbientLightModeInherit.checked = (properties.ambientLightMode === 'inherit'); elZoneAmbientLightModeDisabled.checked = (properties.ambientLightMode === 'disabled'); elZoneAmbientLightModeEnabled.checked = (properties.ambientLightMode === 'enabled'); -======= - elZoneSkyboxModeInherit.checked = (properties.skyboxMode === 'inherit'); - elZoneSkyboxModeDisabled.checked = (properties.skyboxMode === 'disabled'); - elZoneSkyboxModeEnabled.checked = (properties.skyboxMode === 'enabled'); - - // Ambient light - elZoneAmbientLightModeInherit.checked = (properties.ambientLightMode === 'inherit'); - elZoneAmbientLightModeDisabled.checked = (properties.ambientLightMode === 'disabled'); - elZoneAmbientLightModeEnabled.checked = (properties.ambientLightMode === 'enabled'); ->>>>>>> creating new image entity opens image property options elZoneAmbientLightIntensity.value = properties.ambientLight.ambientIntensity.toFixed(2); elZoneAmbientLightURL.value = properties.ambientLight.ambientURL; // Haze -<<<<<<< HEAD elZoneHazeModeInherit.checked = (properties.hazeMode === 'inherit'); elZoneHazeModeDisabled.checked = (properties.hazeMode === 'disabled'); elZoneHazeModeEnabled.checked = (properties.hazeMode === 'enabled'); -======= - elZoneHazeModeInherit.checked = (properties.hazeMode === 'inherit'); - elZoneHazeModeDisabled.checked = (properties.hazeMode === 'disabled'); - elZoneHazeModeEnabled.checked = (properties.hazeMode === 'enabled'); ->>>>>>> creating new image entity opens image property options elZoneHazeRange.value = properties.haze.hazeRange.toFixed(0); elZoneHazeColor.style.backgroundColor = "rgb(" + @@ -1370,24 +1325,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', -<<<<<<< HEAD submit: false, // We don't want to have a submission button -======= ->>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-color-control2').attr('active', 'true'); }, onHide: function(colpick) { $('#property-color-control2').attr('active', 'false'); }, -<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); -======= - onSubmit: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); ->>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); } })); @@ -1403,24 +1349,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', -<<<<<<< HEAD submit: false, // We don't want to have a submission button -======= ->>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-light-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-light-color').attr('active', 'false'); }, -<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); -======= - onSubmit: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); ->>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b); } })); @@ -1432,7 +1369,7 @@ function loaded() { elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape')); - elImageURL.addEventListener('change', createImageURLUpdateFunction('imageURL')); + elImageURL.addEventListener('change', createImageURLUpdateFunction('textures')); elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); elWebDPI.addEventListener('change', createEmitNumberPropertyUpdateFunction('dpi', 0)); @@ -1469,24 +1406,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', -<<<<<<< HEAD submit: false, // We don't want to have a submission button -======= ->>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-text-text-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-text-text-color').attr('active', 'false'); }, -<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); -======= - onSubmit: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); ->>>>>>> creating new image entity opens image property options $(el).attr('active', 'false'); emitColorPropertyUpdate('textColor', rgb.r, rgb.g, rgb.b); } @@ -1502,24 +1430,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', -<<<<<<< HEAD submit: false, // We don't want to have a submission button -======= ->>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-text-background-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-text-background-color').attr('active', 'false'); }, -<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); -======= - onSubmit: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); ->>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('backgroundColor', rgb.r, rgb.g, rgb.b); } })); @@ -1536,24 +1455,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', -<<<<<<< HEAD submit: false, // We don't want to have a submission button -======= ->>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-zone-key-light-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-key-light-color').attr('active', 'false'); }, -<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); -======= - onSubmit: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); ->>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'keyLight'); } })); @@ -1614,24 +1524,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', -<<<<<<< HEAD submit: false, // We don't want to have a submission button -======= ->>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-zone-haze-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-haze-color').attr('active', 'false'); }, -<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); -======= - onSubmit: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); ->>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('hazeColor', rgb.r, rgb.g, rgb.b, 'haze'); } })); @@ -1648,24 +1549,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', -<<<<<<< HEAD submit: false, // We don't want to have a submission button -======= ->>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-zone-haze-glare-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-haze-glare-color').attr('active', 'false'); }, -<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); -======= - onSubmit: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); ->>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('hazeGlareColor', rgb.r, rgb.g, rgb.b, 'haze'); } })); @@ -1699,24 +1591,15 @@ function loaded() { colorScheme: 'dark', layout: 'hex', color: '000000', -<<<<<<< HEAD submit: false, // We don't want to have a submission button -======= ->>>>>>> creating new image entity opens image property options onShow: function(colpick) { $('#property-zone-skybox-color').attr('active', 'true'); }, onHide: function(colpick) { $('#property-zone-skybox-color').attr('active', 'false'); }, -<<<<<<< HEAD onChange: function(hsb, hex, rgb, el) { $(el).css('background-color', '#' + hex); -======= - onSubmit: function(hsb, hex, rgb, el) { - $(el).css('background-color', '#' + hex); - $(el).colpickHide(); ->>>>>>> creating new image entity opens image property options emitColorPropertyUpdate('color', rgb.r, rgb.g, rgb.b, 'skybox'); } })); From d390e20139efdd55dea99abe44959bbf2e203a46 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 24 Jan 2018 11:31:47 -0800 Subject: [PATCH 15/25] removed extraneous commenting and image class --- .../resources/qml/hifi/tablet/EditTabView.qml | 1 - .../entities/src/EntityItemProperties.cpp | 24 --- libraries/entities/src/EntityItemProperties.h | 2 - libraries/entities/src/EntityPropertyFlags.h | 3 - libraries/entities/src/EntityTypes.cpp | 2 - libraries/entities/src/EntityTypes.h | 1 - libraries/entities/src/ImageEntityItem.cpp | 144 ------------------ libraries/entities/src/ImageEntityItem.h | 66 -------- scripts/system/edit.js | 9 +- scripts/system/html/js/entityProperties.js | 1 - 10 files changed, 1 insertion(+), 252 deletions(-) delete mode 100644 libraries/entities/src/ImageEntityItem.cpp delete mode 100644 libraries/entities/src/ImageEntityItem.h diff --git a/interface/resources/qml/hifi/tablet/EditTabView.qml b/interface/resources/qml/hifi/tablet/EditTabView.qml index 482469d355..ea5762d00a 100644 --- a/interface/resources/qml/hifi/tablet/EditTabView.qml +++ b/interface/resources/qml/hifi/tablet/EditTabView.qml @@ -101,7 +101,6 @@ TabView { } } - // for image NewEntityButton { icon: "icons/create-icons/25-web-1-01.svg" text: "IMAGE" diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 7fcfc00ee8..e2a5ddf8b5 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -350,8 +350,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_AMBIENT_LIGHT_MODE, ambientLightMode); CHECK_PROPERTY_CHANGE(PROP_SKYBOX_MODE, skyboxMode); - //CHECK_PROPERTY_CHANGE(PROP_IMAGE_URL, imageURL); - CHECK_PROPERTY_CHANGE(PROP_SOURCE_URL, sourceUrl); CHECK_PROPERTY_CHANGE(PROP_VOXEL_VOLUME_SIZE, voxelVolumeSize); CHECK_PROPERTY_CHANGE(PROP_VOXEL_DATA, voxelData); @@ -592,13 +590,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_SKYBOX_MODE, skyboxMode, getSkyboxModeAsString()); } - - - /*// Image only - if (_type == EntityTypes::Image) { - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IMAGE_URL, imageURL); - }*/ - // Web only if (_type == EntityTypes::Web) { COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SOURCE_URL, sourceUrl); @@ -789,8 +780,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(ambientLightMode, AmbientLightMode); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(skyboxMode, SkyboxMode); - //COPY_PROPERTY_FROM_QSCRIPTVALUE(imageURL, QString, setImageURL); - COPY_PROPERTY_FROM_QSCRIPTVALUE(sourceUrl, QString, setSourceUrl); COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelVolumeSize, glmVec3, setVoxelVolumeSize); COPY_PROPERTY_FROM_QSCRIPTVALUE(voxelData, QByteArray, setVoxelData); @@ -951,8 +940,6 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(ambientLightMode); COPY_PROPERTY_IF_CHANGED(skyboxMode); - //COPY_PROPERTY_IF_CHANGED(imageURL); - COPY_PROPERTY_IF_CHANGED(sourceUrl); COPY_PROPERTY_IF_CHANGED(voxelVolumeSize); COPY_PROPERTY_IF_CHANGED(voxelData); @@ -1146,7 +1133,6 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_VOXEL_SURFACE_STYLE, VoxelSurfaceStyle, voxelSurfaceStyle, uint16_t); ADD_PROPERTY_TO_MAP(PROP_NAME, Name, name, QString); ADD_PROPERTY_TO_MAP(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString); - //ADD_PROPERTY_TO_MAP(PROP_IMAGE_URL, ImageURL, imageURL, QString); ADD_PROPERTY_TO_MAP(PROP_LINE_WIDTH, LineWidth, lineWidth, float); ADD_PROPERTY_TO_MAP(PROP_LINE_POINTS, LinePoints, linePoints, QVector); ADD_PROPERTY_TO_MAP(PROP_HREF, Href, href, QString); @@ -1383,10 +1369,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_DPI, properties.getDPI()); } - /*if (properties.getType() == EntityTypes::Image) { - APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, properties.getImageURL()); - }*/ - if (properties.getType() == EntityTypes::Text) { APPEND_ENTITY_PROPERTY(PROP_TEXT, properties.getText()); APPEND_ENTITY_PROPERTY(PROP_LINE_HEIGHT, properties.getLineHeight()); @@ -1748,10 +1730,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI); } - /*if (properties.getType() == EntityTypes::Image) { - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IMAGE_URL, QString, setImageURL); - }*/ - if (properties.getType() == EntityTypes::Text) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXT, QString, setText); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_HEIGHT, float, setLineHeight); @@ -2069,8 +2047,6 @@ void EntityItemProperties::markAllChanged() { _skybox.markAllChanged(); _haze.markAllChanged(); - //_imageURLChanged = true; - _sourceUrlChanged = true; _voxelVolumeSizeChanged = true; _voxelDataChanged = true; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 5ca28a12c5..3e0770f386 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -67,7 +67,6 @@ class EntityItemProperties { friend class ParticleEffectEntityItem; // TODO: consider removing this friend relationship and use public methods friend class ZoneEntityItem; // TODO: consider removing this friend relationship and use public methods friend class WebEntityItem; // TODO: consider removing this friend relationship and use public methods - //friend class ImageEntityItem; friend class LineEntityItem; // TODO: consider removing this friend relationship and use public methods friend class PolyVoxEntityItem; // TODO: consider removing this friend relationship and use public methods friend class PolyLineEntityItem; // TODO: consider removing this friend relationship and use public methods @@ -195,7 +194,6 @@ public: DEFINE_PROPERTY_GROUP(Haze, haze, HazePropertyGroup); DEFINE_PROPERTY_GROUP(Animation, animation, AnimationPropertyGroup); DEFINE_PROPERTY_REF(PROP_SOURCE_URL, SourceUrl, sourceUrl, QString, ""); - //DEFINE_PROPERTY_REF(PROP_IMAGE_URL, ImageURL, imageURL, QString, ""); DEFINE_PROPERTY(PROP_LINE_WIDTH, LineWidth, lineWidth, float, LineEntityItem::DEFAULT_LINE_WIDTH); DEFINE_PROPERTY_REF(LINE_POINTS, LinePoints, linePoints, QVector, QVector()); DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString, ""); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index ec8f4e08c8..90438ab01c 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -42,9 +42,6 @@ enum EntityPropertyList { PROP_ANIMATION_ALLOW_TRANSLATION, PROP_RELAY_PARENT_JOINTS, - /*// for image - PROP_IMAGE_URL,*/ - // these properties are supported by the EntityItem base class PROP_REGISTRATION_POINT, PROP_ANGULAR_VELOCITY, diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index 6bf5a176a7..cb17c28fd7 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -28,7 +28,6 @@ #include "LineEntityItem.h" #include "PolyVoxEntityItem.h" #include "PolyLineEntityItem.h" -//#include "ImageEntityItem.h" #include "ShapeEntityItem.h" QMap EntityTypes::_typeToNameMap; @@ -48,7 +47,6 @@ REGISTER_ENTITY_TYPE(Zone) REGISTER_ENTITY_TYPE(Line) REGISTER_ENTITY_TYPE(PolyVox) REGISTER_ENTITY_TYPE(PolyLine) -//REGISTER_ENTITY_TYPE(Image) REGISTER_ENTITY_TYPE(Shape) REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, ShapeEntityItem::boxFactory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, ShapeEntityItem::sphereFactory) diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 6fe4274820..316bf2b813 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -48,7 +48,6 @@ public: Line, PolyVox, PolyLine, - //Image, Shape, LAST = Shape } EntityType; diff --git a/libraries/entities/src/ImageEntityItem.cpp b/libraries/entities/src/ImageEntityItem.cpp deleted file mode 100644 index 9969a39ed0..0000000000 --- a/libraries/entities/src/ImageEntityItem.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// -// ImageEntityItem.cpp -// libraries/entities/src -// -// Created by Elisa Lupin-Jimenez on 1/3/18. -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* NOT IN USE - -#include - -#include -#include -#include -#include - -#include "EntitiesLogging.h" -#include "EntityItemProperties.h" -#include "EntityTree.h" -#include "EntityTreeElement.h" -#include "ResourceCache.h" -#include "ShapeEntityItem.h" -#include "ImageEntityItem.h" - -const QString ImageEntityItem::DEFAULT_IMAGE_URL(""); - -EntityItemPointer ImageEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { - EntityItemPointer entity(new ImageEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); - entity->setProperties(properties); - return entity; -} - -ImageEntityItem::ImageEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) { - //_type = EntityTypes::Image; -} - -EntityItemProperties ImageEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { - EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class - COPY_ENTITY_PROPERTY_TO_PROPERTIES(imageURL, getImageURL); - // Using "Quad" shape as defined in ShapeEntityItem.cpp - properties.setShape("Quad"); - return properties; -} - -bool ImageEntityItem::setProperties(const EntityItemProperties& properties) { - bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class - - SET_ENTITY_PROPERTY_FROM_PROPERTIES(imageURL, setImageURL); - - if (somethingChanged) { - bool wantDebug = false; - if (wantDebug) { - uint64_t now = usecTimestampNow(); - int elapsed = now - getLastEdited(); - qCDebug(entities) << "ImageEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << - "now=" << now << " getLastEdited()=" << getLastEdited(); - } - setLastEdited(properties.getLastEdited()); - } - return somethingChanged; -} - -// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time -EntityPropertyFlags ImageEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { - EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); - requestedProperties += PROP_IMAGE_URL; - return requestedProperties; -} - -void ImageEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData, - EntityPropertyFlags& requestedProperties, - EntityPropertyFlags& propertyFlags, - EntityPropertyFlags& propertiesDidntFit, - int& propertyCount, - OctreeElement::AppendState& appendState) const { - - bool successPropertyFits = true; - // Using "Quad" shape as defined in ShapeEntityItem.cpp - APPEND_ENTITY_PROPERTY(PROP_IMAGE_URL, _imageURL); -} - -int ImageEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, - ReadBitstreamToTreeParams& args, - EntityPropertyFlags& propertyFlags, bool overwriteLocalData, - bool& somethingChanged) { - - int bytesRead = 0; - const unsigned char* dataAt = data; - - READ_ENTITY_PROPERTY(PROP_IMAGE_URL, QString, setImageURL); - - return bytesRead; -} - -void ImageEntityItem::setUnscaledDimensions(const glm::vec3& value) { - const float MAX_FLAT_DIMENSION = 0.0001f; - if (value.y > MAX_FLAT_DIMENSION) { - // enforce flatness in Y - glm::vec3 newDimensions = value; - newDimensions.y = MAX_FLAT_DIMENSION; - EntityItem::setUnscaledDimensions(newDimensions); - } else { - EntityItem::setUnscaledDimensions(value); - } -} - -void ImageEntityItem::setImageURL(const QString& value) { - withWriteLock([&] { - if (_imageURL != value) { - auto newURL = QUrl::fromUserInput(value); - - if (newURL.isValid()) { - _imageURL = newURL.toDisplayString(); - } else { - qCDebug(entities) << "Clearing image entity source URL since" << value << "cannot be parsed to a valid URL."; - } - } - }); -} - -QString ImageEntityItem::getImageURL() const { - return resultWithReadLock([&] { - return _imageURL; - }); -} - -void ImageEntityItem::computeShapeInfo(ShapeInfo& info) { - // This will be called whenever DIRTY_SHAPE flag (set by dimension change, etc) - // is set. - - EntityItem::computeShapeInfo(info); -} - -// This value specifies how the shape should be treated by physics calculations. -ShapeType ImageEntityItem::getShapeType() const { - return _collisionShapeType; -} - -*/ diff --git a/libraries/entities/src/ImageEntityItem.h b/libraries/entities/src/ImageEntityItem.h deleted file mode 100644 index 276d21e6f0..0000000000 --- a/libraries/entities/src/ImageEntityItem.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// ImageEntityItem.h -// libraries/entities/src -// -// Created by Elisa Lupin-Jimenez on 1/3/18. -// Copyright 2018 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* NOT IN USE - -#ifndef hifi_ImageEntityItem_h -#define hifi_ImageEntityItem_h - -#include "EntityItem.h" -#include "ShapeEntityItem.h" - -class ImageEntityItem : public EntityItem { -public: - static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); - - ImageEntityItem(const EntityItemID& entityItemID); - - ALLOW_INSTANTIATION // This class can be instantiated - - // methods for getting/setting all properties of an entity - virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; - virtual bool setProperties(const EntityItemProperties& properties) override; - - EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override; - - virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params, - EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData, - EntityPropertyFlags& requestedProperties, - EntityPropertyFlags& propertyFlags, - EntityPropertyFlags& propertiesDidntFit, - int& propertyCount, - OctreeElement::AppendState& appendState) const override; - - int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, - ReadBitstreamToTreeParams& args, - EntityPropertyFlags& propertyFlags, bool overwriteLocalData, - bool& somethingChanged) override; - - void setUnscaledDimensions(const glm::vec3& value) override; - - static const QString DEFAULT_IMAGE_URL; - virtual void setImageURL(const QString& value); - QString getImageURL() const; - - //virtual void computeShapeInfo(ShapeInfo& info) override; - virtual ShapeType getShapeType() const override; - -protected: - QString _imageURL; - - entity::Shape _shape{ entity::Shape::Quad }; - ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_BOX }; - -}; - -#endif // hifi_ImageEntityItem_h - -*/ diff --git a/scripts/system/edit.js b/scripts/system/edit.js index a5c236a6c9..20425c7ea6 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -251,9 +251,7 @@ var toolBar = (function () { // Align entity with Avatar orientation. properties.rotation = MyAvatar.orientation; - // added image here var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Web"]; - //var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web"]; if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { @@ -541,21 +539,16 @@ var toolBar = (function () { }); }); - // for image button addButton("newImageButton", "web-01.svg", function () { createNewEntity({ type: "Model", - // make constant for this later dimensions: { x: 4.16, y: 0.02, z: 2.58 }, modelURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx", - // will this work? - /*get textures() { - return JSON.stringify({ "tex.picture": this.imageURL }); - }*/ + // change to another default image textures: JSON.stringify({ "tex.picture": "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg" }) }); }); diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index e7526fa2e0..59b54b1020 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1000,7 +1000,6 @@ function loaded() { elWebDPI.value = properties.dpi; } else if (properties.type === "Image") { var imageLink = JSON.parse(properties.textures)["tex.picture"]; - debugPrint("image url is: " + imageLink); elImageURL.value = imageLink; } else if (properties.type === "Text") { elTextText.value = properties.text; From bd7204e6efd507be41c4a45d3ec4e21d61d44db2 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 24 Jan 2018 12:01:59 -0800 Subject: [PATCH 16/25] image entity now has grabbable and dynamic options --- scripts/system/edit.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 20425c7ea6..c298da38bc 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -547,6 +547,7 @@ var toolBar = (function () { y: 0.02, z: 2.58 }, + shapeType: "box", modelURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx", // change to another default image textures: JSON.stringify({ "tex.picture": "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg" }) From 2ff47fa454b494ce64d2afa7e4396f0233e32ea7 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Thu, 25 Jan 2018 14:39:45 -0800 Subject: [PATCH 17/25] images auto-add to asset server, started asset browser add link --- interface/resources/qml/hifi/AssetServer.qml | 3 +- interface/src/Application.cpp | 42 ++++++++++++++++---- interface/src/Application.h | 1 + 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index 37c3c2adab..6a4e703413 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -142,8 +142,9 @@ Windows.ScrollingWindow { }); } + // Elisa note - need to link this with specific add entity call function canAddToWorld(path) { - var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i]; + var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i]; if (selectedItems > 1) { return false; diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 99bd4d5758..b53ba61e61 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -335,15 +335,17 @@ static const int MAX_CONCURRENT_RESOURCE_DOWNLOADS = 16; // we will never drop below the 'min' value static const int MIN_PROCESSING_THREAD_POOL_SIZE = 1; -static const QString SNAPSHOT_EXTENSION = ".jpg"; -static const QString SVO_EXTENSION = ".svo"; +static const QString SNAPSHOT_EXTENSION = ".jpg"; +static const QString JPG_EXTENSION = ".jpg"; +static const QString PNG_EXTENSION = ".png"; +static const QString SVO_EXTENSION = ".svo"; static const QString SVO_JSON_EXTENSION = ".svo.json"; static const QString JSON_GZ_EXTENSION = ".json.gz"; static const QString JSON_EXTENSION = ".json"; -static const QString JS_EXTENSION = ".js"; -static const QString FST_EXTENSION = ".fst"; -static const QString FBX_EXTENSION = ".fbx"; -static const QString OBJ_EXTENSION = ".obj"; +static const QString JS_EXTENSION = ".js"; +static const QString FST_EXTENSION = ".fst"; +static const QString FBX_EXTENSION = ".fbx"; +static const QString OBJ_EXTENSION = ".obj"; static const QString AVA_JSON_EXTENSION = ".ava.json"; static const QString WEB_VIEW_TAG = "noDownload=true"; static const QString ZIP_EXTENSION = ".zip"; @@ -382,7 +384,9 @@ const QHash Application::_acceptedExtensi { JS_EXTENSION, &Application::askToLoadScript }, { FST_EXTENSION, &Application::askToSetAvatarUrl }, { JSON_GZ_EXTENSION, &Application::askToReplaceDomainContent }, - { ZIP_EXTENSION, &Application::importFromZIP } + { ZIP_EXTENSION, &Application::importFromZIP }, + { JPG_EXTENSION, &Application::importImage }, + { PNG_EXTENSION, &Application::importImage } }; class DeadlockWatchdogThread : public QThread { @@ -2899,6 +2903,27 @@ bool Application::importFromZIP(const QString& filePath) { return true; } +bool Application::importImage(const QString& urlString) { + qCDebug(interfaceapp) << "dragged image"; + QString filepath(urlString); + filepath.remove("file:///"); + //<> + addAssetToWorld(filepath, "", false, false); + //emit uploadRequest(urlString); + /*auto upload = DependencyManager::get()->createUpload(urlString); + QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable { + if (upload->getError() != AssetUpload::NoError) { + QString errorInfo = "Could not upload model to the Asset Server."; + qWarning(interfaceapp) << "Error downloading model: " + errorInfo; + //addAssetToWorldError(filenameFromPath(urlString), errorInfo); + } else { + //addAssetToWorldSetMapping(urlString, QString("/" + filenameFromPath(urlString)), hash); + } + upload->deleteLater(); + });*/ + return true; +} + // thread-safe void Application::onPresent(quint32 frameCount) { bool expected = false; @@ -6403,6 +6428,7 @@ void Application::addAssetToWorld(QString path, QString zipFile, bool isZip, boo // Automatically upload and add asset to world as an alternative manual process initiated by showAssetServerWidget(). QString mapping; QString filename = filenameFromPath(path); + qCDebug(interfaceapp) << "Filename is: " << filename; if (isZip || isBlocks) { QString assetName = zipFile.section("/", -1).remove(QRegExp("[.]zip(.*)$")); QString assetFolder = path.section("model_repo/", -1); @@ -6425,6 +6451,8 @@ void Application::addAssetToWorld(QString path, QString zipFile, bool isZip, boo } void Application::addAssetToWorldWithNewMapping(QString filePath, QString mapping, int copy) { + qCDebug(interfaceapp) << "mapping request is: " << mapping; + qCDebug(interfaceapp) << "file is located: " << filePath; auto request = DependencyManager::get()->createGetMappingRequest(mapping); QObject::connect(request, &GetMappingRequest::finished, this, [=](GetMappingRequest* request) mutable { diff --git a/interface/src/Application.h b/interface/src/Application.h index ddb8ce11e5..0e9bf95081 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -469,6 +469,7 @@ private: bool importJSONFromURL(const QString& urlString); bool importSVOFromURL(const QString& urlString); bool importFromZIP(const QString& filePath); + bool importImage(const QString& urlString); bool nearbyEntitiesAreReadyForPhysics(); int processOctreeStats(ReceivedMessage& message, SharedNodePointer sendingNode); From 62437dcc2265886c5d0fb7349c4625d4e68d18d7 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Thu, 25 Jan 2018 15:26:26 -0800 Subject: [PATCH 18/25] drag and drop works --- interface/src/Application.cpp | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b53ba61e61..b203487547 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2904,23 +2904,10 @@ bool Application::importFromZIP(const QString& filePath) { } bool Application::importImage(const QString& urlString) { - qCDebug(interfaceapp) << "dragged image"; + qCDebug(interfaceapp) << "An image file has been dropped in"; QString filepath(urlString); filepath.remove("file:///"); - //<> addAssetToWorld(filepath, "", false, false); - //emit uploadRequest(urlString); - /*auto upload = DependencyManager::get()->createUpload(urlString); - QObject::connect(upload, &AssetUpload::finished, this, [=](AssetUpload* upload, const QString& hash) mutable { - if (upload->getError() != AssetUpload::NoError) { - QString errorInfo = "Could not upload model to the Asset Server."; - qWarning(interfaceapp) << "Error downloading model: " + errorInfo; - //addAssetToWorldError(filenameFromPath(urlString), errorInfo); - } else { - //addAssetToWorldSetMapping(urlString, QString("/" + filenameFromPath(urlString)), hash); - } - upload->deleteLater(); - });*/ return true; } @@ -6428,7 +6415,6 @@ void Application::addAssetToWorld(QString path, QString zipFile, bool isZip, boo // Automatically upload and add asset to world as an alternative manual process initiated by showAssetServerWidget(). QString mapping; QString filename = filenameFromPath(path); - qCDebug(interfaceapp) << "Filename is: " << filename; if (isZip || isBlocks) { QString assetName = zipFile.section("/", -1).remove(QRegExp("[.]zip(.*)$")); QString assetFolder = path.section("model_repo/", -1); @@ -6451,8 +6437,6 @@ void Application::addAssetToWorld(QString path, QString zipFile, bool isZip, boo } void Application::addAssetToWorldWithNewMapping(QString filePath, QString mapping, int copy) { - qCDebug(interfaceapp) << "mapping request is: " << mapping; - qCDebug(interfaceapp) << "file is located: " << filePath; auto request = DependencyManager::get()->createGetMappingRequest(mapping); QObject::connect(request, &GetMappingRequest::finished, this, [=](GetMappingRequest* request) mutable { @@ -6519,7 +6503,8 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q addAssetToWorldError(filenameFromPath(filePath), errorInfo); } else { // to prevent files that aren't models from being loaded into world automatically - if (filePath.endsWith(".obj") || filePath.endsWith(".fbx")) { + if (filePath.endsWith(OBJ_EXTENSION) || filePath.endsWith(FBX_EXTENSION) || + filePath.endsWith(JPG_EXTENSION) || filePath.endsWith(PNG_EXTENSION)) { addAssetToWorldAddEntity(filePath, mapping); } else { qCDebug(interfaceapp) << "Zipped contents are not supported entity files"; @@ -6536,8 +6521,17 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { EntityItemProperties properties; properties.setType(EntityTypes::Model); properties.setName(mapping.right(mapping.length() - 1)); - properties.setModelURL("atp:" + mapping); - properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND); + if (filePath.endsWith(PNG_EXTENSION) || filePath.endsWith(JPG_EXTENSION)) { + QJsonObject textures { + {"tex.picture", QString("atp:" + mapping) } + }; + properties.setModelURL("https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx"); + properties.setTextures(QJsonDocument(textures).toJson(QJsonDocument::Compact)); + properties.setShapeType(SHAPE_TYPE_BOX); + } else { + properties.setModelURL("atp:" + mapping); + properties.setShapeType(SHAPE_TYPE_SIMPLE_COMPOUND); + } properties.setCollisionless(true); // Temporarily set so that doesn't collide with avatar. properties.setVisible(false); // Temporarily set so that don't see at large unresized dimensions. glm::vec3 positionOffset = getMyAvatar()->getWorldOrientation() * (getMyAvatar()->getSensorToWorldScale() * glm::vec3(0.0f, 0.0f, -2.0f)); From 9f8e2017ceab378aec06a75c6f447317f68b1e32 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Fri, 26 Jan 2018 14:39:04 -0800 Subject: [PATCH 19/25] can add image directly from asset server --- interface/resources/qml/hifi/AssetServer.qml | 167 ++++++++++-------- .../qml/hifi/dialogs/TabletAssetServer.qml | 167 ++++++++++-------- .../entities/src/EntityScriptingInterface.cpp | 5 +- .../entities/src/EntityScriptingInterface.h | 2 +- 4 files changed, 183 insertions(+), 158 deletions(-) diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index 6a4e703413..04fceec1f3 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -182,92 +182,103 @@ Windows.ScrollingWindow { return; } - var SHAPE_TYPE_NONE = 0; - var SHAPE_TYPE_SIMPLE_HULL = 1; - var SHAPE_TYPE_SIMPLE_COMPOUND = 2; - var SHAPE_TYPE_STATIC_MESH = 3; - var SHAPE_TYPE_BOX = 4; - var SHAPE_TYPE_SPHERE = 5; + if (defaultURL.endsWith(".jpg") || defaultURL.endsWith(".png")) { + var name = assetProxyModel.data(treeView.selection.currentIndex); + var modelURL = "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx"; + var textures = JSON.stringify({ "tex.picture": defaultURL}); + var shapeType = "box"; + var dynamic = false; + var position = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))); + var gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0); + Entities.addModelEntity(name, modelURL, textures, shapeType, dynamic, position, gravity); + } else { + var SHAPE_TYPE_NONE = 0; + var SHAPE_TYPE_SIMPLE_HULL = 1; + var SHAPE_TYPE_SIMPLE_COMPOUND = 2; + var SHAPE_TYPE_STATIC_MESH = 3; + var SHAPE_TYPE_BOX = 4; + var SHAPE_TYPE_SPHERE = 5; - var SHAPE_TYPES = []; - SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision"; - SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model"; - SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes"; - SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons"; - SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box"; - SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere"; + var SHAPE_TYPES = []; + SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision"; + SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model"; + SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes"; + SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons"; + SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box"; + SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere"; - var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; - var DYNAMIC_DEFAULT = false; - var prompt = desktop.customInputDialog({ - textInput: { - label: "Model URL", - text: defaultURL - }, - comboBox: { - label: "Automatic Collisions", - index: SHAPE_TYPE_DEFAULT, - items: SHAPE_TYPES - }, - checkBox: { - label: "Dynamic", - checked: DYNAMIC_DEFAULT, - disableForItems: [ - SHAPE_TYPE_STATIC_MESH - ], - checkStateOnDisable: false, - warningOnDisable: "Models with 'Exact' automatic collisions cannot be dynamic, and should not be used as floors" - } - }); - - prompt.selected.connect(function (jsonResult) { - if (jsonResult) { - var result = JSON.parse(jsonResult); - var url = result.textInput.trim(); - var shapeType; - switch (result.comboBox) { - case SHAPE_TYPE_SIMPLE_HULL: - shapeType = "simple-hull"; - break; - case SHAPE_TYPE_SIMPLE_COMPOUND: - shapeType = "simple-compound"; - break; - case SHAPE_TYPE_STATIC_MESH: - shapeType = "static-mesh"; - break; - case SHAPE_TYPE_BOX: - shapeType = "box"; - break; - case SHAPE_TYPE_SPHERE: - shapeType = "sphere"; - break; - default: - shapeType = "none"; + var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; + var DYNAMIC_DEFAULT = false; + var prompt = desktop.customInputDialog({ + textInput: { + label: "Model URL", + text: defaultURL + }, + comboBox: { + label: "Automatic Collisions", + index: SHAPE_TYPE_DEFAULT, + items: SHAPE_TYPES + }, + checkBox: { + label: "Dynamic", + checked: DYNAMIC_DEFAULT, + disableForItems: [ + SHAPE_TYPE_STATIC_MESH + ], + checkStateOnDisable: false, + warningOnDisable: "Models with 'Exact' automatic collisions cannot be dynamic, and should not be used as floors" } + }); - var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT; - if (shapeType === "static-mesh" && dynamic) { - // The prompt should prevent this case - print("Error: model cannot be both static mesh and dynamic. This should never happen."); - } else if (url) { - var name = assetProxyModel.data(treeView.selection.currentIndex); - var addPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))); - var gravity; - if (dynamic) { - // Create a vector <0, -10, 0>. { x: 0, y: -10, z: 0 } won't work because Qt is dumb and this is a - // different scripting engine from QTScript. - gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 10); - } else { - gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0); + prompt.selected.connect(function (jsonResult) { + if (jsonResult) { + var result = JSON.parse(jsonResult); + var url = result.textInput.trim(); + var shapeType; + switch (result.comboBox) { + case SHAPE_TYPE_SIMPLE_HULL: + shapeType = "simple-hull"; + break; + case SHAPE_TYPE_SIMPLE_COMPOUND: + shapeType = "simple-compound"; + break; + case SHAPE_TYPE_STATIC_MESH: + shapeType = "static-mesh"; + break; + case SHAPE_TYPE_BOX: + shapeType = "box"; + break; + case SHAPE_TYPE_SPHERE: + shapeType = "sphere"; + break; + default: + shapeType = "none"; } - print("Asset browser - adding asset " + url + " (" + name + ") to world."); + var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT; + if (shapeType === "static-mesh" && dynamic) { + // The prompt should prevent this case + print("Error: model cannot be both static mesh and dynamic. This should never happen."); + } else if (url) { + var name = assetProxyModel.data(treeView.selection.currentIndex); + var addPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))); + var gravity; + if (dynamic) { + // Create a vector <0, -10, 0>. { x: 0, y: -10, z: 0 } won't work because Qt is dumb and this is a + // different scripting engine from QTScript. + gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 10); + } else { + gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0); + } - // Entities.addEntity doesn't work from QML, so we use this. - Entities.addModelEntity(name, url, shapeType, dynamic, addPosition, gravity); + print("Asset browser - adding asset " + url + " (" + name + ") to world."); + + // Entities.addEntity doesn't work from QML, so we use this. + Entities.addModelEntity(name, url, "", shapeType, dynamic, addPosition, gravity); + } } - } - }); + }); + } } function copyURLToClipboard(index) { diff --git a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml index a02496a252..ef4fb8d177 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml @@ -182,92 +182,103 @@ Rectangle { return; } - var SHAPE_TYPE_NONE = 0; - var SHAPE_TYPE_SIMPLE_HULL = 1; - var SHAPE_TYPE_SIMPLE_COMPOUND = 2; - var SHAPE_TYPE_STATIC_MESH = 3; - var SHAPE_TYPE_BOX = 4; - var SHAPE_TYPE_SPHERE = 5; + if (defaultURL.endsWith(".jpg") || defaultURL.endsWith(".png")) { + var name = assetProxyModel.data(treeView.selection.currentIndex); + var modelURL = "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx"; + var textures = JSON.stringify({ "tex.picture": defaultURL}); + var shapeType = "box"; + var dynamic = false; + var position = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))); + var gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0); + Entities.addModelEntity(name, modelURL, textures, shapeType, dynamic, position, gravity); + } else { + var SHAPE_TYPE_NONE = 0; + var SHAPE_TYPE_SIMPLE_HULL = 1; + var SHAPE_TYPE_SIMPLE_COMPOUND = 2; + var SHAPE_TYPE_STATIC_MESH = 3; + var SHAPE_TYPE_BOX = 4; + var SHAPE_TYPE_SPHERE = 5; - var SHAPE_TYPES = []; - SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision"; - SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model"; - SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes"; - SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons"; - SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box"; - SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere"; + var SHAPE_TYPES = []; + SHAPE_TYPES[SHAPE_TYPE_NONE] = "No Collision"; + SHAPE_TYPES[SHAPE_TYPE_SIMPLE_HULL] = "Basic - Whole model"; + SHAPE_TYPES[SHAPE_TYPE_SIMPLE_COMPOUND] = "Good - Sub-meshes"; + SHAPE_TYPES[SHAPE_TYPE_STATIC_MESH] = "Exact - All polygons"; + SHAPE_TYPES[SHAPE_TYPE_BOX] = "Box"; + SHAPE_TYPES[SHAPE_TYPE_SPHERE] = "Sphere"; - var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; - var DYNAMIC_DEFAULT = false; - var prompt = tabletRoot.customInputDialog({ - textInput: { - label: "Model URL", - text: defaultURL - }, - comboBox: { - label: "Automatic Collisions", - index: SHAPE_TYPE_DEFAULT, - items: SHAPE_TYPES - }, - checkBox: { - label: "Dynamic", - checked: DYNAMIC_DEFAULT, - disableForItems: [ - SHAPE_TYPE_STATIC_MESH - ], - checkStateOnDisable: false, - warningOnDisable: "Models with 'Exact' automatic collisions cannot be dynamic, and should not be used as floors" - } - }); - - prompt.selected.connect(function (jsonResult) { - if (jsonResult) { - var result = JSON.parse(jsonResult); - var url = result.textInput.trim(); - var shapeType; - switch (result.comboBox) { - case SHAPE_TYPE_SIMPLE_HULL: - shapeType = "simple-hull"; - break; - case SHAPE_TYPE_SIMPLE_COMPOUND: - shapeType = "simple-compound"; - break; - case SHAPE_TYPE_STATIC_MESH: - shapeType = "static-mesh"; - break; - case SHAPE_TYPE_BOX: - shapeType = "box"; - break; - case SHAPE_TYPE_SPHERE: - shapeType = "sphere"; - break; - default: - shapeType = "none"; + var SHAPE_TYPE_DEFAULT = SHAPE_TYPE_STATIC_MESH; + var DYNAMIC_DEFAULT = false; + var prompt = tabletRoot.customInputDialog({ + textInput: { + label: "Model URL", + text: defaultURL + }, + comboBox: { + label: "Automatic Collisions", + index: SHAPE_TYPE_DEFAULT, + items: SHAPE_TYPES + }, + checkBox: { + label: "Dynamic", + checked: DYNAMIC_DEFAULT, + disableForItems: [ + SHAPE_TYPE_STATIC_MESH + ], + checkStateOnDisable: false, + warningOnDisable: "Models with 'Exact' automatic collisions cannot be dynamic, and should not be used as floors" } + }); - var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT; - if (shapeType === "static-mesh" && dynamic) { - // The prompt should prevent this case - print("Error: model cannot be both static mesh and dynamic. This should never happen."); - } else if (url) { - var name = assetProxyModel.data(treeView.selection.currentIndex); - var addPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))); - var gravity; - if (dynamic) { - // Create a vector <0, -10, 0>. { x: 0, y: -10, z: 0 } won't work because Qt is dumb and this is a - // different scripting engine from QTScript. - gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 10); - } else { - gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0); + prompt.selected.connect(function (jsonResult) { + if (jsonResult) { + var result = JSON.parse(jsonResult); + var url = result.textInput.trim(); + var shapeType; + switch (result.comboBox) { + case SHAPE_TYPE_SIMPLE_HULL: + shapeType = "simple-hull"; + break; + case SHAPE_TYPE_SIMPLE_COMPOUND: + shapeType = "simple-compound"; + break; + case SHAPE_TYPE_STATIC_MESH: + shapeType = "static-mesh"; + break; + case SHAPE_TYPE_BOX: + shapeType = "box"; + break; + case SHAPE_TYPE_SPHERE: + shapeType = "sphere"; + break; + default: + shapeType = "none"; } - print("Asset browser - adding asset " + url + " (" + name + ") to world."); + var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT; + if (shapeType === "static-mesh" && dynamic) { + // The prompt should prevent this case + print("Error: model cannot be both static mesh and dynamic. This should never happen."); + } else if (url) { + var name = assetProxyModel.data(treeView.selection.currentIndex); + var addPosition = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))); + var gravity; + if (dynamic) { + // Create a vector <0, -10, 0>. { x: 0, y: -10, z: 0 } won't work because Qt is dumb and this is a + // different scripting engine from QTScript. + gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 10); + } else { + gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0); + } - // Entities.addEntity doesn't work from QML, so we use this. - Entities.addModelEntity(name, url, shapeType, dynamic, addPosition, gravity); + print("Asset browser - adding asset " + url + " (" + name + ") to world."); + + // Entities.addEntity doesn't work from QML, so we use this. + Entities.addModelEntity(name, url, "", shapeType, dynamic, addPosition, gravity); + } } - } - }); + }); + } } function copyURLToClipboard(index) { diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 4342f0e683..06a141a95e 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -299,7 +299,7 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties } } -QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const QString& shapeType, +QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, const QString& shapeType, bool dynamic, const glm::vec3& position, const glm::vec3& gravity) { _activityTracking.addedEntityCount++; @@ -311,6 +311,9 @@ QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QStrin properties.setDynamic(dynamic); properties.setPosition(position); properties.setGravity(gravity); + if (!textures.isEmpty()) { + properties.setTextures(textures); + } return addEntity(properties); } diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index d1b321dbca..919d0e3489 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -158,7 +158,7 @@ public slots: /// temporary method until addEntity can be used from QJSEngine /// Deliberately not adding jsdoc, only used internally. - Q_INVOKABLE QUuid addModelEntity(const QString& name, const QString& modelUrl, const QString& shapeType, bool dynamic, + Q_INVOKABLE QUuid addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, const QString& shapeType, bool dynamic, const glm::vec3& position, const glm::vec3& gravity); /**jsdoc From cc4bafb46fdcd4b599e2d24d2fd09393bec555dd Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Fri, 26 Jan 2018 15:40:22 -0800 Subject: [PATCH 20/25] image entities shown as images in entity list --- interface/resources/qml/hifi/AssetServer.qml | 1 - scripts/system/html/js/entityList.js | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index 04fceec1f3..b173b3826d 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -142,7 +142,6 @@ Windows.ScrollingWindow { }); } - // Elisa note - need to link this with specific add entity call function canAddToWorld(path) { var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i]; diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index 7b25e66c67..dde91dc694 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -156,6 +156,10 @@ function loaded() { var urlParts = url.split('/'); var filename = urlParts[urlParts.length - 1]; + if (url === "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx") { + type = "Image"; + } + if (entities[id] === undefined) { entityList.add([{ id: id, name: name, type: type, url: filename, locked: locked, visible: visible, From f71d9e4d6a4a994cb26187476ac78e86c6f5b998 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Tue, 30 Jan 2018 17:49:30 -0800 Subject: [PATCH 21/25] snapshot referenced locally, won't work on OS --- interface/resources/qml/hifi/AssetServer.qml | 2 +- .../qml/hifi/dialogs/TabletAssetServer.qml | 2 +- interface/resources/snapshot/snapshot.fbx | Bin 0 -> 51420 bytes interface/src/Application.cpp | 2 +- scripts/system/edit.js | 4 ++-- scripts/system/html/js/entityList.js | 4 +++- scripts/system/html/js/entityProperties.js | 3 ++- 7 files changed, 10 insertions(+), 7 deletions(-) create mode 100644 interface/resources/snapshot/snapshot.fbx diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index b173b3826d..42b8118115 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -183,7 +183,7 @@ Windows.ScrollingWindow { if (defaultURL.endsWith(".jpg") || defaultURL.endsWith(".png")) { var name = assetProxyModel.data(treeView.selection.currentIndex); - var modelURL = "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx"; + var modelURL = "qrc:///snapshot/snapshot.fbx"; var textures = JSON.stringify({ "tex.picture": defaultURL}); var shapeType = "box"; var dynamic = false; diff --git a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml index ef4fb8d177..315def6f14 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml @@ -184,7 +184,7 @@ Rectangle { if (defaultURL.endsWith(".jpg") || defaultURL.endsWith(".png")) { var name = assetProxyModel.data(treeView.selection.currentIndex); - var modelURL = "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx"; + var modelURL = "qrc:///snapshot/snapshot.fbx"; var textures = JSON.stringify({ "tex.picture": defaultURL}); var shapeType = "box"; var dynamic = false; diff --git a/interface/resources/snapshot/snapshot.fbx b/interface/resources/snapshot/snapshot.fbx new file mode 100644 index 0000000000000000000000000000000000000000..641a7f82ebd0a67a9364c21867bad4a02d246048 GIT binary patch literal 51420 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

&G zn)U3&NLVlYg3k%9i=l-QG?rwY&lPFRdfN-$!ojKHtN?jwpZweFP!jW1fNRrMz*Wl=AuKoqy55AyU3eH^f^$WO?uQ|Q3)87W! zM%VQ3#OnI)jA6SHckwNm0;qmkMw6tW@TM|j;ZwBA76W$`f zes=!aTM{V(amXl#A5029(ssbCKD7PiNZSEt_|Qf<(st0xb(r3Mr0t-Y_Aq_?NZUab z=wbTyk+uU&>S3s-Z5{UDtKcKM}3o>GeMF{{KcB$g(?AYpNpS!mo7M IwBH~9Z+ICcSO5S3 literal 0 HcmV?d00001 diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b203487547..53c1e3fad5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6525,7 +6525,7 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { QJsonObject textures { {"tex.picture", QString("atp:" + mapping) } }; - properties.setModelURL("https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx"); + properties.setModelURL("qrc:///snapshot/snapshot.fbx"); properties.setTextures(QJsonDocument(textures).toJson(QJsonDocument::Compact)); properties.setShapeType(SHAPE_TYPE_BOX); } else { diff --git a/scripts/system/edit.js b/scripts/system/edit.js index c298da38bc..ece8516567 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -548,9 +548,9 @@ var toolBar = (function () { z: 2.58 }, shapeType: "box", - modelURL: "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx", + modelURL: 'qrc:///snapshot/snapshot.fbx', // change to another default image - textures: JSON.stringify({ "tex.picture": "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/dog.jpg" }) + textures: JSON.stringify({ "tex.picture": 'qrc:///snapshot/img/no-image.jpg' }) }); }); diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js index dde91dc694..85cd77bd28 100644 --- a/scripts/system/html/js/entityList.js +++ b/scripts/system/html/js/entityList.js @@ -156,7 +156,9 @@ function loaded() { var urlParts = url.split('/'); var filename = urlParts[urlParts.length - 1]; - if (url === "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx") { + var snapURL = 'qrc:///snapshot/snapshot.fbx'; + + if (url === snapURL) { type = "Image"; } diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 59b54b1020..acaff333e2 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -797,7 +797,8 @@ function loaded() { elID.value = properties.id; // HTML workaround since image is not yet a separate entity type - if (properties.type === "Model" && properties.modelURL === "https://hifi-content.s3.amazonaws.com/elisalj/image_entity/snapshot.fbx") { + var snapURL = 'qrc:///snapshot/snapshot.fbx'; + if (properties.type === "Model" && properties.modelURL === snapURL) { properties.type = "Image"; } From d7a847930d3f8d88cbbb505a6f6b6bafbbad8ac6 Mon Sep 17 00:00:00 2001 From: Elisa Lupin-Jimenez Date: Wed, 31 Jan 2018 11:44:22 -0800 Subject: [PATCH 22/25] added image icon --- interface/resources/fonts/hifi-glyphs.ttf | Bin 31232 -> 31500 bytes .../fonts/hifi-glyphs/fonts/hifi-glyphs.eot | Bin 0 -> 31678 bytes .../fonts/hifi-glyphs/fonts/hifi-glyphs.svg | 148 ++++++++++++++++++ .../fonts/hifi-glyphs/fonts/hifi-glyphs.ttf | Bin 0 -> 31500 bytes .../fonts/hifi-glyphs/fonts/hifi-glyphs.woff | Bin 0 -> 20032 bytes .../fonts/hifi-glyphs/icons-reference.html | 94 ++++++++++- .../resources/fonts/hifi-glyphs/styles.css | 35 ++++- .../resources/icons/create-icons/image.svg | 23 +++ .../resources/qml/hifi/tablet/EditTabView.qml | 2 +- scripts/system/edit.js | 1 - scripts/system/html/js/entityProperties.js | 2 +- 11 files changed, 298 insertions(+), 7 deletions(-) create mode 100644 interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.eot create mode 100644 interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.svg create mode 100644 interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.ttf create mode 100644 interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.woff create mode 100644 interface/resources/icons/create-icons/image.svg diff --git a/interface/resources/fonts/hifi-glyphs.ttf b/interface/resources/fonts/hifi-glyphs.ttf index 4cc5a0fe4f098a287c1df067c8bff37695f96d34..8907cf7858dd304cdad024bfa1ff4ca5cd94caf9 100644 GIT binary patch delta 724 zcmX|8O=uHg5Ph>h-=@iK`jgG3nn;_(>^4eivq_UGO~Jo*03;0QVN) zX6G`+!tO43VEF|A+uTBVcJti01h6S!VKbM_%s5l^Fo2H$;<;S5k`V@J8z2?H!Cbzy z)bq8w1E5C$1r`>kGZRPhIY1l%$d}J76|h4W0UB;CbTyOD?i_ub28u0Dt*}@u&77$F zfYNh-k#!sa-mUbPOYI{+;NZ}T_jeoG9&-)t4kc;5HcC}WC9NtCSnyeP&}HzJ@u(EYPvN^4f+E^ov|n-DW(Vg0d|0kC*nP%B`gw6E$TNDaYHwBiAl^DrG#$iK__|C zgvNqQH)8RGsp$dcRy}4sMszda|BrZC7X`baPejBPrbc<$R?GqWn-6M7gWo&g@Y| z_0ABp$wt^A$>#-+s4~gUOI;p%;PR4JZB63kHo?uwYRz#?q0T5G=(k{E5D^Sl!^PgV zXrw>VZw^L=tM`g}b*VT{>$OkCZsO=x?RV*^Ad2((%v^P|?5DNrhqBl4|CbHzFM6Dk ACjbBd delta 475 zcmX|-Pe>F27{!0z?6_>Hl;lBV(GkK38QNLUDR4XK+M&==V(DOwy1BW#IkZFUivMnc zu9t>xA`)~ow8=vt6p=S0FG+_EdkD#nVnUZTW~4s&c<=Jw_uf}Nk@;hpLx6hb2{DjN z4&5p){#k?4cOcr=)0^ZiVJLkBwEn>>@&4_bHb@G%JDRubp^+~yLD>UkV%#d&)hZz< zZ3B_ zt$}N19n^G#H0Q0N%}*Hyx#|acY~|BOiC6dFNgar1PZpdz_VZ;ZyoZ|KK{OBq3$*y0~&1KYOszK#GhJ3Ro0XZUASApy0dARxVdMs@1@+ zt-^nf_8?G1_yAr@=z@5iYMY{fmkMuXy@o=qG??fZ80f@_VPLwtqn$Bz!_ea~!*o}j oc6Zu&BxUcwX_D7Z->L4-ly+$eL51KxrwMlxFZ_S{m45ugzdev~Hvj+t diff --git a/interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.eot b/interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.eot new file mode 100644 index 0000000000000000000000000000000000000000..d3591e6499c6afaf63e4a2c0f144f4722c2f8d9f GIT binary patch literal 31678 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 + + +Generated by Fontastic.me + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.ttf b/interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8907cf7858dd304cdad024bfa1ff4ca5cd94caf9 GIT binary patch literal 31500 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 literal 0 HcmV?d00001 diff --git a/interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.woff b/interface/resources/fonts/hifi-glyphs/fonts/hifi-glyphs.woff new file mode 100644 index 0000000000000000000000000000000000000000..152e5b4cfc7c4c4a93501e1299cd76b08f99f111 GIT binary patch literal 20032 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%0AM|Nb=x81LFNbI8I6Rv$RP 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

HiFi Glyphs

-

This font was created inHigh Fidelity

+

This font was created for use inHigh Fidelity

CSS mapping

  • @@ -520,8 +520,52 @@
  • -
    - +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    +

Character mapping

@@ -1034,6 +1078,50 @@
+
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +
  • +
  • +
    + +