From 241849139ffe1c0a28181c7cd32a0d65857379dd Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 15 Jan 2018 10:21:16 -0800 Subject: [PATCH 01/53] wip --- libraries/entities/CMakeLists.txt | 6 +- .../entities/src/EntityItemProperties.cpp | 43 +++++++ libraries/entities/src/EntityItemProperties.h | 37 ++++-- .../entities/src/EntityItemPropertiesMacros.h | 1 + libraries/entities/src/EntityPropertyFlags.h | 7 + libraries/entities/src/EntityTypes.cpp | 2 + libraries/entities/src/EntityTypes.h | 3 +- libraries/entities/src/MaterialEntityItem.cpp | 120 ++++++++++++++++++ libraries/entities/src/MaterialEntityItem.h | 79 ++++++++++++ libraries/shared/src/MaterialMode.h | 18 +++ 10 files changed, 301 insertions(+), 15 deletions(-) create mode 100644 libraries/entities/src/MaterialEntityItem.cpp create mode 100644 libraries/entities/src/MaterialEntityItem.h create mode 100644 libraries/shared/src/MaterialMode.h diff --git a/libraries/entities/CMakeLists.txt b/libraries/entities/CMakeLists.txt index c23740654e..191e43ebbe 100644 --- a/libraries/entities/CMakeLists.txt +++ b/libraries/entities/CMakeLists.txt @@ -1,4 +1,8 @@ set(TARGET_NAME entities) setup_hifi_library(Network Script) include_directories(SYSTEM "${OPENSSL_INCLUDE_DIR}") -link_hifi_libraries(shared networking octree avatars model) +include_hifi_library_headers(fbx) +include_hifi_library_headers(gpu) +include_hifi_library_headers(image) +include_hifi_library_headers(ktx) +link_hifi_libraries(shared networking octree avatars model model-networking) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 8bfce7e2d2..0edec88edf 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -330,6 +330,13 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RADIUS_START, radiusStart); CHECK_PROPERTY_CHANGE(PROP_RADIUS_FINISH, radiusFinish); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_URL, materialURL); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_TYPE, materialMode); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_BLEND_FACTOR, blendFactor); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_PRIORITY, priority); + CHECK_PROPERTY_CHANGE(PROP_PARENT_SHAPE_ID, shapeID); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_BOUNDS, materialBounds); + // Certifiable Properties CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName); CHECK_PROPERTY_CHANGE(PROP_ITEM_DESCRIPTION, itemDescription); @@ -623,6 +630,16 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch); } + // Materials + if (_type == EntityTypes::Material) { + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_URL, materialURL); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_TYPE, materialMode); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_BLEND_FACTOR, blendFactor); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_PRIORITY, priority); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_SHAPE_ID, shapeID); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_BOUNDS, materialBounds); + } + if (!skipDefaults && !strictSemantics) { AABox aaBox = getAABox(); QScriptValue boundingBox = engine->newObject(); @@ -755,6 +772,12 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusSpread, float, setRadiusSpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusStart, float, setRadiusStart); COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusFinish, float, setRadiusFinish); + COPY_PROPERTY_FROM_QSCRIPTVALUE(materialURL, QString, setMaterialURL); + COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMode, MaterialMode, setMaterialMode); + COPY_PROPERTY_FROM_QSCRIPTVALUE(blendFactor, float, setBlendFactor); + COPY_PROPERTY_FROM_QSCRIPTVALUE(priority, int, setPriority); + COPY_PROPERTY_FROM_QSCRIPTVALUE(shapeID, int, setShapeID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(materialBounds, glmVec4, setMaterialBounds); // Certifiable Properties COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName); @@ -1490,6 +1513,16 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_SHAPE, properties.getShape()); } + // Materials + if (properties.getType() == EntityTypes::Material) { + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_URL, properties.getMaterialURL()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, (uint32_t)properties.getMaterialMode()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, properties.getBlendFactor()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, properties.getPriority()); + APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, properties.getShapeID()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, properties.getMaterialBounds()); + } + APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName()); APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL()); APPEND_ENTITY_PROPERTY(PROP_ACTION_DATA, properties.getActionData()); @@ -1845,6 +1878,16 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE, QString, setShape); } + // Materials + if (properties.getType() == EntityTypes::Material) { + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_URL, QString, setMaterialURL); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_PRIORITY, uint32_t, setPriority); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_SHAPE_ID, uint32_t, setShapeID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_BOUNDS, glmVec4, setMaterialBounds); + } + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ACTION_DATA, QByteArray, setActionData); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index c3d04dc7ad..3190d66b63 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -44,6 +44,8 @@ #include "TextEntityItem.h" #include "ZoneEntityItem.h" +#include "MaterialMode.h" + const quint64 UNKNOWN_CREATED_TIME = 0; using ComponentPair = std::pair; @@ -58,19 +60,21 @@ const std::array COMPONENT_MODES = { { /// set of entity item properties via JavaScript hashes/QScriptValues /// all units for SI units (meter, second, radian, etc) class EntityItemProperties { - friend class EntityItem; // TODO: consider removing this friend relationship and use public methods - friend class ModelEntityItem; // TODO: consider removing this friend relationship and use public methods - friend class BoxEntityItem; // TODO: consider removing this friend relationship and use public methods - friend class SphereEntityItem; // TODO: consider removing this friend relationship and use public methods - friend class LightEntityItem; // TODO: consider removing this friend relationship and use public methods - friend class TextEntityItem; // TODO: consider removing this friend relationship and use public methods - 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 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 - friend class ShapeEntityItem; // TODO: consider removing this friend relationship and use public methods + // TODO: consider removing these friend relationship and use public methods + friend class EntityItem; + friend class ModelEntityItem; + friend class BoxEntityItem; + friend class SphereEntityItem; + friend class LightEntityItem; + friend class TextEntityItem; + friend class ParticleEffectEntityItem; + friend class ZoneEntityItem; + friend class WebEntityItem; + friend class LineEntityItem; + friend class PolyVoxEntityItem; + friend class PolyLineEntityItem; + friend class ShapeEntityItem; + friend class MaterialEntityItem; public: EntityItemProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()); virtual ~EntityItemProperties() = default; @@ -218,6 +222,13 @@ public: DEFINE_PROPERTY_REF(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube, AACube()); DEFINE_PROPERTY_REF(PROP_SHAPE, Shape, shape, QString, "Sphere"); + DEFINE_PROPERTY_REF(PROP_MATERIAL_URL, MaterialURL, materialURL, QString, ""); + DEFINE_PROPERTY_REF_ENUM(PROP_MATERIAL_TYPE, MaterialMode, materialMode, MaterialMode, UV); + DEFINE_PROPERTY_REF(PROP_MATERIAL_BLEND_FACTOR, BlendFactor, blendFactor, float, 1.0f); + DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, uint32_t, 0); + DEFINE_PROPERTY_REF(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, uint32_t, 0); + DEFINE_PROPERTY_REF(PROP_MATERIAL_BOUNDS, MaterialBounds, materialBounds, glmVec4, glm::vec4(0, 0, 1, 1)); + // Certifiable Properties - related to Proof of Purchase certificates DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME); DEFINE_PROPERTY_REF(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString, ENTITY_ITEM_DEFAULT_ITEM_DESCRIPTION); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 278d945ab0..c8c8a658ce 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -184,6 +184,7 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu } typedef glm::vec3 glmVec3; +typedef glm::vec4 glmVec4; typedef glm::quat glmQuat; typedef QVector qVectorVec3; typedef QVector qVectorQuat; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 7fd72bf0ee..fc9b5cd709 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -226,6 +226,13 @@ enum EntityPropertyList { PROP_LOCAL_DIMENSIONS, // only used to convert values to and from scripts + PROP_MATERIAL_URL, + PROP_MATERIAL_TYPE, + PROP_MATERIAL_BLEND_FACTOR, + PROP_MATERIAL_PRIORITY, + PROP_PARENT_SHAPE_ID, + PROP_MATERIAL_BOUNDS, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/EntityTypes.cpp b/libraries/entities/src/EntityTypes.cpp index cb17c28fd7..307371c649 100644 --- a/libraries/entities/src/EntityTypes.cpp +++ b/libraries/entities/src/EntityTypes.cpp @@ -29,6 +29,7 @@ #include "PolyVoxEntityItem.h" #include "PolyLineEntityItem.h" #include "ShapeEntityItem.h" +#include "MaterialEntityItem.h" QMap EntityTypes::_typeToNameMap; QMap EntityTypes::_nameToTypeMap; @@ -50,6 +51,7 @@ REGISTER_ENTITY_TYPE(PolyLine) REGISTER_ENTITY_TYPE(Shape) REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, ShapeEntityItem::boxFactory) REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, ShapeEntityItem::sphereFactory) +REGISTER_ENTITY_TYPE(Material) const QString& EntityTypes::getEntityTypeName(EntityType entityType) { QMap::iterator matchedTypeName = _typeToNameMap.find(entityType); diff --git a/libraries/entities/src/EntityTypes.h b/libraries/entities/src/EntityTypes.h index 316bf2b813..62011c6e26 100644 --- a/libraries/entities/src/EntityTypes.h +++ b/libraries/entities/src/EntityTypes.h @@ -49,7 +49,8 @@ public: PolyVox, PolyLine, Shape, - LAST = Shape + Material, + LAST = Material } EntityType; static const QString& getEntityTypeName(EntityType entityType); diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp new file mode 100644 index 0000000000..19daa11490 --- /dev/null +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -0,0 +1,120 @@ +// +// Created by Sam Gondelman on 1/12/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 "MaterialEntityItem.h" + +#include "EntityItemProperties.h" + +EntityItemPointer MaterialEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { + Pointer entity(new MaterialEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); + entity->setProperties(properties); + return entity; +} + +// our non-pure virtual subclass for now... +MaterialEntityItem::MaterialEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) { + _type = EntityTypes::Material; +} + +EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { + EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class + COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMode, getMaterialMode); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(blendFactor, getBlendFactor); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(priority, getPriority); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeID, getShapeID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialBounds, getMaterialBounds); + return properties; +} + +bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { + bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class + + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialURL, setMaterialURL); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMode, setMaterialMode); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(blendFactor, setBlendFactor); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(priority, setPriority); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeID, setShapeID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialBounds, setMaterialBounds); + + if (somethingChanged) { + bool wantDebug = false; + if (wantDebug) { + uint64_t now = usecTimestampNow(); + int elapsed = now - getLastEdited(); + qCDebug(entities) << "MaterialEntityItem::setProperties() AFTER update... edited AGO=" << elapsed << + "now=" << now << " getLastEdited()=" << getLastEdited(); + } + setLastEdited(properties.getLastEdited()); + } + return somethingChanged; +} + +int MaterialEntityItem::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_MATERIAL_URL, QString, setMaterialURL); + READ_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode); + READ_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor); + READ_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, int, setPriority); + READ_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, int, setShapeID); + READ_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, glm::vec4, setMaterialBounds); + + return bytesRead; +} + + +// TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time +EntityPropertyFlags MaterialEntityItem::getEntityProperties(EncodeBitstreamParams& params) const { + EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); + requestedProperties += PROP_MATERIAL_URL; + requestedProperties += PROP_MATERIAL_TYPE; + requestedProperties += PROP_MATERIAL_BLEND_FACTOR; + requestedProperties += PROP_MATERIAL_PRIORITY; + requestedProperties += PROP_PARENT_SHAPE_ID; + requestedProperties += PROP_MATERIAL_BOUNDS; + return requestedProperties; +} + +void MaterialEntityItem::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_MATERIAL_URL, getMaterialURL()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, getMaterialMode()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, getBlendFactor()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, getPriority()); + APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, getShapeID()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, getMaterialBounds()); +} + +void MaterialEntityItem::debugDump() const { + quint64 now = usecTimestampNow(); + qCDebug(entities) << "MATERIAL EntityItem id:" << getEntityItemID() << "---------------------------------------------"; + qCDebug(entities) << " name:" << _name; + qCDebug(entities) << " url:" << _materialURL; + qCDebug(entities) << " material type:" << _materialMode; + qCDebug(entities) << " blend factor:" << _blendFactor; + qCDebug(entities) << " priority:" << _priority; + qCDebug(entities) << " parent shape ID:" << _shapeID; + qCDebug(entities) << " material bounds:" << _materialBounds; + qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); + qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); + qCDebug(entities) << "SHAPE EntityItem Ptr:" << this; +} diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h new file mode 100644 index 0000000000..094c94f24c --- /dev/null +++ b/libraries/entities/src/MaterialEntityItem.h @@ -0,0 +1,79 @@ +// +// Created by Sam Gondelman on 1/12/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_MaterialEntityItem_h +#define hifi_MaterialEntityItem_h + +#include "EntityItem.h" + +#include "MaterialMode.h" +#include + +class MaterialEntityItem : public EntityItem { + using Pointer = std::shared_ptr; +public: + static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); + + MaterialEntityItem(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; + + // TODO: eventually only include properties changed since the params.nodeData->getLastTimeBagEmpty() time + virtual 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; + + + virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData, + bool& somethingChanged) override; + + void debugDump() const override; + + const QString& getMaterialURL() { return _materialURL; } + void setMaterialURL(const QString& materialURL) { _materialURL = materialURL; } + + MaterialMode getMaterialType() { return _materialMode; } + void setMaterialMode(MaterialMode mode); + + float getBlendFactor() { return _blendFactor; } + void setBlendFactor(float blendFactor) { _blendFactor = blendFactor; } + + int getPriority() { return _priority; } + void setPriority(int priority) { _priority = priority; } + + int getShapeID() { return _shapeID; } + void setShapeID(int shapeID) { _shapeID = shapeID; } + + const glm::vec4& getMaterialBounds() { return _materialBounds; } + void setMaterialBounds(const glm::vec4& materialBounds) { _materialBounds = materialBounds; } + +protected: + QString _materialURL; + MaterialMode _materialMode { UV }; + float _blendFactor { 1.0f }; + int _priority { 0 }; + int _shapeID { 0 }; + glm::vec4 _materialBounds { 0, 0, 1, 1 }; + + //NetworkMaterial _material; + +}; + +#endif // hifi_MaterialEntityItem_h diff --git a/libraries/shared/src/MaterialMode.h b/libraries/shared/src/MaterialMode.h new file mode 100644 index 0000000000..05c6d295a5 --- /dev/null +++ b/libraries/shared/src/MaterialMode.h @@ -0,0 +1,18 @@ +// +// Created by Sam Gondelman on 1/12/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_MaterialMode_h +#define hifi_MaterialMode_h + +enum MaterialMode { + UV = 0, + PROJECTED +}; + +#endif // hifi_MaterialMode_h + From 5a771e3a168357708d646dcba70c79ceb7eb4cb4 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 26 Jan 2018 17:08:53 -0500 Subject: [PATCH 02/53] [Case 10865] Ctrl/Cmd/Shift+Click Multi-Select for Asset Browser. * Removes manual selectionModel update from controls-uit/Tree.qml * This was interfering with the Key+Click functionality. It was introduced via Commit 99617600c47 to address a selection issue; however, it's unclear what that issue was. Selection within the Asset Browser works without it at present. * Amends the ContextMenu within the AssetBrowser to work in conjunction with the multi-selection changes. * ContextMenu will _only_ display when triggered within the current selection be it one or more items as opposed to previous behavior of selecting the item the menu was triggered on. * CopyURL is only enabled when the selection size is 1 * Rename is only enabled when the selection size is 1 * Delete is enabled when the selection size is greater than 0 Changes Committed: modified: interface/resources/qml/controls-uit/Tree.qml modified: interface/resources/qml/hifi/AssetServer.qml --- interface/resources/qml/controls-uit/Tree.qml | 4 -- interface/resources/qml/hifi/AssetServer.qml | 41 +++++++++++-------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/interface/resources/qml/controls-uit/Tree.qml b/interface/resources/qml/controls-uit/Tree.qml index 6bd11295b1..5199a10a27 100644 --- a/interface/resources/qml/controls-uit/Tree.qml +++ b/interface/resources/qml/controls-uit/Tree.qml @@ -202,8 +202,4 @@ TreeView { } onDoubleClicked: isExpanded(index) ? collapse(index) : expand(index) - - onClicked: { - selectionModel.setCurrentIndex(index, ItemSelectionModel.ClearAndSelect); - } } diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index 37c3c2adab..7c16b19865 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -694,7 +694,7 @@ Windows.ScrollingWindow { } } } - } + }// End_OF( itemLoader ) Rectangle { id: treeLabelToolTip @@ -731,50 +731,59 @@ Windows.ScrollingWindow { showTimer.stop(); treeLabelToolTip.visible = false; } - } + }// End_OF( treeLabelToolTip ) MouseArea { propagateComposedEvents: true anchors.fill: parent acceptedButtons: Qt.RightButton onClicked: { - if (!HMD.active) { // Popup only displays properly on desktop - var index = treeView.indexAt(mouse.x, mouse.y); - treeView.selection.setCurrentIndex(index, 0x0002); - contextMenu.currentIndex = index; - contextMenu.popup(); + if (treeView.selection.hasSelection && !HMD.active) { // Popup only displays properly on desktop + // Only display the popup if the click triggered within + // the selection. + var clickedIndex = treeView.indexAt(mouse.x, mouse.y); + var displayContextMenu = false; + for ( var i = 0; i < selectedItems; ++i) { + var currentSelectedIndex = treeView.selection.selectedIndexes[i]; + if (clickedIndex === currentSelectedIndex) { + contextMenu.popup(); + break; + } + } } } } - + Menu { id: contextMenu title: "Edit" property var url: "" - property var currentIndex: null MenuItem { text: "Copy URL" + enabled: (selectedItems == 1) onTriggered: { - copyURLToClipboard(contextMenu.currentIndex); + copyURLToClipboard(treeView.selection.currentIndex); } } MenuItem { text: "Rename" + enabled: (selectedItems == 1) onTriggered: { - renameFile(contextMenu.currentIndex); + renameFile(treeView.selection.currentIndex); } } MenuItem { text: "Delete" + enabled: (selectedItems > 0) onTriggered: { - deleteFile(contextMenu.currentIndex); + deleteFile(); } } - } - } + }// End_OF( contextMenu ) + }// End_OF( treeView ) Row { id: infoRow @@ -885,7 +894,7 @@ Windows.ScrollingWindow { "Baking compresses and optimizes files for faster network transfer and display. We recommend you bake your content to reduce initial load times for your visitors."); } } - } + }// End_OF( infoRow ) HifiControls.ContentSection { id: uploadSection @@ -945,7 +954,7 @@ Windows.ScrollingWindow { } } } - } + }// End_OF( uploadSection ) } } From dfdf28f37e4572bb95b6354be850356ad8bffa27 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Fri, 26 Jan 2018 17:34:05 -0500 Subject: [PATCH 03/53] [Case 10865] Some cleanup for multi-selection (details below). * Remove setCurrentIndex call when looping over current selection. * Changed selectedItems var name to selectedItemCount to clarify what it represents. * Change path arg name to paths to clarify that there can be more than a single path contained within it. Changes Committed: modified: interface/resources/qml/hifi/AssetServer.qml --- interface/resources/qml/hifi/AssetServer.qml | 49 ++++++++++---------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index 7c16b19865..30f76fecd6 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -37,7 +37,7 @@ Windows.ScrollingWindow { property var assetProxyModel: Assets.proxyModel; property var assetMappingsModel: Assets.mappingModel; property var currentDirectory; - property var selectedItems: treeView.selection.selectedIndexes.length; + property var selectedItemCount: treeView.selection.selectedIndexes.length; Settings { category: "Overlay.AssetServer" @@ -75,17 +75,17 @@ Windows.ScrollingWindow { }); } - function doDeleteFile(path) { - console.log("Deleting " + path); + function doDeleteFile(paths) { + console.log("Deleting " + paths); - Assets.deleteMappings(path, function(err) { + Assets.deleteMappings(paths, function(err) { if (err) { - console.log("Asset browser - error deleting path: ", path, err); + console.log("Asset browser - error deleting paths: ", paths, err); - box = errorMessageBox("There was an error deleting:\n" + path + "\n" + err); + box = errorMessageBox("There was an error deleting:\n" + paths + "\n" + err); box.selected.connect(reload); } else { - console.log("Asset browser - finished deleting path: ", path); + console.log("Asset browser - finished deleting paths: ", paths); reload(); } }); @@ -145,7 +145,7 @@ Windows.ScrollingWindow { function canAddToWorld(path) { var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i]; - if (selectedItems > 1) { + if (selectedItemCount > 1) { return false; } @@ -155,7 +155,7 @@ Windows.ScrollingWindow { } function canRename() { - if (treeView.selection.hasSelection && selectedItems == 1) { + if (treeView.selection.hasSelection && selectedItemCount == 1) { return true; } else { return false; @@ -333,29 +333,28 @@ Windows.ScrollingWindow { }); } function deleteFile(index) { - var path = []; + var paths = []; if (!index) { - for (var i = 0; i < selectedItems; i++) { - treeView.selection.setCurrentIndex(treeView.selection.selectedIndexes[i], 0x100); - index = treeView.selection.currentIndex; - path[i] = assetProxyModel.data(index, 0x100); + for (var i = 0; i < selectedItemCount; ++i) { + index = treeView.selection.selectedIndexes[i]; + paths[i] = assetProxyModel.data(index, 0x100); } } - if (!path) { + if (!paths) { return; } var modalMessage = ""; - var items = selectedItems.toString(); + var items = selectedItemCount.toString(); var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101); var typeString = isFolder ? 'folder' : 'file'; - if (selectedItems > 1) { + if (selectedItemCount > 1) { modalMessage = "You are about to delete " + items + " items \nDo you want to continue?"; } else { - modalMessage = "You are about to delete the following " + typeString + ":\n" + path + "\nDo you want to continue?"; + modalMessage = "You are about to delete the following " + typeString + ":\n" + paths + "\nDo you want to continue?"; } var object = desktop.messageBox({ @@ -367,7 +366,7 @@ Windows.ScrollingWindow { }); object.selected.connect(function(button) { if (button === OriginalDialogs.StandardButton.Yes) { - doDeleteFile(path); + doDeleteFile(paths); } }); } @@ -743,7 +742,7 @@ Windows.ScrollingWindow { // the selection. var clickedIndex = treeView.indexAt(mouse.x, mouse.y); var displayContextMenu = false; - for ( var i = 0; i < selectedItems; ++i) { + for ( var i = 0; i < selectedItemCount; ++i) { var currentSelectedIndex = treeView.selection.selectedIndexes[i]; if (clickedIndex === currentSelectedIndex) { contextMenu.popup(); @@ -761,7 +760,7 @@ Windows.ScrollingWindow { MenuItem { text: "Copy URL" - enabled: (selectedItems == 1) + enabled: (selectedItemCount == 1) onTriggered: { copyURLToClipboard(treeView.selection.currentIndex); } @@ -769,7 +768,7 @@ Windows.ScrollingWindow { MenuItem { text: "Rename" - enabled: (selectedItems == 1) + enabled: (selectedItemCount == 1) onTriggered: { renameFile(treeView.selection.currentIndex); } @@ -777,7 +776,7 @@ Windows.ScrollingWindow { MenuItem { text: "Delete" - enabled: (selectedItems > 0) + enabled: (selectedItemCount > 0) onTriggered: { deleteFile(); } @@ -796,8 +795,8 @@ Windows.ScrollingWindow { function makeText() { var numPendingBakes = assetMappingsModel.numPendingBakes; - if (selectedItems > 1 || numPendingBakes === 0) { - return selectedItems + " items selected"; + if (selectedItemCount > 1 || numPendingBakes === 0) { + return selectedItemCount + " items selected"; } else { return numPendingBakes + " bakes pending" } From 70e23f3ce86f5837f24eaea39c422aeea23c64f0 Mon Sep 17 00:00:00 2001 From: LaShonda Hopper Date: Tue, 30 Jan 2018 14:00:09 -0500 Subject: [PATCH 04/53] [Case 10865] Bringing in multi-select fix from Desktop AssetServer. Changes Committed: modified: interface/resources/qml/hifi/dialogs/TabletAssetServer.qml --- .../qml/hifi/dialogs/TabletAssetServer.qml | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml index a02496a252..9c61206592 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml @@ -39,7 +39,7 @@ Rectangle { property var assetProxyModel: Assets.proxyModel; property var assetMappingsModel: Assets.mappingModel; property var currentDirectory; - property var selectedItems: treeView.selection.selectedIndexes.length; + property var selectedItemCount: treeView.selection.selectedIndexes.length; Settings { category: "Overlay.AssetServer" @@ -76,17 +76,17 @@ Rectangle { }); } - function doDeleteFile(path) { - console.log("Deleting " + path); + function doDeleteFile(paths) { + console.log("Deleting " + paths); - Assets.deleteMappings(path, function(err) { + Assets.deleteMappings(paths, function(err) { if (err) { - console.log("Asset browser - error deleting path: ", path, err); + console.log("Asset browser - error deleting paths: ", paths, err); - box = errorMessageBox("There was an error deleting:\n" + path + "\n" + err); + box = errorMessageBox("There was an error deleting:\n" + paths + "\n" + err); box.selected.connect(reload); } else { - console.log("Asset browser - finished deleting path: ", path); + console.log("Asset browser - finished deleting paths: ", paths); reload(); } }); @@ -146,7 +146,7 @@ Rectangle { function canAddToWorld(path) { var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i]; - if (selectedItems > 1) { + if (selectedItemCount > 1) { return false; } @@ -156,7 +156,7 @@ Rectangle { } function canRename() { - if (treeView.selection.hasSelection && selectedItems == 1) { + if (treeView.selection.hasSelection && selectedItemCount == 1) { return true; } else { return false; @@ -334,29 +334,28 @@ Rectangle { }); } function deleteFile(index) { - var path = []; + var paths = []; if (!index) { - for (var i = 0; i < selectedItems; i++) { - treeView.selection.setCurrentIndex(treeView.selection.selectedIndexes[i], 0x100); - index = treeView.selection.currentIndex; - path[i] = assetProxyModel.data(index, 0x100); + for (var i = 0; i < selectedItemCount; ++i) { + index = treeView.selection.selectedIndexes[i]; + paths[i] = assetProxyModel.data(index, 0x100); } } - if (!path) { + if (!paths) { return; } var modalMessage = ""; - var items = selectedItems.toString(); + var items = selectedItemCount.toString(); var isFolder = assetProxyModel.data(treeView.selection.currentIndex, 0x101); var typeString = isFolder ? 'folder' : 'file'; - if (selectedItems > 1) { + if (selectedItemCount > 1) { modalMessage = "You are about to delete " + items + " items \nDo you want to continue?"; } else { - modalMessage = "You are about to delete the following " + typeString + ":\n" + path + "\nDo you want to continue?"; + modalMessage = "You are about to delete the following " + typeString + ":\n" + paths + "\nDo you want to continue?"; } var object = tabletRoot.messageBox({ @@ -368,7 +367,7 @@ Rectangle { }); object.selected.connect(function(button) { if (button === OriginalDialogs.StandardButton.Yes) { - doDeleteFile(path); + doDeleteFile(paths); } }); } @@ -693,7 +692,7 @@ Rectangle { } } } - } + }// End_OF( itemLoader ) Rectangle { id: treeLabelToolTip @@ -730,50 +729,59 @@ Rectangle { showTimer.stop(); treeLabelToolTip.visible = false; } - } + }// End_OF( treeLabelToolTip ) MouseArea { propagateComposedEvents: true anchors.fill: parent acceptedButtons: Qt.RightButton onClicked: { - if (!HMD.active) { // Popup only displays properly on desktop - var index = treeView.indexAt(mouse.x, mouse.y); - treeView.selection.setCurrentIndex(index, 0x0002); - contextMenu.currentIndex = index; - contextMenu.popup(); + if (treeView.selection.hasSelection && !HMD.active) { // Popup only displays properly on desktop + // Only display the popup if the click triggered within + // the selection. + var clickedIndex = treeView.indexAt(mouse.x, mouse.y); + var displayContextMenu = false; + for ( var i = 0; i < selectedItemCount; ++i) { + var currentSelectedIndex = treeView.selection.selectedIndexes[i]; + if (clickedIndex === currentSelectedIndex) { + contextMenu.popup(); + break; + } + } } } } - + Menu { id: contextMenu title: "Edit" property var url: "" - property var currentIndex: null MenuItem { text: "Copy URL" + enabled: (selectedItemCount == 1) onTriggered: { - copyURLToClipboard(contextMenu.currentIndex); + copyURLToClipboard(treeView.selection.currentIndex); } } MenuItem { text: "Rename" + enabled: (selectedItemCount == 1) onTriggered: { - renameFile(contextMenu.currentIndex); + renameFile(treeView.selection.currentIndex); } } MenuItem { text: "Delete" + enabled: (selectedItemCount > 0) onTriggered: { - deleteFile(contextMenu.currentIndex); + deleteFile(); } } - } - } + }// End_OF( contextMenu ) + }// End_OF( treeView ) Row { id: infoRow @@ -786,8 +794,8 @@ Rectangle { function makeText() { var numPendingBakes = assetMappingsModel.numPendingBakes; - if (selectedItems > 1 || numPendingBakes === 0) { - return selectedItems + " items selected"; + if (selectedItemCount > 1 || numPendingBakes === 0) { + return selectedItemCount + " items selected"; } else { return numPendingBakes + " bakes pending" } @@ -884,7 +892,7 @@ Rectangle { "Baking compresses and optimizes files for faster network transfer and display. We recommend you bake your content to reduce initial load times for your visitors."); } } - } + }// End_OF( infoRow ) HifiControls.TabletContentSection { id: uploadSection @@ -961,7 +969,7 @@ Rectangle { } } } - } + }// End_OF( uploadSection ) } } From d7f4b033e8f6d5249e43001dac5f1453093a4e06 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 17 Jan 2018 15:56:18 -0800 Subject: [PATCH 05/53] wip finish adding material entity --- .../resources/qml/hifi/tablet/EditTabView.qml | 11 + .../qml/hifi/tablet/NewMaterialDialog.qml | 174 +++++++++++++ .../src/RenderableEntityItem.cpp | 7 +- .../src/RenderableEntityItem.h | 1 - .../src/RenderableMaterialEntityItem.cpp | 238 ++++++++++++++++++ .../src/RenderableMaterialEntityItem.h | 54 ++++ .../entities/src/EntityItemProperties.cpp | 63 ++++- .../entities/src/EntityItemPropertiesMacros.h | 23 ++ libraries/entities/src/MaterialEntityItem.cpp | 229 +++++++++++++++-- libraries/entities/src/MaterialEntityItem.h | 34 ++- libraries/graphics/src/graphics/Material.cpp | 2 +- .../src/model-networking/ModelCache.cpp | 91 ++++++- .../src/model-networking/ModelCache.h | 20 +- .../src/model-networking/TextureCache.cpp | 2 + .../src/model-networking/TextureCache.h | 1 - libraries/networking/src/ResourceCache.cpp | 9 +- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- libraries/octree/src/OctreePacketData.h | 4 + .../src/CauterizedMeshPartPayload.cpp | 4 +- .../src/CauterizedMeshPartPayload.h | 2 +- libraries/render-utils/src/GeometryCache.cpp | 1 - .../render-utils/src/MeshPartPayload.cpp | 152 +---------- libraries/render-utils/src/MeshPartPayload.h | 8 +- libraries/render/CMakeLists.txt | 6 +- libraries/render/src/render/ShapePipeline.cpp | 121 +++++++++ libraries/render/src/render/ShapePipeline.h | 4 + libraries/shared/src/MaterialMode.cpp | 24 ++ libraries/shared/src/MaterialMode.h | 7 + scripts/developer/tests/toolbarTest.js | 12 +- scripts/system/edit.js | 45 +++- scripts/system/html/css/edit-style.css | 49 +++- scripts/system/html/entityProperties.html | 45 ++++ scripts/system/html/js/entityProperties.js | 52 +++- scripts/system/libraries/entityList.js | 10 +- 35 files changed, 1291 insertions(+), 219 deletions(-) create mode 100644 interface/resources/qml/hifi/tablet/NewMaterialDialog.qml create mode 100644 libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp create mode 100644 libraries/entities-renderer/src/RenderableMaterialEntityItem.h create mode 100644 libraries/shared/src/MaterialMode.cpp diff --git a/interface/resources/qml/hifi/tablet/EditTabView.qml b/interface/resources/qml/hifi/tablet/EditTabView.qml index e94325f399..65dd871fb2 100644 --- a/interface/resources/qml/hifi/tablet/EditTabView.qml +++ b/interface/resources/qml/hifi/tablet/EditTabView.qml @@ -133,6 +133,17 @@ TabView { editTabView.currentIndex = 4 } } + + NewEntityButton { + icon: "icons/create-icons/94-model-01.svg" + text: "MATERIAL" + onClicked: { + editRoot.sendToScript({ + method: "newEntityButtonClicked", params: { buttonName: "newMaterialButton" } + }); + editTabView.currentIndex = 2 + } + } } HifiControls.Button { diff --git a/interface/resources/qml/hifi/tablet/NewMaterialDialog.qml b/interface/resources/qml/hifi/tablet/NewMaterialDialog.qml new file mode 100644 index 0000000000..6d3477187b --- /dev/null +++ b/interface/resources/qml/hifi/tablet/NewMaterialDialog.qml @@ -0,0 +1,174 @@ +// +// NewMaterialDialog.qml +// qml/hifi +// +// Created by Sam Gondelman on 1/17/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 +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import QtQuick.Dialogs 1.2 as OriginalDialogs + +import "../../styles-uit" +import "../../controls-uit" +import "../dialogs" + +Rectangle { + id: newMaterialDialog + // width: parent.width + // height: parent.height + HifiConstants { id: hifi } + color: hifi.colors.baseGray; + signal sendToScript(var message); + property bool keyboardEnabled: false + property bool punctuationMode: false + property bool keyboardRasied: false + + function errorMessageBox(message) { + return desktop.messageBox({ + icon: hifi.icons.warning, + defaultButton: OriginalDialogs.StandardButton.Ok, + title: "Error", + text: message + }); + } + + Item { + id: column1 + anchors.rightMargin: 10 + anchors.leftMargin: 10 + anchors.bottomMargin: 10 + anchors.topMargin: 10 + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: keyboard.top + + Text { + id: text1 + text: qsTr("Material URL") + color: "#ffffff" + font.pixelSize: 12 + } + + TextInput { + id: materialURL + height: 20 + text: qsTr("") + color: "white" + anchors.top: text1.bottom + anchors.topMargin: 5 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.right: parent.right + anchors.rightMargin: 0 + font.pixelSize: 12 + + onAccepted: { + newMaterialDialog.keyboardEnabled = false; + } + + MouseArea { + anchors.fill: parent + onClicked: { + newMaterialDialog.keyboardEnabled = HMD.active + parent.focus = true; + parent.forceActiveFocus(); + materialURL.cursorPosition = materialURL.positionAt(mouseX, mouseY, TextInput.CursorBetweenCharaters); + } + } + } + + Rectangle { + id: textInputBox + color: "white" + anchors.fill: materialURL + opacity: 0.1 + } + + Row { + id: row1 + height: 400 + spacing: 30 + anchors.top: materialURL.bottom + anchors.topMargin: 5 + anchors.left: parent.left + anchors.leftMargin: 0 + anchors.right: parent.right + anchors.rightMargin: 0 + + Column { + id: column3 + height: 400 + spacing: 10 + + Text { + id: text3 + text: qsTr("Material Mode") + color: "#ffffff" + font.pixelSize: 12 + } + + ComboBox { + id: materialMode + property var materialArray: ["UV space material", + "3D projected material"] + + width: 200 + z: 100 + transformOrigin: Item.Center + model: materialArray + } + + Row { + id: row3 + width: 200 + height: 400 + spacing: 5 + + anchors.horizontalCenter: column3.horizontalCenter + anchors.horizontalCenterOffset: -20 + + Button { + id: button1 + text: qsTr("Add") + z: -1 + onClicked: { + newMaterialDialog.sendToScript({ + method: "newMaterialDialogAdd", + params: { + textInput: materialURL.text, + comboBox: materialMode.currentIndex + } + }); + } + } + + Button { + id: button2 + z: -1 + text: qsTr("Cancel") + onClicked: { + newMaterialDialog.sendToScript({method: "newMaterialDialogCancel"}) + } + } + } + } + } + } + + Keyboard { + id: keyboard + raised: parent.keyboardEnabled + numeric: parent.punctuationMode + anchors { + bottom: parent.bottom + left: parent.left + right: parent.right + } + } +} diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index fb9aba636b..cbd2df86ad 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -25,6 +25,7 @@ #include "RenderableTextEntityItem.h" #include "RenderableWebEntityItem.h" #include "RenderableZoneEntityItem.h" +#include "RenderableMaterialEntityItem.h" using namespace render; @@ -247,6 +248,10 @@ EntityRenderer::Pointer EntityRenderer::addToScene(EntityTreeRenderer& renderer, result = make_renderer(entity); break; + case Type::Material: + result = make_renderer(entity); + break; + default: break; } @@ -388,4 +393,4 @@ void EntityRenderer::onAddToScene(const EntityItemPointer& entity) { void EntityRenderer::onRemoveFromScene(const EntityItemPointer& entity) { entity->deregisterChangeHandler(_changeHandlerId); QObject::disconnect(this, &EntityRenderer::requestRenderUpdate, this, nullptr); -} +} \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 8eb82e2c6e..e54ae2f6b4 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -59,7 +59,6 @@ protected: virtual void onAddToScene(const EntityItemPointer& entity); virtual void onRemoveFromScene(const EntityItemPointer& entity); -protected: EntityRenderer(const EntityItemPointer& entity); ~EntityRenderer(); diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp new file mode 100644 index 0000000000..83754c1c16 --- /dev/null +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -0,0 +1,238 @@ +// +// Created by Sam Gondelman on 1/18/2018 +// 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 "RenderableMaterialEntityItem.h" + +using namespace render; +using namespace render::entities; + +bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const { + if (entity->getMaterial() != _drawMaterial) { + return true; + } + return false; +} + +void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { + withWriteLock([&] { + _drawMaterial = entity->getMaterial(); + _renderTransform = getModelTransform(); + const float MATERIAL_ENTITY_SCALE = 0.5f; + _renderTransform.postScale(MATERIAL_ENTITY_SCALE); + _renderTransform.postScale(ENTITY_ITEM_DEFAULT_DIMENSIONS); + }); +} + +ItemKey MaterialEntityRenderer::getKey() { + ItemKey::Builder builder; + builder.withTypeShape(); + + if (!_visible) { + builder.withInvisible(); + } + + if (_drawMaterial) { + auto matKey = _drawMaterial->getKey(); + if (matKey.isTranslucent()) { + builder.withTransparent(); + } + } + + return builder.build(); +} + +ShapeKey MaterialEntityRenderer::getShapeKey() { + graphics::MaterialKey drawMaterialKey; + if (_drawMaterial) { + drawMaterialKey = _drawMaterial->getKey(); + } + + bool isTranslucent = drawMaterialKey.isTranslucent(); + bool hasTangents = drawMaterialKey.isNormalMap(); + bool hasSpecular = drawMaterialKey.isMetallicMap(); + bool hasLightmap = drawMaterialKey.isLightmapMap(); + bool isUnlit = drawMaterialKey.isUnlit(); + + ShapeKey::Builder builder; + builder.withMaterial(); + + if (isTranslucent) { + builder.withTranslucent(); + } + if (hasTangents) { + builder.withTangents(); + } + if (hasSpecular) { + builder.withSpecular(); + } + if (hasLightmap) { + builder.withLightmap(); + } + if (isUnlit) { + builder.withUnlit(); + } + + return builder.build(); +} + +glm::vec3 MaterialEntityRenderer::getVertexPos(float phi, float theta) { + return glm::vec3(glm::sin(theta) * glm::cos(phi), glm::cos(theta), glm::sin(theta) * glm::sin(phi)); +} + +glm::vec3 MaterialEntityRenderer::getTangent(float phi, float theta) { + return glm::vec3(-glm::cos(theta) * glm::cos(phi), 0, -glm::cos(theta) * glm::sin(phi)); +} + +void MaterialEntityRenderer::addVertex(std::vector& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv) { + buffer.push_back(pos.x); buffer.push_back(pos.y); buffer.push_back(pos.z); + buffer.push_back(tan.x); buffer.push_back(tan.y); buffer.push_back(tan.z); + buffer.push_back(uv.x); buffer.push_back(uv.y); +} + +void MaterialEntityRenderer::addTriangleFan(std::vector& buffer, int stack, int step) { + float v1 = ((float)stack) / STACKS; + float theta1 = v1 * M_PI; + glm::vec3 tip = getVertexPos(0, theta1); + float v2 = ((float)(stack + step)) / STACKS; + float theta2 = v2 * M_PI; + for (int i = 0; i < SLICES; i++) { + float u1 = ((float)i) / SLICES; + float u2 = ((float)(i + step)) / SLICES; + float phi1 = u1 * M_PI_TIMES_2; + float phi2 = u2 * M_PI_TIMES_2; + /* (flipped for negative step) + p1 + / \ + / \ + / \ + p3 ------ p2 + */ + + glm::vec3 pos2 = getVertexPos(phi2, theta2); + glm::vec3 pos3 = getVertexPos(phi1, theta2); + + glm::vec3 tan1 = getTangent(0, theta1); + glm::vec3 tan2 = getTangent(phi2, theta2); + glm::vec3 tan3 = getTangent(phi1, theta2); + + glm::vec2 uv1 = glm::vec2((u1 + u2) / 2.0f, v1); + glm::vec2 uv2 = glm::vec2(u2, v2); + glm::vec2 uv3 = glm::vec2(u1, v2); + + addVertex(buffer, tip, tan1, uv1); + addVertex(buffer, pos2, tan2, uv2); + addVertex(buffer, pos3, tan3, uv3); + + _numVertices += 3; + } +} + +int MaterialEntityRenderer::_numVertices = 0; +std::shared_ptr MaterialEntityRenderer::_streamFormat = nullptr; +std::shared_ptr MaterialEntityRenderer::_stream = nullptr; +std::shared_ptr MaterialEntityRenderer::_verticesBuffer = nullptr; + +void MaterialEntityRenderer::generateMesh() { + _streamFormat = std::make_shared(); + _stream = std::make_shared(); + _verticesBuffer = std::make_shared(); + + const int NUM_POS_COORDS = 3; + const int NUM_TANGENT_COORDS = 3; + const int VERTEX_TANGENT_OFFSET = NUM_POS_COORDS * sizeof(float); + const int VERTEX_TEXCOORD_OFFSET = VERTEX_TANGENT_OFFSET + NUM_TANGENT_COORDS * sizeof(float); + + _streamFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); + _streamFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); + _streamFormat->setAttribute(gpu::Stream::TANGENT, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), VERTEX_TANGENT_OFFSET); + _streamFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), VERTEX_TEXCOORD_OFFSET); + + _stream->addBuffer(_verticesBuffer, 0, _streamFormat->getChannels().at(0)._stride); + + std::vector vertexBuffer; + + // Top + addTriangleFan(vertexBuffer, 0, 1); + + // Middle section + for (int j = 1; j < STACKS - 1; j++) { + float v1 = ((float)j) / STACKS; + float v2 = ((float)(j + 1)) / STACKS; + float theta1 = v1 * M_PI; + float theta2 = v2 * M_PI; + for (int i = 0; i < SLICES; i++) { + float u1 = ((float)i) / SLICES; + float u2 = ((float)(i + 1)) / SLICES; + float phi1 = u1 * M_PI_TIMES_2; + float phi2 = u2 * M_PI_TIMES_2; + + /* + p2 ---- p3 + | / | + | / | + | / | + p1 ---- p4 + */ + + glm::vec3 pos1 = getVertexPos(phi1, theta2); + glm::vec3 pos2 = getVertexPos(phi1, theta1); + glm::vec3 pos3 = getVertexPos(phi2, theta1); + glm::vec3 pos4 = getVertexPos(phi2, theta2); + + glm::vec3 tan1 = getTangent(phi1, theta2); + glm::vec3 tan2 = getTangent(phi1, theta1); + glm::vec3 tan3 = getTangent(phi2, theta1); + glm::vec3 tan4 = getTangent(phi2, theta2); + + glm::vec2 uv1 = glm::vec2(u1, v2); + glm::vec2 uv2 = glm::vec2(u1, v1); + glm::vec2 uv3 = glm::vec2(u2, v1); + glm::vec2 uv4 = glm::vec2(u2, v2); + + addVertex(vertexBuffer, pos1, tan1, uv1); + addVertex(vertexBuffer, pos2, tan2, uv2); + addVertex(vertexBuffer, pos3, tan3, uv3); + + addVertex(vertexBuffer, pos3, tan3, uv3); + addVertex(vertexBuffer, pos4, tan4, uv4); + addVertex(vertexBuffer, pos1, tan1, uv1); + + _numVertices += 6; + } + } + + // Bottom + addTriangleFan(vertexBuffer, STACKS, -1); + + _verticesBuffer->append(vertexBuffer.size() * sizeof(float), (gpu::Byte*) vertexBuffer.data()); +} + +void MaterialEntityRenderer::doRender(RenderArgs* args) { + PerformanceTimer perfTimer("RenderableMaterialEntityItem::render"); + Q_ASSERT(args->_batch); + + gpu::Batch& batch = *args->_batch; + + batch.setModelTransform(_renderTransform); + + // bind the material + args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing); + args->_details._materialSwitches++; + + // Draw! + if (_numVertices == 0) { + generateMesh(); + } + + batch.setInputFormat(_streamFormat); + batch.setInputStream(0, *_stream); + batch.draw(gpu::TRIANGLES, _numVertices, 0); + + const int NUM_VERTICES_PER_TRIANGLE = 3; + args->_details._trianglesRendered += _numVertices / NUM_VERTICES_PER_TRIANGLE; +} diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h new file mode 100644 index 0000000000..166ad762cc --- /dev/null +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -0,0 +1,54 @@ +// +// Created by Sam Gondelman on 1/18/2018 +// 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_RenderableMaterialEntityItem_h +#define hifi_RenderableMaterialEntityItem_h + +#include "RenderableEntityItem.h" + +#include + +class NetworkMaterial; + +namespace render { namespace entities { + +class MaterialEntityRenderer : public TypedEntityRenderer { + using Parent = TypedEntityRenderer; + using Pointer = std::shared_ptr; +public: + MaterialEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {} + +private: + virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override; + virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; + virtual void doRender(RenderArgs* args) override; + + ItemKey getKey() override; + ShapeKey getShapeKey() override; + + Transform _renderTransform; + + std::shared_ptr _drawMaterial; + + static int _numVertices; + static std::shared_ptr _streamFormat; + static std::shared_ptr _stream; + static std::shared_ptr _verticesBuffer; + + void generateMesh(); + void addTriangleFan(std::vector& buffer, int stack, int step); + static glm::vec3 getVertexPos(float phi, float theta); + static glm::vec3 getTangent(float phi, float theta); + static void addVertex(std::vector& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv); + const int SLICES = 15; + const int STACKS = 9; + const float M_PI_TIMES_2 = 2.0f * M_PI; +}; + +} } +#endif // hifi_RenderableMaterialEntityItem_h diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index f8f8859d73..77300be399 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -115,6 +115,17 @@ void buildStringToShapeTypeLookup() { addShapeType(SHAPE_TYPE_STATIC_MESH); } +QHash stringToMaterialModeLookup; + +void addMaterialMode(MaterialMode mode) { + stringToMaterialModeLookup[MaterialModeHelpers::getNameForMaterialMode(mode)] = mode; +} + +void buildStringToMaterialModeLookup() { + addMaterialMode(UV); + addMaterialMode(PROJECTED); +} + QString getCollisionGroupAsString(uint8_t group) { switch (group) { case USER_COLLISION_GROUP_DYNAMIC: @@ -259,6 +270,21 @@ void EntityItemProperties::setSkyboxModeFromString(const QString& skyboxMode) { } } +QString EntityItemProperties::getMaterialModeAsString() const { + return MaterialModeHelpers::getNameForMaterialMode(_materialMode); +} + +void EntityItemProperties::setMaterialModeFromString(const QString& materialMode) { + if (stringToMaterialModeLookup.empty()) { + buildStringToMaterialModeLookup(); + } + auto materialModeItr = stringToMaterialModeLookup.find(materialMode.toLower()); + if (materialModeItr != stringToMaterialModeLookup.end()) { + _materialMode = materialModeItr.value(); + _materialModeChanged = true; + } +} + EntityPropertyFlags EntityItemProperties::getChangedProperties() const { EntityPropertyFlags changedProperties; @@ -329,7 +355,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RADIUS_SPREAD, radiusSpread); CHECK_PROPERTY_CHANGE(PROP_RADIUS_START, radiusStart); CHECK_PROPERTY_CHANGE(PROP_RADIUS_FINISH, radiusFinish); - CHECK_PROPERTY_CHANGE(PROP_MATERIAL_URL, materialURL); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_TYPE, materialMode); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_BLEND_FACTOR, blendFactor); @@ -635,7 +660,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool // Materials if (_type == EntityTypes::Material) { COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_URL, materialURL); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_TYPE, materialMode); + COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_MATERIAL_TYPE, materialMode, getMaterialModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_BLEND_FACTOR, blendFactor); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_PRIORITY, priority); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_SHAPE_ID, shapeID); @@ -776,7 +801,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusFinish, float, setRadiusFinish); COPY_PROPERTY_FROM_QSCRIPTVALUE(relayParentJoints, bool, setRelayParentJoints); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialURL, QString, setMaterialURL); - COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMode, MaterialMode, setMaterialMode); + COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(materialMode, MaterialMode, setMaterialMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(blendFactor, float, setBlendFactor); COPY_PROPERTY_FROM_QSCRIPTVALUE(priority, int, setPriority); COPY_PROPERTY_FROM_QSCRIPTVALUE(shapeID, int, setShapeID); @@ -1135,6 +1160,13 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_RADIUS_START, RadiusStart, radiusStart, float); ADD_PROPERTY_TO_MAP(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_URL, MaterialURL, materialURL, QString); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_TYPE, MaterialMode, materialMode, MaterialMode); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_BLEND_FACTOR, BlendFactor, blendFactor, float); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_PRIORITY, Priority, priority, uint32_t); + ADD_PROPERTY_TO_MAP(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, uint32_t); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_BOUNDS, MaterialBounds, materialBounds, glmVec4); + // Certifiable Properties ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString); ADD_PROPERTY_TO_MAP(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString); @@ -2067,6 +2099,13 @@ void EntityItemProperties::markAllChanged() { //_alphaStartChanged = true; //_alphaFinishChanged = true; + _materialURLChanged = true; + _materialModeChanged = true; + _blendFactorChanged = true; + _priorityChanged = true; + _shapeIDChanged = true; + _materialBoundsChanged = true; + // Certifiable Properties _itemNameChanged = true; _itemDescriptionChanged = true; @@ -2390,6 +2429,24 @@ QList EntityItemProperties::listChangedProperties() { if (radiusFinishChanged()) { out += "radiusFinish"; } + if (materialURLChanged()) { + out += "materialURL"; + } + if (materialModeChanged()) { + out += "materialMode"; + } + if (blendFactorChanged()) { + out += "blendFactor"; + } + if (priorityChanged()) { + out += "priority"; + } + if (shapeIDChanged()) { + out += "shapeID"; + } + if (materialBoundsChanged()) { + out += "materialBounds"; + } // Certifiable Properties if (itemNameChanged()) { diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index c8c8a658ce..557a8476fa 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -242,6 +242,29 @@ inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isVal return glm::vec3(0); } +inline glmVec4 glmVec4_convertFromScriptValue(const QScriptValue& v, bool& isValid) { + isValid = false; /// assume it can't be converted + QScriptValue x = v.property("x"); + QScriptValue y = v.property("y"); + QScriptValue z = v.property("z"); + QScriptValue w = v.property("w"); + if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { + glm::vec4 newValue(0); + newValue.x = x.toVariant().toFloat(); + newValue.y = y.toVariant().toFloat(); + newValue.z = z.toVariant().toFloat(); + newValue.w = w.toVariant().toFloat(); + isValid = !glm::isnan(newValue.x) && + !glm::isnan(newValue.y) && + !glm::isnan(newValue.z) && + !glm::isnan(newValue.w); + if (isValid) { + return newValue; + } + } + return glm::vec4(0); +} + inline AACube AACube_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; AACube result; diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 19daa11490..bbcc691879 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -10,6 +10,9 @@ #include "EntityItemProperties.h" +#include "QJsonDocument" +#include "QJsonArray" + EntityItemPointer MaterialEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { Pointer entity(new MaterialEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); entity->setProperties(properties); @@ -34,7 +37,7 @@ EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desir bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class - + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialURL, setMaterialURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMode, setMaterialMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(blendFactor, setBlendFactor); @@ -55,6 +58,139 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { return somethingChanged; } +bool MaterialEntityItem::parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB) { + if (array.isArray()) { + QJsonArray colorArray = array.toArray(); + if (colorArray.size() >= 3 && colorArray[0].isDouble() && colorArray[1].isDouble() && colorArray[2].isDouble()) { + isSRGB = true; + if (colorArray.size() >= 4) { + if (colorArray[3].isBool()) { + isSRGB = colorArray[3].toBool(); + } + } + color = glm::vec3(colorArray[0].toDouble(), colorArray[1].toDouble(), colorArray[2].toDouble()); + return true; + } + } + return false; +} + +void MaterialEntityItem::parseJSONMaterial(const QJsonObject& materialJSON) { + QString name = ""; + std::shared_ptr material = std::make_shared(); + for (auto& key : materialJSON.keys()) { + if (key == "name") { + auto nameJSON = materialJSON.value(key); + if (nameJSON.isString()) { + name = nameJSON.toString(); + } + } else if (key == "emissive") { + glm::vec3 color; + bool isSRGB; + bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); + if (valid) { + material->setEmissive(color, isSRGB); + } + } else if (key == "opacity") { + auto value = materialJSON.value(key); + if (value.isDouble()) { + material->setOpacity(value.toDouble()); + } + } else if (key == "albedo") { + glm::vec3 color; + bool isSRGB; + bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); + if (valid) { + material->setAlbedo(color, isSRGB); + } + } else if (key == "roughness") { + auto value = materialJSON.value(key); + if (value.isDouble()) { + material->setRoughness(value.toDouble()); + } + } else if (key == "fresnel") { + glm::vec3 color; + bool isSRGB; + bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); + if (valid) { + material->setFresnel(color, isSRGB); + } + } else if (key == "metallic") { + auto value = materialJSON.value(key); + if (value.isDouble()) { + material->setMetallic(value.toDouble()); + } + } else if (key == "scattering") { + auto value = materialJSON.value(key); + if (value.isDouble()) { + material->setScattering(value.toDouble()); + } + } else if (key == "emissiveMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setEmissiveMap(value.toString()); + } + } else if (key == "albedoMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + bool useAlphaChannel = false; + auto opacityMap = materialJSON.find("opacityMap"); + if (opacityMap != materialJSON.end() && opacityMap->isString() && opacityMap->toString() == value.toString()) { + useAlphaChannel = true; + } + material->setAlbedoMap(value.toString(), useAlphaChannel); + } + } else if (key == "roughnessMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setRoughnessMap(value.toString(), false); + } + } else if (key == "glossMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setRoughnessMap(value.toString(), true); + } + } else if (key == "metallicMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setMetallicMap(value.toString(), false); + } + } else if (key == "specularMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setMetallicMap(value.toString(), true); + } + } else if (key == "normalMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setNormalMap(value.toString(), false); + } + } else if (key == "bumpMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setNormalMap(value.toString(), true); + } + } else if (key == "occlusionMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setOcclusionMap(value.toString()); + } + } else if (key == "scatteringMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setScatteringMap(value.toString()); + } + } else if (key == "lightMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setLightmapMap(value.toString()); + } + } + } + _materials[name] = material; + _materialNames.push_back(name); +} + int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, @@ -66,8 +202,8 @@ int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da READ_ENTITY_PROPERTY(PROP_MATERIAL_URL, QString, setMaterialURL); READ_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode); READ_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor); - READ_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, int, setPriority); - READ_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, int, setShapeID); + READ_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, uint32_t, setPriority); + READ_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, uint32_t, setShapeID); READ_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, glm::vec4, setMaterialBounds); return bytesRead; @@ -96,25 +232,82 @@ void MaterialEntityItem::appendSubclassData(OctreePacketData* packetData, Encode bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_MATERIAL_URL, getMaterialURL()); - APPEND_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, getMaterialMode()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, (uint32_t)getMaterialMode()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, getBlendFactor()); - APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, getPriority()); - APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, getShapeID()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, (uint32_t)getPriority()); + APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, (uint32_t)getShapeID()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, getMaterialBounds()); } void MaterialEntityItem::debugDump() const { quint64 now = usecTimestampNow(); - qCDebug(entities) << "MATERIAL EntityItem id:" << getEntityItemID() << "---------------------------------------------"; - qCDebug(entities) << " name:" << _name; - qCDebug(entities) << " url:" << _materialURL; - qCDebug(entities) << " material type:" << _materialMode; - qCDebug(entities) << " blend factor:" << _blendFactor; - qCDebug(entities) << " priority:" << _priority; - qCDebug(entities) << " parent shape ID:" << _shapeID; - qCDebug(entities) << " material bounds:" << _materialBounds; - qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); - qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); - qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); - qCDebug(entities) << "SHAPE EntityItem Ptr:" << this; + qCDebug(entities) << " MATERIAL EntityItem id:" << getEntityItemID() << "---------------------------------------------"; + qCDebug(entities) << " name:" << _name; + qCDebug(entities) << " material json:" << _materialURL; + qCDebug(entities) << " current material name:" << _currentMaterialName; + qCDebug(entities) << " material type:" << _materialMode; + qCDebug(entities) << " blend factor:" << _blendFactor; + qCDebug(entities) << " priority:" << _priority; + qCDebug(entities) << " parent shape ID:" << _shapeID; + qCDebug(entities) << " material bounds:" << _materialBounds; + qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); + qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); + qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); + qCDebug(entities) << "MATERIAL EntityItem Ptr:" << this; } + +void MaterialEntityItem::setUnscaledDimensions(const glm::vec3& value) { + EntityItem::setUnscaledDimensions(ENTITY_ITEM_DEFAULT_DIMENSIONS); +} + +std::shared_ptr MaterialEntityItem::getMaterial() const { + auto material = _materials.find(_currentMaterialName); + if (material != _materials.end()) { + return material.value(); + } else { + return nullptr; + } +} + +void MaterialEntityItem::setMaterialURL(const QString& materialURLString) { + if (materialURLString.startsWith("userData")) { + QJsonDocument materialJSON = QJsonDocument::fromJson(getUserData().toUtf8()); + _materials.clear(); + _materialNames.clear(); + if (!materialJSON.isNull()) { + if (materialJSON.isArray()) { + QJsonArray materials = materialJSON.array(); + for (auto& material : materials) { + if (!material.isNull() && material.isObject()) { + parseJSONMaterial(material.toObject()); + } + } + } else if (materialJSON.isObject()) { + parseJSONMaterial(materialJSON.object()); + } + } + } + _materialURL = materialURLString; + + // TODO: if URL ends with ?string, set _currentMaterialName = string + + // Since our JSON changed, the current name might not be valid anymore, so we need to update + setCurrentMaterialName(_currentMaterialName); +} + +void MaterialEntityItem::setCurrentMaterialName(const QString& currentMaterialName) { + auto material = _materials.find(currentMaterialName); + if (material != _materials.end()) { + _currentMaterialName = currentMaterialName; + } else if (_materialNames.size() > 0) { + setCurrentMaterialName(_materialNames[0]); + } +} + +void MaterialEntityItem::setUserData(const QString& userData) { + EntityItem::setUserData(userData); + if (_materialURL.startsWith("userData")) { + // Trigger material update when user data changes + setMaterialURL(_materialURL); + } +} \ No newline at end of file diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index 094c94f24c..80fe226b68 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -46,25 +46,34 @@ public: void debugDump() const override; - const QString& getMaterialURL() { return _materialURL; } - void setMaterialURL(const QString& materialURL) { _materialURL = materialURL; } + virtual void setUnscaledDimensions(const glm::vec3& value) override; - MaterialMode getMaterialType() { return _materialMode; } - void setMaterialMode(MaterialMode mode); + QString getMaterialURL() const { return _materialURL; } + void setMaterialURL(const QString& materialURLString); - float getBlendFactor() { return _blendFactor; } + QString getCurrentMaterialName() const { return _currentMaterialName; } + void setCurrentMaterialName(const QString& currentMaterialName); + + MaterialMode getMaterialMode() const { return _materialMode; } + void setMaterialMode(MaterialMode mode) { _materialMode = mode; } + + float getBlendFactor() const { return _blendFactor; } void setBlendFactor(float blendFactor) { _blendFactor = blendFactor; } - int getPriority() { return _priority; } + int getPriority() const { return _priority; } void setPriority(int priority) { _priority = priority; } - int getShapeID() { return _shapeID; } + int getShapeID() const { return _shapeID; } void setShapeID(int shapeID) { _shapeID = shapeID; } - const glm::vec4& getMaterialBounds() { return _materialBounds; } + glm::vec4 getMaterialBounds() const { return _materialBounds; } void setMaterialBounds(const glm::vec4& materialBounds) { _materialBounds = materialBounds; } -protected: + std::shared_ptr getMaterial() const; + + void setUserData(const QString& userData) override; + +private: QString _materialURL; MaterialMode _materialMode { UV }; float _blendFactor { 1.0f }; @@ -72,7 +81,12 @@ protected: int _shapeID { 0 }; glm::vec4 _materialBounds { 0, 0, 1, 1 }; - //NetworkMaterial _material; + QHash> _materials; + std::vector _materialNames; + QString _currentMaterialName; + + void parseJSONMaterial(const QJsonObject& materialJSON); + static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); }; diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index ea5bd331c9..6cc6b8472f 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -221,4 +221,4 @@ bool Material::calculateMaterialInfo() const { _hasCalculatedTextureInfo = allTextures; } return _hasCalculatedTextureInfo; -} +} \ No newline at end of file diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 07f7283bfa..1fe3648838 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -425,7 +425,7 @@ bool Geometry::areTexturesLoaded() const { return true; } -const std::shared_ptr Geometry::getShapeMaterial(int partID) const { +const std::shared_ptr Geometry::getShapeMaterial(int partID) const { if ((partID >= 0) && (partID < (int)_meshParts->size())) { int materialID = _meshParts->at(partID)->materialID; if ((materialID >= 0) && (materialID < (int)_materials.size())) { @@ -491,6 +491,15 @@ void GeometryResourceWatcher::resourceRefreshed() { // _instance.reset(); } +NetworkMaterial::NetworkMaterial(const NetworkMaterial& m) : + Material(m), + _textures(m._textures), + _albedoTransform(m._albedoTransform), + _lightmapParams(m._lightmapParams), + _lightmapTransform(m._lightmapTransform), + _isOriginal(m._isOriginal) +{} + const QString NetworkMaterial::NO_TEXTURE = QString(); const QString& NetworkMaterial::getTextureName(MapChannel channel) { @@ -532,19 +541,85 @@ graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& baseUrl } graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, image::TextureUsage::Type type, MapChannel channel) { - const auto texture = DependencyManager::get()->getTexture(url, type); - _textures[channel].texture = texture; + auto textureCache = DependencyManager::get(); + if (textureCache) { + auto texture = textureCache->getTexture(url, type); + _textures[channel].texture = texture; - auto map = std::make_shared(); - map->setTextureSource(texture->_textureSource); + auto map = std::make_shared(); + if (texture) { + map->setTextureSource(texture->_textureSource); + emit textureFinished(); + } - return map; + return map; + } + return nullptr; +} + +void NetworkMaterial::setAlbedoMap(const QString& url, bool useAlphaChannel) { + auto map = fetchTextureMap(QUrl(url), image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); + if (map) { + map->setUseAlphaChannel(useAlphaChannel); + setTextureMap(MapChannel::ALBEDO_MAP, map); + } +} + +void NetworkMaterial::setNormalMap(const QString& url, bool isBumpmap) { + auto map = fetchTextureMap(QUrl(url), isBumpmap ? image::TextureUsage::BUMP_TEXTURE : image::TextureUsage::NORMAL_TEXTURE, MapChannel::NORMAL_MAP); + if (map) { + setTextureMap(MapChannel::NORMAL_MAP, map); + } +} + +void NetworkMaterial::setRoughnessMap(const QString& url, bool isGloss) { + auto map = fetchTextureMap(QUrl(url), isGloss ? image::TextureUsage::GLOSS_TEXTURE : image::TextureUsage::ROUGHNESS_TEXTURE, MapChannel::ROUGHNESS_MAP); + if (map) { + setTextureMap(MapChannel::ROUGHNESS_MAP, map); + } +} + +void NetworkMaterial::setMetallicMap(const QString& url, bool isSpecular) { + auto map = fetchTextureMap(QUrl(url), isSpecular ? image::TextureUsage::SPECULAR_TEXTURE : image::TextureUsage::METALLIC_TEXTURE, MapChannel::METALLIC_MAP); + if (map) { + setTextureMap(MapChannel::METALLIC_MAP, map); + } +} + +void NetworkMaterial::setOcclusionMap(const QString& url) { + auto map = fetchTextureMap(QUrl(url), image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); + if (map) { + setTextureMap(MapChannel::OCCLUSION_MAP, map); + } +} + +void NetworkMaterial::setEmissiveMap(const QString& url) { + auto map = fetchTextureMap(QUrl(url), image::TextureUsage::EMISSIVE_TEXTURE, MapChannel::EMISSIVE_MAP); + if (map) { + setTextureMap(MapChannel::EMISSIVE_MAP, map); + } +} + +void NetworkMaterial::setScatteringMap(const QString& url) { + auto map = fetchTextureMap(QUrl(url), image::TextureUsage::SCATTERING_TEXTURE, MapChannel::SCATTERING_MAP); + if (map) { + setTextureMap(MapChannel::SCATTERING_MAP, map); + } +} + +void NetworkMaterial::setLightmapMap(const QString& url) { + auto map = fetchTextureMap(QUrl(url), image::TextureUsage::LIGHTMAP_TEXTURE, MapChannel::LIGHTMAP_MAP); + if (map) { + //map->setTextureTransform(_lightmapTransform); + //map->setLightmapOffsetScale(_lightmapParams.x, _lightmapParams.y); + setTextureMap(MapChannel::LIGHTMAP_MAP, map); + } } NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl) : - graphics::Material(*material._material) + graphics::Material(*material._material), + _textures(MapChannel::NUM_MAP_CHANNELS) { - _textures = Textures(MapChannel::NUM_MAP_CHANNELS); if (!material.albedoTexture.filename.isEmpty()) { auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); _albedoTransform = material.albedoTexture.transform; diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index f650b3f2eb..575f94f9bf 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -48,7 +48,7 @@ public: const FBXGeometry& getFBXGeometry() const { return *_fbxGeometry; } const GeometryMeshes& getMeshes() const { return *_meshes; } - const std::shared_ptr getShapeMaterial(int shapeID) const; + const std::shared_ptr getShapeMaterial(int shapeID) const; const QVariantMap getTextures() const; void setTextures(const QVariantMap& textureMap); @@ -131,7 +131,6 @@ private: Geometry::Pointer& _geometryRef; }; - /// Stores cached model geometries. class ModelCache : public ResourceCache, public Dependency { Q_OBJECT @@ -157,11 +156,26 @@ private: virtual ~ModelCache() = default; }; -class NetworkMaterial : public graphics::Material { +class NetworkMaterial : public QObject, public graphics::Material { + Q_OBJECT public: using MapChannel = graphics::Material::MapChannel; + NetworkMaterial() : _textures(MapChannel::NUM_MAP_CHANNELS) {} NetworkMaterial(const FBXMaterial& material, const QUrl& textureBaseUrl); + NetworkMaterial(const NetworkMaterial& material); + + void setAlbedoMap(const QString& url, bool useAlphaChannel); + void setNormalMap(const QString& url, bool isBumpmap); + void setRoughnessMap(const QString& url, bool isGloss); + void setMetallicMap(const QString& url, bool isSpecular); + void setOcclusionMap(const QString& url); + void setEmissiveMap(const QString& url); + void setScatteringMap(const QString& url); + void setLightmapMap(const QString& url); + +signals: + void textureFinished(); protected: friend class Geometry; diff --git a/libraries/model-networking/src/model-networking/TextureCache.cpp b/libraries/model-networking/src/model-networking/TextureCache.cpp index 8153dba3a5..3402758ef1 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.cpp +++ b/libraries/model-networking/src/model-networking/TextureCache.cpp @@ -275,6 +275,8 @@ QSharedPointer TextureCache::createResource(const QUrl& url, const QSh return QSharedPointer(texture, &Resource::deleter); } +int networkTexturePointerMetaTypeId = qRegisterMetaType>(); + NetworkTexture::NetworkTexture(const QUrl& url) : Resource(url), _type(), diff --git a/libraries/model-networking/src/model-networking/TextureCache.h b/libraries/model-networking/src/model-networking/TextureCache.h index 742d003d02..6a88eb641a 100644 --- a/libraries/model-networking/src/model-networking/TextureCache.h +++ b/libraries/model-networking/src/model-networking/TextureCache.h @@ -163,7 +163,6 @@ public: NetworkTexturePointer getTexture(const QUrl& url, image::TextureUsage::Type type = image::TextureUsage::DEFAULT_TEXTURE, const QByteArray& content = QByteArray(), int maxNumPixels = ABSOLUTE_MAX_TEXTURE_NUM_PIXELS); - gpu::TexturePointer getTextureByHash(const std::string& hash); gpu::TexturePointer cacheTextureByHash(const std::string& hash, const gpu::TexturePointer& texture); diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index a3ac995bcf..7ba7cca96d 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -340,14 +340,6 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& return resource; } - if (QThread::currentThread() != thread()) { - qCDebug(networking) << "Fetching asynchronously:" << url; - QMetaObject::invokeMethod(this, "getResource", - Q_ARG(QUrl, url), Q_ARG(QUrl, fallback)); - // Cannot use extra parameter as it might be freed before the invocation - return QSharedPointer(); - } - if (!url.isValid() && !url.isEmpty() && fallback.isValid()) { return getResource(fallback, QUrl()); } @@ -358,6 +350,7 @@ QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& extra); resource->setSelf(resource); resource->setCache(this); + resource->moveToThread(qApp->thread()); connect(resource.data(), &Resource::updateSize, this, &ResourceCache::updateTotalSize); { QWriteLocker locker(&_resourcesLock); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 711aeb2cc2..98ad1ab323 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::SoftEntities); + return static_cast(EntityVersion::MaterialEntities); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::RemovedJurisdictions); diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 458666571c..e13809810c 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -206,7 +206,8 @@ enum class EntityVersion : PacketVersion { OwnershipChallengeFix, ZoneLightInheritModes = 82, ZoneStageRemoved, - SoftEntities + SoftEntities, + MaterialEntities }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index ef4e98798f..7f8eb49101 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -33,6 +33,8 @@ #include #include +#include "MaterialMode.h" + #include "OctreeConstants.h" #include "OctreeElement.h" @@ -249,6 +251,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, float& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } + static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec4& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, bool& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, quint64& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, uint32_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } @@ -257,6 +260,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, rgbColor& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, glm::quat& result) { int bytes = unpackOrientationQuatFromBytes(dataBytes, result); return bytes; } static int unpackDataFromBytes(const unsigned char* dataBytes, ShapeType& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } + static int unpackDataFromBytes(const unsigned char* dataBytes, MaterialMode& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, QString& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QUuid& result); static int unpackDataFromBytes(const unsigned char* dataBytes, xColor& result); diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp index 3d213840dd..41a5bf5faf 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.cpp +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.cpp @@ -38,7 +38,7 @@ void CauterizedMeshPartPayload::updateTransformForCauterizedMesh(const Transform _cauterizedTransform = renderTransform; } -void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { +void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { bool useCauterizedMesh = (renderMode != RenderArgs::RenderMode::SHADOW_RENDER_MODE && renderMode != RenderArgs::RenderMode::SECONDARY_CAMERA_RENDER_MODE) && _enableCauterization; if (useCauterizedMesh) { if (_cauterizedClusterBuffer) { @@ -46,7 +46,7 @@ void CauterizedMeshPartPayload::bindTransform(gpu::Batch& batch, const render::S } batch.setModelTransform(_cauterizedTransform); } else { - ModelMeshPartPayload::bindTransform(batch, locations, renderMode); + ModelMeshPartPayload::bindTransform(batch, renderMode); } } diff --git a/libraries/render-utils/src/CauterizedMeshPartPayload.h b/libraries/render-utils/src/CauterizedMeshPartPayload.h index 2337632047..3c0f90fcb5 100644 --- a/libraries/render-utils/src/CauterizedMeshPartPayload.h +++ b/libraries/render-utils/src/CauterizedMeshPartPayload.h @@ -25,7 +25,7 @@ public: void updateTransformForCauterizedMesh(const Transform& renderTransform); - void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; + void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const override; void setEnableCauterization(bool enableCauterization) { _enableCauterization = enableCauterization; } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 1fd6ca2980..0d76b2c093 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1318,7 +1318,6 @@ void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, in renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color, id); } - void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner, const glm::vec4& color, int id) { diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index c506887fc4..dd5809093e 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -125,126 +125,7 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setInputStream(0, _drawMesh->getVertexStream()); } -void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, bool enableTextures) const { - if (!_drawMaterial) { - return; - } - - auto textureCache = DependencyManager::get(); - - batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, _drawMaterial->getSchemaBuffer()); - batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::TEXMAPARRAY, _drawMaterial->getTexMapArrayBuffer()); - - const auto& materialKey = _drawMaterial->getKey(); - const auto& textureMaps = _drawMaterial->getTextureMaps(); - - int numUnlit = 0; - if (materialKey.isUnlit()) { - numUnlit++; - } - - if (!enableTextures) { - batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getWhiteTexture()); - batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, textureCache->getWhiteTexture()); - batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, textureCache->getBlueTexture()); - batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, textureCache->getBlackTexture()); - batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, textureCache->getWhiteTexture()); - batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, textureCache->getWhiteTexture()); - batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture()); - return; - } - - // Albedo - if (materialKey.isAlbedoMap()) { - auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP); - if (itr != textureMaps.end() && itr->second->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, itr->second->getTextureView()); - } else { - batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getGrayTexture()); - } - } - - // Roughness map - if (materialKey.isRoughnessMap()) { - auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP); - if (itr != textureMaps.end() && itr->second->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, itr->second->getTextureView()); - - // texcoord are assumed to be the same has albedo - } else { - batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, textureCache->getWhiteTexture()); - } - } - - // Normal map - if (materialKey.isNormalMap()) { - auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP); - if (itr != textureMaps.end() && itr->second->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, itr->second->getTextureView()); - - // texcoord are assumed to be the same has albedo - } else { - batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, textureCache->getBlueTexture()); - } - } - - // Metallic map - if (materialKey.isMetallicMap()) { - auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP); - if (itr != textureMaps.end() && itr->second->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, itr->second->getTextureView()); - - // texcoord are assumed to be the same has albedo - } else { - batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, textureCache->getBlackTexture()); - } - } - - // Occlusion map - if (materialKey.isOcclusionMap()) { - auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP); - if (itr != textureMaps.end() && itr->second->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, itr->second->getTextureView()); - - // texcoord are assumed to be the same has albedo - } else { - batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, textureCache->getWhiteTexture()); - } - } - - // Scattering map - if (materialKey.isScatteringMap()) { - auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP); - if (itr != textureMaps.end() && itr->second->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, itr->second->getTextureView()); - - // texcoord are assumed to be the same has albedo - } else { - batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, textureCache->getWhiteTexture()); - } - } - - // Emissive / Lightmap - if (materialKey.isLightmapMap()) { - auto itr = textureMaps.find(graphics::MaterialKey::LIGHTMAP_MAP); - - if (itr != textureMaps.end() && itr->second->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView()); - } else { - batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getGrayTexture()); - } - } else if (materialKey.isEmissiveMap()) { - auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP); - - if (itr != textureMaps.end() && itr->second->isDefined()) { - batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView()); - } else { - batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture()); - } - } -} - -void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { +void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { batch.setModelTransform(_drawTransform); } @@ -252,23 +133,21 @@ void MeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::Loca void MeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("MeshPartPayload::render"); + if (!args) { + return; + } + gpu::Batch& batch = *(args->_batch); - auto locations = args->_shapePipeline->locations; - assert(locations); - // Bind the model transform and the skinCLusterMatrices if needed - bindTransform(batch, locations, args->_renderMode); + bindTransform(batch, args->_renderMode); //Bind the index buffer and vertex buffer and Blend shapes if needed bindMesh(batch); // apply material properties - bindMaterial(batch, locations, args->_enableTexturing); - - if (args) { - args->_details._materialSwitches++; - } + args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing); + args->_details._materialSwitches++; // Draw! { @@ -276,10 +155,8 @@ void MeshPartPayload::render(RenderArgs* args) { drawCall(batch); } - if (args) { - const int INDICES_PER_TRIANGLE = 3; - args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; - } + const int INDICES_PER_TRIANGLE = 3; + args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE; } namespace render { @@ -500,7 +377,7 @@ void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) { } } -void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const { +void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { if (_clusterBuffer) { batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::SKINNING, _clusterBuffer); } @@ -515,17 +392,14 @@ void ModelMeshPartPayload::render(RenderArgs* args) { } gpu::Batch& batch = *(args->_batch); - auto locations = args->_shapePipeline->locations; - assert(locations); - bindTransform(batch, locations, args->_renderMode); + bindTransform(batch, args->_renderMode); //Bind the index buffer and vertex buffer and Blend shapes if needed bindMesh(batch); // apply material properties - bindMaterial(batch, locations, args->_enableTexturing); - + args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing); args->_details._materialSwitches++; // Draw! diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index 8160b9f009..7ec02ae7f0 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -17,7 +17,6 @@ #include #include -#include #include @@ -49,8 +48,7 @@ public: // ModelMeshPartPayload functions to perform render void drawCall(gpu::Batch& batch) const; virtual void bindMesh(gpu::Batch& batch); - virtual void bindMaterial(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, bool enableTextures) const; - virtual void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const; + virtual void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const; // Payload resource cached values Transform _drawTransform; @@ -63,7 +61,7 @@ public: mutable graphics::Box _worldBound; std::shared_ptr _drawMesh; - std::shared_ptr _drawMaterial; + std::shared_ptr _drawMaterial; graphics::Mesh::Part _drawPart; size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; } @@ -109,7 +107,7 @@ public: // ModelMeshPartPayload functions to perform render void bindMesh(gpu::Batch& batch) override; - void bindTransform(gpu::Batch& batch, const render::ShapePipeline::LocationsPointer locations, RenderArgs::RenderMode renderMode) const override; + void bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const override; void computeAdjustedLocalBound(const std::vector& clusterTransforms); diff --git a/libraries/render/CMakeLists.txt b/libraries/render/CMakeLists.txt index 1d88c3e5f5..4f8673cde6 100644 --- a/libraries/render/CMakeLists.txt +++ b/libraries/render/CMakeLists.txt @@ -2,7 +2,9 @@ set(TARGET_NAME render) AUTOSCRIBE_SHADER_LIB(gpu graphics) setup_hifi_library() -# render needs octree only for getAccuracyAngle(float, int) -link_hifi_libraries(shared ktx gpu graphics octree) +# render needs octree only for getAccuracyAngle(float, int), and model-networking for TextureCache +link_hifi_libraries(shared ktx gpu graphics octree model-networking) +include_hifi_library_headers(networking) +include_hifi_library_headers(image) target_nsight() diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 4254280fa1..db4ff604ca 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -15,6 +15,8 @@ #include +#include + using namespace render; ShapePipeline::CustomFactoryMap ShapePipeline::_globalCustomFactoryMap; @@ -157,3 +159,122 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke return shapePipeline; } + +void ShapePipeline::bindMaterial(graphics::MaterialPointer material, gpu::Batch& batch, bool enableTextures) const { + if (!material) { + return; + } + + auto textureCache = DependencyManager::get(); + + batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::MATERIAL, material->getSchemaBuffer()); + batch.setUniformBuffer(ShapePipeline::Slot::BUFFER::TEXMAPARRAY, material->getTexMapArrayBuffer()); + + const auto& materialKey = material->getKey(); + const auto& textureMaps = material->getTextureMaps(); + + int numUnlit = 0; + if (materialKey.isUnlit()) { + numUnlit++; + } + + if (!enableTextures) { + batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getWhiteTexture()); + batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, textureCache->getWhiteTexture()); + batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, textureCache->getBlueTexture()); + batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, textureCache->getBlackTexture()); + batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, textureCache->getWhiteTexture()); + batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, textureCache->getWhiteTexture()); + batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture()); + return; + } + + // Albedo + if (materialKey.isAlbedoMap()) { + auto itr = textureMaps.find(graphics::MaterialKey::ALBEDO_MAP); + if (itr != textureMaps.end() && itr->second->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, itr->second->getTextureView()); + } else { + batch.setResourceTexture(ShapePipeline::Slot::ALBEDO, textureCache->getGrayTexture()); + } + } + + // Roughness map + if (materialKey.isRoughnessMap()) { + auto itr = textureMaps.find(graphics::MaterialKey::ROUGHNESS_MAP); + if (itr != textureMaps.end() && itr->second->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, itr->second->getTextureView()); + + // texcoord are assumed to be the same has albedo + } else { + batch.setResourceTexture(ShapePipeline::Slot::MAP::ROUGHNESS, textureCache->getWhiteTexture()); + } + } + + // Normal map + if (materialKey.isNormalMap()) { + auto itr = textureMaps.find(graphics::MaterialKey::NORMAL_MAP); + if (itr != textureMaps.end() && itr->second->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, itr->second->getTextureView()); + + // texcoord are assumed to be the same has albedo + } else { + batch.setResourceTexture(ShapePipeline::Slot::MAP::NORMAL, textureCache->getBlueTexture()); + } + } + + // Metallic map + if (materialKey.isMetallicMap()) { + auto itr = textureMaps.find(graphics::MaterialKey::METALLIC_MAP); + if (itr != textureMaps.end() && itr->second->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, itr->second->getTextureView()); + + // texcoord are assumed to be the same has albedo + } else { + batch.setResourceTexture(ShapePipeline::Slot::MAP::METALLIC, textureCache->getBlackTexture()); + } + } + + // Occlusion map + if (materialKey.isOcclusionMap()) { + auto itr = textureMaps.find(graphics::MaterialKey::OCCLUSION_MAP); + if (itr != textureMaps.end() && itr->second->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, itr->second->getTextureView()); + + // texcoord are assumed to be the same has albedo + } else { + batch.setResourceTexture(ShapePipeline::Slot::MAP::OCCLUSION, textureCache->getWhiteTexture()); + } + } + + // Scattering map + if (materialKey.isScatteringMap()) { + auto itr = textureMaps.find(graphics::MaterialKey::SCATTERING_MAP); + if (itr != textureMaps.end() && itr->second->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, itr->second->getTextureView()); + + // texcoord are assumed to be the same has albedo + } else { + batch.setResourceTexture(ShapePipeline::Slot::MAP::SCATTERING, textureCache->getWhiteTexture()); + } + } + + // Emissive / Lightmap + if (materialKey.isLightmapMap()) { + auto itr = textureMaps.find(graphics::MaterialKey::LIGHTMAP_MAP); + + if (itr != textureMaps.end() && itr->second->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView()); + } else { + batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getGrayTexture()); + } + } else if (materialKey.isEmissiveMap()) { + auto itr = textureMaps.find(graphics::MaterialKey::EMISSIVE_MAP); + + if (itr != textureMaps.end() && itr->second->isDefined()) { + batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, itr->second->getTextureView()); + } else { + batch.setResourceTexture(ShapePipeline::Slot::MAP::EMISSIVE_LIGHTMAP, textureCache->getBlackTexture()); + } + } +} diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index be77e2f95e..3e358e9ac2 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -18,6 +18,8 @@ #include "Args.h" +#include + namespace render { class Item; class ShapePlumber; @@ -294,6 +296,8 @@ public: void prepareShapeItem(Args* args, const ShapeKey& key, const Item& shape); + void bindMaterial(graphics::MaterialPointer material, gpu::Batch& batch, bool enableTextures) const; + protected: friend class ShapePlumber; diff --git a/libraries/shared/src/MaterialMode.cpp b/libraries/shared/src/MaterialMode.cpp new file mode 100644 index 0000000000..cb656a7bf7 --- /dev/null +++ b/libraries/shared/src/MaterialMode.cpp @@ -0,0 +1,24 @@ +// +// Created by Sam Gondelman on 1/17/2018 +// 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 "MaterialMode.h" + +const char* materialModeNames[] = { + "uv", + "projected" +}; + +static const size_t MATERIAL_MODE_NAMES = (sizeof(materialModeNames) / sizeof((materialModeNames)[0])); + +QString MaterialModeHelpers::getNameForMaterialMode(MaterialMode mode) { + if (((int)mode <= 0) || ((int)mode >= (int)MATERIAL_MODE_NAMES)) { + mode = (MaterialMode)0; + } + + return materialModeNames[(int)mode]; +} \ No newline at end of file diff --git a/libraries/shared/src/MaterialMode.h b/libraries/shared/src/MaterialMode.h index 05c6d295a5..a933693f75 100644 --- a/libraries/shared/src/MaterialMode.h +++ b/libraries/shared/src/MaterialMode.h @@ -9,10 +9,17 @@ #ifndef hifi_MaterialMode_h #define hifi_MaterialMode_h +#include "QString" + enum MaterialMode { UV = 0, PROJECTED }; +class MaterialModeHelpers { +public: + static QString getNameForMaterialMode(MaterialMode mode); +}; + #endif // hifi_MaterialMode_h diff --git a/scripts/developer/tests/toolbarTest.js b/scripts/developer/tests/toolbarTest.js index e21fbd8e19..dfc97ebe39 100644 --- a/scripts/developer/tests/toolbarTest.js +++ b/scripts/developer/tests/toolbarTest.js @@ -11,7 +11,8 @@ var toolBar = (function() { newTextButton, newWebButton, newZoneButton, - newParticleButton + newParticleButton, + newMaterialButton var toolIconUrl = Script.resolvePath("../../system/assets/images/tools/"); @@ -89,6 +90,13 @@ var toolBar = (function() { visible: false }); + newMaterialButton = toolBar.addButton({ + objectName: "newMaterialButton", + imageURL: toolIconUrl + "model-01.svg", + alpha: 0.9, + visible: false + }); + that.setActive(false); newModelButton.clicked(); } @@ -109,8 +117,8 @@ var toolBar = (function() { newTextButton.writeProperty('visible', doShow); newWebButton.writeProperty('visible', doShow); newZoneButton.writeProperty('visible', doShow); - newModelButton.writeProperty('visible', doShow); newParticleButton.writeProperty('visible', doShow); + newMaterialButton.writeProperty('visible', doShow); }; initialize(); diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 87cd3e0faf..928d8ba1fa 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -251,7 +251,7 @@ var toolBar = (function () { // Align entity with Avatar orientation. properties.rotation = MyAvatar.orientation; - var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Web"]; + var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Web", "Material"]; if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { // Adjust position of entity per bounding box prior to creating it. @@ -354,6 +354,9 @@ var toolBar = (function () { var SHAPE_TYPE_SPHERE = 5; var DYNAMIC_DEFAULT = false; + var MATERIAL_MODE_UV = 0; + var MATERIAL_MODE_PROJECTED = 1; + function handleNewModelDialogResult(result) { if (result) { var url = result.textInput; @@ -394,6 +397,28 @@ var toolBar = (function () { } } + function handleNewMaterialDialogResult(result) { + if (result) { + var json = result.textInput; + var materialMode; + switch (result.comboBox) { + case MATERIAL_MODE_PROJECTED: + materialMode = "projected"; + break; + default: + shapeType = "uv"; + } + + if (json) { + createNewEntity({ + type: "Material", + materialURL: json, + materialMode: materialMode + }); + } + } + } + function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.popFromStack(); @@ -404,6 +429,9 @@ var toolBar = (function () { case "newEntityButtonClicked": buttonHandlers[message.params.buttonName](); break; + case "newMaterialDialogAdd": + handleNewMaterialDialogResult(message.params); + break; } } @@ -614,6 +642,17 @@ var toolBar = (function () { }); }); + addButton("newMaterialButton", "model-01.svg", function () { + var MATERIAL_MODES = []; + MATERIAL_MODES[MATERIAL_MODE_UV] = "UV space material"; + MATERIAL_MODES[MATERIAL_MODE_PROJECTED] = "3D projected material"; + var MATERIAL_MODE_DEFAULT = MATERIAL_MODE_UV; + + // tablet version of new material dialog + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet.pushOntoStack("NewMaterialDialog.qml"); + }); + that.setActive(false); } @@ -1983,7 +2022,7 @@ var PropertiesTool = function (opts) { ); } Entities.editEntity(selectionManager.selections[0], data.properties); - if (data.properties.name !== undefined || data.properties.modelURL !== undefined || + if (data.properties.name !== undefined || data.properties.modelURL !== undefined || data.properties.materialURL !== undefined || data.properties.visible !== undefined || data.properties.locked !== undefined) { entityListTool.sendUpdate(); } @@ -1994,7 +2033,7 @@ var PropertiesTool = function (opts) { parentSelectedEntities(); } else if (data.type === 'unparent') { unparentSelectedEntities(); - } else if (data.type === 'saveUserData'){ + } else if (data.type === 'saveUserData') { //the event bridge and json parsing handle our avatar id string differently. var actualID = data.id.split('"')[1]; Entities.editEntity(actualID, data.properties); diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 736d42d593..96084f355f 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, .hyperlink-section, .text-section, .zone-section, .material-section { display: table; } @@ -570,6 +570,7 @@ hr { .physical-group[collapsed="true"] ~ .physical-group, .behavior-group[collapsed="true"] ~ .behavior-group, .model-group[collapsed="true"] ~ .model-group, +.material-group[collapsed="true"] ~ .material-group, .light-group[collapsed="true"] ~ .light-group { display: none !important; } @@ -1386,7 +1387,7 @@ input#reset-to-natural-dimensions { } -#static-userdata{ +#static-userdata { display: none; z-index: 99; position: absolute; @@ -1397,7 +1398,7 @@ input#reset-to-natural-dimensions { background-color: #2e2e2e; } -#userdata-saved{ +#userdata-saved { margin-top:5px; font-size:16px; display:none; @@ -1454,6 +1455,9 @@ input#reset-to-natural-dimensions { order: 6; } +#properties-list.ShapeMenu #material, +#properties-list.BoxMenu #material, +#properties-list.SphereMenu #material, #properties-list.ShapeMenu #light, #properties-list.BoxMenu #light, #properties-list.SphereMenu #light, @@ -1490,6 +1494,7 @@ input#reset-to-natural-dimensions { } /* items to hide */ +#properties-list.ParticleEffectMenu #material, #properties-list.ParticleEffectMenu #base-color-section, #properties-list.ParticleEffectMenu #hyperlink, #properties-list.ParticleEffectMenu #light, @@ -1524,6 +1529,7 @@ input#reset-to-natural-dimensions { order: 7; } /* sections to hide */ +#properties-list.LightMenu #material, #properties-list.LightMenu #model, #properties-list.LightMenu #zone, #properties-list.LightMenu #text, @@ -1560,6 +1566,7 @@ input#reset-to-natural-dimensions { order: 7; } /* sections to hide */ +#properties-list.ModelMenu #material, #properties-list.ModelMenu #light, #properties-list.ModelMenu #zone, #properties-list.ModelMenu #text, @@ -1596,6 +1603,7 @@ input#reset-to-natural-dimensions { order: 7; } /* sections to hide */ +#properties-list.ZoneMenu #material, #properties-list.ZoneMenu #light, #properties-list.ZoneMenu #model, #properties-list.ZoneMenu #text, @@ -1632,6 +1640,7 @@ input#reset-to-natural-dimensions { order: 7; } /* sections to hide */ +#properties-list.WebMenu #material, #properties-list.WebMenu #light, #properties-list.WebMenu #model, #properties-list.WebMenu #zone, @@ -1669,6 +1678,7 @@ input#reset-to-natural-dimensions { order: 7; } /* sections to hide */ +#properties-list.TextMenu #material, #properties-list.TextMenu #light, #properties-list.TextMenu #model, #properties-list.TextMenu #zone, @@ -1681,6 +1691,39 @@ input#reset-to-natural-dimensions { display: none } +/* ----- Order of Menu items for Material ----- */ +#properties-list.MaterialMenu #general { + order: 1; +} +#properties-list.MaterialMenu #material { + order: 2; +} +#properties-list.MaterialMenu #spatial { + order: 3; +} +#properties-list.MaterialMenu #hyperlink { + order: 4; +} +#properties-list.MaterialMenu #behavior { + order: 5; +} + +/* sections to hide */ +#properties-list.MaterialMenu #physical, +#properties-list.MaterialMenu #collision-info, +#properties-list.MaterialMenu #model, +#properties-list.MaterialMenu #light, +#properties-list.MaterialMenu #zone, +#properties-list.MaterialMenu #text, +#properties-list.MaterialMenu #web { + display: none; +} +/* items to hide */ +#properties-list.MaterialMenu #shape-list, +#properties-list.MaterialMenu #base-color-section { + display: none +} + /* Currently always hidden */ #properties-list #polyvox { diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index b93974ee77..93d22180c9 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -761,6 +761,51 @@ +
+ + MaterialM + +
+
+ + +
+
+
+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+
+
+
+
+ +
+
+ diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 72092b66ca..af9d106149 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -24,7 +24,8 @@ var ICON_FOR_TYPE = { Zone: "o", PolyVox: "", Multiple: "", - PolyLine: "" + PolyLine: "", + Material: "" }; var EDITOR_TIMEOUT_DURATION = 1500; @@ -77,7 +78,6 @@ function disableProperties() { if ($('#userdata-editor').css('display') === "block" && elLocked.checked === true) { showStaticUserData(); } - } function showElements(els, show) { @@ -192,6 +192,19 @@ function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, el }; } +function createEmitVec4PropertyUpdateFunction(property, elX, elY, elZ, elW) { + return function () { + var properties = {}; + properties[property] = { + x: elX.value, + y: elY.value, + z: elZ.value, + w: elW.value + }; + updateProperties(properties); + }; +} + function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) { return function() { var properties = {}; @@ -473,7 +486,6 @@ function bindAllNonJSONEditorElements() { } else { if ($('#userdata-editor').css('height') !== "0px") { saveJSONUserData(true); - } } }); @@ -621,6 +633,16 @@ function loaded() { var elModelTextures = document.getElementById("property-model-textures"); var elModelOriginalTextures = document.getElementById("property-model-original-textures"); + var elMaterialURL = document.getElementById("property-material-url"); + var elMaterialMode = document.getElementById("property-material-mode"); + var elBlendFactor = document.getElementById("property-blend-factor"); + var elPriority = document.getElementById("property-priority"); + var elShapeID = document.getElementById("property-shape-id"); + var elMaterialBoundsX = document.getElementById("property-material-bounds-x"); + var elMaterialBoundsY = document.getElementById("property-material-bounds-y"); + var elMaterialBoundsZ = document.getElementById("property-material-bounds-z"); + var elMaterialBoundsW = document.getElementById("property-material-bounds-w"); + var elWebSourceURL = document.getElementById("property-web-source-url"); var elWebDPI = document.getElementById("property-web-dpi"); @@ -1105,6 +1127,17 @@ function loaded() { elXTextureURL.value = properties.xTextureURL; elYTextureURL.value = properties.yTextureURL; elZTextureURL.value = properties.zTextureURL; + } else if (properties.type === "Material") { + elMaterialURL.value = properties.materialURL; + elMaterialMode.value = properties.materialMode; + setDropdownText(elMaterialMode); + elBlendFactor.value = properties.blendFactor.toFixed(2); + elPriority.value = properties.priority; + elShapeID.value = properties.shapeID; + elMaterialBoundsX.value = properties.materialBounds.x.toFixed(2); + elMaterialBoundsY.value = properties.materialBounds.y.toFixed(2); + elMaterialBoundsZ.value = properties.materialBounds.z.toFixed(2); + //elMaterialBoundsW.value = properties.materialBounds.w.toFixed(2); } if (properties.locked) { @@ -1375,6 +1408,19 @@ function loaded() { elModelTextures.addEventListener('change', createEmitTextPropertyUpdateFunction('textures')); + elMaterialURL.addEventListener('change', createEmitTextPropertyUpdateFunction('materialURL')); + elMaterialMode.addEventListener('change', createEmitTextPropertyUpdateFunction('materialMode')); + elBlendFactor.addEventListener('change', createEmitNumberPropertyUpdateFunction('blendFactor', 2)); + elPriority.addEventListener('change', createEmitNumberPropertyUpdateFunction('priority')); + elShapeID.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeID')); + + var materialBoundsChangeFunction = createEmitVec4PropertyUpdateFunction('materialBounds', + elMaterialBoundsX, elMaterialBoundsY, elMaterialBoundsZ, elMaterialBoundsW); + elMaterialBoundsX.addEventListener('change', materialBoundsChangeFunction); + elMaterialBoundsY.addEventListener('change', materialBoundsChangeFunction); + elMaterialBoundsZ.addEventListener('change', materialBoundsChangeFunction); + elMaterialBoundsW.addEventListener('change', materialBoundsChangeFunction); + elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextFaceCamera.addEventListener('change', createEmitCheckedPropertyUpdateFunction('faceCamera')); elTextLineHeight.addEventListener('change', createEmitNumberPropertyUpdateFunction('lineHeight')); diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js index 9d9689000e..d53766ab4e 100644 --- a/scripts/system/libraries/entityList.js +++ b/scripts/system/libraries/entityList.js @@ -77,18 +77,24 @@ EntityListTool = function(opts) { var properties = Entities.getEntityProperties(id); if (!filterInView || Vec3.distance(properties.position, cameraPosition) <= searchRadius) { + var url = ""; + if (properties.type == "Model") { + url = properties.modelURL; + } else if (properties.type == "Material") { + url = properties.materialURL; + } entities.push({ id: id, name: properties.name, type: properties.type, - url: properties.type == "Model" ? properties.modelURL : "", + url: url, locked: properties.locked, visible: properties.visible, verticesCount: valueIfDefined(properties.renderInfo.verticesCount), texturesCount: valueIfDefined(properties.renderInfo.texturesCount), texturesSize: valueIfDefined(properties.renderInfo.texturesSize), hasTransparent: valueIfDefined(properties.renderInfo.hasTransparent), - isBaked: properties.type == "Model" ? properties.modelURL.toLowerCase().endsWith(".baked.fbx") : false, + isBaked: properties.type == "Model" ? url.toLowerCase().endsWith(".baked.fbx") : false, drawCalls: valueIfDefined(properties.renderInfo.drawCalls), hasScript: properties.script !== "" }); From 22b33c7391a76afdb4dcef188404c0b7c56ee6a0 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 5 Feb 2018 11:22:40 +1300 Subject: [PATCH 06/53] Update Overlays circle3d JSDoc per recent code changes --- interface/src/ui/overlays/Circle3DOverlay.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 5e38f28a06..33f40f7c63 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -425,10 +425,10 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) { * Write-only. * @property {Color} outerColor - Sets the values of outerStartColor and outerEndColor. * Write-only. - * @property {Color} innerStartcolor - The color at the inner start point of the overlay. Write-only. - * @property {Color} innerEndColor - The color at the inner end point of the overlay. Write-only. - * @property {Color} outerStartColor - The color at the outer start point of the overlay. Write-only. - * @property {Color} outerEndColor - The color at the outer end point of the overlay. Write-only. + * @property {Color} innerStartcolor - The color at the inner start point of the overlay. + * @property {Color} innerEndColor - The color at the inner end point of the overlay. + * @property {Color} outerStartColor - The color at the outer start point of the overlay. + * @property {Color} outerEndColor - The color at the outer end point of the overlay. * @property {number} alpha=0.5 - The opacity of the overlay, 0.0 - 1.0. Setting this value also sets * the values of innerStartAlpha, innerEndAlpha, outerStartAlpha, and * outerEndAlpha. Synonym: Alpha; write-only. @@ -440,10 +440,10 @@ void Circle3DOverlay::setProperties(const QVariantMap& properties) { * Write-only. * @property {number} outerAlpha - Sets the values of outerStartAlpha and outerEndAlpha. * Write-only. - * @property {number} innerStartAlpha=0 - The alpha at the inner start point of the overlay. Write-only. - * @property {number} innerEndAlpha=0 - The alpha at the inner end point of the overlay. Write-only. - * @property {number} outerStartAlpha=0 - The alpha at the outer start point of the overlay. Write-only. - * @property {number} outerEndAlpha=0 - The alpha at the outer end point of the overlay. Write-only. + * @property {number} innerStartAlpha=0 - The alpha at the inner start point of the overlay. + * @property {number} innerEndAlpha=0 - The alpha at the inner end point of the overlay. + * @property {number} outerStartAlpha=0 - The alpha at the outer start point of the overlay. + * @property {number} outerEndAlpha=0 - The alpha at the outer end point of the overlay. * @property {boolean} hasTickMarks=false - If true, tick marks are drawn. * @property {number} majorTickMarksAngle=0 - The angle between major tick marks, in degrees. From b6ac3484284f7d05e9322658bd281d91bdd95d1e Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 7 Feb 2018 16:30:07 -0800 Subject: [PATCH 07/53] get children of animated entity joints to follow along, again --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 9 +++++++++ libraries/shared/src/SpatiallyNestable.h | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 137203f475..c8d22bb06c 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -985,6 +985,7 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() { return; } + bool changed { false }; // relay any inbound joint changes from scripts/animation/network to the model/rig _jointDataLock.withWriteLock([&] { for (int index = 0; index < _localJointData.size(); ++index) { @@ -992,13 +993,21 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() { if (jointData.rotationDirty) { model->setJointRotation(index, true, jointData.joint.rotation, 1.0f); jointData.rotationDirty = false; + changed = true; } if (jointData.translationDirty) { model->setJointTranslation(index, true, jointData.joint.translation, 1.0f); jointData.translationDirty = false; + changed = true; } } }); + + if (changed) { + forEachChild([&](SpatiallyNestablePointer object) { + object->locationChanged(tellPhysics); + }); + } } using namespace render; diff --git a/libraries/shared/src/SpatiallyNestable.h b/libraries/shared/src/SpatiallyNestable.h index 090ca4c266..5d4793ba4e 100644 --- a/libraries/shared/src/SpatiallyNestable.h +++ b/libraries/shared/src/SpatiallyNestable.h @@ -207,6 +207,10 @@ public: void dump(const QString& prefix = "") const; + virtual void locationChanged(bool tellPhysics = true); // called when a this object's location has changed + virtual void dimensionsChanged() { _queryAACubeSet = false; } // called when a this object's dimensions have changed + virtual void parentDeleted() { } // called on children of a deleted parent + protected: const NestableType _nestableType; // EntityItem or an AvatarData QUuid _id; @@ -218,10 +222,6 @@ protected: mutable ReadWriteLockable _childrenLock; mutable QHash _children; - virtual void locationChanged(bool tellPhysics = true); // called when a this object's location has changed - virtual void dimensionsChanged() { _queryAACubeSet = false; } // called when a this object's dimensions have changed - virtual void parentDeleted() { } // called on children of a deleted parent - // _queryAACube is used to decide where something lives in the octree mutable AACube _queryAACube; mutable bool _queryAACubeSet { false }; From 31c2b8fea92c3b01ca9d8b379ee705205a1aebc5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 7 Feb 2018 16:31:38 -0800 Subject: [PATCH 08/53] oops --- libraries/entities-renderer/src/RenderableModelEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c8d22bb06c..ca15382c71 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1005,7 +1005,7 @@ void RenderableModelEntityItem::copyAnimationJointDataToModel() { if (changed) { forEachChild([&](SpatiallyNestablePointer object) { - object->locationChanged(tellPhysics); + object->locationChanged(false); }); } } From 84cd0e15299d7bfd2d9132b6c6c1c17373ca7faa Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 5 Feb 2018 18:08:36 -0800 Subject: [PATCH 09/53] wip live material swapping on model entities, model overlays, avatars, and albedo swap on shape entities --- domain-server/CMakeLists.txt | 2 + .../icons/create-icons/126-material-01.svg | 9 + .../resources/qml/hifi/tablet/EditTabView.qml | 2 +- interface/src/Application.cpp | 36 +++ interface/src/ui/overlays/ModelOverlay.cpp | 26 ++ interface/src/ui/overlays/ModelOverlay.h | 5 + interface/src/ui/overlays/Overlay.cpp | 10 + interface/src/ui/overlays/Overlay.h | 6 + .../src/avatars-renderer/Avatar.cpp | 30 +++ .../src/avatars-renderer/Avatar.h | 8 + libraries/avatars/CMakeLists.txt | 3 +- libraries/avatars/src/AvatarData.cpp | 2 +- libraries/avatars/src/AvatarData.h | 5 + .../src/RenderableEntityItem.cpp | 13 + .../src/RenderableEntityItem.h | 6 + .../src/RenderableMaterialEntityItem.cpp | 26 +- .../src/RenderableMaterialEntityItem.h | 5 +- .../src/RenderableModelEntityItem.cpp | 26 ++ .../src/RenderableModelEntityItem.h | 7 + .../src/RenderableShapeEntityItem.cpp | 29 +- .../src/RenderableShapeEntityItem.h | 2 +- .../entities/src/DeleteEntityOperator.cpp | 2 +- libraries/entities/src/EntityItem.cpp | 39 ++- libraries/entities/src/EntityItem.h | 22 +- .../entities/src/EntityItemProperties.cpp | 52 ++-- libraries/entities/src/EntityItemProperties.h | 8 +- .../entities/src/EntityItemPropertiesMacros.h | 43 ++- libraries/entities/src/EntityPropertyFlags.h | 4 +- libraries/entities/src/EntityTree.cpp | 48 +++- libraries/entities/src/EntityTree.h | 15 ++ libraries/entities/src/EntityTreeElement.cpp | 26 +- libraries/entities/src/EntityTreeElement.h | 3 +- libraries/entities/src/MaterialEntityItem.cpp | 253 +++++++++++++++--- libraries/entities/src/MaterialEntityItem.h | 43 ++- libraries/entities/src/ModelEntityItem.cpp | 2 +- libraries/entities/src/ShapeEntityItem.cpp | 7 + libraries/entities/src/ShapeEntityItem.h | 6 +- libraries/graphics/src/graphics/Material.cpp | 15 ++ libraries/graphics/src/graphics/Material.h | 36 +++ .../src/model-networking/ModelCache.cpp | 2 +- .../src/model-networking/ModelCache.h | 6 +- libraries/octree/src/OctreePacketData.cpp | 11 + libraries/octree/src/OctreePacketData.h | 5 +- .../render-utils/src/MeshPartPayload.cpp | 32 ++- libraries/render-utils/src/MeshPartPayload.h | 13 +- libraries/render-utils/src/Model.cpp | 44 +++ libraries/render-utils/src/Model.h | 3 + scripts/system/edit.js | 51 ++-- scripts/system/html/css/edit-style.css | 12 +- scripts/system/html/entityProperties.html | 29 +- scripts/system/html/js/entityProperties.js | 61 ++--- tools/jsdoc/package-lock.json | 138 ++++++++++ 52 files changed, 1038 insertions(+), 251 deletions(-) create mode 100644 interface/resources/icons/create-icons/126-material-01.svg create mode 100644 tools/jsdoc/package-lock.json diff --git a/domain-server/CMakeLists.txt b/domain-server/CMakeLists.txt index c1e275e4d3..f67be55b92 100644 --- a/domain-server/CMakeLists.txt +++ b/domain-server/CMakeLists.txt @@ -22,6 +22,8 @@ setup_memory_debugger() symlink_or_copy_directory_beside_target(${_SHOULD_SYMLINK_RESOURCES} "${CMAKE_CURRENT_SOURCE_DIR}/resources" "resources") # link the shared hifi libraries +include_hifi_library_headers(gpu) +include_hifi_library_headers(graphics) link_hifi_libraries(embedded-webserver networking shared avatars) # find OpenSSL diff --git a/interface/resources/icons/create-icons/126-material-01.svg b/interface/resources/icons/create-icons/126-material-01.svg new file mode 100644 index 0000000000..9b6d92505f --- /dev/null +++ b/interface/resources/icons/create-icons/126-material-01.svg @@ -0,0 +1,9 @@ + + + + + + + diff --git a/interface/resources/qml/hifi/tablet/EditTabView.qml b/interface/resources/qml/hifi/tablet/EditTabView.qml index 65dd871fb2..6f97664e06 100644 --- a/interface/resources/qml/hifi/tablet/EditTabView.qml +++ b/interface/resources/qml/hifi/tablet/EditTabView.qml @@ -135,7 +135,7 @@ TabView { } NewEntityButton { - icon: "icons/create-icons/94-model-01.svg" + icon: "icons/create-icons/126-material-01.svg" text: "MATERIAL" onClicked: { editRoot.sendToScript({ diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 1a54c94d53..1cf8f0587f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1580,6 +1580,42 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } }); + EntityTree::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) { + auto avatarManager = DependencyManager::get(); + auto avatar = avatarManager->getAvatarBySessionID(avatarID); + if (avatar) { + avatar->addMaterial(material, shapeID); + return true; + } + return false; + }); + EntityTree::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) { + auto avatarManager = DependencyManager::get(); + auto avatar = avatarManager->getAvatarBySessionID(avatarID); + if (avatar) { + avatar->removeMaterial(material, shapeID); + return true; + } + return false; + }); + + EntityTree::setAddMaterialToOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) { + auto overlay = _overlays.getOverlay(overlayID); + if (overlay) { + overlay->addMaterial(material, shapeID); + return true; + } + return false; + }); + EntityTree::setRemoveMaterialFromOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) { + auto overlay = _overlays.getOverlay(overlayID); + if (overlay) { + overlay->removeMaterial(material, shapeID); + return true; + } + return false; + }); + // Keyboard focus handling for Web overlays. auto overlays = &(qApp->getOverlays()); connect(overlays, &Overlays::overlayDeleted, [=](const OverlayID& overlayID) { diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 4847650163..9e4835a76e 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -632,3 +632,29 @@ uint32_t ModelOverlay::fetchMetaSubItems(render::ItemIDs& subItems) const { } return 0; } + +void ModelOverlay::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { + Parent::addMaterial(material, shapeID); + if (_model && _model->fetchRenderItemIDs().size() > 0) { + _model->addMaterial(material, shapeID); + } +} + +void ModelOverlay::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { + Parent::removeMaterial(material, shapeID); + if (_model && _model->fetchRenderItemIDs().size() > 0) { + _model->removeMaterial(material, shapeID); + } +} + +void ModelOverlay::processMaterials() { + assert(_model); + std::lock_guard lock(_materialsLock); + for (auto& shapeMaterialPair : _materials) { + auto material = shapeMaterialPair.second; + while (!material.empty()) { + _model->addMaterial(material.top(), shapeMaterialPair.first); + material.pop(); + } + } +} \ No newline at end of file diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 08c776c426..827f7f2d5b 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -59,6 +59,9 @@ public: void setDrawInFront(bool drawInFront) override; void setDrawHUDLayer(bool drawHUDLayer) override; + void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + protected: Transform evalRenderTransform() override; @@ -110,6 +113,8 @@ private: bool _drawInFrontDirty { false }; bool _drawInHUDDirty { false }; + void processMaterials(); + }; #endif // hifi_ModelOverlay_h diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 3c952b8338..368ed04062 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -235,3 +235,13 @@ QVector qVectorOverlayIDFromScriptValue(const QScriptValue& array) { } return newVector; } + +void Overlay::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { + std::lock_guard lock(_materialsLock); + _materials[shapeID].push(material); +} + +void Overlay::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { + std::lock_guard lock(_materialsLock); + _materials[shapeID].remove(material); +} \ No newline at end of file diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index e9271f3c3f..4cb3f7c84d 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -91,6 +91,9 @@ public: unsigned int getStackOrder() const { return _stackOrder; } void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; } + virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID); + virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID); + protected: float updatePulse(); @@ -117,6 +120,9 @@ protected: static const xColor DEFAULT_OVERLAY_COLOR; static const float DEFAULT_ALPHA; + std::unordered_map _materials; + std::mutex _materialsLock; + private: OverlayID _overlayID; // only used for non-3d overlays }; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 86635cd3bf..4cd9bbedd7 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -570,6 +570,7 @@ void Avatar::addToScene(AvatarSharedPointer self, const render::ScenePointer& sc } transaction.resetItem(_renderItemID, avatarPayloadPointer); _skeletonModel->addToScene(scene, transaction); + processMaterials(); for (auto& attachmentModel : _attachmentModels) { attachmentModel->addToScene(scene, transaction); } @@ -761,6 +762,7 @@ void Avatar::fixupModelsInScene(const render::ScenePointer& scene) { if (_skeletonModel->isRenderable() && _skeletonModel->needsFixupInScene()) { _skeletonModel->removeFromScene(scene, transaction); _skeletonModel->addToScene(scene, transaction); + processMaterials(); canTryFade = true; _isAnimatingScale = true; } @@ -1760,3 +1762,31 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const { return DEFAULT_AVATAR_EYE_HEIGHT; } } + +void Avatar::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { + std::lock_guard lock(_materialsLock); + _materials[shapeID].push(material); + if (_skeletonModel && _skeletonModel->fetchRenderItemIDs().size() > 0) { + _skeletonModel->addMaterial(material, shapeID); + } +} + +void Avatar::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { + std::lock_guard lock(_materialsLock); + _materials[shapeID].remove(material); + if (_skeletonModel && _skeletonModel->fetchRenderItemIDs().size() > 0) { + _skeletonModel->removeMaterial(material, shapeID); + } +} + +void Avatar::processMaterials() { + assert(_skeletonModel); + std::lock_guard lock(_materialsLock); + for (auto& shapeMaterialPair : _materials) { + auto material = shapeMaterialPair.second; + while (!material.empty()) { + _skeletonModel->addMaterial(material.top(), shapeMaterialPair.first); + material.pop(); + } + } +} \ No newline at end of file diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index c2b404a925..9c355159d8 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -272,6 +272,9 @@ public: virtual void setAvatarEntityDataChanged(bool value) override; + void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + public slots: // FIXME - these should be migrated to use Pose data instead @@ -397,6 +400,11 @@ protected: float _displayNameAlpha { 1.0f }; ThreadSafeValueCache _unscaledEyeHeightCache { DEFAULT_AVATAR_EYE_HEIGHT }; + + std::unordered_map _materials; + std::mutex _materialsLock; + + void processMaterials(); }; #endif // hifi_Avatar_h diff --git a/libraries/avatars/CMakeLists.txt b/libraries/avatars/CMakeLists.txt index fc6d15cced..13fda28f40 100644 --- a/libraries/avatars/CMakeLists.txt +++ b/libraries/avatars/CMakeLists.txt @@ -1,3 +1,4 @@ set(TARGET_NAME avatars) setup_hifi_library(Network Script) -link_hifi_libraries(shared networking) +include_hifi_library_headers(gpu) +link_hifi_libraries(shared networking graphics) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 74888283df..1bbc8cc1a5 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2558,4 +2558,4 @@ void AvatarEntityMapFromScriptValue(const QScriptValue& object, AvatarEntityMap& value[EntityID] = binaryEntityProperties; } -} +} \ No newline at end of file diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index a363fb6d15..b7d594f1dc 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -54,6 +54,8 @@ #include "HeadData.h" #include "PathUtils.h" +#include + using AvatarSharedPointer = std::shared_ptr; using AvatarWeakPointer = std::weak_ptr; using AvatarHash = QHash; @@ -694,6 +696,9 @@ public: bool getIsReplicated() const { return _isReplicated; } + virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID) {} + virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {} + signals: void displayNameChanged(); void sessionDisplayNameChanged(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 49ddf111c3..2f92790d18 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -146,6 +146,9 @@ EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _entity(entity _needsRenderUpdate = true; emit requestRenderUpdate(); }); + _materials = entity->getMaterials(); + connect(entity.get(), &EntityItem::addMaterialToRenderItem, this, &EntityRenderer::addMaterial); + connect(entity.get(), &EntityItem::removeMaterialFromRenderItem, this, &EntityRenderer::removeMaterial); } EntityRenderer::~EntityRenderer() { } @@ -399,4 +402,14 @@ void EntityRenderer::onAddToScene(const EntityItemPointer& entity) { void EntityRenderer::onRemoveFromScene(const EntityItemPointer& entity) { entity->deregisterChangeHandler(_changeHandlerId); QObject::disconnect(this, &EntityRenderer::requestRenderUpdate, this, nullptr); +} + +void EntityRenderer::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { + std::lock_guard lock(_materialsLock); + _materials[shapeID].push(material); +} + +void EntityRenderer::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { + std::lock_guard lock(_materialsLock); + _materials[shapeID].remove(material); } \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index ce5bfb30a4..f58b540aef 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -101,6 +101,10 @@ protected: return result; } +public slots: + virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID); + virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID); + signals: void requestRenderUpdate(); @@ -129,6 +133,8 @@ protected: // Only touched on the rendering thread bool _renderUpdateQueued{ false }; + std::unordered_map _materials; + std::mutex _materialsLock; private: // The base class relies on comparing the model transform to the entity transform in order diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index 83754c1c16..d541d99c4c 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -15,12 +15,18 @@ bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP if (entity->getMaterial() != _drawMaterial) { return true; } + if (entity->getParentID() != _parentID || entity->getClientOnly() != _clientOnly || entity->getOwningAvatarID() != _owningAvatarID) { + return true; + } return false; } void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { withWriteLock([&] { _drawMaterial = entity->getMaterial(); + _parentID = entity->getParentID(); + _clientOnly = entity->getClientOnly(); + _owningAvatarID = entity->getOwningAvatarID(); _renderTransform = getModelTransform(); const float MATERIAL_ENTITY_SCALE = 0.5f; _renderTransform.postScale(MATERIAL_ENTITY_SCALE); @@ -30,7 +36,7 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& ItemKey MaterialEntityRenderer::getKey() { ItemKey::Builder builder; - builder.withTypeShape(); + builder.withTypeShape().withTagBits(render::ItemKey::TAG_BITS_0 | render::ItemKey::TAG_BITS_1); if (!_visible) { builder.withInvisible(); @@ -215,13 +221,25 @@ void MaterialEntityRenderer::generateMesh() { void MaterialEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderableMaterialEntityItem::render"); Q_ASSERT(args->_batch); - gpu::Batch& batch = *args->_batch; - batch.setModelTransform(_renderTransform); + // Don't render if our parent is set or our material is null + QUuid parentID; + Transform renderTransform; + graphics::MaterialPointer drawMaterial; + withReadLock([&] { + parentID = _clientOnly ? _owningAvatarID : _parentID; + renderTransform = _renderTransform; + drawMaterial = _drawMaterial; + }); + if (!parentID.isNull() || !drawMaterial) { + return; + } + + batch.setModelTransform(renderTransform); // bind the material - args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing); + args->_shapePipeline->bindMaterial(drawMaterial, batch, args->_enableTexturing); args->_details._materialSwitches++; // Draw! diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index 166ad762cc..af8cef9351 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -31,6 +31,9 @@ private: ItemKey getKey() override; ShapeKey getShapeKey() override; + QUuid _parentID; + bool _clientOnly; + QUuid _owningAvatarID; Transform _renderTransform; std::shared_ptr _drawMaterial; @@ -47,7 +50,7 @@ private: static void addVertex(std::vector& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv); const int SLICES = 15; const int STACKS = 9; - const float M_PI_TIMES_2 = 2.0f * M_PI; + const float M_PI_TIMES_2 = 2.0f * (float)M_PI; }; } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 137203f475..739ccd9738 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1380,6 +1380,7 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce auto entityRenderer = static_cast(&data); entityRenderer->setSubRenderItemIDs(newRenderItemIDs); }); + processMaterials(); } } @@ -1466,3 +1467,28 @@ void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStr } } +void ModelEntityRenderer::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { + Parent::addMaterial(material, shapeID); + if (_model && _model->fetchRenderItemIDs().size() > 0) { + _model->addMaterial(material, shapeID); + } +} + +void ModelEntityRenderer::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { + Parent::removeMaterial(material, shapeID); + if (_model && _model->fetchRenderItemIDs().size() > 0) { + _model->removeMaterial(material, shapeID); + } +} + +void ModelEntityRenderer::processMaterials() { + assert(_model); + std::lock_guard lock(_materialsLock); + for (auto& shapeMaterialPair : _materials) { + auto material = shapeMaterialPair.second; + while (!material.empty()) { + _model->addMaterial(material.top(), shapeMaterialPair.first); + material.pop(); + } + } +} \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 33fc9910a0..75c6639902 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -138,10 +138,15 @@ namespace render { namespace entities { class ModelEntityRenderer : public TypedEntityRenderer { using Parent = TypedEntityRenderer; friend class EntityRenderer; + Q_OBJECT public: ModelEntityRenderer(const EntityItemPointer& entity); +public slots: + void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + protected: virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction) override; virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override; @@ -194,6 +199,8 @@ private: uint64_t _lastAnimated { 0 }; render::ItemKey _itemKey { render::ItemKey::Builder().withTypeMeta() }; + + void processMaterials(); }; } } // namespace diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index cdee2c5ec9..8163b14608 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -54,8 +54,7 @@ bool ShapeEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin if (_lastUserData != entity->getUserData()) { return true; } - glm::vec4 newColor(toGlm(entity->getXColor()), entity->getLocalRenderAlpha()); - if (newColor != _color) { + if (_material != entity->getMaterial()) { return true; } @@ -78,7 +77,9 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _procedural.setProceduralData(ProceduralData::parse(_lastUserData)); } - _color = vec4(toGlm(entity->getXColor()), entity->getLocalRenderAlpha()); + removeMaterial(_material, 0); + _material = entity->getMaterial(); + addMaterial(_material, 0); _shape = entity->getShape(); _position = entity->getWorldPosition(); @@ -112,14 +113,13 @@ bool ShapeEntityRenderer::isTransparent() const { return Parent::isTransparent(); } - - void ShapeEntityRenderer::doRender(RenderArgs* args) { PerformanceTimer perfTimer("RenderableShapeEntityItem::render"); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; + std::shared_ptr mat; auto geometryCache = DependencyManager::get(); GeometryCache::Shape geometryShape; bool proceduralRender = false; @@ -127,15 +127,22 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { withReadLock([&] { geometryShape = geometryCache->getShapeForEntityShape(_shape); batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation - outColor = _color; - if (_procedural.isReady()) { - _procedural.prepare(batch, _position, _dimensions, _orientation); - outColor = _procedural.getColor(_color); - outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; - proceduralRender = true; + mat = _materials[0].top(); + if (mat) { + outColor = glm::vec4(mat->getAlbedo(), mat->getOpacity()); + if (_procedural.isReady()) { + _procedural.prepare(batch, _position, _dimensions, _orientation); + outColor = _procedural.getColor(outColor); + outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; + proceduralRender = true; + } } }); + if (!mat) { + return; + } + if (proceduralRender) { if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { geometryCache->renderWireShape(batch, geometryShape, outColor); diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.h b/libraries/entities-renderer/src/RenderableShapeEntityItem.h index 433cb41ad2..c913544255 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.h +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.h @@ -34,7 +34,7 @@ private: QString _lastUserData; Transform _renderTransform; entity::Shape _shape { entity::Sphere }; - glm::vec4 _color; + std::shared_ptr _material; glm::vec3 _position; glm::vec3 _dimensions; glm::quat _orientation; diff --git a/libraries/entities/src/DeleteEntityOperator.cpp b/libraries/entities/src/DeleteEntityOperator.cpp index cbd0ad7839..347d40ea49 100644 --- a/libraries/entities/src/DeleteEntityOperator.cpp +++ b/libraries/entities/src/DeleteEntityOperator.cpp @@ -93,7 +93,7 @@ bool DeleteEntityOperator::preRecursion(const OctreeElementPointer& element) { // and we can stop searching. if (entityTreeElement == details.containingElement) { EntityItemPointer theEntity = details.entity; - bool entityDeleted = entityTreeElement->removeEntityItem(theEntity); // remove it from the element + bool entityDeleted = entityTreeElement->removeEntityItem(theEntity, true); // remove it from the element assert(entityDeleted); (void)entityDeleted; // quite warning _tree->clearEntityMapEntry(details.entity->getEntityItemID()); diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index ed13a46414..43510864ba 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -60,14 +60,6 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) : } EntityItem::~EntityItem() { - // clear out any left-over actions - EntityTreeElementPointer element = _element; // use local copy of _element for logic below - EntityTreePointer entityTree = element ? element->getTree() : nullptr; - EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr; - if (simulation) { - clearActions(simulation); - } - // these pointers MUST be correct at delete, else we probably have a dangling backpointer // to this EntityItem in the corresponding data structure. assert(!_simulated); @@ -2937,3 +2929,34 @@ void EntityItem::retrieveMarketplacePublicKey() { networkReply->deleteLater(); }); } + +void EntityItem::preDelete() { + // clear out any left-over actions + EntityTreeElementPointer element = _element; // use local copy of _element for logic below + EntityTreePointer entityTree = element ? element->getTree() : nullptr; + EntitySimulationPointer simulation = entityTree ? entityTree->getSimulation() : nullptr; + if (simulation) { + clearActions(simulation); + } +} + +void EntityItem::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { + std::lock_guard lock(_materialsLock); + _materials[shapeID].push(material); + emit addMaterialToRenderItem(material, shapeID); +} + +void EntityItem::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { + std::lock_guard lock(_materialsLock); + _materials[shapeID].remove(material); + emit removeMaterialFromRenderItem(material, shapeID); +} + +std::unordered_map EntityItem::getMaterials() { + std::unordered_map toReturn; + { + std::lock_guard lock(_materialsLock); + toReturn = _materials; + } + return toReturn; +} \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5f84bcc311..b2804a2e86 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -36,6 +36,8 @@ #include "SimulationFlags.h" #include "EntityDynamicInterface.h" +#include "graphics/Material.h" + class EntitySimulation; class EntityTreeElement; class EntityTreeElementExtraEncodeData; @@ -49,7 +51,6 @@ typedef std::shared_ptr EntityTreeElementPointer; using EntityTreeElementExtraEncodeDataPointer = std::shared_ptr; - #define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0; #define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() override { }; @@ -443,10 +444,10 @@ public: void scriptHasUnloaded() { _loadedScript = ""; _loadedScriptTimestamp = 0; } bool getClientOnly() const { return _clientOnly; } - void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; } + virtual void setClientOnly(bool clientOnly) { _clientOnly = clientOnly; } // if this entity is client-only, which avatar is it associated with? QUuid getOwningAvatarID() const { return _owningAvatarID; } - void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; } + virtual void setOwningAvatarID(const QUuid& owningAvatarID) { _owningAvatarID = owningAvatarID; } virtual bool wantsHandControllerPointerEvents() const { return false; } virtual bool wantsKeyboardFocus() const { return false; } @@ -477,8 +478,18 @@ public: void setCauterized(bool value) { _cauterized = value; } bool getCauterized() const { return _cauterized; } + virtual void postAdd() {} + virtual void preDelete(); + virtual void postParentFixup() {} + + void addMaterial(graphics::MaterialPointer material, quint16 shapeID); + void removeMaterial(graphics::MaterialPointer material, quint16 shapeID); + std::unordered_map getMaterials(); + signals: void requestRenderUpdate(); + void addMaterialToRenderItem(graphics::MaterialPointer material, quint16 shapeID); + void removeMaterialFromRenderItem(graphics::MaterialPointer material, quint16 shapeID); protected: QHash _changeHandlers; @@ -631,6 +642,11 @@ protected: quint64 _lastUpdatedQueryAACubeTimestamp { 0 }; bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera + +private: + std::unordered_map _materials; + std::mutex _materialsLock; + }; #endif // hifi_EntityItem_h diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 965252abf4..19aa6990db 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -360,7 +360,9 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_MATERIAL_BLEND_FACTOR, blendFactor); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_PRIORITY, priority); CHECK_PROPERTY_CHANGE(PROP_PARENT_SHAPE_ID, shapeID); - CHECK_PROPERTY_CHANGE(PROP_MATERIAL_BOUNDS, materialBounds); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_POS, materialPos); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_SCALE, materialScale); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_ROT, materialRot); // Certifiable Properties CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName); @@ -664,7 +666,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_BLEND_FACTOR, blendFactor); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_PRIORITY, priority); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_SHAPE_ID, shapeID); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_BOUNDS, materialBounds); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_POS, materialPos); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_SCALE, materialScale); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_ROT, materialRot); } if (!skipDefaults && !strictSemantics) { @@ -801,11 +805,13 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(radiusFinish, float, setRadiusFinish); COPY_PROPERTY_FROM_QSCRIPTVALUE(relayParentJoints, bool, setRelayParentJoints); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialURL, QString, setMaterialURL); - COPY_PROPERTY_FROM_QSCRITPTVALUE_ENUM(materialMode, MaterialMode, setMaterialMode); + COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(materialMode, MaterialMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(blendFactor, float, setBlendFactor); - COPY_PROPERTY_FROM_QSCRIPTVALUE(priority, int, setPriority); - COPY_PROPERTY_FROM_QSCRIPTVALUE(shapeID, int, setShapeID); - COPY_PROPERTY_FROM_QSCRIPTVALUE(materialBounds, glmVec4, setMaterialBounds); + COPY_PROPERTY_FROM_QSCRIPTVALUE(priority, quint16, setPriority); + COPY_PROPERTY_FROM_QSCRIPTVALUE(shapeID, quint16, setShapeID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(materialPos, glmVec2, setMaterialPos); + COPY_PROPERTY_FROM_QSCRIPTVALUE(materialScale, glmVec2, setMaterialScale); + COPY_PROPERTY_FROM_QSCRIPTVALUE(materialRot, float, setMaterialRot); // Certifiable Properties COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName); @@ -1163,9 +1169,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_MATERIAL_URL, MaterialURL, materialURL, QString); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_TYPE, MaterialMode, materialMode, MaterialMode); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_BLEND_FACTOR, BlendFactor, blendFactor, float); - ADD_PROPERTY_TO_MAP(PROP_MATERIAL_PRIORITY, Priority, priority, uint32_t); - ADD_PROPERTY_TO_MAP(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, uint32_t); - ADD_PROPERTY_TO_MAP(PROP_MATERIAL_BOUNDS, MaterialBounds, materialBounds, glmVec4); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_PRIORITY, Priority, priority, quint16); + ADD_PROPERTY_TO_MAP(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, quint16); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_POS, MaterialPos, materialPos, glmVec2); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_SCALE, MaterialScale, materialScale, glmVec2); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_ROT, MaterialRot, materialRot, float); // Certifiable Properties ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString); @@ -1557,7 +1565,9 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, properties.getBlendFactor()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, properties.getPriority()); APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, properties.getShapeID()); - APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, properties.getMaterialBounds()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_POS, properties.getMaterialPos()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, properties.getMaterialScale()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_ROT, properties.getMaterialRot()); } APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName()); @@ -1921,9 +1931,11 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_URL, QString, setMaterialURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_PRIORITY, uint32_t, setPriority); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_SHAPE_ID, uint32_t, setShapeID); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_BOUNDS, glmVec4, setMaterialBounds); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_PRIORITY, quint16, setPriority); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_SHAPE_ID, quint16, setShapeID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_POS, glmVec2, setMaterialPos); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_SCALE, glmVec2, setMaterialScale); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_ROT, float, setMaterialRot); } READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName); @@ -2104,7 +2116,9 @@ void EntityItemProperties::markAllChanged() { _blendFactorChanged = true; _priorityChanged = true; _shapeIDChanged = true; - _materialBoundsChanged = true; + _materialPosChanged = true; + _materialScaleChanged = true; + _materialRotChanged = true; // Certifiable Properties _itemNameChanged = true; @@ -2444,8 +2458,14 @@ QList EntityItemProperties::listChangedProperties() { if (shapeIDChanged()) { out += "shapeID"; } - if (materialBoundsChanged()) { - out += "materialBounds"; + if (materialPosChanged()) { + out += "materialPos"; + } + if (materialScaleChanged()) { + out += "materialScale"; + } + if (materialRotChanged()) { + out += "materialRot"; } // Certifiable Properties diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 9bedff41df..a8a79b6303 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -225,9 +225,11 @@ public: DEFINE_PROPERTY_REF(PROP_MATERIAL_URL, MaterialURL, materialURL, QString, ""); DEFINE_PROPERTY_REF_ENUM(PROP_MATERIAL_TYPE, MaterialMode, materialMode, MaterialMode, UV); DEFINE_PROPERTY_REF(PROP_MATERIAL_BLEND_FACTOR, BlendFactor, blendFactor, float, 1.0f); - DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, uint32_t, 0); - DEFINE_PROPERTY_REF(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, uint32_t, 0); - DEFINE_PROPERTY_REF(PROP_MATERIAL_BOUNDS, MaterialBounds, materialBounds, glmVec4, glm::vec4(0, 0, 1, 1)); + DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, quint16, 0); + DEFINE_PROPERTY_REF(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, quint16, 0); + DEFINE_PROPERTY_REF(PROP_MATERIAL_POS, MaterialPos, materialPos, glmVec2, glm::vec2(0, 0)); + DEFINE_PROPERTY_REF(PROP_MATERIAL_SCALE, MaterialScale, materialScale, glmVec2, glm::vec2(1, 1)); + DEFINE_PROPERTY_REF(PROP_MATERIAL_ROT, MaterialRot, materialRot, float, 0); // Certifiable Properties - related to Proof of Purchase certificates DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME); diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 2609fe237d..51a23b6867 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -101,6 +101,7 @@ changedProperties += P; \ } +inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec2& v) { return vec2toScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const glm::vec3& v) { return vec3toScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, float v) { return QScriptValue(v); } inline QScriptValue convertScriptValue(QScriptEngine* e, int v) { return QScriptValue(v); } @@ -183,8 +184,8 @@ inline QScriptValue convertScriptValue(QScriptEngine* e, const AACube& v) { retu properties.setProperty(#P, V); \ } +typedef glm::vec2 glmVec2; typedef glm::vec3 glmVec3; -typedef glm::vec4 glmVec4; typedef glm::quat glmQuat; typedef QVector qVectorVec3; typedef QVector qVectorQuat; @@ -222,6 +223,23 @@ inline QByteArray QByteArray_convertFromScriptValue(const QScriptValue& v, bool& return QByteArray::fromBase64(b64.toUtf8()); } +inline glmVec2 glmVec2_convertFromScriptValue(const QScriptValue& v, bool& isValid) { + isValid = false; /// assume it can't be converted + QScriptValue x = v.property("x"); + QScriptValue y = v.property("y"); + if (x.isValid() && y.isValid()) { + glm::vec4 newValue(0); + newValue.x = x.toVariant().toFloat(); + newValue.y = y.toVariant().toFloat(); + isValid = !glm::isnan(newValue.x) && + !glm::isnan(newValue.y); + if (isValid) { + return newValue; + } + } + return glm::vec2(0); +} + inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = false; /// assume it can't be converted QScriptValue x = v.property("x"); @@ -242,29 +260,6 @@ inline glmVec3 glmVec3_convertFromScriptValue(const QScriptValue& v, bool& isVal return glm::vec3(0); } -inline glmVec4 glmVec4_convertFromScriptValue(const QScriptValue& v, bool& isValid) { - isValid = false; /// assume it can't be converted - QScriptValue x = v.property("x"); - QScriptValue y = v.property("y"); - QScriptValue z = v.property("z"); - QScriptValue w = v.property("w"); - if (x.isValid() && y.isValid() && z.isValid() && w.isValid()) { - glm::vec4 newValue(0); - newValue.x = x.toVariant().toFloat(); - newValue.y = y.toVariant().toFloat(); - newValue.z = z.toVariant().toFloat(); - newValue.w = w.toVariant().toFloat(); - isValid = !glm::isnan(newValue.x) && - !glm::isnan(newValue.y) && - !glm::isnan(newValue.z) && - !glm::isnan(newValue.w); - if (isValid) { - return newValue; - } - } - return glm::vec4(0); -} - inline AACube AACube_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = true; AACube result; diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index bd573423a3..17ebddbe9d 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -232,7 +232,9 @@ enum EntityPropertyList { PROP_MATERIAL_BLEND_FACTOR, PROP_MATERIAL_PRIORITY, PROP_PARENT_SHAPE_ID, - PROP_MATERIAL_BOUNDS, + PROP_MATERIAL_POS, + PROP_MATERIAL_SCALE, + PROP_MATERIAL_ROT, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index bf29f3bec9..775b3bd2f7 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -1732,15 +1732,19 @@ void EntityTree::fixupNeedsParentFixups() { } }); entity->locationChanged(true); - } else if (getIsServer() && _avatarIDs.contains(entity->getParentID())) { - // this is a child of an avatar, which the entity server will never have - // a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves. - if (!_childrenOfAvatars.contains(entity->getParentID())) { - _childrenOfAvatars[entity->getParentID()] = QSet(); + entity->postParentFixup(); + } else if (_avatarIDs.contains(entity->getParentID())) { + if (getIsServer()) { + // this is a child of an avatar, which the entity server will never have + // a SpatiallyNestable object for. Add it to a list for cleanup when the avatar leaves. + if (!_childrenOfAvatars.contains(entity->getParentID())) { + _childrenOfAvatars[entity->getParentID()] = QSet(); + } + _childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID(); } - _childrenOfAvatars[entity->getParentID()] += entity->getEntityItemID(); doMove = true; iter.remove(); // and pull it out of the list + entity->postParentFixup(); } if (queryAACubeSuccess && doMove) { @@ -2378,3 +2382,35 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const { return entity->getJointNames(); } +std::function EntityTree::_addMaterialToAvatarOperator = nullptr; +std::function EntityTree::_removeMaterialFromAvatarOperator = nullptr; +std::function EntityTree::_addMaterialToOverlayOperator = nullptr; +std::function EntityTree::_removeMaterialFromOverlayOperator = nullptr; + +bool EntityTree::addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) { + if (_addMaterialToAvatarOperator) { + return _addMaterialToAvatarOperator(avatarID, material, shapeID); + } + return false; +} + +bool EntityTree::removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) { + if (_removeMaterialFromAvatarOperator) { + return _removeMaterialFromAvatarOperator(avatarID, material, shapeID); + } + return false; +} + +bool EntityTree::addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) { + if (_addMaterialToOverlayOperator) { + return _addMaterialToOverlayOperator(overlayID, material, shapeID); + } + return false; +} + +bool EntityTree::removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) { + if (_removeMaterialFromOverlayOperator) { + return _removeMaterialFromOverlayOperator(overlayID, material, shapeID); + } + return false; +} \ No newline at end of file diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 8cb89d6493..a02ce900ff 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -280,6 +280,16 @@ public: void setMyAvatar(std::shared_ptr myAvatar) { _myAvatar = myAvatar; } + static void setAddMaterialToAvatarOperator(std::function addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; } + static void setRemoveMaterialFromAvatarOperator(std::function removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; } + static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID); + static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID); + + static void setAddMaterialToOverlayOperator(std::function addMaterialToOverlayOperator) { _addMaterialToOverlayOperator = addMaterialToOverlayOperator; } + static void setRemoveMaterialFromOverlayOperator(std::function removeMaterialFromOverlayOperator) { _removeMaterialFromOverlayOperator = removeMaterialFromOverlayOperator; } + static bool addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID); + static bool removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID); + signals: void deletingEntity(const EntityItemID& entityID); void deletingEntityPointer(EntityItem* entityID); @@ -387,6 +397,11 @@ private: void validatePop(const QString& certID, const EntityItemID& entityItemID, const SharedNodePointer& senderNode, bool isRetryingValidation); std::shared_ptr _myAvatar{ nullptr }; + + static std::function _addMaterialToAvatarOperator; + static std::function _removeMaterialFromAvatarOperator; + static std::function _addMaterialToOverlayOperator; + static std::function _removeMaterialFromOverlayOperator; }; #endif // hifi_EntityTree_h diff --git a/libraries/entities/src/EntityTreeElement.cpp b/libraries/entities/src/EntityTreeElement.cpp index c9e1ecc3f1..980ed1c104 100644 --- a/libraries/entities/src/EntityTreeElement.cpp +++ b/libraries/entities/src/EntityTreeElement.cpp @@ -896,6 +896,7 @@ EntityItemPointer EntityTreeElement::getEntityWithEntityItemID(const EntityItemI void EntityTreeElement::cleanupEntities() { withWriteLock([&] { foreach(EntityItemPointer entity, _entityItems) { + entity->preDelete(); // NOTE: only EntityTreeElement should ever be changing the value of entity->_element // NOTE: We explicitly don't delete the EntityItem here because since we only // access it by smart pointers, when we remove it from the _entityItems @@ -907,26 +908,10 @@ void EntityTreeElement::cleanupEntities() { bumpChangedContent(); } -bool EntityTreeElement::removeEntityWithEntityItemID(const EntityItemID& id) { - bool foundEntity = false; - withWriteLock([&] { - uint16_t numberOfEntities = _entityItems.size(); - for (uint16_t i = 0; i < numberOfEntities; i++) { - EntityItemPointer& entity = _entityItems[i]; - if (entity->getEntityItemID() == id) { - foundEntity = true; - // NOTE: only EntityTreeElement should ever be changing the value of entity->_element - entity->_element = NULL; - _entityItems.removeAt(i); - bumpChangedContent(); - break; - } - } - }); - return foundEntity; -} - -bool EntityTreeElement::removeEntityItem(EntityItemPointer entity) { +bool EntityTreeElement::removeEntityItem(EntityItemPointer entity, bool deletion) { + if (deletion) { + entity->preDelete(); + } int numEntries = 0; withWriteLock([&] { numEntries = _entityItems.removeAll(entity); @@ -955,6 +940,7 @@ void EntityTreeElement::addEntityItem(EntityItemPointer entity) { }); bumpChangedContent(); entity->_element = getThisPointer(); + entity->postAdd(); } // will average a "common reduced LOD view" from the the child elements... diff --git a/libraries/entities/src/EntityTreeElement.h b/libraries/entities/src/EntityTreeElement.h index a524904c71..2313bde0c4 100644 --- a/libraries/entities/src/EntityTreeElement.h +++ b/libraries/entities/src/EntityTreeElement.h @@ -210,8 +210,7 @@ public: void getEntitiesInside(const AACube& box, QVector& foundEntities); void cleanupEntities(); /// called by EntityTree on cleanup this will free all entities - bool removeEntityWithEntityItemID(const EntityItemID& id); - bool removeEntityItem(EntityItemPointer entity); + bool removeEntityItem(EntityItemPointer entity, bool deletion = false); bool containsEntityBounds(EntityItemPointer entity) const; bool bestFitEntityBounds(EntityItemPointer entity) const; diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index bbcc691879..7026da117c 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -16,6 +16,9 @@ EntityItemPointer MaterialEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { Pointer entity(new MaterialEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); }); entity->setProperties(properties); + // When you reload content, setProperties doesn't have any of the propertiesChanged flags set, so it won't trigger a material add + entity->removeMaterial(); + entity->applyMaterial(); return entity; } @@ -31,7 +34,9 @@ EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desir COPY_ENTITY_PROPERTY_TO_PROPERTIES(blendFactor, getBlendFactor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(priority, getPriority); COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeID, getShapeID); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialBounds, getMaterialBounds); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialPos, getMaterialPos); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialScale, getMaterialScale); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialRot, getMaterialRot); return properties; } @@ -43,7 +48,9 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(blendFactor, setBlendFactor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(priority, setPriority); SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeID, setShapeID); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialBounds, setMaterialBounds); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialPos, setMaterialPos); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialScale, setMaterialScale); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialRot, setMaterialRot); if (somethingChanged) { bool wantDebug = false; @@ -202,9 +209,11 @@ int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da READ_ENTITY_PROPERTY(PROP_MATERIAL_URL, QString, setMaterialURL); READ_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode); READ_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor); - READ_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, uint32_t, setPriority); - READ_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, uint32_t, setShapeID); - READ_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, glm::vec4, setMaterialBounds); + READ_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, quint16, setPriority); + READ_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, quint16, setShapeID); + READ_ENTITY_PROPERTY(PROP_MATERIAL_POS, glm::vec2, setMaterialPos); + READ_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, glm::vec2, setMaterialScale); + READ_ENTITY_PROPERTY(PROP_MATERIAL_ROT, float, setMaterialRot); return bytesRead; } @@ -218,7 +227,9 @@ EntityPropertyFlags MaterialEntityItem::getEntityProperties(EncodeBitstreamParam requestedProperties += PROP_MATERIAL_BLEND_FACTOR; requestedProperties += PROP_MATERIAL_PRIORITY; requestedProperties += PROP_PARENT_SHAPE_ID; - requestedProperties += PROP_MATERIAL_BOUNDS; + requestedProperties += PROP_MATERIAL_POS; + requestedProperties += PROP_MATERIAL_SCALE; + requestedProperties += PROP_MATERIAL_ROT; return requestedProperties; } @@ -234,9 +245,11 @@ void MaterialEntityItem::appendSubclassData(OctreePacketData* packetData, Encode APPEND_ENTITY_PROPERTY(PROP_MATERIAL_URL, getMaterialURL()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, (uint32_t)getMaterialMode()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, getBlendFactor()); - APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, (uint32_t)getPriority()); - APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, (uint32_t)getShapeID()); - APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BOUNDS, getMaterialBounds()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, getPriority()); + APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, getShapeID()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_POS, getMaterialPos()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, getMaterialScale()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_ROT, getMaterialRot()); } void MaterialEntityItem::debugDump() const { @@ -249,7 +262,9 @@ void MaterialEntityItem::debugDump() const { qCDebug(entities) << " blend factor:" << _blendFactor; qCDebug(entities) << " priority:" << _priority; qCDebug(entities) << " parent shape ID:" << _shapeID; - qCDebug(entities) << " material bounds:" << _materialBounds; + qCDebug(entities) << " material pos:" << _materialPos; + qCDebug(entities) << " material scale:" << _materialRot; + qCDebug(entities) << " material rot:" << _materialScale; qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition()); qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions()); qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now); @@ -269,30 +284,38 @@ std::shared_ptr MaterialEntityItem::getMaterial() const { } } -void MaterialEntityItem::setMaterialURL(const QString& materialURLString) { - if (materialURLString.startsWith("userData")) { - QJsonDocument materialJSON = QJsonDocument::fromJson(getUserData().toUtf8()); - _materials.clear(); - _materialNames.clear(); - if (!materialJSON.isNull()) { - if (materialJSON.isArray()) { - QJsonArray materials = materialJSON.array(); - for (auto& material : materials) { - if (!material.isNull() && material.isObject()) { - parseJSONMaterial(material.toObject()); +void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool userDataChanged) { + bool usingUserData = materialURLString.startsWith("userData"); + if (_materialURL != materialURLString || (usingUserData && userDataChanged)) { + removeMaterial(); + _materialURL = materialURLString; + + if (usingUserData) { + QJsonDocument materialJSON = QJsonDocument::fromJson(getUserData().toUtf8()); + _materials.clear(); + _materialNames.clear(); + if (!materialJSON.isNull()) { + if (materialJSON.isArray()) { + QJsonArray materials = materialJSON.array(); + for (auto material : materials) { + if (!material.isNull() && material.isObject()) { + parseJSONMaterial(material.toObject()); + } } + } else if (materialJSON.isObject()) { + parseJSONMaterial(materialJSON.object()); } - } else if (materialJSON.isObject()) { - parseJSONMaterial(materialJSON.object()); } + } else { + // get material via network request } + + // TODO: if URL ends with ?string, try to set _currentMaterialName = string + + // Since our JSON changed, the current name might not be valid anymore, so we need to update + setCurrentMaterialName(_currentMaterialName); + applyMaterial(); } - _materialURL = materialURLString; - - // TODO: if URL ends with ?string, set _currentMaterialName = string - - // Since our JSON changed, the current name might not be valid anymore, so we need to update - setCurrentMaterialName(_currentMaterialName); } void MaterialEntityItem::setCurrentMaterialName(const QString& currentMaterialName) { @@ -300,14 +323,176 @@ void MaterialEntityItem::setCurrentMaterialName(const QString& currentMaterialNa if (material != _materials.end()) { _currentMaterialName = currentMaterialName; } else if (_materialNames.size() > 0) { - setCurrentMaterialName(_materialNames[0]); + _currentMaterialName = _materialNames[0]; } } void MaterialEntityItem::setUserData(const QString& userData) { - EntityItem::setUserData(userData); - if (_materialURL.startsWith("userData")) { - // Trigger material update when user data changes - setMaterialURL(_materialURL); + if (_userData != userData) { + EntityItem::setUserData(userData); + if (_materialURL.startsWith("userData")) { + // Trigger material update when user data changes + setMaterialURL(_materialURL, true); + } } +} + +void MaterialEntityItem::setMaterialPos(const glm::vec2& materialPos) { + if (_materialPos != materialPos) { + removeMaterial(); + _materialPos = materialPos; + applyMaterial(); + } +} + +void MaterialEntityItem::setMaterialScale(const glm::vec2& materialScale) { + if (_materialScale != materialScale) { + removeMaterial(); + _materialScale = materialScale; + applyMaterial(); + } +} + +void MaterialEntityItem::setMaterialRot(const float& materialRot) { + if (_materialRot != materialRot) { + removeMaterial(); + _materialRot = materialRot; + applyMaterial(); + } +} + +void MaterialEntityItem::setBlendFactor(float blendFactor) { + if (_blendFactor != blendFactor) { + removeMaterial(); + _blendFactor = blendFactor; + applyMaterial(); + } +} + +void MaterialEntityItem::setPriority(quint16 priority) { + if (_priority != priority) { + removeMaterial(); + _priority = priority; + applyMaterial(); + } +} + +void MaterialEntityItem::setShapeID(quint16 shapeID) { + if (_shapeID != shapeID) { + removeMaterial(); + _shapeID = shapeID; + applyMaterial(); + } +} + +void MaterialEntityItem::setParentID(const QUuid& parentID) { + if (getParentID() != parentID) { + removeMaterial(); + EntityItem::setParentID(parentID); + applyMaterial(); + } +} + +void MaterialEntityItem::setClientOnly(bool clientOnly) { + if (getClientOnly() != clientOnly) { + removeMaterial(); + EntityItem::setClientOnly(clientOnly); + applyMaterial(); + } +} + +void MaterialEntityItem::setOwningAvatarID(const QUuid& owningAvatarID) { + if (getOwningAvatarID() != owningAvatarID) { + removeMaterial(); + EntityItem::setOwningAvatarID(owningAvatarID); + applyMaterial(); + } +} + +void MaterialEntityItem::removeMaterial() { + graphics::MaterialPointer material = getMaterial(); + QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID(); + if (!material || parentID.isNull()) { + return; + } + + // Our parent could be an entity, an avatar, or an overlay + EntityTreePointer tree = getTree(); + if (tree) { + EntityItemPointer entity = tree->findEntityByEntityItemID(parentID); + if (entity) { + entity->removeMaterial(material, getShapeID()); + return; + } + } + + if (EntityTree::removeMaterialFromAvatar(parentID, material, getShapeID())) { + return; + } + + if (EntityTree::removeMaterialFromOverlay(parentID, material, getShapeID())) { + return; + } + + // if a remove fails, our parent is gone, so we don't need to retry +} + +void MaterialEntityItem::applyMaterial() { + _retryApply = false; + graphics::MaterialPointer material = getMaterial(); + QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID(); + if (!material || parentID.isNull()) { + return; + } + Transform textureTransform; + textureTransform.setTranslation(glm::vec3(_materialPos, 0)); + textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialRot))); + textureTransform.setScale(glm::vec3(_materialScale, 1)); + material->setTextureTransforms(textureTransform); + material->setBlendFactor(getBlendFactor()); + material->setPriority(getPriority()); + + // Our parent could be an entity, an avatar, or an overlay + EntityTreePointer tree = getTree(); + if (tree) { + EntityItemPointer entity = tree->findEntityByEntityItemID(parentID); + if (entity) { + entity->addMaterial(material, getShapeID()); + return; + } + } + + if (EntityTree::addMaterialToAvatar(parentID, material, getShapeID())) { + return; + } + + if (EntityTree::addMaterialToOverlay(parentID, material, getShapeID())) { + return; + } + + // if we've reached this point, we couldn't find our parent, so we need to try again later + _retryApply = true; +} + +void MaterialEntityItem::postAdd() { + removeMaterial(); + applyMaterial(); +} + +void MaterialEntityItem::preDelete() { + EntityItem::preDelete(); + removeMaterial(); +} + +void MaterialEntityItem::postParentFixup() { + removeMaterial(); + applyMaterial(); +} + +void MaterialEntityItem::update(const quint64& now) { + if (_retryApply) { + applyMaterial(); + } + + EntityItem::update(now); } \ No newline at end of file diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index 80fe226b68..40137acf22 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -23,6 +23,9 @@ public: ALLOW_INSTANTIATION // This class can be instantiated + void update(const quint64& now) override; + bool needsToCallUpdate() const override { return true; } + // methods for getting/setting all properties of an entity virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override; virtual bool setProperties(const EntityItemProperties& properties) override; @@ -49,7 +52,7 @@ public: virtual void setUnscaledDimensions(const glm::vec3& value) override; QString getMaterialURL() const { return _materialURL; } - void setMaterialURL(const QString& materialURLString); + void setMaterialURL(const QString& materialURLString, bool userDataChanged = false); QString getCurrentMaterialName() const { return _currentMaterialName; } void setCurrentMaterialName(const QString& currentMaterialName); @@ -58,33 +61,51 @@ public: void setMaterialMode(MaterialMode mode) { _materialMode = mode; } float getBlendFactor() const { return _blendFactor; } - void setBlendFactor(float blendFactor) { _blendFactor = blendFactor; } + void setBlendFactor(float blendFactor); - int getPriority() const { return _priority; } - void setPriority(int priority) { _priority = priority; } + quint16 getPriority() const { return _priority; } + void setPriority(quint16 priority); - int getShapeID() const { return _shapeID; } - void setShapeID(int shapeID) { _shapeID = shapeID; } + quint16 getShapeID() const { return _shapeID; } + void setShapeID(quint16 shapeID); - glm::vec4 getMaterialBounds() const { return _materialBounds; } - void setMaterialBounds(const glm::vec4& materialBounds) { _materialBounds = materialBounds; } + glm::vec2 getMaterialPos() const { return _materialPos; } + void setMaterialPos(const glm::vec2& materialPos); + glm::vec2 getMaterialScale() const { return _materialScale; } + void setMaterialScale(const glm::vec2& materialScale); + float getMaterialRot() const { return _materialRot; } + void setMaterialRot(const float& materialRot); std::shared_ptr getMaterial() const; void setUserData(const QString& userData) override; + void setParentID(const QUuid& parentID) override; + void setClientOnly(bool clientOnly) override; + void setOwningAvatarID(const QUuid& owningAvatarID) override; + + void applyMaterial(); + void removeMaterial(); + + void postAdd() override; + void preDelete() override; + void postParentFixup() override; private: QString _materialURL; MaterialMode _materialMode { UV }; float _blendFactor { 1.0f }; - int _priority { 0 }; - int _shapeID { 0 }; - glm::vec4 _materialBounds { 0, 0, 1, 1 }; + quint16 _priority { 0 }; + quint16 _shapeID { 0 }; + glm::vec2 _materialPos { 0, 0 }; + glm::vec2 _materialScale { 1, 1 }; + float _materialRot { 0 }; QHash> _materials; std::vector _materialNames; QString _currentMaterialName; + bool _retryApply { false }; + void parseJSONMaterial(const QJsonObject& materialJSON); static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 5d33e4c047..bec7bc1906 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -721,4 +721,4 @@ bool ModelEntityItem::isAnimatingSomething() const { _animationProperties.getRunning() && (_animationProperties.getFPS() != 0.0f); }); -} +} \ No newline at end of file diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index cbcfcaaa1d..2425208a87 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -85,6 +85,7 @@ EntityItemPointer ShapeEntityItem::sphereFactory(const EntityItemID& entityID, c ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) { _type = EntityTypes::Shape; _volumeMultiplier *= PI / 6.0f; + _material = std::make_shared(); } EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { @@ -184,6 +185,7 @@ void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit void ShapeEntityItem::setColor(const rgbColor& value) { memcpy(_color, value, sizeof(rgbColor)); + _material->setAlbedo(glm::vec3(_color[0], _color[1], _color[2]) / 255.0f); } xColor ShapeEntityItem::getXColor() const { @@ -204,6 +206,11 @@ void ShapeEntityItem::setColor(const QColor& value) { setAlpha(value.alpha()); } +void ShapeEntityItem::setAlpha(float alpha) { + _alpha = alpha; + _material->setOpacity(alpha); +} + void ShapeEntityItem::setUnscaledDimensions(const glm::vec3& value) { const float MAX_FLAT_DIMENSION = 0.0001f; if ((_shape == entity::Shape::Circle || _shape == entity::Shape::Quad) && value.y > MAX_FLAT_DIMENSION) { diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 84ce1ce57e..7ad1b3c1c2 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -75,7 +75,7 @@ public: void setShape(const QString& shape) { setShape(entity::shapeFromString(shape)); } float getAlpha() const { return _alpha; }; - void setAlpha(float alpha) { _alpha = alpha; } + void setAlpha(float alpha); const rgbColor& getColor() const { return _color; } void setColor(const rgbColor& value); @@ -101,6 +101,8 @@ public: virtual void computeShapeInfo(ShapeInfo& info) override; virtual ShapeType getShapeType() const override; + std::shared_ptr getMaterial() { return _material; } + protected: float _alpha { 1 }; @@ -111,6 +113,8 @@ protected: //! prior functionality where new or unsupported shapes are treated as //! ellipsoids. ShapeType _collisionShapeType{ ShapeType::SHAPE_TYPE_ELLIPSOID }; + + std::shared_ptr _material; }; #endif // hifi_ShapeEntityItem_h diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 6cc6b8472f..7c66c8ab07 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -12,9 +12,13 @@ #include "TextureMap.h" +#include + using namespace graphics; using namespace gpu; +int materialPointerMetaID = qRegisterMetaType("graphics::MaterialPointer"); + Material::Material() : _key(0), _schemaBuffer(), @@ -221,4 +225,15 @@ bool Material::calculateMaterialInfo() const { _hasCalculatedTextureInfo = allTextures; } return _hasCalculatedTextureInfo; +} + +void Material::setTextureTransforms(const Transform& transform) { + for (auto &textureMapItem : _textureMaps) { + if (textureMapItem.second) { + textureMapItem.second->setTextureTransform(transform); + } + } + for (int i = 0; i < NUM_TEXCOORD_TRANSFORMS; i++) { + _texMapArrayBuffer.edit()._texcoordTransforms[i] = transform.getMatrix(); + } } \ No newline at end of file diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index cfbfaa61ea..b9eb881ed8 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -15,11 +15,14 @@ #include #include +#include #include #include +class Transform; + namespace graphics { class TextureMap; @@ -351,6 +354,14 @@ public: size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; } bool hasTextureInfo() const { return _hasCalculatedTextureInfo; } + void setBlendFactor(float blendFactor) { _blendFactor = blendFactor; } + float getBlendFactor() { return _blendFactor; } + + void setPriority(quint16 priority) { _priority = priority; } + quint16 getPriority() { return _priority; } + + void setTextureTransforms(const Transform& transform); + private: mutable MaterialKey _key; mutable UniformBufferView _schemaBuffer; @@ -364,10 +375,35 @@ private: mutable bool _hasCalculatedTextureInfo { false }; bool calculateMaterialInfo() const; + float _blendFactor { 1.0f }; + quint16 _priority { 0 }; }; typedef std::shared_ptr< Material > MaterialPointer; +Q_DECLARE_METATYPE(MaterialPointer) + +class MaterialCompare { +public: + bool operator() (MaterialPointer left, MaterialPointer right) { + return left->getPriority() < right->getPriority(); + } +}; + +class MultiMaterial : public std::priority_queue, MaterialCompare> { +public: + bool remove(const MaterialPointer& value) { + auto it = std::find(c.begin(), c.end(), value); + if (it != c.end()) { + c.erase(it); + std::make_heap(c.begin(), c.end(), comp); + return true; + } else { + return false; + } + } +}; + }; #endif diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 1fe3648838..32deba3687 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -549,7 +549,6 @@ graphics::TextureMapPointer NetworkMaterial::fetchTextureMap(const QUrl& url, im auto map = std::make_shared(); if (texture) { map->setTextureSource(texture->_textureSource); - emit textureFinished(); } return map; @@ -728,6 +727,7 @@ void NetworkMaterial::setTextures(const QVariantMap& textureMap) { if (!occlusionName.isEmpty()) { auto url = textureMap.contains(occlusionName) ? textureMap[occlusionName].toUrl() : QUrl(); + // FIXME: we need to handle the occlusion map transform here auto map = fetchTextureMap(url, image::TextureUsage::OCCLUSION_TEXTURE, MapChannel::OCCLUSION_MAP); setTextureMap(MapChannel::OCCLUSION_MAP, map); } diff --git a/libraries/model-networking/src/model-networking/ModelCache.h b/libraries/model-networking/src/model-networking/ModelCache.h index 575f94f9bf..bbb00d72eb 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.h +++ b/libraries/model-networking/src/model-networking/ModelCache.h @@ -156,8 +156,7 @@ private: virtual ~ModelCache() = default; }; -class NetworkMaterial : public QObject, public graphics::Material { - Q_OBJECT +class NetworkMaterial : public graphics::Material { public: using MapChannel = graphics::Material::MapChannel; @@ -174,9 +173,6 @@ public: void setScatteringMap(const QString& url); void setLightmapMap(const QString& url); -signals: - void textureFinished(); - protected: friend class Geometry; diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index a2aad33058..7108f9a4e4 100644 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -381,6 +381,17 @@ bool OctreePacketData::appendValue(float value) { return success; } +bool OctreePacketData::appendValue(const glm::vec2& value) { + const unsigned char* data = (const unsigned char*)&value; + int length = sizeof(value); + bool success = append(data, length); + if (success) { + _bytesOfValues += length; + _totalBytesOfValues += length; + } + return success; +} + bool OctreePacketData::appendValue(const glm::vec3& value) { const unsigned char* data = (const unsigned char*)&value; int length = sizeof(value); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 7f8eb49101..85100ec177 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -164,6 +164,9 @@ public: /// appends a float value to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(float value); + /// appends a vec2 to the end of the stream, may fail if new data stream is too long to fit in packet + bool appendValue(const glm::vec2& value); + /// appends a non-position vector to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const glm::vec3& value); @@ -250,8 +253,8 @@ public: static quint64 getTotalBytesOfColor() { return _totalBytesOfColor; } /// total bytes of color static int unpackDataFromBytes(const unsigned char* dataBytes, float& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } + static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec2& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec3& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } - static int unpackDataFromBytes(const unsigned char* dataBytes, glm::vec4& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, bool& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, quint64& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } static int unpackDataFromBytes(const unsigned char* dataBytes, uint32_t& result) { memcpy(&result, dataBytes, sizeof(result)); return sizeof(result); } diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index b80327cf14..d24843c87d 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -47,7 +47,7 @@ template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderAr MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material) { updateMeshPart(mesh, partIndex); - updateMaterial(material); + addMaterial(material); } void MeshPartPayload::updateMeshPart(const std::shared_ptr& drawMesh, int partIndex) { @@ -67,8 +67,12 @@ void MeshPartPayload::updateTransform(const Transform& transform, const Transfor _worldBound.transform(_drawTransform); } -void MeshPartPayload::updateMaterial(graphics::MaterialPointer drawMaterial) { - _drawMaterial = drawMaterial; +void MeshPartPayload::addMaterial(graphics::MaterialPointer material) { + _drawMaterials.push(material); +} + +void MeshPartPayload::removeMaterial(graphics::MaterialPointer material) { + _drawMaterials.remove(material); } void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits) { @@ -85,8 +89,8 @@ void MeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tagBits) builder.withLayered(); } - if (_drawMaterial) { - auto matKey = _drawMaterial->getKey(); + if (_drawMaterials.top()) { + auto matKey = _drawMaterials.top()->getKey(); if (matKey.isTranslucent()) { builder.withTransparent(); } @@ -105,8 +109,8 @@ Item::Bound MeshPartPayload::getBound() const { ShapeKey MeshPartPayload::getShapeKey() const { graphics::MaterialKey drawMaterialKey; - if (_drawMaterial) { - drawMaterialKey = _drawMaterial->getKey(); + if (_drawMaterials.top()) { + drawMaterialKey = _drawMaterials.top()->getKey(); } ShapeKey::Builder builder; @@ -160,7 +164,7 @@ void MeshPartPayload::render(RenderArgs* args) { bindMesh(batch); // apply material properties - args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing); + args->_shapePipeline->bindMaterial(_drawMaterials.top(), batch, args->_enableTexturing); args->_details._materialSwitches++; // Draw! @@ -252,7 +256,7 @@ void ModelMeshPartPayload::initCache(const ModelPointer& model) { auto networkMaterial = model->getGeometry()->getShapeMaterial(_shapeID); if (networkMaterial) { - _drawMaterial = networkMaterial; + addMaterial(networkMaterial); } } @@ -298,8 +302,8 @@ void ModelMeshPartPayload::updateKey(bool isVisible, bool isLayered, uint8_t tag builder.withDeformed(); } - if (_drawMaterial) { - auto matKey = _drawMaterial->getKey(); + if (_drawMaterials.top()) { + auto matKey = _drawMaterials.top()->getKey(); if (matKey.isTranslucent()) { builder.withTransparent(); } @@ -329,8 +333,8 @@ void ModelMeshPartPayload::setShapeKey(bool invalidateShapeKey, bool isWireframe } graphics::MaterialKey drawMaterialKey; - if (_drawMaterial) { - drawMaterialKey = _drawMaterial->getKey(); + if (_drawMaterials.top()) { + drawMaterialKey = _drawMaterials.top()->getKey(); } bool isTranslucent = drawMaterialKey.isTranslucent(); @@ -411,7 +415,7 @@ void ModelMeshPartPayload::render(RenderArgs* args) { bindMesh(batch); // apply material properties - args->_shapePipeline->bindMaterial(_drawMaterial, batch, args->_enableTexturing); + args->_shapePipeline->bindMaterial(_drawMaterials.top(), batch, args->_enableTexturing); args->_details._materialSwitches++; // Draw! diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b9ae47fb6a..e6893f1ea7 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -39,8 +39,6 @@ public: virtual void notifyLocationChanged() {} void updateTransform(const Transform& transform, const Transform& offsetTransform); - virtual void updateMaterial(graphics::MaterialPointer drawMaterial); - // Render Item interface virtual render::ItemKey getKey() const; virtual render::Item::Bound getBound() const; @@ -63,13 +61,16 @@ public: mutable graphics::Box _worldBound; std::shared_ptr _drawMesh; - std::shared_ptr _drawMaterial; + graphics::MultiMaterial _drawMaterials; graphics::Mesh::Part _drawPart; size_t getVerticesCount() const { return _drawMesh ? _drawMesh->getNumVertices() : 0; } - size_t getMaterialTextureSize() { return _drawMaterial ? _drawMaterial->getTextureSize() : 0; } - int getMaterialTextureCount() { return _drawMaterial ? _drawMaterial->getTextureCount() : 0; } - bool hasTextureInfo() const { return _drawMaterial ? _drawMaterial->hasTextureInfo() : false; } + size_t getMaterialTextureSize() { return _drawMaterials.top() ? _drawMaterials.top()->getTextureSize() : 0; } + int getMaterialTextureCount() { return _drawMaterials.top() ? _drawMaterials.top()->getTextureCount() : 0; } + bool hasTextureInfo() const { return _drawMaterials.top() ? _drawMaterials.top()->hasTextureInfo() : false; } + + void addMaterial(graphics::MaterialPointer material); + void removeMaterial(graphics::MaterialPointer material); protected: render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index b9ccc28c01..805995edfb 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1524,6 +1524,50 @@ bool Model::isRenderable() const { return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty()); } +void Model::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { + if (shapeID < _modelMeshRenderItemIDs.size()) { + render::Transaction transaction; + auto itemID = _modelMeshRenderItemIDs[shapeID]; + bool visible = isVisible(); + uint8_t viewTagBits = getViewTagBits(); + bool layeredInFront = isLayeredInFront(); + bool layeredInHUD = isLayeredInHUD(); + bool wireframe = isWireframe(); + auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; + bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, + invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { + data.addMaterial(material); + // if the material changed, we might need to update our item key or shape key + data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); + data.setShapeKey(invalidatePayloadShapeKey, wireframe); + }); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); + } +} + +void Model::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { + if (shapeID < _modelMeshRenderItemIDs.size()) { + render::Transaction transaction; + auto itemID = _modelMeshRenderItemIDs[shapeID]; + bool visible = isVisible(); + uint8_t viewTagBits = getViewTagBits(); + bool layeredInFront = isLayeredInFront(); + bool layeredInHUD = isLayeredInHUD(); + bool wireframe = isWireframe(); + auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; + bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, + invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { + data.removeMaterial(material); + // if the material changed, we might need to update our item key or shape key + data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); + data.setShapeKey(invalidatePayloadShapeKey, wireframe); + }); + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); + } +} + class CollisionRenderGeometry : public Geometry { public: CollisionRenderGeometry(graphics::MeshPointer mesh) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index ca0904f334..80067aff2a 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -318,6 +318,9 @@ public: void scaleToFit(); + void addMaterial(graphics::MaterialPointer material, quint16 shapeID); + void removeMaterial(graphics::MaterialPointer material, quint16 shapeID); + public slots: void loadURLFinished(bool success); diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 1763713831..6196a4c5d4 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -342,7 +342,7 @@ var toolBar = (function () { var buttonHandlers = {}; // only used to tablet mode - function addButton(name, image, handler) { + function addButton(name, handler) { buttonHandlers[name] = handler; } @@ -399,7 +399,7 @@ var toolBar = (function () { function handleNewMaterialDialogResult(result) { if (result) { - var json = result.textInput; + var materialURL = result.textInput; var materialMode; switch (result.comboBox) { case MATERIAL_MODE_PROJECTED: @@ -409,11 +409,13 @@ var toolBar = (function () { shapeType = "uv"; } - if (json) { + var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1; + if (materialURL) { createNewEntity({ type: "Material", - materialURL: json, - materialMode: materialMode + materialURL: materialURL, + materialMode: materialMode, + priority: DEFAULT_LAYERED_MATERIAL_PRIORITY }); } } @@ -475,32 +477,22 @@ var toolBar = (function () { that.toggle(); }); - addButton("importEntitiesButton", "assets-01.svg", function() { + addButton("importEntitiesButton", function() { Window.browseChanged.connect(onFileOpenChanged); Window.browseAsync("Select Model to Import", "", "*.json"); }); - addButton("openAssetBrowserButton", "assets-01.svg", function() { + addButton("openAssetBrowserButton", function() { Window.showAssetServer(); }); - addButton("newModelButton", "model-01.svg", function () { - - 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; - + addButton("newModelButton", function () { // tablet version of new-model dialog var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); tablet.pushOntoStack("hifi/tablet/NewModelDialog.qml"); }); - addButton("newCubeButton", "cube-01.svg", function () { + addButton("newCubeButton", function () { createNewEntity({ type: "Box", dimensions: DEFAULT_DIMENSIONS, @@ -512,7 +504,7 @@ var toolBar = (function () { }); }); - addButton("newSphereButton", "sphere-01.svg", function () { + addButton("newSphereButton", function () { createNewEntity({ type: "Sphere", dimensions: DEFAULT_DIMENSIONS, @@ -524,7 +516,7 @@ var toolBar = (function () { }); }); - addButton("newLightButton", "light-01.svg", function () { + addButton("newLightButton", function () { createNewEntity({ type: "Light", dimensions: DEFAULT_LIGHT_DIMENSIONS, @@ -543,7 +535,7 @@ var toolBar = (function () { }); }); - addButton("newTextButton", "text-01.svg", function () { + addButton("newTextButton", function () { createNewEntity({ type: "Text", dimensions: { @@ -566,7 +558,7 @@ var toolBar = (function () { }); }); - addButton("newWebButton", "web-01.svg", function () { + addButton("newWebButton", function () { createNewEntity({ type: "Web", dimensions: { @@ -578,7 +570,7 @@ var toolBar = (function () { }); }); - addButton("newZoneButton", "zone-01.svg", function () { + addButton("newZoneButton", function () { createNewEntity({ type: "Zone", dimensions: { @@ -589,7 +581,7 @@ var toolBar = (function () { }); }); - addButton("newParticleButton", "particle-01.svg", function () { + addButton("newParticleButton", function () { createNewEntity({ type: "ParticleEffect", isEmitting: true, @@ -642,15 +634,10 @@ var toolBar = (function () { }); }); - addButton("newMaterialButton", "model-01.svg", function () { - var MATERIAL_MODES = []; - MATERIAL_MODES[MATERIAL_MODE_UV] = "UV space material"; - MATERIAL_MODES[MATERIAL_MODE_PROJECTED] = "3D projected material"; - var MATERIAL_MODE_DEFAULT = MATERIAL_MODE_UV; - + addButton("newMaterialButton", function () { // tablet version of new material dialog var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - tablet.pushOntoStack("NewMaterialDialog.qml"); + tablet.pushOntoStack("hifi/tablet/NewMaterialDialog.qml"); }); that.setActive(false); diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 96084f355f..dd266311ea 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -645,14 +645,14 @@ hr { margin-left: 10px; } -.text label, .url label, .number label, .textarea label, .rgb label, .xyz label, .pyr label, .dropdown label, .gen label { +.text label, .url label, .number label, .textarea label, .xy label, .wh label, .rgb label, .xyz label,.pyr label, .dropdown label, .gen label { float: left; margin-left: 1px; margin-bottom: 3px; margin-top: -2px; } -.text legend, .url legend, .number legend, .textarea legend, .rgb legend, .xyz legend, .pyr legend, .dropdown legend, .gen legend { +.text legend, .url legend, .number legend, .textarea legend, .xy legend, .wh legend, .rgb legend, .xyz legend, .pyr legend, .dropdown legend, .gen legend { float: left; margin-left: 1px; margin-bottom: 3px; @@ -667,7 +667,7 @@ hr { clear: both; float: left; } -.xyz > div, .pyr > div, .gen > div { +.xy > div, .wh > div, .xyz > div, .pyr > div, .gen > div { clear: both; } @@ -841,6 +841,12 @@ div.refresh input[type="button"] { margin-right: -6px; } +.xy .tuple input { + padding-left: 25px; +} +.wh .tuple input { + padding-left: 45px; +} .rgb .tuple input { padding-left: 65px; } diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 93d22180c9..348d93d589 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -787,7 +787,7 @@
- +
@@ -795,13 +795,26 @@
-
- -
-
-
-
-
+
+
+ +
+
+
+
+ +
+ +
+
+
+
+ +
+ + +
+
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 64f706ce1f..3558a36c04 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -25,7 +25,7 @@ var ICON_FOR_TYPE = { PolyVox: "", Multiple: "", PolyLine: "", - Material: "" + Material: "" }; var EDITOR_TIMEOUT_DURATION = 1500; @@ -167,6 +167,17 @@ function createEmitGroupTextPropertyUpdateFunction(group, propertyName) { }; } +function createEmitVec2PropertyUpdateFunction(property, elX, elY) { + return function () { + var properties = {}; + properties[property] = { + x: elX.value, + y: elY.value + }; + updateProperties(properties); + }; +} + function createEmitVec3PropertyUpdateFunction(property, elX, elY, elZ) { return function() { var properties = {}; @@ -192,19 +203,6 @@ function createEmitGroupVec3PropertyUpdateFunction(group, property, elX, elY, el }; } -function createEmitVec4PropertyUpdateFunction(property, elX, elY, elZ, elW) { - return function () { - var properties = {}; - properties[property] = { - x: elX.value, - y: elY.value, - z: elZ.value, - w: elW.value - }; - updateProperties(properties); - }; -} - function createEmitVec3PropertyUpdateFunctionWithMultiplier(property, elX, elY, elZ, multiplier) { return function() { var properties = {}; @@ -638,10 +636,11 @@ function loaded() { var elBlendFactor = document.getElementById("property-blend-factor"); var elPriority = document.getElementById("property-priority"); var elShapeID = document.getElementById("property-shape-id"); - var elMaterialBoundsX = document.getElementById("property-material-bounds-x"); - var elMaterialBoundsY = document.getElementById("property-material-bounds-y"); - var elMaterialBoundsZ = document.getElementById("property-material-bounds-z"); - var elMaterialBoundsW = document.getElementById("property-material-bounds-w"); + var elMaterialPosX = document.getElementById("property-material-pos-x"); + var elMaterialPosY = document.getElementById("property-material-pos-y"); + var elMaterialScaleX = document.getElementById("property-material-scale-x"); + var elMaterialScaleY = document.getElementById("property-material-scale-y"); + var elMaterialRot = document.getElementById("property-material-rot"); var elWebSourceURL = document.getElementById("property-web-source-url"); var elWebDPI = document.getElementById("property-web-dpi"); @@ -1134,10 +1133,11 @@ function loaded() { elBlendFactor.value = properties.blendFactor.toFixed(2); elPriority.value = properties.priority; elShapeID.value = properties.shapeID; - elMaterialBoundsX.value = properties.materialBounds.x.toFixed(2); - elMaterialBoundsY.value = properties.materialBounds.y.toFixed(2); - elMaterialBoundsZ.value = properties.materialBounds.z.toFixed(2); - //elMaterialBoundsW.value = properties.materialBounds.w.toFixed(2); + elMaterialPosX.value = properties.materialPos.x.toFixed(4); + elMaterialPosY.value = properties.materialPos.y.toFixed(4); + elMaterialScaleX.value = properties.materialScale.x.toFixed(4); + elMaterialScaleY.value = properties.materialScale.y.toFixed(4); + elMaterialRot.value = properties.materialRot.toFixed(2); } if (properties.locked) { @@ -1411,15 +1411,16 @@ function loaded() { elMaterialURL.addEventListener('change', createEmitTextPropertyUpdateFunction('materialURL')); elMaterialMode.addEventListener('change', createEmitTextPropertyUpdateFunction('materialMode')); elBlendFactor.addEventListener('change', createEmitNumberPropertyUpdateFunction('blendFactor', 2)); - elPriority.addEventListener('change', createEmitNumberPropertyUpdateFunction('priority')); - elShapeID.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeID')); + elPriority.addEventListener('change', createEmitNumberPropertyUpdateFunction('priority', 0)); + elShapeID.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeID', 0)); - var materialBoundsChangeFunction = createEmitVec4PropertyUpdateFunction('materialBounds', - elMaterialBoundsX, elMaterialBoundsY, elMaterialBoundsZ, elMaterialBoundsW); - elMaterialBoundsX.addEventListener('change', materialBoundsChangeFunction); - elMaterialBoundsY.addEventListener('change', materialBoundsChangeFunction); - elMaterialBoundsZ.addEventListener('change', materialBoundsChangeFunction); - elMaterialBoundsW.addEventListener('change', materialBoundsChangeFunction); + var materialPosChangeFunction = createEmitVec2PropertyUpdateFunction('materialPos', elMaterialPosX, elMaterialPosY); + elMaterialPosX.addEventListener('change', materialPosChangeFunction); + elMaterialPosY.addEventListener('change', materialPosChangeFunction); + var materialScaleChangeFunction = createEmitVec2PropertyUpdateFunction('materialScale', elMaterialScaleX, elMaterialScaleY); + elMaterialScaleX.addEventListener('change', materialScaleChangeFunction); + elMaterialScaleY.addEventListener('change', materialScaleChangeFunction); + elMaterialRot.addEventListener('change', createEmitNumberPropertyUpdateFunction('materialRot', 2)); elTextText.addEventListener('change', createEmitTextPropertyUpdateFunction('text')); elTextFaceCamera.addEventListener('change', createEmitCheckedPropertyUpdateFunction('faceCamera')); diff --git a/tools/jsdoc/package-lock.json b/tools/jsdoc/package-lock.json new file mode 100644 index 0000000000..073bbf60f6 --- /dev/null +++ b/tools/jsdoc/package-lock.json @@ -0,0 +1,138 @@ +{ + "name": "hifiJSDoc", + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "babylon": { + "version": "7.0.0-beta.19", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-7.0.0-beta.19.tgz", + "integrity": "sha512-Vg0C9s/REX6/WIXN37UKpv5ZhRi6A4pjHlpkE34+8/a6c2W1Q692n3hmc+SZG5lKRnaExLUbxtJ1SVT+KaCQ/A==" + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "catharsis": { + "version": "0.8.9", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.8.9.tgz", + "integrity": "sha1-mMyJDKZS3S7w5ws3klMQ/56Q/Is=", + "requires": { + "underscore-contrib": "0.3.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "js2xmlparser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-3.0.0.tgz", + "integrity": "sha1-P7YOqgicVED5MZ9RdgzNB+JJlzM=", + "requires": { + "xmlcreate": "1.0.2" + } + }, + "jsdoc": { + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-3.5.5.tgz", + "integrity": "sha512-6PxB65TAU4WO0Wzyr/4/YhlGovXl0EVYfpKbpSroSj0qBxT4/xod/l40Opkm38dRHRdQgdeY836M0uVnJQG7kg==", + "requires": { + "babylon": "7.0.0-beta.19", + "bluebird": "3.5.1", + "catharsis": "0.8.9", + "escape-string-regexp": "1.0.5", + "js2xmlparser": "3.0.0", + "klaw": "2.0.0", + "marked": "0.3.12", + "mkdirp": "0.5.1", + "requizzle": "0.2.1", + "strip-json-comments": "2.0.1", + "taffydb": "2.6.2", + "underscore": "1.8.3" + } + }, + "klaw": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-2.0.0.tgz", + "integrity": "sha1-WcEo4Nxc5BAgEVEZTuucv4WGUPY=", + "requires": { + "graceful-fs": "4.1.11" + } + }, + "marked": { + "version": "0.3.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.12.tgz", + "integrity": "sha512-k4NaW+vS7ytQn6MgJn3fYpQt20/mOgYM5Ft9BYMfQJDz2QT6yEeS9XJ8k2Nw8JTeWK/znPPW2n3UJGzyYEiMoA==" + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "requizzle": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.1.tgz", + "integrity": "sha1-aUPDUwxNmn5G8c3dUcFY/GcM294=", + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "taffydb": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.6.2.tgz", + "integrity": "sha1-fLy2S1oUG2ou/CxdLGe04VCyomg=" + }, + "underscore": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", + "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" + }, + "underscore-contrib": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/underscore-contrib/-/underscore-contrib-0.3.0.tgz", + "integrity": "sha1-ZltmwkeD+PorGMn4y7Dix9SMJsc=", + "requires": { + "underscore": "1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "xmlcreate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-1.0.2.tgz", + "integrity": "sha1-+mv3YqYKQT+z3Y9LA8WyaSONMI8=" + } + } +} From ff0b63297883a34624adaea0953078a13b3064b9 Mon Sep 17 00:00:00 2001 From: David Back Date: Thu, 8 Feb 2018 19:31:24 -0800 Subject: [PATCH 10/53] get avatars in range --- libraries/avatars/src/AvatarHashMap.cpp | 14 ++++++++++++++ libraries/avatars/src/AvatarHashMap.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index 61b13d7749..c2e84f6e16 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -30,6 +30,20 @@ QVector AvatarHashMap::getAvatarIdentifiers() { return _avatarHash.keys().toVector(); } +QVector AvatarHashMap::getAvatarsInRange(const glm::vec3& position, float rangeMeters) const { + auto hashCopy = getHashCopy(); + QVector avatarsInRange; + auto rangeMeters2 = rangeMeters * rangeMeters; + for (const AvatarSharedPointer& sharedAvatar : hashCopy) { + glm::vec3 avatarPosition = sharedAvatar->getWorldPosition(); + auto distance2 = glm::distance2(avatarPosition, position); + if (distance2 < rangeMeters2) { + avatarsInRange.push_back(sharedAvatar->getSessionUUID()); + } + } + return avatarsInRange; +} + bool AvatarHashMap::isAvatarInRange(const glm::vec3& position, const float range) { auto hashCopy = getHashCopy(); foreach(const AvatarSharedPointer& sharedAvatar, hashCopy) { diff --git a/libraries/avatars/src/AvatarHashMap.h b/libraries/avatars/src/AvatarHashMap.h index 68fc232685..e4a485028f 100644 --- a/libraries/avatars/src/AvatarHashMap.h +++ b/libraries/avatars/src/AvatarHashMap.h @@ -35,10 +35,12 @@ class AvatarHashMap : public QObject, public Dependency { public: AvatarHash getHashCopy() { QReadLocker lock(&_hashLock); return _avatarHash; } + const AvatarHash getHashCopy() const { QReadLocker lock(&_hashLock); return _avatarHash; } int size() { return _avatarHash.size(); } // Currently, your own avatar will be included as the null avatar id. Q_INVOKABLE QVector getAvatarIdentifiers(); + Q_INVOKABLE QVector getAvatarsInRange(const glm::vec3& position, float rangeMeters) const; // Null/Default-constructed QUuids will return MyAvatar Q_INVOKABLE virtual ScriptAvatarData* getAvatar(QUuid avatarID) { return new ScriptAvatarData(getAvatarBySessionID(avatarID)); } From dc92250b1afc70233a272fdc8e135e8b1eec5673 Mon Sep 17 00:00:00 2001 From: David Back Date: Fri, 9 Feb 2018 14:59:08 -0800 Subject: [PATCH 11/53] change var names --- libraries/avatars/src/AvatarHashMap.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/avatars/src/AvatarHashMap.cpp b/libraries/avatars/src/AvatarHashMap.cpp index c2e84f6e16..b564ad6a3b 100644 --- a/libraries/avatars/src/AvatarHashMap.cpp +++ b/libraries/avatars/src/AvatarHashMap.cpp @@ -33,11 +33,11 @@ QVector AvatarHashMap::getAvatarIdentifiers() { QVector AvatarHashMap::getAvatarsInRange(const glm::vec3& position, float rangeMeters) const { auto hashCopy = getHashCopy(); QVector avatarsInRange; - auto rangeMeters2 = rangeMeters * rangeMeters; + auto rangeMetersSquared = rangeMeters * rangeMeters; for (const AvatarSharedPointer& sharedAvatar : hashCopy) { glm::vec3 avatarPosition = sharedAvatar->getWorldPosition(); - auto distance2 = glm::distance2(avatarPosition, position); - if (distance2 < rangeMeters2) { + auto distanceSquared = glm::distance2(avatarPosition, position); + if (distanceSquared < rangeMetersSquared) { avatarsInRange.push_back(sharedAvatar->getSessionUUID()); } } From f95893f070a0552b1fd30ec7b5de1fea3018d8dc Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 12 Feb 2018 11:09:10 -0800 Subject: [PATCH 12/53] updates to electron-packager and node-notifier for CVEs --- server-console/package-lock.json | 1288 ++++++++++++++++++++---------- server-console/package.json | 4 +- 2 files changed, 851 insertions(+), 441 deletions(-) diff --git a/server-console/package-lock.json b/server-console/package-lock.json index 51b7f2c268..ba8ef3c720 100644 --- a/server-console/package-lock.json +++ b/server-console/package-lock.json @@ -5,11 +5,23 @@ "requires": true, "dependencies": { "abbrev": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.7.tgz", - "integrity": "sha1-W2A1su6dT7XPhZ8Iqb6BsghJGEM=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" + } + }, "always-tail": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/always-tail/-/always-tail-0.2.0.tgz", @@ -28,10 +40,11 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, - "ansicolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansicolors/-/ansicolors-0.2.1.tgz", - "integrity": "sha1-vgiVmQl7dKXJxKhKDNvNtivYeu8=" + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=", + "dev": true }, "array-find-index": { "version": "1.0.1", @@ -40,20 +53,37 @@ "dev": true }, "asar": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/asar/-/asar-0.11.0.tgz", - "integrity": "sha1-uSbnksMV+MBIxDNx4yWwnJenZGQ=", + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/asar/-/asar-0.14.2.tgz", + "integrity": "sha512-eKo4ywQDq9dC/0Pu6UJsX4PxNi5ZlC4/NQ1JORUW4xkMRrEWpoLPpkngmQ6K7ZkioVjE2ZafLMmHPAQKMO0BdA==", "dev": true, "requires": { - "chromium-pickle-js": "0.1.0", + "chromium-pickle-js": "0.2.0", "commander": "2.9.0", - "cuint": "0.2.1", + "cuint": "0.2.2", "glob": "6.0.4", - "minimatch": "3.0.0", + "minimatch": "3.0.4", "mkdirp": "0.5.1", - "mksnapshot": "0.3.0" + "mksnapshot": "0.3.1", + "tmp": "0.0.28" }, "dependencies": { + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, "glob": { "version": "6.0.4", "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", @@ -62,10 +92,19 @@ "requires": { "inflight": "1.0.4", "inherits": "2.0.1", - "minimatch": "3.0.0", + "minimatch": "3.0.4", "once": "1.3.3", "path-is-absolute": "1.0.0" } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.11" + } } } }, @@ -84,6 +123,18 @@ "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "author-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz", + "integrity": "sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA=", + "dev": true + }, "aws-sign2": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", @@ -103,9 +154,9 @@ "integrity": "sha1-qRzdHr7xqGZZ5w/03vAWJfwtZ1Y=" }, "base64-js": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.8.tgz", - "integrity": "sha1-EQHpVE9KdrG8OybUUsqW16NeeXg=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.0.tgz", + "integrity": "sha1-o5mS1yNYSBGYK+XikLtqU9hnAPE=", "dev": true }, "binary": { @@ -147,9 +198,9 @@ } }, "bluebird": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.10.2.tgz", - "integrity": "sha1-AkpVFylTCIV/FPkfEQb8O1VfRGs=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", "dev": true }, "boolbase": { @@ -201,15 +252,6 @@ "map-obj": "1.0.1" } }, - "cardinal": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cardinal/-/cardinal-0.5.0.tgz", - "integrity": "sha1-ANX2YdvUqr/ffUHOSKWlm8o1opE=", - "requires": { - "ansicolors": "0.2.1", - "redeyed": "0.5.0" - } - }, "caseless": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.11.0.tgz", @@ -249,36 +291,11 @@ } }, "chromium-pickle-js": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.1.0.tgz", - "integrity": "sha1-HUixB9ghJqLz4hHC6iX4A7pVGyE=", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha1-BKEGZywYsIWrd02YPfo+oTjyIgU=", "dev": true }, - "cli-table": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.1.tgz", - "integrity": "sha1-9TsFJmqLGguTSz0IIebi3FkUriM=", - "requires": { - "colors": "1.0.3" - } - }, - "cli-usage": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/cli-usage/-/cli-usage-0.1.2.tgz", - "integrity": "sha1-SXwg6vEuwneTk6m/rCJcX2y5FS0=", - "requires": { - "marked": "0.3.5", - "marked-terminal": "1.6.1", - "minimist": "0.2.0" - }, - "dependencies": { - "minimist": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=" - } - } - }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -289,6 +306,12 @@ "wrap-ansi": "2.0.0" } }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, "code-point-at": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.0.0.tgz", @@ -297,11 +320,6 @@ "number-is-nan": "1.0.0" } }, - "colors": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", - "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" - }, "combined-stream": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", @@ -318,6 +336,12 @@ "graceful-readlink": "1.0.1" } }, + "compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha1-AWLsLZNR9d3VmpICy6k1NmpyUIA=", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -385,16 +409,10 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-1.0.0.tgz", "integrity": "sha1-18wt9FGAZm+Z0rFEYmOUaeAPc2w=" }, - "ctype": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", - "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=", - "dev": true - }, "cuint": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.1.tgz", - "integrity": "sha1-VlBFzoEnxwxr80D1kcAEin1M/rw=", + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz", + "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", "dev": true }, "dashdash": { @@ -432,7 +450,7 @@ "graceful-fs": "4.1.3", "mkpath": "0.1.0", "nopt": "3.0.6", - "q": "1.4.1", + "q": "1.5.1", "readable-stream": "1.1.14", "touch": "0.0.3" } @@ -527,37 +545,205 @@ "integrity": "sha1-DboCXtM9DkW/j0DG6b487i+YbCg=" }, "electron-osx-sign": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.3.0.tgz", - "integrity": "sha1-SXIB38g1OMVLNPGkBexuIaAf904=", + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.4.8.tgz", + "integrity": "sha1-8Ln63e2eHlTsNfqJh3tcbDTHvEA=", "dev": true, "requires": { + "bluebird": "3.5.1", + "compare-version": "0.1.2", + "debug": "2.6.9", + "isbinaryfile": "3.0.2", "minimist": "1.2.0", - "run-series": "1.1.4" + "plist": "2.1.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "electron-packager": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-6.0.2.tgz", - "integrity": "sha1-juAGaf6KNjCVAnMvz+0RfX7prCk=", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/electron-packager/-/electron-packager-11.0.0.tgz", + "integrity": "sha512-ufyYMe3Gt6IEZm9RuG+KK3Nh+V2jZHWg9gihp8wylUNtleQihECIXtQdpPJxH9740XFERVPraNEaa7cZvDzpyw==", "dev": true, "requires": { - "asar": "0.11.0", - "electron-download": "2.1.1", - "electron-osx-sign": "0.3.0", + "asar": "0.14.2", + "debug": "3.1.0", + "electron-download": "4.1.0", + "electron-osx-sign": "0.4.8", "extract-zip": "1.5.0", - "fs-extra": "0.26.7", - "get-package-info": "0.0.2", - "minimist": "1.2.0", - "mkdirp": "0.5.1", - "mv": "2.1.1", - "ncp": "2.0.0", - "object-assign": "4.0.1", - "plist": "1.2.0", - "rcedit": "0.5.0", - "resolve": "1.1.7", - "rimraf": "2.5.2", - "run-series": "1.1.4" + "fs-extra": "5.0.0", + "get-package-info": "1.0.0", + "mz": "2.7.0", + "nodeify": "1.0.1", + "parse-author": "2.0.0", + "pify": "3.0.0", + "plist": "2.1.0", + "pruner": "0.0.7", + "rcedit": "0.9.0", + "resolve": "1.5.0", + "sanitize-filename": "1.6.1", + "semver": "5.5.0", + "yargs-parser": "8.1.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "electron-download": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/electron-download/-/electron-download-4.1.0.tgz", + "integrity": "sha1-v5MsdG8vh//MCdHdRy8v9rkYeEU=", + "dev": true, + "requires": { + "debug": "2.6.9", + "env-paths": "1.0.0", + "fs-extra": "2.1.2", + "minimist": "1.2.0", + "nugget": "2.0.1", + "path-exists": "3.0.0", + "rc": "1.1.6", + "semver": "5.5.0", + "sumchecker": "2.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "fs-extra": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-2.1.2.tgz", + "integrity": "sha1-BGxwFjzvmq1GsOSn+kZ/si1x3jU=", + "dev": true, + "requires": { + "graceful-fs": "4.1.3", + "jsonfile": "2.2.3" + } + } + } + }, + "fs-extra": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "dev": true, + "requires": { + "graceful-fs": "4.1.3", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + }, + "dependencies": { + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "nugget": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/nugget/-/nugget-2.0.1.tgz", + "integrity": "sha1-IBCVpIfhrTYIGzQy+jytpPjQcbA=", + "dev": true, + "requires": { + "debug": "2.6.9", + "minimist": "1.2.0", + "pretty-bytes": "1.0.4", + "progress-stream": "1.2.0", + "request": "2.71.0", + "single-line-log": "1.1.2", + "throttleit": "0.0.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "single-line-log": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/single-line-log/-/single-line-log-1.1.2.tgz", + "integrity": "sha1-wvg/Jzo+GhbtsJlWYdoO1e8DM2Q=", + "dev": true, + "requires": { + "string-width": "1.0.1" + } + }, + "throttleit": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-0.0.2.tgz", + "integrity": "sha1-z+34jmDADdlpe2H90qg0OptoDq8=", + "dev": true + } } }, "electron-prebuilt": { @@ -583,6 +769,12 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" }, + "env-paths": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-1.0.0.tgz", + "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=", + "dev": true + }, "error-ex": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.0.tgz", @@ -597,11 +789,6 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "esprima-fb": { - "version": "12001.1.0-dev-harmony-fb", - "resolved": "https://registry.npmjs.org/esprima-fb/-/esprima-fb-12001.1.0-dev-harmony-fb.tgz", - "integrity": "sha1-2EQAOEupXOJnjGF60kp/QICNqRU=" - }, "extend": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", @@ -641,6 +828,18 @@ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz", "integrity": "sha1-4QgOBljjALBilJkMxw4VAiNf1VA=" }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, "fd-slicer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", @@ -712,20 +911,87 @@ } }, "get-package-info": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-0.0.2.tgz", - "integrity": "sha1-csOPvuLnZyhCSgDcFOJN0aKMI5E=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-package-info/-/get-package-info-1.0.0.tgz", + "integrity": "sha1-ZDJ5ZWPigRPNlHTbvQAFKYWkmZw=", "dev": true, "requires": { - "bluebird": "3.3.5", - "lodash.get": "4.2.1", - "resolve": "1.1.7" + "bluebird": "3.5.1", + "debug": "2.6.9", + "lodash.get": "4.4.2", + "read-pkg-up": "2.0.0" }, "dependencies": { - "bluebird": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.3.5.tgz", - "integrity": "sha1-XudH8ce9lnZYtoOTZDCu51OVWjQ=", + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.3", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.3.5", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", "dev": true } } @@ -763,6 +1029,12 @@ "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", "integrity": "sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE=" }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, "har-validator": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", @@ -893,14 +1165,6 @@ "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" }, - "is-absolute": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", - "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", - "requires": { - "is-relative": "0.1.3" - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -944,16 +1208,17 @@ "xtend": "4.0.1" } }, + "is-promise": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", + "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=", + "dev": true + }, "is-property": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" }, - "is-relative": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", - "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=" - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -970,10 +1235,16 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, + "isbinaryfile": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.2.tgz", + "integrity": "sha1-Sj6XTsDLqQBNP8bN5yCeppNopiE=", + "dev": true + }, "isexe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-1.1.2.tgz", - "integrity": "sha1-NvPiLmB1CSD15yQaR2qMakInWtA=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" }, "isstream": { "version": "0.1.2", @@ -1000,6 +1271,12 @@ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz", "integrity": "sha1-UDVPGfYDkXxpX3C4Wvp3w7DyNQY=" }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", @@ -1051,136 +1328,34 @@ "strip-bom": "2.0.0" } }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "2.0.0", + "path-exists": "3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, "lodash": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" }, - "lodash._arraycopy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arraycopy/-/lodash._arraycopy-3.0.0.tgz", - "integrity": "sha1-due3wfH7klRzdIeKVi7Qaj5Q9uE=" - }, - "lodash._arrayeach": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._arrayeach/-/lodash._arrayeach-3.0.0.tgz", - "integrity": "sha1-urFWsqkNPxu9XGU0AzSeXlkz754=" - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" - } - }, - "lodash._baseclone": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lodash._baseclone/-/lodash._baseclone-3.3.0.tgz", - "integrity": "sha1-MDUZv2OT/n5C802LYw73eU41Qrc=", - "requires": { - "lodash._arraycopy": "3.0.0", - "lodash._arrayeach": "3.0.0", - "lodash._baseassign": "3.2.0", - "lodash._basefor": "3.0.3", - "lodash.isarray": "3.0.4", - "lodash.keys": "3.1.2" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=" - }, - "lodash._basefor": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basefor/-/lodash._basefor-3.0.3.tgz", - "integrity": "sha1-dVC06SGO8J+tJDQ7YSAhx5tMIMI=" - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" - }, - "lodash._createassigner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", - "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", - "requires": { - "lodash._bindcallback": "3.0.1", - "lodash._isiterateecall": "3.0.9", - "lodash.restparam": "3.6.1" - } - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=" - }, - "lodash._stringtopath": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/lodash._stringtopath/-/lodash._stringtopath-4.7.1.tgz", - "integrity": "sha1-1GYKFaWZeYj6WTAaO/2gXJpt494=", - "dev": true - }, - "lodash.assign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", - "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", - "requires": { - "lodash._baseassign": "3.2.0", - "lodash._createassigner": "3.1.1", - "lodash.keys": "3.1.2" - } - }, - "lodash.clonedeep": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-3.0.2.tgz", - "integrity": "sha1-oKHkDYKl6on/WxR7hETtY9koJ9s=", - "requires": { - "lodash._baseclone": "3.3.0", - "lodash._bindcallback": "3.0.1" - } - }, "lodash.get": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.2.1.tgz", - "integrity": "sha1-bpr8h7imwCFgZnpw9sjOEHiusRs=", - "dev": true, - "requires": { - "lodash._stringtopath": "4.7.1" - } - }, - "lodash.isarguments": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.0.8.tgz", - "integrity": "sha1-W/jaiH8B8qnknAoXXNrrMYoOQ9w=" - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=" - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.0.8", - "lodash.isarray": "3.0.4" - } - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true }, "loud-rejection": { "version": "1.3.0", @@ -1207,23 +1382,6 @@ "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", "dev": true }, - "marked": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.5.tgz", - "integrity": "sha1-QROhWsXXvKFYpargciRYe5+hW5Q=" - }, - "marked-terminal": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-1.6.1.tgz", - "integrity": "sha1-BM0cfIsO9I2z9oAQ1zpXqWYcbM8=", - "requires": { - "cardinal": "0.5.0", - "chalk": "1.1.3", - "cli-table": "0.3.1", - "lodash.assign": "3.2.0", - "node-emoji": "0.1.0" - } - }, "meow": { "version": "3.7.0", "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", @@ -1266,7 +1424,8 @@ "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true }, "mkdirp": { "version": "0.5.1", @@ -1290,180 +1449,214 @@ "dev": true }, "mksnapshot": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/mksnapshot/-/mksnapshot-0.3.0.tgz", - "integrity": "sha1-MuqYStb1MjJMaj+uZACHa4WChAc=", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/mksnapshot/-/mksnapshot-0.3.1.tgz", + "integrity": "sha1-JQHAVldDbXQs6Vik/5LHfkDdN+Y=", "dev": true, "requires": { "decompress-zip": "0.3.0", "fs-extra": "0.26.7", - "request": "2.55.0" + "request": "2.83.0" }, "dependencies": { - "asn1": { - "version": "0.1.11", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", - "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", - "dev": true - }, "assert-plus": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", - "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", - "dev": true - }, - "async": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", - "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, "aws-sign2": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", - "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", "dev": true }, - "bl": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz", - "integrity": "sha1-wGt5evCF6gC8Unr8jvzxHeIjIFQ=", + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "dev": true, "requires": { - "readable-stream": "1.0.34" + "hoek": "4.2.0" } }, "caseless": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.9.0.tgz", - "integrity": "sha1-t7Zc5r8UE4hlOc/VM/CzDv+pz4g=", + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "combined-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", - "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", "dev": true, "requires": { - "delayed-stream": "0.0.5" + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + } } }, - "delayed-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", - "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, "form-data": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.2.0.tgz", - "integrity": "sha1-Jvi8JtpkQOKZy9z7aQNcT3em5GY=", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", "dev": true, "requires": { - "async": "0.9.2", - "combined-stream": "0.0.7", - "mime-types": "2.0.14" + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" } }, "har-validator": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-1.8.0.tgz", - "integrity": "sha1-2DhCsOtMQ1lgrrEIoGejqpTA7rI=", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "bluebird": "2.10.2", - "chalk": "1.1.3", - "commander": "2.9.0", - "is-my-json-valid": "2.13.1" + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "hawk": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-2.3.1.tgz", - "integrity": "sha1-HnMc45RH+h0PbXB/e87r7A/R7B8=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.1.0" } }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", + "dev": true + }, "http-signature": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", - "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "asn1": "0.1.11", - "assert-plus": "0.1.5", - "ctype": "0.5.3" + "assert-plus": "1.0.0", + "jsprim": "1.2.2", + "sshpk": "1.7.4" } }, "mime-db": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.12.0.tgz", - "integrity": "sha1-PQxjGA9FjrENMlqqN9fFiuMS6dc=", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", "dev": true }, "mime-types": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.0.14.tgz", - "integrity": "sha1-MQ4VnbI+B3+Lsit0jav6SVcUCqY=", + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { - "mime-db": "1.12.0" + "mime-db": "1.30.0" } }, "oauth-sign": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.6.0.tgz", - "integrity": "sha1-fb6uRPbKRU4fFoRR1jB0ZzWBPOM=", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, "qs": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-2.4.2.tgz", - "integrity": "sha1-9854jld33wtQENp/fE5zujJHD1o=", + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", "dev": true }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.1", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, "request": { - "version": "2.55.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.55.0.tgz", - "integrity": "sha1-11wc32eddrsQD5v/4f5VG1wk6T0=", + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", "dev": true, "requires": { - "aws-sign2": "0.5.0", - "bl": "0.9.5", - "caseless": "0.9.0", - "combined-stream": "0.0.7", + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "0.2.0", - "har-validator": "1.8.0", - "hawk": "2.3.1", - "http-signature": "0.10.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.0.14", - "node-uuid": "1.4.7", - "oauth-sign": "0.6.0", - "qs": "2.4.2", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", "stringstream": "0.0.5", - "tough-cookie": "2.2.2", - "tunnel-agent": "0.4.2" + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" } + }, + "sntp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", + "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "uuid": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "dev": true } } }, @@ -1508,29 +1701,39 @@ } } }, + "mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "requires": { + "any-promise": "1.3.0", + "object-assign": "4.0.1", + "thenify-all": "1.6.0" + } + }, "ncp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=", "dev": true }, - "node-emoji": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-0.1.0.tgz", - "integrity": "sha1-P0QkpVuo7VDCVKE4WLJEVPQYJgI=" - }, "node-notifier": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-4.5.0.tgz", - "integrity": "sha1-Ap7pjXqbxOlsnLUb6dTzYTI/6ps=", + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-5.2.1.tgz", + "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", "requires": { - "cli-usage": "0.1.2", "growly": "1.3.0", - "lodash.clonedeep": "3.0.2", - "minimist": "1.2.0", - "semver": "5.1.0", - "shellwords": "0.1.0", - "which": "1.2.4" + "semver": "5.5.0", + "shellwords": "0.1.1", + "which": "1.3.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" + } } }, "node-uuid": { @@ -1538,13 +1741,23 @@ "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz", "integrity": "sha1-baWhdmjEs91ZYjvaEc9/pMH2Cm8=" }, + "nodeify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nodeify/-/nodeify-1.0.1.tgz", + "integrity": "sha1-ZKtpp7268DzhB7TwM1yHwLnpGx0=", + "dev": true, + "requires": { + "is-promise": "1.0.1", + "promise": "1.3.0" + } + }, "nopt": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.0.7" + "abbrev": "1.1.1" } }, "normalize-package-data": { @@ -1642,6 +1855,45 @@ "lcid": "1.0.0" } }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-limit": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", + "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "dev": true, + "requires": { + "p-try": "1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "1.2.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "parse-author": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz", + "integrity": "sha1-00YL8d3Q367tQtp1QkLmX7aEqB8=", + "dev": true, + "requires": { + "author-regex": "1.0.0" + } + }, "parse-json": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", @@ -1662,6 +1914,12 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.0.tgz", "integrity": "sha1-Jj2tpmqz8vsQv3+dJN2PPlcO+RI=" }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, "path-type": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", @@ -1679,6 +1937,12 @@ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", "dev": true }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -1699,15 +1963,14 @@ } }, "plist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/plist/-/plist-1.2.0.tgz", - "integrity": "sha1-CEtQk93JJQbiWfh0uNmxr7jHlZM=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-2.1.0.tgz", + "integrity": "sha1-V8zbeggh3yGDEhejytVOPhRqECU=", "dev": true, "requires": { - "base64-js": "0.0.8", - "util-deprecate": "1.0.2", - "xmlbuilder": "4.0.0", - "xmldom": "0.1.22" + "base64-js": "1.2.0", + "xmlbuilder": "8.2.2", + "xmldom": "0.1.27" } }, "pretty-bytes": { @@ -1735,6 +1998,55 @@ "through2": "0.2.3" } }, + "promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-1.3.0.tgz", + "integrity": "sha1-5cyaTIJ45GZP/twBx9qEhCsEAXU=", + "dev": true, + "requires": { + "is-promise": "1.0.1" + } + }, + "pruner": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/pruner/-/pruner-0.0.7.tgz", + "integrity": "sha1-NF+8s+gHARY6HXrfVrrCKaWh5ME=", + "dev": true, + "requires": { + "fs-extra": "4.0.3" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "4.1.3", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true, + "optional": true + } + } + } + } + }, "pseudomap": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", @@ -1749,10 +2061,16 @@ "once": "1.3.3" } }, - "q": { + "punycode": { "version": "1.4.1", - "resolved": "https://registry.npmjs.org/q/-/q-1.4.1.tgz", - "integrity": "sha1-VXBbzZPF82c1MMLCy8DCs63cKG4=", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", "dev": true }, "qs": { @@ -1773,9 +2091,9 @@ } }, "rcedit": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-0.5.0.tgz", - "integrity": "sha1-72a1p/AxB1IUGjTiLyPCJDPBzxU=", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/rcedit/-/rcedit-0.9.0.tgz", + "integrity": "sha1-ORDfVzRTmeKwMl9KUZAH+J5V7xw=", "dev": true }, "read-pkg": { @@ -1820,14 +2138,6 @@ "strip-indent": "1.0.1" } }, - "redeyed": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/redeyed/-/redeyed-0.5.0.tgz", - "integrity": "sha1-erAA5g7jh1rBFdKe2zLBQDxsJdE=", - "requires": { - "esprima-fb": "12001.1.0-dev-harmony-fb" - } - }, "request": { "version": "2.71.0", "resolved": "https://registry.npmjs.org/request/-/request-2.71.0.tgz", @@ -1865,10 +2175,13 @@ } }, "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } }, "rimraf": { "version": "2.5.2", @@ -1878,21 +2191,31 @@ "glob": "7.0.3" } }, - "run-series": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.4.tgz", - "integrity": "sha1-iac93F51ye+KtjIMChYA1qQRebk=", + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, + "sanitize-filename": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.1.tgz", + "integrity": "sha1-YS2hyWRz+gLczaktzVtKsWSmdyo=", + "dev": true, + "requires": { + "truncate-utf8-bytes": "1.0.2" + } + }, "semver": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.1.0.tgz", - "integrity": "sha1-hfLPhVBGXE3wAM99hvawVBBqueU=" + "integrity": "sha1-hfLPhVBGXE3wAM99hvawVBBqueU=", + "dev": true }, "shellwords": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.0.tgz", - "integrity": "sha1-Zq/Ue2oSky2Qccv9mKUueFzQuhQ=" + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" }, "signal-exit": { "version": "2.1.2", @@ -2017,6 +2340,32 @@ "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", "dev": true }, + "sumchecker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-2.0.2.tgz", + "integrity": "sha1-D0LBDl0F2l1C7qPlbDOZo31sWz4=", + "dev": true, + "requires": { + "debug": "2.6.9" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -2063,6 +2412,24 @@ } } }, + "thenify": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.0.tgz", + "integrity": "sha1-5p44obq+lpsBCCB5eLn2K4hgSDk=", + "dev": true, + "requires": { + "any-promise": "1.3.0" + } + }, + "thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY=", + "dev": true, + "requires": { + "thenify": "3.3.0" + } + }, "throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", @@ -2089,6 +2456,15 @@ } } }, + "tmp": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.28.tgz", + "integrity": "sha1-Fyc1t/YU6nrzlmT6hM8N5OUV0SA=", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, "touch": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/touch/-/touch-0.0.3.tgz", @@ -2104,7 +2480,7 @@ "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", "dev": true, "requires": { - "abbrev": "1.0.7" + "abbrev": "1.1.1" } } } @@ -2126,6 +2502,15 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "dev": true, + "requires": { + "utf8-byte-length": "1.0.4" + } + }, "tunnel-agent": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.2.tgz", @@ -2143,6 +2528,18 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "dev": true + }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=", + "dev": true + }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2167,12 +2564,11 @@ } }, "which": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/which/-/which-1.2.4.tgz", - "integrity": "sha1-FVf5YIBgTlsRs1meufRbUKnv1yI=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "requires": { - "is-absolute": "0.1.7", - "isexe": "1.1.2" + "isexe": "2.0.0" } }, "window-size": { @@ -2194,18 +2590,15 @@ "integrity": "sha1-HmWWmWXMvC20VIxrhKbyxa7dRzk=" }, "xmlbuilder": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.0.0.tgz", - "integrity": "sha1-mLj2UcowqmJANvEn0RzGbce5B6M=", - "dev": true, - "requires": { - "lodash": "3.10.1" - } + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", + "integrity": "sha1-aSSGc0ELS6QuGmE2VR0pIjNap3M=", + "dev": true }, "xmldom": { - "version": "0.1.22", - "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.22.tgz", - "integrity": "sha1-EN5OXpZJgfA8jMcvrcCNFLbDqiY=", + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz", + "integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk=", "dev": true }, "xtend": { @@ -2237,6 +2630,23 @@ "y18n": "3.2.1" } }, + "yargs-parser": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-8.1.0.tgz", + "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", + "dev": true, + "requires": { + "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, "yauzl": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", diff --git a/server-console/package.json b/server-console/package.json index 8d2a177e0a..9f47d0e4cc 100644 --- a/server-console/package.json +++ b/server-console/package.json @@ -8,7 +8,7 @@ "" ], "devDependencies": { - "electron-packager": "^6.0.2", + "electron-packager": "^11.0.0", "electron-prebuilt": "0.37.5" }, "repository": { @@ -27,7 +27,7 @@ "cheerio": "^0.19.0", "extend": "^3.0.0", "fs-extra": "^0.26.4", - "node-notifier": "^4.4.0", + "node-notifier": "^5.2.1", "os-homedir": "^1.0.1", "request": "^2.67.0", "request-progress": "1.0.2", From 9e8aa1898cc3c6ffe0b797b9d711effa72337aa0 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 9 Feb 2018 15:24:07 -0800 Subject: [PATCH 13/53] warnings, load material from URL, shapeID -> parentMaterialID --- assignment-client/src/assets/AssetServer.h | 7 +- interface/src/Application.cpp | 16 +- interface/src/ui/overlays/ModelOverlay.cpp | 12 +- interface/src/ui/overlays/ModelOverlay.h | 4 +- interface/src/ui/overlays/Overlay.cpp | 8 +- interface/src/ui/overlays/Overlay.h | 6 +- .../src/avatars-renderer/Avatar.cpp | 12 +- .../src/avatars-renderer/Avatar.h | 6 +- libraries/avatars/src/AvatarData.h | 4 +- .../src/RenderableEntityItem.cpp | 8 +- .../src/RenderableEntityItem.h | 6 +- .../src/RenderableMaterialEntityItem.cpp | 8 +- .../src/RenderableModelEntityItem.cpp | 12 +- .../src/RenderableModelEntityItem.h | 4 +- .../src/RenderableShapeEntityItem.cpp | 6 +- libraries/entities/src/EntityItem.cpp | 16 +- libraries/entities/src/EntityItem.h | 12 +- .../entities/src/EntityItemProperties.cpp | 28 +-- libraries/entities/src/EntityItemProperties.h | 3 +- libraries/entities/src/EntityPropertyFlags.h | 3 +- libraries/entities/src/EntityTree.cpp | 24 +- libraries/entities/src/EntityTree.h | 24 +- libraries/entities/src/MaterialEntityItem.cpp | 215 ++++-------------- libraries/entities/src/MaterialEntityItem.h | 15 +- libraries/graphics/src/graphics/Material.h | 4 - .../src/model-networking/MaterialCache.cpp | 175 ++++++++++++++ .../src/model-networking/MaterialCache.h | 46 ++++ .../src/model-networking/ModelCache.cpp | 2 +- libraries/networking/src/ResourceRequest.cpp | 2 +- libraries/render-utils/src/Model.cpp | 92 ++++---- libraries/render-utils/src/Model.h | 6 +- libraries/shared/src/RegisteredMetaTypes.h | 7 + scripts/system/html/entityProperties.html | 11 +- scripts/system/html/js/entityProperties.js | 9 +- 34 files changed, 447 insertions(+), 366 deletions(-) create mode 100644 libraries/model-networking/src/model-networking/MaterialCache.cpp create mode 100644 libraries/model-networking/src/model-networking/MaterialCache.h diff --git a/assignment-client/src/assets/AssetServer.h b/assignment-client/src/assets/AssetServer.h index 5e7a3c1700..1470249bf3 100644 --- a/assignment-client/src/assets/AssetServer.h +++ b/assignment-client/src/assets/AssetServer.h @@ -21,12 +21,7 @@ #include "AssetUtils.h" #include "ReceivedMessage.h" -namespace std { - template <> - struct hash { - size_t operator()(const QString& v) const { return qHash(v); } - }; -} +#include "RegisteredMetaTypes.h" struct AssetMeta { AssetMeta() { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f8fa8f9b17..ce4027945d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1587,37 +1587,37 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } }); - EntityTree::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) { + EntityTree::setAddMaterialToAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const QString& parentMaterialID) { auto avatarManager = DependencyManager::get(); auto avatar = avatarManager->getAvatarBySessionID(avatarID); if (avatar) { - avatar->addMaterial(material, shapeID); + avatar->addMaterial(material, parentMaterialID); return true; } return false; }); - EntityTree::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) { + EntityTree::setRemoveMaterialFromAvatarOperator([](const QUuid& avatarID, graphics::MaterialPointer material, const QString& parentMaterialID) { auto avatarManager = DependencyManager::get(); auto avatar = avatarManager->getAvatarBySessionID(avatarID); if (avatar) { - avatar->removeMaterial(material, shapeID); + avatar->removeMaterial(material, parentMaterialID); return true; } return false; }); - EntityTree::setAddMaterialToOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) { + EntityTree::setAddMaterialToOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, const QString& parentMaterialID) { auto overlay = _overlays.getOverlay(overlayID); if (overlay) { - overlay->addMaterial(material, shapeID); + overlay->addMaterial(material, parentMaterialID); return true; } return false; }); - EntityTree::setRemoveMaterialFromOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) { + EntityTree::setRemoveMaterialFromOverlayOperator([&](const QUuid& overlayID, graphics::MaterialPointer material, const QString& parentMaterialID) { auto overlay = _overlays.getOverlay(overlayID); if (overlay) { - overlay->removeMaterial(material, shapeID); + overlay->removeMaterial(material, parentMaterialID); return true; } return false; diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index bf95494d19..ab7f55d6e7 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -633,17 +633,17 @@ uint32_t ModelOverlay::fetchMetaSubItems(render::ItemIDs& subItems) const { return 0; } -void ModelOverlay::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { - Overlay::addMaterial(material, shapeID); +void ModelOverlay::addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { + Overlay::addMaterial(material, parentMaterialID); if (_model && _model->fetchRenderItemIDs().size() > 0) { - _model->addMaterial(material, shapeID); + _model->addMaterial(material, parentMaterialID); } } -void ModelOverlay::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { - Overlay::removeMaterial(material, shapeID); +void ModelOverlay::removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { + Overlay::removeMaterial(material, parentMaterialID); if (_model && _model->fetchRenderItemIDs().size() > 0) { - _model->removeMaterial(material, shapeID); + _model->removeMaterial(material, parentMaterialID); } } diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 827f7f2d5b..6761b1508c 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -59,8 +59,8 @@ public: void setDrawInFront(bool drawInFront) override; void setDrawHUDLayer(bool drawHUDLayer) override; - void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override; - void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + void addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) override; + void removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) override; protected: Transform evalRenderTransform() override; diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index 368ed04062..04d6c2fe4d 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -236,12 +236,12 @@ QVector qVectorOverlayIDFromScriptValue(const QScriptValue& array) { return newVector; } -void Overlay::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { +void Overlay::addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { std::lock_guard lock(_materialsLock); - _materials[shapeID].push(material); + _materials[parentMaterialID].push(material); } -void Overlay::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { +void Overlay::removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { std::lock_guard lock(_materialsLock); - _materials[shapeID].remove(material); + _materials[parentMaterialID].remove(material); } \ No newline at end of file diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 4cb3f7c84d..bd9f7942fd 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -91,8 +91,8 @@ public: unsigned int getStackOrder() const { return _stackOrder; } void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; } - virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID); - virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID); + virtual void addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID); + virtual void removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID); protected: float updatePulse(); @@ -120,7 +120,7 @@ protected: static const xColor DEFAULT_OVERLAY_COLOR; static const float DEFAULT_ALPHA; - std::unordered_map _materials; + std::unordered_map _materials; std::mutex _materialsLock; private: diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 4cd9bbedd7..3276a8fe89 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1763,19 +1763,19 @@ float Avatar::getUnscaledEyeHeightFromSkeleton() const { } } -void Avatar::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { +void Avatar::addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { std::lock_guard lock(_materialsLock); - _materials[shapeID].push(material); + _materials[parentMaterialID].push(material); if (_skeletonModel && _skeletonModel->fetchRenderItemIDs().size() > 0) { - _skeletonModel->addMaterial(material, shapeID); + _skeletonModel->addMaterial(material, parentMaterialID); } } -void Avatar::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { +void Avatar::removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { std::lock_guard lock(_materialsLock); - _materials[shapeID].remove(material); + _materials[parentMaterialID].remove(material); if (_skeletonModel && _skeletonModel->fetchRenderItemIDs().size() > 0) { - _skeletonModel->removeMaterial(material, shapeID); + _skeletonModel->removeMaterial(material, parentMaterialID); } } diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 9c355159d8..49aa664a9f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -272,8 +272,8 @@ public: virtual void setAvatarEntityDataChanged(bool value) override; - void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override; - void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + void addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) override; + void removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) override; public slots: @@ -401,7 +401,7 @@ protected: ThreadSafeValueCache _unscaledEyeHeightCache { DEFAULT_AVATAR_EYE_HEIGHT }; - std::unordered_map _materials; + std::unordered_map _materials; std::mutex _materialsLock; void processMaterials(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index fbd586f153..832585a483 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -696,8 +696,8 @@ public: bool getIsReplicated() const { return _isReplicated; } - virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID) {} - virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) {} + virtual void addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) {} + virtual void removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) {} signals: void displayNameChanged(); diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 2f92790d18..81d7dceb0d 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -404,12 +404,12 @@ void EntityRenderer::onRemoveFromScene(const EntityItemPointer& entity) { QObject::disconnect(this, &EntityRenderer::requestRenderUpdate, this, nullptr); } -void EntityRenderer::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { +void EntityRenderer::addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { std::lock_guard lock(_materialsLock); - _materials[shapeID].push(material); + _materials[parentMaterialID].push(material); } -void EntityRenderer::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { +void EntityRenderer::removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { std::lock_guard lock(_materialsLock); - _materials[shapeID].remove(material); + _materials[parentMaterialID].remove(material); } \ No newline at end of file diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index f58b540aef..6247a97c21 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -102,8 +102,8 @@ protected: } public slots: - virtual void addMaterial(graphics::MaterialPointer material, quint16 shapeID); - virtual void removeMaterial(graphics::MaterialPointer material, quint16 shapeID); + virtual void addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID); + virtual void removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID); signals: void requestRenderUpdate(); @@ -133,7 +133,7 @@ protected: // Only touched on the rendering thread bool _renderUpdateQueued{ false }; - std::unordered_map _materials; + std::unordered_map _materials; std::mutex _materialsLock; private: diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index d541d99c4c..ad17202d8e 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -102,10 +102,10 @@ void MaterialEntityRenderer::addVertex(std::vector& buffer, const glm::ve void MaterialEntityRenderer::addTriangleFan(std::vector& buffer, int stack, int step) { float v1 = ((float)stack) / STACKS; - float theta1 = v1 * M_PI; + float theta1 = v1 * (float)M_PI; glm::vec3 tip = getVertexPos(0, theta1); float v2 = ((float)(stack + step)) / STACKS; - float theta2 = v2 * M_PI; + float theta2 = v2 * (float)M_PI; for (int i = 0; i < SLICES; i++) { float u1 = ((float)i) / SLICES; float u2 = ((float)(i + step)) / SLICES; @@ -169,8 +169,8 @@ void MaterialEntityRenderer::generateMesh() { for (int j = 1; j < STACKS - 1; j++) { float v1 = ((float)j) / STACKS; float v2 = ((float)(j + 1)) / STACKS; - float theta1 = v1 * M_PI; - float theta2 = v2 * M_PI; + float theta1 = v1 * (float)M_PI; + float theta2 = v2 * (float)M_PI; for (int i = 0; i < SLICES; i++) { float u1 = ((float)i) / SLICES; float u2 = ((float)(i + 1)) / SLICES; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 739ccd9738..e28ba797d5 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1467,17 +1467,17 @@ void ModelEntityRenderer::mapJoints(const TypedEntityPointer& entity, const QStr } } -void ModelEntityRenderer::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { - Parent::addMaterial(material, shapeID); +void ModelEntityRenderer::addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { + Parent::addMaterial(material, parentMaterialID); if (_model && _model->fetchRenderItemIDs().size() > 0) { - _model->addMaterial(material, shapeID); + _model->addMaterial(material, parentMaterialID); } } -void ModelEntityRenderer::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { - Parent::removeMaterial(material, shapeID); +void ModelEntityRenderer::removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { + Parent::removeMaterial(material, parentMaterialID); if (_model && _model->fetchRenderItemIDs().size() > 0) { - _model->removeMaterial(material, shapeID); + _model->removeMaterial(material, parentMaterialID); } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 75c6639902..3951deaa2d 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -144,8 +144,8 @@ public: ModelEntityRenderer(const EntityItemPointer& entity); public slots: - void addMaterial(graphics::MaterialPointer material, quint16 shapeID) override; - void removeMaterial(graphics::MaterialPointer material, quint16 shapeID) override; + void addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) override; + void removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) override; protected: virtual void removeFromScene(const ScenePointer& scene, Transaction& transaction) override; diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 8bed9c70ee..5c5df38350 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -77,9 +77,9 @@ void ShapeEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce _procedural.setProceduralData(ProceduralData::parse(_lastUserData)); } - removeMaterial(_material, 0); + removeMaterial(_material, "0"); _material = entity->getMaterial(); - addMaterial(_material, 0); + addMaterial(_material, "0"); _shape = entity->getShape(); _position = entity->getWorldPosition(); @@ -127,7 +127,7 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { withReadLock([&] { geometryShape = geometryCache->getShapeForEntityShape(_shape); batch.setModelTransform(_renderTransform); // use a transform with scale, rotation, registration point and translation - mat = _materials[0].top(); + mat = _materials["0"].top(); if (mat) { outColor = glm::vec4(mat->getAlbedo(), mat->getOpacity()); if (_procedural.isReady()) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 43510864ba..3ea81e5a36 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -2940,20 +2940,20 @@ void EntityItem::preDelete() { } } -void EntityItem::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { +void EntityItem::addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { std::lock_guard lock(_materialsLock); - _materials[shapeID].push(material); - emit addMaterialToRenderItem(material, shapeID); + _materials[parentMaterialID].push(material); + emit addMaterialToRenderItem(material, parentMaterialID); } -void EntityItem::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { +void EntityItem::removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { std::lock_guard lock(_materialsLock); - _materials[shapeID].remove(material); - emit removeMaterialFromRenderItem(material, shapeID); + _materials[parentMaterialID].remove(material); + emit removeMaterialFromRenderItem(material, parentMaterialID); } -std::unordered_map EntityItem::getMaterials() { - std::unordered_map toReturn; +std::unordered_map EntityItem::getMaterials() { + std::unordered_map toReturn; { std::lock_guard lock(_materialsLock); toReturn = _materials; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index b2804a2e86..97d2f32a04 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -482,14 +482,14 @@ public: virtual void preDelete(); virtual void postParentFixup() {} - void addMaterial(graphics::MaterialPointer material, quint16 shapeID); - void removeMaterial(graphics::MaterialPointer material, quint16 shapeID); - std::unordered_map getMaterials(); + void addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID); + void removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID); + std::unordered_map getMaterials(); signals: void requestRenderUpdate(); - void addMaterialToRenderItem(graphics::MaterialPointer material, quint16 shapeID); - void removeMaterialFromRenderItem(graphics::MaterialPointer material, quint16 shapeID); + void addMaterialToRenderItem(graphics::MaterialPointer material, const QString& parentMaterialID); + void removeMaterialFromRenderItem(graphics::MaterialPointer material, const QString& parentMaterialID); protected: QHash _changeHandlers; @@ -644,7 +644,7 @@ protected: bool _cauterized { false }; // if true, don't draw because it would obscure 1st-person camera private: - std::unordered_map _materials; + std::unordered_map _materials; std::mutex _materialsLock; }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 19aa6990db..450d0727f9 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -357,9 +357,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RADIUS_FINISH, radiusFinish); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_URL, materialURL); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_TYPE, materialMode); - CHECK_PROPERTY_CHANGE(PROP_MATERIAL_BLEND_FACTOR, blendFactor); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_PRIORITY, priority); - CHECK_PROPERTY_CHANGE(PROP_PARENT_SHAPE_ID, shapeID); + CHECK_PROPERTY_CHANGE(PROP_PARENT_MATERIAL_ID, parentMaterialID); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_POS, materialPos); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_SCALE, materialScale); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_ROT, materialRot); @@ -663,9 +662,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool if (_type == EntityTypes::Material) { COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_URL, materialURL); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_MATERIAL_TYPE, materialMode, getMaterialModeAsString()); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_BLEND_FACTOR, blendFactor); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_PRIORITY, priority); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_SHAPE_ID, shapeID); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARENT_MATERIAL_ID, parentMaterialID); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_POS, materialPos); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_SCALE, materialScale); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_ROT, materialRot); @@ -806,9 +804,8 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(relayParentJoints, bool, setRelayParentJoints); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialURL, QString, setMaterialURL); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(materialMode, MaterialMode); - COPY_PROPERTY_FROM_QSCRIPTVALUE(blendFactor, float, setBlendFactor); COPY_PROPERTY_FROM_QSCRIPTVALUE(priority, quint16, setPriority); - COPY_PROPERTY_FROM_QSCRIPTVALUE(shapeID, quint16, setShapeID); + COPY_PROPERTY_FROM_QSCRIPTVALUE(parentMaterialID, QString, setParentMaterialID); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialPos, glmVec2, setMaterialPos); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialScale, glmVec2, setMaterialScale); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialRot, float, setMaterialRot); @@ -1168,9 +1165,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_MATERIAL_URL, MaterialURL, materialURL, QString); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_TYPE, MaterialMode, materialMode, MaterialMode); - ADD_PROPERTY_TO_MAP(PROP_MATERIAL_BLEND_FACTOR, BlendFactor, blendFactor, float); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_PRIORITY, Priority, priority, quint16); - ADD_PROPERTY_TO_MAP(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, quint16); + ADD_PROPERTY_TO_MAP(PROP_PARENT_MATERIAL_ID, ParentMaterialID, parentMaterialID, QString); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_POS, MaterialPos, materialPos, glmVec2); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_SCALE, MaterialScale, materialScale, glmVec2); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_ROT, MaterialRot, materialRot, float); @@ -1562,9 +1558,8 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy if (properties.getType() == EntityTypes::Material) { APPEND_ENTITY_PROPERTY(PROP_MATERIAL_URL, properties.getMaterialURL()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, (uint32_t)properties.getMaterialMode()); - APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, properties.getBlendFactor()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, properties.getPriority()); - APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, properties.getShapeID()); + APPEND_ENTITY_PROPERTY(PROP_PARENT_MATERIAL_ID, properties.getParentMaterialID()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_POS, properties.getMaterialPos()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, properties.getMaterialScale()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_ROT, properties.getMaterialRot()); @@ -1930,9 +1925,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int if (properties.getType() == EntityTypes::Material) { READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_URL, QString, setMaterialURL); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_PRIORITY, quint16, setPriority); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_SHAPE_ID, quint16, setShapeID); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARENT_MATERIAL_ID, QString, setParentMaterialID); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_POS, glmVec2, setMaterialPos); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_SCALE, glmVec2, setMaterialScale); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_ROT, float, setMaterialRot); @@ -2113,9 +2107,8 @@ void EntityItemProperties::markAllChanged() { _materialURLChanged = true; _materialModeChanged = true; - _blendFactorChanged = true; _priorityChanged = true; - _shapeIDChanged = true; + _parentMaterialIDChanged = true; _materialPosChanged = true; _materialScaleChanged = true; _materialRotChanged = true; @@ -2449,14 +2442,11 @@ QList EntityItemProperties::listChangedProperties() { if (materialModeChanged()) { out += "materialMode"; } - if (blendFactorChanged()) { - out += "blendFactor"; - } if (priorityChanged()) { out += "priority"; } - if (shapeIDChanged()) { - out += "shapeID"; + if (parentMaterialIDChanged()) { + out += "parentMaterialID"; } if (materialPosChanged()) { out += "materialPos"; diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index a8a79b6303..daa2272e36 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -224,9 +224,8 @@ public: DEFINE_PROPERTY_REF(PROP_MATERIAL_URL, MaterialURL, materialURL, QString, ""); DEFINE_PROPERTY_REF_ENUM(PROP_MATERIAL_TYPE, MaterialMode, materialMode, MaterialMode, UV); - DEFINE_PROPERTY_REF(PROP_MATERIAL_BLEND_FACTOR, BlendFactor, blendFactor, float, 1.0f); DEFINE_PROPERTY_REF(PROP_MATERIAL_PRIORITY, Priority, priority, quint16, 0); - DEFINE_PROPERTY_REF(PROP_PARENT_SHAPE_ID, ShapeID, shapeID, quint16, 0); + DEFINE_PROPERTY_REF(PROP_PARENT_MATERIAL_ID, ParentMaterialID, parentMaterialID, QString, "0"); DEFINE_PROPERTY_REF(PROP_MATERIAL_POS, MaterialPos, materialPos, glmVec2, glm::vec2(0, 0)); DEFINE_PROPERTY_REF(PROP_MATERIAL_SCALE, MaterialScale, materialScale, glmVec2, glm::vec2(1, 1)); DEFINE_PROPERTY_REF(PROP_MATERIAL_ROT, MaterialRot, materialRot, float, 0); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 17ebddbe9d..6ed2186760 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -229,9 +229,8 @@ enum EntityPropertyList { PROP_MATERIAL_URL, PROP_MATERIAL_TYPE, - PROP_MATERIAL_BLEND_FACTOR, PROP_MATERIAL_PRIORITY, - PROP_PARENT_SHAPE_ID, + PROP_PARENT_MATERIAL_ID, PROP_MATERIAL_POS, PROP_MATERIAL_SCALE, PROP_MATERIAL_ROT, diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 775b3bd2f7..9935718568 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2382,35 +2382,35 @@ QStringList EntityTree::getJointNames(const QUuid& entityID) const { return entity->getJointNames(); } -std::function EntityTree::_addMaterialToAvatarOperator = nullptr; -std::function EntityTree::_removeMaterialFromAvatarOperator = nullptr; -std::function EntityTree::_addMaterialToOverlayOperator = nullptr; -std::function EntityTree::_removeMaterialFromOverlayOperator = nullptr; +std::function EntityTree::_addMaterialToAvatarOperator = nullptr; +std::function EntityTree::_removeMaterialFromAvatarOperator = nullptr; +std::function EntityTree::_addMaterialToOverlayOperator = nullptr; +std::function EntityTree::_removeMaterialFromOverlayOperator = nullptr; -bool EntityTree::addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) { +bool EntityTree::addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const QString& parentMaterialID) { if (_addMaterialToAvatarOperator) { - return _addMaterialToAvatarOperator(avatarID, material, shapeID); + return _addMaterialToAvatarOperator(avatarID, material, parentMaterialID); } return false; } -bool EntityTree::removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID) { +bool EntityTree::removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const QString& parentMaterialID) { if (_removeMaterialFromAvatarOperator) { - return _removeMaterialFromAvatarOperator(avatarID, material, shapeID); + return _removeMaterialFromAvatarOperator(avatarID, material, parentMaterialID); } return false; } -bool EntityTree::addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) { +bool EntityTree::addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const QString& parentMaterialID) { if (_addMaterialToOverlayOperator) { - return _addMaterialToOverlayOperator(overlayID, material, shapeID); + return _addMaterialToOverlayOperator(overlayID, material, parentMaterialID); } return false; } -bool EntityTree::removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID) { +bool EntityTree::removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const QString& parentMaterialID) { if (_removeMaterialFromOverlayOperator) { - return _removeMaterialFromOverlayOperator(overlayID, material, shapeID); + return _removeMaterialFromOverlayOperator(overlayID, material, parentMaterialID); } return false; } \ No newline at end of file diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index a02ce900ff..a532f64fc9 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -280,15 +280,15 @@ public: void setMyAvatar(std::shared_ptr myAvatar) { _myAvatar = myAvatar; } - static void setAddMaterialToAvatarOperator(std::function addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; } - static void setRemoveMaterialFromAvatarOperator(std::function removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; } - static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID); - static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, quint16 shapeID); + static void setAddMaterialToAvatarOperator(std::function addMaterialToAvatarOperator) { _addMaterialToAvatarOperator = addMaterialToAvatarOperator; } + static void setRemoveMaterialFromAvatarOperator(std::function removeMaterialFromAvatarOperator) { _removeMaterialFromAvatarOperator = removeMaterialFromAvatarOperator; } + static bool addMaterialToAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const QString& parentMaterialID); + static bool removeMaterialFromAvatar(const QUuid& avatarID, graphics::MaterialPointer material, const QString& parentMaterialID); - static void setAddMaterialToOverlayOperator(std::function addMaterialToOverlayOperator) { _addMaterialToOverlayOperator = addMaterialToOverlayOperator; } - static void setRemoveMaterialFromOverlayOperator(std::function removeMaterialFromOverlayOperator) { _removeMaterialFromOverlayOperator = removeMaterialFromOverlayOperator; } - static bool addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID); - static bool removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, quint16 shapeID); + static void setAddMaterialToOverlayOperator(std::function addMaterialToOverlayOperator) { _addMaterialToOverlayOperator = addMaterialToOverlayOperator; } + static void setRemoveMaterialFromOverlayOperator(std::function removeMaterialFromOverlayOperator) { _removeMaterialFromOverlayOperator = removeMaterialFromOverlayOperator; } + static bool addMaterialToOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const QString& parentMaterialID); + static bool removeMaterialFromOverlay(const QUuid& overlayID, graphics::MaterialPointer material, const QString& parentMaterialID); signals: void deletingEntity(const EntityItemID& entityID); @@ -398,10 +398,10 @@ private: std::shared_ptr _myAvatar{ nullptr }; - static std::function _addMaterialToAvatarOperator; - static std::function _removeMaterialFromAvatarOperator; - static std::function _addMaterialToOverlayOperator; - static std::function _removeMaterialFromOverlayOperator; + static std::function _addMaterialToAvatarOperator; + static std::function _removeMaterialFromAvatarOperator; + static std::function _addMaterialToOverlayOperator; + static std::function _removeMaterialFromOverlayOperator; }; #endif // hifi_EntityTree_h diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 7026da117c..1ebaa4f21a 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -31,9 +31,8 @@ EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desir EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMode, getMaterialMode); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(blendFactor, getBlendFactor); COPY_ENTITY_PROPERTY_TO_PROPERTIES(priority, getPriority); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeID, getShapeID); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(parentMaterialID, getParentMaterialID); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialPos, getMaterialPos); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialScale, getMaterialScale); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialRot, getMaterialRot); @@ -45,9 +44,8 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialURL, setMaterialURL); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMode, setMaterialMode); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(blendFactor, setBlendFactor); SET_ENTITY_PROPERTY_FROM_PROPERTIES(priority, setPriority); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeID, setShapeID); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(parentMaterialID, setParentMaterialID); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialPos, setMaterialPos); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialScale, setMaterialScale); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialRot, setMaterialRot); @@ -65,139 +63,6 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { return somethingChanged; } -bool MaterialEntityItem::parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB) { - if (array.isArray()) { - QJsonArray colorArray = array.toArray(); - if (colorArray.size() >= 3 && colorArray[0].isDouble() && colorArray[1].isDouble() && colorArray[2].isDouble()) { - isSRGB = true; - if (colorArray.size() >= 4) { - if (colorArray[3].isBool()) { - isSRGB = colorArray[3].toBool(); - } - } - color = glm::vec3(colorArray[0].toDouble(), colorArray[1].toDouble(), colorArray[2].toDouble()); - return true; - } - } - return false; -} - -void MaterialEntityItem::parseJSONMaterial(const QJsonObject& materialJSON) { - QString name = ""; - std::shared_ptr material = std::make_shared(); - for (auto& key : materialJSON.keys()) { - if (key == "name") { - auto nameJSON = materialJSON.value(key); - if (nameJSON.isString()) { - name = nameJSON.toString(); - } - } else if (key == "emissive") { - glm::vec3 color; - bool isSRGB; - bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); - if (valid) { - material->setEmissive(color, isSRGB); - } - } else if (key == "opacity") { - auto value = materialJSON.value(key); - if (value.isDouble()) { - material->setOpacity(value.toDouble()); - } - } else if (key == "albedo") { - glm::vec3 color; - bool isSRGB; - bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); - if (valid) { - material->setAlbedo(color, isSRGB); - } - } else if (key == "roughness") { - auto value = materialJSON.value(key); - if (value.isDouble()) { - material->setRoughness(value.toDouble()); - } - } else if (key == "fresnel") { - glm::vec3 color; - bool isSRGB; - bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); - if (valid) { - material->setFresnel(color, isSRGB); - } - } else if (key == "metallic") { - auto value = materialJSON.value(key); - if (value.isDouble()) { - material->setMetallic(value.toDouble()); - } - } else if (key == "scattering") { - auto value = materialJSON.value(key); - if (value.isDouble()) { - material->setScattering(value.toDouble()); - } - } else if (key == "emissiveMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setEmissiveMap(value.toString()); - } - } else if (key == "albedoMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - bool useAlphaChannel = false; - auto opacityMap = materialJSON.find("opacityMap"); - if (opacityMap != materialJSON.end() && opacityMap->isString() && opacityMap->toString() == value.toString()) { - useAlphaChannel = true; - } - material->setAlbedoMap(value.toString(), useAlphaChannel); - } - } else if (key == "roughnessMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setRoughnessMap(value.toString(), false); - } - } else if (key == "glossMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setRoughnessMap(value.toString(), true); - } - } else if (key == "metallicMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setMetallicMap(value.toString(), false); - } - } else if (key == "specularMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setMetallicMap(value.toString(), true); - } - } else if (key == "normalMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setNormalMap(value.toString(), false); - } - } else if (key == "bumpMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setNormalMap(value.toString(), true); - } - } else if (key == "occlusionMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setOcclusionMap(value.toString()); - } - } else if (key == "scatteringMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setScatteringMap(value.toString()); - } - } else if (key == "lightMap") { - auto value = materialJSON.value(key); - if (value.isString()) { - material->setLightmapMap(value.toString()); - } - } - } - _materials[name] = material; - _materialNames.push_back(name); -} - int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args, EntityPropertyFlags& propertyFlags, bool overwriteLocalData, @@ -208,9 +73,8 @@ int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da READ_ENTITY_PROPERTY(PROP_MATERIAL_URL, QString, setMaterialURL); READ_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, MaterialMode, setMaterialMode); - READ_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, float, setBlendFactor); READ_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, quint16, setPriority); - READ_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, quint16, setShapeID); + READ_ENTITY_PROPERTY(PROP_PARENT_MATERIAL_ID, QString, setParentMaterialID); READ_ENTITY_PROPERTY(PROP_MATERIAL_POS, glm::vec2, setMaterialPos); READ_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, glm::vec2, setMaterialScale); READ_ENTITY_PROPERTY(PROP_MATERIAL_ROT, float, setMaterialRot); @@ -224,9 +88,8 @@ EntityPropertyFlags MaterialEntityItem::getEntityProperties(EncodeBitstreamParam EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params); requestedProperties += PROP_MATERIAL_URL; requestedProperties += PROP_MATERIAL_TYPE; - requestedProperties += PROP_MATERIAL_BLEND_FACTOR; requestedProperties += PROP_MATERIAL_PRIORITY; - requestedProperties += PROP_PARENT_SHAPE_ID; + requestedProperties += PROP_PARENT_MATERIAL_ID; requestedProperties += PROP_MATERIAL_POS; requestedProperties += PROP_MATERIAL_SCALE; requestedProperties += PROP_MATERIAL_ROT; @@ -244,9 +107,8 @@ void MaterialEntityItem::appendSubclassData(OctreePacketData* packetData, Encode bool successPropertyFits = true; APPEND_ENTITY_PROPERTY(PROP_MATERIAL_URL, getMaterialURL()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_TYPE, (uint32_t)getMaterialMode()); - APPEND_ENTITY_PROPERTY(PROP_MATERIAL_BLEND_FACTOR, getBlendFactor()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_PRIORITY, getPriority()); - APPEND_ENTITY_PROPERTY(PROP_PARENT_SHAPE_ID, getShapeID()); + APPEND_ENTITY_PROPERTY(PROP_PARENT_MATERIAL_ID, getParentMaterialID()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_POS, getMaterialPos()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_SCALE, getMaterialScale()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_ROT, getMaterialRot()); @@ -259,9 +121,8 @@ void MaterialEntityItem::debugDump() const { qCDebug(entities) << " material json:" << _materialURL; qCDebug(entities) << " current material name:" << _currentMaterialName; qCDebug(entities) << " material type:" << _materialMode; - qCDebug(entities) << " blend factor:" << _blendFactor; qCDebug(entities) << " priority:" << _priority; - qCDebug(entities) << " parent shape ID:" << _shapeID; + qCDebug(entities) << " parent material ID:" << _parentMaterialID; qCDebug(entities) << " material pos:" << _materialPos; qCDebug(entities) << " material scale:" << _materialRot; qCDebug(entities) << " material rot:" << _materialScale; @@ -290,6 +151,8 @@ void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool u removeMaterial(); _materialURL = materialURLString; + // TODO: if URL ends with ?string, try to set _currentMaterialName = string + if (usingUserData) { QJsonDocument materialJSON = QJsonDocument::fromJson(getUserData().toUtf8()); _materials.clear(); @@ -299,22 +162,39 @@ void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool u QJsonArray materials = materialJSON.array(); for (auto material : materials) { if (!material.isNull() && material.isObject()) { - parseJSONMaterial(material.toObject()); + auto networkMaterial = NetworkMaterialResource::parseJSONMaterial(material.toObject()); + _materials[networkMaterial.first] = networkMaterial.second; + _materialNames.push_back(networkMaterial.first); } } } else if (materialJSON.isObject()) { - parseJSONMaterial(materialJSON.object()); + auto networkMaterial = NetworkMaterialResource::parseJSONMaterial(materialJSON.object()); + _materials[networkMaterial.first] = networkMaterial.second; + _materialNames.push_back(networkMaterial.first); } } + // Since our material changed, the current name might not be valid anymore, so we need to update + setCurrentMaterialName(_currentMaterialName); + applyMaterial(); } else { - // get material via network request + _networkMaterial = MaterialCache::instance().getMaterial(materialURLString); + auto onMaterialRequestFinished = [&](bool success) { + if (success) { + _materials[_networkMaterial->name] = _networkMaterial->networkMaterial; + _materialNames.push_back(_networkMaterial->name); + + setCurrentMaterialName(_currentMaterialName); + applyMaterial(); + } + }; + if (_networkMaterial) { + if (_networkMaterial->isLoaded()) { + onMaterialRequestFinished(!_networkMaterial->isFailed()); + } else { + connect(_networkMaterial.data(), &Resource::finished, this, onMaterialRequestFinished); + } + } } - - // TODO: if URL ends with ?string, try to set _currentMaterialName = string - - // Since our JSON changed, the current name might not be valid anymore, so we need to update - setCurrentMaterialName(_currentMaterialName); - applyMaterial(); } } @@ -361,14 +241,6 @@ void MaterialEntityItem::setMaterialRot(const float& materialRot) { } } -void MaterialEntityItem::setBlendFactor(float blendFactor) { - if (_blendFactor != blendFactor) { - removeMaterial(); - _blendFactor = blendFactor; - applyMaterial(); - } -} - void MaterialEntityItem::setPriority(quint16 priority) { if (_priority != priority) { removeMaterial(); @@ -377,10 +249,10 @@ void MaterialEntityItem::setPriority(quint16 priority) { } } -void MaterialEntityItem::setShapeID(quint16 shapeID) { - if (_shapeID != shapeID) { +void MaterialEntityItem::setParentMaterialID(const QString& parentMaterialID) { + if (_parentMaterialID != parentMaterialID) { removeMaterial(); - _shapeID = shapeID; + _parentMaterialID = parentMaterialID; applyMaterial(); } } @@ -421,16 +293,16 @@ void MaterialEntityItem::removeMaterial() { if (tree) { EntityItemPointer entity = tree->findEntityByEntityItemID(parentID); if (entity) { - entity->removeMaterial(material, getShapeID()); + entity->removeMaterial(material, getParentMaterialID()); return; } } - if (EntityTree::removeMaterialFromAvatar(parentID, material, getShapeID())) { + if (EntityTree::removeMaterialFromAvatar(parentID, material, getParentMaterialID())) { return; } - if (EntityTree::removeMaterialFromOverlay(parentID, material, getShapeID())) { + if (EntityTree::removeMaterialFromOverlay(parentID, material, getParentMaterialID())) { return; } @@ -449,7 +321,6 @@ void MaterialEntityItem::applyMaterial() { textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialRot))); textureTransform.setScale(glm::vec3(_materialScale, 1)); material->setTextureTransforms(textureTransform); - material->setBlendFactor(getBlendFactor()); material->setPriority(getPriority()); // Our parent could be an entity, an avatar, or an overlay @@ -457,16 +328,16 @@ void MaterialEntityItem::applyMaterial() { if (tree) { EntityItemPointer entity = tree->findEntityByEntityItemID(parentID); if (entity) { - entity->addMaterial(material, getShapeID()); + entity->addMaterial(material, getParentMaterialID()); return; } } - if (EntityTree::addMaterialToAvatar(parentID, material, getShapeID())) { + if (EntityTree::addMaterialToAvatar(parentID, material, getParentMaterialID())) { return; } - if (EntityTree::addMaterialToOverlay(parentID, material, getShapeID())) { + if (EntityTree::addMaterialToOverlay(parentID, material, getParentMaterialID())) { return; } diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index 40137acf22..dde9b60da9 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -13,6 +13,7 @@ #include "MaterialMode.h" #include +#include class MaterialEntityItem : public EntityItem { using Pointer = std::shared_ptr; @@ -60,14 +61,11 @@ public: MaterialMode getMaterialMode() const { return _materialMode; } void setMaterialMode(MaterialMode mode) { _materialMode = mode; } - float getBlendFactor() const { return _blendFactor; } - void setBlendFactor(float blendFactor); - quint16 getPriority() const { return _priority; } void setPriority(quint16 priority); - quint16 getShapeID() const { return _shapeID; } - void setShapeID(quint16 shapeID); + QString getParentMaterialID() const { return _parentMaterialID; } + void setParentMaterialID(const QString& parentMaterialID); glm::vec2 getMaterialPos() const { return _materialPos; } void setMaterialPos(const glm::vec2& materialPos); @@ -93,22 +91,19 @@ public: private: QString _materialURL; MaterialMode _materialMode { UV }; - float _blendFactor { 1.0f }; quint16 _priority { 0 }; - quint16 _shapeID { 0 }; + QString _parentMaterialID { "0" }; glm::vec2 _materialPos { 0, 0 }; glm::vec2 _materialScale { 1, 1 }; float _materialRot { 0 }; + NetworkMaterialResourcePointer _networkMaterial; QHash> _materials; std::vector _materialNames; QString _currentMaterialName; bool _retryApply { false }; - void parseJSONMaterial(const QJsonObject& materialJSON); - static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); - }; #endif // hifi_MaterialEntityItem_h diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 6731d544b8..5b3396dfc5 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -354,9 +354,6 @@ public: size_t getTextureSize() const { calculateMaterialInfo(); return _textureSize; } bool hasTextureInfo() const { return _hasCalculatedTextureInfo; } - void setBlendFactor(float blendFactor) { _blendFactor = blendFactor; } - float getBlendFactor() { return _blendFactor; } - void setPriority(quint16 priority) { _priority = priority; } quint16 getPriority() { return _priority; } @@ -375,7 +372,6 @@ private: mutable bool _hasCalculatedTextureInfo { false }; bool calculateMaterialInfo() const; - float _blendFactor { 1.0f }; quint16 _priority { 0 }; }; diff --git a/libraries/model-networking/src/model-networking/MaterialCache.cpp b/libraries/model-networking/src/model-networking/MaterialCache.cpp new file mode 100644 index 0000000000..723448f65a --- /dev/null +++ b/libraries/model-networking/src/model-networking/MaterialCache.cpp @@ -0,0 +1,175 @@ +// +// Created by Sam Gondelman on 2/9/2018 +// 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 "MaterialCache.h" + +#include "QJsonObject" +#include "QJsonDocument" +#include "QJsonArray" + +NetworkMaterialResource::NetworkMaterialResource(const QUrl& url) : + Resource(url) {} + +void NetworkMaterialResource::downloadFinished(const QByteArray& data) { + if (_url.toString().endsWith(".json")) { + QJsonDocument materialJSON = QJsonDocument::fromJson(data); + if (!materialJSON.isNull() && materialJSON.isObject()) { + auto parsedMaterial = parseJSONMaterial(materialJSON.object()); + name = parsedMaterial.first; + networkMaterial = parsedMaterial.second; + } + } + + // TODO: parse other material types + + finishedLoading(true); +} + +bool NetworkMaterialResource::parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB) { + if (array.isArray()) { + QJsonArray colorArray = array.toArray(); + if (colorArray.size() >= 3 && colorArray[0].isDouble() && colorArray[1].isDouble() && colorArray[2].isDouble()) { + isSRGB = true; + if (colorArray.size() >= 4) { + if (colorArray[3].isBool()) { + isSRGB = colorArray[3].toBool(); + } + } + color = glm::vec3(colorArray[0].toDouble(), colorArray[1].toDouble(), colorArray[2].toDouble()); + return true; + } + } + return false; +} + +std::pair> NetworkMaterialResource::parseJSONMaterial(const QJsonObject& materialJSON) { + QString name = ""; + std::shared_ptr material = std::make_shared(); + for (auto& key : materialJSON.keys()) { + if (key == "name") { + auto nameJSON = materialJSON.value(key); + if (nameJSON.isString()) { + name = nameJSON.toString(); + } + } else if (key == "emissive") { + glm::vec3 color; + bool isSRGB; + bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); + if (valid) { + material->setEmissive(color, isSRGB); + } + } else if (key == "opacity") { + auto value = materialJSON.value(key); + if (value.isDouble()) { + material->setOpacity(value.toDouble()); + } + } else if (key == "albedo") { + glm::vec3 color; + bool isSRGB; + bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); + if (valid) { + material->setAlbedo(color, isSRGB); + } + } else if (key == "roughness") { + auto value = materialJSON.value(key); + if (value.isDouble()) { + material->setRoughness(value.toDouble()); + } + } else if (key == "fresnel") { + glm::vec3 color; + bool isSRGB; + bool valid = parseJSONColor(materialJSON.value(key), color, isSRGB); + if (valid) { + material->setFresnel(color, isSRGB); + } + } else if (key == "metallic") { + auto value = materialJSON.value(key); + if (value.isDouble()) { + material->setMetallic(value.toDouble()); + } + } else if (key == "scattering") { + auto value = materialJSON.value(key); + if (value.isDouble()) { + material->setScattering(value.toDouble()); + } + } else if (key == "emissiveMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setEmissiveMap(value.toString()); + } + } else if (key == "albedoMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + bool useAlphaChannel = false; + auto opacityMap = materialJSON.find("opacityMap"); + if (opacityMap != materialJSON.end() && opacityMap->isString() && opacityMap->toString() == value.toString()) { + useAlphaChannel = true; + } + material->setAlbedoMap(value.toString(), useAlphaChannel); + } + } else if (key == "roughnessMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setRoughnessMap(value.toString(), false); + } + } else if (key == "glossMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setRoughnessMap(value.toString(), true); + } + } else if (key == "metallicMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setMetallicMap(value.toString(), false); + } + } else if (key == "specularMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setMetallicMap(value.toString(), true); + } + } else if (key == "normalMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setNormalMap(value.toString(), false); + } + } else if (key == "bumpMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setNormalMap(value.toString(), true); + } + } else if (key == "occlusionMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setOcclusionMap(value.toString()); + } + } else if (key == "scatteringMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setScatteringMap(value.toString()); + } + } else if (key == "lightMap") { + auto value = materialJSON.value(key); + if (value.isString()) { + material->setLightmapMap(value.toString()); + } + } + } + return std::pair>(name, material); +} + +MaterialCache& MaterialCache::instance() { + static MaterialCache _instance; + return _instance; +} + +NetworkMaterialResourcePointer MaterialCache::getMaterial(const QUrl& url) { + return ResourceCache::getResource(url, QUrl(), nullptr).staticCast(); +} + +QSharedPointer MaterialCache::createResource(const QUrl& url, const QSharedPointer& fallback, const void* extra) { + return QSharedPointer(new NetworkMaterialResource(url), &Resource::deleter); +} \ No newline at end of file diff --git a/libraries/model-networking/src/model-networking/MaterialCache.h b/libraries/model-networking/src/model-networking/MaterialCache.h new file mode 100644 index 0000000000..1b0f1c577c --- /dev/null +++ b/libraries/model-networking/src/model-networking/MaterialCache.h @@ -0,0 +1,46 @@ +// +// Created by Sam Gondelman on 2/9/2018 +// 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_MaterialCache_h +#define hifi_MaterialCache_h + +#include + +#include "glm/glm.hpp" + +#include "ModelCache.h" + +class NetworkMaterialResource : public Resource { +public: + NetworkMaterialResource(const QUrl& url); + + QString getType() const override { return "NetworkMaterial"; } + + virtual void downloadFinished(const QByteArray& data) override; + + QString name { "" }; + std::shared_ptr networkMaterial { nullptr }; + + static std::pair> parseJSONMaterial(const QJsonObject& materialJSON); + +private: + static bool parseJSONColor(const QJsonValue& array, glm::vec3& color, bool& isSRGB); +}; + +using NetworkMaterialResourcePointer = QSharedPointer; + +class MaterialCache : public ResourceCache { +public: + static MaterialCache& instance(); + + NetworkMaterialResourcePointer getMaterial(const QUrl& url); + +protected: + virtual QSharedPointer createResource(const QUrl& url, const QSharedPointer& fallback, const void* extra) override; +}; + +#endif diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 32deba3687..739f401ee7 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -495,8 +495,8 @@ NetworkMaterial::NetworkMaterial(const NetworkMaterial& m) : Material(m), _textures(m._textures), _albedoTransform(m._albedoTransform), - _lightmapParams(m._lightmapParams), _lightmapTransform(m._lightmapTransform), + _lightmapParams(m._lightmapParams), _isOriginal(m._isOriginal) {} diff --git a/libraries/networking/src/ResourceRequest.cpp b/libraries/networking/src/ResourceRequest.cpp index 5d39583c9e..115e665b77 100644 --- a/libraries/networking/src/ResourceRequest.cpp +++ b/libraries/networking/src/ResourceRequest.cpp @@ -23,7 +23,7 @@ void ResourceRequest::send() { QMetaObject::invokeMethod(this, "send", Qt::QueuedConnection); return; } - + Q_ASSERT(_state == NotStarted); _state = InProgress; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 805995edfb..3a9ea45d77 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1524,48 +1524,62 @@ bool Model::isRenderable() const { return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty()); } -void Model::addMaterial(graphics::MaterialPointer material, quint16 shapeID) { - if (shapeID < _modelMeshRenderItemIDs.size()) { - render::Transaction transaction; - auto itemID = _modelMeshRenderItemIDs[shapeID]; - bool visible = isVisible(); - uint8_t viewTagBits = getViewTagBits(); - bool layeredInFront = isLayeredInFront(); - bool layeredInHUD = isLayeredInHUD(); - bool wireframe = isWireframe(); - auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; - bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); - transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, - invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { - data.addMaterial(material); - // if the material changed, we might need to update our item key or shape key - data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); - data.setShapeKey(invalidatePayloadShapeKey, wireframe); - }); - AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); - } +std::vector Model::getMeshIDsFromMaterialID(const QString& parentMaterialID) { + std::vector toReturn; + // TODO: first, try to find all meshes with materials that match parentMaterialID as a string + // if none, return parentMaterialID as a uint + toReturn.push_back(parentMaterialID.toUInt()); + return toReturn; } -void Model::removeMaterial(graphics::MaterialPointer material, quint16 shapeID) { - if (shapeID < _modelMeshRenderItemIDs.size()) { - render::Transaction transaction; - auto itemID = _modelMeshRenderItemIDs[shapeID]; - bool visible = isVisible(); - uint8_t viewTagBits = getViewTagBits(); - bool layeredInFront = isLayeredInFront(); - bool layeredInHUD = isLayeredInHUD(); - bool wireframe = isWireframe(); - auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; - bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); - transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, - invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { - data.removeMaterial(material); - // if the material changed, we might need to update our item key or shape key - data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); - data.setShapeKey(invalidatePayloadShapeKey, wireframe); - }); - AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +void Model::addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { + std::vector shapeIDs = getMeshIDsFromMaterialID(parentMaterialID); + render::Transaction transaction; + for (auto shapeID : shapeIDs) { + if (shapeID < _modelMeshRenderItemIDs.size()) { + auto itemID = _modelMeshRenderItemIDs[shapeID]; + bool visible = isVisible(); + uint8_t viewTagBits = getViewTagBits(); + bool layeredInFront = isLayeredInFront(); + bool layeredInHUD = isLayeredInHUD(); + bool wireframe = isWireframe(); + auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; + bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, + invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { + data.addMaterial(material); + // if the material changed, we might need to update our item key or shape key + data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); + data.setShapeKey(invalidatePayloadShapeKey, wireframe); + }); + } } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} + +void Model::removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID) { + std::vector shapeIDs = getMeshIDsFromMaterialID(parentMaterialID); + render::Transaction transaction; + for (auto shapeID : shapeIDs) { + if (shapeID < _modelMeshRenderItemIDs.size()) { + auto itemID = _modelMeshRenderItemIDs[shapeID]; + bool visible = isVisible(); + uint8_t viewTagBits = getViewTagBits(); + bool layeredInFront = isLayeredInFront(); + bool layeredInHUD = isLayeredInHUD(); + bool wireframe = isWireframe(); + auto meshIndex = _modelMeshRenderItemShapes[shapeID].meshIndex; + bool invalidatePayloadShapeKey = shouldInvalidatePayloadShapeKey(meshIndex); + transaction.updateItem(itemID, [material, visible, layeredInFront, layeredInHUD, viewTagBits, + invalidatePayloadShapeKey, wireframe](ModelMeshPartPayload& data) { + data.removeMaterial(material); + // if the material changed, we might need to update our item key or shape key + data.updateKey(visible, layeredInFront || layeredInHUD, viewTagBits); + data.setShapeKey(invalidatePayloadShapeKey, wireframe); + }); + } + } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); } class CollisionRenderGeometry : public Geometry { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 80067aff2a..b4152324bc 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -318,8 +318,8 @@ public: void scaleToFit(); - void addMaterial(graphics::MaterialPointer material, quint16 shapeID); - void removeMaterial(graphics::MaterialPointer material, quint16 shapeID); + void addMaterial(graphics::MaterialPointer material, const QString& parentMaterialID); + void removeMaterial(graphics::MaterialPointer material, const QString& parentMaterialID); public slots: void loadURLFinished(bool success); @@ -471,6 +471,8 @@ private: float _loadingPriority { 0.0f }; void calculateTextureInfo(); + + std::vector getMeshIDsFromMaterialID(const QString& parentMaterialID); }; Q_DECLARE_METATYPE(ModelPointer) diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 25b2cec331..4dbbd190ff 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -256,6 +256,13 @@ namespace std { return result; } }; + + template <> + struct hash { + size_t operator()(const QString& a) const { + return qHash(a); + } + }; } enum ContactEventType { diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 348d93d589..5eedd1c7e4 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -780,19 +780,14 @@ -
- - -
-
-
- - +
+ +
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 3558a36c04..01ec4ae283 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -633,9 +633,8 @@ function loaded() { var elMaterialURL = document.getElementById("property-material-url"); var elMaterialMode = document.getElementById("property-material-mode"); - var elBlendFactor = document.getElementById("property-blend-factor"); var elPriority = document.getElementById("property-priority"); - var elShapeID = document.getElementById("property-shape-id"); + var elParentMaterialID = document.getElementById("property-parent-material-id"); var elMaterialPosX = document.getElementById("property-material-pos-x"); var elMaterialPosY = document.getElementById("property-material-pos-y"); var elMaterialScaleX = document.getElementById("property-material-scale-x"); @@ -1130,9 +1129,8 @@ function loaded() { elMaterialURL.value = properties.materialURL; elMaterialMode.value = properties.materialMode; setDropdownText(elMaterialMode); - elBlendFactor.value = properties.blendFactor.toFixed(2); elPriority.value = properties.priority; - elShapeID.value = properties.shapeID; + elParentMaterialID.value = properties.parentMaterialID; elMaterialPosX.value = properties.materialPos.x.toFixed(4); elMaterialPosY.value = properties.materialPos.y.toFixed(4); elMaterialScaleX.value = properties.materialScale.x.toFixed(4); @@ -1410,9 +1408,8 @@ function loaded() { elMaterialURL.addEventListener('change', createEmitTextPropertyUpdateFunction('materialURL')); elMaterialMode.addEventListener('change', createEmitTextPropertyUpdateFunction('materialMode')); - elBlendFactor.addEventListener('change', createEmitNumberPropertyUpdateFunction('blendFactor', 2)); elPriority.addEventListener('change', createEmitNumberPropertyUpdateFunction('priority', 0)); - elShapeID.addEventListener('change', createEmitNumberPropertyUpdateFunction('shapeID', 0)); + elParentMaterialID.addEventListener('change', createEmitTextPropertyUpdateFunction('parentMaterialID')); var materialPosChangeFunction = createEmitVec2PropertyUpdateFunction('materialPos', elMaterialPosX, elMaterialPosY); elMaterialPosX.addEventListener('change', materialPosChangeFunction); From ad409618640071ca84824765c656b7467a53ac19 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 12 Feb 2018 13:46:27 -0800 Subject: [PATCH 14/53] fix tangents (I think), update material rendering when transform changes --- .../src/RenderableMaterialEntityItem.cpp | 13 ++++++++++++- .../src/RenderableMaterialEntityItem.h | 3 +++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index ad17202d8e..529aa03124 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -18,6 +18,9 @@ bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP if (entity->getParentID() != _parentID || entity->getClientOnly() != _clientOnly || entity->getOwningAvatarID() != _owningAvatarID) { return true; } + if (entity->getMaterialPos() != _materialPos || entity->getMaterialScale() != _materialScale || entity->getMaterialRot() != _materialRot) { + return true; + } return false; } @@ -27,6 +30,9 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& _parentID = entity->getParentID(); _clientOnly = entity->getClientOnly(); _owningAvatarID = entity->getOwningAvatarID(); + _materialPos = entity->getMaterialPos(); + _materialScale = entity->getMaterialScale(); + _materialRot = entity->getMaterialRot(); _renderTransform = getModelTransform(); const float MATERIAL_ENTITY_SCALE = 0.5f; _renderTransform.postScale(MATERIAL_ENTITY_SCALE); @@ -91,7 +97,7 @@ glm::vec3 MaterialEntityRenderer::getVertexPos(float phi, float theta) { } glm::vec3 MaterialEntityRenderer::getTangent(float phi, float theta) { - return glm::vec3(-glm::cos(theta) * glm::cos(phi), 0, -glm::cos(theta) * glm::sin(phi)); + return glm::vec3(-glm::cos(theta) * glm::cos(phi), glm::sin(theta), -glm::cos(theta) * glm::sin(phi)); } void MaterialEntityRenderer::addVertex(std::vector& buffer, const glm::vec3& pos, const glm::vec3& tan, const glm::vec2 uv) { @@ -227,16 +233,21 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { QUuid parentID; Transform renderTransform; graphics::MaterialPointer drawMaterial; + Transform textureTransform; withReadLock([&] { parentID = _clientOnly ? _owningAvatarID : _parentID; renderTransform = _renderTransform; drawMaterial = _drawMaterial; + textureTransform.setTranslation(glm::vec3(_materialPos, 0)); + textureTransform.setRotation(glm::vec3(0, 0, glm::radians(_materialRot))); + textureTransform.setScale(glm::vec3(_materialScale, 1)); }); if (!parentID.isNull() || !drawMaterial) { return; } batch.setModelTransform(renderTransform); + drawMaterial->setTextureTransforms(textureTransform); // bind the material args->_shapePipeline->bindMaterial(drawMaterial, batch, args->_enableTexturing); diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index af8cef9351..4af21d84f6 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -34,6 +34,9 @@ private: QUuid _parentID; bool _clientOnly; QUuid _owningAvatarID; + glm::vec2 _materialPos; + glm::vec2 _materialScale; + float _materialRot; Transform _renderTransform; std::shared_ptr _drawMaterial; From 5048bf16cb62260c03c7f47720ca63de61aaa8ba Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 12 Feb 2018 23:01:19 +0000 Subject: [PATCH 15/53] Fixed Async Prompts/Assets/Dialogs --- interface/src/scripting/WindowScriptingInterface.cpp | 11 +++++++---- libraries/ui/src/OffscreenUi.cpp | 9 ++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index fc45555bf9..d61823e9ee 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -120,16 +120,19 @@ QScriptValue WindowScriptingInterface::confirm(const QString& message) { /// \param const QString& defaultText default text in the text box /// \return QScriptValue string text value in text box if the dialog was accepted, `null` otherwise. QScriptValue WindowScriptingInterface::prompt(const QString& message, const QString& defaultText) { - bool ok = false; - QString result = OffscreenUi::getText(nullptr, "", message, QLineEdit::Normal, defaultText, &ok); - return ok ? QScriptValue(result) : QScriptValue::NullValue; + QString result = OffscreenUi::getText(nullptr, "", message, QLineEdit::Normal, defaultText); + if (QScriptValue(result).equals("")) { + return QScriptValue::NullValue; + } + return QScriptValue(result); } /// Display a prompt with a text box /// \param const QString& message message to display /// \param const QString& defaultText default text in the text box void WindowScriptingInterface::promptAsync(const QString& message, const QString& defaultText) { - ModalDialogListener* dlg = OffscreenUi::getTextAsync(nullptr, "", message, QLineEdit::Normal, defaultText); + bool ok = false; + ModalDialogListener* dlg = OffscreenUi::getTextAsync(nullptr, "", message, QLineEdit::Normal, defaultText, &ok); connect(dlg, &ModalDialogListener::response, this, [=] (QVariant result) { disconnect(dlg, &ModalDialogListener::response, this, nullptr); emit promptTextChanged(result.toString()); diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 221f5013bf..2bea2bbd91 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -336,10 +336,11 @@ class InputDialogListener : public ModalDialogListener { return; } connect(_dialog, SIGNAL(selected(QVariant)), this, SLOT(onSelected(const QVariant&))); + connect(_dialog, SIGNAL(canceled()), this, SLOT(onSelected())); } private slots: - void onSelected(const QVariant& result) { + void onSelected(const QVariant& result = "") { _result = result; auto offscreenUi = DependencyManager::get(); emit response(_result); @@ -700,10 +701,11 @@ class FileDialogListener : public ModalDialogListener { return; } connect(_dialog, SIGNAL(selectedFile(QVariant)), this, SLOT(onSelectedFile(QVariant))); + connect(_dialog, SIGNAL(canceled()), this, SLOT(onSelectedFile())); } private slots: - void onSelectedFile(QVariant file) { + void onSelectedFile(QVariant file = "") { _result = file.toUrl().toLocalFile(); _finished = true; auto offscreenUi = DependencyManager::get(); @@ -949,10 +951,11 @@ class AssetDialogListener : public ModalDialogListener { return; } connect(_dialog, SIGNAL(selectedAsset(QVariant)), this, SLOT(onSelectedAsset(QVariant))); + connect(_dialog, SIGNAL(canceled()), this, SLOT(onSelectedAsset())); } private slots: - void onSelectedAsset(QVariant asset) { + void onSelectedAsset(QVariant asset = "") { _result = asset; auto offscreenUi = DependencyManager::get(); emit response(_result); From ddcee05b14637a342dd286c93482fba289300a0f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 13 Feb 2018 09:41:00 -0800 Subject: [PATCH 16/53] added control button for controller API --- interface/resources/controllers/keyboardMouse.json | 4 ++-- .../src/input-plugins/KeyboardMouseDevice.cpp | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index 54d2467f78..b3f16a115e 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -88,8 +88,8 @@ ] }, - { "from": "Keyboard.W", "to": "Actions.LONGITUDINAL_FORWARD" }, - { "from": "Keyboard.S", "to": "Actions.LONGITUDINAL_BACKWARD" }, + { "from": "Keyboard.W", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_FORWARD" }, + { "from": "Keyboard.S", "when": "!Keyboard.Control", "to": "Actions.LONGITUDINAL_BACKWARD" }, { "from": "Keyboard.C", "to": "Actions.VERTICAL_DOWN" }, { "from": "Keyboard.E", "to": "Actions.VERTICAL_UP" }, { "from": "Keyboard.Left", "when": "Keyboard.RightMouseButton", "to": "Actions.LATERAL_LEFT" }, diff --git a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp index e9ec6d8910..ef7f482e44 100755 --- a/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp +++ b/libraries/input-plugins/src/input-plugins/KeyboardMouseDevice.cpp @@ -54,11 +54,9 @@ void KeyboardMouseDevice::InputDevice::focusOutEvent() { void KeyboardMouseDevice::keyPressEvent(QKeyEvent* event) { auto input = _inputDevice->makeInput((Qt::Key) event->key()); - if (!(event->modifiers() & Qt::KeyboardModifier::ControlModifier)) { - auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel()); - if (result.second) { - // key pressed again ? without catching the release event ? - } + auto result = _inputDevice->_buttonPressedMap.insert(input.getChannel()); + if (result.second) { + // key pressed again ? without catching the release event ? } } @@ -237,6 +235,7 @@ controller::Input::NamedVector KeyboardMouseDevice::InputDevice::getAvailableInp availableInputs.append(Input::NamedPair(makeInput(Qt::Key_PageUp), QKeySequence(Qt::Key_PageUp).toString())); availableInputs.append(Input::NamedPair(makeInput(Qt::Key_PageDown), QKeySequence(Qt::Key_PageDown).toString())); availableInputs.append(Input::NamedPair(makeInput(Qt::Key_Tab), QKeySequence(Qt::Key_Tab).toString())); + availableInputs.append(Input::NamedPair(makeInput(Qt::Key_Control), "Control")); availableInputs.append(Input::NamedPair(makeInput(Qt::LeftButton), "LeftMouseButton")); availableInputs.append(Input::NamedPair(makeInput(Qt::MiddleButton), "MiddleMouseButton")); From cf3d8e446376e4a4f4b9c3b637b8b835533c8892 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 13 Feb 2018 11:07:15 -0800 Subject: [PATCH 17/53] remove cached file --- interface/resources/qml/js/Utils.jsc | Bin 6516 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 interface/resources/qml/js/Utils.jsc diff --git a/interface/resources/qml/js/Utils.jsc b/interface/resources/qml/js/Utils.jsc deleted file mode 100644 index 8da68e4e192018ee2b4f3d835ec91f36f0161eca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6516 zcmcIoZDrF4*+OKP^~mxE_StR<97M?dYinHhXIH0prUNWm)BPSkkxI9zIccH zbDYc+&t`mYYoRZ%dcNJC7t6S;1kom{uKi%kZQQ*B-}@Ea#y#@Sit;ack*DT2py=+} zfuFX0y&bsG4t&xMe9-`o8bF@`3>v_=0VE9IX#==m0KYMS=MCVp0laDeYXyq{m#>ENBdlKi6Kn!P8Tz-gSf=^W4f1vJz z>OP?E{p$W>bw7z?g5MlwFfTkK{Y3k0%wPWl) z&?-R|Nd~OQ(pqO|>7zFD;=ilaYBV{~8D84z4za!=ysGK#f#f15cOtKd^CTCgW+(F3YvinYJCd&`a))r0Mo85U*Q-9!M*I7$0`-qB z_gRHiN|Dr;D9>%Ew0z6Wn-=@9$24G=wcYQAKr;$=G(+YT?S4gBPFhi3D=YPBjMwP(DtXg0@d zG_^09dbG0=GK0s0m5|xhXBFIQ_sX@rd#zip<)W#5p*M~l7I0kJ>Rx3@lVReJ;DNwB zDyZ3=2tQI@%!JdrBFuEc?sBA(9kgr3Y_aT2sk*B@nIUjOEkzeu#m^h8RqKk4g`M3sB#sj3Z zin4^&CHb`Bz^YaPh9305YFR;C*(6#-3l|K#%Uq~N?&pFYMV^-~(A@o8!1hi6=630V z=D8$YpkTiX7yMeo-YZonuRF86K3C#h$;)v~gtsnv`C8)2tn*te(mN*CdaZPdOV`he z*)_jyCu3zh886w%`HhxMf1eQDtm(Upqbj0Vx%OZr)gDguj!@-{XXzA|(w?PRE?x30 zEpTbky|hS!BgqTa0w)epy`_*v_84x=)^DWM#;N*^jM^Bf-(bR$)d{)5D$iF5i3b%r z#w^&U)1~N17geDbU5O$&)0=CYvjc#Aq(q)qH~AvR+Mm@cT4=hL1Xn8N@U?K^55MR2@%P2jgn8(i`O7~6 zxK$c)64LT_sgcZ&vec+z2H&rkC;mPWHh*!|K2jnUvlTP=pUo?u3hWUVoWmK4R^9)I zAzh!oRhDhE@4~X)XSJ_SUh|m1>hz)>Epi;v7^*bQ;}j93m2wi&RX?}-C7*gUq#NI@ zGOc58rVV>dQzIEaEO@PCVBLT$(j!F`RMAv8#^*$lYgTusRYURAwMF8EZetxI82B+s z`z+1wmz6ELSf7j!Xm+HgDrNgfDV*#t+ROb#9?Zyt{A%Rsvj0*NGhTn2Ds33J1MhAU zlsa=S4A+@{l}G8soHY(5De)+!Qogr%YCETuPj1^b!^~uX&&5@)|bMPIn zYR$nz?l-^k>yW^`7fQN$B&>{o^T;%79xpqkx?C&O8g-&Yt<(Ukr3_kWe<|r^QX-BN zry-R27SG-x}NZM;N{71_wRxwXjRK=*ls0BKHr)#V_Lkxd5bo6SDGTeHa_CrUP zBCi|1{m}7&DsBaO^KwJnp0@J-amzQ0+i%-y?QXk(T}a-t~cHo^z>QDFD)6)fXCSbJk% eP^J00or-VRsaUCE2A`?b=Mm4BnYXId>i+-+$aWzB From f64e5f2444343bd15a05dc0fee9fdb65477efc61 Mon Sep 17 00:00:00 2001 From: samcake Date: Tue, 13 Feb 2018 13:06:26 -0800 Subject: [PATCH 18/53] Introducing the cull group --- .../src/avatars-renderer/Avatar.cpp | 2 +- libraries/render/src/render/CullTask.cpp | 24 +++++++++++++++++++ libraries/render/src/render/Item.cpp | 10 ++++++++ libraries/render/src/render/Item.h | 19 +++++++++++++++ .../src/render/RenderFetchCullSortTask.cpp | 4 ++-- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index 86635cd3bf..9cdd4e2d00 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -50,7 +50,7 @@ const glm::vec3 HAND_TO_PALM_OFFSET(0.0f, 0.12f, 0.08f); namespace render { template <> const ItemKey payloadGetKey(const AvatarSharedPointer& avatar) { - return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1); + return ItemKey::Builder::opaqueShape().withTypeMeta().withTagBits(ItemKey::TAG_BITS_0 | ItemKey::TAG_BITS_1).withCullGroup(); } template <> const Item::Bound payloadGetBound(const AvatarSharedPointer& avatar) { return static_pointer_cast(avatar)->getBounds(); diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 4dec3030ef..467cf5adbf 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -227,6 +227,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -239,6 +242,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -251,6 +257,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -263,6 +272,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -277,6 +289,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (filter.test(item.getKey())) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -290,6 +305,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, ItemBound itemBound(id, item.getBound()); if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -304,6 +322,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, ItemBound itemBound(id, item.getBound()); if (test.frustumTest(itemBound.bound)) { outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } @@ -319,6 +340,9 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, if (test.frustumTest(itemBound.bound)) { if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); + if (item.getKey().isCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); + } } } } diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 612dba076b..b8ca091c40 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -113,6 +113,16 @@ const ShapeKey Item::getShapeKey() const { return shapeKey; } +uint32_t Item::fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const { + ItemIDs subItems; + auto numSubs = fetchMetaSubItems(subItems); + + for (auto id : subItems) { + subItemBounds.emplace_back(id, scene.getItem(id).getBound()); + } + return numSubs; +} + namespace render { template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload) { if (!payload) { diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index ff4b3a0458..3c82e49e8d 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -78,11 +78,13 @@ public: INVISIBLE, // Visible or not in the scene? SHADOW_CASTER, // Item cast shadows LAYERED, // Item belongs to one of the layers different from the default layer + CULL_GROUP, // As a meta item, the culling of my sub items is based solely on my bounding box and my visibility in the FIRST_TAG_BIT, // 8 Tags available to organize the items and filter them against LAST_TAG_BIT = FIRST_TAG_BIT + NUM_TAGS, __SMALLER, // Reserved bit for spatialized item to indicate that it is smaller than expected in the cell in which it belongs (probably because it overlaps over several smaller cells) + __META_CULLED, // Reserved bit for sub item of a meta render item to indicate that the culling is tied to the culling of the meta render item, not this one NUM_FLAGS, // Not a valid flag }; @@ -122,6 +124,7 @@ public: Builder& withInvisible() { _flags.set(INVISIBLE); return (*this); } Builder& withShadowCaster() { _flags.set(SHADOW_CASTER); return (*this); } Builder& withLayered() { _flags.set(LAYERED); return (*this); } + Builder& withCullGroup() { _flags.set(CULL_GROUP); return (*this); } Builder& withTag(Tag tag) { _flags.set(FIRST_TAG_BIT + tag); return (*this); } // Set ALL the tags in one call using the Tag bits @@ -132,6 +135,9 @@ public: static Builder transparentShape() { return Builder().withTypeShape().withTransparent(); } static Builder light() { return Builder().withTypeLight(); } static Builder background() { return Builder().withViewSpace().withLayered(); } + + // Not meant to be public, part of the inner item / key / filter system + Builder& __withMetaCulled() { _flags.set(__META_CULLED); return (*this); } }; ItemKey(const Builder& builder) : ItemKey(builder._flags) {} @@ -159,6 +165,9 @@ public: bool isLayered() const { return _flags[LAYERED]; } bool isSpatial() const { return !isLayered(); } + bool isCullGroup() const { return _flags[CULL_GROUP]; } + void setCullGroup(bool cullGroup) { (cullGroup ? _flags.set(CULL_GROUP) : _flags.reset(CULL_GROUP)); } + bool isTag(Tag tag) const { return _flags[FIRST_TAG_BIT + tag]; } uint8_t getTagBits() const { return ((_flags.to_ulong() & KEY_TAG_BITS_MASK) >> FIRST_TAG_BIT); } @@ -166,6 +175,9 @@ public: bool isSmall() const { return _flags[__SMALLER]; } void setSmaller(bool smaller) { (smaller ? _flags.set(__SMALLER) : _flags.reset(__SMALLER)); } + bool isMetaCulled() const { return _flags[__META_CULLED]; } + void setMetaCulled(bool metaCulled) { (metaCulled ? _flags.set(__META_CULLED) : _flags.reset(__META_CULLED)); } + bool operator==(const ItemKey& key) { return (_flags == key._flags); } bool operator!=(const ItemKey& key) { return (_flags != key._flags); } }; @@ -221,6 +233,12 @@ public: Builder& withoutLayered() { _value.reset(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); } Builder& withLayered() { _value.set(ItemKey::LAYERED); _mask.set(ItemKey::LAYERED); return (*this); } + Builder& withoutCullGroup() { _value.reset(ItemKey::CULL_GROUP); _mask.set(ItemKey::CULL_GROUP); return (*this); } + Builder& withCullGroup() { _value.set(ItemKey::CULL_GROUP); _mask.set(ItemKey::CULL_GROUP); return (*this); } + + Builder& withoutMetaCulled() { _value.reset(ItemKey::__META_CULLED); _mask.set(ItemKey::__META_CULLED); return (*this); } + Builder& withMetaCulled() { _value.set(ItemKey::__META_CULLED); _mask.set(ItemKey::__META_CULLED); return (*this); } + Builder& withoutTag(ItemKey::Tag tagIndex) { _value.reset(ItemKey::FIRST_TAG_BIT + tagIndex); _mask.set(ItemKey::FIRST_TAG_BIT + tagIndex); return (*this); } Builder& withTag(ItemKey::Tag tagIndex) { _value.set(ItemKey::FIRST_TAG_BIT + tagIndex); _mask.set(ItemKey::FIRST_TAG_BIT + tagIndex); return (*this); } // Set ALL the tags in one call using the Tag bits and the Tag bits touched @@ -420,6 +438,7 @@ public: // Meta Type Interface uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } + uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const; // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 6fb9ba88aa..4fe5e2f1be 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -22,7 +22,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin // CPU jobs: // Fetch and cull the items from the scene - const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered().withTagBits(tagBits, tagMask); + const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered().withoutMetaCulled().withTagBits(tagBits, tagMask); const auto spatialFilter = render::Varying(filter); const auto fetchInput = FetchSpatialTree::Inputs(filter, glm::ivec2(0,0)).asVarying(); const auto spatialSelection = task.addJob("FetchSceneSelection", fetchInput); @@ -30,7 +30,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto culledSpatialSelection = task.addJob("CullSceneSelection", cullInputs, cullFunctor, RenderDetails::ITEM); // Overlays are not culled - const ItemFilter overlayfilter = ItemFilter::Builder().withVisible().withTagBits(tagBits, tagMask); + const ItemFilter overlayfilter = ItemFilter::Builder().withVisible().withoutMetaCulled().withTagBits(tagBits, tagMask); const auto nonspatialFilter = render::Varying(overlayfilter); const auto nonspatialSelection = task.addJob("FetchOverlaySelection", nonspatialFilter); From 8cd00c49d6bf9820a4814bf3afd3edc4b7f56dee Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 13 Feb 2018 13:21:40 -0800 Subject: [PATCH 19/53] PAL: Prevent opening of Availability from WebView --- interface/resources/qml/hifi/Pal.qml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/Pal.qml b/interface/resources/qml/hifi/Pal.qml index 02971cc984..bb54ba9e57 100644 --- a/interface/resources/qml/hifi/Pal.qml +++ b/interface/resources/qml/hifi/Pal.qml @@ -48,7 +48,7 @@ Rectangle { // The letterbox used for popup messages LetterboxMessage { id: letterboxMessage; - z: 999; // Force the popup on top of everything else + z: 998; // Force the popup on top of everything else } Connections { target: GlobalServices @@ -60,7 +60,7 @@ Rectangle { // The ComboDialog used for setting availability ComboDialog { id: comboDialog; - z: 999; // Force the ComboDialog on top of everything else + z: 998; // Force the ComboDialog on top of everything else dialogWidth: parent.width - 50; dialogHeight: parent.height - 100; } @@ -1013,7 +1013,7 @@ Rectangle { } MouseArea { anchors.fill: parent; - enabled: myData.userName !== "Unknown user"; + enabled: myData.userName !== "Unknown user" && !userInfoViewer.visible; hoverEnabled: true; onClicked: { popupComboDialog("Set your availability:", @@ -1044,6 +1044,7 @@ Rectangle { HifiControls.TabletWebView { id: userInfoViewer; + z: 999; anchors { top: parent.top; bottom: parent.bottom; From 38290064c1c6510f2d3dd6b2333c03ef7dd2b6a8 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 13 Feb 2018 13:24:08 -0800 Subject: [PATCH 20/53] replace materials by name, hide material mode for now --- libraries/entities/src/MaterialEntityItem.cpp | 8 ++- libraries/entities/src/MaterialEntityItem.h | 29 +++++++++-- libraries/graphics/src/graphics/Material.cpp | 3 ++ libraries/graphics/src/graphics/Material.h | 5 ++ .../src/model-networking/ModelCache.cpp | 1 + libraries/render-utils/src/Model.cpp | 24 +++++++-- libraries/render-utils/src/Model.h | 3 +- scripts/system/html/entityProperties.html | 34 ++++++++----- scripts/system/html/js/entityProperties.js | 49 ++++++++++++++++--- 9 files changed, 126 insertions(+), 30 deletions(-) diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 1ebaa4f21a..fcca2d9803 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -346,8 +346,12 @@ void MaterialEntityItem::applyMaterial() { } void MaterialEntityItem::postAdd() { - removeMaterial(); - applyMaterial(); + // postAdd is called every time we are added to a new octree cell, but we only need to update the material the first time + if (!_hasBeenAddedToOctree) { + removeMaterial(); + applyMaterial(); + _hasBeenAddedToOctree = true; + } } void MaterialEntityItem::preDelete() { diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index dde9b60da9..d015bae681 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -19,7 +19,7 @@ class MaterialEntityItem : public EntityItem { using Pointer = std::shared_ptr; public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); - + MaterialEntityItem(const EntityItemID& entityItemID); ALLOW_INSTANTIATION // This class can be instantiated @@ -44,9 +44,9 @@ public: virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead, - ReadBitstreamToTreeParams& args, - EntityPropertyFlags& propertyFlags, bool overwriteLocalData, - bool& somethingChanged) override; + ReadBitstreamToTreeParams& args, + EntityPropertyFlags& propertyFlags, bool overwriteLocalData, + bool& somethingChanged) override; void debugDump() const override; @@ -89,20 +89,39 @@ public: void postParentFixup() override; private: + // URL for this material. Currently, only JSON format is supported. Set to "userData" to use the user data to live edit a material. + // The following fields are supported in the JSON: + // strings: + // name (NOT YET USED) + // floats: + // opacity, roughness, metallic, scattering + // colors (arrays of 3 floats 0-1. Optional fourth value in array can be a boolean isSRGB): + // emissive, albedo, fresnel + // urls to textures: + // emissiveMap, albedoMap, metallicMap, roughnessMap, normalMap, occlusionMap, lightmapMap, scatteringMap QString _materialURL; + // Type of material. "uv" or "projected". NOT YET IMPLEMENTED, only UV is used MaterialMode _materialMode { UV }; + // Priority for this material when applying it to its parent. Only the highest priority material will be used. Materials with the same priority are (essentially) randomly sorted. + // Base materials that come with models always have priority 0. quint16 _priority { 0 }; + // An identifier for choosing a submesh or submeshes within a parent. If in the format "mat::", all submeshes with material name "" will be replaced. Otherwise, + // parentMaterialID will be parsed as an unsigned int (strings not starting with "mat::" will parse to 0), representing the mesh index to modify. QString _parentMaterialID { "0" }; + // Offset position in UV-space of top left of material, (0, 0) to (1, 1) glm::vec2 _materialPos { 0, 0 }; + // How much to scale this material within its parent's UV-space glm::vec2 _materialScale { 1, 1 }; + // How much to rotate this material within its parent's UV-space (degrees) float _materialRot { 0 }; - + NetworkMaterialResourcePointer _networkMaterial; QHash> _materials; std::vector _materialNames; QString _currentMaterialName; bool _retryApply { false }; + bool _hasBeenAddedToOctree { false }; }; diff --git a/libraries/graphics/src/graphics/Material.cpp b/libraries/graphics/src/graphics/Material.cpp index 7c66c8ab07..2bf58bc6fb 100755 --- a/libraries/graphics/src/graphics/Material.cpp +++ b/libraries/graphics/src/graphics/Material.cpp @@ -34,6 +34,7 @@ Material::Material() : } Material::Material(const Material& material) : + _name(material._name), _key(material._key), _textureMaps(material._textureMaps) { @@ -50,6 +51,8 @@ Material::Material(const Material& material) : Material& Material::operator= (const Material& material) { QMutexLocker locker(&_textureMapsMutex); + _name = material._name; + _key = (material._key); _textureMaps = (material._textureMaps); _hasCalculatedTextureInfo = false; diff --git a/libraries/graphics/src/graphics/Material.h b/libraries/graphics/src/graphics/Material.h index 5b3396dfc5..5abc090be3 100755 --- a/libraries/graphics/src/graphics/Material.h +++ b/libraries/graphics/src/graphics/Material.h @@ -359,6 +359,11 @@ public: void setTextureTransforms(const Transform& transform); + const QString& getName() { return _name; } + +protected: + QString _name { "" }; + private: mutable MaterialKey _key; mutable UniformBufferView _schemaBuffer; diff --git a/libraries/model-networking/src/model-networking/ModelCache.cpp b/libraries/model-networking/src/model-networking/ModelCache.cpp index 739f401ee7..19ee05d1e2 100644 --- a/libraries/model-networking/src/model-networking/ModelCache.cpp +++ b/libraries/model-networking/src/model-networking/ModelCache.cpp @@ -619,6 +619,7 @@ NetworkMaterial::NetworkMaterial(const FBXMaterial& material, const QUrl& textur graphics::Material(*material._material), _textures(MapChannel::NUM_MAP_CHANNELS) { + _name = material.name; if (!material.albedoTexture.filename.isEmpty()) { auto map = fetchTextureMap(textureBaseUrl, material.albedoTexture, image::TextureUsage::ALBEDO_TEXTURE, MapChannel::ALBEDO_MAP); _albedoTransform = material.albedoTexture.transform; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3a9ea45d77..84687a46d0 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -828,6 +828,7 @@ void Model::removeFromScene(const render::ScenePointer& scene, render::Transacti _modelMeshRenderItemIDs.clear(); _modelMeshRenderItemsMap.clear(); _modelMeshRenderItems.clear(); + _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); foreach(auto item, _collisionRenderItemsMap.keys()) { @@ -1456,6 +1457,7 @@ void Model::createVisibleRenderItemSet() { Q_ASSERT(_modelMeshRenderItems.isEmpty()); _modelMeshRenderItems.clear(); + _modelMeshMaterialNames.clear(); _modelMeshRenderItemShapes.clear(); Transform transform; @@ -1479,6 +1481,7 @@ void Model::createVisibleRenderItemSet() { int numParts = (int)mesh->getNumParts(); for (int partIndex = 0; partIndex < numParts; partIndex++) { _modelMeshRenderItems << std::make_shared(shared_from_this(), i, partIndex, shapeID, transform, offset); + _modelMeshMaterialNames.push_back(getGeometry()->getShapeMaterial(shapeID)->getName()); _modelMeshRenderItemShapes.emplace_back(ShapeInfo{ (int)i }); shapeID++; } @@ -1524,11 +1527,24 @@ bool Model::isRenderable() const { return !_meshStates.empty() || (isLoaded() && _renderGeometry->getMeshes().empty()); } -std::vector Model::getMeshIDsFromMaterialID(const QString& parentMaterialID) { - std::vector toReturn; - // TODO: first, try to find all meshes with materials that match parentMaterialID as a string +std::vector Model::getMeshIDsFromMaterialID(QString parentMaterialID) { + // try to find all meshes with materials that match parentMaterialID as a string // if none, return parentMaterialID as a uint - toReturn.push_back(parentMaterialID.toUInt()); + std::vector toReturn; + const QString MATERIAL_NAME_PREFIX = "mat::"; + if (parentMaterialID.startsWith(MATERIAL_NAME_PREFIX)) { + parentMaterialID.replace(0, MATERIAL_NAME_PREFIX.size(), QString("")); + for (int i = 0; i < _modelMeshMaterialNames.size(); i++) { + if (_modelMeshMaterialNames[i] == parentMaterialID) { + toReturn.push_back(i); + } + } + } + + if (toReturn.empty()) { + toReturn.push_back(parentMaterialID.toUInt()); + } + return toReturn; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index b4152324bc..67bc646473 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -438,6 +438,7 @@ protected: render::ItemIDs _modelMeshRenderItemIDs; using ShapeInfo = struct { int meshIndex; }; std::vector _modelMeshRenderItemShapes; + std::vector _modelMeshMaterialNames; bool _addedToScene { false }; // has been added to scene bool _needsFixupInScene { true }; // needs to be removed/re-added to scene @@ -472,7 +473,7 @@ private: void calculateTextureInfo(); - std::vector getMeshIDsFromMaterialID(const QString& parentMaterialID); + std::vector getMeshIDsFromMaterialID(QString parentMaterialID); }; Q_DECLARE_METATYPE(ModelPointer) diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 5eedd1c7e4..a70e42a7e1 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -772,12 +772,19 @@
-