diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llimage/llimage.cpp | 4 | ||||
-rw-r--r-- | indra/llimage/llimagej2c.cpp | 14 | ||||
-rw-r--r-- | indra/llkdu/llimagej2ckdu.cpp | 9 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial.cpp | 109 | ||||
-rw-r--r-- | indra/llprimitive/llgltfmaterial.h | 62 | ||||
-rw-r--r-- | indra/newview/VIEWER_VERSION.txt | 2 | ||||
-rw-r--r-- | indra/newview/llinventorybridge.cpp | 6 | ||||
-rw-r--r-- | indra/newview/llinventorygallery.cpp | 33 | ||||
-rw-r--r-- | indra/newview/llinventorygallery.h | 1 | ||||
-rw-r--r-- | indra/newview/llinventorygallerymenu.cpp | 288 | ||||
-rw-r--r-- | indra/newview/llpanelavatar.cpp | 5 | ||||
-rw-r--r-- | indra/newview/llpanelavatar.h | 2 | ||||
-rw-r--r-- | indra/newview/llpanelgroupnotices.cpp | 7 | ||||
-rw-r--r-- | indra/newview/llpanelmaininventory.cpp | 1 | ||||
-rw-r--r-- | indra/newview/llpanelprofile.cpp | 46 | ||||
-rw-r--r-- | indra/newview/llpanelprofile.h | 6 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/menu_gallery_inventory.xml | 228 |
17 files changed, 751 insertions, 72 deletions
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 031471d1fe..7ac80825b5 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -2130,6 +2130,10 @@ U8* LLImageFormatted::reallocateData(S32 size) // virtual void LLImageFormatted::deleteData() { + if (mDecoding) + { + LL_ERRS() << "LLImageFormatted::deleteData() is called during decoding" << LL_ENDL; + } sGlobalFormattedMemory -= getDataSize(); LLImageBase::deleteData(); } diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 8dba1641a6..a4957466d4 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -157,10 +157,10 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; LLTimer elapsed; - bool res = true; - resetLastError(); + mDecoding = true; + bool res; // Check to make sure that this instance has been initialized with data if (!getData() || (getDataSize() < 16)) { @@ -171,7 +171,6 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir { // Update the raw discard level updateRawDiscardLevel(); - mDecoding = true; res = mImpl->decodeImpl(*this, *raw_imagep, decode_time, first_channel, max_channel_count); } @@ -181,12 +180,21 @@ bool LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 fir { // Failed raw_imagep->deleteData(); + res = false; } else { mDecoding = false; } } + else + { + if (mDecoding) + { + LL_WARNS() << "decodeImpl failed but mDecoding is TRUE" << LL_ENDL; + mDecoding = false; + } + } if (!mLastError.empty()) { diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp index 2ad42d6b87..d96cd105dd 100644 --- a/indra/llkdu/llimagej2ckdu.cpp +++ b/indra/llkdu/llimagej2ckdu.cpp @@ -514,6 +514,7 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; ECodeStreamMode mode = MODE_FAST; + bool limit_time = decode_time > 0.0f; LLTimer decode_timer; if (!mCodeStreamp->exists()) @@ -578,16 +579,18 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco mCodeStreamp.get())); } // Do the actual processing - F32 remaining_time = decode_time - decode_timer.getElapsedTimeF32(); + F32 remaining_time = limit_time ? static_cast<F32>(decode_time - decode_timer.getElapsedTimeF32()) : 0.0f; // This is where we do the actual decode. If we run out of time, return false. - if (mDecodeState->processTileDecode(remaining_time, (decode_time > 0.0f))) + if (mDecodeState->processTileDecode(remaining_time, limit_time)) { mDecodeState.reset(); } else { // Not finished decoding yet. - // setLastError("Ran out of time while decoding"); + base.setLastError("Ran out of time while decoding"); + base.decodeFailed(); + cleanupCodeStream(); return false; } } diff --git a/indra/llprimitive/llgltfmaterial.cpp b/indra/llprimitive/llgltfmaterial.cpp index ae165f7fa4..e9d3350ee9 100644 --- a/indra/llprimitive/llgltfmaterial.cpp +++ b/indra/llprimitive/llgltfmaterial.cpp @@ -47,16 +47,49 @@ const char* const LLGLTFMaterial::GLTF_FILE_EXTENSION_TRANSFORM_ROTATION = "rota // special UUID that indicates a null UUID in override data const LLUUID LLGLTFMaterial::GLTF_OVERRIDE_NULL_UUID = LLUUID("ffffffff-ffff-ffff-ffff-ffffffffffff"); +LLGLTFMaterial::LLGLTFMaterial() +{ + // IMPORTANT: since we use the hash of the member variables memory block of + // this class to detect changes, we must ensure that all its padding bytes + // have been zeroed out. But of course, we must leave the LLRefCount member + // variable untouched (and skip it when hashing), and we cannot either + // touch the local texture overrides map (else we destroy pointers, and + // sundry private data, which would lead to a crash when using that map). + // The variable members have therefore been arranged so that anything, + // starting at mLocalTexDataDigest and up to the end of the members, can be + // safely zeroed. HB + const size_t offset = intptr_t(&mLocalTexDataDigest) - intptr_t(this); + memset((void*)((const char*)this + offset), 0, sizeof(*this) - offset); + + // Now that we zeroed out our member variables, we can set the ones that + // should not be zero to their default value. HB + mBaseColor.set(1.f, 1.f, 1.f, 1.f); + mMetallicFactor = mRoughnessFactor = 1.f; + mAlphaCutoff = 0.5f; + for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + { + mTextureTransform[i].mScale.set(1.f, 1.f); +#if 0 + mTextureTransform[i].mOffset.clear(); + mTextureTransform[i].mRotation = 0.f; +#endif + } +#if 0 + mLocalTexDataDigest = 0; + mAlphaMode = ALPHA_MODE_OPAQUE; // This is 0 + mOverrideDoubleSided = mOverrideAlphaMode = false; +#endif +} + void LLGLTFMaterial::TextureTransform::getPacked(F32 (&packed)[8]) const { packed[0] = mScale.mV[VX]; packed[1] = mScale.mV[VY]; packed[2] = mRotation; - // packed[3] = unused packed[4] = mOffset.mV[VX]; packed[5] = mOffset.mV[VY]; - // packed[6] = unused - // packed[7] = unused + // Not used but nonetheless zeroed for proper hashing. HB + packed[3] = packed[6] = packed[7] = 0.f; } bool LLGLTFMaterial::TextureTransform::operator==(const TextureTransform& other) const @@ -89,13 +122,37 @@ LLGLTFMaterial& LLGLTFMaterial::operator=(const LLGLTFMaterial& rhs) mOverrideDoubleSided = rhs.mOverrideDoubleSided; mOverrideAlphaMode = rhs.mOverrideAlphaMode; - mTrackingIdToLocalTexture = rhs.mTrackingIdToLocalTexture; - - updateTextureTracking(); + if (rhs.mTrackingIdToLocalTexture.empty()) + { + mTrackingIdToLocalTexture.clear(); + mLocalTexDataDigest = 0; + } + else + { + mTrackingIdToLocalTexture = rhs.mTrackingIdToLocalTexture; + updateLocalTexDataDigest(); + updateTextureTracking(); + } return *this; } +void LLGLTFMaterial::updateLocalTexDataDigest() +{ + mLocalTexDataDigest = 0; + if (!mTrackingIdToLocalTexture.empty()) + { + for (local_tex_map_t::const_iterator + it = mTrackingIdToLocalTexture.begin(), + end = mTrackingIdToLocalTexture.end(); + it != end; ++it) + { + mLocalTexDataDigest ^= it->first.getDigest64() ^ + it->second.getDigest64(); + } + } +} + bool LLGLTFMaterial::operator==(const LLGLTFMaterial& rhs) const { return mTextureId == rhs.mTextureId && @@ -547,7 +604,7 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat) { LL_PROFILE_ZONE_SCOPED; - for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) { LLUUID& texture_id = mTextureId[i]; const LLUUID& override_texture_id = override_mat.mTextureId[i]; @@ -588,7 +645,7 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat) mDoubleSided = override_mat.mDoubleSided; } - for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) { if (override_mat.mTextureTransform[i].mOffset != getDefaultTextureOffset()) { @@ -606,9 +663,13 @@ void LLGLTFMaterial::applyOverride(const LLGLTFMaterial& override_mat) } } - mTrackingIdToLocalTexture.insert(override_mat.mTrackingIdToLocalTexture.begin(), override_mat.mTrackingIdToLocalTexture.begin()); - - updateTextureTracking(); + if (!override_mat.mTrackingIdToLocalTexture.empty()) + { + auto it = override_mat.mTrackingIdToLocalTexture.begin(); + mTrackingIdToLocalTexture.insert(it, it); + updateLocalTexDataDigest(); + updateTextureTracking(); + } } void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& data) @@ -618,7 +679,7 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d // make every effort to shave bytes here - for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) { LLUUID& texture_id = mTextureId[i]; const LLUUID& override_texture_id = override_mat.mTextureId[i]; @@ -663,7 +724,7 @@ void LLGLTFMaterial::getOverrideLLSD(const LLGLTFMaterial& override_mat, LLSD& d data["ds"] = override_mat.mDoubleSided; } - for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) { if (override_mat.mTextureTransform[i].mOffset != getDefaultTextureOffset()) { @@ -742,7 +803,7 @@ void LLGLTFMaterial::applyOverrideLLSD(const LLSD& data) const LLSD& ti = data["ti"]; if (ti.isArray()) { - for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) { const LLSD& o = ti[i]["o"]; if (o.isDefined()) @@ -768,27 +829,36 @@ void LLGLTFMaterial::applyOverrideLLSD(const LLSD& data) LLUUID LLGLTFMaterial::getHash() const { LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; - // HACK - hash the bytes of this object but don't include the ref count - LLUUID hash; - HBXXH128::digest(hash, (unsigned char*)this + sizeof(LLRefCount), sizeof(*this) - sizeof(LLRefCount)); - return hash; + // *HACK: hash the bytes of this object but do not include the ref count + // neither the local texture overrides (which is a map, with pointers to + // key/value pairs that would change from one LLGLTFMaterial instance to + // the other, even though the key/value pairs could be the same, and stored + // elsewhere in the memory heap or on the stack). + // Note: this does work properly to compare two LLGLTFMaterial instances + // only because the padding bytes between their member variables have been + // dutifully zeroed in the constructor. HB + const size_t offset = intptr_t(&mLocalTexDataDigest) - intptr_t(this); + return HBXXH128::digest((const void*)((const char*)this + offset), + sizeof(*this) - offset); } void LLGLTFMaterial::addLocalTextureTracking(const LLUUID& tracking_id, const LLUUID& tex_id) { mTrackingIdToLocalTexture[tracking_id] = tex_id; + updateLocalTexDataDigest(); } void LLGLTFMaterial::removeLocalTextureTracking(const LLUUID& tracking_id) { mTrackingIdToLocalTexture.erase(tracking_id); + updateLocalTexDataDigest(); } bool LLGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const LLUUID& old_id, const LLUUID& new_id) { bool res = false; - for (int i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) + for (U32 i = 0; i < GLTF_TEXTURE_INFO_COUNT; ++i) { if (mTextureId[i] == old_id) { @@ -809,6 +879,7 @@ bool LLGLTFMaterial::replaceLocalTexture(const LLUUID& tracking_id, const LLUUID { mTrackingIdToLocalTexture.erase(tracking_id); } + updateLocalTexDataDigest(); return res; } diff --git a/indra/llprimitive/llgltfmaterial.h b/indra/llprimitive/llgltfmaterial.h index 02f62fb08c..9f817d6a19 100644 --- a/indra/llprimitive/llgltfmaterial.h +++ b/indra/llprimitive/llgltfmaterial.h @@ -81,7 +81,7 @@ public: ALPHA_MODE_MASK }; - LLGLTFMaterial() {} + LLGLTFMaterial(); LLGLTFMaterial(const LLGLTFMaterial& rhs); LLGLTFMaterial& operator=(const LLGLTFMaterial& rhs); @@ -110,25 +110,6 @@ public: static const char* const GLTF_FILE_EXTENSION_TRANSFORM_ROTATION; static const LLUUID GLTF_OVERRIDE_NULL_UUID; - std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId; - std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform; - - // NOTE: initialize values to defaults according to the GLTF spec - // NOTE: these values should be in linear color space - LLColor4 mBaseColor = LLColor4(1, 1, 1, 1); - LLColor3 mEmissiveColor = LLColor3(0, 0, 0); - - F32 mMetallicFactor = 1.f; - F32 mRoughnessFactor = 1.f; - F32 mAlphaCutoff = 0.5f; - - bool mDoubleSided = false; - AlphaMode mAlphaMode = ALPHA_MODE_OPAQUE; - - // override specific flags for state that can't use off-by-epsilon or UUID hack - bool mOverrideDoubleSided = false; - bool mOverrideAlphaMode = false; - // get a UUID based on a hash of this LLGLTFMaterial LLUUID getHash() const; @@ -229,10 +210,6 @@ public: virtual bool replaceLocalTexture(const LLUUID& tracking_id, const LLUUID &old_id, const LLUUID& new_id); virtual void updateTextureTracking(); - // These fields are local to viewer and are a part of local bitmap support - typedef std::map<LLUUID, LLUUID> local_tex_map_t; - local_tex_map_t mTrackingIdToLocalTexture; - protected: static LLVector2 vec2FromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const LLVector2& default_value); static F32 floatFromJson(const std::map<std::string, tinygltf::Value>& object, const char* key, const F32 default_value); @@ -249,4 +226,41 @@ protected: void writeToTexture(tinygltf::Model& model, T& texture_info, TextureInfo texture_info_id, bool force_write = false) const; template<typename T> static void writeToTexture(tinygltf::Model& model, T& texture_info, const LLUUID& texture_id, const TextureTransform& transform, bool force_write = false); + + // Used to update the digest of the mTrackingIdToLocalTexture map each time + // it is changed; this way, that digest can be used by the fast getHash() + // method intsead of having to hash all individual keys and values. HB + void updateLocalTexDataDigest(); + +public: + // These fields are local to viewer and are a part of local bitmap support + // IMPORTANT: do not move this member down (and do not move + // mLocalTexDataDigest either): the getHash() method does rely on the + // current ordering. HB + typedef std::map<LLUUID, LLUUID> local_tex_map_t; + local_tex_map_t mTrackingIdToLocalTexture; + + // Used to store a digest of mTrackingIdToLocalTexture when the latter is + // not empty, or zero otherwise. HB + U64 mLocalTexDataDigest; + + std::array<LLUUID, GLTF_TEXTURE_INFO_COUNT> mTextureId; + std::array<TextureTransform, GLTF_TEXTURE_INFO_COUNT> mTextureTransform; + + // NOTE: initialize values to defaults according to the GLTF spec + // NOTE: these values should be in linear color space + LLColor4 mBaseColor; + LLColor3 mEmissiveColor; + + F32 mMetallicFactor; + F32 mRoughnessFactor; + F32 mAlphaCutoff; + + AlphaMode mAlphaMode; + bool mDoubleSided; + + // Override specific flags for state that can't use off-by-epsilon or UUID + // hack + bool mOverrideDoubleSided; + bool mOverrideAlphaMode; }; diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index 0e7b60da8a..a8a1887568 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -7.1.2
\ No newline at end of file +7.1.2 diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 932a0316dd..b44fcf3e03 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4360,12 +4360,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items if (!isInboxFolder() // don't allow creation in inbox && outfits_id != mUUID) { - bool menu_items_added = false; // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694. if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat)) { items.push_back(std::string("New Folder")); - menu_items_added = true; } if (!isMarketplaceListingsFolder()) { @@ -4383,10 +4381,6 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items disabled_items.push_back("New Settings"); } } - if (menu_items_added) - { - items.push_back(std::string("Create Separator")); - } } getClipboardEntries(false, items, disabled_items, flags); } diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 68581d04eb..7ded32cf19 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -2022,6 +2022,39 @@ void LLInventoryGallery::pasteAsLink(const LLUUID& dest, } } +void LLInventoryGallery::doCreate(const LLUUID& dest, const LLSD& userdata) +{ + + LLViewerInventoryCategory* cat = gInventory.getCategory(dest); + if (cat && mFolderID != dest) + { + menu_create_inventory_item(NULL, dest, userdata, LLUUID::null); + } + else + { + // todo: needs to reset current floater's filter, + // like reset_inventory_filter() + + LLHandle<LLPanel> handle = getHandle(); + std::function<void(const LLUUID&)> callback_cat_created = + [handle](const LLUUID& new_id) + { + gInventory.notifyObservers(); + LLInventoryGallery* panel = static_cast<LLInventoryGallery*>(handle.get()); + if (panel && new_id.notNull()) + { + panel->clearSelection(); + if (panel->mItemMap.count(new_id) != 0) + { + panel->addItemSelection(new_id, true); + } + } + }; + + menu_create_inventory_item(NULL, mFolderID, userdata, LLUUID::null, callback_cat_created); + } +} + void LLInventoryGallery::claimEditHandler() { gEditMenuHandler = this; diff --git a/indra/newview/llinventorygallery.h b/indra/newview/llinventorygallery.h index 0c52e7b713..bc4ac7db2a 100644 --- a/indra/newview/llinventorygallery.h +++ b/indra/newview/llinventorygallery.h @@ -166,6 +166,7 @@ public: void deleteSelection(); bool canDeleteSelection(); void pasteAsLink(); + void doCreate(const LLUUID& dest, const LLSD& userdata); void setSortOrder(U32 order, bool update = false); U32 getSortOrder() { return mSortOrder; }; diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 5f4b816b99..c8ac73b838 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -32,9 +32,11 @@ #include "llappearancemgr.h" #include "llavataractions.h" #include "llclipboard.h" +#include "llenvironment.h" #include "llfloaterreg.h" #include "llfloatersidepanelcontainer.h" #include "llfloaterworldmap.h" +#include "llfriendcard.h" #include "llinventorybridge.h" #include "llinventoryfunctions.h" #include "llinventorymodel.h" @@ -48,6 +50,41 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" + +void modify_outfit(BOOL append, const LLUUID& cat_id, LLInventoryModel* model) +{ + LLViewerInventoryCategory* cat = model->getCategory(cat_id); + if (!cat) return; + + // checking amount of items to wear + static LLCachedControl<U32> max_items(gSavedSettings, "WearFolderLimit", 125); + LLInventoryModel::cat_array_t cats; + LLInventoryModel::item_array_t items; + LLFindWearablesEx not_worn(/*is_worn=*/ false, /*include_body_parts=*/ false); + model->collectDescendentsIf(cat_id, + cats, + items, + LLInventoryModel::EXCLUDE_TRASH, + not_worn); + + if (items.size() > max_items()) + { + LLSD args; + args["AMOUNT"] = llformat("%d", static_cast<U32>(max_items)); + LLNotificationsUtil::add("TooManyWearables", args); + return; + } + if (model->isObjectDescendentOf(cat_id, gInventory.getRootFolderID())) + { + LLAppearanceMgr::instance().wearInventoryCategory(cat, FALSE, append); + } + else + { + // Library, we need to copy content first + LLAppearanceMgr::instance().wearInventoryCategory(cat, TRUE, append); + } +} + LLContextMenu* LLInventoryGalleryContextMenu::createMenu() { LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -57,11 +94,33 @@ LLContextMenu* LLInventoryGalleryContextMenu::createMenu() registrar.add("Inventory.FileUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::fileUploadLocation, this, _2)); registrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLFolderType::FT_TRASH)); registrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLFolderType::FT_LOST_AND_FOUND)); + registrar.add("Inventory.DoCreate", [this](LLUICtrl*, const LLSD& data) + { + if (mRootFolder) + { + mGallery->doCreate(mGallery->getRootFolder(), data); + } + else + { + mGallery->doCreate(mUUIDs.front(), data); + } + }); std::set<LLUUID> uuids(mUUIDs.begin(), mUUIDs.end()); registrar.add("Inventory.Share", boost::bind(&LLAvatarActions::shareWithAvatars, uuids, gFloaterView->getParentFloater(mGallery))); enable_registrar.add("Inventory.CanSetUploadLocation", boost::bind(&LLInventoryGalleryContextMenu::canSetUploadLocation, this, _2)); + enable_registrar.add("Inventory.EnvironmentEnabled", [](LLUICtrl*, const LLSD&) + { + return LLEnvironment::instance().isInventoryEnabled(); + }); + enable_registrar.add("Inventory.MaterialsEnabled", [](LLUICtrl*, const LLSD&) + { + std::string agent_url = gAgent.getRegionCapability("UpdateMaterialAgentInventory"); + std::string task_url = gAgent.getRegionCapability("UpdateMaterialTaskInventory"); + + return (!agent_url.empty() && !task_url.empty()); + }); LLContextMenu* menu = createFromFile("menu_gallery_inventory.xml"); @@ -186,6 +245,22 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata) { ungroup_folder_items(mUUIDs.front()); } + else if ("replaceoutfit" == action) + { + modify_outfit(FALSE, mUUIDs.front(), &gInventory); + } + else if ("addtooutfit" == action) + { + modify_outfit(TRUE, mUUIDs.front(), &gInventory); + } + else if ("removefromoutfit" == action) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(mUUIDs.front()); + if (cat) + { + LLAppearanceMgr::instance().takeOffOutfit(cat->getLinkedUUID()); + } + } else if ("take_off" == action || "detach" == action) { for (LLUUID& selected_id : mUUIDs) @@ -295,6 +370,54 @@ void LLInventoryGalleryContextMenu::doToSelected(const LLSD& userdata) preview_texture->saveAs(); } } + else if (("copy_to_marketplace_listings" == action) + || ("move_to_marketplace_listings" == action)) + { + LLViewerInventoryItem* itemp = gInventory.getItem(mUUIDs.front()); + bool copy_operation = "copy_to_marketplace_listings" == action; + bool can_copy = itemp ? itemp->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID()) : false; + + + if (can_copy) + { + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (itemp) + { + move_item_to_marketplacelistings(itemp, marketplacelistings_id, copy_operation); + } + } + else + { + uuid_vec_t lamdba_list = mUUIDs; + LLNotificationsUtil::add( + "ConfirmCopyToMarketplace", + LLSD(), + LLSD(), + [lamdba_list](const LLSD& notification, const LLSD& response) + { + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + // option == 0 Move no copy item(s) + // option == 1 Don't move no copy item(s) (leave them behind) + bool copy_and_move = option == 0; + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + + // main inventory only allows one item? + LLViewerInventoryItem* itemp = gInventory.getItem(lamdba_list.front()); + if (itemp) + { + if (itemp->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID(), gAgent.getGroupID())) + { + move_item_to_marketplacelistings(itemp, marketplacelistings_id, true); + } + else if (copy_and_move) + { + move_item_to_marketplacelistings(itemp, marketplacelistings_id, false); + } + } + } + ); + } + } } void LLInventoryGalleryContextMenu::rename(const LLUUID& item_id) @@ -388,6 +511,56 @@ bool is_inbox_folder(LLUUID item_id) return gInventory.isObjectDescendentOf(item_id, inbox_id); } +bool can_list_on_marketplace(const LLUUID &id) +{ + const LLInventoryObject* obj = gInventory.getObject(id); + bool can_list = (obj != NULL); + + if (can_list) + { + const LLUUID& object_id = obj->getLinkedUUID(); + can_list = object_id.notNull(); + + if (can_list) + { + std::string error_msg; + const LLUUID& marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (marketplacelistings_id.notNull()) + { + LLViewerInventoryCategory* master_folder = gInventory.getCategory(marketplacelistings_id); + LLInventoryCategory* cat = gInventory.getCategory(id); + if (cat) + { + can_list = can_move_folder_to_marketplace(master_folder, master_folder, cat, error_msg); + } + else + { + LLInventoryItem* item = gInventory.getItem(id); + can_list = (item ? can_move_item_to_marketplace(master_folder, master_folder, item, error_msg) : false); + } + } + else + { + can_list = false; + } + } + } + + return can_list; +} + +bool check_folder_for_contents_of_type(const LLUUID &id, LLInventoryModel* model, LLInventoryCollectFunctor& is_type) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t item_array; + model->collectDescendentsIf(id, + cat_array, + item_array, + LLInventoryModel::EXCLUDE_TRASH, + is_type); + return item_array.size() > 0; +} + void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* menu) { LLUUID selected_id = mUUIDs.front(); @@ -409,6 +582,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men bool is_in_trash = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH)); bool is_lost_and_found = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND)); bool is_outfits= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS)); + bool is_in_favorites = gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)); //bool is_favorites= (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE)); bool is_system_folder = false; @@ -456,6 +630,49 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men items.push_back(std::string("open_in_new_window")); items.push_back(std::string("Open Folder Separator")); } + + // wearables related functionality for folders. + LLFindWearables is_wearable; + LLIsType is_object(LLAssetType::AT_OBJECT); + LLIsType is_gesture(LLAssetType::AT_GESTURE); + + if (check_folder_for_contents_of_type(selected_id, &gInventory, is_wearable) + || check_folder_for_contents_of_type(selected_id, &gInventory, is_object) + || check_folder_for_contents_of_type(selected_id, &gInventory, is_gesture)) + { + // Only enable add/replace outfit for non-system folders. + if (!is_system_folder) + { + // Adding an outfit onto another (versus replacing) doesn't make sense. + if (folder_type != LLFolderType::FT_OUTFIT) + { + items.push_back(std::string("Add To Outfit")); + if (!LLAppearanceMgr::instance().getCanAddToCOF(selected_id)) + { + disabled_items.push_back(std::string("Add To Outfit")); + } + } + + items.push_back(std::string("Replace Outfit")); + if (!LLAppearanceMgr::instance().getCanReplaceCOF(selected_id)) + { + disabled_items.push_back(std::string("Replace Outfit")); + } + } + if (is_agent_inventory) + { + items.push_back(std::string("Folder Wearables Separator")); + // Note: If user tries to unwear "My Inventory", it's going to deactivate everything including gestures + // Might be safer to disable this for "My Inventory" + items.push_back(std::string("Remove From Outfit")); + if (folder_type != LLFolderType::FT_ROOT_INVENTORY // Unless COF is empty, whih shouldn't be, warrantied to have worn items + && !LLAppearanceMgr::getCanRemoveFromCOF(selected_id)) // expensive from root! + { + disabled_items.push_back(std::string("Remove From Outfit")); + } + } + items.push_back(std::string("Outfit Separator")); + } } else { @@ -503,11 +720,30 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } else { + if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits) + { + LLViewerInventoryCategory* category = gInventory.getCategory(selected_id); + if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category)) + { + items.push_back(std::string("New Folder")); + } + + items.push_back(std::string("create_new")); + items.push_back(std::string("New Script")); + items.push_back(std::string("New Note")); + items.push_back(std::string("New Gesture")); + items.push_back(std::string("New Material")); + items.push_back(std::string("New Clothes")); + items.push_back(std::string("New Body Parts")); + items.push_back(std::string("New Settings")); + } + if(can_share_item(selected_id)) { items.push_back(std::string("Share")); } - if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox_folder(selected_id)) + + if (LLClipboard::instance().hasContents() && is_agent_inventory && !is_cof && !is_inbox) { items.push_back(std::string("Paste")); @@ -519,7 +755,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men } if (is_folder && is_agent_inventory) { - if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox_folder(selected_id)) + if (!is_cof && (folder_type != LLFolderType::FT_OUTFIT) && !is_outfits && !is_inbox) { if (!gInventory.isObjectDescendentOf(selected_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD)) && !isRootFolder()) { @@ -706,6 +942,54 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men disabled_items.push_back(std::string("New Folder")); disabled_items.push_back(std::string("upload_def")); + disabled_items.push_back(std::string("create_new")); + } + + if (is_agent_inventory && !mRootFolder) + { + items.push_back(std::string("New folder from selected")); + items.push_back(std::string("Subfolder Separator")); + if (!is_only_items_selected(mUUIDs) && !is_only_cats_selected(mUUIDs)) + { + disabled_items.push_back(std::string("New folder from selected")); + } + } + + // Marketplace + bool can_list = false; + const LLUUID marketplacelistings_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MARKETPLACE_LISTINGS); + if (marketplacelistings_id.notNull() && !is_inbox && !obj->getIsLinkType()) + { + if (is_folder) + { + LLViewerInventoryCategory* cat = gInventory.getCategory(selected_id); + if (cat + && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) + && gInventory.isObjectDescendentOf(selected_id, gInventory.getRootFolderID())) + { + can_list = true; + } + } + else if (selected_item + && selected_item->getPermissions().allowOperationBy(PERM_TRANSFER, gAgent.getID()) + && selected_item->getPermissions().getOwner() != ALEXANDRIA_LINDEN_ID + && LLAssetType::AT_CALLINGCARD != selected_item->getType()) + { + can_list = true; + } + } + + if (can_list) + { + items.push_back(std::string("Marketplace Separator")); + items.push_back(std::string("Marketplace Copy")); + items.push_back(std::string("Marketplace Move")); + + if (!can_list_on_marketplace(selected_id)) + { + disabled_items.push_back(std::string("Marketplace Copy")); + disabled_items.push_back(std::string("Marketplace Move")); + } } } diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index ff33efe4aa..e3d887d943 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -39,11 +39,6 @@ LLProfileDropTarget::LLProfileDropTarget(const LLProfileDropTarget::Params& p) mAgentID(p.agent_id) {} -void LLProfileDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data) -{ - LL_INFOS() << "LLProfileDropTarget::doDrop()" << LL_ENDL; -} - BOOL LLProfileDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index f182660c8e..bfde921df0 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -59,8 +59,6 @@ public: LLProfileDropTarget(const Params&); ~LLProfileDropTarget() {} - void doDrop(EDragAndDropType cargo_type, void* cargo_data); - // // LLView functionality virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 82f880c9ee..54121c2656 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -89,8 +89,6 @@ public: LLGroupDropTarget(const Params&); ~LLGroupDropTarget() {}; - void doDrop(EDragAndDropType cargo_type, void* cargo_data); - // // LLView functionality virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, @@ -114,11 +112,6 @@ LLGroupDropTarget::LLGroupDropTarget(const LLGroupDropTarget::Params& p) mGroupID(p.group_id) {} -void LLGroupDropTarget::doDrop(EDragAndDropType cargo_type, void* cargo_data) -{ - LL_INFOS() << "LLGroupDropTarget::doDrop()" << LL_ENDL; -} - BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, void* cargo_data, diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 20241aac24..a5a768776a 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -56,6 +56,7 @@ #include "lltrans.h" #include "llviewermenu.h" #include "llviewertexturelist.h" +#include "llviewerinventory.h" #include "llsidepanelinventory.h" #include "llfolderview.h" #include "llradiogroup.h" diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index ffbed778c1..00fa3853f7 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -46,6 +46,7 @@ #include "lltexteditor.h" #include "lltexturectrl.h" #include "lltoggleablemenu.h" +#include "lltooldraganddrop.h" #include "llgrouplist.h" #include "llurlaction.h" @@ -1012,6 +1013,51 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key) mAvatarNameCacheConnection = LLAvatarNameCache::get(getAvatarId(), boost::bind(&LLPanelProfileSecondLife::onAvatarNameCache, this, _1, _2)); } + +BOOL LLPanelProfileSecondLife::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) +{ + // Try children first + if (LLPanelProfileTab::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg) + && *accept != ACCEPT_NO) + { + return TRUE; + } + + // No point sharing with own profile + if (getSelfProfile()) + { + return FALSE; + } + + // Exclude fields that look like they are editable. + S32 child_x = 0; + S32 child_y = 0; + if (localPointToOtherView(x, y, &child_x, &child_y, mDescriptionEdit) + && mDescriptionEdit->pointInView(child_x, child_y)) + { + return FALSE; + } + + if (localPointToOtherView(x, y, &child_x, &child_y, mGroupList) + && mGroupList->pointInView(child_x, child_y)) + { + return FALSE; + } + + // Share + LLToolDragAndDrop::handleGiveDragAndDrop(getAvatarId(), + LLUUID::null, + drop, + cargo_type, + cargo_data, + accept); + return TRUE; +} + void LLPanelProfileSecondLife::updateData() { LLUUID avatar_id = getAvatarId(); diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index 11632a10ae..45655cd67b 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -78,6 +78,12 @@ public: void onOpen(const LLSD& key) override; + BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, + EDragAndDropType cargo_type, + void* cargo_data, + EAcceptance* accept, + std::string& tooltip_msg) override; + /** * LLFriendObserver trigger */ diff --git a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml index d82c453e5f..feaba45cf8 100644 --- a/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_gallery_inventory.xml @@ -426,6 +426,234 @@ <menu_item_separator layout="topleft" name="Subfolder Separator" /> + <menu + label="Create new" + layout="topleft" + name="create_new"> + <menu_item_call + label="New Folder" + layout="topleft" + name="New Folder"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="category" /> + </menu_item_call> + <menu_item_call + label="New Script" + layout="topleft" + name="New Script"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="lsl" /> + </menu_item_call> + <menu_item_call + label="New Notecard" + layout="topleft" + name="New Note"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="notecard" /> + </menu_item_call> + <menu_item_call + label="New Gesture" + layout="topleft" + name="New Gesture"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="gesture" /> + </menu_item_call> + <menu_item_call + label="New Material" + layout="topleft" + name="New Material"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="material" /> + <menu_item_call.on_enable + function="Inventory.MaterialsEnabled" /> + </menu_item_call> + <menu + label="New Clothes" + layout="topleft" + name="New Clothes"> + <menu_item_call + label="New Shirt" + layout="topleft" + name="New Shirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shirt" /> + </menu_item_call> + <menu_item_call + label="New Pants" + layout="topleft" + name="New Pants"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="pants" /> + </menu_item_call> + <menu_item_call + label="New Shoes" + layout="topleft" + name="New Shoes"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shoes" /> + </menu_item_call> + <menu_item_call + label="New Socks" + layout="topleft" + name="New Socks"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="socks" /> + </menu_item_call> + <menu_item_call + label="New Jacket" + layout="topleft" + name="New Jacket"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="jacket" /> + </menu_item_call> + <menu_item_call + label="New Skirt" + layout="topleft" + name="New Skirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="skirt" /> + </menu_item_call> + <menu_item_call + label="New Gloves" + layout="topleft" + name="New Gloves"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="gloves" /> + </menu_item_call> + <menu_item_call + label="New Undershirt" + layout="topleft" + name="New Undershirt"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="undershirt" /> + </menu_item_call> + <menu_item_call + label="New Underpants" + layout="topleft" + name="New Underpants"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="underpants" /> + </menu_item_call> + <menu_item_call + label="New Alpha Mask" + layout="topleft" + name="New Alpha Mask"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="alpha" /> + </menu_item_call> + <menu_item_call + label="New Tattoo" + layout="topleft" + name="New Tattoo"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="tattoo" /> + </menu_item_call> + <menu_item_call + label="New Universal" + layout="topleft" + name="New Universal"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="universal" /> + </menu_item_call> + <menu_item_call + label="New Physics" + layout="topleft" + name="New Physics"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="physics" /> + </menu_item_call> + </menu> + <menu + label="New Body Parts" + layout="topleft" + name="New Body Parts"> + <menu_item_call + label="New Shape" + layout="topleft" + name="New Shape"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="shape" /> + </menu_item_call> + <menu_item_call + label="New Skin" + layout="topleft" + name="New Skin"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="skin" /> + </menu_item_call> + <menu_item_call + label="New Hair" + layout="topleft" + name="New Hair"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="hair" /> + </menu_item_call> + <menu_item_call + label="New Eyes" + layout="topleft" + name="New Eyes"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="eyes" /> + </menu_item_call> + </menu> + <menu + label="New Settings" + layout="topleft" + name="New Settings"> + <menu_item_call + label="New Sky" + layout="topleft" + name="New Sky"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="sky"/> + <menu_item_call.on_enable + function="Inventory.EnvironmentEnabled" /> + </menu_item_call> + <menu_item_call + label="New Water" + layout="topleft" + name="New Water"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="water"/> + <menu_item_call.on_enable + function="Inventory.EnvironmentEnabled" /> + </menu_item_call> + <menu_item_call + label="New Day Cycle" + layout="topleft" + name="New Day Cycle"> + <menu_item_call.on_click + function="Inventory.DoCreate" + parameter="daycycle"/> + <menu_item_call.on_enable + function="Inventory.EnvironmentEnabled" /> + </menu_item_call> + </menu> + </menu> <menu_item_call label="Create folder from selected" layout="topleft" |