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(-) (limited to 'indra/newview') 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(-) (limited to 'indra/newview') 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(-) (limited to 'indra/newview') 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(-) (limited to 'indra/newview') 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 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(-) (limited to 'indra/newview') 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 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(-) (limited to 'indra/newview') 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: Wed, 28 Apr 2010 14:14:06 -0400 Subject: Compile error fix for missing description field in link_inventory_item. --- indra/newview/llinventorybridge.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 9275ddc4e3..c6f806178c 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -1835,11 +1835,13 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, else { LLPointer cb = NULL; + const std::string empty_description = ""; link_inventory_item( gAgent.getID(), inv_cat->getUUID(), mUUID, inv_cat->getName(), + empty_description, LLAssetType::AT_LINK_FOLDER, cb); } @@ -2510,11 +2512,13 @@ void LLFolderBridge::pasteLinkFromClipboard() const LLUUID &object_id = (*iter); if (LLInventoryCategory *cat = model->getCategory(object_id)) { + const std::string empty_description = ""; link_inventory_item( gAgent.getID(), cat->getUUID(), parent_id, cat->getName(), + empty_description, LLAssetType::AT_LINK_FOLDER, LLPointer(NULL)); } @@ -2525,7 +2529,7 @@ void LLFolderBridge::pasteLinkFromClipboard() item->getLinkedUUID(), parent_id, item->getName(), - item->getDescription(), + item->getDescription(), LLAssetType::AT_LINK, LLPointer(NULL)); } -- cgit v1.2.3 From dacc5afbf0f1bde7454c1eadf56edb669d0741a9 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Tue, 27 Apr 2010 17:25:01 -0700 Subject: Architectural changes to LLPlugin message processing. LLPluginProcessParent can now optionally use a separate thread for reading messages from plugin sockets. If this is enabled, it will spawn a single thread and use apr_pollset_poll to wake up the thread when incoming data arrives instead of polling all the descriptors round-robin every frame. This should be somewhat more efficient, and should also allow blocking requests from plugins to be serviced much more quickly (once we start using them). This is currently disabled by default, until it's had a bit more focused testing on multiple platforms. Hooked up the switch to use the message read thread to the PluginUseReadThread debug setting and an item in the Advanced menu in the viewer, and to a checkbox in the UI in llmediaplugintest. Updated some debug logging in the plugin system to have appropriate tags and not log dire-looking warnings during normal operation. LLPluginProcessParent now once again explicitly kills plugin processes (instead of just closing their sockets and waiting for them to exit). The problem we were attempting to solve by not doing the kill (letting the webkit plugin write its cookie file on exit) has been solved another way. LLPluginProcessParent::sendMessage() now attempts to write the outgoing message to the socket immediately instead of waiting for the next frame. This should reduce the latency of sending plugin messages. Added a separate fast timer for LLViewerMedia::updateMedia(). --- indra/newview/app_settings/settings.xml | 13 +++++++++++++ indra/newview/llappviewer.cpp | 3 +++ indra/newview/llviewermedia.cpp | 11 +++++++++++ indra/newview/skins/default/xui/en/menu_viewer.xml | 10 ++++++++++ 4 files changed, 37 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 6f11a6d616..280c3d642c 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5585,6 +5585,19 @@ Value 8 + + PluginUseReadThread + + Comment + Use a separate thread to read incoming messages from plugins + Persist + 1 + Type + Boolean + Value + 0 + + PrecachingDelay Comment diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 2f9bbb1407..4f7c0c3549 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1530,6 +1530,9 @@ bool LLAppViewer::cleanup() LLViewerMedia::saveCookieFile(); + // Stop the plugin read thread if it's running. + LLPluginProcessParent::setUseReadThread(false); + llinfos << "Shutting down Threads" << llendflush; // Let threads finish diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index fd2bb0fdf9..8e210554fb 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -732,10 +732,21 @@ static bool proximity_comparitor(const LLViewerMediaImpl* i1, const LLViewerMedi } } +static LLFastTimer::DeclareTimer FTM_MEDIA_UPDATE("Update Media"); + ////////////////////////////////////////////////////////////////////////////////////////// // static void LLViewerMedia::updateMedia(void *dummy_arg) { + LLFastTimer t1(FTM_MEDIA_UPDATE); + + bool use_read_thread = gSavedSettings.getBOOL("PluginUseReadThread"); + if(LLPluginProcessParent::getUseReadThread() != use_read_thread) + { + // Enable/disable the plugin read thread + LLPluginProcessParent::setUseReadThread(use_read_thread); + } + sAnyMediaShowing = false; sUpdatedCookies = getCookieStore()->getChangedCookies(); if(!sUpdatedCookies.empty()) diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index 3af80f63fe..df4f33adf0 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1339,6 +1339,16 @@ function="ToggleControl" parameter="RunMultipleThreads" /> + + + + -- 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(-) (limited to 'indra/newview') 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(-) (limited to 'indra/newview') 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(-) (limited to 'indra/newview') 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 (limited to 'indra/newview') 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 @@ + + + +