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