llfloaterclothing.cpp

Go to the documentation of this file.
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 // static
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 // LLFloaterClothing
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 // virtual
00102 LLFloaterClothing::~LLFloaterClothing()
00103 {
00104         gInventory.removeObserver(sObserver);
00105         delete sObserver;
00106         sObserver = NULL;
00107 
00108         sInstance = NULL;
00109 }
00110 
00111 
00112 // virtual
00113 void LLFloaterClothing::onClose(bool app_quitting)
00114 {
00115         gSavedSettings.setBOOL("ClothingBtnState", FALSE);
00116 
00117         LLFloater::onClose(app_quitting);
00118 }
00119 
00120 
00121 // static
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                 // Update button labels
00144                 onCommitList(NULL, self);
00145         }
00146 
00147         gSavedSettings.setBOOL("ClothingBtnState", TRUE);
00148 }
00149 
00150 // static
00151 void LLFloaterClothing::toggleVisibility()
00152 {
00153         if(sInstance && sInstance->getVisible())
00154         {
00155                 sInstance->close();
00156         }
00157         else
00158         {
00159                 show();
00160         }
00161 }
00162 
00163 // static
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                                 // no selection, no commit on change
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                         // Update button labels
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         //llinfos << "buildClothingList" << llendl;
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);              // flags = wearable type
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                 // hidden column for sorting
00296                 U32 flags = item->getFlags();   // flags = wearable type
00297                 enum EWearableType wearable_type = (enum EWearableType)flags;
00298                 const char* wearable_label = LLWearable::typeToTypeLabel(wearable_type);
00299                 //line->addColumn(wearable_label, FONT, -1);    // invisible
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                 // We're loading
00313                 list->addSimpleElement(LOADING_STRING);
00314                 mAllowSelection = FALSE;
00315         }
00316         else
00317         {
00318                 // Weird case, we're done loading but have no clothing
00319                 list->addSimpleElement("No clothing found.");
00320                 mAllowSelection = FALSE;
00321         }
00322 }
00323 
00324 // static
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                 // can't take off underpants with PG accounts
00362                 return (!gAgent.isTeen());
00363         }
00364 }
00365 
00366 // static
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         // Can only take off certain types
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 // static
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                 // If already wearing, can't wear again
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                 // Can always wear something you're not wearing now
00421                 self->childEnable("wear_btn");
00422                 self->childEnable("take_off_btn");
00423         }
00424 }

Generated on Thu Jul 1 06:08:32 2010 for Second Life Viewer by  doxygen 1.4.7