diff options
Diffstat (limited to 'indra/newview/llcofwearables.cpp')
| -rw-r--r-- | indra/newview/llcofwearables.cpp | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 6bd15d4b61..f5d144dcc6 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -292,7 +292,8 @@ LLCOFWearables::LLCOFWearables() : LLPanel(), mBodyPartsTab(NULL), mLastSelectedTab(NULL), mAccordionCtrl(NULL), - mCOFVersion(-1) + mCOFVersion(-1), + mRefreshPending(false) { mClothingMenu = new CofClothingContextMenu(this); mAttachmentMenu = new CofAttachmentContextMenu(this); @@ -326,6 +327,10 @@ bool LLCOFWearables::postBuild() mClothing->setCommitOnSelectionChange(true); mBodyParts->setCommitOnSelectionChange(true); + mClothing->setReorderValidateCallback(boost::bind(&LLCOFWearables::canReorderClothing, this, _1, _2)); + mClothing->setReorderCallback(boost::bind(&LLCOFWearables::onClothingReordered, this, _1, _2)); + mClothing->setReorderEndedCallback(boost::bind(&LLCOFWearables::onReorderEnded, this)); + //clothing is sorted according to its position relatively to the body mAttachments->setComparator(&WEARABLE_NAME_COMPARATOR); mBodyParts->setComparator(&WEARABLE_NAME_COMPARATOR); @@ -377,6 +382,50 @@ void LLCOFWearables::onSelectionChange(LLFlatListView* selected_list) onCommit(); } +bool LLCOFWearables::canReorderClothing(const LLSD& dragged_value, const LLSD& neighbour_value) +{ + LLViewerInventoryItem* dragged = gInventory.getItem(dragged_value.asUUID()); + LLViewerInventoryItem* neighbour = gInventory.getItem(neighbour_value.asUUID()); + if (!dragged || !neighbour) return false; // reject placeholder/dummy rows + if (!dragged->isWearableType() || !neighbour->isWearableType()) return false; + + return dragged->getWearableType() == neighbour->getWearableType(); +} + +void LLCOFWearables::onClothingReordered(const LLSD& dragged_value, S32 /*new_index*/) +{ + LLViewerInventoryItem* item = gInventory.getItem(dragged_value.asUUID()); + if (!item || !item->isWearableType()) return; + + LLWearableType::EType type = item->getWearableType(); + + // Persist the affected type group's full order from the list's current order + // (furthest-to-closest), which covers both single- and multi-row drags. + uuid_vec_t ordered_link_ids; + std::vector<LLSD> values; + mClothing->getValues(values); + for (const LLSD& value : values) + { + LLViewerInventoryItem* other = gInventory.getItem(value.asUUID()); + if (!other || !other->isWearableType() || other->getWearableType() != type) continue; + + ordered_link_ids.push_back(value.asUUID()); + } + + if (ordered_link_ids.size() < 2) return; + + LLAppearanceMgr::getInstance()->reorderWearableGroup(type, ordered_link_ids); +} + +void LLCOFWearables::onReorderEnded() +{ + // Run a refresh that arrived (and was skipped) while the drag was active. + if (mRefreshPending) + { + refresh(); + } +} + void LLCOFWearables::onAccordionTabStateChanged(LLUICtrl* ctrl, const LLSD& expanded) { bool had_selected_items = mClothing->numSelected() || mAttachments->numSelected() || mBodyParts->numSelected(); @@ -401,6 +450,15 @@ void LLCOFWearables::onAccordionTabStateChanged(LLUICtrl* ctrl, const LLSD& expa void LLCOFWearables::refresh() { + // Don't rebuild mid-drag, clearing the list would cancel the active reorder. + // Remember it so onReorderEnded() can re-run the skipped refresh on release. + if (mClothing && mClothing->isReorderActive()) + { + mRefreshPending = true; + return; + } + mRefreshPending = false; + const LLUUID cof_id = LLAppearanceMgr::instance().getCOF(); if (cof_id.isNull()) { @@ -560,6 +618,12 @@ LLPanelClothingListItem* LLCOFWearables::buildClothingListItem(LLViewerInventory item_panel->setShowMoveUpButton(!first); item_panel->setShowMoveDownButton(!last); + // hint that rows in a multi-layer group can be dragged to reorder + if (!(first && last)) + { + item_panel->setToolTip(LLTrans::getString("ReorderClothingTooltip")); + } + //setting callbacks //*TODO move that item panel's inner structure disclosing stuff into the panels item_panel->childSetAction("btn_delete", boost::bind(mCOFCallbacks.mDeleteWearable)); |
