From 6e4fd99df807fe0f14ffd879a02f071c344c46b6 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Wed, 21 Apr 2010 17:03:04 -0400 Subject: Various fixes for multi-attachments support. Ported over from https://hg.lindenlab.com/seraphlinden/seraph-viewer-for-server-1.40/ --- indra/newview/llagentwearables.cpp | 4 ++++ indra/newview/llselectmgr.cpp | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 7f248eee30..ff4404c6c9 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1991,7 +1991,11 @@ void LLAgentWearables::userAttachMultipleAttachments(LLInventoryModel::item_arra msg->nextBlockFast(_PREHASH_ObjectData ); msg->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID()); msg->addUUIDFast(_PREHASH_OwnerID, item->getPermissions().getOwner()); +#if ENABLE_MULTIATTACHMENTS + msg->addU8Fast(_PREHASH_AttachmentPt, 0 | ATTACHMENT_ADD ); +#else msg->addU8Fast(_PREHASH_AttachmentPt, 0 ); // Wear at the previous or default attachment point +#endif pack_permissions_slam(msg, item->getFlags(), item->getPermissions()); msg->addStringFast(_PREHASH_Name, item->getName()); msg->addStringFast(_PREHASH_Description, item->getDescription()); diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index d03a492cd1..2c26bada20 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -3624,14 +3624,14 @@ void LLSelectMgr::sendAttach(U8 attachment_point) return; } -#if ENABLE_MULTIATTACHMENTS - attachment_point |= ATTACHMENT_ADD; -#endif BOOL build_mode = LLToolMgr::getInstance()->inEdit(); // Special case: Attach to default location for this object. if (0 == attachment_point || get_if_there(gAgentAvatarp->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL)) { +#if ENABLE_MULTIATTACHMENTS + attachment_point |= ATTACHMENT_ADD; +#endif sendListToRegions( "ObjectAttach", packAgentIDAndSessionAndAttachment, -- cgit v1.2.3 From 417436f1e92f213f8cf8ce3d68f7616b54604a04 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Wed, 21 Apr 2010 17:03:32 -0400 Subject: Fix for properly allowing deletion from COF when an item appears there that's not worn/attached. --- indra/newview/llinventorybridge.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index b85bf0d518..83057d7cc3 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -211,10 +211,14 @@ BOOL LLInvFVBridge::isItemRemovable() const return FALSE; } - // Disable delete from COF folder; have users explicitly choose "detach/take off". + // Disable delete from COF folder; have users explicitly choose "detach/take off", + // unless the item is not worn but in the COF (i.e. is bugged). if (LLAppearanceMgr::instance().getIsProtectedCOFItem(mUUID)) { - return FALSE; + if (get_is_item_worn(mUUID)) + { + return FALSE; + } } const LLInventoryObject *obj = model->getItem(mUUID); @@ -712,7 +716,7 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, const LLInventoryObject *obj = getInventoryObject(); // Don't allow delete as a direct option from COF folder. - if (obj && obj->getIsLinkType() && isCOFFolder()) + if (obj && obj->getIsLinkType() && isCOFFolder() && get_is_item_worn(mUUID)) { return; } -- cgit v1.2.3 From 404fe5b5256dd87cdb7b7e75096a20a29ae8bf32 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Mon, 26 Apr 2010 16:43:02 -0400 Subject: EXT-7076 : Allow "paste as link" for any item EXT-7077 : Enable paste as link for folders Took out code that was stopping paste for god-mode only. Now everyone can do it. Corrected a bool logic error for protected folder restrictions. --- indra/newview/llinventorybridge.cpp | 53 +++++++++++++++---------------------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 83057d7cc3..04d62ff0bc 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -498,7 +498,7 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const } } const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i)); - if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())) + if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType())) { return FALSE; } @@ -645,13 +645,10 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, disabled_items.push_back(std::string("Paste")); } - if (gAgent.isGodlike()) + items.push_back(std::string("Paste As Link")); + if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) { - items.push_back(std::string("Paste As Link")); - if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0) - { - disabled_items.push_back(std::string("Paste As Link")); - } + disabled_items.push_back(std::string("Paste As Link")); } items.push_back(std::string("Paste Separator")); @@ -1449,17 +1446,11 @@ BOOL LLItemBridge::isItemCopyable() const return FALSE; } - if (gAgent.isGodlike()) - { - // All items can be copied in god mode since you can - // at least paste-as-link the item, though you - // still may not be able paste the item. - return TRUE; - } - else - { - return (item->getPermissions().allowCopyBy(gAgent.getID())); - } + // All items can be copied in god mode since you can + // at least paste-as-link the item, though you + // still may not be able paste the item. + return TRUE; + // return (item->getPermissions().allowCopyBy(gAgent.getID())); } return FALSE; } @@ -1600,7 +1591,8 @@ BOOL LLFolderBridge::isUpToDate() const BOOL LLFolderBridge::isItemCopyable() const { - return FALSE; + // Can copy folders to paste-as-link, but not for straight paste. + return TRUE; } BOOL LLFolderBridge::copyToClipboard() const @@ -2504,7 +2496,6 @@ void LLFolderBridge::pasteLinkFromClipboard() ++iter) { const LLUUID &object_id = (*iter); -#if SUPPORT_ENSEMBLES if (LLInventoryCategory *cat = model->getCategory(object_id)) { link_inventory_item( @@ -2515,18 +2506,16 @@ void LLFolderBridge::pasteLinkFromClipboard() LLAssetType::AT_LINK_FOLDER, LLPointer(NULL)); } - else -#endif - if (LLInventoryItem *item = model->getItem(object_id)) - { - link_inventory_item( - gAgent.getID(), - item->getLinkedUUID(), - parent_id, - item->getName(), - LLAssetType::AT_LINK, - LLPointer(NULL)); - } + else if (LLInventoryItem *item = model->getItem(object_id)) + { + link_inventory_item( + gAgent.getID(), + item->getLinkedUUID(), + parent_id, + item->getName(), + LLAssetType::AT_LINK, + LLPointer(NULL)); + } } } } -- cgit v1.2.3 From ed21ab1546d8870fc32b6830af5b4fe6b6c836df Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 27 Apr 2010 14:02:10 -0400 Subject: EXT-7108 Creating link to openable item should not open the item (e.g. notecard) When you create a link to a notecard, you'll no longer open the notecard. --- indra/newview/llviewermessage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c8a4b27f40..08462f4e58 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1083,7 +1083,7 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name) //////////////////////////////////////////////////////////////////////////////// // Special handling for various types. - const LLAssetType::EType asset_type = item->getType(); + const LLAssetType::EType asset_type = item->getActualType(); if (check_offer_throttle(from_name, false)) // If we are throttled, don't display { LL_DEBUGS("Messaging") << "Highlighting inventory item: " << item->getUUID() << LL_ENDL; -- cgit v1.2.3 From 5f104c1cb585771946d3611e7ec04cb1221f8779 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 27 Apr 2010 14:02:49 -0400 Subject: EXT-7076 : Allow "paste as link" for any item Changed llassettype dictionary table to enable linking to most item types. --- indra/llcommon/llassettype.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 1c664e093b..2cd29448ae 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -77,23 +77,23 @@ LLAssetDictionary::LLAssetDictionary() { // DESCRIPTION TYPE NAME HUMAN NAME CAN LINK? CAN FETCH? CAN KNOW? // |--------------------|-----------|-------------------|-----------|-----------|---------| - addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", false, false, true)); - addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", false, true, true)); - addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", false, false, false)); - addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", false, true, true)); - addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", false, false, false)); + addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", true, false, true)); + addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", true, true, true)); + addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", true, false, false)); + addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", true, true, true)); + addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", true, false, false)); addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", true, true, true)); addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", true, false, false)); - addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", false, false, true)); + addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", true, false, true)); addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", true, false, false)); - addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", false, false, false)); - addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", false, false, false)); - addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", false, false, false)); + addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", true, false, false)); + addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", true, false, false)); + addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", true, false, false)); addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", true, true, true)); - addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", false, false, false)); - addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", false, false, false)); - addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", false, false, false)); - addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", false, true, true)); + addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", true, false, false)); + addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", true, false, false)); + addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", true, false, false)); + addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", true, true, true)); addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", true, true, true)); addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", false, false, false)); -- cgit v1.2.3 From c495e7f42a3e20f217949cb32e3e63043b978334 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 27 Apr 2010 14:03:42 -0400 Subject: EXT-7109 : Ensure "Open" works for all types, change to "Open Original" for links Added new "Open Original" menu item for links, to clarify that you're opening the item the link is pointing to. --- indra/newview/llinventorybridge.cpp | 35 ++++++++++++++++------ indra/newview/llinventorybridge.h | 2 +- .../skins/default/xui/en/menu_inventory.xml | 8 +++++ 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 04d62ff0bc..023e1a0461 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -678,7 +678,8 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { disabled_items.push_back(std::string("Share")); } - items.push_back(std::string("Open")); + + addOpenRightClickMenuOption(items); items.push_back(std::string("Properties")); getClipboardEntries(true, items, disabled_items, flags); @@ -734,6 +735,17 @@ void LLInvFVBridge::addDeleteContextMenuOptions(menuentry_vec_t &items, } } +void LLInvFVBridge::addOpenRightClickMenuOption(menuentry_vec_t &items) +{ + const LLInventoryObject *obj = getInventoryObject(); + const BOOL is_link = (obj && obj->getIsLinkType()); + + if (is_link) + items.push_back(std::string("Open Original")); + else + items.push_back(std::string("Open")); +} + // *TODO: remove this BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const { @@ -1100,7 +1112,7 @@ void LLItemBridge::performAction(LLInventoryModel* model, std::string action) gotoItem(); } - if ("open" == action) + if ("open" == action || "open_original" == action) { openItem(); return; @@ -3324,7 +3336,7 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) disabled_items.push_back(std::string("Share")); } - items.push_back(std::string("Open")); + addOpenRightClickMenuOption(items); items.push_back(std::string("Properties")); getClipboardEntries(true, items, disabled_items, flags); @@ -3690,7 +3702,7 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags) { disabled_items.push_back(std::string("Share")); } - items.push_back(std::string("Open")); + addOpenRightClickMenuOption(items); items.push_back(std::string("Properties")); getClipboardEntries(true, items, disabled_items, flags); @@ -3969,7 +3981,7 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if (!is_sidepanel) { - items.push_back(std::string("Open")); + addOpenRightClickMenuOption(items); items.push_back(std::string("Properties")); } @@ -4707,7 +4719,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags) if (can_open && !is_sidepanel) { - items.push_back(std::string("Open")); + addOpenRightClickMenuOption(items); } if (!is_sidepanel) @@ -5168,9 +5180,13 @@ const LLUUID &LLLinkFolderBridge::getFolderID() const // static void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type, - const LLUUID& uuid,LLInventoryModel* model) + const LLUUID& uuid, + LLInventoryModel* model) { - LLInvFVBridgeAction* action = createAction(asset_type,uuid,model); + // Perform indirection in case of link. + const LLUUID& linked_uuid = gInventory.getLinkedItemID(uuid); + + LLInvFVBridgeAction* action = createAction(asset_type,linked_uuid,model); if(action) { action->doIt(); @@ -5283,7 +5299,8 @@ protected: }; -class LLNotecardBridgeAction: public LLInvFVBridgeAction +class LLNotecardBridgeAction +: public LLInvFVBridgeAction { friend class LLInvFVBridgeAction; public: diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index f378d219f6..de63bdd76b 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -135,7 +135,7 @@ protected: menuentry_vec_t &disabled_items); virtual void addDeleteContextMenuOptions(menuentry_vec_t &items, menuentry_vec_t &disabled_items); - + virtual void addOpenRightClickMenuOption(menuentry_vec_t &items); protected: LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml index 5e1f6b58e8..11459ad0e6 100644 --- a/indra/newview/skins/default/xui/en/menu_inventory.xml +++ b/indra/newview/skins/default/xui/en/menu_inventory.xml @@ -409,6 +409,14 @@ function="Inventory.DoToSelected" parameter="open" /> + + + Date: Tue, 27 Apr 2010 22:35:54 +0300 Subject: Additional commit for EXT-6956 (Create perpetual loading indicator widget). - Made the indicator rotate clockwise (by flipping the images and reversing the order they're traversed). - The textures are now preloaded. Approved by Erica. --HG-- branch : product-engine --- indra/llui/llloadingindicator.cpp | 6 ++---- .../skins/default/textures/icons/Progress_1.png | Bin 464 -> 470 bytes .../skins/default/textures/icons/Progress_10.png | Bin 461 -> 461 bytes .../skins/default/textures/icons/Progress_11.png | Bin 471 -> 475 bytes .../skins/default/textures/icons/Progress_12.png | Bin 457 -> 455 bytes .../skins/default/textures/icons/Progress_2.png | Bin 461 -> 453 bytes .../skins/default/textures/icons/Progress_3.png | Bin 487 -> 454 bytes .../skins/default/textures/icons/Progress_4.png | Bin 466 -> 454 bytes .../skins/default/textures/icons/Progress_5.png | Bin 477 -> 468 bytes .../skins/default/textures/icons/Progress_6.png | Bin 460 -> 462 bytes .../skins/default/textures/icons/Progress_7.png | Bin 483 -> 469 bytes .../skins/default/textures/icons/Progress_8.png | Bin 467 -> 454 bytes .../skins/default/textures/icons/Progress_9.png | Bin 483 -> 469 bytes indra/newview/skins/default/textures/textures.xml | 24 ++++++++++----------- 14 files changed, 14 insertions(+), 16 deletions(-) diff --git a/indra/llui/llloadingindicator.cpp b/indra/llui/llloadingindicator.cpp index 8dec6ea9df..f8b029e19c 100644 --- a/indra/llui/llloadingindicator.cpp +++ b/indra/llui/llloadingindicator.cpp @@ -78,10 +78,8 @@ void LLLoadingIndicator::Data::initSingleton() LLPointer LLLoadingIndicator::Data::getNextImage(S8& idx) const { - // Actually selects previous image because - // current images seem to be in wrong order; - // performs array bounds checking. - idx = idx > 0 ? llmin(NIMAGES-1, idx-1) : NIMAGES-1; + // Calculate next index, performing array bounds checking. + idx = (idx >= NIMAGES || idx < 0) ? 0 : (idx + 1) % NIMAGES; return mImages[idx]; } diff --git a/indra/newview/skins/default/textures/icons/Progress_1.png b/indra/newview/skins/default/textures/icons/Progress_1.png index 58b56003c4..5d6efbfa2a 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_1.png and b/indra/newview/skins/default/textures/icons/Progress_1.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_10.png b/indra/newview/skins/default/textures/icons/Progress_10.png index 07fe0be8a3..28203324f1 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_10.png and b/indra/newview/skins/default/textures/icons/Progress_10.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_11.png b/indra/newview/skins/default/textures/icons/Progress_11.png index 215d68cc46..6b87be0c3f 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_11.png and b/indra/newview/skins/default/textures/icons/Progress_11.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_12.png b/indra/newview/skins/default/textures/icons/Progress_12.png index d755588621..089d58b090 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_12.png and b/indra/newview/skins/default/textures/icons/Progress_12.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_2.png b/indra/newview/skins/default/textures/icons/Progress_2.png index 6640ee227b..94cb73b1f7 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_2.png and b/indra/newview/skins/default/textures/icons/Progress_2.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_3.png b/indra/newview/skins/default/textures/icons/Progress_3.png index 5decbe977e..a04a5b5263 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_3.png and b/indra/newview/skins/default/textures/icons/Progress_3.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_4.png b/indra/newview/skins/default/textures/icons/Progress_4.png index 56e81c17aa..a467098d82 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_4.png and b/indra/newview/skins/default/textures/icons/Progress_4.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_5.png b/indra/newview/skins/default/textures/icons/Progress_5.png index a89bf2ac62..ea64f1d907 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_5.png and b/indra/newview/skins/default/textures/icons/Progress_5.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_6.png b/indra/newview/skins/default/textures/icons/Progress_6.png index 233c479540..fe4447935f 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_6.png and b/indra/newview/skins/default/textures/icons/Progress_6.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_7.png b/indra/newview/skins/default/textures/icons/Progress_7.png index 631d7a6819..64fa294771 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_7.png and b/indra/newview/skins/default/textures/icons/Progress_7.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_8.png b/indra/newview/skins/default/textures/icons/Progress_8.png index ac0e3f13f7..a1c9a7f2eb 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_8.png and b/indra/newview/skins/default/textures/icons/Progress_8.png differ diff --git a/indra/newview/skins/default/textures/icons/Progress_9.png b/indra/newview/skins/default/textures/icons/Progress_9.png index 17fb4a0335..f3e9723184 100644 Binary files a/indra/newview/skins/default/textures/icons/Progress_9.png and b/indra/newview/skins/default/textures/icons/Progress_9.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 1080ff347c..bbb82d86b1 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -580,17 +580,17 @@ with the same filename but different name - - - - - - - - - - - - + + + + + + + + + + + + -- cgit v1.2.3 From aa7b3312c201ccea29a0e07a38021bec764bfc64 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 27 Apr 2010 17:20:35 -0400 Subject: Small XML fix for Inventory Floater, which was obscuring the text showing the number of items fetched. --- indra/newview/skins/default/xui/en/panel_main_inventory.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index 27d66945d9..46625144e1 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -3,7 +3,7 @@ background_visible="true" default_tab_group="1" follows="all" - height="408" + height="423" label="Things" layout="topleft" min_height="350" @@ -48,7 +48,7 @@ left="10" max_length="300" name="inventory search editor" - top="3" + top="18" width="303" /> Date: Tue, 27 Apr 2010 18:39:09 -0400 Subject: DEV-49349 : AIS hides broken inventory links after a relog inventory_and_asset_types_match is always true for links (i.e. links should not have to be a certain inventory type). --- indra/llinventory/llinventorytype.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 4ef5df0b28..c050f20a9d 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -181,6 +181,10 @@ bool LLInventoryType::cannotRestrictPermissions(LLInventoryType::EType type) bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type, LLAssetType::EType asset_type) { + // Links can be of any inventory type. + if (LLAssetType::lookupIsLinkType(asset_type)) + return true; + const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(inventory_type); if (!entry) return false; -- cgit v1.2.3 From 872b4d7ed0bd532e349d3c177a63d48e17d0bdb3 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Wed, 28 Apr 2010 11:00:53 +0300 Subject: Fixed critical bug EXT-4837 ( [NUX] When filter results in null state, provide a message suggesting the user try global search.) Implemented passing of entered filter substring without head spaces to search URI in help message for null filtered results. * Updated setting "no item message" to use search term from filter editor for avatar & group lists and for inventory panels. * Updated appropriate translatable strings to get [SEARCH_TERM] substitution. * Updated processing of filter substring to pass original string to methods applied new filter. Additional necessary changes * Changed place to set "no item message" for group list from refresh to where filter is updated (like in avatar lists) * Removed converting of filter substring to upper case in Places & My Appearance sidepanels (this conversion has already been implemented in where filter is applied) * Added a separate message for Landmarks to set search URI to secondlife:///app/search/places for Lanmarks panel; other inventory related panels have URL to all searched categories (secondlife:///app/search/all) Reviewed by Vadim Savchuk at https://codereview.productengine.com/secondlife/r/326/ --HG-- branch : product-engine --- indra/llui/llflatlistview.cpp | 9 +++++++-- indra/llui/llflatlistview.h | 6 +++--- indra/newview/llavatarlist.cpp | 8 +++++--- indra/newview/llfolderview.cpp | 4 +++- indra/newview/llgrouplist.cpp | 13 ++++++++----- indra/newview/llinventoryfilter.cpp | 5 +++-- indra/newview/llinventoryfilter.h | 2 ++ indra/newview/llpanellandmarks.cpp | 1 + indra/newview/llpanelpeople.cpp | 20 ++++++++++++-------- indra/newview/llpanelpeople.h | 1 + indra/newview/llpanelplaces.cpp | 3 +-- indra/newview/llsidepanelappearance.cpp | 3 +-- indra/newview/skins/default/xui/en/panel_people.xml | 8 ++++---- indra/newview/skins/default/xui/en/strings.xml | 3 ++- 14 files changed, 53 insertions(+), 33 deletions(-) diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index e0b2244654..ec247b25c3 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -1147,12 +1147,17 @@ LLFlatListViewEx::LLFlatListViewEx(const Params& p) } -void LLFlatListViewEx::updateNoItemsMessage(bool items_filtered) +void LLFlatListViewEx::updateNoItemsMessage(const std::string& filter_string) { + bool items_filtered = !filter_string.empty(); if (items_filtered) { // items were filtered - setNoItemsCommentText(mNoFilteredItemsMsg); + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(filter_string); + std::string text = mNoFilteredItemsMsg; + LLStringUtil::format(text, args); + setNoItemsCommentText(text); } else { diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index f7d094f7e7..4f718ab0dc 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -470,10 +470,10 @@ protected: /** * Applies a message for empty list depend on passed argument. * - * @param items_filtered - if true message for filtered items will be set, otherwise for - * completely empty list. + * @param filter_string - if is not empty, message for filtered items will be set, otherwise for + * completely empty list. Value of filter string will be passed as search_term in SLURL. */ - void updateNoItemsMessage(bool items_filtered); + void updateNoItemsMessage(const std::string& filter_string); private: std::string mNoFilteredItemsMsg; diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp index 8ba47b5198..e32daf55ca 100644 --- a/indra/newview/llavatarlist.cpp +++ b/indra/newview/llavatarlist.cpp @@ -176,13 +176,15 @@ void LLAvatarList::clear() void LLAvatarList::setNameFilter(const std::string& filter) { - if (mNameFilter != filter) + std::string filter_upper = filter; + LLStringUtil::toUpper(filter_upper); + if (mNameFilter != filter_upper) { - mNameFilter = filter; + mNameFilter = filter_upper; // update message for empty state here instead of refresh() to avoid blinking when switch // between tabs. - updateNoItemsMessage(!mNameFilter.empty()); + updateNoItemsMessage(filter); setDirty(); } } diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index c492bfcef1..eba4cdfa31 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -946,7 +946,9 @@ void LLFolderView::draw() } else { - mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage()); + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(getFilter()->getFilterSubStringOrig()); + mStatusText = LLTrans::getString(getFilter()->getEmptyLookupMessage(), args); //font->renderUTF8(mStatusText, 0, 2, 1, sSearchStatusColor, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE ); } mStatusTextBox->setValue(mStatusText); diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index f21b6e1085..252c34cf9c 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -131,9 +131,15 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask) void LLGroupList::setNameFilter(const std::string& filter) { - if (mNameFilter != filter) + std::string filter_upper = filter; + LLStringUtil::toUpper(filter_upper); + if (mNameFilter != filter_upper) { - mNameFilter = filter; + mNameFilter = filter_upper; + + // set no items message depend on filter state + updateNoItemsMessage(filter); + setDirty(); } } @@ -151,9 +157,6 @@ void LLGroupList::refresh() LLUUID id; bool have_filter = !mNameFilter.empty(); - // set no items message depend on filter state & total count of groups - updateNoItemsMessage(have_filter); - clear(); for(S32 i = 0; i < count; ++i) diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index 1a488175ac..901a570487 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -329,9 +329,10 @@ void LLInventoryFilter::setFilterSubString(const std::string& string) // appending new characters const BOOL more_restrictive = mFilterSubString.size() < string.size() && !string.substr(0, mFilterSubString.size()).compare(mFilterSubString); - mFilterSubString = string; + mFilterSubStringOrig = string; + LLStringUtil::trimHead(mFilterSubStringOrig); + mFilterSubString = mFilterSubStringOrig; LLStringUtil::toUpper(mFilterSubString); - LLStringUtil::trimHead(mFilterSubString); if (less_restrictive) { setModified(FILTER_LESS_RESTRICTIVE); diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index b01554edc8..2376ba5d22 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -84,6 +84,7 @@ public: void setFilterSubString(const std::string& string); const std::string& getFilterSubString(BOOL trim = FALSE) const; + const std::string& getFilterSubStringOrig() const { return mFilterSubStringOrig; } BOOL hasFilterString() const; void setFilterPermissions(PermissionMask perms); @@ -181,6 +182,7 @@ private: std::string::size_type mSubStringMatchOffset; std::string mFilterSubString; + std::string mFilterSubStringOrig; const std::string mName; S32 mFilterGeneration; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 67d40a39b1..0a978d1b26 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -583,6 +583,7 @@ void LLLandmarksPanel::initLandmarksPanel(LLPlacesInventoryPanel* inventory_list if (!inventory_list->getFilter()) return; + inventory_list->getFilter()->setEmptyLookupMessage("PlacesNoMatchingItems"); inventory_list->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK); inventory_list->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, inventory_list, _1, _2)); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index f60951ca66..f2c0f92f9b 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -443,6 +443,7 @@ public: LLPanelPeople::LLPanelPeople() : LLPanel(), mFilterSubString(LLStringUtil::null), + mFilterSubStringOrig(LLStringUtil::null), mFilterEditor(NULL), mTabContainer(NULL), mOnlineFriendList(NULL), @@ -658,7 +659,9 @@ void LLPanelPeople::updateFriendListHelpText() { //update help text for empty lists std::string message_name = mFilterSubString.empty() ? "no_friends_msg" : "no_filtered_friends_msg"; - no_friends_text->setText(getString(message_name)); + LLStringUtil::format_map_t args; + args["[SEARCH_TERM]"] = LLURI::escape(mFilterSubStringOrig); + no_friends_text->setText(getString(message_name, args)); } } @@ -981,10 +984,11 @@ bool LLPanelPeople::isRealGroup() void LLPanelPeople::onFilterEdit(const std::string& search_string) { - std::string search_upper = search_string; + mFilterSubStringOrig = search_string; + LLStringUtil::trimHead(mFilterSubStringOrig); // Searches are case-insensitive + std::string search_upper = mFilterSubStringOrig; LLStringUtil::toUpper(search_upper); - LLStringUtil::trimHead(search_upper); if (mFilterSubString == search_upper) return; @@ -999,11 +1003,11 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string) // Apply new filter. - mNearbyList->setNameFilter(mFilterSubString); - mOnlineFriendList->setNameFilter(mFilterSubString); - mAllFriendList->setNameFilter(mFilterSubString); - mRecentList->setNameFilter(mFilterSubString); - mGroupList->setNameFilter(mFilterSubString); + mNearbyList->setNameFilter(mFilterSubStringOrig); + mOnlineFriendList->setNameFilter(mFilterSubStringOrig); + mAllFriendList->setNameFilter(mFilterSubStringOrig); + mRecentList->setNameFilter(mFilterSubStringOrig); + mGroupList->setNameFilter(mFilterSubStringOrig); setAccordionCollapsedByUser("tab_online", false); setAccordionCollapsedByUser("tab_all", false); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 1bd3ea471c..17c45a034b 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -169,6 +169,7 @@ private: Updater* mRecentListUpdater; std::string mFilterSubString; + std::string mFilterSubStringOrig; }; #endif //LL_LLPANELPEOPLE_H diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 89293d0e50..51a11e97e4 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -528,8 +528,7 @@ void LLPanelPlaces::onFilterEdit(const std::string& search_string, bool force_fi std::string string = search_string; // Searches are case-insensitive - LLStringUtil::toUpper(string); - LLStringUtil::trimHead(string); + // but we don't convert the typed string to upper-case so that it can be fed to the web search as-is. mActivePanel->onSearchEdit(string); } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 87494daaa9..f38df19de0 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -197,8 +197,7 @@ void LLSidepanelAppearance::onFilterEdit(const std::string& search_string) mFilterSubString = search_string; // Searches are case-insensitive - LLStringUtil::toUpper(mFilterSubString); - LLStringUtil::trimHead(mFilterSubString); + // but we don't convert the typed string to upper-case so that it can be fed to the web search as-is. mPanelOutfitsInventory->onSearchEdit(mFilterSubString); } diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml index fa4213667b..066ea3be6e 100644 --- a/indra/newview/skins/default/xui/en/panel_people.xml +++ b/indra/newview/skins/default/xui/en/panel_people.xml @@ -16,13 +16,13 @@ value="No recent people. Looking for people to hang out with? Try [secondlife:///app/search/people Search] or the [secondlife:///app/worldmap World Map]." /> + value="Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search]." /> + value="Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search]." /> @@ -36,7 +36,7 @@ Looking for people to hang out with? Try the [secondlife:///app/worldmap World M - Didn't find what you're looking for? Try [secondlife:///app/search/people Search]. + Didn't find what you're looking for? Try [secondlife:///app/search/people/[SEARCH_TERM] Search]. + value="Didn't find what you're looking for? Try [secondlife:///app/search/groups/[SEARCH_TERM] Search]." /> diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index bf30e89a59..b0e43e72ed 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -1842,7 +1842,8 @@ Clears (deletes) the media and all params from the given face. Press ESC to return to World View - Didn't find what you're looking for? Try [secondlife:///app/search/all Search]. + Didn't find what you're looking for? Try [secondlife:///app/search/all/[SEARCH_TERM] Search]. + Didn't find what you're looking for? Try [secondlife:///app/search/places/[SEARCH_TERM] Search]. Drag a landmark here to add it to your favorites. You do not have a copy of this texture in your inventory -- cgit v1.2.3 From 9e8f820e35d9d9ea9318f51ac1f46b11f61a68f7 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Wed, 28 Apr 2010 11:26:03 +0300 Subject: Improved xml file according to Eric's suggestion: controls are not intended to be translated marked with translate="false" attribute. Trivial, not reviewed. --HG-- branch : product-engine --- indra/newview/skins/default/xui/en/outfit_accordion_tab.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml index b3150bb98b..5fcc9b012b 100644 --- a/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml +++ b/indra/newview/skins/default/xui/en/outfit_accordion_tab.xml @@ -1,6 +1,7 @@ + -- cgit v1.2.3 From e8540593e6bfd17f86b76dcfcac9442cea9a8cb6 Mon Sep 17 00:00:00 2001 From: Andrew Dyukov Date: Wed, 28 Apr 2010 14:48:16 +0300 Subject: Fixed low bug EXT-6776 ([FRAGMENTATION] Call strings need change). - Removed string fragmentation by changing concatenation of name and action to whole-sentence strings. Reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/328 --HG-- branch : product-engine --- indra/newview/llimview.cpp | 33 +++++++++++++------------- indra/newview/skins/default/xui/en/strings.xml | 5 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index f03026715d..15dbc03f70 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -257,9 +257,8 @@ LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state, const LLVoiceChannel::EDirection& direction) { - std::string you = LLTrans::getString("You"); - std::string started_call = LLTrans::getString("started_call"); - std::string joined_call = LLTrans::getString("joined_call"); + std::string you_joined_call = LLTrans::getString("you_joined_call"); + std::string you_started_call = LLTrans::getString("you_started_call"); std::string other_avatar_name = ""; std::string message; @@ -277,13 +276,15 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES switch(new_state) { case LLVoiceChannel::STATE_CALL_STARTED : - message = other_avatar_name + " " + started_call; - LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); - - break; + { + LLStringUtil::format_map_t string_args; + string_args["[NAME]"] = other_avatar_name; + message = LLTrans::getString("name_started_call", string_args); + LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); + break; + } case LLVoiceChannel::STATE_CONNECTED : - message = you + " " + joined_call; - LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); + LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_joined_call); default: break; } @@ -293,8 +294,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES switch(new_state) { case LLVoiceChannel::STATE_CALL_STARTED : - message = you + " " + started_call; - LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); + LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_started_call); break; case LLVoiceChannel::STATE_CONNECTED : message = LLTrans::getString("answered_call"); @@ -312,8 +312,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES switch(new_state) { case LLVoiceChannel::STATE_CONNECTED : - message = you + " " + joined_call; - LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); + LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_joined_call); default: break; } @@ -323,8 +322,7 @@ void LLIMModel::LLIMSession::onVoiceChannelStateChanged(const LLVoiceChannel::ES switch(new_state) { case LLVoiceChannel::STATE_CALL_STARTED : - message = you + " " + started_call; - LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, message); + LLIMModel::getInstance()->addMessage(mSessionID, SYSTEM_FROM, LLUUID::null, you_started_call); break; default: break; @@ -2069,8 +2067,9 @@ void LLIncomingCallDialog::processCallResponse(S32 response) // send notification message to the corresponding chat if (mPayload["notify_box_type"].asString() == "VoiceInviteGroup" || mPayload["notify_box_type"].asString() == "VoiceInviteAdHoc") { - std::string started_call = LLTrans::getString("started_call"); - std::string message = mPayload["caller_name"].asString() + " " + started_call; + LLStringUtil::format_map_t string_args; + string_args["[NAME]"] = mPayload["caller_name"].asString(); + std::string message = LLTrans::getString("name_started_call", string_args); LLIMModel::getInstance()->addMessageSilently(session_id, SYSTEM_FROM, LLUUID::null, message); } } diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index b0e43e72ed..3cba76cbfa 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -2951,8 +2951,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Your call has been answered - Started a voice call - Joined the voice call + You started a voice call + You joined the voice call + [NAME] started a voice call Joining voice call... -- cgit v1.2.3 From 6d3c960525afda3bcdb7ef3e58b67ae1bd4a4dd3 Mon Sep 17 00:00:00 2001 From: Eugene Mutavchi Date: Wed, 28 Apr 2010 14:50:33 +0300 Subject: Implemented major task EXT-6979 (Connect wearable editor texture and color editors to the textures stored in the wearables themselves): - added PickerControlEntry - dictionary entry which contains information about particular picker control - added ColorSwatchCtrls and TextureCtrls - lists of PickerControlEntries, contain information about color and texture controls for particular EWearableType - implemented some helper functions for picker management Reviewed by Neal Orman at https://codereview.productengine.com/secondlife/r/327/ --HG-- branch : product-engine --- indra/newview/llpaneleditwearable.cpp | 461 ++++++++++++++++++++- indra/newview/llpaneleditwearable.h | 5 +- .../skins/default/xui/en/panel_edit_alpha.xml | 25 +- .../skins/default/xui/en/panel_edit_eyes.xml | 7 +- .../skins/default/xui/en/panel_edit_gloves.xml | 14 +- .../skins/default/xui/en/panel_edit_hair.xml | 7 +- .../skins/default/xui/en/panel_edit_jacket.xml | 15 +- .../skins/default/xui/en/panel_edit_pants.xml | 10 +- .../skins/default/xui/en/panel_edit_shirt.xml | 10 +- .../skins/default/xui/en/panel_edit_shoes.xml | 10 +- .../skins/default/xui/en/panel_edit_skin.xml | 17 +- .../skins/default/xui/en/panel_edit_skirt.xml | 10 +- .../skins/default/xui/en/panel_edit_socks.xml | 10 +- .../skins/default/xui/en/panel_edit_underpants.xml | 10 +- .../skins/default/xui/en/panel_edit_undershirt.xml | 10 +- 15 files changed, 569 insertions(+), 52 deletions(-) diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index da74295f9e..d40e0f2d97 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -51,6 +51,12 @@ #include "llagentwearables.h" #include "llscrollingpanelparam.h" +#include "llcolorswatch.h" +#include "lltexturectrl.h" +#include "lltextureentry.h" +#include "llviewercontrol.h" // gSavedSettings +#include "llviewertexturelist.h" + // register panel with appropriate XML static LLRegisterPanelClassWrapper t_edit_wearable("panel_edit_wearable"); @@ -88,6 +94,8 @@ enum ESubpart { SUBPART_TATTOO }; +using namespace LLVOAvatarDefines; + typedef std::vector subpart_vec_t; // Locally defined classes @@ -110,14 +118,17 @@ public: WearableEntry(EWearableType type, const std::string &title, const std::string &desc_title, - U8 num_subparts, ... ); // number of subparts followed by a list of ESubparts + U8 num_color_swatches, // number of 'color_swatches' + U8 num_texture_pickers, // number of 'texture_pickers' + U8 num_subparts, ... ); // number of subparts followed by a list of ETextureIndex and ESubparts const EWearableType mWearableType; const std::string mTitle; const std::string mDescTitle; subpart_vec_t mSubparts; - + texture_vec_t mColorSwatchCtrls; + texture_vec_t mTextureCtrls; }; struct Wearables : public LLDictionary @@ -158,6 +169,35 @@ public: } mSubparts; const SubpartEntry* getSubpart(ESubpart subpart) const { return mSubparts.lookup(subpart); } + + //-------------------------------------------------------------------- + // Picker Control Entries + //-------------------------------------------------------------------- +public: + struct PickerControlEntry : public LLDictionaryEntry + { + PickerControlEntry(ETextureIndex tex_index, + const std::string name, + const LLUUID default_image_id = LLUUID::null, + const bool allow_no_texture = false); + ETextureIndex mTextureIndex; + const std::string mControlName; + const LLUUID mDefaultImageId; + const bool mAllowNoTexture; + }; + + struct ColorSwatchCtrls : public LLDictionary + { + ColorSwatchCtrls(); + } mColorSwatchCtrls; + + struct TextureCtrls : public LLDictionary + { + TextureCtrls(); + } mTextureCtrls; + + const PickerControlEntry* getTexturePicker(ETextureIndex index) const { return mTextureCtrls.lookup(index); } + const PickerControlEntry* getColorSwatch(ETextureIndex index) const { return mColorSwatchCtrls.lookup(index); } }; LLEditWearableDictionary::LLEditWearableDictionary() @@ -172,26 +212,28 @@ LLEditWearableDictionary::~LLEditWearableDictionary() LLEditWearableDictionary::Wearables::Wearables() { - addEntry(WT_SHAPE, new WearableEntry(WT_SHAPE,"edit_shape_title","shape_desc_text",9, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS, SUBPART_SHAPE_WHOLE)); - addEntry(WT_SKIN, new WearableEntry(WT_SKIN,"edit_skin_title","skin_desc_text",4, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL)); - addEntry(WT_HAIR, new WearableEntry(WT_HAIR,"edit_hair_title","hair_desc_text",4, SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL)); - addEntry(WT_EYES, new WearableEntry(WT_EYES,"edit_eyes_title","eyes_desc_text",1, SUBPART_EYES)); - addEntry(WT_SHIRT, new WearableEntry(WT_SHIRT,"edit_shirt_title","shirt_desc_text",1, SUBPART_SHIRT)); - addEntry(WT_PANTS, new WearableEntry(WT_PANTS,"edit_pants_title","pants_desc_text",1, SUBPART_PANTS)); - addEntry(WT_SHOES, new WearableEntry(WT_SHOES,"edit_shoes_title","shoes_desc_text",1, SUBPART_SHOES)); - addEntry(WT_SOCKS, new WearableEntry(WT_SOCKS,"edit_socks_title","socks_desc_text",1, SUBPART_SOCKS)); - addEntry(WT_JACKET, new WearableEntry(WT_JACKET,"edit_jacket_title","jacket_desc_text",1, SUBPART_JACKET)); - addEntry(WT_GLOVES, new WearableEntry(WT_GLOVES,"edit_gloves_title","gloves_desc_text",1, SUBPART_GLOVES)); - addEntry(WT_UNDERSHIRT, new WearableEntry(WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text",1, SUBPART_UNDERSHIRT)); - addEntry(WT_UNDERPANTS, new WearableEntry(WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text",1, SUBPART_UNDERPANTS)); - addEntry(WT_SKIRT, new WearableEntry(WT_SKIRT,"edit_skirt_title","skirt_desc_text",1, SUBPART_SKIRT)); - addEntry(WT_ALPHA, new WearableEntry(WT_ALPHA,"edit_alpha_title","alpha_desc_text",1, SUBPART_ALPHA)); - addEntry(WT_TATTOO, new WearableEntry(WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",1, SUBPART_TATTOO)); + addEntry(WT_SHAPE, new WearableEntry(WT_SHAPE,"edit_shape_title","shape_desc_text",0,0,9, SUBPART_SHAPE_HEAD, SUBPART_SHAPE_EYES, SUBPART_SHAPE_EARS, SUBPART_SHAPE_NOSE, SUBPART_SHAPE_MOUTH, SUBPART_SHAPE_CHIN, SUBPART_SHAPE_TORSO, SUBPART_SHAPE_LEGS, SUBPART_SHAPE_WHOLE)); + addEntry(WT_SKIN, new WearableEntry(WT_SKIN,"edit_skin_title","skin_desc_text",0,3,4, TEX_HEAD_BODYPAINT, TEX_UPPER_BODYPAINT, TEX_LOWER_BODYPAINT, SUBPART_SKIN_COLOR, SUBPART_SKIN_FACEDETAIL, SUBPART_SKIN_MAKEUP, SUBPART_SKIN_BODYDETAIL)); + addEntry(WT_HAIR, new WearableEntry(WT_HAIR,"edit_hair_title","hair_desc_text",0,1,4, TEX_HAIR, SUBPART_HAIR_COLOR, SUBPART_HAIR_STYLE, SUBPART_HAIR_EYEBROWS, SUBPART_HAIR_FACIAL)); + addEntry(WT_EYES, new WearableEntry(WT_EYES,"edit_eyes_title","eyes_desc_text",0,1,1, TEX_EYES_IRIS, SUBPART_EYES)); + addEntry(WT_SHIRT, new WearableEntry(WT_SHIRT,"edit_shirt_title","shirt_desc_text",1,1,1, TEX_UPPER_SHIRT, TEX_UPPER_SHIRT, SUBPART_SHIRT)); + addEntry(WT_PANTS, new WearableEntry(WT_PANTS,"edit_pants_title","pants_desc_text",1,1,1, TEX_LOWER_PANTS, TEX_LOWER_PANTS, SUBPART_PANTS)); + addEntry(WT_SHOES, new WearableEntry(WT_SHOES,"edit_shoes_title","shoes_desc_text",1,1,1, TEX_LOWER_SHOES, TEX_LOWER_SHOES, SUBPART_SHOES)); + addEntry(WT_SOCKS, new WearableEntry(WT_SOCKS,"edit_socks_title","socks_desc_text",1,1,1, TEX_LOWER_SOCKS, TEX_LOWER_SOCKS, SUBPART_SOCKS)); + addEntry(WT_JACKET, new WearableEntry(WT_JACKET,"edit_jacket_title","jacket_desc_text",1,2,1, TEX_UPPER_JACKET, TEX_UPPER_JACKET, TEX_LOWER_JACKET, SUBPART_JACKET)); + addEntry(WT_GLOVES, new WearableEntry(WT_GLOVES,"edit_gloves_title","gloves_desc_text",1,1,1, TEX_UPPER_GLOVES, TEX_UPPER_GLOVES, SUBPART_GLOVES)); + addEntry(WT_UNDERSHIRT, new WearableEntry(WT_UNDERSHIRT,"edit_undershirt_title","undershirt_desc_text",1,1,1, TEX_UPPER_UNDERSHIRT, TEX_UPPER_UNDERSHIRT, SUBPART_UNDERSHIRT)); + addEntry(WT_UNDERPANTS, new WearableEntry(WT_UNDERPANTS,"edit_underpants_title","underpants_desc_text",1,1,1, TEX_LOWER_UNDERPANTS, TEX_LOWER_UNDERPANTS, SUBPART_UNDERPANTS)); + addEntry(WT_SKIRT, new WearableEntry(WT_SKIRT,"edit_skirt_title","skirt_desc_text",1,1,1, TEX_SKIRT, TEX_SKIRT, SUBPART_SKIRT)); + addEntry(WT_ALPHA, new WearableEntry(WT_ALPHA,"edit_alpha_title","alpha_desc_text",0,5,1, TEX_LOWER_ALPHA, TEX_UPPER_ALPHA, TEX_HEAD_ALPHA, TEX_EYES_ALPHA, TEX_HAIR_ALPHA, SUBPART_ALPHA)); + addEntry(WT_TATTOO, new WearableEntry(WT_TATTOO,"edit_tattoo_title","tattoo_desc_text",0,3,1, TEX_LOWER_TATTOO, TEX_UPPER_TATTOO, TEX_HEAD_TATTOO, SUBPART_TATTOO)); } LLEditWearableDictionary::WearableEntry::WearableEntry(EWearableType type, const std::string &title, const std::string &desc_title, + U8 num_color_swatches, + U8 num_texture_pickers, U8 num_subparts, ... ) : LLDictionaryEntry(title), mWearableType(type), @@ -201,6 +243,18 @@ LLEditWearableDictionary::WearableEntry::WearableEntry(EWearableType type, va_list argp; va_start(argp, num_subparts); + for (U8 i = 0; i < num_color_swatches; ++i) + { + ETextureIndex index = (ETextureIndex)va_arg(argp,int); + mColorSwatchCtrls.push_back(index); + } + + for (U8 i = 0; i < num_texture_pickers; ++i) + { + ETextureIndex index = (ETextureIndex)va_arg(argp,int); + mTextureCtrls.push_back(index); + } + for (U8 i = 0; i < num_subparts; ++i) { ESubpart part = (ESubpart)va_arg(argp,int); @@ -265,6 +319,269 @@ LLEditWearableDictionary::SubpartEntry::SubpartEntry(ESubpart part, { } +LLEditWearableDictionary::ColorSwatchCtrls::ColorSwatchCtrls() +{ + addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Color/Tint" )); + addEntry ( TEX_LOWER_PANTS, new PickerControlEntry (TEX_LOWER_PANTS, "Color/Tint" )); + addEntry ( TEX_LOWER_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "Color/Tint" )); + addEntry ( TEX_LOWER_SOCKS, new PickerControlEntry (TEX_LOWER_SOCKS, "Color/Tint" )); + addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Color/Tint" )); + addEntry ( TEX_SKIRT, new PickerControlEntry (TEX_SKIRT, "Color/Tint" )); + addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Color/Tint" )); + addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Color/Tint" )); + addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Color/Tint" )); +} + +LLEditWearableDictionary::TextureCtrls::TextureCtrls() +{ + addEntry ( TEX_HEAD_BODYPAINT, new PickerControlEntry (TEX_HEAD_BODYPAINT, "Head Tattoos", LLUUID::null, TRUE )); + addEntry ( TEX_UPPER_BODYPAINT, new PickerControlEntry (TEX_UPPER_BODYPAINT, "Upper Tattoos", LLUUID::null, TRUE )); + addEntry ( TEX_LOWER_BODYPAINT, new PickerControlEntry (TEX_LOWER_BODYPAINT, "Lower Tattoos", LLUUID::null, TRUE )); + addEntry ( TEX_HAIR, new PickerControlEntry (TEX_HAIR, "Texture", LLUUID( gSavedSettings.getString( "UIImgDefaultHairUUID" ) ), FALSE )); + addEntry ( TEX_EYES_IRIS, new PickerControlEntry (TEX_EYES_IRIS, "Iris", LLUUID( gSavedSettings.getString( "UIImgDefaultEyesUUID" ) ), FALSE )); + addEntry ( TEX_UPPER_SHIRT, new PickerControlEntry (TEX_UPPER_SHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShirtUUID" ) ), FALSE )); + addEntry ( TEX_LOWER_PANTS, new PickerControlEntry (TEX_LOWER_PANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultPantsUUID" ) ), FALSE )); + addEntry ( TEX_LOWER_SHOES, new PickerControlEntry (TEX_LOWER_SHOES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultShoesUUID" ) ), FALSE )); + addEntry ( TEX_LOWER_SOCKS, new PickerControlEntry (TEX_LOWER_SOCKS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSocksUUID" ) ), FALSE )); + addEntry ( TEX_UPPER_JACKET, new PickerControlEntry (TEX_UPPER_JACKET, "Upper Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE )); + addEntry ( TEX_LOWER_JACKET, new PickerControlEntry (TEX_LOWER_JACKET, "Lower Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultJacketUUID" ) ), FALSE )); + addEntry ( TEX_SKIRT, new PickerControlEntry (TEX_SKIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultSkirtUUID" ) ), FALSE )); + addEntry ( TEX_UPPER_GLOVES, new PickerControlEntry (TEX_UPPER_GLOVES, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultGlovesUUID" ) ), FALSE )); + addEntry ( TEX_UPPER_UNDERSHIRT, new PickerControlEntry (TEX_UPPER_UNDERSHIRT, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE )); + addEntry ( TEX_LOWER_UNDERPANTS, new PickerControlEntry (TEX_LOWER_UNDERPANTS, "Fabric", LLUUID( gSavedSettings.getString( "UIImgDefaultUnderwearUUID" ) ), FALSE )); + addEntry ( TEX_LOWER_ALPHA, new PickerControlEntry (TEX_LOWER_ALPHA, "Lower Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); + addEntry ( TEX_UPPER_ALPHA, new PickerControlEntry (TEX_UPPER_ALPHA, "Upper Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); + addEntry ( TEX_HEAD_ALPHA, new PickerControlEntry (TEX_HEAD_ALPHA, "Head Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); + addEntry ( TEX_EYES_ALPHA, new PickerControlEntry (TEX_EYES_ALPHA, "Eye Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); + addEntry ( TEX_HAIR_ALPHA, new PickerControlEntry (TEX_HAIR_ALPHA, "Hair Alpha", LLUUID( gSavedSettings.getString( "UIImgDefaultAlphaUUID" ) ), TRUE )); + addEntry ( TEX_LOWER_TATTOO, new PickerControlEntry (TEX_LOWER_TATTOO, "Lower Tattoo", LLUUID::null, TRUE )); + addEntry ( TEX_UPPER_TATTOO, new PickerControlEntry (TEX_UPPER_TATTOO, "Upper Tattoo", LLUUID::null, TRUE )); + addEntry ( TEX_HEAD_TATTOO, new PickerControlEntry (TEX_HEAD_TATTOO, "Head Tattoo", LLUUID::null, TRUE )); +} + +LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex tex_index, + const std::string name, + const LLUUID default_image_id, + const bool allow_no_texture) : + LLDictionaryEntry(name), + mTextureIndex(tex_index), + mControlName(name), + mDefaultImageId(default_image_id), + mAllowNoTexture(allow_no_texture) +{ +} + +// Helper functions. + +// Specializations of this template function return a vector of texture indexes of particular control type +// (i.e. LLColorSwatchCtrl or LLTextureCtrl) which are contained in given WearableEntry. +template +const texture_vec_t& +get_pickers_indexes(const LLEditWearableDictionary::WearableEntry *wearable_entry); + +// Specializations of this template function return picker control entry for particular control type. +template +const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* +get_picker_entry (const ETextureIndex index); + +typedef boost::function function_t; + +typedef struct PickerControlEntryNamePredicate +{ + PickerControlEntryNamePredicate(const std::string name) : mName (name) {}; + bool operator()(const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) const + { + return (entry && entry->mName == mName); + } +private: + const std::string mName; +} PickerControlEntryNamePredicate; + +static const texture_vec_t null_texture_vec; + +// A full specialization of get_pickers_indexes for LLColorSwatchCtrl +template <> +const texture_vec_t& +get_pickers_indexes (const LLEditWearableDictionary::WearableEntry *wearable_entry) +{ + if (!wearable_entry) + { + llwarns << "could not get LLColorSwatchCtrl indexes for null wearable entry." << llendl; + return null_texture_vec; + } + return wearable_entry->mColorSwatchCtrls; +} + +// A full specialization of get_pickers_indexes for LLTextureCtrl +template <> +const texture_vec_t& +get_pickers_indexes (const LLEditWearableDictionary::WearableEntry *wearable_entry) +{ + if (!wearable_entry) + { + llwarns << "could not get LLTextureCtrl indexes for null wearable entry." << llendl; + return null_texture_vec; + } + return wearable_entry->mTextureCtrls; +} + +// A full specialization of get_picker_entry for LLColorSwatchCtrl +template <> +const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* +get_picker_entry (const ETextureIndex index) +{ + return LLEditWearableDictionary::getInstance()->getColorSwatch(index); +} + +// A full specialization of get_picker_entry for LLTextureCtrl +template <> +const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* +get_picker_entry (const ETextureIndex index) +{ + return LLEditWearableDictionary::getInstance()->getTexturePicker(index); +} + +template +const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* +find_picker_ctrl_entry_if(EWearableType type, const Predicate pred) +{ + const LLEditWearableDictionary::WearableEntry *wearable_entry + = LLEditWearableDictionary::getInstance()->getWearable(type); + if (!wearable_entry) + { + llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl; + return NULL; + } + const texture_vec_t& indexes = get_pickers_indexes(wearable_entry); + for (texture_vec_t::const_iterator + iter = indexes.begin(), + iter_end = indexes.end(); + iter != iter_end; ++iter) + { + const ETextureIndex te = *iter; + const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry + = get_picker_entry(te); + if (!entry) + { + llwarns << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << llendl; + continue; + } + if (pred(entry)) + { + return entry; + } + } + return NULL; +} + +template +void +for_each_picker_ctrl_entry(LLPanel* panel, EWearableType type, function_t fun) +{ + if (!panel) + { + llwarns << "the panel wasn't passed for wearable of type: " << type << llendl; + return; + } + const LLEditWearableDictionary::WearableEntry *wearable_entry + = LLEditWearableDictionary::getInstance()->getWearable(type); + if (!wearable_entry) + { + llwarns << "could not get wearable dictionary entry for wearable of type: " << type << llendl; + return; + } + const texture_vec_t& indexes = get_pickers_indexes(wearable_entry); + for (texture_vec_t::const_iterator + iter = indexes.begin(), + iter_end = indexes.end(); + iter != iter_end; ++iter) + { + const ETextureIndex te = *iter; + const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry + = get_picker_entry(te); + if (!entry) + { + llwarns << "could not get picker dictionary entry (" << te << ") for wearable of type: " << type << llendl; + continue; + } + fun (panel, entry); + } +} + +// The helper functions for pickers management +static void init_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +{ + LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild(entry->mControlName); + if (color_swatch_ctrl) + { + color_swatch_ctrl->setOriginal(self->getWearable()->getClothesColor(entry->mTextureIndex)); + } +} + +static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +{ + LLTextureCtrl* texture_ctrl = panel->getChild(entry->mControlName); + if (texture_ctrl) + { + texture_ctrl->setDefaultImageAssetID(entry->mDefaultImageId); + texture_ctrl->setAllowNoTexture(entry->mAllowNoTexture); + // Don't allow (no copy) or (notransfer) textures to be selected. + texture_ctrl->setImmediateFilterPermMask(PERM_NONE); + texture_ctrl->setNonImmediateFilterPermMask(PERM_NONE); + } +} + +static void update_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +{ + LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild(entry->mControlName); + if (color_swatch_ctrl) + { + color_swatch_ctrl->set(self->getWearable()->getClothesColor(entry->mTextureIndex)); + } +} + +static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +{ + LLTextureCtrl* texture_ctrl = panel->getChild(entry->mControlName); + if (texture_ctrl) + { + LLUUID new_id; + LLLocalTextureObject *lto = self->getWearable()->getLocalTextureObject(entry->mTextureIndex); + if( lto && (lto->getID() != IMG_DEFAULT_AVATAR) ) + { + new_id = lto->getID(); + } + else + { + new_id = LLUUID::null; + } + LLUUID old_id = texture_ctrl->getImageAssetID(); + if (old_id != new_id) + { + // texture has changed, close the floater to avoid DEV-22461 + texture_ctrl->closeDependentFloater(); + } + texture_ctrl->setImageAssetID(new_id); + } +} + +static void set_enabled_color_swatch_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +{ + LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild(entry->mControlName); + if (color_swatch_ctrl) + { + color_swatch_ctrl->setEnabled(enabled); + } +} + +static void set_enabled_texture_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +{ + LLTextureCtrl* texture_ctrl = panel->getChild(entry->mControlName); + if (texture_ctrl) + { + texture_ctrl->setEnabled(enabled); + } +} // LLPanelEditWearable @@ -273,6 +590,8 @@ LLPanelEditWearable::LLPanelEditWearable() , mWearablePtr(NULL) , mWearableItem(NULL) { + mCommitCallbackRegistrar.add("ColorSwatch.Commit", boost::bind(&LLPanelEditWearable::onColorSwatchCommit, this, _1)); + mCommitCallbackRegistrar.add("TexturePicker.Commit", boost::bind(&LLPanelEditWearable::onTexturePickerCommit, this, _1)); } //virtual @@ -341,6 +660,10 @@ BOOL LLPanelEditWearable::isDirty() const void LLPanelEditWearable::draw() { updateVerbs(); + if (getWearable()) + { + updatePanelPickerControls(getWearable()->getType()); + } LLPanel::draw(); } @@ -361,6 +684,102 @@ void LLPanelEditWearable::onRevertButtonClicked(void* userdata) panel->revertChanges(); } +void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl) +{ + const LLTextureCtrl* texture_ctrl = dynamic_cast(ctrl); + if (!texture_ctrl) + { + llwarns << "got commit signal from not LLTextureCtrl." << llendl; + return; + } + + if (getWearable()) + { + EWearableType type = getWearable()->getType(); + const PickerControlEntryNamePredicate name_pred(texture_ctrl->getName()); + const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry + = find_picker_ctrl_entry_if(type, name_pred); + if (entry) + { + // Set the new version + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(texture_ctrl->getImageAssetID()); + if( image->getID().isNull() ) + { + image = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR); + } + if (getWearable()) + { + U32 index = gAgentWearables.getWearableIndex(getWearable()); + gAgentAvatarp->setLocalTexture(entry->mTextureIndex, image, FALSE, index); + LLVisualParamHint::requestHintUpdates(); + gAgentAvatarp->wearableUpdated(type, FALSE); + } + } + else + { + llwarns << "could not get texture picker dictionary entry for wearable of type: " << type << llendl; + } + } +} + +void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl) +{ + if (getWearable()) + { + EWearableType type = getWearable()->getType(); + const PickerControlEntryNamePredicate name_pred(ctrl->getName()); + const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry + = find_picker_ctrl_entry_if(type, name_pred); + if (entry) + { + const LLColor4& old_color = getWearable()->getClothesColor(entry->mTextureIndex); + const LLColor4& new_color = LLColor4(ctrl->getValue()); + if( old_color != new_color ) + { + getWearable()->setClothesColor(entry->mTextureIndex, new_color, TRUE); + LLVisualParamHint::requestHintUpdates(); + gAgentAvatarp->wearableUpdated(getWearable()->getType(), FALSE); + } + } + else + { + llwarns << "could not get color swatch dictionary entry for wearable of type: " << type << llendl; + } + } +} + +void LLPanelEditWearable::updatePanelPickerControls(EWearableType type) +{ + LLPanel* panel = getPanel(type); + if (!panel) + return; + + bool is_modifiable = false; + bool is_complete = false; + bool is_copyable = false; + + if(mWearableItem) + { + const LLPermissions& perm = mWearableItem->getPermissions(); + is_modifiable = perm.allowModifyBy(gAgent.getID(), gAgent.getGroupID()); + is_copyable = perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID()); + is_complete = mWearableItem->isFinished(); + } + + if (is_modifiable && is_complete) + { + // Update picker controls + for_each_picker_ctrl_entry (panel, type, boost::bind(update_color_swatch_ctrl, this, _1, _2)); + for_each_picker_ctrl_entry (panel, type, boost::bind(update_texture_ctrl, this, _1, _2)); + } + + if (!is_modifiable || !is_complete || !is_copyable) + { + // Disable controls + for_each_picker_ctrl_entry (panel, type, boost::bind(set_enabled_color_swatch_ctrl, false, _1, _2)); + for_each_picker_ctrl_entry (panel, type, boost::bind(set_enabled_texture_ctrl, false, _1, _2)); + } +} void LLPanelEditWearable::saveChanges() { @@ -428,6 +847,9 @@ void LLPanelEditWearable::showWearable(LLWearable* wearable, BOOL show) mDescTitle->setText(description_title); } + // Update picker controls state + for_each_picker_ctrl_entry (targetPanel, type, boost::bind(set_enabled_color_swatch_ctrl, show, _1, _2)); + for_each_picker_ctrl_entry (targetPanel, type, boost::bind(set_enabled_texture_ctrl, show, _1, _2)); } void LLPanelEditWearable::initializePanel() @@ -493,6 +915,11 @@ void LLPanelEditWearable::initializePanel() updateScrollingPanelUI(); } + + // initialize texture and color picker controls + for_each_picker_ctrl_entry (getPanel(type), type, boost::bind(init_color_swatch_ctrl, this, _1, _2)); + for_each_picker_ctrl_entry (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2)); + updateVerbs(); } diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 8b63685177..76b0ddb3cc 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -77,6 +77,10 @@ private: // update bottom bar buttons ("Save", "Revert", etc) void updateVerbs(); + void onColorSwatchCommit(const LLUICtrl*); + void onTexturePickerCommit(const LLUICtrl*); + void updatePanelPickerControls(EWearableType type); + // the pointer to the wearable we're editing. NULL means we're not editing a wearable. LLWearable *mWearablePtr; LLViewerInventoryItem* mWearableItem; @@ -112,7 +116,6 @@ private: LLPanel *mPanelSkirt; LLPanel *mPanelAlpha; LLPanel *mPanelTattoo; - }; #endif diff --git a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml index 1d0c0a02b0..cfcdc25f81 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_alpha.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_alpha.xml @@ -32,7 +32,10 @@ name="Lower Alpha" tool_tip="Click to choose a picture" top="10" - width="94" /> + width="94" > + + + width="94"> + + + width="94" > + + + width="94" > + + + width="94" > + + - + width="64" > + + + + width="64" > + + - - + + + + - + width="64" > + + + + width="74" > + + + width="74" > + + + width="74" > + + + width="64" > + + + width="64" > + + + width="64" > + + + width="64" > + + + width="64" > + + + width="64" > + + + width="74" > + + + width="74" > + + - + width="74" > + + + + width="64" > + + + width="64" > + + + width="64" > + + + width="64" > + + + width="64" > + + + width="64" > + + + width="64" > + + + width="64" > + + Date: Wed, 28 Apr 2010 17:31:15 +0300 Subject: Fixed Windows build after chengeset (15508dc34f63) Implemented major task EXT-6979 (Connect wearable editor texture and color edito...: added default bodies for overloading of function templates removed qualifier before PickerControlEntry class name. --HG-- branch : product-engine --- indra/newview/llpaneleditwearable.cpp | 39 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index d40e0f2d97..3c112b8b5e 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -372,24 +372,25 @@ LLEditWearableDictionary::PickerControlEntry::PickerControlEntry(ETextureIndex t } // Helper functions. +static const texture_vec_t null_texture_vec; // Specializations of this template function return a vector of texture indexes of particular control type // (i.e. LLColorSwatchCtrl or LLTextureCtrl) which are contained in given WearableEntry. template const texture_vec_t& -get_pickers_indexes(const LLEditWearableDictionary::WearableEntry *wearable_entry); +get_pickers_indexes(const LLEditWearableDictionary::WearableEntry *wearable_entry) { return null_texture_vec; } // Specializations of this template function return picker control entry for particular control type. template -const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* -get_picker_entry (const ETextureIndex index); +const LLEditWearableDictionary::PickerControlEntry* +get_picker_entry (const ETextureIndex index) { return NULL; } -typedef boost::function function_t; +typedef boost::function function_t; typedef struct PickerControlEntryNamePredicate { PickerControlEntryNamePredicate(const std::string name) : mName (name) {}; - bool operator()(const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) const + bool operator()(const LLEditWearableDictionary::PickerControlEntry* entry) const { return (entry && entry->mName == mName); } @@ -397,8 +398,6 @@ private: const std::string mName; } PickerControlEntryNamePredicate; -static const texture_vec_t null_texture_vec; - // A full specialization of get_pickers_indexes for LLColorSwatchCtrl template <> const texture_vec_t& @@ -427,7 +426,7 @@ get_pickers_indexes (const LLEditWearableDictionary::WearableEntr // A full specialization of get_picker_entry for LLColorSwatchCtrl template <> -const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* +const LLEditWearableDictionary::PickerControlEntry* get_picker_entry (const ETextureIndex index) { return LLEditWearableDictionary::getInstance()->getColorSwatch(index); @@ -435,14 +434,14 @@ get_picker_entry (const ETextureIndex index) // A full specialization of get_picker_entry for LLTextureCtrl template <> -const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* +const LLEditWearableDictionary::PickerControlEntry* get_picker_entry (const ETextureIndex index) { return LLEditWearableDictionary::getInstance()->getTexturePicker(index); } template -const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* +const LLEditWearableDictionary::PickerControlEntry* find_picker_ctrl_entry_if(EWearableType type, const Predicate pred) { const LLEditWearableDictionary::WearableEntry *wearable_entry @@ -459,7 +458,7 @@ find_picker_ctrl_entry_if(EWearableType type, const Predicate pred) iter != iter_end; ++iter) { const ETextureIndex te = *iter; - const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry + const LLEditWearableDictionary::PickerControlEntry* entry = get_picker_entry(te); if (!entry) { @@ -497,7 +496,7 @@ for_each_picker_ctrl_entry(LLPanel* panel, EWearableType type, function_t fun) iter != iter_end; ++iter) { const ETextureIndex te = *iter; - const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry + const LLEditWearableDictionary::PickerControlEntry* entry = get_picker_entry(te); if (!entry) { @@ -509,7 +508,7 @@ for_each_picker_ctrl_entry(LLPanel* panel, EWearableType type, function_t fun) } // The helper functions for pickers management -static void init_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +static void init_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) { LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild(entry->mControlName); if (color_swatch_ctrl) @@ -518,7 +517,7 @@ static void init_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, co } } -static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) { LLTextureCtrl* texture_ctrl = panel->getChild(entry->mControlName); if (texture_ctrl) @@ -531,7 +530,7 @@ static void init_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const L } } -static void update_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +static void update_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) { LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild(entry->mControlName); if (color_swatch_ctrl) @@ -540,7 +539,7 @@ static void update_color_swatch_ctrl(LLPanelEditWearable* self, LLPanel* panel, } } -static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) { LLTextureCtrl* texture_ctrl = panel->getChild(entry->mControlName); if (texture_ctrl) @@ -565,7 +564,7 @@ static void update_texture_ctrl(LLPanelEditWearable* self, LLPanel* panel, const } } -static void set_enabled_color_swatch_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +static void set_enabled_color_swatch_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) { LLColorSwatchCtrl* color_swatch_ctrl = panel->getChild(entry->mControlName); if (color_swatch_ctrl) @@ -574,7 +573,7 @@ static void set_enabled_color_swatch_ctrl(bool enabled, LLPanel* panel, const LL } } -static void set_enabled_texture_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry) +static void set_enabled_texture_ctrl(bool enabled, LLPanel* panel, const LLEditWearableDictionary::PickerControlEntry* entry) { LLTextureCtrl* texture_ctrl = panel->getChild(entry->mControlName); if (texture_ctrl) @@ -697,7 +696,7 @@ void LLPanelEditWearable::onTexturePickerCommit(const LLUICtrl* ctrl) { EWearableType type = getWearable()->getType(); const PickerControlEntryNamePredicate name_pred(texture_ctrl->getName()); - const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry + const LLEditWearableDictionary::PickerControlEntry* entry = find_picker_ctrl_entry_if(type, name_pred); if (entry) { @@ -728,7 +727,7 @@ void LLPanelEditWearable::onColorSwatchCommit(const LLUICtrl* ctrl) { EWearableType type = getWearable()->getType(); const PickerControlEntryNamePredicate name_pred(ctrl->getName()); - const LLEditWearableDictionary::PickerControlEntry::PickerControlEntry* entry + const LLEditWearableDictionary::PickerControlEntry* entry = find_picker_ctrl_entry_if(type, name_pred); if (entry) { -- cgit v1.2.3 From f9a120e8983a72b6de2f146acec55e079255b70e Mon Sep 17 00:00:00 2001 From: Igor Borovkov Date: Wed, 28 Apr 2010 17:47:08 +0300 Subject: partial implementation of EXT-6723 Create specialized view of inventory for "clothing" accordion tab of outfit editor - added grouping clothing items by wearable type (shirt, jeans etc.) - added sorting clothing items by wearing order in groups - added separators between items of the same wearable type (lists: clothing, body parts) - added list specific button bars - partially added dummy items for missing wearable types in the COF (clothing list) Reviewed by Mike Antipov at https://codereview.productengine.com/secondlife/r/322 --HG-- branch : product-engine --- indra/newview/llappearancemgr.cpp | 10 +- indra/newview/llappearancemgr.h | 12 +- indra/newview/llcofwearables.cpp | 149 ++++++++++++++++++--- indra/newview/llcofwearables.h | 10 ++ .../xui/en/panel_bodyparts_list_button_bar.xml | 36 +++++ .../xui/en/panel_clothing_list_button_bar.xml | 37 +++++ .../skins/default/xui/en/panel_cof_wearables.xml | 1 + 7 files changed, 227 insertions(+), 28 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml create mode 100644 indra/newview/skins/default/xui/en/panel_clothing_list_button_bar.xml diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5586b3cd4d..e93e29ecde 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -1092,7 +1092,8 @@ void LLAppearanceMgr::updateAppearanceFromCOF() } //preparing the list of wearables in the correct order for LLAgentWearables - std::sort(wear_items.begin(), wear_items.end(), sort_by_description); + sortItemsByActualDescription(wear_items); + LLWearableHoldingPattern* holder = new LLWearableHoldingPattern; @@ -1910,6 +1911,13 @@ bool LLAppearanceMgr::moveWearable(LLViewerInventoryItem* item, bool closer_to_b return result; } +//static +void LLAppearanceMgr::sortItemsByActualDescription(LLInventoryModel::item_array_t& items) +{ + if (items.size() < 2) return; + + std::sort(items.begin(), items.end(), sort_by_description); +} //#define DUMP_CAT_VERBOSE diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index a308a3efa9..516dada39d 100644 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -48,6 +48,8 @@ class LLAppearanceMgr: public LLSingleton friend class LLSingleton; public: + typedef std::vector wearables_by_type_t; + void updateAppearanceFromCOF(); bool needToSaveCOF(); void updateCOF(const LLUUID& category, bool append = false); @@ -143,17 +145,17 @@ public: bool moveWearable(LLViewerInventoryItem* item, bool closer_to_body); + static void sortItemsByActualDescription(LLInventoryModel::item_array_t& items); + + //Divvy items into arrays by wearable type + static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type); + protected: LLAppearanceMgr(); ~LLAppearanceMgr(); private: - typedef std::vector wearables_by_type_t; - - //Divvy items into arrays by wearable type - static void divvyWearablesByType(const LLInventoryModel::item_array_t& items, wearables_by_type_t& items_by_type); - //Check ordering information on wearables stored in links' descriptions and update if it is invalid void updateClothingOrderingInfo(); diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index f0442ee3f6..e21644e119 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -94,47 +94,139 @@ void LLCOFWearables::refresh() clear(); LLInventoryModel::cat_array_t cats; - LLInventoryModel::item_array_t items; + LLInventoryModel::item_array_t cof_items; + + gInventory.collectDescendents(LLAppearanceMgr::getInstance()->getCOF(), cats, cof_items, LLInventoryModel::EXCLUDE_TRASH); + + populateAttachmentsAndBodypartsLists(cof_items); + + + LLAppearanceMgr::wearables_by_type_t clothing_by_type(WT_COUNT); + LLAppearanceMgr::getInstance()->divvyWearablesByType(cof_items, clothing_by_type); - gInventory.collectDescendents(LLAppearanceMgr::getInstance()->getCOF(), cats, items, LLInventoryModel::EXCLUDE_TRASH); - if (items.empty()) return; + populateClothingList(clothing_by_type); +} + - for (U32 i = 0; i < items.size(); ++i) +void LLCOFWearables::populateAttachmentsAndBodypartsLists(const LLInventoryModel::item_array_t& cof_items) +{ + for (U32 i = 0; i < cof_items.size(); ++i) { - LLViewerInventoryItem* item = items.get(i); + LLViewerInventoryItem* item = cof_items.get(i); if (!item) continue; + const LLAssetType::EType item_type = item->getType(); + if (item_type == LLAssetType::AT_CLOTHING) continue; + LLPanelInventoryListItem* item_panel = LLPanelInventoryListItem::createItemPanel(item); if (!item_panel) continue; - switch (item->getType()) + if (item_type == LLAssetType::AT_OBJECT) { - case LLAssetType::AT_OBJECT: - mAttachments->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); - break; + mAttachments->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); + } + else if (item_type == LLAssetType::AT_BODYPART) + { + mBodyParts->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); + addWearableTypeSeparator(mBodyParts); + } + } + + if (mAttachments->size()) + { + mAttachments->sort(); //*TODO by Name + mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false) + } - case LLAssetType::AT_BODYPART: - mBodyParts->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); - break; + if (mBodyParts->size()) + { + mBodyParts->sort(); //*TODO by name + } + + addListButtonBar(mBodyParts, "panel_bodyparts_list_button_bar.xml"); + mBodyParts->notify(REARRANGE); +} + + +void LLCOFWearables::populateClothingList(LLAppearanceMgr::wearables_by_type_t& clothing_by_type) +{ + llassert(clothing_by_type.size() == WT_COUNT); + + addListButtonBar(mClothing, "panel_clothing_list_button_bar.xml"); + + for (U32 type = WT_SHIRT; type < WT_COUNT; ++type) + { + U32 size = clothing_by_type[type].size(); + if (!size) continue; + + LLAppearanceMgr::sortItemsByActualDescription(clothing_by_type[type]); + + for (U32 i = 0; i < size; i++) + { + LLViewerInventoryItem* item = clothing_by_type[type][i]; - case LLAssetType::AT_CLOTHING: - mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); - break; + LLPanelInventoryListItem* item_panel = LLPanelInventoryListItem::createItemPanel(item); + if (!item_panel) continue; - default: break; + mClothing->addItem(item_panel, item->getUUID(), ADD_BOTTOM, false); } + + addWearableTypeSeparator(mClothing); } - mAttachments->sort(); //*TODO by Name - mAttachments->notify(REARRANGE); //notifying the parent about the list's size change (cause items were added with rearrange=false) - - mClothing->sort(); //*TODO by actual inventory item description + addClothingTypesDummies(clothing_by_type); + mClothing->notify(REARRANGE); +} + +void LLCOFWearables::addListButtonBar(LLFlatListView* list, std::string xml_filename) +{ + llassert(list); + llassert(xml_filename.length()); - mBodyParts->sort(); //*TODO by name - mBodyParts->notify(REARRANGE); + LLPanel::Params params; + LLPanel* button_bar = LLUICtrlFactory::create(params); + LLUICtrlFactory::instance().buildPanel(button_bar, xml_filename); + + LLRect rc = button_bar->getRect(); + button_bar->reshape(list->getItemsRect().getWidth(), rc.getHeight()); + + list->addItem(button_bar, LLUUID::null, ADD_TOP, false); } +//adding dummy items for missing wearable types +void LLCOFWearables::addClothingTypesDummies(const LLAppearanceMgr::wearables_by_type_t& clothing_by_type) +{ + llassert(clothing_by_type.size() == WT_COUNT); + + for (U32 type = WT_SHIRT; type < WT_COUNT; type++) + { + U32 size = clothing_by_type[type].size(); + if (size) continue; + + //*TODO create dummy item panel + + //*TODO add dummy item panel -> mClothing->addItem(dummy_item_panel, item->getUUID(), ADD_BOTTOM, false); + + addWearableTypeSeparator(mClothing); + } +} + +void LLCOFWearables::addWearableTypeSeparator(LLFlatListView* list) +{ + llassert(list); + + static LLXMLNodePtr separator_xml_node = getXMLNode("panel_wearable_type_separator.xml"); + if (separator_xml_node->isNull()) return; + + LLPanel* separator = LLUICtrlFactory::defaultBuilder(separator_xml_node, NULL, NULL); + + LLRect rc = separator->getRect(); + rc.setOriginAndSize(0, 0, list->getItemsRect().getWidth(), rc.getHeight()); + separator->setRect(rc); + + list->addItem(separator, LLUUID::null, ADD_BOTTOM, false); +} LLUUID LLCOFWearables::getSelectedUUID() { @@ -150,4 +242,17 @@ void LLCOFWearables::clear() mBodyParts->clear(); } +LLXMLNodePtr LLCOFWearables::getXMLNode(std::string xml_filename) +{ + LLXMLNodePtr xmlNode = NULL; + bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, xmlNode); + if (!success) + { + llwarning("Failed to read xml", 0); + return NULL; + } + + return xmlNode; +} + //EOF diff --git a/indra/newview/llcofwearables.h b/indra/newview/llcofwearables.h index 58d67ed32f..28d58887da 100644 --- a/indra/newview/llcofwearables.h +++ b/indra/newview/llcofwearables.h @@ -34,6 +34,8 @@ #define LL_LLCOFWEARABLES_H #include "llpanel.h" +#include "llinventorymodel.h" +#include "llappearancemgr.h" class LLFlatListView; @@ -52,8 +54,16 @@ public: protected: + void populateAttachmentsAndBodypartsLists(const LLInventoryModel::item_array_t& cof_items); + void populateClothingList(LLAppearanceMgr::wearables_by_type_t& clothing_by_type); + + void addListButtonBar(LLFlatListView* list, std::string xml_filename); + void addClothingTypesDummies(const LLAppearanceMgr::wearables_by_type_t& clothing_by_type); + void addWearableTypeSeparator(LLFlatListView* list); void onSelectionChange(LLFlatListView* selected_list); + LLXMLNodePtr LLCOFWearables::getXMLNode(std::string xml_filename); + LLFlatListView* mAttachments; LLFlatListView* mClothing; LLFlatListView* mBodyParts; diff --git a/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml b/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml new file mode 100644 index 0000000000..9d19b89a61 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_bodyparts_list_button_bar.xml @@ -0,0 +1,36 @@ + + + +