summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/foldertypes.xml58
-rw-r--r--indra/newview/llfloaterinventory.cpp28
-rw-r--r--indra/newview/llfloaterproperties.cpp1
-rw-r--r--indra/newview/llfolderview.cpp41
-rw-r--r--indra/newview/llfolderview.h3
-rw-r--r--indra/newview/llfolderviewitem.cpp2
-rw-r--r--indra/newview/llfolderviewitem.h14
-rw-r--r--indra/newview/llinventorybridge.cpp257
-rw-r--r--indra/newview/llinventorybridge.h26
-rw-r--r--indra/newview/llinventorymodel.cpp35
-rw-r--r--indra/newview/llinventorymodel.h6
-rw-r--r--indra/newview/lltooldraganddrop.cpp10
-rw-r--r--indra/newview/llviewerinventory.cpp14
-rw-r--r--indra/newview/llviewerinventory.h1
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml101
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
17 files changed, 523 insertions, 78 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 5dec4a8688..d06571fb7a 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -211,6 +211,7 @@ set(viewer_SOURCE_FILES
llfloaterwater.cpp
llfloaterwindlight.cpp
llfloaterworldmap.cpp
+ llfoldertype.cpp
llfolderview.cpp
llfolderviewitem.cpp
llfollowcam.cpp
@@ -646,6 +647,7 @@ set(viewer_HEADER_FILES
llfloaterwater.h
llfloaterwindlight.h
llfloaterworldmap.h
+ llfoldertype.h
llfolderview.h
llfoldervieweventlistener.h
llfolderviewitem.h
diff --git a/indra/newview/app_settings/foldertypes.xml b/indra/newview/app_settings/foldertypes.xml
new file mode 100644
index 0000000000..4d4d479bdd
--- /dev/null
+++ b/indra/newview/app_settings/foldertypes.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<ensemble_defs>
+ <ensemble
+ asset_num="-1"
+ xui_name="default"
+ icon_name="inv_plain_closed.tga"
+ />
+ <ensemble
+ asset_num="27"
+ xui_name="head"
+ icon_name="inv_folder_outfit_head.tga"
+ />
+ <ensemble
+ asset_num="28"
+ xui_name="gloves"
+ icon_name="inv_folder_outfit_gloves.tga"
+ />
+ <ensemble
+ asset_num="29"
+ xui_name="jacket"
+ icon_name="inv_folder_outfit_jacket.tga"
+ />
+ <ensemble
+ asset_num="30"
+ xui_name="pants"
+ icon_name="inv_folder_outfit_pants.tga"
+ />
+ <ensemble
+ asset_num="31"
+ xui_name="shape"
+ icon_name="inv_folder_outfit_shape.tga"
+ />
+ <ensemble
+ asset_num="32"
+ xui_name="shoes"
+ icon_name="inv_folder_outfit_shoes.tga"
+ />
+ <ensemble
+ asset_num="33"
+ xui_name="shirt"
+ icon_name="inv_folder_outfit_shirt.tga"
+ />
+ <ensemble
+ asset_num="34"
+ xui_name="skirt"
+ icon_name="inv_folder_outfit_skirt.tga"
+ />
+ <ensemble
+ asset_num="35"
+ xui_name="underpants"
+ icon_name="inv_folder_outfit_underpants.tga"
+ />
+ <ensemble
+ asset_num="36"
+ xui_name="undershirt"
+ icon_name="inv_folder_outfit_undershirt.tga"
+ />
+</ensemble_defs>
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index d326e0e970..d05a32dc88 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -1533,12 +1533,14 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
<< ((S32) objectp->getType())
<< " (shouldn't happen)" << llendl;
}
- else if (objectp->getType() == LLAssetType::AT_CATEGORY) // build new view for category
+ else if (objectp->getType() == LLAssetType::AT_CATEGORY &&
+ objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)
{
LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
- LLInventoryType::IT_CATEGORY,
- this,
- objectp->getUUID());
+ objectp->getType(),
+ LLInventoryType::IT_CATEGORY,
+ this,
+ objectp->getUUID());
if (new_listener)
{
@@ -1553,15 +1555,17 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
itemp = folderp;
}
}
- else // build new view for item
+ else
{
+ // Build new view for item
LLInventoryItem* item = (LLInventoryItem*)objectp;
- LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(
- item->getType(),
- item->getInventoryType(),
- this,
- item->getUUID(),
- item->getFlags());
+ LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(item->getType(),
+ item->getActualType(),
+ item->getInventoryType(),
+ this,
+ item->getUUID(),
+ item->getFlags());
+
if (new_listener)
{
LLFolderViewItem::Params params;
@@ -1591,7 +1595,7 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
}
}
if ((id.isNull() ||
- (objectp && objectp->getType() == LLAssetType::AT_CATEGORY)))
+ (objectp && objectp->getType() == LLAssetType::AT_CATEGORY)))
{
LLViewerInventoryCategory::cat_array_t* categories;
LLViewerInventoryItem::item_array_t* items;
diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp
index efc273c6e5..ca7c929d74 100644
--- a/indra/newview/llfloaterproperties.cpp
+++ b/indra/newview/llfloaterproperties.cpp
@@ -658,6 +658,7 @@ void LLFloaterProperties::onCommitName(LLUICtrl* ctrl, void* data)
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
+ gInventory.updateLinkedObjects(new_item->getUUID());
gInventory.notifyObservers();
}
else
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 6ef011f1de..c54eafb67a 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -34,10 +34,12 @@
#include "llfolderview.h"
+#include "llagent.h"
#include "llcallbacklist.h"
#include "llinventorybridge.h"
#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
#include "llinventoryfilter.h"
+#include "llfoldertype.h"
#include "llfloaterinventory.h"// hacked in for the bonus context menu items.
#include "llkeyboard.h"
#include "lllineeditor.h"
@@ -1094,6 +1096,35 @@ void LLFolderView::propertiesSelectedItems( void )
}
}
+void LLFolderView::changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type)
+{
+ LLFolderBridge *folder_bridge = LLFolderBridge::sSelf;
+
+ if (!folder_bridge) return;
+ LLViewerInventoryCategory *cat = folder_bridge->getCategory();
+ if (!cat) return;
+
+ const LLUUID &folder_id = cat->getUUID();
+ const LLUUID &parent_id = cat->getParentUUID();
+ const std::string &name = cat->getName();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_UpdateInventoryFolder);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_FolderData);
+ msg->addUUIDFast(_PREHASH_FolderID, folder_id);
+ msg->addUUIDFast(_PREHASH_ParentID, parent_id);
+ msg->addS8Fast(_PREHASH_Type, new_folder_type);
+ msg->addStringFast(_PREHASH_Name, name);
+ gAgent.sendReliableMessage();
+
+ cat->setPreferredType(new_folder_type);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
+ gInventory.updateLinkedObjects(folder_id);
+}
+
void LLFolderView::autoOpenItem( LLFolderViewFolder* item )
{
if (mAutoOpenItems.check() == item || mAutoOpenItems.getDepth() >= (U32)AUTO_OPEN_STACK_DEPTH)
@@ -1904,6 +1935,16 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)
LLInventoryClipboard::instance().reset();
}
+ static const std::string change_folder_string = "change_folder_type_";
+ if (action.length() > change_folder_string.length() &&
+ (action.compare(0,change_folder_string.length(),"change_folder_type_") == 0))
+ {
+ LLAssetType::EType new_folder_type = LLFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length()));
+ changeType(model, new_folder_type);
+ return true;
+ }
+
+
std::set<LLUUID> selected_items;
getSelectionList(selected_items);
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index d944a4fa18..8d9d52cd17 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -190,6 +190,9 @@ public:
void openSelectedItems( void );
void propertiesSelectedItems( void );
+ // change the folder type
+ void changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type);
+
void autoOpenItem(LLFolderViewFolder* item);
void closeAutoOpenedFolders();
BOOL autoOpenTest(LLFolderViewFolder* item);
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 7032e86958..43f3ea8d8f 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -230,7 +230,7 @@ void LLFolderViewItem::refreshFromListener()
// *TODO: to be removed when database supports multi language. This is a
// temporary attempt to display the inventory folder in the user locale.
- if (preferred_type != LLAssetType::AT_NONE)
+ if (LLAssetType::lookupIsProtectedCategoryType(preferred_type))
{
mLabel = LLTrans::getString("InvFolder " + mLabel);
};
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 57807005c2..31866c83c8 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -157,13 +157,6 @@ protected:
BOOL mIsLoading;
LLTimer mTimeSinceRequestStart;
- // This function clears the currently selected item, and records
- // the specified selected item appropriately for display and use
- // in the UI. If open is TRUE, then folders are opened up along
- // the way to the selection.
- void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
- BOOL take_keyboard_focus = TRUE);
-
// helper function to change the selection from the root.
void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
@@ -176,6 +169,13 @@ protected:
virtual BOOL addFolder(LLFolderViewFolder*) { return FALSE; }
public:
+ // This function clears the currently selected item, and records
+ // the specified selected item appropriately for display and use
+ // in the UI. If open is TRUE, then folders are opened up along
+ // the way to the selection.
+ void setSelectionFromRoot(LLFolderViewItem* selection, BOOL openitem,
+ BOOL take_keyboard_focus = TRUE);
+
// This function is called when the folder view is dirty. It's
// implemented here but called by derived classes when folding the
// views.
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index b705543e44..edbeed2aa4 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -51,6 +51,7 @@
#include "llviewercontrol.h"
#include "llfirstuse.h"
+#include "llfoldertype.h"
#include "llfloaterchat.h"
#include "llfloatercustomize.h"
#include "llfloaterproperties.h"
@@ -604,7 +605,7 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
if(obj)
{
- *type = LLAssetType::lookupDragAndDropType(obj->getType());
+ *type = LLAssetType::lookupDragAndDropType(obj->getActualType());
if(*type == DAD_NONE)
{
return FALSE;
@@ -653,11 +654,11 @@ BOOL LLInvFVBridge::isLinkedObjectInTrash() const
{
if (isInTrash()) return TRUE;
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- LLInventoryObject *obj = model->getObject(mUUID);
+ LLInventoryObject *obj = getInventoryObject();
if (obj && LLAssetType::lookupIsLinkType(obj->getActualType()))
{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
const LLUUID& trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
}
@@ -735,6 +736,7 @@ const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
}
LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
const LLUUID& uuid,
@@ -833,12 +835,22 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
break;
case LLAssetType::AT_CATEGORY:
case LLAssetType::AT_ROOT_CATEGORY:
+ if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
+ {
+ // Create a link folder handler instead.
+ new_listener = new LLLinkFolderBridge(inventory, uuid);
+ break;
+ }
new_listener = new LLFolderBridge(inventory, uuid);
break;
case LLAssetType::AT_LINK:
// Only should happen for broken links.
new_listener = new LLLinkItemBridge(inventory, uuid);
break;
+ case LLAssetType::AT_LINK_FOLDER:
+ // Only should happen for broken links.
+ new_listener = new LLLinkItemBridge(inventory, uuid);
+ break;
default:
llinfos << "Unhandled asset type (llassetstorage.h): "
<< (S32)asset_type << llendl;
@@ -875,6 +887,10 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ }
if ("open" == action)
{
openItem();
@@ -1005,6 +1021,19 @@ void LLItemBridge::restoreToWorld()
}
}
+void LLItemBridge::gotoItem(LLFolderView *folder)
+{
+ LLInventoryObject *obj = getInventoryObject();
+ if (obj && LLAssetType::lookupIsLinkType(obj->getActualType()))
+ {
+ LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
+ if (active_panel)
+ {
+ active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
+ }
+ }
+}
+
LLUIImagePtr LLItemBridge::getIcon() const
{
return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
@@ -1075,7 +1104,8 @@ std::string LLItemBridge::getLabelSuffix() const
static std::string NO_COPY =LLTrans::getString("no_copy");
static std::string NO_MOD = LLTrans::getString("no_modify");
static std::string NO_XFER = LLTrans::getString("no_transfer");
-
+ static std::string LINK = LLTrans::getString("link");
+ static std::string BROKEN_LINK = LLTrans::getString("broken_link");
std::string suffix;
LLInventoryItem* item = getItem();
if(item)
@@ -1084,8 +1114,10 @@ std::string LLItemBridge::getLabelSuffix() const
if(LLAssetType::AT_CALLINGCARD != item->getType()
&& item->getPermissions().getOwner() == gAgent.getID())
{
- BOOL link = (item->getActualType() == LLAssetType::AT_LINK);
- const char* LINK = " (link)"; // *TODO: Seraph translate
+ BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
+ if (broken_link) return BROKEN_LINK;
+
+ BOOL link = LLAssetType::lookupIsLinkType(item->getActualType());
if (link) return LINK;
BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
@@ -1146,7 +1178,7 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)
buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
- renameLinkedItems(item->getUUID(),new_name);
+ model->updateLinkedObjects(item->getUUID());
model->notifyObservers();
}
@@ -1204,7 +1236,7 @@ BOOL LLItemBridge::isItemCopyable() const
// All items can be copied, not all can be pasted.
// The only time an item can't be copied is if it's a link
// return (item->getPermissions().allowCopyBy(gAgent.getID()));
- if (item->getActualType() == LLAssetType::AT_LINK)
+ if (LLAssetType::lookupIsLinkType(item->getActualType()))
{
return FALSE;
}
@@ -1259,7 +1291,7 @@ BOOL LLFolderBridge::isItemMovable()
LLInventoryObject* obj = getInventoryObject();
if(obj)
{
- return (LLAssetType::AT_NONE == ((LLInventoryCategory*)obj)->getPreferredType());
+ return (!LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)obj)->getPreferredType()));
}
return FALSE;
}
@@ -1295,7 +1327,7 @@ BOOL LLFolderBridge::isItemRemovable()
return FALSE;
}
- if( LLAssetType::AT_NONE != category->getPreferredType() )
+ if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
{
return FALSE;
}
@@ -1308,7 +1340,7 @@ BOOL LLFolderBridge::isItemRemovable()
for( i = 0; i < descendent_categories.count(); i++ )
{
LLInventoryCategory* category = descendent_categories[i];
- if( LLAssetType::AT_NONE != category->getPreferredType() )
+ if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
{
return FALSE;
}
@@ -1403,7 +1435,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
BOOL move_is_into_trash = (mUUID == trash_id)
|| model->isObjectDescendentOf(mUUID, trash_id);
- BOOL is_movable = (LLAssetType::AT_NONE == inv_cat->getPreferredType());
+ BOOL is_movable = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType()));
if( is_movable )
{
gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
@@ -1411,7 +1443,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
for( i = 0; i < descendent_categories.count(); i++ )
{
LLInventoryCategory* category = descendent_categories[i];
- if( LLAssetType::AT_NONE != category->getPreferredType() )
+ if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
{
// ...can't move "special folders" like Textures
is_movable = FALSE;
@@ -1868,7 +1900,7 @@ void LLFolderBridge::openItem()
BOOL LLFolderBridge::isItemRenameable() const
{
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
- if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE)
+ if(cat && !LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())
&& (cat->getOwnerID() == gAgent.getID()))
{
return TRUE;
@@ -1904,13 +1936,26 @@ LLAssetType::EType LLFolderBridge::getPreferredType() const
// Icons for folders are based on the preferred type
LLUIImagePtr LLFolderBridge::getIcon() const
{
- const char* control = NULL;
LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
preferred_type = cat->getPreferredType();
}
+ return getIcon(preferred_type);
+}
+
+LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type)
+{
+ if (preferred_type >= LLAssetType::AT_FOLDER_ENSEMBLE_START &&
+ preferred_type <= LLAssetType::AT_FOLDER_ENSEMBLE_END)
+ {
+ LLUIImage* icon = LLUI::getUIImage(LLFolderType::lookupIconName(preferred_type));
+ if (icon)
+ return icon;
+ }
+
+ const char* control = NULL;
switch(preferred_type)
{
case LLAssetType::AT_TEXTURE:
@@ -1984,7 +2029,7 @@ BOOL LLFolderBridge::renameItem(const std::string& new_name)
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
- renameLinkedItems(cat->getUUID(),new_name);
+ model->updateLinkedObjects(cat->getUUID());
model->notifyObservers();
}
@@ -2066,15 +2111,24 @@ void LLFolderBridge::pasteLinkFromClipboard()
LLInventoryModel* model = getInventoryModel();
if(model)
{
- LLInventoryItem* item = NULL;
LLDynamicArray<LLUUID> objects;
LLInventoryClipboard::instance().retrieve(objects);
S32 count = objects.count();
LLUUID parent_id(mUUID);
for(S32 i = 0; i < count; i++)
{
- item = model->getItem(objects.get(i));
- if (item)
+ const LLUUID &object_id = objects.get(i);
+ if (LLInventoryCategory *cat = model->getCategory(object_id))
+ {
+ link_inventory_item(
+ gAgent.getID(),
+ cat->getUUID(),
+ parent_id,
+ cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else if (LLInventoryItem *item = model->getItem(object_id))
{
link_inventory_item(
gAgent.getID(),
@@ -2103,7 +2157,7 @@ void LLFolderBridge::folderOptionsMenu()
const LLInventoryCategory* category = model->getCategory(mUUID);
bool is_default_folder = category &&
- (LLAssetType::AT_NONE != category->getPreferredType());
+ (LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()));
// calling card related functionality for folders.
@@ -2199,7 +2253,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
mItems.push_back(std::string("New Gesture"));
mItems.push_back(std::string("New Clothes"));
mItems.push_back(std::string("New Body Parts"));
+ mItems.push_back(std::string("Change Type"));
+ LLViewerInventoryCategory *cat = getCategory();
+ if (cat && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
+ {
+ mDisabledItems.push_back(std::string("Change Type"));
+ }
+
getClipboardEntries(false, mItems, mDisabledItems, flags);
//Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
@@ -2268,26 +2329,27 @@ BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
BOOL accept = FALSE;
switch(cargo_type)
{
- case DAD_TEXTURE:
- case DAD_SOUND:
- case DAD_CALLINGCARD:
- case DAD_LANDMARK:
- case DAD_SCRIPT:
- case DAD_OBJECT:
- case DAD_NOTECARD:
- case DAD_CLOTHING:
- case DAD_BODYPART:
- case DAD_ANIMATION:
- case DAD_GESTURE:
- accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
- drop);
- break;
- case DAD_CATEGORY:
- accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data,
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_CALLINGCARD:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_CLOTHING:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ case DAD_LINK:
+ accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
drop);
- break;
- default:
- break;
+ break;
+ case DAD_CATEGORY:
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data,
+ drop);
+ break;
+ default:
+ break;
}
return accept;
}
@@ -2490,14 +2552,14 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
BOOL is_movable = TRUE;
- switch( inv_item->getType() )
+ switch( inv_item->getActualType() )
{
case LLAssetType::AT_ROOT_CATEGORY:
is_movable = FALSE;
break;
case LLAssetType::AT_CATEGORY:
- is_movable = ( LLAssetType::AT_NONE == ((LLInventoryCategory*)inv_item)->getPreferredType() );
+ is_movable = !LLAssetType::lookupIsProtectedCategoryType(((LLInventoryCategory*)inv_item)->getPreferredType());
break;
default:
break;
@@ -2511,11 +2573,11 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
{
case LLAssetType::AT_CLOTHING:
case LLAssetType::AT_BODYPART:
- is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID());
+ is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID(), TRUE);
break;
case LLAssetType::AT_OBJECT:
- is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
+ is_movable = !avatar->isWearingAttachment(inv_item->getUUID(), TRUE);
break;
default:
break;
@@ -3435,7 +3497,7 @@ LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
}
LLInventoryItem* item = getItem();
- if (item->getActualType() == LLAssetType::AT_LINK)
+ if (LLAssetType::lookupIsLinkType(item->getActualType()))
{
font |= LLFontGL::ITALIC;
}
@@ -3533,13 +3595,18 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
else
{
+ LLInventoryItem* item = getItem();
+ if (item && LLAssetType::lookupIsLinkType(item->getActualType()))
+ {
+ items.push_back(std::string("Goto Link"));
+ }
+
items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
LLObjectBridge::sContextMenuItemID = mUUID;
- LLInventoryItem* item = getItem();
if(item)
{
LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
@@ -3619,7 +3686,7 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
- renameLinkedItems(item->getUUID(),new_name);
+ model->updateLinkedObjects(item->getUUID());
model->notifyObservers();
@@ -4513,6 +4580,11 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Open"));
}
+ if (item && LLAssetType::lookupIsLinkType(item->getActualType()))
+ {
+ items.push_back(std::string("Goto Link"));
+ }
+
items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags);
@@ -5093,3 +5165,94 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
hideContextEntries(menu, items, disabled_items);
}
+
+
+// +=================================================+
+// | LLLinkBridge |
+// +=================================================+
+// For broken links.
+
+std::string LLLinkFolderBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkFolderBridge::getIcon() const
+{
+ LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
+ {
+ preferred_type = cat->getPreferredType();
+ }
+ }
+ return LLFolderBridge::getIcon(preferred_type);
+}
+
+void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Goto Link"));
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hideContextEntries(menu, items, disabled_items);
+}
+
+void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ return;
+ }
+ LLItemBridge::performAction(folder,model,action);
+}
+
+void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
+{
+ const LLUUID &cat_uuid = getFolderID();
+ if (!cat_uuid.isNull())
+ {
+ if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid))
+ {
+ if (LLInventoryModel* model = getInventoryModel())
+ {
+ model->fetchDescendentsOf(cat_uuid);
+ }
+ base_folder->setOpen(TRUE);
+ folder->setSelectionFromRoot(base_folder,TRUE);
+ }
+ }
+}
+
+const LLUUID &LLLinkFolderBridge::getFolderID() const
+{
+ if (LLViewerInventoryItem *link_item = getItem())
+ {
+ if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
+ {
+ const LLUUID& cat_uuid = cat->getUUID();
+ return cat_uuid;
+ }
+ }
+ return LLUUID::null;
+}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index a37b7969ed..915dfec629 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -133,6 +133,7 @@ public:
// This method is a convenience function which creates the correct
// type of bridge based on some basic information
static LLInvFVBridge* createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
LLInventoryType::EType inv_type,
LLInventoryPanel* inventory,
const LLUUID& uuid,
@@ -156,6 +157,7 @@ public:
}
virtual std::string getLabelSuffix() const { return LLStringUtil::null; }
virtual void openItem() {}
+ virtual void gotoItem(LLFolderView *folder) {} // for links
virtual void previewItem() {openItem();}
virtual void showProperties();
virtual BOOL isItemRenameable() const { return TRUE; }
@@ -231,6 +233,7 @@ public:
virtual void selectItem();
virtual void restoreItem();
virtual void restoreToWorld();
+ virtual void gotoItem(LLFolderView *folder);
virtual LLUIImagePtr getIcon() const;
virtual const std::string& getDisplayName() const;
@@ -274,6 +277,8 @@ public:
virtual LLAssetType::EType getPreferredType() const;
virtual LLUIImagePtr getIcon() const;
+ static LLUIImagePtr getIcon(LLAssetType::EType asset_type);
+
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL removeItem();
virtual void pasteFromClipboard();
@@ -591,6 +596,27 @@ protected:
static std::string sPrefix;
};
+
+class LLLinkFolderBridge : public LLItemBridge
+{
+ friend class LLInvFVBridge;
+public:
+ virtual const std::string& getPrefix() { return sPrefix; }
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+ virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
+ virtual void gotoItem(LLFolderView *folder);
+
+protected:
+ LLLinkFolderBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+ LLItemBridge(inventory, uuid) {}
+ const LLUUID &getFolderID() const;
+
+protected:
+ static std::string sPrefix;
+};
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridgeAction (& its derived classes)
//
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 2c281a4615..bba0c9a90d 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -475,6 +475,35 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
}
}
+void LLInventoryModel::updateLinkedObjects(const LLUUID& object_id)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLLinkedItemIDMatches is_linked_item_match(object_id);
+ collectDescendentsIf(gInventory.getRootFolderID(),
+ cat_array,
+ item_array,
+ LLInventoryModel::INCLUDE_TRASH,
+ is_linked_item_match);
+
+ for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin();
+ cat_iter != cat_array.end();
+ cat_iter++)
+ {
+ LLViewerInventoryCategory *linked_cat = (*cat_iter);
+ addChangedMask(LLInventoryObserver::LABEL, linked_cat->getUUID());
+ };
+
+ for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ LLViewerInventoryItem *linked_item = (*iter);
+ addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
+ };
+ notifyObservers();
+}
+
void LLInventoryModel::collectLinkedItems(const LLUUID& id,
item_array_t& items)
{
@@ -825,10 +854,10 @@ void LLInventoryModel::purgeObject(const LLUUID &id)
void LLInventoryModel::purgeLinkedObjects(const LLUUID &id)
{
- LLInventoryItem* itemp = getItem(id);
- if (!itemp) return;
+ LLInventoryObject* objectp = getObject(id);
+ if (!objectp) return;
- if (LLAssetType::lookupIsLinkType(itemp->getActualType()))
+ if (LLAssetType::lookupIsLinkType(objectp->getActualType()))
{
return;
}
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index c402fea886..f470a77985 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -181,7 +181,6 @@ public:
cat_array_t& categories,
item_array_t& items,
BOOL include_trash);
-
void collectDescendentsIf(const LLUUID& id,
cat_array_t& categories,
item_array_t& items,
@@ -192,8 +191,9 @@ public:
// Assumes item_id is itself not a linked item.
void collectLinkedItems(const LLUUID& item_id,
item_array_t& items);
-
- // This method will return false if this inventory model is in an usabel state.
+ // Updates all linked objects pointing to this id.
+ void updateLinkedObjects(const LLUUID& object_id);
+
// The inventory model usage is sensitive to the initial construction of the
// model.
bool isInventoryUsable();
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 3a7ef4dfc9..d2e07f0725 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -473,6 +473,14 @@ LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::sDragAndDrop3d[DAD_COUNT]
&LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
&LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
},
+ // Source: DAD_LINK
+ {
+ &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
+ &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
+ &LLToolDragAndDrop::dad3dNULL, // Dest: DT_AVATAR
+ &LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT
+ &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
+ },
};
LLToolDragAndDrop::LLToolDragAndDrop()
@@ -1894,7 +1902,7 @@ BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
acceptable = FALSE;
break;
case LLAssetType::AT_OBJECT:
- if(my_avatar->isWearingAttachment(item->getUUID()))
+ if(my_avatar->isWearingAttachment(item->getUUID(), TRUE))
{
acceptable = FALSE;
}
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index 54b0a4f568..66da7d89fb 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -403,7 +403,8 @@ void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const
void LLViewerInventoryCategory::updateServer(BOOL is_new) const
{
// communicate that change with the server.
- if(LLAssetType::AT_NONE != mPreferredType)
+
+ if (LLAssetType::lookupIsProtectedCategoryType(mPreferredType))
{
LLNotifications::instance().add("CannotModifyProtectedCategories");
return;
@@ -427,7 +428,7 @@ void LLViewerInventoryCategory::removeFromServer( void )
llinfos << "Removing inventory category " << mUUID << " from server."
<< llendl;
// communicate that change with the server.
- if(LLAssetType::AT_NONE != mPreferredType)
+ if(LLAssetType::lookupIsProtectedCategoryType(mPreferredType))
{
LLNotifications::instance().add("CannotRemoveProtectedCategories");
return;
@@ -977,7 +978,10 @@ LLAssetType::EType LLViewerInventoryItem::getType() const
{
return linked_item->getType();
}
-
+ if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
+ {
+ return linked_category->getType();
+ }
return LLInventoryItem::getType();
}
@@ -997,6 +1001,10 @@ const std::string& LLViewerInventoryItem::getName() const
{
return linked_item->getName();
}
+ if (const LLViewerInventoryCategory *linked_category = getLinkedCategory())
+ {
+ return linked_category->getName();
+ }
return LLInventoryItem::getName();
}
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 7084c9f37a..5198f5efc7 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -141,7 +141,6 @@ public:
};
LLTransactionID getTransactionID() const { return mTransactionID; }
-protected:
const LLViewerInventoryItem *getLinkedItem() const;
const LLViewerInventoryCategory *getLinkedCategory() const;
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 6f2fd5e5e5..c788f8f095 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -77,6 +77,14 @@
parameter="category" />
</menu_item_call>
<menu_item_call
+ label="New Current"
+ layout="topleft"
+ name="New Current">
+ <menu_item_call.on_click
+ function="Inventory.DoCreate"
+ parameter="current" />
+ </menu_item_call>
+ <menu_item_call
label="New Script"
layout="topleft"
name="New Script">
@@ -230,6 +238,91 @@
parameter="eyes" />
</menu_item_call>
</menu>
+ <menu
+ label="Change Type"
+ layout="topleft"
+ name="Change Type">
+ <menu_item_call
+ label="Default"
+ layout="topleft"
+ name="Default">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_default" />
+ </menu_item_call>
+ <menu_item_call
+ label="Gloves"
+ layout="topleft"
+ name="Gloves">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="Jacket"
+ layout="topleft"
+ name="Jacket">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pants"
+ layout="topleft"
+ name="Pants">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="Shape"
+ layout="topleft"
+ name="Shape">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_shape" />
+ </menu_item_call>
+ <menu_item_call
+ label="Shoes"
+ layout="topleft"
+ name="Shoes">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="Shirt"
+ layout="topleft"
+ name="Shirt">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Skirt"
+ layout="topleft"
+ name="Skirt">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Underpants"
+ layout="topleft"
+ name="Underpants">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="Undershirt"
+ layout="topleft"
+ name="Undershirt">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="change_folder_type_undershirt" />
+ </menu_item_call>
+ </menu>
<menu_item_call
label="Teleport"
layout="topleft"
@@ -271,6 +364,14 @@
parameter="restore" />
</menu_item_call>
<menu_item_call
+ label="Goto Link"
+ layout="topleft"
+ name="Goto Link">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="goto" />
+ </menu_item_call>
+ <menu_item_call
label="Open"
layout="topleft"
name="Open">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index e54ef88f34..626c084f0c 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -346,6 +346,8 @@ this texture in your inventory
<string name="no_modify" value=" (no modify)" />
<string name="no_copy" value=" (no copy)" />
<string name="worn" value=" (worn)" />
+ <string name="link" value=" (link)" />
+ <string name="broken_link" value=" (broken_link)" />
<string name="LoadingContents">Loading contents...</string>
<string name="NoContents">No contents</string>