Since multiwear, the low 8 bit of inventory items, if they are of type IT_WEARABLE, is used for the wearable type (WT_*). Older viewers and bots (like Second Inventory) create inventory items with 0 in those bits. This causes all those item to appear as shapes in multi-wear capable viewers. This gives rise to many problems: 1) You can't wear them, because the inventory and asset wearable type mismatch, which makes Singularity just abort. 2) Before it aborts, it already removed your old shape, thinking you are about to wear another shape - and told the server that you are wearing this broken item now. The result is that you see no change, until you relog when you are suddenly wearing the broken "shape" and stay a cloud forever. This commit detects the problem for AT_CLOTHING wearables, because they are not compatible with the type 'shape' after all (which is is AT_BODYPART). It still doesn't know what the wearable type is, but sets the type temporarily to the new value WT_UNKNOWN. Since this is at least not a shape anymore, it doesn't cause you shape to be removed when wearing it. Moreover, once the asset is downloaded, the mismatch is detected and corrected: you can now wear -say- pants, or other clothing. Inventory clothing items with an unknown wearable type now have a red question mark icon in the inventory. What does NOT work yet: 1) If you copy such an item and paste it, then the new copy has a shape icon again (and all the previously mentioned problems). 2) If you wear broken hair, skin or eyes (which still show as shapes in the inventory) then your shape is still removed, and wearing them fails because they are not multiwear capable and you are already wearing such a body part. What should be done here is that the removed shape is added back and the real body part that you're trying to wear is removed. 3) Although this code attempts to fix the mFlags in the inventory, the icon in the inventory doesn't change from question mark to the right thing.
183 lines
8.3 KiB
C++
183 lines
8.3 KiB
C++
/**
|
|
* @file llwearabletype.cpp
|
|
* @brief LLWearableType class implementation
|
|
*
|
|
* $LicenseInfo:firstyear=2002&license=viewerlgpl$
|
|
* Second Life Viewer Source Code
|
|
* Copyright (C) 2010, Linden Research, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation;
|
|
* version 2.1 of the License only.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
|
* $/LicenseInfo$
|
|
*/
|
|
|
|
#include "linden_common.h"
|
|
#include "llwearabletype.h"
|
|
#include "llinventorytype.h"
|
|
|
|
static LLTranslationBridge* sTrans = NULL;
|
|
|
|
// static
|
|
void LLWearableType::initClass(LLTranslationBridge* trans)
|
|
{
|
|
sTrans = trans;
|
|
}
|
|
|
|
void LLWearableType::cleanupClass()
|
|
{
|
|
delete sTrans;
|
|
}
|
|
|
|
struct WearableEntry : public LLDictionaryEntry
|
|
{
|
|
WearableEntry(const std::string &name,
|
|
const std::string& default_new_name,
|
|
LLAssetType::EType assetType,
|
|
LLInventoryType::EIconName iconName,
|
|
BOOL disable_camera_switch = FALSE,
|
|
BOOL allow_multiwear = TRUE) :
|
|
LLDictionaryEntry(name),
|
|
mAssetType(assetType),
|
|
mDefaultNewName(default_new_name),
|
|
//*TODO:Translate
|
|
mLabel(/*sTrans->getString*/(name)),
|
|
mIconName(iconName),
|
|
mDisableCameraSwitch(disable_camera_switch),
|
|
mAllowMultiwear(allow_multiwear)
|
|
{
|
|
|
|
}
|
|
const LLAssetType::EType mAssetType;
|
|
const std::string mLabel;
|
|
const std::string mDefaultNewName; //keep mLabel for backward compatibility
|
|
LLInventoryType::EIconName mIconName;
|
|
BOOL mDisableCameraSwitch;
|
|
BOOL mAllowMultiwear;
|
|
};
|
|
|
|
class LLWearableDictionary : public LLSingleton<LLWearableDictionary>,
|
|
public LLDictionary<LLWearableType::EType, WearableEntry>
|
|
{
|
|
public:
|
|
LLWearableDictionary();
|
|
|
|
// [RLVa:KB] - Checked: 2010-03-03 (RLVa-1.2.0a) | Added: RLVa-1.2.0a
|
|
protected:
|
|
// The default implementation asserts on 'notFound()' and returns -1 which isn't a valid EWearableType
|
|
virtual LLWearableType::EType notFound() const { return LLWearableType::WT_INVALID; }
|
|
// [/RLVa:KB]
|
|
};
|
|
|
|
LLWearableDictionary::LLWearableDictionary()
|
|
{
|
|
addEntry(LLWearableType::WT_SHAPE, new WearableEntry("shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
|
|
addEntry(LLWearableType::WT_SKIN, new WearableEntry("skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
|
|
addEntry(LLWearableType::WT_HAIR, new WearableEntry("hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
|
|
addEntry(LLWearableType::WT_EYES, new WearableEntry("eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE));
|
|
addEntry(LLWearableType::WT_SHIRT, new WearableEntry("shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_PANTS, new WearableEntry("pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_SHOES, new WearableEntry("shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_SOCKS, new WearableEntry("socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_JACKET, new WearableEntry("jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_GLOVES, new WearableEntry("gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry("undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry("underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_SKIRT, new WearableEntry("skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_ALPHA, new WearableEntry("alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_TATTOO, new WearableEntry("tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
|
|
|
|
// addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE));
|
|
// [SL:KB] - Patch: Appearance-Misc | Checked: 2011-05-29 (Catznip-2.6)
|
|
addEntry(LLWearableType::WT_PHYSICS, new WearableEntry("physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, FALSE));
|
|
// [/SL:KB]
|
|
|
|
addEntry(LLWearableType::WT_UNKNOWN, new WearableEntry("unknown", "Clothing", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNKNOWN, FALSE, TRUE));
|
|
addEntry(LLWearableType::WT_INVALID, new WearableEntry("invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
|
|
addEntry(LLWearableType::WT_NONE, new WearableEntry("none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
|
|
}
|
|
|
|
// static
|
|
LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name)
|
|
{
|
|
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
|
const LLWearableType::EType wearable = dict->lookup(type_name);
|
|
return wearable;
|
|
}
|
|
|
|
// static
|
|
const std::string& LLWearableType::getTypeName(LLWearableType::EType type)
|
|
{
|
|
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
|
const WearableEntry *entry = dict->lookup(type);
|
|
if (!entry) return getTypeName(WT_INVALID);
|
|
return entry->mName;
|
|
}
|
|
|
|
//static
|
|
const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type)
|
|
{
|
|
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
|
const WearableEntry *entry = dict->lookup(type);
|
|
if (!entry) return getTypeDefaultNewName(WT_INVALID);
|
|
return entry->mDefaultNewName;
|
|
}
|
|
|
|
// static
|
|
const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type)
|
|
{
|
|
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
|
const WearableEntry *entry = dict->lookup(type);
|
|
if (!entry) return getTypeLabel(WT_INVALID);
|
|
return entry->mLabel;
|
|
}
|
|
|
|
// static
|
|
LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type)
|
|
{
|
|
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
|
const WearableEntry *entry = dict->lookup(type);
|
|
if (!entry) return getAssetType(WT_INVALID);
|
|
return entry->mAssetType;
|
|
}
|
|
|
|
// static
|
|
LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type)
|
|
{
|
|
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
|
const WearableEntry *entry = dict->lookup(type);
|
|
if (!entry) return getIconName(WT_INVALID);
|
|
return entry->mIconName;
|
|
}
|
|
|
|
// static
|
|
BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)
|
|
{
|
|
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
|
const WearableEntry *entry = dict->lookup(type);
|
|
if (!entry) return FALSE;
|
|
return entry->mDisableCameraSwitch;
|
|
}
|
|
|
|
// static
|
|
BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
|
|
{
|
|
const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
|
|
const WearableEntry *entry = dict->lookup(type);
|
|
if (!entry) return FALSE;
|
|
return entry->mAllowMultiwear;
|
|
}
|
|
|