From bc319cb3401c0ee742a1bb9333d0a6df0881d3cc Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sat, 11 Jan 2020 22:29:07 -0800 Subject: [PATCH 001/105] zone occlusion --- interface/src/graphics/WorldBox.h | 4 - .../src/RenderableEntityItem.cpp | 27 +++++- .../src/RenderableEntityItem.h | 4 + .../src/RenderableModelEntityItem.cpp | 10 +++ .../src/RenderableModelEntityItem.h | 1 + .../src/RenderableTextEntityItem.cpp | 19 +++++ .../src/RenderableTextEntityItem.h | 2 + .../src/RenderableZoneEntityItem.cpp | 7 ++ libraries/entities/src/EntityItem.cpp | 20 +++++ libraries/entities/src/EntityItem.h | 8 ++ .../entities/src/EntityItemProperties.cpp | 15 ++++ libraries/entities/src/EntityItemProperties.h | 1 + .../entities/src/EntityItemPropertiesMacros.h | 7 ++ libraries/entities/src/EntityPropertyFlags.h | 1 + libraries/networking/src/udt/PacketHeaders.h | 1 + libraries/octree/src/OctreePacketData.cpp | 22 +++++ libraries/octree/src/OctreePacketData.h | 4 + .../render-utils/src/MeshPartPayload.cpp | 28 ++++++- libraries/render-utils/src/MeshPartPayload.h | 6 ++ libraries/render-utils/src/Model.cpp | 10 +++ libraries/render-utils/src/Model.h | 2 + libraries/render/src/render/Args.h | 10 +-- libraries/render/src/render/CullTask.cpp | 84 +++++++------------ libraries/render/src/render/CullTask.h | 16 ++-- libraries/render/src/render/Item.cpp | 6 ++ libraries/render/src/render/Item.h | 13 ++- .../src/render/RenderFetchCullSortTask.cpp | 1 + libraries/shared/src/RegisteredMetaTypes.cpp | 18 ++++ libraries/shared/src/RegisteredMetaTypes.h | 2 + 29 files changed, 272 insertions(+), 77 deletions(-) diff --git a/interface/src/graphics/WorldBox.h b/interface/src/graphics/WorldBox.h index 114777ba0f..4d53652c0e 100644 --- a/interface/src/graphics/WorldBox.h +++ b/interface/src/graphics/WorldBox.h @@ -19,8 +19,6 @@ #include #include "Menu.h" - - class WorldBoxRenderData { public: typedef render::Payload Payload; @@ -29,8 +27,6 @@ public: int _val = 0; static render::ItemID _item; // unique WorldBoxRenderData - - static void renderWorldBox(RenderArgs* args, gpu::Batch& batch); }; diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index ae56a8fc47..dcf90cd966 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -128,7 +128,7 @@ std::shared_ptr make_renderer(const EntityItemPointer& entity) { return std::shared_ptr(new T(entity), [](T* ptr) { ptr->deleteLater(); }); } -EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entity->getCreated()), _entity(entity) {} +EntityRenderer::EntityRenderer(const EntityItemPointer& entity) : _created(entity->getCreated()), _entity(entity), _entityID(entity->getID()) {} EntityRenderer::~EntityRenderer() {} @@ -196,6 +196,23 @@ uint32_t EntityRenderer::metaFetchMetaSubItems(ItemIDs& subItems) const { return 0; } +bool EntityRenderer::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + auto renderWithZones = resultWithReadLock>([&] { + return _renderWithZones; + }); + if (!renderWithZones.isEmpty()) { + if (!containingZones.empty()) { + for (auto renderWithZone : renderWithZones) { + if (containingZones.find(renderWithZone) != containingZones.end()) { + return true; + } + } + } + return false; + } + return true; +} + void EntityRenderer::render(RenderArgs* args) { if (!isValidRenderItem()) { return; @@ -385,6 +402,10 @@ bool EntityRenderer::needsRenderUpdateFromEntity(const EntityItemPointer& entity return true; } + if (entity->needsZoneOcclusionUpdate()) { + return true; + } + return false; } @@ -426,6 +447,10 @@ void EntityRenderer::doRenderUpdateSynchronous(const ScenePointer& scene, Transa _canCastShadow = entity->getCanCastShadow(); setCullWithParent(entity->getCullWithParent()); _cauterized = entity->getCauterized(); + if (entity->needsZoneOcclusionUpdate()) { + entity->resetNeedsZoneOcclusionUpdate(); + setRenderWithZones(entity->getRenderWithZones()); + } entity->setNeedsRenderUpdate(false); }); } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.h b/libraries/entities-renderer/src/RenderableEntityItem.h index 227eb6a018..9c787d82c2 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.h +++ b/libraries/entities-renderer/src/RenderableEntityItem.h @@ -65,6 +65,7 @@ public: virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const override; virtual Item::Bound getBound() override; + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override; protected: virtual bool needsRenderUpdateFromEntity() const final { return needsRenderUpdateFromEntity(_entity); } @@ -109,6 +110,7 @@ protected: virtual void setRenderLayer(RenderLayer value) { _renderLayer = value; } virtual void setPrimitiveMode(PrimitiveMode value) { _primitiveMode = value; } virtual void setCullWithParent(bool value) { _cullWithParent = value; } + virtual void setRenderWithZones(const QVector& renderWithZones) { _renderWithZones = renderWithZones; } template T withReadLockResult(const std::function& f) { @@ -143,6 +145,7 @@ protected: bool _cullWithParent { false }; RenderLayer _renderLayer { RenderLayer::WORLD }; PrimitiveMode _primitiveMode { PrimitiveMode::SOLID }; + QVector _renderWithZones; bool _cauterized { false }; bool _moving { false }; // Only touched on the rendering thread @@ -153,6 +156,7 @@ protected: std::mutex _materialsLock; quint64 _created; + QUuid _entityID; // The base class relies on comparing the model transform to the entity transform in order // to trigger an update, so the member must not be visible to derived classes as a modifiable diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5fbbdfa0b8..107890cd21 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1324,6 +1324,9 @@ void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& sce setKey(didVisualGeometryRequestSucceed); _model->setTagMask(getTagMask()); _model->setHifiRenderLayer(getHifiRenderLayer()); + _model->setPrimitiveMode(_primitiveMode); + _model->setCullWithParent(_cullWithParent); + _model->setRenderWithZones(_renderWithZones); emit requestRenderUpdate(); if(didVisualGeometryRequestSucceed) { emit DependencyManager::get()-> @@ -1507,6 +1510,13 @@ void ModelEntityRenderer::setCullWithParent(bool value) { } } +void ModelEntityRenderer::setRenderWithZones(const QVector& renderWithZones) { + Parent::setRenderWithZones(renderWithZones); + if (_model) { + _model->setRenderWithZones(renderWithZones); + } +} + // NOTE: this only renders the "meta" portion of the Model, namely it renders debugging items void ModelEntityRenderer::doRender(RenderArgs* args) { DETAILED_PROFILE_RANGE(render_detail, "MetaModelRender"); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 0119c7bc26..84384532d0 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -165,6 +165,7 @@ protected: void setRenderLayer(RenderLayer value) override; void setPrimitiveMode(PrimitiveMode value) override; void setCullWithParent(bool value) override; + void setRenderWithZones(const QVector& renderWithZones) override; private: void animate(const TypedEntityPointer& entity); diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp index fbd10e2f5b..2ba1acea11 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.cpp @@ -289,6 +289,17 @@ ShapeKey entities::TextPayload::getShapeKey() const { return ShapeKey::Builder::invalid(); } +bool entities::TextPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + auto entityTreeRenderer = DependencyManager::get(); + if (entityTreeRenderer) { + auto renderable = entityTreeRenderer->renderableForEntityId(_entityID); + if (renderable) { + return std::static_pointer_cast(renderable)->passesZoneOcclusionTest(containingZones); + } + } + return false; +} + void entities::TextPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("TextPayload::render"); Q_ASSERT(args->_batch); @@ -388,4 +399,12 @@ template <> const ShapeKey shapeGetShapeKey(const TextPayload::Pointer& payload) template <> void payloadRender(const TextPayload::Pointer& payload, RenderArgs* args) { return payload->render(args); } + +template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} + } diff --git a/libraries/entities-renderer/src/RenderableTextEntityItem.h b/libraries/entities-renderer/src/RenderableTextEntityItem.h index 63cf3e6e9e..87102daa32 100644 --- a/libraries/entities-renderer/src/RenderableTextEntityItem.h +++ b/libraries/entities-renderer/src/RenderableTextEntityItem.h @@ -94,6 +94,7 @@ public: Item::Bound getBound() const; ShapeKey getShapeKey() const; void render(RenderArgs* args); + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; protected: QUuid _entityID; @@ -109,6 +110,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const entities::TextPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const entities::TextPayload::Pointer& payload); template <> void payloadRender(const entities::TextPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const entities::TextPayload::Pointer& payload, const std::unordered_set& containingZones); } #endif // hifi_RenderableTextEntityItem_h diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index bbb8c67ad1..948c6ca762 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -71,6 +71,11 @@ void ZoneEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity } void ZoneEntityRenderer::doRender(RenderArgs* args) { + // This is necessary so that zones can themselves be zone culled + if (!passesZoneOcclusionTest(CullTest::_prevContainingZones)) { + return; + } + if (!_stage) { _stage = args->_scene->getStage(); assert(_stage); @@ -180,6 +185,8 @@ void ZoneEntityRenderer::doRender(RenderArgs* args) { _bloomStage->_currentFrame.pushBloom(_bloomIndex); } } + + CullTest::_containingZones.insert(_entityID); } void ZoneEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index cc215d3528..0fffe2de35 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -105,6 +105,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_RENDER_LAYER; requestedProperties += PROP_PRIMITIVE_MODE; requestedProperties += PROP_IGNORE_PICK_INTERSECTION; + requestedProperties += PROP_RENDER_WITH_ZONES; requestedProperties += _grabProperties.getEntityProperties(params); // Physics @@ -300,6 +301,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)getRenderLayer()); APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, getIgnorePickIntersection()); + APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, getRenderWithZones()); withReadLock([&] { _grabProperties.appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -875,6 +877,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); READ_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); + READ_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); withWriteLock([&] { int bytesFromGrab = _grabProperties.readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData, @@ -1354,6 +1357,7 @@ EntityItemProperties EntityItem::getProperties(const EntityPropertyFlags& desire COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderLayer, getRenderLayer); COPY_ENTITY_PROPERTY_TO_PROPERTIES(primitiveMode, getPrimitiveMode); COPY_ENTITY_PROPERTY_TO_PROPERTIES(ignorePickIntersection, getIgnorePickIntersection); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(renderWithZones, getRenderWithZones); withReadLock([&] { _grabProperties.getProperties(properties); }); @@ -1503,6 +1507,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderLayer, setRenderLayer); SET_ENTITY_PROPERTY_FROM_PROPERTIES(primitiveMode, setPrimitiveMode); SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignorePickIntersection, setIgnorePickIntersection); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(renderWithZones, setRenderWithZones); withWriteLock([&] { bool grabPropertiesChanged = _grabProperties.setProperties(properties); somethingChanged |= grabPropertiesChanged; @@ -3520,3 +3525,18 @@ void EntityItem::disableGrab(GrabPointer grab) { } } } + +void EntityItem::setRenderWithZones(const QVector& renderWithZones) { + withWriteLock([&] { + if (_renderWithZones != renderWithZones) { + _needsZoneOcclusionUpdate = true; + _renderWithZones = renderWithZones; + } + }); +} + +QVector EntityItem::getRenderWithZones() const { + return resultWithReadLock>([&] { + return _renderWithZones; + }); +} \ No newline at end of file diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 14b8b259cc..2d2d158ebd 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -577,6 +577,11 @@ public: bool needsRenderUpdate() const { return resultWithReadLock([&] { return _needsRenderUpdate; }); } void setNeedsRenderUpdate(bool needsRenderUpdate) { withWriteLock([&] { _needsRenderUpdate = needsRenderUpdate; }); } + void setRenderWithZones(const QVector& renderWithZones); + QVector getRenderWithZones() const; + bool needsZoneOcclusionUpdate() const { return _needsZoneOcclusionUpdate; } + void resetNeedsZoneOcclusionUpdate() { withWriteLock([&] { _needsZoneOcclusionUpdate = false; }); } + signals: void spaceUpdate(std::pair data); @@ -765,6 +770,9 @@ protected: QHash _grabActions; + QVector _renderWithZones; + mutable bool _needsZoneOcclusionUpdate { false }; + bool _cullWithParent { false }; mutable bool _needsRenderUpdate { false }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 2b8f2b4c14..54f84beee1 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -421,6 +421,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_RENDER_LAYER, renderLayer); CHECK_PROPERTY_CHANGE(PROP_PRIMITIVE_MODE, primitiveMode); CHECK_PROPERTY_CHANGE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); + CHECK_PROPERTY_CHANGE(PROP_RENDER_WITH_ZONES, renderWithZones); changedProperties += _grab.getChangedProperties(); // Physics @@ -793,6 +794,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * avatar entities, false if they won't be. * @property {Uuid} cloneOriginID - The ID of the entity that this entity was cloned from. * + * @property {Uuid[]} renderWithZones=[]] - A list of entity IDs representing with which zones this entity should render. + * If it is empty, this entity will render normally. Otherwise, this entity will only render if your avatar is within + * one of the zones in this list. + * * @property {Entities.Grab} grab - The entity's grab-related properties. * * @property {string} itemName="" - Certifiable name of the Marketplace item. @@ -1583,6 +1588,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_RENDER_LAYER, renderLayer, getRenderLayerAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE_GETTER(PROP_PRIMITIVE_MODE, primitiveMode, getPrimitiveModeAsString()); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IGNORE_PICK_INTERSECTION, ignorePickIntersection); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_RENDER_WITH_ZONES, renderWithZones); _grab.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties); // Physics @@ -2000,6 +2006,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(renderLayer, RenderLayer); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(primitiveMode, PrimitiveMode); COPY_PROPERTY_FROM_QSCRIPTVALUE(ignorePickIntersection, bool, setIgnorePickIntersection); + COPY_PROPERTY_FROM_QSCRIPTVALUE(renderWithZones, qVectorQUuid, setRenderWithZones); _grab.copyFromScriptValue(object, _defaultSettings); // Physics @@ -2293,6 +2300,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(renderLayer); COPY_PROPERTY_IF_CHANGED(primitiveMode); COPY_PROPERTY_IF_CHANGED(ignorePickIntersection); + COPY_PROPERTY_IF_CHANGED(renderWithZones); _grab.merge(other._grab); // Physics @@ -2585,6 +2593,7 @@ bool EntityItemProperties::getPropertyInfo(const QString& propertyName, EntityPr ADD_PROPERTY_TO_MAP(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer); ADD_PROPERTY_TO_MAP(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode); ADD_PROPERTY_TO_MAP(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool); + ADD_PROPERTY_TO_MAP(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector); { // Grab ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_GRABBABLE, Grab, grab, Grabbable, grabbable); ADD_GROUP_PROPERTY_TO_MAP(PROP_GRAB_KINEMATIC, Grab, grab, GrabKinematic, grabKinematic); @@ -3073,6 +3082,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_RENDER_LAYER, (uint32_t)properties.getRenderLayer()); APPEND_ENTITY_PROPERTY(PROP_PRIMITIVE_MODE, (uint32_t)properties.getPrimitiveMode()); APPEND_ENTITY_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, properties.getIgnorePickIntersection()); + APPEND_ENTITY_PROPERTY(PROP_RENDER_WITH_ZONES, properties.getRenderWithZones()); _staticGrab.setProperties(properties); _staticGrab.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState); @@ -3562,6 +3572,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_LAYER, RenderLayer, setRenderLayer); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PRIMITIVE_MODE, PrimitiveMode, setPrimitiveMode); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IGNORE_PICK_INTERSECTION, bool, setIgnorePickIntersection); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_RENDER_WITH_ZONES, QVector, setRenderWithZones); properties.getGrab().decodeFromEditPacket(propertyFlags, dataAt, processedBytes); // Physics @@ -3979,6 +3990,7 @@ void EntityItemProperties::markAllChanged() { _renderLayerChanged = true; _primitiveModeChanged = true; _ignorePickIntersectionChanged = true; + _renderWithZonesChanged = true; _grab.markAllChanged(); // Physics @@ -4381,6 +4393,9 @@ QList EntityItemProperties::listChangedProperties() { if (ignorePickIntersectionChanged()) { out += "ignorePickIntersection"; } + if (renderWithZonesChanged()) { + out += "renderWithZones"; + } getGrab().listChangedProperties(out); // Physics diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 63d8183899..69c25cecdd 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -192,6 +192,7 @@ public: DEFINE_PROPERTY_REF_ENUM(PROP_RENDER_LAYER, RenderLayer, renderLayer, RenderLayer, RenderLayer::WORLD); DEFINE_PROPERTY_REF_ENUM(PROP_PRIMITIVE_MODE, PrimitiveMode, primitiveMode, PrimitiveMode, PrimitiveMode::SOLID); DEFINE_PROPERTY(PROP_IGNORE_PICK_INTERSECTION, IgnorePickIntersection, ignorePickIntersection, bool, false); + DEFINE_PROPERTY_REF(PROP_RENDER_WITH_ZONES, RenderWithZones, renderWithZones, QVector, QVector()); DEFINE_PROPERTY_GROUP(Grab, grab, GrabPropertyGroup); // Physics diff --git a/libraries/entities/src/EntityItemPropertiesMacros.h b/libraries/entities/src/EntityItemPropertiesMacros.h index 4c989ef74e..c25eb21e6c 100644 --- a/libraries/entities/src/EntityItemPropertiesMacros.h +++ b/libraries/entities/src/EntityItemPropertiesMacros.h @@ -119,6 +119,7 @@ inline QScriptValue qVectorVec3Color_convertScriptValue(QScriptEngine* e, const inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorQuatToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) {return qVectorBoolToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) { return qVectorFloatToScriptValue(e, v); } +inline QScriptValue convertScriptValue(QScriptEngine* e, const QVector& v) { return qVectorQUuidToScriptValue(e, v); } inline QScriptValue convertScriptValue(QScriptEngine* e, const QRect& v) { return qRectToScriptValue(e, v); } @@ -216,6 +217,7 @@ typedef QVector qVectorVec3; typedef QVector qVectorQuat; typedef QVector qVectorBool; typedef QVector qVectorFloat; +typedef QVector qVectorQUuid; inline float float_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toFloat(&isValid); } inline quint64 quint64_convertFromScriptValue(const QScriptValue& v, bool& isValid) { return v.toVariant().toULongLong(&isValid); } inline quint32 quint32_convertFromScriptValue(const QScriptValue& v, bool& isValid) { @@ -293,6 +295,11 @@ inline qVectorBool qVectorBool_convertFromScriptValue(const QScriptValue& v, boo return qVectorBoolFromScriptValue(v); } +inline qVectorQUuid qVectorQUuid_convertFromScriptValue(const QScriptValue& v, bool& isValid) { + isValid = true; + return qVectorQUuidFromScriptValue(v); +} + inline glm::quat quat_convertFromScriptValue(const QScriptValue& v, bool& isValid) { isValid = false; /// assume it can't be converted QScriptValue x = v.property("x"); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index d5af337a7d..c186b2b87f 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -43,6 +43,7 @@ enum EntityPropertyList { PROP_RENDER_LAYER, PROP_PRIMITIVE_MODE, PROP_IGNORE_PICK_INTERSECTION, + PROP_RENDER_WITH_ZONES, // Grab PROP_GRAB_GRABBABLE, PROP_GRAB_KINEMATIC, diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index fbf575065e..1bfeff5e7f 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -275,6 +275,7 @@ enum class EntityVersion : PacketVersion { ShadowBiasAndDistance, TextEntityFonts, ScriptServerKinematicMotion, + ZoneOcclusion, // Add new versions above here NUM_PACKET_TYPE, diff --git a/libraries/octree/src/OctreePacketData.cpp b/libraries/octree/src/OctreePacketData.cpp index 8ab502e951..5e6825c886 100755 --- a/libraries/octree/src/OctreePacketData.cpp +++ b/libraries/octree/src/OctreePacketData.cpp @@ -482,6 +482,19 @@ bool OctreePacketData::appendValue(const QVector& value) { return success; } +bool OctreePacketData::appendValue(const QVector& value) { + uint16_t qVecSize = value.size(); + bool success = appendValue(qVecSize); + if (success) { + success = append((const unsigned char*)value.constData(), qVecSize * sizeof(QUuid)); + if (success) { + _bytesOfValues += qVecSize * sizeof(QUuid); + _totalBytesOfValues += qVecSize * sizeof(QUuid); + } + } + return success; +} + bool OctreePacketData::appendValue(const glm::quat& value) { const size_t VALUES_PER_QUAT = 4; const size_t PACKED_QUAT_SIZE = sizeof(uint16_t) * VALUES_PER_QUAT; @@ -774,6 +787,15 @@ int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVecto return (dataBytes - start) + (int)sizeof(uint16_t); } +int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QVector& result) { + uint16_t length; + memcpy(&length, dataBytes, sizeof(uint16_t)); + dataBytes += sizeof(length); + result.resize(length); + memcpy(result.data(), dataBytes, length * sizeof(QUuid)); + return sizeof(uint16_t) + length * sizeof(QUuid); +} + int OctreePacketData::unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result) { uint16_t length; memcpy(&length, dataBytes, sizeof(length)); diff --git a/libraries/octree/src/OctreePacketData.h b/libraries/octree/src/OctreePacketData.h index 46e5de9bda..2050dd1487 100644 --- a/libraries/octree/src/OctreePacketData.h +++ b/libraries/octree/src/OctreePacketData.h @@ -186,6 +186,9 @@ public: /// appends a QVector of bools to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const QVector& value); + /// appends a QVector of QUuids to the end of the stream, may fail if new data stream is too long to fit in packet + bool appendValue(const QVector& value); + /// appends a packed quat to the end of the stream, may fail if new data stream is too long to fit in packet bool appendValue(const glm::quat& value); @@ -284,6 +287,7 @@ public: static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); + static int unpackDataFromBytes(const unsigned char* dataBytes, QVector& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QByteArray& result); static int unpackDataFromBytes(const unsigned char* dataBytes, AACube& result); static int unpackDataFromBytes(const unsigned char* dataBytes, QRect& result); diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index e82af5395f..88ba24cbc2 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -55,6 +55,13 @@ template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payl template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args) { return payload->render(args); } + +template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} } MeshPartPayload::MeshPartPayload(const std::shared_ptr& mesh, int partIndex, graphics::MaterialPointer material, const uint64_t& created) : @@ -167,10 +174,23 @@ void MeshPartPayload::bindMesh(gpu::Batch& batch) { batch.setInputStream(0, _drawMesh->getVertexStream()); } - void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { +void MeshPartPayload::bindTransform(gpu::Batch& batch, RenderArgs::RenderMode renderMode) const { batch.setModelTransform(_drawTransform); } +bool MeshPartPayload::passesZoneOcclusionTest(const std::unordered_set& containingZones) const { + if (!_renderWithZones.isEmpty()) { + if (!containingZones.empty()) { + for (auto renderWithZone : _renderWithZones) { + if (containingZones.find(renderWithZone) != containingZones.end()) { + return true; + } + } + } + return false; + } + return true; +} void MeshPartPayload::render(RenderArgs* args) { PerformanceTimer perfTimer("MeshPartPayload::render"); @@ -242,6 +262,12 @@ template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, Ren return payload->render(args); } +template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones) { + if (payload) { + return payload->passesZoneOcclusionTest(containingZones); + } + return false; +} } ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index ee205bd778..db3e1fca4d 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -75,11 +75,15 @@ public: void setCullWithParent(bool value) { _cullWithParent = value; } + void setRenderWithZones(const QVector& renderWithZones) { _renderWithZones = renderWithZones; } + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const; + static bool enableMaterialProceduralShaders; protected: render::ItemKey _itemKey{ render::ItemKey::Builder::opaqueShape().build() }; bool _cullWithParent { false }; + QVector _renderWithZones; uint64_t _created; }; @@ -88,6 +92,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const MeshPartPayload::Pointer& payload); template <> void payloadRender(const MeshPartPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const MeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); } class ModelMeshPartPayload : public MeshPartPayload { @@ -154,6 +159,7 @@ namespace render { template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload); template <> const ShapeKey shapeGetShapeKey(const ModelMeshPartPayload::Pointer& payload); template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args); + template <> bool payloadPassesZoneOcclusionTest(const ModelMeshPartPayload::Pointer& payload, const std::unordered_set& containingZones); } #endif // hifi_MeshPartPayload_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d8172112ff..db4fc46e36 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -976,6 +976,16 @@ void Model::setCullWithParent(bool cullWithParent) { } } +void Model::setRenderWithZones(const QVector& renderWithZones) { + render::Transaction transaction; + for(auto item : _modelMeshRenderItemIDs) { + transaction.updateItem(item, [renderWithZones](ModelMeshPartPayload& data) { + data.setRenderWithZones(renderWithZones); + }); + } + AbstractViewStateInterface::instance()->getMain3DScene()->enqueueTransaction(transaction); +} + const render::ItemKey Model::getRenderItemKeyGlobalFlags() const { return _renderItemKeyGlobalFlags; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index b677861e9f..ec68db4b27 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -131,6 +131,8 @@ public: void setCullWithParent(bool value); + void setRenderWithZones(const QVector& renderWithZones); + // Access the current RenderItemKey Global Flags used by the model and applied to the render items representing the parts of the model. const render::ItemKey getRenderItemKeyGlobalFlags() const; diff --git a/libraries/render/src/render/Args.h b/libraries/render/src/render/Args.h index a75192bad7..5fee00b370 100644 --- a/libraries/render/src/render/Args.h +++ b/libraries/render/src/render/Args.h @@ -13,15 +13,16 @@ #include #include #include +#include #include #include #include +#include #include #include "Forward.h" - class AABox; namespace render { @@ -142,13 +143,6 @@ namespace render { bool _takingSnapshot { false }; StencilMaskMode _stencilMaskMode { StencilMaskMode::NONE }; std::function _stencilMaskOperator; - - float _visionSqueezeX { 0.0f }; - float _visionSqueezeY { 0.0f }; - float _visionSqueezeTransition { 0.15f }; - int _visionSqueezePerEye { 0 }; - float _visionSqueezeGroundPlaneY { 0.0f }; - float _visionSqueezeSpotlightSize { 0.02f }; }; } diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 068d6f9851..f309d5a3bf 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -19,6 +19,9 @@ using namespace render; +std::unordered_set CullTest::_containingZones = std::unordered_set(); +std::unordered_set CullTest::_prevContainingZones = std::unordered_set(); + CullTest::CullTest(CullFunctor& functor, RenderArgs* pargs, RenderDetails::Item& renderDetails, ViewFrustumPointer antiFrustum) : _functor(functor), _args(pargs), @@ -64,46 +67,8 @@ bool CullTest::solidAngleTest(const AABox& bound) { return true; } -void render::cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, - const ItemBounds& inItems, ItemBounds& outItems) { - assert(renderContext->args); - assert(renderContext->args->hasViewFrustum()); - - RenderArgs* args = renderContext->args; - const ViewFrustum& frustum = args->getViewFrustum(); - - details._considered += (int)inItems.size(); - - // Culling / LOD - for (auto item : inItems) { - if (item.bound.isNull()) { - outItems.emplace_back(item); // One more Item to render - continue; - } - - // TODO: some entity types (like lights) might want to be rendered even - // when they are outside of the view frustum... - bool inView; - { - PerformanceTimer perfTimer("boxIntersectsFrustum"); - inView = frustum.boxIntersectsFrustum(item.bound); - } - if (inView) { - bool bigEnoughToRender; - { - PerformanceTimer perfTimer("shouldRender"); - bigEnoughToRender = cullFunctor(args, item.bound); - } - if (bigEnoughToRender) { - outItems.emplace_back(item); // One more Item to render - } else { - details._tooSmall++; - } - } else { - details._outOfView++; - } - } - details._rendered += (int)outItems.size(); +bool CullTest::zoneOcclusionTest(const render::Item& item) { + return item.passesZoneOcclusionTest(_containingZones); } void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const ItemFilter& filter, ItemBounds& outItems) { @@ -117,7 +82,7 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const outItems.reserve(items.size()); for (auto& id : items) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && item.passesZoneOcclusionTest(CullTest::_containingZones)) { outItems.emplace_back(ItemBound(id, item.getBound())); } } @@ -126,7 +91,6 @@ void FetchNonspatialItems::run(const RenderContextPointer& renderContext, const void FetchSpatialTree::configure(const Config& config) { _justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum); _freezeFrustum = config.freezeFrustum; - _lodAngle = config.lodAngle; } void FetchSpatialTree::run(const RenderContextPointer& renderContext, const Inputs& inputs, ItemSpatialTree::ItemSelection& outSelection) { @@ -215,7 +179,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideFitItems"); for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -230,7 +194,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideSmallItems"); for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -245,7 +209,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialFitItems"); for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -260,7 +224,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialSmallItems"); for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -277,7 +241,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideFitItems"); for (auto id : inSelection.insideItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); outItems.emplace_back(itemBound); if (item.getKey().isMetaCullGroup()) { @@ -292,7 +256,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("insideSmallItems"); for (auto id : inSelection.insideSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); if (test.solidAngleTest(itemBound.bound)) { outItems.emplace_back(itemBound); @@ -309,7 +273,7 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialFitItems"); for (auto id : inSelection.partialItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); if (test.frustumTest(itemBound.bound)) { outItems.emplace_back(itemBound); @@ -326,14 +290,12 @@ void CullSpatialSelection::run(const RenderContextPointer& renderContext, PerformanceTimer perfTimer("partialSmallItems"); for (auto id : inSelection.partialSubcellItems) { auto& item = scene->getItem(id); - if (filter.test(item.getKey())) { + if (filter.test(item.getKey()) && test.zoneOcclusionTest(item)) { ItemBound itemBound(id, item.getBound()); - if (test.frustumTest(itemBound.bound)) { - if (test.solidAngleTest(itemBound.bound)) { - outItems.emplace_back(itemBound); - if (item.getKey().isMetaCullGroup()) { - item.fetchMetaSubItemBounds(outItems, (*scene)); - } + if (test.frustumTest(itemBound.bound) && test.solidAngleTest(itemBound.bound)) { + outItems.emplace_back(itemBound); + if (item.getKey().isMetaCullGroup()) { + item.fetchMetaSubItemBounds(outItems, (*scene)); } } } @@ -444,3 +406,13 @@ void ApplyCullFunctorOnItemBounds::run(const RenderContextPointer& renderContext args->popViewFrustum(); } } + +void ClearContainingZones::run(const RenderContextPointer& renderContext) { + // This is a bit of a hack. We want to do zone culling as early as possible, so we do it + // during the RenderFetchCullSortTask (in CullSpatialSelection and FetchNonspatialItems), + // but the zones aren't collected until after (in SetupZones). To get around this, + // we actually use the zones from the previous frame to render, and then clear at the beginning + // of the next frame + CullTest::_prevContainingZones = CullTest::_containingZones; + CullTest::_containingZones.clear(); +} \ No newline at end of file diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index e67edd6666..9a7466223d 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -19,9 +19,6 @@ namespace render { using CullFunctor = std::function; - void cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, - const ItemBounds& inItems, ItemBounds& outItems); - // Culling Frustum / solidAngle test helper class struct CullTest { CullFunctor _functor; @@ -36,6 +33,10 @@ namespace render { bool frustumTest(const AABox& bound); bool antiFrustumTest(const AABox& bound); bool solidAngleTest(const AABox& bound); + bool zoneOcclusionTest(const render::Item& item); + + static std::unordered_set _containingZones; + static std::unordered_set _prevContainingZones; }; class FetchNonspatialItems { @@ -48,7 +49,6 @@ namespace render { Q_OBJECT Q_PROPERTY(int numItems READ getNumItems) Q_PROPERTY(bool freezeFrustum MEMBER freezeFrustum WRITE setFreezeFrustum) - Q_PROPERTY(float LODAngle MEMBER lodAngle NOTIFY dirty) public: int numItems{ 0 }; @@ -56,7 +56,6 @@ namespace render { bool freezeFrustum{ false }; - float lodAngle{ 2.0 }; public slots: void setFreezeFrustum(bool enabled) { freezeFrustum = enabled; emit dirty(); } @@ -68,7 +67,6 @@ namespace render { bool _freezeFrustum{ false }; // initialized by Config bool _justFrozeFrustum{ false }; ViewFrustum _frozenFrustum; - float _lodAngle; public: using Config = FetchSpatialTreeConfig; @@ -159,6 +157,12 @@ namespace render { render::CullFunctor _cullFunctor; }; + + class ClearContainingZones { + public: + using JobModel = Job::Model; + void run(const RenderContextPointer& renderContext); + }; } #endif // hifi_render_CullTask_h; \ No newline at end of file diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index 532964777f..f21df58368 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -154,4 +154,10 @@ namespace render { return payload->metaFetchMetaSubItems(subItems); } + template <> bool payloadPassesZoneOcclusionTest(const PayloadProxyInterface::Pointer& payload, const std::unordered_set& containingZones) { + if (!payload) { + return false; + } + return payload->passesZoneOcclusionTest(containingZones); + } } diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 3383101b5b..cb9fb32c7f 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -436,6 +436,8 @@ public: virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const = 0; + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const = 0; + ~PayloadInterface() {} // Status interface is local to the base class @@ -487,6 +489,8 @@ public: uint32_t fetchMetaSubItems(ItemIDs& subItems) const { return _payload->fetchMetaSubItems(subItems); } uint32_t fetchMetaSubItemBounds(ItemBounds& subItemBounds, Scene& scene) const; + bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const { return _payload->passesZoneOcclusionTest(containingZones); } + // Access the status const StatusPointer& getStatus() const { return _payload->getStatus(); } @@ -537,6 +541,10 @@ template const ShapeKey shapeGetShapeKey(const std::shared_ptr& pay // Meta items act as the grouping object for several sub items (typically shapes). template uint32_t metaFetchMetaSubItems(const std::shared_ptr& payloadData, ItemIDs& subItems) { return 0; } +// Zone Occlusion Interface +// Allows payloads to determine if they should render or not, based on the zones that contain the current camera +template bool payloadPassesZoneOcclusionTest(const std::shared_ptr& payloadData, const std::unordered_set& containingZones) { return true; } + // THe Payload class is the real Payload to be used // THis allow anything to be turned into a Payload as long as the required interface functions are available // When creating a new kind of payload from a new "stuff" class then you need to create specialized version for "stuff" @@ -561,6 +569,8 @@ public: // Meta Type Interface virtual uint32_t fetchMetaSubItems(ItemIDs& subItems) const override { return metaFetchMetaSubItems(_data, subItems); } + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const override { return payloadPassesZoneOcclusionTest(_data, containingZones); } + protected: DataPointer _data; @@ -615,6 +625,7 @@ public: virtual Item::Bound getBound() = 0; virtual void render(RenderArgs* args) = 0; virtual uint32_t metaFetchMetaSubItems(ItemIDs& subItems) const = 0; + virtual bool passesZoneOcclusionTest(const std::unordered_set& containingZones) const = 0; }; template <> const ItemKey payloadGetKey(const PayloadProxyInterface::Pointer& payload); @@ -622,7 +633,7 @@ template <> const Item::Bound payloadGetBound(const PayloadProxyInterface::Point template <> void payloadRender(const PayloadProxyInterface::Pointer& payload, RenderArgs* args); template <> uint32_t metaFetchMetaSubItems(const PayloadProxyInterface::Pointer& payload, ItemIDs& subItems); template <> const ShapeKey shapeGetShapeKey(const PayloadProxyInterface::Pointer& payload); - +template <> bool payloadPassesZoneOcclusionTest(const PayloadProxyInterface::Pointer& payload, const std::unordered_set& containingZones); typedef Item::PayloadPointer PayloadPointer; typedef std::vector Payloads; diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index ebcf5a432b..b2656a597f 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -74,6 +74,7 @@ void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varyin const auto filteredLayeredOpaque = task.addJob("FilterLayeredOpaque", layeredOpaques, ItemKey::Layer::LAYER_1); const auto filteredLayeredTransparent = task.addJob("FilterLayeredTransparent", layeredTransparents, ItemKey::Layer::LAYER_1); + task.addJob("ClearContainingZones"); output = Output(BucketList{ opaques, transparents, lights, metas, filteredLayeredOpaque.getN(0), filteredLayeredTransparent.getN(0), diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 87cd269c97..97ca26b221 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -36,6 +36,7 @@ int qVectorVec3MetaTypeId = qRegisterMetaType>(); int qVectorQuatMetaTypeId = qRegisterMetaType>(); int qVectorBoolMetaTypeId = qRegisterMetaType>(); int qVectorGLMUint32MetaTypeId = qRegisterMetaType>("QVector"); +int qVectorQUuidMetaTypeId = qRegisterMetaType>(); int quatMetaTypeId = qRegisterMetaType(); int pickRayMetaTypeId = qRegisterMetaType(); int collisionMetaTypeId = qRegisterMetaType(); @@ -58,6 +59,7 @@ void registerMetaTypes(QScriptEngine* engine) { qScriptRegisterMetaType(engine, qVectorBoolToScriptValue, qVectorBoolFromScriptValue); qScriptRegisterMetaType(engine, qVectorFloatToScriptValue, qVectorFloatFromScriptValue); qScriptRegisterMetaType(engine, qVectorIntToScriptValue, qVectorIntFromScriptValue); + qScriptRegisterMetaType(engine, qVectorQUuidToScriptValue, qVectorQUuidFromScriptValue); qScriptRegisterMetaType(engine, qSizeFToScriptValue, qSizeFFromScriptValue); qScriptRegisterMetaType(engine, qRectToScriptValue, qRectFromScriptValue); @@ -874,6 +876,22 @@ QVector qVectorFloatFromScriptValue(const QScriptValue& array) { return newVector; } +QScriptValue qVectorQUuidToScriptValue(QScriptEngine* engine, const QVector& vector) { + QScriptValue array = engine->newArray(); + for (int i = 0; i < vector.size(); i++) { + array.setProperty(i, quuidToScriptValue(engine, vector.at(i))); + } + return array; +} + +void qVectorQUuidFromScriptValue(const QScriptValue& array, QVector& vector) { + int length = array.property("length").toInteger(); + + for (int i = 0; i < length; i++) { + vector << array.property(i).toVariant().toUuid(); + } +} + QVector qVectorQUuidFromScriptValue(const QScriptValue& array) { if (!array.isArray()) { return QVector(); diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 3b47bb70c6..fa7ae624b2 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -247,6 +247,8 @@ QVector qVectorFloatFromScriptValue(const QScriptValue& array); QScriptValue qVectorIntToScriptValue(QScriptEngine* engine, const QVector& vector); void qVectorIntFromScriptValue(const QScriptValue& array, QVector& vector); +QScriptValue qVectorQUuidToScriptValue(QScriptEngine* engine, const QVector& vector); +void qVectorQUuidFromScriptValue(const QScriptValue& array, QVector& vector); QVector qVectorQUuidFromScriptValue(const QScriptValue& array); QScriptValue aaCubeToScriptValue(QScriptEngine* engine, const AACube& aaCube); From 1a4266a64a93db554fea764aba38bb4596177b40 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Jan 2020 14:33:06 +1300 Subject: [PATCH 002/105] Review JSDoc updates from recent commits --- .../src/avatars/ScriptableAvatar.h | 10 +++++----- interface/src/avatar/MyAvatar.h | 18 +++++++++--------- interface/src/ui/InteractiveWindow.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 2 +- .../src/avatars-renderer/Avatar.h | 4 ++-- .../src/avatars-renderer/ScriptAvatar.h | 4 ++-- libraries/avatars/src/AvatarData.h | 10 +++++----- libraries/avatars/src/ScriptAvatarData.h | 2 +- .../GraphicsScriptingInterface.cpp | 2 +- .../src/graphics-scripting/ScriptableMesh.h | 4 ++-- .../graphics-scripting/ScriptableMeshPart.h | 2 +- .../src/graphics-scripting/ScriptableModel.h | 4 ++-- .../src/graphics/BufferViewHelpers.cpp | 2 +- libraries/shared/src/JointData.h | 2 +- libraries/shared/src/RegisteredMetaTypes.cpp | 2 +- 15 files changed, 35 insertions(+), 35 deletions(-) diff --git a/assignment-client/src/avatars/ScriptableAvatar.h b/assignment-client/src/avatars/ScriptableAvatar.h index 500c3f44fb..1e6046ba7e 100644 --- a/assignment-client/src/avatars/ScriptableAvatar.h +++ b/assignment-client/src/avatars/ScriptableAvatar.h @@ -82,15 +82,15 @@ *

Note: This property will automatically be set to true if the Controller system has valid facial * blend shape actions.

* @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating - * facial blend shapes, false if automatic blinking is disabled. Set this property to false if - * you wish to fully control the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. + * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control + * the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property - * to true to prevent the iris from being obscured by the upper or lower lids. Set this property to - * false if you wish to fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. + * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to + * fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate * automatically based on detected microphone input, false if this automatic movement is disabled. Set - * this property to false if you wish to fully control the mouth facial blend shapes via the + * this property to false to fully control the mouth facial blend shapes via the * {@link MyAvatar.setBlendshape} method. * * @example Create a scriptable avatar. diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9b9bc2d9df..0f46af458e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -154,12 +154,12 @@ class MyAvatar : public Avatar { *

Note: This property will automatically be set to true if the controller system has * valid facial blend shape actions.

* @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating - * facial blend shapes, false if automatic blinking is disabled. Set this property to false - * to fully control the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. + * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control + * the blink facial blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property - * to true to prevent the iris from being obscured by the upper or lower lids. Set this property to - * false to fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. + * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to + * fully control the eye blend shapes via the {@link MyAvatar.setBlendshape} method. * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate * automatically based on detected microphone input, false if this automatic movement is disabled. Set * this property to false to fully control the mouth facial blend shapes via the @@ -1793,15 +1793,15 @@ public: /**jsdoc * Turns the avatar's head until it faces the target point within a +90/-90 degree range. - * Once this method is called, API calls will have full control of the head for a limited time. - * If this method is not called for 2 seconds, the engine will regain control of the head. + * Once this method is called, API calls have full control of the head for a limited time. + * If this method is not called for 2 seconds, the engine regains control of the head. * @function MyAvatar.setHeadLookAt * @param {Vec3} lookAtTarget - The target point in world coordinates. */ Q_INVOKABLE void setHeadLookAt(const glm::vec3& lookAtTarget); /**jsdoc - * Returns the current target point of the head's look direction in world coordinates. + * Gets the current target point of the head's look direction in world coordinates. * @function MyAvatar.getHeadLookAt * @returns {Vec3} The head's look-at target in world coordinates. */ @@ -1815,7 +1815,7 @@ public: /**jsdoc * Forces the avatar's eyes to look at a specified location. Once this method is called, API calls - * have full control of the eyes for a limited time. If this method is not called for two seconds, + * full control of the eyes for a limited time. If this method is not called for 2 seconds, * the engine regains control of the eyes. * @function MyAvatar.setEyesLookAt * @param {Vec3} lookAtTarget - The target point in world coordinates. @@ -1823,7 +1823,7 @@ public: Q_INVOKABLE void setEyesLookAt(const glm::vec3& lookAtTarget); /**jsdoc - * Returns the current target point of the eyes look direction in world coordinates. + * Gets the current target point of the eyes look direction in world coordinates. * @function MyAvatar.getEyesLookAt * @returns {Vec3} The eyes' look-at target in world coordinates. */ diff --git a/interface/src/ui/InteractiveWindow.cpp b/interface/src/ui/InteractiveWindow.cpp index 2acac2c529..0ac1f05737 100644 --- a/interface/src/ui/InteractiveWindow.cpp +++ b/interface/src/ui/InteractiveWindow.cpp @@ -145,7 +145,7 @@ void InteractiveWindow::emitMainWindowResizeEvent() { * @property {InteractiveWindow.Flags} [additionalFlags=0] - Customizes window behavior. * @property {InteractiveWindow.OverrideFlags} [overrideFlags=0] - Customizes window controls. - * @property {InteractiveWindow.RelativePositionAnchor} [relativePositionAnchor] - he anchor for the + * @property {InteractiveWindow.RelativePositionAnchor} [relativePositionAnchor] - The anchor for the * relativePosition, if used. * @property {Vec2} [relativePosition] - The position of the window, relative to the relativePositionAnchor, in * pixels. Excludes the window frame. diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a9e16e9ff1..3792057052 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -1925,7 +1925,7 @@ void Avatar::setParentJointIndex(quint16 parentJointIndex) { * @typedef {object} SkeletonJoint * @property {string} name - Joint name. * @property {number} index - Joint index. - * @property {number} parentIndex - Index of this joint's parent (-1 if no parent). + * @property {number} parentIndex - Index of this joint's parent (-1 if no parent). */ QList Avatar::getSkeleton() { SkeletonModelPointer skeletonModel = _skeletonModel; diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index dcd4d00db0..2c36a92b0f 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -442,7 +442,7 @@ public: void setOrientationViaScript(const glm::quat& orientation) override; /**jsdoc - * Gets the ID of the entity of avatar that the avatar is parented to. + * Gets the ID of the entity or avatar that the avatar is parented to. * @function MyAvatar.getParentID * @returns {Uuid} The ID of the entity or avatar that the avatar is parented to. {@link Uuid(0)|Uuid.NULL} if not parented. */ @@ -450,7 +450,7 @@ public: Q_INVOKABLE virtual const QUuid getParentID() const override { return SpatiallyNestable::getParentID(); } /**jsdoc - * Sets the ID of the entity of avatar that the avatar is parented to. + * Sets the ID of the entity or avatar that the avatar is parented to. * @function MyAvatar.setParentID * @param {Uuid} parentID - The ID of the entity or avatar that the avatar should be parented to. Set to * {@link Uuid(0)|Uuid.NULL} to unparent. diff --git a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h index 3f8fc4f88b..abc15ae11b 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h @@ -19,7 +19,7 @@ /**jsdoc * Information about an avatar. * - *

Created using {@link MyAvatar.getTargetAvatar} or {@link AvatarList.getAvatar}.

+ *

Create using {@link MyAvatar.getTargetAvatar} or {@link AvatarList.getAvatar}.

* * @class ScriptAvatar * @hideconstructor @@ -152,7 +152,7 @@ public slots: /**jsdoc - * Gets the ID of the entity of avatar that the avatar is parented to. + * Gets the ID of the entity or avatar that the avatar is parented to. * @function ScriptAvatar.getParentID * @returns {Uuid} The ID of the entity or avatar that the avatar is parented to. {@link Uuid(0)|Uuid.NULL} if not parented * or avatar data aren't available. diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 24808b98bf..40e3a056da 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -538,12 +538,12 @@ class AvatarData : public QObject, public SpatiallyNestable { *

Note: This property will automatically be set to true if the controller system has * valid facial blend shape actions.

* @property {boolean} hasProceduralBlinkFaceMovement=true - true if avatars blink automatically by animating - * facial blend shapes, false if automatic blinking is disabled. Set this property to false - * to fully control the blink facial blend shapes via the {@link Avatar.setBlendshape} method. + * facial blend shapes, false if automatic blinking is disabled. Set to false to fully control + * the blink facial blend shapes via the {@link Avatar.setBlendshape} method. * @property {boolean} hasProceduralEyeFaceMovement=true - true if the facial blend shapes for an avatar's eyes * adjust automatically as the eyes move, false if this automatic movement is disabled. Set this property - * to true to prevent the iris from being obscured by the upper or lower lids. Set this property to - * false to fully control the eye blend shapes via the {@link Avatar.setBlendshape} method. + * to true to prevent the iris from being obscured by the upper or lower lids. Set to false to + * fully control the eye blend shapes via the {@link Avatar.setBlendshape} method. * @property {boolean} hasAudioEnabledFaceMovement=true - true if the avatar's mouth blend shapes animate * automatically based on detected microphone input, false if this automatic movement is disabled. Set * this property to false to fully control the mouth facial blend shapes via the @@ -1542,7 +1542,7 @@ signals: void sessionDisplayNameChanged(); /**jsdoc - * Triggered when the avatar's model (i.e., skeletonModelURL property value) is changed. + * Triggered when the avatar's model (i.e., skeletonModelURL property value) changes. * @function Avatar.skeletonModelURLChanged * @returns {Signal} * @example Report when your avatar's skeleton model changes. diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index 7dcd7cc7e1..128bf9aef7 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -248,7 +248,7 @@ signals: void sessionDisplayNameChanged(); /**jsdoc - * Triggered when the avatar's model (i.e., skeletonModelURL property value) is changed. + * Triggered when the avatar's model (i.e., skeletonModelURL property value) changes. * @function ScriptAvatar.skeletonModelURLChanged * @returns {Signal} */ diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp index 9d36cfd91a..a27eff9cbe 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.cpp @@ -434,7 +434,7 @@ namespace scriptable { * @property {string} [glossMap] - The URL of the gloss texture image. * Only use one of roughnessMap and glossMap. * "hifi_pbr" model only. - * @property {string} [normalMa]p - The URL of the normal texture image. + * @property {string} [normalMap] - The URL of the normal texture image. * If "fallthrough" then it and bumpMap fall through to the material below. * Only use one of normalMap and bumpMap. * "hifi_pbr" model only. diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h index 8d70eda9e4..0e7eecc03b 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMesh.h @@ -31,7 +31,7 @@ namespace scriptable { /**jsdoc * A handle to in-memory mesh data in a {@link GraphicsModel}. * - *

Created using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, or {@link GraphicsMesh.cloneMesh}.

+ *

Create using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, or {@link GraphicsMesh.cloneMesh}.

* * @class GraphicsMesh * @hideconstructor @@ -133,7 +133,7 @@ namespace scriptable { QVector findNearbyVertexIndices(const glm::vec3& origin, float epsilon = 1e-6) const; /**jsdoc - * Adds an attribute to the (whole) mesh's vertices. + * Adds an attribute for all vertices. * @function GraphicsMesh.addAttribute * @param {Graphics.BufferTypeName} name - The name of the attribute. * @param {Graphics.BufferType} [defaultValue] - The value to give the attributes added to the vertices. diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h index 78ddb4f2b0..878b239f3d 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableMeshPart.h @@ -13,7 +13,7 @@ namespace scriptable { /**jsdoc * A handle to in-memory mesh part data in a {@link GraphicsModel}. * - *

Created using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, {@link GraphicsMesh.cloneMesh}, or + *

Create using the {@link Graphics} API, {@link GraphicsModel.cloneModel}, {@link GraphicsMesh.cloneMesh}, or * {@link GraphicsMeshPart.cloneMeshPart}.

* * @class GraphicsMeshPart diff --git a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h index 6dc2a06747..a6f135c321 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h +++ b/libraries/graphics-scripting/src/graphics-scripting/ScriptableModel.h @@ -22,7 +22,7 @@ namespace scriptable { *

Note: The model may be used for more than one instance of an item displayed in the scene. Modifying the model updates * all instances displayed.

* - *

Created using the {@link Graphics} API or {@link GraphicsModel.cloneModel}.

+ *

Create using the {@link Graphics} API or {@link GraphicsModel.cloneModel}.

* * @class GraphicsModel * @hideconstructor @@ -34,7 +34,7 @@ namespace scriptable { * @property {Uuid} objectID - The ID of the entity or avatar that the model is associated with, if any; null * if the model is not associated with an entity or avatar. * Read-only. - * @property {number} numMeshes - The number of meshes contained in the model. + * @property {number} numMeshes - The number of meshes in the model. * Read-only. * @property {GraphicsMesh[]} meshes - The meshes in the model. Each mesh may have more than one mesh part. * Read-only. diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.cpp b/libraries/graphics/src/graphics/BufferViewHelpers.cpp index 076cb92dcf..87d19ec6a2 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.cpp +++ b/libraries/graphics/src/graphics/BufferViewHelpers.cpp @@ -76,7 +76,7 @@ const std::array ZERO123 = { { "0", "1", "2", "3" } }; * {@link Vec2}"texcoord4"Fifth UV coordinates buffer. * * - * @typedef {Vec3|vec2} Graphics.BufferType + * @typedef {Vec4|Vec3|Vec2} Graphics.BufferType */ QMap ATTRIBUTES{ {"position", gpu::Stream::POSITION }, diff --git a/libraries/shared/src/JointData.h b/libraries/shared/src/JointData.h index 3f957fa046..329c2dd151 100644 --- a/libraries/shared/src/JointData.h +++ b/libraries/shared/src/JointData.h @@ -16,7 +16,7 @@ public: // Used by the avatar mixer to describe a single joint // Translations relative to their parent joint // Rotations are absolute (i.e. not relative to parent) and are in rig space. -// No JSDoc because its not provided as a type to the script engine. +// No JSDoc because it's not provided as a type to the script engine. class JointData { public: glm::quat rotation; diff --git a/libraries/shared/src/RegisteredMetaTypes.cpp b/libraries/shared/src/RegisteredMetaTypes.cpp index 7c30d4f205..7faaebbae9 100644 --- a/libraries/shared/src/RegisteredMetaTypes.cpp +++ b/libraries/shared/src/RegisteredMetaTypes.cpp @@ -1309,7 +1309,7 @@ void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) { /**jsdoc * A triangle in a mesh. * @typedef {object} MeshFace - * @property {number[]} vertices - The indexes of the three vertices that make up the fase. + * @property {number[]} vertices - The indexes of the three vertices that make up the face. */ QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace) { QScriptValue obj = engine->newObject(); From eae3336f5735b38775088a6b97d887cfbb18d8f5 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Jan 2020 15:06:32 +1300 Subject: [PATCH 003/105] Fix up docs links --- .../hifi/avatarPackager/AvatarPackagerApp.qml | 2 +- .../qml/hifi/avatarPackager/AvatarProject.qml | 2 +- .../qml/hifi/avatarapp/MessageBoxes.qml | 2 +- .../qml/hifi/commerce/checkout/Checkout.qml | 2 +- .../qml/hifi/commerce/purchases/Purchases.qml | 2 +- interface/src/Application.cpp | 2 +- interface/src/avatar/AvatarDoctor.cpp | 2 +- interface/src/avatar/MyAvatar.h | 14 +++++++------- .../src/avatars-renderer/Avatar.h | 4 ++-- .../src/avatars-renderer/ScriptAvatar.h | 4 ++-- libraries/avatars/src/AvatarData.h | 18 +++++++++--------- libraries/avatars/src/ScriptAvatarData.h | 8 ++++---- libraries/image/src/image/TextureProcessing.h | 2 +- libraries/midi/src/Midi.h | 2 +- libraries/script-engine/src/ScriptEngine.h | 2 +- libraries/script-engine/src/Vec3.h | 2 +- 16 files changed, 35 insertions(+), 35 deletions(-) diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml index 278ce36362..9158e25f75 100644 --- a/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml +++ b/interface/resources/qml/hifi/avatarPackager/AvatarPackagerApp.qml @@ -229,7 +229,7 @@ Item { } function openDocs() { - Qt.openUrlExternally("https://docs.highfidelity.com/create/avatars/package-avatar.html"); + Qt.openUrlExternally("https://docs.projectathena.dev/create/avatars/package-avatar.html"); } function openVideo() { diff --git a/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml b/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml index e5bffa7829..5dd2dd0bd6 100644 --- a/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml +++ b/interface/resources/qml/hifi/avatarPackager/AvatarProject.qml @@ -326,7 +326,7 @@ Item { text: "This item is not for sale yet, learn more." onLinkActivated: { - Qt.openUrlExternally("https://docs.highfidelity.com/sell/add-item/upload-avatar.html"); + Qt.openUrlExternally("https://docs.projectathena.dev/sell/add-item/upload-avatar.html"); } } diff --git a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml index 7d25438a1f..decb5e0807 100644 --- a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml +++ b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml @@ -7,7 +7,7 @@ MessageBox { popup.onButton2Clicked = callback; popup.titleText = 'Specify Avatar URL' popup.bodyText = 'This will not overwrite your existing favorite if you are wearing one.
' + - '' + + '' + 'Learn to make a custom avatar by opening this link on your desktop.' + '' popup.inputText.visible = true; diff --git a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml index 41ac9232e2..315fc540dd 100644 --- a/interface/resources/qml/hifi/commerce/checkout/Checkout.qml +++ b/interface/resources/qml/hifi/commerce/checkout/Checkout.qml @@ -778,7 +778,7 @@ Rectangle { lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + "If you want to save the state of the content in this domain, create a backup before proceeding.

" + "For more information about backing up and restoring content, " + - "" + + "" + "click here to open info on your desktop browser."; lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = function() { diff --git a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml index 85e5211649..40365ef9e7 100644 --- a/interface/resources/qml/hifi/commerce/purchases/Purchases.qml +++ b/interface/resources/qml/hifi/commerce/purchases/Purchases.qml @@ -602,7 +602,7 @@ Rectangle { lightboxPopup.bodyText = "Rezzing this content set will replace the existing environment and all of the items in this domain. " + "If you want to save the state of the content in this domain, create a backup before proceeding.

" + "For more information about backing up and restoring content, " + - "
" + + "" + "click here to open info on your desktop browser."; lightboxPopup.button1text = "CANCEL"; lightboxPopup.button1method = function() { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 36f1f4132a..776f78774c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -7749,7 +7749,7 @@ bool Application::askToReplaceDomainContent(const QString& url) { static const QString infoText = simpleWordWrap("Your domain's content will be replaced with a new content set. " "If you want to save what you have now, create a backup before proceeding. For more information about backing up " "and restoring content, visit the documentation page at: ", MAX_CHARACTERS_PER_LINE) + - "\nhttps://docs.highfidelity.com/create-and-explore/start-working-in-your-sandbox/restoring-sandbox-content"; + "\nhttps://docs.projectathena.dev/host/maintain-domain.html"; ModalDialogListener* dig = OffscreenUi::asyncQuestion("Are you sure you want to replace this domain's content set?", infoText, QMessageBox::Yes | QMessageBox::No, QMessageBox::No); diff --git a/interface/src/avatar/AvatarDoctor.cpp b/interface/src/avatar/AvatarDoctor.cpp index 4ff6fb7553..3c56170825 100644 --- a/interface/src/avatar/AvatarDoctor.cpp +++ b/interface/src/avatar/AvatarDoctor.cpp @@ -55,7 +55,7 @@ static QStringList HAND_MAPPING_SUFFIXES = { "HandThumb1", }; -const QUrl PACKAGE_AVATAR_DOCS_BASE_URL = QUrl("https://docs.highfidelity.com/create/avatars/package-avatar.html"); +const QUrl PACKAGE_AVATAR_DOCS_BASE_URL = QUrl("https://docs.projectathena.dev/create/avatars/package-avatar.html"); AvatarDoctor::AvatarDoctor(const QUrl& avatarFSTFileUrl) : _avatarFSTFileUrl(avatarFSTFileUrl) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0f46af458e..8ab532358b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -654,7 +654,7 @@ public: *

Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see - * Avatar Standards.

+ * Avatar Standards.

* @function MyAvatar.overrideAnimation * @param {string} url - The URL to the animation file. Animation files may be in glTF or FBX format, but only need to * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs @@ -762,7 +762,7 @@ public: *

Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see - * Avatar Standards. + * Avatar Standards. * @function MyAvatar.overrideRoleAnimation * @param {string} role - The animation role to override * @param {string} url - The URL to the animation file. Animation files need to be in glTF or FBX format, but only need to @@ -1920,7 +1920,7 @@ public: /**jsdoc * Enables and disables flow simulation of physics on the avatar's hair, clothes, and body parts. See - * {@link https://docs.highfidelity.com/create/avatars/add-flow.html|Add Flow to Your Avatar} for more + * {@link https://docs.projectathena.dev/create/avatars/add-flow.html|Add Flow to Your Avatar} for more * information. * @function MyAvatar.useFlow * @param {boolean} isActive - true if flow simulation is enabled on the joint, false if it isn't. @@ -2284,7 +2284,7 @@ public slots: /**jsdoc * Gets the URL of the override animation graph. - *

See {@link https://docs.highfidelity.com/create/avatars/custom-animations.html|Custom Avatar Animations} for + *

See {@link https://docs.projectathena.dev/create/avatars/custom-animations.html|Custom Avatar Animations} for * information on animation graphs.

* @function MyAvatar.getAnimGraphOverrideUrl * @returns {string} The URL of the override animation graph JSON file. "" if there is no override animation @@ -2294,7 +2294,7 @@ public slots: /**jsdoc * Sets the animation graph to use in preference to the default animation graph. - *

See {@link https://docs.highfidelity.com/create/avatars/custom-animations.html|Custom Avatar Animations} for + *

See {@link https://docs.projectathena.dev/create/avatars/custom-animations.html|Custom Avatar Animations} for * information on animation graphs.

* @function MyAvatar.setAnimGraphOverrideUrl * @param {string} url - The URL of the animation graph JSON file to use. Set to "" to clear an override. @@ -2303,7 +2303,7 @@ public slots: /**jsdoc * Gets the URL of animation graph (i.e., the avatar animation JSON) that's currently being used for avatar animations. - *

See {@link https://docs.highfidelity.com/create/avatars/custom-animations.html|Custom Avatar Animations} for + *

See {@link https://docs.projectathena.dev/create/avatars/custom-animations.html|Custom Avatar Animations} for * information on animation graphs.

* @function MyAvatar.getAnimGraphUrl * @returns {string} The URL of the current animation graph JSON file. @@ -2314,7 +2314,7 @@ public slots: /**jsdoc * Sets the current animation graph (i.e., the avatar animation JSON) to use for avatar animations and makes it the default. - *

See {@link https://docs.highfidelity.com/create/avatars/custom-animations.html|Custom Avatar Animations} for + *

See {@link https://docs.projectathena.dev/create/avatars/custom-animations.html|Custom Avatar Animations} for * information on animation graphs.

* @function MyAvatar.setAnimGraphUrl * @param {string} url - The URL of the animation graph JSON file to use. diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h index 2c36a92b0f..cd1fc7c7fc 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.h @@ -207,7 +207,7 @@ public: /**jsdoc * Gets the default rotation of a joint (in the current avatar) relative to its parent. *

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function MyAvatar.getDefaultJointRotation * @param {number} index - The joint index. * @returns {Quat} The default rotation of the joint if the joint index is valid, otherwise {@link Quat(0)|Quat.IDENTITY}. @@ -218,7 +218,7 @@ public: * Gets the default translation of a joint (in the current avatar) relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function MyAvatar.getDefaultJointTranslation * @param {number} index - The joint index. * @returns {Vec3} The default translation of the joint (in model coordinates) if the joint index is valid, otherwise diff --git a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h index abc15ae11b..b5fdad078e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h @@ -87,7 +87,7 @@ public slots: /**jsdoc * Gets the default rotation of a joint in the avatar relative to its parent. *

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getDefaultJointRotation * @param {number} index - The joint index. * @returns {Quat} The default rotation of the joint if avatar data are available and the joint index is valid, otherwise @@ -99,7 +99,7 @@ public slots: * Gets the default translation of a joint in the avatar relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getDefaultJointTranslation * @param {number} index - The joint index. * @returns {Vec3} The default translation of the joint (in model coordinates) if avatar data are available and the joint diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 40e3a056da..fac23a5f96 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -796,7 +796,7 @@ public: * @param {Quat} rotation - The rotation of the joint relative to its parent. * @param {Vec3} translation - The translation of the joint relative to its parent, in model coordinates. * @example Set your avatar to it's default T-pose for a while.
- * Avatar in T-pose + * Avatar in T-pose * // Set all joint translations and rotations to defaults. * var i, length, rotation, translation; * for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) { @@ -860,7 +860,7 @@ public: /**jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function Avatar.getJointRotation * @param {number} index - The index of the joint. * @returns {Quat} The rotation of the joint relative to its parent. @@ -871,7 +871,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function Avatar.getJointTranslation * @param {number} index - The index of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates. @@ -904,7 +904,7 @@ public: * @param {string} name - The name of the joint. * @param {Quat} rotation - The rotation of the joint relative to its parent. * @example Set your avatar to its default T-pose then rotate its right arm.
- * Avatar in T-pose with arm rotated + * Avatar in T-pose with arm rotated * // Set all joint translations and rotations to defaults. * var i, length, rotation, translation; * for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) { @@ -939,7 +939,7 @@ public: * @param {Vec3} translation - The translation of the joint relative to its parent, in model coordinates. * @example Stretch your avatar's neck. Depending on the avatar you are using, you will either see a gap between * the head and body or you will see the neck stretched.
- * Avatar with neck stretched + * Avatar with neck stretched * // Stretch your avatar's neck. * MyAvatar.setJointTranslation("Neck", Vec3.multiply(2, MyAvatar.getJointTranslation("Neck"))); * @@ -981,7 +981,7 @@ public: /**jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function Avatar.getJointRotation * @param {string} name - The name of the joint. * @returns {Quat} The rotation of the joint relative to its parent. @@ -996,7 +996,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function Avatar.getJointTranslation * @param {number} name - The name of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates. @@ -1041,7 +1041,7 @@ public: * @param {Quat[]} jointRotations - The rotations for all joints in the avatar. The values are in the same order as the * array returned by {@link MyAvatar.getJointNames}, or {@link Avatar.getJointNames} if using the Avatar API. * @example Set your avatar to its default T-pose then rotate its right arm.
- * Avatar in T-pose + * Avatar in T-pose * // Set all joint translations and rotations to defaults. * var i, length, rotation, translation; * for (i = 0, length = MyAvatar.getJointNames().length; i < length; i++) { @@ -1138,7 +1138,7 @@ public: * set hasScriptedBlendshapes back to false when the animation is complete. * @function Avatar.setBlendshape * @param {string} name - The name of the blendshape, per the - * {@link https://docs.highfidelity.com/create/avatars/avatar-standards.html#blendshapes Avatar Standards}. + * {@link https://docs.projectathena.dev/create/avatars/avatar-standards.html#blendshapes Avatar Standards}. * @param {number} value - A value between 0.0 and 1.0. * @example Open your avatar's mouth wide. * MyAvatar.hasScriptedBlendshapes = true; diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index 128bf9aef7..bddbf5f887 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -117,7 +117,7 @@ public: /**jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function ScriptAvatar.getJointRotation * @param {number} index - The index of the joint. * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data @@ -129,7 +129,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getJointTranslation * @param {number} index - The index of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} @@ -139,7 +139,7 @@ public: /**jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function ScriptAvatar.getJointRotation * @param {string} name - The name of the joint. * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data @@ -151,7 +151,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

Warning: These coordinates are not necessarily in meters.

*

For information on the joint hierarchy used, see - * Avatar Standards.

+ * Avatar Standards.

* @function ScriptAvatar.getJointTranslation * @param {number} name - The name of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} diff --git a/libraries/image/src/image/TextureProcessing.h b/libraries/image/src/image/TextureProcessing.h index c1817a08a6..677d48c61f 100644 --- a/libraries/image/src/image/TextureProcessing.h +++ b/libraries/image/src/image/TextureProcessing.h @@ -33,7 +33,7 @@ namespace TextureUsage { /**jsdoc *

Describes the type of texture.

*

See also: {@link Material} and - * {@link https://docs.highfidelity.com/create/3d-models/pbr-materials-guide.html|PBR Materials Guide}.

+ * {@link https://docs.projectathena.dev/create/3d-models/pbr-materials-guide.html|PBR Materials Guide}.

* * * diff --git a/libraries/midi/src/Midi.h b/libraries/midi/src/Midi.h index 5b7c82d6da..986682d7f9 100644 --- a/libraries/midi/src/Midi.h +++ b/libraries/midi/src/Midi.h @@ -23,7 +23,7 @@ /**jsdoc * The Midi API provides the ability to connect Interface with musical instruments and other external or virtual * devices via the MIDI protocol. For further information and examples, see the tutorial: - * Use MIDI to Control Your Environment. + * Use MIDI to Control Your Environment. * *

Note: Only works on Windows.

* diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 71af673e6c..4265390995 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -417,7 +417,7 @@ public: /**jsdoc * Provides access to methods or objects provided in an external JavaScript or JSON file. - * See {@link https://docs.highfidelity.com/script/js-tips.html} for further details. + * See {@link https://docs.projectathena.dev/script/js-tips.html} for further details. * @function Script.require * @param {string} module - The module to use. May be a JavaScript file, a JSON file, or the name of a system module such * as "appUi" (i.e., the "appUi.js" system module JavaScript file). diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h index 86df912d0e..a8fe51efe8 100644 --- a/libraries/script-engine/src/Vec3.h +++ b/libraries/script-engine/src/Vec3.h @@ -24,7 +24,7 @@ /**jsdoc * The Vec3 API provides facilities for generating and manipulating 3-dimensional vectors. High Fidelity uses a * right-handed Cartesian coordinate system where the y-axis is the "up" and the negative z-axis is the "front" direction. - * High Fidelity coordinate system + * High Fidelity coordinate system * * @namespace Vec3 * @variation 0 From b816d7053a89c7485cb88a7230fa942ed025dd4e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Jan 2020 21:07:33 +1300 Subject: [PATCH 004/105] Update models used in JSDoc examples --- interface/src/avatar/MyAvatar.h | 10 +++++----- libraries/avatars/src/AvatarData.h | 4 ++-- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- .../graphics-scripting/GraphicsScriptingInterface.h | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8ab532358b..6856e8b58c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -665,7 +665,7 @@ public: * @param {number} firstFrame - The frame to start the animation at. * @param {number} lastFrame - The frame to end the animation at. * @example - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreAnimation(); @@ -688,7 +688,7 @@ public: * @param {number} firstFrame - The frame to start the animation at. * @param {number} lastFrame - The frame to end the animation at. * @example - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideHandAnimation(isLeft, ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreHandAnimation(); @@ -705,7 +705,7 @@ public: * animation, this function has no effect.

* @function MyAvatar.restoreAnimation * @example - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreAnimation(); @@ -722,7 +722,7 @@ public: * @function MyAvatar.restoreHandAnimation * @param isLeft {boolean} Set to true if using the left hand * @example - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideHandAnimation(isLeft, ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreHandAnimation(); @@ -780,7 +780,7 @@ public: * hanging at its sides when it is not moving, the avatar will stand and clap its hands. Note that just as it did before, as soon as the avatar * starts to move, the animation will smoothly blend into the walk animation used by the "walkFwd" animation role. * // An animation of the avatar clapping its hands while standing. Restore default after 30s. - * var ANIM_URL = "https://s3.amazonaws.com/hifi-public/animations/ClapAnimations/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideRoleAnimation("idleStand", ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreRoleAnimation(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index fac23a5f96..2f595fab08 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1274,7 +1274,7 @@ public: * null to remove all attachments. * @deprecated This function is deprecated and will be removed. Use avatar entities instead. * @example - * var hatURL = "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx"; + * var hatURL = "https://apidocs.projectathena.dev/models/cowboy-hat.fbx"; * var attachments = MyAvatar.getAttachmentData(); * * for (var i = 0; i < attachments.length; i++) { @@ -1311,7 +1311,7 @@ public: * @deprecated This function is deprecated and will be removed. Use avatar entities instead. * @example * var attachment = { - * modelURL: "https://s3.amazonaws.com/hifi-public/tony/cowboy-hat.fbx", + * modelURL: "https://apidocs.projectathena.dev/models/cowboy-hat.fbx", * jointName: "Head", * translation: {"x": 0, "y": 0.25, "z": 0}, * rotation: {"x": 0, "y": 0, "z": 0, "w": 1}, diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 1d476af22f..ebdbbc4397 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1036,8 +1036,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * type: "Model", * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -2 })), * rotation: MyAvatar.orientation, - * modelURL: "http://content.highfidelity.com/seefo/production/puck-attach/vive_tracker_puck.obj", - * dimensions: { x: 0.0945, y: 0.0921, z: 0.0423 }, + * modelURL: "https://apidocs.projectathena.dev/models/cowboy-hat.fbx", + * dimensions: { x: 0.8569, y: 0.3960, z: 1.0744 }, * lifetime: 300 // Delete after 5 minutes. * }); */ diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h index 9b56433bf6..ed3e207eaf 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h @@ -87,8 +87,8 @@ public slots: * type: "Model", * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(Camera.orientation, { x: -0.5, y: 0, z: -3 })), * rotation: MyAvatar.orientation, - * modelURL: "http://content.highfidelity.com/seefo/production/puck-attach/vive_tracker_puck.obj", - * dimensions: { x: 0.945, y: 0.921, z: 0.423 }, + * modelURL: "https://apidocs.projectathena.dev/models/cowboy-hat.fbx", + * dimensions: { x: 0.8569, y: 0.3960, z: 1.0744 }, * lifetime: 300 // Delete after 5 minutes. * }); * var shapeEntityID = Entities.addEntity({ From 0666c3bbb109ba03b36e518f66161863706e0fb1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Jan 2020 21:31:50 +1300 Subject: [PATCH 005/105] Document that MyAvatar goto methods have safe landing --- interface/src/avatar/MyAvatar.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6856e8b58c..0d018eb007 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -2051,7 +2051,8 @@ public slots: float getGravity(); /**jsdoc - * Moves the avatar to a new position and/or orientation in the domain, while taking into account Avatar leg-length. + * Moves the avatar to a new position and/or orientation in the domain, with safe landing, while taking into account avatar + * leg length. * @function MyAvatar.goToFeetLocation * @param {Vec3} position - The new position for the avatar, in world coordinates. * @param {boolean} [hasOrientation=false] - Set to true to set the orientation of the avatar. @@ -2076,14 +2077,14 @@ public slots: bool hasOrientation = false, const glm::quat& newOrientation = glm::quat(), bool shouldFaceLocation = false, bool withSafeLanding = true); /**jsdoc - * Moves the avatar to a new position and (optional) orientation in the domain. + * Moves the avatar to a new position and (optional) orientation in the domain, with safe landing. * @function MyAvatar.goToLocation * @param {MyAvatar.GoToProperties} target - The goto target. */ void goToLocation(const QVariant& properties); /**jsdoc - * Moves the avatar to a new position and then enables collisions. + * Moves the avatar to a new position, with safe landing, and enables collisions. * @function MyAvatar.goToLocationAndEnableCollisions * @param {Vec3} position - The new position for the avatar, in world coordinates. */ From 3c4e073874679c911189eb381687454f46deac01 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Fri, 28 Feb 2020 23:52:24 -0500 Subject: [PATCH 006/105] Properties Editor using tabs Properties Editor using tabs instead of collapsible sections to avoid painful scrolling. --- .../html/entityProperties.html | 21 +- .../html/js/entityProperties.js | 261 +++++++++++------- .../entityProperties/html/tabs/base.png | Bin 0 -> 671 bytes .../entityProperties/html/tabs/behavior.png | Bin 0 -> 754 bytes .../entityProperties/html/tabs/collision.png | Bin 0 -> 693 bytes .../entityProperties/html/tabs/grid.png | Bin 0 -> 711 bytes .../entityProperties/html/tabs/image.png | Bin 0 -> 707 bytes .../entityProperties/html/tabs/light.png | Bin 0 -> 811 bytes .../entityProperties/html/tabs/material.png | Bin 0 -> 445 bytes .../entityProperties/html/tabs/model.png | Bin 0 -> 902 bytes .../entityProperties/html/tabs/particles.png | Bin 0 -> 770 bytes .../html/tabs/particles_acceleration.png | Bin 0 -> 914 bytes .../html/tabs/particles_alpha.png | Bin 0 -> 891 bytes .../html/tabs/particles_color.png | Bin 0 -> 1753 bytes .../html/tabs/particles_constraints.png | Bin 0 -> 1049 bytes .../html/tabs/particles_emit.png | Bin 0 -> 915 bytes .../html/tabs/particles_size.png | Bin 0 -> 757 bytes .../html/tabs/particles_spin.png | Bin 0 -> 772 bytes .../entityProperties/html/tabs/physics.png | Bin 0 -> 719 bytes .../entityProperties/html/tabs/shape.png | Bin 0 -> 815 bytes .../entityProperties/html/tabs/spatial.png | Bin 0 -> 692 bytes .../entityProperties/html/tabs/tabs.css | 53 ++++ .../entityProperties/html/tabs/text.png | Bin 0 -> 567 bytes .../create/entityProperties/html/tabs/web.png | Bin 0 -> 835 bytes .../entityProperties/html/tabs/zone.png | Bin 0 -> 552 bytes .../html/tabs/zone_ambient_light.png | Bin 0 -> 1549 bytes .../html/tabs/zone_avatar_priority.png | Bin 0 -> 784 bytes .../entityProperties/html/tabs/zone_bloom.png | Bin 0 -> 767 bytes .../entityProperties/html/tabs/zone_haze.png | Bin 0 -> 594 bytes .../html/tabs/zone_key_light.png | Bin 0 -> 947 bytes .../html/tabs/zone_skybox.png | Bin 0 -> 921 bytes 31 files changed, 241 insertions(+), 94 deletions(-) create mode 100644 scripts/system/create/entityProperties/html/tabs/base.png create mode 100644 scripts/system/create/entityProperties/html/tabs/behavior.png create mode 100644 scripts/system/create/entityProperties/html/tabs/collision.png create mode 100644 scripts/system/create/entityProperties/html/tabs/grid.png create mode 100644 scripts/system/create/entityProperties/html/tabs/image.png create mode 100644 scripts/system/create/entityProperties/html/tabs/light.png create mode 100644 scripts/system/create/entityProperties/html/tabs/material.png create mode 100644 scripts/system/create/entityProperties/html/tabs/model.png create mode 100644 scripts/system/create/entityProperties/html/tabs/particles.png create mode 100644 scripts/system/create/entityProperties/html/tabs/particles_acceleration.png create mode 100644 scripts/system/create/entityProperties/html/tabs/particles_alpha.png create mode 100644 scripts/system/create/entityProperties/html/tabs/particles_color.png create mode 100644 scripts/system/create/entityProperties/html/tabs/particles_constraints.png create mode 100644 scripts/system/create/entityProperties/html/tabs/particles_emit.png create mode 100644 scripts/system/create/entityProperties/html/tabs/particles_size.png create mode 100644 scripts/system/create/entityProperties/html/tabs/particles_spin.png create mode 100644 scripts/system/create/entityProperties/html/tabs/physics.png create mode 100644 scripts/system/create/entityProperties/html/tabs/shape.png create mode 100644 scripts/system/create/entityProperties/html/tabs/spatial.png create mode 100644 scripts/system/create/entityProperties/html/tabs/tabs.css create mode 100644 scripts/system/create/entityProperties/html/tabs/text.png create mode 100644 scripts/system/create/entityProperties/html/tabs/web.png create mode 100644 scripts/system/create/entityProperties/html/tabs/zone.png create mode 100644 scripts/system/create/entityProperties/html/tabs/zone_ambient_light.png create mode 100644 scripts/system/create/entityProperties/html/tabs/zone_avatar_priority.png create mode 100644 scripts/system/create/entityProperties/html/tabs/zone_bloom.png create mode 100644 scripts/system/create/entityProperties/html/tabs/zone_haze.png create mode 100644 scripts/system/create/entityProperties/html/tabs/zone_key_light.png create mode 100644 scripts/system/create/entityProperties/html/tabs/zone_skybox.png diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index 876e75ec35..241ddd1e75 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -1,4 +1,11 @@ +
ValueNameDescription
Play a clapping animation on your avatar for three seconds. Override left hand animation for three seconds. Play a clapping animation on your avatar for three seconds. Override left hand animation for three seconds. Remove a hat attachment if your avatar is wearing it.Attach a cowboy hat to your avatar's head.
+ + + + +
+
+
+
+ +
+
diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index e581fbd194..95f680b49b 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1,3 +1,10 @@ +//VERSION 2.0 +// Modified by Alezia Kurdis on on 02/27/2020 +// for "Project Athena" +// +// Addition of a tab mechanism instead of collapsible sections to reduce the scrolling. +// +//VERSION 1.0 // entityProperties.js // // Created by Ryan Huffman on 13 Nov 2014 @@ -10,6 +17,8 @@ /* global alert, augmentSpinButtons, clearTimeout, console, document, Element, EventBridge, JSONEditor, openEventBridge, setTimeout, window, _, $ */ +var currentTab = "base"; + const DEGREES_TO_RADIANS = Math.PI / 180.0; const NO_SELECTION = ","; @@ -40,6 +49,7 @@ const PROPERTY_MULTI_DISPLAY_MODE = Object.freeze({ const GROUPS = [ { id: "base", + label: "ENTITY", properties: [ { label: NO_SELECTION, @@ -112,12 +122,12 @@ const GROUPS = [ lines: "Wireframe", }, propertyID: "primitiveMode", - }, + } ] }, { id: "shape", - addToGroup: "base", + label: "SHAPE", properties: [ { label: "Shape", @@ -132,12 +142,12 @@ const GROUPS = [ label: "Color", type: "color", propertyID: "color", - }, + } ] }, { id: "text", - addToGroup: "base", + label: "TEXT", properties: [ { label: "Text", @@ -220,12 +230,12 @@ const GROUPS = [ label: "Unlit", type: "bool", propertyID: "unlit", - }, + } ] }, { id: "zone", - addToGroup: "base", + label: "ZONE", properties: [ { label: "Shape Type", @@ -255,7 +265,13 @@ const GROUPS = [ label: "Filter", type: "string", propertyID: "filterURL", - }, + } + ] + }, + { + id: "zone_key_light", + label: "ZONE KEY LIGHT", + properties: [ { label: "Key Light", type: "dropdown", @@ -324,7 +340,13 @@ const GROUPS = [ decimals: 2, propertyID: "keyLight.shadowMaxDistance", showPropertyRule: { "keyLightMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_skybox", + label: "ZONE SKYBOX", + properties: [ { label: "Skybox", type: "dropdown", @@ -342,7 +364,13 @@ const GROUPS = [ type: "string", propertyID: "skybox.url", showPropertyRule: { "skyboxMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_ambient_light", + label: "ZONE AMBIENT LIGHT", + properties: [ { label: "Ambient Light", type: "dropdown", @@ -371,7 +399,13 @@ const GROUPS = [ className: "black", onClick: copySkyboxURLToAmbientURL } ], propertyID: "copyURLToAmbient", showPropertyRule: { "ambientLightMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_haze", + label: "ZONE HAZE", + properties: [ { label: "Haze", type: "dropdown", @@ -454,7 +488,13 @@ const GROUPS = [ decimals: 0, propertyID: "haze.hazeGlareAngle", showPropertyRule: { "hazeMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_bloom", + label: "ZONE BLOOM", + properties: [ { label: "Bloom", type: "dropdown", @@ -490,19 +530,24 @@ const GROUPS = [ decimals: 3, propertyID: "bloom.bloomSize", showPropertyRule: { "bloomMode": "enabled" }, - }, + } + ] + }, + { + id: "zone_avatar_priority", + label: "ZONE AVATAR PRIORITY", + properties: [ { label: "Avatar Priority", type: "dropdown", options: { inherit: "Inherit", crowd: "Crowd", hero: "Hero" }, propertyID: "avatarPriority", - }, - + } ] - }, + }, { id: "model", - addToGroup: "base", + label: "MODEL", properties: [ { label: "Model", @@ -587,12 +632,12 @@ const GROUPS = [ label: "Group Culled", type: "bool", propertyID: "groupCulled", - }, + } ] }, { id: "image", - addToGroup: "base", + label: "IMAGE", properties: [ { label: "Image", @@ -630,12 +675,12 @@ const GROUPS = [ label: "Keep Aspect Ratio", type: "bool", propertyID: "keepAspectRatio", - }, + } ] }, { id: "web", - addToGroup: "base", + label: "WEB", properties: [ { label: "Source", @@ -675,12 +720,12 @@ const GROUPS = [ type: "string", propertyID: "scriptURL", placeholder: "URL", - }, + } ] }, { id: "light", - addToGroup: "base", + label: "LIGHT", properties: [ { label: "Light Color", @@ -726,12 +771,12 @@ const GROUPS = [ step: 0.01, decimals: 2, propertyID: "cutoff", - }, + } ] }, { id: "material", - addToGroup: "base", + label: "MATERIAL", properties: [ { label: "Material URL", @@ -800,12 +845,12 @@ const GROUPS = [ label: "Material Repeat", type: "bool", propertyID: "materialRepeat", - }, + } ] }, { id: "grid", - addToGroup: "base", + label: "GRID", properties: [ { label: "Color", @@ -833,12 +878,12 @@ const GROUPS = [ step: 0.01, decimals: 2, propertyID: "minorGridEvery", - }, + } ] }, { id: "particles", - addToGroup: "base", + label: "PARTICLES", properties: [ { label: "Emit", @@ -864,13 +909,13 @@ const GROUPS = [ type: "texture", propertyID: "particleTextures", propertyName: "textures", // actual entity property name - }, + } ] }, { - id: "particles_emit", - label: "EMIT", - isMinor: true, + id: "particles_emit", + label: "PARTICLES EMIT", + //isMinor: true, properties: [ { label: "Emit Rate", @@ -937,13 +982,13 @@ const GROUPS = [ label: "Trails", type: "bool", propertyID: "emitterShouldTrail", - }, + } ] }, { - id: "particles_size", - label: "SIZE", - isMinor: true, + id: "particles_size", + label: "PARTICLES SIZE", + //isMinor: true, properties: [ { type: "triple", @@ -972,7 +1017,7 @@ const GROUPS = [ decimals: 2, propertyID: "radiusFinish", fallbackProperty: "particleRadius", - }, + } ] }, { @@ -981,13 +1026,13 @@ const GROUPS = [ step: 0.01, decimals: 2, propertyID: "radiusSpread", - }, + } ] }, { id: "particles_color", - label: "COLOR", - isMinor: true, + label: "PARTICLES COLOR", + //isMinor: true, properties: [ { type: "triple", @@ -1011,20 +1056,20 @@ const GROUPS = [ type: "color", propertyID: "colorFinish", fallbackProperty: "color", - }, + } ] }, { label: "Color Spread", type: "color", propertyID: "colorSpread", - }, + } ] }, { id: "particles_alpha", - label: "ALPHA", - isMinor: true, + label: "PARTICLES ALPHA", + //isMinor: true, properties: [ { type: "triple", @@ -1053,7 +1098,7 @@ const GROUPS = [ decimals: 3, propertyID: "alphaFinish", fallbackProperty: "alpha", - }, + } ] }, { @@ -1062,13 +1107,13 @@ const GROUPS = [ step: 0.001, decimals: 3, propertyID: "alphaSpread", - }, + } ] }, { id: "particles_acceleration", - label: "ACCELERATION", - isMinor: true, + label: "PARTICLES ACCELERATION", + //isMinor: true, properties: [ { label: "Emit Acceleration", @@ -1087,13 +1132,13 @@ const GROUPS = [ round: 100, subLabels: [ "x", "y", "z" ], propertyID: "accelerationSpread", - }, + } ] }, { id: "particles_spin", - label: "SPIN", - isMinor: true, + label: "PARTICLES SPIN", + //isMinor: true, properties: [ { type: "triple", @@ -1128,7 +1173,7 @@ const GROUPS = [ unit: "deg", propertyID: "spinFinish", fallbackProperty: "particleSpin", - }, + } ] }, { @@ -1144,13 +1189,13 @@ const GROUPS = [ label: "Rotate with Entity", type: "bool", propertyID: "rotateWithEntity", - }, + } ] }, { id: "particles_constraints", - label: "CONSTRAINTS", - isMinor: true, + label: "PARTICLES CONSTRAINTS", + //isMinor: true, properties: [ { type: "triple", @@ -1174,7 +1219,7 @@ const GROUPS = [ multiplier: DEGREES_TO_RADIANS, unit: "deg", propertyID: "polarFinish", - }, + } ], }, { @@ -1199,7 +1244,7 @@ const GROUPS = [ multiplier: DEGREES_TO_RADIANS, unit: "deg", propertyID: "azimuthFinish", - }, + } ] } ] @@ -1299,7 +1344,7 @@ const GROUPS = [ buttons: [ { id: "selection", label: "Selection to Grid", className: "black", onClick: moveSelectionToGrid }, { id: "all", label: "All to Grid", className: "black", onClick: moveAllToGrid } ], propertyID: "alignToGrid", - }, + } ] }, { @@ -1404,7 +1449,7 @@ const GROUPS = [ { id: "edit", label: "Edit as JSON", className: "blue", onClick: newJSONEditor }, { id: "save", label: "Save User Data", className: "black", onClick: saveUserData } ], propertyID: "userData", - }, + } ] }, { @@ -1469,7 +1514,7 @@ const GROUPS = [ label: "Dynamic", type: "bool", propertyID: "dynamic", - }, + } ] }, { @@ -1554,7 +1599,7 @@ const GROUPS = [ decimals: 4, unit: "m/s2", propertyID: "acceleration", - }, + } ] }, ]; @@ -1563,14 +1608,16 @@ const GROUPS_PER_TYPE = { None: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], Shape: [ 'base', 'shape', 'spatial', 'behavior', 'collision', 'physics' ], Text: [ 'base', 'text', 'spatial', 'behavior', 'collision', 'physics' ], - Zone: [ 'base', 'zone', 'spatial', 'behavior', 'physics' ], + Zone: [ 'base', 'zone', 'zone_key_light', 'zone_skybox', 'zone_ambient_light', 'zone_haze', + 'zone_bloom', 'zone_avatar_priority', 'spatial', 'behavior', 'physics' ], Model: [ 'base', 'model', 'spatial', 'behavior', 'collision', 'physics' ], Image: [ 'base', 'image', 'spatial', 'behavior', 'collision', 'physics' ], Web: [ 'base', 'web', 'spatial', 'behavior', 'collision', 'physics' ], Light: [ 'base', 'light', 'spatial', 'behavior', 'collision', 'physics' ], Material: [ 'base', 'material', 'spatial', 'behavior' ], ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', 'particles_alpha', - 'particles_acceleration', 'particles_spin', 'particles_constraints', 'spatial', 'behavior', 'physics' ], + 'particles_acceleration', 'particles_spin', 'particles_constraints', 'spatial', 'behavior', 'physics' ], + PolyLine: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], PolyVox: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], Grid: [ 'base', 'grid', 'spatial', 'behavior', 'physics' ], @@ -1842,9 +1889,15 @@ function resetServerScriptStatus() { function showGroupsForType(type) { if (type === "Box" || type === "Sphere") { showGroupsForTypes(["Shape"]); + showOnTheSamePage("Shape"); return; } + if (type === "None"){ + showGroupsForTypes(["None"]); + return; + } showGroupsForTypes([type]); + showOnTheSamePage(type); } function getGroupsForTypes(types) { @@ -1858,9 +1911,15 @@ function getGroupsForTypes(types) { function showGroupsForTypes(types) { Object.entries(elGroups).forEach(([groupKey, elGroup]) => { if (types.map(type => GROUPS_PER_TYPE[type].includes(groupKey)).every(function (hasGroup) { return hasGroup; })) { - elGroup.style.display = "block"; + elGroup.style.display = "none"; + if(types != "None"){ + document.getElementById("tab-" + groupKey).style.display = "block"; + }else{ + document.getElementById("tab-" + groupKey).style.display = "none"; + } } else { elGroup.style.display = "none"; + document.getElementById("tab-" + groupKey).style.display = "none"; } }); } @@ -3678,6 +3737,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { const shownGroups = getGroupsForTypes(entityTypes); showGroupsForTypes(entityTypes); + showOnTheSamePage(entityTypes); const lockedMultiValue = getMultiplePropertyValue('locked'); @@ -3954,32 +4014,24 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { function loaded() { openEventBridge(function() { - let elPropertiesList = document.getElementById("properties-list"); - + let elPropertiesList = document.getElementById("properties-pages"); + let tabs = ""; + GROUPS.forEach(function(group) { let elGroup; - if (group.addToGroup !== undefined) { - let fieldset = document.getElementById("properties-" + group.addToGroup); - elGroup = document.createElement('div'); - fieldset.appendChild(elGroup); - } else { - elGroup = document.createElement('div'); - elGroup.className = 'section ' + (group.isMinor ? "minor" : "major"); - elGroup.setAttribute("id", "properties-" + group.id); - elPropertiesList.appendChild(elGroup); - } + elGroup = document.createElement('div'); + elGroup.className = 'section ' + "major"; + elGroup.setAttribute("id", "properties-" + group.id); + elPropertiesList.appendChild(elGroup); + + if (group.label !== undefined) { let elLegend = document.createElement('div'); - elLegend.className = "section-header"; - - elLegend.appendChild(createElementFromHTML(`
${group.label}
`)); - - let elSpan = document.createElement('span'); - elSpan.className = "collapse-icon"; - elSpan.innerText = "M"; - elLegend.appendChild(elSpan); - elGroup.appendChild(elLegend); + elLegend.className = "tab-section-header"; + elLegend.appendChild(createElementFromHTML(`
${group.label}
`)); + elGroup.appendChild(elLegend); + tabs = tabs +''; } group.properties.forEach(function(propertyData) { @@ -3991,7 +4043,7 @@ function loaded() { propertyElementID = propertyElementID.replace('.', '-'); let elContainer, elLabel; - + if (propertyData.replaceID === undefined) { // Create subheader, or create new property and append it. if (propertyType === "sub-header") { @@ -4108,9 +4160,6 @@ function loaded() { elGroups[group.id] = elGroup; }); - let minorSections = document.querySelectorAll(".section.minor"); - minorSections[minorSections.length - 1].className += " last"; - updateVisibleSpaceModeProperties(); if (window.EventBridge !== undefined) { @@ -4252,7 +4301,7 @@ function loaded() { elDiv.insertBefore(elStaticMaterialData, elMaterialData); elDiv.insertBefore(elMaterialDataEditor, elMaterialData); elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData); - + /* // Collapsible sections let elCollapsible = document.getElementsByClassName("collapse-icon"); @@ -4268,7 +4317,8 @@ function loaded() { let curCollapsibleElement = elCollapsible[collapseIndex]; curCollapsibleElement.addEventListener("click", toggleCollapsedEvent, true); } - + */ + // Textarea scrollbars let elTextareas = document.getElementsByTagName("TEXTAREA"); @@ -4422,12 +4472,17 @@ function loaded() { e.target.select(); }; } - + + document.getElementById("tabs").innerHTML = tabs; + bindAllNonJSONEditorElements(); showGroupsForType("None"); + showPage("base"); resetProperties(); - disableProperties(); + disableProperties(); + + }); augmentSpinButtons(); @@ -4442,3 +4497,23 @@ function loaded() { EventBridge.emitWebEvent(JSON.stringify({ type: 'propertiesPageReady' })); }, 1000); } + +function showOnTheSamePage(entityType) { + if(GROUPS_PER_TYPE[entityType].includes(currentTab) == false){ + currentTab = "base"; + } + showPage(currentTab); +} + +function showPage(id) { + currentTab = id; + Object.entries(elGroups).forEach(([groupKey, elGroup]) => { + if (groupKey == id) { + elGroup.style.display = "block"; + document.getElementById("tab-" + groupKey).style.backgroundColor = "#2E2E2E"; + } else { + elGroup.style.display = "none"; + document.getElementById("tab-" + groupKey).style.backgroundColor = "#404040"; + } + }); +} \ No newline at end of file diff --git a/scripts/system/create/entityProperties/html/tabs/base.png b/scripts/system/create/entityProperties/html/tabs/base.png new file mode 100644 index 0000000000000000000000000000000000000000..1eed920742a3aee17134a9773018882ee83ab0ff GIT binary patch literal 671 zcmWm4ZAcRV9Dwov-Oby%Ik{=(oNu=`nzhi`QYm$}wM-**T7fgfu>@a0Y}s^(N5IR(`0(EF%ylOY1|anV>{!QfxM6?1A66r^i@wLBJF9060Mzxu@?wBC1pw0t5I6*2 zwg7Ay0NZAOGcJJmrh)3&0su6w$e_Do|6&Oq9%?a8hLc69d5%Rwg`#~w=^&pqIsDlV zLRg$O!snrby~qj1#V6?~ich&D$@B7*9gYR*OH`{32n}j!U^S<264v$9*Jz)+!u=gFx*1tCbH*rNeoEea=$Tt`I51vZX6A4q>>%Z@kK`(PEa>Hl?ba~D#YxQ z$0FZ!*8!U_N>a?6V5Hi3FFIeA2^`>%eBrzPl^ib*P+|zFr`?!st0On9N5DS9tY@=q zfcTs<5705ZN_u-YrNOJc70H0byLOzMG`T42Lu1z_VP=(O2#vhrc+gXPmNZPM5 zcaK^v`}ijoC#ZJo0xlR$wL1w;4r5nnn#{iNzwe+lW0|o+-pDgKg0e<=t7LC4uC3Ji zFba^abe6XLPLBD0M5aVg;d2&#tPHayYWUGPgABdB#|HD+N}*(H*C1<4JIo`t7k2v>Bz#4w>ZJO2Z88RU%s literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/behavior.png b/scripts/system/create/entityProperties/html/tabs/behavior.png new file mode 100644 index 0000000000000000000000000000000000000000..9201fbfb721790b6c5ad3ff7451a2d28b53e165a GIT binary patch literal 754 zcmXBKYe-XJ7y#h+oSmH=C)3Y{rfcMvX{MNIF1wNYrc-Azvx_k^axKtx)fJ_M+1Wxp zmV~5`n&5;kQeX)aB)7tCSig0H|_I#w`F4 zK8IrgV4{5e3;+a_nF@{o1ghsy(AqXPm=c580MK);^7rOO0Kj`pTg(6_VgUHl0KfbI z{3n2;NdTX%0Bf58=9iu?8pr~m?Kwunwu(`k&+pgEmQe(flRe?UppEJbwUEe2Yw>&5 zmW5~OJ8de#ubzAwNyb4`dtxYBkPAonzF=XUb7nOf0tbi6DerMy9Bb__!gm>|3eU>K zt!`-;D`*Bibw%Mcg;?96JVrY(^2?-9V~seka}z0kNlQhfEl_+06w^Dg0PUx}@%C@N z>e0kawz76cs_4wzl^1!E<#2<1I~fj8P3!ZmZUZU7j{dM5 z4vUW|&nvqE-h*~Jr#9>G5(1OACL)^>SzCnGz?``^LJkCpKRqV)@+A#EL=8m#3wm8M zsUra!qy4pmjf-@ycA^#w?Z~W%qd8m|mXvWaq(0jmhc42NXr1dr`mg0yCD6i~-jAWW zhxek^e2nd-d5Bta{(eUsQ`mA_lRf^JBG7}D?y0FO?r!bi3reqD% z@lK2O`E2c#nvnRa0AXc!1dYf{0zdWchH+4_AT@=eg{Jyq)_lTcsidXv87bOMp+X_b z-8)r?^d&${%6?p&xxruM@g+rQ^z|0$%VIPJj-@Ej$xt+RL4MY`I;6GB&~=QJ_Svts zC{#fQ!UW2p)#V29|A+f|ta69y5M^6vuiL8-uXcx@)0ULD`(?TLK#8X5?Q#OIALdiY X3R8urbTtLlZUBIs%v@tvy4Cd;>L3MH literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/collision.png b/scripts/system/create/entityProperties/html/tabs/collision.png new file mode 100644 index 0000000000000000000000000000000000000000..c9bed393854c2317061ba781ab2baf502886420a GIT binary patch literal 693 zcmXAiZ%7ky0EXY2o4d5>wb|*W*srvu=}&t^ z3!cGhii16IFwl}3_X)xq$}M4^I=B}FcV(bNsiH@2v`ld$VVctuu1MjQ@hJ$;v8Ax= zC!_7LXJld~Zw{Lr!h9U*(Z2TQ9j|ur=}`r#MD|8$?XN(}Hs+qQhT@R2*_|Y*B}Z+; zlsAq1YF#?~uh#q0M>aLWdn7icoUo3^mH+J{;p64yg)}z98KWk=`H`TeYL!fISyw>b zj!0&0%as31UwY-;TAbt(<%;_FIM#7;XC4_{FRlr0 z5WZ9Aqr^p5ggQC*m=1-vT{l;vg#pTYkc@_2-NjrA7MoqZBx5QEH#0|fjz2734Xe4P zW6zD*eJW;?Y<@c#4N^*JqE)J7F-*2NM;FJBC~JJWUMUB6r}bHLlqVz3>Tr2NfZA7sk`PFfx#` z%r<$Sd@8^jZGD@a;~Z+yR@!Wol*wRu$L9!Uf7{Z--0$7f)*jxmPeS+!_v|(%+%>$c zd6G5U%9dUPWq2T~ati}(J>$t&^uy;fIdqj%SvG~HblRT2K?o0!M&S3C6ARAgnoIyN MXwGki|@P7%Wo@}n@P(xasZ&Sj0O_` z1nopg0bsE%bsYfws*J@o0E%5ZVbFDdN08^za?${t?G4`i4gf%>jiwxc`X~Ut8DL`@ zfL{Wz?g#i`21xD%2)ul!Y%~J^Pt7u<71%yneB0Ych**pToz4{mBr_2U6zVDghSfg@ z#Q!QDp~aW%xS!a@&Z)#V+>jQj`N7BF)b2Y9xFBh536~jy z!XrqKx*c^}FNQ*u)#2 zFDHza6nj#Tke9X*2RN1LyUrIWbJ_y-wD&)wghx&x&)^|QCZg}6o`;@m)%5=hDlTCx gOwQpv^bAP=lLC4CPd!J^W&;3Z9m_TJr<DbosK2XIqbPH zBJ8}(GB1mbgg?w5n)PFiN%Q`)QO}yi$S#|mxjE~P&wrngw|ucJDJ=HJ=0Fge7x$ zXM(a%(zcR+R#qHpsy(1J?cNKH$wz_(^s$2!+1Pg)OTVsjA=}|Bx1-lr>)Y5fzww*H*z^UaE^flKcmc+6one5CSu$YCkK{W0pPLpI(5$v*GuSzy@0#Up2 ztIz7t;pi8<)7QDpc);CC6f0fXUECl+REp9)h?J2*b#xod;44gC#O|ryk&f(p6pWVGP5pq3pJIkc_jlykV)8b-}|tPHl!JrTL(7f zE5(9Vm(gzNIhn!x`j?XKgHIBJ*^r6UI%N^5lG#)}oW7jB79ul9C1+NV2NHYX85*Q9 z!RXY()(sp*KuqT%Bgq4f4XOPHLo_zVXcOA=?SH(aG1>O!95@Es$IWV5a_7@Pbkv1q zr$yGGM<-G^>B~EXAnD^YZVYm3AnP&yMKToN> zcxp?_o<5>=09d W*Xq6BN9Mc-fYOq3_2$Cr{r>@Br}mQo literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/light.png b/scripts/system/create/entityProperties/html/tabs/light.png new file mode 100644 index 0000000000000000000000000000000000000000..bed097d54efa5c90948c3b60e9502ccc0b94839f GIT binary patch literal 811 zcmV+`1JwM9P)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;p-DtRRCwBA{Qv(y0|}rXh$VqI8i@ZAqX8g*SV%CO z5r}PpSRRPkfcQHxng9ZbiGeim7m68))c_Dc=oa_^aTy-H0ww@43z{4Va{@6h7I6?Rg6ds}EDjJr=!)2Zcs5jFEt;G*5PJc!HxL^D zF%yzp98}MCAQnW{2M|EmTmo|Wd?3z&^38yF=YLFa1c)7>Y9fGmJrE0_n+Fg;j0BQt zJP^+T;-5gg9Ei^Y@joEe2I2@H76Ia7AnwCu06+jS;0R9;wnK8M3Kn^3Al?X76N1Ye zfB?c}I5QBR1mdSaERM$!ph&+6#E)=AK0pBB(r5s6Ss9dX3B-y>@{&O83T1~u)dpfS z3m|}4pkb(il+GKWVGII?q4a!cuD1u`Pe8m0h&6#&6o?N%)ffWtdT2gUg^Jw+2q2Ix zSCLZ28zANZ;zTIl2cH8HhKbiJt=EXF$w~ zBsLN1T4QWx0R#}fWZDANn1LjA1e#*lp?q(sn)T4&!Y~IQfbdzs4a9q(2E-s)@EFQ= z0^)B#d=rReahU@UK=>?RfJPuFonM2x`Vf*2wgK^59GMV~0Ro7S1t2^Vi2nldc_97` z_0a_&{tiu5c=ZDW5DSsD-alwXa~z04g%>B3&jiK)aA^hzAYv?F2jVwCY==}$f@-v* zP>b*afB+)Kf?q%^0mPeu_y>|cBWUT0w>Sm}AYv?-4Q)wSLNgl!w8{keU@{>K00M}Z pNQPlhv2hw&w0Pr6_vjcPzyNIGDB#oJJ_rB+002ovPDHLkV1jqEENlP( literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/material.png b/scripts/system/create/entityProperties/html/tabs/material.png new file mode 100644 index 0000000000000000000000000000000000000000..458c6bad48768ceb48a9104384e0668aa62a7b7d GIT binary patch literal 445 zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4mJh`h6m-gKNuJoI14-?iy0WWg+Z8+Vb&aw z3YK(7Uq=RpjeRx011B>uFeoH@1o<*BRH-sBG&D0X{QS?r(D0Ihq11qZ;Z*_ygVhWM z2J!q!@kiYl7#NK`T^vIyZYBNs|KFZjm(hV?qr=Oe4sZC6_^@1Qj`=*Bqgb->hk`&m z1B-z2754j$GnzSi*E`H=_`%Lt8suQZ-_gp*#PO^--X-b-YezrRM|-AMM;7*_F>olT zsjN2^cv+ex!xYXe;NZh!!p6YpQq0Z3)bUJ=fkoh~E(3?ctY`)Shb2)5c#hO}1bi1i z#=xNi#DQ+$aa}*XHaO!$YXS1P>go) z;rr{niWOvhh@*$2v5>Od*Gn#H=@mBZ biH9LQM#qjZ?@tZ`0|SGntDnm{r-UW|yn%$Q literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/model.png b/scripts/system/create/entityProperties/html/tabs/model.png new file mode 100644 index 0000000000000000000000000000000000000000..79aa6b3830a79de2addaa77f6cc1b8fa529576ae GIT binary patch literal 902 zcmW-ge^8Tk9LGP;^X&J}X9!N#lE<3`>CzF8pfck-oP%k~67BRt!(lR&BkowbfasYL zJRDd4BGPHPVbMUbg@|s03Jj5lLX$P)=FmW7%m{HjZ*#56LiZe1y2n#H&mO{sAfcQUiXaI`6deoGuXcS}Xe7>V(D z*i{l>HazVmykG6lK!INCvO7}-y{c^qtBC=)mK=Seu`aUJpG7}&%=!`a%kWWvN5fgn8Vg;@SEuAD|-rW>I z%5G=e3-!h2xXka%XS%J~jN9gj~-cM{zLRW%@MOxBlC5d$6i3eAeP!#erMY zHg5@h`8b_@m0ffpry^QN-y}DH-n4EQsu( zOzCeYSmrLC>9~%jR9KFB)p+to28igvx<6VczUcA&D5HdW&uq(9HG-LbMDRnD;I;1S z30|pc-JnJgiM9_&kyXm)1xFrdf9R%On$Z)2!{c&`fw1SyegeV{&kuJB4gadIRdmJ2 aKxTm&?d?hP;?GmZ0_VC-_P*lEL;nGCU{_rL literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/particles.png b/scripts/system/create/entityProperties/html/tabs/particles.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0d47cacb7665e2553a63ceed9291712163d1fa GIT binary patch literal 770 zcmWlVe@u*F9KgTtbN9Yocir{0imt>X)gr?ozsvKUt1dZ|V~23gkJN0(S`$vaFNf!_ zX0gOj$3K3J`o|iUUoUHBbN+~!4cC@oMvUH)&hE2){`>s(39MXRY}BXf0l-*dx0M4x zN>rTy03Y_`s{jzY%f7Y-z>pY~gLCJjg|9Ua9 zq7DC}KA2K3*$uQSp7WGd=m9Y- zq*IVtCG{mS^UKUW*`*7-KuR?o7pvsT>ZbY4LKq({QW*Si=#s7E`i*w&aSfo|K4d#0?0Qwsp}z1q++J zmDZlMefp&mSo;~*F&BHSzlJS4+PlRbv&ORcv{B!f-uY;PpF_H{kA>R&>3A+RZqh54 zLfzXBUCRZ}evE9^jPa)Xhu%GiT3qd@O6AS zo=7aOcl^0^Cm(JjrX$%~iYkUVq?;;dop-dQIE&tBI}CZl=m5QpG}tF8@oa|pu%iO_aP-O!EEG{^h=|B@i{&d5eup7 zgoquP8D2a1-P$js86WrNi%$kpMuVOKN}_K)(2Hh}b3J*M1J@oZB1SYvN3u~JZ7nV9 zd=BK-@Gl^3^tu6&!=!x}Zq5n`b#0zu`ZKbPmR1wLQJkXX9r&?Q;z^rIsvz@P@l%CY zcd3g)B(&#SouoWAR-Ywqth&RmL;YaYp%qkQ4fn;h=&7Zz0wNQatd#5+ z+?^-9q7hetycxT?DyrF@-vbG==%eK(oW=6X2giNk-r!`03h&e;LsuFpX}ICYeqy1e z88U1X+sS@!rg$O5F*k?QVn?_)IJ)7?WuTbSv-;N33D}G8c0a1pwk|GqH3|t2B!NNK9dCKuZ)cchPDMwIedsXp3s5!Hj2j$*=_g`ewUuwk#KN&6 zcj)pz=CZkyt+wK!N;-KuR%o_lAu@5*5Fcwm^~OE3%G=Ab2$tS7RlDBTQrbn&dFHj)wz|eX_vnEzWcoTp0PF7 zX_UE20MOK1tL*@glS)nlz{oUGPW;>&OD2;p)Tx|8GTMTs1}aCJE0bQ3y8X3v=$1VVC_dIco{&rJ{E zgS1eIKdlZ)JwW(3ZFv!U@;L_~7NdmZnbGj!7$F)Br}WIYWnZ2=PDZ|Zt?##87(y+j zS-FL1-~_+cg5zmi4}atiDZY*F$XX8_z8R+k$HW0(@O*z4h;7K_kJj*Xop}x;wQ*+C z$kWe!LB$cp&L zc)_(|jOlbP+%=Fs?$p!E=Nx^a(J}49TEe}Y+vUE;PURnyz z1E}>z*3q$fBJfCrg+PYFm1EYQ}o8 zIPm=!cv1ZAME~}cI)wED43D^ zEANbwku!KrDV%;YP>3NkT$9I7cMa{W*eZ>Df)~#gr!jbC53R_ldfk)Hje}VCd6O?K zVb<@^HqXi^@nn1IvWt)hDfdgv?-osAlZ^dE2ks)Kv-VYBoDeE~9Jze&<0Sxq`kKb- IYZhnU{~O0lBLDyZ literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/particles_color.png b/scripts/system/create/entityProperties/html/tabs/particles_color.png new file mode 100644 index 0000000000000000000000000000000000000000..ac66a902cf8fdd78547a53568b0788862bbe22a7 GIT binary patch literal 1753 zcmWlYeN@u-0>;0*h@haDTY$P`E47u57w?^E8CZJN@@>wXF7M%|lDN5&l}(%E53-1+ zrRJTI^9*N8J(~^8I%=9=_&QCjPB(kIfL`U6bKpx86!_iaAD{o8Kc4e>&T}axDVF5s z;|2gA#m7ab0syF+;Bf!|Lvf@P06-ANWu5}S-Fp)hXlUF_UO0Gwt5@CE`PLJk0>@G5WU9{}Kz2HsR_ENcY9)_0?ctvT+14)`d+RA$rKg!T9S}e*V><+f zM~`w0)wO(x&viL)tAPkmgV>+%NaQ5hUP(z9*_9gtSshE;wFrz*ot+&ly8v4txR}#| z1P2p|6A8rgfD2GZSa#Q$QtnI7!AIOiFvv!n_B^X_0f(8@DVp26PQ!NtxOT&r74|B z3tRcMeiuDT^{XVWBeD#;x(xTip8oS}IrTI<|I2TfOqNq%UGvwX#Q>cNZaIU<95Az+ zD_VBdA~C$RKV&nnZl6JgVlWGEdipzwPzBdV4Vz5QVAW!4H+BK(9t|8;b7)gHH(MM^ zN;!}IdS9Gjp+1>tR%WG`GCIDE@ZPHZ1cZjlbB?Ni`m?tE{%g+X&tK5W9OnNsr# zO@7YDxzNMi#|)2W^Q?DQIohXp)Z!>ye0e2(^rLarx+G!rT9^3(=?)yNI;rYMzsBO} zEyezNmdI(jWL!l^H>=Jh&z)V@j#_4drVNN`0+aA=rDkF>70o~R!IixYHIi|6YS9!H z!)J-mxF<)TzI~+wi_`aN1anB0df+=0T6W372-PkiVTrn1$AhzvK`y4d6$U(CJoM3& zC4>H;{Ax+}2XdM`K(b4GgAz6svH?2;-D{M0(h-_RlT7+>a2J&1g{;^6Ff#XNU! zQ03TCNS3*ixe1J(!j3*;2}B6KM<4T%=~3Iy+Vo1Io|~=tc}y%zOw(MS9Muq4p`oWR zk%HI-VoGZ}LOa0`xV+oEdFdi~Zup98ouF?b#a$Eb-L@RTOb|FXCWQ48ieOvm{WZn= zHWN=8z^Nu)T%VaO4oo2o05UiD0DJ?1bIvRwl-Xk8mtqv;0d;%c=I@#c^5JHahGF82 zCbgFE$3dJlRzvJEZg8YeI6}U#trdlq4XvK~pLvDoYmS`jZ-1~{^VYA~ZoMj$4Xe_ywSo;QktFQAVk8Po;LYc^3 zoo2w|L$xIs;;^l|n~W3OVQno!rK-Nb+|^{+g4(PCfTsthZ_UHqQEx36Ec=jWdtmi` zb)9R!DzWKss_@DwF5mTYp?|*ByZY($!`ooRE6l7nOY(TF<=p@^xGH%~(k9QF6%(+F z;G})dX02bMNEveHZ+vLInAq5mA#r)pYeHxqi5ue~oFWcKel&2NW8&YKlh2Zwvu$#Pz}Q6juCVsG`Le(g%z#>?er9Cg$iwdF{4 zgCEw3A~{`(!WZ<6Yd`Yb$7ivDZWv!IeRBjEv@t-p$7WYqJ|nz1nh+GK?~MG*I<|ad z$zNNT*MelJdytd=nS(peXnSwEDK6~C+Z^7|za7i9H5J#E5IDP^lYC^z>G$!cw(ybE s6=G>3lIpdLvS16N(zt+0?J*$ zYlR?Q3<(*7Y>=!W4o2oC8A)cX@r8-ZAxcK*8gnufuf&c(Y54Gbd%iu-@pR*El|rik z098tIVkQ7+){#>HFkiXT1pw}4$$1q3O7C?r=jyGKx`L)Uuk>68M=6PHR@JYZYi(`qE%d%Zn&Vw=bSZEL zQBf~N$eagzA&RpUpB;=kDt1c--*= zv#LJn1{j&?BE)9i1vg{Rkl&st+(ytBFq?)>#huaUDJ6OLSr;+K2s7p%+JXZvdTNaS z_6^(q1Nvl78atc%F&@J)8eTcEy-pmWY>cpg;ZKyQUrV z;>P)4m1X~Q?G{ouDY!I-?ERFZ21Nr#w&aE+3)+XIIQ~+&x7Df-@xNH# zAF_4eQV(;TJopMYYb?Xjgrf-MU|b~+36HUm$O5M0ZlvYEX&L7^aHtSEr;i35&#${z zAWu8@4P*8g)*-&D)knCol#L!V{EaD-tAk6U}|;ZDJE{c`scbQp53W! zSjg;lacDlq@N-bTvNuwN_`*0Bp;|OqW+wPRL!>+Qj%5`Q={+Wlqz~)NB$sXJs|3^N zEPJiN4)OF+emGy4@zaK$#Blj`-z4Te8*cjS4Yp#r0$p?upO{P7ry&f{?x2sMWrPi< z=dAsscbG7h)CpKaiLi~XWJgwt2b7O^yUMh;j16iJ(B2;JO?ebduMkc%x~-U$p)Hsg zgOPN#k@C&TvvAKd*PG7{z?DgoV>jt*&}kV*khHfc*C-VE)NInH2eeu@ufEy$$->SP zYDIS#dO(x|EVV>U`8lFiJDQZV9?EPj~__HYF=N%q|vMw8KkHWfdcKV-vRZ@hRUtR69QnZ~8 zXJBV0|GD~sD`B;LPjrQ5pu|HYi}#C~i>ft+W4zgt#ZPcCCHjK9Ezj|-WB#A}N=h;% z4l3{pQnDvL`EcJ_v|bc8F>NxTAK&E;0tPPhgPPAf)Zuu|77`KHOp#Uz2n@m^~&B}U$JKdo7Op(`pCmbg9rzja9vj%}DAK}n}y zG_mOZDpF4%lwISh?<+ul$}X)ur66DrsargeX9l;EJ@ACI8qxYXMh#-5Ib&*)2i5J7(Saws-MPn$I7g3AERYQJ1Fh zXsbf#!I@Iw18{dvM?@lQo*LN zCGOJax#{+Zu*670B#t7OTeP%|34{Io$_xsQaTfiYyQEqh$raQSNzd?)*I)1VU{k}6 ztW0MnfUIz+t{K3pWugVZ{IR!m0MbXH-A4gy?lKNzyW_N}Vt5tk`a zEVsuk7EvahCM{sHPA8F6=pNyFbN`!AvQw}4Pz)4+mqzv*fQ zD^&G2$k4fU76p+=+@|qquH)(RjMTA54hY0L@cAO2>Psv=m7H}YX^GJOsIva-8l~G+ zF{j%4?3?~ICq0`X%3a50kyRXZ@uz1cO!wbGaJ z;?G=awcH!}C0mW#G6|inzBKUQ-dvM&<(aQ()T}kumf`$Jx9pIAk!e`iri-)3J@q9Zjk4W5uTmB5selv!;wU7uu6KMIB`7 ze&SW$u2D`PZYwQ4XV(tLBk?~^xwIR>A;J zSreUKzntb>qg`(o9P*c(+~-;A0j~`*&)CAOMU)-Bx$#Q!EV9%3&7SZ?WdV5cX6zwd h4b~te4e$9U5X;f>qW-HA$ITc3gts-+U98z3`yaC=1g!u7 literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/particles_spin.png b/scripts/system/create/entityProperties/html/tabs/particles_spin.png new file mode 100644 index 0000000000000000000000000000000000000000..32238ed8f33fe6a1fdbc6b654178712f1e3021f9 GIT binary patch literal 772 zcmWlWaZFTo0LQ<-$9s>1JK%R(a2So}abV1618o9w7tJgAf)g|sbPuGuo}sx?P#&ipxbnQh6YwF38aBZ(O|*E|++?f&@u_xb0u&p@E@ z<(%vl*#L5U4fR0)jx-h-z}@cWlK`^18eZE6SeK_EIPp>15O;a}9w2@s{O>Cx0F)gK zK|jz_3g|IlAqD6Ufc+J~Y%8!~3@GRv-gf0BKE1|nrcqq7 z(Dv*^4T$J`n33?TRrT#P$_oQKeOX_*86uV(rP+C_%h4>GwE^oCiI>rJk^2xVbM4Mo zPZrSc*vOx~yTglh!Fz?VWlz^E&XRs2x+eUOKg$&dRH|RDf*bv zb!ZKJYlpqNudUHRy+7*bJtD)Ujw(4+sGggV%>I-Xn+X*EF!>h}+L_<$ha3!-!b1Yj z)bBWcI<|$W#?|gHyK$6X6!=Z%&NH?}MF^I*N9||67_U(KCW>4)bNOf@d3Qa1)S9SS zeZ!_h(8f;v`n0@6w8CMt$(?`SzR8u&z7R>0;j+NN%h6B2TxMK!ezrjPdwgf34xt=< znw!=N@#5$9#DdpWely=Jg=%+iBFDyW4_s#;hdWM6^zHtM`DcRez+oa-wvG$sj$HPR zeK5VRBYJB{J($7$>}U z;n7t~w_kjUzW+h9#9(jPGLi$qhBxc_pRB0br2&A?+gN|Dt~L5UWwj6P literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/physics.png b/scripts/system/create/entityProperties/html/tabs/physics.png new file mode 100644 index 0000000000000000000000000000000000000000..f0fc451d37067de6e77a17d0da65f274bb85973e GIT binary patch literal 719 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 literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/web.png b/scripts/system/create/entityProperties/html/tabs/web.png new file mode 100644 index 0000000000000000000000000000000000000000..c1fc5736193f968574eb64a4827c14dfd181ad0c GIT binary patch literal 835 zcmWmBZA=?=9KiA4J@k6C^!lHr<-tz>Gh4EB6d3@(j{;CWBzHgQUD;U0Z2Ci`gQ;;cK|$f8X&(r)E=(`pg(ificJH*c>dG0YNmuDP+FQS z02Ue11;(StOZdm!1NMb#UnZA8DINIJ8oXjw_ehxv^l44W8r^)AQNL7*QqCUvA*4|} z4(hi1Mute3R_hv8U09H&x~kAi)T9Ho56#Ro7o9h9RR>TiL_xkszjAkwPYJ3=+du^Q zqo-%@h{ycSSdRP~!y@BPjxIdMskeNYZDh?jo09#~`v{Y>8C{4t#xB4Kd5aGFt9$%LRzk=VwuWg^H&mrniDaC{~h zFkxwbaCqd8$#XDagDmKl$ zyrIEcAnV3;2g=X|f2)Dk2uonRt;brld5px&^7p=PEwXvL_*nY6$kh2H{mw@D48774 z={_0!9k8@N`RHYxyHOkGqGG(ernjv4<}AHpj0{wxK)wHP=MLYi*}TQHp2xOJnE}Dn z8`RxW#6`iX_iZ6w!^Z-|zp-K4o68z^jTvPm@QAm+t1e!H(7ATy#k}0>0gne#l@j=y zpR^}myFWTyKAV%LuJ41B6BEjA$4)BpdZh`GkxO08z@kK(6(|lyJ67MDubVps0N~oa KxAv2o4*&lh4>h9z literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/zone.png b/scripts/system/create/entityProperties/html/tabs/zone.png new file mode 100644 index 0000000000000000000000000000000000000000..276ba2679991e820a961fabdcd89d804c48499ec GIT binary patch literal 552 zcmWm8Pe_wt0LSs)^S&#y1gK*`HV3G` zfPrdY%Lkl%3LLocxbtHpKxW-e$N5_u{!A{HJI(&-;`PCGeW)b7d)6M+RBAui<`dS2 zbR?KD(Gh-HPnDyxEUzk2F=W8bfGA-lE5Aoyuf=(W~ctUkxoIeVl?|U{4<} zaLv6m4{}+7sl|>ZGO*JnZgH(_O)If+jT{j`;zFER605PmxS<1_wEx0;wRTeMOYskQ z6?Qm iTC`7++~!5^LKBFHM&r`#yRZF20N_5;;+$*njs6E|&akNf literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/zone_ambient_light.png b/scripts/system/create/entityProperties/html/tabs/zone_ambient_light.png new file mode 100644 index 0000000000000000000000000000000000000000..ff01b16aaf0baa4fc791c8d79b741088f5e22a37 GIT binary patch literal 1549 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 literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/zone_haze.png b/scripts/system/create/entityProperties/html/tabs/zone_haze.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf96692f834c6830fce76295e73b676ec5f03e4 GIT binary patch literal 594 zcmWm4T}V@500!XqoU^n4xnts-v-G?02h5>nkr?VXb*Z4{%t9|rYe5E5imapr&t~O{ zis>*^1W$?Nl|LX6WEaYWLuSk_GP*KJNRw(2v8A-w#dG)Eudk~#Xf0X*hU%({1_0(5 zwGzPQ&EhZsO=neeH=s+1VK6ox8;UEoS{pF`xOd;-2SA)v4Yk0n3_$D$B2hrx0bF^& zZW~ZE0wi4@YF#-EFmiQ;t+D6RrEoMFEhqo9fl~KJgEv|FedhQgpRHOhn3J>0win#t z1fh=`H3&3Euh+k)i%PE%A(v8(^@x6YGyl+SUTCHM(zvM!t}9rVdk?v%MRbO5zCHL%#lZjT0MvO#klHymjiC?Ck@o$NWQwXxh zN_&mja=BecLvtD;2K`sn!}?av35B2=Q{)a8q;M4OoDn9l>JF1(YmnP&6u~z8;sP6z z>8E3z%^>d>H8Hi%?A!avUoJ2KR$V;lI2C7RST8@OYHIh@*diiFM5@eULK;g`XR7yX zET!#9L!VRgloak>iC=U55J&tEO0e==PmxcLel4_|8=VE~t4SZo?9+JDY%SMxC;Ubtnx(ZTMtTtMZINEQq7k|0$k4Y;=itCyk4fIHpRWX? XMA6=zi^c`{H2_rG>ndi-+C2XOVAjQD literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/zone_key_light.png b/scripts/system/create/entityProperties/html/tabs/zone_key_light.png new file mode 100644 index 0000000000000000000000000000000000000000..6527c65320bf61d9df5b514c6abeb961a28d40f1 GIT binary patch literal 947 zcmWmBZA=?=9KiA4^-8ZjTKY#G3M-=rOolKj55)|(mH*N5G`De*E~!uDVJ_lAVha+G zEzm0p$Cjak%rQ1ux3~mR#$a^|8&QyJgt#awYITbt2#a>XNMy6sh8kXc-hJPFd$>bo zDta3Y0IG^|a}@w2Y>~?VV5wza000#B@)w!_B4f4?FnDpRkiNzqWC6x|PyF|MKL9XC z%Bv0nv^@#n>;wpg0i1sTH0J>LYXF`d0MNYASM4nYAfKu*vzFFh>H^_#*u-qoViE6C z35o8FO2bq{CiO-B^|_tJs~$cOgF49bDuj0_mCEn%luS^=db3Op-v*V#OSw-Rk3iM9 zzbNYJCDM_Lw1h)~fo}+@L`C_v+3vrct$AmTeSnRGoJn_Q|B9#15iuDOM>e{V*7G`y zD+X^jFwe|h3Fje-kRqdI&NQ2=t7ynXI@9tV$@6)121DWWbrG+e7)B_J?(kOSJf$Nf0x^=K$qwP#Kb78&@NblR zser6A8S+DXK#hSezmiwR3egxTXG-l=F5tdC%undpriX`_2S=yX z?WU$tBYFvYZQ#ff2!wZ)(`?s6_UDWEE-fBVzD=ZAM)&r$vjaOY%+UJdN$i`w0@Fr| zFIzYK{K+^cxJnw62X|zluLy@BI^H80mm1W}g=pxL${7xYTy-+f#(nB^_xV;AW$F5q zbR@sHN$^EDq+pyig^BO0@%$swuot`{mJjh!UgnQ0`?G>Y$=uYZtXZ6;l(H?`tJV7r0aQ#56LX6{X zqD60T_l9dZCyH_Y75CGX1;0l;N0R(HvGoW~b287NqM^q^kfc6vq2 z^`15Le=g0g!}?qA49-&sD;MmWpn6U-yr$=jdA9DA+w<0y+RHFvx3S)2LYe?WU3*Ss St}T2C08mkK$b7B1#`QmdhF5<8 literal 0 HcmV?d00001 diff --git a/scripts/system/create/entityProperties/html/tabs/zone_skybox.png b/scripts/system/create/entityProperties/html/tabs/zone_skybox.png new file mode 100644 index 0000000000000000000000000000000000000000..17697a817b95c802e2a3384acec627dd5d1d71da GIT binary patch literal 921 zcmWmBYfMvT9DwovdCzHS%PD=OP77jqS8fyB6rl=i()TDR7;zOhGIs$|650@SbOaq6 z!YLpgT(Y4s1*SkTCdCUA$1W0`z>ZUKWWZb`b5YXBWeXdYxe3v<3m<;po^MaRW!HAC zCR76e+RTi!YydDUQ7Hjn;^5{508p1?>@5Wd)GuM6_0&?q*@P?spy$(yXS*8#fD~k8 zX90W^1t8V{EcyY&KLEkJ^~9@+*nq)=OSfXSO!hh#^tg&`(PFxm=lL;uRVnGfTc%XO=pyf)h!6f)f%9mi zIp}OV>xjpz7zd)@EPk$))fwGqRvbW!91#t|08{2IP|o%nB-S||Dw)LQ5GjxGrjlH( ze8e%MS6B~;FgT3_()Ld{^8k4rBo)a&H^?VZ5C2LjAk_-jWqa^Etq3maPay{wYbq(M zweBb1FrIXa>05CehWXtMsUo2GO2!d=ycTeKUD3`c;{~B>dL4ckU`>v6gj>RZ!}|57 z45NeHE2S(kNh>`CZ#4P)ht4476zeeHIPiv%Lg&$%y9tQHY@*gi_nB(@D)dd)Lxyz5 z!I)oMMc0m1JYGgbnwrmAbKDnQmcH;EbKoH)_a-&$F#!uE{ui8Xm;9d1s|Kh~2 zOY|idBXL}3z0>I5fZLDE4-0CJh$E)&InS9i?&daoY(cs{Pc6?i+yEr0hrb{`GZL1u zawRQR%6sh}RJjB;02nUryII%9HtOYWVE=(>jFlO4sINgIzT zZ#i6U8K`{eAsW(c-*5q~DR{BwJPlLI?^%3C_XEHIL>y`CGGRaKNua-L`JJXdaL2IrL-X0PcHaaDrMm|lSW61_R zFW~D+PZ;slH|df9sd7%(JEJxovNLsoV)cI0-KT!n?fW6ayyeRB08AIg`cQ9cB=;ZP z!{;mwZhF=$=9V+^+$B!o?w_x-t|liAPknBq6H-xnH{5YqKLf Date: Sat, 29 Feb 2020 13:59:38 -0500 Subject: [PATCH 007/105] Delete particles_acceleration.png No going to be used. --- .../html/tabs/particles_acceleration.png | Bin 914 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 scripts/system/create/entityProperties/html/tabs/particles_acceleration.png diff --git a/scripts/system/create/entityProperties/html/tabs/particles_acceleration.png b/scripts/system/create/entityProperties/html/tabs/particles_acceleration.png deleted file mode 100644 index 5a52591bf7dd6ef5334040ade840b0b00ec33ac8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 914 zcmWm4e^8TU902g|`|jo4+!%XcquB!Xh+&vBnP3gf@w^0cgiHiHn|VpEo-O3U#pSG< z+`CEKEB-itg&ughQ5l_g)yiacM995d=!xvSdAG`|n3o-$rSI9r63%t}@%is_u)(!n zt2U_tKwImqZUlhE3sfus{N`Ji0)Rz(obC<)jeY?IeP}CZl=m5QpG}tF8@oa|pu%iO_aP-O!EEG{^h=|B@i{&d5eup7 zgoquP8D2a1-P$js86WrNi%$kpMuVOKN}_K)(2Hh}b3J*M1J@oZB1SYvN3u~JZ7nV9 zd=BK-@Gl^3^tu6&!=!x}Zq5n`b#0zu`ZKbPmR1wLQJkXX9r&?Q;z^rIsvz@P@l%CY zcd3g)B(&#SouoWAR-Ywqth&RmL;YaYp%qkQ4fn;h=&7Zz0wNQatd#5+ z+?^-9q7hetycxT?DyrF@-vbG==%eK(oW=6X2giNk-r!`03h&e;LsuFpX}ICYeqy1e z88U1X+sS@!rg$O5F*k?QVn?_)IJ)7?WuTbSv-;N33D}G8c0a1pwk|GqH3|t2B!NNK9dCKuZ)cchPDMwIedsXp3s5!Hj2j$*=_g`ewUuwk#KN&6 zcj)pz=CZkyt+wK!N;-KuR%o_lAu@5*5Fc Date: Sat, 29 Feb 2020 14:00:10 -0500 Subject: [PATCH 008/105] Delete particles_spin.png Not going to be used. --- .../entityProperties/html/tabs/particles_spin.png | Bin 772 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 scripts/system/create/entityProperties/html/tabs/particles_spin.png diff --git a/scripts/system/create/entityProperties/html/tabs/particles_spin.png b/scripts/system/create/entityProperties/html/tabs/particles_spin.png deleted file mode 100644 index 32238ed8f33fe6a1fdbc6b654178712f1e3021f9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 772 zcmWlWaZFTo0LQ<-$9s>1JK%R(a2So}abV1618o9w7tJgAf)g|sbPuGuo}sx?P#&ipxbnQh6YwF38aBZ(O|*E|++?f&@u_xb0u&p@E@ z<(%vl*#L5U4fR0)jx-h-z}@cWlK`^18eZE6SeK_EIPp>15O;a}9w2@s{O>Cx0F)gK zK|jz_3g|IlAqD6Ufc+J~Y%8!~3@GRv-gf0BKE1|nrcqq7 z(Dv*^4T$J`n33?TRrT#P$_oQKeOX_*86uV(rP+C_%h4>GwE^oCiI>rJk^2xVbM4Mo zPZrSc*vOx~yTglh!Fz?VWlz^E&XRs2x+eUOKg$&dRH|RDf*bv zb!ZKJYlpqNudUHRy+7*bJtD)Ujw(4+sGggV%>I-Xn+X*EF!>h}+L_<$ha3!-!b1Yj z)bBWcI<|$W#?|gHyK$6X6!=Z%&NH?}MF^I*N9||67_U(KCW>4)bNOf@d3Qa1)S9SS zeZ!_h(8f;v`n0@6w8CMt$(?`SzR8u&z7R>0;j+NN%h6B2TxMK!ezrjPdwgf34xt=< znw!=N@#5$9#DdpWely=Jg=%+iBFDyW4_s#;hdWM6^zHtM`DcRez+oa-wvG$sj$HPR zeK5VRBYJB{J($7$>}U z;n7t~w_kjUzW+h9#9(jPGLi$qhBxc_pRB0br2&A?+gN|Dt~L5UWwj6P From bb422a38321fa02d9c0c991c21c1dffb6c10bf05 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sat, 29 Feb 2020 14:02:57 -0500 Subject: [PATCH 009/105] Icons for sections reorganization behavior will be split: behavior, scripts particles_behavior will replace: particles_acceleration and particles_spin --- .../entityProperties/html/tabs/behavior.png | Bin 754 -> 1053 bytes .../html/tabs/particles_behavior.png | Bin 0 -> 650 bytes .../entityProperties/html/tabs/scripts.png | Bin 0 -> 754 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 scripts/system/create/entityProperties/html/tabs/particles_behavior.png create mode 100644 scripts/system/create/entityProperties/html/tabs/scripts.png diff --git a/scripts/system/create/entityProperties/html/tabs/behavior.png b/scripts/system/create/entityProperties/html/tabs/behavior.png index 9201fbfb721790b6c5ad3ff7451a2d28b53e165a..12662b8a1de2255a07eec846daf130232f8af4e5 100644 GIT binary patch delta 951 zcmV;o14#Vx1)T_xbbkYrNklG&0SF)_9EPhyT@C_qK&%MFUO@a6ioKv>aZoj-K&*z%Ab)@W!e#*n5YGl;0cda( zKwY>Ohz|nsekdCxmJd}U2-U-mZWurSVY9#&h;4y*ClDJ$4g3q0`--IJ4^++wh<5<7 z9aJw000p00tnp#XDA&D z4cGZV{0QoOEg-%IO|F4J>;uGafVdcl?*nlpRId}VfdB!7Y=JBg8$j8&pc+6fS_Z@k zK>P!UF9GpCXdbu;b#)35p9kU(P`!pwv%ml#fRHVy0e@lzAl?HFZ&3K30pf6|D@C9Y z%L>E~p$-TJ;*&tk2Nl~5HKPV*C_n%qN3uWEMbXfRbAhH1P*@*E%H66!Tn)s>pecdv;4;g>} zLJlHOvVRi-;zp>~KO@D>4QQJG4#aDr`QtJ)g@J%JG&k2m&A1FR6d-_*eV_r2D1B(k z0fA{i{0WG|pt)BH>PmhfJ`Tk7Ks*(Qw?Ta(1x;xhFhcY8~#tOLZmfVc>V^PoA@ z99ojH0r6yLzUhEsF{l~x&@u}Q00M{+R^b5a16`FN2G2oCWj~<# zsAAsWlAb`*#c>|K64A2yF09tDPfQns%7T3$NK z1Ahb%dQmYS>e@bNq=L$xZXhm%rVdbHcomv-|3D*L3R-t`L-j5|HV`0y&@DIx4W5V4 zG6m$aFVN)a1&sq6AU+CBL7G792u+Pop}G4MvVi~rgd7Lx#Wu(nSeQUP7xyF)%25A+)%NhNhP1(1t)Kvf;=8Ab=QY-E08} ZFaSES%W(CmMw|cu002ovPDHLkV1h2cbV2|C delta 650 zcmV;50(JeJ2=WDxbbkV9Nkl00aQ zMj-wIwVVxz{}bWJA3)py#1qgZ0Ro5xh;x9r4~RQ~_&5;90C5NqcLDKvAZ90E!CxS@ z1mb=m{sY8QpyJFR2Lc2T$bupuJ_p2yp$c{aaUc-?1L74#hJVBos82v<%>v?IK%5K2 z$p8TavfvvKYXb2qXz=`n+AdFGaGwO?c&J5QP#=8;2q2IJRzS=N4eLKp+t)zFKwt(C zs{rwD9N`ZV&j#Y}K>QPk-GF!+5I+T(0T4hS3qC#uTlOZ&MpFk7D zTWAnX2PpywAbb`uLwym9M@=aZn*wnpG=k?s`7dA!0Dl6A(z56kG`zPWIp`;{0)PM_ zCX%_KDFj=Yv>Hd;zyUx2u@ER@SfJ&THoD7@g7G&rg1=!i1R#J2sAFo0MWcv0T5sSSuEW!ADN|oQf6wbhm9C&4R<$9 zuN0AKvP5VQ27?|fdVo|ooggJWC@nHVCmEVhtBCc$g&%(3eqE)-1u@ad(Et!*G8)PN zAaRA92Y{KT-C+PwoHACO22jSYK+r$1GPnkPksiQz(f;>94*-x_V_6ZvnT-Hq8^G@f zfVco)(*Z2j0OYy>5*ja8kL3d}U^3{-o8Ozmkx1k)X;lR7IKyhZjx}pZy@%)J1Y22Y z4{KeIOTsF&%Ug#iWH4RRf*>5HH-*3lYFA0s;8S2ng9ihL<8g#HCy|fJz-MQrTxw!M zD$UO?OsI}zj|>74D@Avl6k$T~I!&*^rjZ zZ_r-YvaE&Ft?E~kz+vT^wfUO1-Xv+vSs5pdc|sh!NFS||9y`N3_G2Q_2k(%N#aVM! zFN5E*p*Yg23OJVMc+Zg+(XW-5w!3J8)IfhkrFm5KJcZdzcZ_sQ439d#>(%4wBAET% zne)h(a;|EaHvor+o=rN#OOB_0HR+4Gs=#!-qmcF_4?_8kh2aUAoVaH_np#;m|Bnei zq;_S0=Oup$`Bf0B7QvMflqdd)l`4=m7q4c0soQIZu6qj$N_2oY4d)E!#kPG#RvF$r zYdleGv=sWhNKSBf=jgXInrX)aB)7tCSig0H|_I#w`F4 zK8IrgV4{5e3;+a_nF@{o1ghsy(AqXPm=c580MK);^7rOO0Kj`pTg(6_VgUHl0KfbI z{3n2;NdTX%0Bf58=9iu?8pr~m?Kwunwu(`k&+pgEmQe(flRe?UppEJbwUEe2Yw>&5 zmW5~OJ8de#ubzAwNyb4`dtxYBkPAonzF=XUb7nOf0tbi6DerMy9Bb__!gm>|3eU>K zt!`-;D`*Bibw%Mcg;?96JVrY(^2?-9V~seka}z0kNlQhfEl_+06w^Dg0PUx}@%C@N z>e0kawz76cs_4wzl^1!E<#2<1I~fj8P3!ZmZUZU7j{dM5 z4vUW|&nvqE-h*~Jr#9>G5(1OACL)^>SzCnGz?``^LJkCpKRqV)@+A#EL=8m#3wm8M zsUra!qy4pmjf-@ycA^#w?Z~W%qd8m|mXvWaq(0jmhc42NXr1dr`mg0yCD6i~-jAWW zhxek^e2nd-d5Bta{(eUsQ`mA_lRf^JBG7}D?y0FO?r!bi3reqD% z@lK2O`E2c#nvnRa0AXc!1dYf{0zdWchH+4_AT@=eg{Jyq)_lTcsidXv87bOMp+X_b z-8)r?^d&${%6?p&xxruM@g+rQ^z|0$%VIPJj-@Ej$xt+RL4MY`I;6GB&~=QJ_Svts zC{#fQ!UW2p)#V29|A+f|ta69y5M^6vuiL8-uXcx@)0ULD`(?TLK#8X5?Q#OIALdiY X3R8urbTtLlZUBIs%v@tvy4Cd;>L3MH literal 0 HcmV?d00001 From 29e780e3f186ad3809be09dda687d121477faea1 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sat, 29 Feb 2020 14:07:15 -0500 Subject: [PATCH 010/105] Sections reorganization 1- Section "behavior" is now split in 2 sections: "behavior" and "scripts" 2- Particles sections: "particles_acceleration" and "particles_spin" has been joined as a new section: "particles_behavior" 3- Particles section: "particles_alpha" has been merged under section: "particles_color" --- .../html/js/entityProperties.js | 77 +++++++++---------- 1 file changed, 35 insertions(+), 42 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 95f680b49b..a18f9e37c8 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1063,14 +1063,7 @@ const GROUPS = [ label: "Color Spread", type: "color", propertyID: "colorSpread", - } - ] - }, - { - id: "particles_alpha", - label: "PARTICLES ALPHA", - //isMinor: true, - properties: [ + }, { type: "triple", label: "Alpha", @@ -1107,12 +1100,12 @@ const GROUPS = [ step: 0.001, decimals: 3, propertyID: "alphaSpread", - } + } ] }, { - id: "particles_acceleration", - label: "PARTICLES ACCELERATION", + id: "particles_behavior", + label: "PARTICLES BEHAVIOR", //isMinor: true, properties: [ { @@ -1132,14 +1125,7 @@ const GROUPS = [ round: 100, subLabels: [ "x", "y", "z" ], propertyID: "accelerationSpread", - } - ] - }, - { - id: "particles_spin", - label: "PARTICLES SPIN", - //isMinor: true, - properties: [ + }, { type: "triple", label: "Spin", @@ -1414,6 +1400,19 @@ const GROUPS = [ type: "bool", propertyID: "ignorePickIntersection", }, + { + label: "Lifetime", + type: "number", + unit: "s", + propertyID: "lifetime", + } + ] + }, +, + { + id: "scripts", + label: "SCRIPTS", + properties: [ { label: "Script", type: "string", @@ -1436,12 +1435,6 @@ const GROUPS = [ propertyID: "serverScriptStatus", selectionVisibility: PROPERTY_SELECTION_VISIBILITY.SINGLE_SELECTION, }, - { - label: "Lifetime", - type: "number", - unit: "s", - propertyID: "lifetime", - }, { label: "User Data", type: "textarea", @@ -1451,7 +1444,7 @@ const GROUPS = [ propertyID: "userData", } ] - }, + }, { id: "collision", label: "COLLISION", @@ -1605,23 +1598,23 @@ const GROUPS = [ ]; const GROUPS_PER_TYPE = { - None: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - Shape: [ 'base', 'shape', 'spatial', 'behavior', 'collision', 'physics' ], - Text: [ 'base', 'text', 'spatial', 'behavior', 'collision', 'physics' ], + None: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Shape: [ 'base', 'shape', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Text: [ 'base', 'text', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Zone: [ 'base', 'zone', 'zone_key_light', 'zone_skybox', 'zone_ambient_light', 'zone_haze', - 'zone_bloom', 'zone_avatar_priority', 'spatial', 'behavior', 'physics' ], - Model: [ 'base', 'model', 'spatial', 'behavior', 'collision', 'physics' ], - Image: [ 'base', 'image', 'spatial', 'behavior', 'collision', 'physics' ], - Web: [ 'base', 'web', 'spatial', 'behavior', 'collision', 'physics' ], - Light: [ 'base', 'light', 'spatial', 'behavior', 'collision', 'physics' ], - Material: [ 'base', 'material', 'spatial', 'behavior' ], - ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', 'particles_alpha', - 'particles_acceleration', 'particles_spin', 'particles_constraints', 'spatial', 'behavior', 'physics' ], - PolyLine: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - PolyLine: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - PolyVox: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], - Grid: [ 'base', 'grid', 'spatial', 'behavior', 'physics' ], - Multiple: [ 'base', 'spatial', 'behavior', 'collision', 'physics' ], + 'zone_bloom', 'zone_avatar_priority', 'spatial', 'behavior', 'scripts', 'physics' ], + Model: [ 'base', 'model', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Image: [ 'base', 'image', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Web: [ 'base', 'web', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Light: [ 'base', 'light', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts' ], + ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', + 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], + PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + PolyVox: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], + Grid: [ 'base', 'grid', 'spatial', 'behavior', 'scripts', 'physics' ], + Multiple: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], }; const EDITOR_TIMEOUT_DURATION = 1500; From 0eb6f1f1833b71e9cae51520a5ae31ef1303e95e Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sat, 29 Feb 2020 15:52:06 -0500 Subject: [PATCH 011/105] Fix page height blocking dropdown Fix the page height that blocked the correct use of the shape dropdown. The layout looks more stable now. --- .../system/create/entityProperties/html/entityProperties.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index 241ddd1e75..150025ef41 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -53,13 +53,13 @@ - +
From fa7143c87ece9c479704acad5e19f2e77ac51f7f Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 1 Mar 2020 22:35:48 -0500 Subject: [PATCH 012/105] Replace tabulations for spaces. Replace tabulations for spaces in the code. --- .../html/entityProperties.html | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index 150025ef41..3bfbb32cce 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -1,6 +1,6 @@ - - - -
-
+
+ + + + + +
+
+
+
+ +
+
From 5c7e6e43c2c6037cbd8b6dcc4b6983e8b4091301 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 1 Mar 2020 22:36:43 -0500 Subject: [PATCH 013/105] Replace tabulations for spaces. Replace tabulations for spaces in the code. --- .../entityProperties/html/tabs/tabs.css | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/scripts/system/create/entityProperties/html/tabs/tabs.css b/scripts/system/create/entityProperties/html/tabs/tabs.css index 135f53bb6b..010d6400a3 100644 --- a/scripts/system/create/entityProperties/html/tabs/tabs.css +++ b/scripts/system/create/entityProperties/html/tabs/tabs.css @@ -9,45 +9,45 @@ */ div.tabsContainer{ - float: left; - width:32px; - padding: 0px; - } - + float: left; + width:32px; + padding: 0px; + } + .tabsContainer button { - //display: block; - //color: black; - padding: 4px; - //width:100%; - text-align: center; - cursor: pointer; - transition: 0.4s; - font-size: 14px; - background-color: #404040; - border-color: #404040; - border-width: 1px 0px 1px 1px; - border-radius: 5px 0px 0px 5px; - outline:none; - } + //display: block; + //color: black; + padding: 4px; + //width:100%; + text-align: center; + cursor: pointer; + transition: 0.4s; + font-size: 14px; + background-color: #404040; + border-color: #404040; + border-width: 1px 0px 1px 1px; + border-radius: 5px 0px 0px 5px; + outline:none; + } .tabsContainer button:hover { - background-color: #575757; - } + background-color: #575757; + } .tabsContainer button.active { - background-color: #2E2E2E; - } + background-color: #2E2E2E; + } div.labelTabHeader{ - font-size: 20px; - font-weight: 700; - height: 40px; - color:#ffffff; - } + font-size: 20px; + font-weight: 700; + height: 40px; + color:#ffffff; + } div.tab-section-header{ - width:100%; - padding: 5px; - } \ No newline at end of file + width:100%; + padding: 5px; + } \ No newline at end of file From f3096ae74d41bcf96571741ca6399f490782e58c Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 1 Mar 2020 22:37:44 -0500 Subject: [PATCH 014/105] Replace tabulations for spaces. Replace tabulations for spaces in the code. --- .../html/js/entityProperties.js | 140 +++++++++--------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index a18f9e37c8..70efc9058d 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1,5 +1,5 @@ //VERSION 2.0 -// Modified by Alezia Kurdis on on 02/27/2020 +// Modified by Alezia Kurdis on on 02/27/2020 // for "Project Athena" // // Addition of a tab mechanism instead of collapsible sections to reduce the scrolling. @@ -49,7 +49,7 @@ const PROPERTY_MULTI_DISPLAY_MODE = Object.freeze({ const GROUPS = [ { id: "base", - label: "ENTITY", + label: "ENTITY", properties: [ { label: NO_SELECTION, @@ -127,7 +127,7 @@ const GROUPS = [ }, { id: "shape", - label: "SHAPE", + label: "SHAPE", properties: [ { label: "Shape", @@ -147,7 +147,7 @@ const GROUPS = [ }, { id: "text", - label: "TEXT", + label: "TEXT", properties: [ { label: "Text", @@ -235,7 +235,7 @@ const GROUPS = [ }, { id: "zone", - label: "ZONE", + label: "ZONE", properties: [ { label: "Shape Type", @@ -270,7 +270,7 @@ const GROUPS = [ }, { id: "zone_key_light", - label: "ZONE KEY LIGHT", + label: "ZONE KEY LIGHT", properties: [ { label: "Key Light", @@ -340,12 +340,12 @@ const GROUPS = [ decimals: 2, propertyID: "keyLight.shadowMaxDistance", showPropertyRule: { "keyLightMode": "enabled" }, - } + } ] - }, + }, { id: "zone_skybox", - label: "ZONE SKYBOX", + label: "ZONE SKYBOX", properties: [ { label: "Skybox", @@ -364,12 +364,12 @@ const GROUPS = [ type: "string", propertyID: "skybox.url", showPropertyRule: { "skyboxMode": "enabled" }, - } + } ] - }, + }, { id: "zone_ambient_light", - label: "ZONE AMBIENT LIGHT", + label: "ZONE AMBIENT LIGHT", properties: [ { label: "Ambient Light", @@ -399,12 +399,12 @@ const GROUPS = [ className: "black", onClick: copySkyboxURLToAmbientURL } ], propertyID: "copyURLToAmbient", showPropertyRule: { "ambientLightMode": "enabled" }, - } + } ] - }, + }, { id: "zone_haze", - label: "ZONE HAZE", + label: "ZONE HAZE", properties: [ { label: "Haze", @@ -488,12 +488,12 @@ const GROUPS = [ decimals: 0, propertyID: "haze.hazeGlareAngle", showPropertyRule: { "hazeMode": "enabled" }, - } + } ] }, { id: "zone_bloom", - label: "ZONE BLOOM", + label: "ZONE BLOOM", properties: [ { label: "Bloom", @@ -530,24 +530,24 @@ const GROUPS = [ decimals: 3, propertyID: "bloom.bloomSize", showPropertyRule: { "bloomMode": "enabled" }, - } + } ] - }, + }, { id: "zone_avatar_priority", - label: "ZONE AVATAR PRIORITY", + label: "ZONE AVATAR PRIORITY", properties: [ { label: "Avatar Priority", type: "dropdown", options: { inherit: "Inherit", crowd: "Crowd", hero: "Hero" }, propertyID: "avatarPriority", - } + } ] - }, + }, { id: "model", - label: "MODEL", + label: "MODEL", properties: [ { label: "Model", @@ -637,7 +637,7 @@ const GROUPS = [ }, { id: "image", - label: "IMAGE", + label: "IMAGE", properties: [ { label: "Image", @@ -680,7 +680,7 @@ const GROUPS = [ }, { id: "web", - label: "WEB", + label: "WEB", properties: [ { label: "Source", @@ -725,7 +725,7 @@ const GROUPS = [ }, { id: "light", - label: "LIGHT", + label: "LIGHT", properties: [ { label: "Light Color", @@ -776,7 +776,7 @@ const GROUPS = [ }, { id: "material", - label: "MATERIAL", + label: "MATERIAL", properties: [ { label: "Material URL", @@ -850,7 +850,7 @@ const GROUPS = [ }, { id: "grid", - label: "GRID", + label: "GRID", properties: [ { label: "Color", @@ -883,7 +883,7 @@ const GROUPS = [ }, { id: "particles", - label: "PARTICLES", + label: "PARTICLES", properties: [ { label: "Emit", @@ -913,7 +913,7 @@ const GROUPS = [ ] }, { - id: "particles_emit", + id: "particles_emit", label: "PARTICLES EMIT", //isMinor: true, properties: [ @@ -986,7 +986,7 @@ const GROUPS = [ ] }, { - id: "particles_size", + id: "particles_size", label: "PARTICLES SIZE", //isMinor: true, properties: [ @@ -1100,7 +1100,7 @@ const GROUPS = [ step: 0.001, decimals: 3, propertyID: "alphaSpread", - } + } ] }, { @@ -1181,7 +1181,7 @@ const GROUPS = [ { id: "particles_constraints", label: "PARTICLES CONSTRAINTS", - //isMinor: true, + //isMinor: true, properties: [ { type: "triple", @@ -1444,7 +1444,7 @@ const GROUPS = [ propertyID: "userData", } ] - }, + }, { id: "collision", label: "COLLISION", @@ -1602,14 +1602,14 @@ const GROUPS_PER_TYPE = { Shape: [ 'base', 'shape', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Text: [ 'base', 'text', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Zone: [ 'base', 'zone', 'zone_key_light', 'zone_skybox', 'zone_ambient_light', 'zone_haze', - 'zone_bloom', 'zone_avatar_priority', 'spatial', 'behavior', 'scripts', 'physics' ], + 'zone_bloom', 'zone_avatar_priority', 'spatial', 'behavior', 'scripts', 'physics' ], Model: [ 'base', 'model', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Image: [ 'base', 'image', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Web: [ 'base', 'web', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Light: [ 'base', 'light', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts' ], ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', - 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], + 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], PolyVox: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], @@ -1882,15 +1882,15 @@ function resetServerScriptStatus() { function showGroupsForType(type) { if (type === "Box" || type === "Sphere") { showGroupsForTypes(["Shape"]); - showOnTheSamePage("Shape"); + showOnTheSamePage("Shape"); return; } - if (type === "None"){ + if (type === "None"){ showGroupsForTypes(["None"]); - return; - } + return; + } showGroupsForTypes([type]); - showOnTheSamePage(type); + showOnTheSamePage(type); } function getGroupsForTypes(types) { @@ -1905,14 +1905,14 @@ function showGroupsForTypes(types) { Object.entries(elGroups).forEach(([groupKey, elGroup]) => { if (types.map(type => GROUPS_PER_TYPE[type].includes(groupKey)).every(function (hasGroup) { return hasGroup; })) { elGroup.style.display = "none"; - if(types != "None"){ - document.getElementById("tab-" + groupKey).style.display = "block"; - }else{ - document.getElementById("tab-" + groupKey).style.display = "none"; - } + if(types != "None"){ + document.getElementById("tab-" + groupKey).style.display = "block"; + }else{ + document.getElementById("tab-" + groupKey).style.display = "none"; + } } else { elGroup.style.display = "none"; - document.getElementById("tab-" + groupKey).style.display = "none"; + document.getElementById("tab-" + groupKey).style.display = "none"; } }); } @@ -3730,7 +3730,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { const shownGroups = getGroupsForTypes(entityTypes); showGroupsForTypes(entityTypes); - showOnTheSamePage(entityTypes); + showOnTheSamePage(entityTypes); const lockedMultiValue = getMultiplePropertyValue('locked'); @@ -4009,22 +4009,22 @@ function loaded() { openEventBridge(function() { let elPropertiesList = document.getElementById("properties-pages"); let tabs = ""; - + GROUPS.forEach(function(group) { let elGroup; - elGroup = document.createElement('div'); - elGroup.className = 'section ' + "major"; - elGroup.setAttribute("id", "properties-" + group.id); - elPropertiesList.appendChild(elGroup); + elGroup = document.createElement('div'); + elGroup.className = 'section ' + "major"; + elGroup.setAttribute("id", "properties-" + group.id); + elPropertiesList.appendChild(elGroup); - + if (group.label !== undefined) { let elLegend = document.createElement('div'); - elLegend.className = "tab-section-header"; + elLegend.className = "tab-section-header"; elLegend.appendChild(createElementFromHTML(`
${group.label}
`)); - elGroup.appendChild(elLegend); - tabs = tabs +''; + elGroup.appendChild(elLegend); + tabs = tabs +''; } group.properties.forEach(function(propertyData) { @@ -4036,7 +4036,7 @@ function loaded() { propertyElementID = propertyElementID.replace('.', '-'); let elContainer, elLabel; - + if (propertyData.replaceID === undefined) { // Create subheader, or create new property and append it. if (propertyType === "sub-header") { @@ -4311,7 +4311,7 @@ function loaded() { curCollapsibleElement.addEventListener("click", toggleCollapsedEvent, true); } */ - + // Textarea scrollbars let elTextareas = document.getElementsByTagName("TEXTAREA"); @@ -4465,16 +4465,16 @@ function loaded() { e.target.select(); }; } - + document.getElementById("tabs").innerHTML = tabs; - + bindAllNonJSONEditorElements(); showGroupsForType("None"); - showPage("base"); + showPage("base"); resetProperties(); disableProperties(); - + }); @@ -4492,21 +4492,21 @@ function loaded() { } function showOnTheSamePage(entityType) { - if(GROUPS_PER_TYPE[entityType].includes(currentTab) == false){ - currentTab = "base"; - } - showPage(currentTab); + if(GROUPS_PER_TYPE[entityType].includes(currentTab) == false){ + currentTab = "base"; + } + showPage(currentTab); } function showPage(id) { - currentTab = id; + currentTab = id; Object.entries(elGroups).forEach(([groupKey, elGroup]) => { if (groupKey == id) { elGroup.style.display = "block"; - document.getElementById("tab-" + groupKey).style.backgroundColor = "#2E2E2E"; + document.getElementById("tab-" + groupKey).style.backgroundColor = "#2E2E2E"; } else { elGroup.style.display = "none"; - document.getElementById("tab-" + groupKey).style.backgroundColor = "#404040"; + document.getElementById("tab-" + groupKey).style.backgroundColor = "#404040"; } }); } \ No newline at end of file From 124b3fe6a233c53a0012acbe7b7004e9923e9bed Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 2 Mar 2020 23:10:33 -0500 Subject: [PATCH 015/105] Code minor adjustments. Code minor adjustments to be compliant with the coding convention. --- .../html/entityProperties.html | 96 +++++++++---------- 1 file changed, 46 insertions(+), 50 deletions(-) diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index 3bfbb32cce..42d73b5007 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -15,57 +15,53 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html --> - - - Properties - - - - - - - - - - - - - - - - - - - - - -
-
- -
-
-
-
-
-
-
-
+ + Properties + + + + + + + + + + + + + + + + + + + +
+
+ +
+
+
+
+
+
+
+
+
+ + + + + +
+
+
+
+ +
+
- - - - - -
-
-
-
- -
-
-
- - + From 4a1926a9016cdc06a653c03b565ea450dc4a708f Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 2 Mar 2020 23:11:45 -0500 Subject: [PATCH 016/105] Code minor adjustments. Code minor adjustments to be compliant with the coding convention. --- .../entityProperties/html/tabs/tabs.css | 70 +++++++++---------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/scripts/system/create/entityProperties/html/tabs/tabs.css b/scripts/system/create/entityProperties/html/tabs/tabs.css index 010d6400a3..90cf201211 100644 --- a/scripts/system/create/entityProperties/html/tabs/tabs.css +++ b/scripts/system/create/entityProperties/html/tabs/tabs.css @@ -8,46 +8,44 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html */ -div.tabsContainer{ - float: left; - width:32px; - padding: 0px; - } - -.tabsContainer button { - //display: block; - //color: black; - padding: 4px; - //width:100%; - text-align: center; - cursor: pointer; - transition: 0.4s; - font-size: 14px; - background-color: #404040; - border-color: #404040; - border-width: 1px 0px 1px 1px; - border-radius: 5px 0px 0px 5px; - outline:none; - } +div.tabsContainer { + float: left; + width:32px; + padding: 0px; +} +.tabsContainer button { + //display: block; + //color: black; + padding: 4px; + //width:100%; + text-align: center; + cursor: pointer; + transition: 0.4s; + font-size: 14px; + background-color: #404040; + border-color: #404040; + border-width: 1px 0px 1px 1px; + border-radius: 5px 0px 0px 5px; + outline:none; +} .tabsContainer button:hover { - background-color: #575757; - } - + background-color: #575757; +} .tabsContainer button.active { - background-color: #2E2E2E; - } + background-color: #2E2E2E; +} -div.labelTabHeader{ - font-size: 20px; - font-weight: 700; - height: 40px; - color:#ffffff; - } +div.labelTabHeader { + font-size: 20px; + font-weight: 700; + height: 40px; + color:#ffffff; +} -div.tab-section-header{ - width:100%; - padding: 5px; - } \ No newline at end of file +div.tab-section-header { + width:100%; + padding: 5px; +} \ No newline at end of file From d1c641de49d6c4deb2448319c630117d7f0d4078 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 2 Mar 2020 23:13:47 -0500 Subject: [PATCH 017/105] Code minor adjustments. Code minor adjustments to be compliant with the coding convention. --- .../html/js/entityProperties.js | 261 +++++++++--------- 1 file changed, 130 insertions(+), 131 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 70efc9058d..d9fbe7c97c 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1,5 +1,5 @@ //VERSION 2.0 -// Modified by Alezia Kurdis on on 02/27/2020 +// Modified by Alezia Kurdis on on 02/27/2020 // for "Project Athena" // // Addition of a tab mechanism instead of collapsible sections to reduce the scrolling. @@ -147,7 +147,7 @@ const GROUPS = [ }, { id: "text", - label: "TEXT", + label: "TEXT", properties: [ { label: "Text", @@ -235,7 +235,7 @@ const GROUPS = [ }, { id: "zone", - label: "ZONE", + label: "ZONE", properties: [ { label: "Shape Type", @@ -270,7 +270,7 @@ const GROUPS = [ }, { id: "zone_key_light", - label: "ZONE KEY LIGHT", + label: "ZONE KEY LIGHT", properties: [ { label: "Key Light", @@ -345,7 +345,7 @@ const GROUPS = [ }, { id: "zone_skybox", - label: "ZONE SKYBOX", + label: "ZONE SKYBOX", properties: [ { label: "Skybox", @@ -364,12 +364,12 @@ const GROUPS = [ type: "string", propertyID: "skybox.url", showPropertyRule: { "skyboxMode": "enabled" }, - } + } ] - }, + }, { id: "zone_ambient_light", - label: "ZONE AMBIENT LIGHT", + label: "ZONE AMBIENT LIGHT", properties: [ { label: "Ambient Light", @@ -399,12 +399,12 @@ const GROUPS = [ className: "black", onClick: copySkyboxURLToAmbientURL } ], propertyID: "copyURLToAmbient", showPropertyRule: { "ambientLightMode": "enabled" }, - } + } ] - }, + }, { id: "zone_haze", - label: "ZONE HAZE", + label: "ZONE HAZE", properties: [ { label: "Haze", @@ -488,12 +488,12 @@ const GROUPS = [ decimals: 0, propertyID: "haze.hazeGlareAngle", showPropertyRule: { "hazeMode": "enabled" }, - } + } ] }, { id: "zone_bloom", - label: "ZONE BLOOM", + label: "ZONE BLOOM", properties: [ { label: "Bloom", @@ -530,24 +530,24 @@ const GROUPS = [ decimals: 3, propertyID: "bloom.bloomSize", showPropertyRule: { "bloomMode": "enabled" }, - } + } ] - }, + }, { id: "zone_avatar_priority", - label: "ZONE AVATAR PRIORITY", + label: "ZONE AVATAR PRIORITY", properties: [ { label: "Avatar Priority", type: "dropdown", options: { inherit: "Inherit", crowd: "Crowd", hero: "Hero" }, propertyID: "avatarPriority", - } + } ] - }, + }, { id: "model", - label: "MODEL", + label: "MODEL", properties: [ { label: "Model", @@ -637,7 +637,7 @@ const GROUPS = [ }, { id: "image", - label: "IMAGE", + label: "IMAGE", properties: [ { label: "Image", @@ -680,7 +680,7 @@ const GROUPS = [ }, { id: "web", - label: "WEB", + label: "WEB", properties: [ { label: "Source", @@ -725,7 +725,7 @@ const GROUPS = [ }, { id: "light", - label: "LIGHT", + label: "LIGHT", properties: [ { label: "Light Color", @@ -776,7 +776,7 @@ const GROUPS = [ }, { id: "material", - label: "MATERIAL", + label: "MATERIAL", properties: [ { label: "Material URL", @@ -850,7 +850,7 @@ const GROUPS = [ }, { id: "grid", - label: "GRID", + label: "GRID", properties: [ { label: "Color", @@ -883,7 +883,7 @@ const GROUPS = [ }, { id: "particles", - label: "PARTICLES", + label: "PARTICLES", properties: [ { label: "Emit", @@ -913,7 +913,7 @@ const GROUPS = [ ] }, { - id: "particles_emit", + id: "particles_emit", label: "PARTICLES EMIT", //isMinor: true, properties: [ @@ -986,7 +986,7 @@ const GROUPS = [ ] }, { - id: "particles_size", + id: "particles_size", label: "PARTICLES SIZE", //isMinor: true, properties: [ @@ -1100,7 +1100,7 @@ const GROUPS = [ step: 0.001, decimals: 3, propertyID: "alphaSpread", - } + } ] }, { @@ -1444,7 +1444,7 @@ const GROUPS = [ propertyID: "userData", } ] - }, + }, { id: "collision", label: "COLLISION", @@ -1609,7 +1609,7 @@ const GROUPS_PER_TYPE = { Light: [ 'base', 'light', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts' ], ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', - 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], + 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], PolyVox: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], @@ -1698,7 +1698,7 @@ function isFlagSet(value, flag) { */ function getPropertyInputElement(propertyID) { - let property = properties[propertyID]; + let property = properties[propertyID]; switch (property.data.type) { case 'string': case 'number': @@ -1783,7 +1783,7 @@ function setPropertyVisibility(property, visible) { function resetProperties() { for (let propertyID in properties) { - let property = properties[propertyID]; + let property = properties[propertyID]; let propertyData = property.data; switch (propertyData.type) { @@ -1860,7 +1860,7 @@ function resetProperties() { break; } } - + let showPropertyRules = properties[propertyID].showPropertyRules; if (showPropertyRules !== undefined) { for (let propertyToHide in showPropertyRules) { @@ -1885,7 +1885,7 @@ function showGroupsForType(type) { showOnTheSamePage("Shape"); return; } - if (type === "None"){ + if (type === "None") { showGroupsForTypes(["None"]); return; } @@ -1905,9 +1905,9 @@ function showGroupsForTypes(types) { Object.entries(elGroups).forEach(([groupKey, elGroup]) => { if (types.map(type => GROUPS_PER_TYPE[type].includes(groupKey)).every(function (hasGroup) { return hasGroup; })) { elGroup.style.display = "none"; - if(types != "None"){ + if (types !== "None") { document.getElementById("tab-" + groupKey).style.display = "block"; - }else{ + } else { document.getElementById("tab-" + groupKey).style.display = "none"; } } else { @@ -2309,7 +2309,7 @@ function updateCheckedSubProperty(propertyName, propertyMultiValue, subPropertyE * PROPERTY ELEMENT CREATION FUNCTIONS */ -function createStringProperty(property, elProperty) { +function createStringProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; @@ -2322,12 +2322,12 @@ function createStringProperty(property, elProperty) { ${propertyData.readOnly ? 'readonly' : ''}/> `); - + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); if (propertyData.onChange !== undefined) { elInput.addEventListener('change', propertyData.onChange); } - + let elMultiDiff = document.createElement('span'); elMultiDiff.className = "multi-diff"; @@ -2338,7 +2338,7 @@ function createStringProperty(property, elProperty) { if (propertyData.buttons !== undefined) { addButtons(elProperty, elementID, propertyData.buttons, false); } - + return elInput; } @@ -2346,9 +2346,9 @@ function createBoolProperty(property, elProperty) { let propertyName = property.name; let elementID = property.elementID; let propertyData = property.data; - + elProperty.className = "checkbox"; - + if (propertyData.glyph !== undefined) { let elSpan = document.createElement('span'); elSpan.innerHTML = propertyData.glyph; @@ -2577,7 +2577,7 @@ function createVec3Property(property, elProperty) { let propertyData = property.data; elProperty.className = propertyData.vec3Type + " fstuple"; - + let elNumberX = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.X_NUMBER]); let elNumberY = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.Y_NUMBER]); let elNumberZ = createTupleNumberInput(property, propertyData.subLabels[VECTOR_ELEMENTS.Z_NUMBER]); @@ -2592,7 +2592,7 @@ function createVec3Property(property, elProperty) { elNumberX.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'x')); elNumberY.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'y')); elNumberZ.setMultiDiffStepFunction(createMultiDiffStepFunction(property, 'z')); - + let elResult = []; elResult[VECTOR_ELEMENTS.X_NUMBER] = elNumberX; elResult[VECTOR_ELEMENTS.Y_NUMBER] = elNumberY; @@ -2600,11 +2600,11 @@ function createVec3Property(property, elProperty) { return elResult; } -function createVec2Property(property, elProperty) { +function createVec2Property(property, elProperty) { let propertyData = property.data; elProperty.className = propertyData.vec2Type + " fstuple"; - + let elTuple = document.createElement('div'); elTuple.className = "tuple"; @@ -2641,19 +2641,19 @@ function createColorProperty(property, elProperty) { let propertyName = property.name; let elementID = property.elementID; let propertyData = property.data; - + elProperty.className += " rgb fstuple"; - + let elColorPicker = document.createElement('div'); elColorPicker.className = "color-picker"; elColorPicker.setAttribute("id", elementID); - + let elTuple = document.createElement('div'); elTuple.className = "tuple"; - + elProperty.appendChild(elColorPicker); elProperty.appendChild(elTuple); - + if (propertyData.min === undefined) { propertyData.min = COLOR_MIN; } @@ -2663,19 +2663,19 @@ function createColorProperty(property, elProperty) { if (propertyData.step === undefined) { propertyData.step = COLOR_STEP; } - + let elNumberR = createTupleNumberInput(property, "red"); let elNumberG = createTupleNumberInput(property, "green"); let elNumberB = createTupleNumberInput(property, "blue"); elTuple.appendChild(elNumberR.elDiv); elTuple.appendChild(elNumberG.elDiv); elTuple.appendChild(elNumberB.elDiv); - + let valueChangeFunction = createEmitColorPropertyUpdateFunction(property); elNumberR.setValueChangeFunction(valueChangeFunction); elNumberG.setValueChangeFunction(valueChangeFunction); elNumberB.setValueChangeFunction(valueChangeFunction); - + let colorPickerID = "#" + elementID; colorPickers[colorPickerID] = $(colorPickerID).colpick({ colorScheme: 'dark', @@ -2704,7 +2704,7 @@ function createColorProperty(property, elProperty) { } } }); - + let elResult = []; elResult[COLOR_ELEMENTS.COLOR_PICKER] = elColorPicker; elResult[COLOR_ELEMENTS.RED_NUMBER] = elNumberR; @@ -2729,26 +2729,26 @@ function createDropdownProperty(property, propertyID, elProperty) { option.text = propertyData.options[optionKey]; elInput.add(option); } - + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); elProperty.appendChild(elInput); - + return elInput; } -function createTextareaProperty(property, elProperty) { +function createTextareaProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; - + elProperty.className = "textarea"; - + let elInput = document.createElement('textarea'); elInput.setAttribute("id", elementID); if (propertyData.readOnly) { elInput.readOnly = true; - } - + } + elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); let elMultiDiff = document.createElement('span'); @@ -2756,42 +2756,42 @@ function createTextareaProperty(property, elProperty) { elProperty.appendChild(elInput); elProperty.appendChild(elMultiDiff); - + if (propertyData.buttons !== undefined) { addButtons(elProperty, elementID, propertyData.buttons, true); } - + return elInput; } -function createIconProperty(property, elProperty) { +function createIconProperty(property, elProperty) { let elementID = property.elementID; elProperty.className = "value"; - + let elSpan = document.createElement('span'); elSpan.setAttribute("id", elementID + "-icon"); elSpan.className = 'icon'; elProperty.appendChild(elSpan); - + return elSpan; } -function createTextureProperty(property, elProperty) { +function createTextureProperty(property, elProperty) { let elementID = property.elementID; - + elProperty.className = "texture"; - + let elDiv = document.createElement("div"); let elImage = document.createElement("img"); elDiv.className = "texture-image no-texture"; elDiv.appendChild(elImage); - + let elInput = document.createElement('input'); elInput.setAttribute("id", elementID); elInput.setAttribute("type", "text"); - + let imageLoad = function(url) { elDiv.style.display = null; if (url.slice(0, 5).toLowerCase() === "atp:/") { @@ -2828,7 +2828,7 @@ function createTextureProperty(property, elProperty) { elMultiDiff.className = "multi-diff"; elProperty.appendChild(elMultiDiff); elProperty.appendChild(elDiv); - + let elResult = []; elResult[TEXTURE_ELEMENTS.IMAGE] = elImage; elResult[TEXTURE_ELEMENTS.TEXT_INPUT] = elInput; @@ -2844,23 +2844,23 @@ function createButtonsProperty(property, elProperty) { if (propertyData.buttons !== undefined) { addButtons(elProperty, elementID, propertyData.buttons, false); } - + return elProperty; } function createDynamicMultiselectProperty(property, elProperty) { let elementID = property.elementID; let propertyData = property.data; - + elProperty.className = "dynamic-multiselect"; - + let elDivOptions = document.createElement('div'); elDivOptions.setAttribute("id", elementID + "-options"); elDivOptions.style = "overflow-y:scroll;max-height:160px;"; - + let elDivButtons = document.createElement('div'); elDivButtons.setAttribute("id", elDivOptions.getAttribute("id") + "-buttons"); - + let elLabel = document.createElement('label'); elLabel.innerText = "No Options"; elDivOptions.appendChild(elLabel); @@ -2868,10 +2868,10 @@ function createDynamicMultiselectProperty(property, elProperty) { let buttons = [ { id: "selectAll", label: "Select All", className: "black", onClick: selectAllMaterialTarget }, { id: "clearAll", label: "Clear All", className: "black", onClick: clearAllMaterialTarget } ]; addButtons(elDivButtons, elementID, buttons, false); - + elProperty.appendChild(elDivOptions); elProperty.appendChild(elDivButtons); - + return elDivOptions; } @@ -2889,13 +2889,13 @@ function createTupleNumberInput(property, subLabel) { let propertyElementID = property.elementID; let propertyData = property.data; let elementID = propertyElementID + "-" + subLabel.toLowerCase(); - + let elLabel = document.createElement('label'); elLabel.className = "sublabel " + subLabel; elLabel.innerText = subLabel[0].toUpperCase() + subLabel.slice(1); elLabel.setAttribute("for", elementID); elLabel.style.visibility = "visible"; - + let dragStartFunction = createDragStartFunction(property); let dragEndFunction = createDragEndFunction(property); let elDraggableNumber = new DraggableNumber(propertyData.min, propertyData.max, propertyData.step, @@ -2903,14 +2903,14 @@ function createTupleNumberInput(property, subLabel) { elDraggableNumber.elInput.setAttribute("id", elementID); elDraggableNumber.elDiv.className += " fstuple"; elDraggableNumber.elDiv.insertBefore(elLabel, elDraggableNumber.elLeftArrow); - + return elDraggableNumber; } function addButtons(elProperty, propertyID, buttons, newRow) { let elDiv = document.createElement('div'); elDiv.className = "row"; - + buttons.forEach(function(button) { let elButton = document.createElement('input'); elButton.className = button.className; @@ -2932,7 +2932,7 @@ function addButtons(elProperty, propertyID, buttons, newRow) { } function createProperty(propertyData, propertyElementID, propertyName, propertyID, elProperty) { - let property = { + let property = { data: propertyData, elementID: propertyElementID, name: propertyName, @@ -3523,15 +3523,15 @@ function requestMaterialTarget() { entityID: getFirstSelectedID(), })); } - + function setMaterialTargetData(materialTargetData) { let elDivOptions = getPropertyInputElement("parentMaterialName"); resetDynamicMultiselectProperty(elDivOptions); - + if (materialTargetData === undefined) { return; } - + elDivOptions.firstChild.style.display = "none"; // hide "No Options" text elDivOptions.parentNode.lastChild.style.display = null; // show Select/Clear all buttons @@ -3539,7 +3539,7 @@ function setMaterialTargetData(materialTargetData) { for (let i = 0; i < numMeshes; ++i) { addMaterialTarget(elDivOptions, i, false); } - + let materialNames = materialTargetData.materialNames; let materialNamesAdded = []; for (let i = 0; i < materialNames.length; ++i) { @@ -3549,7 +3549,7 @@ function setMaterialTargetData(materialTargetData) { materialNamesAdded.push(materialName); } } - + materialTargetPropertyUpdate(elDivOptions.propertyValue); } @@ -3557,12 +3557,12 @@ function addMaterialTarget(elDivOptions, targetID, isMaterialName) { let elementID = elDivOptions.getAttribute("id"); elementID += isMaterialName ? "-material-" : "-mesh-"; elementID += targetID; - + let elDiv = document.createElement('div'); elDiv.className = "materialTargetDiv"; elDiv.onclick = onToggleMaterialTarget; elDivOptions.appendChild(elDiv); - + let elInput = document.createElement('input'); elInput.className = "materialTargetInput"; elInput.setAttribute("type", "checkbox"); @@ -3570,12 +3570,12 @@ function addMaterialTarget(elDivOptions, targetID, isMaterialName) { elInput.setAttribute("targetID", targetID); elInput.setAttribute("isMaterialName", isMaterialName); elDiv.appendChild(elInput); - + let elLabel = document.createElement('label'); elLabel.setAttribute("for", elementID); elLabel.innerText = isMaterialName ? "Material " + targetID : "Mesh Index " + targetID; elDiv.appendChild(elLabel); - + return elDiv; } @@ -3608,7 +3608,7 @@ function clearAllMaterialTarget() { function sendMaterialTargetProperty() { let elDivOptions = getPropertyInputElement("parentMaterialName"); let elInputs = elDivOptions.getElementsByClassName("materialTargetInput"); - + let materialTargetList = []; for (let i = 0; i < elInputs.length; ++i) { let elInput = elInputs[i]; @@ -3621,26 +3621,26 @@ function sendMaterialTargetProperty() { } } } - + let propertyValue = materialTargetList.join(","); if (propertyValue.length > 1) { propertyValue = "[" + propertyValue + "]"; } - + updateProperty("parentMaterialName", propertyValue, false); } function materialTargetPropertyUpdate(propertyValue) { let elDivOptions = getPropertyInputElement("parentMaterialName"); let elInputs = elDivOptions.getElementsByClassName("materialTargetInput"); - + if (propertyValue.startsWith('[')) { propertyValue = propertyValue.substring(1, propertyValue.length); } if (propertyValue.endsWith(']')) { propertyValue = propertyValue.substring(0, propertyValue.length - 1); } - + let materialTargets = propertyValue.split(","); for (let i = 0; i < elInputs.length; ++i) { let elInput = elInputs[i]; @@ -3651,7 +3651,7 @@ function materialTargetPropertyUpdate(propertyValue) { } elInput.checked = materialTargets.indexOf(materialTargetName) >= 0; } - + elDivOptions.propertyValue = propertyValue; } @@ -4014,29 +4014,29 @@ function loaded() { let elGroup; elGroup = document.createElement('div'); - elGroup.className = 'section ' + "major"; + elGroup.className = 'section ' + "major"; elGroup.setAttribute("id", "properties-" + group.id); elPropertiesList.appendChild(elGroup); - - + if (group.label !== undefined) { let elLegend = document.createElement('div'); elLegend.className = "tab-section-header"; elLegend.appendChild(createElementFromHTML(`
${group.label}
`)); - elGroup.appendChild(elLegend); + elGroup.appendChild(elLegend); tabs = tabs +''; + //tabs = tabs +''; } - + group.properties.forEach(function(propertyData) { let propertyType = propertyData.type; - let propertyID = propertyData.propertyID; + let propertyID = propertyData.propertyID; let propertyName = propertyData.propertyName !== undefined ? propertyData.propertyName : propertyID; let propertySpaceMode = propertyData.spaceMode !== undefined ? propertyData.spaceMode : PROPERTY_SPACE_MODE.ALL; let propertyElementID = "property-" + propertyID; propertyElementID = propertyElementID.replace('.', '-'); - + let elContainer, elLabel; - + if (propertyData.replaceID === undefined) { // Create subheader, or create new property and append it. if (propertyType === "sub-header") { @@ -4126,15 +4126,15 @@ function loaded() { property.elContainer = elContainer; property.spaceMode = propertySpaceMode; property.group_id = group.id; - + if (property.type !== 'placeholder') { properties[propertyID] = property; - } + } if (propertyData.type === 'number' || propertyData.type === 'number-draggable' || propertyData.type === 'vec2' || propertyData.type === 'vec3' || propertyData.type === 'rect') { propertyRangeRequests.push(propertyID); } - + let showPropertyRule = propertyData.showPropertyRule; if (showPropertyRule !== undefined) { let dependentProperty = Object.keys(showPropertyRule)[0]; @@ -4149,12 +4149,12 @@ function loaded() { } } }); - + elGroups[group.id] = elGroup; }); updateVisibleSpaceModeProperties(); - + if (window.EventBridge !== undefined) { EventBridge.scriptEventReceived.connect(function(data) { data = JSON.parse(data); @@ -4233,7 +4233,7 @@ function loaded() { EventBridge.emitWebEvent(JSON.stringify({ type: 'tooltipsRequest' })); EventBridge.emitWebEvent(JSON.stringify({ type: 'propertyRangeRequest', properties: propertyRangeRequests })); } - + // Server Script Status let elServerScriptStatusOuter = document.getElementById('div-property-serverScriptStatus'); let elServerScriptStatusContainer = document.getElementById('div-property-serverScriptStatus').childNodes[1]; @@ -4242,7 +4242,7 @@ function loaded() { let elServerScriptStatus = document.createElement('div'); elServerScriptStatus.setAttribute("id", serverScriptStatusElementID); elServerScriptStatusContainer.appendChild(elServerScriptStatus); - + // Server Script Error let elServerScripts = getPropertyInputElement("serverScripts"); let elDiv = document.createElement('div'); @@ -4252,11 +4252,11 @@ function loaded() { elServerScriptError.setAttribute("id", serverScriptErrorElementID); elDiv.appendChild(elServerScriptError); elServerScriptStatusContainer.appendChild(elDiv); - + let elScript = getPropertyInputElement("script"); elScript.parentNode.className = "url refresh"; elServerScripts.parentNode.className = "url refresh"; - + // User Data let userDataProperty = properties["userData"]; let elUserData = userDataProperty.elInput; @@ -4275,7 +4275,7 @@ function loaded() { elDiv.insertBefore(elStaticUserData, elUserData); elDiv.insertBefore(elUserDataEditor, elUserData); elDiv.insertBefore(elUserDataEditorStatus, elUserData); - + // Material Data let materialDataProperty = properties["materialData"]; let elMaterialData = materialDataProperty.elInput; @@ -4311,7 +4311,7 @@ function loaded() { curCollapsibleElement.addEventListener("click", toggleCollapsedEvent, true); } */ - + // Textarea scrollbars let elTextareas = document.getElementsByTagName("TEXTAREA"); @@ -4328,7 +4328,7 @@ function loaded() { event; mouseup is a partial stand-in but doesn't handle resizing if mouse moves outside textarea rectangle. */ curTextAreaElement.addEventListener("mouseup", textareaOnChangeEvent, false); } - + // Dropdowns // For each dropdown the following replacement is created in place of the original dropdown... // Structure created: @@ -4340,7 +4340,7 @@ function loaded() { //
  • ...
  • // // - // + // let elDropdowns = document.getElementsByTagName("select"); for (let dropDownIndex = 0; dropDownIndex < elDropdowns.length; ++dropDownIndex) { let elDropdown = elDropdowns[dropDownIndex]; @@ -4389,7 +4389,7 @@ function loaded() { li.addEventListener("click", setDropdownValue); ul.appendChild(li); } - + let propertyID = elDropdown.getAttribute("propertyID"); let property = properties[propertyID]; property.elInput = dt; @@ -4450,14 +4450,14 @@ function loaded() { } })); }, false); - + window.onblur = function() { // Fake a change event let ev = document.createEvent("HTMLEvents"); ev.initEvent("change", true, true); document.activeElement.dispatchEvent(ev); }; - + // For input and textarea elements, select all of the text on focus let els = document.querySelectorAll("input, textarea"); for (let i = 0; i < els.length; ++i) { @@ -4465,17 +4465,16 @@ function loaded() { e.target.select(); }; } - + document.getElementById("tabs").innerHTML = tabs; - - bindAllNonJSONEditorElements(); + + bindAllNonJSONEditorElements(); showGroupsForType("None"); showPage("base"); resetProperties(); disableProperties(); - - + }); augmentSpinButtons(); @@ -4492,7 +4491,7 @@ function loaded() { } function showOnTheSamePage(entityType) { - if(GROUPS_PER_TYPE[entityType].includes(currentTab) == false){ + if (!GROUPS_PER_TYPE[entityType].includes(currentTab)) { currentTab = "base"; } showPage(currentTab); @@ -4501,7 +4500,7 @@ function showOnTheSamePage(entityType) { function showPage(id) { currentTab = id; Object.entries(elGroups).forEach(([groupKey, elGroup]) => { - if (groupKey == id) { + if (groupKey === id) { elGroup.style.display = "block"; document.getElementById("tab-" + groupKey).style.backgroundColor = "#2E2E2E"; } else { From e6a45690ba400d30a4d0b1859ea49ba81eef6890 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 2 Mar 2020 23:53:55 -0500 Subject: [PATCH 018/105] Color Adjustments The color has been attenuated on those 2 icons. It was too present compared to the others. --- .../create/entityProperties/html/tabs/base.png | Bin 671 -> 669 bytes .../entityProperties/html/tabs/scripts.png | Bin 754 -> 755 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/scripts/system/create/entityProperties/html/tabs/base.png b/scripts/system/create/entityProperties/html/tabs/base.png index 1eed920742a3aee17134a9773018882ee83ab0ff..9f656abe2745438cda8d86081d5e2dc7a0e60266 100644 GIT binary patch delta 563 zcmV-30?hrN1)T+ub$=5{L_t(|+G70w|33o+ECCS(K%5E0LO}c-h}nVo7Z9@o@oy;o z2P%FFh+~2H9RpSn1113ihy_U`9f3wb0CLzDXdGMvVq+lQ0K{_W3IPI$TniYW5q$xOy`i)r)Dl@_MF0Uri3N<% z)b;@ClSfcXK*>=6rU)Q_SjaT|4>ZZ1f=2vLBtz|hcs3A+f;a#HM2-)>0r5$wq3qC9 z1@g&1ApQhZqkjWa3=lx%1`#MpO8~Jn5KBQZh;Iq?5i?97Kmd^&M8BXI9ejo+UpN2= zAQmE$Be8LU6#xVfJ_FK#I0q?H;Yvwt&?2K9n>v61!e+sLq|~5Gqz~RhE%=8n0T4he zI9vq+`9M4i%E#ve5WWuOGovd22q1hx^cIK@F;EBq0)Ggf1<_(NE00gs4{V3;=@`ThW;VL&*RD002ovPDHLkV1oNn B&?^7{ delta 565 zcmV-50?PfJ1)l|wb$=B}L_t(|+G70w|33o+FoK8zAkGA0At3$^#Oy%)3y4{P_&1dP z0~J37#IZp9jsYuxm5|Kmai!`QSK^umIvhAl?qd zoLHRo7l^rmcr_5qK*e?gaWoLW#^wWn07CY`RVdQ}yNlqM3xA030`Wf}egf5V28iXb z`2Zk*m>9?dEI|AP8VA>a*cga60I?jpLVy4w*8&D;L|*`6ZzydDwL}(K5kLS@VgVyG zwLO6PgD3%rC4g8Oh^3$y#J7a{h#963Ab`jXqF+#q4n89?00aO8 z5DO8>k=QuF3IGBKp8;t=oC9^~e>^FP4TzTmaXU7300G2;yOaW_23;b3@E&TxKXeIz z0Aj)6DiFvA;#p8WJ|BSabts=1T>(G<;R~X-KzxXSLVo}dK=>?RhNf|1^9I(41_&U0 zanJ@0rXP5M2n0BQcqKG%V8j7H0O9k2AT*~k6A=ocxFi7rh)^VVA@T7QdQWkc3;+Ry zFNi>O@*NW66eB1B0tnfH?@(F=h%W;%7m0?0;z|u_=1-U)KmZ|Iunt-?Ey7XG5Cd3| z>S-_l2reLG3woihj)q3=KN1aRf;Me7192lv5Fo$+9ct0B(5o5%00000NkvXXu0mjf Dc!STq diff --git a/scripts/system/create/entityProperties/html/tabs/scripts.png b/scripts/system/create/entityProperties/html/tabs/scripts.png index 9201fbfb721790b6c5ad3ff7451a2d28b53e165a..2249af165b1af0253ac963c3b1202c8150cf3d28 100644 GIT binary patch delta 650 zcmV;50(JfJ1@i@vb$@9|L_t(|+G70w|33pQ0YCsTG0+$Q1Q5$ghLs??5Qyu5m>Y;0 zf%ps5ayB6TPlO|X0C58lPe7Lh2p|?9&H>^+AnpX><3Jn(#34Z31;popn4N$He}UK% zi2H%~4-ij*iZg>82oOLZ3yOgF91tIdD%c6cfk6BZh*uC95`RmeJ^`6E3y6OKaV`)i z0|XGrf^R^q3B;?Q!SfetyF7`(eG-V{p%!^Tee@Y1fIt>l0Wl{utp7l5Ujr2bff+!o z0>r;@gg;0;8;HLH@lPOj1LA2w{1jvcKmdU(_yons;1|?4AaDn&@edvgzCwdk02&et zf%quMB7gv5A%7wX_YfIGu*7fzh_j$U^cx_6Sg4fTLBW{<#J8adBpn*bnE(NV&w_tY zx)_LMa0C%3-d+Q-IS|`JBN>#EYJj)}6n_8#gwKNi&|m^30wpYw{2v-mhR_Ip0!_Vu`blKx_lVp+GDI5(Ee!Tox<_;zVe=2D#c9h^wKg zW*#&+uvs7m#BtC#IRFv_2q0V*fGVFTXf?P6h(l;1P~*w kTNMBSMDtb!K!5=NZyRIsgCw delta 649 zcmV;40(SlL1@Z-ub$@6{L_t(|+G70w|33pQ0YCsTG0+$Q1Q1ITLlcND1mZd%<_2O$ zApQcioDGQo6XD1oK->Vt6VN3A0*D2ObAY%Hh&zG!I1tAGaR?B10r7btW+!05Um&&w z;(j3h1H@CH;>;ii0t67qf+8S32gHY=3U&fB``p9JD~s6}2-AAJT0Adm%CK+FjZ>pxK2*FeQUUy4#f7*NCu^(8X#@~#UDTb;j`dBG?+k%KnY7E|A)qtAvA)YKoi7U zXb?>YDFO%}d=@Z6eG!aDO(_tY0&yfXg6Bf{FJKA)0)L3ovgj2wytg7b=qIuQfB+&U zlDVNN1Y4Q38b{o~0YCt;5GZ3EP&?Y4;`2i@9H@wR2gC)STn!LF zxGVrAGke$f0d85%!~SmNv>5ZeH8C=d&Q1OWmFmj#P~I1!qzL9TWN;%aEB znFkFHY!-+CaU3*G4uAv!0tlA{pvor-S`BUiVjgITX$Qoouo#XUXJ??n15Q-{0mMk_ jRs}!+(Y#dw5MTi1TYof$S%shg0000 Date: Tue, 3 Mar 2020 19:21:14 -0500 Subject: [PATCH 019/105] Fix for the multiselection. This is the fix for the multiselection case. (It doesn't include the solution for User Data.) --- .../entityProperties/html/js/entityProperties.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index d9fbe7c97c..7bfc869f04 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -4491,7 +4491,15 @@ function loaded() { } function showOnTheSamePage(entityType) { - if (!GROUPS_PER_TYPE[entityType].includes(currentTab)) { + var i; + var numbType = entityType.length; + var matchingType = 0; + for (i = 0; i < numbType; i++) { + if (GROUPS_PER_TYPE[entityType[i]].includes(currentTab)) { + matchingType = matchingType + 1; + } + } + if (matchingType !== numbType) { currentTab = "base"; } showPage(currentTab); From 206b1b12c5d516d424b82c5bf98561c33afe562c Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 4 Mar 2020 18:26:23 -0500 Subject: [PATCH 020/105] Additional fixes about the formatting. Additional fixes about the formatting. --- .../create/entityProperties/html/tabs/tabs.css | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/system/create/entityProperties/html/tabs/tabs.css b/scripts/system/create/entityProperties/html/tabs/tabs.css index 90cf201211..540a4a4e7e 100644 --- a/scripts/system/create/entityProperties/html/tabs/tabs.css +++ b/scripts/system/create/entityProperties/html/tabs/tabs.css @@ -1,5 +1,5 @@ /* -// tab.css.css +// tabs.css // // Created by Alezia Kurdis on 02/27/2020 // for "Project Athena" @@ -10,15 +10,12 @@ div.tabsContainer { float: left; - width:32px; + width: 32px; padding: 0px; } .tabsContainer button { - //display: block; - //color: black; padding: 4px; - //width:100%; text-align: center; cursor: pointer; transition: 0.4s; @@ -27,7 +24,7 @@ div.tabsContainer { border-color: #404040; border-width: 1px 0px 1px 1px; border-radius: 5px 0px 0px 5px; - outline:none; + outline: none; } .tabsContainer button:hover { @@ -42,10 +39,10 @@ div.labelTabHeader { font-size: 20px; font-weight: 700; height: 40px; - color:#ffffff; + color: #ffffff; } div.tab-section-header { - width:100%; + width: 100%; padding: 5px; -} \ No newline at end of file +} From d934018c7be0b14bc7a91d21cf7542ac56e7ef65 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 4 Mar 2020 18:42:57 -0500 Subject: [PATCH 021/105] Codes minor adjustments Codes minor adjustments. Some formatting issues. Use element instead of a string --- .../html/js/entityProperties.js | 47 ++++--------------- 1 file changed, 10 insertions(+), 37 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 7bfc869f04..26eb94e8da 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -33,7 +33,7 @@ const PROPERTY_SELECTION_VISIBILITY = Object.freeze({ SINGLE_SELECTION: 1, MULTIPLE_SELECTIONS: 2, MULTI_DIFF_SELECTIONS: 4, - ANY_SELECTIONS: 7, /* SINGLE_SELECTION | MULTIPLE_SELECTIONS | MULTI_DIFF_SELECTIONS */ + ANY_SELECTIONS: 7 /* SINGLE_SELECTION | MULTIPLE_SELECTIONS | MULTI_DIFF_SELECTIONS */ }); // Multiple-selection behavior @@ -43,7 +43,7 @@ const PROPERTY_MULTI_DISPLAY_MODE = Object.freeze({ * Comma separated values * Limited for properties with type "string" or "textarea" and readOnly enabled */ - COMMA_SEPARATED_VALUES: 1, + COMMA_SEPARATED_VALUES: 1 }); const GROUPS = [ @@ -915,7 +915,6 @@ const GROUPS = [ { id: "particles_emit", label: "PARTICLES EMIT", - //isMinor: true, properties: [ { label: "Emit Rate", @@ -988,7 +987,6 @@ const GROUPS = [ { id: "particles_size", label: "PARTICLES SIZE", - //isMinor: true, properties: [ { type: "triple", @@ -1032,7 +1030,6 @@ const GROUPS = [ { id: "particles_color", label: "PARTICLES COLOR", - //isMinor: true, properties: [ { type: "triple", @@ -1106,7 +1103,6 @@ const GROUPS = [ { id: "particles_behavior", label: "PARTICLES BEHAVIOR", - //isMinor: true, properties: [ { label: "Emit Acceleration", @@ -1181,7 +1177,6 @@ const GROUPS = [ { id: "particles_constraints", label: "PARTICLES CONSTRAINTS", - //isMinor: true, properties: [ { type: "triple", @@ -1408,7 +1403,6 @@ const GROUPS = [ } ] }, -, { id: "scripts", label: "SCRIPTS", @@ -4008,8 +4002,8 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { function loaded() { openEventBridge(function() { let elPropertiesList = document.getElementById("properties-pages"); - let tabs = ""; - + let elTabs = document.getElementById("tabs"); + GROUPS.forEach(function(group) { let elGroup; @@ -4023,8 +4017,7 @@ function loaded() { elLegend.className = "tab-section-header"; elLegend.appendChild(createElementFromHTML(`
    ${group.label}
    `)); elGroup.appendChild(elLegend); - tabs = tabs +''; - //tabs = tabs +''; + elTabs.appendChild(createElementFromHTML('')); } group.properties.forEach(function(propertyData) { @@ -4294,23 +4287,6 @@ function loaded() { elDiv.insertBefore(elStaticMaterialData, elMaterialData); elDiv.insertBefore(elMaterialDataEditor, elMaterialData); elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData); - /* - // Collapsible sections - let elCollapsible = document.getElementsByClassName("collapse-icon"); - - let toggleCollapsedEvent = function(event) { - let element = this.parentNode.parentNode; - let isCollapsed = element.dataset.collapsed !== "true"; - element.dataset.collapsed = isCollapsed ? "true" : false; - element.setAttribute("collapsed", isCollapsed ? "true" : "false"); - this.textContent = isCollapsed ? "L" : "M"; - }; - - for (let collapseIndex = 0, numCollapsibles = elCollapsible.length; collapseIndex < numCollapsibles; ++collapseIndex) { - let curCollapsibleElement = elCollapsible[collapseIndex]; - curCollapsibleElement.addEventListener("click", toggleCollapsedEvent, true); - } - */ // Textarea scrollbars let elTextareas = document.getElementsByTagName("TEXTAREA"); @@ -4466,8 +4442,6 @@ function loaded() { }; } - document.getElementById("tabs").innerHTML = tabs; - bindAllNonJSONEditorElements(); showGroupsForType("None"); @@ -4491,15 +4465,14 @@ function loaded() { } function showOnTheSamePage(entityType) { - var i; - var numbType = entityType.length; - var matchingType = 0; - for (i = 0; i < numbType; i++) { + let numberOfTypes = entityType.length; + let matchingType = 0; + for (let i = 0; i < numberOfTypes; i++) { if (GROUPS_PER_TYPE[entityType[i]].includes(currentTab)) { matchingType = matchingType + 1; } } - if (matchingType !== numbType) { + if (matchingType !== numberOfTypes) { currentTab = "base"; } showPage(currentTab); @@ -4516,4 +4489,4 @@ function showPage(id) { document.getElementById("tab-" + groupKey).style.backgroundColor = "#404040"; } }); -} \ No newline at end of file +} From 8ab40e1a0832c2a064327c8a20ff572d93748e60 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Tue, 10 Mar 2020 00:48:54 -0400 Subject: [PATCH 022/105] Fix the userData and materialData editor Fix the userData and materialData editor. Only 2 conditions have been modified to make it works. I have removed a significant quantity of dead code that was trying to overlay a static text an obscure reason. Please, retest this. In case I missed something that I don't know. --- .../html/js/entityProperties.js | 52 +------------------ 1 file changed, 2 insertions(+), 50 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 26eb94e8da..9e476d80aa 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1741,12 +1741,6 @@ function disableChildren(el, selector) { function enableProperties() { enableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); enableChildren(document, ".colpick"); - - let elLocked = getPropertyInputElement("locked"); - if (elLocked.checked === false) { - removeStaticUserData(); - removeStaticMaterialData(); - } } function disableProperties() { @@ -1755,16 +1749,6 @@ function disableProperties() { for (let pickKey in colorPickers) { colorPickers[pickKey].colpickHide(); } - - let elLocked = getPropertyInputElement("locked"); - if (elLocked.checked === true) { - if ($('#property-userData-editor').css('display') === "block") { - showStaticUserData(); - } - if ($('#property-materialData-editor').css('display') === "block") { - showStaticMaterialData(); - } - } } function showPropertyElement(propertyID, show) { @@ -3217,19 +3201,6 @@ function hideUserDataSaved() { $('#property-userData-saved').hide(); } -function showStaticUserData() { - if (editor !== null) { - let $propertyUserDataStatic = $('#property-userData-static'); - $propertyUserDataStatic.show(); - $propertyUserDataStatic.css('height', $('#property-userData-editor').height()); - $propertyUserDataStatic.text(editor.getText()); - } -} - -function removeStaticUserData() { - $('#property-userData-static').hide(); -} - function setEditorJSON(json) { editor.set(json); if (editor.hasOwnProperty('expandAll')) { @@ -3382,19 +3353,6 @@ function hideMaterialDataSaved() { $('#property-materialData-saved').hide(); } -function showStaticMaterialData() { - if (materialEditor !== null) { - let $propertyMaterialDataStatic = $('#property-materialData-static'); - $propertyMaterialDataStatic.show(); - $propertyMaterialDataStatic.css('height', $('#property-materialData-editor').height()); - $propertyMaterialDataStatic.text(materialEditor.getText()); - } -} - -function removeStaticMaterialData() { - $('#property-materialData-static').hide(); -} - function setMaterialEditorJSON(json) { materialEditor.set(json); if (materialEditor.hasOwnProperty('expandAll')) { @@ -3935,7 +3893,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { } } - if (json !== null) { + if (json !== null && !lockedMultiValue.isMultiDiffValue && !lockedMultiValue.value) { if (editor === null) { createJSONEditor(); } @@ -3967,7 +3925,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { } } - if (materialJson !== null) { + if (materialJson !== null && !lockedMultiValue.isMultiDiffValue && !lockedMultiValue.value) { if (materialEditor === null) { createJSONMaterialEditor(); } @@ -4255,8 +4213,6 @@ function loaded() { let elUserData = userDataProperty.elInput; let userDataElementID = userDataProperty.elementID; elDiv = elUserData.parentNode; - let elStaticUserData = document.createElement('div'); - elStaticUserData.setAttribute("id", userDataElementID + "-static"); let elUserDataEditor = document.createElement('div'); elUserDataEditor.setAttribute("id", userDataElementID + "-editor"); let elUserDataEditorStatus = document.createElement('div'); @@ -4265,7 +4221,6 @@ function loaded() { elUserDataSaved.setAttribute("id", userDataElementID + "-saved"); elUserDataSaved.innerText = "Saved!"; elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elUserDataSaved); - elDiv.insertBefore(elStaticUserData, elUserData); elDiv.insertBefore(elUserDataEditor, elUserData); elDiv.insertBefore(elUserDataEditorStatus, elUserData); @@ -4274,8 +4229,6 @@ function loaded() { let elMaterialData = materialDataProperty.elInput; let materialDataElementID = materialDataProperty.elementID; elDiv = elMaterialData.parentNode; - let elStaticMaterialData = document.createElement('div'); - elStaticMaterialData.setAttribute("id", materialDataElementID + "-static"); let elMaterialDataEditor = document.createElement('div'); elMaterialDataEditor.setAttribute("id", materialDataElementID + "-editor"); let elMaterialDataEditorStatus = document.createElement('div'); @@ -4284,7 +4237,6 @@ function loaded() { elMaterialDataSaved.setAttribute("id", materialDataElementID + "-saved"); elMaterialDataSaved.innerText = "Saved!"; elDiv.childNodes[JSON_EDITOR_ROW_DIV_INDEX].appendChild(elMaterialDataSaved); - elDiv.insertBefore(elStaticMaterialData, elMaterialData); elDiv.insertBefore(elMaterialDataEditor, elMaterialData); elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData); From f29cde66cd430e1788528dca5669eb3f772f6e50 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 16 Mar 2020 23:16:14 -0400 Subject: [PATCH 023/105] Add alpha property on Shape entity Add the tooltip for the alpha property of Shape entity. --- scripts/system/create/assets/data/createAppTooltips.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 24f443f901..331b9aec65 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -5,6 +5,9 @@ "color": { "tooltip": "The RGB value of this entity." }, + "shapeAlpha": { + "tooltip": "The alpha of this entity." + }, "text": { "tooltip": "The text to display on the entity." }, From 1b3744ac73638e33e48bf354c4c1c68e9c7ae207 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 16 Mar 2020 23:19:04 -0400 Subject: [PATCH 024/105] Add alpha property on Shape entity Add the "Alpha" property on the "Shape" entity editor. propertyID: "shapeAlpha", propertyName: "alpha", --- .../entityProperties/html/js/entityProperties.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 9e476d80aa..68fff96856 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -142,7 +142,17 @@ const GROUPS = [ label: "Color", type: "color", propertyID: "color", - } + }, + { + label: "Alpha", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "shapeAlpha", + propertyName: "alpha", + }, ] }, { From 500c2eff5d2cc0a99c5df71d5cb7442b449b2cbf Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 18 Mar 2020 00:01:53 -0400 Subject: [PATCH 025/105] Adding tooltips for 3 other missing properties Adding tooltips for 3 other missing properties: - "alpha" of the "Image" Entity. - "billboardMode" of the "Web" Entity. - "showKeyboardFocusHighlight" of the "Web" Entity. --- .../system/create/assets/data/createAppTooltips.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 331b9aec65..4b32bbf6db 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -199,6 +199,9 @@ "tooltip": "The tint to be applied to the image.", "jsPropertyName": "color" }, + "imageAlpha": { + "tooltip": "The alpha of the image." + }, "emissive": { "tooltip": "If enabled, the image will display at full brightness." }, @@ -218,6 +221,13 @@ "dpi": { "tooltip": "The resolution to display the page at, in pixels per inch. Use this to resize your web source in the frame." }, + "webBillboardMode": { + "tooltip": "If enabled, determines how the entity will face the camera.", + "jsPropertyName": "billboardMode" + }, + "showKeyboardFocusHighlight": { + "tooltip": "If enabled, highlights when it has keyboard focus." + }, "isEmitting": { "tooltip": "If enabled, then particles are emitted." }, From 35e76610a865e62bd41a41f4ae12e4a4b9e09b3c Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 18 Mar 2020 00:06:18 -0400 Subject: [PATCH 026/105] Added 3 other missing properties Added 3 other missing properties: - "alpha" of the "Image" Entity. - "billboardMode" of the "Web" Entity. - "showKeyboardFocusHighlight" of the "Web" Entity. --- .../html/js/entityProperties.js | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 68fff96856..63aa39e552 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1,15 +1,9 @@ -//VERSION 2.0 -// Modified by Alezia Kurdis on on 02/27/2020 -// for "Project Athena" -// -// Addition of a tab mechanism instead of collapsible sections to reduce the scrolling. -// -//VERSION 1.0 // entityProperties.js // // Created by Ryan Huffman on 13 Nov 2014 // Modified by David Back on 19 Oct 2018 // Copyright 2014 High Fidelity, Inc. +// Copyright 2020 Project Athena contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -661,6 +655,16 @@ const GROUPS = [ propertyID: "imageColor", propertyName: "color", // actual entity property name }, + { + label: "Alpha", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "imageAlpha", + propertyName: "alpha", + }, { label: "Emissive", type: "bool", @@ -725,6 +729,18 @@ const GROUPS = [ decimals: 0, propertyID: "maxFPS", }, + { + label: "Billboard Mode", + type: "dropdown", + options: { none: "None", yaw: "Yaw", full: "Full"}, + propertyID: "webBillboardMode", + propertyName: "billboardMode", // actual entity property name + }, + { + label: "Focus Highlight", + type: "bool", + propertyID: "showKeyboardFocusHighlight", + }, { label: "Script URL", type: "string", @@ -1870,7 +1886,7 @@ function resetServerScriptStatus() { function showGroupsForType(type) { if (type === "Box" || type === "Sphere") { showGroupsForTypes(["Shape"]); - showOnTheSamePage("Shape"); + showOnTheSamePage(["Shape"]); return; } if (type === "None") { @@ -1878,7 +1894,7 @@ function showGroupsForType(type) { return; } showGroupsForTypes([type]); - showOnTheSamePage(type); + showOnTheSamePage([type]); } function getGroupsForTypes(types) { From e371823896b4348f1594d3ba60898a23f50cd29b Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 18 Mar 2020 18:33:09 -0400 Subject: [PATCH 027/105] Move the tabs.css with other css Move the tabs.css with other css --- scripts/system/html/css/tabs.css | 77 ++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 scripts/system/html/css/tabs.css diff --git a/scripts/system/html/css/tabs.css b/scripts/system/html/css/tabs.css new file mode 100644 index 0000000000..37383b6d99 --- /dev/null +++ b/scripts/system/html/css/tabs.css @@ -0,0 +1,77 @@ +/* +// tabs.css +// +// Created by Alezia Kurdis on 27 Feb 2020 +// Copyright 2020 Project Athena contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + +div.tabsContainer { + float: left; + width: 32px; + padding: 0px; +} + +.tabsContainer button { + padding: 4px; + text-align: center; + cursor: pointer; + transition: 0.4s; + font-size: 14px; + background-color: #404040; + border-color: #404040; + border-width: 1px 0px 1px 1px; + border-radius: 5px 0px 0px 5px; + outline: none; +} + +.tabsContainer button:hover { + background-color: #575757; +} + +.tabsContainer button.active { + background-color: #2E2E2E; +} + +div.labelTabHeader { + font-size: 20px; + font-weight: 700; + height: 40px; + color: #ffffff; +} + +div.tab-section-header { + width: 100%; + padding: 5px; +} + +table.tabsTableFrame { + width:100%; + min-height: 352px; + display: block; +} + +tr.tabsTrFrame { + width:100%; +} + +td.tabsFrame { + width:32px; + vertical-align:top; + background-color:#575757; + padding:0px; + border:0px; +} + +td.tabsPropertiesFrame { + width:100%; + vertical-align: top; + border:0px; +} + +div.tabsPropertiesPage { + min-height: 352px; + display: block; +} From 022ea6c5fb29d455704d14c48c5522116573599b Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 18 Mar 2020 18:34:51 -0400 Subject: [PATCH 028/105] Moved tabs.css to system/html/css Moved tabs.css to system/html/css with other css. --- .../entityProperties/html/tabs/tabs.css | 48 ------------------- 1 file changed, 48 deletions(-) delete mode 100644 scripts/system/create/entityProperties/html/tabs/tabs.css diff --git a/scripts/system/create/entityProperties/html/tabs/tabs.css b/scripts/system/create/entityProperties/html/tabs/tabs.css deleted file mode 100644 index 540a4a4e7e..0000000000 --- a/scripts/system/create/entityProperties/html/tabs/tabs.css +++ /dev/null @@ -1,48 +0,0 @@ -/* -// tabs.css -// -// Created by Alezia Kurdis on 02/27/2020 -// for "Project Athena" -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -*/ - -div.tabsContainer { - float: left; - width: 32px; - padding: 0px; -} - -.tabsContainer button { - padding: 4px; - text-align: center; - cursor: pointer; - transition: 0.4s; - font-size: 14px; - background-color: #404040; - border-color: #404040; - border-width: 1px 0px 1px 1px; - border-radius: 5px 0px 0px 5px; - outline: none; -} - -.tabsContainer button:hover { - background-color: #575757; -} - -.tabsContainer button.active { - background-color: #2E2E2E; -} - -div.labelTabHeader { - font-size: 20px; - font-weight: 700; - height: 40px; - color: #ffffff; -} - -div.tab-section-header { - width: 100%; - padding: 5px; -} From e52e1bafc6e5bfb0e7af1595f0071b2f6355d636 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 18 Mar 2020 18:38:41 -0400 Subject: [PATCH 029/105] Moved tabs.css reference -Change the path for the new location of tabs.css -Local "style" migrated to "class" --- .../html/entityProperties.html | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index 42d73b5007..b1d5e2805e 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -1,18 +1,14 @@ @@ -21,7 +17,7 @@ - + @@ -50,13 +46,13 @@
    - - - "; } else { - listedZoneInner += ""; + listedZoneInner += ""; } } else { for ( i = 0; i < selectedZones.length; i++ ) { From 420af951318945765267cc12012c573ea4559c41 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Thu, 16 Apr 2020 16:18:39 -0700 Subject: [PATCH 043/105] models support flipped normals on double sided geometry --- .../entities-renderer/src/paintStroke.slf | 6 ++++-- libraries/graphics/src/graphics/Material.slh | 1 - libraries/render-utils/src/CullFace.slh | 20 +++++++++++++++++++ libraries/render-utils/src/model.slf | 5 +++-- libraries/render-utils/src/simple.slf | 9 +++++---- .../render-utils/src/simple_procedural.slf | 3 ++- 6 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 libraries/render-utils/src/CullFace.slh diff --git a/libraries/entities-renderer/src/paintStroke.slf b/libraries/entities-renderer/src/paintStroke.slf index 3d5cc190d0..eb46be1e20 100644 --- a/libraries/entities-renderer/src/paintStroke.slf +++ b/libraries/entities-renderer/src/paintStroke.slf @@ -19,6 +19,8 @@ <@include paintStroke.slh@> <$declarePolyLineBuffers()$> +<@include CullFace.slh@> + LAYOUT(binding=0) uniform sampler2D _texture; <@if not HIFI_USE_FORWARD@> @@ -35,9 +37,9 @@ void main(void) { <@if not HIFI_USE_FORWARD@> <@if HIFI_USE_TRANSLUCENT@> - packDeferredFragmentTranslucent((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb, DEFAULT_ROUGHNESS); + packDeferredFragmentTranslucent(evalFrontOrBackFaceNormal(_normalWS), texel.a, texel.rgb, DEFAULT_ROUGHNESS); <@else@> - packDeferredFragmentUnlit((2.0 * float(gl_FrontFacing) - 1.0) * _normalWS, texel.a, texel.rgb); + packDeferredFragmentUnlit(evalFrontOrBackFaceNormal(_normalWS), texel.a, texel.rgb); <@endif@> <@else@> _fragColor0 = texel; diff --git a/libraries/graphics/src/graphics/Material.slh b/libraries/graphics/src/graphics/Material.slh index 328ff4a3af..274dbc1cdd 100644 --- a/libraries/graphics/src/graphics/Material.slh +++ b/libraries/graphics/src/graphics/Material.slh @@ -13,7 +13,6 @@ <@include graphics/ShaderConstants.h@> - const int MAX_TEXCOORDS = 2; struct TexMapArray { diff --git a/libraries/render-utils/src/CullFace.slh b/libraries/render-utils/src/CullFace.slh new file mode 100644 index 0000000000..61b76bb22f --- /dev/null +++ b/libraries/render-utils/src/CullFace.slh @@ -0,0 +1,20 @@ + +<@if not CULL_FACE_SLH@> +<@def CULL_FACE_SLH@> + +// NOTE: this calculation happens once per fragment. this could be optimized by creating different shaders (via defines) +// for front, back, and double-sided. for front/back-only triangles, this will simplify to always 1 or always -1 +vec3 evalFrontOrBackFaceNormal(vec3 normal) { + return (2.0 * float(gl_FrontFacing) - 1.0) * normal; +} + +<@endif@> diff --git a/libraries/render-utils/src/model.slf b/libraries/render-utils/src/model.slf index a6cc82e335..98abc29d8c 100644 --- a/libraries/render-utils/src/model.slf +++ b/libraries/render-utils/src/model.slf @@ -13,6 +13,7 @@ <@include graphics/Material.slh@> <@include graphics/MaterialTextures.slh@> <@include render-utils/ShaderConstants.h@> +<@include CullFace.slh@> <@if not HIFI_USE_SHADOW@> <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> @@ -129,7 +130,7 @@ void main(void) { _fragColor0 = vec4(albedo * isUnlitEnabled(), opacity); <@else@> packDeferredFragmentUnlit( - normalize(_normalWS), + evalFrontOrBackFaceNormal(normalize(_normalWS)), opacity, albedo * isUnlitEnabled()); <@endif@> @@ -195,7 +196,7 @@ void main(void) { <@else@> vec3 fragNormalWS = _normalWS; <@endif@> - fragNormalWS = normalize(fragNormalWS); + fragNormalWS = evalFrontOrBackFaceNormal(normalize(fragNormalWS)); <@if HIFI_USE_FORWARD@> TransformCamera cam = getTransformCamera(); diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 9760216682..fabe85cb4f 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -13,6 +13,7 @@ <@include gpu/Color.slh@> <@include DefaultMaterials.slh@> <@include render-utils/ShaderConstants.h@> +<@include CullFace.slh@> <@if HIFI_USE_FORWARD or HIFI_USE_TRANSLUCENT@> <@if not HIFI_USE_UNLIT@> @@ -94,7 +95,7 @@ void main(void) { 1.0, DEFAULT_OCCLUSION, fragPosition, - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + evalFrontOrBackFaceNormal(normalize(_normalWS)), texel.rgb, fresnel, metallic, @@ -111,7 +112,7 @@ void main(void) { 1.0, DEFAULT_OCCLUSION, fragPosition, - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + evalFrontOrBackFaceNormal(normalize(_normalWS)), texel.rgb, fresnel, metallic, @@ -119,7 +120,7 @@ void main(void) { texel.a); <@else@> packDeferredFragment( - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + evalFrontOrBackFaceNormal(normalize(_normalWS)), 1.0, texel.rgb, DEFAULT_ROUGHNESS, @@ -141,7 +142,7 @@ void main(void) { , texel.a); <@else@> packDeferredFragmentUnlit( - normalize(_normalWS) * (2.0 * float(gl_FrontFacing) - 1.0), + evalFrontOrBackFaceNormal(normalize(_normalWS)), 1.0, texel.rgb <@if HIFI_USE_FADE@> diff --git a/libraries/render-utils/src/simple_procedural.slf b/libraries/render-utils/src/simple_procedural.slf index 5b0eb62cca..cc8edbb415 100644 --- a/libraries/render-utils/src/simple_procedural.slf +++ b/libraries/render-utils/src/simple_procedural.slf @@ -24,6 +24,7 @@ <@include gpu/Transform.slh@> <$declareStandardCameraTransform()$> +<@include CullFace.slh@> <@include render-utils/ShaderConstants.h@> layout(location=RENDER_UTILS_ATTR_POSITION_MS) in vec4 _positionMS; @@ -66,7 +67,7 @@ float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition pro #line 2030 void main(void) { - vec3 normal = normalize(_normalWS.xyz) * (2.0 * float(gl_FrontFacing) - 1.0); + vec3 normal = evalFrontOrBackFaceNormal(normalize(_normalWS.xyz)); vec3 diffuse = _color.rgb; vec3 fresnel = DEFAULT_FRESNEL; float roughness = DEFAULT_ROUGHNESS; From 8c475d3e02a62f7b2653cfbb981691dbb47ab251 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Apr 2020 08:45:59 +1200 Subject: [PATCH 044/105] Add icon file as published in Community Apps repo --- .../marketplace/record/icon.svg | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 unpublishedScripts/marketplace/record/icon.svg diff --git a/unpublishedScripts/marketplace/record/icon.svg b/unpublishedScripts/marketplace/record/icon.svg new file mode 100644 index 0000000000..06f8a3276f --- /dev/null +++ b/unpublishedScripts/marketplace/record/icon.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + From 997eb14ddcc25e2975e289b441fc4ad421e6d9a5 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 7 Feb 2020 19:37:00 +0100 Subject: [PATCH 045/105] release mode proof portfiles --- cmake/ports/polyvox/portfile.cmake | 48 +++++++++++++++++++----------- cmake/ports/vhacd/portfile.cmake | 17 +++++++---- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/cmake/ports/polyvox/portfile.cmake b/cmake/ports/polyvox/portfile.cmake index 54cc74d4dd..275a1a940f 100644 --- a/cmake/ports/polyvox/portfile.cmake +++ b/cmake/ports/polyvox/portfile.cmake @@ -23,33 +23,45 @@ vcpkg_install_cmake() file(INSTALL ${SOURCE_PATH}/LICENSE.TXT DESTINATION ${CURRENT_PACKAGES_DIR}/share/polyvox RENAME copyright) file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/include) -file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/lib) -file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/debug/lib) +if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/lib) +endif() +if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/debug/lib) +endif() if(WIN32) - file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxCore/lib/Release/PolyVoxCore.lib ${CURRENT_PACKAGES_DIR}/lib/PolyVoxCore.lib) - file(RENAME ${CURRENT_PACKAGES_DIR}/debug/PolyVoxCore/lib/Debug/PolyVoxCore.lib ${CURRENT_PACKAGES_DIR}/debug/lib/PolyVoxCore.lib) - file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxUtil/lib/PolyVoxUtil.lib ${CURRENT_PACKAGES_DIR}/lib/PolyVoxUtil.lib) - file(RENAME ${CURRENT_PACKAGES_DIR}/debug/PolyVoxUtil/lib/PolyVoxUtil.lib ${CURRENT_PACKAGES_DIR}/debug/lib/PolyVoxUtil.lib) + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxCore/lib/Release/PolyVoxCore.lib ${CURRENT_PACKAGES_DIR}/lib/PolyVoxCore.lib) + file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxUtil/lib/PolyVoxUtil.lib ${CURRENT_PACKAGES_DIR}/lib/PolyVoxUtil.lib) + endif() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(RENAME ${CURRENT_PACKAGES_DIR}/debug/PolyVoxCore/lib/Debug/PolyVoxCore.lib ${CURRENT_PACKAGES_DIR}/debug/lib/PolyVoxCore.lib) + file(RENAME ${CURRENT_PACKAGES_DIR}/debug/PolyVoxUtil/lib/PolyVoxUtil.lib ${CURRENT_PACKAGES_DIR}/debug/lib/PolyVoxUtil.lib) + endif() file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxCore/include/PolyVoxCore ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore) file(RENAME ${CURRENT_PACKAGES_DIR}/PolyVoxUtil/include/PolyVoxUtil ${CURRENT_PACKAGES_DIR}/include/PolyVoxUtil) file(RENAME ${CURRENT_PACKAGES_DIR}/cmake/PolyVoxConfig.cmake ${CURRENT_PACKAGES_DIR}/share/polyvox/polyvoxConfig.cmake) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/cmake) - file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/cmake) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/PolyVoxCore) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/PolyVoxUtil) - file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/PolyVoxUtil) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/cmake) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/PolyVoxCore) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/PolyVoxUtil) else() - file(GLOB LIBS ${CURRENT_PACKAGES_DIR}/lib/Release/*) - foreach(_lib ${LIBS}) - file(RELATIVE_PATH _libName ${CURRENT_PACKAGES_DIR}/lib/Release ${_lib}) - file(RENAME ${_lib} ${CURRENT_PACKAGES_DIR}/lib/${_libName}) - endforeach() - file(GLOB LIBS ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/*) - foreach(_lib ${LIBS}) - file(RELATIVE_PATH _libName ${CURRENT_PACKAGES_DIR}/debug/lib/Debug ${_lib}) - file(RENAME ${_lib} ${CURRENT_PACKAGES_DIR}/debug/lib/${_libName}) - endforeach() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(GLOB LIBS ${CURRENT_PACKAGES_DIR}/lib/Release/*) + foreach(_lib ${LIBS}) + file(RELATIVE_PATH _libName ${CURRENT_PACKAGES_DIR}/lib/Release ${_lib}) + file(RENAME ${_lib} ${CURRENT_PACKAGES_DIR}/lib/${_libName}) + endforeach() + endif() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(GLOB LIBS ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/*) + foreach(_lib ${LIBS}) + file(RELATIVE_PATH _libName ${CURRENT_PACKAGES_DIR}/debug/lib/Debug ${_lib}) + file(RENAME ${_lib} ${CURRENT_PACKAGES_DIR}/debug/lib/${_libName}) + endforeach() + endif() file(RENAME ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore.temp) file(RENAME ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore.temp/PolyVoxCore ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/include/PolyVoxCore.temp) diff --git a/cmake/ports/vhacd/portfile.cmake b/cmake/ports/vhacd/portfile.cmake index 02d90cab18..3a13e461a6 100644 --- a/cmake/ports/vhacd/portfile.cmake +++ b/cmake/ports/vhacd/portfile.cmake @@ -22,10 +22,17 @@ vcpkg_configure_cmake( vcpkg_install_cmake() file(COPY ${CMAKE_CURRENT_LIST_DIR}/copyright DESTINATION ${CURRENT_PACKAGES_DIR}/share/vhacd) -file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) +if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) +endif() + if (WIN32) - file(RENAME ${CURRENT_PACKAGES_DIR}/lib/Release/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/lib/VHACD.lib) - file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/lib/Release) - file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/debug/lib/VHACD.lib) - file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/lib/Debug) + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(RENAME ${CURRENT_PACKAGES_DIR}/lib/Release/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/lib/VHACD.lib) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/lib/Release) + endif() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/debug/lib/VHACD.lib) + file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/lib/Debug) + endif() endif() \ No newline at end of file From 48ee437c00e640849e69da3ddf1608cbde37e48d Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 8 Feb 2020 15:43:39 +0100 Subject: [PATCH 046/105] cmake -D VCPKG_BUILD_TYPE could be set to either release debug or release in order to build vcpkg in a specific build type, otherwise it will build with debug and release --- .github/workflows/pr_build.yml | 4 +- CMakeLists.txt | 6 ++- cmake/macros/TargetDraco.cmake | 3 +- cmake/macros/TargetOpenEXR.cmake | 2 + cmake/ports/quazip/portfile.cmake | 12 ++++-- hifi_vcpkg.py | 62 ++++++++++++++++++++++++++----- prebuild.py | 8 ++++ 7 files changed, 79 insertions(+), 18 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index d1ecb1bb02..2d603ea6f4 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -79,7 +79,7 @@ jobs: - name: Configure CMake working-directory: ${{runner.workspace}}/build shell: bash - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE $CMAKE_EXTRA + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release $CMAKE_EXTRA - name: Build Application working-directory: ${{runner.workspace}}/build shell: bash @@ -126,7 +126,7 @@ jobs: - name: Configure CMake working-directory: ${{runner.workspace}}/build shell: bash - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_TOOLS:BOOLEAN=FALSE + run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release -DBUILD_TOOLS:BOOLEAN=FALSE - name: shell: bash working-directory: ${{runner.workspace}}/build diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bf7b8bc56..ecbfd2eed9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,8 +67,12 @@ if (HIFI_ANDROID) WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) else() + set(VCPKG_BUILD_TYPE_PARAM "") + if (VCPKG_BUILD_TYPE) + set(VCPKG_BUILD_TYPE_PARAM --vcpkg-build-type ${VCPKG_BUILD_TYPE}) + endif() execute_process( - COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --release-type ${RELEASE_TYPE} --build-root ${CMAKE_BINARY_DIR} + COMMAND ${HIFI_PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/prebuild.py --release-type ${RELEASE_TYPE} --build-root ${CMAKE_BINARY_DIR} ${VCPKG_BUILD_TYPE_PARAM} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) # squelch the Policy CMP0074 warning without requiring an update to cmake 3.12. diff --git a/cmake/macros/TargetDraco.cmake b/cmake/macros/TargetDraco.cmake index 520786d4c3..e23069d1d3 100755 --- a/cmake/macros/TargetDraco.cmake +++ b/cmake/macros/TargetDraco.cmake @@ -1,6 +1,5 @@ macro(TARGET_DRACO) set(LIBS draco dracodec dracoenc) - find_library(LIBPATH ${LIB} PATHS ) if (ANDROID) set(INSTALL_DIR ${HIFI_ANDROID_PRECOMPILED}/draco) set(DRACO_INCLUDE_DIRS "${INSTALL_DIR}/include" CACHE STRING INTERNAL) @@ -12,6 +11,8 @@ macro(TARGET_DRACO) else() set(LIB_SEARCH_PATH_RELEASE ${VCPKG_INSTALL_ROOT}/lib/) set(LIB_SEARCH_PATH_DEBUG ${VCPKG_INSTALL_ROOT}/debug/lib/) + set(DRACO_LIBRARY_RELEASE "") + set(DRACO_LIBRARY_DEBUG "") foreach(LIB ${LIBS}) find_library(${LIB}_LIBPATH ${LIB} PATHS ${LIB_SEARCH_PATH_RELEASE} NO_DEFAULT_PATH) list(APPEND DRACO_LIBRARY_RELEASE ${${LIB}_LIBPATH}) diff --git a/cmake/macros/TargetOpenEXR.cmake b/cmake/macros/TargetOpenEXR.cmake index 8d61f216e7..9d63ba3ef4 100644 --- a/cmake/macros/TargetOpenEXR.cmake +++ b/cmake/macros/TargetOpenEXR.cmake @@ -28,6 +28,8 @@ macro(TARGET_OPENEXR) string(REGEX MATCHALL "[0-9]" OPENEXR_MINOR_VERSION ${TMP}) endif() + set(OPENEXR_LIBRARY_RELEASE "") + set(OPENEXR_LIBRARY_DEBUG "") foreach(OPENEXR_LIB IlmImf IlmImfUtil diff --git a/cmake/ports/quazip/portfile.cmake b/cmake/ports/quazip/portfile.cmake index 07a8ebc3c3..7ff2d07173 100644 --- a/cmake/ports/quazip/portfile.cmake +++ b/cmake/ports/quazip/portfile.cmake @@ -24,10 +24,14 @@ vcpkg_configure_cmake( vcpkg_install_cmake() if (WIN32) - file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/bin) - file(RENAME ${CURRENT_PACKAGES_DIR}/lib/quazip5.dll ${CURRENT_PACKAGES_DIR}/bin/quazip5.dll) - file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/debug/bin) - file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/quazip5d.dll ${CURRENT_PACKAGES_DIR}/debug/bin/quazip5.dll) + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/bin) + file(RENAME ${CURRENT_PACKAGES_DIR}/lib/quazip5.dll ${CURRENT_PACKAGES_DIR}/bin/quazip5.dll) + endif() + if (NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(MAKE_DIRECTORY ${CURRENT_PACKAGES_DIR}/debug/bin) + file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/quazip5d.dll ${CURRENT_PACKAGES_DIR}/debug/bin/quazip5.dll) + endif() elseif(DEFINED VCPKG_TARGET_IS_LINUX) # We only want static libs. file(GLOB QUAZIP5_DYNAMIC_LIBS ${CURRENT_PACKAGES_DIR}/lib/libquazip5.so* ${CURRENT_PACKAGES_DIR}/debug/lib/libquazip5d.so*) diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 9846d386c4..8aa928f8fe 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -21,6 +21,7 @@ get_filename_component(CMAKE_TOOLCHAIN_FILE "{}" ABSOLUTE CACHE) get_filename_component(CMAKE_TOOLCHAIN_FILE_UNCACHED "{}" ABSOLUTE) set(VCPKG_INSTALL_ROOT "{}") set(VCPKG_TOOLS_DIR "{}") +set(VCPKG_TARGET_TRIPLET "{}") """ CMAKE_TEMPLATE_NON_ANDROID = """ @@ -34,7 +35,11 @@ endif() self.args = args # our custom ports, relative to the script location self.sourcePortsPath = args.ports_path - self.id = hifi_utils.hashFolder(self.sourcePortsPath)[:8] + self.vcpkgBuildType = args.vcpkg_build_type + if (self.vcpkgBuildType): + self.id = hifi_utils.hashFolder(self.sourcePortsPath)[:8] + "-" + self.vcpkgBuildType + else: + self.id = hifi_utils.hashFolder(self.sourcePortsPath)[:8] self.configFilePath = os.path.join(args.build_root, 'vcpkg.cmake') self.assets_url = self.readVar('EXTERNAL_BUILD_ASSETS') @@ -82,15 +87,15 @@ endif() if 'Windows' == system: self.exe = os.path.join(self.path, 'vcpkg.exe') - self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.bat') ] + self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.bat'), '-disableMetrics' ] self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-win32-client.zip%3FversionId=tSFzbw01VkkVFeRQ6YuAY4dro2HxJR9U' self.vcpkgHash = 'a650db47a63ccdc9904b68ddd16af74772e7e78170b513ea8de5a3b47d032751a3b73dcc7526d88bcb500753ea3dd9880639ca842bb176e2bddb1710f9a58cd3' self.hostTriplet = 'x64-windows' if usePrebuilt: - self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-win32.zip%3FversionId=3SF3mDC8dkQH1JP041m88xnYmWNzZflx" + self.prebuiltArchive = "https://ipfs.io/ipfs/QmcBggttJQb1vYeyz29FXfaxnJ5c1HfZW72xNQepnENude/vcpkg-win32-a2623c6a-release.zip" elif 'Darwin' == system: self.exe = os.path.join(self.path, 'vcpkg') - self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '--allowAppleClang' ] + self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '--allowAppleClang', '-disableMetrics' ] self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-osx-client.tgz%3FversionId=j0b4azo_zTlH_Q9DElEWOz1UMYZ2nqQw' self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d' self.hostTriplet = 'x64-osx' @@ -98,7 +103,7 @@ endif() self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-osx.tgz%3FversionId=6JrIMTdvpBF3MAsjA92BMkO79Psjzs6Z" else: self.exe = os.path.join(self.path, 'vcpkg') - self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh') ] + self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '-disableMetrics' ] self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-linux-client.tgz%3FversionId=y7mct0gFicEXz5hJy3KROBugcLR56YWf' self.vcpkgHash = '6a1ce47ef6621e699a4627e8821ad32528c82fce62a6939d35b205da2d299aaa405b5f392df4a9e5343dd6a296516e341105fbb2dd8b48864781d129d7fba10d' self.hostTriplet = 'x64-linux' @@ -206,6 +211,19 @@ endif() print(actualCommands) hifi_utils.executeSubprocess(actualCommands, folder=self.path, env=self.buildEnv) + def copyTripletForBuildType(self, triplet): + print('Copying triplet ' + triplet + ' to have build type ' + self.vcpkgBuildType) + tripletPath = os.path.join(self.path, 'triplets', triplet + '.cmake') + tripletForBuildTypePath = os.path.join(self.path, 'triplets', self.getTripletWithBuildType(triplet) + '.cmake') + shutil.copy(tripletPath, tripletForBuildTypePath) + with open(tripletForBuildTypePath, "a") as tripletForBuildTypeFile: + tripletForBuildTypeFile.write("set(VCPKG_BUILD_TYPE " + self.vcpkgBuildType + ")\n") + + def getTripletWithBuildType(self, triplet): + if (not self.vcpkgBuildType): + return triplet + return triplet + '-' + self.vcpkgBuildType + def setupDependencies(self, qt=None): if self.prebuiltArchive: if not os.path.isfile(self.prebuildTagFile): @@ -224,12 +242,16 @@ endif() self.setupAndroidDependencies() print("Installing host tools") - self.run(['install', '--triplet', self.hostTriplet, 'hifi-host-tools']) + if (self.vcpkgBuildType): + self.copyTripletForBuildType(self.hostTriplet) + self.run(['install', '--triplet', self.getTripletWithBuildType(self.hostTriplet), 'hifi-host-tools']) # If not android, install the hifi-client-deps libraries if not self.args.android: print("Installing build dependencies") - self.run(['install', '--triplet', self.triplet, 'hifi-client-deps']) + if (self.vcpkgBuildType): + self.copyTripletForBuildType(self.triplet) + self.run(['install', '--triplet', self.getTripletWithBuildType(self.triplet), 'hifi-client-deps']) def cleanBuilds(self): if self.noClean: @@ -276,12 +298,32 @@ endif() with open(self.prebuildTagFile, 'w') as f: f.write(self.tagContents) + def fixupCmakeScript(self): + cmakeScript = os.path.join(self.path, 'scripts/buildsystems/vcpkg.cmake') + newCmakeScript = cmakeScript + '.new' + isFileChanged = False + removalPrefix = "set(VCPKG_TARGET_TRIPLET " + # Open original file in read only mode and dummy file in write mode + with open(cmakeScript, 'r') as read_obj, open(newCmakeScript, 'w') as write_obj: + # Line by line copy data from original file to dummy file + for line in read_obj: + if not line.startswith(removalPrefix): + write_obj.write(line) + else: + isFileChanged = True + + if isFileChanged: + shutil.move(newCmakeScript, cmakeScript) + else: + os.remove(newCmakeScript) + + def writeConfig(self): print("Writing cmake config to {}".format(self.configFilePath)) # Write out the configuration for use by CMake cmakeScript = os.path.join(self.path, 'scripts/buildsystems/vcpkg.cmake') - installPath = os.path.join(self.path, 'installed', self.triplet) - toolsPath = os.path.join(self.path, 'installed', self.hostTriplet, 'tools') + installPath = os.path.join(self.path, 'installed', self.getTripletWithBuildType(self.triplet)) + toolsPath = os.path.join(self.path, 'installed', self.getTripletWithBuildType(self.hostTriplet), 'tools') cmakeTemplate = VcpkgRepo.CMAKE_TEMPLATE if self.args.android: @@ -289,7 +331,7 @@ endif() cmakeTemplate += 'set(HIFI_ANDROID_PRECOMPILED "{}")\n'.format(precompiled) else: cmakeTemplate += VcpkgRepo.CMAKE_TEMPLATE_NON_ANDROID - cmakeConfig = cmakeTemplate.format(cmakeScript, cmakeScript, installPath, toolsPath).replace('\\', '/') + cmakeConfig = cmakeTemplate.format(cmakeScript, cmakeScript, installPath, toolsPath, self.getTripletWithBuildType(self.hostTriplet)).replace('\\', '/') with open(self.configFilePath, 'w') as f: f.write(cmakeConfig) diff --git a/prebuild.py b/prebuild.py index 03677f21d7..66c74630e7 100644 --- a/prebuild.py +++ b/prebuild.py @@ -94,6 +94,7 @@ def parse_args(): parser.add_argument('--force-build', action='store_true') parser.add_argument('--release-type', type=str, default="DEV", help="DEV, PR, or PRODUCTION") parser.add_argument('--vcpkg-root', type=str, help='The location of the vcpkg distribution') + parser.add_argument('--vcpkg-build-type', type=str, help='Could be `release` or `debug`. By default it doesn`t set the build-type') parser.add_argument('--build-root', required=True, type=str, help='The location of the cmake build') parser.add_argument('--ports-path', type=str, default=defaultPortsPath) parser.add_argument('--ci-build', action='store_true', default=os.getenv('CI_BUILD') is not None) @@ -142,6 +143,10 @@ def main(): pm.writeVar('QT_CMAKE_PREFIX_PATH', qtInstallPath) # Only allow one instance of the program to run at a time + + if qtInstallPath != '': + pm.writeVar('QT_CMAKE_PREFIX_PATH', qtInstallPath) + with hifi_singleton.Singleton(pm.lockFile) as lock: with timer('Bootstraping'): @@ -175,6 +180,9 @@ def main(): qtPath = os.path.join(pm.androidPackagePath, 'qt') hifi_android.QtPackager(appPath, qtPath).bundle() + # Fixup the vcpkg cmake to not reset VCPKG_TARGET_TRIPLET + pm.fixupCmakeScript() + # Write the vcpkg config to the build directory last with timer('Writing configuration'): pm.writeConfig() From 98e79fd698c5e95b894616283d70a03ae9851513 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 13 Feb 2020 19:27:59 +0100 Subject: [PATCH 047/105] update zlib port --- cmake/ports/zlib/CONTROL | 2 +- .../cmake_dont_build_more_than_needed.patch | 58 ++++++++++++++----- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/cmake/ports/zlib/CONTROL b/cmake/ports/zlib/CONTROL index aa7c7b6e92..601fb1bc0e 100644 --- a/cmake/ports/zlib/CONTROL +++ b/cmake/ports/zlib/CONTROL @@ -1,4 +1,4 @@ Source: zlib -Version: 1.2.11-5 +Version: 1.2.11-6 Homepage: https://www.zlib.net/ Description: A compression library diff --git a/cmake/ports/zlib/cmake_dont_build_more_than_needed.patch b/cmake/ports/zlib/cmake_dont_build_more_than_needed.patch index 229a2d055b..a374f76d62 100644 --- a/cmake/ports/zlib/cmake_dont_build_more_than_needed.patch +++ b/cmake/ports/zlib/cmake_dont_build_more_than_needed.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 0fe939d..8d2f5f1 100644 +index 0fe939d..a1291d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ set(VERSION "1.2.11") @@ -10,24 +10,56 @@ index 0fe939d..8d2f5f1 100644 set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries") -@@ -211,7 +212,15 @@ elseif(BUILD_SHARED_LIBS AND WIN32) +@@ -124,9 +125,11 @@ set(ZLIB_SRCS + ) + + if(NOT MINGW) +- set(ZLIB_DLL_SRCS +- win32/zlib1.rc # If present will override custom build rule below. +- ) ++ if(BUILD_SHARED_LIBS) ++ set(ZLIB_DLL_SRCS ++ win32/zlib1.rc # If present will override custom build rule below. ++ ) ++ endif() + endif() + + if(CMAKE_COMPILER_IS_GNUCC) +@@ -180,11 +183,12 @@ if(MINGW) + -I ${CMAKE_CURRENT_BINARY_DIR} + -o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj + -i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib1.rc) +- set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) ++ if(BUILD_SHARED_LIBS) ++ set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj) ++ endif() + endif(MINGW) + +-add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) +-add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) ++add_library(zlib ${ZLIB_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS}) + set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL) + set_target_properties(zlib PROPERTIES SOVERSION 1) + +@@ -201,7 +205,7 @@ endif() + + if(UNIX) + # On unix-like platforms the library is almost always called libz +- set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z) ++ set_target_properties(zlib PROPERTIES OUTPUT_NAME z) + if(NOT APPLE) + set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/zlib.map\"") + endif() +@@ -211,7 +215,7 @@ elseif(BUILD_SHARED_LIBS AND WIN32) endif() if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) - install(TARGETS zlib zlibstatic -+ if (BUILD_SHARED_LIBS) -+ set(ZLIB_TARGETS zlib) -+ set_target_properties(zlibstatic PROPERTIES EXCLUDE_FROM_ALL ON) -+ else() -+ set(ZLIB_TARGETS zlibstatic) -+ set_target_properties(zlib PROPERTIES EXCLUDE_FROM_ALL ON) -+ endif() -+ -+ install(TARGETS ${ZLIB_TARGETS} ++ install(TARGETS zlib RUNTIME DESTINATION "${INSTALL_BIN_DIR}" ARCHIVE DESTINATION "${INSTALL_LIB_DIR}" LIBRARY DESTINATION "${INSTALL_LIB_DIR}" ) -@@ -230,6 +239,7 @@ endif() +@@ -230,6 +234,7 @@ endif() # Example binaries #============================================================================ @@ -35,7 +67,7 @@ index 0fe939d..8d2f5f1 100644 add_executable(example test/example.c) target_link_libraries(example zlib) add_test(example example) -@@ -247,3 +257,4 @@ if(HAVE_OFF64_T) +@@ -247,3 +252,4 @@ if(HAVE_OFF64_T) target_link_libraries(minigzip64 zlib) set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64") endif() From 3ea3330beaf8fce6ed258fc8c6d2baa3bb5b43a9 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 13 Feb 2020 20:11:14 +0100 Subject: [PATCH 048/105] enable tbb for osx --- cmake/ports/hifi-deps/CONTROL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/ports/hifi-deps/CONTROL b/cmake/ports/hifi-deps/CONTROL index d4b4acd4c5..ff689c7a2a 100644 --- a/cmake/ports/hifi-deps/CONTROL +++ b/cmake/ports/hifi-deps/CONTROL @@ -1,4 +1,4 @@ Source: hifi-deps -Version: 0.1.4-github-actions +Version: 0.1.5-github-actions Description: Collected dependencies for High Fidelity applications Build-Depends: bullet3, draco, etc2comp, glad, glm, nvtt, openexr (!android), openssl (windows), opus, polyvox, tbb (!android), vhacd, webrtc (!android), zlib From 0c8359816cefd39809a9d3a4e850830df4f8cffa Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 15 Feb 2020 17:03:18 +0100 Subject: [PATCH 049/105] - make vcpkg output smaller by removing downloads and packages folders - only build the full version of the clients for now (server+client) - disable using a predefined vcpkg for CI builds for now. - --- hifi_vcpkg.py | 14 ++++++++++---- prebuild.py | 5 ++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 8aa928f8fe..03ed303022 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -91,16 +91,16 @@ endif() self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-win32-client.zip%3FversionId=tSFzbw01VkkVFeRQ6YuAY4dro2HxJR9U' self.vcpkgHash = 'a650db47a63ccdc9904b68ddd16af74772e7e78170b513ea8de5a3b47d032751a3b73dcc7526d88bcb500753ea3dd9880639ca842bb176e2bddb1710f9a58cd3' self.hostTriplet = 'x64-windows' - if usePrebuilt: - self.prebuiltArchive = "https://ipfs.io/ipfs/QmcBggttJQb1vYeyz29FXfaxnJ5c1HfZW72xNQepnENude/vcpkg-win32-a2623c6a-release.zip" + #if usePrebuilt: + # self.prebuiltArchive = "https://ipfs.io/ipfs/QmcBggttJQb1vYeyz29FXfaxnJ5c1HfZW72xNQepnENude/vcpkg-win32-a2623c6a-release.zip" elif 'Darwin' == system: self.exe = os.path.join(self.path, 'vcpkg') self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '--allowAppleClang', '-disableMetrics' ] self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-osx-client.tgz%3FversionId=j0b4azo_zTlH_Q9DElEWOz1UMYZ2nqQw' self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d' self.hostTriplet = 'x64-osx' - if usePrebuilt: - self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-osx.tgz%3FversionId=6JrIMTdvpBF3MAsjA92BMkO79Psjzs6Z" + #if usePrebuilt: + # self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-osx.tgz%3FversionId=6JrIMTdvpBF3MAsjA92BMkO79Psjzs6Z" else: self.exe = os.path.join(self.path, 'vcpkg') self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '-disableMetrics' ] @@ -262,6 +262,12 @@ endif() print("Wiping build trees") shutil.rmtree(builddir, ignore_errors=True) + # Removes large files used to build the vcpkg, for CI purposes. + def cleanupDevelopmentFiles(self): + shutil.rmtree(os.path.join(self.path, "downloads"), ignore_errors=True) + shutil.rmtree(os.path.join(self.path, "packages"), ignore_errors=True) + + def setupAndroidDependencies(self): # vcpkg prebuilt if not os.path.isdir(os.path.join(self.path, 'installed', 'arm64-android')): diff --git a/prebuild.py b/prebuild.py index 66c74630e7..b15c83e4fe 100644 --- a/prebuild.py +++ b/prebuild.py @@ -165,7 +165,7 @@ def main(): pm.setupDependencies(qt=qtInstallPath) # wipe out the build directories (after writing the tag, since failure - # here shouldn't invalidte the vcpkg install) + # here shouldn't invalidate the vcpkg install) with timer('Cleaning builds'): pm.cleanBuilds() @@ -183,6 +183,9 @@ def main(): # Fixup the vcpkg cmake to not reset VCPKG_TARGET_TRIPLET pm.fixupCmakeScript() + # Cleanup downloads and packages folders in vcpkg to make it smaller for CI + pm.cleanupDevelopmentFiles() + # Write the vcpkg config to the build directory last with timer('Writing configuration'): pm.writeConfig() From ba7f7406250f5a30607506ad2b249194553c4684 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 15 Feb 2020 17:17:41 +0100 Subject: [PATCH 050/105] try fix osx vcpkg build --- hifi_vcpkg.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 03ed303022..4d347a289a 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -99,6 +99,8 @@ endif() self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-osx-client.tgz%3FversionId=j0b4azo_zTlH_Q9DElEWOz1UMYZ2nqQw' self.vcpkgHash = '519d666d02ef22b87c793f016ca412e70f92e1d55953c8f9bd4ee40f6d9f78c1df01a6ee293907718f3bbf24075cc35492fb216326dfc50712a95858e9cbcb4d' self.hostTriplet = 'x64-osx' + # Potential fix for a vcpkg build issue on OSX (see https://github.com/microsoft/vcpkg/issues/9029) + self.bootstrapEnv['CXXFLAGS'] = '-D_CTERMID_H_' #if usePrebuilt: # self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-osx.tgz%3FversionId=6JrIMTdvpBF3MAsjA92BMkO79Psjzs6Z" else: From 466e1a7ce3c21786a2363a42a3180ebf64fda35f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 31 Mar 2020 13:39:54 +0200 Subject: [PATCH 051/105] - disable osx GHA build for now - fix tbb issue, the repo moved to another location which changed the hash of the source --- cmake/ports/tbb/CONTROL | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/ports/tbb/CONTROL b/cmake/ports/tbb/CONTROL index da29e48794..73569fe661 100644 --- a/cmake/ports/tbb/CONTROL +++ b/cmake/ports/tbb/CONTROL @@ -1,4 +1,4 @@ Source: tbb Version: 2019_U8-1 -Homepage: https://github.com/01org/tbb +Homepage: https://github.com/oneapi-src/oneTBB Description: Intel's Threading Building Blocks. From 25932d3ab5f63263b89148bbd877c5270357cb83 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Apr 2020 11:12:23 +0200 Subject: [PATCH 052/105] the new build upload script --- .github/workflows/pr_build.yml | 7 ++ tools/ci-scripts/upload_to_publish_server.py | 77 ++++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 tools/ci-scripts/upload_to_publish_server.py diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 2d603ea6f4..fba23772fe 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -105,6 +105,13 @@ jobs: shell: bash working-directory: ${{runner.workspace}}/build run: cat ./_CPack_Packages/win64/NSIS/NSISOutput.log + - name: Upload Artifact + shell: bash + working-directory: ${{runner.workspace}}/build + env: + GITHUB_CONTEXT: ${{ toJson(github) }} + ARTIFACT_PATTERN: HighFidelity-Beta-PR${{ github.event.number }}-*.exe + run: python "$GITHUB_WORKSPACE\tools\ci-scripts\upload_to_publish_server.py" build_full_linux: runs-on: ubuntu-latest diff --git a/tools/ci-scripts/upload_to_publish_server.py b/tools/ci-scripts/upload_to_publish_server.py new file mode 100644 index 0000000000..8b363f36aa --- /dev/null +++ b/tools/ci-scripts/upload_to_publish_server.py @@ -0,0 +1,77 @@ +import os +import json +from hashlib import sha256 +import http.client +from http import HTTPStatus +import time +import struct +import random +import glob + +FILE_READ_BUFFER = 4096 + +path = os.path.join(os.getcwd(), os.environ['ARTIFACT_PATTERN']) +files = glob.glob(path, recursive=False) +uploading_files = [] +for archive_file in files: + file = open(archive_file, 'rb') + sha256_hash = sha256() + file.seek(0, 0) + for byte_block in iter(lambda: file.read(FILE_READ_BUFFER), b""): + sha256_hash.update(byte_block) + + checksum = sha256_hash.hexdigest() + + uploading_files.append({ + "filename": os.path.basename(archive_file), + "sha256_checksum": checksum, + "file_length": file.tell() + }) + file.close() + +print("BuildFileHashes: " + json.dumps(uploading_files)) + +file_contents = [] +file_sizes = [] + +for archiveFile in files: + file = open(archiveFile, 'rb') + file_data = file.read() + file_sizes.append(len(file_data)) + file_contents.append(file_data) + file.close() + +conn = http.client.HTTPSConnection("athena-build-uploader.thoys.nl") + +context = json.loads(os.environ['GITHUB_CONTEXT']) + +owner_and_repository = context["repository"].split("/") +owner = owner_and_repository[0] +repository = owner_and_repository[1] + +headers = { + "owner": owner, + "repo": repository, + "commit_hash": context["event"]["pull_request"]["head"]["sha"], + "pull_number": context["event"]["number"], + "job_name": os.environ["JOB_NAME"], + "run_id": context["run_id"], + "file_sizes": ','.join(str(e) for e in file_sizes) +} + +concat_file_body = b''.join(file_contents) + +print("Total files size: " + str(len(concat_file_body))) + +conn.request("PUT", "/", body=concat_file_body, headers=headers) +response = conn.getresponse() + +EXIT_CODE_OK = 0 +EXIT_CODE_ERROR = 1 + +if (response.status == HTTPStatus.OK): + print("response: ", json.loads(response.read())) + exit(EXIT_CODE_OK) +else: + print(response.status, response.reason, response.read()) + exit(EXIT_CODE_ERROR) From b89ddf33eca4d67b2d2610eba7de7ae15b05fd92 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Apr 2020 12:07:53 +0200 Subject: [PATCH 053/105] fix missing url --- hifi_qt.py | 6 +----- hifi_utils.py | 4 ++++ prebuild.py | 9 ++++++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/hifi_qt.py b/hifi_qt.py index 6cae3bf59d..b046342745 100644 --- a/hifi_qt.py +++ b/hifi_qt.py @@ -29,7 +29,7 @@ endif() self.configFilePath = os.path.join(args.build_root, 'qt.cmake') self.version = os.getenv('VIRCADIA_USE_QT_VERSION', '5.12.3') - self.assets_url = self.readVar('EXTERNAL_BUILD_ASSETS') + self.assets_url = hifi_utils.readEnviromentVariableFromFile(args.build_root, 'EXTERNAL_BUILD_ASSETS') defaultBasePath = os.path.expanduser('~/hifi/qt') self.basePath = os.getenv('HIFI_QT_BASE', defaultBasePath) @@ -89,10 +89,6 @@ endif() print("Machine : " + platform.machine()) raise Exception('UNKNOWN OPERATING SYSTEM!!!') - def readVar(self, var): - with open(os.path.join(self.args.build_root, '_env', var + ".txt")) as fp: - return fp.read() - def writeConfig(self): print("Writing cmake config to {}".format(self.configFilePath)) # Write out the configuration for use by CMake diff --git a/hifi_utils.py b/hifi_utils.py index 3a49f6d52b..157e5858a8 100644 --- a/hifi_utils.py +++ b/hifi_utils.py @@ -121,3 +121,7 @@ def downloadAndExtract(url, destPath, hash=None, hasher=hashlib.sha512(), isZip= with tarfile.open(tempFileName, 'r:*') as tgz: tgz.extractall(destPath) os.remove(tempFileName) + +def readEnviromentVariableFromFile(buildRootDir, var): + with open(os.path.join(buildRootDir, '_env', var + ".txt")) as fp: + return fp.read() diff --git a/prebuild.py b/prebuild.py index b15c83e4fe..d0bbc75fb7 100644 --- a/prebuild.py +++ b/prebuild.py @@ -95,6 +95,7 @@ def parse_args(): parser.add_argument('--release-type', type=str, default="DEV", help="DEV, PR, or PRODUCTION") parser.add_argument('--vcpkg-root', type=str, help='The location of the vcpkg distribution') parser.add_argument('--vcpkg-build-type', type=str, help='Could be `release` or `debug`. By default it doesn`t set the build-type') + parser.add_argument('--vcpkg-skip-clean', action='store_true', help='Skip the cleanup of vcpkg downloads and packages folders after vcpkg build completition.') parser.add_argument('--build-root', required=True, type=str, help='The location of the cmake build') parser.add_argument('--ports-path', type=str, default=defaultPortsPath) parser.add_argument('--ci-build', action='store_true', default=os.getenv('CI_BUILD') is not None) @@ -114,6 +115,7 @@ def main(): del os.environ[var] args = parse_args() + assets_url = hifi_utils.readEnviromentVariableFromFile(args.build_root, 'EXTERNAL_BUILD_ASSETS') if args.ci_build: logging.basicConfig(datefmt='%H:%M:%S', format='%(asctime)s %(guid)s %(message)s', level=logging.INFO) @@ -126,7 +128,7 @@ def main(): if 'Windows' == system and 'CI_BUILD' in os.environ and os.environ["CI_BUILD"] == "Github": logger.info("Downloading NSIS") with timer('NSIS'): - hifi_utils.downloadAndExtract('https://athena-public.s3.amazonaws.com/dependencies/NSIS-hifi-plugins-1.0.tgz', "C:/Program Files (x86)") + hifi_utils.downloadAndExtract(assets_url + '/dependencies/NSIS-hifi-plugins-1.0.tgz', "C:/Program Files (x86)") qtInstallPath = '' # If not android, install our Qt build @@ -183,8 +185,9 @@ def main(): # Fixup the vcpkg cmake to not reset VCPKG_TARGET_TRIPLET pm.fixupCmakeScript() - # Cleanup downloads and packages folders in vcpkg to make it smaller for CI - pm.cleanupDevelopmentFiles() + if not args.vcpkg_skip_clean: + # Cleanup downloads and packages folders in vcpkg to make it smaller for CI + pm.cleanupDevelopmentFiles() # Write the vcpkg config to the build directory last with timer('Writing configuration'): From 53bb62756f6bef68db7e9a9e0b4f9a6e2025fbba Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Apr 2020 16:10:33 +0200 Subject: [PATCH 054/105] fix more links --- cmake/ports/glad/portfile.cmake | 7 ++++--- cmake/ports/polyvox/portfile.cmake | 4 +++- cmake/ports/quazip/portfile.cmake | 3 ++- cmake/ports/vhacd/portfile.cmake | 6 ++++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/cmake/ports/glad/portfile.cmake b/cmake/ports/glad/portfile.cmake index 56ee59e0d4..54b1d91c89 100644 --- a/cmake/ports/glad/portfile.cmake +++ b/cmake/ports/glad/portfile.cmake @@ -1,17 +1,19 @@ include(vcpkg_common_functions) vcpkg_check_linkage(ONLY_STATIC_LIBRARY) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) + if (ANDROID) vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/glad/glad32es.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad32es.zip SHA512 2e02ac633eed8f2ba2adbf96ea85d08998f48dd2e9ec9a88ec3c25f48eaf1405371d258066327c783772fcb3793bdb82bd7375fdabb2ba5e2ce0835468b17f65 ) else() # else Linux desktop vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/glad/glad45.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/glad/glad45.zip SHA512 653a7b873f9fbc52e0ab95006cc3143bc7b6f62c6e032bc994e87669273468f37978525c9af5efe36f924cb4acd221eb664ad9af0ce4bf711b4f1be724c0065e FILENAME glad45.zip ) @@ -33,4 +35,3 @@ vcpkg_install_cmake() file(COPY ${CMAKE_CURRENT_LIST_DIR}/copyright DESTINATION ${CURRENT_PACKAGES_DIR}/share/glad) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/include) - diff --git a/cmake/ports/polyvox/portfile.cmake b/cmake/ports/polyvox/portfile.cmake index 275a1a940f..9204b26dbd 100644 --- a/cmake/ports/polyvox/portfile.cmake +++ b/cmake/ports/polyvox/portfile.cmake @@ -1,9 +1,11 @@ include(vcpkg_common_functions) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) + # else Linux desktop vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/polyvox-master-2015-7-15.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/polyvox-master-2015-7-15.zip SHA512 cc04cd43ae74b9c7bb065953540c0048053fcba6b52dc4218b3d9431fba178d65ad4f6c53cc1122ba61d0ab4061e99a7ebbb15db80011d607c5070ebebf8eddc FILENAME polyvox.zip ) diff --git a/cmake/ports/quazip/portfile.cmake b/cmake/ports/quazip/portfile.cmake index 7ff2d07173..0789062892 100644 --- a/cmake/ports/quazip/portfile.cmake +++ b/cmake/ports/quazip/portfile.cmake @@ -1,10 +1,11 @@ include(vcpkg_common_functions) file(READ "${VCPKG_ROOT_DIR}/_env/QT_CMAKE_PREFIX_PATH.txt" QT_CMAKE_PREFIX_PATH) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/quazip-0.7.3.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/quazip-0.7.3.zip SHA512 b2d812b6346317fd6d8f4f1344ad48b721d697c429acc8b7e7cb776ce5cba15a59efd64b2c5ae1f31b5a3c928014f084aa1379fd55d8a452a6cf4fd510b3afcc FILENAME quazip.zip ) diff --git a/cmake/ports/vhacd/portfile.cmake b/cmake/ports/vhacd/portfile.cmake index 3a13e461a6..4c74bb6532 100644 --- a/cmake/ports/vhacd/portfile.cmake +++ b/cmake/ports/vhacd/portfile.cmake @@ -1,10 +1,12 @@ include(vcpkg_common_functions) vcpkg_check_linkage(ONLY_STATIC_LIBRARY) +file(READ "${VCPKG_ROOT_DIR}/_env/EXTERNAL_BUILD_ASSETS.txt" EXTERNAL_BUILD_ASSETS) + # else Linux desktop vcpkg_download_distfile( SOURCE_ARCHIVE - URLS https://athena-public.s3.amazonaws.com/dependencies/v-hacd-master.zip + URLS ${EXTERNAL_BUILD_ASSETS}/dependencies/v-hacd-master.zip SHA512 5d9bd4872ead9eb3574e4806d6c4f490353a04036fd5f571e1e44f47cb66b709e311abcd53af30bae0015a690152170aeed93209a626c28ebcfd6591f3bb036f FILENAME vhacd.zip ) @@ -35,4 +37,4 @@ if (WIN32) file(RENAME ${CURRENT_PACKAGES_DIR}/debug/lib/Debug/VHACD_LIB.lib ${CURRENT_PACKAGES_DIR}/debug/lib/VHACD.lib) file(REMOVE_RECURSE ${CURRENT_PACKAGES_DIR}/debug/lib/Debug) endif() -endif() \ No newline at end of file +endif() From 35efa33b747e7628e2c6793e75e0c2d38e37fd4c Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 8 Apr 2020 17:47:13 +0200 Subject: [PATCH 055/105] - set the correct artifact filter - add missing JOB_NAME env --- .github/workflows/pr_build.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index fba23772fe..715effb1f5 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -39,6 +39,7 @@ jobs: id: buildenv1 run: | echo ::set-env name=GIT_COMMIT_SHORT::`echo $GIT_COMMIT | cut -c1-7` + echo ::set-env name=JOB_NAME::build-${{matrix.os}} # Linux build variables if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then echo ::set-env name=PYTHON_EXEC::python3 @@ -110,11 +111,13 @@ jobs: working-directory: ${{runner.workspace}}/build env: GITHUB_CONTEXT: ${{ toJson(github) }} - ARTIFACT_PATTERN: HighFidelity-Beta-PR${{ github.event.number }}-*.exe + ARTIFACT_PATTERN: ProjectAthena-Alpha-PR${{ github.event.number }}-*.exe run: python "$GITHUB_WORKSPACE\tools\ci-scripts\upload_to_publish_server.py" build_full_linux: runs-on: ubuntu-latest + env: + JOB_NAME: build_full_linux if: github.event.action != 'labeled' || github.event.label.name == 'rebuild' steps: - uses: actions/checkout@v1 From 0ebe33b447bf0e8d71e97b7a04b2d1abd5362ed2 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Sat, 11 Apr 2020 17:58:54 +0200 Subject: [PATCH 056/105] change upload server --- tools/ci-scripts/upload_to_publish_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ci-scripts/upload_to_publish_server.py b/tools/ci-scripts/upload_to_publish_server.py index 8b363f36aa..5e1a9b24f2 100644 --- a/tools/ci-scripts/upload_to_publish_server.py +++ b/tools/ci-scripts/upload_to_publish_server.py @@ -41,7 +41,7 @@ for archiveFile in files: file_contents.append(file_data) file.close() -conn = http.client.HTTPSConnection("athena-build-uploader.thoys.nl") +conn = http.client.HTTPSConnection("build-uploader.vircadia.com") context = json.loads(os.environ['GITHUB_CONTEXT']) From 403925ef0e5cb339bb231d901a13ae5b1ac39c2f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 15 Apr 2020 11:05:44 +0200 Subject: [PATCH 057/105] add missing exceptions qt downloader --- hifi_qt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hifi_qt.py b/hifi_qt.py index b046342745..803c848f36 100644 --- a/hifi_qt.py +++ b/hifi_qt.py @@ -74,10 +74,10 @@ endif() self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.6-ubuntu-19.10.tar.xz' elif u_major > 18 and ( u_major != 19 and u_minor != 4): print("We don't support " + distro.name(pretty=True) + " yet. Perhaps consider helping us out?") - raise Exception('UNSUPPORTED LINUX VERSION!!!') + raise Exception('YET UNSUPPORTED VERSION OF LINUX DISTRO!!!') else: print("Sorry, " + distro.name(pretty=True) + " is old and won't be officially supported. Please consider upgrading."); - raise Exception('UNSUPPORTED LINUX VERSION!!!') + raise Exception('UNKNOWN LINUX DISTRO VERSION!!!') else: print("Sorry, " + distro.name(pretty=True) + " is not supported. Please consider helping us out.") print("It's also possible to build Qt for your distribution, please see the documentation at:") From ba62b06f2529e531a0cc65365c8f1e95593156df Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 15 Apr 2020 11:15:26 +0200 Subject: [PATCH 058/105] move comment to the code it belongs to --- prebuild.py | 1 + 1 file changed, 1 insertion(+) diff --git a/prebuild.py b/prebuild.py index d0bbc75fb7..cc315a49a4 100644 --- a/prebuild.py +++ b/prebuild.py @@ -149,6 +149,7 @@ def main(): if qtInstallPath != '': pm.writeVar('QT_CMAKE_PREFIX_PATH', qtInstallPath) + # Only allow one instance of the program to run at a time with hifi_singleton.Singleton(pm.lockFile) as lock: with timer('Bootstraping'): From e71a94cc3ef7b98a4de24071551dbbdad162c71e Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 15 Apr 2020 11:45:21 +0200 Subject: [PATCH 059/105] Build.md: Generating a release/debug only vcpkg build docs --- BUILD.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/BUILD.md b/BUILD.md index bc032d4ec7..1cad8724b3 100644 --- a/BUILD.md +++ b/BUILD.md @@ -73,6 +73,18 @@ Create a build directory in the root of your checkout and then run the CMake bui If cmake gives you the same error message repeatedly after the build fails, try removing `CMakeCache.txt`. +##### Generating a release/debug only vcpkg build + +In order to generate a release or debug only vcpkg package, you could use the use the `VCPKG_BUILD_TYPE` define in your cmake generate command. Building a release only vcpkg can drastically decrease the total build time. + +For release only vcpkg: + +`cmake .. -DVCPKG_BUILD_TYPE=release` + +For debug only vcpkg: + +`cmake .. -DVCPKG_BUILD_TYPE=debug` + #### Variables Any variables that need to be set for CMake to find dependencies can be set as ENV variables in your shell profile, or passed directly to CMake with a `-D` flag appended to the `cmake ..` command. From 1dd843c916abff18db5a208ca673a14d42bdf2f3 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 17 Apr 2020 15:23:20 +0200 Subject: [PATCH 060/105] set correct JOB_NAME in osx/windows GHA environment --- .github/workflows/pr_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 715effb1f5..dd373d0ad5 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -39,7 +39,7 @@ jobs: id: buildenv1 run: | echo ::set-env name=GIT_COMMIT_SHORT::`echo $GIT_COMMIT | cut -c1-7` - echo ::set-env name=JOB_NAME::build-${{matrix.os}} + echo ::set-env name=JOB_NAME::"build (${{matrix.os}}, ${{matrix.build_type}})" # Linux build variables if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then echo ::set-env name=PYTHON_EXEC::python3 From 3a4b312b534662776fa20b30c720f2a2f9e1dc06 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Fri, 17 Apr 2020 16:15:07 +0200 Subject: [PATCH 061/105] ubuntu github actions: use pip3 instead of python 2.7 version of pip --- .github/workflows/pr_build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index dd373d0ad5..685966ee63 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -127,10 +127,10 @@ jobs: - name: Update apt repository index run: sudo apt update - name: Install apt packages - run: sudo apt install -y mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 + run: sudo apt install -y mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 python3-setuptools - name: Install python modules shell: bash - run: pip install boto3 distro PyGithub + run: pip3 install boto3 distro PyGithub - name: Create Build Environment run: cmake -E make_directory ${{runner.workspace}}/build - name: Configure CMake From 0f0a8ad7bf89984631c562c0683dea5490bef4f6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Apr 2020 10:42:22 +1200 Subject: [PATCH 062/105] Update branding and AC script location --- unpublishedScripts/marketplace/record/html/record.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/unpublishedScripts/marketplace/record/html/record.html b/unpublishedScripts/marketplace/record/html/record.html index 89392e6951..cadb55a62f 100644 --- a/unpublishedScripts/marketplace/record/html/record.html +++ b/unpublishedScripts/marketplace/record/html/record.html @@ -3,6 +3,7 @@ // // Created by David Rowe on 5 Apr 2017. // Copyright 2017 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -41,9 +42,9 @@

    Setup Instructions

    In your sandbox domain:

      -
    • Right-click the High Fidelity Sandbox icon in your system tray and click “Settings”.
    • +
    • Right-click the Vircadia Sandbox icon in your system tray and click “Settings”.
    • In the “Scripts” section add a new row and paste in this script URL:
      - +
    • Set the number of recordings you’d like to run at a given time in the “Instances” slot.
    • Click “Save and restart”.
    • From 8cf1766df48131da3b1287480a31e343ed316193 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 20 Apr 2020 15:43:07 +1200 Subject: [PATCH 063/105] Update AC script URL --- unpublishedScripts/marketplace/record/html/record.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpublishedScripts/marketplace/record/html/record.html b/unpublishedScripts/marketplace/record/html/record.html index cadb55a62f..810238a580 100644 --- a/unpublishedScripts/marketplace/record/html/record.html +++ b/unpublishedScripts/marketplace/record/html/record.html @@ -44,7 +44,7 @@
      • Right-click the Vircadia Sandbox icon in your system tray and click “Settings”.
      • In the “Scripts” section add a new row and paste in this script URL:
        - +
      • Set the number of recordings you’d like to run at a given time in the “Instances” slot.
      • Click “Save and restart”.
      • From fd63e0ed4fb1fe7178fcc87160b256ae3ee44f86 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 22 Apr 2020 12:20:30 +0200 Subject: [PATCH 064/105] set linux github action to 16.04 to maintain backward compatibility --- .github/workflows/pr_build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 685966ee63..cd7c42ff80 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -9,7 +9,8 @@ env: BUILD_TYPE: Release CI_BUILD: Github GIT_COMMIT: ${{ github.sha }} - HIFI_VCPKG_BOOTSTRAP: true + # VCPKG did not build well on OSX disabling HIFI_VCPKG_BOOTSTRAP, which invokes a download to a working version of vcpkg + # HIFI_VCPKG_BOOTSTRAP: true RELEASE_TYPE: PR RELEASE_NUMBER: ${{ github.event.number }} VERSION_CODE: ${{ github.event.number }} @@ -115,7 +116,7 @@ jobs: run: python "$GITHUB_WORKSPACE\tools\ci-scripts\upload_to_publish_server.py" build_full_linux: - runs-on: ubuntu-latest + runs-on: ubuntu-16.04 env: JOB_NAME: build_full_linux if: github.event.action != 'labeled' || github.event.label.name == 'rebuild' From 5fa8571c0ba62d4e79450b815fdd4779a8253b3d Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 22 Apr 2020 19:14:18 +0200 Subject: [PATCH 065/105] shared seems to require linking with CoreFoundation and OpenGL on OSX --- libraries/shared/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/shared/CMakeLists.txt b/libraries/shared/CMakeLists.txt index eb3e286843..57904be586 100644 --- a/libraries/shared/CMakeLists.txt +++ b/libraries/shared/CMakeLists.txt @@ -13,6 +13,13 @@ if (ANDROID) target_link_libraries(${TARGET_NAME} android) endif() +if (APPLE) + find_library(FRAMEWORK_IOKIT IOKit) + find_library(CORE_FOUNDATION CoreFoundation) + find_library(OpenGL OpenGL) + target_link_libraries(${TARGET_NAME} ${FRAMEWORK_IOKIT} ${CORE_FOUNDATION} ${OpenGL}) +endif() + target_zlib() target_nsight() target_json() From b4362ea85ae04e4520d347c3438b0d073c570208 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 22 Apr 2020 22:59:01 +0200 Subject: [PATCH 066/105] move template functions to header --- .../src/graphics/BufferViewHelpers.cpp | 44 ---------------- .../graphics/src/graphics/BufferViewHelpers.h | 50 ++++++++++++++++++- 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.cpp b/libraries/graphics/src/graphics/BufferViewHelpers.cpp index 076cb92dcf..58ddbc9f58 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.cpp +++ b/libraries/graphics/src/graphics/BufferViewHelpers.cpp @@ -120,50 +120,6 @@ template<> glm::uint32 forEach(const gpu::BufferView& view, std::func return forEachGlmVec(view, func); } -template -QVariant glmVecToVariant(const T& v, bool asArray /*= false*/) { - static const auto len = T().length(); - if (asArray) { - QVariantList list; - for (int i = 0; i < len ; i++) { - list << v[i]; - } - return list; - } else { - QVariantMap obj; - for (int i = 0; i < len ; i++) { - obj[XYZW[i]] = v[i]; - } - return obj; - } -} - -template -const T glmVecFromVariant(const QVariant& v) { - auto isMap = v.type() == (QVariant::Type)QMetaType::QVariantMap; - static const auto len = T().length(); - const auto& components = isMap ? XYZW : ZERO123; - T result; - QVariantMap map; - QVariantList list; - if (isMap) map = v.toMap(); else list = v.toList(); - for (int i = 0; i < len ; i++) { - float value; - if (isMap) { - value = map.value(components[i]).toFloat(); - } else { - value = list.value(i).toFloat(); - } -#ifdef DEBUG_BUFFERVIEW_HELPERS - if (value != value) { // NAN - qWarning().nospace()<< "vec" << len << "." << components[i] << " NAN received from script.... " << v.toString(); - } -#endif - result[i] = value; - } - return result; -} - // QVector => BufferView template gpu::BufferView newFromVector(const QVector& elements, const gpu::Element& elementType) { diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.h b/libraries/graphics/src/graphics/BufferViewHelpers.h index 3635ef64e5..4c467b5175 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.h +++ b/libraries/graphics/src/graphics/BufferViewHelpers.h @@ -27,8 +27,54 @@ namespace buffer_helpers { extern const std::array XYZW; extern const std::array ZERO123; - template QVariant glmVecToVariant(const T& v, bool asArray = false); - template const T glmVecFromVariant(const QVariant& v); + template + QVariant glmVecToVariant(const T& v, bool asArray = false) { + static const auto len = T().length(); + if (asArray) { + QVariantList list; + for (int i = 0; i < len; i++) { + list << v[i]; + } + return list; + } else { + QVariantMap obj; + for (int i = 0; i < len; i++) { + obj[XYZW[i]] = v[i]; + } + return obj; + } + } + + template + const T glmVecFromVariant(const QVariant& v) { + auto isMap = v.type() == (QVariant::Type)QMetaType::QVariantMap; + static const auto len = T().length(); + const auto& components = isMap ? XYZW : ZERO123; + T result; + QVariantMap map; + QVariantList list; + if (isMap) { + map = v.toMap(); + } else { + list = v.toList(); + } + for (int i = 0; i < len; i++) { + float value; + if (isMap) { + value = map.value(components[i]).toFloat(); + } else { + value = list.value(i).toFloat(); + } +#ifdef DEBUG_BUFFERVIEW_HELPERS + if (value != value) { // NAN + qWarning().nospace() << "vec" << len << "." << components[i] << " NAN received from script.... " << v.toString(); + } +#endif + result[i] = value; + } + return result; + } + glm::uint32 forEachVariant(const gpu::BufferView& view, std::function func, const char* hint = ""); template glm::uint32 forEach(const gpu::BufferView& view, std::function func); From c4a0fc30bbe8b57e66d3806d9bf026fe1dc01caa Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 22 Apr 2020 23:09:17 +0200 Subject: [PATCH 067/105] fix not matching declaration/definition argument name --- libraries/graphics/src/graphics/BufferViewHelpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/graphics/src/graphics/BufferViewHelpers.h b/libraries/graphics/src/graphics/BufferViewHelpers.h index 4c467b5175..c42bb0426d 100644 --- a/libraries/graphics/src/graphics/BufferViewHelpers.h +++ b/libraries/graphics/src/graphics/BufferViewHelpers.h @@ -82,7 +82,7 @@ namespace buffer_helpers { template gpu::BufferView newFromVector(const QVector& elements, const gpu::Element& elementType); template gpu::BufferView newFromVariantList(const QVariantList& list, const gpu::Element& elementType); - template QVector variantToVector(const QVariant& list); + template QVector variantToVector(const QVariant& value); template QVector bufferToVector(const gpu::BufferView& view, const char *hint = ""); // note: these do value conversions from the underlying buffer type into the template type From f186c9341a3c32bb02e95e6a8c30235e3d8391b7 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 22 Apr 2020 20:46:07 +0200 Subject: [PATCH 068/105] linux gha fix # Conflicts: # .github/workflows/pr_build.yml --- .github/workflows/pr_build.yml | 65 ++++++++++++++-------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index cd7c42ff80..b28e237f96 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -29,8 +29,12 @@ jobs: build: strategy: matrix: - os: [windows-latest, macOS-latest] + os: [windows-latest, macOS-latest, ubuntu-18.04] build_type: [full] + include: + - os: ubuntu-18.04 + build_type: full + apt-dependencies: mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 fail-fast: false runs-on: ${{matrix.os}} if: github.event.action != 'labeled' || github.event.label.name == 'rebuild' @@ -41,10 +45,12 @@ jobs: run: | echo ::set-env name=GIT_COMMIT_SHORT::`echo $GIT_COMMIT | cut -c1-7` echo ::set-env name=JOB_NAME::"build (${{matrix.os}}, ${{matrix.build_type}})" + # Linux build variables - if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then + if [[ "${{ matrix.os }}" = "ubuntu-"* ]]; then echo ::set-env name=PYTHON_EXEC::python3 echo ::set-env name=INSTALLER_EXT::tgz + echo ::set-env name=CMAKE_BUILD_EXTRA::"-- -j3" fi # Mac build variables if [ "${{ matrix.os }}" = "macOS-latest" ]; then @@ -63,11 +69,11 @@ jobs: shell: bash run: | echo "${{ steps.buildenv1.outputs.symbols_archive }}" - echo ::set-env name=ARTIFACT_PATTERN::HighFidelity-Beta-*.$INSTALLER_EXT + echo ::set-env name=ARTIFACT_PATTERN::ProjectAthena-Alpha-PR${{ github.event.number }}-*.$INSTALLER_EXT # Build type variables echo ::set-env name=INSTALLER::HighFidelity-Beta-$RELEASE_NUMBER-$GIT_COMMIT_SHORT.$INSTALLER_EXT - name: Clear Working Directory - if: matrix.os[1] == 'windows' + if: startsWith(matrix.os, 'windows') shell: bash working-directory: ${{runner.workspace}} run: rm -rf ./* @@ -75,6 +81,18 @@ jobs: with: submodules: true fetch-depth: 1 + - name: Install dependencies + shell: bash + if: startsWith(matrix.os, 'ubuntu') + run: | + echo "Installing Python Modules:" + pip3 install distro || exit 1 + + echo "Updating apt repository index" + sudo apt update || exit 1 + + echo "Installing apt packages" + sudo apt install -y ${{ matrix.apt-dependencies }} || exit 1 - name: Create Build Environment shell: bash run: cmake -E make_directory "${{runner.workspace}}/build" @@ -85,23 +103,23 @@ jobs: - name: Build Application working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target $APP_NAME + run: cmake --build . --config $BUILD_TYPE --target $APP_NAME $CMAKE_BUILD_EXTRA - name: Build Domain Server working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target domain-server + run: cmake --build . --config $BUILD_TYPE --target domain-server $CMAKE_BUILD_EXTRA - name: Build Assignment Client working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target assignment-client + run: cmake --build . --config $BUILD_TYPE --target assignment-client $CMAKE_BUILD_EXTRA - name: Build Console working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target packaged-server-console + run: cmake --build . --config $BUILD_TYPE --target packaged-server-console $CMAKE_BUILD_EXTRA - name: Build Installer working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target package + run: cmake --build . --config $BUILD_TYPE --target package $CMAKE_BUILD_EXTRA - name: Output Installer Logs if: failure() && matrix.os == 'windows-latest' shell: bash @@ -112,33 +130,4 @@ jobs: working-directory: ${{runner.workspace}}/build env: GITHUB_CONTEXT: ${{ toJson(github) }} - ARTIFACT_PATTERN: ProjectAthena-Alpha-PR${{ github.event.number }}-*.exe run: python "$GITHUB_WORKSPACE\tools\ci-scripts\upload_to_publish_server.py" - - build_full_linux: - runs-on: ubuntu-16.04 - env: - JOB_NAME: build_full_linux - if: github.event.action != 'labeled' || github.event.label.name == 'rebuild' - steps: - - uses: actions/checkout@v1 - with: - submodules: true - fetch-depth: 1 - - name: Update apt repository index - run: sudo apt update - - name: Install apt packages - run: sudo apt install -y mesa-common-dev libegl1 libglvnd-dev libdouble-conversion1 libpulse0 python3-setuptools - - name: Install python modules - shell: bash - run: pip3 install boto3 distro PyGithub - - name: Create Build Environment - run: cmake -E make_directory ${{runner.workspace}}/build - - name: Configure CMake - working-directory: ${{runner.workspace}}/build - shell: bash - run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DVCPKG_BUILD_TYPE=release -DBUILD_TOOLS:BOOLEAN=FALSE - - name: - shell: bash - working-directory: ${{runner.workspace}}/build - run: cmake --build . -- -j3 From ee8ee9c6118343eeb86bcc9ef91b49da3a3ceab5 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 23 Apr 2020 09:48:09 +0200 Subject: [PATCH 069/105] disable build tools --- .github/workflows/pr_build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index b28e237f96..05f049fae6 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -51,6 +51,7 @@ jobs: echo ::set-env name=PYTHON_EXEC::python3 echo ::set-env name=INSTALLER_EXT::tgz echo ::set-env name=CMAKE_BUILD_EXTRA::"-- -j3" + echo ::set-env name=CMAKE_EXTRA::"-DBUILD_TOOLS:BOOLEAN=FALSE" fi # Mac build variables if [ "${{ matrix.os }}" = "macOS-latest" ]; then From 5375c341a634d98ce63400166336a8d5e99c6e6c Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 23 Apr 2020 11:10:56 +0200 Subject: [PATCH 070/105] fix upload script path --- .github/workflows/pr_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 05f049fae6..0a854f687b 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -131,4 +131,4 @@ jobs: working-directory: ${{runner.workspace}}/build env: GITHUB_CONTEXT: ${{ toJson(github) }} - run: python "$GITHUB_WORKSPACE\tools\ci-scripts\upload_to_publish_server.py" + run: python "$GITHUB_WORKSPACE/tools/ci-scripts/upload_to_publish_server.py" From 3105b7f7c6601ee8f96dd785ea1fceb1e98fa11a Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 23 Apr 2020 12:24:45 +0200 Subject: [PATCH 071/105] use PYTHON_EXEC for upload script to select the correct version of python --- .github/workflows/pr_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 0a854f687b..43709d02cf 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -131,4 +131,4 @@ jobs: working-directory: ${{runner.workspace}}/build env: GITHUB_CONTEXT: ${{ toJson(github) }} - run: python "$GITHUB_WORKSPACE/tools/ci-scripts/upload_to_publish_server.py" + run: $PYTHON_EXEC "$GITHUB_WORKSPACE/tools/ci-scripts/upload_to_publish_server.py" From 44cc1c14b405e5bdda59a62aecbbed5f98b7be41 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 23 Apr 2020 14:00:23 +0200 Subject: [PATCH 072/105] get multiple linux artifacts to check them out --- .github/workflows/pr_build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 43709d02cf..57d32741ca 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -49,7 +49,7 @@ jobs: # Linux build variables if [[ "${{ matrix.os }}" = "ubuntu-"* ]]; then echo ::set-env name=PYTHON_EXEC::python3 - echo ::set-env name=INSTALLER_EXT::tgz + echo ::set-env name=INSTALLER_EXT::* echo ::set-env name=CMAKE_BUILD_EXTRA::"-- -j3" echo ::set-env name=CMAKE_EXTRA::"-DBUILD_TOOLS:BOOLEAN=FALSE" fi From da6b59f3f2bad2c216311f3fd117f4f1952f9904 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 26 Apr 2020 21:54:05 +0000 Subject: [PATCH 073/105] Don't let Linux build of glm with clang-9 fail due to stray semicolon --- cmake/ports/glm/disable_warnings_as_error.patch | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cmake/ports/glm/disable_warnings_as_error.patch b/cmake/ports/glm/disable_warnings_as_error.patch index f87616b1ec..5dabaa6323 100644 --- a/cmake/ports/glm/disable_warnings_as_error.patch +++ b/cmake/ports/glm/disable_warnings_as_error.patch @@ -1,7 +1,16 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 756673a3..5fbc8906 100644 +index 756673a..9b3aa07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt +@@ -194,7 +194,7 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message("GLM: Clang - ${CMAKE_CXX_COMPILER_ID} compiler") + endif() + +- add_compile_options(-Werror -Weverything) ++ add_compile_options(-Weverything) + add_compile_options(-Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-c++11-long-long -Wno-padded -Wno-gnu-anonymous-struct -Wno-nested-anon-types) + add_compile_options(-Wno-undefined-reinterpret-cast -Wno-sign-conversion -Wno-unused-variable -Wno-missing-prototypes -Wno-unreachable-code -Wno-missing-variable-declarations -Wno-sign-compare -Wno-global-constructors -Wno-unused-macros -Wno-format-nonliteral) + @@ -216,7 +216,7 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") message("GLM: Visual C++ - ${CMAKE_CXX_COMPILER_ID} compiler") endif() From bbda0cc6d009ecf6d7576c33927186f8f5724ae6 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 27 Apr 2020 01:17:45 +0200 Subject: [PATCH 074/105] CR fixes --- hifi_qt.py | 2 +- hifi_vcpkg.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hifi_qt.py b/hifi_qt.py index 803c848f36..10708e4bc9 100644 --- a/hifi_qt.py +++ b/hifi_qt.py @@ -74,7 +74,7 @@ endif() self.qtUrl = self.assets_url + '/dependencies/vcpkg/qt5-install-5.12.6-ubuntu-19.10.tar.xz' elif u_major > 18 and ( u_major != 19 and u_minor != 4): print("We don't support " + distro.name(pretty=True) + " yet. Perhaps consider helping us out?") - raise Exception('YET UNSUPPORTED VERSION OF LINUX DISTRO!!!') + raise Exception('LINUX DISTRO IS NOT SUPPORTED YET!!!') else: print("Sorry, " + distro.name(pretty=True) + " is old and won't be officially supported. Please consider upgrading."); raise Exception('UNKNOWN LINUX DISTRO VERSION!!!') diff --git a/hifi_vcpkg.py b/hifi_vcpkg.py index 4d347a289a..569bd49545 100644 --- a/hifi_vcpkg.py +++ b/hifi_vcpkg.py @@ -83,7 +83,9 @@ endif() self.bootstrapEnv = os.environ.copy() self.buildEnv = os.environ.copy() self.prebuiltArchive = None - usePrebuilt = ('CI_BUILD' in os.environ) and os.environ["CI_BUILD"] == "Github" and (not self.noClean) + usePrebuilt = False + # usePrebuild Disabled, to re-enabled using the prebuilt archives for GitHub action builds uncomment the following line: + # usePrebuilt = ('CI_BUILD' in os.environ) and os.environ["CI_BUILD"] == "Github" and (not self.noClean) if 'Windows' == system: self.exe = os.path.join(self.path, 'vcpkg.exe') @@ -91,8 +93,8 @@ endif() self.vcpkgUrl = self.assets_url + '/dependencies/vcpkg/builds/vcpkg-win32-client.zip%3FversionId=tSFzbw01VkkVFeRQ6YuAY4dro2HxJR9U' self.vcpkgHash = 'a650db47a63ccdc9904b68ddd16af74772e7e78170b513ea8de5a3b47d032751a3b73dcc7526d88bcb500753ea3dd9880639ca842bb176e2bddb1710f9a58cd3' self.hostTriplet = 'x64-windows' - #if usePrebuilt: - # self.prebuiltArchive = "https://ipfs.io/ipfs/QmcBggttJQb1vYeyz29FXfaxnJ5c1HfZW72xNQepnENude/vcpkg-win32-a2623c6a-release.zip" + if usePrebuilt: + self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-win32.zip%3FversionId=3SF3mDC8dkQH1JP041m88xnYmWNzZflx" elif 'Darwin' == system: self.exe = os.path.join(self.path, 'vcpkg') self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '--allowAppleClang', '-disableMetrics' ] @@ -101,8 +103,8 @@ endif() self.hostTriplet = 'x64-osx' # Potential fix for a vcpkg build issue on OSX (see https://github.com/microsoft/vcpkg/issues/9029) self.bootstrapEnv['CXXFLAGS'] = '-D_CTERMID_H_' - #if usePrebuilt: - # self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-osx.tgz%3FversionId=6JrIMTdvpBF3MAsjA92BMkO79Psjzs6Z" + if usePrebuilt: + self.prebuiltArchive = self.assets_url + "/dependencies/vcpkg/builds/vcpkg-osx.tgz%3FversionId=6JrIMTdvpBF3MAsjA92BMkO79Psjzs6Z" else: self.exe = os.path.join(self.path, 'vcpkg') self.bootstrapCmds = [ os.path.join(self.path, 'bootstrap-vcpkg.sh'), '-disableMetrics' ] From 5e997d7b6001ca7a01b91f959b9dd5f2cb27c381 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 27 Apr 2020 20:38:23 +1200 Subject: [PATCH 075/105] Fix up Vircadia URLs --- interface/resources/qml/hifi/avatarapp/MessageBoxes.qml | 2 +- interface/src/avatar/MyAvatar.h | 8 ++++---- .../avatars-renderer/src/avatars-renderer/ScriptAvatar.h | 4 ++-- libraries/avatars/src/AvatarData.h | 4 ++-- libraries/avatars/src/ScriptAvatarData.h | 8 ++++---- libraries/entities/src/EntityItemProperties.cpp | 2 +- .../src/graphics-scripting/GraphicsScriptingInterface.h | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml index decb5e0807..ac09f14d9e 100644 --- a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml +++ b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml @@ -7,7 +7,7 @@ MessageBox { popup.onButton2Clicked = callback; popup.titleText = 'Specify Avatar URL' popup.bodyText = 'This will not overwrite your existing favorite if you are wearing one.
        ' + - '' + + '' + 'Learn to make a custom avatar by opening this link on your desktop.' + '' popup.inputText.visible = true; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0d018eb007..2a83ab69c1 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -654,7 +654,7 @@ public: *

        Note: When using pre-built animation data, it's critical that the joint orientation of the source animation and target * rig are equivalent, since the animation data applies absolute values onto the joints. If the orientations are different, * the avatar will move in unpredictable ways. For more information about avatar joint orientation standards, see - * Avatar Standards.

        + * Avatar Standards.

        * @function MyAvatar.overrideAnimation * @param {string} url - The URL to the animation file. Animation files may be in glTF or FBX format, but only need to * contain the avatar skeleton and animation data. glTF models may be in JSON or binary format (".gltf" or ".glb" URLs @@ -665,7 +665,7 @@ public: * @param {number} firstFrame - The frame to start the animation at. * @param {number} lastFrame - The frame to end the animation at. * @example
    - * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.vircadia.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreAnimation(); @@ -688,7 +688,7 @@ public: * @param {number} firstFrame - The frame to start the animation at. * @param {number} lastFrame - The frame to end the animation at. * @example - * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.vircadia.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideHandAnimation(isLeft, ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreHandAnimation(); @@ -705,7 +705,7 @@ public: * animation, this function has no effect.

    * @function MyAvatar.restoreAnimation * @example - * var ANIM_URL = "https://apidocs.projectathena.dev/models/ClapHands_Standing.fbx"; + * var ANIM_URL = "https://apidocs.vircadia.dev/models/ClapHands_Standing.fbx"; * MyAvatar.overrideAnimation(ANIM_URL, 30, true, 0, 53); * Script.setTimeout(function () { * MyAvatar.restoreAnimation(); diff --git a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h index b5fdad078e..0b89e9d59e 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h +++ b/libraries/avatars-renderer/src/avatars-renderer/ScriptAvatar.h @@ -87,7 +87,7 @@ public slots: /**jsdoc * Gets the default rotation of a joint in the avatar relative to its parent. *

    For information on the joint hierarchy used, see - * Avatar Standards.

    + * Avatar Standards.

    * @function ScriptAvatar.getDefaultJointRotation * @param {number} index - The joint index. * @returns {Quat} The default rotation of the joint if avatar data are available and the joint index is valid, otherwise @@ -99,7 +99,7 @@ public slots: * Gets the default translation of a joint in the avatar relative to its parent, in model coordinates. *

    Warning: These coordinates are not necessarily in meters.

    *

    For information on the joint hierarchy used, see - * Avatar Standards.

    + * Avatar Standards.

    * @function ScriptAvatar.getDefaultJointTranslation * @param {number} index - The joint index. * @returns {Vec3} The default translation of the joint (in model coordinates) if avatar data are available and the joint diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 2f595fab08..d6a4497ee7 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -1274,7 +1274,7 @@ public: * null to remove all attachments. * @deprecated This function is deprecated and will be removed. Use avatar entities instead. * @example - * var hatURL = "https://apidocs.projectathena.dev/models/cowboy-hat.fbx"; + * var hatURL = "https://apidocs.vircadia.dev/models/cowboy-hat.fbx"; * var attachments = MyAvatar.getAttachmentData(); * * for (var i = 0; i < attachments.length; i++) { @@ -1311,7 +1311,7 @@ public: * @deprecated This function is deprecated and will be removed. Use avatar entities instead. * @example * var attachment = { - * modelURL: "https://apidocs.projectathena.dev/models/cowboy-hat.fbx", + * modelURL: "https://apidocs.vircadia.dev/models/cowboy-hat.fbx", * jointName: "Head", * translation: {"x": 0, "y": 0.25, "z": 0}, * rotation: {"x": 0, "y": 0, "z": 0, "w": 1}, diff --git a/libraries/avatars/src/ScriptAvatarData.h b/libraries/avatars/src/ScriptAvatarData.h index bddbf5f887..290e8c178a 100644 --- a/libraries/avatars/src/ScriptAvatarData.h +++ b/libraries/avatars/src/ScriptAvatarData.h @@ -117,7 +117,7 @@ public: /**jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function ScriptAvatar.getJointRotation * @param {number} index - The index of the joint. * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data @@ -129,7 +129,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

    Warning: These coordinates are not necessarily in meters.

    *

    For information on the joint hierarchy used, see - * Avatar Standards.

    + * Avatar Standards.

    * @function ScriptAvatar.getJointTranslation * @param {number} index - The index of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} @@ -139,7 +139,7 @@ public: /**jsdoc * Gets the rotation of a joint relative to its parent. For information on the joint hierarchy used, see - * Avatar Standards. + * Avatar Standards. * @function ScriptAvatar.getJointRotation * @param {string} name - The name of the joint. * @returns {Quat} The rotation of the joint relative to its parent, or {@link Quat(0)|Quat.IDENTITY} if the avatar data @@ -151,7 +151,7 @@ public: * Gets the translation of a joint relative to its parent, in model coordinates. *

    Warning: These coordinates are not necessarily in meters.

    *

    For information on the joint hierarchy used, see - * Avatar Standards.

    + * Avatar Standards.

    * @function ScriptAvatar.getJointTranslation * @param {number} name - The name of the joint. * @returns {Vec3} The translation of the joint relative to its parent, in model coordinates, or {@link Vec3(0)|Vec3.ZERO} diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 8c20914ec7..c81cd2a70a 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -1036,7 +1036,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * type: "Model", * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -2 })), * rotation: MyAvatar.orientation, - * modelURL: "https://apidocs.projectathena.dev/models/cowboy-hat.fbx", + * modelURL: "https://apidocs.vircadia.dev/models/cowboy-hat.fbx", * dimensions: { x: 0.8569, y: 0.3960, z: 1.0744 }, * lifetime: 300 // Delete after 5 minutes. * }); diff --git a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h index ed3e207eaf..0f24ae8461 100644 --- a/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h +++ b/libraries/graphics-scripting/src/graphics-scripting/GraphicsScriptingInterface.h @@ -87,7 +87,7 @@ public slots: * type: "Model", * position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(Camera.orientation, { x: -0.5, y: 0, z: -3 })), * rotation: MyAvatar.orientation, - * modelURL: "https://apidocs.projectathena.dev/models/cowboy-hat.fbx", + * modelURL: "https://apidocs.vircadia.dev/models/cowboy-hat.fbx", * dimensions: { x: 0.8569, y: 0.3960, z: 1.0744 }, * lifetime: 300 // Delete after 5 minutes. * }); From e850e6fe226c45930085b95d7f56cda28b4796f7 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 27 Apr 2020 22:05:24 -0400 Subject: [PATCH 076/105] Adding field screenshare Adding field screenshare to avoid conflict --- .../html/js/entityProperties.js | 52 +++++++++++-------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 78ebe5b5cb..59755df122 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -67,11 +67,16 @@ const GROUPS = [ replaceID: "placeholder-property-id", multiDisplayMode: PROPERTY_MULTI_DISPLAY_MODE.COMMA_SEPARATED_VALUES, }, - { + /*{ label: "Description", type: "string", propertyID: "description", - }, + },*/ + { //THIS IS ONLY FOR THE TEST ########################################## + label: "Description", + type: "multipleZonesSelection", + propertyID: "description", + }, // END TEST ############################# { label: "Parent", type: "string", @@ -115,11 +120,6 @@ const GROUPS = [ lines: "Wireframe", }, propertyID: "primitiveMode", - }, - { - label: "Render With Zones", - type: "multipleZonesSelection", - propertyID: "renderWithZones", } ] }, @@ -580,6 +580,12 @@ const GROUPS = [ type: "dropdown", options: { inherit: "Inherit", crowd: "Crowd", hero: "Hero" }, propertyID: "avatarPriority", + }, + { + label: "Screen-share", + type: "dropdown", + options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, + propertyID: "screenshare", } ] }, @@ -1897,7 +1903,7 @@ function resetProperties() { } case 'multipleZonesSelection': { property.elInput.classList.remove('multi-diff'); - property.elInput.value = "[]"; + property.elInput.value = "[]"; //################################## PROBABLY SOMETHING TO ADJUST HERE! setZonesSelectionData(property.elInput, false); break; } @@ -3582,19 +3588,20 @@ function addZoneToZonesSelection(propertyId) { let selectedZones = JSON.parse(hiddenField.value); let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; if (!selectedZones.includes(zoneToAdd)) { - selectedZones.push(zoneToAdd); + selectedZones.push(zoneToAdd); } hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); - updateProperty(propertyName, selectedZones, false); + updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST + //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY } function removeZoneFromZonesSelection(propertyId, zoneId) { let hiddenField = document.getElementById(propertyId); if(JSON.stringify(hiddenField.value) === '"undefined"') { hiddenField.value = "[]"; - } + } let selectedZones = JSON.parse(hiddenField.value); let index = selectedZones.indexOf(zoneId); if (index > -1) { @@ -3603,7 +3610,8 @@ function removeZoneFromZonesSelection(propertyId, zoneId) { hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); - updateProperty(propertyName, selectedZones, false); + updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST + //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY } function displaySelectedZones(propertyId, isEditable) { @@ -3621,7 +3629,7 @@ function displaySelectedZones(propertyId, isEditable) { if (!isMultiple) { listedZoneInner += ""; } else { - listedZoneInner += ""; + listedZoneInner += ""; } } else { for ( i = 0; i < selectedZones.length; i++ ) { @@ -3637,10 +3645,9 @@ function displaySelectedZones(propertyId, isEditable) { } } if (isEditable) { - listedZoneInner += ""; + listedZoneInner += ""; } else { - listedZoneInner += ""; + listedZoneInner += ""; } } } @@ -3659,7 +3666,7 @@ function createZonesSelection(property, elProperty) { elProperty.className = "multipleZonesSelection"; let elInput = document.createElement('input'); elInput.setAttribute("id", elementID); - elInput.setAttribute("type", "hidden"); + elInput.setAttribute("type", "hidden"); // must be hidden ################################################################################# HEIL! ICITTE! elInput.className = "hiddenMultiZonesSelection"; let elZonesSelector = document.createElement('div'); @@ -3687,8 +3694,7 @@ function setZonesSelectionData(element, isEditable) { } zoneSelector += ""; } - zoneSelector += " "; - zoneSelector += ""; + zoneSelector += " "; zoneSelector += "
    "; zoneSelectorContainer.innerHTML = zoneSelector; displaySelectedZones(element.id, isEditable); @@ -4102,14 +4108,18 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { break; } case 'multipleZonesSelection': { - property.elInput.value = JSON.stringify(propertyValue); + if (propertyValue == ""){ //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = "[]"; //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + } else { //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = propertyValue; //JSON.stringify(propertyValue); //##### TO CHECK depending what type the value is.. expecting an array so it willbe manage as a string. + } //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { setZonesSelectionData(property.elInput, false); } else { setZonesSelectionData(property.elInput, true); } break; - } + } case 'icon': { property.elSpan.innerHTML = propertyData.icons[propertyValue]; property.elSpan.style.display = "inline-block"; From cc6fc40b0eaf5f5c267e189557bc6c1a77b89fd7 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 27 Apr 2020 22:19:04 -0400 Subject: [PATCH 077/105] to avoid regression. --- .../html/js/entityProperties.js | 225 +++++++++++++++++- 1 file changed, 218 insertions(+), 7 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 0d15b8ece5..59755df122 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -2,7 +2,7 @@ // // Created by Ryan Huffman on 13 Nov 2014 // Copyright 2014 High Fidelity, Inc. -// Copyright 2020 Project Athena contributors. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -67,11 +67,16 @@ const GROUPS = [ replaceID: "placeholder-property-id", multiDisplayMode: PROPERTY_MULTI_DISPLAY_MODE.COMMA_SEPARATED_VALUES, }, - { + /*{ label: "Description", type: "string", propertyID: "description", - }, + },*/ + { //THIS IS ONLY FOR THE TEST ########################################## + label: "Description", + type: "multipleZonesSelection", + propertyID: "description", + }, // END TEST ############################# { label: "Parent", type: "string", @@ -575,6 +580,12 @@ const GROUPS = [ type: "dropdown", options: { inherit: "Inherit", crowd: "Crowd", hero: "Hero" }, propertyID: "avatarPriority", + }, + { + label: "Screen-share", + type: "dropdown", + options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, + propertyID: "screenshare", } ] }, @@ -1669,7 +1680,6 @@ const GROUPS_PER_TYPE = { ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], - PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], PolyVox: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Grid: [ 'base', 'grid', 'spatial', 'behavior', 'scripts', 'physics' ], Multiple: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], @@ -1739,7 +1749,7 @@ let selectedEntityIDs = new Set(); let currentSelections = []; let createAppTooltip = new CreateAppTooltip(); let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL; - +let zonesList = []; function createElementFromHTML(htmlString) { let elTemplate = document.createElement('template'); @@ -1765,6 +1775,8 @@ function getPropertyInputElement(propertyID) { case 'textarea': case 'texture': return property.elInput; + case 'multipleZonesSelection': + return property.elInput; case 'number-draggable': return property.elNumber.elInput; case 'rect': @@ -1805,6 +1817,7 @@ function disableChildren(el, selector) { function enableProperties() { enableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); enableChildren(document, ".colpick"); + enableAllMultipleZoneSelector(); } function disableProperties() { @@ -1813,6 +1826,7 @@ function disableProperties() { for (let pickKey in colorPickers) { colorPickers[pickKey].colpickHide(); } + disableAllMultipleZoneSelector(); } function showPropertyElement(propertyID, show) { @@ -1887,6 +1901,12 @@ function resetProperties() { setTextareaScrolling(property.elInput); break; } + case 'multipleZonesSelection': { + property.elInput.classList.remove('multi-diff'); + property.elInput.value = "[]"; //################################## PROBABLY SOMETHING TO ADJUST HERE! + setZonesSelectionData(property.elInput, false); + break; + } case 'icon': { property.elSpan.style.display = "none"; break; @@ -3036,6 +3056,10 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI property.elInput = createTextareaProperty(property, elProperty); break; } + case 'multipleZonesSelection': { + property.elInput = createZonesSelection(property, elProperty); + break; + } case 'icon': { property.elSpan = createIconProperty(property, elProperty); break; @@ -3528,6 +3552,175 @@ function setTextareaScrolling(element) { element.setAttribute("scrolling", isScrolling ? "true" : "false"); } +/** + * ZONE SELECTOR FUNCTIONS + */ + +function enableAllMultipleZoneSelector() { + let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); + let i, propId; + for ( i = 0; i < allMultiZoneSelectors.length; i++ ) { + propId = allMultiZoneSelectors[i].id; + displaySelectedZones(propId, true); + } +} + +function disableAllMultipleZoneSelector() { + let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); + let i, propId; + for ( i = 0; i < allMultiZoneSelectors.length; i++ ) { + propId = allMultiZoneSelectors[i].id; + displaySelectedZones(propId, false); + } +} + +function requestZoneList() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "zoneListRequest" + })); +} + +function addZoneToZonesSelection(propertyId) { + let hiddenField = document.getElementById(propertyId); + if(JSON.stringify(hiddenField.value) === '"undefined"') { + hiddenField.value = "[]"; + } + let selectedZones = JSON.parse(hiddenField.value); + let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; + if (!selectedZones.includes(zoneToAdd)) { + selectedZones.push(zoneToAdd); + } + hiddenField.value = JSON.stringify(selectedZones); + displaySelectedZones(propertyId, true); + let propertyName = propertyId.replace("property-", ""); + updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST + //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY +} + +function removeZoneFromZonesSelection(propertyId, zoneId) { + let hiddenField = document.getElementById(propertyId); + if(JSON.stringify(hiddenField.value) === '"undefined"') { + hiddenField.value = "[]"; + } + let selectedZones = JSON.parse(hiddenField.value); + let index = selectedZones.indexOf(zoneId); + if (index > -1) { + selectedZones.splice(index, 1); + } + hiddenField.value = JSON.stringify(selectedZones); + displaySelectedZones(propertyId, true); + let propertyName = propertyId.replace("property-", ""); + updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST + //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY +} + +function displaySelectedZones(propertyId, isEditable) { + let i,j, name, listedZoneInner, hiddenData, isMultiple; + hiddenData = document.getElementById(propertyId).value; + if (JSON.stringify(hiddenData) === '"undefined"') { + isMultiple = true; + hiddenData = "[]"; + } else { + isMultiple = false; + } + let selectedZones = JSON.parse(hiddenData); + listedZoneInner = "
    + + + - From 5fad30dc179d1fb193e1526ad71b47522ac70440 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 18 Mar 2020 19:12:48 -0400 Subject: [PATCH 030/105] Added 5 missing properties Added 5 missing properties On "TEXT" entity: - font - textEffect - textEffectThickness - textEffectColor On "WEB" entity: - inputMode --- .../create/assets/data/createAppTooltips.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 4b32bbf6db..9ea7ad886b 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -26,6 +26,18 @@ "lineHeight": { "tooltip": "The height of each line of text. This determines the size of the text." }, + "font": { + "tooltip": "The font to render the text. Supported values: \"Courier\", \"Inconsolata\", \"Roboto\", \"Timeless\", or a URL to a .sdff file." + }, + "textEffect": { + "tooltip": "The effect that is applied to the text." + }, + "textEffectColor": { + "tooltip": "The color of the text effect." + }, + "textEffectThickness": { + "tooltip": "The magnitude of the text effect." + }, "textBillboardMode": { "tooltip": "If enabled, determines how the entity will face the camera.", "jsPropertyName": "billboardMode" @@ -225,6 +237,9 @@ "tooltip": "If enabled, determines how the entity will face the camera.", "jsPropertyName": "billboardMode" }, + "inputMode": { + "tooltip": "The user input mode to use." + }, "showKeyboardFocusHighlight": { "tooltip": "If enabled, highlights when it has keyboard focus." }, From 1b53014030c17f9e095d9dca6bb3f20587142bf6 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 18 Mar 2020 19:39:18 -0400 Subject: [PATCH 031/105] Added 5 missing properties Added 5 missing properties On "TEXT" entity: - font - textEffect - textEffectThickness - textEffectColor On "WEB" entity: - inputMode Added "physics" section to "MATERIAL" entity. Allowed negative values to be entered on the following light intensity properties: - ZONE: keyLight intensity - ZONE: ambientLight intensity - LIGHT: intensity --- .../html/js/entityProperties.js | 48 +++++++++++++++++-- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 63aa39e552..d5e29ac165 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1,7 +1,6 @@ // entityProperties.js // // Created by Ryan Huffman on 13 Nov 2014 -// Modified by David Back on 19 Oct 2018 // Copyright 2014 High Fidelity, Inc. // Copyright 2020 Project Athena contributors. // @@ -195,6 +194,36 @@ const GROUPS = [ unit: "m", propertyID: "lineHeight", }, + { + label: "Font", + type: "string", + propertyID: "font", + }, + { + label: "Effect", + type: "dropdown", + options: { + none: "None", + outline: "Outline", + outlineFill: "Outline with fill", + shadow: "Shadow" + }, + propertyID: "textEffect", + }, + { + label: "Effect Color", + type: "color", + propertyID: "textEffectColor", + }, + { + label: "Effect Thickness", + type: "number-draggable", + min: 0.0, + max: 0.5, + step: 0.01, + decimals: 2, + propertyID: "textEffectThickness", + }, { label: "Billboard Mode", type: "dropdown", @@ -292,7 +321,7 @@ const GROUPS = [ { label: "Light Intensity", type: "number-draggable", - min: 0, + min: -40, max: 40, step: 0.01, decimals: 2, @@ -384,7 +413,7 @@ const GROUPS = [ { label: "Ambient Intensity", type: "number-draggable", - min: 0, + min: -200, max: 200, step: 0.1, decimals: 2, @@ -736,6 +765,15 @@ const GROUPS = [ propertyID: "webBillboardMode", propertyName: "billboardMode", // actual entity property name }, + { + label: "Input Mode", + type: "dropdown", + options: { + touch: "Touch events", + mouse: "Mouse events" + }, + propertyID: "inputMode", + }, { label: "Focus Highlight", type: "bool", @@ -762,7 +800,7 @@ const GROUPS = [ { label: "Intensity", type: "number-draggable", - min: 0, + min: -1000, max: 10000, step: 0.1, decimals: 2, @@ -1627,7 +1665,7 @@ const GROUPS_PER_TYPE = { Image: [ 'base', 'image', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Web: [ 'base', 'web', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Light: [ 'base', 'light', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], - Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts' ], + Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts', 'physics' ], ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], From 1f72e995d76369b9052383180f8590f7f69a22ea Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Thu, 19 Mar 2020 01:00:21 -0400 Subject: [PATCH 032/105] Fix the "outline fill" of the textEffect property Fix the "outline fill" of the textEffect property The value to used was "outline fill" and not "outlineFill" as the JS doc pretends. Issue #221 has been open to fix the JSdoc. The usage of a space separated value has been imagined to preserve the backward compatibility of the existing script. in order to support a list (space separated) of effects to apply instead of a single effect as today. --- .../system/create/entityProperties/html/js/entityProperties.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index d5e29ac165..8f3fdc53f2 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -205,7 +205,7 @@ const GROUPS = [ options: { none: "None", outline: "Outline", - outlineFill: "Outline with fill", + "outline fill": "Outline with fill", shadow: "Shadow" }, propertyID: "textEffect", From c86bf3dd7dfc906eaa5651a2d0e4f20dd870251f Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Fri, 20 Mar 2020 23:01:28 -0400 Subject: [PATCH 033/105] New tooltips for the alpha properties. This fix replaces the text of the tooltips of all the "alpha" properties by a more informative text for profane users. --- .../create/assets/data/createAppTooltips.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 9ea7ad886b..68b7cfe59a 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -3,10 +3,10 @@ "tooltip": "The shape of this entity's geometry." }, "color": { - "tooltip": "The RGB value of this entity." + "tooltip": "The color of this entity." }, "shapeAlpha": { - "tooltip": "The alpha of this entity." + "tooltip": "Set the opacity of the entity between 0.0 fully transparent and 1.0 completely opaque." }, "text": { "tooltip": "The text to display on the entity." @@ -15,13 +15,13 @@ "tooltip": "The color of the text." }, "textAlpha": { - "tooltip": "The alpha of the text." + "tooltip": "Set the opacity of the text between 0.0 fully transparent and 1.0 completely opaque." }, "backgroundColor": { "tooltip": "The color of the background." }, "backgroundAlpha": { - "tooltip": "The alpha of the background." + "tooltip": "Set the opacity of the background between 0.0 fully transparent and 1.0 completely opaque." }, "lineHeight": { "tooltip": "The height of each line of text. This determines the size of the text." @@ -212,7 +212,7 @@ "jsPropertyName": "color" }, "imageAlpha": { - "tooltip": "The alpha of the image." + "tooltip": "Set the opacity of the image between 0.0 fully transparent and 1.0 completely opaque." }, "emissive": { "tooltip": "If enabled, the image will display at full brightness." @@ -319,20 +319,20 @@ "tooltip": "The spread in color that each particle is given, resulting in a variety of colors." }, "particleAlphaTriple": { - "tooltip": "The alpha of each particle.", + "tooltip": "Set the opacity of the each particle between 0.0 fully transparent and 1.0 completely opaque.", "jsPropertyName": "alpha" }, "alpha": { - "tooltip": "The alpha of each particle." + "tooltip": "Set the opacity of the each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaStart": { - "tooltip": "The start alpha of each particle." + "tooltip": "Set the initial opacity level of the each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaFinish": { - "tooltip": "The finish alpha of each particle." + "tooltip": "Set the final opacity level of the each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaSpread": { - "tooltip": "The spread in alpha that each particle is given, resulting in a variety of alphas." + "tooltip": "The spread in opacity that each particle is given, resulting in a variety of opacity levels." }, "emitAcceleration": { "tooltip": "The acceleration that is applied to each particle during its lifetime." @@ -602,7 +602,7 @@ "tooltip": "The tint of the web entity." }, "webAlpha": { - "tooltip": "The alpha of the web entity." + "tooltip": "Set the opacity of the web entity between 0.0 fully transparent and 1.0 completely opaque." }, "maxFPS": { "tooltip": "The FPS at which to render the web entity. Higher values will have a performance impact." From 90ef2ee0700938c8475bbc042405bd821b0ddcfa Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 22 Mar 2020 16:25:29 -0400 Subject: [PATCH 034/105] Replace Label "Allow Transition" Replace Label "Allow Transition" for "Allow Translation". --- .../system/create/entityProperties/html/js/entityProperties.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 8f3fdc53f2..0d15b8ece5 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -620,7 +620,7 @@ const GROUPS = [ propertyID: "animation.loop", }, { - label: "Allow Transition", + label: "Allow Translation", type: "bool", propertyID: "animation.allowTranslation", }, From 4b4a1bd8c01247d43665ed6728aad068d86bba5c Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Fri, 3 Apr 2020 23:23:20 -0400 Subject: [PATCH 035/105] Icons for "Multiple Zones Selector" Renderer 2 new icon added for the "Multiple Zones Selector" Renderer (required for the new property "renderWithZones" for PR#78): "Add" and "Remove". --- scripts/system/html/css/img/add_icon.png | Bin 0 -> 725 bytes scripts/system/html/css/img/remove_icon.png | Bin 0 -> 827 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 scripts/system/html/css/img/add_icon.png create mode 100644 scripts/system/html/css/img/remove_icon.png diff --git a/scripts/system/html/css/img/add_icon.png b/scripts/system/html/css/img/add_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f60e5561f2404416da3c61b33459a50011237795 GIT binary patch literal 725 zcmWlQeN2pT0LQ=2bI-liUH9nXlGdKyw&aS|sf*O_(yL^rGRLG-M)Q(dHHYMRDqLg9 z+eQ+Zmm6lgv1zmvS8Gd?@dq*EiA*!@$X4`X_s8e2&*#%*UYDiz3GxA;&dE;C2cYw! zkOBA@{rV~ZWkvR;D!^Ckg+gmvAOL2kDbEBrn`{5AKMQ~>&CbsQ4n_ie128oQ@ZW%% zWx%)5qjAXG8!*&#-tx&3j+hb&pDV3gQ52u9{aB)57{u%)o~pE4A!cX$Xsp0!+^#I;+n zY5i*A$b01|81{KZDOcXFb^cViPn$y7LqZ@ZCcZ1gp5!UBhK1d0F=?Z^K`X8gpf%c| zB%z;ZmT=Dwdm?fIKa$b=+HHcIz)9j2s%fd%K&C_N3p+}AoCKjtzz{Y*XjWZ|q5q%9PiUF8^IZ1VNl>FC)Adu3n==AjLQxfA9li#~Rw zX-DTu_Ljf9FOLT;9ZcY6v&g57hS~jL^<|0PG?j84ceFK?^TBGCtTk^;^sksnrE9AZ zeXE;h*t;h&f3nCH@cWwQfZI`|at#s{kF;2RoVO|4BgQmC!3o2Ky?nS>WexU+tY8K1=bPcLmMhgWuaqV~FgQvLh=d9(nL9Le+Q=&0ywoy;9q;t)) zA@kBllyixLrAroV!Z literal 0 HcmV?d00001 diff --git a/scripts/system/html/css/img/remove_icon.png b/scripts/system/html/css/img/remove_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7a34bd0304896700a1ae1999fa2fe784a1fb93bd GIT binary patch literal 827 zcmV-B1H}A^P)z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRZ;u}MThRCwBA{Qv(y1FZl+05LJp5C8-a3yd*!>Qrp< zVnFNx#125L4#Yx0{1b>j0P!Ip-T=hs&^2XeXM<^g0K(_;I3PX`#0!Bq3aa)d5WfUs zDIl%|;*0>tq^{1zIPX+X@3#ZZuoU7@}`2KB8eC_Z5d z00IcvaBm=10OEQez7G`xrIeY_I6yaeClI#-F$Yv^HW1%NHXI;;kPQbJ^c{#dB8e@9 z8eRm%Jy0=FL-k7l@sp z=^PY4m(Y9!N-dvZ9Do2qHe4ErPhtt%e?S}wO@5&8e-Ff#&@_(@-a#`N7ytwi6I$|O z#gQWHp}_%C!w1b^*Z?cCnE(NVZ1@#u7DrE>c0jxt8blyV`hmC#nz7K;$^tPDi~|rr z$iV`N{Td*aLrUL{K)fA@pF&g9O=!?@A*G5UsE=SN?k~(hfB-_ac?*t)ZkfAd03gP3B(al$AAGq03o{^AwbA6rj|Z00G2;!$pUo$u19Ch_wRo zH)yH=6=Iw~{0E5FLkqi$*bD&(AVykN&;S8M(+V0OzyQ))ga|16d?o+@002ovPDHLk FV1l|4EUW+k literal 0 HcmV?d00001 From 0338d8a9f494c60e17803c1a1eabc0d076153532 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Fri, 3 Apr 2020 23:27:01 -0400 Subject: [PATCH 036/105] New classes for the "Multiple Zones Selector" Renderer Added: New CSS classes for the "Multiple Zones Selector" Renderer (Required for the new property "renderWithZones" for PR#78) --- scripts/system/html/css/edit-style.css | 3618 ++++++++++++------------ 1 file changed, 1822 insertions(+), 1796 deletions(-) diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 470e57ad6d..4aea29de38 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1,1796 +1,1822 @@ -/* -// edit-style.css -// -// Created by Ryan Huffman on 13 Nov 2014 -// Copyright 2014 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 -*/ - -@font-face { - font-family: Raleway-Regular; - src: url(../../../../resources/fonts/Raleway-Regular.ttf), /* Windows production */ - url(../../../../fonts/Raleway-Regular.ttf), /* OSX production */ - url(../../../../interface/resources/fonts/Raleway-Regular.ttf), /* Development, running script in /HiFi/examples */ - url(../fonts/Raleway-Regular.ttf); /* Marketplace script */ -} - -@font-face { - font-family: Raleway-Light; - src: url(../../../../resources/fonts/Raleway-Light.ttf), - url(../../../../fonts/Raleway-Light.ttf), - url(../../../../interface/resources/fonts/Raleway-Light.ttf), - url(../fonts/Raleway-Light.ttf); -} - -@font-face { - font-family: Raleway-Bold; - src: url(../../../../resources/fonts/Raleway-Bold.ttf), - url(../../../../fonts/Raleway-Bold.ttf), - url(../../../../interface/resources/fonts/Raleway-Bold.ttf), - url(../fonts/Raleway-Bold.ttf); -} - -@font-face { - font-family: Raleway-SemiBold; - src: url(../../../../resources/fonts/Raleway-SemiBold.ttf), - url(../../../../fonts/Raleway-SemiBold.ttf), - url(../../../../interface/resources/fonts/Raleway-SemiBold.ttf), - url(../fonts/Raleway-SemiBold.ttf); -} - -@font-face { - font-family: FiraSans-SemiBold; - src: url(../../../../resources/fonts/FiraSans-SemiBold.ttf), - url(../../../../fonts/FiraSans-SemiBold.ttf), - url(../../../../interface/resources/fonts/FiraSans-SemiBold.ttf), - url(../fonts/FiraSans-SemiBold.ttf); -} - -@font-face { - font-family: AnonymousPro-Regular; - src: url(../../../../resources/fonts/AnonymousPro-Regular.ttf), - url(../../../../fonts/AnonymousPro-Regular.ttf), - url(../../../../interface/resources/fonts/AnonymousPro-Regular.ttf), - url(../fonts/AnonymousPro-Regular.ttf); -} - -@font-face { - font-family: HiFi-Glyphs; - src: url(../../../../resources/fonts/hifi-glyphs.ttf), - url(../../../../fonts/hifi-glyphs.ttf), - url(../../../../interface/resources/fonts/hifi-glyphs.ttf), - url(../fonts/hifi-glyphs.ttf); -} - -* { - margin: 0; - padding: 0; -} - -body { - - color: #afafaf; - background-color: #404040; - font-family: Raleway-Regular; - font-size: 12px; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - - overflow-x: hidden; - overflow-y: auto; -} - -table { - font-family: FiraSans-SemiBold; - font-size: 15px; - color: #afafaf; - border-collapse: collapse; - width: 100%; - border: 2px solid #575757; - border-radius: 7px; -} - -thead { - font-family: Raleway-Regular; - font-size: 12px; - text-transform: uppercase; - background-color: #1c1c1c; - padding: 1px 0; - border-bottom: 1px solid #575757; - width: 100%; -} - -tbody { - width: 100%; - display: block; -} - -tfoot { - font-family: Raleway-Light; - font-size: 13px; - background-color: #1c1c1c; - border-top: 1px solid #575757; - width: 100%; -} - -tfoot tr { - background-color: #1c1cff; -} - -thead tr { - height: 26px; /* 28px with thead padding */ -} - -thead th { - height: 26px; - background-color: #1c1c1c; - border-right: 1px solid #575757; -} - -thead th:last-child { - border: none; -} - -tbody td { - height: 26px; -} - -tfoot td { - height: 18px; - width: 100%; - background-color: #1c1c1c; - margin-left: 12px; -} - -tr { - width: 100%; - cursor: pointer; -} - -tr:nth-child(odd) { - background-color: #2e2e2e; -} - -tr:nth-child(even) { - background-color: #1c1c1c; -} - -tr:focus { - outline: none; -} - -tr.selected { - color: #000000; - background-color: #00b4ef; -} - -tr.selected + tr.selected { - border-top: 1px solid #2e2e2e; -} - -th { - text-align: center; - word-wrap: nowrap; - white-space: nowrap; - padding-left: 12px; - padding-right: 12px; -} - -td { - overflow: hidden; - text-overflow: clip; - white-space: nowrap; - word-wrap: nowrap; - padding-left: 12px; - padding-right: 12px; -} - -td.hidden { - padding-left: 0; - padding-right: 0; -} - -td.url { - white-space: nowrap; - overflow: hidden; -} - - -input[type="text"], input[type="search"], input[type="number"], textarea { - margin: 0; - padding: 0 12px; - color: #afafaf; - background-color: #252525; - border: none; - font-family: FiraSans-SemiBold; - font-size: 15px; -} - -textarea { - font-family: AnonymousPro-Regular; - font-size: 16px; - padding-top: 5px; - padding-bottom: 5px; - min-height: 64px; - width: 100%; - resize: vertical; -} - -input::-webkit-input-placeholder { - font-style: italic; -} - -input:focus, textarea:focus, button:focus { - color: #fff; - background-color: #000; - outline: 1px solid #00b4ef; - outline-offset: -1px; -} - -input::selection, textarea::selection { - color: #000000; - background-color: #00b4ef; -} - -input.search { - border-radius: 14px; -} - -input.search:focus { - outline: none; - box-sizing: border-box; - height: 26px; - margin-top: 1px; - margin-bottom: 1px; - box-shadow: 0 0 0 1px #00b4ef; -} - -input:disabled, textarea:disabled, .draggable-number.text[disabled="disabled"] { - background-color: #383838; - color: #afafaf; -} - -input[type="text"] { - height: 28px; - width: 100%; -} - -input.multi-diff:not(:focus) + span.multi-diff, -textarea.multi-diff:not(:focus) + span.multi-diff, -.draggable-number.multi-diff>input:not(:focus)+span.multi-diff, -dl>dt.multi-diff:not(:focus) + span.multi-diff { - visibility: visible; - position: absolute; - display: inline-block; - z-index: 2; - top: 7.5px; - left: 20px; - max-width: 50px; - min-width: 10px; - width: 50%; - height: 13px; - background-image: linear-gradient(transparent 0%, transparent 10%, #afafaf 10%, #afafaf 20%, transparent 20%, transparent 45%, #afafaf 45%, #afafaf 55%, transparent 55%, transparent 80%, #afafaf 80%, #afafaf 90%, transparent 90%, transparent 100%); - background-repeat: no-repeat; - pointer-events: none; -} - -input.multi-diff:not(:focus)::-webkit-input-placeholder, input.multi-diff:not(:focus) { - color: transparent; -} - -.draggable-number.multi-diff .text { - color: transparent; -} - -.dropdown > span.multi-diff { - top: 5px; - left: 10px; -} - -.text, .url, .texture, .textarea { - position: relative; -} - -input[type="search"] { - height: 28px; - width: 100%; -} -input[type="search"]::-webkit-search-cancel-button { - -webkit-appearance: none; - height: 20px; - width: 20px; - background-image: url('data:image/png;base64,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') -} - -input[type="number"] { - position: relative; - height: 28px; - width: 124px; -} -input[type=number] { - padding-right: 3px; -} -input[type=number]::-webkit-inner-spin-button { - opacity: 1.0; - display: block; - position: relative; - width: 10px; - height: 90%; - overflow: hidden; - font-family: HiFi-Glyphs; - font-size: 32px; - color: #afafaf; - cursor: pointer; - background-color: #000000; -} -input[type=number]::-webkit-inner-spin-button:before, -input[type=number]::-webkit-inner-spin-button:after { - position:absolute; - left: -19px; - line-height: 8px; - text-align: center; -} -input[type=number]::-webkit-inner-spin-button:before { - content: "6"; - top: 4px; -} -input[type=number]::-webkit-inner-spin-button:after { - content: "5"; - bottom: 4px; -} - -input[type=number].hover-up::-webkit-inner-spin-button:before, -input[type=number].hover-down::-webkit-inner-spin-button:after { - color: #ffffff; -} - -input[type=range] { - -webkit-appearance: none; - background: #2e2e2e; - height: 1.8rem; - border-radius: 1rem; -} -input[type=range]::-webkit-slider-thumb { - -webkit-appearance:none; - width: 0.6rem; - height: 1.8rem; - padding:0; - margin: 0; - background-color: #696969; - border-radius: 1rem; -} -input[type=range]::-webkit-slider-thumb:hover { - background-color: white; -} -input[type=range]:focus { - outline: none; -} - -input.no-spin::-webkit-outer-spin-button, -input.no-spin::-webkit-inner-spin-button { - display: none; - -webkit-appearance: none; - margin: 0; /* <-- Apparently some margin are still there even though it's hidden */ - padding-right: 12px; -} - -input[type=button], button.hifi-edit-button { - font-family: Raleway-Bold; - font-size: 13px; - text-transform: uppercase; - vertical-align: top; - height: 28px; - min-width: 120px; - padding: 0 18px; - margin-right: 6px; - border-radius: 5px; - border: none; - color: #fff; - background-color: #000; - background: linear-gradient(#343434 20%, #000 100%); - cursor: pointer; -} - -input[type=button].glyph, button.hifi-edit-button.glyph { - font-family: HiFi-Glyphs; - font-size: 20px; - text-transform: none; - min-width: 32px; - padding: 0; -} - -input[type=button].red, button.hifi-edit-button.red { - color: #fff; - background-color: #94132e; - background: linear-gradient(#d42043 20%, #94132e 100%); -} -input[type=button].blue, button.hifi-edit-button.blue { - color: #fff; - background-color: #1080b8; - background: linear-gradient(#00b4ef 20%, #1080b8 100%); -} -input[type=button].white, button.hifi-edit-button.white { - color: #121212; - background-color: #afafaf; - background: linear-gradient(#fff 20%, #afafaf 100%); -} - -input[type=button]:enabled:hover, button.hifi-edit-button:enabled:hover { - background: linear-gradient(#000, #000); - border: none; -} -input[type=button].red:enabled:hover, button.hifi-edit-button.red:enabled:hover { - background: linear-gradient(#d42043, #d42043); - border: none; -} -input[type=button].blue:enabled:hover, button.hifi-edit-button.blue:enabled:hover { - background: linear-gradient(#00b4ef, #00b4ef); - border: none; -} -input[type=button].white:enabled:hover, button.hifi-edit-button.white:enabled:hover { - background: linear-gradient(#fff, #fff); - border: none; -} - -input[type=button]:active, button.hifi-edit-button:active { - background: linear-gradient(#343434, #343434); -} -input[type=button].red:active, button.hifi-edit-button.red:active { - background: linear-gradient(#94132e, #94132e); -} -input[type=button].blue:active, button.hifi-edit-button.blue:active { - background: linear-gradient(#1080b8, #1080b8); -} -input[type=button].white:active, button.hifi-edit-button.white:active { - background: linear-gradient(#afafaf, #afafaf); -} - -input[type=button]:disabled, button.hifi-edit-button:disabled { - color: #252525; - background: linear-gradient(#575757 20%, #252525 100%); -} - -input[type=button][pressed=pressed], button.hifi-edit-button[pressed=pressed] { - color: #00b4ef; -} - -input[type=checkbox] { - display: none; -} -input[type=checkbox] + label { - padding-left: 24px; - background-repeat: no-repeat; - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACpSURBVDhPY2xoaGD68+dPMSMjY9L////VgTQjAw4AlH8PxLOPHj1azWxjY1MBVNsBFBfBpwkEgNKcQGwtJyfHyATkF0KEiQdAzYlMQEIUyicFyDD9+/ePgRxMvsb///4zkIOZ/v0HmkAGHginYjGNGAzS+BpdkAj8mun/3//92DyPD//993cG88nTJ4+Zm5p/BSZeJYb/DEJADEzNOPF7hn8Mk69cvVIPAHN5pyfo70F5AAAAAElFTkSuQmCC); - cursor: pointer; -} -input[type=checkbox]:enabled + label:hover { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAClSURBVDhPY2hoaGD6//9/6b9//64D8T8gGycASr/7+/dv5/79+1kYgIxKqDjRAKiniRFIv2JgYBAFYlLAE0aQ66AckgDjjx8/yNP44cMH8jS+fPmSPI0PHz4kT+PNmzfJ03jp0iXyNJ46dYo8jYcPHyYnAbxm+vnzZz8wLhlIwd+/f5/BrKSkdExCQuLrnz9/lIBpUAiIQekXF34PTGmTT548WQ8AokXg+rhVtPYAAAAASUVORK5CYII=); -} -input[type=checkbox]:checked + label { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFLSURBVDhPjZK9SgNBFIXvbCaQRDQq7mIhQRPBRisJKcwLWOobaCsExEaxcEEQe0trGysfwg0EwWoDsbFIJUaIBJOwus547saNP3FlPzgzzJxzL5edFbZtG77v7wkhtrXWS9gFRQC/DZ07jnOYKJfL+8ie4n7mvyIGdhpay+VyQuK8y5dPZoHuVtbpZcLi4wjJ1x4t316R9dDgBlsSi8mGu7pJjyJFzVaH+r7iqyHSELSQzVADjS0UgjlDKUUsLzVO98+9kSLGV5qaHXhjU0GWNSxk3hCIwnsfeMNCjTArLmHeUBodoLiE+R+jxuHPUZP4elGE3teonx2S/Q7lJzOUlkYQ+A4/xzyegzNhXmJpwTMXry9IFjcoa84O0r+QXpcK1cugCLREZadyoA19Ergxwf96nKjd1KqlYqmLQ540TUNwItUmRWdu3T36AODjwgpY9xqqAAAAAElFTkSuQmCC); -} -input[type=checkbox]:checked + label:hover { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEySURBVDhPnZLPSsNAEMa/XVPBCE0RhNy0OarP4Av4AD6JB0GwVBA8efBBxHsgh4CQswcRoUIpiIpVAm3zZ5M4szFSbQPBH3xkJvNNZskOer2eLIriKM/ze1JOcS1UHmdZduF5ngEKjr/fN4Z6+oKerwA2gxC4HAFPEWVLsAzgZAvYt3Q6Enw6jg7uBAaTFMNwhpnKdbXCkAJdy8ROu4XrXW2HTJIErHcFDD6nC02Mom8PwymeE2gvS0ZRBBaTlsOXEmdlrfLLOI7Bakrl/zWxCT8T/904f9QW/b06qtrCUdtFCqdjYs2Q2jAPX8c2XQd7Kr/wfV8vwIPs4Ga1ixe5Xrr/YFLTYfKIvWzM6ZtwXZdX7lxXG0L+sxXHcW5t254opRzawQ0S72+dPmjTroIgOP0CQSMt5LDn1T8AAAAASUVORK5CYII=); -} -input.multi-diff[type=checkbox] + label { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFbSURBVDhPY2xoaGD68+dPMSMjY9L////VgTQjAw4AlH8PxLOPHj1azWxjY1MBVNsBFBfBpwkEgNKcQGwtJyfHyALkF4IE34gqM9zU9WT4wicG4mIA1l/fGIyOL2EQeP8EZEAiC5AQBUlcMQ5ieMXIwfDo9SeG73/+gRXDAAsTI4Pd9wdgTVAgw/Tv3z8GEP7Jwctw78M3DE0goPr6BoPludVgdTAM1wgCv//9B9PIQOPNDYaAGxtRNIEw03+gYhDGBtSBNgVc3wiWR8dM//4DTQBidKD++jqD//X1YDlsGMWpMKD26jqD79V1GM5DxihOZQWGntqrawy+V9ZiOA0dw21k/f6JwerzHQbvS2swTMeGGfPz8l8BLRP9KizDwP0WHk+EwGum/3//94M8y/nmEdZAwIb//vs7g/nk6ZPHzE3NvwITrxLDfwYhIAamZpz4PcM/hslXrl6pBwAmfz5iaAlAuAAAAABJRU5ErkJggg==); -} -input.multi-diff[type=checkbox] + label:hover { - background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFPSURBVDhPjZJBSwJBHMXfrG6rWEkl1MFDGOihDn2JIIrqc3QJunbyFhUkRieD+hYepWteuxctXiJ1Q5xmdmZ3bWZTUHezfvAu/3lv3n+HRblcTrbb7fN+v/8eBMFgFpxz13Gcu3q9bqHb7V4M5/9GhatE3cIsy0o99YBKC3jliCWbBK43gK0MoDI9otfTB/vPBC9Uwu4xMC8IzSOSBsFxIYNqMTGcAIYQAlodD3j5/IqENIc5gqt1P/SNZKhaXR0a5E/5BEcrwH1xEHrGZbiuC604DpZ81AoiPJ/WROM4e4sSt3kaaRopNrg7z1FZdSLmcU2saqrX20lTXC5/RFabFmk2m+GLnBnbWJMOThJv4SV/QRqNBjNNM9UiGeQHdDiejZSSG5TSG71zjnVivyVOKlNLlEqlx+xCds7zvU31G6Z938dvEq4QjLMH27ZPvwHFVYQr3h7uHwAAAABJRU5ErkJggg==); -} - -.rgb.fstuple .color-picker.multi-diff:after { - width: 20px; - height: 20px; - content: ' '; - background: darkgray; - display: flex; - clip-path: polygon(0 0, 0 100%, 100% 100%); -} - -.icon-input input { - position: relative; - padding-left: 36px; -} -.icon-input span { - position: absolute; - left: 6px; - top: -2px; - font-family: HiFi-Glyphs; - font-size: 30px; - color: #afafaf; -} -.icon-input input:focus + span { - color: #ffffff; -} - -.icon { - font-family: HiFi-Glyphs; - color: white; -} - -#property-type-icon { - font-size: 50px; -} - -.selectable { - -webkit-touch-callout: text; - -webkit-user-select: text; - -khtml-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - user-select: text; - cursor: text; -} - -.color-box { - display: inline-block; - width: 15pt; - height: 15pt; - border: 0.75pt solid black; - margin: 1.5pt; - cursor: pointer; -} - -.color-box.highlight { - width: 13.5pt; - height: 13.5pt; - border: 1.5pt solid black; -} - -#properties-list { - display: flex; - flex-direction: column; - - margin-top: 16px; -} - -#properties-list .fieldset { - position: relative; - /* 0.1px on the top is to prevent margin collapsing between this and it's first child */ - margin: 0 -21px 21px -21px; - padding: 0.1px 21px 0 21px; - border: none; - border-top: 1px rgb(90,90,90) solid; - box-shadow: 0 -1px 0 rgb(37,37,37); -} - -#properties-list .fieldset.fstuple, #properties-list .fieldset.fsrow { - margin-top: 21px; - border: none; - box-shadow: none; -} - -#properties-list > .fieldset[data-collapsed="true"] + .fieldset { - margin-top: 0; -} - -#properties-list > .fieldset[data-collapsed="true"] > *:not(div.legend) { - display: none !important; -} - -.section-header { - padding: 0 16px; - border-top: 1px rgb(90,90,90) solid; - box-shadow: 1px -1px 0 rgb(37,37,37); - border-bottom: 1px solid rgb(37, 37, 37); -} - -div.section-header, hr { - display: flex; - flex-flow: row nowrap; - padding: 10px 16px; - font-family: Raleway-Regular; - font-size: 12px; - color: #afafaf; - height: 28px; - text-transform: uppercase; - outline: none; - margin-bottom: 10px; - align-items: center; -} - -.section.minor { - margin: 0 21px; - box-shadow: 1px -1px 0 rgb(37,37,37); - border-left: 1px solid #575757; -} - -.container.property { - padding: 0 16px; -} - -.stretch { - width: 100%; -} - -div.section-header .label { - width: 100%; -} - -.section.minor div.section-header { - border-right: 0; -} - -div.section[collapsed="true"] > .container { - display: none; -} - -div.section[collapsed="true"], div.section[collapsed="true"] > .section-header { - margin-bottom: 0; -} - -.section.major { - margin-bottom: 20px; -} - -.section.minor.last { - margin-bottom: 20px; - border-bottom: 1px solid rgb(37,37,37); -} - -.section-header { - background-color: #373737; -} - - -.section-header span { - font-size: 30px; - font-family: HiFi-Glyphs; -} - -.triple-label { - text-transform: uppercase; - text-align: center; - padding: 6px 0; - cursor: default; -} - -.triple-item { - margin-right: 10px; -} - -.triple-item.rgb.fstuple { - display: block !important; -} - -.section-header[collapsed="true"] { - margin-bottom: -21px; -} - -#properties-list .sub-section-header { - border-top: none; - box-shadow: none; - margin-top: 8px; -} - -.sub-section-header + .property { - margin-top: 0; -} - -hr { - border: none; - padding-top: 2px; -} - -.property { - min-height: 28px; -} - -.property.checkbox { - width: auto; -} - -span.indented { - padding-left: 16px; -} - -.property label, .number label { - display: table-cell; - vertical-align: middle; - font-family: Raleway-SemiBold; - font-size: 14px; -} -.property label .unit, .number label .unit { - margin-left: 8px; - font-family: Raleway-Light; - font-size: 13px; -} - -.property div.legend, .number div.legend { - display: table-cell; - vertical-align: middle; - font-family: Raleway-SemiBold; - font-size: 14px; -} -.property div.legend .unit, .number div.legend .unit { - margin-left: 8px; - font-family: Raleway-Light; - font-size: 13px; -} - -.value { - display: block; - min-height: 18px; -} -.value label { - display: inline-block; - vertical-align: top; -} -.value div.legend { - display: inline-block; - vertical-align: top; - width: 48px; -} -.value span { - font-size: 15px; - margin-right: 4px; -} - -#placeholder-property-type { - display: flex; - align-items: center; - width: auto; - margin-right: 20px; -} - -#placeholder-property-locked { - margin-left: 6px; -} - -.checkbox + .checkbox { - margin-top: 0; -} - -.checkbox-sub-props { - margin-top: 18px; -} - -.property .number { - float: left; -} -.property .number + .number { - margin-left: 10px; -} - -.property.range label{ - padding-bottom: 3px; -} -.property.range input[type=number]{ - margin-left: 0.8rem; - width: 5.4rem; - height: 1.8rem; -} - -.dropdown { - position: relative; - margin-bottom: -17px; -} - -.dropdown select { - clear: both; -} - -.dropdown dl { - clear: both; - cursor: pointer; - font-family: FiraSans-SemiBold; - font-size: 15px; - width: 292px; - height: 28px; - padding: 0 28px 0 12px; - color: #afafaf; - background: #575757; - position: relative; - display: flex; - align-items: center; -} - -.dropdown dl[dropped="true"] { - color: #404040; - background: linear-gradient(#afafaf, #afafaf); - z-index: 998; -} - -.dropdown dt { - height: 100%; - box-sizing: border-box; - border-right: 1px solid #121212; - width: 100%; -} -.dropdown dt:hover { - color: #404040; -} -.dropdown dt:focus { - outline: none; -} -.dropdown dt span:first-child { - display: inline-block; - position: relative; - top: 5px; -} -.dropdown dt span:last-child { - font-family: HiFi-Glyphs; - font-size: 42px; - float: right; - margin-right: -48px; - position: relative; - left: -12px; - top: -9px; -} - -.dropdown dd { - position: absolute; - top: 28px; - left: 3px; - display: none; -} -.dropdown dl[dropped="true"] dd { - display: block; -} - -.dropdown li { - list-style-type: none; - padding: 3px 0 1px 12px; - width: 320px; - height: auto; - font-family: FiraSans-SemiBold; - font-size: 15px; - color: #404040; - background-color: #afafaf; - z-index: 999; -} -.dropdown li:hover { - background-color: #00b4ef; -} - -.dropdown dl[disabled="disabled"], .dropdown dl[disabled="disabled"][dropped="true"] { - color: #252525; - background: linear-gradient(#575757 20%, #252525 100%); -} -.dropdown dl[disabled="disabled"] dd { - display: none; -} -.dropdown dl[disabled="disabled"] dt:hover { - color: #252525; -} - -.multiselect-box { - position: absolute; -} -.multiselect-box select { - font-family: FiraSans-SemiBold; - font-size: 15px; - color: #afafaf; - background-color: #252525; - border: none; - text-align-last: center; -} -.over-select { - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; -} -.multiselect-options { - position: absolute; - display: none; - border: none; -} -.multiselect-options span { - font-family: hifi-glyphs; - font-size: 13px; - color: #000000; -} -.multiselect-options label { - z-index: 2; - display: block; - font-family: FiraSans-SemiBold; - font-size: 11px; - color: #000000; - background-color: #afafaf; -} -.multiselect-options label:hover { - background-color: #1e90ff; -} -.multiselect-options input[type=checkbox] + label { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADUOYnF4LQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIMSURBVFjD7ZmxkqowFIZ/7mwJPen1AezV3t6hFvrQhweAHvrQ8wL2xt4HwD7ppd+tvHOvu0gCYdEZTsmAfpNzzpcTcAB84o3iD94sZuCx4+Pxwvl8dl4JcL1ef84lMQPPwBZDSgkp5XsASylBKUUYhhBCvDbw7XYDpRRKKTRNA8YYOOevC5ymKZRS/13jnHdCTwLMOW8tAc45GGNomuY1gKuq6lxFIQQopdMDXy4X5HmudW8URdMCSynBGNOG3Ww20wHf9dVWl4+wbav7a8CMsW9G+Cm22+1T2F8BzvMc1+u18z5CCJIkseNhKSX2+z2qqjLWl84zhBAURQHXde0A31Oa57nWbqSrLwDwPA9FUcD3fTtb82NKu8QOAHVda+srSRJt2E7gtpQKIXA4HH6csmzpyxj4dDo9TalSCpRS1HX9TV86RujSlxGwlBJpmnY+rJRCGIZ/s2BTX9qnZgBwHAee52mJ/l7nx+PRqr6MVtj3fZRlaVRf/5aGDX0Z17DrusiyrHfqhuqrt9aiKEIcx4OBTfU1aOMIggBlWYIQ0utP+uhr8CyxXC5RFIUxdBAE1srKePgxbcbVamWlnAZNa7rNSAhBlmWv8yLlWTPa0Nco83BbM2ZZZsUIowzwj80YxzEWi8VoB4IPGz9yb0YhBHa73agnGGtHJNd1R4ed9FVV33Awf6ebgd8b+Av9A/rq6s3hjgAAAABJRU5ErkJggg=='); - background-size: 11px 11px; - background-position: top 5px left 14px; -} -.multiselect-options input[type=checkbox]:enabled + label:hover { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADUOYnF4LQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIMSURBVFjD7ZmxkqowFIZ/7mwJPen1AezV3t6hFvrQhweAHvrQ8wL2xt4HwD7ppd+tvHOvu0gCYdEZTsmAfpNzzpcTcAB84o3iD94sZuCx4+Pxwvl8dl4JcL1ef84lMQPPwBZDSgkp5XsASylBKUUYhhBCvDbw7XYDpRRKKTRNA8YYOOevC5ymKZRS/13jnHdCTwLMOW8tAc45GGNomuY1gKuq6lxFIQQopdMDXy4X5HmudW8URdMCSynBGNOG3Ww20wHf9dVWl4+wbav7a8CMsW9G+Cm22+1T2F8BzvMc1+u18z5CCJIkseNhKSX2+z2qqjLWl84zhBAURQHXde0A31Oa57nWbqSrLwDwPA9FUcD3fTtb82NKu8QOAHVda+srSRJt2E7gtpQKIXA4HH6csmzpyxj4dDo9TalSCpRS1HX9TV86RujSlxGwlBJpmnY+rJRCGIZ/s2BTX9qnZgBwHAee52mJ/l7nx+PRqr6MVtj3fZRlaVRf/5aGDX0Z17DrusiyrHfqhuqrt9aiKEIcx4OBTfU1aOMIggBlWYIQ0utP+uhr8CyxXC5RFIUxdBAE1srKePgxbcbVamWlnAZNa7rNSAhBlmWv8yLlWTPa0Nco83BbM2ZZZsUIowzwj80YxzEWi8VoB4IPGz9yb0YhBHa73agnGGtHJNd1R4ed9FVV33Awf6ebgd8b+Av9A/rq6s3hjgAAAABJRU5ErkJggg=='); -} -.multiselect-options input[type=checkbox]:checked + label { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADMveELP9QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIqSURBVFjD7ZmxkqowFIb/7GwJPfT6APZib+9QC33o4QGghz70vIC9sfcBsE966bPNWlxnlQTDRWc4JUT4hpPz5SQSAAofFF/4sJiBx47v+wun04m8E+B6vVbzlJiBZ2CLIYRQQgj1EcBCCEUpRRRF4Jyrtwa+Xq+glEJKia7rkKYpGGPqbYHzPFdSyn+uMcZ6oScBZowpzvmje0jTVHVd9x7ATdMoxtjTMZxzUErV5MDn81mVZak1No7jab+wEEKlaaoNGwQBmQz4pq9H8/IeNo5jMmnRpWmKeyP8FZvN5insfwEuy1JdLpfecb7vI8uy3tb2Szelu91ONU1jtP9jjKmmabRgq6qC4zh2VrpbSsuy1FqNdPUFAK7roqoqeJ6ntXH4Mk1pn9gBoG1bbX1lWaYN2wv8KKWcc+z3+z+7LFv6MgY+Ho9PUyqlBKUUbduqe33pGKFPX0bAQgiV53nvj6WUiKIIt2K0qS/tXTMAEELguq6W6H/nOQ6Hg1V9GX1hz/NIXdckCALtB7Vta1VfxnPYcRwURUEeNSGmYaqvwVqL45gkSfIysKm+Xlo4wjAkdV3D9/1BLxmir5d7ieVySaqqMoYOw3CwEV5ufkyLcbVaIUkSq2d1xt2abjH6vo+iKKwfLA5uL58Vow19jdIPPyrGoiisGGGUBv6+GJMkwWKxGO2M+dvGQ36LEZxztd1uRz0Qt7ZFchwHY8NOelQ1NAjm/+lm4M8G/gH2zx33BSr7jAAAAABJRU5ErkJggg=='); -} -.multiselect-options input[type=checkbox]:checked + label:hover { - background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADMveELP9QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIqSURBVFjD7ZmxkqowFIb/7GwJPfT6APZib+9QC33o4QGghz70vIC9sfcBsE966bPNWlxnlQTDRWc4JUT4hpPz5SQSAAofFF/4sJiBx47v+wun04m8E+B6vVbzlJiBZ2CLIYRQQgj1EcBCCEUpRRRF4Jyrtwa+Xq+glEJKia7rkKYpGGPqbYHzPFdSyn+uMcZ6oScBZowpzvmje0jTVHVd9x7ATdMoxtjTMZxzUErV5MDn81mVZak1No7jab+wEEKlaaoNGwQBmQz4pq9H8/IeNo5jMmnRpWmKeyP8FZvN5insfwEuy1JdLpfecb7vI8uy3tb2Szelu91ONU1jtP9jjKmmabRgq6qC4zh2VrpbSsuy1FqNdPUFAK7roqoqeJ6ntXH4Mk1pn9gBoG1bbX1lWaYN2wv8KKWcc+z3+z+7LFv6MgY+Ho9PUyqlBKUUbduqe33pGKFPX0bAQgiV53nvj6WUiKIIt2K0qS/tXTMAEELguq6W6H/nOQ6Hg1V9GX1hz/NIXdckCALtB7Vta1VfxnPYcRwURUEeNSGmYaqvwVqL45gkSfIysKm+Xlo4wjAkdV3D9/1BLxmir5d7ieVySaqqMoYOw3CwEV5ufkyLcbVaIUkSq2d1xt2abjH6vo+iKKwfLA5uL58Vow19jdIPPyrGoiisGGGUBv6+GJMkwWKxGO2M+dvGQ36LEZxztd1uRz0Qt7ZFchwHY8NOelQ1NAjm/+lm4M8G/gH2zx33BSr7jAAAAABJRU5ErkJggg=='); -} - -.dynamic-multiselect { - position: relative; - top: 6px; - padding-bottom: 6px; -} - -div.refresh { - box-sizing: border-box; - padding-right: 44px; -} -div.refresh input[type="button"] { - float: right; - margin-right: -44px; - position: relative; - left: 10px; -} - -.color-picker { - box-sizing: border-box; - width: 26px; - height: 26px; - border: 3px solid #2B2B2B; - cursor: pointer; -} -.color-picker:focus { - outline: none; -} -.color-picker[active="true"] { - border-color: #000; -} - -.color-picker[disabled="disabled"] { - border-color: #afafaf; -} - -.colpick { - z-index: 3; -} -.colpick[disabled="disabled"] { - display: none !important; -} - -.rgb label { - float: left; - margin-top: 10px; - margin-left: 21px; -} -.rgb label + * { - clear: both; -} - -.rgb div.legend { - float: left; - margin-top: 10px; - margin-left: 21px; -} -.rgb div.legend + * { - clear: both; -} - -.draggable-number-container { - flex: 0 1 124px; -} -.draggable-number { - position: relative; - height: 28px; - flex: 0 1 124px; - display: flex; - align-items: center; -} - -.draggable-number .text { - position: absolute; - display: inline-block; - color: #afafaf; - background-color: #252525; - font-family: FiraSans-SemiBold; - font-size: 15px; - margin: 0; - padding: 0 16px; - height: 28px; - width: 100%; - line-height: 2; - box-sizing: border-box; - z-index: 1; -} -.draggable-number .text:hover { - cursor: ew-resize; -} -.draggable-number .left-arrow, .draggable-number .right-arrow { - position: absolute; - display: inline-block; - font-family: HiFi-Glyphs; - font-size: 20px; - z-index: 2; -} -.draggable-number span:hover { - cursor: default; -} -.draggable-number .left-arrow { - top: 3px; - left: 0; - transform: rotate(180deg); -} -.draggable-number .right-arrow { - top: 3px; - right: 0; -} -.draggable-number input[type=number] { - position: absolute; - right: 0; - width: 100%; -} -.draggable-number input[type=button] { - position: absolute; - top: 0; -} -.draggable-number input::-webkit-inner-spin-button { - -webkit-appearance: none; - visibility: hidden; -} -.draggable-number.fstuple { - height: 28px; - width: 124px; - left: 12px; -} -.draggable-number.fstuple + .draggable-number.fstuple { - margin-left: 28px; -} -.draggable-number.fstuple input { - right: -10px; -} -.draggable-number.fstuple .sublabel { - position: absolute; - top: 6px; - left: -16px; - font-family: FiraSans-SemiBold; - font-size: 15px; -} - -.rect .rect-row { - margin-bottom: 8px; -} - -.row .property { - width: auto; - display: inline-block; - margin-right: 6px; -} -.row .property:last-child { - margin-right: 0; -} -.row .property input { - clear: both; - float: left; -} - -.property.texture { - display: block; -} -.property.texture input { - margin: 0.4rem 0; -} -.texture-image img { - padding: 0; - margin: 0; - width: 100%; - height: 100%; - display: none; -} -.texture-image { - display: block; - position: relative; - background-repeat: no-repeat; - background-position: center; - background-size: 100% 100%; - margin-top: 0.4rem; - height:128px; - width: 128px; - background-image: url('data:image/png;base64,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'); -} -.texture-image.no-texture { - background-image: url('data:image/png;base64,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'); -} -.texture-image.no-preview { - background-image: url('data:image/png;base64,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'); -} - -.two-column { - display: table; - width: 100%; -} -.two-column > div { - display: table-cell; - width: 50%; -} - -#properties-list .fieldset .two-column { - padding-top: 10px; - display: flex; -} - -#properties-list .two-column .fieldset { - width: 50%; - margin: 0; - padding: 0; - border-top: none; - box-shadow: none; -} - -#properties-list .two-column .column { - position: relative; - top: -10px; -} - -#properties-list .two-column .fieldset div.legend { - width: 100%; - margin: 21px -21px 0 -21px; - padding: 16px 0 0 21px; - font-family: Raleway-Regular; - font-size: 12px; - color: #afafaf; - height: 10px; - text-transform: uppercase; - outline: none; -} - -#properties-list .two-column + .property { - margin-top: 6px; -} - -.fieldset .checkbox-sub-props { - margin-top: 0; -} - -.fieldset .checkbox-sub-props .property:first-child { - margin-top: 0; -} - -.column { - vertical-align: top; -} - -.indent { - margin-left: 24px; -} - -::-webkit-scrollbar { - width: 20px; - height: 10px; -} -::-webkit-scrollbar-track { - background-color: #2e2e2e; -} -#entity-table-scroll::-webkit-scrollbar-track { - border-bottom-right-radius: 7px; -} - -::-webkit-scrollbar-thumb { - background-color: #696969; - border: 2px solid #2e2e2e; - border-radius: 8px; -} - -/* FIXME: Revisit textarea resizer/corner when move to Qt 5.6 or later: see if can get resizer/corner to always be visible and -have correct background color with and without scrollbars. */ -textarea:enabled::-webkit-resizer { - background-size: 10px 10px; - background: #252525 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAXSURBVChTY1RVVWXADZigNA4wMqUZGACS3gCD5UUtKAAAAABJRU5ErkJggg==) no-repeat bottom right; -} -textarea:focus::-webkit-resizer { - background-size: 10px 10px; - background: #000000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACOSURBVChThdC5DQQhDAXQvyRI5LQxFdABARWQElAPogYkiqEWQhLYGe8xxzJaS5a/8AuQHwDG2n+Lvee0hBDQWlO+hRvy3mNZFjDG5vCDOOeIMaL3/guPKISAWiu9n+AVSSlhraXdF86Qcw6tNdoTvEOlFOScd6iUOv3JGEMopYQx9jNvaawnoHnNr8Z4AuRLPOq2gPgnAAAAAElFTkSuQmCC) no-repeat bottom right; -} -textarea:enabled[scrolling="true"]::-webkit-resizer { - background-size: 10px 10px; - background: #2e2e2e url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACKSURBVChTjdAxDsMgDAXQT4UYuQIzCwsSKxsSJ4YDoByDY7AwUOG2aZMQqX+xhd9gzIwxA3/k8a7LCCFgraX+Fk4UY4RSCoyxNfwgzjlyzhhjXOEvSimhtUbvB3hGUkp472m2wxUKIaD3TnOCd6jWim3bvlBrfdjJOUeolEJoZj/4PMH83bl/BXgCWSs2Z09IjgoAAAAASUVORK5CYII=) no-repeat bottom right; -} - - -div#grid-section, body#entity-list-body { - padding-bottom: 0; - margin: 16px; -} - -#entity-list-header { - margin-bottom: 36px; -} - -#entity-list-header div { - display: inline-block; - width: 65px; - margin-right: 6px; -} - -#entity-list-header div input:first-child { - margin-right: 0; - float: left; - width: 33px; - border-right: 1px solid #808080; - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -#entity-list-header div input:last-child { - margin-right: 0; - float: right; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -#delete { - float: right; - margin-right: 0; - background-color: #ff0000; -} - -#entity-list { - position: relative; /* New positioning context. */ -} - -#filter-area { - padding-right: 168px; - padding-bottom: 24px; -} - -#filter-type-multiselect-box select { - border-radius: 14.5px; - width: 107px; - height: 28px; -} -#filter-type-options { - position: absolute; - top: 48px; -} -#filter-type-options div { - position: relative; - height: 22px; -} -#filter-type-options span { - position: relative; - top: 3px; - font-family: HiFi-Glyphs; - font-size: 13px; - color: #000000; - padding-left: 6px; - padding-right: 4px; -} -#filter-type-options label { - position: absolute; - top: -20px; - z-index: 2; - height: 22px; - width: 200px; - padding-top: 1px; -} -#filter-type-options-buttons { - top: -22px; - width: 224px; - z-index: 2; - background-color: #afafaf; - padding-bottom: 6px; -} -#filter-type-options input[type=button] { - position: relative; - left: 16px; - z-index: 3; - height: 23px; - min-width: 60px; - font-size: 10px; - color: #000; - background: linear-gradient(#afafaf 20%, #808080 100%); -} -#filter-type-options input[type=button]:enabled:hover { - background: linear-gradient(#afafaf 20%, #575757 100%); -} - -#filter-search-and-icon { - position: relative; - left: 118px; - width: calc(100% - 126px); -} - -#filter-in-view { - position: absolute; - top: 0; - right: 126px; -} - -#filter-radius-and-unit { - position: relative; - float: right; - margin-right: -168px; - top: -45px; -} -#filter-radius-and-unit label { - margin-left: 2px; -} -#filter-radius-and-unit span { - position: relative; - top: 25px; - right: 9px; - z-index: 2; - font-style: italic; -} -#filter-radius-and-unit input { - width: 120px; - border-radius: 14.5px; - font-style: italic; -} -#filter-radius-and-unit input[type=number]::-webkit-inner-spin-button { - display: none; -} - -#entity-list-footer { - padding-top: 9px; -} - -#footer-text { - float: right; - padding-top: 12px; - padding-right: 22px; -} - -input[type=button]#export { - height: 38px; - width: 180px; -} - -#no-entities { - display: none; - position: absolute; - top: 80px; - padding: 12px; - font-family: FiraSans-SemiBold; - font-size: 15px; - font-style: italic; - color: #afafaf; -} - -#entity-table-columns-multiselect { - position: absolute; - top: 51px; - right: 22px; -} -#entity-table-columns-multiselect-box select { - height: 28px; - width: 20px; - background-color: #1c1c1c; - border-top-right-radius: 7px; -} -#entity-table-columns-options { - position: absolute; - top: 50px; - right: 110px; -} -#entity-table-columns-options div { - position: relative; - height: 22px; -} -#entity-table-columns-options label { - position: absolute; - top: -22px; - height: 22px; - width: 100px; - padding-top: 4px; -} -#entity-table-columns-options input[type=checkbox] + label { - padding-left: 30px; -} - -#entity-table-scroll { - /* Height is set by JavaScript. */ - width: 100%; - overflow-x: hidden; - overflow-y: auto; - box-sizing: border-box; - padding-top: 28px; /* Space for header and footer outside of scroll region. */ - margin-top: 28px; - border-left: 2px solid #575757; - border-right: 2px solid #575757; - border-bottom: 2px solid #575757; - border-bottom-left-radius: 7px; - border-bottom-right-radius: 7px; - background-color: #1c1c1c; -} - -#entity-table-scroll .glyph { - font-family: HiFi-Glyphs; - font-size: 15px; -} - -#entity-table { - margin-top: -28px; - margin-bottom: -18px; - table-layout: fixed; - border: none; - background-color: #1c1c1c; -} - -#entity-table thead tr, #entity-table thead tr th { - background: none; -} - -#entity-table .glyph { - margin: 0 -2px 0 -2px; - vertical-align: middle; -} - -#entity-table thead { - box-sizing: border-box; - border: 2px solid #575757; - border-top-left-radius: 7px; - border-top-right-radius: 7px; - border-bottom: 1px solid #575757; - position: absolute; - top: 49px; - left: 0; - width: 100%; - word-wrap: nowrap; - white-space: nowrap; - overflow: hidden; -} - -#entity-table th { - display: inline-block; - box-sizing: border-box; - padding: 5px 0 0 0; - vertical-align: middle; - overflow: hidden; - text-overflow: ellipsis; -} - -#entity-table th:focus { - outline: none; -} - -#entity-table th .glyph { - position: relative; - left: 4px; -} -#entity-table th .glyph + .sort-order { - position: relative; - left: 4px; -} - -#entity-table thead .sort-order { - display: inline-block; - width: 8px; - margin: -5px 0 -3px 0; - vertical-align: middle; -} - -#entity-table thead .resizer { - position: absolute; - top: 1px; - height: 26px; - width: 10px; - cursor: col-resize; -} - -#entity-table .dragging { - background-color: #b3ecff; -} - -#entity-table td { - box-sizing: border-box; -} -#entity-table td.glyph { - text-align: center; - padding: 0; -} - -#properties-base { - border-top: none !important; - box-shadow: none !important; - margin-bottom: 5px !important; -} - -#properties-base #property-type-icon { - font-family: HiFi-Glyphs; - font-size: 31px; - color: #00b4ef; - margin: -4px 12px -4px -2px; - width: auto; - display: none; -} - -#properties-base #property-type { - padding: 5px 24px 5px 0; - border-right: 1px solid #808080; - width: auto; - display: inline-block; -} - -#properties-base .checkbox label span { - font-family: HiFi-Glyphs; - font-size: 20px; - padding-right: 6px; - vertical-align: top; - position: relative; - top: -4px; -} - -#properties-base input[type=checkbox]:checked + label span { - color: #ffffff; -} - -#id label { - width: 24px; -} -#property-id { - display: inline-block; -} -#property-id::selection { - color: #000000; - background-color: #00b4ef; -} - -input#property-scale-button-rescale { - min-width: 50px; - left: 152px; -} -input#property-scale-button-reset { - margin-right: 0; - left: 250px; -} - -#property-userData-static, -#property-materialData-static { - display: none; - z-index: 99; - position: absolute; - width: 96%; - padding-left: 1%; - margin-top: 5px; - margin-bottom: 10px; - background-color: #2e2e2e; -} - -#property-userData-saved, -#property-materialData-saved { - margin-top: 5px; - font-size: 16px; - display: none; -} - - -#div-property-collisionSoundURL[style*="display: none"] + .property { - margin-top: 0; -} - -.context-menu { - display: none; - position: fixed; - color: #000000; - background-color: #afafaf; - padding: 5px 0 5px 0; - cursor: default; -} -.context-menu li { - list-style-type: none; - padding: 4px 18px 4px 18px; - margin: 0; - white-space: nowrap; -} -.context-menu li:hover { - background-color: #e3e3e3; -} -.context-menu li.separator { - border-top: 1px solid #333333; - margin: 5px 5px; - padding: 0 0; -} -.context-menu li.disabled { - color: #333333; -} -.context-menu li.separator:hover, .context-menu li.disabled:hover { - background-color: #afafaf; -} - -input.rename-entity { - height: 100%; - width: 100%; - border: none; - font-family: FiraSans-SemiBold; - font-size: 15px; - /* need this to show the text cursor when the input field is empty */ - padding-left: 2px; -} - -.create-app-tooltip { - z-index: 100; - position: absolute; - background: #6a6a6a; - border: 1px solid black; - width: 258px; - min-height: 20px; - padding: 5px; - z-index: 100; -} - -.create-app-tooltip .create-app-tooltip-description { - font-size: 12px; - font-style: italic; - color: #ffffff; -} - -.create-app-tooltip .create-app-tooltip-js-attribute { - font-family: Raleway-SemiBold; - font-size: 11px; - color: #000000; - bottom: 0; - margin-top: 5px; -} - -#toggle-space-mode::before { - font-family: HiFi-Glyphs; - font-size: 20px; - text-transform: none; - min-width: 32px; - padding-right: 4px; - vertical-align: middle; -} - -#toggle-space-mode.space-mode-local::before { - content: "m"; -} - -#toggle-space-mode.space-mode-world::before { - content: "\e02c"; -} - -.container { - display: flex; - flex-flow: row nowrap; - margin-bottom: 8px; - min-height: 28px; -} - -.container > label { - margin-top: 6px; - width: 160px; - min-width: 160px; - max-width: 160px; -} - -.container > div.checkbox { - padding-top: 6px; -} - -.container > .value { - width: 100%; -} - -.container .row { - display: flex; - flex-flow: row nowrap; -} - -.container.shrink { - width: min-content; -} - -.fstuple { - display: flex; - flex-flow: row; -} -.fstuple input { - margin-left: 4px; - margin-right: 10px; -} -.fstuple label.red, .fstuple label.x, .fstuple label.w { - color: #C62147; -} -.fstuple label.green, .fstuple label.y, .fstuple label.h { - color: #359D85; -} -.fstuple label.blue, .fstuple label.z { - color: #0093C5; -} - -.xyz.fstuple, .pyr.fstuple { - position: relative; - left: -12px; - min-width: 50px; - width: 100px; -} - -.rgb.fstuple .tuple { - display: none; -} - -input.number-slider { - background: #575757; - border-radius: 4px; - color: white; -} - -.fstuple > div { - display: flex; - align-items: center; - justify-content: left; -} - -.flex-row { - display: flex; - flex-flow: row; -} - -.flex-column { - display: flex; - flex-flow: column; -} - -.flex-center { - align-items: center; -} - -.flex-evenly-spaced { - flex: 1; -} - -#property-serverScripts-status { - font-family: Raleway-Light; - font-size: 14px; - margin: 6px 0; - cursor: default; -} - -#property-name, #property-id { - display: flex; - width: 100%; -} - -.spacemode-hidden { - display: none; -} - -#placeholder-property-type { - min-width: 0; -} - -.collapse-icon { - cursor: pointer; -} - -#property-userData-editor.error { - border: 2px solid red; -} - -#property-userData-editorStatus { - color: white; - background-color: red; - padding: 5px; - display: none; - cursor: pointer; -} - -#property-materialData-editor.error { - border: 2px solid red; -} - -#property-materialData-editorStatus { - color: white; - background-color: red; - padding: 5px; - display: none; - cursor: pointer; -} - -input[type=number].hide-spinner::-webkit-inner-spin-button { - -webkit-appearance: none; - visibility: hidden; -} - -div.jsoneditor-menu a.jsoneditor-poweredBy { - display: none; -} +/* +// edit-style.css +// +// Created by Ryan Huffman on 13 Nov 2014 +// Copyright 2014 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +*/ + +@font-face { + font-family: Raleway-Regular; + src: url(../../../../resources/fonts/Raleway-Regular.ttf), /* Windows production */ + url(../../../../fonts/Raleway-Regular.ttf), /* OSX production */ + url(../../../../interface/resources/fonts/Raleway-Regular.ttf), /* Development, running script in /HiFi/examples */ + url(../fonts/Raleway-Regular.ttf); /* Marketplace script */ +} + +@font-face { + font-family: Raleway-Light; + src: url(../../../../resources/fonts/Raleway-Light.ttf), + url(../../../../fonts/Raleway-Light.ttf), + url(../../../../interface/resources/fonts/Raleway-Light.ttf), + url(../fonts/Raleway-Light.ttf); +} + +@font-face { + font-family: Raleway-Bold; + src: url(../../../../resources/fonts/Raleway-Bold.ttf), + url(../../../../fonts/Raleway-Bold.ttf), + url(../../../../interface/resources/fonts/Raleway-Bold.ttf), + url(../fonts/Raleway-Bold.ttf); +} + +@font-face { + font-family: Raleway-SemiBold; + src: url(../../../../resources/fonts/Raleway-SemiBold.ttf), + url(../../../../fonts/Raleway-SemiBold.ttf), + url(../../../../interface/resources/fonts/Raleway-SemiBold.ttf), + url(../fonts/Raleway-SemiBold.ttf); +} + +@font-face { + font-family: FiraSans-SemiBold; + src: url(../../../../resources/fonts/FiraSans-SemiBold.ttf), + url(../../../../fonts/FiraSans-SemiBold.ttf), + url(../../../../interface/resources/fonts/FiraSans-SemiBold.ttf), + url(../fonts/FiraSans-SemiBold.ttf); +} + +@font-face { + font-family: AnonymousPro-Regular; + src: url(../../../../resources/fonts/AnonymousPro-Regular.ttf), + url(../../../../fonts/AnonymousPro-Regular.ttf), + url(../../../../interface/resources/fonts/AnonymousPro-Regular.ttf), + url(../fonts/AnonymousPro-Regular.ttf); +} + +@font-face { + font-family: HiFi-Glyphs; + src: url(../../../../resources/fonts/hifi-glyphs.ttf), + url(../../../../fonts/hifi-glyphs.ttf), + url(../../../../interface/resources/fonts/hifi-glyphs.ttf), + url(../fonts/hifi-glyphs.ttf); +} + +* { + margin: 0; + padding: 0; +} + +body { + + color: #afafaf; + background-color: #404040; + font-family: Raleway-Regular; + font-size: 12px; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + overflow-x: hidden; + overflow-y: auto; +} + +table { + font-family: FiraSans-SemiBold; + font-size: 15px; + color: #afafaf; + border-collapse: collapse; + width: 100%; + border: 2px solid #575757; + border-radius: 7px; +} + +thead { + font-family: Raleway-Regular; + font-size: 12px; + text-transform: uppercase; + background-color: #1c1c1c; + padding: 1px 0; + border-bottom: 1px solid #575757; + width: 100%; +} + +tbody { + width: 100%; + display: block; +} + +tfoot { + font-family: Raleway-Light; + font-size: 13px; + background-color: #1c1c1c; + border-top: 1px solid #575757; + width: 100%; +} + +tfoot tr { + background-color: #1c1cff; +} + +thead tr { + height: 26px; /* 28px with thead padding */ +} + +thead th { + height: 26px; + background-color: #1c1c1c; + border-right: 1px solid #575757; +} + +thead th:last-child { + border: none; +} + +tbody td { + height: 26px; +} + +tfoot td { + height: 18px; + width: 100%; + background-color: #1c1c1c; + margin-left: 12px; +} + +tr { + width: 100%; + cursor: pointer; +} + +tr:nth-child(odd) { + background-color: #2e2e2e; +} + +tr:nth-child(even) { + background-color: #1c1c1c; +} + +tr:focus { + outline: none; +} + +tr.selected { + color: #000000; + background-color: #00b4ef; +} + +tr.selected + tr.selected { + border-top: 1px solid #2e2e2e; +} + +th { + text-align: center; + word-wrap: nowrap; + white-space: nowrap; + padding-left: 12px; + padding-right: 12px; +} + +td { + overflow: hidden; + text-overflow: clip; + white-space: nowrap; + word-wrap: nowrap; + padding-left: 12px; + padding-right: 12px; +} + +td.hidden { + padding-left: 0; + padding-right: 0; +} + +td.url { + white-space: nowrap; + overflow: hidden; +} + + +input[type="text"], input[type="search"], input[type="number"], textarea { + margin: 0; + padding: 0 12px; + color: #afafaf; + background-color: #252525; + border: none; + font-family: FiraSans-SemiBold; + font-size: 15px; +} + +textarea { + font-family: AnonymousPro-Regular; + font-size: 16px; + padding-top: 5px; + padding-bottom: 5px; + min-height: 64px; + width: 100%; + resize: vertical; +} + +input::-webkit-input-placeholder { + font-style: italic; +} + +input:focus, textarea:focus, button:focus { + color: #fff; + background-color: #000; + outline: 1px solid #00b4ef; + outline-offset: -1px; +} + +input::selection, textarea::selection { + color: #000000; + background-color: #00b4ef; +} + +input.search { + border-radius: 14px; +} + +input.search:focus { + outline: none; + box-sizing: border-box; + height: 26px; + margin-top: 1px; + margin-bottom: 1px; + box-shadow: 0 0 0 1px #00b4ef; +} + +input:disabled, textarea:disabled, .draggable-number.text[disabled="disabled"] { + background-color: #383838; + color: #afafaf; +} + +input[type="text"] { + height: 28px; + width: 100%; +} + +input.multi-diff:not(:focus) + span.multi-diff, +textarea.multi-diff:not(:focus) + span.multi-diff, +.draggable-number.multi-diff>input:not(:focus)+span.multi-diff, +dl>dt.multi-diff:not(:focus) + span.multi-diff { + visibility: visible; + position: absolute; + display: inline-block; + z-index: 2; + top: 7.5px; + left: 20px; + max-width: 50px; + min-width: 10px; + width: 50%; + height: 13px; + background-image: linear-gradient(transparent 0%, transparent 10%, #afafaf 10%, #afafaf 20%, transparent 20%, transparent 45%, #afafaf 45%, #afafaf 55%, transparent 55%, transparent 80%, #afafaf 80%, #afafaf 90%, transparent 90%, transparent 100%); + background-repeat: no-repeat; + pointer-events: none; +} + +input.multi-diff:not(:focus)::-webkit-input-placeholder, input.multi-diff:not(:focus) { + color: transparent; +} + +.draggable-number.multi-diff .text { + color: transparent; +} + +.dropdown > span.multi-diff { + top: 5px; + left: 10px; +} + +.text, .url, .texture, .textarea { + position: relative; +} + +input[type="search"] { + height: 28px; + width: 100%; +} +input[type="search"]::-webkit-search-cancel-button { + -webkit-appearance: none; + height: 20px; + width: 20px; + background-image: url('data:image/png;base64,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') +} + +input[type="number"] { + position: relative; + height: 28px; + width: 124px; +} +input[type=number] { + padding-right: 3px; +} +input[type=number]::-webkit-inner-spin-button { + opacity: 1.0; + display: block; + position: relative; + width: 10px; + height: 90%; + overflow: hidden; + font-family: HiFi-Glyphs; + font-size: 32px; + color: #afafaf; + cursor: pointer; + background-color: #000000; +} +input[type=number]::-webkit-inner-spin-button:before, +input[type=number]::-webkit-inner-spin-button:after { + position:absolute; + left: -19px; + line-height: 8px; + text-align: center; +} +input[type=number]::-webkit-inner-spin-button:before { + content: "6"; + top: 4px; +} +input[type=number]::-webkit-inner-spin-button:after { + content: "5"; + bottom: 4px; +} + +input[type=number].hover-up::-webkit-inner-spin-button:before, +input[type=number].hover-down::-webkit-inner-spin-button:after { + color: #ffffff; +} + +input[type=range] { + -webkit-appearance: none; + background: #2e2e2e; + height: 1.8rem; + border-radius: 1rem; +} +input[type=range]::-webkit-slider-thumb { + -webkit-appearance:none; + width: 0.6rem; + height: 1.8rem; + padding:0; + margin: 0; + background-color: #696969; + border-radius: 1rem; +} +input[type=range]::-webkit-slider-thumb:hover { + background-color: white; +} +input[type=range]:focus { + outline: none; +} + +input.no-spin::-webkit-outer-spin-button, +input.no-spin::-webkit-inner-spin-button { + display: none; + -webkit-appearance: none; + margin: 0; /* <-- Apparently some margin are still there even though it's hidden */ + padding-right: 12px; +} + +input[type=button], button.hifi-edit-button { + font-family: Raleway-Bold; + font-size: 13px; + text-transform: uppercase; + vertical-align: top; + height: 28px; + min-width: 120px; + padding: 0 18px; + margin-right: 6px; + border-radius: 5px; + border: none; + color: #fff; + background-color: #000; + background: linear-gradient(#343434 20%, #000 100%); + cursor: pointer; +} + +input[type=button].glyph, button.hifi-edit-button.glyph { + font-family: HiFi-Glyphs; + font-size: 20px; + text-transform: none; + min-width: 32px; + padding: 0; +} + +input[type=button].red, button.hifi-edit-button.red { + color: #fff; + background-color: #94132e; + background: linear-gradient(#d42043 20%, #94132e 100%); +} +input[type=button].blue, button.hifi-edit-button.blue { + color: #fff; + background-color: #1080b8; + background: linear-gradient(#00b4ef 20%, #1080b8 100%); +} +input[type=button].white, button.hifi-edit-button.white { + color: #121212; + background-color: #afafaf; + background: linear-gradient(#fff 20%, #afafaf 100%); +} + +input[type=button]:enabled:hover, button.hifi-edit-button:enabled:hover { + background: linear-gradient(#000, #000); + border: none; +} +input[type=button].red:enabled:hover, button.hifi-edit-button.red:enabled:hover { + background: linear-gradient(#d42043, #d42043); + border: none; +} +input[type=button].blue:enabled:hover, button.hifi-edit-button.blue:enabled:hover { + background: linear-gradient(#00b4ef, #00b4ef); + border: none; +} +input[type=button].white:enabled:hover, button.hifi-edit-button.white:enabled:hover { + background: linear-gradient(#fff, #fff); + border: none; +} + +input[type=button]:active, button.hifi-edit-button:active { + background: linear-gradient(#343434, #343434); +} +input[type=button].red:active, button.hifi-edit-button.red:active { + background: linear-gradient(#94132e, #94132e); +} +input[type=button].blue:active, button.hifi-edit-button.blue:active { + background: linear-gradient(#1080b8, #1080b8); +} +input[type=button].white:active, button.hifi-edit-button.white:active { + background: linear-gradient(#afafaf, #afafaf); +} + +input[type=button]:disabled, button.hifi-edit-button:disabled { + color: #252525; + background: linear-gradient(#575757 20%, #252525 100%); +} + +input[type=button][pressed=pressed], button.hifi-edit-button[pressed=pressed] { + color: #00b4ef; +} + +input[type=checkbox] { + display: none; +} +input[type=checkbox] + label { + padding-left: 24px; + background-repeat: no-repeat; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACpSURBVDhPY2xoaGD68+dPMSMjY9L////VgTQjAw4AlH8PxLOPHj1azWxjY1MBVNsBFBfBpwkEgNKcQGwtJyfHyATkF0KEiQdAzYlMQEIUyicFyDD9+/ePgRxMvsb///4zkIOZ/v0HmkAGHginYjGNGAzS+BpdkAj8mun/3//92DyPD//993cG88nTJ4+Zm5p/BSZeJYb/DEJADEzNOPF7hn8Mk69cvVIPAHN5pyfo70F5AAAAAElFTkSuQmCC); + cursor: pointer; +} +input[type=checkbox]:enabled + label:hover { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAClSURBVDhPY2hoaGD6//9/6b9//64D8T8gGycASr/7+/dv5/79+1kYgIxKqDjRAKiniRFIv2JgYBAFYlLAE0aQ66AckgDjjx8/yNP44cMH8jS+fPmSPI0PHz4kT+PNmzfJ03jp0iXyNJ46dYo8jYcPHyYnAbxm+vnzZz8wLhlIwd+/f5/BrKSkdExCQuLrnz9/lIBpUAiIQekXF34PTGmTT548WQ8AokXg+rhVtPYAAAAASUVORK5CYII=); +} +input[type=checkbox]:checked + label { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFLSURBVDhPjZK9SgNBFIXvbCaQRDQq7mIhQRPBRisJKcwLWOobaCsExEaxcEEQe0trGysfwg0EwWoDsbFIJUaIBJOwus547saNP3FlPzgzzJxzL5edFbZtG77v7wkhtrXWS9gFRQC/DZ07jnOYKJfL+8ie4n7mvyIGdhpay+VyQuK8y5dPZoHuVtbpZcLi4wjJ1x4t316R9dDgBlsSi8mGu7pJjyJFzVaH+r7iqyHSELSQzVADjS0UgjlDKUUsLzVO98+9kSLGV5qaHXhjU0GWNSxk3hCIwnsfeMNCjTArLmHeUBodoLiE+R+jxuHPUZP4elGE3teonx2S/Q7lJzOUlkYQ+A4/xzyegzNhXmJpwTMXry9IFjcoa84O0r+QXpcK1cugCLREZadyoA19Ergxwf96nKjd1KqlYqmLQ540TUNwItUmRWdu3T36AODjwgpY9xqqAAAAAElFTkSuQmCC); +} +input[type=checkbox]:checked + label:hover { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEySURBVDhPnZLPSsNAEMa/XVPBCE0RhNy0OarP4Av4AD6JB0GwVBA8efBBxHsgh4CQswcRoUIpiIpVAm3zZ5M4szFSbQPBH3xkJvNNZskOer2eLIriKM/ze1JOcS1UHmdZduF5ngEKjr/fN4Z6+oKerwA2gxC4HAFPEWVLsAzgZAvYt3Q6Enw6jg7uBAaTFMNwhpnKdbXCkAJdy8ROu4XrXW2HTJIErHcFDD6nC02Mom8PwymeE2gvS0ZRBBaTlsOXEmdlrfLLOI7Bakrl/zWxCT8T/904f9QW/b06qtrCUdtFCqdjYs2Q2jAPX8c2XQd7Kr/wfV8vwIPs4Ga1ixe5Xrr/YFLTYfKIvWzM6ZtwXZdX7lxXG0L+sxXHcW5t254opRzawQ0S72+dPmjTroIgOP0CQSMt5LDn1T8AAAAASUVORK5CYII=); +} +input.multi-diff[type=checkbox] + label { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFbSURBVDhPY2xoaGD68+dPMSMjY9L////VgTQjAw4AlH8PxLOPHj1azWxjY1MBVNsBFBfBpwkEgNKcQGwtJyfHyALkF4IE34gqM9zU9WT4wicG4mIA1l/fGIyOL2EQeP8EZEAiC5AQBUlcMQ5ieMXIwfDo9SeG73/+gRXDAAsTI4Pd9wdgTVAgw/Tv3z8GEP7Jwctw78M3DE0goPr6BoPludVgdTAM1wgCv//9B9PIQOPNDYaAGxtRNIEw03+gYhDGBtSBNgVc3wiWR8dM//4DTQBidKD++jqD//X1YDlsGMWpMKD26jqD79V1GM5DxihOZQWGntqrawy+V9ZiOA0dw21k/f6JwerzHQbvS2swTMeGGfPz8l8BLRP9KizDwP0WHk+EwGum/3//94M8y/nmEdZAwIb//vs7g/nk6ZPHzE3NvwITrxLDfwYhIAamZpz4PcM/hslXrl6pBwAmfz5iaAlAuAAAAABJRU5ErkJggg==); +} +input.multi-diff[type=checkbox] + label:hover { + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFPSURBVDhPjZJBSwJBHMXfrG6rWEkl1MFDGOihDn2JIIrqc3QJunbyFhUkRieD+hYepWteuxctXiJ1Q5xmdmZ3bWZTUHezfvAu/3lv3n+HRblcTrbb7fN+v/8eBMFgFpxz13Gcu3q9bqHb7V4M5/9GhatE3cIsy0o99YBKC3jliCWbBK43gK0MoDI9otfTB/vPBC9Uwu4xMC8IzSOSBsFxIYNqMTGcAIYQAlodD3j5/IqENIc5gqt1P/SNZKhaXR0a5E/5BEcrwH1xEHrGZbiuC604DpZ81AoiPJ/WROM4e4sSt3kaaRopNrg7z1FZdSLmcU2saqrX20lTXC5/RFabFmk2m+GLnBnbWJMOThJv4SV/QRqNBjNNM9UiGeQHdDiejZSSG5TSG71zjnVivyVOKlNLlEqlx+xCds7zvU31G6Z938dvEq4QjLMH27ZPvwHFVYQr3h7uHwAAAABJRU5ErkJggg==); +} + +.rgb.fstuple .color-picker.multi-diff:after { + width: 20px; + height: 20px; + content: ' '; + background: darkgray; + display: flex; + clip-path: polygon(0 0, 0 100%, 100% 100%); +} + +.icon-input input { + position: relative; + padding-left: 36px; +} +.icon-input span { + position: absolute; + left: 6px; + top: -2px; + font-family: HiFi-Glyphs; + font-size: 30px; + color: #afafaf; +} +.icon-input input:focus + span { + color: #ffffff; +} + +.icon { + font-family: HiFi-Glyphs; + color: white; +} + +#property-type-icon { + font-size: 50px; +} + +.selectable { + -webkit-touch-callout: text; + -webkit-user-select: text; + -khtml-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; + cursor: text; +} + +.color-box { + display: inline-block; + width: 15pt; + height: 15pt; + border: 0.75pt solid black; + margin: 1.5pt; + cursor: pointer; +} + +.color-box.highlight { + width: 13.5pt; + height: 13.5pt; + border: 1.5pt solid black; +} + +#properties-list { + display: flex; + flex-direction: column; + + margin-top: 16px; +} + +#properties-list .fieldset { + position: relative; + /* 0.1px on the top is to prevent margin collapsing between this and it's first child */ + margin: 0 -21px 21px -21px; + padding: 0.1px 21px 0 21px; + border: none; + border-top: 1px rgb(90,90,90) solid; + box-shadow: 0 -1px 0 rgb(37,37,37); +} + +#properties-list .fieldset.fstuple, #properties-list .fieldset.fsrow { + margin-top: 21px; + border: none; + box-shadow: none; +} + +#properties-list > .fieldset[data-collapsed="true"] + .fieldset { + margin-top: 0; +} + +#properties-list > .fieldset[data-collapsed="true"] > *:not(div.legend) { + display: none !important; +} + +.section-header { + padding: 0 16px; + border-top: 1px rgb(90,90,90) solid; + box-shadow: 1px -1px 0 rgb(37,37,37); + border-bottom: 1px solid rgb(37, 37, 37); +} + +div.section-header, hr { + display: flex; + flex-flow: row nowrap; + padding: 10px 16px; + font-family: Raleway-Regular; + font-size: 12px; + color: #afafaf; + height: 28px; + text-transform: uppercase; + outline: none; + margin-bottom: 10px; + align-items: center; +} + +.section.minor { + margin: 0 21px; + box-shadow: 1px -1px 0 rgb(37,37,37); + border-left: 1px solid #575757; +} + +.container.property { + padding: 0 16px; +} + +.stretch { + width: 100%; +} + +div.section-header .label { + width: 100%; +} + +.section.minor div.section-header { + border-right: 0; +} + +div.section[collapsed="true"] > .container { + display: none; +} + +div.section[collapsed="true"], div.section[collapsed="true"] > .section-header { + margin-bottom: 0; +} + +.section.major { + margin-bottom: 20px; +} + +.section.minor.last { + margin-bottom: 20px; + border-bottom: 1px solid rgb(37,37,37); +} + +.section-header { + background-color: #373737; +} + + +.section-header span { + font-size: 30px; + font-family: HiFi-Glyphs; +} + +.triple-label { + text-transform: uppercase; + text-align: center; + padding: 6px 0; + cursor: default; +} + +.triple-item { + margin-right: 10px; +} + +.triple-item.rgb.fstuple { + display: block !important; +} + +.section-header[collapsed="true"] { + margin-bottom: -21px; +} + +#properties-list .sub-section-header { + border-top: none; + box-shadow: none; + margin-top: 8px; +} + +.sub-section-header + .property { + margin-top: 0; +} + +hr { + border: none; + padding-top: 2px; +} + +.property { + min-height: 28px; +} + +.property.checkbox { + width: auto; +} + +span.indented { + padding-left: 16px; +} + +.property label, .number label { + display: table-cell; + vertical-align: middle; + font-family: Raleway-SemiBold; + font-size: 14px; +} +.property label .unit, .number label .unit { + margin-left: 8px; + font-family: Raleway-Light; + font-size: 13px; +} + +.property div.legend, .number div.legend { + display: table-cell; + vertical-align: middle; + font-family: Raleway-SemiBold; + font-size: 14px; +} +.property div.legend .unit, .number div.legend .unit { + margin-left: 8px; + font-family: Raleway-Light; + font-size: 13px; +} + +.value { + display: block; + min-height: 18px; +} +.value label { + display: inline-block; + vertical-align: top; +} +.value div.legend { + display: inline-block; + vertical-align: top; + width: 48px; +} +.value span { + font-size: 15px; + margin-right: 4px; +} + +#placeholder-property-type { + display: flex; + align-items: center; + width: auto; + margin-right: 20px; +} + +#placeholder-property-locked { + margin-left: 6px; +} + +.checkbox + .checkbox { + margin-top: 0; +} + +.checkbox-sub-props { + margin-top: 18px; +} + +.property .number { + float: left; +} +.property .number + .number { + margin-left: 10px; +} + +.property.range label{ + padding-bottom: 3px; +} +.property.range input[type=number]{ + margin-left: 0.8rem; + width: 5.4rem; + height: 1.8rem; +} + +.dropdown { + position: relative; + margin-bottom: -17px; +} + +.dropdown select { + clear: both; +} + +.dropdown dl { + clear: both; + cursor: pointer; + font-family: FiraSans-SemiBold; + font-size: 15px; + width: 292px; + height: 28px; + padding: 0 28px 0 12px; + color: #afafaf; + background: #575757; + position: relative; + display: flex; + align-items: center; +} + +.dropdown dl[dropped="true"] { + color: #404040; + background: linear-gradient(#afafaf, #afafaf); + z-index: 998; +} + +.dropdown dt { + height: 100%; + box-sizing: border-box; + border-right: 1px solid #121212; + width: 100%; +} +.dropdown dt:hover { + color: #404040; +} +.dropdown dt:focus { + outline: none; +} +.dropdown dt span:first-child { + display: inline-block; + position: relative; + top: 5px; +} +.dropdown dt span:last-child { + font-family: HiFi-Glyphs; + font-size: 42px; + float: right; + margin-right: -48px; + position: relative; + left: -12px; + top: -9px; +} + +.dropdown dd { + position: absolute; + top: 28px; + left: 3px; + display: none; +} +.dropdown dl[dropped="true"] dd { + display: block; +} + +.dropdown li { + list-style-type: none; + padding: 3px 0 1px 12px; + width: 320px; + height: auto; + font-family: FiraSans-SemiBold; + font-size: 15px; + color: #404040; + background-color: #afafaf; + z-index: 999; +} +.dropdown li:hover { + background-color: #00b4ef; +} + +.dropdown dl[disabled="disabled"], .dropdown dl[disabled="disabled"][dropped="true"] { + color: #252525; + background: linear-gradient(#575757 20%, #252525 100%); +} +.dropdown dl[disabled="disabled"] dd { + display: none; +} +.dropdown dl[disabled="disabled"] dt:hover { + color: #252525; +} + +.multiselect-box { + position: absolute; +} +.multiselect-box select { + font-family: FiraSans-SemiBold; + font-size: 15px; + color: #afafaf; + background-color: #252525; + border: none; + text-align-last: center; +} +.over-select { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; +} +.multiselect-options { + position: absolute; + display: none; + border: none; +} +.multiselect-options span { + font-family: hifi-glyphs; + font-size: 13px; + color: #000000; +} +.multiselect-options label { + z-index: 2; + display: block; + font-family: FiraSans-SemiBold; + font-size: 11px; + color: #000000; + background-color: #afafaf; +} +.multiselect-options label:hover { + background-color: #1e90ff; +} +.multiselect-options input[type=checkbox] + label { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADUOYnF4LQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIMSURBVFjD7ZmxkqowFIZ/7mwJPen1AezV3t6hFvrQhweAHvrQ8wL2xt4HwD7ppd+tvHOvu0gCYdEZTsmAfpNzzpcTcAB84o3iD94sZuCx4+Pxwvl8dl4JcL1ef84lMQPPwBZDSgkp5XsASylBKUUYhhBCvDbw7XYDpRRKKTRNA8YYOOevC5ymKZRS/13jnHdCTwLMOW8tAc45GGNomuY1gKuq6lxFIQQopdMDXy4X5HmudW8URdMCSynBGNOG3Ww20wHf9dVWl4+wbav7a8CMsW9G+Cm22+1T2F8BzvMc1+u18z5CCJIkseNhKSX2+z2qqjLWl84zhBAURQHXde0A31Oa57nWbqSrLwDwPA9FUcD3fTtb82NKu8QOAHVda+srSRJt2E7gtpQKIXA4HH6csmzpyxj4dDo9TalSCpRS1HX9TV86RujSlxGwlBJpmnY+rJRCGIZ/s2BTX9qnZgBwHAee52mJ/l7nx+PRqr6MVtj3fZRlaVRf/5aGDX0Z17DrusiyrHfqhuqrt9aiKEIcx4OBTfU1aOMIggBlWYIQ0utP+uhr8CyxXC5RFIUxdBAE1srKePgxbcbVamWlnAZNa7rNSAhBlmWv8yLlWTPa0Nco83BbM2ZZZsUIowzwj80YxzEWi8VoB4IPGz9yb0YhBHa73agnGGtHJNd1R4ed9FVV33Awf6ebgd8b+Av9A/rq6s3hjgAAAABJRU5ErkJggg=='); + background-size: 11px 11px; + background-position: top 5px left 14px; +} +.multiselect-options input[type=checkbox]:enabled + label:hover { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADUOYnF4LQAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIMSURBVFjD7ZmxkqowFIZ/7mwJPen1AezV3t6hFvrQhweAHvrQ8wL2xt4HwD7ppd+tvHOvu0gCYdEZTsmAfpNzzpcTcAB84o3iD94sZuCx4+Pxwvl8dl4JcL1ef84lMQPPwBZDSgkp5XsASylBKUUYhhBCvDbw7XYDpRRKKTRNA8YYOOevC5ymKZRS/13jnHdCTwLMOW8tAc45GGNomuY1gKuq6lxFIQQopdMDXy4X5HmudW8URdMCSynBGNOG3Ww20wHf9dVWl4+wbav7a8CMsW9G+Cm22+1T2F8BzvMc1+u18z5CCJIkseNhKSX2+z2qqjLWl84zhBAURQHXde0A31Oa57nWbqSrLwDwPA9FUcD3fTtb82NKu8QOAHVda+srSRJt2E7gtpQKIXA4HH6csmzpyxj4dDo9TalSCpRS1HX9TV86RujSlxGwlBJpmnY+rJRCGIZ/s2BTX9qnZgBwHAee52mJ/l7nx+PRqr6MVtj3fZRlaVRf/5aGDX0Z17DrusiyrHfqhuqrt9aiKEIcx4OBTfU1aOMIggBlWYIQ0utP+uhr8CyxXC5RFIUxdBAE1srKePgxbcbVamWlnAZNa7rNSAhBlmWv8yLlWTPa0Nco83BbM2ZZZsUIowzwj80YxzEWi8VoB4IPGz9yb0YhBHa73agnGGtHJNd1R4ed9FVV33Awf6ebgd8b+Av9A/rq6s3hjgAAAABJRU5ErkJggg=='); +} +.multiselect-options input[type=checkbox]:checked + label { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADMveELP9QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIqSURBVFjD7ZmxkqowFIb/7GwJPfT6APZib+9QC33o4QGghz70vIC9sfcBsE966bPNWlxnlQTDRWc4JUT4hpPz5SQSAAofFF/4sJiBx47v+wun04m8E+B6vVbzlJiBZ2CLIYRQQgj1EcBCCEUpRRRF4Jyrtwa+Xq+glEJKia7rkKYpGGPqbYHzPFdSyn+uMcZ6oScBZowpzvmje0jTVHVd9x7ATdMoxtjTMZxzUErV5MDn81mVZak1No7jab+wEEKlaaoNGwQBmQz4pq9H8/IeNo5jMmnRpWmKeyP8FZvN5insfwEuy1JdLpfecb7vI8uy3tb2Szelu91ONU1jtP9jjKmmabRgq6qC4zh2VrpbSsuy1FqNdPUFAK7roqoqeJ6ntXH4Mk1pn9gBoG1bbX1lWaYN2wv8KKWcc+z3+z+7LFv6MgY+Ho9PUyqlBKUUbduqe33pGKFPX0bAQgiV53nvj6WUiKIIt2K0qS/tXTMAEELguq6W6H/nOQ6Hg1V9GX1hz/NIXdckCALtB7Vta1VfxnPYcRwURUEeNSGmYaqvwVqL45gkSfIysKm+Xlo4wjAkdV3D9/1BLxmir5d7ieVySaqqMoYOw3CwEV5ufkyLcbVaIUkSq2d1xt2abjH6vo+iKKwfLA5uL58Vow19jdIPPyrGoiisGGGUBv6+GJMkwWKxGO2M+dvGQ36LEZxztd1uRz0Qt7ZFchwHY8NOelQ1NAjm/+lm4M8G/gH2zx33BSr7jAAAAABJRU5ErkJggg=='); +} +.multiselect-options input[type=checkbox]:checked + label:hover { + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADMveELP9QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIqSURBVFjD7ZmxkqowFIb/7GwJPfT6APZib+9QC33o4QGghz70vIC9sfcBsE966bPNWlxnlQTDRWc4JUT4hpPz5SQSAAofFF/4sJiBx47v+wun04m8E+B6vVbzlJiBZ2CLIYRQQgj1EcBCCEUpRRRF4Jyrtwa+Xq+glEJKia7rkKYpGGPqbYHzPFdSyn+uMcZ6oScBZowpzvmje0jTVHVd9x7ATdMoxtjTMZxzUErV5MDn81mVZak1No7jab+wEEKlaaoNGwQBmQz4pq9H8/IeNo5jMmnRpWmKeyP8FZvN5insfwEuy1JdLpfecb7vI8uy3tb2Szelu91ONU1jtP9jjKmmabRgq6qC4zh2VrpbSsuy1FqNdPUFAK7roqoqeJ6ntXH4Mk1pn9gBoG1bbX1lWaYN2wv8KKWcc+z3+z+7LFv6MgY+Ho9PUyqlBKUUbduqe33pGKFPX0bAQgiV53nvj6WUiKIIt2K0qS/tXTMAEELguq6W6H/nOQ6Hg1V9GX1hz/NIXdckCALtB7Vta1VfxnPYcRwURUEeNSGmYaqvwVqL45gkSfIysKm+Xlo4wjAkdV3D9/1BLxmir5d7ieVySaqqMoYOw3CwEV5ufkyLcbVaIUkSq2d1xt2abjH6vo+iKKwfLA5uL58Vow19jdIPPyrGoiisGGGUBv6+GJMkwWKxGO2M+dvGQ36LEZxztd1uRz0Qt7ZFchwHY8NOelQ1NAjm/+lm4M8G/gH2zx33BSr7jAAAAABJRU5ErkJggg=='); +} + +.dynamic-multiselect { + position: relative; + top: 6px; + padding-bottom: 6px; +} + +div.refresh { + box-sizing: border-box; + padding-right: 44px; +} +div.refresh input[type="button"] { + float: right; + margin-right: -44px; + position: relative; + left: 10px; +} + +.color-picker { + box-sizing: border-box; + width: 26px; + height: 26px; + border: 3px solid #2B2B2B; + cursor: pointer; +} +.color-picker:focus { + outline: none; +} +.color-picker[active="true"] { + border-color: #000; +} + +.color-picker[disabled="disabled"] { + border-color: #afafaf; +} + +.colpick { + z-index: 3; +} +.colpick[disabled="disabled"] { + display: none !important; +} + +.rgb label { + float: left; + margin-top: 10px; + margin-left: 21px; +} +.rgb label + * { + clear: both; +} + +.rgb div.legend { + float: left; + margin-top: 10px; + margin-left: 21px; +} +.rgb div.legend + * { + clear: both; +} + +.draggable-number-container { + flex: 0 1 124px; +} +.draggable-number { + position: relative; + height: 28px; + flex: 0 1 124px; + display: flex; + align-items: center; +} + +.draggable-number .text { + position: absolute; + display: inline-block; + color: #afafaf; + background-color: #252525; + font-family: FiraSans-SemiBold; + font-size: 15px; + margin: 0; + padding: 0 16px; + height: 28px; + width: 100%; + line-height: 2; + box-sizing: border-box; + z-index: 1; +} +.draggable-number .text:hover { + cursor: ew-resize; +} +.draggable-number .left-arrow, .draggable-number .right-arrow { + position: absolute; + display: inline-block; + font-family: HiFi-Glyphs; + font-size: 20px; + z-index: 2; +} +.draggable-number span:hover { + cursor: default; +} +.draggable-number .left-arrow { + top: 3px; + left: 0; + transform: rotate(180deg); +} +.draggable-number .right-arrow { + top: 3px; + right: 0; +} +.draggable-number input[type=number] { + position: absolute; + right: 0; + width: 100%; +} +.draggable-number input[type=button] { + position: absolute; + top: 0; +} +.draggable-number input::-webkit-inner-spin-button { + -webkit-appearance: none; + visibility: hidden; +} +.draggable-number.fstuple { + height: 28px; + width: 124px; + left: 12px; +} +.draggable-number.fstuple + .draggable-number.fstuple { + margin-left: 28px; +} +.draggable-number.fstuple input { + right: -10px; +} +.draggable-number.fstuple .sublabel { + position: absolute; + top: 6px; + left: -16px; + font-family: FiraSans-SemiBold; + font-size: 15px; +} + +.rect .rect-row { + margin-bottom: 8px; +} + +.row .property { + width: auto; + display: inline-block; + margin-right: 6px; +} +.row .property:last-child { + margin-right: 0; +} +.row .property input { + clear: both; + float: left; +} + +.property.texture { + display: block; +} +.property.texture input { + margin: 0.4rem 0; +} +.texture-image img { + padding: 0; + margin: 0; + width: 100%; + height: 100%; + display: none; +} +.texture-image { + display: block; + position: relative; + background-repeat: no-repeat; + background-position: center; + background-size: 100% 100%; + margin-top: 0.4rem; + height:128px; + width: 128px; + background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAABhNJREFUeNrsnVFy4joQRVsSCwAqBMwqsrRsIavMEkICoeAf2+8j1R5ZGDBgpLzoUDVVmTT2dc8It/paOpi3t7faOSciImVZyn6/l6qqRETEWivj8VistYPFd7ud1HUtIiLGGBmPx5JKX0RkMplIzvmPnHNijBERaS7Ef1lrB40bY1oXgH5a/ZH+8P7+LlVVycfHR/MGa60URdGcYOi4MUaKomhGaGx9EZHlcplMP2X+Ly8vPwOgLEtxzklVVVJVVfOznqAsy9YFXhuvqqq5AF/Lj+srtr7+LpV+yvz1mNF+vxcRkdVqJdZaeXp6ap1ws9m0TjibzVoj6lJ8vV6fjJdlKev1ujViU+j7t8tc8p9Op1KWpYw06L9JL0Av0r9l+jXl3nhd11JV1VE8tn5YM3PI3xjzoxVOGvyDU7zQj6s/0tGmI++amtNV087F9Wf/FnVPzRtCXz8RdV1nlb/efUbaJy4Wi0FqzjU1yRgjs9ls0Jp3jb6IyPPzczL9lPkvFot/dwCtB/om/x9oyJoXxps65NW8mPpdNTeX/JtBEtYE/+AUL/Tj6g/qA3TVnD41a6g++Bp9rYOp9FPnH80HOBcvy1I2m81D++BL+o/2AX5r/vgA+AD4AOif8AH8EdpVcy71sX3jWp/8W2AKff/TkUv+Oufr9AF0YuKc66xJ18T7eNP3nP9WfZ0EzufzJPqp8y+KQuq67vYBdETqCDpVU/rEw5oUnr+rD46h73/qUuinzh8fAP22D6AjxznXcqq6akrf+KmaFB6vf4+t7/sAelfIJf/GB9jtdmKMkdVq1dQM3zg4VVNU/NY+1Bgjh8Oh6YM1+dj6X19fzXwgp/wbH0DFtS7oyf0RdKqmhPFr+1RdseKfP7a+Px/IKX98APTbPoDOJrv60L417d54TH3V8lfS5pT/yfUA6/X6qOZcqkm3xrUm6X9CTH3fB0ihnzr/Ix9A/3T1qbfWpGvjMfX9T0UK/dT54wOg/88H8EfGPTVr6D740frhLDmn/Hv5AH1qku9t31KTzh3/aP1LPsBfzr+XDxCO0K6ack/N6qp5MfUv+QB/Of/ePsCQfWmfc6EfV3/kjzZrrRwOh9YtKHSm/LjOH3yrMTzej4c1y//51PHoP0a/tR7AOSdFURw9rz5VU049zw7jl2qWrosP++BY+iI/+wJS6afMv9kXoA6gvimsieHzZr/m6MTp3PPuc3G9SP95OPpx9JtOgT4cHwA+QCJ9+ADwAeADsC+AfQHo/4b1APAB4APAB4APAB8APgB9OD4AfAD4AFFqEnwA+AD4APgA6P86HwA+AHyAZhIBHwA+AHwA+AD04X/eB4APAB8APgB8APgA8AHow/P0AeADwAeADwAfAD4AfAD68Px8APgA8AHgA8AHgA8AH0DO70/v6lHvjaOfVn8U/iLcXx5OUML96X49vRTX3/nPw9FPo9+sB5hMJuKck+VyeVRTrLWtdfNdcf95eldNCuOfn5+tSYy/Pz+2voi0fICc8p/P5z93gJAPEN4+wufN4evaePj99eH+ePTj6p/1Abp60kt9Ksf/v46HDwAfAD6A/6gUPgD7AtgXwPP4DNcDwAeADwAfAD4AfAD4ADyPz289AHyA+Pqp84cPIPAB8AHwAfAB8AHgA7Q+HfAB4APAB4APAB+APjw3HwA+AHwA+ADwAeADwAegD8/TB4APAB8APgB8APgA8AHow/PzAeADwAeADwAfAD4AfACJ//316KfVH/mjLeb31+vx/kWhH0+/tR7AOSdFUUT9/nq9oK4+OJa+iLT25+eUf7MvIOQDxPr+en2F++PRj6PfdAr04fgA8AES6cMHgA8AH4B9AewLQP83rAeADwAfAD4AfAD4APAB6MPxAeADwAeIUpPgA8AHwAfAB0D/1/kA8AHgAzSTCPgA8AHgA8AHoA//8z4AfAD4APAB4APAB4APQB+epw8AHwA+AHwA+ADwAeAD0Ifn5wPAB4APAB8APgB8gBz5AOb19bX2TYLpdNpqQ7bbbctJGjJeVZVst9vWLSu2/vf3t+Sc/yicFIRr0C7Fu76f/lw8XBePflr9/wYAqWwWUSLcO54AAAAASUVORK5CYII='); +} +.texture-image.no-texture { + background-image: url('data:image/png;base64,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'); +} +.texture-image.no-preview { + background-image: url('data:image/png;base64,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'); +} + +.two-column { + display: table; + width: 100%; +} +.two-column > div { + display: table-cell; + width: 50%; +} + +#properties-list .fieldset .two-column { + padding-top: 10px; + display: flex; +} + +#properties-list .two-column .fieldset { + width: 50%; + margin: 0; + padding: 0; + border-top: none; + box-shadow: none; +} + +#properties-list .two-column .column { + position: relative; + top: -10px; +} + +#properties-list .two-column .fieldset div.legend { + width: 100%; + margin: 21px -21px 0 -21px; + padding: 16px 0 0 21px; + font-family: Raleway-Regular; + font-size: 12px; + color: #afafaf; + height: 10px; + text-transform: uppercase; + outline: none; +} + +#properties-list .two-column + .property { + margin-top: 6px; +} + +.fieldset .checkbox-sub-props { + margin-top: 0; +} + +.fieldset .checkbox-sub-props .property:first-child { + margin-top: 0; +} + +.column { + vertical-align: top; +} + +.indent { + margin-left: 24px; +} + +::-webkit-scrollbar { + width: 20px; + height: 10px; +} +::-webkit-scrollbar-track { + background-color: #2e2e2e; +} +#entity-table-scroll::-webkit-scrollbar-track { + border-bottom-right-radius: 7px; +} + +::-webkit-scrollbar-thumb { + background-color: #696969; + border: 2px solid #2e2e2e; + border-radius: 8px; +} + +/* FIXME: Revisit textarea resizer/corner when move to Qt 5.6 or later: see if can get resizer/corner to always be visible and +have correct background color with and without scrollbars. */ +textarea:enabled::-webkit-resizer { + background-size: 10px 10px; + background: #252525 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAIAAAACUFjqAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAXSURBVChTY1RVVWXADZigNA4wMqUZGACS3gCD5UUtKAAAAABJRU5ErkJggg==) no-repeat bottom right; +} +textarea:focus::-webkit-resizer { + background-size: 10px 10px; + background: #000000 url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACOSURBVChThdC5DQQhDAXQvyRI5LQxFdABARWQElAPogYkiqEWQhLYGe8xxzJaS5a/8AuQHwDG2n+Lvee0hBDQWlO+hRvy3mNZFjDG5vCDOOeIMaL3/guPKISAWiu9n+AVSSlhraXdF86Qcw6tNdoTvEOlFOScd6iUOv3JGEMopYQx9jNvaawnoHnNr8Z4AuRLPOq2gPgnAAAAAElFTkSuQmCC) no-repeat bottom right; +} +textarea:enabled[scrolling="true"]::-webkit-resizer { + background-size: 10px 10px; + background: #2e2e2e url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAACKSURBVChTjdAxDsMgDAXQT4UYuQIzCwsSKxsSJ4YDoByDY7AwUOG2aZMQqX+xhd9gzIwxA3/k8a7LCCFgraX+Fk4UY4RSCoyxNfwgzjlyzhhjXOEvSimhtUbvB3hGUkp472m2wxUKIaD3TnOCd6jWim3bvlBrfdjJOUeolEJoZj/4PMH83bl/BXgCWSs2Z09IjgoAAAAASUVORK5CYII=) no-repeat bottom right; +} + + +div#grid-section, body#entity-list-body { + padding-bottom: 0; + margin: 16px; +} + +#entity-list-header { + margin-bottom: 36px; +} + +#entity-list-header div { + display: inline-block; + width: 65px; + margin-right: 6px; +} + +#entity-list-header div input:first-child { + margin-right: 0; + float: left; + width: 33px; + border-right: 1px solid #808080; + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +#entity-list-header div input:last-child { + margin-right: 0; + float: right; + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +#delete { + float: right; + margin-right: 0; + background-color: #ff0000; +} + +#entity-list { + position: relative; /* New positioning context. */ +} + +#filter-area { + padding-right: 168px; + padding-bottom: 24px; +} + +#filter-type-multiselect-box select { + border-radius: 14.5px; + width: 107px; + height: 28px; +} +#filter-type-options { + position: absolute; + top: 48px; +} +#filter-type-options div { + position: relative; + height: 22px; +} +#filter-type-options span { + position: relative; + top: 3px; + font-family: HiFi-Glyphs; + font-size: 13px; + color: #000000; + padding-left: 6px; + padding-right: 4px; +} +#filter-type-options label { + position: absolute; + top: -20px; + z-index: 2; + height: 22px; + width: 200px; + padding-top: 1px; +} +#filter-type-options-buttons { + top: -22px; + width: 224px; + z-index: 2; + background-color: #afafaf; + padding-bottom: 6px; +} +#filter-type-options input[type=button] { + position: relative; + left: 16px; + z-index: 3; + height: 23px; + min-width: 60px; + font-size: 10px; + color: #000; + background: linear-gradient(#afafaf 20%, #808080 100%); +} +#filter-type-options input[type=button]:enabled:hover { + background: linear-gradient(#afafaf 20%, #575757 100%); +} + +#filter-search-and-icon { + position: relative; + left: 118px; + width: calc(100% - 126px); +} + +#filter-in-view { + position: absolute; + top: 0; + right: 126px; +} + +#filter-radius-and-unit { + position: relative; + float: right; + margin-right: -168px; + top: -45px; +} +#filter-radius-and-unit label { + margin-left: 2px; +} +#filter-radius-and-unit span { + position: relative; + top: 25px; + right: 9px; + z-index: 2; + font-style: italic; +} +#filter-radius-and-unit input { + width: 120px; + border-radius: 14.5px; + font-style: italic; +} +#filter-radius-and-unit input[type=number]::-webkit-inner-spin-button { + display: none; +} + +#entity-list-footer { + padding-top: 9px; +} + +#footer-text { + float: right; + padding-top: 12px; + padding-right: 22px; +} + +input[type=button]#export { + height: 38px; + width: 180px; +} + +#no-entities { + display: none; + position: absolute; + top: 80px; + padding: 12px; + font-family: FiraSans-SemiBold; + font-size: 15px; + font-style: italic; + color: #afafaf; +} + +#entity-table-columns-multiselect { + position: absolute; + top: 51px; + right: 22px; +} +#entity-table-columns-multiselect-box select { + height: 28px; + width: 20px; + background-color: #1c1c1c; + border-top-right-radius: 7px; +} +#entity-table-columns-options { + position: absolute; + top: 50px; + right: 110px; +} +#entity-table-columns-options div { + position: relative; + height: 22px; +} +#entity-table-columns-options label { + position: absolute; + top: -22px; + height: 22px; + width: 100px; + padding-top: 4px; +} +#entity-table-columns-options input[type=checkbox] + label { + padding-left: 30px; +} + +#entity-table-scroll { + /* Height is set by JavaScript. */ + width: 100%; + overflow-x: hidden; + overflow-y: auto; + box-sizing: border-box; + padding-top: 28px; /* Space for header and footer outside of scroll region. */ + margin-top: 28px; + border-left: 2px solid #575757; + border-right: 2px solid #575757; + border-bottom: 2px solid #575757; + border-bottom-left-radius: 7px; + border-bottom-right-radius: 7px; + background-color: #1c1c1c; +} + +#entity-table-scroll .glyph { + font-family: HiFi-Glyphs; + font-size: 15px; +} + +#entity-table { + margin-top: -28px; + margin-bottom: -18px; + table-layout: fixed; + border: none; + background-color: #1c1c1c; +} + +#entity-table thead tr, #entity-table thead tr th { + background: none; +} + +#entity-table .glyph { + margin: 0 -2px 0 -2px; + vertical-align: middle; +} + +#entity-table thead { + box-sizing: border-box; + border: 2px solid #575757; + border-top-left-radius: 7px; + border-top-right-radius: 7px; + border-bottom: 1px solid #575757; + position: absolute; + top: 49px; + left: 0; + width: 100%; + word-wrap: nowrap; + white-space: nowrap; + overflow: hidden; +} + +#entity-table th { + display: inline-block; + box-sizing: border-box; + padding: 5px 0 0 0; + vertical-align: middle; + overflow: hidden; + text-overflow: ellipsis; +} + +#entity-table th:focus { + outline: none; +} + +#entity-table th .glyph { + position: relative; + left: 4px; +} +#entity-table th .glyph + .sort-order { + position: relative; + left: 4px; +} + +#entity-table thead .sort-order { + display: inline-block; + width: 8px; + margin: -5px 0 -3px 0; + vertical-align: middle; +} + +#entity-table thead .resizer { + position: absolute; + top: 1px; + height: 26px; + width: 10px; + cursor: col-resize; +} + +#entity-table .dragging { + background-color: #b3ecff; +} + +#entity-table td { + box-sizing: border-box; +} +#entity-table td.glyph { + text-align: center; + padding: 0; +} + +#properties-base { + border-top: none !important; + box-shadow: none !important; + margin-bottom: 5px !important; +} + +#properties-base #property-type-icon { + font-family: HiFi-Glyphs; + font-size: 31px; + color: #00b4ef; + margin: -4px 12px -4px -2px; + width: auto; + display: none; +} + +#properties-base #property-type { + padding: 5px 24px 5px 0; + border-right: 1px solid #808080; + width: auto; + display: inline-block; +} + +#properties-base .checkbox label span { + font-family: HiFi-Glyphs; + font-size: 20px; + padding-right: 6px; + vertical-align: top; + position: relative; + top: -4px; +} + +#properties-base input[type=checkbox]:checked + label span { + color: #ffffff; +} + +#id label { + width: 24px; +} +#property-id { + display: inline-block; +} +#property-id::selection { + color: #000000; + background-color: #00b4ef; +} + +input#property-scale-button-rescale { + min-width: 50px; + left: 152px; +} +input#property-scale-button-reset { + margin-right: 0; + left: 250px; +} + +#property-userData-static, +#property-materialData-static { + display: none; + z-index: 99; + position: absolute; + width: 96%; + padding-left: 1%; + margin-top: 5px; + margin-bottom: 10px; + background-color: #2e2e2e; +} + +#property-userData-saved, +#property-materialData-saved { + margin-top: 5px; + font-size: 16px; + display: none; +} + + +#div-property-collisionSoundURL[style*="display: none"] + .property { + margin-top: 0; +} + +.context-menu { + display: none; + position: fixed; + color: #000000; + background-color: #afafaf; + padding: 5px 0 5px 0; + cursor: default; +} +.context-menu li { + list-style-type: none; + padding: 4px 18px 4px 18px; + margin: 0; + white-space: nowrap; +} +.context-menu li:hover { + background-color: #e3e3e3; +} +.context-menu li.separator { + border-top: 1px solid #333333; + margin: 5px 5px; + padding: 0 0; +} +.context-menu li.disabled { + color: #333333; +} +.context-menu li.separator:hover, .context-menu li.disabled:hover { + background-color: #afafaf; +} + +input.rename-entity { + height: 100%; + width: 100%; + border: none; + font-family: FiraSans-SemiBold; + font-size: 15px; + /* need this to show the text cursor when the input field is empty */ + padding-left: 2px; +} + +.create-app-tooltip { + z-index: 100; + position: absolute; + background: #6a6a6a; + border: 1px solid black; + width: 258px; + min-height: 20px; + padding: 5px; + z-index: 100; +} + +.create-app-tooltip .create-app-tooltip-description { + font-size: 12px; + font-style: italic; + color: #ffffff; +} + +.create-app-tooltip .create-app-tooltip-js-attribute { + font-family: Raleway-SemiBold; + font-size: 11px; + color: #000000; + bottom: 0; + margin-top: 5px; +} + +#toggle-space-mode::before { + font-family: HiFi-Glyphs; + font-size: 20px; + text-transform: none; + min-width: 32px; + padding-right: 4px; + vertical-align: middle; +} + +#toggle-space-mode.space-mode-local::before { + content: "m"; +} + +#toggle-space-mode.space-mode-world::before { + content: "\e02c"; +} + +.container { + display: flex; + flex-flow: row nowrap; + margin-bottom: 8px; + min-height: 28px; +} + +.container > label { + margin-top: 6px; + width: 160px; + min-width: 160px; + max-width: 160px; +} + +.container > div.checkbox { + padding-top: 6px; +} + +.container > .value { + width: 100%; +} + +.container .row { + display: flex; + flex-flow: row nowrap; +} + +.container.shrink { + width: min-content; +} + +.fstuple { + display: flex; + flex-flow: row; +} +.fstuple input { + margin-left: 4px; + margin-right: 10px; +} +.fstuple label.red, .fstuple label.x, .fstuple label.w { + color: #C62147; +} +.fstuple label.green, .fstuple label.y, .fstuple label.h { + color: #359D85; +} +.fstuple label.blue, .fstuple label.z { + color: #0093C5; +} + +.xyz.fstuple, .pyr.fstuple { + position: relative; + left: -12px; + min-width: 50px; + width: 100px; +} + +.rgb.fstuple .tuple { + display: none; +} + +input.number-slider { + background: #575757; + border-radius: 4px; + color: white; +} + +.fstuple > div { + display: flex; + align-items: center; + justify-content: left; +} + +.flex-row { + display: flex; + flex-flow: row; +} + +.flex-column { + display: flex; + flex-flow: column; +} + +.flex-center { + align-items: center; +} + +.flex-evenly-spaced { + flex: 1; +} + +#property-serverScripts-status { + font-family: Raleway-Light; + font-size: 14px; + margin: 6px 0; + cursor: default; +} + +#property-name, #property-id { + display: flex; + width: 100%; +} + +.spacemode-hidden { + display: none; +} + +#placeholder-property-type { + min-width: 0; +} + +.collapse-icon { + cursor: pointer; +} + +#property-userData-editor.error { + border: 2px solid red; +} + +#property-userData-editorStatus { + color: white; + background-color: red; + padding: 5px; + display: none; + cursor: pointer; +} + +#property-materialData-editor.error { + border: 2px solid red; +} + +#property-materialData-editorStatus { + color: white; + background-color: red; + padding: 5px; + display: none; + cursor: pointer; +} + +input[type=number].hide-spinner::-webkit-inner-spin-button { + -webkit-appearance: none; + visibility: hidden; +} + +div.jsoneditor-menu a.jsoneditor-poweredBy { + display: none; +} +td.zoneItem { + width: 100%; +} + +select.zoneSelect { + clear: both; + cursor: pointer; + font-family: FiraSans-SemiBold; + font-size: 15px; + width: 90%; + height: 28px; + padding: 0 28px 0 12px; + color: #afafaf; + background: #575757; + position: relative; + display: inline; + border: 0px; + align-items: center; + outline: none; +} + +div.multiZoneSelToolbar { + padding: 0px; +} + From 0afca55e18f1867b5c7f86a7e1d4f308e7776a12 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Fri, 3 Apr 2020 23:32:45 -0400 Subject: [PATCH 037/105] Add the new property "renderWithZones" This adds the Tooltip for new property "renderWithZones" (Required for PR#78) --- .../create/assets/data/createAppTooltips.json | 49 +++++++++++++++---- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 24f443f901..d473dc5a8e 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -3,7 +3,10 @@ "tooltip": "The shape of this entity's geometry." }, "color": { - "tooltip": "The RGB value of this entity." + "tooltip": "The color of this entity." + }, + "shapeAlpha": { + "tooltip": "Set the opacity of the entity between 0.0 fully transparent and 1.0 completely opaque." }, "text": { "tooltip": "The text to display on the entity." @@ -12,17 +15,29 @@ "tooltip": "The color of the text." }, "textAlpha": { - "tooltip": "The alpha of the text." + "tooltip": "Set the opacity of the text between 0.0 fully transparent and 1.0 completely opaque." }, "backgroundColor": { "tooltip": "The color of the background." }, "backgroundAlpha": { - "tooltip": "The alpha of the background." + "tooltip": "Set the opacity of the background between 0.0 fully transparent and 1.0 completely opaque." }, "lineHeight": { "tooltip": "The height of each line of text. This determines the size of the text." }, + "font": { + "tooltip": "The font to render the text. Supported values: \"Courier\", \"Inconsolata\", \"Roboto\", \"Timeless\", or a URL to a .sdff file." + }, + "textEffect": { + "tooltip": "The effect that is applied to the text." + }, + "textEffectColor": { + "tooltip": "The color of the text effect." + }, + "textEffectThickness": { + "tooltip": "The magnitude of the text effect." + }, "textBillboardMode": { "tooltip": "If enabled, determines how the entity will face the camera.", "jsPropertyName": "billboardMode" @@ -196,6 +211,9 @@ "tooltip": "The tint to be applied to the image.", "jsPropertyName": "color" }, + "imageAlpha": { + "tooltip": "Set the opacity of the image between 0.0 fully transparent and 1.0 completely opaque." + }, "emissive": { "tooltip": "If enabled, the image will display at full brightness." }, @@ -215,6 +233,16 @@ "dpi": { "tooltip": "The resolution to display the page at, in pixels per inch. Use this to resize your web source in the frame." }, + "webBillboardMode": { + "tooltip": "If enabled, determines how the entity will face the camera.", + "jsPropertyName": "billboardMode" + }, + "inputMode": { + "tooltip": "The user input mode to use." + }, + "showKeyboardFocusHighlight": { + "tooltip": "If enabled, highlights when it has keyboard focus." + }, "isEmitting": { "tooltip": "If enabled, then particles are emitted." }, @@ -291,20 +319,20 @@ "tooltip": "The spread in color that each particle is given, resulting in a variety of colors." }, "particleAlphaTriple": { - "tooltip": "The alpha of each particle.", + "tooltip": "Set the opacity of the each particle between 0.0 fully transparent and 1.0 completely opaque.", "jsPropertyName": "alpha" }, "alpha": { - "tooltip": "The alpha of each particle." + "tooltip": "Set the opacity of the each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaStart": { - "tooltip": "The start alpha of each particle." + "tooltip": "Set the initial opacity level of the each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaFinish": { - "tooltip": "The finish alpha of each particle." + "tooltip": "Set the final opacity level of the each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaSpread": { - "tooltip": "The spread in alpha that each particle is given, resulting in a variety of alphas." + "tooltip": "The spread in opacity that each particle is given, resulting in a variety of opacity levels." }, "emitAcceleration": { "tooltip": "The acceleration that is applied to each particle during its lifetime." @@ -567,6 +595,9 @@ "primitiveMode": { "tooltip": "The mode in which to draw an entity, either \"Solid\" or \"Wireframe\"." }, + "renderWithZones": { + "tooltip": "This entity will be rendered only from the specified zones. If not specified, the entity will be always rendered." + }, "groupCulled": { "tooltip": "If false, individual pieces of the entity may be culled by the render engine. If true, either the entire entity will be culled, or it won't at all." }, @@ -574,7 +605,7 @@ "tooltip": "The tint of the web entity." }, "webAlpha": { - "tooltip": "The alpha of the web entity." + "tooltip": "Set the opacity of the web entity between 0.0 fully transparent and 1.0 completely opaque." }, "maxFPS": { "tooltip": "The FPS at which to render the web entity. Higher values will have a performance impact." From 16c5d8c051e073cb5e411587eef143a90f206def Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Fri, 3 Apr 2020 23:37:18 -0400 Subject: [PATCH 038/105] Support for "Multiple Zones Selector" Renderer Add the code to expose the Zones list to the entityProperty. as support for the new "Multiple Zones Selector" Renderer type. (Required to support the new property "renderWithZones" for PR #78) --- scripts/system/create/edit.js | 5739 +++++++++++++++++---------------- 1 file changed, 2881 insertions(+), 2858 deletions(-) diff --git a/scripts/system/create/edit.js b/scripts/system/create/edit.js index ef07aa4d6e..1ab8b7f75d 100644 --- a/scripts/system/create/edit.js +++ b/scripts/system/create/edit.js @@ -1,2858 +1,2881 @@ -// edit.js -// -// Created by Brad Hefta-Gaub on 10/2/14. -// Persist toolbar by HRS 6/11/15. -// Copyright 2014 High Fidelity, Inc. -// -// This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager, - Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, - progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, OverlaySystemWindow, - keyUpEventFromUIWindow:true */ - -(function() { // BEGIN LOCAL_SCOPE - -"use strict"; - -var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton"; - -var CONTROLLER_MAPPING_NAME = "com.highfidelity.editMode"; - -Script.include([ - "../libraries/stringHelpers.js", - "../libraries/dataViewHelpers.js", - "../libraries/progressDialog.js", - "../libraries/ToolTip.js", - "../libraries/entityCameraTool.js", - "../libraries/utils.js", - "../libraries/entityIconOverlayManager.js", - "../libraries/gridTool.js", - "entityList/entityList.js", - "entitySelectionTool/entitySelectionTool.js" -]); - -var CreateWindow = Script.require('./modules/createWindow.js'); - -var TITLE_OFFSET = 60; -var CREATE_TOOLS_WIDTH = 490; -var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942; - -var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg"; - -var createToolsWindow = new CreateWindow( - Script.resolvePath("qml/EditTools.qml"), - 'Create Tools', - 'com.highfidelity.create.createToolsWindow', - function () { - var windowHeight = Window.innerHeight - TITLE_OFFSET; - if (windowHeight > MAX_DEFAULT_ENTITY_LIST_HEIGHT) { - windowHeight = MAX_DEFAULT_ENTITY_LIST_HEIGHT; - } - return { - size: { - x: CREATE_TOOLS_WIDTH, - y: windowHeight - }, - position: { - x: Window.x + Window.innerWidth - CREATE_TOOLS_WIDTH, - y: Window.y + TITLE_OFFSET - } - } - }, - false -); - -/** - * @description Returns true in case we should use the tablet version of the CreateApp - * @returns boolean - */ -var shouldUseEditTabletApp = function() { - return HMD.active || (!HMD.active && !Settings.getValue("desktopTabletBecomesToolbar", true)); -}; - - -var selectionDisplay = SelectionDisplay; -var selectionManager = SelectionManager; - -var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg"); -var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg"); -var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg"); -var ZONE_URL = Script.resolvePath("assets/images/icon-zone.svg"); - -var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect', 'Zone'], function(entityID) { - var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']); - if (properties.type === 'Light') { - return { - url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, - }; - } else if (properties.type === 'Zone') { - return { - url: ZONE_URL, - }; - } else { - return { - url: PARTICLE_SYSTEM_URL, - }; - } -}); - -var cameraManager = new CameraManager(); - -var grid = new Grid(); -var gridTool = new GridTool({ - horizontalGrid: grid, - createToolsWindow: createToolsWindow, - shouldUseEditTabletApp: shouldUseEditTabletApp -}); -gridTool.setVisible(false); - -var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js'); -var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"]); - -var entityListTool = new EntityListTool(shouldUseEditTabletApp); - -selectionManager.addEventListener(function () { - selectionDisplay.updateHandles(); - entityIconOverlayManager.updatePositions(); - entityShapeVisualizer.setEntities(selectionManager.selections); -}); - -var DEGREES_TO_RADIANS = Math.PI / 180.0; -var RADIANS_TO_DEGREES = 180.0 / Math.PI; - -var MIN_ANGULAR_SIZE = 2; -var MAX_ANGULAR_SIZE = 45; -var allowLargeModels = true; -var allowSmallModels = true; - -var DEFAULT_DIMENSION = 0.20; - -var DEFAULT_DIMENSIONS = { - x: DEFAULT_DIMENSION, - y: DEFAULT_DIMENSION, - z: DEFAULT_DIMENSION -}; - -var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); - -var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; -var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; -var MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Create Mode"; -var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Create Mode"; - -var MENU_CREATE_ENTITIES_GRABBABLE = "Create Entities As Grabbable (except Zones, Particles, and Lights)"; -var MENU_ALLOW_SELECTION_LARGE = "Allow Selecting of Large Models"; -var MENU_ALLOW_SELECTION_SMALL = "Allow Selecting of Small Models"; -var MENU_ALLOW_SELECTION_LIGHTS = "Allow Selecting of Lights"; - -var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; -var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; -var SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "showLightsAndParticlesInEditMode"; -var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; - -var SETTING_EDIT_PREFIX = "Edit/"; - - -var CREATE_ENABLED_ICON = "icons/tablet-icons/edit-i.svg"; -var CREATE_DISABLED_ICON = "icons/tablet-icons/edit-disabled.svg"; - -// marketplace info, etc. not quite ready yet. -var SHOULD_SHOW_PROPERTY_MENU = false; -var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain."; -var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain."; - -var isActive = false; -var createButton = null; - -var IMPORTING_SVO_OVERLAY_WIDTH = 144; -var IMPORTING_SVO_OVERLAY_HEIGHT = 30; -var IMPORTING_SVO_OVERLAY_MARGIN = 5; -var IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; -var importingSVOImageOverlay = Overlays.addOverlay("image", { - imageURL: Script.resolvePath("assets/images/hourglass.svg"), - width: 20, - height: 20, - alpha: 1.0, - x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH, - y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT, - visible: false -}); -var importingSVOTextOverlay = Overlays.addOverlay("text", { - font: { - size: 14 - }, - text: "Importing SVO...", - leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN, - x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN, - y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN, - width: IMPORTING_SVO_OVERLAY_WIDTH, - height: IMPORTING_SVO_OVERLAY_HEIGHT, - backgroundColor: { - red: 80, - green: 80, - blue: 80 - }, - backgroundAlpha: 0.7, - visible: false -}); - -var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace"; -var marketplaceWindow = new OverlayWebWindow({ - title: 'Marketplace', - source: "about:blank", - width: 900, - height: 700, - visible: false -}); - -function showMarketplace(marketplaceID) { - var url = MARKETPLACE_URL; - if (marketplaceID) { - url = url + "/items/" + marketplaceID; - } - marketplaceWindow.setURL(url); - marketplaceWindow.setVisible(true); - marketplaceWindow.raise(); - - UserActivityLogger.logAction("opened_marketplace"); -} - -function hideMarketplace() { - marketplaceWindow.setVisible(false); - marketplaceWindow.setURL("about:blank"); -} - -// function toggleMarketplace() { -// if (marketplaceWindow.visible) { -// hideMarketplace(); -// } else { -// showMarketplace(); -// } -// } - -function adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation) { - // Adjust the position such that the bounding box (registration, dimensions and orientation) lies behind the original - // position in the given direction. - var CORNERS = [ - { x: 0, y: 0, z: 0 }, - { x: 0, y: 0, z: 1 }, - { x: 0, y: 1, z: 0 }, - { x: 0, y: 1, z: 1 }, - { x: 1, y: 0, z: 0 }, - { x: 1, y: 0, z: 1 }, - { x: 1, y: 1, z: 0 }, - { x: 1, y: 1, z: 1 }, - ]; - - // Go through all corners and find least (most negative) distance in front of position. - var distance = 0; - for (var i = 0, length = CORNERS.length; i < length; i++) { - var cornerVector = - Vec3.multiplyQbyV(orientation, Vec3.multiplyVbyV(Vec3.subtract(CORNERS[i], registration), dimensions)); - var cornerDistance = Vec3.dot(cornerVector, direction); - distance = Math.min(cornerDistance, distance); - } - position = Vec3.sum(Vec3.multiply(distance, direction), position); - return position; -} - -var GRABBABLE_ENTITIES_MENU_CATEGORY = "Edit"; - -// Handles any edit mode updates required when domains have switched -function checkEditPermissionsAndUpdate() { - if ((createButton === null) || (createButton === undefined)) { - //--EARLY EXIT--( nothing to safely update ) - return; - } - - var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); - createButton.editProperties({ - icon: (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON), - captionColor: (hasRezPermissions ? "#ffffff" : "#888888"), - }); - - if (!hasRezPermissions && isActive) { - that.setActive(false); - tablet.gotoHomeScreen(); - } -} - -// Copies the properties in `b` into `a`. `a` will be modified. -function copyProperties(a, b) { - for (var key in b) { - a[key] = b[key]; - } - return a; -} - -const DEFAULT_DYNAMIC_PROPERTIES = { - dynamic: true, - damping: 0.39347, - angularDamping: 0.39347, - gravity: { x: 0, y: -9.8, z: 0 }, -}; - -const DEFAULT_NON_DYNAMIC_PROPERTIES = { - dynamic: false, - damping: 0, - angularDamping: 0, - gravity: { x: 0, y: 0, z: 0 }, -}; - -const DEFAULT_ENTITY_PROPERTIES = { - All: { - description: "", - rotation: { x: 0, y: 0, z: 0, w: 1 }, - collidesWith: "static,dynamic,kinematic,otherAvatar,myAvatar", - collisionSoundURL: "", - cloneable: false, - ignoreIK: true, - canCastShadow: true, - href: "", - script: "", - serverScripts:"", - velocity: { - x: 0, - y: 0, - z: 0 - }, - angularVelocity: { - x: 0, - y: 0, - z: 0 - }, - restitution: 0.5, - friction: 0.5, - density: 1000, - dynamic: false, - }, - Shape: { - shape: "Box", - dimensions: { x: 0.2, y: 0.2, z: 0.2 }, - color: { red: 0, green: 180, blue: 239 }, - }, - Text: { - text: "Text", - dimensions: { - x: 0.65, - y: 0.3, - z: 0.01 - }, - textColor: { red: 255, green: 255, blue: 255 }, - backgroundColor: { red: 0, green: 0, blue: 0 }, - lineHeight: 0.06, - faceCamera: false, - }, - Zone: { - dimensions: { - x: 10, - y: 10, - z: 10 - }, - flyingAllowed: true, - ghostingAllowed: true, - filter: "", - keyLightMode: "inherit", - keyLightColor: { red: 255, green: 255, blue: 255 }, - keyLight: { - intensity: 1.0, - direction: { - x: 0.0, - y: -0.707106769084930, // 45 degrees - z: 0.7071067690849304 - }, - castShadows: true - }, - ambientLightMode: "inherit", - ambientLight: { - ambientIntensity: 0.5, - ambientURL: "" - }, - hazeMode: "inherit", - haze: { - hazeRange: 1000, - hazeAltitudeEffect: false, - hazeBaseRef: 0, - hazeColor: { - red: 128, - green: 154, - blue: 179 - }, - hazeBackgroundBlend: 0, - hazeEnableGlare: false, - hazeGlareColor: { - red: 255, - green: 229, - blue: 179 - }, - }, - shapeType: "box", - bloomMode: "inherit", - avatarPriority: "inherit" - }, - Model: { - collisionShape: "none", - compoundShapeURL: "", - animation: { - url: "", - running: false, - allowTranslation: false, - loop: true, - hold: false, - currentFrame: 0, - firstFrame: 0, - lastFrame: 100000, - fps: 30.0, - } - }, - Image: { - dimensions: { - x: 0.5385, - y: 0.2819, - z: 0.0092 - }, - shapeType: "box", - collisionless: true, - keepAspectRatio: false, - imageURL: DEFAULT_IMAGE - }, - Web: { - dimensions: { - x: 1.6, - y: 0.9, - z: 0.01 - }, - sourceUrl: "https://projectathena.io/", - dpi: 30, - }, - ParticleEffect: { - lifespan: 1.5, - maxParticles: 10, - textures: "https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png", - emitRate: 5.5, - emitSpeed: 0, - speedSpread: 0, - emitDimensions: { x: 0, y: 0, z: 0 }, - emitOrientation: { x: 0, y: 0, z: 0, w: 1 }, - emitterShouldTrail: true, - particleRadius: 0.25, - radiusStart: 0, - radiusSpread: 0, - particleColor: { - red: 255, - green: 255, - blue: 255 - }, - colorSpread: { - red: 0, - green: 0, - blue: 0 - }, - alpha: 0, - alphaStart: 1, - alphaSpread: 0, - emitAcceleration: { - x: 0, - y: 2.5, - z: 0 - }, - accelerationSpread: { - x: 0, - y: 0, - z: 0 - }, - particleSpin: 0, - spinSpread: 0, - rotateWithEntity: false, - polarStart: 0, - polarFinish: Math.PI, - azimuthStart: -Math.PI, - azimuthFinish: Math.PI - }, - Light: { - color: { red: 255, green: 255, blue: 255 }, - intensity: 5.0, - dimensions: DEFAULT_LIGHT_DIMENSIONS, - falloffRadius: 1.0, - isSpotlight: false, - exponent: 1.0, - cutoff: 75.0, - }, -}; - -var toolBar = (function () { - var EDIT_SETTING = "io.highfidelity.isEditing"; // for communication with other scripts - var that = {}, - toolBar, - activeButton = null, - systemToolbar = null, - dialogWindow = null, - tablet = null; - - function createNewEntity(requestedProperties) { - var dimensions = requestedProperties.dimensions ? requestedProperties.dimensions : DEFAULT_DIMENSIONS; - var position = getPositionToCreateEntity(); - var entityID = null; - - var properties = {}; - - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.All); - - var type = requestedProperties.type; - if (type === "Box" || type === "Sphere") { - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.Shape); - } else { - copyProperties(properties, DEFAULT_ENTITY_PROPERTIES[type]); - } - - // We apply the requested properties first so that they take priority over any default properties. - copyProperties(properties, requestedProperties); - - if (properties.dynamic) { - copyProperties(properties, DEFAULT_DYNAMIC_PROPERTIES); - } else { - copyProperties(properties, DEFAULT_NON_DYNAMIC_PROPERTIES); - } - - - if (position !== null && position !== undefined) { - var direction; - if (Camera.mode === "entity" || Camera.mode === "independent") { - direction = Camera.orientation; - } else { - direction = MyAvatar.orientation; - } - direction = Vec3.multiplyQbyV(direction, Vec3.UNIT_Z); - - var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web", "Material"]; - if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { - - // Adjust position of entity per bounding box prior to creating it. - var registration = properties.registration; - if (registration === undefined) { - var DEFAULT_REGISTRATION = { x: 0.5, y: 0.5, z: 0.5 }; - registration = DEFAULT_REGISTRATION; - } - - var orientation = properties.orientation; - if (orientation === undefined) { - properties.orientation = MyAvatar.orientation; - var DEFAULT_ORIENTATION = properties.orientation; - orientation = DEFAULT_ORIENTATION; - } else { - // If the orientation is already defined, we perform the corresponding rotation assuming that - // our start referential is the avatar referential. - properties.orientation = Quat.multiply(MyAvatar.orientation, properties.orientation); - var DEFAULT_ORIENTATION = properties.orientation; - orientation = DEFAULT_ORIENTATION; - } - - position = adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation); - } - - position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions); - properties.position = position; - - if (!properties.grab) { - properties.grab = {}; - if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) && - !(properties.type === "Zone" || properties.type === "Light" || properties.type === "ParticleEffect")) { - properties.grab.grabbable = true; - } else { - properties.grab.grabbable = false; - } - } - - entityID = Entities.addEntity(properties); - SelectionManager.addEntity(entityID, false, this); - SelectionManager.saveProperties(); - pushCommandForSelections([{ - entityID: entityID, - properties: properties - }], [], true); - - var POST_ADJUST_ENTITY_TYPES = ["Model"]; - if (POST_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { - // Adjust position of entity per bounding box after it has been created and auto-resized. - var initialDimensions = Entities.getEntityProperties(entityID, ["dimensions"]).dimensions; - var DIMENSIONS_CHECK_INTERVAL = 200; - var MAX_DIMENSIONS_CHECKS = 10; - var dimensionsCheckCount = 0; - var dimensionsCheckFunction = function () { - dimensionsCheckCount++; - var properties = Entities.getEntityProperties(entityID, ["dimensions", "registrationPoint", "rotation"]); - if (!Vec3.equal(properties.dimensions, initialDimensions)) { - position = adjustPositionPerBoundingBox(position, direction, properties.registrationPoint, - properties.dimensions, properties.rotation); - position = grid.snapToSurface(grid.snapToGrid(position, false, properties.dimensions), - properties.dimensions); - Entities.editEntity(entityID, { - position: position - }); - selectionManager._update(false, this); - } else if (dimensionsCheckCount < MAX_DIMENSIONS_CHECKS) { - Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL); - } - }; - Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL); - } - } else { - Window.notifyEditError("Can't create " + properties.type + ": " + - properties.type + " would be out of bounds."); - } - - selectionManager.clearSelections(this); - entityListTool.sendUpdate(); - selectionManager.setSelections([entityID], this); - - Window.setFocus(); - - return entityID; - } - - function closeExistingDialogWindow() { - if (dialogWindow) { - dialogWindow.close(); - dialogWindow = null; - } - } - - function cleanup() { - that.setActive(false); - if (tablet) { - tablet.removeButton(activeButton); - } - if (systemToolbar) { - systemToolbar.removeButton(EDIT_TOGGLE_BUTTON); - } - } - - var buttonHandlers = {}; // only used to tablet mode - - function addButton(name, handler) { - buttonHandlers[name] = handler; - } - - var SHAPE_TYPE_NONE = 0; - var SHAPE_TYPE_SIMPLE_HULL = 1; - var SHAPE_TYPE_SIMPLE_COMPOUND = 2; - var SHAPE_TYPE_STATIC_MESH = 3; - var SHAPE_TYPE_BOX = 4; - var SHAPE_TYPE_SPHERE = 5; - var DYNAMIC_DEFAULT = false; - - var MATERIAL_MODE_UV = 0; - var MATERIAL_MODE_PROJECTED = 1; - - function handleNewModelDialogResult(result) { - if (result) { - var url = result.url; - var shapeType; - switch (result.collisionShapeIndex) { - case SHAPE_TYPE_SIMPLE_HULL: - shapeType = "simple-hull"; - break; - case SHAPE_TYPE_SIMPLE_COMPOUND: - shapeType = "simple-compound"; - break; - case SHAPE_TYPE_STATIC_MESH: - shapeType = "static-mesh"; - break; - case SHAPE_TYPE_BOX: - shapeType = "box"; - break; - case SHAPE_TYPE_SPHERE: - shapeType = "sphere"; - break; - default: - shapeType = "none"; - } - - var dynamic = result.dynamic !== null ? result.dynamic : DYNAMIC_DEFAULT; - if (shapeType === "static-mesh" && dynamic) { - // The prompt should prevent this case - print("Error: model cannot be both static mesh and dynamic. This should never happen."); - } else if (url) { - createNewEntity({ - type: "Model", - modelURL: url, - shapeType: shapeType, - grab: { - grabbable: result.grabbable - }, - dynamic: dynamic, - }); - } - } - } - - function handleNewMaterialDialogResult(result) { - if (result) { - var materialURL = result.textInput; - //var materialMappingMode; - //switch (result.comboBox) { - // case MATERIAL_MODE_PROJECTED: - // materialMappingMode = "projected"; - // break; - // default: - // shapeType = "uv"; - //} - var materialData = ""; - if (materialURL.startsWith("materialData")) { - materialData = JSON.stringify({ - "materials": {} - }); - } - - var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1; - if (materialURL) { - createNewEntity({ - type: "Material", - materialURL: materialURL, - //materialMappingMode: materialMappingMode, - priority: DEFAULT_LAYERED_MATERIAL_PRIORITY, - materialData: materialData - }); - } - } - } - - function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - tablet.popFromStack(); - switch (message.method) { - case "newModelDialogAdd": - handleNewModelDialogResult(message.params); - closeExistingDialogWindow(); - break; - case "newModelDialogCancel": - closeExistingDialogWindow(); - break; - case "newEntityButtonClicked": - buttonHandlers[message.params.buttonName](); - break; - case "newMaterialDialogAdd": - handleNewMaterialDialogResult(message.params); - closeExistingDialogWindow(); - break; - case "newMaterialDialogCancel": - closeExistingDialogWindow(); - break; - } - } - - var entitiesToDelete = []; - var deletedEntityTimer = null; - var DELETE_ENTITY_TIMER_TIMEOUT = 100; - - function checkDeletedEntityAndUpdate(entityID) { - // Allow for multiple entity deletes before updating the entities selected. - entitiesToDelete.push(entityID); - if (deletedEntityTimer !== null) { - Script.clearTimeout(deletedEntityTimer); - } - deletedEntityTimer = Script.setTimeout(function () { - if (entitiesToDelete.length > 0) { - selectionManager.removeEntities(entitiesToDelete, this); - } - entityListTool.removeEntities(entitiesToDelete, selectionManager.selections); - entitiesToDelete = []; - deletedEntityTimer = null; - }, DELETE_ENTITY_TIMER_TIMEOUT); - } - - function initialize() { - Script.scriptEnding.connect(cleanup); - Window.domainChanged.connect(function () { - if (isActive) { - tablet.gotoHomeScreen(); - } - that.setActive(false); - that.clearEntityList(); - checkEditPermissionsAndUpdate(); - }); - - HMD.displayModeChanged.connect(function() { - if (isActive) { - tablet.gotoHomeScreen(); - } - that.setActive(false); - }); - - Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) { - if (isActive && !canAdjustLocks) { - that.setActive(false); - } - checkEditPermissionsAndUpdate(); - }); - - Entities.canRezChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezTmpChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezCertifiedChanged.connect(checkEditPermissionsAndUpdate); - Entities.canRezTmpCertifiedChanged.connect(checkEditPermissionsAndUpdate); - var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); - - Entities.deletingEntity.connect(checkDeletedEntityAndUpdate); - - var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON); - tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - activeButton = tablet.addButton({ - captionColor: hasRezPermissions ? "#ffffff" : "#888888", - icon: createButtonIconRsrc, - activeIcon: "icons/tablet-icons/edit-a.svg", - text: "CREATE", - sortOrder: 10 - }); - createButton = activeButton; - tablet.screenChanged.connect(function (type, url) { - var isGoingToHomescreenOnDesktop = (!shouldUseEditTabletApp() && - (url === 'hifi/tablet/TabletHome.qml' || url === '')); - if (isActive && (type !== "QML" || url !== Script.resolvePath("qml/Edit.qml")) && !isGoingToHomescreenOnDesktop) { - that.setActive(false); - } - }); - tablet.fromQml.connect(fromQml); - createToolsWindow.fromQml.addListener(fromQml); - - createButton.clicked.connect(function() { - if ( ! (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()) ) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG); - return; - } - - that.toggle(); - }); - - addButton("importEntitiesButton", function() { - Window.browseChanged.connect(onFileOpenChanged); - Window.browseAsync("Select Model to Import", "", "*.json"); - }); - - addButton("openAssetBrowserButton", function() { - Window.showAssetServer(); - }); - function createNewEntityDialogButtonCallback(entityType) { - return function() { - if (shouldUseEditTabletApp()) { - // tablet version of new-model dialog - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - tablet.pushOntoStack(Script.resolvePath("qml/New" + entityType + "Dialog.qml")); - } else { - closeExistingDialogWindow(); - var qmlPath = Script.resolvePath("qml/New" + entityType + "Window.qml"); - var DIALOG_WINDOW_SIZE = { x: 500, y: 300 }; - dialogWindow = Desktop.createWindow(qmlPath, { - title: "New " + entityType + " Entity", - additionalFlags: Desktop.ALWAYS_ON_TOP | Desktop.CLOSE_BUTTON_HIDES, - presentationMode: Desktop.PresentationMode.NATIVE, - size: DIALOG_WINDOW_SIZE, - visible: true - }); - dialogWindow.fromQml.connect(fromQml); - } - }; - } - - addButton("newModelButton", createNewEntityDialogButtonCallback("Model")); - - addButton("newShapeButton", function () { - createNewEntity({ - type: "Shape", - shape: "Cube", - }); - }); - - addButton("newLightButton", function () { - createNewEntity({ - type: "Light", - }); - }); - - addButton("newTextButton", function () { - createNewEntity({ - type: "Text", - }); - }); - - addButton("newImageButton", function () { - createNewEntity({ - type: "Image", - }); - }); - - addButton("newWebButton", function () { - createNewEntity({ - type: "Web", - }); - }); - - addButton("newZoneButton", function () { - createNewEntity({ - type: "Zone", - }); - }); - - addButton("newParticleButton", function () { - createNewEntity({ - type: "ParticleEffect", - }); - }); - - addButton("newMaterialButton", createNewEntityDialogButtonCallback("Material")); - - var deactivateCreateIfDesktopWindowsHidden = function() { - if (!shouldUseEditTabletApp() && !entityListTool.isVisible() && !createToolsWindow.isVisible()) { - that.setActive(false); - } - }; - entityListTool.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden); - createToolsWindow.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden); - - that.setActive(false); - } - - that.clearEntityList = function () { - entityListTool.clearEntityList(); - }; - - that.toggle = function () { - that.setActive(!isActive); - if (!isActive) { - tablet.gotoHomeScreen(); - } - }; - - that.setActive = function (active) { - ContextOverlay.enabled = !active; - Settings.setValue(EDIT_SETTING, active); - if (active) { - Controller.captureEntityClickEvents(); - } else { - Controller.releaseEntityClickEvents(); - - closeExistingDialogWindow(); - } - if (active === isActive) { - return; - } - if (active && !Entities.canRez() && !Entities.canRezTmp() && !Entities.canRezCertified() && !Entities.canRezTmpCertified()) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG); - return; - } - Messages.sendLocalMessage("edit-events", JSON.stringify({ - enabled: active - })); - isActive = active; - activeButton.editProperties({isActive: isActive}); - undoHistory.setEnabled(isActive); - - var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - - if (!isActive) { - entityListTool.setVisible(false); - gridTool.setVisible(false); - grid.setEnabled(false); - propertiesTool.setVisible(false); - selectionManager.clearSelections(this); - cameraManager.disable(); - selectionDisplay.disableTriggerMapping(); - tablet.landscape = false; - Controller.disableMapping(CONTROLLER_MAPPING_NAME); - } else { - if (shouldUseEditTabletApp()) { - tablet.loadQMLSource(Script.resolvePath("qml/Edit.qml"), true); - } else { - // make other apps inactive while in desktop mode - tablet.gotoHomeScreen(); - } - UserActivityLogger.enabledEdit(); - entityListTool.setVisible(true); - entityListTool.sendUpdate(); - gridTool.setVisible(true); - grid.setEnabled(true); - propertiesTool.setVisible(true); - selectionDisplay.enableTriggerMapping(); - print("starting tablet in landscape mode"); - tablet.landscape = true; - Controller.enableMapping(CONTROLLER_MAPPING_NAME); - // Not sure what the following was meant to accomplish, but it currently causes - // everybody else to think that Interface has lost focus overall. fogbugzid:558 - // Window.setFocus(); - } - entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - }; - - initialize(); - return that; -})(); - -var selectedEntityID; -var orientation; -var intersection; - - -function rayPlaneIntersection(pickRay, point, normal) { // - // - // This version of the test returns the intersection of a line with a plane - // - var collides = Vec3.dot(pickRay.direction, normal); - - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides; - - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); -} - -function rayPlaneIntersection2(pickRay, point, normal) { - // - // This version of the test returns false if the ray is directed away from the plane - // - var collides = Vec3.dot(pickRay.direction, normal); - var d = -Vec3.dot(point, normal); - var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides; - if (t < 0.0) { - return false; - } else { - return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); - } -} - -function findClickedEntity(event) { - var pickZones = event.isControl; - - if (pickZones) { - Entities.setZonesArePickable(true); - } - - var pickRay = Camera.computePickRay(event.x, event.y); - var tabletIDs = getMainTabletIDs(); - if (tabletIDs.length > 0) { - var overlayResult = Overlays.findRayIntersection(pickRay, true, tabletIDs); - if (overlayResult.intersects) { - return null; - } - } - - var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking - var iconResult = entityIconOverlayManager.findRayIntersection(pickRay); - iconResult.accurate = true; - - if (pickZones) { - Entities.setZonesArePickable(false); - } - - var result; - - if (iconResult.intersects) { - result = iconResult; - } else if (entityResult.intersects) { - result = entityResult; - } else { - return null; - } - - if (!result.accurate) { - return null; - } - - var foundEntity = result.entityID; - return { - pickRay: pickRay, - entityID: foundEntity, - intersection: result.intersection - }; -} - -// Handles selections on overlays while in edit mode by querying entities from -// entityIconOverlayManager. -function handleOverlaySelectionToolUpdates(channel, message, sender) { - var wantDebug = false; - if (sender !== MyAvatar.sessionUUID || channel !== 'entityToolUpdates') - return; - - var data = JSON.parse(message); - - if (data.method === "selectOverlay") { - if (!selectionDisplay.triggered() || selectionDisplay.triggeredHand === data.hand) { - if (wantDebug) { - print("setting selection to overlay " + data.overlayID); - } - var entity = entityIconOverlayManager.findEntity(data.overlayID); - - if (entity !== null) { - selectionManager.setSelections([entity], this); - } - } - } -} - -function handleMessagesReceived(channel, message, sender) { - switch( channel ){ - case 'entityToolUpdates': { - handleOverlaySelectionToolUpdates( channel, message, sender ); - break; - } - default: { - return; - } - } -} - -Messages.subscribe("entityToolUpdates"); -Messages.messageReceived.connect(handleMessagesReceived); - -var mouseHasMovedSincePress = false; -var mousePressStartTime = 0; -var mousePressStartPosition = { - x: 0, - y: 0 -}; -var mouseDown = false; - -function mousePressEvent(event) { - mouseDown = true; - mousePressStartPosition = { - x: event.x, - y: event.y - }; - mousePressStartTime = Date.now(); - mouseHasMovedSincePress = false; - mouseCapturedByTool = false; - - if (propertyMenu.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { - mouseCapturedByTool = true; - return; - } - if (isActive) { - if (cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { - // Event handled; do nothing. - return; - } - } -} - -var mouseCapturedByTool = false; -var lastMousePosition = null; -var CLICK_TIME_THRESHOLD = 500 * 1000; // 500 ms -var CLICK_MOVE_DISTANCE_THRESHOLD = 20; -var IDLE_MOUSE_TIMEOUT = 200; - -var lastMouseMoveEvent = null; - -function mouseMoveEventBuffered(event) { - lastMouseMoveEvent = event; -} - -function mouseMove(event) { - if (mouseDown && !mouseHasMovedSincePress) { - var timeSincePressMicro = Date.now() - mousePressStartTime; - - var dX = mousePressStartPosition.x - event.x; - var dY = mousePressStartPosition.y - event.y; - var sqDist = (dX * dX) + (dY * dY); - - // If less than CLICK_TIME_THRESHOLD has passed since the mouse click AND the mouse has moved - // less than CLICK_MOVE_DISTANCE_THRESHOLD distance, then don't register this as a mouse move - // yet. The goal is to provide mouse clicks that are more lenient to small movements. - if (timeSincePressMicro < CLICK_TIME_THRESHOLD && sqDist < CLICK_MOVE_DISTANCE_THRESHOLD) { - return; - } - mouseHasMovedSincePress = true; - } - - if (!isActive) { - return; - } - - // allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing - if (selectionDisplay.mouseMoveEvent(event) || propertyMenu.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) { - return; - } - - lastMousePosition = { - x: event.x, - y: event.y - }; -} - -function mouseReleaseEvent(event) { - mouseDown = false; - - if (lastMouseMoveEvent) { - mouseMove(lastMouseMoveEvent); - lastMouseMoveEvent = null; - } - if (propertyMenu.mouseReleaseEvent(event)) { - return true; - } - if (isActive && selectionManager.hasSelection()) { - tooltip.show(false); - } - if (mouseCapturedByTool) { - - return; - } - - cameraManager.mouseReleaseEvent(event); - - if (!mouseHasMovedSincePress) { - mouseClickEvent(event); - } -} - -function wasTabletOrEditHandleClicked(event) { - var rayPick = Camera.computePickRay(event.x, event.y); - var result = Overlays.findRayIntersection(rayPick, true); - if (result.intersects) { - var overlayID = result.overlayID; - var tabletIDs = getMainTabletIDs(); - if (tabletIDs.indexOf(overlayID) >= 0) { - return true; - } else if (selectionDisplay.isEditHandle(overlayID)) { - return true; - } - } - return false; -} - -function mouseClickEvent(event) { - var wantDebug = false; - var result, properties, tabletClicked; - if (isActive && event.isLeftButton) { - result = findClickedEntity(event); - var tabletOrEditHandleClicked = wasTabletOrEditHandleClicked(event); - if (tabletOrEditHandleClicked) { - return; - } - - if (result === null || result === undefined) { - if (!event.isShifted) { - selectionManager.clearSelections(this); - } - return; - } - toolBar.setActive(true); - var pickRay = result.pickRay; - var foundEntity = result.entityID; - if (HMD.tabletID && foundEntity === HMD.tabletID) { - return; - } - properties = Entities.getEntityProperties(foundEntity); - var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; - - if (wantDebug) { - print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal); - } - // P P - Model - // /| A - Palm - // / | d B - unit vector toward tip - // / | X - base of the perpendicular line - // A---X----->B d - distance fom axis - // x x - distance from A - // - // |X-A| = (P-A).B - // X === A + ((P-A).B)B - // d = |P-X| - - var A = pickRay.origin; - var B = Vec3.normalize(pickRay.direction); - var P = properties.position; - - var x = Vec3.dot(Vec3.subtract(P, A), B); - - var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * - 180 / Math.PI; - - var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && - (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); - - if (0 < x && sizeOK) { - selectedEntityID = foundEntity; - orientation = MyAvatar.orientation; - intersection = rayPlaneIntersection(pickRay, P, Quat.getForward(orientation)); - - if (!event.isShifted) { - selectionManager.setSelections([foundEntity], this); - } else { - selectionManager.addEntity(foundEntity, true, this); - } - selectionManager.saveProperties(); - - if (wantDebug) { - print("Model selected: " + foundEntity); - } - selectionDisplay.select(selectedEntityID, event); - - if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) { - cameraManager.enable(); - cameraManager.focus(selectionManager.worldPosition, - selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } - } else if (event.isRightButton) { - result = findClickedEntity(event); - if (result) { - if (SHOULD_SHOW_PROPERTY_MENU !== true) { - return; - } - properties = Entities.getEntityProperties(result.entityID); - if (properties.marketplaceID) { - propertyMenu.marketplaceID = properties.marketplaceID; - propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); - } else { - propertyMenu.marketplaceID = null; - propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info"); - } - propertyMenu.setPosition(event.x, event.y); - propertyMenu.show(); - } else { - propertyMenu.hide(); - } - } -} - -Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseMoveEvent.connect(mouseMoveEventBuffered); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - - -// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already -// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that -// added it. -var modelMenuAddedDelete = false; -var originalLightsArePickable = Entities.getLightsArePickable(); - -function setupModelMenus() { - // adj our menuitems - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Undo", - shortcutKey: 'Ctrl+Z', - position: 0, - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Redo", - shortcutKey: 'Ctrl+Y', - position: 1, - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Entities", - isSeparator: true - }); - if (!Menu.menuItemExists("Edit", "Delete")) { - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Delete", - shortcutKeyEvent: { - text: "delete" - }, - afterItem: "Entities", - }); - modelMenuAddedDelete = true; - } - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Parent Entity to Last", - afterItem: "Entities" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Unparent Entity", - afterItem: "Parent Entity to Last" - }); - - Menu.addMenuItem({ - menuName: GRABBABLE_ENTITIES_MENU_CATEGORY, - menuItemName: MENU_CREATE_ENTITIES_GRABBABLE, - afterItem: "Unparent Entity", - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, true) - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_LARGE, - afterItem: MENU_CREATE_ENTITIES_GRABBABLE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, true) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_SMALL, - afterItem: MENU_ALLOW_SELECTION_LARGE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, true) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_ALLOW_SELECTION_LIGHTS, - afterItem: MENU_ALLOW_SELECTION_SMALL, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, false) - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Select All Entities In Box", - afterItem: "Allow Selecting of Lights" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Select All Entities Touching Box", - afterItem: "Select All Entities In Box" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Export Entities", - afterItem: "Entities" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Import Entities", - afterItem: "Export Entities" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: "Import Entities from URL", - afterItem: "Import Entities" - }); - - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_AUTO_FOCUS_ON_SELECT, - isCheckable: true, - isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_EASE_ON_FOCUS, - afterItem: MENU_AUTO_FOCUS_ON_SELECT, - isCheckable: true, - isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, - afterItem: MENU_EASE_ON_FOCUS, - isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false" - }); - Menu.addMenuItem({ - menuName: "Edit", - menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, - afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, - isCheckable: true, - isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false" - }); - - Entities.setLightsArePickable(false); -} - -setupModelMenus(); // do this when first running our script. - -function cleanupModelMenus() { - Menu.removeMenuItem("Edit", "Undo"); - Menu.removeMenuItem("Edit", "Redo"); - - Menu.removeSeparator("Edit", "Entities"); - if (modelMenuAddedDelete) { - // delete our menuitems - Menu.removeMenuItem("Edit", "Delete"); - } - - Menu.removeMenuItem("Edit", "Parent Entity to Last"); - Menu.removeMenuItem("Edit", "Unparent Entity"); - Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); - Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); - Menu.removeMenuItem("Edit", "Select All Entities In Box"); - Menu.removeMenuItem("Edit", "Select All Entities Touching Box"); - - Menu.removeMenuItem("Edit", "Export Entities"); - Menu.removeMenuItem("Edit", "Import Entities"); - Menu.removeMenuItem("Edit", "Import Entities from URL"); - - Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT); - Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS); - Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE); - Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE); - Menu.removeMenuItem("Edit", MENU_CREATE_ENTITIES_GRABBABLE); -} - -Script.scriptEnding.connect(function () { - toolBar.setActive(false); - Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)); - Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE)); - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL)); - Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LIGHTS)); - - - progressDialog.cleanup(); - cleanupModelMenus(); - tooltip.cleanup(); - selectionDisplay.cleanup(); - entityShapeVisualizer.cleanup(); - Entities.setLightsArePickable(originalLightsArePickable); - - Overlays.deleteOverlay(importingSVOImageOverlay); - Overlays.deleteOverlay(importingSVOTextOverlay); - - Controller.keyReleaseEvent.disconnect(keyReleaseEvent); - Controller.keyPressEvent.disconnect(keyPressEvent); - - Controller.mousePressEvent.disconnect(mousePressEvent); - Controller.mouseMoveEvent.disconnect(mouseMoveEventBuffered); - Controller.mouseReleaseEvent.disconnect(mouseReleaseEvent); - - Messages.messageReceived.disconnect(handleMessagesReceived); - Messages.unsubscribe("entityToolUpdates"); - createButton = null; -}); - -var lastOrientation = null; -var lastPosition = null; - -// Do some stuff regularly, like check for placement of various overlays -Script.update.connect(function (deltaTime) { - progressDialog.move(); - selectionDisplay.checkControllerMove(); - var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1); - var dPosition = Vec3.distance(Camera.position, lastPosition); - if (dOrientation > 0.001 || dPosition > 0.001) { - propertyMenu.hide(); - lastOrientation = Camera.orientation; - lastPosition = Camera.position; - } - if (lastMouseMoveEvent) { - mouseMove(lastMouseMoveEvent); - lastMouseMoveEvent = null; - } -}); - -function insideBox(center, dimensions, point) { - return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && - (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && - (Math.abs(point.z - center.z) <= (dimensions.z / 2.0)); -} - -function selectAllEntitiesInCurrentSelectionBox(keepIfTouching) { - if (selectionManager.hasSelection()) { - // Get all entities touching the bounding box of the current selection - var boundingBoxCorner = Vec3.subtract(selectionManager.worldPosition, - Vec3.multiply(selectionManager.worldDimensions, 0.5)); - var entities = Entities.findEntitiesInBox(boundingBoxCorner, selectionManager.worldDimensions); - - if (!keepIfTouching) { - var isValid; - if (selectionManager.localPosition === null || selectionManager.localPosition === undefined) { - isValid = function (position) { - return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); - }; - } else { - isValid = function (position) { - var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation), - Vec3.subtract(position, - selectionManager.localPosition)); - return insideBox(Vec3.ZERO, selectionManager.localDimensions, localPosition); - }; - } - for (var i = 0; i < entities.length; ++i) { - var properties = Entities.getEntityProperties(entities[i]); - if (!isValid(properties.position)) { - entities.splice(i, 1); - --i; - } - } - } - selectionManager.setSelections(entities, this); - } -} - -function sortSelectedEntities(selected) { - var sortedEntities = selected.slice(); - var begin = 0; - while (begin < sortedEntities.length) { - var elementRemoved = false; - var next = begin + 1; - while (next < sortedEntities.length) { - var beginID = sortedEntities[begin]; - var nextID = sortedEntities[next]; - - if (Entities.isChildOfParent(beginID, nextID)) { - sortedEntities[begin] = nextID; - sortedEntities[next] = beginID; - sortedEntities.splice(next, 1); - elementRemoved = true; - break; - } else if (Entities.isChildOfParent(nextID, beginID)) { - sortedEntities.splice(next, 1); - elementRemoved = true; - break; - } - next++; - } - if (!elementRemoved) { - begin++; - } - } - return sortedEntities; -} - -function recursiveDelete(entities, childrenList, deletedIDs, entityHostType) { - var wantDebug = false; - var entitiesLength = entities.length; - var initialPropertySets = Entities.getMultipleEntityProperties(entities); - var entityHostTypes = Entities.getMultipleEntityProperties(entities, 'entityHostType'); - for (var i = 0; i < entitiesLength; ++i) { - var entityID = entities[i]; - - if (entityHostTypes[i].entityHostType !== entityHostType) { - if (wantDebug) { - console.log("Skipping deletion of entity " + entityID + " with conflicting entityHostType: " + - entityHostTypes[i].entityHostType + ", expected: " + entityHostType); - } - continue; - } - - var children = Entities.getChildrenIDs(entityID); - var grandchildrenList = []; - recursiveDelete(children, grandchildrenList, deletedIDs, entityHostType); - childrenList.push({ - entityID: entityID, - properties: initialPropertySets[i], - children: grandchildrenList - }); - deletedIDs.push(entityID); - Entities.deleteEntity(entityID); - } -} - -function unparentSelectedEntities() { - if (SelectionManager.hasSelection()) { - var selectedEntities = selectionManager.selections; - var parentCheck = false; - - if (selectedEntities.length < 1) { - Window.notifyEditError("You must have an entity selected in order to unparent it."); - return; - } - selectedEntities.forEach(function (id, index) { - var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; - if (parentId !== null && parentId.length > 0 && parentId !== Uuid.NULL) { - parentCheck = true; - } - Entities.editEntity(id, {parentID: null}); - return true; - }); - if (parentCheck) { - if (selectedEntities.length > 1) { - Window.notify("Entities unparented"); - } else { - Window.notify("Entity unparented"); - } - } else { - if (selectedEntities.length > 1) { - Window.notify("Selected Entities have no parents"); - } else { - Window.notify("Selected Entity does not have a parent"); - } - } - } else { - Window.notifyEditError("You have nothing selected to unparent"); - } -} -function parentSelectedEntities() { - if (SelectionManager.hasSelection()) { - var selectedEntities = selectionManager.selections; - if (selectedEntities.length <= 1) { - Window.notifyEditError("You must have multiple entities selected in order to parent them"); - return; - } - var parentCheck = false; - var lastEntityId = selectedEntities[selectedEntities.length - 1]; - selectedEntities.forEach(function (id, index) { - if (lastEntityId !== id) { - var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; - if (parentId !== lastEntityId) { - parentCheck = true; - } - Entities.editEntity(id, {parentID: lastEntityId}); - } - }); - - if (parentCheck) { - Window.notify("Entities parented"); - } else { - Window.notify("Entities are already parented to last"); - } - } else { - Window.notifyEditError("You have nothing selected to parent"); - } -} -function deleteSelectedEntities() { - if (SelectionManager.hasSelection()) { - var deletedIDs = []; - - SelectionManager.saveProperties(); - var savedProperties = []; - var newSortedSelection = sortSelectedEntities(selectionManager.selections); - var entityHostTypes = Entities.getMultipleEntityProperties(newSortedSelection, 'entityHostType'); - for (var i = 0; i < newSortedSelection.length; ++i) { - var entityID = newSortedSelection[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - if (initialProperties.locked || - (initialProperties.avatarEntity && initialProperties.owningAvatarID !== MyAvatar.sessionUUID)) { - continue; - } - var children = Entities.getChildrenIDs(entityID); - var childList = []; - recursiveDelete(children, childList, deletedIDs, entityHostTypes[i].entityHostType); - savedProperties.push({ - entityID: entityID, - properties: initialProperties, - children: childList - }); - deletedIDs.push(entityID); - Entities.deleteEntity(entityID); - } - - if (savedProperties.length > 0) { - SelectionManager.clearSelections(this); - pushCommandForSelections([], savedProperties); - entityListTool.deleteEntities(deletedIDs); - } - } -} - -function toggleSelectedEntitiesLocked() { - if (SelectionManager.hasSelection()) { - var locked = !Entities.getEntityProperties(SelectionManager.selections[0], ["locked"]).locked; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - Entities.editEntity(entityID, { - locked: locked - }); - } - entityListTool.sendUpdate(); - selectionManager._update(false, this); - } -} - -function toggleSelectedEntitiesVisible() { - if (SelectionManager.hasSelection()) { - var visible = !Entities.getEntityProperties(SelectionManager.selections[0], ["visible"]).visible; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - Entities.editEntity(entityID, { - visible: visible - }); - } - entityListTool.sendUpdate(); - selectionManager._update(false, this); - } -} - -function onFileSaveChanged(filename) { - Window.saveFileChanged.disconnect(onFileSaveChanged); - if (filename !== "") { - var success = Clipboard.exportEntities(filename, selectionManager.selections); - if (!success) { - Window.notifyEditError("Export failed."); - } - } -} - -function onFileOpenChanged(filename) { - // disconnect the event, otherwise the requests will stack up - try { - // Not all calls to onFileOpenChanged() connect an event. - Window.browseChanged.disconnect(onFileOpenChanged); - } catch (e) { - // Ignore. - } - - var importURL = null; - if (filename !== "") { - importURL = filename; - if (!/^(http|https):\/\//.test(filename)) { - importURL = "file:///" + importURL; - } - } - if (importURL) { - if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) { - toolBar.toggle(); - } - importSVO(importURL); - } -} - -function onPromptTextChanged(prompt) { - Window.promptTextChanged.disconnect(onPromptTextChanged); - if (prompt !== "") { - if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) { - toolBar.toggle(); - } - importSVO(prompt); - } -} - -function handleMenuEvent(menuItem) { - if (menuItem === "Allow Selecting of Small Models") { - allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); - } else if (menuItem === "Allow Selecting of Large Models") { - allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); - } else if (menuItem === "Allow Selecting of Lights") { - Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); - } else if (menuItem === "Delete") { - deleteSelectedEntities(); - } else if (menuItem === "Undo") { - undoHistory.undo(); - } else if (menuItem === "Redo") { - undoHistory.redo(); - } else if (menuItem === "Parent Entity to Last") { - parentSelectedEntities(); - } else if (menuItem === "Unparent Entity") { - unparentSelectedEntities(); - } else if (menuItem === "Export Entities") { - if (!selectionManager.hasSelection()) { - Window.notifyEditError("No entities have been selected."); - } else { - Window.saveFileChanged.connect(onFileSaveChanged); - Window.saveAsync("Select Where to Save", "", "*.json"); - } - } else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") { - if (menuItem === "Import Entities") { - Window.browseChanged.connect(onFileOpenChanged); - Window.browseAsync("Select Model to Import", "", "*.json"); - } else { - Window.promptTextChanged.connect(onPromptTextChanged); - Window.promptAsync("URL of SVO to import", ""); - } - } else if (menuItem === "Select All Entities In Box") { - selectAllEntitiesInCurrentSelectionBox(false); - } else if (menuItem === "Select All Entities Touching Box") { - selectAllEntitiesInCurrentSelectionBox(true); - } else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) { - entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); - } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) { - Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); - } else if (menuItem === MENU_CREATE_ENTITIES_GRABBABLE) { - Settings.setValue(SETTING_EDIT_PREFIX + menuItem, Menu.isOptionChecked(menuItem)); - } - tooltip.show(false); -} - -var HALF_TREE_SCALE = 16384; - -function getPositionToCreateEntity(extra) { - var CREATE_DISTANCE = 2; - var position; - var delta = extra !== undefined ? extra : 0; - if (Camera.mode === "entity" || Camera.mode === "independent") { - position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getForward(Camera.orientation), CREATE_DISTANCE + delta)); - } else { - position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getForward(MyAvatar.orientation), CREATE_DISTANCE + delta)); - } - - if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) { - return null; - } - return position; -} - -function importSVO(importURL) { - if (!Entities.canRez() && !Entities.canRezTmp() && - !Entities.canRezCertified() && !Entities.canRezTmpCertified()) { - Window.notifyEditError(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); - return; - } - - Overlays.editOverlay(importingSVOTextOverlay, { - visible: true - }); - Overlays.editOverlay(importingSVOImageOverlay, { - visible: true - }); - - var success = Clipboard.importEntities(importURL); - - if (success) { - var VERY_LARGE = 10000; - var isLargeImport = Clipboard.getClipboardContentsLargestDimension() >= VERY_LARGE; - var position = Vec3.ZERO; - if (!isLargeImport) { - position = getPositionToCreateEntity(Clipboard.getClipboardContentsLargestDimension() / 2); - } - if (position !== null && position !== undefined) { - var pastedEntityIDs = Clipboard.pasteEntities(position); - if (!isLargeImport) { - // The first entity in Clipboard gets the specified position with the rest being relative to it. Therefore, move - // entities after they're imported so that they're all the correct distance in front of and with geometric mean - // centered on the avatar/camera direction. - var deltaPosition = Vec3.ZERO; - var entityPositions = []; - var entityParentIDs = []; - - var propType = Entities.getEntityProperties(pastedEntityIDs[0], ["type"]).type; - var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect"]; - if (NO_ADJUST_ENTITY_TYPES.indexOf(propType) === -1) { - var targetDirection; - if (Camera.mode === "entity" || Camera.mode === "independent") { - targetDirection = Camera.orientation; - } else { - targetDirection = MyAvatar.orientation; - } - targetDirection = Vec3.multiplyQbyV(targetDirection, Vec3.UNIT_Z); - - var targetPosition = getPositionToCreateEntity(); - var deltaParallel = HALF_TREE_SCALE; // Distance to move entities parallel to targetDirection. - var deltaPerpendicular = Vec3.ZERO; // Distance to move entities perpendicular to targetDirection. - for (var i = 0, length = pastedEntityIDs.length; i < length; i++) { - var curLoopEntityProps = Entities.getEntityProperties(pastedEntityIDs[i], ["position", "dimensions", - "registrationPoint", "rotation", "parentID"]); - var adjustedPosition = adjustPositionPerBoundingBox(targetPosition, targetDirection, - curLoopEntityProps.registrationPoint, curLoopEntityProps.dimensions, curLoopEntityProps.rotation); - var delta = Vec3.subtract(adjustedPosition, curLoopEntityProps.position); - var distance = Vec3.dot(delta, targetDirection); - deltaParallel = Math.min(distance, deltaParallel); - deltaPerpendicular = Vec3.sum(Vec3.subtract(delta, Vec3.multiply(distance, targetDirection)), - deltaPerpendicular); - entityPositions[i] = curLoopEntityProps.position; - entityParentIDs[i] = curLoopEntityProps.parentID; - } - deltaPerpendicular = Vec3.multiply(1 / pastedEntityIDs.length, deltaPerpendicular); - deltaPosition = Vec3.sum(Vec3.multiply(deltaParallel, targetDirection), deltaPerpendicular); - } - - if (grid.getSnapToGrid()) { - var firstEntityProps = Entities.getEntityProperties(pastedEntityIDs[0], ["position", "dimensions", - "registrationPoint"]); - var positionPreSnap = Vec3.sum(deltaPosition, firstEntityProps.position); - position = grid.snapToSurface(grid.snapToGrid(positionPreSnap, false, firstEntityProps.dimensions, - firstEntityProps.registrationPoint), firstEntityProps.dimensions, firstEntityProps.registrationPoint); - deltaPosition = Vec3.subtract(position, firstEntityProps.position); - } - - if (!Vec3.equal(deltaPosition, Vec3.ZERO)) { - for (var editEntityIndex = 0, numEntities = pastedEntityIDs.length; editEntityIndex < numEntities; editEntityIndex++) { - if (Uuid.isNull(entityParentIDs[editEntityIndex])) { - Entities.editEntity(pastedEntityIDs[editEntityIndex], { - position: Vec3.sum(deltaPosition, entityPositions[editEntityIndex]) - }); - } - } - } - } - - if (isActive) { - selectionManager.setSelections(pastedEntityIDs, this); - } - } else { - Window.notifyEditError("Can't import entities: entities would be out of bounds."); - } - } else { - Window.notifyEditError("There was an error importing the entity file."); - } - - Overlays.editOverlay(importingSVOTextOverlay, { - visible: false - }); - Overlays.editOverlay(importingSVOImageOverlay, { - visible: false - }); -} -Window.svoImportRequested.connect(importSVO); - -Menu.menuItemEvent.connect(handleMenuEvent); - -var keyPressEvent = function (event) { - if (isActive) { - cameraManager.keyPressEvent(event); - } -}; -var keyReleaseEvent = function (event) { - if (isActive) { - cameraManager.keyReleaseEvent(event); - } -}; -Controller.keyReleaseEvent.connect(keyReleaseEvent); -Controller.keyPressEvent.connect(keyPressEvent); - -function deleteKey(value) { - if (value === 0) { // on release - deleteSelectedEntities(); - } -} -function deselectKey(value) { - if (value === 0) { // on release - selectionManager.clearSelections(this); - } -} -function toggleKey(value) { - if (value === 0) { // on release - selectionDisplay.toggleSpaceMode(); - } -} -function focusKey(value) { - if (value === 0) { // on release - cameraManager.enable(); - if (selectionManager.hasSelection()) { - cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions, - Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); - } - } -} -function gridKey(value) { - if (value === 0) { // on release - if (selectionManager.hasSelection()) { - grid.moveToSelection(); - } - } -} -function recursiveAdd(newParentID, parentData) { - if (parentData.children !== undefined) { - var children = parentData.children; - for (var i = 0; i < children.length; i++) { - var childProperties = children[i].properties; - childProperties.parentID = newParentID; - var newChildID = Entities.addEntity(childProperties); - recursiveAdd(newChildID, children[i]); - } - } -} - -var UndoHistory = function(onUpdate) { - this.history = []; - // The current position is the index of the last executed action in the history array. - // - // -1 0 1 2 3 <- position - // A B C D <- actions in history - // - // If our lastExecutedIndex is 1, the last executed action is B. - // If we undo, we undo B (index 1). If we redo, we redo C (index 2). - this.lastExecutedIndex = -1; - this.enabled = true; - this.onUpdate = onUpdate; -}; - -UndoHistory.prototype.pushCommand = function(undoFn, undoArgs, redoFn, redoArgs) { - if (!this.enabled) { - return; - } - // Delete any history following the last executed action. - this.history.splice(this.lastExecutedIndex + 1); - this.history.push({ - undoFn: undoFn, - undoArgs: undoArgs, - redoFn: redoFn, - redoArgs: redoArgs - }); - this.lastExecutedIndex++; - - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.setEnabled = function(enabled) { - this.enabled = enabled; - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.canUndo = function() { - return this.enabled && this.lastExecutedIndex >= 0; -}; -UndoHistory.prototype.canRedo = function() { - return this.enabled && this.lastExecutedIndex < this.history.length - 1; -}; -UndoHistory.prototype.undo = function() { - if (!this.canUndo()) { - console.warn("Cannot undo action"); - return; - } - - var command = this.history[this.lastExecutedIndex]; - command.undoFn(command.undoArgs); - this.lastExecutedIndex--; - - if (this.onUpdate) { - this.onUpdate(); - } -}; -UndoHistory.prototype.redo = function() { - if (!this.canRedo()) { - console.warn("Cannot redo action"); - return; - } - - var command = this.history[this.lastExecutedIndex + 1]; - command.redoFn(command.redoArgs); - this.lastExecutedIndex++; - - if (this.onUpdate) { - this.onUpdate(); - } -}; - -function updateUndoRedoMenuItems() { - Menu.setMenuEnabled("Edit > Undo", undoHistory.canUndo()); - Menu.setMenuEnabled("Edit > Redo", undoHistory.canRedo()); -} -var undoHistory = new UndoHistory(updateUndoRedoMenuItems); -updateUndoRedoMenuItems(); - -// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently -// possible to create an entity with a specific id, earlier undo commands to the deleted entity -// will fail if there isn't a way to find the new entity id. -var DELETED_ENTITY_MAP = {}; - -function applyEntityProperties(data) { - var editEntities = data.editEntities; - var createEntities = data.createEntities; - var deleteEntities = data.deleteEntities; - var selectedEntityIDs = []; - var selectEdits = createEntities.length === 0 || !data.selectCreated; - var i, entityID, entityProperties; - for (i = 0; i < createEntities.length; i++) { - entityID = createEntities[i].entityID; - entityProperties = createEntities[i].properties; - var newEntityID = Entities.addEntity(entityProperties); - recursiveAdd(newEntityID, createEntities[i]); - DELETED_ENTITY_MAP[entityID] = newEntityID; - if (data.selectCreated) { - selectedEntityIDs.push(newEntityID); - } - } - for (i = 0; i < deleteEntities.length; i++) { - entityID = deleteEntities[i].entityID; - if (DELETED_ENTITY_MAP[entityID] !== undefined) { - entityID = DELETED_ENTITY_MAP[entityID]; - } - Entities.deleteEntity(entityID); - var index = selectedEntityIDs.indexOf(entityID); - if (index >= 0) { - selectedEntityIDs.splice(index, 1); - } - } - for (i = 0; i < editEntities.length; i++) { - entityID = editEntities[i].entityID; - if (DELETED_ENTITY_MAP[entityID] !== undefined) { - entityID = DELETED_ENTITY_MAP[entityID]; - } - entityProperties = editEntities[i].properties; - if (entityProperties !== null) { - Entities.editEntity(entityID, entityProperties); - } - if (selectEdits) { - selectedEntityIDs.push(entityID); - } - } - - // We might be getting an undo while edit.js is disabled. If that is the case, don't set - // our selections, causing the edit widgets to display. - if (isActive) { - selectionManager.setSelections(selectedEntityIDs, this); - selectionManager.saveProperties(); - } -} - -// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the -// redo command, and the saved properties for the undo command. Also, include create and delete entity data. -function pushCommandForSelections(createdEntityData, deletedEntityData, doNotSaveEditProperties) { - doNotSaveEditProperties = false; - var undoData = { - editEntities: [], - createEntities: deletedEntityData || [], - deleteEntities: createdEntityData || [], - selectCreated: true - }; - var redoData = { - editEntities: [], - createEntities: createdEntityData || [], - deleteEntities: deletedEntityData || [], - selectCreated: true - }; - for (var i = 0; i < SelectionManager.selections.length; i++) { - var entityID = SelectionManager.selections[i]; - var initialProperties = SelectionManager.savedProperties[entityID]; - var currentProperties = null; - if (!initialProperties) { - continue; - } - - if (doNotSaveEditProperties) { - initialProperties = null; - } else { - currentProperties = Entities.getEntityProperties(entityID); - } - - undoData.editEntities.push({ - entityID: entityID, - properties: initialProperties - }); - redoData.editEntities.push({ - entityID: entityID, - properties: currentProperties - }); - } - undoHistory.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); -} - -var ServerScriptStatusMonitor = function(entityID, statusCallback) { - var self = this; - - self.entityID = entityID; - self.active = true; - self.sendRequestTimerID = null; - - var onStatusReceived = function(success, isRunning, status, errorInfo) { - if (self.active) { - statusCallback({ - statusRetrieved: success, - isRunning: isRunning, - status: status, - errorInfo: errorInfo - }); - self.sendRequestTimerID = Script.setTimeout(function() { - if (self.active) { - Entities.getServerScriptStatus(entityID, onStatusReceived); - } - }, 1000); - } - }; - self.stop = function() { - self.active = false; - }; - - Entities.getServerScriptStatus(entityID, onStatusReceived); -}; - -var PropertiesTool = function (opts) { - var that = {}; - - var webView = null; - webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); - webView.setVisible = function(value) {}; - - var visible = false; - - // This keeps track of the last entity ID that was selected. If multiple entities - // are selected or if no entity is selected this will be `null`. - var currentSelectedEntityID = null; - var statusMonitor = null; - var blockPropertyUpdates = false; - - that.setVisible = function (newVisible) { - visible = newVisible; - webView.setVisible(shouldUseEditTabletApp() && visible); - createToolsWindow.setVisible(!shouldUseEditTabletApp() && visible); - }; - - that.setVisible(false); - - function emitScriptEvent(data) { - var dataString = JSON.stringify(data); - webView.emitScriptEvent(dataString); - createToolsWindow.emitScriptEvent(dataString); - } - - function updateScriptStatus(info) { - info.type = "server_script_status"; - emitScriptEvent(info); - } - - function resetScriptStatus() { - updateScriptStatus({ - statusRetrieved: undefined, - isRunning: undefined, - status: "", - errorInfo: "" - }); - } - - that.setSpaceMode = function(spaceMode) { - emitScriptEvent({ - type: 'setSpaceMode', - spaceMode: spaceMode - }) - }; - - function updateSelections(selectionUpdated, caller) { - if (blockPropertyUpdates) { - return; - } - - var data = { - type: 'update', - spaceMode: selectionDisplay.getSpaceMode(), - isPropertiesToolUpdate: caller === this, - }; - - if (selectionUpdated) { - resetScriptStatus(); - - if (selectionManager.selections.length !== 1) { - if (statusMonitor !== null) { - statusMonitor.stop(); - statusMonitor = null; - } - currentSelectedEntityID = null; - } else if (currentSelectedEntityID !== selectionManager.selections[0]) { - if (statusMonitor !== null) { - statusMonitor.stop(); - } - var entityID = selectionManager.selections[0]; - currentSelectedEntityID = entityID; - statusMonitor = new ServerScriptStatusMonitor(entityID, updateScriptStatus); - } - } - - var selections = []; - for (var i = 0; i < selectionManager.selections.length; i++) { - var entity = {}; - entity.id = selectionManager.selections[i]; - entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); - if (entity.properties.rotation !== undefined) { - entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); - } - if (entity.properties.localRotation !== undefined) { - entity.properties.localRotation = Quat.safeEulerAngles(entity.properties.localRotation); - } - if (entity.properties.emitOrientation !== undefined) { - entity.properties.emitOrientation = Quat.safeEulerAngles(entity.properties.emitOrientation); - } - if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) { - entity.properties.keyLight.direction = Vec3.toPolar(entity.properties.keyLight.direction); - entity.properties.keyLight.direction.z = 0.0; - } - selections.push(entity); - } - data.selections = selections; - - emitScriptEvent(data); - } - selectionManager.addEventListener(updateSelections, this); - - - var onWebEventReceived = function(data) { - try { - data = JSON.parse(data); - } catch(e) { - return; - } - var i, properties, dY, diff, newPosition; - if (data.type === "update") { - - if (data.properties || data.propertiesMap) { - var propertiesMap = data.propertiesMap; - if (propertiesMap === undefined) { - propertiesMap = [{ - entityIDs: data.ids, - properties: data.properties, - }]; - } - - var sendListUpdate = false; - propertiesMap.forEach(function(propertiesObject) { - var properties = propertiesObject.properties; - var updateEntityIDs = propertiesObject.entityIDs; - if (properties.dynamic === false) { - // this object is leaving dynamic, so we zero its velocities - properties.localVelocity = Vec3.ZERO; - properties.localAngularVelocity = Vec3.ZERO; - } - if (properties.rotation !== undefined) { - properties.rotation = Quat.fromVec3Degrees(properties.rotation); - } - if (properties.localRotation !== undefined) { - properties.localRotation = Quat.fromVec3Degrees(properties.localRotation); - } - if (properties.emitOrientation !== undefined) { - properties.emitOrientation = Quat.fromVec3Degrees(properties.emitOrientation); - } - if (properties.keyLight !== undefined && properties.keyLight.direction !== undefined) { - var currentKeyLightDirection = Vec3.toPolar(Entities.getEntityProperties(selectionManager.selections[0], ['keyLight.direction']).keyLight.direction); - if (properties.keyLight.direction.x === undefined) { - properties.keyLight.direction.x = currentKeyLightDirection.x; - } - if (properties.keyLight.direction.y === undefined) { - properties.keyLight.direction.y = currentKeyLightDirection.y; - } - properties.keyLight.direction = Vec3.fromPolar(properties.keyLight.direction.x, properties.keyLight.direction.y); - } - - updateEntityIDs.forEach(function (entityID) { - Entities.editEntity(entityID, properties); - }); - - if (properties.name !== undefined || properties.modelURL !== undefined || properties.materialURL !== undefined || - properties.visible !== undefined || properties.locked !== undefined) { - - sendListUpdate = true; - } - - }); - if (sendListUpdate) { - entityListTool.sendUpdate(); - } - } - - - if (data.onlyUpdateEntities) { - blockPropertyUpdates = true; - } else { - pushCommandForSelections(); - SelectionManager.saveProperties(); - } - selectionManager._update(false, this); - blockPropertyUpdates = false; - } else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') { - data.ids.forEach(function(entityID) { - Entities.editEntity(entityID, data.properties); - }); - } else if (data.type === "showMarketplace") { - showMarketplace(); - } else if (data.type === "action") { - if (data.action === "moveSelectionToGrid") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); - diff = { - x: 0, - y: dY, - z: 0 - }; - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "moveAllToGrid") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; - dY = grid.getOrigin().y - bottomY; - diff = { - x: 0, - y: dY, - z: 0 - }; - newPosition = Vec3.sum(properties.position, diff); - Entities.editEntity(selectionManager.selections[i], { - position: newPosition - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "resetToNaturalDimensions") { - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - var naturalDimensions = properties.naturalDimensions; - - // If any of the natural dimensions are not 0, resize - if (properties.type === "Model" && naturalDimensions.x === 0 && naturalDimensions.y === 0 && - naturalDimensions.z === 0) { - Window.notifyEditError("Cannot reset entity to its natural dimensions: Model URL" + - " is invalid or the model has not yet been loaded."); - } else { - Entities.editEntity(selectionManager.selections[i], { - dimensions: properties.naturalDimensions - }); - } - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "previewCamera") { - if (selectionManager.hasSelection()) { - Camera.mode = "entity"; - Camera.cameraEntity = selectionManager.selections[0]; - } - } else if (data.action === "rescaleDimensions") { - var multiplier = data.percentage / 100.0; - if (selectionManager.hasSelection()) { - selectionManager.saveProperties(); - for (i = 0; i < selectionManager.selections.length; i++) { - properties = selectionManager.savedProperties[selectionManager.selections[i]]; - Entities.editEntity(selectionManager.selections[i], { - dimensions: Vec3.multiply(multiplier, properties.dimensions) - }); - } - pushCommandForSelections(); - selectionManager._update(false, this); - } - } else if (data.action === "reloadClientScripts") { - if (selectionManager.hasSelection()) { - var timestamp = Date.now(); - for (i = 0; i < selectionManager.selections.length; i++) { - Entities.editEntity(selectionManager.selections[i], { - scriptTimestamp: timestamp - }); - } - } - } else if (data.action === "reloadServerScripts") { - if (selectionManager.hasSelection()) { - for (i = 0; i < selectionManager.selections.length; i++) { - Entities.reloadServerScripts(selectionManager.selections[i]); - } - } - } - } else if (data.type === "propertiesPageReady") { - updateSelections(true); - } else if (data.type === "tooltipsRequest") { - emitScriptEvent({ - type: 'tooltipsReply', - tooltips: Script.require('./assets/data/createAppTooltips.json'), - hmdActive: HMD.active, - }); - } else if (data.type === "propertyRangeRequest") { - var propertyRanges = {}; - data.properties.forEach(function (property) { - propertyRanges[property] = Entities.getPropertyInfo(property); - }); - emitScriptEvent({ - type: 'propertyRangeReply', - propertyRanges: propertyRanges, - }); - } else if (data.type === "materialTargetRequest") { - var parentModelData; - var properties = Entities.getEntityProperties(data.entityID, ["type", "parentID"]); - if (properties.type === "Material" && properties.parentID !== Uuid.NULL) { - var parentType = Entities.getEntityProperties(properties.parentID, ["type"]).type; - if (parentType === "Model" || Entities.getNestableType(properties.parentID) === "avatar") { - parentModelData = Graphics.getModel(properties.parentID); - } else if (parentType === "Shape" || parentType === "Box" || parentType === "Sphere") { - parentModelData = {}; - parentModelData.numMeshes = 1; - parentModelData.materialNames = []; - } - } - emitScriptEvent({ - type: 'materialTargetReply', - entityID: data.entityID, - materialTargetData: parentModelData, - }); - } - }; - - HMD.displayModeChanged.connect(function() { - emitScriptEvent({ - type: 'hmdActiveChanged', - hmdActive: HMD.active, - }); - }); - - createToolsWindow.webEventReceived.addListener(this, onWebEventReceived); - - webView.webEventReceived.connect(this, onWebEventReceived); - - return that; -}; - - -var PopupMenu = function () { - var self = this; - - var MENU_ITEM_HEIGHT = 21; - var MENU_ITEM_SPACING = 1; - var TEXT_MARGIN = 7; - - var overlays = []; - var overlayInfo = {}; - - var visible = false; - - var upColor = { - red: 0, - green: 0, - blue: 0 - }; - var downColor = { - red: 192, - green: 192, - blue: 192 - }; - var overColor = { - red: 128, - green: 128, - blue: 128 - }; - - self.onSelectMenuItem = function () {}; - - self.addMenuItem = function (name) { - var id = Overlays.addOverlay("text", { - text: name, - backgroundAlpha: 1.0, - backgroundColor: upColor, - topMargin: TEXT_MARGIN, - leftMargin: TEXT_MARGIN, - width: 210, - height: MENU_ITEM_HEIGHT, - font: { - size: 12 - }, - visible: false - }); - overlays.push(id); - overlayInfo[id] = { - name: name - }; - return id; - }; - - self.updateMenuItemText = function (id, newText) { - Overlays.editOverlay(id, { - text: newText - }); - }; - - self.setPosition = function (x, y) { - for (var key in overlayInfo) { - Overlays.editOverlay(key, { - x: x, - y: y - }); - y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING; - } - }; - - self.onSelected = function () {}; - - var pressingOverlay = null; - var hoveringOverlay = null; - - self.mousePressEvent = function (event) { - if (event.isLeftButton) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (overlay in overlayInfo) { - pressingOverlay = overlay; - Overlays.editOverlay(pressingOverlay, { - backgroundColor: downColor - }); - } else { - self.hide(); - } - return false; - } - }; - self.mouseMoveEvent = function (event) { - if (visible) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (!pressingOverlay) { - if (hoveringOverlay !== null && overlay !== hoveringOverlay) { - Overlays.editOverlay(hoveringOverlay, { - backgroundColor: upColor - }); - hoveringOverlay = null; - } - if (overlay !== hoveringOverlay && overlay in overlayInfo) { - Overlays.editOverlay(overlay, { - backgroundColor: overColor - }); - hoveringOverlay = overlay; - } - } - } - return false; - }; - self.mouseReleaseEvent = function (event) { - var overlay = Overlays.getOverlayAtPoint({ - x: event.x, - y: event.y - }); - if (pressingOverlay !== null && pressingOverlay !== undefined) { - if (overlay === pressingOverlay) { - self.onSelectMenuItem(overlayInfo[overlay].name); - } - Overlays.editOverlay(pressingOverlay, { - backgroundColor: upColor - }); - pressingOverlay = null; - self.hide(); - } - }; - - self.setVisible = function (newVisible) { - if (newVisible !== visible) { - visible = newVisible; - for (var key in overlayInfo) { - Overlays.editOverlay(key, { - visible: newVisible - }); - } - } - }; - self.show = function () { - self.setVisible(true); - }; - self.hide = function () { - self.setVisible(false); - }; - - function cleanup() { - ContextOverlay.enabled = true; - for (var i = 0; i < overlays.length; i++) { - Overlays.deleteOverlay(overlays[i]); - } - Controller.mousePressEvent.disconnect(self.mousePressEvent); - Controller.mouseMoveEvent.disconnect(self.mouseMoveEvent); - Controller.mouseReleaseEvent.disconnect(self.mouseReleaseEvent); - - Entities.canRezChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezTmpChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezCertifiedChanged.disconnect(checkEditPermissionsAndUpdate); - Entities.canRezTmpCertifiedChanged.disconnect(checkEditPermissionsAndUpdate); - } - - Controller.mousePressEvent.connect(self.mousePressEvent); - Controller.mouseMoveEvent.connect(self.mouseMoveEvent); - Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent); - Script.scriptEnding.connect(cleanup); - - return this; -}; - -function whenPressed(fn) { - return function(value) { - if (value > 0) { - fn(); - } - }; -} - -function whenReleased(fn) { - return function(value) { - if (value === 0) { - fn(); - } - }; -} - -var isOnMacPlatform = Controller.getValue(Controller.Hardware.Application.PlatformMac); - -var mapping = Controller.newMapping(CONTROLLER_MAPPING_NAME); -if (isOnMacPlatform) { - mapping.from([Controller.Hardware.Keyboard.Backspace]).to(deleteKey); -} else { - mapping.from([Controller.Hardware.Keyboard.Delete]).to(deleteKey); -} -mapping.from([Controller.Hardware.Keyboard.T]).to(toggleKey); -mapping.from([Controller.Hardware.Keyboard.F]).to(focusKey); -mapping.from([Controller.Hardware.Keyboard.G]).to(gridKey); -mapping.from([Controller.Hardware.Keyboard.X]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.cutSelectedEntities() })); -mapping.from([Controller.Hardware.Keyboard.C]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.copySelectedEntities() })); -mapping.from([Controller.Hardware.Keyboard.V]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.pasteEntities() })); -mapping.from([Controller.Hardware.Keyboard.D]) - .when([Controller.Hardware.Keyboard.Control]) - .to(whenReleased(function() { selectionManager.duplicateSelection() })); - -// Bind undo to ctrl-shift-z to maintain backwards-compatibility -mapping.from([Controller.Hardware.Keyboard.Z]) - .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift]) - .to(whenPressed(function() { undoHistory.redo() })); - - -mapping.from([Controller.Hardware.Keyboard.P]) - .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift]) - .to(whenReleased(function() { unparentSelectedEntities(); })); - -mapping.from([Controller.Hardware.Keyboard.P]) - .when([Controller.Hardware.Keyboard.Control, !Controller.Hardware.Keyboard.Shift]) - .to(whenReleased(function() { parentSelectedEntities(); })); - -keyUpEventFromUIWindow = function(keyUpEvent) { - var WANT_DEBUG_MISSING_SHORTCUTS = false; - - var pressedValue = 0.0; - - if ((!isOnMacPlatform && keyUpEvent.keyCodeString === "Delete") - || (isOnMacPlatform && keyUpEvent.keyCodeString === "Backspace")) { - - deleteKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "T") { - toggleKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "F") { - focusKey(pressedValue); - } else if (keyUpEvent.keyCodeString === "G") { - gridKey(pressedValue); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "X") { - selectionManager.cutSelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "C") { - selectionManager.copySelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "V") { - selectionManager.pasteEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "D") { - selectionManager.duplicateSelection(); - } else if (!isOnMacPlatform && keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") { - undoHistory.undo(); // undo is only handled via handleMenuItem on Mac - } else if (keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { - parentSelectedEntities(); - } else if (keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { - unparentSelectedEntities(); - } else if (!isOnMacPlatform && - ((keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") || - (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "Y"))) { - undoHistory.redo(); // redo is only handled via handleMenuItem on Mac - } else if (WANT_DEBUG_MISSING_SHORTCUTS) { - console.warn("unhandled key event: " + JSON.stringify(keyUpEvent)) - } -}; - -var propertyMenu = new PopupMenu(); - -propertyMenu.onSelectMenuItem = function (name) { - - if (propertyMenu.marketplaceID) { - showMarketplace(propertyMenu.marketplaceID); - } -}; - -var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); - -var propertiesTool = new PropertiesTool(); - -selectionDisplay.onSpaceModeChange = function(spaceMode) { - entityListTool.setSpaceMode(spaceMode); - propertiesTool.setSpaceMode(spaceMode); -}; - -}()); // END LOCAL_SCOPE +// edit.js +// +// Created by Brad Hefta-Gaub on 10/2/14. +// Persist toolbar by HRS 6/11/15. +// Copyright 2014 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. +// +// This script allows you to edit entities with a new UI/UX for mouse and trackpad based editing +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +/* global Script, SelectionDisplay, LightOverlayManager, CameraManager, Grid, GridTool, EntityListTool, Vec3, SelectionManager, + Overlays, OverlayWebWindow, UserActivityLogger, Settings, Entities, Tablet, Toolbars, Messages, Menu, Camera, + progressDialog, tooltip, MyAvatar, Quat, Controller, Clipboard, HMD, UndoStack, OverlaySystemWindow, + keyUpEventFromUIWindow:true */ + +(function() { // BEGIN LOCAL_SCOPE + +"use strict"; + +var EDIT_TOGGLE_BUTTON = "com.highfidelity.interface.system.editButton"; + +var CONTROLLER_MAPPING_NAME = "com.highfidelity.editMode"; + +Script.include([ + "../libraries/stringHelpers.js", + "../libraries/dataViewHelpers.js", + "../libraries/progressDialog.js", + "../libraries/ToolTip.js", + "../libraries/entityCameraTool.js", + "../libraries/utils.js", + "../libraries/entityIconOverlayManager.js", + "../libraries/gridTool.js", + "entityList/entityList.js", + "entitySelectionTool/entitySelectionTool.js" +]); + +var CreateWindow = Script.require('./modules/createWindow.js'); + +var TITLE_OFFSET = 60; +var CREATE_TOOLS_WIDTH = 490; +var MAX_DEFAULT_ENTITY_LIST_HEIGHT = 942; + +var DEFAULT_IMAGE = "https://hifi-content.s3.amazonaws.com/DomainContent/production/no-image.jpg"; + +var createToolsWindow = new CreateWindow( + Script.resolvePath("qml/EditTools.qml"), + 'Create Tools', + 'com.highfidelity.create.createToolsWindow', + function () { + var windowHeight = Window.innerHeight - TITLE_OFFSET; + if (windowHeight > MAX_DEFAULT_ENTITY_LIST_HEIGHT) { + windowHeight = MAX_DEFAULT_ENTITY_LIST_HEIGHT; + } + return { + size: { + x: CREATE_TOOLS_WIDTH, + y: windowHeight + }, + position: { + x: Window.x + Window.innerWidth - CREATE_TOOLS_WIDTH, + y: Window.y + TITLE_OFFSET + } + } + }, + false +); + +/** + * @description Returns true in case we should use the tablet version of the CreateApp + * @returns boolean + */ +var shouldUseEditTabletApp = function() { + return HMD.active || (!HMD.active && !Settings.getValue("desktopTabletBecomesToolbar", true)); +}; + + +var selectionDisplay = SelectionDisplay; +var selectionManager = SelectionManager; + +var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg"); +var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg"); +var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg"); +var ZONE_URL = Script.resolvePath("assets/images/icon-zone.svg"); + +var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect', 'Zone'], function(entityID) { + var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']); + if (properties.type === 'Light') { + return { + url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL, + }; + } else if (properties.type === 'Zone') { + return { + url: ZONE_URL, + }; + } else { + return { + url: PARTICLE_SYSTEM_URL, + }; + } +}); + +var cameraManager = new CameraManager(); + +var grid = new Grid(); +var gridTool = new GridTool({ + horizontalGrid: grid, + createToolsWindow: createToolsWindow, + shouldUseEditTabletApp: shouldUseEditTabletApp +}); +gridTool.setVisible(false); + +var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js'); +var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"]); + +var entityListTool = new EntityListTool(shouldUseEditTabletApp); + +selectionManager.addEventListener(function () { + selectionDisplay.updateHandles(); + entityIconOverlayManager.updatePositions(); + entityShapeVisualizer.setEntities(selectionManager.selections); +}); + +var DEGREES_TO_RADIANS = Math.PI / 180.0; +var RADIANS_TO_DEGREES = 180.0 / Math.PI; + +var MIN_ANGULAR_SIZE = 2; +var MAX_ANGULAR_SIZE = 45; +var allowLargeModels = true; +var allowSmallModels = true; + +var DEFAULT_DIMENSION = 0.20; + +var DEFAULT_DIMENSIONS = { + x: DEFAULT_DIMENSION, + y: DEFAULT_DIMENSION, + z: DEFAULT_DIMENSION +}; + +var DEFAULT_LIGHT_DIMENSIONS = Vec3.multiply(20, DEFAULT_DIMENSIONS); + +var MENU_AUTO_FOCUS_ON_SELECT = "Auto Focus on Select"; +var MENU_EASE_ON_FOCUS = "Ease Orientation on Focus"; +var MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "Show Lights and Particle Systems in Create Mode"; +var MENU_SHOW_ZONES_IN_EDIT_MODE = "Show Zones in Create Mode"; + +var MENU_CREATE_ENTITIES_GRABBABLE = "Create Entities As Grabbable (except Zones, Particles, and Lights)"; +var MENU_ALLOW_SELECTION_LARGE = "Allow Selecting of Large Models"; +var MENU_ALLOW_SELECTION_SMALL = "Allow Selecting of Small Models"; +var MENU_ALLOW_SELECTION_LIGHTS = "Allow Selecting of Lights"; + +var SETTING_AUTO_FOCUS_ON_SELECT = "autoFocusOnSelect"; +var SETTING_EASE_ON_FOCUS = "cameraEaseOnFocus"; +var SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE = "showLightsAndParticlesInEditMode"; +var SETTING_SHOW_ZONES_IN_EDIT_MODE = "showZonesInEditMode"; + +var SETTING_EDIT_PREFIX = "Edit/"; + + +var CREATE_ENABLED_ICON = "icons/tablet-icons/edit-i.svg"; +var CREATE_DISABLED_ICON = "icons/tablet-icons/edit-disabled.svg"; + +// marketplace info, etc. not quite ready yet. +var SHOULD_SHOW_PROPERTY_MENU = false; +var INSUFFICIENT_PERMISSIONS_ERROR_MSG = "You do not have the necessary permissions to edit on this domain."; +var INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG = "You do not have the necessary permissions to place items on this domain."; + +var isActive = false; +var createButton = null; + +var IMPORTING_SVO_OVERLAY_WIDTH = 144; +var IMPORTING_SVO_OVERLAY_HEIGHT = 30; +var IMPORTING_SVO_OVERLAY_MARGIN = 5; +var IMPORTING_SVO_OVERLAY_LEFT_MARGIN = 34; +var importingSVOImageOverlay = Overlays.addOverlay("image", { + imageURL: Script.resolvePath("assets/images/hourglass.svg"), + width: 20, + height: 20, + alpha: 1.0, + x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH, + y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT, + visible: false +}); +var importingSVOTextOverlay = Overlays.addOverlay("text", { + font: { + size: 14 + }, + text: "Importing SVO...", + leftMargin: IMPORTING_SVO_OVERLAY_LEFT_MARGIN, + x: Window.innerWidth - IMPORTING_SVO_OVERLAY_WIDTH - IMPORTING_SVO_OVERLAY_MARGIN, + y: Window.innerHeight - IMPORTING_SVO_OVERLAY_HEIGHT - IMPORTING_SVO_OVERLAY_MARGIN, + width: IMPORTING_SVO_OVERLAY_WIDTH, + height: IMPORTING_SVO_OVERLAY_HEIGHT, + backgroundColor: { + red: 80, + green: 80, + blue: 80 + }, + backgroundAlpha: 0.7, + visible: false +}); + +var MARKETPLACE_URL = Account.metaverseServerURL + "/marketplace"; +var marketplaceWindow = new OverlayWebWindow({ + title: 'Marketplace', + source: "about:blank", + width: 900, + height: 700, + visible: false +}); + +function showMarketplace(marketplaceID) { + var url = MARKETPLACE_URL; + if (marketplaceID) { + url = url + "/items/" + marketplaceID; + } + marketplaceWindow.setURL(url); + marketplaceWindow.setVisible(true); + marketplaceWindow.raise(); + + UserActivityLogger.logAction("opened_marketplace"); +} + +function hideMarketplace() { + marketplaceWindow.setVisible(false); + marketplaceWindow.setURL("about:blank"); +} + +// function toggleMarketplace() { +// if (marketplaceWindow.visible) { +// hideMarketplace(); +// } else { +// showMarketplace(); +// } +// } + +function adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation) { + // Adjust the position such that the bounding box (registration, dimensions and orientation) lies behind the original + // position in the given direction. + var CORNERS = [ + { x: 0, y: 0, z: 0 }, + { x: 0, y: 0, z: 1 }, + { x: 0, y: 1, z: 0 }, + { x: 0, y: 1, z: 1 }, + { x: 1, y: 0, z: 0 }, + { x: 1, y: 0, z: 1 }, + { x: 1, y: 1, z: 0 }, + { x: 1, y: 1, z: 1 }, + ]; + + // Go through all corners and find least (most negative) distance in front of position. + var distance = 0; + for (var i = 0, length = CORNERS.length; i < length; i++) { + var cornerVector = + Vec3.multiplyQbyV(orientation, Vec3.multiplyVbyV(Vec3.subtract(CORNERS[i], registration), dimensions)); + var cornerDistance = Vec3.dot(cornerVector, direction); + distance = Math.min(cornerDistance, distance); + } + position = Vec3.sum(Vec3.multiply(distance, direction), position); + return position; +} + +var GRABBABLE_ENTITIES_MENU_CATEGORY = "Edit"; + +// Handles any edit mode updates required when domains have switched +function checkEditPermissionsAndUpdate() { + if ((createButton === null) || (createButton === undefined)) { + //--EARLY EXIT--( nothing to safely update ) + return; + } + + var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); + createButton.editProperties({ + icon: (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON), + captionColor: (hasRezPermissions ? "#ffffff" : "#888888"), + }); + + if (!hasRezPermissions && isActive) { + that.setActive(false); + tablet.gotoHomeScreen(); + } +} + +// Copies the properties in `b` into `a`. `a` will be modified. +function copyProperties(a, b) { + for (var key in b) { + a[key] = b[key]; + } + return a; +} + +const DEFAULT_DYNAMIC_PROPERTIES = { + dynamic: true, + damping: 0.39347, + angularDamping: 0.39347, + gravity: { x: 0, y: -9.8, z: 0 }, +}; + +const DEFAULT_NON_DYNAMIC_PROPERTIES = { + dynamic: false, + damping: 0, + angularDamping: 0, + gravity: { x: 0, y: 0, z: 0 }, +}; + +const DEFAULT_ENTITY_PROPERTIES = { + All: { + description: "", + rotation: { x: 0, y: 0, z: 0, w: 1 }, + collidesWith: "static,dynamic,kinematic,otherAvatar,myAvatar", + collisionSoundURL: "", + cloneable: false, + ignoreIK: true, + canCastShadow: true, + href: "", + script: "", + serverScripts:"", + velocity: { + x: 0, + y: 0, + z: 0 + }, + angularVelocity: { + x: 0, + y: 0, + z: 0 + }, + restitution: 0.5, + friction: 0.5, + density: 1000, + dynamic: false, + }, + Shape: { + shape: "Box", + dimensions: { x: 0.2, y: 0.2, z: 0.2 }, + color: { red: 0, green: 180, blue: 239 }, + }, + Text: { + text: "Text", + dimensions: { + x: 0.65, + y: 0.3, + z: 0.01 + }, + textColor: { red: 255, green: 255, blue: 255 }, + backgroundColor: { red: 0, green: 0, blue: 0 }, + lineHeight: 0.06, + faceCamera: false, + }, + Zone: { + dimensions: { + x: 10, + y: 10, + z: 10 + }, + flyingAllowed: true, + ghostingAllowed: true, + filter: "", + keyLightMode: "inherit", + keyLightColor: { red: 255, green: 255, blue: 255 }, + keyLight: { + intensity: 1.0, + direction: { + x: 0.0, + y: -0.707106769084930, // 45 degrees + z: 0.7071067690849304 + }, + castShadows: true + }, + ambientLightMode: "inherit", + ambientLight: { + ambientIntensity: 0.5, + ambientURL: "" + }, + hazeMode: "inherit", + haze: { + hazeRange: 1000, + hazeAltitudeEffect: false, + hazeBaseRef: 0, + hazeColor: { + red: 128, + green: 154, + blue: 179 + }, + hazeBackgroundBlend: 0, + hazeEnableGlare: false, + hazeGlareColor: { + red: 255, + green: 229, + blue: 179 + }, + }, + shapeType: "box", + bloomMode: "inherit", + avatarPriority: "inherit" + }, + Model: { + collisionShape: "none", + compoundShapeURL: "", + animation: { + url: "", + running: false, + allowTranslation: false, + loop: true, + hold: false, + currentFrame: 0, + firstFrame: 0, + lastFrame: 100000, + fps: 30.0, + } + }, + Image: { + dimensions: { + x: 0.5385, + y: 0.2819, + z: 0.0092 + }, + shapeType: "box", + collisionless: true, + keepAspectRatio: false, + imageURL: DEFAULT_IMAGE + }, + Web: { + dimensions: { + x: 1.6, + y: 0.9, + z: 0.01 + }, + sourceUrl: "https://projectathena.io/", + dpi: 30, + }, + ParticleEffect: { + lifespan: 1.5, + maxParticles: 10, + textures: "https://content.highfidelity.com/DomainContent/production/Particles/wispy-smoke.png", + emitRate: 5.5, + emitSpeed: 0, + speedSpread: 0, + emitDimensions: { x: 0, y: 0, z: 0 }, + emitOrientation: { x: 0, y: 0, z: 0, w: 1 }, + emitterShouldTrail: true, + particleRadius: 0.25, + radiusStart: 0, + radiusSpread: 0, + particleColor: { + red: 255, + green: 255, + blue: 255 + }, + colorSpread: { + red: 0, + green: 0, + blue: 0 + }, + alpha: 0, + alphaStart: 1, + alphaSpread: 0, + emitAcceleration: { + x: 0, + y: 2.5, + z: 0 + }, + accelerationSpread: { + x: 0, + y: 0, + z: 0 + }, + particleSpin: 0, + spinSpread: 0, + rotateWithEntity: false, + polarStart: 0, + polarFinish: Math.PI, + azimuthStart: -Math.PI, + azimuthFinish: Math.PI + }, + Light: { + color: { red: 255, green: 255, blue: 255 }, + intensity: 5.0, + dimensions: DEFAULT_LIGHT_DIMENSIONS, + falloffRadius: 1.0, + isSpotlight: false, + exponent: 1.0, + cutoff: 75.0, + }, +}; + +var toolBar = (function () { + var EDIT_SETTING = "io.highfidelity.isEditing"; // for communication with other scripts + var that = {}, + toolBar, + activeButton = null, + systemToolbar = null, + dialogWindow = null, + tablet = null; + + function createNewEntity(requestedProperties) { + var dimensions = requestedProperties.dimensions ? requestedProperties.dimensions : DEFAULT_DIMENSIONS; + var position = getPositionToCreateEntity(); + var entityID = null; + + var properties = {}; + + copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.All); + + var type = requestedProperties.type; + if (type === "Box" || type === "Sphere") { + copyProperties(properties, DEFAULT_ENTITY_PROPERTIES.Shape); + } else { + copyProperties(properties, DEFAULT_ENTITY_PROPERTIES[type]); + } + + // We apply the requested properties first so that they take priority over any default properties. + copyProperties(properties, requestedProperties); + + if (properties.dynamic) { + copyProperties(properties, DEFAULT_DYNAMIC_PROPERTIES); + } else { + copyProperties(properties, DEFAULT_NON_DYNAMIC_PROPERTIES); + } + + + if (position !== null && position !== undefined) { + var direction; + if (Camera.mode === "entity" || Camera.mode === "independent") { + direction = Camera.orientation; + } else { + direction = MyAvatar.orientation; + } + direction = Vec3.multiplyQbyV(direction, Vec3.UNIT_Z); + + var PRE_ADJUST_ENTITY_TYPES = ["Box", "Sphere", "Shape", "Text", "Image", "Web", "Material"]; + if (PRE_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { + + // Adjust position of entity per bounding box prior to creating it. + var registration = properties.registration; + if (registration === undefined) { + var DEFAULT_REGISTRATION = { x: 0.5, y: 0.5, z: 0.5 }; + registration = DEFAULT_REGISTRATION; + } + + var orientation = properties.orientation; + if (orientation === undefined) { + properties.orientation = MyAvatar.orientation; + var DEFAULT_ORIENTATION = properties.orientation; + orientation = DEFAULT_ORIENTATION; + } else { + // If the orientation is already defined, we perform the corresponding rotation assuming that + // our start referential is the avatar referential. + properties.orientation = Quat.multiply(MyAvatar.orientation, properties.orientation); + var DEFAULT_ORIENTATION = properties.orientation; + orientation = DEFAULT_ORIENTATION; + } + + position = adjustPositionPerBoundingBox(position, direction, registration, dimensions, orientation); + } + + position = grid.snapToSurface(grid.snapToGrid(position, false, dimensions), dimensions); + properties.position = position; + + if (!properties.grab) { + properties.grab = {}; + if (Menu.isOptionChecked(MENU_CREATE_ENTITIES_GRABBABLE) && + !(properties.type === "Zone" || properties.type === "Light" || properties.type === "ParticleEffect")) { + properties.grab.grabbable = true; + } else { + properties.grab.grabbable = false; + } + } + + entityID = Entities.addEntity(properties); + SelectionManager.addEntity(entityID, false, this); + SelectionManager.saveProperties(); + pushCommandForSelections([{ + entityID: entityID, + properties: properties + }], [], true); + + var POST_ADJUST_ENTITY_TYPES = ["Model"]; + if (POST_ADJUST_ENTITY_TYPES.indexOf(properties.type) !== -1) { + // Adjust position of entity per bounding box after it has been created and auto-resized. + var initialDimensions = Entities.getEntityProperties(entityID, ["dimensions"]).dimensions; + var DIMENSIONS_CHECK_INTERVAL = 200; + var MAX_DIMENSIONS_CHECKS = 10; + var dimensionsCheckCount = 0; + var dimensionsCheckFunction = function () { + dimensionsCheckCount++; + var properties = Entities.getEntityProperties(entityID, ["dimensions", "registrationPoint", "rotation"]); + if (!Vec3.equal(properties.dimensions, initialDimensions)) { + position = adjustPositionPerBoundingBox(position, direction, properties.registrationPoint, + properties.dimensions, properties.rotation); + position = grid.snapToSurface(grid.snapToGrid(position, false, properties.dimensions), + properties.dimensions); + Entities.editEntity(entityID, { + position: position + }); + selectionManager._update(false, this); + } else if (dimensionsCheckCount < MAX_DIMENSIONS_CHECKS) { + Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL); + } + }; + Script.setTimeout(dimensionsCheckFunction, DIMENSIONS_CHECK_INTERVAL); + } + } else { + Window.notifyEditError("Can't create " + properties.type + ": " + + properties.type + " would be out of bounds."); + } + + selectionManager.clearSelections(this); + entityListTool.sendUpdate(); + selectionManager.setSelections([entityID], this); + + Window.setFocus(); + + return entityID; + } + + function closeExistingDialogWindow() { + if (dialogWindow) { + dialogWindow.close(); + dialogWindow = null; + } + } + + function cleanup() { + that.setActive(false); + if (tablet) { + tablet.removeButton(activeButton); + } + if (systemToolbar) { + systemToolbar.removeButton(EDIT_TOGGLE_BUTTON); + } + } + + var buttonHandlers = {}; // only used to tablet mode + + function addButton(name, handler) { + buttonHandlers[name] = handler; + } + + var SHAPE_TYPE_NONE = 0; + var SHAPE_TYPE_SIMPLE_HULL = 1; + var SHAPE_TYPE_SIMPLE_COMPOUND = 2; + var SHAPE_TYPE_STATIC_MESH = 3; + var SHAPE_TYPE_BOX = 4; + var SHAPE_TYPE_SPHERE = 5; + var DYNAMIC_DEFAULT = false; + + var MATERIAL_MODE_UV = 0; + var MATERIAL_MODE_PROJECTED = 1; + + function handleNewModelDialogResult(result) { + if (result) { + var url = result.url; + var shapeType; + switch (result.collisionShapeIndex) { + case SHAPE_TYPE_SIMPLE_HULL: + shapeType = "simple-hull"; + break; + case SHAPE_TYPE_SIMPLE_COMPOUND: + shapeType = "simple-compound"; + break; + case SHAPE_TYPE_STATIC_MESH: + shapeType = "static-mesh"; + break; + case SHAPE_TYPE_BOX: + shapeType = "box"; + break; + case SHAPE_TYPE_SPHERE: + shapeType = "sphere"; + break; + default: + shapeType = "none"; + } + + var dynamic = result.dynamic !== null ? result.dynamic : DYNAMIC_DEFAULT; + if (shapeType === "static-mesh" && dynamic) { + // The prompt should prevent this case + print("Error: model cannot be both static mesh and dynamic. This should never happen."); + } else if (url) { + createNewEntity({ + type: "Model", + modelURL: url, + shapeType: shapeType, + grab: { + grabbable: result.grabbable + }, + dynamic: dynamic, + }); + } + } + } + + function handleNewMaterialDialogResult(result) { + if (result) { + var materialURL = result.textInput; + //var materialMappingMode; + //switch (result.comboBox) { + // case MATERIAL_MODE_PROJECTED: + // materialMappingMode = "projected"; + // break; + // default: + // shapeType = "uv"; + //} + var materialData = ""; + if (materialURL.startsWith("materialData")) { + materialData = JSON.stringify({ + "materials": {} + }); + } + + var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1; + if (materialURL) { + createNewEntity({ + type: "Material", + materialURL: materialURL, + //materialMappingMode: materialMappingMode, + priority: DEFAULT_LAYERED_MATERIAL_PRIORITY, + materialData: materialData + }); + } + } + } + + function fromQml(message) { // messages are {method, params}, like json-rpc. See also sendToQml. + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet.popFromStack(); + switch (message.method) { + case "newModelDialogAdd": + handleNewModelDialogResult(message.params); + closeExistingDialogWindow(); + break; + case "newModelDialogCancel": + closeExistingDialogWindow(); + break; + case "newEntityButtonClicked": + buttonHandlers[message.params.buttonName](); + break; + case "newMaterialDialogAdd": + handleNewMaterialDialogResult(message.params); + closeExistingDialogWindow(); + break; + case "newMaterialDialogCancel": + closeExistingDialogWindow(); + break; + } + } + + var entitiesToDelete = []; + var deletedEntityTimer = null; + var DELETE_ENTITY_TIMER_TIMEOUT = 100; + + function checkDeletedEntityAndUpdate(entityID) { + // Allow for multiple entity deletes before updating the entities selected. + entitiesToDelete.push(entityID); + if (deletedEntityTimer !== null) { + Script.clearTimeout(deletedEntityTimer); + } + deletedEntityTimer = Script.setTimeout(function () { + if (entitiesToDelete.length > 0) { + selectionManager.removeEntities(entitiesToDelete, this); + } + entityListTool.removeEntities(entitiesToDelete, selectionManager.selections); + entitiesToDelete = []; + deletedEntityTimer = null; + }, DELETE_ENTITY_TIMER_TIMEOUT); + } + + function initialize() { + Script.scriptEnding.connect(cleanup); + Window.domainChanged.connect(function () { + if (isActive) { + tablet.gotoHomeScreen(); + } + that.setActive(false); + that.clearEntityList(); + checkEditPermissionsAndUpdate(); + }); + + HMD.displayModeChanged.connect(function() { + if (isActive) { + tablet.gotoHomeScreen(); + } + that.setActive(false); + }); + + Entities.canAdjustLocksChanged.connect(function (canAdjustLocks) { + if (isActive && !canAdjustLocks) { + that.setActive(false); + } + checkEditPermissionsAndUpdate(); + }); + + Entities.canRezChanged.connect(checkEditPermissionsAndUpdate); + Entities.canRezTmpChanged.connect(checkEditPermissionsAndUpdate); + Entities.canRezCertifiedChanged.connect(checkEditPermissionsAndUpdate); + Entities.canRezTmpCertifiedChanged.connect(checkEditPermissionsAndUpdate); + var hasRezPermissions = (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()); + + Entities.deletingEntity.connect(checkDeletedEntityAndUpdate); + + var createButtonIconRsrc = (hasRezPermissions ? CREATE_ENABLED_ICON : CREATE_DISABLED_ICON); + tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + activeButton = tablet.addButton({ + captionColor: hasRezPermissions ? "#ffffff" : "#888888", + icon: createButtonIconRsrc, + activeIcon: "icons/tablet-icons/edit-a.svg", + text: "CREATE", + sortOrder: 10 + }); + createButton = activeButton; + tablet.screenChanged.connect(function (type, url) { + var isGoingToHomescreenOnDesktop = (!shouldUseEditTabletApp() && + (url === 'hifi/tablet/TabletHome.qml' || url === '')); + if (isActive && (type !== "QML" || url !== Script.resolvePath("qml/Edit.qml")) && !isGoingToHomescreenOnDesktop) { + that.setActive(false); + } + }); + tablet.fromQml.connect(fromQml); + createToolsWindow.fromQml.addListener(fromQml); + + createButton.clicked.connect(function() { + if ( ! (Entities.canRez() || Entities.canRezTmp() || Entities.canRezCertified() || Entities.canRezTmpCertified()) ) { + Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG); + return; + } + + that.toggle(); + }); + + addButton("importEntitiesButton", function() { + Window.browseChanged.connect(onFileOpenChanged); + Window.browseAsync("Select Model to Import", "", "*.json"); + }); + + addButton("openAssetBrowserButton", function() { + Window.showAssetServer(); + }); + function createNewEntityDialogButtonCallback(entityType) { + return function() { + if (shouldUseEditTabletApp()) { + // tablet version of new-model dialog + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + tablet.pushOntoStack(Script.resolvePath("qml/New" + entityType + "Dialog.qml")); + } else { + closeExistingDialogWindow(); + var qmlPath = Script.resolvePath("qml/New" + entityType + "Window.qml"); + var DIALOG_WINDOW_SIZE = { x: 500, y: 300 }; + dialogWindow = Desktop.createWindow(qmlPath, { + title: "New " + entityType + " Entity", + additionalFlags: Desktop.ALWAYS_ON_TOP | Desktop.CLOSE_BUTTON_HIDES, + presentationMode: Desktop.PresentationMode.NATIVE, + size: DIALOG_WINDOW_SIZE, + visible: true + }); + dialogWindow.fromQml.connect(fromQml); + } + }; + } + + addButton("newModelButton", createNewEntityDialogButtonCallback("Model")); + + addButton("newShapeButton", function () { + createNewEntity({ + type: "Shape", + shape: "Cube", + }); + }); + + addButton("newLightButton", function () { + createNewEntity({ + type: "Light", + }); + }); + + addButton("newTextButton", function () { + createNewEntity({ + type: "Text", + }); + }); + + addButton("newImageButton", function () { + createNewEntity({ + type: "Image", + }); + }); + + addButton("newWebButton", function () { + createNewEntity({ + type: "Web", + }); + }); + + addButton("newZoneButton", function () { + createNewEntity({ + type: "Zone", + }); + }); + + addButton("newParticleButton", function () { + createNewEntity({ + type: "ParticleEffect", + }); + }); + + addButton("newMaterialButton", createNewEntityDialogButtonCallback("Material")); + + var deactivateCreateIfDesktopWindowsHidden = function() { + if (!shouldUseEditTabletApp() && !entityListTool.isVisible() && !createToolsWindow.isVisible()) { + that.setActive(false); + } + }; + entityListTool.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden); + createToolsWindow.interactiveWindowHidden.addListener(this, deactivateCreateIfDesktopWindowsHidden); + + that.setActive(false); + } + + that.clearEntityList = function () { + entityListTool.clearEntityList(); + }; + + that.toggle = function () { + that.setActive(!isActive); + if (!isActive) { + tablet.gotoHomeScreen(); + } + }; + + that.setActive = function (active) { + ContextOverlay.enabled = !active; + Settings.setValue(EDIT_SETTING, active); + if (active) { + Controller.captureEntityClickEvents(); + } else { + Controller.releaseEntityClickEvents(); + + closeExistingDialogWindow(); + } + if (active === isActive) { + return; + } + if (active && !Entities.canRez() && !Entities.canRezTmp() && !Entities.canRezCertified() && !Entities.canRezTmpCertified()) { + Window.notifyEditError(INSUFFICIENT_PERMISSIONS_ERROR_MSG); + return; + } + Messages.sendLocalMessage("edit-events", JSON.stringify({ + enabled: active + })); + isActive = active; + activeButton.editProperties({isActive: isActive}); + undoHistory.setEnabled(isActive); + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + + if (!isActive) { + entityListTool.setVisible(false); + gridTool.setVisible(false); + grid.setEnabled(false); + propertiesTool.setVisible(false); + selectionManager.clearSelections(this); + cameraManager.disable(); + selectionDisplay.disableTriggerMapping(); + tablet.landscape = false; + Controller.disableMapping(CONTROLLER_MAPPING_NAME); + } else { + if (shouldUseEditTabletApp()) { + tablet.loadQMLSource(Script.resolvePath("qml/Edit.qml"), true); + } else { + // make other apps inactive while in desktop mode + tablet.gotoHomeScreen(); + } + UserActivityLogger.enabledEdit(); + entityListTool.setVisible(true); + entityListTool.sendUpdate(); + gridTool.setVisible(true); + grid.setEnabled(true); + propertiesTool.setVisible(true); + selectionDisplay.enableTriggerMapping(); + print("starting tablet in landscape mode"); + tablet.landscape = true; + Controller.enableMapping(CONTROLLER_MAPPING_NAME); + // Not sure what the following was meant to accomplish, but it currently causes + // everybody else to think that Interface has lost focus overall. fogbugzid:558 + // Window.setFocus(); + } + entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); + Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); + }; + + initialize(); + return that; +})(); + +var selectedEntityID; +var orientation; +var intersection; + + +function rayPlaneIntersection(pickRay, point, normal) { // + // + // This version of the test returns the intersection of a line with a plane + // + var collides = Vec3.dot(pickRay.direction, normal); + + var d = -Vec3.dot(point, normal); + var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides; + + return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); +} + +function rayPlaneIntersection2(pickRay, point, normal) { + // + // This version of the test returns false if the ray is directed away from the plane + // + var collides = Vec3.dot(pickRay.direction, normal); + var d = -Vec3.dot(point, normal); + var t = -(Vec3.dot(pickRay.origin, normal) + d) / collides; + if (t < 0.0) { + return false; + } else { + return Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction, t)); + } +} + +function findClickedEntity(event) { + var pickZones = event.isControl; + + if (pickZones) { + Entities.setZonesArePickable(true); + } + + var pickRay = Camera.computePickRay(event.x, event.y); + var tabletIDs = getMainTabletIDs(); + if (tabletIDs.length > 0) { + var overlayResult = Overlays.findRayIntersection(pickRay, true, tabletIDs); + if (overlayResult.intersects) { + return null; + } + } + + var entityResult = Entities.findRayIntersection(pickRay, true); // want precision picking + var iconResult = entityIconOverlayManager.findRayIntersection(pickRay); + iconResult.accurate = true; + + if (pickZones) { + Entities.setZonesArePickable(false); + } + + var result; + + if (iconResult.intersects) { + result = iconResult; + } else if (entityResult.intersects) { + result = entityResult; + } else { + return null; + } + + if (!result.accurate) { + return null; + } + + var foundEntity = result.entityID; + return { + pickRay: pickRay, + entityID: foundEntity, + intersection: result.intersection + }; +} + +// Handles selections on overlays while in edit mode by querying entities from +// entityIconOverlayManager. +function handleOverlaySelectionToolUpdates(channel, message, sender) { + var wantDebug = false; + if (sender !== MyAvatar.sessionUUID || channel !== 'entityToolUpdates') + return; + + var data = JSON.parse(message); + + if (data.method === "selectOverlay") { + if (!selectionDisplay.triggered() || selectionDisplay.triggeredHand === data.hand) { + if (wantDebug) { + print("setting selection to overlay " + data.overlayID); + } + var entity = entityIconOverlayManager.findEntity(data.overlayID); + + if (entity !== null) { + selectionManager.setSelections([entity], this); + } + } + } +} + +function handleMessagesReceived(channel, message, sender) { + switch( channel ){ + case 'entityToolUpdates': { + handleOverlaySelectionToolUpdates( channel, message, sender ); + break; + } + default: { + return; + } + } +} + +Messages.subscribe("entityToolUpdates"); +Messages.messageReceived.connect(handleMessagesReceived); + +var mouseHasMovedSincePress = false; +var mousePressStartTime = 0; +var mousePressStartPosition = { + x: 0, + y: 0 +}; +var mouseDown = false; + +function mousePressEvent(event) { + mouseDown = true; + mousePressStartPosition = { + x: event.x, + y: event.y + }; + mousePressStartTime = Date.now(); + mouseHasMovedSincePress = false; + mouseCapturedByTool = false; + + if (propertyMenu.mousePressEvent(event) || progressDialog.mousePressEvent(event)) { + mouseCapturedByTool = true; + return; + } + if (isActive) { + if (cameraManager.mousePressEvent(event) || selectionDisplay.mousePressEvent(event)) { + // Event handled; do nothing. + return; + } + } +} + +var mouseCapturedByTool = false; +var lastMousePosition = null; +var CLICK_TIME_THRESHOLD = 500 * 1000; // 500 ms +var CLICK_MOVE_DISTANCE_THRESHOLD = 20; +var IDLE_MOUSE_TIMEOUT = 200; + +var lastMouseMoveEvent = null; + +function mouseMoveEventBuffered(event) { + lastMouseMoveEvent = event; +} + +function mouseMove(event) { + if (mouseDown && !mouseHasMovedSincePress) { + var timeSincePressMicro = Date.now() - mousePressStartTime; + + var dX = mousePressStartPosition.x - event.x; + var dY = mousePressStartPosition.y - event.y; + var sqDist = (dX * dX) + (dY * dY); + + // If less than CLICK_TIME_THRESHOLD has passed since the mouse click AND the mouse has moved + // less than CLICK_MOVE_DISTANCE_THRESHOLD distance, then don't register this as a mouse move + // yet. The goal is to provide mouse clicks that are more lenient to small movements. + if (timeSincePressMicro < CLICK_TIME_THRESHOLD && sqDist < CLICK_MOVE_DISTANCE_THRESHOLD) { + return; + } + mouseHasMovedSincePress = true; + } + + if (!isActive) { + return; + } + + // allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing + if (selectionDisplay.mouseMoveEvent(event) || propertyMenu.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) { + return; + } + + lastMousePosition = { + x: event.x, + y: event.y + }; +} + +function mouseReleaseEvent(event) { + mouseDown = false; + + if (lastMouseMoveEvent) { + mouseMove(lastMouseMoveEvent); + lastMouseMoveEvent = null; + } + if (propertyMenu.mouseReleaseEvent(event)) { + return true; + } + if (isActive && selectionManager.hasSelection()) { + tooltip.show(false); + } + if (mouseCapturedByTool) { + + return; + } + + cameraManager.mouseReleaseEvent(event); + + if (!mouseHasMovedSincePress) { + mouseClickEvent(event); + } +} + +function wasTabletOrEditHandleClicked(event) { + var rayPick = Camera.computePickRay(event.x, event.y); + var result = Overlays.findRayIntersection(rayPick, true); + if (result.intersects) { + var overlayID = result.overlayID; + var tabletIDs = getMainTabletIDs(); + if (tabletIDs.indexOf(overlayID) >= 0) { + return true; + } else if (selectionDisplay.isEditHandle(overlayID)) { + return true; + } + } + return false; +} + +function mouseClickEvent(event) { + var wantDebug = false; + var result, properties, tabletClicked; + if (isActive && event.isLeftButton) { + result = findClickedEntity(event); + var tabletOrEditHandleClicked = wasTabletOrEditHandleClicked(event); + if (tabletOrEditHandleClicked) { + return; + } + + if (result === null || result === undefined) { + if (!event.isShifted) { + selectionManager.clearSelections(this); + } + return; + } + toolBar.setActive(true); + var pickRay = result.pickRay; + var foundEntity = result.entityID; + if (HMD.tabletID && foundEntity === HMD.tabletID) { + return; + } + properties = Entities.getEntityProperties(foundEntity); + var halfDiagonal = Vec3.length(properties.dimensions) / 2.0; + + if (wantDebug) { + print("Checking properties: " + properties.id + " " + " - Half Diagonal:" + halfDiagonal); + } + // P P - Model + // /| A - Palm + // / | d B - unit vector toward tip + // / | X - base of the perpendicular line + // A---X----->B d - distance fom axis + // x x - distance from A + // + // |X-A| = (P-A).B + // X === A + ((P-A).B)B + // d = |P-X| + + var A = pickRay.origin; + var B = Vec3.normalize(pickRay.direction); + var P = properties.position; + + var x = Vec3.dot(Vec3.subtract(P, A), B); + + var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * + 180 / Math.PI; + + var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE) && + (allowSmallModels || angularSize > MIN_ANGULAR_SIZE); + + if (0 < x && sizeOK) { + selectedEntityID = foundEntity; + orientation = MyAvatar.orientation; + intersection = rayPlaneIntersection(pickRay, P, Quat.getForward(orientation)); + + if (!event.isShifted) { + selectionManager.setSelections([foundEntity], this); + } else { + selectionManager.addEntity(foundEntity, true, this); + } + selectionManager.saveProperties(); + + if (wantDebug) { + print("Model selected: " + foundEntity); + } + selectionDisplay.select(selectedEntityID, event); + + if (Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)) { + cameraManager.enable(); + cameraManager.focus(selectionManager.worldPosition, + selectionManager.worldDimensions, + Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + } + } + } else if (event.isRightButton) { + result = findClickedEntity(event); + if (result) { + if (SHOULD_SHOW_PROPERTY_MENU !== true) { + return; + } + properties = Entities.getEntityProperties(result.entityID); + if (properties.marketplaceID) { + propertyMenu.marketplaceID = properties.marketplaceID; + propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); + } else { + propertyMenu.marketplaceID = null; + propertyMenu.updateMenuItemText(showMenuItem, "No marketplace info"); + } + propertyMenu.setPosition(event.x, event.y); + propertyMenu.show(); + } else { + propertyMenu.hide(); + } + } +} + +Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseMoveEvent.connect(mouseMoveEventBuffered); +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + + +// In order for editVoxels and editModels to play nice together, they each check to see if a "delete" menu item already +// exists. If it doesn't they add it. If it does they don't. They also only delete the menu item if they were the one that +// added it. +var modelMenuAddedDelete = false; +var originalLightsArePickable = Entities.getLightsArePickable(); + +function setupModelMenus() { + // adj our menuitems + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Undo", + shortcutKey: 'Ctrl+Z', + position: 0, + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Redo", + shortcutKey: 'Ctrl+Y', + position: 1, + }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Entities", + isSeparator: true + }); + if (!Menu.menuItemExists("Edit", "Delete")) { + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Delete", + shortcutKeyEvent: { + text: "delete" + }, + afterItem: "Entities", + }); + modelMenuAddedDelete = true; + } + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Parent Entity to Last", + afterItem: "Entities" + }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Unparent Entity", + afterItem: "Parent Entity to Last" + }); + + Menu.addMenuItem({ + menuName: GRABBABLE_ENTITIES_MENU_CATEGORY, + menuItemName: MENU_CREATE_ENTITIES_GRABBABLE, + afterItem: "Unparent Entity", + isCheckable: true, + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_CREATE_ENTITIES_GRABBABLE, true) + }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_ALLOW_SELECTION_LARGE, + afterItem: MENU_CREATE_ENTITIES_GRABBABLE, + isCheckable: true, + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, true) + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_ALLOW_SELECTION_SMALL, + afterItem: MENU_ALLOW_SELECTION_LARGE, + isCheckable: true, + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, true) + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_ALLOW_SELECTION_LIGHTS, + afterItem: MENU_ALLOW_SELECTION_SMALL, + isCheckable: true, + isChecked: Settings.getValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, false) + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Select All Entities In Box", + afterItem: "Allow Selecting of Lights" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Select All Entities Touching Box", + afterItem: "Select All Entities In Box" + }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Export Entities", + afterItem: "Entities" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Import Entities", + afterItem: "Export Entities" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: "Import Entities from URL", + afterItem: "Import Entities" + }); + + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_AUTO_FOCUS_ON_SELECT, + isCheckable: true, + isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) === "true" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_EASE_ON_FOCUS, + afterItem: MENU_AUTO_FOCUS_ON_SELECT, + isCheckable: true, + isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) === "true" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, + afterItem: MENU_EASE_ON_FOCUS, + isCheckable: true, + isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) !== "false" + }); + Menu.addMenuItem({ + menuName: "Edit", + menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE, + afterItem: MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, + isCheckable: true, + isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) !== "false" + }); + + Entities.setLightsArePickable(false); +} + +setupModelMenus(); // do this when first running our script. + +function cleanupModelMenus() { + Menu.removeMenuItem("Edit", "Undo"); + Menu.removeMenuItem("Edit", "Redo"); + + Menu.removeSeparator("Edit", "Entities"); + if (modelMenuAddedDelete) { + // delete our menuitems + Menu.removeMenuItem("Edit", "Delete"); + } + + Menu.removeMenuItem("Edit", "Parent Entity to Last"); + Menu.removeMenuItem("Edit", "Unparent Entity"); + Menu.removeMenuItem("Edit", "Allow Selecting of Large Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Small Models"); + Menu.removeMenuItem("Edit", "Allow Selecting of Lights"); + Menu.removeMenuItem("Edit", "Select All Entities In Box"); + Menu.removeMenuItem("Edit", "Select All Entities Touching Box"); + + Menu.removeMenuItem("Edit", "Export Entities"); + Menu.removeMenuItem("Edit", "Import Entities"); + Menu.removeMenuItem("Edit", "Import Entities from URL"); + + Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT); + Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS); + Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE); + Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE); + Menu.removeMenuItem("Edit", MENU_CREATE_ENTITIES_GRABBABLE); +} + +Script.scriptEnding.connect(function () { + toolBar.setActive(false); + Settings.setValue(SETTING_AUTO_FOCUS_ON_SELECT, Menu.isOptionChecked(MENU_AUTO_FOCUS_ON_SELECT)); + Settings.setValue(SETTING_EASE_ON_FOCUS, Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + Settings.setValue(SETTING_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); + Settings.setValue(SETTING_SHOW_ZONES_IN_EDIT_MODE, Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); + + Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LARGE, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LARGE)); + Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_SMALL, Menu.isOptionChecked(MENU_ALLOW_SELECTION_SMALL)); + Settings.setValue(SETTING_EDIT_PREFIX + MENU_ALLOW_SELECTION_LIGHTS, Menu.isOptionChecked(MENU_ALLOW_SELECTION_LIGHTS)); + + + progressDialog.cleanup(); + cleanupModelMenus(); + tooltip.cleanup(); + selectionDisplay.cleanup(); + entityShapeVisualizer.cleanup(); + Entities.setLightsArePickable(originalLightsArePickable); + + Overlays.deleteOverlay(importingSVOImageOverlay); + Overlays.deleteOverlay(importingSVOTextOverlay); + + Controller.keyReleaseEvent.disconnect(keyReleaseEvent); + Controller.keyPressEvent.disconnect(keyPressEvent); + + Controller.mousePressEvent.disconnect(mousePressEvent); + Controller.mouseMoveEvent.disconnect(mouseMoveEventBuffered); + Controller.mouseReleaseEvent.disconnect(mouseReleaseEvent); + + Messages.messageReceived.disconnect(handleMessagesReceived); + Messages.unsubscribe("entityToolUpdates"); + createButton = null; +}); + +var lastOrientation = null; +var lastPosition = null; + +// Do some stuff regularly, like check for placement of various overlays +Script.update.connect(function (deltaTime) { + progressDialog.move(); + selectionDisplay.checkControllerMove(); + var dOrientation = Math.abs(Quat.dot(Camera.orientation, lastOrientation) - 1); + var dPosition = Vec3.distance(Camera.position, lastPosition); + if (dOrientation > 0.001 || dPosition > 0.001) { + propertyMenu.hide(); + lastOrientation = Camera.orientation; + lastPosition = Camera.position; + } + if (lastMouseMoveEvent) { + mouseMove(lastMouseMoveEvent); + lastMouseMoveEvent = null; + } +}); + +function insideBox(center, dimensions, point) { + return (Math.abs(point.x - center.x) <= (dimensions.x / 2.0)) && + (Math.abs(point.y - center.y) <= (dimensions.y / 2.0)) && + (Math.abs(point.z - center.z) <= (dimensions.z / 2.0)); +} + +function selectAllEntitiesInCurrentSelectionBox(keepIfTouching) { + if (selectionManager.hasSelection()) { + // Get all entities touching the bounding box of the current selection + var boundingBoxCorner = Vec3.subtract(selectionManager.worldPosition, + Vec3.multiply(selectionManager.worldDimensions, 0.5)); + var entities = Entities.findEntitiesInBox(boundingBoxCorner, selectionManager.worldDimensions); + + if (!keepIfTouching) { + var isValid; + if (selectionManager.localPosition === null || selectionManager.localPosition === undefined) { + isValid = function (position) { + return insideBox(selectionManager.worldPosition, selectionManager.worldDimensions, position); + }; + } else { + isValid = function (position) { + var localPosition = Vec3.multiplyQbyV(Quat.inverse(selectionManager.localRotation), + Vec3.subtract(position, + selectionManager.localPosition)); + return insideBox(Vec3.ZERO, selectionManager.localDimensions, localPosition); + }; + } + for (var i = 0; i < entities.length; ++i) { + var properties = Entities.getEntityProperties(entities[i]); + if (!isValid(properties.position)) { + entities.splice(i, 1); + --i; + } + } + } + selectionManager.setSelections(entities, this); + } +} + +function sortSelectedEntities(selected) { + var sortedEntities = selected.slice(); + var begin = 0; + while (begin < sortedEntities.length) { + var elementRemoved = false; + var next = begin + 1; + while (next < sortedEntities.length) { + var beginID = sortedEntities[begin]; + var nextID = sortedEntities[next]; + + if (Entities.isChildOfParent(beginID, nextID)) { + sortedEntities[begin] = nextID; + sortedEntities[next] = beginID; + sortedEntities.splice(next, 1); + elementRemoved = true; + break; + } else if (Entities.isChildOfParent(nextID, beginID)) { + sortedEntities.splice(next, 1); + elementRemoved = true; + break; + } + next++; + } + if (!elementRemoved) { + begin++; + } + } + return sortedEntities; +} + +function recursiveDelete(entities, childrenList, deletedIDs, entityHostType) { + var wantDebug = false; + var entitiesLength = entities.length; + var initialPropertySets = Entities.getMultipleEntityProperties(entities); + var entityHostTypes = Entities.getMultipleEntityProperties(entities, 'entityHostType'); + for (var i = 0; i < entitiesLength; ++i) { + var entityID = entities[i]; + + if (entityHostTypes[i].entityHostType !== entityHostType) { + if (wantDebug) { + console.log("Skipping deletion of entity " + entityID + " with conflicting entityHostType: " + + entityHostTypes[i].entityHostType + ", expected: " + entityHostType); + } + continue; + } + + var children = Entities.getChildrenIDs(entityID); + var grandchildrenList = []; + recursiveDelete(children, grandchildrenList, deletedIDs, entityHostType); + childrenList.push({ + entityID: entityID, + properties: initialPropertySets[i], + children: grandchildrenList + }); + deletedIDs.push(entityID); + Entities.deleteEntity(entityID); + } +} + +function unparentSelectedEntities() { + if (SelectionManager.hasSelection()) { + var selectedEntities = selectionManager.selections; + var parentCheck = false; + + if (selectedEntities.length < 1) { + Window.notifyEditError("You must have an entity selected in order to unparent it."); + return; + } + selectedEntities.forEach(function (id, index) { + var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; + if (parentId !== null && parentId.length > 0 && parentId !== Uuid.NULL) { + parentCheck = true; + } + Entities.editEntity(id, {parentID: null}); + return true; + }); + if (parentCheck) { + if (selectedEntities.length > 1) { + Window.notify("Entities unparented"); + } else { + Window.notify("Entity unparented"); + } + } else { + if (selectedEntities.length > 1) { + Window.notify("Selected Entities have no parents"); + } else { + Window.notify("Selected Entity does not have a parent"); + } + } + } else { + Window.notifyEditError("You have nothing selected to unparent"); + } +} +function parentSelectedEntities() { + if (SelectionManager.hasSelection()) { + var selectedEntities = selectionManager.selections; + if (selectedEntities.length <= 1) { + Window.notifyEditError("You must have multiple entities selected in order to parent them"); + return; + } + var parentCheck = false; + var lastEntityId = selectedEntities[selectedEntities.length - 1]; + selectedEntities.forEach(function (id, index) { + if (lastEntityId !== id) { + var parentId = Entities.getEntityProperties(id, ["parentID"]).parentID; + if (parentId !== lastEntityId) { + parentCheck = true; + } + Entities.editEntity(id, {parentID: lastEntityId}); + } + }); + + if (parentCheck) { + Window.notify("Entities parented"); + } else { + Window.notify("Entities are already parented to last"); + } + } else { + Window.notifyEditError("You have nothing selected to parent"); + } +} +function deleteSelectedEntities() { + if (SelectionManager.hasSelection()) { + var deletedIDs = []; + + SelectionManager.saveProperties(); + var savedProperties = []; + var newSortedSelection = sortSelectedEntities(selectionManager.selections); + var entityHostTypes = Entities.getMultipleEntityProperties(newSortedSelection, 'entityHostType'); + for (var i = 0; i < newSortedSelection.length; ++i) { + var entityID = newSortedSelection[i]; + var initialProperties = SelectionManager.savedProperties[entityID]; + if (initialProperties.locked || + (initialProperties.avatarEntity && initialProperties.owningAvatarID !== MyAvatar.sessionUUID)) { + continue; + } + var children = Entities.getChildrenIDs(entityID); + var childList = []; + recursiveDelete(children, childList, deletedIDs, entityHostTypes[i].entityHostType); + savedProperties.push({ + entityID: entityID, + properties: initialProperties, + children: childList + }); + deletedIDs.push(entityID); + Entities.deleteEntity(entityID); + } + + if (savedProperties.length > 0) { + SelectionManager.clearSelections(this); + pushCommandForSelections([], savedProperties); + entityListTool.deleteEntities(deletedIDs); + } + } +} + +function toggleSelectedEntitiesLocked() { + if (SelectionManager.hasSelection()) { + var locked = !Entities.getEntityProperties(SelectionManager.selections[0], ["locked"]).locked; + for (var i = 0; i < selectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + Entities.editEntity(entityID, { + locked: locked + }); + } + entityListTool.sendUpdate(); + selectionManager._update(false, this); + } +} + +function toggleSelectedEntitiesVisible() { + if (SelectionManager.hasSelection()) { + var visible = !Entities.getEntityProperties(SelectionManager.selections[0], ["visible"]).visible; + for (var i = 0; i < selectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + Entities.editEntity(entityID, { + visible: visible + }); + } + entityListTool.sendUpdate(); + selectionManager._update(false, this); + } +} + +function onFileSaveChanged(filename) { + Window.saveFileChanged.disconnect(onFileSaveChanged); + if (filename !== "") { + var success = Clipboard.exportEntities(filename, selectionManager.selections); + if (!success) { + Window.notifyEditError("Export failed."); + } + } +} + +function onFileOpenChanged(filename) { + // disconnect the event, otherwise the requests will stack up + try { + // Not all calls to onFileOpenChanged() connect an event. + Window.browseChanged.disconnect(onFileOpenChanged); + } catch (e) { + // Ignore. + } + + var importURL = null; + if (filename !== "") { + importURL = filename; + if (!/^(http|https):\/\//.test(filename)) { + importURL = "file:///" + importURL; + } + } + if (importURL) { + if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) { + toolBar.toggle(); + } + importSVO(importURL); + } +} + +function onPromptTextChanged(prompt) { + Window.promptTextChanged.disconnect(onPromptTextChanged); + if (prompt !== "") { + if (!isActive && (Entities.canRez() && Entities.canRezTmp() && Entities.canRezCertified() && Entities.canRezTmpCertified())) { + toolBar.toggle(); + } + importSVO(prompt); + } +} + +function handleMenuEvent(menuItem) { + if (menuItem === "Allow Selecting of Small Models") { + allowSmallModels = Menu.isOptionChecked("Allow Selecting of Small Models"); + } else if (menuItem === "Allow Selecting of Large Models") { + allowLargeModels = Menu.isOptionChecked("Allow Selecting of Large Models"); + } else if (menuItem === "Allow Selecting of Lights") { + Entities.setLightsArePickable(Menu.isOptionChecked("Allow Selecting of Lights")); + } else if (menuItem === "Delete") { + deleteSelectedEntities(); + } else if (menuItem === "Undo") { + undoHistory.undo(); + } else if (menuItem === "Redo") { + undoHistory.redo(); + } else if (menuItem === "Parent Entity to Last") { + parentSelectedEntities(); + } else if (menuItem === "Unparent Entity") { + unparentSelectedEntities(); + } else if (menuItem === "Export Entities") { + if (!selectionManager.hasSelection()) { + Window.notifyEditError("No entities have been selected."); + } else { + Window.saveFileChanged.connect(onFileSaveChanged); + Window.saveAsync("Select Where to Save", "", "*.json"); + } + } else if (menuItem === "Import Entities" || menuItem === "Import Entities from URL") { + if (menuItem === "Import Entities") { + Window.browseChanged.connect(onFileOpenChanged); + Window.browseAsync("Select Model to Import", "", "*.json"); + } else { + Window.promptTextChanged.connect(onPromptTextChanged); + Window.promptAsync("URL of SVO to import", ""); + } + } else if (menuItem === "Select All Entities In Box") { + selectAllEntitiesInCurrentSelectionBox(false); + } else if (menuItem === "Select All Entities Touching Box") { + selectAllEntitiesInCurrentSelectionBox(true); + } else if (menuItem === MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE) { + entityIconOverlayManager.setVisible(isActive && Menu.isOptionChecked(MENU_SHOW_LIGHTS_AND_PARTICLES_IN_EDIT_MODE)); + } else if (menuItem === MENU_SHOW_ZONES_IN_EDIT_MODE) { + Entities.setDrawZoneBoundaries(isActive && Menu.isOptionChecked(MENU_SHOW_ZONES_IN_EDIT_MODE)); + } else if (menuItem === MENU_CREATE_ENTITIES_GRABBABLE) { + Settings.setValue(SETTING_EDIT_PREFIX + menuItem, Menu.isOptionChecked(menuItem)); + } + tooltip.show(false); +} + +var HALF_TREE_SCALE = 16384; + +function getPositionToCreateEntity(extra) { + var CREATE_DISTANCE = 2; + var position; + var delta = extra !== undefined ? extra : 0; + if (Camera.mode === "entity" || Camera.mode === "independent") { + position = Vec3.sum(Camera.position, Vec3.multiply(Quat.getForward(Camera.orientation), CREATE_DISTANCE + delta)); + } else { + position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getForward(MyAvatar.orientation), CREATE_DISTANCE + delta)); + } + + if (position.x > HALF_TREE_SCALE || position.y > HALF_TREE_SCALE || position.z > HALF_TREE_SCALE) { + return null; + } + return position; +} + +function importSVO(importURL) { + if (!Entities.canRez() && !Entities.canRezTmp() && + !Entities.canRezCertified() && !Entities.canRezTmpCertified()) { + Window.notifyEditError(INSUFFICIENT_PERMISSIONS_IMPORT_ERROR_MSG); + return; + } + + Overlays.editOverlay(importingSVOTextOverlay, { + visible: true + }); + Overlays.editOverlay(importingSVOImageOverlay, { + visible: true + }); + + var success = Clipboard.importEntities(importURL); + + if (success) { + var VERY_LARGE = 10000; + var isLargeImport = Clipboard.getClipboardContentsLargestDimension() >= VERY_LARGE; + var position = Vec3.ZERO; + if (!isLargeImport) { + position = getPositionToCreateEntity(Clipboard.getClipboardContentsLargestDimension() / 2); + } + if (position !== null && position !== undefined) { + var pastedEntityIDs = Clipboard.pasteEntities(position); + if (!isLargeImport) { + // The first entity in Clipboard gets the specified position with the rest being relative to it. Therefore, move + // entities after they're imported so that they're all the correct distance in front of and with geometric mean + // centered on the avatar/camera direction. + var deltaPosition = Vec3.ZERO; + var entityPositions = []; + var entityParentIDs = []; + + var propType = Entities.getEntityProperties(pastedEntityIDs[0], ["type"]).type; + var NO_ADJUST_ENTITY_TYPES = ["Zone", "Light", "ParticleEffect"]; + if (NO_ADJUST_ENTITY_TYPES.indexOf(propType) === -1) { + var targetDirection; + if (Camera.mode === "entity" || Camera.mode === "independent") { + targetDirection = Camera.orientation; + } else { + targetDirection = MyAvatar.orientation; + } + targetDirection = Vec3.multiplyQbyV(targetDirection, Vec3.UNIT_Z); + + var targetPosition = getPositionToCreateEntity(); + var deltaParallel = HALF_TREE_SCALE; // Distance to move entities parallel to targetDirection. + var deltaPerpendicular = Vec3.ZERO; // Distance to move entities perpendicular to targetDirection. + for (var i = 0, length = pastedEntityIDs.length; i < length; i++) { + var curLoopEntityProps = Entities.getEntityProperties(pastedEntityIDs[i], ["position", "dimensions", + "registrationPoint", "rotation", "parentID"]); + var adjustedPosition = adjustPositionPerBoundingBox(targetPosition, targetDirection, + curLoopEntityProps.registrationPoint, curLoopEntityProps.dimensions, curLoopEntityProps.rotation); + var delta = Vec3.subtract(adjustedPosition, curLoopEntityProps.position); + var distance = Vec3.dot(delta, targetDirection); + deltaParallel = Math.min(distance, deltaParallel); + deltaPerpendicular = Vec3.sum(Vec3.subtract(delta, Vec3.multiply(distance, targetDirection)), + deltaPerpendicular); + entityPositions[i] = curLoopEntityProps.position; + entityParentIDs[i] = curLoopEntityProps.parentID; + } + deltaPerpendicular = Vec3.multiply(1 / pastedEntityIDs.length, deltaPerpendicular); + deltaPosition = Vec3.sum(Vec3.multiply(deltaParallel, targetDirection), deltaPerpendicular); + } + + if (grid.getSnapToGrid()) { + var firstEntityProps = Entities.getEntityProperties(pastedEntityIDs[0], ["position", "dimensions", + "registrationPoint"]); + var positionPreSnap = Vec3.sum(deltaPosition, firstEntityProps.position); + position = grid.snapToSurface(grid.snapToGrid(positionPreSnap, false, firstEntityProps.dimensions, + firstEntityProps.registrationPoint), firstEntityProps.dimensions, firstEntityProps.registrationPoint); + deltaPosition = Vec3.subtract(position, firstEntityProps.position); + } + + if (!Vec3.equal(deltaPosition, Vec3.ZERO)) { + for (var editEntityIndex = 0, numEntities = pastedEntityIDs.length; editEntityIndex < numEntities; editEntityIndex++) { + if (Uuid.isNull(entityParentIDs[editEntityIndex])) { + Entities.editEntity(pastedEntityIDs[editEntityIndex], { + position: Vec3.sum(deltaPosition, entityPositions[editEntityIndex]) + }); + } + } + } + } + + if (isActive) { + selectionManager.setSelections(pastedEntityIDs, this); + } + } else { + Window.notifyEditError("Can't import entities: entities would be out of bounds."); + } + } else { + Window.notifyEditError("There was an error importing the entity file."); + } + + Overlays.editOverlay(importingSVOTextOverlay, { + visible: false + }); + Overlays.editOverlay(importingSVOImageOverlay, { + visible: false + }); +} +Window.svoImportRequested.connect(importSVO); + +Menu.menuItemEvent.connect(handleMenuEvent); + +var keyPressEvent = function (event) { + if (isActive) { + cameraManager.keyPressEvent(event); + } +}; +var keyReleaseEvent = function (event) { + if (isActive) { + cameraManager.keyReleaseEvent(event); + } +}; +Controller.keyReleaseEvent.connect(keyReleaseEvent); +Controller.keyPressEvent.connect(keyPressEvent); + +function deleteKey(value) { + if (value === 0) { // on release + deleteSelectedEntities(); + } +} +function deselectKey(value) { + if (value === 0) { // on release + selectionManager.clearSelections(this); + } +} +function toggleKey(value) { + if (value === 0) { // on release + selectionDisplay.toggleSpaceMode(); + } +} +function focusKey(value) { + if (value === 0) { // on release + cameraManager.enable(); + if (selectionManager.hasSelection()) { + cameraManager.focus(selectionManager.worldPosition, selectionManager.worldDimensions, + Menu.isOptionChecked(MENU_EASE_ON_FOCUS)); + } + } +} +function gridKey(value) { + if (value === 0) { // on release + if (selectionManager.hasSelection()) { + grid.moveToSelection(); + } + } +} +function recursiveAdd(newParentID, parentData) { + if (parentData.children !== undefined) { + var children = parentData.children; + for (var i = 0; i < children.length; i++) { + var childProperties = children[i].properties; + childProperties.parentID = newParentID; + var newChildID = Entities.addEntity(childProperties); + recursiveAdd(newChildID, children[i]); + } + } +} + +var UndoHistory = function(onUpdate) { + this.history = []; + // The current position is the index of the last executed action in the history array. + // + // -1 0 1 2 3 <- position + // A B C D <- actions in history + // + // If our lastExecutedIndex is 1, the last executed action is B. + // If we undo, we undo B (index 1). If we redo, we redo C (index 2). + this.lastExecutedIndex = -1; + this.enabled = true; + this.onUpdate = onUpdate; +}; + +UndoHistory.prototype.pushCommand = function(undoFn, undoArgs, redoFn, redoArgs) { + if (!this.enabled) { + return; + } + // Delete any history following the last executed action. + this.history.splice(this.lastExecutedIndex + 1); + this.history.push({ + undoFn: undoFn, + undoArgs: undoArgs, + redoFn: redoFn, + redoArgs: redoArgs + }); + this.lastExecutedIndex++; + + if (this.onUpdate) { + this.onUpdate(); + } +}; +UndoHistory.prototype.setEnabled = function(enabled) { + this.enabled = enabled; + if (this.onUpdate) { + this.onUpdate(); + } +}; +UndoHistory.prototype.canUndo = function() { + return this.enabled && this.lastExecutedIndex >= 0; +}; +UndoHistory.prototype.canRedo = function() { + return this.enabled && this.lastExecutedIndex < this.history.length - 1; +}; +UndoHistory.prototype.undo = function() { + if (!this.canUndo()) { + console.warn("Cannot undo action"); + return; + } + + var command = this.history[this.lastExecutedIndex]; + command.undoFn(command.undoArgs); + this.lastExecutedIndex--; + + if (this.onUpdate) { + this.onUpdate(); + } +}; +UndoHistory.prototype.redo = function() { + if (!this.canRedo()) { + console.warn("Cannot redo action"); + return; + } + + var command = this.history[this.lastExecutedIndex + 1]; + command.redoFn(command.redoArgs); + this.lastExecutedIndex++; + + if (this.onUpdate) { + this.onUpdate(); + } +}; + +function updateUndoRedoMenuItems() { + Menu.setMenuEnabled("Edit > Undo", undoHistory.canUndo()); + Menu.setMenuEnabled("Edit > Redo", undoHistory.canRedo()); +} +var undoHistory = new UndoHistory(updateUndoRedoMenuItems); +updateUndoRedoMenuItems(); + +// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently +// possible to create an entity with a specific id, earlier undo commands to the deleted entity +// will fail if there isn't a way to find the new entity id. +var DELETED_ENTITY_MAP = {}; + +function applyEntityProperties(data) { + var editEntities = data.editEntities; + var createEntities = data.createEntities; + var deleteEntities = data.deleteEntities; + var selectedEntityIDs = []; + var selectEdits = createEntities.length === 0 || !data.selectCreated; + var i, entityID, entityProperties; + for (i = 0; i < createEntities.length; i++) { + entityID = createEntities[i].entityID; + entityProperties = createEntities[i].properties; + var newEntityID = Entities.addEntity(entityProperties); + recursiveAdd(newEntityID, createEntities[i]); + DELETED_ENTITY_MAP[entityID] = newEntityID; + if (data.selectCreated) { + selectedEntityIDs.push(newEntityID); + } + } + for (i = 0; i < deleteEntities.length; i++) { + entityID = deleteEntities[i].entityID; + if (DELETED_ENTITY_MAP[entityID] !== undefined) { + entityID = DELETED_ENTITY_MAP[entityID]; + } + Entities.deleteEntity(entityID); + var index = selectedEntityIDs.indexOf(entityID); + if (index >= 0) { + selectedEntityIDs.splice(index, 1); + } + } + for (i = 0; i < editEntities.length; i++) { + entityID = editEntities[i].entityID; + if (DELETED_ENTITY_MAP[entityID] !== undefined) { + entityID = DELETED_ENTITY_MAP[entityID]; + } + entityProperties = editEntities[i].properties; + if (entityProperties !== null) { + Entities.editEntity(entityID, entityProperties); + } + if (selectEdits) { + selectedEntityIDs.push(entityID); + } + } + + // We might be getting an undo while edit.js is disabled. If that is the case, don't set + // our selections, causing the edit widgets to display. + if (isActive) { + selectionManager.setSelections(selectedEntityIDs, this); + selectionManager.saveProperties(); + } +} + +// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the +// redo command, and the saved properties for the undo command. Also, include create and delete entity data. +function pushCommandForSelections(createdEntityData, deletedEntityData, doNotSaveEditProperties) { + doNotSaveEditProperties = false; + var undoData = { + editEntities: [], + createEntities: deletedEntityData || [], + deleteEntities: createdEntityData || [], + selectCreated: true + }; + var redoData = { + editEntities: [], + createEntities: createdEntityData || [], + deleteEntities: deletedEntityData || [], + selectCreated: true + }; + for (var i = 0; i < SelectionManager.selections.length; i++) { + var entityID = SelectionManager.selections[i]; + var initialProperties = SelectionManager.savedProperties[entityID]; + var currentProperties = null; + if (!initialProperties) { + continue; + } + + if (doNotSaveEditProperties) { + initialProperties = null; + } else { + currentProperties = Entities.getEntityProperties(entityID); + } + + undoData.editEntities.push({ + entityID: entityID, + properties: initialProperties + }); + redoData.editEntities.push({ + entityID: entityID, + properties: currentProperties + }); + } + undoHistory.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData); +} + +var ServerScriptStatusMonitor = function(entityID, statusCallback) { + var self = this; + + self.entityID = entityID; + self.active = true; + self.sendRequestTimerID = null; + + var onStatusReceived = function(success, isRunning, status, errorInfo) { + if (self.active) { + statusCallback({ + statusRetrieved: success, + isRunning: isRunning, + status: status, + errorInfo: errorInfo + }); + self.sendRequestTimerID = Script.setTimeout(function() { + if (self.active) { + Entities.getServerScriptStatus(entityID, onStatusReceived); + } + }, 1000); + } + }; + self.stop = function() { + self.active = false; + }; + + Entities.getServerScriptStatus(entityID, onStatusReceived); +}; + +var PropertiesTool = function (opts) { + var that = {}; + + var webView = null; + webView = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + webView.setVisible = function(value) {}; + + var visible = false; + + // This keeps track of the last entity ID that was selected. If multiple entities + // are selected or if no entity is selected this will be `null`. + var currentSelectedEntityID = null; + var statusMonitor = null; + var blockPropertyUpdates = false; + + that.setVisible = function (newVisible) { + visible = newVisible; + webView.setVisible(shouldUseEditTabletApp() && visible); + createToolsWindow.setVisible(!shouldUseEditTabletApp() && visible); + }; + + that.setVisible(false); + + function emitScriptEvent(data) { + var dataString = JSON.stringify(data); + webView.emitScriptEvent(dataString); + createToolsWindow.emitScriptEvent(dataString); + } + + function updateScriptStatus(info) { + info.type = "server_script_status"; + emitScriptEvent(info); + } + + function resetScriptStatus() { + updateScriptStatus({ + statusRetrieved: undefined, + isRunning: undefined, + status: "", + errorInfo: "" + }); + } + + that.setSpaceMode = function(spaceMode) { + emitScriptEvent({ + type: 'setSpaceMode', + spaceMode: spaceMode + }) + }; + + function updateSelections(selectionUpdated, caller) { + if (blockPropertyUpdates) { + return; + } + + var data = { + type: 'update', + spaceMode: selectionDisplay.getSpaceMode(), + isPropertiesToolUpdate: caller === this, + }; + + if (selectionUpdated) { + resetScriptStatus(); + + if (selectionManager.selections.length !== 1) { + if (statusMonitor !== null) { + statusMonitor.stop(); + statusMonitor = null; + } + currentSelectedEntityID = null; + } else if (currentSelectedEntityID !== selectionManager.selections[0]) { + if (statusMonitor !== null) { + statusMonitor.stop(); + } + var entityID = selectionManager.selections[0]; + currentSelectedEntityID = entityID; + statusMonitor = new ServerScriptStatusMonitor(entityID, updateScriptStatus); + } + } + + var selections = []; + for (var i = 0; i < selectionManager.selections.length; i++) { + var entity = {}; + entity.id = selectionManager.selections[i]; + entity.properties = Entities.getEntityProperties(selectionManager.selections[i]); + if (entity.properties.rotation !== undefined) { + entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation); + } + if (entity.properties.localRotation !== undefined) { + entity.properties.localRotation = Quat.safeEulerAngles(entity.properties.localRotation); + } + if (entity.properties.emitOrientation !== undefined) { + entity.properties.emitOrientation = Quat.safeEulerAngles(entity.properties.emitOrientation); + } + if (entity.properties.keyLight !== undefined && entity.properties.keyLight.direction !== undefined) { + entity.properties.keyLight.direction = Vec3.toPolar(entity.properties.keyLight.direction); + entity.properties.keyLight.direction.z = 0.0; + } + selections.push(entity); + } + data.selections = selections; + + emitScriptEvent(data); + } + selectionManager.addEventListener(updateSelections, this); + + + var onWebEventReceived = function(data) { + try { + data = JSON.parse(data); + } catch(e) { + return; + } + var i, properties, dY, diff, newPosition; + if (data.type === "update") { + + if (data.properties || data.propertiesMap) { + var propertiesMap = data.propertiesMap; + if (propertiesMap === undefined) { + propertiesMap = [{ + entityIDs: data.ids, + properties: data.properties, + }]; + } + + var sendListUpdate = false; + propertiesMap.forEach(function(propertiesObject) { + var properties = propertiesObject.properties; + var updateEntityIDs = propertiesObject.entityIDs; + if (properties.dynamic === false) { + // this object is leaving dynamic, so we zero its velocities + properties.localVelocity = Vec3.ZERO; + properties.localAngularVelocity = Vec3.ZERO; + } + if (properties.rotation !== undefined) { + properties.rotation = Quat.fromVec3Degrees(properties.rotation); + } + if (properties.localRotation !== undefined) { + properties.localRotation = Quat.fromVec3Degrees(properties.localRotation); + } + if (properties.emitOrientation !== undefined) { + properties.emitOrientation = Quat.fromVec3Degrees(properties.emitOrientation); + } + if (properties.keyLight !== undefined && properties.keyLight.direction !== undefined) { + var currentKeyLightDirection = Vec3.toPolar(Entities.getEntityProperties(selectionManager.selections[0], ['keyLight.direction']).keyLight.direction); + if (properties.keyLight.direction.x === undefined) { + properties.keyLight.direction.x = currentKeyLightDirection.x; + } + if (properties.keyLight.direction.y === undefined) { + properties.keyLight.direction.y = currentKeyLightDirection.y; + } + properties.keyLight.direction = Vec3.fromPolar(properties.keyLight.direction.x, properties.keyLight.direction.y); + } + + updateEntityIDs.forEach(function (entityID) { + Entities.editEntity(entityID, properties); + }); + + if (properties.name !== undefined || properties.modelURL !== undefined || properties.materialURL !== undefined || + properties.visible !== undefined || properties.locked !== undefined) { + + sendListUpdate = true; + } + + }); + if (sendListUpdate) { + entityListTool.sendUpdate(); + } + } + + + if (data.onlyUpdateEntities) { + blockPropertyUpdates = true; + } else { + pushCommandForSelections(); + SelectionManager.saveProperties(); + } + selectionManager._update(false, this); + blockPropertyUpdates = false; + } else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') { + data.ids.forEach(function(entityID) { + Entities.editEntity(entityID, data.properties); + }); + } else if (data.type === "showMarketplace") { + showMarketplace(); + } else if (data.type === "action") { + if (data.action === "moveSelectionToGrid") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + dY = grid.getOrigin().y - (selectionManager.worldPosition.y - selectionManager.worldDimensions.y / 2); + diff = { + x: 0, + y: dY, + z: 0 + }; + for (i = 0; i < selectionManager.selections.length; i++) { + properties = selectionManager.savedProperties[selectionManager.selections[i]]; + newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(selectionManager.selections[i], { + position: newPosition + }); + } + pushCommandForSelections(); + selectionManager._update(false, this); + } + } else if (data.action === "moveAllToGrid") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (i = 0; i < selectionManager.selections.length; i++) { + properties = selectionManager.savedProperties[selectionManager.selections[i]]; + var bottomY = properties.boundingBox.center.y - properties.boundingBox.dimensions.y / 2; + dY = grid.getOrigin().y - bottomY; + diff = { + x: 0, + y: dY, + z: 0 + }; + newPosition = Vec3.sum(properties.position, diff); + Entities.editEntity(selectionManager.selections[i], { + position: newPosition + }); + } + pushCommandForSelections(); + selectionManager._update(false, this); + } + } else if (data.action === "resetToNaturalDimensions") { + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (i = 0; i < selectionManager.selections.length; i++) { + properties = selectionManager.savedProperties[selectionManager.selections[i]]; + var naturalDimensions = properties.naturalDimensions; + + // If any of the natural dimensions are not 0, resize + if (properties.type === "Model" && naturalDimensions.x === 0 && naturalDimensions.y === 0 && + naturalDimensions.z === 0) { + Window.notifyEditError("Cannot reset entity to its natural dimensions: Model URL" + + " is invalid or the model has not yet been loaded."); + } else { + Entities.editEntity(selectionManager.selections[i], { + dimensions: properties.naturalDimensions + }); + } + } + pushCommandForSelections(); + selectionManager._update(false, this); + } + } else if (data.action === "previewCamera") { + if (selectionManager.hasSelection()) { + Camera.mode = "entity"; + Camera.cameraEntity = selectionManager.selections[0]; + } + } else if (data.action === "rescaleDimensions") { + var multiplier = data.percentage / 100.0; + if (selectionManager.hasSelection()) { + selectionManager.saveProperties(); + for (i = 0; i < selectionManager.selections.length; i++) { + properties = selectionManager.savedProperties[selectionManager.selections[i]]; + Entities.editEntity(selectionManager.selections[i], { + dimensions: Vec3.multiply(multiplier, properties.dimensions) + }); + } + pushCommandForSelections(); + selectionManager._update(false, this); + } + } else if (data.action === "reloadClientScripts") { + if (selectionManager.hasSelection()) { + var timestamp = Date.now(); + for (i = 0; i < selectionManager.selections.length; i++) { + Entities.editEntity(selectionManager.selections[i], { + scriptTimestamp: timestamp + }); + } + } + } else if (data.action === "reloadServerScripts") { + if (selectionManager.hasSelection()) { + for (i = 0; i < selectionManager.selections.length; i++) { + Entities.reloadServerScripts(selectionManager.selections[i]); + } + } + } + } else if (data.type === "propertiesPageReady") { + updateSelections(true); + } else if (data.type === "tooltipsRequest") { + emitScriptEvent({ + type: 'tooltipsReply', + tooltips: Script.require('./assets/data/createAppTooltips.json'), + hmdActive: HMD.active, + }); + } else if (data.type === "propertyRangeRequest") { + var propertyRanges = {}; + data.properties.forEach(function (property) { + propertyRanges[property] = Entities.getPropertyInfo(property); + }); + emitScriptEvent({ + type: 'propertyRangeReply', + propertyRanges: propertyRanges, + }); + } else if (data.type === "materialTargetRequest") { + var parentModelData; + var properties = Entities.getEntityProperties(data.entityID, ["type", "parentID"]); + if (properties.type === "Material" && properties.parentID !== Uuid.NULL) { + var parentType = Entities.getEntityProperties(properties.parentID, ["type"]).type; + if (parentType === "Model" || Entities.getNestableType(properties.parentID) === "avatar") { + parentModelData = Graphics.getModel(properties.parentID); + } else if (parentType === "Shape" || parentType === "Box" || parentType === "Sphere") { + parentModelData = {}; + parentModelData.numMeshes = 1; + parentModelData.materialNames = []; + } + } + emitScriptEvent({ + type: 'materialTargetReply', + entityID: data.entityID, + materialTargetData: parentModelData, + }); + } else if (data.type === "zoneListRequest") { + emitScriptEvent({ + type: 'zoneListRequest', + zones: getExistingZoneList() + }); + } + }; + + HMD.displayModeChanged.connect(function() { + emitScriptEvent({ + type: 'hmdActiveChanged', + hmdActive: HMD.active, + }); + }); + + createToolsWindow.webEventReceived.addListener(this, onWebEventReceived); + + webView.webEventReceived.connect(this, onWebEventReceived); + + return that; +}; + + +var PopupMenu = function () { + var self = this; + + var MENU_ITEM_HEIGHT = 21; + var MENU_ITEM_SPACING = 1; + var TEXT_MARGIN = 7; + + var overlays = []; + var overlayInfo = {}; + + var visible = false; + + var upColor = { + red: 0, + green: 0, + blue: 0 + }; + var downColor = { + red: 192, + green: 192, + blue: 192 + }; + var overColor = { + red: 128, + green: 128, + blue: 128 + }; + + self.onSelectMenuItem = function () {}; + + self.addMenuItem = function (name) { + var id = Overlays.addOverlay("text", { + text: name, + backgroundAlpha: 1.0, + backgroundColor: upColor, + topMargin: TEXT_MARGIN, + leftMargin: TEXT_MARGIN, + width: 210, + height: MENU_ITEM_HEIGHT, + font: { + size: 12 + }, + visible: false + }); + overlays.push(id); + overlayInfo[id] = { + name: name + }; + return id; + }; + + self.updateMenuItemText = function (id, newText) { + Overlays.editOverlay(id, { + text: newText + }); + }; + + self.setPosition = function (x, y) { + for (var key in overlayInfo) { + Overlays.editOverlay(key, { + x: x, + y: y + }); + y += MENU_ITEM_HEIGHT + MENU_ITEM_SPACING; + } + }; + + self.onSelected = function () {}; + + var pressingOverlay = null; + var hoveringOverlay = null; + + self.mousePressEvent = function (event) { + if (event.isLeftButton) { + var overlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (overlay in overlayInfo) { + pressingOverlay = overlay; + Overlays.editOverlay(pressingOverlay, { + backgroundColor: downColor + }); + } else { + self.hide(); + } + return false; + } + }; + self.mouseMoveEvent = function (event) { + if (visible) { + var overlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (!pressingOverlay) { + if (hoveringOverlay !== null && overlay !== hoveringOverlay) { + Overlays.editOverlay(hoveringOverlay, { + backgroundColor: upColor + }); + hoveringOverlay = null; + } + if (overlay !== hoveringOverlay && overlay in overlayInfo) { + Overlays.editOverlay(overlay, { + backgroundColor: overColor + }); + hoveringOverlay = overlay; + } + } + } + return false; + }; + self.mouseReleaseEvent = function (event) { + var overlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (pressingOverlay !== null && pressingOverlay !== undefined) { + if (overlay === pressingOverlay) { + self.onSelectMenuItem(overlayInfo[overlay].name); + } + Overlays.editOverlay(pressingOverlay, { + backgroundColor: upColor + }); + pressingOverlay = null; + self.hide(); + } + }; + + self.setVisible = function (newVisible) { + if (newVisible !== visible) { + visible = newVisible; + for (var key in overlayInfo) { + Overlays.editOverlay(key, { + visible: newVisible + }); + } + } + }; + self.show = function () { + self.setVisible(true); + }; + self.hide = function () { + self.setVisible(false); + }; + + function cleanup() { + ContextOverlay.enabled = true; + for (var i = 0; i < overlays.length; i++) { + Overlays.deleteOverlay(overlays[i]); + } + Controller.mousePressEvent.disconnect(self.mousePressEvent); + Controller.mouseMoveEvent.disconnect(self.mouseMoveEvent); + Controller.mouseReleaseEvent.disconnect(self.mouseReleaseEvent); + + Entities.canRezChanged.disconnect(checkEditPermissionsAndUpdate); + Entities.canRezTmpChanged.disconnect(checkEditPermissionsAndUpdate); + Entities.canRezCertifiedChanged.disconnect(checkEditPermissionsAndUpdate); + Entities.canRezTmpCertifiedChanged.disconnect(checkEditPermissionsAndUpdate); + } + + Controller.mousePressEvent.connect(self.mousePressEvent); + Controller.mouseMoveEvent.connect(self.mouseMoveEvent); + Controller.mouseReleaseEvent.connect(self.mouseReleaseEvent); + Script.scriptEnding.connect(cleanup); + + return this; +}; + +function whenPressed(fn) { + return function(value) { + if (value > 0) { + fn(); + } + }; +} + +function whenReleased(fn) { + return function(value) { + if (value === 0) { + fn(); + } + }; +} + +var isOnMacPlatform = Controller.getValue(Controller.Hardware.Application.PlatformMac); + +var mapping = Controller.newMapping(CONTROLLER_MAPPING_NAME); +if (isOnMacPlatform) { + mapping.from([Controller.Hardware.Keyboard.Backspace]).to(deleteKey); +} else { + mapping.from([Controller.Hardware.Keyboard.Delete]).to(deleteKey); +} +mapping.from([Controller.Hardware.Keyboard.T]).to(toggleKey); +mapping.from([Controller.Hardware.Keyboard.F]).to(focusKey); +mapping.from([Controller.Hardware.Keyboard.G]).to(gridKey); +mapping.from([Controller.Hardware.Keyboard.X]) + .when([Controller.Hardware.Keyboard.Control]) + .to(whenReleased(function() { selectionManager.cutSelectedEntities() })); +mapping.from([Controller.Hardware.Keyboard.C]) + .when([Controller.Hardware.Keyboard.Control]) + .to(whenReleased(function() { selectionManager.copySelectedEntities() })); +mapping.from([Controller.Hardware.Keyboard.V]) + .when([Controller.Hardware.Keyboard.Control]) + .to(whenReleased(function() { selectionManager.pasteEntities() })); +mapping.from([Controller.Hardware.Keyboard.D]) + .when([Controller.Hardware.Keyboard.Control]) + .to(whenReleased(function() { selectionManager.duplicateSelection() })); + +// Bind undo to ctrl-shift-z to maintain backwards-compatibility +mapping.from([Controller.Hardware.Keyboard.Z]) + .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift]) + .to(whenPressed(function() { undoHistory.redo() })); + + +mapping.from([Controller.Hardware.Keyboard.P]) + .when([Controller.Hardware.Keyboard.Control, Controller.Hardware.Keyboard.Shift]) + .to(whenReleased(function() { unparentSelectedEntities(); })); + +mapping.from([Controller.Hardware.Keyboard.P]) + .when([Controller.Hardware.Keyboard.Control, !Controller.Hardware.Keyboard.Shift]) + .to(whenReleased(function() { parentSelectedEntities(); })); + +keyUpEventFromUIWindow = function(keyUpEvent) { + var WANT_DEBUG_MISSING_SHORTCUTS = false; + + var pressedValue = 0.0; + + if ((!isOnMacPlatform && keyUpEvent.keyCodeString === "Delete") + || (isOnMacPlatform && keyUpEvent.keyCodeString === "Backspace")) { + + deleteKey(pressedValue); + } else if (keyUpEvent.keyCodeString === "T") { + toggleKey(pressedValue); + } else if (keyUpEvent.keyCodeString === "F") { + focusKey(pressedValue); + } else if (keyUpEvent.keyCodeString === "G") { + gridKey(pressedValue); + } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "X") { + selectionManager.cutSelectedEntities(); + } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "C") { + selectionManager.copySelectedEntities(); + } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "V") { + selectionManager.pasteEntities(); + } else if (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "D") { + selectionManager.duplicateSelection(); + } else if (!isOnMacPlatform && keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") { + undoHistory.undo(); // undo is only handled via handleMenuItem on Mac + } else if (keyUpEvent.controlKey && !keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { + parentSelectedEntities(); + } else if (keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "P") { + unparentSelectedEntities(); + } else if (!isOnMacPlatform && + ((keyUpEvent.controlKey && keyUpEvent.shiftKey && keyUpEvent.keyCodeString === "Z") || + (keyUpEvent.controlKey && keyUpEvent.keyCodeString === "Y"))) { + undoHistory.redo(); // redo is only handled via handleMenuItem on Mac + } else if (WANT_DEBUG_MISSING_SHORTCUTS) { + console.warn("unhandled key event: " + JSON.stringify(keyUpEvent)) + } +}; + +var propertyMenu = new PopupMenu(); + +propertyMenu.onSelectMenuItem = function (name) { + + if (propertyMenu.marketplaceID) { + showMarketplace(propertyMenu.marketplaceID); + } +}; + +var showMenuItem = propertyMenu.addMenuItem("Show in Marketplace"); + +var propertiesTool = new PropertiesTool(); + +selectionDisplay.onSpaceModeChange = function(spaceMode) { + entityListTool.setSpaceMode(spaceMode); + propertiesTool.setSpaceMode(spaceMode); +}; + +function getExistingZoneList() { + var center = {"x": 0, "y": 0, "z": 0}; + var existingZoneIDs = Entities.findEntitiesByType("Zone", center, 17000); + var listExistingZones = []; + var thisZone = {}; + var properties; + for (var k = 0; k < existingZoneIDs.length; k++) { + properties = Entities.getEntityProperties(existingZoneIDs[k], ["name"]); + thisZone = { + "id": existingZoneIDs[k], + "name": properties.name + }; + listExistingZones.push(thisZone); + } + return listExistingZones; +} + +}()); // END LOCAL_SCOPE From 4a3405484c7da69fb213e4ad977ff4ce95cb4791 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Fri, 3 Apr 2020 23:43:36 -0400 Subject: [PATCH 039/105] Add new property "renderWithZones" Add the new property "renderWithZones" to the Create App. For this, a new type of renderer type has been added: "Multiple Zones Selector". (Required for the PR#78) --- .../html/js/entityProperties.js | 305 ++++++++++++++++-- 1 file changed, 285 insertions(+), 20 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 9e476d80aa..8d5594be3b 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1,15 +1,8 @@ -//VERSION 2.0 -// Modified by Alezia Kurdis on on 02/27/2020 -// for "Project Athena" -// -// Addition of a tab mechanism instead of collapsible sections to reduce the scrolling. -// -//VERSION 1.0 // entityProperties.js // // Created by Ryan Huffman on 13 Nov 2014 -// Modified by David Back on 19 Oct 2018 // Copyright 2014 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -122,6 +115,11 @@ const GROUPS = [ lines: "Wireframe", }, propertyID: "primitiveMode", + }, + { + label: "Render With Zones", + type: "multipleZonesSelection", + propertyID: "renderWithZones", } ] }, @@ -142,7 +140,17 @@ const GROUPS = [ label: "Color", type: "color", propertyID: "color", - } + }, + { + label: "Alpha", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "shapeAlpha", + propertyName: "alpha", + }, ] }, { @@ -191,6 +199,36 @@ const GROUPS = [ unit: "m", propertyID: "lineHeight", }, + { + label: "Font", + type: "string", + propertyID: "font", + }, + { + label: "Effect", + type: "dropdown", + options: { + none: "None", + outline: "Outline", + "outline fill": "Outline with fill", + shadow: "Shadow" + }, + propertyID: "textEffect", + }, + { + label: "Effect Color", + type: "color", + propertyID: "textEffectColor", + }, + { + label: "Effect Thickness", + type: "number-draggable", + min: 0.0, + max: 0.5, + step: 0.01, + decimals: 2, + propertyID: "textEffectThickness", + }, { label: "Billboard Mode", type: "dropdown", @@ -288,7 +326,7 @@ const GROUPS = [ { label: "Light Intensity", type: "number-draggable", - min: 0, + min: -40, max: 40, step: 0.01, decimals: 2, @@ -380,7 +418,7 @@ const GROUPS = [ { label: "Ambient Intensity", type: "number-draggable", - min: 0, + min: -200, max: 200, step: 0.1, decimals: 2, @@ -587,7 +625,7 @@ const GROUPS = [ propertyID: "animation.loop", }, { - label: "Allow Transition", + label: "Allow Translation", type: "bool", propertyID: "animation.allowTranslation", }, @@ -651,6 +689,16 @@ const GROUPS = [ propertyID: "imageColor", propertyName: "color", // actual entity property name }, + { + label: "Alpha", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "imageAlpha", + propertyName: "alpha", + }, { label: "Emissive", type: "bool", @@ -715,6 +763,27 @@ const GROUPS = [ decimals: 0, propertyID: "maxFPS", }, + { + label: "Billboard Mode", + type: "dropdown", + options: { none: "None", yaw: "Yaw", full: "Full"}, + propertyID: "webBillboardMode", + propertyName: "billboardMode", // actual entity property name + }, + { + label: "Input Mode", + type: "dropdown", + options: { + touch: "Touch events", + mouse: "Mouse events" + }, + propertyID: "inputMode", + }, + { + label: "Focus Highlight", + type: "bool", + propertyID: "showKeyboardFocusHighlight", + }, { label: "Script URL", type: "string", @@ -736,7 +805,7 @@ const GROUPS = [ { label: "Intensity", type: "number-draggable", - min: 0, + min: -1000, max: 10000, step: 0.1, decimals: 2, @@ -1601,11 +1670,10 @@ const GROUPS_PER_TYPE = { Image: [ 'base', 'image', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Web: [ 'base', 'web', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Light: [ 'base', 'light', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], - Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts' ], + Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts', 'physics' ], ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], - PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], PolyVox: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Grid: [ 'base', 'grid', 'spatial', 'behavior', 'scripts', 'physics' ], Multiple: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], @@ -1675,7 +1743,7 @@ let selectedEntityIDs = new Set(); let currentSelections = []; let createAppTooltip = new CreateAppTooltip(); let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL; - +let zonesList = []; function createElementFromHTML(htmlString) { let elTemplate = document.createElement('template'); @@ -1701,6 +1769,8 @@ function getPropertyInputElement(propertyID) { case 'textarea': case 'texture': return property.elInput; + case 'multipleZonesSelection': + return property.elInput; case 'number-draggable': return property.elNumber.elInput; case 'rect': @@ -1741,6 +1811,7 @@ function disableChildren(el, selector) { function enableProperties() { enableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); enableChildren(document, ".colpick"); + enableAllMultipleZoneSelector(); } function disableProperties() { @@ -1749,6 +1820,7 @@ function disableProperties() { for (let pickKey in colorPickers) { colorPickers[pickKey].colpickHide(); } + disableAllMultipleZoneSelector(); } function showPropertyElement(propertyID, show) { @@ -1823,6 +1895,12 @@ function resetProperties() { setTextareaScrolling(property.elInput); break; } + case 'multipleZonesSelection': { + property.elInput.classList.remove('multi-diff'); + property.elInput.value = "[]"; + setZonesSelectionData(property.elInput, false); + break; + } case 'icon': { property.elSpan.style.display = "none"; break; @@ -1860,7 +1938,7 @@ function resetServerScriptStatus() { function showGroupsForType(type) { if (type === "Box" || type === "Sphere") { showGroupsForTypes(["Shape"]); - showOnTheSamePage("Shape"); + showOnTheSamePage(["Shape"]); return; } if (type === "None") { @@ -1868,7 +1946,7 @@ function showGroupsForType(type) { return; } showGroupsForTypes([type]); - showOnTheSamePage(type); + showOnTheSamePage([type]); } function getGroupsForTypes(types) { @@ -2972,6 +3050,10 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI property.elInput = createTextareaProperty(property, elProperty); break; } + case 'multipleZonesSelection': { + property.elInput = createZonesSelection(property, elProperty); + break; + } case 'icon': { property.elSpan = createIconProperty(property, elProperty); break; @@ -3464,6 +3546,175 @@ function setTextareaScrolling(element) { element.setAttribute("scrolling", isScrolling ? "true" : "false"); } +/** + * ZONE SELECTOR FUNCTIONS + */ + +function enableAllMultipleZoneSelector() { + let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); + let i, propId; + for ( i = 0; i < allMultiZoneSelectors.length; i++ ) { + propId = allMultiZoneSelectors[i].id; + displaySelectedZones(propId, true); + } +} + +function disableAllMultipleZoneSelector() { + let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); + let i, propId; + for ( i = 0; i < allMultiZoneSelectors.length; i++ ) { + propId = allMultiZoneSelectors[i].id; + displaySelectedZones(propId, false); + } +} + +function requestZoneList() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "zoneListRequest" + })); +} + +function addZoneToZonesSelection(propertyId) { + let hiddenField = document.getElementById(propertyId); + if(JSON.stringify(hiddenField.value) === '"undefined"') { + hiddenField.value = "[]"; + } + let selectedZones = JSON.parse(hiddenField.value); + let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; + if (!selectedZones.includes(zoneToAdd)) { + selectedZones.push(zoneToAdd); + } + hiddenField.value = JSON.stringify(selectedZones); + displaySelectedZones(propertyId, true); + let propertyName = propertyId.replace("property-", ""); + updateProperty(propertyName, selectedZones, false); +} + +function removeZoneFromZonesSelection(propertyId, zoneId) { + let hiddenField = document.getElementById(propertyId); + if(JSON.stringify(hiddenField.value) === '"undefined"') { + hiddenField.value = "[]"; + } + let selectedZones = JSON.parse(hiddenField.value); + let index = selectedZones.indexOf(zoneId); + if (index > -1) { + selectedZones.splice(index, 1); + } + hiddenField.value = JSON.stringify(selectedZones); + displaySelectedZones(propertyId, true); + let propertyName = propertyId.replace("property-", ""); + updateProperty(propertyName, selectedZones, false); +} + +function displaySelectedZones(propertyId, isEditable) { + let i,j, name, listedZoneInner, hiddenData, isMultiple; + hiddenData = document.getElementById(propertyId).value; + if (JSON.stringify(hiddenData) === '"undefined"') { + isMultiple = true; + hiddenData = "[]"; + } else { + isMultiple = false; + } + let selectedZones = JSON.parse(hiddenData); + listedZoneInner = "
    -
    +
    +
    "; + if (selectedZones.length === 0) { + if (!isMultiple) { + listedZoneInner += ""; + } else { + listedZoneInner += ""; + } + } else { + for ( i = 0; i < selectedZones.length; i++ ) { + name = "{ERROR: NOT FOUND}"; + for ( j = 0; j < zonesList.length; j++ ) { + if (selectedZones[i] === zonesList[j].id) { + if (zonesList[j].name !== "") { + name = zonesList[j].name; + } else { + name = zonesList[j].id; + } + break; + } + } + if (isEditable) { + listedZoneInner += ""; + } else { + listedZoneInner += ""; + } + } + } + listedZoneInner += "
      
    [ WARNING: Any changes will apply to all ] 
    " + name + ""; + listedZoneInner += "
    " + name + " 
    "; + document.getElementById("selected-zones-" + propertyId).innerHTML = listedZoneInner; + if (isEditable) { + document.getElementById("multiZoneSelTools-" + propertyId).style.display = "block"; + } else { + document.getElementById("multiZoneSelTools-" + propertyId).style.display = "none"; + } +} + +function createZonesSelection(property, elProperty) { + let elementID = property.elementID; + requestZoneList(); + elProperty.className = "multipleZonesSelection"; + let elInput = document.createElement('input'); + elInput.setAttribute("id", elementID); + elInput.setAttribute("type", "hidden"); + elInput.className = "hiddenMultiZonesSelection"; + + let elZonesSelector = document.createElement('div'); + elZonesSelector.setAttribute("id", "zones-selector-" + elementID); + + let elMultiDiff = document.createElement('span'); + elMultiDiff.className = "multi-diff"; + + elProperty.appendChild(elInput); + elProperty.appendChild(elZonesSelector); + elProperty.appendChild(elMultiDiff); + + return elInput; +} + +function setZonesSelectionData(element, isEditable) { + let zoneSelectorContainer = document.getElementById("zones-selector-" + element.id); + let zoneSelector = "
     "; + zoneSelector += "
    "; + zoneSelector += "
    "; + zoneSelectorContainer.innerHTML = zoneSelector; + displaySelectedZones(element.id, isEditable); +} + +function updateAllZoneSelect() { + let allZoneSelects = document.querySelectorAll(".zoneSelect"); + let i, j, name, propId; + for ( i = 0; i < allZoneSelects.length; i++ ) { + allZoneSelects[i].options.length = 0; + for ( j = 0; j < zonesList.length; j++ ) { + if (zonesList[j].name === "") { + name = zonesList[j].id; + } else { + name = zonesList[j].name; + } + allZoneSelects[i].options[j] = new Option(name, zonesList[j].id, false , false); + } + propId = allZoneSelects[i].id.replace("zones-select-", ""); + if (document.getElementById("multiZoneSelTools-" + propId).style.display === "block") { + displaySelectedZones(propId, true); + } else { + displaySelectedZones(propId, false); + } + } +} /** * MATERIAL TARGET FUNCTIONS @@ -3637,7 +3888,9 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { selectedEntityIDs = new Set(selections.map(selection => selection.id)); const multipleSelections = currentSelections.length > 1; const hasSelectedEntityChanged = !areSetsEqual(selectedEntityIDs, previouslySelectedEntityIDs); - + + requestZoneList(); + if (selections.length === 0) { deleteJSONEditor(); deleteJSONMaterialEditor(); @@ -3692,7 +3945,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { } else { enableProperties(); disableSaveUserDataButton(); - disableSaveMaterialDataButton() + disableSaveMaterialDataButton(); } const certificateIDMultiValue = getMultiplePropertyValue('certificateID'); @@ -3848,6 +4101,15 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { setTextareaScrolling(property.elInput); break; } + case 'multipleZonesSelection': { + property.elInput.value = JSON.stringify(propertyValue); + if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { + setZonesSelectionData(property.elInput, false); + } else { + setZonesSelectionData(property.elInput, true); + } + break; + } case 'icon': { property.elSpan.innerHTML = propertyData.icons[propertyValue]; property.elSpan.style.display = "inline-block"; @@ -4177,6 +4439,9 @@ function loaded() { if (data.entityID === getFirstSelectedID()) { setMaterialTargetData(data.materialTargetData); } + } else if (data.type === 'zoneListRequest') { + zonesList = data.zones; + updateAllZoneSelect(); } }); From cdef49d633a271cccacd18b33cd1900bcf0edd4a Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sat, 4 Apr 2020 22:18:59 -0400 Subject: [PATCH 040/105] Fix tooltip text for particles alpha properties Fix the tooltip's text for particle alpha properties. --- scripts/system/create/assets/data/createAppTooltips.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index d473dc5a8e..860558bbfe 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -319,17 +319,17 @@ "tooltip": "The spread in color that each particle is given, resulting in a variety of colors." }, "particleAlphaTriple": { - "tooltip": "Set the opacity of the each particle between 0.0 fully transparent and 1.0 completely opaque.", + "tooltip": "Set the opacity of each particle between 0.0 fully transparent and 1.0 completely opaque.", "jsPropertyName": "alpha" }, "alpha": { - "tooltip": "Set the opacity of the each particle between 0.0 fully transparent and 1.0 completely opaque." + "tooltip": "Set the opacity of each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaStart": { - "tooltip": "Set the initial opacity level of the each particle between 0.0 fully transparent and 1.0 completely opaque." + "tooltip": "Set the initial opacity level of each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaFinish": { - "tooltip": "Set the final opacity level of the each particle between 0.0 fully transparent and 1.0 completely opaque." + "tooltip": "Set the final opacity level of each particle between 0.0 fully transparent and 1.0 completely opaque." }, "alphaSpread": { "tooltip": "The spread in opacity that each particle is given, resulting in a variety of opacity levels." From 6d33713e35b4f93f14ea93947dcc8d775389275f Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 5 Apr 2020 02:14:10 -0400 Subject: [PATCH 041/105] Better tooltip for renderWithZones property Better tooltip for renderWithZones property --- scripts/system/create/assets/data/createAppTooltips.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/create/assets/data/createAppTooltips.json b/scripts/system/create/assets/data/createAppTooltips.json index 860558bbfe..94d8fe1ab6 100644 --- a/scripts/system/create/assets/data/createAppTooltips.json +++ b/scripts/system/create/assets/data/createAppTooltips.json @@ -596,7 +596,7 @@ "tooltip": "The mode in which to draw an entity, either \"Solid\" or \"Wireframe\"." }, "renderWithZones": { - "tooltip": "This entity will be rendered only from the specified zones. If not specified, the entity will be always rendered." + "tooltip": "If set, this entity will only render when your avatar is inside of a zone in this list." }, "groupCulled": { "tooltip": "If false, individual pieces of the entity may be culled by the render engine. If true, either the entire entity will be culled, or it won't at all." From 9c5f8fc9461219406486b19c1bf570733d07956c Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 5 Apr 2020 02:18:51 -0400 Subject: [PATCH 042/105] Typo missing dot. --- .../system/create/entityProperties/html/js/entityProperties.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 8d5594be3b..78ebe5b5cb 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -3621,7 +3621,7 @@ function displaySelectedZones(propertyId, isEditable) { if (!isMultiple) { listedZoneInner += "
      
    [ WARNING: Any changes will apply to all ] 
    [ WARNING: Any changes will apply to all. ] 
    Play a clapping animation on your avatar for three seconds. Override left hand animation for three seconds. Play a clapping animation on your avatar for three seconds. Remove a hat attachment if your avatar is wearing it.Attach a cowboy hat to your avatar's head.
      
    [ WARNING: Any changes will apply to all. ] 
    [ WARNING: Any changes will apply to all ] 
    " + name + ""; - listedZoneInner += "
    " + name + "
    " + name + " 
    " + name + " 
    "; + if (selectedZones.length === 0) { + if (!isMultiple) { + listedZoneInner += ""; + } else { + listedZoneInner += ""; + } + } else { + for ( i = 0; i < selectedZones.length; i++ ) { + name = "{ERROR: NOT FOUND}"; + for ( j = 0; j < zonesList.length; j++ ) { + if (selectedZones[i] === zonesList[j].id) { + if (zonesList[j].name !== "") { + name = zonesList[j].name; + } else { + name = zonesList[j].id; + } + break; + } + } + if (isEditable) { + listedZoneInner += ""; + } else { + listedZoneInner += ""; + } + } + } + listedZoneInner += "
      
    [ WARNING: Any changes will apply to all ] 
    " + name + "
    " + name + " 
    "; + document.getElementById("selected-zones-" + propertyId).innerHTML = listedZoneInner; + if (isEditable) { + document.getElementById("multiZoneSelTools-" + propertyId).style.display = "block"; + } else { + document.getElementById("multiZoneSelTools-" + propertyId).style.display = "none"; + } +} + +function createZonesSelection(property, elProperty) { + let elementID = property.elementID; + requestZoneList(); + elProperty.className = "multipleZonesSelection"; + let elInput = document.createElement('input'); + elInput.setAttribute("id", elementID); + elInput.setAttribute("type", "hidden"); // must be hidden ################################################################################# HEIL! ICITTE! + elInput.className = "hiddenMultiZonesSelection"; + + let elZonesSelector = document.createElement('div'); + elZonesSelector.setAttribute("id", "zones-selector-" + elementID); + + let elMultiDiff = document.createElement('span'); + elMultiDiff.className = "multi-diff"; + + elProperty.appendChild(elInput); + elProperty.appendChild(elZonesSelector); + elProperty.appendChild(elMultiDiff); + + return elInput; +} + +function setZonesSelectionData(element, isEditable) { + let zoneSelectorContainer = document.getElementById("zones-selector-" + element.id); + let zoneSelector = "
     
    "; + zoneSelector += "
    "; + zoneSelectorContainer.innerHTML = zoneSelector; + displaySelectedZones(element.id, isEditable); +} + +function updateAllZoneSelect() { + let allZoneSelects = document.querySelectorAll(".zoneSelect"); + let i, j, name, propId; + for ( i = 0; i < allZoneSelects.length; i++ ) { + allZoneSelects[i].options.length = 0; + for ( j = 0; j < zonesList.length; j++ ) { + if (zonesList[j].name === "") { + name = zonesList[j].id; + } else { + name = zonesList[j].name; + } + allZoneSelects[i].options[j] = new Option(name, zonesList[j].id, false , false); + } + propId = allZoneSelects[i].id.replace("zones-select-", ""); + if (document.getElementById("multiZoneSelTools-" + propId).style.display === "block") { + displaySelectedZones(propId, true); + } else { + displaySelectedZones(propId, false); + } + } +} /** * MATERIAL TARGET FUNCTIONS @@ -3701,7 +3894,9 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { selectedEntityIDs = new Set(selections.map(selection => selection.id)); const multipleSelections = currentSelections.length > 1; const hasSelectedEntityChanged = !areSetsEqual(selectedEntityIDs, previouslySelectedEntityIDs); - + + requestZoneList(); + if (selections.length === 0) { deleteJSONEditor(); deleteJSONMaterialEditor(); @@ -3756,7 +3951,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { } else { enableProperties(); disableSaveUserDataButton(); - disableSaveMaterialDataButton() + disableSaveMaterialDataButton(); } const certificateIDMultiValue = getMultiplePropertyValue('certificateID'); @@ -3912,6 +4107,19 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { setTextareaScrolling(property.elInput); break; } + case 'multipleZonesSelection': { + if (propertyValue == ""){ //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = "[]"; //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + } else { //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = propertyValue; //JSON.stringify(propertyValue); //##### TO CHECK depending what type the value is.. expecting an array so it willbe manage as a string. + } //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { + setZonesSelectionData(property.elInput, false); + } else { + setZonesSelectionData(property.elInput, true); + } + break; + } case 'icon': { property.elSpan.innerHTML = propertyData.icons[propertyValue]; property.elSpan.style.display = "inline-block"; @@ -4241,6 +4449,9 @@ function loaded() { if (data.entityID === getFirstSelectedID()) { setMaterialTargetData(data.materialTargetData); } + } else if (data.type === 'zoneListRequest') { + zonesList = data.zones; + updateAllZoneSelect(); } }); From 75747a6a2fae3d47cf7747301f2a8400bf1166d5 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 27 Apr 2020 22:20:19 -0400 Subject: [PATCH 078/105] to avoid regression --- .../html/js/entityProperties.js | 319 ++++++++++++++++-- 1 file changed, 297 insertions(+), 22 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 9e476d80aa..59755df122 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1,15 +1,8 @@ -//VERSION 2.0 -// Modified by Alezia Kurdis on on 02/27/2020 -// for "Project Athena" -// -// Addition of a tab mechanism instead of collapsible sections to reduce the scrolling. -// -//VERSION 1.0 // entityProperties.js // // Created by Ryan Huffman on 13 Nov 2014 -// Modified by David Back on 19 Oct 2018 // Copyright 2014 High Fidelity, Inc. +// Copyright 2020 Vircadia contributors. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -74,11 +67,16 @@ const GROUPS = [ replaceID: "placeholder-property-id", multiDisplayMode: PROPERTY_MULTI_DISPLAY_MODE.COMMA_SEPARATED_VALUES, }, - { + /*{ label: "Description", type: "string", propertyID: "description", - }, + },*/ + { //THIS IS ONLY FOR THE TEST ########################################## + label: "Description", + type: "multipleZonesSelection", + propertyID: "description", + }, // END TEST ############################# { label: "Parent", type: "string", @@ -142,7 +140,17 @@ const GROUPS = [ label: "Color", type: "color", propertyID: "color", - } + }, + { + label: "Alpha", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "shapeAlpha", + propertyName: "alpha", + }, ] }, { @@ -191,6 +199,36 @@ const GROUPS = [ unit: "m", propertyID: "lineHeight", }, + { + label: "Font", + type: "string", + propertyID: "font", + }, + { + label: "Effect", + type: "dropdown", + options: { + none: "None", + outline: "Outline", + "outline fill": "Outline with fill", + shadow: "Shadow" + }, + propertyID: "textEffect", + }, + { + label: "Effect Color", + type: "color", + propertyID: "textEffectColor", + }, + { + label: "Effect Thickness", + type: "number-draggable", + min: 0.0, + max: 0.5, + step: 0.01, + decimals: 2, + propertyID: "textEffectThickness", + }, { label: "Billboard Mode", type: "dropdown", @@ -288,7 +326,7 @@ const GROUPS = [ { label: "Light Intensity", type: "number-draggable", - min: 0, + min: -40, max: 40, step: 0.01, decimals: 2, @@ -380,7 +418,7 @@ const GROUPS = [ { label: "Ambient Intensity", type: "number-draggable", - min: 0, + min: -200, max: 200, step: 0.1, decimals: 2, @@ -542,6 +580,12 @@ const GROUPS = [ type: "dropdown", options: { inherit: "Inherit", crowd: "Crowd", hero: "Hero" }, propertyID: "avatarPriority", + }, + { + label: "Screen-share", + type: "dropdown", + options: { inherit: "Inherit", disabled: "Off", enabled: "On" }, + propertyID: "screenshare", } ] }, @@ -587,7 +631,7 @@ const GROUPS = [ propertyID: "animation.loop", }, { - label: "Allow Transition", + label: "Allow Translation", type: "bool", propertyID: "animation.allowTranslation", }, @@ -651,6 +695,16 @@ const GROUPS = [ propertyID: "imageColor", propertyName: "color", // actual entity property name }, + { + label: "Alpha", + type: "number-draggable", + min: 0, + max: 1, + step: 0.01, + decimals: 2, + propertyID: "imageAlpha", + propertyName: "alpha", + }, { label: "Emissive", type: "bool", @@ -715,6 +769,27 @@ const GROUPS = [ decimals: 0, propertyID: "maxFPS", }, + { + label: "Billboard Mode", + type: "dropdown", + options: { none: "None", yaw: "Yaw", full: "Full"}, + propertyID: "webBillboardMode", + propertyName: "billboardMode", // actual entity property name + }, + { + label: "Input Mode", + type: "dropdown", + options: { + touch: "Touch events", + mouse: "Mouse events" + }, + propertyID: "inputMode", + }, + { + label: "Focus Highlight", + type: "bool", + propertyID: "showKeyboardFocusHighlight", + }, { label: "Script URL", type: "string", @@ -736,7 +811,7 @@ const GROUPS = [ { label: "Intensity", type: "number-draggable", - min: 0, + min: -1000, max: 10000, step: 0.1, decimals: 2, @@ -1601,11 +1676,10 @@ const GROUPS_PER_TYPE = { Image: [ 'base', 'image', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Web: [ 'base', 'web', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Light: [ 'base', 'light', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], - Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts' ], + Material: [ 'base', 'material', 'spatial', 'behavior', 'scripts', 'physics' ], ParticleEffect: [ 'base', 'particles', 'particles_emit', 'particles_size', 'particles_color', 'particles_behavior', 'particles_constraints', 'spatial', 'behavior', 'scripts', 'physics' ], PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], - PolyLine: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], PolyVox: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], Grid: [ 'base', 'grid', 'spatial', 'behavior', 'scripts', 'physics' ], Multiple: [ 'base', 'spatial', 'behavior', 'scripts', 'collision', 'physics' ], @@ -1675,7 +1749,7 @@ let selectedEntityIDs = new Set(); let currentSelections = []; let createAppTooltip = new CreateAppTooltip(); let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL; - +let zonesList = []; function createElementFromHTML(htmlString) { let elTemplate = document.createElement('template'); @@ -1701,6 +1775,8 @@ function getPropertyInputElement(propertyID) { case 'textarea': case 'texture': return property.elInput; + case 'multipleZonesSelection': + return property.elInput; case 'number-draggable': return property.elNumber.elInput; case 'rect': @@ -1741,6 +1817,7 @@ function disableChildren(el, selector) { function enableProperties() { enableChildren(document.getElementById("properties-list"), ENABLE_DISABLE_SELECTOR); enableChildren(document, ".colpick"); + enableAllMultipleZoneSelector(); } function disableProperties() { @@ -1749,6 +1826,7 @@ function disableProperties() { for (let pickKey in colorPickers) { colorPickers[pickKey].colpickHide(); } + disableAllMultipleZoneSelector(); } function showPropertyElement(propertyID, show) { @@ -1823,6 +1901,12 @@ function resetProperties() { setTextareaScrolling(property.elInput); break; } + case 'multipleZonesSelection': { + property.elInput.classList.remove('multi-diff'); + property.elInput.value = "[]"; //################################## PROBABLY SOMETHING TO ADJUST HERE! + setZonesSelectionData(property.elInput, false); + break; + } case 'icon': { property.elSpan.style.display = "none"; break; @@ -1860,7 +1944,7 @@ function resetServerScriptStatus() { function showGroupsForType(type) { if (type === "Box" || type === "Sphere") { showGroupsForTypes(["Shape"]); - showOnTheSamePage("Shape"); + showOnTheSamePage(["Shape"]); return; } if (type === "None") { @@ -1868,7 +1952,7 @@ function showGroupsForType(type) { return; } showGroupsForTypes([type]); - showOnTheSamePage(type); + showOnTheSamePage([type]); } function getGroupsForTypes(types) { @@ -2972,6 +3056,10 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI property.elInput = createTextareaProperty(property, elProperty); break; } + case 'multipleZonesSelection': { + property.elInput = createZonesSelection(property, elProperty); + break; + } case 'icon': { property.elSpan = createIconProperty(property, elProperty); break; @@ -3464,6 +3552,175 @@ function setTextareaScrolling(element) { element.setAttribute("scrolling", isScrolling ? "true" : "false"); } +/** + * ZONE SELECTOR FUNCTIONS + */ + +function enableAllMultipleZoneSelector() { + let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); + let i, propId; + for ( i = 0; i < allMultiZoneSelectors.length; i++ ) { + propId = allMultiZoneSelectors[i].id; + displaySelectedZones(propId, true); + } +} + +function disableAllMultipleZoneSelector() { + let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); + let i, propId; + for ( i = 0; i < allMultiZoneSelectors.length; i++ ) { + propId = allMultiZoneSelectors[i].id; + displaySelectedZones(propId, false); + } +} + +function requestZoneList() { + EventBridge.emitWebEvent(JSON.stringify({ + type: "zoneListRequest" + })); +} + +function addZoneToZonesSelection(propertyId) { + let hiddenField = document.getElementById(propertyId); + if(JSON.stringify(hiddenField.value) === '"undefined"') { + hiddenField.value = "[]"; + } + let selectedZones = JSON.parse(hiddenField.value); + let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; + if (!selectedZones.includes(zoneToAdd)) { + selectedZones.push(zoneToAdd); + } + hiddenField.value = JSON.stringify(selectedZones); + displaySelectedZones(propertyId, true); + let propertyName = propertyId.replace("property-", ""); + updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST + //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY +} + +function removeZoneFromZonesSelection(propertyId, zoneId) { + let hiddenField = document.getElementById(propertyId); + if(JSON.stringify(hiddenField.value) === '"undefined"') { + hiddenField.value = "[]"; + } + let selectedZones = JSON.parse(hiddenField.value); + let index = selectedZones.indexOf(zoneId); + if (index > -1) { + selectedZones.splice(index, 1); + } + hiddenField.value = JSON.stringify(selectedZones); + displaySelectedZones(propertyId, true); + let propertyName = propertyId.replace("property-", ""); + updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST + //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY +} + +function displaySelectedZones(propertyId, isEditable) { + let i,j, name, listedZoneInner, hiddenData, isMultiple; + hiddenData = document.getElementById(propertyId).value; + if (JSON.stringify(hiddenData) === '"undefined"') { + isMultiple = true; + hiddenData = "[]"; + } else { + isMultiple = false; + } + let selectedZones = JSON.parse(hiddenData); + listedZoneInner = ""; + if (selectedZones.length === 0) { + if (!isMultiple) { + listedZoneInner += ""; + } else { + listedZoneInner += ""; + } + } else { + for ( i = 0; i < selectedZones.length; i++ ) { + name = "{ERROR: NOT FOUND}"; + for ( j = 0; j < zonesList.length; j++ ) { + if (selectedZones[i] === zonesList[j].id) { + if (zonesList[j].name !== "") { + name = zonesList[j].name; + } else { + name = zonesList[j].id; + } + break; + } + } + if (isEditable) { + listedZoneInner += ""; + } else { + listedZoneInner += ""; + } + } + } + listedZoneInner += "
      
    [ WARNING: Any changes will apply to all ] 
    " + name + "
    " + name + " 
    "; + document.getElementById("selected-zones-" + propertyId).innerHTML = listedZoneInner; + if (isEditable) { + document.getElementById("multiZoneSelTools-" + propertyId).style.display = "block"; + } else { + document.getElementById("multiZoneSelTools-" + propertyId).style.display = "none"; + } +} + +function createZonesSelection(property, elProperty) { + let elementID = property.elementID; + requestZoneList(); + elProperty.className = "multipleZonesSelection"; + let elInput = document.createElement('input'); + elInput.setAttribute("id", elementID); + elInput.setAttribute("type", "hidden"); // must be hidden ################################################################################# HEIL! ICITTE! + elInput.className = "hiddenMultiZonesSelection"; + + let elZonesSelector = document.createElement('div'); + elZonesSelector.setAttribute("id", "zones-selector-" + elementID); + + let elMultiDiff = document.createElement('span'); + elMultiDiff.className = "multi-diff"; + + elProperty.appendChild(elInput); + elProperty.appendChild(elZonesSelector); + elProperty.appendChild(elMultiDiff); + + return elInput; +} + +function setZonesSelectionData(element, isEditable) { + let zoneSelectorContainer = document.getElementById("zones-selector-" + element.id); + let zoneSelector = "
     
    "; + zoneSelector += "
    "; + zoneSelectorContainer.innerHTML = zoneSelector; + displaySelectedZones(element.id, isEditable); +} + +function updateAllZoneSelect() { + let allZoneSelects = document.querySelectorAll(".zoneSelect"); + let i, j, name, propId; + for ( i = 0; i < allZoneSelects.length; i++ ) { + allZoneSelects[i].options.length = 0; + for ( j = 0; j < zonesList.length; j++ ) { + if (zonesList[j].name === "") { + name = zonesList[j].id; + } else { + name = zonesList[j].name; + } + allZoneSelects[i].options[j] = new Option(name, zonesList[j].id, false , false); + } + propId = allZoneSelects[i].id.replace("zones-select-", ""); + if (document.getElementById("multiZoneSelTools-" + propId).style.display === "block") { + displaySelectedZones(propId, true); + } else { + displaySelectedZones(propId, false); + } + } +} /** * MATERIAL TARGET FUNCTIONS @@ -3637,7 +3894,9 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { selectedEntityIDs = new Set(selections.map(selection => selection.id)); const multipleSelections = currentSelections.length > 1; const hasSelectedEntityChanged = !areSetsEqual(selectedEntityIDs, previouslySelectedEntityIDs); - + + requestZoneList(); + if (selections.length === 0) { deleteJSONEditor(); deleteJSONMaterialEditor(); @@ -3692,7 +3951,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { } else { enableProperties(); disableSaveUserDataButton(); - disableSaveMaterialDataButton() + disableSaveMaterialDataButton(); } const certificateIDMultiValue = getMultiplePropertyValue('certificateID'); @@ -3848,6 +4107,19 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { setTextareaScrolling(property.elInput); break; } + case 'multipleZonesSelection': { + if (propertyValue == ""){ //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = "[]"; //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + } else { //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = propertyValue; //JSON.stringify(propertyValue); //##### TO CHECK depending what type the value is.. expecting an array so it willbe manage as a string. + } //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { + setZonesSelectionData(property.elInput, false); + } else { + setZonesSelectionData(property.elInput, true); + } + break; + } case 'icon': { property.elSpan.innerHTML = propertyData.icons[propertyValue]; property.elSpan.style.display = "inline-block"; @@ -4177,6 +4449,9 @@ function loaded() { if (data.entityID === getFirstSelectedID()) { setMaterialTargetData(data.materialTargetData); } + } else if (data.type === 'zoneListRequest') { + zonesList = data.zones; + updateAllZoneSelect(); } }); From c42734cba84d0dc931d921a53a899b493322bb20 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 27 Apr 2020 22:47:49 -0400 Subject: [PATCH 079/105] adding screenshare with the real file --- .../html/js/entityProperties.js | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 59755df122..b634517d03 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -67,16 +67,11 @@ const GROUPS = [ replaceID: "placeholder-property-id", multiDisplayMode: PROPERTY_MULTI_DISPLAY_MODE.COMMA_SEPARATED_VALUES, }, - /*{ + { label: "Description", type: "string", propertyID: "description", - },*/ - { //THIS IS ONLY FOR THE TEST ########################################## - label: "Description", - type: "multipleZonesSelection", - propertyID: "description", - }, // END TEST ############################# + }, { label: "Parent", type: "string", @@ -120,6 +115,11 @@ const GROUPS = [ lines: "Wireframe", }, propertyID: "primitiveMode", + }, + { + label: "Render With Zones", + type: "multipleZonesSelection", + propertyID: "renderWithZones", } ] }, @@ -1903,7 +1903,7 @@ function resetProperties() { } case 'multipleZonesSelection': { property.elInput.classList.remove('multi-diff'); - property.elInput.value = "[]"; //################################## PROBABLY SOMETHING TO ADJUST HERE! + property.elInput.value = "[]"; setZonesSelectionData(property.elInput, false); break; } @@ -3588,20 +3588,19 @@ function addZoneToZonesSelection(propertyId) { let selectedZones = JSON.parse(hiddenField.value); let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; if (!selectedZones.includes(zoneToAdd)) { - selectedZones.push(zoneToAdd); + selectedZones.push(zoneToAdd); } hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); - updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST - //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY + updateProperty(propertyName, selectedZones, false); } function removeZoneFromZonesSelection(propertyId, zoneId) { let hiddenField = document.getElementById(propertyId); if(JSON.stringify(hiddenField.value) === '"undefined"') { hiddenField.value = "[]"; - } + } let selectedZones = JSON.parse(hiddenField.value); let index = selectedZones.indexOf(zoneId); if (index > -1) { @@ -3610,8 +3609,7 @@ function removeZoneFromZonesSelection(propertyId, zoneId) { hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); - updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST - //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY + updateProperty(propertyName, selectedZones, false); } function displaySelectedZones(propertyId, isEditable) { @@ -3629,7 +3627,7 @@ function displaySelectedZones(propertyId, isEditable) { if (!isMultiple) { listedZoneInner += "  "; } else { - listedZoneInner += "[ WARNING: Any changes will apply to all ] "; + listedZoneInner += "[ WARNING: Any changes will apply to all. ] "; } } else { for ( i = 0; i < selectedZones.length; i++ ) { @@ -3645,9 +3643,10 @@ function displaySelectedZones(propertyId, isEditable) { } } if (isEditable) { - listedZoneInner += "" + name + ""; + listedZoneInner += "" + name + ""; + listedZoneInner += ""; } else { - listedZoneInner += "" + name + " "; + listedZoneInner += "" + name + " "; } } } @@ -3666,7 +3665,7 @@ function createZonesSelection(property, elProperty) { elProperty.className = "multipleZonesSelection"; let elInput = document.createElement('input'); elInput.setAttribute("id", elementID); - elInput.setAttribute("type", "hidden"); // must be hidden ################################################################################# HEIL! ICITTE! + elInput.setAttribute("type", "hidden"); elInput.className = "hiddenMultiZonesSelection"; let elZonesSelector = document.createElement('div'); @@ -3694,7 +3693,8 @@ function setZonesSelectionData(element, isEditable) { } zoneSelector += ""; } - zoneSelector += " "; + zoneSelector += " "; + zoneSelector += ""; zoneSelector += "
    "; zoneSelectorContainer.innerHTML = zoneSelector; displaySelectedZones(element.id, isEditable); @@ -4108,18 +4108,14 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { break; } case 'multipleZonesSelection': { - if (propertyValue == ""){ //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - property.elInput.value = "[]"; //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - } else { //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - property.elInput.value = propertyValue; //JSON.stringify(propertyValue); //##### TO CHECK depending what type the value is.. expecting an array so it willbe manage as a string. - } //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = JSON.stringify(propertyValue); if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { setZonesSelectionData(property.elInput, false); } else { setZonesSelectionData(property.elInput, true); } break; - } + } case 'icon': { property.elSpan.innerHTML = propertyData.icons[propertyValue]; property.elSpan.style.display = "inline-block"; From 8c1d80d49581e8fc8950ffcab9fc66c72c84047b Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 27 Apr 2020 22:48:47 -0400 Subject: [PATCH 080/105] To really avoid a regression --- .../html/js/entityProperties.js | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 59755df122..b634517d03 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -67,16 +67,11 @@ const GROUPS = [ replaceID: "placeholder-property-id", multiDisplayMode: PROPERTY_MULTI_DISPLAY_MODE.COMMA_SEPARATED_VALUES, }, - /*{ + { label: "Description", type: "string", propertyID: "description", - },*/ - { //THIS IS ONLY FOR THE TEST ########################################## - label: "Description", - type: "multipleZonesSelection", - propertyID: "description", - }, // END TEST ############################# + }, { label: "Parent", type: "string", @@ -120,6 +115,11 @@ const GROUPS = [ lines: "Wireframe", }, propertyID: "primitiveMode", + }, + { + label: "Render With Zones", + type: "multipleZonesSelection", + propertyID: "renderWithZones", } ] }, @@ -1903,7 +1903,7 @@ function resetProperties() { } case 'multipleZonesSelection': { property.elInput.classList.remove('multi-diff'); - property.elInput.value = "[]"; //################################## PROBABLY SOMETHING TO ADJUST HERE! + property.elInput.value = "[]"; setZonesSelectionData(property.elInput, false); break; } @@ -3588,20 +3588,19 @@ function addZoneToZonesSelection(propertyId) { let selectedZones = JSON.parse(hiddenField.value); let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; if (!selectedZones.includes(zoneToAdd)) { - selectedZones.push(zoneToAdd); + selectedZones.push(zoneToAdd); } hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); - updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST - //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY + updateProperty(propertyName, selectedZones, false); } function removeZoneFromZonesSelection(propertyId, zoneId) { let hiddenField = document.getElementById(propertyId); if(JSON.stringify(hiddenField.value) === '"undefined"') { hiddenField.value = "[]"; - } + } let selectedZones = JSON.parse(hiddenField.value); let index = selectedZones.indexOf(zoneId); if (index > -1) { @@ -3610,8 +3609,7 @@ function removeZoneFromZonesSelection(propertyId, zoneId) { hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); - updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST - //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY + updateProperty(propertyName, selectedZones, false); } function displaySelectedZones(propertyId, isEditable) { @@ -3629,7 +3627,7 @@ function displaySelectedZones(propertyId, isEditable) { if (!isMultiple) { listedZoneInner += "  "; } else { - listedZoneInner += "[ WARNING: Any changes will apply to all ] "; + listedZoneInner += "[ WARNING: Any changes will apply to all. ] "; } } else { for ( i = 0; i < selectedZones.length; i++ ) { @@ -3645,9 +3643,10 @@ function displaySelectedZones(propertyId, isEditable) { } } if (isEditable) { - listedZoneInner += "" + name + ""; + listedZoneInner += "" + name + ""; + listedZoneInner += ""; } else { - listedZoneInner += "" + name + " "; + listedZoneInner += "" + name + " "; } } } @@ -3666,7 +3665,7 @@ function createZonesSelection(property, elProperty) { elProperty.className = "multipleZonesSelection"; let elInput = document.createElement('input'); elInput.setAttribute("id", elementID); - elInput.setAttribute("type", "hidden"); // must be hidden ################################################################################# HEIL! ICITTE! + elInput.setAttribute("type", "hidden"); elInput.className = "hiddenMultiZonesSelection"; let elZonesSelector = document.createElement('div'); @@ -3694,7 +3693,8 @@ function setZonesSelectionData(element, isEditable) { } zoneSelector += ""; } - zoneSelector += " "; + zoneSelector += " "; + zoneSelector += ""; zoneSelector += "
    "; zoneSelectorContainer.innerHTML = zoneSelector; displaySelectedZones(element.id, isEditable); @@ -4108,18 +4108,14 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { break; } case 'multipleZonesSelection': { - if (propertyValue == ""){ //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - property.elInput.value = "[]"; //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - } else { //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - property.elInput.value = propertyValue; //JSON.stringify(propertyValue); //##### TO CHECK depending what type the value is.. expecting an array so it willbe manage as a string. - } //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = JSON.stringify(propertyValue); if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { setZonesSelectionData(property.elInput, false); } else { setZonesSelectionData(property.elInput, true); } break; - } + } case 'icon': { property.elSpan.innerHTML = propertyData.icons[propertyValue]; property.elSpan.style.display = "inline-block"; From 962d4671ebc917b934456dbbfb2cb94edc504452 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Mon, 27 Apr 2020 22:49:42 -0400 Subject: [PATCH 081/105] To avoid a regression at some point --- .../html/js/entityProperties.js | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 59755df122..b634517d03 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -67,16 +67,11 @@ const GROUPS = [ replaceID: "placeholder-property-id", multiDisplayMode: PROPERTY_MULTI_DISPLAY_MODE.COMMA_SEPARATED_VALUES, }, - /*{ + { label: "Description", type: "string", propertyID: "description", - },*/ - { //THIS IS ONLY FOR THE TEST ########################################## - label: "Description", - type: "multipleZonesSelection", - propertyID: "description", - }, // END TEST ############################# + }, { label: "Parent", type: "string", @@ -120,6 +115,11 @@ const GROUPS = [ lines: "Wireframe", }, propertyID: "primitiveMode", + }, + { + label: "Render With Zones", + type: "multipleZonesSelection", + propertyID: "renderWithZones", } ] }, @@ -1903,7 +1903,7 @@ function resetProperties() { } case 'multipleZonesSelection': { property.elInput.classList.remove('multi-diff'); - property.elInput.value = "[]"; //################################## PROBABLY SOMETHING TO ADJUST HERE! + property.elInput.value = "[]"; setZonesSelectionData(property.elInput, false); break; } @@ -3588,20 +3588,19 @@ function addZoneToZonesSelection(propertyId) { let selectedZones = JSON.parse(hiddenField.value); let zoneToAdd = document.getElementById("zones-select-" + propertyId).value; if (!selectedZones.includes(zoneToAdd)) { - selectedZones.push(zoneToAdd); + selectedZones.push(zoneToAdd); } hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); - updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST - //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY + updateProperty(propertyName, selectedZones, false); } function removeZoneFromZonesSelection(propertyId, zoneId) { let hiddenField = document.getElementById(propertyId); if(JSON.stringify(hiddenField.value) === '"undefined"') { hiddenField.value = "[]"; - } + } let selectedZones = JSON.parse(hiddenField.value); let index = selectedZones.indexOf(zoneId); if (index > -1) { @@ -3610,8 +3609,7 @@ function removeZoneFromZonesSelection(propertyId, zoneId) { hiddenField.value = JSON.stringify(selectedZones); displaySelectedZones(propertyId, true); let propertyName = propertyId.replace("property-", ""); - updateProperty(propertyName, JSON.stringify(selectedZones), false); //FOR TEMPORARY STRING FOR TEST - //updateProperty(propertyName, selectedZones, false); //DIRECTLY FOR ARRY + updateProperty(propertyName, selectedZones, false); } function displaySelectedZones(propertyId, isEditable) { @@ -3629,7 +3627,7 @@ function displaySelectedZones(propertyId, isEditable) { if (!isMultiple) { listedZoneInner += "  "; } else { - listedZoneInner += "[ WARNING: Any changes will apply to all ] "; + listedZoneInner += "[ WARNING: Any changes will apply to all. ] "; } } else { for ( i = 0; i < selectedZones.length; i++ ) { @@ -3645,9 +3643,10 @@ function displaySelectedZones(propertyId, isEditable) { } } if (isEditable) { - listedZoneInner += "" + name + ""; + listedZoneInner += "" + name + ""; + listedZoneInner += ""; } else { - listedZoneInner += "" + name + " "; + listedZoneInner += "" + name + " "; } } } @@ -3666,7 +3665,7 @@ function createZonesSelection(property, elProperty) { elProperty.className = "multipleZonesSelection"; let elInput = document.createElement('input'); elInput.setAttribute("id", elementID); - elInput.setAttribute("type", "hidden"); // must be hidden ################################################################################# HEIL! ICITTE! + elInput.setAttribute("type", "hidden"); elInput.className = "hiddenMultiZonesSelection"; let elZonesSelector = document.createElement('div'); @@ -3694,7 +3693,8 @@ function setZonesSelectionData(element, isEditable) { } zoneSelector += ""; } - zoneSelector += " "; + zoneSelector += " "; + zoneSelector += ""; zoneSelector += "
    "; zoneSelectorContainer.innerHTML = zoneSelector; displaySelectedZones(element.id, isEditable); @@ -4108,18 +4108,14 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { break; } case 'multipleZonesSelection': { - if (propertyValue == ""){ //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - property.elInput.value = "[]"; //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - } else { //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS - property.elInput.value = propertyValue; //JSON.stringify(propertyValue); //##### TO CHECK depending what type the value is.. expecting an array so it willbe manage as a string. - } //THIS IS A PATCH FOR TESTING WITh A STRING FIELDS + property.elInput.value = JSON.stringify(propertyValue); if (lockedMultiValue.isMultiDiffValue || lockedMultiValue.value) { setZonesSelectionData(property.elInput, false); } else { setZonesSelectionData(property.elInput, true); } break; - } + } case 'icon': { property.elSpan.innerHTML = propertyData.icons[propertyValue]; property.elSpan.style.display = "inline-block"; From 488cea43cdec8af1af255d78f057009f6cc39fe4 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Mon, 4 May 2020 11:28:35 +0200 Subject: [PATCH 082/105] disk usage github actions, for debugging linux build issue --- .github/workflows/pr_build.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index 57d32741ca..f5104dbe43 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -121,6 +121,13 @@ jobs: working-directory: ${{runner.workspace}}/build shell: bash run: cmake --build . --config $BUILD_TYPE --target package $CMAKE_BUILD_EXTRA + - name: Output system stats + if: ${{ always() }} + working-directory: ${{runner.workspace}}/build + shell: bash + run: | + echo "Disk usage:" + df -h - name: Output Installer Logs if: failure() && matrix.os == 'windows-latest' shell: bash From 0d02f62ad5687e55eb613679865f11078fb3ca8e Mon Sep 17 00:00:00 2001 From: MotoFufu9k Date: Tue, 5 May 2020 00:37:41 +0200 Subject: [PATCH 083/105] Change all mentions of "hifi-snap-by-" to "vircadia-snap-by-" --- interface/src/scripting/WindowScriptingInterface.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index bf39073db1..0c2fdd1614 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -325,7 +325,7 @@ public slots: * @param {number} [aspectRatio=0] - The width/height ratio of the snapshot required. If the value is 0, the * full resolution is used (window dimensions in desktop mode; HMD display dimensions in HMD mode), otherwise one of the * dimensions is adjusted in order to match the aspect ratio. - * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user + * @param {string} [filename=""] - If a filename is not provided, the image is saved as "vircadia-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". *

    Still images are saved in JPEG or PNG format according to the extension provided — ".jpg", * ".jpeg", or ".png" — or if not provided then in JPEG format with an extension of @@ -364,7 +364,7 @@ public slots: * @function Window.takeSecondaryCameraSnapshot * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. - * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user + * @param {string} [filename=""] - If a filename is not provided, the image is saved as "vircadia-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". *

    Images are saved in JPEG or PNG format according to the extension provided — ".jpg", * ".jpeg", or ".png" — or if not provided then in JPEG format with an extension of @@ -383,7 +383,7 @@ public slots: * otherwise it is saved as an equirectangular image. * @param {boolean} [notify=true] - This value is passed on through the {@link Window.stillSnapshotTaken|stillSnapshotTaken} * signal. - * @param {string} [filename=""] - If a filename is not provided, the image is saved as "hifi-snap-by-<user + * @param {string} [filename=""] - If a filename is not provided, the image is saved as "vircadia-snap-by-<user * name>-on-YYYY-MM-DD_HH-MM-SS". *

    Images are saved in JPEG or PNG format according to the extension provided — ".jpg", * ".jpeg", or ".png" — or if not provided then in JPEG format with an extension of From a7101428713dd17e278b4b39c6ea22b954d62764 Mon Sep 17 00:00:00 2001 From: MotoFufu9k Date: Tue, 5 May 2020 00:39:25 +0200 Subject: [PATCH 084/105] Change "FILENAME_PATH_FORMAT" to "vircadia..." --- interface/src/ui/Snapshot.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index bb9971e582..4882d6e5da 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -42,9 +42,9 @@ #include "Snapshot.h" #include "SnapshotUploader.h" -// filename format: hifi-snap-by-%username%-on-%date%_%time%_@-%location%.jpg +// filename format: vircadia-snap-by-%username%-on-%date%_%time%_@-%location%.jpg // %1 <= username, %2 <= date and time, %3 <= current location -const QString FILENAME_PATH_FORMAT = "hifi-snap-by-%1-on-%2.jpg"; +const QString FILENAME_PATH_FORMAT = "vircadia-snap-by-%1-on-%2.jpg"; const QString DATETIME_FORMAT = "yyyy-MM-dd_hh-mm-ss"; const QString SNAPSHOTS_DIRECTORY = "Snapshots"; const QString URL = "highfidelity_url"; From 748439f055bbfc46078903b56be97398d1e3d44a Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Wed, 6 May 2020 23:20:21 +0200 Subject: [PATCH 085/105] add retry command for packaging, since linux screenshare has about a 50% chance to fail a build --- .github/workflows/pr_build.yml | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr_build.yml b/.github/workflows/pr_build.yml index f5104dbe43..4b3d66da50 100644 --- a/.github/workflows/pr_build.yml +++ b/.github/workflows/pr_build.yml @@ -120,7 +120,30 @@ jobs: - name: Build Installer working-directory: ${{runner.workspace}}/build shell: bash - run: cmake --build . --config $BUILD_TYPE --target package $CMAKE_BUILD_EXTRA + run: | + echo "Retry code from https://unix.stackexchange.com/a/137639" + function fail { + echo $1 >&2 + exit 1 + } + + function retry { + local n=1 + local max=5 + local delay=15 + while true; do + "$@" && break || { + if [[ $n -lt $max ]]; then + ((n++)) + echo "Command failed. Attempt $n/$max:" + sleep $delay; + else + fail "The command has failed after $n attempts." + fi + } + done + } + retry cmake --build . --config $BUILD_TYPE --target package $CMAKE_BUILD_EXTRA - name: Output system stats if: ${{ always() }} working-directory: ${{runner.workspace}}/build From cc308c11b621bc9ccc70444d1d9fe0fe39be99e5 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 6 May 2020 23:06:33 -0400 Subject: [PATCH 086/105] Minor Code Adjustment Line 50: removed extra space char. --- .../system/create/entityProperties/html/entityProperties.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index b1d5e2805e..6eadf4d3c0 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -47,7 +47,7 @@ - + From f43b0f52f52578b3972bff62a9ce85a453223ada Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 6 May 2020 23:16:56 -0400 Subject: [PATCH 087/105] Minor code adjustments Add missing space between ":" and the value for many class attributes. --- scripts/system/html/css/tabs.css | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/system/html/css/tabs.css b/scripts/system/html/css/tabs.css index 37383b6d99..87e1c11ee8 100644 --- a/scripts/system/html/css/tabs.css +++ b/scripts/system/html/css/tabs.css @@ -48,25 +48,25 @@ div.tab-section-header { } table.tabsTableFrame { - width:100%; + width: 100%; min-height: 352px; display: block; } tr.tabsTrFrame { - width:100%; + width: 100%; } td.tabsFrame { - width:32px; - vertical-align:top; - background-color:#575757; - padding:0px; - border:0px; + width: 32px; + vertical-align: top; + background-color: #575757; + padding: 0px; + border: 0px; } td.tabsPropertiesFrame { - width:100%; + width: 100%; vertical-align: top; border:0px; } From 5180c9b247e900314b2819358073a1b810076a80 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Wed, 6 May 2020 23:36:39 -0400 Subject: [PATCH 088/105] Minor Code Adjustment --- .../html/js/entityProperties.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index b634517d03..8c041d2563 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -115,12 +115,12 @@ const GROUPS = [ lines: "Wireframe", }, propertyID: "primitiveMode", - }, + }/*, { label: "Render With Zones", type: "multipleZonesSelection", propertyID: "renderWithZones", - } + }*/ ] }, { @@ -3559,7 +3559,7 @@ function setTextareaScrolling(element) { function enableAllMultipleZoneSelector() { let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); let i, propId; - for ( i = 0; i < allMultiZoneSelectors.length; i++ ) { + for (i = 0; i < allMultiZoneSelectors.length; i++) { propId = allMultiZoneSelectors[i].id; displaySelectedZones(propId, true); } @@ -3568,7 +3568,7 @@ function enableAllMultipleZoneSelector() { function disableAllMultipleZoneSelector() { let allMultiZoneSelectors = document.querySelectorAll(".hiddenMultiZonesSelection"); let i, propId; - for ( i = 0; i < allMultiZoneSelectors.length; i++ ) { + for (i = 0; i < allMultiZoneSelectors.length; i++) { propId = allMultiZoneSelectors[i].id; displaySelectedZones(propId, false); } @@ -3582,7 +3582,7 @@ function requestZoneList() { function addZoneToZonesSelection(propertyId) { let hiddenField = document.getElementById(propertyId); - if(JSON.stringify(hiddenField.value) === '"undefined"') { + if (JSON.stringify(hiddenField.value) === '"undefined"') { hiddenField.value = "[]"; } let selectedZones = JSON.parse(hiddenField.value); @@ -3598,7 +3598,7 @@ function addZoneToZonesSelection(propertyId) { function removeZoneFromZonesSelection(propertyId, zoneId) { let hiddenField = document.getElementById(propertyId); - if(JSON.stringify(hiddenField.value) === '"undefined"') { + if (JSON.stringify(hiddenField.value) === '"undefined"') { hiddenField.value = "[]"; } let selectedZones = JSON.parse(hiddenField.value); @@ -3630,9 +3630,9 @@ function displaySelectedZones(propertyId, isEditable) { listedZoneInner += ""; } } else { - for ( i = 0; i < selectedZones.length; i++ ) { + for (i = 0; i < selectedZones.length; i++) { name = "{ERROR: NOT FOUND}"; - for ( j = 0; j < zonesList.length; j++ ) { + for (j = 0; j < zonesList.length; j++) { if (selectedZones[i] === zonesList[j].id) { if (zonesList[j].name !== "") { name = zonesList[j].name; @@ -3685,7 +3685,7 @@ function setZonesSelectionData(element, isEditable) { let zoneSelectorContainer = document.getElementById("zones-selector-" + element.id); let zoneSelector = "
    "; } } else { - for ( i = 0; i < selectedZones.length; i++ ) { + for (i = 0; i < selectedZones.length; i++) { name = "{ERROR: NOT FOUND}"; - for ( j = 0; j < zonesList.length; j++ ) { + for (j = 0; j < zonesList.length; j++) { if (selectedZones[i] === zonesList[j].id) { if (zonesList[j].name !== "") { name = zonesList[j].name; @@ -3685,7 +3685,7 @@ function setZonesSelectionData(element, isEditable) { let zoneSelectorContainer = document.getElementById("zones-selector-" + element.id); let zoneSelector = "
    "; } } else { - for ( i = 0; i < selectedZones.length; i++ ) { + for (i = 0; i < selectedZones.length; i++) { name = "{ERROR: NOT FOUND}"; - for ( j = 0; j < zonesList.length; j++ ) { + for (j = 0; j < zonesList.length; j++) { if (selectedZones[i] === zonesList[j].id) { if (zonesList[j].name !== "") { name = zonesList[j].name; @@ -3685,7 +3685,7 @@ function setZonesSelectionData(element, isEditable) { let zoneSelectorContainer = document.getElementById("zones-selector-" + element.id); let zoneSelector = "
    [ WARNING: Any changes will apply to all. ] 
    [ WARNING: Any changes will apply to all. ] 
    [ WARNING: Any changes will apply to all. ]