aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfloaterclothing.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfloaterclothing.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llfloaterclothing.cpp')
-rw-r--r--linden/indra/newview/llfloaterclothing.cpp414
1 files changed, 414 insertions, 0 deletions
diff --git a/linden/indra/newview/llfloaterclothing.cpp b/linden/indra/newview/llfloaterclothing.cpp
new file mode 100644
index 0000000..627b2c6
--- /dev/null
+++ b/linden/indra/newview/llfloaterclothing.cpp
@@ -0,0 +1,414 @@
1/**
2 * @file llfloaterclothing.cpp
3 * @author James Cook
4 * @brief Read-only list of clothing from your inventory.
5 *
6 * Copyright (c) 2004-2007, Linden Research, Inc.
7 *
8 * The source code in this file ("Source Code") is provided by Linden Lab
9 * to you under the terms of the GNU General Public License, version 2.0
10 * ("GPL"), unless you have obtained a separate licensing agreement
11 * ("Other License"), formally executed by you and Linden Lab. Terms of
12 * the GPL can be found in doc/GPL-license.txt in this distribution, or
13 * online at http://secondlife.com/developers/opensource/gplv2
14 *
15 * There are special exceptions to the terms and conditions of the GPL as
16 * it is applied to this Source Code. View the full text of the exception
17 * in the file doc/FLOSS-exception.txt in this software distribution, or
18 * online at http://secondlife.com/developers/opensource/flossexception
19 *
20 * By copying, modifying or distributing this software, you acknowledge
21 * that you have read and understood your obligations described above,
22 * and agree to abide by those obligations.
23 *
24 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
25 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
26 * COMPLETENESS OR PERFORMANCE.
27 */
28
29#include "llviewerprecompiledheaders.h"
30
31#include "llfloaterclothing.h"
32
33#include "lldir.h"
34#include "llinventory.h"
35
36#include "llagent.h"
37#include "llinventorymodel.h"
38#include "llinventoryview.h"
39#include "llkeyboard.h"
40#include "llscrollbar.h"
41#include "llscrolllistctrl.h"
42#include "llvieweruictrlfactory.h"
43#include "llviewerinventory.h"
44#include "llvoavatar.h"
45#include "llviewercontrol.h"
46
47const LLString LOADING_STRING("Loading...");
48
49// static
50LLFloaterClothing* LLFloaterClothing::sInstance = NULL;
51LLFloaterClothingObserver* LLFloaterClothing::sObserver = NULL;
52
53class LLFloaterClothingObserver : public LLInventoryObserver
54{
55public:
56 LLFloaterClothingObserver() {}
57 virtual ~LLFloaterClothingObserver() {}
58
59 virtual void changed(U32 mask)
60 {
61 LLFloaterClothing::refreshAll();
62 }
63};
64
65//---------------------------------------------------------------------------
66// LLFloaterClothing
67//---------------------------------------------------------------------------
68LLFloaterClothing::LLFloaterClothing()
69: LLFloater("floater_clothing", "FloaterClothingRect", ""),
70 mSelectedID(),
71 mAllowSelection(FALSE)
72{
73 gUICtrlFactory->buildFloater(this, "floater_clothing.xml");
74
75 sInstance = this;
76
77 sObserver = new LLFloaterClothingObserver;
78 gInventory.addObserver(sObserver);
79
80 childSetAction("take_off_btn", onClickTakeOff, this);
81 childSetAction("wear_btn", onClickWear, this);
82
83 childSetDoubleClickCallback("clothing_list", onClickWear);
84 childSetCommitCallback("clothing_list", onCommitList, this);
85
86 LLCtrlListInterface* list = childGetListInterface("clothing_list");
87 if (list)
88 {
89 list->addSimpleElement(LOADING_STRING);
90 }
91
92 setDefaultBtn("wear_btn");
93
94 gInventory.startBackgroundFetch();
95}
96
97// virtual
98LLFloaterClothing::~LLFloaterClothing()
99{
100 gInventory.removeObserver(sObserver);
101 delete sObserver;
102 sObserver = NULL;
103
104 sInstance = NULL;
105}
106
107
108// virtual
109void LLFloaterClothing::onClose(bool app_quitting)
110{
111 gSavedSettings.setBOOL("ClothingBtnState", FALSE);
112
113 LLFloater::onClose(app_quitting);
114}
115
116
117// static
118void LLFloaterClothing::show(void*)
119{
120 if (sInstance)
121 {
122 sInstance->setVisibleAndFrontmost();
123 }
124 else
125 {
126 LLFloaterClothing *self = new LLFloaterClothing();
127
128 self->buildClothingList();
129
130 if (self->mAllowSelection)
131 {
132 LLCtrlSelectionInterface* iface = self->childGetSelectionInterface("clothing_list");
133 if (iface) iface->selectFirstItem();
134 }
135 self->childSetFocus("clothing_list");
136
137 self->mSelectedID = LLUUID::null;
138
139 // Update button labels
140 onCommitList(NULL, self);
141 }
142
143 gSavedSettings.setBOOL("ClothingBtnState", TRUE);
144}
145
146// static
147void LLFloaterClothing::toggleVisibility()
148{
149 if(sInstance && sInstance->getVisible())
150 {
151 sInstance->close();
152 }
153 else
154 {
155 show();
156 }
157}
158
159// static
160void LLFloaterClothing::refreshAll()
161{
162 if (sInstance)
163 {
164 sInstance->buildClothingList();
165
166 LLCtrlListInterface* list = sInstance->childGetListInterface("clothing_list");
167 if (list)
168 {
169 if (!sInstance->mAllowSelection)
170 {
171 // no selection, no commit on change
172 list->operateOnSelection(LLCtrlListInterface::OP_DESELECT);
173 }
174 else if (sInstance->mSelectedID.isNull())
175 {
176 list->selectFirstItem();
177 }
178 else
179 {
180 if (list->setCurrentByID(sInstance->mSelectedID))
181 {
182 LLCtrlScrollInterface *scroll = sInstance->childGetScrollInterface("clothing_list");
183 if (scroll)
184 {
185 scroll->scrollToShowSelected();
186 }
187 }
188 else
189 {
190 list->selectFirstItem();
191 }
192 }
193
194 // Update button labels
195 onCommitList(NULL, sInstance);
196 }
197 }
198}
199
200class LLIsClothing : public LLInventoryCollectFunctor
201{
202public:
203 LLIsClothing() {}
204 virtual ~LLIsClothing() {}
205 virtual bool operator()(LLInventoryCategory* cat,
206 LLInventoryItem* item)
207 {
208 if (item)
209 {
210 LLAssetType::EType at = item->getType();
211 if (at == LLAssetType::AT_CLOTHING
212 || at == LLAssetType::AT_BODYPART)
213 {
214 U32 flags = item->getFlags();
215 switch(flags)
216 {
217 case WT_SHAPE:
218 case WT_SKIN:
219 case WT_HAIR:
220 case WT_EYES:
221 return FALSE;
222 case WT_SHIRT:
223 case WT_PANTS:
224 case WT_SKIRT:
225 case WT_UNDERSHIRT:
226 case WT_UNDERPANTS:
227 return TRUE;
228 default:
229 return TRUE;
230 }
231 }
232 }
233 return FALSE;
234 }
235};
236
237
238
239void LLFloaterClothing::buildClothingList()
240{
241 //llinfos << "buildClothingList" << llendl;
242
243 LLCtrlListInterface *list = childGetListInterface("clothing_list");
244 if (!list) return;
245
246 list->operateOnAll(LLCtrlListInterface::OP_DELETE);
247
248 LLInventoryModel::cat_array_t cats;
249 LLInventoryModel::item_array_t items;
250
251 LLIsClothing is_clothing;
252 gInventory.collectDescendentsIf(gAgent.getInventoryRootID(),
253 cats,
254 items,
255 LLInventoryModel::EXCLUDE_TRASH,
256 is_clothing);
257
258 S32 count = items.count();
259 for(S32 i = 0; i < count; ++i)
260 {
261 LLInventoryItem* item = items.get(i);
262
263 LLSD row;
264 row["id"] = item->getUUID();
265
266 LLUUID image_id = get_item_icon_uuid(item->getType(),
267 item->getInventoryType(),
268 item->getFlags()); // flags = wearable type
269 row["columns"][0]["column"] = "icon";
270 row["columns"][0]["type"] = "icon";
271 row["columns"][0]["value"] = image_id;
272
273 LLString text = item->getName();
274 LLString style = "NORMAL";
275 if( gAgent.isWearingItem( item->getUUID() ) )
276 {
277 text.append(" (worn)");
278 style = "BOLD";
279 }
280 row["columns"][1]["column"] = "name";
281 row["columns"][1]["value"] = text;
282 row["columns"][1]["font"] = "SANSSERIFSMALL";
283 row["columns"][1]["font-style"] = style;
284
285 // hidden column for sorting
286 U32 flags = item->getFlags(); // flags = wearable type
287 enum EWearableType wearable_type = (enum EWearableType)flags;
288 const char* wearable_label = LLWearable::typeToTypeLabel(wearable_type);
289 //line->addColumn(wearable_label, FONT, -1); // invisible
290 row["columns"][2]["column"] = "sort";
291 row["columns"][2]["value"] = wearable_label;
292
293 list->addElement(row);
294 }
295
296 if (count > 0)
297 {
298 mAllowSelection = TRUE;
299 }
300 else if (LLInventoryModel::backgroundFetchActive())
301 {
302 // We're loading
303 list->addSimpleElement(LOADING_STRING);
304 mAllowSelection = FALSE;
305 }
306 else
307 {
308 // Weird case, we're done loading but have no clothing
309 list->addSimpleElement("No clothing found.");
310 mAllowSelection = FALSE;
311 }
312}
313
314// static
315void LLFloaterClothing::onClickWear(void* data)
316{
317 LLFloaterClothing* self = (LLFloaterClothing*)data;
318
319 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
320
321 LLViewerInventoryItem* inv_item = gInventory.getItem(item_id);
322 if (!inv_item)
323 {
324 llwarns << "Can't find inventory item to wear" << llendl;
325 return;
326 }
327
328 wear_inventory_item_on_avatar(inv_item);
329}
330
331BOOL wearable_can_take_off(EWearableType wearable_type)
332{
333 switch(wearable_type)
334 {
335 default:
336 case WT_SHAPE:
337 case WT_SKIN:
338 case WT_HAIR:
339 case WT_EYES:
340 return FALSE;
341 case WT_SHIRT:
342 case WT_PANTS:
343 case WT_SHOES:
344 case WT_SOCKS:
345 case WT_JACKET:
346 case WT_GLOVES:
347 case WT_SKIRT:
348 return TRUE;
349 case WT_UNDERSHIRT:
350 case WT_UNDERPANTS:
351 // can't take off underpants with PG accounts
352 return (gAgent.mAccess >= SIM_ACCESS_MATURE);
353 }
354}
355
356// static
357void LLFloaterClothing::onClickTakeOff(void* data)
358{
359 LLFloaterClothing* self = (LLFloaterClothing*)data;
360
361 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
362
363 LLInventoryItem* inv_item = gInventory.getItem(item_id);
364 if (!inv_item)
365 {
366 llwarns << "Can't find inventory item to wear" << llendl;
367 return;
368 }
369
370 LLVOAvatar* avatar = gAgent.getAvatarObject();
371 if( !avatar ) return;
372
373 EWearableType wearable_type = (EWearableType)inv_item->getFlags();
374
375 // Can only take off certain types
376 if (!wearable_can_take_off(wearable_type)) return;
377
378 LLWearable* wearable = gAgent.getWearable(wearable_type);
379 if( !wearable ) return;
380
381 gAgent.removeWearable(wearable_type);
382}
383
384
385// static
386void LLFloaterClothing::onCommitList(LLUICtrl* ctrl, void* data)
387{
388 LLFloaterClothing* self = (LLFloaterClothing*)data;
389
390 const LLUUID& item_id = self->childGetValue("clothing_list").asUUID();
391 self->mSelectedID = item_id;
392
393 LLVOAvatar* avatar = gAgent.getAvatarObject();
394 if( !avatar ) return;
395
396 if(gAgent.isWearingItem( item_id ) )
397 {
398 // If already wearing, can't wear again
399 self->childDisable("wear_btn");
400
401 LLInventoryItem* inv_item = gInventory.getItem(item_id);
402 if (!inv_item) return;
403
404 EWearableType wearable_type = (EWearableType)inv_item->getFlags();
405 BOOL can_take_off = wearable_can_take_off(wearable_type);
406 self->childSetEnabled("take_off_btn", can_take_off);
407 }
408 else
409 {
410 // Can always wear something you're not wearing now
411 self->childEnable("wear_btn");
412 self->childEnable("take_off_btn");
413 }
414}