diff options
| -rw-r--r-- | indra/newview/llinventorybridge.cpp | 199 | ||||
| -rw-r--r-- | indra/newview/llinventorybridge.h | 2 | ||||
| -rw-r--r-- | indra/newview/llinventorygallery.cpp | 57 | ||||
| -rw-r--r-- | indra/newview/llinventorygallerymenu.cpp | 8 | ||||
| -rw-r--r-- | indra/newview/llinventorymodel.cpp | 3 | ||||
| -rw-r--r-- | indra/newview/lloutfitslist.cpp | 3 | 
6 files changed, 202 insertions, 70 deletions
| diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8d31c4dde7..fd9d08a26d 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -105,6 +105,44 @@ static bool check_item(const LLUUID& item_id,  // Helper functions + +namespace { +    enum EMyOutfitsSubfolderType +    { +        MY_OUTFITS_NO, +        MY_OUTFITS_SUBFOLDER, +        MY_OUTFITS_OUTFIT, +    }; + +    EMyOutfitsSubfolderType myoutfit_object_subfolder_type(LLInventoryModel* model, const LLUUID& obj_id, +        const LLUUID& cat_id) +    { +        if (obj_id == cat_id) return MY_OUTFITS_NO; + +        const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id); +        while (test_cat) +        { +            if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) +            { +                return MY_OUTFITS_OUTFIT; +            } + +            const LLUUID& parent_id = test_cat->getParentUUID(); +            if (parent_id.isNull()) +            { +                return MY_OUTFITS_NO; +            } +            if (parent_id == cat_id) +            { +                return MY_OUTFITS_SUBFOLDER; +            } +            test_cat = model->getCategory(parent_id); +        } + +        return MY_OUTFITS_NO; +    } +} +  bool isAddAction(const std::string& action)  {      return ("wear" == action || "attach" == action || "activate" == action); @@ -2912,13 +2950,22 @@ bool LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,              if (mUUID == my_outifts_id)              { -                // Category can contains objects, +                // Category can't contains objects,                  // create a new folder and populate it with links to original objects                  dropToMyOutfits(inv_cat, cb);              } -            else if (getCategory() && getCategory()->getParentUUID() == my_outifts_id) +            else if (move_is_into_my_outfits)              { -                dropToMyOutfitsSubfolder(inv_cat, mUUID, cb); +                EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); +                if (res == MY_OUTFITS_SUBFOLDER) +                { +                    // turn it into outfit +                    dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_OUTFIT, cb); +                } +                else +                { +                    dropToMyOutfitsSubfolder(inv_cat, mUUID, LLFolderType::FT_NONE, cb); +                }              }              // if target is current outfit folder we use link              else if (move_is_into_current_outfit && @@ -4012,6 +4059,7 @@ void LLFolderBridge::perform_pasteFromClipboard()                  {                      if (!move_is_into_my_outfits && item && can_move_to_outfit(item, move_is_into_current_outfit))                      { +                        // todo: this is going to create dupplicate folders?                          dropToOutfit(item, move_is_into_current_outfit, cb);                      }                      else if (move_is_into_my_outfits && LLAssetType::AT_CATEGORY == obj->getType()) @@ -4024,9 +4072,18 @@ void LLFolderBridge::perform_pasteFromClipboard()                              {                                  dropToMyOutfits(cat, cb);                              } -                            else if (getCategory() && getCategory()->getParentUUID() == mUUID) +                            else if (move_is_into_my_outfits)                              { -                                dropToMyOutfitsSubfolder(cat, mUUID, cb); +                                EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); +                                if (res == MY_OUTFITS_SUBFOLDER) +                                { +                                    // turn it into outfit +                                    dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_OUTFIT, cb); +                                } +                                else +                                { +                                    dropToMyOutfitsSubfolder(cat, mUUID, LLFolderType::FT_NONE, cb); +                                }                              }                          }                          else @@ -4361,63 +4418,85 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t&   items      else if(isAgentInventory()) // do not allow creating in library      {          LLViewerInventoryCategory *cat = getCategory(); -        // BAP removed protected check to re-enable standard ops in untyped folders. -        // Not sure what the right thing is to do here. -        if (!isCOFFolder() && cat && (cat->getPreferredType() != LLFolderType::FT_OUTFIT)) -        { -            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()) -                { -                    items.push_back(std::string("upload_def")); -                    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 (!LLEnvironment::instance().isInventoryEnabled()) -                    { -                        disabled_items.push_back("New Settings"); -                    } -                } -                else -                { -                    items.push_back(std::string("New Listing Folder")); -                } -                if (menu_items_added) -                { -                    items.push_back(std::string("Create Separator")); -                } -            } -            getClipboardEntries(false, items, disabled_items, flags); -        } -        else + +        if (cat)          { -            // Want some but not all of the items from getClipboardEntries for outfits. -            if (cat && (cat->getPreferredType() == LLFolderType::FT_OUTFIT)) +            if (cat->getPreferredType() == LLFolderType::FT_OUTFIT)              { +                // Want some but not all of the items from getClipboardEntries for outfits. +                items.push_back(std::string("New Outfit Folder"));                  items.push_back(std::string("Rename"));                  items.push_back(std::string("thumbnail"));                  addDeleteContextMenuOptions(items, disabled_items);                  // EXT-4030: disallow deletion of currently worn outfit -                const LLViewerInventoryItem *base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink(); +                const LLViewerInventoryItem* base_outfit_link = LLAppearanceMgr::instance().getBaseOutfitLink();                  if (base_outfit_link && (cat == base_outfit_link->getLinkedCategory()))                  {                      disabled_items.push_back(std::string("Delete"));                  }              } +            else if (outfits_id == mUUID) +            { +                getClipboardEntries(false, items, disabled_items, flags); +            } +            else if (!isCOFFolder()) +            { +                EMyOutfitsSubfolderType in_my_outfits = myoutfit_object_subfolder_type(model, mUUID, outfits_id); +                if (in_my_outfits != MY_OUTFITS_NO) +                { +                    if (in_my_outfits == MY_OUTFITS_SUBFOLDER) +                    { +                        // Not inside an outfit, but inside 'my outfits' +                        items.push_back(std::string("New Outfit")); +                    } + +                    items.push_back(std::string("New Outfit Folder")); +                    items.push_back(std::string("Rename")); +                    items.push_back(std::string("thumbnail")); + +                    addDeleteContextMenuOptions(items, disabled_items); +                } +                else +                { +                    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()) +                        { +                            items.push_back(std::string("upload_def")); +                            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 (!LLEnvironment::instance().isInventoryEnabled()) +                            { +                                disabled_items.push_back("New Settings"); +                            } +                        } +                        else +                        { +                            items.push_back(std::string("New Listing Folder")); +                        } +                        if (menu_items_added) +                        { +                            items.push_back(std::string("Create Separator")); +                        } +                    } +                    getClipboardEntries(false, items, disabled_items, flags); +                } +            }          }          if (model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT) == mUUID) @@ -4570,7 +4649,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags,   menuentry_vec_t&          if (((flags & ITEM_IN_MULTI_SELECTION) == 0) && hasChildren() && (type != LLFolderType::FT_OUTFIT))          { -            items.push_back(std::string("Ungroup folder items")); +            const LLUUID my_outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); +            if (!gInventory.isObjectDescendentOf(mUUID, my_outfits)) +            { +                items.push_back(std::string("Ungroup folder items")); +            }          }      }      else @@ -5350,7 +5433,7 @@ void LLFolderBridge::dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLI                                   inv_cat->getThumbnailUUID());  } -void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLPointer<LLInventoryCallback> cb) +void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type, LLPointer<LLInventoryCallback> cb)  {      LLViewerInventoryCategory* cat = getInventoryModel()->getCategory(dest_id);      const LLUUID outfits_id = getInventoryModel()->findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); @@ -5358,7 +5441,7 @@ void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, cons      if (cat && cat->getParentUUID() == outfits_id)      {          getInventoryModel()->createNewCategory(dest_id, -            LLFolderType::FT_OUTFIT, +            preferred_type,              inv_cat->getName(),              func,              inv_cat->getThumbnailUUID()); @@ -5366,7 +5449,7 @@ void LLFolderBridge::dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, cons      else      {          getInventoryModel()->createNewCategory(outfits_id, -            LLFolderType::FT_OUTFIT, +            preferred_type,              inv_cat->getName(),              func,              inv_cat->getThumbnailUUID()); @@ -5476,10 +5559,6 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,      const bool move_is_into_favorites = (mUUID == favorites_id);      const bool move_is_into_my_outfits = (mUUID == my_outifts_id) || model->isObjectDescendentOf(mUUID, my_outifts_id);      const bool move_is_into_outfit = move_is_into_my_outfits || (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); -    const bool move_is_into_my_outfits_subfolder = move_is_into_my_outfits -                                                   && getCategory() -                                                   && getCategory()->getParentUUID() == my_outifts_id -                                                   && getCategory()->getPreferredType() != LLFolderType::FT_OUTFIT;      const bool move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id);      const bool move_is_into_marketplacelistings = model->isObjectDescendentOf(mUUID, marketplacelistings_id);      const bool move_is_from_marketplacelistings = model->isObjectDescendentOf(inv_item->getUUID(), marketplacelistings_id); @@ -5550,7 +5629,9 @@ bool LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,          }          else if (user_confirm && (move_is_into_current_outfit || move_is_into_outfit))          { -            accept = !move_is_into_my_outfits_subfolder && can_move_to_outfit(inv_item, move_is_into_current_outfit); +            EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, mUUID, my_outifts_id); +            // don't allow items in my outfits' subfodlers, only in outfits and outfit's subfolders +            accept = res != MY_OUTFITS_SUBFOLDER && can_move_to_outfit(inv_item, move_is_into_current_outfit);          }          else if (user_confirm && (move_is_into_favorites || move_is_into_landmarks))          { diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index b7bdef9b21..a101c7368a 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -369,7 +369,7 @@ protected:      void dropToFavorites(LLInventoryItem* inv_item, LLPointer<LLInventoryCallback> cb = NULL);      void dropToOutfit(LLInventoryItem* inv_item, bool move_is_into_current_outfit, LLPointer<LLInventoryCallback> cb = NULL);      void dropToMyOutfits(LLInventoryCategory* inv_cat, LLPointer<LLInventoryCallback> cb = NULL); -    void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLPointer<LLInventoryCallback> cb = NULL); +    void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest, LLFolderType::EType preferred_type, LLPointer<LLInventoryCallback> cb = NULL);      //--------------------------------------------------------------------      // Messy hacks for handling folder options diff --git a/indra/newview/llinventorygallery.cpp b/indra/newview/llinventorygallery.cpp index 6188b812d5..15bc578c64 100644 --- a/indra/newview/llinventorygallery.cpp +++ b/indra/newview/llinventorygallery.cpp @@ -60,11 +60,49 @@ static LLPanelInjector<LLInventoryGallery> t_inventory_gallery("inventory_galler  const S32 GALLERY_ITEMS_PER_ROW_MIN = 2;  const S32 FAST_LOAD_THUMBNAIL_TRSHOLD = 50; // load folders below this value immediately + +namespace { +    enum EMyOutfitsSubfolderType +    { +        MY_OUTFITS_NO, +        MY_OUTFITS_SUBFOLDER, +        MY_OUTFITS_OUTFIT, +    }; + +    EMyOutfitsSubfolderType myoutfit_object_subfolder_type(LLInventoryModel* model, const LLUUID& obj_id, +        const LLUUID& cat_id) +    { +        if (obj_id == cat_id) return MY_OUTFITS_NO; + +        const LLViewerInventoryCategory* test_cat = model->getCategory(obj_id); +        while (test_cat) +        { +            if (test_cat->getPreferredType() == LLFolderType::FT_OUTFIT) +            { +                return MY_OUTFITS_OUTFIT; +            } + +            const LLUUID& parent_id = test_cat->getParentUUID(); +            if (parent_id.isNull()) +            { +                return MY_OUTFITS_NO; +            } +            if (parent_id == cat_id) +            { +                return MY_OUTFITS_SUBFOLDER; +            } +            test_cat = model->getCategory(parent_id); +        } + +        return MY_OUTFITS_NO; +    } +} +  // Helper dnd functions  bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat, bool drop, std::string& tooltip_msg, bool is_link);  bool dragItemIntoFolder(LLUUID folder_id, LLInventoryItem* inv_item, bool drop, std::string& tooltip_msg, bool user_confirm);  void dropToMyOutfits(LLInventoryCategory* inv_cat); -void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id); +void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID& dest_id, LLFolderType::EType preferred_type);  class LLGalleryPanel: public LLPanel  { @@ -3899,9 +3937,18 @@ bool dragCategoryIntoFolder(LLUUID dest_id, LLInventoryCategory* inv_cat,                  // create a new folder and populate it with links to original objects                  dropToMyOutfits(inv_cat);              } -            else if (dest_cat && dest_cat->getParentUUID() == my_outifts_id) +            else if (move_is_into_my_outfits)              { -                dropToMyOutfitsSubfolder(inv_cat, dest_id); +                EMyOutfitsSubfolderType res = myoutfit_object_subfolder_type(model, dest_id, my_outifts_id); +                if (res == MY_OUTFITS_SUBFOLDER) +                { +                    // turn it into outfit +                    dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_OUTFIT); +                } +                else +                { +                    dropToMyOutfitsSubfolder(inv_cat, dest_id, LLFolderType::FT_NONE); +                }              }              // if target is current outfit folder we use link              else if (move_is_into_current_outfit && @@ -4047,10 +4094,10 @@ void dropToMyOutfits(LLInventoryCategory* inv_cat)      gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID());  } -void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id) +void dropToMyOutfitsSubfolder(LLInventoryCategory* inv_cat, const LLUUID &dest_id, LLFolderType::EType preferred_type)  {      // Note: creation will take time, so passing folder id to callback is slightly unreliable,      // but so is collecting and passing descendants' ids      inventory_func_type func = boost::bind(&outfitFolderCreatedCallback, inv_cat->getUUID(), _1); -    gInventory.createNewCategory(dest_id, LLFolderType::FT_OUTFIT, inv_cat->getName(), func, inv_cat->getThumbnailUUID()); +    gInventory.createNewCategory(dest_id, preferred_type, inv_cat->getName(), func, inv_cat->getThumbnailUUID());  } diff --git a/indra/newview/llinventorygallerymenu.cpp b/indra/newview/llinventorygallerymenu.cpp index 25b339d51e..3ef5071c97 100644 --- a/indra/newview/llinventorygallerymenu.cpp +++ b/indra/newview/llinventorygallerymenu.cpp @@ -586,7 +586,9 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men      bool is_trash = (selected_id == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH));      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)); +    const LLUUID my_outfits = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); +    bool is_outfits= (selected_id == my_outfits); +    bool is_in_outfits = is_outfits || gInventory.isObjectDescendentOf(selected_id, 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)); @@ -725,7 +727,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men      }      else      { -        if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits) +        if (is_agent_inventory && !is_inbox && !is_cof && !is_in_favorites && !is_outfits && !is_in_outfits)          {              LLViewerInventoryCategory* category = gInventory.getCategory(selected_id);              if (!category || !LLFriendCardsManager::instance().isCategoryInFriendFolder(category)) @@ -778,7 +780,7 @@ void LLInventoryGalleryContextMenu::updateMenuItemsVisibility(LLContextMenu* men              items.push_back(std::string("Subfolder Separator"));              if (!is_system_folder && !isRootFolder())              { -                if(has_children && (folder_type != LLFolderType::FT_OUTFIT)) +                if(has_children && (folder_type != LLFolderType::FT_OUTFIT) && !is_in_outfits)                  {                      items.push_back(std::string("Ungroup folder items"));                  } diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 9fffe6378e..6f4d2db12e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1007,7 +1007,8 @@ void LLInventoryModel::createNewCategory(const LLUUID& parent_id,          return;      } -    if (preferred_type != LLFolderType::FT_NONE) +    if (preferred_type != LLFolderType::FT_NONE +        && preferred_type != LLFolderType::FT_OUTFIT)      {          // Ultimately this should only be done for non-singleton          // types. Requires back-end changes to guarantee that others diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index cfbfe8f8e0..9d8493549d 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -845,7 +845,8 @@ public:                      LLInventoryModel::cat_array_t* cats;                      LLInventoryModel::item_array_t* items;                      gInventory.getDirectDescendentsOf(inv_cat->getUUID(), cats, items); -                    if (items->size() > 3) // eyes, skin, hair and shape are required +                    if (cats->empty() // protection against outfits inside +                        && items->size() > 3) // eyes, skin, hair and shape are required                      {                          // For now assume this to be an old style outfit, not a subfolder                          // but ideally no such 'outfits' should be left in My Outfits | 
