00001
00033 #include "llviewerprecompiledheaders.h"
00034
00035 #include "llfloaterclothing.h"
00036
00037 #include "lldir.h"
00038 #include "llinventory.h"
00039
00040 #include "llagent.h"
00041 #include "llinventorymodel.h"
00042 #include "llinventoryview.h"
00043 #include "llkeyboard.h"
00044 #include "llscrollbar.h"
00045 #include "llscrolllistctrl.h"
00046 #include "llvieweruictrlfactory.h"
00047 #include "llviewerinventory.h"
00048 #include "llvoavatar.h"
00049 #include "llviewercontrol.h"
00050
00051 const LLString LOADING_STRING("Loading...");
00052
00053
00054 LLFloaterClothing* LLFloaterClothing::sInstance = NULL;
00055 LLFloaterClothingObserver* LLFloaterClothing::sObserver = NULL;
00056
00057 class LLFloaterClothingObserver : public LLInventoryObserver
00058 {
00059 public:
00060 LLFloaterClothingObserver() {}
00061 virtual ~LLFloaterClothingObserver() {}
00062
00063 virtual void changed(U32 mask)
00064 {
00065 LLFloaterClothing::refreshAll();
00066 }
00067 };
00068
00069
00070
00071
00072 LLFloaterClothing::LLFloaterClothing()
00073 : LLFloater("floater_clothing", "FloaterClothingRect", ""),
00074 mSelectedID(),
00075 mAllowSelection(FALSE)
00076 {
00077 gUICtrlFactory->buildFloater(this, "floater_clothing.xml");
00078
00079 sInstance = this;
00080
00081 sObserver = new LLFloaterClothingObserver;
00082 gInventory.addObserver(sObserver);
00083
00084 childSetAction("take_off_btn", onClickTakeOff, this);
00085 childSetAction("wear_btn", onClickWear, this);
00086
00087 childSetDoubleClickCallback("clothing_list", onClickWear);
00088 childSetCommitCallback("clothing_list", onCommitList, this);
00089
00090 LLCtrlListInterface* list = childGetListInterface("clothing_list");
00091 if (list)
00092 {
00093 list->addSimpleElement(LOADING_STRING);
00094 }
00095
00096 setDefaultBtn("wear_btn");
00097
00098 gInventory.startBackgroundFetch();
00099 }
00100
00101
00102 LLFloaterClothing::~LLFloaterClothing()
00103 {
00104 gInventory.removeObserver(sObserver);
00105 delete sObserver;
00106 sObserver = NULL;
00107
00108 sInstance = NULL;
00109 }
00110
00111
00112
00113 void LLFloaterClothing::onClose(bool app_quitting)
00114 {
00115 gSavedSettings.setBOOL("ClothingBtnState", FALSE);
00116
00117 LLFloater::onClose(app_quitting);
00118 }
00119
00120
00121
00122 void LLFloaterClothing::show(void*)
00123 {
00124 if (sInstance)
00125 {
00126 sInstance->setVisibleAndFrontmost();
00127 }
00128 else
00129 {
00130 LLFloaterClothing *self = new LLFloaterClothing();
00131
00132 self->buildClothingList();
00133
00134 if (self->mAllowSelection)
00135 {
00136 LLCtrlSelectionInterface* iface = self->childGetSelectionInterface("clothing_list");
00137 if (iface) iface->selectFirstItem();
00138 }
00139 self->childSetFocus("clothing_list");
00140
00141 self->mSelectedID = LLUUID::null;
00142
00143
00144 onCommitList(NULL, self);
00145 }
00146
00147 gSavedSettings.setBOOL("ClothingBtnState", TRUE);
00148 }
00149
00150
00151 void LLFloaterClothing::toggleVisibility()
00152 {
00153 if(sInstance && sInstance->getVisible())
00154 {
00155 sInstance->close();
00156 }
00157 else
00158 {
00159 show();
00160 }
00161 }
00162
00163
00164 void LLFloaterClothing::refreshAll()
00165 {
00166 if (sInstance)
00167 {
00168 sInstance->buildClothingList();
00169
00170 LLCtrlListInterface* list = sInstance->childGetListInterface("clothing_list");
00171 if (list)
00172 {
00173 if (!sInstance->mAllowSelection)
00174 {
00175
00176 list->operateOnSelection(LLCtrlListInterface::OP_DESELECT);
00177 }
00178 else if (sInstance->mSelectedID.isNull())
00179 {
00180 list->selectFirstItem();
00181 }
00182 else
00183 {
00184 if (list->setCurrentByID(sInstance->mSelectedID))
00185 {
00186 LLCtrlScrollInterface *scroll = sInstance->childGetScrollInterface("clothing_list");
00187 if (scroll)
00188 {
00189 scroll->scrollToShowSelected();
00190 }
00191 }
00192 else
00193 {
00194 list->selectFirstItem();
00195 }
00196 }
00197
00198
00199 onCommitList(NULL, sInstance);
00200 }
00201 }
00202 }
00203
00204 class LLIsClothing : public LLInventoryCollectFunctor
00205 {
00206 public:
00207 LLIsClothing() {}
00208 virtual ~LLIsClothing() {}
00209 virtual bool operator()(LLInventoryCategory* cat,
00210 LLInventoryItem* item)
00211 {
00212 if (item)
00213 {
00214 LLAssetType::EType at = item->getType();
00215 if (at == LLAssetType::AT_CLOTHING
00216 || at == LLAssetType::AT_BODYPART)
00217 {
00218 U32 flags = item->getFlags();
00219 switch(flags)
00220 {
00221 case WT_SHAPE:
00222 case WT_SKIN:
00223 case WT_HAIR:
00224 case WT_EYES:
00225 return FALSE;
00226 case WT_SHIRT:
00227 case WT_PANTS:
00228 case WT_SKIRT:
00229 case WT_UNDERSHIRT:
00230 case WT_UNDERPANTS:
00231 return TRUE;
00232 default:
00233 return TRUE;
00234 }
00235 }
00236 }
00237 return FALSE;
00238 }
00239 };
00240
00241
00242
00243 void LLFloaterClothing::buildClothingList()
00244 {
00245
00246
00247 LLCtrlListInterface *list = childGetListInterface("clothing_list");
00248 if (!list) return;
00249
00250 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00251
00252 LLInventoryModel::cat_array_t cats;
00253 LLInventoryModel::item_array_t items;
00254
00255 LLIsClothing is_clothing;
00256 gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
00257 cats,
00258 items,
00259 LLInventoryModel::EXCLUDE_TRASH,
00260 is_clothing);
00261
00262 S32 count = items.count();
00263 for(S32 i = 0; i < count; ++i)
00264 {
00265 LLInventoryItem* item = items.get(i);
00266
00267 LLSD row;
00268 row["id"] = item->getUUID();
00269
00270 BOOL item_is_multi = FALSE;
00271 if ( item->getFlags() & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS )
00272 {
00273 item_is_multi = TRUE;
00274 }
00275
00276 LLUUID image_id = get_item_icon_uuid(item->getType(),
00277 item->getInventoryType(),
00278 item->getFlags(), item_is_multi);
00279 row["columns"][0]["column"] = "icon";
00280 row["columns"][0]["type"] = "icon";
00281 row["columns"][0]["value"] = image_id;
00282
00283 LLString text = item->getName();
00284 LLString style = "NORMAL";
00285 if( gAgent.isWearingItem( item->getUUID() ) )
00286 {
00287 text.append(" (worn)");
00288 style = "BOLD";
00289 }
00290 row["columns"][1]["column"] = "name";
00291 row["columns"][1]["value"] = text;
00292 row["columns"][1]["font"] = "SANSSERIFSMALL";
00293 row["columns"][1]["font-style"] = style;
00294
00295
00296 U32 flags = item->getFlags();
00297 enum EWearableType wearable_type = (enum EWearableType)flags;
00298 const char* wearable_label = LLWearable::typeToTypeLabel(wearable_type);
00299
00300 row["columns"][2]["column"] = "sort";
00301 row["columns"][2]["value"] = wearable_label;
00302
00303 list->addElement(row);
00304 }
00305
00306 if (count > 0)
00307 {
00308 mAllowSelection = TRUE;
00309 }
00310 else if (LLInventoryModel::backgroundFetchActive())
00311 {
00312
00313 list->addSimpleElement(LOADING_STRING);
00314 mAllowSelection = FALSE;
00315 }
00316 else
00317 {
00318
00319 list->addSimpleElement("No clothing found.");
00320 mAllowSelection = FALSE;
00321 }
00322 }
00323
00324
00325 void LLFloaterClothing::onClickWear(void* data)
00326 {
00327 LLFloaterClothing* self = (LLFloaterClothing*)data;
00328
00329 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
00330
00331 LLViewerInventoryItem* inv_item = gInventory.getItem(item_id);
00332 if (!inv_item)
00333 {
00334 llwarns << "Can't find inventory item to wear" << llendl;
00335 return;
00336 }
00337
00338 wear_inventory_item_on_avatar(inv_item);
00339 }
00340
00341 BOOL wearable_can_take_off(EWearableType wearable_type)
00342 {
00343 switch(wearable_type)
00344 {
00345 default:
00346 case WT_SHAPE:
00347 case WT_SKIN:
00348 case WT_HAIR:
00349 case WT_EYES:
00350 return FALSE;
00351 case WT_SHIRT:
00352 case WT_PANTS:
00353 case WT_SHOES:
00354 case WT_SOCKS:
00355 case WT_JACKET:
00356 case WT_GLOVES:
00357 case WT_SKIRT:
00358 return TRUE;
00359 case WT_UNDERSHIRT:
00360 case WT_UNDERPANTS:
00361
00362 return (!gAgent.isTeen());
00363 }
00364 }
00365
00366
00367 void LLFloaterClothing::onClickTakeOff(void* data)
00368 {
00369 LLFloaterClothing* self = (LLFloaterClothing*)data;
00370
00371 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
00372
00373 LLInventoryItem* inv_item = gInventory.getItem(item_id);
00374 if (!inv_item)
00375 {
00376 llwarns << "Can't find inventory item to wear" << llendl;
00377 return;
00378 }
00379
00380 LLVOAvatar* avatar = gAgent.getAvatarObject();
00381 if( !avatar ) return;
00382
00383 EWearableType wearable_type = (EWearableType)inv_item->getFlags();
00384
00385
00386 if (!wearable_can_take_off(wearable_type)) return;
00387
00388 LLWearable* wearable = gAgent.getWearable(wearable_type);
00389 if( !wearable ) return;
00390
00391 gAgent.removeWearable(wearable_type);
00392 }
00393
00394
00395
00396 void LLFloaterClothing::onCommitList(LLUICtrl* ctrl, void* data)
00397 {
00398 LLFloaterClothing* self = (LLFloaterClothing*)data;
00399
00400 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
00401 self->mSelectedID = item_id;
00402
00403 LLVOAvatar* avatar = gAgent.getAvatarObject();
00404 if( !avatar ) return;
00405
00406 if(gAgent.isWearingItem( item_id ) )
00407 {
00408
00409 self->childDisable("wear_btn");
00410
00411 LLInventoryItem* inv_item = gInventory.getItem(item_id);
00412 if (!inv_item) return;
00413
00414 EWearableType wearable_type = (EWearableType)inv_item->getFlags();
00415 BOOL can_take_off = wearable_can_take_off(wearable_type);
00416 self->childSetEnabled("take_off_btn", can_take_off);
00417 }
00418 else
00419 {
00420
00421 self->childEnable("wear_btn");
00422 self->childEnable("take_off_btn");
00423 }
00424 }