00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llfloatercustomize.h"
00035 #include "llfontgl.h"
00036 #include "llbutton.h"
00037 #include "lliconctrl.h"
00038 #include "llresmgr.h"
00039 #include "llmorphview.h"
00040 #include "llfloatertools.h"
00041 #include "llagent.h"
00042 #include "lltoolmorph.h"
00043 #include "llvoavatar.h"
00044 #include "llradiogroup.h"
00045 #include "lltoolmgr.h"
00046 #include "llviewermenu.h"
00047 #include "llscrollcontainer.h"
00048 #include "llscrollingpanellist.h"
00049 #include "llsliderctrl.h"
00050 #include "lltabcontainervertical.h"
00051 #include "llviewerwindow.h"
00052 #include "llinventorymodel.h"
00053 #include "llinventoryview.h"
00054 #include "lltextbox.h"
00055 #include "lllineeditor.h"
00056 #include "llviewerimagelist.h"
00057 #include "llfocusmgr.h"
00058 #include "llviewerwindow.h"
00059 #include "llviewercamera.h"
00060 #include "llgenepool.h"
00061 #include "llappearance.h"
00062 #include "imageids.h"
00063 #include "llmodaldialog.h"
00064 #include "llassetstorage.h"
00065 #include "lltexturectrl.h"
00066 #include "lltextureentry.h"
00067 #include "llwearablelist.h"
00068 #include "llviewerinventory.h"
00069 #include "lldbstrings.h"
00070 #include "llcolorswatch.h"
00071 #include "llglheaders.h"
00072 #include "llui.h"
00073 #include "llviewermessage.h"
00074 #include "llimagejpeg.h"
00075 #include "llviewercontrol.h"
00076 #include "llvieweruictrlfactory.h"
00077
00078 #include "llfilepicker.h"
00079
00080
00081
00082
00083 LLFloaterCustomize* gFloaterCustomize = NULL;
00084
00085 const F32 PARAM_STEP_TIME_THRESHOLD = 0.25f;
00086
00088
00089
00090 class LLUndoWearable
00091 : public LLUndoAction
00092 {
00093 protected:
00094 LLAppearance mAppearance;
00095
00096 protected:
00097 LLUndoWearable() {};
00098 virtual ~LLUndoWearable(){};
00099
00100 public:
00101 static LLUndoAction *create() { return new LLUndoWearable(); }
00102
00103 void setVisualParam(S32 param_id, F32 weight);
00104 void setColor( LLVOAvatar::ETextureIndex te, const LLColor4& color );
00105 void setTexture( LLVOAvatar::ETextureIndex te, const LLUUID& asset_id );
00106 void setWearable( EWearableType type );
00107
00108 virtual void undo() {applyUndoRedo();}
00109 virtual void redo() {applyUndoRedo();}
00110 void applyUndoRedo();
00111 };
00112
00113
00115
00116
00117 class LLFloaterCustomizeObserver : public LLInventoryObserver
00118 {
00119 public:
00120 LLFloaterCustomizeObserver(LLFloaterCustomize* fc) : mFC(fc) {}
00121 virtual ~LLFloaterCustomizeObserver() {}
00122 virtual void changed(U32 mask) { mFC->updateScrollingPanelUI(); }
00123 protected:
00124 LLFloaterCustomize* mFC;
00125 };
00126
00128
00129
00130
00131 class LLWearableSaveAsDialog : public LLModalDialog
00132 {
00133 private:
00134 LLString mItemName;
00135 void (*mCommitCallback)(LLWearableSaveAsDialog*,void*);
00136 void* mCallbackUserData;
00137
00138 public:
00139 LLWearableSaveAsDialog( const LLString& desc, void(*commit_cb)(LLWearableSaveAsDialog*,void*), void* userdata )
00140 : LLModalDialog( "", 240, 100 ),
00141 mCommitCallback( commit_cb ),
00142 mCallbackUserData( userdata )
00143 {
00144 gUICtrlFactory->buildFloater(this, "floater_wearable_save_as.xml");
00145
00146 childSetAction("Save", LLWearableSaveAsDialog::onSave, this );
00147 childSetAction("Cancel", LLWearableSaveAsDialog::onCancel, this );
00148 childSetTextArg("name ed", "[DESC]", desc);
00149 }
00150
00151 virtual void startModal()
00152 {
00153 LLModalDialog::startModal();
00154 LLLineEditor* edit = LLUICtrlFactory::getLineEditorByName(this, "name ed");
00155 if (!edit) return;
00156 edit->setFocus(TRUE);
00157 edit->selectAll();
00158 }
00159
00160 const LLString& getItemName() { return mItemName; }
00161
00162 static void onSave( void* userdata )
00163 {
00164 LLWearableSaveAsDialog* self = (LLWearableSaveAsDialog*) userdata;
00165 self->mItemName = self->childGetValue("name ed").asString();
00166 LLString::trim(self->mItemName);
00167 if( !self->mItemName.empty() )
00168 {
00169 if( self->mCommitCallback )
00170 {
00171 self->mCommitCallback( self, self->mCallbackUserData );
00172 }
00173 self->close();
00174 }
00175 }
00176
00177 static void onCancel( void* userdata )
00178 {
00179 LLWearableSaveAsDialog* self = (LLWearableSaveAsDialog*) userdata;
00180 self->close();
00181 }
00182 };
00183
00185
00186 BOOL edit_wearable_for_teens(EWearableType type)
00187 {
00188 switch(type)
00189 {
00190 case WT_UNDERSHIRT:
00191 case WT_UNDERPANTS:
00192 return FALSE;
00193 default:
00194 return TRUE;
00195 }
00196 }
00197
00198 class LLMakeOutfitDialog : public LLModalDialog
00199 {
00200 private:
00201 LLString mFolderName;
00202 void (*mCommitCallback)(LLMakeOutfitDialog*,void*);
00203 void* mCallbackUserData;
00204 std::vector<std::pair<std::string,S32> > mCheckBoxList;
00205
00206 public:
00207 LLMakeOutfitDialog( void(*commit_cb)(LLMakeOutfitDialog*,void*), void* userdata )
00208 : LLModalDialog("",515, 510, TRUE ),
00209 mCommitCallback( commit_cb ),
00210 mCallbackUserData( userdata )
00211 {
00212 gUICtrlFactory->buildFloater(this, "floater_new_outfit_dialog.xml");
00213
00214
00215 for( S32 i = 0; i < WT_COUNT; i++ )
00216 {
00217 LLString name = LLString("checkbox_") + LLWearable::typeToTypeLabel( (EWearableType)i );
00218 mCheckBoxList.push_back(std::make_pair(name,i));
00219
00220 if (gAgent.isTeen() &&
00221 !edit_wearable_for_teens((EWearableType)i))
00222 {
00223
00224 LLString name = LLString("checkbox_") + LLWearable::typeToTypeLabel( (EWearableType)i );
00225 childSetVisible(name, FALSE);
00226 }
00227 }
00228
00229
00230 LLVOAvatar* avatar = gAgent.getAvatarObject();
00231 if( avatar )
00232 {
00233 for (LLViewerJointAttachment* attachment = avatar->mAttachmentPoints.getFirstData();
00234 attachment;
00235 attachment = gAgent.getAvatarObject()->mAttachmentPoints.getNextData())
00236 {
00237 BOOL object_attached = ( attachment->getNumObjects() > 0 );
00238 S32 attachment_pt = avatar->mAttachmentPoints.getCurrentKeyWithoutIncrement();
00239 LLString name = LLString("checkbox_") + attachment->getName();
00240 mCheckBoxList.push_back(std::make_pair(name,attachment_pt));
00241 childSetEnabled(name, object_attached);
00242 }
00243 }
00244
00245 childSetAction("Save", onSave, this );
00246 childSetAction("Cancel", onCancel, this );
00247 }
00248
00249 BOOL getRenameClothing()
00250 {
00251 return childGetValue("rename").asBoolean();
00252
00253 }
00254 virtual void draw()
00255 {
00256 BOOL one_or_more_items_selected = FALSE;
00257 for( S32 i = 0; i < (S32)mCheckBoxList.size(); i++ )
00258 {
00259 if( childGetValue(mCheckBoxList[i].first).asBoolean() )
00260 {
00261 one_or_more_items_selected = TRUE;
00262 break;
00263 }
00264 }
00265
00266 childSetEnabled("Save", one_or_more_items_selected );
00267
00268 LLModalDialog::draw();
00269 }
00270
00271 const LLString& getFolderName() { return mFolderName; }
00272
00273 void setWearableToInclude( S32 wearable, S32 enabled, S32 selected )
00274 {
00275 if( (0 <= wearable) && (wearable < WT_COUNT) )
00276 {
00277 LLString name = LLString("checkbox_") + LLWearable::typeToTypeLabel( (EWearableType)wearable );
00278 childSetEnabled(name, enabled);
00279 childSetValue(name, selected);
00280 }
00281 }
00282
00283 void getIncludedItems( LLDynamicArray<S32> &wearables_to_include, LLDynamicArray<S32> &attachments_to_include )
00284 {
00285 for( S32 i = 0; i < (S32)mCheckBoxList.size(); i++)
00286 {
00287 LLString name = mCheckBoxList[i].first;
00288 BOOL checked = childGetValue(name).asBoolean();
00289 if (i < WT_COUNT )
00290 {
00291 if( checked )
00292 {
00293 wearables_to_include.put(i);
00294 }
00295 }
00296 else
00297 {
00298 if( checked )
00299 {
00300 S32 attachment_pt = mCheckBoxList[i].second;
00301 attachments_to_include.put( attachment_pt );
00302 }
00303 }
00304 }
00305 }
00306
00307 static void onSave( void* userdata )
00308 {
00309 LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata;
00310 self->mFolderName = self->childGetValue("name ed").asString();
00311 LLString::trim(self->mFolderName);
00312 if( !self->mFolderName.empty() )
00313 {
00314 if( self->mCommitCallback )
00315 {
00316 self->mCommitCallback( self, self->mCallbackUserData );
00317 }
00318 self->close();
00319 }
00320 }
00321
00322 static void onCancel( void* userdata )
00323 {
00324 LLMakeOutfitDialog* self = (LLMakeOutfitDialog*) userdata;
00325 self->close();
00326 }
00327 };
00328
00330
00331
00332 enum ESubpart {
00333 SUBPART_SHAPE_HEAD = 1,
00334 SUBPART_SHAPE_EYES,
00335 SUBPART_SHAPE_EARS,
00336 SUBPART_SHAPE_NOSE,
00337 SUBPART_SHAPE_MOUTH,
00338 SUBPART_SHAPE_CHIN,
00339 SUBPART_SHAPE_TORSO,
00340 SUBPART_SHAPE_LEGS,
00341 SUBPART_SHAPE_WHOLE,
00342 SUBPART_SHAPE_DETAIL,
00343 SUBPART_SKIN_COLOR,
00344 SUBPART_SKIN_FACEDETAIL,
00345 SUBPART_SKIN_MAKEUP,
00346 SUBPART_SKIN_BODYDETAIL,
00347 SUBPART_HAIR_COLOR,
00348 SUBPART_HAIR_STYLE,
00349 SUBPART_HAIR_EYEBROWS,
00350 SUBPART_HAIR_FACIAL,
00351 SUBPART_EYES,
00352 SUBPART_SHIRT,
00353 SUBPART_PANTS,
00354 SUBPART_SHOES,
00355 SUBPART_SOCKS,
00356 SUBPART_JACKET,
00357 SUBPART_GLOVES,
00358 SUBPART_UNDERSHIRT,
00359 SUBPART_UNDERPANTS,
00360 SUBPART_SKIRT
00361 };
00362
00363 struct LLSubpart
00364 {
00365 LLSubpart() : mSex( SEX_BOTH ) {}
00366
00367 LLString mButtonName;
00368 LLString mTargetJoint;
00369 LLString mEditGroup;
00370 LLVector3d mTargetOffset;
00371 LLVector3d mCameraOffset;
00372 ESex mSex;
00373 };
00374
00376
00377 class LLPanelEditWearable : public LLPanel, public LLEditMenuHandler
00378 {
00379 public:
00380 LLPanelEditWearable( EWearableType type );
00381 virtual ~LLPanelEditWearable();
00382
00383 virtual BOOL postBuild();
00384 virtual void draw();
00385 virtual BOOL isDirty() const;
00386
00387 void addSubpart(const LLString& name, ESubpart id, LLSubpart* part );
00388 void addTextureDropTarget( LLVOAvatar::ETextureIndex te, const LLString& name, const LLUUID& default_image_id, BOOL allow_no_texture );
00389 void addColorSwatch( LLVOAvatar::ETextureIndex te, const LLString& name );
00390
00391 const char* getLabel() { return LLWearable::typeToTypeLabel( mType ); }
00392 EWearableType getType() { return mType; }
00393
00394 LLSubpart* getCurrentSubpart() { return mSubpartList[mCurrentSubpart]; }
00395 ESubpart getDefaultSubpart();
00396 void setSubpart( ESubpart subpart );
00397 void switchToDefaultSubpart();
00398
00399 void setWearable(LLWearable* wearable, U32 perm_mask, BOOL is_complete);
00400
00401 void addVisualParamToUndoBuffer( S32 param_id, F32 current_weight );
00402
00403 void setUIPermissions(U32 perm_mask, BOOL is_complete);
00404
00405 virtual void setVisible( BOOL visible );
00406
00407
00408 virtual void undo();
00409 virtual BOOL canUndo();
00410 virtual void redo();
00411 virtual BOOL canRedo();
00412
00413
00414 static void onBtnSubpart( void* userdata );
00415 static void onBtnTakeOff( void* userdata );
00416 static void onBtnRandomize( void* userdata );
00417 static void onBtnSave( void* userdata );
00418
00419 static void onBtnSaveAs( void* userdata );
00420 static void onSaveAsCommit( LLWearableSaveAsDialog* save_as_dialog, void* userdata );
00421
00422 static void onBtnRevert( void* userdata );
00423 static void onBtnTakeOffDialog( S32 option, void* userdata );
00424 static void onBtnCreateNew( void* userdata );
00425 static void onTextureCommit( LLUICtrl* ctrl, void* userdata );
00426 static void onColorCommit( LLUICtrl* ctrl, void* userdata );
00427 static void onCommitSexChange( LLUICtrl*, void* userdata );
00428 static void onSelectAutoWearOption(S32 option, void* data);
00429
00430
00431
00432 private:
00433 EWearableType mType;
00434 BOOL mCanTakeOff;
00435 std::map<LLString, S32> mTextureList;
00436 std::map<LLString, S32> mColorList;
00437 std::map<ESubpart, LLSubpart*> mSubpartList;
00438 ESubpart mCurrentSubpart;
00439 LLUndoBuffer* mUndoBuffer;
00440 };
00441
00443
00444 LLPanelEditWearable::LLPanelEditWearable( EWearableType type )
00445 : LLPanel( LLWearable::typeToTypeLabel( type ) ),
00446 mType( type )
00447 {
00448 const S32 NUM_DISTORTION_UNDO_ENTRIES = 50;
00449 mUndoBuffer = new LLUndoBuffer(LLUndoWearable::create, NUM_DISTORTION_UNDO_ENTRIES);
00450 }
00451
00452 BOOL LLPanelEditWearable::postBuild()
00453 {
00454 LLAssetType::EType asset_type = LLWearable::typeToAssetType( mType );
00455 LLUUID icon_id( gViewerArt.getString(asset_type == LLAssetType::AT_CLOTHING ?
00456 "inv_item_clothing.tga" :
00457 "inv_item_bodypart.tga" ) );
00458 childSetValue("icon", icon_id);
00459
00460 childSetAction("Create New", LLPanelEditWearable::onBtnCreateNew, this );
00461
00462
00463 mCanTakeOff =
00464 LLWearable::typeToAssetType( mType ) == LLAssetType::AT_CLOTHING &&
00465 !( gAgent.isTeen() && (mType == WT_UNDERSHIRT || mType == WT_UNDERPANTS) );
00466 childSetVisible("Take Off", mCanTakeOff);
00467 childSetAction("Take Off", LLPanelEditWearable::onBtnTakeOff, this );
00468
00469 childSetAction("Save", &LLPanelEditWearable::onBtnSave, (void*)this );
00470
00471 childSetAction("Save As", &LLPanelEditWearable::onBtnSaveAs, (void*)this );
00472
00473 childSetAction("Revert", &LLPanelEditWearable::onBtnRevert, (void*)this );
00474
00475 return TRUE;
00476 }
00477
00478 LLPanelEditWearable::~LLPanelEditWearable()
00479 {
00480 delete mUndoBuffer;
00481
00482 std::for_each(mSubpartList.begin(), mSubpartList.end(), DeletePairedPointer());
00483
00484
00485 if( gEditMenuHandler == this )
00486 {
00487 gEditMenuHandler = NULL;
00488 }
00489 }
00490
00491 void LLPanelEditWearable::addSubpart( const LLString& name, ESubpart id, LLSubpart* part )
00492 {
00493 if (!name.empty())
00494 {
00495 childSetAction(name, &LLPanelEditWearable::onBtnSubpart, (void*)id);
00496 part->mButtonName = name;
00497 }
00498 mSubpartList[id] = part;
00499
00500 }
00501
00502
00503 void LLPanelEditWearable::onBtnSubpart(void* userdata)
00504 {
00505 LLFloaterCustomize* floater_customize = gFloaterCustomize;
00506 if (!floater_customize) return;
00507 LLPanelEditWearable* self = floater_customize->getCurrentWearablePanel();
00508 if (!self) return;
00509 ESubpart subpart = (ESubpart) (intptr_t)userdata;
00510 self->setSubpart( subpart );
00511 }
00512
00513 void LLPanelEditWearable::setSubpart( ESubpart subpart )
00514 {
00515 mCurrentSubpart = subpart;
00516
00517 for (std::map<ESubpart, LLSubpart*>::iterator iter = mSubpartList.begin();
00518 iter != mSubpartList.end(); ++iter)
00519 {
00520 LLButton* btn = LLUICtrlFactory::getButtonByName(this, iter->second->mButtonName);
00521 if (btn)
00522 {
00523 btn->setToggleState( subpart == iter->first );
00524 }
00525 }
00526
00527 LLSubpart* part = get_if_there(mSubpartList, (ESubpart)subpart, (LLSubpart*)NULL);
00528 if( part )
00529 {
00530
00531 LLFloaterCustomize::param_map sorted_params;
00532 LLVOAvatar* avatar = gAgent.getAvatarObject();
00533 ESex avatar_sex = avatar->getSex();
00534 LLViewerInventoryItem* item;
00535 item = (LLViewerInventoryItem*)gAgent.getWearableInventoryItem(mType);
00536 U32 perm_mask = 0x0;
00537 BOOL is_complete = FALSE;
00538 if(item)
00539 {
00540 perm_mask = item->getPermissions().getMaskOwner();
00541 is_complete = item->isComplete();
00542 }
00543 setUIPermissions(perm_mask, is_complete);
00544 BOOL editable = ((perm_mask & PERM_MODIFY) && is_complete) ? TRUE : FALSE;
00545
00546 for(LLViewerVisualParam* param = (LLViewerVisualParam *)avatar->getFirstVisualParam();
00547 param;
00548 param = (LLViewerVisualParam *)avatar->getNextVisualParam())
00549 {
00550 if (param->getID() == -1
00551 || param->getGroup() != VISUAL_PARAM_GROUP_TWEAKABLE
00552 || param->getEditGroup() != part->mEditGroup
00553 || !(param->getSex() & avatar_sex))
00554 {
00555 continue;
00556 }
00557
00558
00559 LLFloaterCustomize::param_map::value_type vt(-param->getDisplayOrder(), LLFloaterCustomize::editable_param(editable, param));
00560 llassert( sorted_params.find(-param->getDisplayOrder()) == sorted_params.end() );
00561 sorted_params.insert(vt);
00562 }
00563 gFloaterCustomize->generateVisualParamHints(NULL, sorted_params);
00564 gFloaterCustomize->updateScrollingPanelUI();
00565
00566
00567
00568 gMorphView->setCameraTargetJoint( gAgent.getAvatarObject()->getJoint( part->mTargetJoint ) );
00569 gMorphView->setCameraTargetOffset( part->mTargetOffset );
00570 gMorphView->setCameraOffset( part->mCameraOffset );
00571 gMorphView->setCameraDistToDefault();
00572 if (gSavedSettings.getBOOL("AppearanceCameraMovement"))
00573 {
00574 gMorphView->updateCamera();
00575 }
00576 }
00577 }
00578
00579
00580 void LLPanelEditWearable::onBtnRandomize( void* userdata )
00581 {
00582 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00583
00584 LLVOAvatar* avatar = gAgent.getAvatarObject();
00585 LLViewerInventoryItem* item = (LLViewerInventoryItem*)gAgent.getWearableInventoryItem(self->mType);
00586 if(avatar
00587 && item
00588 && item->getPermissions().allowModifyBy(gAgent.getID(), gAgent.getGroupID())
00589 && item->isComplete())
00590 {
00591
00592 LLUndoWearable* action = (LLUndoWearable*)(self->mUndoBuffer->getNextAction());
00593 action->setWearable( self->mType );
00594
00595 ESex old_sex = avatar->getSex();
00596
00597 gFloaterCustomize->spawnWearableAppearance( self->mType );
00598
00599 gFloaterCustomize->updateScrollingPanelList(TRUE);
00600
00601 ESex new_sex = avatar->getSex();
00602 if( old_sex != new_sex )
00603 {
00604
00605 gSavedSettings.setU32("AvatarSex", (new_sex == SEX_MALE) );
00606
00607
00608 self->setSubpart( SUBPART_SHAPE_WHOLE );
00609 }
00610 }
00611 }
00612
00613
00614
00615 void LLPanelEditWearable::onBtnTakeOff( void* userdata )
00616 {
00617 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00618
00619 LLWearable* wearable = gAgent.getWearable( self->mType );
00620 if( !wearable )
00621 {
00622 return;
00623 }
00624
00625 gAgent.removeWearable( self->mType );
00626 }
00627
00628
00629 void LLPanelEditWearable::onBtnSave( void* userdata )
00630 {
00631 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00632 gAgent.saveWearable( self->mType );
00633 }
00634
00635
00636 void LLPanelEditWearable::onBtnSaveAs( void* userdata )
00637 {
00638 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00639 LLWearable* wearable = gAgent.getWearable( self->getType() );
00640 if( wearable )
00641 {
00642 LLWearableSaveAsDialog* save_as_dialog = new LLWearableSaveAsDialog( wearable->getName(), onSaveAsCommit, self );
00643 save_as_dialog->startModal();
00644
00645 }
00646 }
00647
00648
00649 void LLPanelEditWearable::onSaveAsCommit( LLWearableSaveAsDialog* save_as_dialog, void* userdata )
00650 {
00651 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00652 LLVOAvatar* avatar = gAgent.getAvatarObject();
00653 if( avatar )
00654 {
00655 gAgent.saveWearableAs( self->getType(), save_as_dialog->getItemName(), FALSE );
00656 }
00657 }
00658
00659
00660
00661 void LLPanelEditWearable::onBtnRevert( void* userdata )
00662 {
00663 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00664 gAgent.revertWearable( self->mType );
00665 }
00666
00667
00668 void LLPanelEditWearable::onBtnCreateNew( void* userdata )
00669 {
00670 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00671 gViewerWindow->alertXml("AutoWearNewClothing", onSelectAutoWearOption, self);
00672 }
00673 void LLPanelEditWearable::onSelectAutoWearOption(S32 option, void* data)
00674 {
00675 LLPanelEditWearable* self = (LLPanelEditWearable*) data;
00676 LLVOAvatar* avatar = gAgent.getAvatarObject();
00677 if(avatar)
00678 {
00679
00680 LLWearable* wearable = gWearableList.createNewWearable( self->getType() );
00681 LLAssetType::EType asset_type = wearable->getAssetType();
00682
00683 LLUUID folder_id;
00684
00685 folder_id = gInventory.findCategoryUUIDForType(asset_type);
00686
00687
00688 LLPointer<LLInventoryCallback> cb = option == 0 ?
00689 new WearOnAvatarCallback : NULL;
00690 create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
00691 folder_id, wearable->getTransactionID(), wearable->getName(), wearable->getDescription(),
00692 asset_type, LLInventoryType::IT_WEARABLE, wearable->getType(),
00693 wearable->getPermissions().getMaskNextOwner(), cb);
00694 }
00695 }
00696 void LLPanelEditWearable::addColorSwatch( LLVOAvatar::ETextureIndex te, const LLString& name )
00697 {
00698 childSetCommitCallback(name, LLPanelEditWearable::onColorCommit, this);
00699 mColorList[name] = te;
00700 }
00701
00702
00703 void LLPanelEditWearable::onColorCommit( LLUICtrl* ctrl, void* userdata )
00704 {
00705 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00706 LLColorSwatchCtrl* color_ctrl = (LLColorSwatchCtrl*) ctrl;
00707
00708 LLVOAvatar* avatar = gAgent.getAvatarObject();
00709 if( avatar )
00710 {
00711 LLVOAvatar::ETextureIndex te = (LLVOAvatar::ETextureIndex)(self->mColorList[ctrl->getName()]);
00712
00713 LLColor4 old_color = avatar->getClothesColor( te );
00714 const LLColor4& new_color = color_ctrl->get();
00715 if( old_color != new_color )
00716 {
00717
00718 LLUndoWearable* action = (LLUndoWearable*)(self->mUndoBuffer->getNextAction());
00719 action->setColor( te, old_color );
00720
00721
00722 avatar->setClothesColor( te, new_color, TRUE );
00723 gAgent.sendAgentSetAppearance();
00724
00725 LLVisualParamHint::requestHintUpdates();
00726 }
00727 }
00728 }
00729
00730
00731 void LLPanelEditWearable::addTextureDropTarget( LLVOAvatar::ETextureIndex te, const LLString& name,
00732 const LLUUID& default_image_id, BOOL allow_no_texture )
00733 {
00734 childSetCommitCallback(name, LLPanelEditWearable::onTextureCommit, this);
00735 LLTextureCtrl* texture_ctrl = LLViewerUICtrlFactory::getTexturePickerByName(this, name);
00736 if (texture_ctrl)
00737 {
00738 texture_ctrl->setDefaultImageAssetID(default_image_id);
00739 texture_ctrl->setAllowNoTexture( allow_no_texture );
00740
00741 texture_ctrl->setImmediateFilterPermMask(PERM_NONE);
00742 texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE);
00743 }
00744 mTextureList[name] = te;
00745 }
00746
00747
00748 void LLPanelEditWearable::onTextureCommit( LLUICtrl* ctrl, void* userdata )
00749 {
00750 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
00751 LLTextureCtrl* texture_ctrl = (LLTextureCtrl*) ctrl;
00752
00753 LLVOAvatar* avatar = gAgent.getAvatarObject();
00754 if( avatar )
00755 {
00756 LLVOAvatar::ETextureIndex te = (LLVOAvatar::ETextureIndex)(self->mTextureList[ctrl->getName()]);
00757
00758
00759 LLViewerImage* existing_image = avatar->getTEImage( te );
00760 if( existing_image )
00761 {
00762 LLUndoWearable* action = (LLUndoWearable*)(self->mUndoBuffer->getNextAction());
00763 action->setTexture( te, existing_image->getID() );
00764 }
00765
00766
00767 LLViewerImage* image = gImageList.getImage( texture_ctrl->getImageAssetID() );
00768 if( image->getID().isNull() )
00769 {
00770 image = gImageList.getImage(IMG_DEFAULT_AVATAR);
00771 }
00772 avatar->setLocTexTE( te, image, TRUE );
00773 gAgent.sendAgentSetAppearance();
00774 }
00775 }
00776
00777
00778 ESubpart LLPanelEditWearable::getDefaultSubpart()
00779 {
00780 switch( mType )
00781 {
00782 case WT_SHAPE: return SUBPART_SHAPE_WHOLE;
00783 case WT_SKIN: return SUBPART_SKIN_COLOR;
00784 case WT_HAIR: return SUBPART_HAIR_COLOR;
00785 case WT_EYES: return SUBPART_EYES;
00786 case WT_SHIRT: return SUBPART_SHIRT;
00787 case WT_PANTS: return SUBPART_PANTS;
00788 case WT_SHOES: return SUBPART_SHOES;
00789 case WT_SOCKS: return SUBPART_SOCKS;
00790 case WT_JACKET: return SUBPART_JACKET;
00791 case WT_GLOVES: return SUBPART_GLOVES;
00792 case WT_UNDERSHIRT: return SUBPART_UNDERSHIRT;
00793 case WT_UNDERPANTS: return SUBPART_UNDERPANTS;
00794 case WT_SKIRT: return SUBPART_SKIRT;
00795
00796 default: llassert(0); return SUBPART_SHAPE_WHOLE;
00797 }
00798 }
00799
00800
00801 void LLPanelEditWearable::draw()
00802 {
00803 if( gFloaterCustomize->isMinimized() )
00804 {
00805 return;
00806 }
00807
00808 LLVOAvatar* avatar = gAgent.getAvatarObject();
00809 if( !avatar )
00810 {
00811 return;
00812 }
00813
00814 if( getVisible() )
00815 {
00816 if( gFloaterCustomize->isFrontmost() && !gFocusMgr.getKeyboardFocus() )
00817 {
00818
00819 gEditMenuHandler = this;
00820 }
00821
00822 LLWearable* wearable = gAgent.getWearable( mType );
00823 BOOL has_wearable = (wearable != NULL );
00824 BOOL is_dirty = isDirty();
00825 BOOL is_modifiable = FALSE;
00826 BOOL is_copyable = FALSE;
00827 BOOL is_complete = FALSE;
00828 LLViewerInventoryItem* item;
00829 item = (LLViewerInventoryItem*)gAgent.getWearableInventoryItem(mType);
00830 if(item)
00831 {
00832 const LLPermissions& perm = item->getPermissions();
00833 is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID());
00834 is_copyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID());
00835 is_complete = item->isComplete();
00836 }
00837
00838 childSetEnabled("Save", is_modifiable && is_complete && has_wearable && is_dirty);
00839 childSetEnabled("Save As", is_copyable && is_complete && has_wearable);
00840 childSetEnabled("Revert", has_wearable && is_dirty );
00841 childSetEnabled("Take Off", has_wearable );
00842 childSetVisible("Take Off", mCanTakeOff );
00843 childSetVisible("Create New", !has_wearable );
00844
00845 childSetVisible("not worn instructions", !has_wearable );
00846 childSetVisible("no modify instructions", has_wearable && !is_modifiable);
00847
00848 for (std::map<ESubpart, LLSubpart*>::iterator iter = mSubpartList.begin();
00849 iter != mSubpartList.end(); ++iter)
00850 {
00851 if( has_wearable && is_complete && is_modifiable )
00852 {
00853 childSetEnabled(iter->second->mButtonName, iter->second->mSex & avatar->getSex() );
00854 }
00855 else
00856 {
00857 childSetEnabled(iter->second->mButtonName, FALSE );
00858 }
00859 }
00860
00861 childSetVisible("square", !is_modifiable);
00862
00863 childSetVisible("title", FALSE);
00864 childSetVisible("title_no_modify", FALSE);
00865 childSetVisible("title_not_worn", FALSE);
00866 childSetVisible("title_loading", FALSE);
00867
00868 childSetVisible("path", FALSE);
00869
00870 if(has_wearable && !is_modifiable)
00871 {
00872
00873 childSetVisible("title_no_modify", TRUE);
00874 childSetTextArg("title_no_modify", "[DESC]", LLString(LLWearable::typeToTypeLabel( mType )));
00875
00876 for( std::map<LLString, S32>::iterator iter = mTextureList.begin();
00877 iter != mTextureList.end(); ++iter )
00878 {
00879 childSetVisible(iter->first, FALSE );
00880 }
00881 for( std::map<LLString, S32>::iterator iter = mColorList.begin();
00882 iter != mColorList.end(); ++iter )
00883 {
00884 childSetVisible(iter->first, FALSE );
00885 }
00886 }
00887 else if(has_wearable && !is_complete)
00888 {
00889
00890 childSetVisible("title_loading", TRUE);
00891 childSetTextArg("title_loading", "[DESC]", LLString(LLWearable::typeToTypeLabel( mType )));
00892
00893 LLString path;
00894 const LLUUID& item_id = gAgent.getWearableItem( wearable->getType() );
00895 gInventory.appendPath(item_id, path);
00896 childSetVisible("path", TRUE);
00897 childSetTextArg("path", "[PATH]", path);
00898
00899 for( std::map<LLString, S32>::iterator iter = mTextureList.begin();
00900 iter != mTextureList.end(); ++iter )
00901 {
00902 childSetVisible(iter->first, FALSE );
00903 }
00904 for( std::map<LLString, S32>::iterator iter = mColorList.begin();
00905 iter != mColorList.end(); ++iter )
00906 {
00907 childSetVisible(iter->first, FALSE );
00908 }
00909 }
00910 else if(has_wearable && is_modifiable)
00911 {
00912 childSetVisible("title", TRUE);
00913 childSetTextArg("title", "[DESC]", wearable->getName() );
00914
00915 LLString path;
00916 const LLUUID& item_id = gAgent.getWearableItem( wearable->getType() );
00917 gInventory.appendPath(item_id, path);
00918 childSetVisible("path", TRUE);
00919 childSetTextArg("path", "[PATH]", path);
00920
00921 for( std::map<LLString, S32>::iterator iter = mTextureList.begin();
00922 iter != mTextureList.end(); ++iter )
00923 {
00924 LLString name = iter->first;
00925 LLTextureCtrl* texture_ctrl = LLViewerUICtrlFactory::getTexturePickerByName(this, name);
00926 S32 te_index = iter->second;
00927 childSetVisible(name, is_copyable && is_modifiable && is_complete );
00928 if (texture_ctrl)
00929 {
00930 const LLTextureEntry* te = avatar->getTE(te_index);
00931 if( te && (te->getID() != IMG_DEFAULT_AVATAR) )
00932 {
00933 texture_ctrl->setImageAssetID( te->getID() );
00934 }
00935 else
00936 {
00937 texture_ctrl->setImageAssetID( LLUUID::null );
00938 }
00939 }
00940 }
00941
00942 for( std::map<LLString, S32>::iterator iter = mColorList.begin();
00943 iter != mColorList.end(); ++iter )
00944 {
00945 LLString name = iter->first;
00946 S32 te_index = iter->second;
00947 childSetVisible(name, is_modifiable && is_complete );
00948 childSetEnabled(name, is_modifiable && is_complete );
00949 LLColorSwatchCtrl* ctrl = LLViewerUICtrlFactory::getColorSwatchByName(this, name);
00950 if (ctrl)
00951 {
00952 ctrl->set(avatar->getClothesColor( (LLVOAvatar::ETextureIndex)te_index ) );
00953 }
00954 }
00955 }
00956 else
00957 {
00958
00959 childSetVisible("title_not_worn", TRUE);
00960 childSetTextArg("title_not_worn", "[DESC]", LLString(LLWearable::typeToTypeLabel( mType )));
00961
00962 for( std::map<LLString, S32>::iterator iter = mTextureList.begin();
00963 iter != mTextureList.end(); ++iter )
00964 {
00965 childSetVisible(iter->first, FALSE );
00966 }
00967 for( std::map<LLString, S32>::iterator iter = mColorList.begin();
00968 iter != mColorList.end(); ++iter )
00969 {
00970 childSetVisible(iter->first, FALSE );
00971 }
00972 }
00973
00974 childSetVisible("icon", has_wearable && is_modifiable);
00975
00976 LLPanel::draw();
00977 }
00978 }
00979
00980 void LLPanelEditWearable::setWearable(LLWearable* wearable, U32 perm_mask, BOOL is_complete)
00981 {
00982 if( wearable )
00983 {
00984 setUIPermissions(perm_mask, is_complete);
00985 }
00986 mUndoBuffer->flushActions();
00987 }
00988
00989 void LLPanelEditWearable::addVisualParamToUndoBuffer( S32 param_id, F32 current_weight )
00990 {
00991 LLUndoWearable* action = (LLUndoWearable*)(mUndoBuffer->getNextAction());
00992 action->setVisualParam( param_id, current_weight );
00993 }
00994
00995 void LLPanelEditWearable::undo()
00996 {
00997 mUndoBuffer->undoAction();
00998 }
00999
01000 void LLPanelEditWearable::redo()
01001 {
01002 mUndoBuffer->redoAction();
01003 }
01004
01005 BOOL LLPanelEditWearable::canUndo()
01006 {
01007 return mUndoBuffer->canUndo();
01008 }
01009
01010 BOOL LLPanelEditWearable::canRedo()
01011 {
01012 return mUndoBuffer->canRedo();
01013 }
01014
01015 void LLPanelEditWearable::switchToDefaultSubpart()
01016 {
01017 setSubpart( getDefaultSubpart() );
01018 }
01019
01020 void LLPanelEditWearable::setVisible(BOOL visible)
01021 {
01022 LLPanel::setVisible( visible );
01023 if( !visible )
01024 {
01025
01026 if( gEditMenuHandler == this )
01027 {
01028 gEditMenuHandler = NULL;
01029 }
01030
01031 for( std::map<LLString, S32>::iterator iter = mColorList.begin();
01032 iter != mColorList.end(); ++iter )
01033 {
01034
01035 childSetEnabled(iter->first, FALSE );
01036 }
01037 }
01038 }
01039
01040 BOOL LLPanelEditWearable::isDirty() const
01041 {
01042 LLWearable* wearable = gAgent.getWearable( mType );
01043 if( !wearable )
01044 {
01045 return FALSE;
01046 }
01047
01048 if( wearable->isDirty() )
01049 {
01050 return TRUE;
01051 }
01052
01053 return FALSE;
01054 }
01055
01056
01057 void LLPanelEditWearable::onCommitSexChange( LLUICtrl*, void* userdata )
01058 {
01059 LLPanelEditWearable* self = (LLPanelEditWearable*) userdata;
01060
01061 LLVOAvatar* avatar = gAgent.getAvatarObject();
01062 if (!avatar)
01063 {
01064 return;
01065 }
01066
01067 if( !gAgent.isWearableModifiable(self->mType))
01068 {
01069 return;
01070 }
01071
01072 ESex new_sex = gSavedSettings.getU32("AvatarSex") ? SEX_MALE : SEX_FEMALE;
01073
01074 LLViewerVisualParam* param = (LLViewerVisualParam*)avatar->getVisualParam( "male" );
01075 if( !param )
01076 {
01077 return;
01078 }
01079
01080 self->addVisualParamToUndoBuffer( param->getID(), param->getWeight() );
01081 param->setWeight( (new_sex == SEX_MALE), TRUE );
01082
01083 avatar->updateSexDependentLayerSets( TRUE );
01084
01085 avatar->updateVisualParams();
01086
01087 gFloaterCustomize->clearScrollingPanelList();
01088
01089
01090 self->setSubpart( SUBPART_SHAPE_WHOLE );
01091
01092 gAgent.sendAgentSetAppearance();
01093 }
01094
01095 void LLPanelEditWearable::setUIPermissions(U32 perm_mask, BOOL is_complete)
01096 {
01097 BOOL is_copyable = (perm_mask & PERM_COPY) ? TRUE : FALSE;
01098 BOOL is_modifiable = (perm_mask & PERM_MODIFY) ? TRUE : FALSE;
01099
01100 childSetEnabled("Save", is_modifiable && is_complete);
01101 childSetEnabled("Save As", is_copyable && is_complete);
01102 childSetEnabled("Randomize", is_modifiable && is_complete);
01103 childSetEnabled("sex radio", is_modifiable && is_complete);
01104 for( std::map<LLString, S32>::iterator iter = mTextureList.begin();
01105 iter != mTextureList.end(); ++iter )
01106 {
01107 childSetVisible(iter->first, is_copyable && is_modifiable && is_complete );
01108 }
01109 for( std::map<LLString, S32>::iterator iter = mColorList.begin();
01110 iter != mColorList.end(); ++iter )
01111 {
01112 childSetVisible(iter->first, is_modifiable && is_complete );
01113 }
01114 }
01115
01117
01118
01119 class LLScrollingPanelParam : public LLScrollingPanel
01120 {
01121 public:
01122 LLScrollingPanelParam( const LLString& name, LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify );
01123 virtual ~LLScrollingPanelParam();
01124
01125 virtual void draw();
01126 virtual void setVisible( BOOL visible );
01127 virtual void updatePanel(BOOL allow_modify);
01128
01129 static void onSliderMouseDown(LLUICtrl* ctrl, void* userdata);
01130 static void onSliderMoved(LLUICtrl* ctrl, void* userdata);
01131 static void onSliderMouseUp(LLUICtrl* ctrl, void* userdata);
01132
01133 static void onHintMinMouseDown(void* userdata);
01134 static void onHintMinHeldDown(void* userdata);
01135 static void onHintMaxMouseDown(void* userdata);
01136 static void onHintMaxHeldDown(void* userdata);
01137 static void onHintMinMouseUp(void* userdata);
01138 static void onHintMaxMouseUp(void* userdata);
01139
01140 void onHintMouseDown( LLVisualParamHint* hint );
01141 void onHintHeldDown( LLVisualParamHint* hint );
01142
01143 F32 weightToPercent( F32 weight );
01144 F32 percentToWeight( F32 percent );
01145
01146 public:
01147 LLViewerVisualParam* mParam;
01148 LLVisualParamHint* mHintMin;
01149 LLVisualParamHint* mHintMax;
01150 static S32 sUpdateDelayFrames;
01151
01152 protected:
01153 LLTimer mMouseDownTimer;
01154 F32 mLastHeldTime;
01155
01156 BOOL mAllowModify;
01157 };
01158
01159
01160 S32 LLScrollingPanelParam::sUpdateDelayFrames = 0;
01161
01162 const S32 BTN_BORDER = 2;
01163 const S32 PARAM_HINT_WIDTH = 128;
01164 const S32 PARAM_HINT_HEIGHT = 128;
01165 const S32 PARAM_HINT_LABEL_HEIGHT = 16;
01166 const S32 PARAM_PANEL_WIDTH = 2 * (3* BTN_BORDER + PARAM_HINT_WIDTH + LLPANEL_BORDER_WIDTH);
01167 const S32 PARAM_PANEL_HEIGHT = 2 * BTN_BORDER + PARAM_HINT_HEIGHT + PARAM_HINT_LABEL_HEIGHT + 4 * LLPANEL_BORDER_WIDTH;
01168
01169 LLScrollingPanelParam::LLScrollingPanelParam( const LLString& name,
01170 LLViewerJointMesh* mesh, LLViewerVisualParam* param, BOOL allow_modify )
01171 : LLScrollingPanel( name, LLRect( 0, PARAM_PANEL_HEIGHT, PARAM_PANEL_WIDTH, 0 ) ),
01172 mParam(param),
01173 mAllowModify(allow_modify)
01174 {
01175 gUICtrlFactory->buildPanel(this, "panel_scrolling_param.xml");
01176
01177 S32 pos_x = 2 * LLPANEL_BORDER_WIDTH;
01178 S32 pos_y = 3 * LLPANEL_BORDER_WIDTH + SLIDERCTRL_HEIGHT;
01179 F32 min_weight = param->getMinWeight();
01180 F32 max_weight = param->getMaxWeight();
01181
01182 mHintMin = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, min_weight);
01183 pos_x += PARAM_HINT_WIDTH + 3 * BTN_BORDER;
01184 mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, max_weight );
01185
01186 mHintMin->setAllowsUpdates( FALSE );
01187 mHintMax->setAllowsUpdates( FALSE );
01188 childSetValue("param slider", weightToPercent(param->getWeight()));
01189 childSetLabelArg("param slider", "[DESC]", param->getDisplayName());
01190 childSetEnabled("param slider", mAllowModify);
01191 childSetCommitCallback("param slider", LLScrollingPanelParam::onSliderMoved, this);
01192
01193
01194 LLString min_name = param->getMinDisplayName();
01195 LLString max_name = param->getMaxDisplayName();
01196 childSetValue("min param text", min_name);
01197 childSetValue("max param text", max_name);
01198
01199 LLButton* less = LLUICtrlFactory::getButtonByName(this, "less");
01200 if (less)
01201 {
01202 less->setMouseDownCallback( LLScrollingPanelParam::onHintMinMouseDown );
01203 less->setMouseUpCallback( LLScrollingPanelParam::onHintMinMouseUp );
01204 less->setHeldDownCallback( LLScrollingPanelParam::onHintMinHeldDown );
01205 less->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
01206 }
01207
01208 LLButton* more = LLUICtrlFactory::getButtonByName(this, "more");
01209 if (more)
01210 {
01211 more->setMouseDownCallback( LLScrollingPanelParam::onHintMaxMouseDown );
01212 more->setMouseUpCallback( LLScrollingPanelParam::onHintMaxMouseUp );
01213 more->setHeldDownCallback( LLScrollingPanelParam::onHintMaxHeldDown );
01214 more->setHeldDownDelay( PARAM_STEP_TIME_THRESHOLD );
01215 }
01216
01217 setVisible(FALSE);
01218 setBorderVisible( FALSE );
01219 }
01220
01221 LLScrollingPanelParam::~LLScrollingPanelParam()
01222 {
01223 delete mHintMin;
01224 delete mHintMax;
01225 }
01226
01227 void LLScrollingPanelParam::updatePanel(BOOL allow_modify)
01228 {
01229 LLViewerVisualParam* param = mHintMin->getVisualParam();
01230 childSetValue("param slider", weightToPercent( param->getWeight() ) );
01231 mHintMin->requestUpdate( sUpdateDelayFrames++ );
01232 mHintMax->requestUpdate( sUpdateDelayFrames++ );
01233
01234 mAllowModify = allow_modify;
01235 childSetEnabled("param slider", mAllowModify);
01236 childSetEnabled("less", mAllowModify);
01237 childSetEnabled("more", mAllowModify);
01238 }
01239
01240 void LLScrollingPanelParam::setVisible( BOOL visible )
01241 {
01242 if( getVisible() != visible )
01243 {
01244 LLPanel::setVisible( visible );
01245 mHintMin->setAllowsUpdates( visible );
01246 mHintMax->setAllowsUpdates( visible );
01247
01248 if( visible )
01249 {
01250 mHintMin->setUpdateDelayFrames( sUpdateDelayFrames++ );
01251 mHintMax->setUpdateDelayFrames( sUpdateDelayFrames++ );
01252 }
01253 }
01254 }
01255
01256 void LLScrollingPanelParam::draw()
01257 {
01258 if( gFloaterCustomize->isMinimized() )
01259 {
01260 return;
01261 }
01262
01263 childSetVisible("less", mHintMin->getVisible());
01264 childSetVisible("more", mHintMax->getVisible());
01265
01266 if( getVisible() )
01267 {
01268
01269 childSetVisible( "min param text", FALSE );
01270 childSetVisible( "max param text", FALSE );
01271 LLPanel::draw();
01272
01273
01274 glPushMatrix();
01275 {
01276 const LLRect& r = mHintMin->getRect();
01277 F32 left = (F32)(r.mLeft + BTN_BORDER);
01278 F32 bot = (F32)(r.mBottom + BTN_BORDER);
01279 glTranslatef(left, bot, 0.f);
01280 mHintMin->draw();
01281 }
01282 glPopMatrix();
01283
01284 glPushMatrix();
01285 {
01286 const LLRect& r = mHintMax->getRect();
01287 F32 left = (F32)(r.mLeft + BTN_BORDER);
01288 F32 bot = (F32)(r.mBottom + BTN_BORDER);
01289 glTranslatef(left, bot, 0.f);
01290 mHintMax->draw();
01291 }
01292 glPopMatrix();
01293
01294
01295
01296 childSetVisible( "min param text", TRUE );
01297 drawChild(getChildByName("min param text"), BTN_BORDER, BTN_BORDER);
01298
01299 childSetVisible( "max param text", TRUE );
01300 drawChild(getChildByName("max param text"), BTN_BORDER, BTN_BORDER);
01301 }
01302 }
01303
01304
01305 void LLScrollingPanelParam::onSliderMoved(LLUICtrl* ctrl, void* userdata)
01306 {
01307 LLSliderCtrl* slider = (LLSliderCtrl*) ctrl;
01308 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01309 LLViewerVisualParam* param = self->mParam;
01310
01311 F32 current_weight = gAgent.getAvatarObject()->getVisualParamWeight( param );
01312 F32 new_weight = self->percentToWeight( (F32)slider->getValue().asReal() );
01313 if (current_weight != new_weight )
01314 {
01315 gAgent.getAvatarObject()->setVisualParamWeight( param, new_weight, TRUE);
01316 gAgent.getAvatarObject()->updateVisualParams();
01317 }
01318 }
01319
01320
01321 void LLScrollingPanelParam::onSliderMouseDown(LLUICtrl* ctrl, void* userdata)
01322 {
01323 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01324 LLViewerVisualParam* param = self->mParam;
01325
01326
01327 F32 current_weight = gAgent.getAvatarObject()->getVisualParamWeight( param );
01328
01329 if( gFloaterCustomize )
01330 {
01331 LLPanelEditWearable* panel = gFloaterCustomize->getCurrentWearablePanel();
01332 if( panel )
01333 {
01334 panel->addVisualParamToUndoBuffer( param->getID(), current_weight );
01335 }
01336 }
01337 }
01338
01339
01340 void LLScrollingPanelParam::onSliderMouseUp(LLUICtrl* ctrl, void* userdata)
01341 {
01342 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01343
01344
01345 gAgent.sendAgentSetAppearance();
01346
01347 LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
01348 }
01349
01350
01351 void LLScrollingPanelParam::onHintMinMouseDown( void* userdata )
01352 {
01353 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01354 self->onHintMouseDown( self->mHintMin );
01355 }
01356
01357
01358 void LLScrollingPanelParam::onHintMaxMouseDown( void* userdata )
01359 {
01360 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01361 self->onHintMouseDown( self->mHintMax );
01362 }
01363
01364
01365 void LLScrollingPanelParam::onHintMouseDown( LLVisualParamHint* hint )
01366 {
01367
01368 F32 current_weight = gAgent.getAvatarObject()->getVisualParamWeight( hint->getVisualParam() );
01369
01370
01371 if( hint->getVisualParamWeight() != current_weight )
01372 {
01373
01374 if( gFloaterCustomize )
01375 {
01376 LLPanelEditWearable* panel = gFloaterCustomize->getCurrentWearablePanel();
01377 if( panel )
01378 {
01379 panel->addVisualParamToUndoBuffer( hint->getVisualParam()->getID(), current_weight );
01380 }
01381 }
01382
01383 mMouseDownTimer.reset();
01384 mLastHeldTime = 0.f;
01385 }
01386 }
01387
01388
01389 void LLScrollingPanelParam::onHintMinHeldDown( void* userdata )
01390 {
01391 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01392 self->onHintHeldDown( self->mHintMin );
01393 }
01394
01395
01396 void LLScrollingPanelParam::onHintMaxHeldDown( void* userdata )
01397 {
01398 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01399 self->onHintHeldDown( self->mHintMax );
01400 }
01401
01402 void LLScrollingPanelParam::onHintHeldDown( LLVisualParamHint* hint )
01403 {
01404 F32 current_weight = gAgent.getAvatarObject()->getVisualParamWeight( hint->getVisualParam() );
01405
01406 if (current_weight != hint->getVisualParamWeight() )
01407 {
01408 const F32 FULL_BLEND_TIME = 2.f;
01409 F32 elapsed_time = mMouseDownTimer.getElapsedTimeF32() - mLastHeldTime;
01410 mLastHeldTime += elapsed_time;
01411
01412 F32 new_weight;
01413 if (current_weight > hint->getVisualParamWeight() )
01414 {
01415 new_weight = current_weight - (elapsed_time / FULL_BLEND_TIME);
01416 }
01417 else
01418 {
01419 new_weight = current_weight + (elapsed_time / FULL_BLEND_TIME);
01420 }
01421
01422
01423
01424 F32 new_percent = weightToPercent(new_weight);
01425 LLSliderCtrl* slider = LLUICtrlFactory::getSliderByName(this, "param slider");
01426 if (slider)
01427 {
01428 if (slider->getMinValue() < new_percent
01429 && new_percent < slider->getMaxValue())
01430 {
01431 gAgent.getAvatarObject()->setVisualParamWeight( hint->getVisualParam(), new_weight, TRUE);
01432 gAgent.getAvatarObject()->updateVisualParams();
01433
01434 slider->setValue( weightToPercent( new_weight ) );
01435 }
01436 }
01437 }
01438 }
01439
01440
01441 void LLScrollingPanelParam::onHintMinMouseUp( void* userdata )
01442 {
01443 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01444
01445 F32 elapsed_time = self->mMouseDownTimer.getElapsedTimeF32();
01446
01447 LLVOAvatar* avatar = gAgent.getAvatarObject();
01448 if (avatar)
01449 {
01450 LLVisualParamHint* hint = self->mHintMin;
01451
01452 if (elapsed_time < PARAM_STEP_TIME_THRESHOLD)
01453 {
01454
01455 F32 current_weight = gAgent.getAvatarObject()->getVisualParamWeight( hint->getVisualParam() );
01456 F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight();
01457
01458 F32 new_weight = current_weight - (range / 10.f);
01459 F32 new_percent = self->weightToPercent(new_weight);
01460 LLSliderCtrl* slider = LLUICtrlFactory::getSliderByName(self, "param slider");
01461 if (slider)
01462 {
01463 if (slider->getMinValue() < new_percent
01464 && new_percent < slider->getMaxValue())
01465 {
01466 avatar->setVisualParamWeight(hint->getVisualParam(), new_weight, TRUE);
01467 slider->setValue( self->weightToPercent( new_weight ) );
01468 }
01469 }
01470 }
01471
01472
01473 gAgent.sendAgentSetAppearance();
01474 }
01475
01476 LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
01477 }
01478
01479 void LLScrollingPanelParam::onHintMaxMouseUp( void* userdata )
01480 {
01481 LLScrollingPanelParam* self = (LLScrollingPanelParam*) userdata;
01482
01483 F32 elapsed_time = self->mMouseDownTimer.getElapsedTimeF32();
01484
01485 LLVOAvatar* avatar = gAgent.getAvatarObject();
01486 if (avatar)
01487 {
01488 LLVisualParamHint* hint = self->mHintMax;
01489
01490 if (elapsed_time < PARAM_STEP_TIME_THRESHOLD)
01491 {
01492
01493 F32 current_weight = gAgent.getAvatarObject()->getVisualParamWeight( hint->getVisualParam() );
01494 F32 range = self->mHintMax->getVisualParamWeight() - self->mHintMin->getVisualParamWeight();
01495
01496 F32 new_weight = current_weight + (range / 10.f);
01497 F32 new_percent = self->weightToPercent(new_weight);
01498 LLSliderCtrl* slider = LLUICtrlFactory::getSliderByName(self, "param slider");
01499 if (slider)
01500 {
01501 if (slider->getMinValue() < new_percent
01502 && new_percent < slider->getMaxValue())
01503 {
01504 avatar->setVisualParamWeight(hint->getVisualParam(), new_weight, TRUE);
01505 slider->setValue( self->weightToPercent( new_weight ) );
01506 }
01507 }
01508 }
01509
01510
01511 gAgent.sendAgentSetAppearance();
01512 }
01513
01514 LLVisualParamHint::requestHintUpdates( self->mHintMin, self->mHintMax );
01515 }
01516
01517
01518 F32 LLScrollingPanelParam::weightToPercent( F32 weight )
01519 {
01520 LLViewerVisualParam* param = mParam;
01521 return (weight - param->getMinWeight()) / (param->getMaxWeight() - param->getMinWeight()) * 100.f;
01522 }
01523
01524 F32 LLScrollingPanelParam::percentToWeight( F32 percent )
01525 {
01526 LLViewerVisualParam* param = mParam;
01527 return percent / 100.f * (param->getMaxWeight() - param->getMinWeight()) + param->getMinWeight();
01528 }
01529
01530 const LLString& LLFloaterCustomize::getEditGroup()
01531 {
01532 return getCurrentWearablePanel()->getCurrentSubpart()->mEditGroup;
01533 }
01534
01535
01537
01538
01539
01540 EWearableType LLFloaterCustomize::sCurrentWearableType = WT_SHAPE;
01541
01542 struct WearablePanelData
01543 {
01544 WearablePanelData(LLFloaterCustomize* floater, EWearableType type)
01545 : mFloater(floater), mType(type) {}
01546 LLFloaterCustomize* mFloater;
01547 EWearableType mType;
01548 };
01549
01550 LLFloaterCustomize::LLFloaterCustomize()
01551 : LLFloater("customize"),
01552 mScrollingPanelList( NULL ),
01553 mGenePool( NULL ),
01554 mInventoryObserver(NULL),
01555 mNextStepAfterSaveAllCallback( NULL ),
01556 mNextStepAfterSaveAllUserdata( NULL )
01557 {
01558 gSavedSettings.setU32("AvatarSex", (gAgent.getAvatarObject()->getSex() == SEX_MALE) );
01559
01560 mResetParams = new LLVisualParamReset();
01561
01562
01563 mInventoryObserver = new LLFloaterCustomizeObserver(this);
01564 gInventory.addObserver(mInventoryObserver);
01565
01566 LLCallbackMap::map_t factory_map;
01567 factory_map["Shape"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_SHAPE) ) );
01568 factory_map["Skin"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_SKIN) ) );
01569 factory_map["Hair"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_HAIR) ) );
01570 factory_map["Eyes"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_EYES) ) );
01571 factory_map["Shirt"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_SHIRT) ) );
01572 factory_map["Pants"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_PANTS) ) );
01573 factory_map["Shoes"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_SHOES) ) );
01574 factory_map["Socks"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_SOCKS) ) );
01575 factory_map["Jacket"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_JACKET) ) );
01576 factory_map["Gloves"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_GLOVES) ) );
01577 factory_map["Undershirt"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_UNDERSHIRT) ) );
01578 factory_map["Underpants"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_UNDERPANTS) ) );
01579 factory_map["Skirt"] = LLCallbackMap(createWearablePanel, (void*)(new WearablePanelData(this, WT_SKIRT) ) );
01580
01581 gUICtrlFactory->buildFloater(this, "floater_customize.xml", &factory_map);
01582
01583 }
01584
01585 BOOL LLFloaterCustomize::postBuild()
01586 {
01587 childSetAction("Make Outfit", LLFloaterCustomize::onBtnMakeOutfit, (void*)this);
01588 childSetAction("Save All", LLFloaterCustomize::onBtnSaveAll, (void*)this);
01589 childSetAction("Close", LLFloater::onClickClose, (void*)this);
01590
01591
01592 initWearablePanels();
01593
01594
01595 childSetTabChangeCallback("customize tab container", "Shape", onTabChanged, (void*)WT_SHAPE );
01596 childSetTabChangeCallback("customize tab container", "Skin", onTabChanged, (void*)WT_SKIN );
01597 childSetTabChangeCallback("customize tab container", "Hair", onTabChanged, (void*)WT_HAIR );
01598 childSetTabChangeCallback("customize tab container", "Eyes", onTabChanged, (void*)WT_EYES );
01599 childSetTabChangeCallback("customize tab container", "Shirt", onTabChanged, (void*)WT_SHIRT );
01600 childSetTabChangeCallback("customize tab container", "Pants", onTabChanged, (void*)WT_PANTS );
01601 childSetTabChangeCallback("customize tab container", "Shoes", onTabChanged, (void*)WT_SHOES );
01602 childSetTabChangeCallback("customize tab container", "Socks", onTabChanged, (void*)WT_SOCKS );
01603 childSetTabChangeCallback("customize tab container", "Jacket", onTabChanged, (void*)WT_JACKET );
01604 childSetTabChangeCallback("customize tab container", "Gloves", onTabChanged, (void*)WT_GLOVES );
01605 childSetTabChangeCallback("customize tab container", "Undershirt", onTabChanged, (void*)WT_UNDERSHIRT );
01606 childSetTabChangeCallback("customize tab container", "Underpants", onTabChanged, (void*)WT_UNDERPANTS );
01607 childSetTabChangeCallback("customize tab container", "Skirt", onTabChanged, (void*)WT_SKIRT );
01608
01609
01610 if (gAgent.isTeen())
01611 {
01612 LLTabContainerCommon* tab_container = LLUICtrlFactory::getTabContainerByName(this, "customize tab container");
01613 if (tab_container)
01614 {
01615 LLPanel* panel;
01616 panel = tab_container->getPanelByName("Undershirt");
01617 if (panel) tab_container->removeTabPanel(panel);
01618 panel = tab_container->getPanelByName("Underpants");
01619 if (panel) tab_container->removeTabPanel(panel);
01620 }
01621 }
01622
01623
01624 initScrollingPanelList();
01625
01626 childShowTab("customize tab container", "Shape", true);
01627
01628 return TRUE;
01629 }
01630
01632
01633
01634 void LLFloaterCustomize::setCurrentWearableType( EWearableType type )
01635 {
01636 if( LLFloaterCustomize::sCurrentWearableType != type )
01637 {
01638 LLFloaterCustomize::sCurrentWearableType = type;
01639
01640 S32 type_int = (S32)type;
01641 if( gFloaterCustomize
01642 && gFloaterCustomize->mWearablePanelList[type_int])
01643 {
01644 LLString panelname = gFloaterCustomize->mWearablePanelList[type_int]->getName();
01645 gFloaterCustomize->childShowTab("customize tab container", panelname);
01646 gFloaterCustomize->switchToDefaultSubpart();
01647 }
01648 }
01649 }
01650
01651
01652 void LLFloaterCustomize::onBtnSaveAll( void* userdata )
01653 {
01654 gAgent.saveAllWearables();
01655 }
01656
01657
01658
01659 void LLFloaterCustomize::onBtnSnapshot( void* userdata )
01660 {
01661
01662 send_sound_trigger(LLUUID(gSavedSettings.getString("UISndSnapshot")), 1.0f);
01663
01664 LLPointer<LLImageRaw> raw = new LLImageRaw;
01665 BOOL success = gViewerWindow->rawSnapshot(raw,
01666 gViewerWindow->getWindowWidth(),
01667 gViewerWindow->getWindowHeight(),
01668 TRUE,
01669 FALSE,
01670 FALSE);
01671 if (!success) return;
01672
01673 LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG;
01674 success = jpeg_image->encode(raw);
01675 if(!success) return;
01676
01677 LLString filepath("C:\\snapshot");
01678 filepath += ".jpg";
01679
01680 success = jpeg_image->save(filepath);
01681 }
01682
01683
01684 void LLFloaterCustomize::onBtnMakeOutfit( void* userdata )
01685 {
01686 LLVOAvatar* avatar = gAgent.getAvatarObject();
01687 if(avatar)
01688 {
01689 LLMakeOutfitDialog* dialog = new LLMakeOutfitDialog( onMakeOutfitCommit, NULL );
01690
01691
01692 for( S32 i = 0; i < WT_COUNT; i++ )
01693 {
01694 BOOL enabled = (gAgent.getWearable( (EWearableType) i ) != NULL);
01695 BOOL selected = (enabled && (WT_SHIRT <= i) && (i < WT_COUNT));
01696 if (gAgent.isTeen()
01697 && !edit_wearable_for_teens((EWearableType)i))
01698 {
01699 dialog->setWearableToInclude( i, FALSE, FALSE );
01700 }
01701 else
01702 {
01703 dialog->setWearableToInclude( i, enabled, selected );
01704 }
01705 }
01706 dialog->startModal();
01707 }
01708 }
01709
01710
01711 void LLFloaterCustomize::onMakeOutfitCommit( LLMakeOutfitDialog* dialog, void* userdata )
01712 {
01713 LLVOAvatar* avatar = gAgent.getAvatarObject();
01714 if(avatar)
01715 {
01716 LLDynamicArray<S32> wearables_to_include;
01717 LLDynamicArray<S32> attachments_to_include;
01718
01719 dialog->getIncludedItems( wearables_to_include, attachments_to_include );
01720
01721 gAgent.makeNewOutfit( dialog->getFolderName(), wearables_to_include, attachments_to_include, dialog->getRenameClothing() );
01722 }
01723 }
01724
01726
01727
01728 void* LLFloaterCustomize::createWearablePanel(void* userdata)
01729 {
01730 WearablePanelData* data = (WearablePanelData*)userdata;
01731 EWearableType type = data->mType;
01732 LLPanelEditWearable* panel;
01733 if ((gAgent.isTeen() && !edit_wearable_for_teens(data->mType) ))
01734 {
01735 panel = NULL;
01736 }
01737 else
01738 {
01739 panel = new LLPanelEditWearable( type );
01740 }
01741 data->mFloater->mWearablePanelList[type] = panel;
01742 delete data;
01743 return panel;
01744 }
01745
01746 void LLFloaterCustomize::initWearablePanels()
01747 {
01748 LLSubpart* part;
01749
01751
01752 LLPanelEditWearable* panel = mWearablePanelList[ WT_SHAPE ];
01753
01754
01755 part = new LLSubpart();
01756 part->mTargetJoint = "mPelvis";
01757 part->mEditGroup = "shape_body";
01758 part->mTargetOffset.setVec(0.f, 0.f, 0.1f);
01759 part->mCameraOffset.setVec(-2.5f, 0.5f, 0.8f);
01760 panel->addSubpart( "Body", SUBPART_SHAPE_WHOLE, part );
01761
01762
01763 part = new LLSubpart();
01764 part->mTargetJoint = "mHead";
01765 part->mEditGroup = "shape_head";
01766 part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
01767 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
01768 panel->addSubpart( "Head", SUBPART_SHAPE_HEAD, part );
01769
01770 part = new LLSubpart();
01771 part->mTargetJoint = "mHead";
01772 part->mEditGroup = "shape_eyes";
01773 part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
01774 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
01775 panel->addSubpart( "Eyes", SUBPART_SHAPE_EYES, part );
01776
01777 part = new LLSubpart();
01778 part->mTargetJoint = "mHead";
01779 part->mEditGroup = "shape_ears";
01780 part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
01781 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
01782 panel->addSubpart( "Ears", SUBPART_SHAPE_EARS, part );
01783
01784 part = new LLSubpart();
01785 part->mTargetJoint = "mHead";
01786 part->mEditGroup = "shape_nose";
01787 part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
01788 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
01789 panel->addSubpart( "Nose", SUBPART_SHAPE_NOSE, part );
01790
01791
01792 part = new LLSubpart();
01793 part->mTargetJoint = "mHead";
01794 part->mEditGroup = "shape_mouth";
01795 part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
01796 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
01797 panel->addSubpart( "Mouth", SUBPART_SHAPE_MOUTH, part );
01798
01799
01800 part = new LLSubpart();
01801 part->mTargetJoint = "mHead";
01802 part->mEditGroup = "shape_chin";
01803 part->mTargetOffset.setVec(0.f, 0.f, 0.05f );
01804 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f );
01805 panel->addSubpart( "Chin", SUBPART_SHAPE_CHIN, part );
01806
01807
01808 part = new LLSubpart();
01809 part->mTargetJoint = "mTorso";
01810 part->mEditGroup = "shape_torso";
01811 part->mTargetOffset.setVec(0.f, 0.f, 0.3f);
01812 part->mCameraOffset.setVec(-1.f, 0.15f, 0.3f);
01813 panel->addSubpart( "Torso", SUBPART_SHAPE_TORSO, part );
01814
01815
01816 part = new LLSubpart();
01817 part->mTargetJoint = "mPelvis";
01818 part->mEditGroup = "shape_legs";
01819 part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
01820 part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
01821 panel->addSubpart( "Legs", SUBPART_SHAPE_LEGS, part );
01822
01823 panel->childSetCommitCallback("sex radio", LLPanelEditWearable::onCommitSexChange, panel);
01824 panel->childSetAction("Randomize", &LLPanelEditWearable::onBtnRandomize, panel);
01825
01827
01828 panel = mWearablePanelList[ WT_SKIN ];
01829
01830 part = new LLSubpart();
01831 part->mTargetJoint = "mHead";
01832 part->mEditGroup = "skin_color";
01833 part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
01834 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
01835 panel->addSubpart( "Skin Color", SUBPART_SKIN_COLOR, part );
01836
01837 part = new LLSubpart();
01838 part->mTargetJoint = "mHead";
01839 part->mEditGroup = "skin_facedetail";
01840 part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
01841 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
01842 panel->addSubpart( "Face Detail", SUBPART_SKIN_FACEDETAIL, part );
01843
01844 part = new LLSubpart();
01845 part->mTargetJoint = "mHead";
01846 part->mEditGroup = "skin_makeup";
01847 part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
01848 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
01849 panel->addSubpart( "Makeup", SUBPART_SKIN_MAKEUP, part );
01850
01851 part = new LLSubpart();
01852 part->mTargetJoint = "mPelvis";
01853 part->mEditGroup = "skin_bodydetail";
01854 part->mTargetOffset.setVec(0.f, 0.f, -0.2f);
01855 part->mCameraOffset.setVec(-2.5f, 0.5f, 0.5f);
01856 panel->addSubpart( "Body Detail", SUBPART_SKIN_BODYDETAIL, part );
01857
01858 panel->addTextureDropTarget( LLVOAvatar::TEX_HEAD_BODYPAINT, "Head Tattoos", LLUUID::null, TRUE );
01859 panel->addTextureDropTarget( LLVOAvatar::TEX_UPPER_BODYPAINT, "Upper Tattoos", LLUUID::null, TRUE );
01860 panel->addTextureDropTarget( LLVOAvatar::TEX_LOWER_BODYPAINT, "Lower Tattoos", LLUUID::null, TRUE );
01861
01862 panel->childSetAction("Randomize", &LLPanelEditWearable::onBtnRandomize, panel);
01863
01865
01866 panel = mWearablePanelList[ WT_HAIR ];
01867
01868 part = new LLSubpart();
01869 part->mTargetJoint = "mHead";
01870 part->mEditGroup = "hair_color";
01871 part->mTargetOffset.setVec(0.f, 0.f, 0.10f);
01872 part->mCameraOffset.setVec(-0.4f, 0.05f, 0.10f);
01873 panel->addSubpart( "Color", SUBPART_HAIR_COLOR, part );
01874
01875 part = new LLSubpart();
01876 part->mTargetJoint = "mHead";
01877 part->mEditGroup = "hair_style";
01878 part->mTargetOffset.setVec(0.f, 0.f, 0.10f);
01879 part->mCameraOffset.setVec(-0.4f, 0.05f, 0.10f);
01880 panel->addSubpart( "Style", SUBPART_HAIR_STYLE, part );
01881
01882 part = new LLSubpart();
01883 part->mTargetJoint = "mHead";
01884 part->mEditGroup = "hair_eyebrows";
01885 part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
01886 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
01887 panel->addSubpart( "Eyebrows", SUBPART_HAIR_EYEBROWS, part );
01888
01889 part = new LLSubpart();
01890 part->mSex = SEX_MALE;
01891 part->mTargetJoint = "mHead";
01892 part->mEditGroup = "hair_facial";
01893 part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
01894 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
01895 panel->addSubpart( "Facial", SUBPART_HAIR_FACIAL, part );
01896
01897 panel->addTextureDropTarget(LLVOAvatar::TEX_HAIR, "Texture",
01898 LLUUID( gSavedSettings.getString( "UIImgDefaultHairUUID" ) ),
01899 FALSE );
01900
01901 panel->childSetAction("Randomize", &LLPanelEditWearable::onBtnRandomize, panel);
01902
01904
01905 panel = mWearablePanelList[ WT_EYES ];
01906
01907 part = new LLSubpart();
01908 part->mTargetJoint = "mHead";
01909 part->mEditGroup = "eyes";
01910 part->mTargetOffset.setVec(0.f, 0.f, 0.05f);
01911 part->mCameraOffset.setVec(-0.5f, 0.05f, 0.07f);
01912 panel->addSubpart( "", SUBPART_EYES, part );
01913
01914 panel->addTextureDropTarget(LLVOAvatar::TEX_EYES_IRIS, "Iris",
01915 LLUUID( gSavedSettings.getString( "UIImgDefaultEyesUUID" ) ),
01916 FALSE );
01917
01918 panel->childSetAction("Randomize", &LLPanelEditWearable::onBtnRandomize, panel);
01919
01921
01922 panel = mWearablePanelList[ WT_SHIRT ];
01923
01924 part = new LLSubpart();
01925 part->mTargetJoint = "mTorso";
01926 part->mEditGroup = "shirt";
01927 part->mTargetOffset.setVec(0.f, 0.f, 0.3f);
01928 part->mCameraOffset.setVec(-1.f, 0.15f, 0.3f);
01929 panel->addSubpart( "", SUBPART_SHIRT, part );
01930
01931 panel->addTextureDropTarget( LLVOAvatar::TEX_UPPER_SHIRT, "Fabric",
01932 LLUUID( gSavedSettings.getString( "UIImgDefaultShirtUUID" ) ),
01933 FALSE );
01934
01935 panel->addColorSwatch( LLVOAvatar::TEX_UPPER_SHIRT, "Color/Tint" );
01936
01937
01939
01940 panel = mWearablePanelList[ WT_PANTS ];
01941
01942 part = new LLSubpart();
01943 part->mTargetJoint = "mPelvis";
01944 part->mEditGroup = "pants";
01945 part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
01946 part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
01947 panel->addSubpart( "", SUBPART_PANTS, part );
01948
01949 panel->addTextureDropTarget(LLVOAvatar::TEX_LOWER_PANTS, "Fabric",
01950 LLUUID( gSavedSettings.getString( "UIImgDefaultPantsUUID" ) ),
01951 FALSE );
01952
01953 panel->addColorSwatch( LLVOAvatar::TEX_LOWER_PANTS, "Color/Tint" );
01954
01955
01957
01958 panel = mWearablePanelList[ WT_SHOES ];
01959
01960 if (panel)
01961 {
01962 part = new LLSubpart();
01963 part->mTargetJoint = "mPelvis";
01964 part->mEditGroup = "shoes";
01965 part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
01966 part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
01967 panel->addSubpart( "", SUBPART_SHOES, part );
01968
01969 panel->addTextureDropTarget( LLVOAvatar::TEX_LOWER_SHOES, "Fabric",
01970 LLUUID( gSavedSettings.getString( "UIImgDefaultShoesUUID" ) ),
01971 FALSE );
01972
01973 panel->addColorSwatch( LLVOAvatar::TEX_LOWER_SHOES, "Color/Tint" );
01974 }
01975
01976
01978
01979 panel = mWearablePanelList[ WT_SOCKS ];
01980
01981 if (panel)
01982 {
01983 part = new LLSubpart();
01984 part->mTargetJoint = "mPelvis";
01985 part->mEditGroup = "socks";
01986 part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
01987 part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
01988 panel->addSubpart( "", SUBPART_SOCKS, part );
01989
01990 panel->addTextureDropTarget( LLVOAvatar::TEX_LOWER_SOCKS, "Fabric",
01991 LLUUID( gSavedSettings.getString( "UIImgDefaultSocksUUID" ) ),
01992 FALSE );
01993
01994 panel->addColorSwatch( LLVOAvatar::TEX_LOWER_SOCKS, "Color/Tint" );
01995 }
01996
01998
01999 panel = mWearablePanelList[ WT_JACKET ];
02000
02001 if (panel)
02002 {
02003 part = new LLSubpart();
02004 part->mTargetJoint = "mTorso";
02005 part->mEditGroup = "jacket";
02006 part->mTargetOffset.setVec(0.f, 0.f, 0.f);
02007 part->mCameraOffset.setVec(-2.f, 0.1f, 0.3f);
02008 panel->addSubpart( "", SUBPART_JACKET, part );
02009
02010 panel->addTextureDropTarget( LLVOAvatar::TEX_UPPER_JACKET, "Upper Fabric",
02011 LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ),
02012 FALSE );
02013 panel->addTextureDropTarget( LLVOAvatar::TEX_LOWER_JACKET, "Lower Fabric",
02014 LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ),
02015 FALSE );
02016
02017 panel->addColorSwatch( LLVOAvatar::TEX_UPPER_JACKET, "Color/Tint" );
02018 }
02019
02021
02022 panel = mWearablePanelList[ WT_SKIRT ];
02023
02024 if (panel)
02025 {
02026 part = new LLSubpart();
02027 part->mTargetJoint = "mPelvis";
02028 part->mEditGroup = "skirt";
02029 part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
02030 part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
02031 panel->addSubpart( "", SUBPART_SKIRT, part );
02032
02033 panel->addTextureDropTarget( LLVOAvatar::TEX_SKIRT, "Fabric",
02034 LLUUID( gSavedSettings.getString( "UIImgDefaultSkirtUUID" ) ),
02035 FALSE );
02036
02037 panel->addColorSwatch( LLVOAvatar::TEX_SKIRT, "Color/Tint" );
02038 }
02039
02040
02042
02043 panel = mWearablePanelList[ WT_GLOVES ];
02044
02045 if (panel)
02046 {
02047 part = new LLSubpart();
02048 part->mTargetJoint = "mTorso";
02049 part->mEditGroup = "gloves";
02050 part->mTargetOffset.setVec(0.f, 0.f, 0.f);
02051 part->mCameraOffset.setVec(-1.f, 0.15f, 0.f);
02052 panel->addSubpart( "", SUBPART_GLOVES, part );
02053
02054 panel->addTextureDropTarget( LLVOAvatar::TEX_UPPER_GLOVES, "Fabric",
02055 LLUUID( gSavedSettings.getString( "UIImgDefaultGlovesUUID" ) ),
02056 FALSE );
02057
02058 panel->addColorSwatch( LLVOAvatar::TEX_UPPER_GLOVES, "Color/Tint" );
02059 }
02060
02061
02063
02064 panel = mWearablePanelList[ WT_UNDERSHIRT ];
02065
02066 if (panel)
02067 {
02068 part = new LLSubpart();
02069 part->mTargetJoint = "mTorso";
02070 part->mEditGroup = "undershirt";
02071 part->mTargetOffset.setVec(0.f, 0.f, 0.3f);
02072 part->mCameraOffset.setVec(-1.f, 0.15f, 0.3f);
02073 panel->addSubpart( "", SUBPART_UNDERSHIRT, part );
02074
02075 panel->addTextureDropTarget( LLVOAvatar::TEX_UPPER_UNDERSHIRT, "Fabric",
02076 LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ),
02077 FALSE );
02078
02079 panel->addColorSwatch( LLVOAvatar::TEX_UPPER_UNDERSHIRT, "Color/Tint" );
02080 }
02081
02083
02084 panel = mWearablePanelList[ WT_UNDERPANTS ];
02085
02086 if (panel)
02087 {
02088 part = new LLSubpart();
02089 part->mTargetJoint = "mPelvis";
02090 part->mEditGroup = "underpants";
02091 part->mTargetOffset.setVec(0.f, 0.f, -0.5f);
02092 part->mCameraOffset.setVec(-1.6f, 0.15f, -0.5f);
02093 panel->addSubpart( "", SUBPART_UNDERPANTS, part );
02094
02095 panel->addTextureDropTarget( LLVOAvatar::TEX_LOWER_UNDERPANTS, "Fabric",
02096 LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ),
02097 FALSE );
02098
02099 panel->addColorSwatch( LLVOAvatar::TEX_LOWER_UNDERPANTS, "Color/Tint" );
02100 }
02101 }
02102
02104
02105 LLFloaterCustomize::~LLFloaterCustomize()
02106 {
02107 llinfos << "Destroying LLFloaterCustomize" << llendl;
02108 delete mGenePool;
02109 delete mResetParams;
02110 gInventory.removeObserver(mInventoryObserver);
02111 delete mInventoryObserver;
02112 }
02113
02114 void LLFloaterCustomize::switchToDefaultSubpart()
02115 {
02116 getCurrentWearablePanel()->switchToDefaultSubpart();
02117 }
02118
02119 void LLFloaterCustomize::spawnWearableAppearance(EWearableType type)
02120 {
02121 if( !mGenePool )
02122 {
02123 mGenePool = new LLGenePool();
02124 }
02125
02126 LLVOAvatar* avatar = gAgent.getAvatarObject();
02127 if( avatar )
02128 {
02129 mGenePool->spawn( type );
02130 }
02131 }
02132
02133
02134 void LLFloaterCustomize::draw()
02135 {
02136 if( isMinimized() )
02137 {
02138 LLFloater::draw();
02139 return;
02140 }
02141
02142
02143
02144 if( getVisible() )
02145 {
02146
02147
02148
02149 updateInventoryUI();
02150
02151 LLScrollingPanelParam::sUpdateDelayFrames = 0;
02152
02153 childSetEnabled("Save All", isDirty() );
02154 LLFloater::draw();
02155 }
02156 }
02157
02158 BOOL LLFloaterCustomize::isDirty() const
02159 {
02160 for(S32 i = 0; i < WT_COUNT; i++)
02161 {
02162 if( mWearablePanelList[i]
02163 && mWearablePanelList[i]->isDirty() )
02164 {
02165 return TRUE;
02166 }
02167 }
02168 return FALSE;
02169 }
02170
02171
02172
02173 void LLFloaterCustomize::onTabChanged( void* userdata, bool from_click )
02174 {
02175 EWearableType wearable_type = (EWearableType) (intptr_t)userdata;
02176 LLFloaterCustomize::setCurrentWearableType( wearable_type );
02177 }
02178
02179 void LLFloaterCustomize::onClose(bool app_quitting)
02180 {
02181
02182 gFloaterView->sendChildToBack(this);
02183 handle_reset_view();
02184 }
02185
02186
02188
02189 const S32 LOWER_BTN_HEIGHT = 18 + 8;
02190
02191 const S32 FLOATER_CUSTOMIZE_BUTTON_WIDTH = 82;
02192 const S32 FLOATER_CUSTOMIZE_BOTTOM_PAD = 30;
02193 const S32 LINE_HEIGHT = 16;
02194 const S32 HEADER_PAD = 8;
02195 const S32 HEADER_HEIGHT = 3 * (LINE_HEIGHT + LLFLOATER_VPAD) + (2 * LLPANEL_BORDER_WIDTH) + HEADER_PAD;
02196
02197 void LLFloaterCustomize::initScrollingPanelList()
02198 {
02199 LLScrollableContainerView* scroll_container =
02200 LLUICtrlFactory::getScrollableContainerByName(this, "panel_container");
02201
02202
02203 mScrollingPanelList = new LLScrollingPanelList("panel_list", LLRect());
02204 if (scroll_container)
02205 {
02206 scroll_container->setScrolledView(mScrollingPanelList);
02207 scroll_container->addChild(mScrollingPanelList);
02208 }
02209 }
02210
02211 void LLFloaterCustomize::clearScrollingPanelList()
02212 {
02213 if( mScrollingPanelList )
02214 {
02215 mScrollingPanelList->clearPanels();
02216 }
02217 }
02218
02219 void LLFloaterCustomize::generateVisualParamHints(LLViewerJointMesh* joint_mesh, LLFloaterCustomize::param_map& params)
02220 {
02221
02222
02223
02224 if( mScrollingPanelList )
02225 {
02226 mScrollingPanelList->clearPanels();
02227 param_map::iterator end = params.end();
02228 for(param_map::iterator it = params.begin(); it != end; ++it)
02229 {
02230 mScrollingPanelList->addPanel( new LLScrollingPanelParam( "LLScrollingPanelParam", joint_mesh, (*it).second.second, (*it).second.first) );
02231 }
02232 }
02233 }
02234
02235 void LLFloaterCustomize::setWearable(EWearableType type, LLWearable* wearable, U32 perm_mask, BOOL is_complete)
02236 {
02237 llassert( type < WT_COUNT );
02238 gSavedSettings.setU32("AvatarSex", (gAgent.getAvatarObject()->getSex() == SEX_MALE) );
02239
02240 LLPanelEditWearable* panel = mWearablePanelList[ type ];
02241 if( panel )
02242 {
02243 panel->setWearable(wearable, perm_mask, is_complete);
02244 updateScrollingPanelList((perm_mask & PERM_MODIFY) ? is_complete : FALSE);
02245 }
02246 }
02247
02248 void LLFloaterCustomize::updateScrollingPanelList(BOOL allow_modify)
02249 {
02250 if( mScrollingPanelList )
02251 {
02252 LLScrollingPanelParam::sUpdateDelayFrames = 0;
02253 mScrollingPanelList->updatePanels(allow_modify );
02254 }
02255 }
02256
02257
02258 void LLFloaterCustomize::askToSaveAllIfDirty( void(*next_step_callback)(BOOL proceed, void* userdata), void* userdata )
02259 {
02260 if( isDirty())
02261 {
02262
02263 mNextStepAfterSaveAllCallback = next_step_callback;
02264 mNextStepAfterSaveAllUserdata = userdata;
02265
02266
02267 gViewerWindow->alertXml("SaveClothingBodyChanges",
02268 LLFloaterCustomize::onSaveAllDialog, this);
02269 return;
02270 }
02271
02272
02273 if( next_step_callback )
02274 {
02275 next_step_callback( TRUE, userdata );
02276 }
02277 }
02278
02279
02280
02281 void LLFloaterCustomize::onSaveAllDialog( S32 option, void* userdata )
02282 {
02283 LLFloaterCustomize* self = (LLFloaterCustomize*) userdata;
02284
02285 BOOL proceed = FALSE;
02286
02287 switch( option )
02288 {
02289 case 0:
02290 gAgent.saveAllWearables();
02291 proceed = TRUE;
02292 break;
02293
02294 case 1:
02295 {
02296
02297 EWearableType cur = getCurrentWearableType();
02298 gAgent.revertAllWearables();
02299 setCurrentWearableType( cur );
02300 proceed = TRUE;
02301 }
02302 break;
02303
02304 case 2:
02305 break;
02306
02307 default:
02308 llassert(0);
02309 break;
02310 }
02311
02312 if( self->mNextStepAfterSaveAllCallback )
02313 {
02314 self->mNextStepAfterSaveAllCallback( proceed, self->mNextStepAfterSaveAllUserdata );
02315 }
02316 }
02317
02318
02319 class LLCurrentlyWorn : public LLInventoryFetchObserver
02320 {
02321 public:
02322 LLCurrentlyWorn() {}
02323 ~LLCurrentlyWorn() {}
02324 virtual void done() { }
02325 };
02326
02327 void LLFloaterCustomize::fetchInventory()
02328 {
02329
02330 LLInventoryFetchObserver::item_ref_t ids;
02331 LLUUID item_id;
02332 for(S32 type = (S32)WT_SHAPE; type < (S32)WT_COUNT; ++type)
02333 {
02334 item_id = gAgent.getWearableItem((EWearableType)type);
02335 if(item_id.notNull())
02336 {
02337 ids.push_back(item_id);
02338 }
02339 }
02340
02341
02342
02343 LLCurrentlyWorn worn;
02344 worn.fetchItems(ids);
02345 }
02346
02347 void LLFloaterCustomize::updateInventoryUI()
02348 {
02349 BOOL all_complete = TRUE;
02350 BOOL is_complete = FALSE;
02351 U32 perm_mask = 0x0;
02352 LLPanelEditWearable* panel;
02353 LLViewerInventoryItem* item;
02354 for(S32 i = 0; i < WT_COUNT; ++i)
02355 {
02356 item = NULL;
02357 panel = mWearablePanelList[i];
02358 if(panel)
02359 {
02360 item = (LLViewerInventoryItem*)gAgent.getWearableInventoryItem(panel->getType());
02361 }
02362 if(item)
02363 {
02364 is_complete = item->isComplete();
02365 if(!is_complete)
02366 {
02367 all_complete = FALSE;
02368 }
02369 perm_mask = item->getPermissions().getMaskOwner();
02370 }
02371 else
02372 {
02373 is_complete = false;
02374 perm_mask = 0x0;
02375 }
02376 if(i == sCurrentWearableType)
02377 {
02378 if(panel)
02379 {
02380 panel->setUIPermissions(perm_mask, is_complete);
02381 }
02382 BOOL is_vis = panel && item && is_complete && (perm_mask & PERM_MODIFY);
02383 childSetVisible("panel_container", is_vis);
02384 }
02385 }
02386 childSetEnabled("Make Outfit", all_complete);
02387 }
02388
02389 void LLFloaterCustomize::updateScrollingPanelUI()
02390 {
02391 LLPanelEditWearable* panel = mWearablePanelList[sCurrentWearableType];
02392 if(panel)
02393 {
02394 LLViewerInventoryItem* item = (LLViewerInventoryItem*)gAgent.getWearableInventoryItem(panel->getType());
02395 if(item)
02396 {
02397 U32 perm_mask = item->getPermissions().getMaskOwner();
02398 BOOL is_complete = item->isComplete();
02399 updateScrollingPanelList((perm_mask & PERM_MODIFY) ? is_complete : FALSE);
02400 }
02401 }
02402 }
02403
02405
02406
02407 void LLUndoWearable::setVisualParam( S32 param_id, F32 weight)
02408 {
02409 mAppearance.clear();
02410 mAppearance.addParam( param_id, weight );
02411 }
02412
02413 void LLUndoWearable::setTexture( LLVOAvatar::ETextureIndex te, const LLUUID& asset_id )
02414 {
02415 mAppearance.clear();
02416 mAppearance.addTexture( te, asset_id );
02417 }
02418
02419 void LLUndoWearable::setColor( LLVOAvatar::ETextureIndex te, const LLColor4& color )
02420 {
02421 LLVOAvatar* avatar = gAgent.getAvatarObject();
02422 if( !avatar )
02423 {
02424 return;
02425 }
02426
02427 const char* param_name[3];
02428 if( avatar->teToColorParams( te, param_name ) )
02429 {
02430 mAppearance.clear();
02431 LLVisualParam* param;
02432 param = avatar->getVisualParam( param_name[0] );
02433 if( param )
02434 {
02435 mAppearance.addParam( param->getID(), color.mV[VX] );
02436 }
02437 param = avatar->getVisualParam( param_name[1] );
02438 if( param )
02439 {
02440 mAppearance.addParam( param->getID(), color.mV[VY] );
02441 }
02442 param = avatar->getVisualParam( param_name[2] );
02443 if( param )
02444 {
02445 mAppearance.addParam( param->getID(), color.mV[VZ] );
02446 }
02447 }
02448 }
02449
02450 void LLUndoWearable::setWearable( EWearableType type )
02451 {
02452 LLVOAvatar* avatar = gAgent.getAvatarObject();
02453 if( !avatar )
02454 {
02455 return;
02456 }
02457
02458 mAppearance.clear();
02459
02460 for( LLVisualParam* param = avatar->getFirstVisualParam(); param; param = avatar->getNextVisualParam() )
02461 {
02462 LLViewerVisualParam* viewer_param = (LLViewerVisualParam*)param;
02463 if( (viewer_param->getWearableType() == type) &&
02464 (viewer_param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE) )
02465 {
02466 mAppearance.addParam( viewer_param->getID(), viewer_param->getWeight() );
02467 }
02468 }
02469
02470 for( S32 te = 0; te < LLVOAvatar::TEX_NUM_ENTRIES; te++ )
02471 {
02472 if( LLVOAvatar::getTEWearableType( te ) == type )
02473 {
02474 LLViewerImage* te_image = avatar->getTEImage( te );
02475 if( te_image )
02476 {
02477 mAppearance.addTexture( te, te_image->getID() );
02478 }
02479 }
02480 }
02481 }
02482
02483
02484 void LLUndoWearable::applyUndoRedo()
02485 {
02486 LLVOAvatar* avatar = gAgent.getAvatarObject();
02487 if( !avatar )
02488 {
02489 return;
02490 }
02491
02492 ESex old_sex = avatar->getSex();
02493
02494
02495 for( F32* weightp = mAppearance.mParamMap.getFirstData(); weightp; weightp = mAppearance.mParamMap.getNextData() )
02496 {
02497 S32 param_id = mAppearance.mParamMap.getCurrentKeyWithoutIncrement();
02498
02499 F32 existing_weight = gAgent.getAvatarObject()->getVisualParamWeight( param_id );
02500 avatar->setVisualParamWeight(param_id, *weightp, TRUE);
02501 *weightp = existing_weight;
02502 }
02503
02504
02505 for( S32 i = 0; i < LLVOAvatar::TEX_NUM_ENTRIES; i++ )
02506 {
02507 const LLUUID& image_id = mAppearance.mTextures[i];
02508 if( !image_id.isNull() )
02509 {
02510 LLViewerImage* existing_image = avatar->getTEImage( i );
02511 if( existing_image )
02512 {
02513 const LLUUID& existing_asset_id = existing_image->getID();
02514 avatar->setLocTexTE( i, gImageList.getImage( mAppearance.mTextures[i] ), TRUE );
02515 mAppearance.mTextures[i] = existing_asset_id;
02516 }
02517 }
02518 }
02519
02520 avatar->updateVisualParams();
02521
02522 ESex new_sex = avatar->getSex();
02523 if( old_sex != new_sex )
02524 {
02525 gSavedSettings.setU32( "AvatarSex", (new_sex == SEX_MALE) );
02526 avatar->updateSexDependentLayerSets( TRUE );
02527 }
02528
02529 LLVisualParamHint::requestHintUpdates();
02530
02531 if( gFloaterCustomize )
02532 {
02533 gFloaterCustomize->updateScrollingPanelList(TRUE);
02534 }
02535
02536 gAgent.sendAgentSetAppearance();
02537 }