summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llcommon/llassettype.cpp126
-rw-r--r--indra/llcommon/llassettype.h44
-rw-r--r--indra/llcommon/lldictionary.h4
-rw-r--r--indra/llcommon/stdenums.h3
-rw-r--r--indra/llinventory/llinventory.cpp2
-rw-r--r--indra/llinventory/llinventorytype.cpp77
-rw-r--r--indra/llinventory/llinventorytype.h7
-rw-r--r--indra/llmessage/lltransfersourceasset.cpp8
-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
25 files changed, 701 insertions, 171 deletions
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index e4102a622d..d431071c25 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -44,19 +44,29 @@ struct AssetEntry : public LLDictionaryEntry
{
AssetEntry(const char *desc_name,
const char *type_name, // 8 character limit!
- const char *human_name,
+ const char *human_name, // for decoding to human readable form; put any and as many printable characters you want in each one
const char *category_name, // used by llinventorymodel when creating new categories
EDragAndDropType dad_type,
- bool can_link);
+ bool can_link, // can you create a link to this type?
+ bool is_protected) // can the viewer change categories of this type?
+ :
+ LLDictionaryEntry(desc_name),
+ mTypeName(type_name),
+ mHumanName(human_name),
+ mCategoryName(category_name),
+ mDadType(dad_type),
+ mCanLink(can_link),
+ mIsProtected(is_protected)
+ {
+ llassert(strlen(mTypeName) <= 8);
+ }
- // limited to 8 characters
const char *mTypeName;
- // human readable form. Put as many printable characters you want in each one.
- // (c.f. llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES).
const char *mHumanName;
const char *mCategoryName;
EDragAndDropType mDadType;
bool mCanLink;
+ bool mIsProtected;
};
class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
@@ -68,52 +78,49 @@ public:
LLAssetDictionary::LLAssetDictionary()
{
- addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, FALSE));
- addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, FALSE));
- addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, FALSE));
- addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, FALSE));
- addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE));
- addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE));
- addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, FALSE));
- addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE));
- addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE));
- addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, FALSE));
- addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE));
- addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, FALSE));
- addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, FALSE));
- addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE));
+ // DESCRIPTION TYPE NAME HUMAN NAME CATEGORY NAME DRAG&DROP CAN LINK? PROTECTED?
+ // |--------------------|-----------|-------------------|-------------------|---------------|-----------|-----------|
+ addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, FALSE, TRUE));
+ addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, FALSE, TRUE));
+ addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, FALSE, TRUE));
+ addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE, TRUE));
+ addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE, TRUE));
+ addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, FALSE, TRUE));
+ addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE, TRUE));
+ addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE, TRUE));
+ addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, FALSE, TRUE));
+ addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE, TRUE));
+ addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, FALSE, TRUE));
+ addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE, TRUE));
+ addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "New Folder", DAD_NONE, FALSE));
- addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", "New Folder", DAD_NONE, FALSE));
+ addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "Link", DAD_LINK, FALSE, TRUE));
+ addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", "New Folder", DAD_LINK, FALSE, TRUE));
- addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE));
-};
+ for (S32 ensemble_num = S32(LLAssetType::AT_FOLDER_ENSEMBLE_START);
+ ensemble_num <= S32(LLAssetType::AT_FOLDER_ENSEMBLE_END);
+ ensemble_num++)
+ {
+ addEntry(LLAssetType::EType(ensemble_num), new AssetEntry("ENSEMBLE", "ensemble", "ensemble", "New Folder", DAD_CATEGORY, TRUE, FALSE));
+ }
-AssetEntry::AssetEntry(const char *desc_name,
- const char *type_name,
- const char *human_name,
- const char *category_name,
- EDragAndDropType dad_type,
- bool can_link) :
- LLDictionaryEntry(desc_name),
- mTypeName(type_name),
- mHumanName(human_name),
- mCategoryName(category_name),
- mDadType(dad_type),
- mCanLink(can_link)
-{
- llassert(strlen(mTypeName) <= 8);
-}
+ addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("CURRENT", "current", "current outfit", "Current Outfit", DAD_CATEGORY, FALSE, TRUE));
+ addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "Outfit", DAD_CATEGORY, TRUE, FALSE));
+ addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", "My Outfits", DAD_CATEGORY, FALSE, TRUE));
+
+ addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE, FALSE));
+};
// static
LLAssetType::EType LLAssetType::getType(const std::string& desc_name)
@@ -128,11 +135,11 @@ const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
{
const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type);
if (entry)
-{
+ {
return entry->mName;
}
else
- {
+ {
static const std::string error_string = "BAD TYPE";
return error_string;
}
@@ -154,7 +161,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type)
}
// static
-LLAssetType::EType LLAssetType::lookup( const char* name )
+LLAssetType::EType LLAssetType::lookup(const char* name)
{
return lookup(ll_safe_string(name));
}
@@ -191,7 +198,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
}
// static
-LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name )
+LLAssetType::EType LLAssetType::lookupHumanReadable(const char* name)
{
return lookupHumanReadable(ll_safe_string(name));
}
@@ -261,6 +268,21 @@ bool LLAssetType::lookupIsLinkType(EType asset_type)
return false;
}
+// static
+// Only ensembles and plain folders aren't protected. "Protected" means
+// you can't change certain properties such as their type.
+bool LLAssetType::lookupIsProtectedCategoryType(EType asset_type)
+{
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ const AssetEntry *entry = dict->lookup(asset_type);
+ if (entry)
+ {
+ return entry->mIsProtected;
+ }
+ return true;
+}
+
+
// static. Generate a good default description
void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type,
std::string& description)
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 353bd57bb9..8ab7510494 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -125,7 +125,7 @@ public:
AT_SIMSTATE = 22,
// Simstate file.
-
+
AT_FAVORITE = 23,
// favorite items
@@ -135,21 +135,35 @@ public:
AT_LINK_FOLDER = 25,
// Inventory folder link
- AT_COUNT = 26,
+ AT_FOLDER_ENSEMBLE_START = 26,
+ AT_FOLDER_ENSEMBLE_END = 45,
+ // This range is reserved for special clothing folder types.
+
+ AT_CURRENT_OUTFIT = 46,
+ // Current outfit
- // +************************************************+
- // | TO ADD AN ELEMENT TO THIS ENUM: |
- // +************************************************+
- // | 1. INSERT BEFORE AT_COUNT |
- // | 2. INCREMENT AT_COUNT BY 1 |
- // | 3. ADD TO LLAssetDictionary in llassettype.cpp |
- // +************************************************+
+ AT_OUTFIT = 47,
+ // Predefined outfit ("look")
+
+ AT_MY_OUTFITS = 48,
+ // Folder that holds your outfits.
+
+
+ AT_COUNT = 49,
+ // +*********************************************************+
+ // | TO ADD AN ELEMENT TO THIS ENUM: |
+ // +*********************************************************+
+ // | 1. INSERT BEFORE AT_COUNT |
+ // | 2. INCREMENT AT_COUNT BY 1 |
+ // | 3. ADD TO LLAssetDictionary in LLAssetType.cpp |
+ // | 3. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
+ // +*********************************************************+
AT_NONE = -1
};
// machine transation between type and strings
- static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
+ static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate
static EType lookup(const std::string& type_name);
static const char* lookup(EType asset_type);
@@ -158,8 +172,6 @@ public:
static EType lookupHumanReadable(const std::string& readable_name);
static const char* lookupHumanReadable(EType asset_type);
- static const char* lookupCategoryName(EType asset_type);
-
// Generate a good default description. You may want to add a verb
// or agent name after this depending on your application.
static void generateDescriptionFor(LLAssetType::EType asset_type,
@@ -168,9 +180,13 @@ public:
static EType getType(const std::string& desc_name);
static const std::string& getDesc(EType asset_type);
static EDragAndDropType lookupDragAndDropType(EType asset_type);
+
static bool lookupCanLink(EType asset_type);
static bool lookupIsLinkType(EType asset_type);
+ static const char* lookupCategoryName(EType asset_type);
+ static bool lookupIsProtectedCategoryType(EType asset_type);
+
/* TODO: Change return types from "const char *" to "const std::string &".
This is fairly straightforward, but requires changing some calls to use .c_str().
e.g.:
@@ -180,8 +196,8 @@ public:
private:
// don't instantiate or derive one of these objects
- LLAssetType() {}
- ~LLAssetType() {}
+ LLAssetType( void ) {}
+ ~LLAssetType( void ) {}
};
#endif // LL_LLASSETTYPE_H
diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h
index 856947def8..436b689ca6 100644
--- a/indra/llcommon/lldictionary.h
+++ b/indra/llcommon/lldictionary.h
@@ -95,6 +95,10 @@ public:
protected:
void addEntry(Index index, Entry *entry)
{
+ if (lookup(index))
+ {
+ llerrs << "Dictionary entry already added (attempted to add duplicate entry)" << llendl;
+ }
(*this)[index] = entry;
}
};
diff --git a/indra/llcommon/stdenums.h b/indra/llcommon/stdenums.h
index 41da51fce3..1a5678dde1 100644
--- a/indra/llcommon/stdenums.h
+++ b/indra/llcommon/stdenums.h
@@ -54,7 +54,8 @@ enum EDragAndDropType
DAD_BODYPART = 11,
DAD_ANIMATION = 12,
DAD_GESTURE = 13,
- DAD_COUNT = 14, // number of types in this enum
+ DAD_LINK = 14,
+ DAD_COUNT = 15, // number of types in this enum
};
// Reasons for drags to be denied.
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 597e19e7ea..2d507bd560 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -1624,7 +1624,7 @@ LLSD ll_create_sd_from_inventory_category(LLPointer<LLInventoryCategory> cat)
rv[INV_PARENT_ID_LABEL] = cat->getParentUUID();
rv[INV_NAME_LABEL] = cat->getName();
rv[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(cat->getType());
- if(LLAssetType::AT_NONE != cat->getPreferredType())
+ if(LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
{
rv[INV_PREFERRED_TYPE_LABEL] =
LLAssetType::lookup(cat->getPreferredType());
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index 2dc229226f..a445466b26 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -44,9 +44,23 @@ static const std::string empty_string;
///----------------------------------------------------------------------------
struct InventoryEntry : public LLDictionaryEntry
{
- InventoryEntry(const std::string &name,
- const std::string &human_name,
- int num_asset_types = 0, ...);
+ InventoryEntry(const std::string &name, // unlike asset type names, not limited to 8 characters; need not match asset type names
+ const std::string &human_name, // for decoding to human readable form; put any and as many printable characters you want in each one.
+ int num_asset_types = 0, ...)
+ :
+ LLDictionaryEntry(name),
+ mHumanName(human_name)
+ {
+ va_list argp;
+ va_start(argp, num_asset_types);
+ // Read in local textures
+ for (U8 i=0; i < num_asset_types; i++)
+ {
+ LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int);
+ mAssetTypes.push_back(t);
+ }
+ }
+
const std::string mHumanName;
typedef std::vector<LLAssetType::EType> asset_vec_t;
asset_vec_t mAssetTypes;
@@ -115,25 +129,35 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_GESTURE, // AT_GESTURE
LLInventoryType::IT_NONE, // AT_SIMSTATE
LLInventoryType::IT_FAVORITE, // AT_FAVORITE
+
LLInventoryType::IT_NONE, // AT_LINK
LLInventoryType::IT_NONE, // AT_LINK_FOLDER
-};
-InventoryEntry::InventoryEntry(const std::string &name,
- const std::string &human_name,
- int num_asset_types, ...) :
- LLDictionaryEntry(name),
- mHumanName(human_name)
-{
- va_list argp;
- va_start(argp, num_asset_types);
- // Read in local textures
- for (U8 i=0; i < num_asset_types; i++)
- {
- LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int);
- mAssetTypes.push_back(t);
- }
-}
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+ LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
+
+ LLInventoryType::IT_CATEGORY, // AT_CURRENT_OUTFIT
+ LLInventoryType::IT_CATEGORY, // AT_OUTFIT
+ LLInventoryType::IT_CATEGORY, // AT_MY_OUTFITS
+};
// static
const std::string &LLInventoryType::lookup(EType type)
@@ -173,6 +197,21 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a
}
}
+
+// add any types that we don't want the user to be able to change permissions on.
+// static
+bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type)
+{
+ switch(type)
+ {
+ case IT_CALLINGCARD:
+ case IT_LANDMARK:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type,
LLAssetType::EType asset_type)
{
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index 1aad90d51b..14b28bfe4b 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -83,10 +83,13 @@ public:
// return the default inventory for the given asset type.
static EType defaultForAssetType(LLAssetType::EType asset_type);
+ // true if this type cannot have restricted permissions.
+ static bool cannotRestrictPermissions(EType type);
+
private:
// don't instantiate or derive one of these objects
- LLInventoryType() {}
- ~LLInventoryType() {}
+ LLInventoryType( void );
+ ~LLInventoryType( void );
};
// helper function that returns true if inventory type and asset type
diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp
index c715e16e34..5a1cd95ffc 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -296,10 +296,10 @@ bool is_asset_id_knowable(LLAssetType::EType type)
case LLAssetType::AT_FAVORITE:
case LLAssetType::AT_LINK:
case LLAssetType::AT_LINK_FOLDER:
- rv = true;
- break;
- default:
- break;
+ rv = true;
+ break;
+ default:
+ break;
}
return rv;
}
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>