From 7e74e18548d9b508e3d4c3233044302742942eba Mon Sep 17 00:00:00 2001 From: "Eric M. Tulla (BigPapi)" Date: Wed, 11 Nov 2009 20:27:29 -0500 Subject: Fix for EXT-2244 - Auto fill the My Outfits folder from library/clothing if empty -Reviewed by Seraph --- indra/newview/llagentwearables.cpp | 150 ++++++++++++++++++++++++++++++++++++- indra/newview/llagentwearables.h | 6 +- indra/newview/llinventorymodel.cpp | 10 +-- indra/newview/llinventorymodel.h | 11 ++- 4 files changed, 162 insertions(+), 15 deletions(-) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 3fc1055acd..1b1c65640f 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -84,6 +84,26 @@ protected: void processWearablesMessage(); }; +class LLLibraryOutfitsFetch : public LLInventoryFetchDescendentsObserver +{ +public: + enum ELibraryOutfitFetchStep { + LOFS_FOLDER = 0, + LOFS_OUTFITS, + LOFS_CONTENTS + }; + LLLibraryOutfitsFetch() : mCurrFetchStep(LOFS_FOLDER), mOutfitsPopulated(false) {} + ~LLLibraryOutfitsFetch() {} + virtual void done(); +protected: + void folderDone(void); + void outfitsDone(void); + void contentsDone(void); + enum ELibraryOutfitFetchStep mCurrFetchStep; + std::vector< std::pair< LLUUID, std::string > > mOutfits; + bool mOutfitsPopulated; +}; + LLAgentWearables gAgentWearables; BOOL LLAgentWearables::mInitialWearablesUpdateReceived = FALSE; @@ -904,6 +924,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs // will call done for us when everything is here. gInventory.addObserver(outfit); } + + gAgentWearables.populateMyOutfitsFolder(); } } @@ -2003,18 +2025,142 @@ void LLAgentWearables::updateServer() gAgent.sendAgentSetAppearance(); } +void LLAgentWearables::populateMyOutfitsFolder(void) +{ + LLLibraryOutfitsFetch* outfits = new LLLibraryOutfitsFetch(); + + // What we do here is get the complete information on the items in + // the inventory, and set up an observer that will wait for that to + // happen. + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + const LLUUID my_outfits_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + + folders.push_back(my_outfits_id); + outfits->fetchDescendents(folders); + if(outfits->isEverythingComplete()) + { + // everything is already here - call done. + outfits->done(); + } + else + { + // it's all on it's way - add an observer, and the inventory + // will call done for us when everything is here. + gInventory.addObserver(outfits); + } +} + +void LLLibraryOutfitsFetch::done() +{ + switch (mCurrFetchStep){ + case LOFS_FOLDER: + mCurrFetchStep = LOFS_OUTFITS; + folderDone(); + break; + case LOFS_OUTFITS: + mCurrFetchStep = LOFS_CONTENTS; + outfitsDone(); + break; + case LOFS_CONTENTS: + // No longer need this observer hanging around. + gInventory.removeObserver(this); + contentsDone(); + break; + default: + gInventory.removeObserver(this); + delete this; + return; + } + if (mOutfitsPopulated) + { + delete this; + } +} + +void LLLibraryOutfitsFetch::folderDone(void) +{ + // Early out if we already have items in My Outfits. + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + if (cat_array.count() > 0 || wearable_array.count() > 0) + { + mOutfitsPopulated = true; + gInventory.removeObserver(this); + return; + } + + // Get the UUID of the library's clothing folder + const LLUUID library_clothing_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING, false, true); + + mCompleteFolders.clear(); + + // What we do here is get the complete information on the items in + // the inventory, and set up an observer that will wait for that to + // happen. + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + folders.push_back(library_clothing_id); + fetchDescendents(folders); + if(isEverythingComplete()) + { + // everything is already here - call done. + outfitsDone(); + } +} + +void LLLibraryOutfitsFetch::outfitsDone(void) +{ + LLInventoryModel::cat_array_t cat_array; + LLInventoryModel::item_array_t wearable_array; + gInventory.collectDescendents(mCompleteFolders.front(), cat_array, wearable_array, + LLInventoryModel::EXCLUDE_TRASH); + + LLInventoryFetchDescendentsObserver::folder_ref_t folders; + for(S32 i = 0; i < cat_array.count(); ++i) + { + if (cat_array.get(i)->getName() != "More Outfits" && cat_array.get(i)->getName() != "Ruth"){ + folders.push_back(cat_array.get(i)->getUUID()); + mOutfits.push_back( std::make_pair(cat_array.get(i)->getUUID(), cat_array.get(i)->getName() )); + } + } + mCompleteFolders.clear(); + fetchDescendents(folders); + if(isEverythingComplete()) + { + // everything is already here - call done. + contentsDone(); + } +} + +void LLLibraryOutfitsFetch::contentsDone(void) +{ + for(S32 i = 0; i < mOutfits.size(); ++i) + { + // First, make a folder in the My Outfits directory. + const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS); + LLUUID folder_id = gInventory.createNewCategory(parent_id, + LLFolderType::FT_OUTFIT, + mOutfits[i].second); + + LLAppearanceManager::shallowCopyCategory(mOutfits[i].first, folder_id, NULL); + gInventory.notifyObservers(); + } + mOutfitsPopulated = true; +} + void LLInitialWearablesFetch::done() { // No longer need this observer hanging around. gInventory.removeObserver(this); - + // Fetch the wearable items from the Current Outfit Folder LLInventoryModel::cat_array_t cat_array; LLInventoryModel::item_array_t wearable_array; LLFindWearables is_wearable; gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array, LLInventoryModel::EXCLUDE_TRASH, is_wearable); - + LLAppearanceManager::setAttachmentInvLinkEnable(true); if (wearable_array.count() > 0) { diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h index 317f4a7e4f..9b13cb842c 100644 --- a/indra/newview/llagentwearables.h +++ b/indra/newview/llagentwearables.h @@ -169,9 +169,11 @@ public: const LLDynamicArray& attachments_to_include, BOOL rename_clothing); - // Note: wearables_to_include should be a list of EWearableType types - // attachments_to_include should be a list of attachment points LLUUID makeNewOutfitLinks(const std::string& new_folder_name); + + // Should only be called if we *know* we've never done so before, since users may + // not want the Library outfits to stay in their quick outfit selector and can delete them. + void populateMyOutfitsFolder(void); private: void makeNewOutfitDone(S32 type, U32 index); diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 4b7e364cf9..cc7a1ae14e 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -321,10 +321,10 @@ void LLInventoryModel::unlockDirectDescendentArrays(const LLUUID& cat_id) // specifies 'type' as what it defaults to containing. The category is // not necessarily only for that type. *NOTE: This will create a new // inventory category on the fly if one does not exist. -const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType t, bool create_folder) +const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType t, bool create_folder, bool find_in_library) { - const LLUUID &rv = findCatUUID(t); - if(rv.isNull() && isInventoryUsable() && create_folder) + const LLUUID &rv = findCatUUID(t, find_in_library); + if(rv.isNull() && isInventoryUsable() && (create_folder && !find_in_library)) { const LLUUID &root_id = gInventory.getRootFolderID(); if(root_id.notNull()) @@ -337,9 +337,9 @@ const LLUUID LLInventoryModel::findCategoryUUIDForType(LLFolderType::EType t, bo // Internal method which looks for a category with the specified // preferred type. Returns LLUUID::null if not found. -const LLUUID &LLInventoryModel::findCatUUID(LLFolderType::EType preferred_type) const +const LLUUID &LLInventoryModel::findCatUUID(LLFolderType::EType preferred_type, bool find_in_library) const { - const LLUUID &root_id = gInventory.getRootFolderID(); + const LLUUID &root_id = (find_in_library) ? gInventory.getLibraryRootFolderID() : gInventory.getRootFolderID(); if(LLFolderType::FT_CATEGORY == preferred_type) { return root_id; diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index faf026887a..b33237f466 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -275,13 +275,12 @@ public: // findCategoryUUIDForType() returns the uuid of the category that // specifies 'type' as what it defaults to containing. The - // category is not necessarily only for that type. *NOTE: This - // will create a new inventory category on the fly if one does not - // exist. - + // category is not necessarily only for that type. *NOTE: If create_folder is true, this + // will create a new inventory category on the fly if one does not exist. *NOTE: if find_in_library is + // true it will search in the user's library folder instead of "My Inventory" // SDK: Added flag to specify whether the folder should be created if not found. This fixes the horrible // multiple trash can bug. - const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder = true); + const LLUUID findCategoryUUIDForType(LLFolderType::EType preferred_type, bool create_folder = true, bool find_in_library = false); // Call this method when it's time to update everyone on a new // state, by default, the inventory model will not update @@ -432,7 +431,7 @@ protected: // // Internal method which looks for a category with the specified // preferred type. Returns LLUUID::null if not found - const LLUUID &findCatUUID(LLFolderType::EType preferred_type) const; + const LLUUID &findCatUUID(LLFolderType::EType preferred_type, bool find_in_library = false) const; // Empty the entire contents void empty(); -- cgit v1.2.3 From 0daf4297d43e97a4b715196e9821cc290ebd65b3 Mon Sep 17 00:00:00 2001 From: James Cook Date: Fri, 13 Nov 2009 16:16:12 -0800 Subject: EXT-2484 Auto Set Touch to Buy when a user checks the For Sale option Reviewed with Richard. --- indra/newview/llpanelpermissions.cpp | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 2d3f901370..1051326e72 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -970,19 +970,32 @@ void LLPanelPermissions::setAllSaleInfo() if (price < 0) sale_type = LLSaleInfo::FS_NOT; - LLSaleInfo sale_info(sale_type, price); - LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(sale_info); + LLSaleInfo old_sale_info; + LLSelectMgr::getInstance()->selectGetSaleInfo(old_sale_info); + + LLSaleInfo new_sale_info(sale_type, price); + LLSelectMgr::getInstance()->selectionSetObjectSaleInfo(new_sale_info); - // If turned off for-sale, make sure click-action buy is turned - // off as well - if (sale_type == LLSaleInfo::FS_NOT) + U8 old_click_action = 0; + LLSelectMgr::getInstance()->selectionGetClickAction(&old_click_action); + + if (old_sale_info.isForSale() + && !new_sale_info.isForSale() + && old_click_action == CLICK_ACTION_BUY) { - U8 click_action = 0; - LLSelectMgr::getInstance()->selectionGetClickAction(&click_action); - if (click_action == CLICK_ACTION_BUY) - { - LLSelectMgr::getInstance()->selectionSetClickAction(CLICK_ACTION_TOUCH); - } + // If turned off for-sale, make sure click-action buy is turned + // off as well + LLSelectMgr::getInstance()-> + selectionSetClickAction(CLICK_ACTION_TOUCH); + } + else if (new_sale_info.isForSale() + && !old_sale_info.isForSale() + && old_click_action == CLICK_ACTION_TOUCH) + { + // If just turning on for-sale, preemptively turn on one-click buy + // unless user have a different click action set + LLSelectMgr::getInstance()-> + selectionSetClickAction(CLICK_ACTION_BUY); } } -- cgit v1.2.3 From 6be35d363fb9e9f04c5344cab808ef40e63cbfab Mon Sep 17 00:00:00 2001 From: Rick Pasetto Date: Fri, 13 Nov 2009 17:42:38 -0800 Subject: Integrated most of the final artwork into the media controls --- .../default/xui/en/panel_prim_media_controls.xml | 372 +++++++++++---------- 1 file changed, 193 insertions(+), 179 deletions(-) diff --git a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml index 70c5d7b823..98025e28db 100644 --- a/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml +++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml @@ -77,10 +77,14 @@ width="22" top="4"> - - + + + width="14"> @@ -408,27 +422,33 @@ function="MediaCtrl.CommitURL" /> auto_resize="false" user_resize="false" layout="topleft" - min_width="20" + min_width="14" height="14" - width="20"> + width="14"> + + + + + + min_width="22" width="22"> - min_width="22" width="22"> - Date: Fri, 13 Nov 2009 18:15:35 -0800 Subject: Tweaks to media priority calculation. Enabled CPU limit setting by default (set to 100% of 1 CPU). Lowered default limits on plugin priorities: 2 normal+, 4 low, 8 total. Limit on total number of instances now only applies to inworld media -- media instances in the UI (such as the help browser and search) don't count toward the limit. UI media will still bump inworld media down from normal/low priority, though. Several improvements to plugin manager debug code in the nearby media list. Don't load unloaded instances that are at PRIORITY_SLIDESHOW or PRIORITY_HIDDEN (they don't get unloaded, they just won't be loaded unless they're at higher priority). Added LLViewerMediaImpl::isPlayable(), which indicates whether an instance would be loaded if it were high enough in the priority list (taking into account autoplay and current load state). Priority algorithm now takes this into account. Fixed a couple of issues with approximate texture interest calculation and its use in setting priorities. Adjusted sleep times on low and normal priorities to be more friendly. --- indra/llplugin/llpluginclassmedia.cpp | 4 +- indra/llplugin/llpluginprocesschild.cpp | 5 ++- indra/newview/app_settings/settings.xml | 10 ++--- indra/newview/llviewermedia.cpp | 75 +++++++++++++++++++++++++++++---- indra/newview/llviewermedia.h | 5 ++- 5 files changed, 80 insertions(+), 19 deletions(-) diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index 42d5ec49cd..c3d8a5aa23 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -593,10 +593,10 @@ void LLPluginClassMedia::setPriority(EPriority priority) mSleepTime = 1.0f; break; case PRIORITY_LOW: - mSleepTime = 1.0f / 50.0f; + mSleepTime = 1.0f / 25.0f; break; case PRIORITY_NORMAL: - mSleepTime = 1.0f / 100.0f; + mSleepTime = 1.0f / 50.0f; break; case PRIORITY_HIGH: mSleepTime = 1.0f / 100.0f; diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index 450dcb3c78..fc95136d9e 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -37,12 +37,13 @@ #include "llpluginmessageclasses.h" static const F32 HEARTBEAT_SECONDS = 1.0f; +static const F32 PLUGIN_IDLE_SECONDS = 1.0f / 100.0f; // Each call to idle will give the plugin this much time. LLPluginProcessChild::LLPluginProcessChild() { mInstance = NULL; mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP); - mSleepTime = 1.0f / 100.0f; // default: send idle messages at 100Hz + mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz mCPUElapsed = 0.0f; } @@ -155,7 +156,7 @@ void LLPluginProcessChild::idle(void) { // Provide some time to the plugin LLPluginMessage message("base", "idle"); - message.setValueReal("time", mSleepTime); + message.setValueReal("time", PLUGIN_IDLE_SECONDS); sendMessageToPlugin(message); mInstance->idle(); diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 8ad52784d3..52de17bff5 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -5369,7 +5369,7 @@ Type F32 Value - 0.0 + 1.0 PluginInstancesLow @@ -5385,24 +5385,24 @@ PluginInstancesNormal Comment - Limit on the number of inworld media plugins that will run at "normal" priority + Limit on the number of inworld media plugins that will run at "normal" or higher priority Persist 1 Type U32 Value - 4 + 2 PluginInstancesTotal Comment - Hard limit on the number of plugins that will be instantiated at once + Hard limit on the number of plugins that will be instantiated at once for inworld media Persist 1 Type U32 Value - 16 + 8 PrecachingDelay diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 251d7d4a13..70490d3a6e 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -541,6 +541,16 @@ bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLView // The item with user focus always comes to the front of the list, period. return false; } + else if(i1->isParcelMedia()) + { + // The parcel media impl sorts above all other inworld media, unless one has focus. + return true; + } + else if(i2->isParcelMedia()) + { + // The parcel media impl sorts above all other inworld media, unless one has focus. + return false; + } else if(i1->getUsedInUI() && !i2->getUsedInUI()) { // i1 is a UI element, i2 is not. This makes i1 "less than" i2, so it sorts earlier in our list. @@ -551,14 +561,14 @@ bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLView // i2 is a UI element, i1 is not. This makes i2 "less than" i1, so it sorts earlier in our list. return false; } - else if(i1->isParcelMedia()) + else if(i1->isPlayable() && !i2->isPlayable()) { - // The parcel media impl sorts above all other inworld media, unless one has focus. + // Playable items sort above ones that wouldn't play even if they got high enough priority return true; } - else if(i2->isParcelMedia()) + else if(!i1->isPlayable() && i2->isPlayable()) { - // The parcel media impl sorts above all other inworld media, unless one has focus. + // Playable items sort above ones that wouldn't play even if they got high enough priority return false; } else @@ -629,10 +639,12 @@ void LLViewerMedia::updateMedia() else if(pimpl->hasFocus()) { new_priority = LLPluginClassMedia::PRIORITY_HIGH; + impl_count_interest_normal++; // count this against the count of "normal" instances for priority purposes } else if(pimpl->getUsedInUI()) { new_priority = LLPluginClassMedia::PRIORITY_NORMAL; + impl_count_interest_normal++; } else { @@ -640,7 +652,17 @@ void LLViewerMedia::updateMedia() // Heuristic -- if the media texture's approximate screen area is less than 1/4 of the native area of the texture, // turn it down to low instead of normal. This may downsample for plugins that support it. - bool media_is_small = pimpl->getInterest() < (pimpl->getApproximateTextureInterest() / 4); + bool media_is_small = false; + F64 approximate_interest = pimpl->getApproximateTextureInterest(); + if(approximate_interest == 0.0f) + { + // this media has no current size, which probably means it's not loaded. + media_is_small = true; + } + else if(pimpl->getInterest() < (approximate_interest / 4)) + { + media_is_small = true; + } if(pimpl->getInterest() == 0.0f) { @@ -678,7 +700,7 @@ void LLViewerMedia::updateMedia() } } - if(new_priority != LLPluginClassMedia::PRIORITY_UNLOADED) + if(!pimpl->getUsedInUI() && (new_priority != LLPluginClassMedia::PRIORITY_UNLOADED)) { impl_count_total++; } @@ -1588,6 +1610,10 @@ void LLViewerMediaImpl::update() { // This media source should not be loaded. } + else if(mPriority <= LLPluginClassMedia::PRIORITY_SLIDESHOW) + { + // Don't load new instances that are at PRIORITY_SLIDESHOW or below. They're just kept around to preserve state. + } else if(mMimeTypeProbe != NULL) { // this media source is doing a MIME type probe -- don't try loading it again. @@ -1816,7 +1842,7 @@ bool LLViewerMediaImpl::isMediaPaused() ////////////////////////////////////////////////////////////////////////////////////////// // -bool LLViewerMediaImpl::hasMedia() +bool LLViewerMediaImpl::hasMedia() const { return mMediaSource != NULL; } @@ -1850,6 +1876,31 @@ bool LLViewerMediaImpl::isForcedUnloaded() const return false; } +////////////////////////////////////////////////////////////////////////////////////////// +// +bool LLViewerMediaImpl::isPlayable() const +{ + if(isForcedUnloaded()) + { + // All of the forced-unloaded criteria also imply not playable. + return false; + } + + if(hasMedia()) + { + // Anything that's already playing is, by definition, playable. + return true; + } + + if(!mMediaURL.empty()) + { + // If something has navigated the instance, it's ready to be played. + return true; + } + + return false; +} + ////////////////////////////////////////////////////////////////////////////////////////// void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginClassMediaOwner::EMediaEvent event) { @@ -2094,7 +2145,13 @@ F64 LLViewerMediaImpl::getApproximateTextureInterest() result = mMediaSource->getFullWidth(); result *= mMediaSource->getFullHeight(); } - + else + { + // No media source is loaded -- all we have to go on is the texture size that has been set on the impl, if any. + result = mMediaWidth; + result *= mMediaHeight; + } + return result; } @@ -2135,7 +2192,7 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority) { if(mPriority != priority) { - LL_INFOS("PluginPriority") + LL_DEBUGS("PluginPriority") << "changing priority of media id " << mTextureId << " from " << LLPluginClassMedia::priorityToString(mPriority) << " to " << LLPluginClassMedia::priorityToString(priority) diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 639aed4b8a..a06079786e 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -194,7 +194,7 @@ public: bool isMediaPlaying(); bool isMediaPaused(); - bool hasMedia(); + bool hasMedia() const; bool isMediaFailed() const { return mMediaSourceFailed; }; void resetPreviousMediaState(); @@ -204,6 +204,9 @@ public: // returns true if this instance should not be loaded (disabled, muted object, crashed, etc.) bool isForcedUnloaded() const; + // returns true if this instance could be playable based on autoplay setting, current load state, etc. + bool isPlayable() const; + void setIsParcelMedia(bool is_parcel_media) { mIsParcelMedia = is_parcel_media; }; bool isParcelMedia() const { return mIsParcelMedia; }; -- cgit v1.2.3 From 68c6ff791ffdd01e98cf7fae61b868db4a6d1698 Mon Sep 17 00:00:00 2001 From: "Eric M. Tulla (BigPapi)" Date: Fri, 13 Nov 2009 22:22:30 -0500 Subject: Fix for post-merge compile error. --- indra/newview/llagentwearables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index a6664778fb..ab518adadd 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2145,7 +2145,7 @@ void LLLibraryOutfitsFetch::contentsDone(void) LLFolderType::FT_OUTFIT, mOutfits[i].second); - LLAppearanceManager::shallowCopyCategory(mOutfits[i].first, folder_id, NULL); + LLAppearanceManager::getInstance()->shallowCopyCategory(mOutfits[i].first, folder_id, NULL); gInventory.notifyObservers(); } mOutfitsPopulated = true; -- cgit v1.2.3 From f67a8ad12ee4984a37d8ac7e551cdcc03ed5ecd3 Mon Sep 17 00:00:00 2001 From: Steve Bennetts Date: Fri, 13 Nov 2009 22:54:55 -0800 Subject: Mutex lock fix for texture cache. Also a fix for texture purging when reducing the cache size. --- indra/llcommon/llqueuedthread.cpp | 1 + indra/newview/lltexturecache.cpp | 58 ++++++++++++++++++++++----------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index e7ad571a90..eacbbb3ee0 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -96,6 +96,7 @@ void LLQueuedThread::shutdown() if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS) { ++active_count; + req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest } req->deleteRequest(); } diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 9be342c424..2e2f342cca 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -834,9 +834,9 @@ bool LLTextureCache::updateTextureEntryList(const LLUUID& id, S32 bodysize) S32 idx = openAndReadEntry(id, entry, false); if (idx < 0) { - // TODO: change to llwarns - llerrs << "Failed to open entry: " << id << llendl; - removeFromCache(id); + llwarns << "Failed to open entry: " << id << llendl; + removeHeaderCacheEntry(id); + LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); return false; } else if (oldbodysize != entry.mBodySize) @@ -1212,9 +1212,9 @@ void LLTextureCache::readHeaderCache() if (num_entries) { U32 empty_entries = 0; - typedef std::pair lru_data_t; + typedef std::pair lru_data_t; std::set lru; - std::vector purge_list; + std::vector purge_list; for (U32 i=0; i 0) { if (entry.mBodySize > entry.mImageSize) { // Shouldn't happen, failsafe only llwarns << "Bad entry: " << i << ": " << id << ": BodySize: " << entry.mBodySize << llendl; - purge_list.push_back(id); + purge_list.push_back(i); } } } @@ -1243,6 +1243,7 @@ void LLTextureCache::readHeaderCache() // Special case: cache size was reduced, need to remove entries // Note: After we prune entries, we will call this again and create the LRU U32 entries_to_purge = (num_entries-empty_entries) - sCacheMaxEntries; + llinfos << "Texture Cache Entries: " << num_entries << " Max: " << sCacheMaxEntries << " Empty: " << empty_entries << " Purging: " << entries_to_purge << llendl; if (entries_to_purge > 0) { for (std::set::iterator iter = lru.begin(); iter != lru.end(); ++iter) @@ -1252,13 +1253,17 @@ void LLTextureCache::readHeaderCache() break; } } + llassert_always(entries_to_purge <= 0); + llassert_always(purge_list.size() == entries_to_purge); } else { S32 lru_entries = (S32)((F32)sCacheMaxEntries * TEXTURE_CACHE_LRU_SIZE); for (std::set::iterator iter = lru.begin(); iter != lru.end(); ++iter) { - mLRU.insert(iter->second); + S32 idx = iter->second; + const LLUUID& id = entries[idx].mID; + mLRU.insert(id); // llinfos << "LRU: " << iter->first << " : " << iter->second << llendl; if (--lru_entries <= 0) break; @@ -1267,9 +1272,14 @@ void LLTextureCache::readHeaderCache() if (purge_list.size() > 0) { - for (std::vector::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) + for (std::vector::iterator iter = purge_list.begin(); iter != purge_list.end(); ++iter) { - removeFromCache(*iter); + S32 idx = *iter; + const LLUUID& id = entries[idx].mID; + entries[idx].mImageSize = -1; // set cached entry size to -1 + bool res = removeHeaderCacheEntry(id); // sets entry size on disk to -1 + llassert_always(res); + LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); } // If we removed any entries, we need to rebuild the entries list, // write the header, and call this again @@ -1307,6 +1317,7 @@ void LLTextureCache::purgeAllTextures(bool purge_directories) for (S32 i=0; i<16; i++) { std::string dirname = mTexturesDirName + delem + subdirs[i]; + llinfos << "Deleting files in directory: " << dirname << llendl; gDirUtilp->deleteFilesInDir(dirname,mask); if (purge_directories) { @@ -1624,24 +1635,20 @@ void LLTextureCache::addCompleted(Responder* responder, bool success) ////////////////////////////////////////////////////////////////////////////// // Called from MAIN thread (endWork()) - +// Ensuere that mHeaderMutex is locked first! bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) { - if (!mReadOnly) + Entry entry; + S32 idx = openAndReadEntry(id, entry, false); + if (idx >= 0) { - LLMutexLock lock(&mHeaderMutex); - Entry entry; - S32 idx = openAndReadEntry(id, entry, false); - if (idx >= 0) - { - entry.mImageSize = -1; - entry.mBodySize = 0; - writeEntryAndClose(idx, entry); - mFreeList.insert(idx); - mHeaderIDMap.erase(id); - mTexturesSizeMap.erase(id); - return true; - } + entry.mImageSize = -1; + entry.mBodySize = 0; + writeEntryAndClose(idx, entry); + mFreeList.insert(idx); + mHeaderIDMap.erase(id); + mTexturesSizeMap.erase(id); + return true; } return false; } @@ -1651,6 +1658,7 @@ void LLTextureCache::removeFromCache(const LLUUID& id) //llwarns << "Removing texture from cache: " << id << llendl; if (!mReadOnly) { + LLMutexLock lock(&mHeaderMutex); removeHeaderCacheEntry(id); LLAPRFile::remove(getTextureFileName(id), getLocalAPRFilePool()); } -- cgit v1.2.3 From 9e11d70225d3e53e2ee31304c4930f01939fe1c3 Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Sat, 14 Nov 2009 18:12:18 +0200 Subject: Fixed major bug EXT-2316 "Insert the option "pay" in the profile": - Added menu item according to Communications design spec in section 4.1.2.1. --HG-- branch : product-engine --- indra/newview/llpanelavatar.cpp | 25 ++++++++++++++++++++++ indra/newview/llpanelavatar.h | 12 +++++++++-- .../skins/default/xui/en/menu_profile_overflow.xml | 15 +++++++++++++ .../newview/skins/default/xui/en/panel_profile.xml | 20 ++++++++++++----- 4 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 indra/newview/skins/default/xui/en/menu_profile_overflow.xml diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 3b54f1546e..f0aa189b7f 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -41,6 +41,7 @@ #include "llimview.h" #include "lltexteditor.h" #include "lltexturectrl.h" +#include "lltoggleablemenu.h" #include "lltooldraganddrop.h" #include "llscrollcontainer.h" #include "llavatariconctrl.h" @@ -333,8 +334,14 @@ BOOL LLPanelAvatarProfile::postBuild() childSetCommitCallback("im",(boost::bind(&LLPanelAvatarProfile::onIMButtonClick,this)),NULL); childSetCommitCallback("call",(boost::bind(&LLPanelAvatarProfile::onCallButtonClick,this)),NULL); childSetCommitCallback("teleport",(boost::bind(&LLPanelAvatarProfile::onTeleportButtonClick,this)),NULL); + childSetCommitCallback("overflow_btn", boost::bind(&LLPanelAvatarProfile::onOverflowButtonClicked, this), NULL); childSetCommitCallback("share",(boost::bind(&LLPanelAvatarProfile::onShareButtonClick,this)),NULL); + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + registrar.add("Profile.Pay", boost::bind(&LLPanelAvatarProfile::pay, this)); + + mProfileMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_profile_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + LLTextureCtrl* pic = getChild("2nd_life_pic"); pic->setFallbackImageName("default_profile_picture.j2c"); @@ -513,6 +520,11 @@ void LLPanelAvatarProfile::fillAccountStatus(const LLAvatarData* avatar_data) childSetValue("acc_status_text", caption_text); } +void LLPanelAvatarProfile::pay() +{ + LLAvatarActions::pay(getAvatarId()); +} + void LLPanelAvatarProfile::onUrlTextboxClicked(const std::string& url) { LLWeb::loadURL(url); @@ -552,6 +564,19 @@ void LLPanelAvatarProfile::onShareButtonClick() //*TODO not implemented } +void LLPanelAvatarProfile::onOverflowButtonClicked() +{ + if (!mProfileMenu->toggleVisibility()) + return; + + LLView* btn = getChild("overflow_btn"); + LLRect rect = btn->getRect(); + + mProfileMenu->updateParent(LLMenuGL::sMenuContainer); + mProfileMenu->setButtonRect(btn->getLocalRect(), btn); + LLMenuGL::showPopup(this, mProfileMenu, rect.mRight, rect.mTop); +} + ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index ae0b8e9844..a0caf0c915 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -38,6 +38,7 @@ class LLComboBox; class LLLineEditor; +class LLToggleableMenu; enum EOnlineStatus { @@ -160,12 +161,17 @@ protected: * Fills Avatar's online status. */ virtual void fillOnlineStatus(const LLAvatarData* avatar_data); - + /** * Fills account status. */ virtual void fillAccountStatus(const LLAvatarData* avatar_data); + /** + * Opens "Pay Resident" dialog. + */ + void pay(); + void onUrlTextboxClicked(const std::string& url); void onHomepageTextboxClicked(); void onAddFriendButtonClick(); @@ -173,10 +179,12 @@ protected: void onCallButtonClick(); void onTeleportButtonClick(); void onShareButtonClick(); + void onOverflowButtonClicked(); private: - std::string mGroups; + std::string mGroups; + LLToggleableMenu* mProfileMenu; }; /** diff --git a/indra/newview/skins/default/xui/en/menu_profile_overflow.xml b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml new file mode 100644 index 0000000000..7b52fecef7 --- /dev/null +++ b/indra/newview/skins/default/xui/en/menu_profile_overflow.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml index 0f5e96416d..5110b6b2ef 100644 --- a/indra/newview/skins/default/xui/en/panel_profile.xml +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -283,7 +283,7 @@ mouse_opaque="false" name="add_friend" top="5" - width="75" /> + width="76" /> + width="18"> + + -- cgit v1.2.3 From aba8b04cfc6763ee565a5ae9929e8be044272b08 Mon Sep 17 00:00:00 2001 From: Dmitry Oleshko Date: Mon, 16 Nov 2009 18:51:54 +0200 Subject: fix of a normal bug (EXT-2448) [BSI] Notification toasts should resize when text is to long to be displayed A maximum number of characters for textbox/texteditor could be set only through XML. In case when a corresponding attribute was absent - the maximun number was set to 255, and there were no chance (no function) to change it. So in this fix such a function was added. --HG-- branch : product-engine --- indra/llui/lltextbase.h | 1 + indra/newview/lltoastnotifypanel.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 70d78c77cd..c376a73615 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -139,6 +139,7 @@ public: // TODO: add optional style parameter virtual void setText(const LLStringExplicit &utf8str , const LLStyle::Params& input_params = LLStyle::Params()); // uses default style virtual std::string getText() const; + void setMaxTextLength(S32 length) { mMaxTextByteLength = length; } // wide-char versions void setWText(const LLWString& text); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 0c23947a8c..48b68e4292 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -128,6 +128,7 @@ mAddedDefaultBtn(false) // *TODO: magic numbers(???) - copied from llnotify.cpp(250) const S32 MAX_LENGTH = 512 + 20 + DB_FIRST_NAME_BUF_SIZE + DB_LAST_NAME_BUF_SIZE + DB_INV_ITEM_NAME_BUF_SIZE; + mTextBox->setMaxTextLength(MAX_LENGTH); mTextBox->setVisible(TRUE); mTextBox->setValue(notification->getMessage()); -- cgit v1.2.3 From 211529eee9a4cbb36961af75e94af73da920d08d Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Mon, 16 Nov 2009 11:54:53 -0500 Subject: re-adding "make outfit button" the "make outfit" button in the appearance editor was accidentally removed (merge issue). Re-adding the XML tag for the button to floater_customize.xml Reviewed by Bigpapi --- indra/newview/skins/default/xui/en/floater_customize.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml index 6c4f10e61e..9d2a811d9f 100644 --- a/indra/newview/skins/default/xui/en/floater_customize.xml +++ b/indra/newview/skins/default/xui/en/floater_customize.xml @@ -3379,6 +3379,16 @@ scratch and wear it. layout="topleft" name="panel_list" /> +