diff options
| author | Vadim Savchuk <vsavchuk@productengine.com> | 2010-04-23 15:41:15 +0300 | 
|---|---|---|
| committer | Vadim Savchuk <vsavchuk@productengine.com> | 2010-04-23 15:41:15 +0300 | 
| commit | efd7b2502df521e945274db74f88297a358e5144 (patch) | |
| tree | faeec4371a2e84e7dee00cbb9b51bba51e9b981d | |
| parent | d24a134df906d5a602bd939f48520bfdab08093b (diff) | |
| parent | 5405bf10cdb2a1c75f0f28ec88e82a6ba5487183 (diff) | |
merge
--HG--
branch : product-engine
| -rw-r--r-- | indra/newview/llagentwearables.cpp | 33 | ||||
| -rw-r--r-- | indra/newview/llagentwearables.h | 2 | ||||
| -rw-r--r-- | indra/newview/llappearancemgr.cpp | 93 | ||||
| -rw-r--r-- | indra/newview/llappearancemgr.h | 2 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitedit.cpp | 37 | ||||
| -rw-r--r-- | indra/newview/llpaneloutfitedit.h | 4 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_outfit_edit.xml | 24 | 
7 files changed, 190 insertions, 5 deletions
| diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 466f2d499d..8a880e5ace 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2031,6 +2031,39 @@ void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL upload_bake)  	}  } +bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool closer_to_body) +{ +	if (!item) return false; +	if (!item->isWearableType()) return false; + +	wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(item->getWearableType()); +	if (wearable_iter == mWearableDatas.end()) return false; + +	wearableentry_vec_t& wearable_vec = wearable_iter->second; +	if (wearable_vec.empty()) return false; + +	const LLUUID& asset_id = item->getAssetUUID(); + +	//nowhere to move if the wearable is already on any boundary (closest to the body/furthest from the body) +	if (closer_to_body && asset_id == wearable_vec.front()->getAssetID()) return false; +	if (!closer_to_body && asset_id == wearable_vec.back()->getAssetID()) return false; + +	for (U32 i = 0; i < wearable_vec.size(); ++i) +	{ +		LLWearable* wearable = wearable_vec[i]; +		if (!wearable) continue; +		if (wearable->getAssetID() != asset_id) continue; +		 +		//swapping wearables +		U32 swap_i = closer_to_body ? i-1 : i+1; +		wearable_vec[i] = wearable_vec[swap_i]; +		wearable_vec[swap_i] = wearable; +		return true; +	} + +	return false; +} +  void LLAgentWearables::updateServer()  {  	sendAgentWearablesUpdate(); diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 585fd3f8b3..d3b18f68f1 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -82,6 +82,8 @@ public:  	void			animateAllWearableParams(F32 delta, BOOL upload_bake); +	bool			moveWearable(const LLViewerInventoryItem* item, bool closer_to_body); +  	//--------------------------------------------------------------------  	// Accessors  	//-------------------------------------------------------------------- diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 9e02886e4f..a6a3aa28d6 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -122,6 +122,38 @@ private:  	bool mAppend;  }; + +//Inventory callback updating "dirty" state when destroyed +class LLUpdateDirtyState: public LLInventoryCallback +{ +public: +	LLUpdateDirtyState() {} +	virtual ~LLUpdateDirtyState(){ LLAppearanceMgr::getInstance()->updateIsDirty(); } +	virtual void fire(const LLUUID&) {} +}; + + +//Inventory collect functor collecting wearables of a specific wearable type +class LLFindClothesOfType : public LLInventoryCollectFunctor +{ +public: +	LLFindClothesOfType(EWearableType type) : mWearableType(type) {} +	virtual ~LLFindClothesOfType() {} +	virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) +	{ +		if (!item) return false; +		if (item->getType() != LLAssetType::AT_CLOTHING) return false; +		 +		LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item); +		if (!vitem || vitem->getWearableType() != mWearableType) return false; + +		return true; +	} + +	const EWearableType mWearableType; +}; + +  LLUpdateAppearanceOnDestroy::LLUpdateAppearanceOnDestroy():  	mFireCount(0)  { @@ -1593,8 +1625,11 @@ bool LLAppearanceMgr::updateBaseOutfit()  	// in a Base Outfit we do not remove items, only links  	purgeCategory(base_outfit_id, false); + +	LLPointer<LLInventoryCallback> dirty_state_updater = new LLUpdateDirtyState(); +  	//COF contains only links so we copy to the Base Outfit only links -	shallowCopyCategoryContents(getCOF(), base_outfit_id, NULL); +	shallowCopyCategoryContents(getCOF(), base_outfit_id, dirty_state_updater);  	return true;  } @@ -1802,6 +1837,62 @@ void LLAppearanceMgr::removeItemFromAvatar(const LLUUID& id_to_remove)  	}  } + +bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_body) +{ +	if (!item || !item->isWearableType()) return false; +	if (item->getType() != LLAssetType::AT_CLOTHING) return false; +	if (!gInventory.isObjectDescendentOf(item->getUUID(), getCOF())) return false; + +	LLInventoryModel::cat_array_t cats; +	LLInventoryModel::item_array_t items; +	gInventory.collectDescendentsIf(getCOF(), cats, items, true, LLFindClothesOfType(item->getWearableType())); +	if (items.empty()) return false; + +	//*TODO all items are not guarantied to have valid descriptions (check?) +	std::sort(items.begin(), items.end(), WearablesOrderComparator(item->getWearableType())); + +	if (closer_to_body && items.front() == item) return false; +	if (!closer_to_body && items.back() == item) return false; +	 +	LLInventoryModel::item_array_t::iterator it = std::find(items.begin(), items.end(), item); +	if (items.end() == it) return false; + + +	//swapping descriptions +	closer_to_body ? --it : ++it; +	LLViewerInventoryItem* swap_item = *it; +	if (!swap_item) return false; +	std::string tmp = swap_item->LLInventoryItem::getDescription(); +	swap_item->setDescription(item->LLInventoryItem::getDescription()); +	item->setDescription(tmp); + + +	//items need to be updated on a dataserver +	item->setComplete(TRUE); +	item->updateServer(FALSE); +	gInventory.updateItem(item); + +	swap_item->setComplete(TRUE); +	swap_item->updateServer(FALSE); +	gInventory.updateItem(swap_item); + +	//to cause appearance of the agent to be updated +	bool result = false; +	if (result = gAgentWearables.moveWearable(item, closer_to_body)) +	{ +		gAgentAvatarp->wearableUpdated(item->getWearableType(), TRUE); +	} + +	setOutfitDirty(true); + +	//*TODO do we need to notify observers here in such a way? +	gInventory.notifyObservers(); + +	return result; +} + +  //#define DUMP_CAT_VERBOSE  void LLAppearanceMgr::dumpCat(const LLUUID& cat_id, const std::string& msg) diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index efb5274c5b..a308a3efa9 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -141,6 +141,8 @@ public:  	LLUUID makeNewOutfitLinks(const std::string& new_folder_name); +	bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body); +  protected:  	LLAppearanceMgr();  	~LLAppearanceMgr(); diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index e139cb31d6..ae181e2819 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -73,6 +73,9 @@ const U64 WEARABLE_MASK = (1LL << LLInventoryType::IT_WEARABLE);  const U64 ATTACHMENT_MASK = (1LL << LLInventoryType::IT_ATTACHMENT) | (1LL << LLInventoryType::IT_OBJECT);  const U64 ALL_ITEMS_MASK = WEARABLE_MASK | ATTACHMENT_MASK; +static const std::string SAVE_BTN("save_btn"); +static const std::string REVERT_BTN("revert_btn"); +  class LLInventoryLookObserver : public LLInventoryObserver  {  public: @@ -221,10 +224,9 @@ BOOL LLPanelOutfitEdit::postBuild()  	mEditWearableBtn->setVisible(FALSE);  	mEditWearableBtn->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this)); -	childSetAction("revert_btn", boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance())); +	childSetAction(REVERT_BTN, boost::bind(&LLAppearanceMgr::wearBaseOutfit, LLAppearanceMgr::getInstance())); -	childSetAction("save_btn", boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false)); -	childSetAction("save_as_btn", boost::bind(&LLPanelOutfitEdit::saveOutfit, this, true)); +	childSetAction(SAVE_BTN, boost::bind(&LLPanelOutfitEdit::saveOutfit, this, false));  	childSetAction("save_flyout_btn", boost::bind(&LLPanelOutfitEdit::showSaveMenu, this));  	LLUICtrl::CommitCallbackRegistry::ScopedRegistrar save_registar; @@ -234,10 +236,22 @@ BOOL LLPanelOutfitEdit::postBuild()  	mWearableListManager = new LLFilteredWearableListManager(  		getChild<LLInventoryItemsList>("filtered_wearables_list"), ALL_ITEMS_MASK); +		 +	childSetAction("move_closer_btn", boost::bind(&LLPanelOutfitEdit::moveWearable, this, true)); +	childSetAction("move_further_btn", boost::bind(&LLPanelOutfitEdit::moveWearable, this, false));  	return TRUE;  } +void LLPanelOutfitEdit::moveWearable(bool closer_to_body) +{ +	LLViewerInventoryItem* wearable_to_move = gInventory.getItem(mLookContents->getSelectionInterface()->getCurrentID()); +	LLAppearanceMgr::getInstance()->moveWearable(wearable_to_move, closer_to_body); + +	//*TODO why not to listen to inventory? +	updateLookInfo(); +} +  void LLPanelOutfitEdit::showAddWearablesPanel()  {  	childSetVisible("add_wearables_panel", childGetValue("add_btn")); @@ -267,6 +281,8 @@ void LLPanelOutfitEdit::saveOutfit(bool as_new)  	{  		panel_outfits_inventory->onSave();  	} + +	//*TODO how to get to know when base outfit is updated or new outfit is created?  }  void LLPanelOutfitEdit::showSaveMenu() @@ -542,10 +558,12 @@ void LLPanelOutfitEdit::lookFetched(void)  		columns[0]["value"] = item->getName();  		columns[1]["column"] = "look_item_sort";  		columns[1]["type"] = "text"; // TODO: multi-wearable sort "type" should go here. -		columns[1]["value"] = "BAR"; // TODO: Multi-wearable sort index should go here +		columns[1]["value"] = item->LLInventoryItem::getDescription();  		mLookContents->addElement(row);  	} + +	updateVerbs();  }  void LLPanelOutfitEdit::updateLookInfo() @@ -589,4 +607,15 @@ void LLPanelOutfitEdit::displayCurrentOutfit()  	updateLookInfo();  } +//private +void LLPanelOutfitEdit::updateVerbs() +{ +	bool outfit_is_dirty = LLAppearanceMgr::getInstance()->isOutfitDirty(); +	 +	childSetEnabled(SAVE_BTN, outfit_is_dirty); +	childSetEnabled(REVERT_BTN, outfit_is_dirty); + +	mSaveMenu->setItemEnabled("save_outfit", outfit_is_dirty); +} +  // EOF diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 308ee23115..b6f121d484 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -87,6 +87,8 @@ public:  		// Sends a request for data about the given parcel, which will  		// only update the location if there is none already available. +	void moveWearable(bool closer_to_body); +  	void showAddWearablesPanel();  	void showWearablesFilter();  	void showFilteredWearablesPanel(); @@ -110,6 +112,8 @@ public:  private: +	void updateVerbs(); +  	//*TODO got rid of mCurrentOutfitID  	LLUUID				mCurrentOutfitID; diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index b1f0ff15cb..314d2389ae 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -222,6 +222,30 @@                   top="1"                   width="31" />                  <button +                 follows="bottom|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Movement_Forward_On" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="1" +                 name="move_closer_btn" +                 top="1" +                 width="31" /> +                <button +                 follows="bottom|left" +                 height="25" +                 image_hover_unselected="Toolbar_Middle_Over" +                 image_overlay="Movement_Backward_On" +                 image_selected="Toolbar_Middle_Selected" +                 image_unselected="Toolbar_Middle_Off" +                 layout="topleft" +                 left_pad="1" +                 name="move_further_btn" +                 top="1" +                 width="31" /> +                <button                   follows="bottom|right"                   height="25"                   image_hover_unselected="Toolbar_Middle_Over" | 
