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 "lluictrlfactory.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 LLUICtrlFactory::getInstance()->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 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("clothing_list");
00091 if (list)
00092 {
00093 list->addCommentText(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 LLScrollListCtrl* list = getChild<LLScrollListCtrl>("clothing_list");
00248
00249 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
00250
00251 LLInventoryModel::cat_array_t cats;
00252 LLInventoryModel::item_array_t items;
00253
00254 LLIsClothing is_clothing;
00255 gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
00256 cats,
00257 items,
00258 LLInventoryModel::EXCLUDE_TRASH,
00259 is_clothing);
00260
00261 S32 count = items.count();
00262 for(S32 i = 0; i < count; ++i)
00263 {
00264 LLInventoryItem* item = items.get(i);
00265
00266 LLSD row;
00267 row["id"] = item->getUUID();
00268
00269 BOOL item_is_multi = FALSE;
00270 if ( item->getFlags() & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS )
00271 {
00272 item_is_multi = TRUE;
00273 }
00274
00275 LLString icon_name = get_item_icon_name(item->getType(),
00276 item->getInventoryType(),
00277 item->getFlags(), item_is_multi);
00278 row["columns"][0]["column"] = "icon";
00279 row["columns"][0]["type"] = "icon";
00280 row["columns"][0]["value"] = icon_name;
00281
00282 LLString text = item->getName();
00283 LLString style = "NORMAL";
00284 if( gAgent.isWearingItem( item->getUUID() ) )
00285 {
00286 text.append(" (worn)");
00287 style = "BOLD";
00288 }
00289 row["columns"][1]["column"] = "name";
00290 row["columns"][1]["value"] = text;
00291 row["columns"][1]["font"] = "SANSSERIFSMALL";
00292 row["columns"][1]["font-style"] = style;
00293
00294
00295 U32 flags = item->getFlags();
00296 enum EWearableType wearable_type = (enum EWearableType)flags;
00297 const char* wearable_label = LLWearable::typeToTypeLabel(wearable_type);
00298
00299 row["columns"][2]["column"] = "sort";
00300 row["columns"][2]["value"] = wearable_label;
00301
00302 list->addElement(row);
00303 }
00304
00305 if (count > 0)
00306 {
00307 mAllowSelection = TRUE;
00308 }
00309 else if (LLInventoryModel::backgroundFetchActive())
00310 {
00311
00312 list->addCommentText(LOADING_STRING);
00313 mAllowSelection = FALSE;
00314 }
00315 else
00316 {
00317
00318 list->addCommentText("No clothing found.");
00319 mAllowSelection = FALSE;
00320 }
00321 }
00322
00323
00324 void LLFloaterClothing::onClickWear(void* data)
00325 {
00326 LLFloaterClothing* self = (LLFloaterClothing*)data;
00327
00328 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
00329
00330 LLViewerInventoryItem* inv_item = gInventory.getItem(item_id);
00331 if (!inv_item)
00332 {
00333 llwarns << "Can't find inventory item to wear" << llendl;
00334 return;
00335 }
00336
00337 wear_inventory_item_on_avatar(inv_item);
00338 }
00339
00340 BOOL wearable_can_take_off(EWearableType wearable_type)
00341 {
00342 switch(wearable_type)
00343 {
00344 default:
00345 case WT_SHAPE:
00346 case WT_SKIN:
00347 case WT_HAIR:
00348 case WT_EYES:
00349 return FALSE;
00350 case WT_SHIRT:
00351 case WT_PANTS:
00352 case WT_SHOES:
00353 case WT_SOCKS:
00354 case WT_JACKET:
00355 case WT_GLOVES:
00356 case WT_SKIRT:
00357 return TRUE;
00358 case WT_UNDERSHIRT:
00359 case WT_UNDERPANTS:
00360
00361 return (!gAgent.isTeen());
00362 }
00363 }
00364
00365
00366 void LLFloaterClothing::onClickTakeOff(void* data)
00367 {
00368 LLFloaterClothing* self = (LLFloaterClothing*)data;
00369
00370 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
00371
00372 LLInventoryItem* inv_item = gInventory.getItem(item_id);
00373 if (!inv_item)
00374 {
00375 llwarns << "Can't find inventory item to wear" << llendl;
00376 return;
00377 }
00378
00379 LLVOAvatar* avatar = gAgent.getAvatarObject();
00380 if( !avatar ) return;
00381
00382 EWearableType wearable_type = (EWearableType)inv_item->getFlags();
00383
00384
00385 if (!wearable_can_take_off(wearable_type)) return;
00386
00387 LLWearable* wearable = gAgent.getWearable(wearable_type);
00388 if( !wearable ) return;
00389
00390 gAgent.removeWearable(wearable_type);
00391 }
00392
00393
00394
00395 void LLFloaterClothing::onCommitList(LLUICtrl* ctrl, void* data)
00396 {
00397 LLFloaterClothing* self = (LLFloaterClothing*)data;
00398
00399 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
00400 self->mSelectedID = item_id;
00401
00402 LLVOAvatar* avatar = gAgent.getAvatarObject();
00403 if( !avatar ) return;
00404
00405 if(gAgent.isWearingItem( item_id ) )
00406 {
00407
00408 self->childDisable("wear_btn");
00409
00410 LLInventoryItem* inv_item = gInventory.getItem(item_id);
00411 if (!inv_item) return;
00412
00413 EWearableType wearable_type = (EWearableType)inv_item->getFlags();
00414 BOOL can_take_off = wearable_can_take_off(wearable_type);
00415 self->childSetEnabled("take_off_btn", can_take_off);
00416 }
00417 else
00418 {
00419
00420 self->childEnable("wear_btn");
00421 self->childEnable("take_off_btn");
00422 }
00423 }