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 "lluictrlfactory.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         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 // 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         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);              // flags = wearable type
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                 // hidden column for sorting
00295                 U32 flags = item->getFlags();   // flags = wearable type
00296                 enum EWearableType wearable_type = (enum EWearableType)flags;
00297                 const char* wearable_label = LLWearable::typeToTypeLabel(wearable_type);
00298                 //line->addColumn(wearable_label, FONT, -1);    // invisible
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                 // We're loading
00312                 list->addCommentText(LOADING_STRING);
00313                 mAllowSelection = FALSE;
00314         }
00315         else
00316         {
00317                 // Weird case, we're done loading but have no clothing
00318                 list->addCommentText("No clothing found.");
00319                 mAllowSelection = FALSE;
00320         }
00321 }
00322 
00323 // static
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                 // can't take off underpants with PG accounts
00361                 return (!gAgent.isTeen());
00362         }
00363 }
00364 
00365 // static
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         // Can only take off certain types
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 // static
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                 // If already wearing, can't wear again
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                 // Can always wear something you're not wearing now
00420                 self->childEnable("wear_btn");
00421                 self->childEnable("take_off_btn");
00422         }
00423 }

Generated on Fri May 16 08:33:23 2008 for SecondLife by  doxygen 1.5.5