summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Lihatskiy <alihatskiy@productengine.com>2025-04-18 18:11:09 +0300
committerAndrey Lihatskiy <alihatskiy@productengine.com>2025-04-18 18:11:09 +0300
commit01f73fe120244f1849e987f0273e2bbbbb87d342 (patch)
tree69843c7cdef5db189b605d13a554ad0f0c9c54d8
parent082c9158b2ad961b747ca6a7bd55bc2a79f27b6a (diff)
parentd3d8513c3b5a7f25adac777d9d59896d8dbd14c0 (diff)
Merge branch 'release/2025.05' into marchcat/05-develop
-rw-r--r--indra/llui/llfolderview.cpp5
-rw-r--r--indra/llui/llfolderview.h2
-rw-r--r--indra/llui/llfolderviewitem.cpp34
-rw-r--r--indra/newview/llinventoryfunctions.cpp24
-rw-r--r--indra/newview/llinventorylistitem.cpp56
-rw-r--r--indra/newview/llinventorylistitem.h6
-rw-r--r--indra/newview/lloutfitgallery.cpp12
-rw-r--r--indra/newview/llwearableitemslist.cpp8
-rw-r--r--indra/newview/llwearableitemslist.h2
-rw-r--r--indra/newview/skins/default/xui/en/floater_my_inventory.xml2
10 files changed, 101 insertions, 50 deletions
diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp
index dc1b81666a..b664065532 100644
--- a/indra/llui/llfolderview.cpp
+++ b/indra/llui/llfolderview.cpp
@@ -1693,11 +1693,6 @@ LLRect LLFolderView::getVisibleRect()
return visible_rect;
}
-S32 LLFolderView::getVisibleContentWidth()
-{
- return (mScrollContainer ? mScrollContainer->getVisibleContentRect().getWidth() : 0);
-}
-
bool LLFolderView::getShowSelectionContext()
{
if (mShowSelectionContext)
diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h
index d3d8f8daff..bcdbdf8c07 100644
--- a/indra/llui/llfolderview.h
+++ b/indra/llui/llfolderview.h
@@ -221,8 +221,8 @@ public:
void scrollToShowSelection();
void scrollToShowItem(LLFolderViewItem* item, const LLRect& constraint_rect);
void setScrollContainer( LLScrollContainer* parent ) { mScrollContainer = parent; }
+ LLScrollContainer* getScrollContainer() { return mScrollContainer; }
LLRect getVisibleRect();
- S32 getVisibleContentWidth();
bool search(LLFolderViewItem* first_item, const std::string &search_string, bool backward);
void setShowSelectionContext(bool show) { mShowSelectionContext = show; }
diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp
index 879dd270ce..9ca77dbe46 100644
--- a/indra/llui/llfolderviewitem.cpp
+++ b/indra/llui/llfolderviewitem.cpp
@@ -73,6 +73,9 @@ const F32 LLFolderViewItem::FOLDER_OPEN_TIME_CONSTANT = 0.03f;
const LLColor4U DEFAULT_WHITE(255, 255, 255);
+constexpr S32 FAVORITE_IMAGE_SIZE = 14;
+constexpr S32 FAVORITE_IMAGE_PAD = 3;
+
//static
LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style)
@@ -460,6 +463,10 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height )
}
mLabelWidth = getLabelXPos() + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel.c_str()) + getLabelFontForStyle(LLFontGL::NORMAL)->getWidth(mLabelSuffix.c_str()) + mLabelPaddingRight;
mLabelWidthDirty = false;
+ if (mIsFavorite)
+ {
+ mLabelWidth += FAVORITE_IMAGE_SIZE + FAVORITE_IMAGE_PAD;
+ }
}
*width = llmax(*width, mLabelWidth);
@@ -825,18 +832,25 @@ void LLFolderViewItem::drawFavoriteIcon()
if (favorite_image)
{
- constexpr S32 PAD = 3;
- constexpr S32 image_size = 14;
-
- S32 width = mRoot->getVisibleContentWidth(); // star should stick to scroller's right side
- if (width <= 0)
+ S32 x_offset = 0;
+ LLScrollContainer* scroll = mRoot->getScrollContainer();
+ if (scroll)
{
- width = getRect().getWidth();
+ S32 width = scroll->getVisibleContentRect().getWidth();
+ S32 offset = scroll->getDocPosHorizontal();
+ x_offset = width + offset;
+ }
+ else
+ {
+ x_offset = getRect().getWidth();
}
-
gl_draw_scaled_image(
- width - image_size - PAD, getRect().getHeight() - mItemHeight + PAD,
- image_size, image_size, favorite_image->getImage(), sFgColor);
+ x_offset - FAVORITE_IMAGE_SIZE - FAVORITE_IMAGE_PAD,
+ getRect().getHeight() - mItemHeight + FAVORITE_IMAGE_PAD,
+ FAVORITE_IMAGE_SIZE,
+ FAVORITE_IMAGE_SIZE,
+ favorite_image->getImage(),
+ sFgColor);
}
}
@@ -1908,7 +1922,7 @@ void LLFolderViewFolder::onIdleUpdateFavorites(void* data)
}
else
{
- LL_WARNS() << "FAVORITE_ADDED for a folder without favorites" << LL_ENDL;
+ // already up to date
self->mFavoritesDirtyFlags = 0;
gIdleCallbacks.deleteFunction(&LLFolderViewFolder::onIdleUpdateFavorites, self);
}
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index 22ee036a6d..a2626daa2e 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -2150,21 +2150,10 @@ void validate_marketplacelistings(
void change_item_parent(const LLUUID& item_id, const LLUUID& new_parent_id)
{
- LLInventoryItem* inv_item = gInventory.getItem(item_id);
+ LLViewerInventoryItem* inv_item = gInventory.getItem(item_id);
if (inv_item)
{
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(inv_item->getParentUUID(), -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent_id, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(inv_item);
- new_item->setParent(new_parent_id);
- new_item->updateParentOnServer(false);
- gInventory.updateItem(new_item);
- gInventory.notifyObservers();
+ gInventory.changeItemParent(inv_item, new_parent_id, false);
}
}
@@ -2172,17 +2161,17 @@ void move_items_to_folder(const LLUUID& new_cat_uuid, const uuid_vec_t& selected
{
for (uuid_vec_t::const_iterator it = selected_uuids.begin(); it != selected_uuids.end(); ++it)
{
- LLInventoryItem* inv_item = gInventory.getItem(*it);
+ LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
if (inv_item)
{
- change_item_parent(*it, new_cat_uuid);
+ gInventory.changeItemParent(inv_item, new_cat_uuid, false);
}
else
{
- LLInventoryCategory* inv_cat = gInventory.getCategory(*it);
+ LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (inv_cat && !LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()))
{
- gInventory.changeCategoryParent((LLViewerInventoryCategory*)inv_cat, new_cat_uuid, false);
+ gInventory.changeCategoryParent(inv_cat, new_cat_uuid, false);
}
}
}
@@ -3577,7 +3566,6 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
}
else if ("new_folder_from_selected" == action)
{
-
LLInventoryObject* first_item = gInventory.getObject(*ids.begin());
if (!first_item)
{
diff --git a/indra/newview/llinventorylistitem.cpp b/indra/newview/llinventorylistitem.cpp
index e210975a5a..5fb5b0f23f 100644
--- a/indra/newview/llinventorylistitem.cpp
+++ b/indra/newview/llinventorylistitem.cpp
@@ -43,7 +43,19 @@
static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelInventoryListItemBaseParams(&typeid(LLPanelInventoryListItemBase::Params), "inventory_list_item");
-static const S32 WIDGET_SPACING = 3;
+constexpr S32 WIDGET_SPACING = 3;
+constexpr S32 FAVORITE_IMAGE_SIZE = 14;
+constexpr S32 FAVORITE_IMAGE_PAD = 3;
+
+bool get_is_item_favorite(const LLViewerInventoryItem* inv)
+{
+ if (inv->getIsLinkType())
+ {
+ LLInventoryObject* obj = gInventory.getObject(inv->getLinkedUUID());
+ return obj && obj->getIsFavorite();
+ }
+ return inv->getIsFavorite();
+}
LLPanelInventoryListItemBase::Params::Params()
: default_style("default_style"),
@@ -75,19 +87,30 @@ void LLPanelInventoryListItemBase::draw()
LLViewerInventoryItem* inv_item = getItem();
if (inv_item)
{
- updateItem(inv_item->getName());
+ updateItem(inv_item->getName(), get_is_item_favorite(inv_item));
}
setNeedsRefresh(false);
}
+ static LLUICachedControl<bool> draw_star("InventoryFavoritesUseStar", true);
+
+ LLRect local_rect = getLocalRect();
if (mHovered && mHoverImage)
{
- mHoverImage->draw(getLocalRect());
+ mHoverImage->draw(local_rect);
+ }
+ else if (mIsFavorite && draw_star())
+ {
+
+ static LLPointer<LLUIImage> fav_img = LLRender2D::getInstance()->getUIImage("Inv_Favorite_Star_Full");
+ gl_draw_scaled_image(
+ local_rect.getWidth() - FAVORITE_IMAGE_SIZE - FAVORITE_IMAGE_PAD, FAVORITE_IMAGE_PAD,
+ FAVORITE_IMAGE_SIZE, FAVORITE_IMAGE_SIZE, fav_img->getImage());
}
if (mSelected && mSelectedImage)
{
- mSelectedImage->draw(getLocalRect());
+ mSelectedImage->draw(local_rect);
}
if (mSeparatorVisible && mSeparatorImage)
@@ -95,7 +118,7 @@ void LLPanelInventoryListItemBase::draw()
// place under bottom of listitem, using image height
// item_pad in list using the item should be >= image height
// to avoid cropping of top of the next item.
- LLRect separator_rect = getLocalRect();
+ LLRect separator_rect = local_rect;
separator_rect.mTop = separator_rect.mBottom;
separator_rect.mBottom -= mSeparatorImage->getHeight();
F32 alpha = getCurrentTransparency();
@@ -107,9 +130,15 @@ void LLPanelInventoryListItemBase::draw()
// virtual
void LLPanelInventoryListItemBase::updateItem(const std::string& name,
+ bool favorite,
EItemState item_state)
{
setIconImage(mIconImage);
+ if (mIsFavorite != favorite)
+ {
+ mIsFavorite = favorite;
+ reshapeMiddleWidgets();
+ }
setTitle(name, mHighlightedText, item_state);
}
@@ -164,7 +193,7 @@ bool LLPanelInventoryListItemBase::postBuild()
if (inv_item)
{
mIconImage = LLInventoryIcon::getIcon(inv_item->getType(), inv_item->getInventoryType(), inv_item->getFlags(), false);
- updateItem(inv_item->getName());
+ updateItem(inv_item->getName(), get_is_item_favorite(inv_item));
}
setNeedsRefresh(true);
@@ -290,6 +319,7 @@ LLPanelInventoryListItemBase::LLPanelInventoryListItemBase(LLViewerInventoryItem
mHovered(false),
mSelected(false),
mSeparatorVisible(false),
+ mIsFavorite(false),
mHoverImage(params.hover_image),
mSelectedImage(params.selected_image),
mSeparatorImage(params.separator_image)
@@ -392,6 +422,16 @@ void LLPanelInventoryListItemBase::setTitle(const std::string& title,
default:;
}
+ if (mIsFavorite)
+ {
+ static LLUICachedControl<bool> use_color("InventoryFavoritesColorText", true);
+ if (use_color)
+ {
+ static const LLUIColor favorite_color = LLUIColorTable::instance().getColor("InventoryFavoriteColor", LLColor4::white);
+ style_params.color = favorite_color;
+ }
+ }
+
LLTextUtil::textboxSetHighlightedVal(
mTitleCtrl,
style_params,
@@ -466,6 +506,10 @@ void LLPanelInventoryListItemBase::reshapeMiddleWidgets()
S32 name_left = icon_rect.mRight + getWidgetSpacing();
S32 name_right = getLocalRect().getWidth() - mRightWidgetsWidth - getWidgetSpacing();
+ if (mIsFavorite)
+ {
+ name_right -= FAVORITE_IMAGE_SIZE + FAVORITE_IMAGE_PAD;
+ }
LLRect name_rect(mTitleCtrl->getRect());
name_rect.set(name_left, name_rect.mTop, name_right, name_rect.mBottom);
mTitleCtrl->setShape(name_rect);
diff --git a/indra/newview/llinventorylistitem.h b/indra/newview/llinventorylistitem.h
index 21540a380b..40a86001a4 100644
--- a/indra/newview/llinventorylistitem.h
+++ b/indra/newview/llinventorylistitem.h
@@ -167,6 +167,7 @@ protected:
* Called after inventory item was updated, update panel widgets to reflect inventory changes.
*/
virtual void updateItem(const std::string& name,
+ bool favorite,
EItemState item_state = IS_DEFAULT);
void setLeftWidgetsWidth(S32 width) { mLeftWidgetsWidth = width; }
@@ -222,8 +223,9 @@ private:
LLUIImagePtr mSelectedImage;
LLUIImagePtr mSeparatorImage;
- bool mSelected;
- bool mSeparatorVisible;
+ bool mSelected = false;
+ bool mSeparatorVisible = false;
+ bool mIsFavorite = false; // note that any setter needs to update tittle
std::string mHighlightedText;
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index 1767990aed..7ab63be009 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -432,24 +432,28 @@ bool compareGalleryItem(LLOutfitGalleryItem* item1, LLOutfitGalleryItem* item2)
switch (sort_by_name())
{
case 2:
+ // Sort by favorites - favorite items first, then alphabetically
if (item1->isFavorite() != item2->isFavorite())
{
return item1->isFavorite();
+ }
break;
case 1:
+ // Sort by images - items with non-default images first, then alphabetically
if (item1->isDefaultImage() != item2->isDefaultImage())
+ {
+ return item2->isDefaultImage();
+ }
break;
default:
+ // Sort alphabetically only
break;
}
+ // Final comparison is always alphabetical by name
std::string name1 = item1->getItemName();
std::string name2 = item2->getItemName();
return (LLStringUtil::compareDict(name1, name2) < 0);
- }
- {
- return item2->isDefaultImage();
- }
}
void LLOutfitGallery::reArrangeRows(S32 row_diff)
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index a4e84d3b3a..8b0492ceed 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -195,6 +195,7 @@ LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item
// virtual
void LLPanelWearableOutfitItem::updateItem(const std::string& name,
+ bool favorite,
EItemState item_state)
{
std::string search_label = name;
@@ -225,7 +226,7 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name,
}
}
- LLPanelInventoryListItemBase::updateItem(search_label, item_state);
+ LLPanelInventoryListItemBase::updateItem(search_label, favorite, item_state);
}
//////////////////////////////////////////////////////////////////////////
@@ -452,6 +453,7 @@ LLPanelAttachmentListItem* LLPanelAttachmentListItem::create(LLViewerInventoryIt
}
void LLPanelAttachmentListItem::updateItem(const std::string& name,
+ bool favorite,
EItemState item_state)
{
std::string title_joint = name;
@@ -469,7 +471,7 @@ void LLPanelAttachmentListItem::updateItem(const std::string& name,
title_joint = title_joint + " (" + trans_name + ")";
}
- LLPanelInventoryListItemBase::updateItem(title_joint, item_state);
+ LLPanelInventoryListItemBase::updateItem(title_joint, favorite, item_state);
}
//////////////////////////////////////////////////////////////////////////
@@ -497,7 +499,7 @@ bool LLPanelDummyClothingListItem::postBuild()
addWidgetToRightSide("btn_add_panel");
setIconImage(LLInventoryIcon::getIcon(LLAssetType::AT_CLOTHING, LLInventoryType::IT_NONE, mWearableType, false));
- updateItem(wearableTypeToString(mWearableType));
+ updateItem(wearableTypeToString(mWearableType), false);
// Make it look loke clothing item - reserve space for 'delete' button
setLeftWidgetsWidth(getChildView("item_icon")->getRect().mLeft);
diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h
index 3fe1059176..7ba64c90da 100644
--- a/indra/newview/llwearableitemslist.h
+++ b/indra/newview/llwearableitemslist.h
@@ -94,6 +94,7 @@ public:
* Updates item name and (worn) suffix.
*/
/*virtual*/ void updateItem(const std::string& name,
+ bool favorite,
EItemState item_state = IS_DEFAULT);
void onAddWearable();
@@ -147,6 +148,7 @@ public:
/** Set item title. Joint name is added to the title in parenthesis */
/*virtual*/ void updateItem(const std::string& name,
+ bool favorite,
EItemState item_state = IS_DEFAULT);
protected:
diff --git a/indra/newview/skins/default/xui/en/floater_my_inventory.xml b/indra/newview/skins/default/xui/en/floater_my_inventory.xml
index a9900f05b7..881c1f7469 100644
--- a/indra/newview/skins/default/xui/en/floater_my_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_my_inventory.xml
@@ -12,7 +12,7 @@
save_visibility="true"
reuse_instance="true"
title="INVENTORY"
- width="363" >
+ width="418" >
<panel
class="sidepanel_inventory"
name="main_panel"