From 38115eb90b1760025ee299a167f6a9a2311f59ab Mon Sep 17 00:00:00 2001 From: Dmitry Zaporozhan Date: Thu, 12 Nov 2009 12:15:32 +0200 Subject: Fixed path to image Generic_Object_Small --HG-- branch : product-engine --- indra/newview/skins/default/textures/textures.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 0e533b1c0e..508ae68975 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -117,7 +117,7 @@ - + -- cgit v1.2.3 From fed26cf76ebf401decc4e3fb2faa7b5f822bb588 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 17 Nov 2009 15:00:25 -0500 Subject: EXT-2568 : Reset Current Look string if wearing from non-outfit If you wear a category, then the current look string on the appearance sidepanel gets set back to NULL. --HG-- branch : avatar-pipeline --- indra/newview/llappearancemgr.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 043f6f37bf..71cd6faecc 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -536,6 +536,7 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) linkAll(cof, obj_items, link_waiter); linkAll(cof, gest_items, link_waiter); + LLSidepanelAppearance* panel_appearance = dynamic_cast(LLSideTray::getInstance()->getPanel("sidepanel_appearance")); // Add link to outfit if category is an outfit. LLViewerInventoryCategory* catp = gInventory.getCategory(category); if (!append && catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT) @@ -544,13 +545,18 @@ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append) LLAssetType::AT_LINK_FOLDER, link_waiter); // Update the current outfit name of the appearance sidepanel. - LLSidepanelAppearance* panel_appearance = dynamic_cast(LLSideTray::getInstance()->getPanel("sidepanel_appearance")); if (panel_appearance) { panel_appearance->refreshCurrentOutfitName(catp->getName()); } } - + else + { + if (panel_appearance) + { + panel_appearance->refreshCurrentOutfitName(""); + } + } } void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder, bool append) -- cgit v1.2.3 From 08cbeea3c72be69137b7ca7d4a95cc7d80fc176e Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 17 Nov 2009 15:03:14 -0500 Subject: EXT-2583 : Some sidepanel inventory folders appear blank Starting sidepanel inventory folders as open by default. Also did some minor syntactic cleanup on the folder filter iterators. --HG-- branch : avatar-pipeline --- indra/newview/llfolderviewitem.cpp | 40 ++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index bf74c5c936..1096f25f0c 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -1253,6 +1253,10 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // filter self only on first pass through LLFolderViewItem::filter( filter ); } + if (mDontShowInHierarchy) + { + setOpen(); + } } if (getRoot()->getDebugFilters()) @@ -1286,9 +1290,10 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // now query children for (folders_t::iterator iter = mFolders.begin(); - iter != mFolders.end();) + iter != mFolders.end(); + ++iter) { - folders_t::iterator fit = iter++; + LLFolderViewFolder* folder = (*iter); // have we run out of iterations this frame? if (filter.getFilterCount() < 0) { @@ -1298,15 +1303,15 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) // mMostFilteredDescendantGeneration might have been reset // in which case we need to update it even for folders that // don't need to be filtered anymore - if ((*fit)->getCompletedFilterGeneration() >= filter_generation) + if (folder->getCompletedFilterGeneration() >= filter_generation) { // track latest generation to pass any child items - if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter.getMinRequiredGeneration())) + if (folder->getFiltered() || folder->hasFilteredDescendants(filter.getMinRequiredGeneration())) { mMostFilteredDescendantGeneration = filter_generation; if (getRoot()->needsAutoSelect() && autoopen_folders) { - (*fit)->setOpenArrangeRecursively(TRUE); + folder->setOpenArrangeRecursively(TRUE); } } // just skip it, it has already been filtered @@ -1314,48 +1319,49 @@ void LLFolderViewFolder::filter( LLInventoryFilter& filter) } // update this folders filter status (and children) - (*fit)->filter( filter ); + folder->filter( filter ); // track latest generation to pass any child items - if ((*fit)->getFiltered() || (*fit)->hasFilteredDescendants(filter_generation)) + if (folder->getFiltered() || folder->hasFilteredDescendants(filter_generation)) { mMostFilteredDescendantGeneration = filter_generation; if (getRoot()->needsAutoSelect() && autoopen_folders) { - (*fit)->setOpenArrangeRecursively(TRUE); + folder->setOpenArrangeRecursively(TRUE); } } } for (items_t::iterator iter = mItems.begin(); - iter != mItems.end();) + iter != mItems.end(); + ++iter) { - items_t::iterator iit = iter++; + LLFolderViewItem* item = (*iter); if (filter.getFilterCount() < 0) { break; } - if ((*iit)->getLastFilterGeneration() >= filter_generation) + if (item->getLastFilterGeneration() >= filter_generation) { - if ((*iit)->getFiltered()) + if (item->getFiltered()) { mMostFilteredDescendantGeneration = filter_generation; } continue; } - if ((*iit)->getLastFilterGeneration() >= must_pass_generation && - !(*iit)->getFiltered(must_pass_generation)) + if (item->getLastFilterGeneration() >= must_pass_generation && + !item->getFiltered(must_pass_generation)) { // failed to pass an earlier filter that was a subset of the current one // go ahead and flag this item as done - (*iit)->setFiltered(FALSE, filter_generation); + item->setFiltered(FALSE, filter_generation); continue; } - (*iit)->filter( filter ); + item->filter( filter ); - if ((*iit)->getFiltered(filter.getMinRequiredGeneration())) + if (item->getFiltered(filter.getMinRequiredGeneration())) { mMostFilteredDescendantGeneration = filter_generation; } -- cgit v1.2.3 From 2b0a997b13de15c7aae009b52d7353c97e1781f3 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Tue, 17 Nov 2009 15:06:27 -0500 Subject: Small fix for updating enabled state of Wear/Edit buttons. --HG-- branch : avatar-pipeline --- indra/newview/llpaneloutfitsinventory.cpp | 4 ++++ indra/newview/llsidepanelappearance.cpp | 1 + 2 files changed, 5 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 5ad9bf056e..c4bde369db 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -148,12 +148,16 @@ void LLPanelOutfitsInventory::onNew() { const std::string& outfit_name = LLViewerFolderType::lookupNewCategoryName(LLFolderType::FT_OUTFIT); LLUUID outfit_folder = gAgentWearables.makeNewOutfitLinks(outfit_name); + /* getRootFolder()->setSelectionByID(outfit_folder, TRUE); getRootFolder()->setNeedsAutoRename(TRUE); + getRootFolder()->startRenamingSelectedItem(); + */ } void LLPanelOutfitsInventory::onSelectionChange(const std::deque &items, BOOL user_action) { + updateListCommands(); updateParent(); } diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index aeab3e2876..28c06b41e0 100644 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -140,6 +140,7 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) { fetchInventory(); refreshCurrentOutfitName(); + updateVerbs(); if(key.size() == 0) return; -- cgit v1.2.3 From 815f336a157cc33233633deed66634195d3dc552 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Wed, 18 Nov 2009 11:23:59 -0500 Subject: For EXT-2574, EXT-2577: remove from outfit now enforces mandatory body parts, teen underthings --HG-- branch : avatar-pipeline --- indra/newview/llinventorybridge.cpp | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 2d8b058ed8..aef412d24a 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4294,32 +4294,37 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ { for(i = 0; i < wearable_count; ++i) { - if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) ) + LLViewerInventoryItem *item = item_array.get(i); + if (item->getType() == LLAssetType::AT_BODYPART) + continue; + if (gAgent.isTeen() && item->isWearableType() && + (item->getWearableType() == WT_UNDERPANTS || item->getWearableType() == WT_UNDERSHIRT)) + continue; + if( gAgentWearables.isWearingItem (item->getLinkedUUID()) ) { - LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(), - item_array.get(i)->getName(), - item_array.get(i)->getType(), + LLWearableList::instance().getAsset(item->getAssetUUID(), + item->getName(), + item->getType(), LLWearableBridge::onRemoveFromAvatarArrived, - new OnRemoveStruct(item_array.get(i)->getUUID())); - + new OnRemoveStruct(item->getLinkedUUID())); } } } - if (obj_count > 0) { for(i = 0; i < obj_count; ++i) { + LLViewerInventoryItem *obj_item = obj_item_array.get(i); gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv); gMessageSystem->nextBlockFast(_PREHASH_ObjectData ); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() ); + gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item->getLinkedUUID() ); gMessageSystem->sendReliable( gAgent.getRegion()->getHost() ); // this object might have been selected, so let the selection manager know it's gone now - LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID()); + LLViewerObject *found_obj = gObjectList.findObject( obj_item->getLinkedUUID()); if (found_obj) { LLSelectMgr::getInstance()->remove(found_obj); @@ -4331,10 +4336,11 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_ { for(i = 0; i < gest_count; ++i) { - if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) ) + LLViewerInventoryItem *gest_item = gest_item_array.get(i); + if ( LLGestureManager::instance().isGestureActive( gest_item->getLinkedUUID()) ) { - LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() ); - gInventory.updateItem( gest_item_array.get(i) ); + LLGestureManager::instance().deactivateGesture( gest_item->getLinkedUUID() ); + gInventory.updateItem( gest_item ); gInventory.notifyObservers(); } -- cgit v1.2.3 From 0c95f8bf30bc6ec9835c5a298bf27115a2a92047 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 19 Nov 2009 12:03:11 -0500 Subject: For EXT-2623 - object missing wearables and attachments on initial login --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 57 ++++++++++++++++++++++++++++++++--- indra/newview/llinventoryobserver.cpp | 3 +- 2 files changed, 55 insertions(+), 5 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 6b2033fc6f..e78ea88b94 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2196,11 +2196,48 @@ void LLInitialWearablesFetch::processContents() delete this; } +class LLFetchAndLinkObserver: public LLInventoryFetchObserver +{ +public: + LLFetchAndLinkObserver(LLInventoryFetchObserver::item_ref_t& ids): + m_ids(ids) + { + llwarns << "LLFetchAndLinkObserver" << llendl; + } + ~LLFetchAndLinkObserver() + { + llwarns << "~LLFetchAndLinkObserver" << llendl; + } + virtual void done() + { + gInventory.removeObserver(this); + // Link to all fetched items in COF. + for (LLInventoryFetchObserver::item_ref_t::iterator it = m_ids.begin(); + it != m_ids.end(); + ++it) + { + LLUUID id = *it; + LLViewerInventoryItem *item = gInventory.getItem(*it); + if (!item) + { + llwarns << "LLFetchAndLinkObserver fetch failed!" << llendl; + continue; + } + link_inventory_item(gAgent.getID(), item->getLinkedUUID(), LLAppearanceManager::instance().getCOF(), item->getName(), + LLAssetType::AT_LINK, LLPointer(NULL)); + } + + } +private: + LLInventoryFetchObserver::item_ref_t m_ids; +}; + void LLInitialWearablesFetch::processWearablesMessage() { if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead. { - const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); + const LLUUID current_outfit_id = LLAppearanceManager::instance().getCOF(); + LLInventoryFetchObserver::item_ref_t ids; for (U8 i = 0; i < mAgentInitialWearables.size(); ++i) { // Populate the current outfit folder with links to the wearables passed in the message @@ -2209,9 +2246,7 @@ void LLInitialWearablesFetch::processWearablesMessage() if (wearable_data->mAssetID.notNull()) { #ifdef USE_CURRENT_OUTFIT_FOLDER - const std::string link_name = "WearableLink"; // Unimportant what this is named, it isn't exposed. - link_inventory_item(gAgent.getID(), wearable_data->mItemID, current_outfit_id, link_name, - LLAssetType::AT_LINK, LLPointer(NULL)); + ids.push_back(wearable_data->mItemID); #endif // Fetch the wearables LLWearableList::instance().getAsset(wearable_data->mAssetID, @@ -2225,6 +2260,20 @@ void LLInitialWearablesFetch::processWearablesMessage() << wearable_data->mItemID << " assetID " << wearable_data->mAssetID << llendl; } } + + // Need to fetch the inventory items for ids, then create links to them after they arrive. + LLFetchAndLinkObserver *fetcher = new LLFetchAndLinkObserver(ids); + fetcher->fetchItems(ids); + // If no items to be fetched, done will never be triggered. + // TODO: Change LLInventoryFetchObserver::fetchItems to trigger done() on this condition. + if (fetcher->isEverythingComplete()) + { + fetcher->done(); + } + else + { + gInventory.addObserver(fetcher); + } } else { diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index 3ccf593d27..e904fb6c92 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -115,7 +115,8 @@ void LLInventoryFetchObserver::changed(U32 mask) // BUG: This can cause done() to get called prematurely below. // This happens with the LLGestureInventoryFetchObserver that // loads gestures at startup. JC - it = mIncomplete.erase(it); + //it = mIncomplete.erase(it); + ++it; continue; } if(item->isComplete()) -- cgit v1.2.3 From ddb7ce417979cedf733dadb09dbe0edd49b9f4bc Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Thu, 19 Nov 2009 13:55:07 -0500 Subject: EXT-2601 edit appearance: label_min / label_max not translated strings are already in strings.xml, just had to actually translate the labels where they were being applied. Code reviewed by Bigpapi --HG-- branch : avatar-pipeline --- indra/newview/llscrollingpanelparam.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp index b5e55df1f5..32a915608e 100644 --- a/indra/newview/llscrollingpanelparam.cpp +++ b/indra/newview/llscrollingpanelparam.cpp @@ -86,9 +86,8 @@ LLScrollingPanelParam::LLScrollingPanelParam( const LLPanel::Params& panel_param childSetEnabled("param slider", mAllowModify); childSetCommitCallback("param slider", LLScrollingPanelParam::onSliderMoved, this); - // *TODO: Translate - std::string min_name = param->getMinDisplayName(); - std::string max_name = param->getMaxDisplayName(); + std::string min_name = LLTrans::getString(param->getMinDisplayName()); + std::string max_name = LLTrans::getString(param->getMaxDisplayName()); childSetValue("min param text", min_name); childSetValue("max param text", max_name); -- cgit v1.2.3 From 62ce5fa4628672c8f9b95faac2797ce82c59deed Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 19 Nov 2009 16:00:40 -0500 Subject: For EXT-2623 - object missing wearables and attachments on initial login --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 30 +++++++++++++++++++++++++----- indra/newview/llappearancemgr.cpp | 4 ++++ indra/newview/llinventoryobserver.cpp | 19 ++++++++++++++----- indra/newview/llinventoryobserver.h | 3 ++- 4 files changed, 45 insertions(+), 11 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index e78ea88b94..a93b0c1357 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2190,8 +2190,6 @@ void LLInitialWearablesFetch::processContents() else { processWearablesMessage(); - // Create links for attachments that may have arrived before the COF existed. - LLAppearanceManager::instance().linkRegisteredAttachments(); } delete this; } @@ -2200,7 +2198,8 @@ class LLFetchAndLinkObserver: public LLInventoryFetchObserver { public: LLFetchAndLinkObserver(LLInventoryFetchObserver::item_ref_t& ids): - m_ids(ids) + m_ids(ids), + LLInventoryFetchObserver(true) { llwarns << "LLFetchAndLinkObserver" << llendl; } @@ -2220,13 +2219,12 @@ public: LLViewerInventoryItem *item = gInventory.getItem(*it); if (!item) { - llwarns << "LLFetchAndLinkObserver fetch failed!" << llendl; + llwarns << "fetch failed!" << llendl; continue; } link_inventory_item(gAgent.getID(), item->getLinkedUUID(), LLAppearanceManager::instance().getCOF(), item->getName(), LLAssetType::AT_LINK, LLPointer(NULL)); } - } private: LLInventoryFetchObserver::item_ref_t m_ids; @@ -2261,6 +2259,28 @@ void LLInitialWearablesFetch::processWearablesMessage() } } + // Add all current attachments to the requested items as well. + LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if( avatar ) + { + for (LLVOAvatar::attachment_map_t::const_iterator iter = avatar->mAttachmentPoints.begin(); + iter != avatar->mAttachmentPoints.end(); ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + if (!attachment) continue; + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = (*attachment_iter); + if (!attached_object) continue; + const LLUUID& item_id = attached_object->getItemID(); + if (item_id.isNull()) continue; + ids.push_back(item_id); + } + } + } + // Need to fetch the inventory items for ids, then create links to them after they arrive. LLFetchAndLinkObserver *fetcher = new LLFetchAndLinkObserver(ids); fetcher->fetchItems(ids); diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 60c6061e96..bec70ce827 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -990,6 +990,10 @@ void LLAppearanceManager::registerAttachment(const LLUUID& item_id) gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); gInventory.notifyObservers(); } + else + { + llwarns << "missing item, can't link" << llendl; + } } else { diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp index e904fb6c92..06f4b36df3 100644 --- a/indra/newview/llinventoryobserver.cpp +++ b/indra/newview/llinventoryobserver.cpp @@ -112,11 +112,20 @@ void LLInventoryFetchObserver::changed(U32 mask) LLViewerInventoryItem* item = gInventory.getItem(*it); if(!item) { - // BUG: This can cause done() to get called prematurely below. - // This happens with the LLGestureInventoryFetchObserver that - // loads gestures at startup. JC - //it = mIncomplete.erase(it); - ++it; + if (mRetryIfMissing) + { + // BAP changed to skip these items, so we should keep retrying until they arrive. + // Did not make this the default behavior because of uncertainty about impact - + // could cause some observers that currently complete to wait forever. + ++it; + } + else + { + // BUG: This can cause done() to get called prematurely below. + // This happens with the LLGestureInventoryFetchObserver that + // loads gestures at startup. JC + it = mIncomplete.erase(it); + } continue; } if(item->isComplete()) diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h index 384e6292e8..3a083e913b 100644 --- a/indra/newview/llinventoryobserver.h +++ b/indra/newview/llinventoryobserver.h @@ -106,7 +106,7 @@ protected: class LLInventoryFetchObserver : public LLInventoryObserver { public: - LLInventoryFetchObserver() {} + LLInventoryFetchObserver(bool retry_if_missing = false): mRetryIfMissing(retry_if_missing) {} virtual void changed(U32 mask); typedef std::vector item_ref_t; @@ -116,6 +116,7 @@ public: virtual void done() = 0; protected: + bool mRetryIfMissing; item_ref_t mComplete; item_ref_t mIncomplete; }; -- cgit v1.2.3 From fae78349915a1f8603beb034166f8ea5c64dc5a6 Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Thu, 19 Nov 2009 17:36:13 -0500 Subject: cleanup: log file spam --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index a93b0c1357..6595e28622 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2160,7 +2160,6 @@ void LLLibraryOutfitsFetch::contentsDone(void) LLInitialWearablesFetch::~LLInitialWearablesFetch() { - llinfos << "~LLInitialWearablesFetch" << llendl; } // virtual @@ -2201,11 +2200,9 @@ public: m_ids(ids), LLInventoryFetchObserver(true) { - llwarns << "LLFetchAndLinkObserver" << llendl; } ~LLFetchAndLinkObserver() { - llwarns << "~LLFetchAndLinkObserver" << llendl; } virtual void done() { -- cgit v1.2.3 From ad86caf4790d45b0d7c6776c9f840e3023c52033 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Thu, 19 Nov 2009 17:56:30 -0500 Subject: EXT-2668 : Screwy logic for figuring out if a folder is removable EXT-2661 : "Remove From Outfit" on COF doesn't take off my outfit EXT-2662 : Can't delete a worn item link Cleaned up the whole "isItemRemovable" logic, and having folders figure this out recursively via children. Changed the isItemRemovable logic so that links aren't treated as worn for the purposes of deletion. --HG-- branch : avatar-pipeline --- indra/newview/llfolderviewitem.cpp | 16 +++++++ indra/newview/llfolderviewitem.h | 3 ++ indra/newview/llinventorybridge.cpp | 94 ++++++++++++++++++------------------- indra/newview/llinventorybridge.h | 2 - 4 files changed, 64 insertions(+), 51 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 1096f25f0c..41e3279795 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -2030,6 +2030,22 @@ void LLFolderViewFolder::openItem( void ) toggleOpen(); } +void LLFolderViewFolder::applyFunctorToChildren(LLFolderViewFunctor& functor) +{ + for (folders_t::iterator iter = mFolders.begin(); + iter != mFolders.end();) + { + folders_t::iterator fit = iter++; + functor.doItem((*fit)); + } + for (items_t::iterator iter = mItems.begin(); + iter != mItems.end();) + { + items_t::iterator iit = iter++; + functor.doItem((*iit)); + } +} + void LLFolderViewFolder::applyFunctorRecursively(LLFolderViewFunctor& functor) { functor.doFolder(this); diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 30387812a6..f6264ec968 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -501,6 +501,9 @@ public: void applyFunctorRecursively(LLFolderViewFunctor& functor); virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); + // Just apply this functor to the folder's immediate children. + void applyFunctorToChildren(LLFolderViewFunctor& functor); + virtual void openItem( void ); virtual BOOL addItem(LLFolderViewItem* item); virtual BOOL addFolder( LLFolderViewFolder* folder); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index bb8b45ef11..578cf7bebc 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -171,16 +171,33 @@ time_t LLInvFVBridge::getCreationDate() const return 0; } -// Can be destoryed (or moved to trash) +// Can be destroyed (or moved to trash) BOOL LLInvFVBridge::isItemRemovable() { - LLInventoryModel* model = getInventoryModel(); - if(!model) return FALSE; - if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) + const LLInventoryModel* model = getInventoryModel(); + if(!model) + { + return FALSE; + } + if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID())) + { + return FALSE; + } + const LLInventoryObject *obj = model->getItem(mUUID); + if (obj && obj->getIsLinkType()) { return TRUE; } - return FALSE; + if (gAgentWearables.isWearingItem(mUUID)) + { + return FALSE; + } + const LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); + if (avatar && avatar->isWearingAttachment(mUUID)) + { + return FALSE; + } + return TRUE; } // Can be moved to another folder @@ -1303,6 +1320,23 @@ void LLFolderBridge::selectItem() } +// Iterate through a folder's children to determine if +// all the children are removable. +class LLIsItemRemovable : public LLFolderViewFunctor +{ +public: + LLIsItemRemovable() : mPassed(TRUE) {} + virtual void doFolder(LLFolderViewFolder* folder) + { + mPassed &= folder->getListener()->isItemRemovable(); + } + virtual void doItem(LLFolderViewItem* item) + { + mPassed &= item->getListener()->isItemRemovable(); + } + BOOL mPassed; +}; + // Can be destroyed (or moved to trash) BOOL LLFolderBridge::isItemRemovable() { @@ -1334,41 +1368,17 @@ BOOL LLFolderBridge::isItemRemovable() return FALSE; } - LLInventoryModel::cat_array_t descendent_categories; - LLInventoryModel::item_array_t descendent_items; - gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE ); - - S32 i; - for( i = 0; i < descendent_categories.count(); i++ ) + LLInventoryPanel* panel = dynamic_cast(mInventoryPanel.get()); + LLFolderViewFolder* folderp = dynamic_cast(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL); + if (folderp) { - LLInventoryCategory* category = descendent_categories[i]; - if(LLFolderType::lookupIsProtectedType(category->getPreferredType())) + LLIsItemRemovable folder_test; + folderp->applyFunctorToChildren(folder_test); + if (!folder_test.mPassed) { return FALSE; } } - - for( i = 0; i < descendent_items.count(); i++ ) - { - LLInventoryItem* item = descendent_items[i]; - if( (item->getType() == LLAssetType::AT_CLOTHING) || - (item->getType() == LLAssetType::AT_BODYPART) ) - { - if(gAgentWearables.isWearingItem(item->getUUID())) - { - return FALSE; - } - } - else - if( item->getType() == LLAssetType::AT_OBJECT ) - { - if(avatar->isWearingAttachment(item->getUUID())) - { - return FALSE; - } - } - } - return TRUE; } @@ -3772,14 +3782,6 @@ LLItemBridge(inventory, uuid), mInvType(type) mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE; } -BOOL LLObjectBridge::isItemRemovable() -{ - LLVOAvatarSelf* avatar = gAgent.getAvatarObject(); - if(!avatar) return FALSE; - if(avatar->isWearingAttachment(mUUID)) return FALSE; - return LLInvFVBridge::isItemRemovable(); -} - LLUIImagePtr LLObjectBridge::getIcon() const { return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject ); @@ -4299,12 +4301,6 @@ BOOL LLWearableBridge::renameItem(const std::string& new_name) return LLItemBridge::renameItem(new_name); } -BOOL LLWearableBridge::isItemRemovable() -{ - if (gAgentWearables.isWearingItem(mUUID)) return FALSE; - return LLInvFVBridge::isItemRemovable(); -} - std::string LLWearableBridge::getLabelSuffix() const { if( gAgentWearables.isWearingItem( mUUID ) ) diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 49e64ebdde..7534548894 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -508,7 +508,6 @@ public: virtual LLFontGL::StyleFlags getLabelStyle() const; virtual std::string getLabelSuffix() const; virtual void buildContextMenu(LLMenuGL& menu, U32 flags); - virtual BOOL isItemRemovable(); virtual BOOL renameItem(const std::string& new_name); LLInventoryObject* getObject() const; @@ -546,7 +545,6 @@ public: virtual void openItem(); virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual std::string getLabelSuffix() const; - virtual BOOL isItemRemovable(); virtual BOOL renameItem(const std::string& new_name); static void onWearOnAvatar( void* userdata ); // Access to wearOnAvatar() from menu -- cgit v1.2.3 From 56a861138b451ab7f7c20c6c461a6243edca8069 Mon Sep 17 00:00:00 2001 From: Loren Shih Date: Thu, 19 Nov 2009 21:57:14 -0500 Subject: EXT-2675 : Folder that contains baseitems for COF doesn't load on first click EXT-2456 : Usability: Inventory > Clothing > context menu not intuitive RightClickFetchInventoryObserver now works correctly to update menu FetchInventoryDescendents now triggers notifyObservers properly Fixed up gInventory.notifyObservers logic --HG-- branch : avatar-pipeline --- indra/newview/llappviewer.cpp | 2 +- indra/newview/llinventorybridge.cpp | 5 +++++ indra/newview/llinventorymodel.cpp | 27 +++++++++++++++------------ indra/newview/llinventorymodel.h | 9 ++++++--- 4 files changed, 27 insertions(+), 16 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index a5ca06ce30..af17286c9c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -3534,7 +3534,7 @@ void LLAppViewer::idle() gEventNotifier.update(); gIdleCallbacks.callFunctions(); - gInventory.notifyObservers(); + gInventory.idleNotifyObservers(); } if (gDisconnected) diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 578cf7bebc..c8540bdbd2 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -492,6 +492,7 @@ void hide_context_entries(LLMenuGL& menu, } else { + (*itor)->setVisible(TRUE); for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2) { if (*itor2 == name) @@ -2359,6 +2360,10 @@ void LLFolderBridge::folderOptionsMenu() mItems.push_back(std::string("Remove From Outfit")); } hide_context_entries(*mMenu, mItems, disabled_items); + + // Reposition the menu, in case we're adding items to an existing menu. + mMenu->needsArrange(); + mMenu->arrangeAndClear(); } BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index fbaab385fe..9e37c5be38 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1118,9 +1118,16 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const return mObservers.find(observer) != mObservers.end(); } -// Call this method when it's time to update everyone on a new state, -// by default, the inventory model will not update observers -// automatically. +void LLInventoryModel::idleNotifyObservers() +{ + if (mModifyMask == LLInventoryObserver::NONE && (mChangedItemIDs.size() == 0)) + { + return; + } + notifyObservers(""); +} + +// Call this method when it's time to update everyone on a new state. // The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328] void LLInventoryModel::notifyObservers(const std::string service_name) { @@ -1133,13 +1140,6 @@ void LLInventoryModel::notifyObservers(const std::string service_name) return; } - if ((mModifyMask == LLInventoryObserver::NONE) && (service_name == "")) - { - mModifyMask = LLInventoryObserver::NONE; - mChangedItemIDs.clear(); - return; - } - mIsNotifyObservers = TRUE; for (observer_list_t::iterator iter = mObservers.begin(); iter != mObservers.end(); ) @@ -3308,8 +3308,7 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id); if(agent_id != gAgent.getID()) { - llwarns << "Got a UpdateInventoryItem for the wrong agent." - << llendl; + llwarns << "Got a UpdateInventoryItem for the wrong agent." << llendl; return; } LLUUID parent_id; @@ -3320,6 +3319,7 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) msg->getS32("AgentData", "Version", version); S32 descendents; msg->getS32("AgentData", "Descendents", descendents); + S32 i; S32 count = msg->getNumberOfBlocksFast(_PREHASH_FolderData); LLPointer tcategory = new LLViewerInventoryCategory(owner_id); @@ -3349,6 +3349,9 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**) { cat->setVersion(version); cat->setDescendentCount(descendents); + // Get this UUID on the changed list so that whatever's listening for it + // will get triggered. + gInventory.addChangedMask(LLInventoryObserver::INTERNAL, cat->getUUID()); } gInventory.notifyObservers(); } diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index da12dbdf7f..50f54cb842 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -252,9 +252,12 @@ public: // multiple trash can bug. 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 - // observers automatically. + // This gets called by the idle loop. It only updates if new + // state is detected. Call notifyObservers() manually to update + // regardless of whether state change has been indicated. + void idleNotifyObservers(); + + // Call this method to explicitly update everyone on a new state. // The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328] void notifyObservers(const std::string service_name=""); -- cgit v1.2.3 From 3c4a98ff3cdc756918a2dea0c5d3dd58aa08bca3 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Fri, 20 Nov 2009 17:14:50 +0200 Subject: Work on normal task EXT-2640 (Create a tabbed IM multifloater) - initial commit: added xml file and base implementation of the tabbed IM multifloater --HG-- branch : product-engine --- indra/newview/CMakeLists.txt | 2 + indra/newview/llimfloatercontainer.cpp | 97 ++++++++++++++++++++++ indra/newview/llimfloatercontainer.h | 61 ++++++++++++++ indra/newview/llviewerfloaterreg.cpp | 2 + .../skins/default/xui/en/floater_im_container.xml | 38 +++++++++ 5 files changed, 200 insertions(+) create mode 100644 indra/newview/llimfloatercontainer.cpp create mode 100644 indra/newview/llimfloatercontainer.h create mode 100644 indra/newview/skins/default/xui/en/floater_im_container.xml (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e7458529be..e7ce6a8fbd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -239,6 +239,7 @@ set(viewer_SOURCE_FILES llhudtext.cpp llhudview.cpp llimfloater.cpp + llimfloatercontainer.cpp llimhandler.cpp llimpanel.cpp llimview.cpp @@ -737,6 +738,7 @@ set(viewer_HEADER_FILES llhudtext.h llhudview.h llimfloater.h + llimfloatercontainer.h llimpanel.h llimview.h llinspect.h diff --git a/indra/newview/llimfloatercontainer.cpp b/indra/newview/llimfloatercontainer.cpp new file mode 100644 index 0000000000..94017526c8 --- /dev/null +++ b/indra/newview/llimfloatercontainer.cpp @@ -0,0 +1,97 @@ +/** + * @file llimfloatercontainer.cpp + * @brief Multifloater containing active IM sessions in separate tab container tabs + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#include "llviewerprecompiledheaders.h" + +#include "llimfloatercontainer.h" + +// TODO: mantipov: replace with floater_im_session +#include "llimpanel.h" + +// +// LLIMFloaterContainer +// +LLIMFloaterContainer::LLIMFloaterContainer(const LLSD& seed) +: LLMultiFloater(seed), + mActiveVoiceFloater(NULL) +{ + mAutoResize = FALSE; +} + +LLIMFloaterContainer::~LLIMFloaterContainer() +{ +} + +BOOL LLIMFloaterContainer::postBuild() +{ + // TODO: mantipov: verify if it is needed + mTabContainer->lockTabs(); + return TRUE; +} + +void LLIMFloaterContainer::onOpen(const LLSD& key) +{ + // TODO: mantipov: verify if it is needed + if (key.isDefined()) + { + LLFloaterIMPanel* impanel = gIMMgr->findFloaterBySession(key.asUUID()); + if (impanel) + { + impanel->openFloater(); + } + } +} + +void LLIMFloaterContainer::addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainer::eInsertionPoint insertion_point) +{ + if(!floaterp) return; + + // already here + if (floaterp->getHost() == this) + { + openFloater(floaterp->getKey()); + return; + } + + LLMultiFloater::addFloater(floaterp, select_added_floater, insertion_point); + + // make sure active voice icon shows up for new tab + if (floaterp == mActiveVoiceFloater) + { + mTabContainer->setTabImage(floaterp, "active_voice_tab.tga"); + } +} + +// EOF diff --git a/indra/newview/llimfloatercontainer.h b/indra/newview/llimfloatercontainer.h new file mode 100644 index 0000000000..10cde56c6e --- /dev/null +++ b/indra/newview/llimfloatercontainer.h @@ -0,0 +1,61 @@ +/** + * @file llimfloatercontainer.h + * @brief Multifloater containing active IM sessions in separate tab container tabs + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLIMFLOATERCONTAINER_H +#define LL_LLIMFLOATERCONTAINER_H + +#include "llfloater.h" +#include "llmultifloater.h" + +class LLTabContainer; + +class LLIMFloaterContainer : public LLMultiFloater +{ +public: + LLIMFloaterContainer(const LLSD& seed); + virtual ~LLIMFloaterContainer(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onOpen(const LLSD& key); + + /*virtual*/ void addFloater(LLFloater* floaterp, + BOOL select_added_floater, + LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); + + static LLFloater* getCurrentVoiceFloater(); + +protected: + + LLFloater* mActiveVoiceFloater; +}; + +#endif // LL_LLIMFLOATERCONTAINER_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 7772f613f0..f84e3c9939 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -109,6 +109,7 @@ #include "llfloaterwhitelistentry.h" #include "llfloaterwindlight.h" #include "llfloaterworldmap.h" +#include "llimfloatercontainer.h" #include "llinspectavatar.h" #include "llinspectgroup.h" #include "llinspectobject.h" @@ -171,6 +172,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("im_container", "floater_im_container.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/skins/default/xui/en/floater_im_container.xml b/indra/newview/skins/default/xui/en/floater_im_container.xml new file mode 100644 index 0000000000..a1a0aee97b --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_im_container.xml @@ -0,0 +1,38 @@ + + + + + -- cgit v1.2.3 From 13a6077b780117be0fa3a054426d139ca1d35df9 Mon Sep 17 00:00:00 2001 From: Dmitry Zaporozhan Date: Fri, 20 Nov 2009 19:17:38 +0200 Subject: Implemented normal task EXT-2081 - Object IM chiclets art needs to be hooked up to LLDialog chiclets. Implemented LLDialog(LLScriptFloater) and Script Chiclets. --HG-- branch : product-engine --- indra/newview/CMakeLists.txt | 2 + indra/newview/llchiclet.cpp | 56 ++++ indra/newview/llchiclet.h | 34 +++ indra/newview/llimview.cpp | 2 +- indra/newview/llnotificationscripthandler.cpp | 51 +++- indra/newview/llscreenchannel.cpp | 4 +- indra/newview/llscriptfloater.cpp | 335 +++++++++++++++++++++ indra/newview/llscriptfloater.h | 114 +++++++ indra/newview/llviewerfloaterreg.cpp | 2 + indra/newview/llviewermessage.cpp | 10 + .../skins/default/xui/en/floater_script.xml | 19 ++ .../newview/skins/default/xui/en/notifications.xml | 23 +- 12 files changed, 634 insertions(+), 18 deletions(-) create mode 100644 indra/newview/llscriptfloater.cpp create mode 100644 indra/newview/llscriptfloater.h create mode 100644 indra/newview/skins/default/xui/en/floater_script.xml (limited to 'indra/newview') diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index e7458529be..8537c92ff7 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -364,6 +364,7 @@ set(viewer_SOURCE_FILES llremoteparcelrequest.cpp llsavedsettingsglue.cpp llscreenchannel.cpp + llscriptfloater.cpp llscrollingpanelparam.cpp llsearchcombobox.cpp llsearchhistory.cpp @@ -860,6 +861,7 @@ set(viewer_HEADER_FILES llrootview.h llsavedsettingsglue.h llscreenchannel.h + llscriptfloater.h llscrollingpanelparam.h llsearchcombobox.h llsearchhistory.h diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index caf6917d90..15c4c5f95d 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -43,6 +43,7 @@ #include "lllocalcliprect.h" #include "llmenugl.h" #include "lloutputmonitorctrl.h" +#include "llscriptfloater.h" #include "lltextbox.h" #include "llvoiceclient.h" #include "llvoicecontrolpanel.h" @@ -1392,3 +1393,58 @@ LLChicletSpeakerCtrl::LLChicletSpeakerCtrl(const Params&p) : LLOutputMonitorCtrl(p) { } + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLScriptChiclet::Params::Params() + : avatar_icon("avatar_icon") +{ + // *TODO Vadim: Get rid of hardcoded values. + rect(CHICLET_RECT); + name("dialog_chiclet"); + + avatar_icon.name("avatar_icon"); + avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + + avatar_icon.rect(CHICLET_ICON_RECT); + avatar_icon.mouse_opaque(false); +} + +LLScriptChiclet::LLScriptChiclet(const Params&p) + : LLIMChiclet(p) + , mChicletIconCtrl(NULL) +{ + mImage = LLUI::getUIImage("Generic_Object_Small"); +} + +void LLScriptChiclet::setSessionId(const LLUUID& session_id) +{ + setShowNewMessagesIcon( getSessionId() != session_id ); + + LLIMChiclet::setSessionId(session_id); + LLNotificationPtr notification = LLNotifications::getInstance()->find( + LLScriptFloaterManager::getInstance()->getNotificationId(session_id)); + if(notification) + { + setToolTip(notification->getSubstitutions()["TITLE"].asString()); + } +} + +void LLScriptChiclet::draw() +{ + mImage->draw(getLocalRect()); + LLIMChiclet::draw(); +} + +void LLScriptChiclet::onMouseDown() +{ + LLScriptFloaterManager::getInstance()->toggleScriptFloater(getSessionId()); +} + +BOOL LLScriptChiclet::handleMouseDown(S32 x, S32 y, MASK mask) +{ + onMouseDown(); + return LLChiclet::handleMouseDown(x, y, mask); +} diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index bb5dc1e550..a46f817c13 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -533,6 +533,40 @@ private: LLMenuGL* mPopupMenu; }; +class LLScriptChiclet : public LLIMChiclet +{ +public: + + struct Params : public LLInitParam::Block + { + Optional avatar_icon; + + Params(); + }; + + void setSessionId(const LLUUID& session_id); + + void setCounter(S32 counter){} + + S32 getCounter() { return 0; } + + void onMouseDown(); + + BOOL handleMouseDown(S32 x, S32 y, MASK mask); + + void draw(); + +protected: + + LLScriptChiclet(const Params&); + friend class LLUICtrlFactory; + +private: + + LLPointer mImage; + LLChicletAvatarIconCtrl* mChicletIconCtrl; +}; + /** * Implements Group chat chiclet. */ diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index dd78bb631f..b509fe4043 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -49,7 +49,7 @@ #include "llbottomtray.h" #include "llcallingcard.h" #include "llchat.h" -#include "llchiclet.h" +#include "llchiclet.h" #include "llresmgr.h" #include "llfloaterchat.h" #include "llfloaterchatterbox.h" diff --git a/indra/newview/llnotificationscripthandler.cpp b/indra/newview/llnotificationscripthandler.cpp index 70b86e8b97..84a8191375 100644 --- a/indra/newview/llnotificationscripthandler.cpp +++ b/indra/newview/llnotificationscripthandler.cpp @@ -38,6 +38,7 @@ #include "llviewercontrol.h" #include "llviewerwindow.h" #include "llnotificationmanager.h" +#include "llscriptfloater.h" using namespace LLNotificationsUI; @@ -90,25 +91,37 @@ bool LLScriptHandler::processNotification(const LLSD& notify) if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change") { - LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); - - LLToast::Params p; - p.notif_id = notification->getID(); - p.notification = notification; - p.panel = notify_box; - p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); - - LLScreenChannel* channel = dynamic_cast(mChannel); - if(channel) - channel->addToast(p); - - // send a signal to the counter manager - mNewNotificationSignal(); - + if("ScriptDialog" == notification->getName() || "ScriptDialogGroup" == notification->getName()) + { + LLScriptFloaterManager::getInstance()->onAddNotification(notification->getID()); + } + else + { + LLToastNotifyPanel* notify_box = new LLToastNotifyPanel(notification); + + LLToast::Params p; + p.notif_id = notification->getID(); + p.notification = notification; + p.panel = notify_box; + p.on_delete_toast = boost::bind(&LLScriptHandler::onDeleteToast, this, _1); + + LLScreenChannel* channel = dynamic_cast(mChannel); + if(channel) + { + channel->addToast(p); + } + + // send a signal to the counter manager + mNewNotificationSignal(); + } } else if (notify["sigtype"].asString() == "delete") { mChannel->killToastByNotificationID(notification->getID()); + if("ScriptDialog" == notification->getName()) + { + LLScriptFloaterManager::getInstance()->removeNotification(notification->getID()); + } } return true; } @@ -123,6 +136,14 @@ void LLScriptHandler::onDeleteToast(LLToast* toast) // send a signal to a listener to let him perform some action // in this case listener is a SysWellWindow and it will remove a corresponding item from its list mNotificationIDSignal(toast->getNotificationID()); + + LLNotificationPtr notification = LLNotifications::getInstance()->find(toast->getNotificationID()); + + if( notification && ("ScriptDialog" == notification->getName() + || "ScriptDialogGroup" == notification->getName()) ) + { + LLScriptFloaterManager::getInstance()->onRemoveNotification(notification->getID()); + } } //-------------------------------------------------------------------------- diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 81eb133b07..f033251831 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -46,6 +46,7 @@ #include "lldockablefloater.h" #include "llsyswellwindow.h" #include "llimfloater.h" +#include "llscriptfloater.h" #include @@ -698,7 +699,8 @@ void LLScreenChannel::updateShowToastsState() } // for IM floaters showed in a docked state - prohibit showing of ani toast - if(dynamic_cast(floater)) + if(dynamic_cast(floater) + || dynamic_cast(floater) ) { setShowToasts(!(floater->getVisible() && floater->isDocked())); if (!getShowToasts()) diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp new file mode 100644 index 0000000000..6fdde1df99 --- /dev/null +++ b/indra/newview/llscriptfloater.cpp @@ -0,0 +1,335 @@ +/** + * @file llscriptfloater.cpp + * @brief LLScriptFloater class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llscriptfloater.h" + +#include "llbottomtray.h" +#include "llchannelmanager.h" +#include "llchiclet.h" +#include "llfloaterreg.h" +#include "llscreenchannel.h" +#include "lltoastnotifypanel.h" +#include "llviewerwindow.h" + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLUUID notification_id_to_object_id(const LLUUID& notification_id) +{ + LLNotificationPtr notification = LLNotifications::getInstance()->find(notification_id); + if(notification) + { + return notification->getPayload()["object_id"].asUUID(); + } + return LLUUID::null; +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +LLScriptFloater::LLScriptFloater(const LLSD& key) +: LLTransientDockableFloater(NULL, true, key) +, mObjectId(key.asUUID()) +{ +} + +bool LLScriptFloater::toggle(const LLUUID& object_id) +{ + LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", object_id); + + // show existing floater + if(floater) + { + if(floater->getVisible()) + { + floater->setVisible(false); + return false; + } + else + { + floater->setVisible(TRUE); + floater->setFocus(TRUE); + return true; + } + } + else + { + show(object_id); + return true; + } +} + +LLScriptFloater* LLScriptFloater::show(const LLUUID& object_id) +{ + LLScriptFloater* floater = LLFloaterReg::showTypedInstance("script_floater", object_id); + floater->createForm(object_id); + + if (floater->getDockControl() == NULL) + { + LLChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet(object_id); + if (chiclet == NULL) + { + llerror("Dock chiclet for LLScriptFloater doesn't exist", 0); + } + else + { + LLBottomTray::getInstance()->getChicletPanel()->scrollToChiclet(chiclet); + } + + floater->setDockControl(new LLDockControl(chiclet, floater, floater->getDockTongue(), + LLDockControl::TOP, boost::bind(&LLScriptFloater::getAllowedRect, floater, _1))); + } + + return floater; +} + +void LLScriptFloater::getAllowedRect(LLRect& rect) +{ + rect = gViewerWindow->getWorldViewRectRaw(); +} + +void LLScriptFloater::createForm(const LLUUID& object_id) +{ + static const std::string PANEL_NAME = "_notification_panel_"; + + LLPanel* old_panel = findChild(PANEL_NAME); + if(old_panel) + { + removeChild(old_panel); + } + + LLNotificationPtr notification = LLNotifications::getInstance()->find( + LLScriptFloaterManager::getInstance()->getNotificationId(object_id)); + if(NULL == notification) + { + return; + } + LLToastNotifyPanel* panel = new LLToastNotifyPanel(notification); + panel->setName(PANEL_NAME); + addChild(panel); + + LLRect panel_rect; + + panel_rect = panel->getRect(); + panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight()); + reshape(panel_rect.getWidth(), panel_rect.getHeight()); + panel->setRect(panel_rect); + + LLRect toast_rect = getRect(); + toast_rect.setLeftTopAndSize(toast_rect.mLeft, toast_rect.mTop, panel_rect.getWidth(), panel_rect.getHeight() + getHeaderHeight()); + reshape(toast_rect.getWidth(), toast_rect.getHeight()); + setRect(toast_rect); +} + +void LLScriptFloater::onClose(bool app_quitting) +{ + LLScriptFloaterManager::getInstance()->closeScriptFloater(getObjectId()); + setObjectId(LLUUID::null); +} + +void LLScriptFloater::setDocked(bool docked, bool pop_on_undock /* = true */) +{ + LLTransientDockableFloater::setDocked(docked, pop_on_undock); + + updateToasts(); +} + +void LLScriptFloater::setVisible(BOOL visible) +{ + LLTransientDockableFloater::setVisible(visible); + + updateToasts(); +} + +void LLScriptFloater::updateToasts() +{ + using namespace LLNotificationsUI; + + // find channel + LLScreenChannel* channel = dynamic_cast(LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + // update notification channel state + if(channel) + { + channel->updateShowToastsState(); + } +} + +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// + +void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) +{ + // get scripted Object's ID + LLUUID object_id = notification_id_to_object_id(notification_id); + if(object_id.isNull()) + { + llerrs << "Invalid notification, no object id" << llendl; + return; + } + + // If an Object spawns more-than-one floater, only the newest one is shown. + // The other is automatically closed. + script_notification_map_t::iterator it = mNotifications.find(object_id); + if(it != mNotifications.end()) + { + removeNotification(notification_id); + } + + LLNotificationData nd = {notification_id}; + mNotifications.insert(std::make_pair(object_id, nd)); + + LLBottomTray::getInstance()->getChicletPanel()->createChiclet(object_id); +} + +void LLScriptFloaterManager::onRemoveNotification(const LLUUID& notification_id) +{ + LLUUID object_id = notification_id_to_object_id(notification_id); + if(object_id.isNull()) + { + llerrs << "Invalid notification, no object id" << llendl; + return; + } + + using namespace LLNotificationsUI; + + // remove related toast + LLScreenChannel* channel = dynamic_cast(LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + if(channel) + { + channel->killToastByNotificationID(getToastNotificationId(object_id)); + } + + mNotifications.erase(object_id); + + // remove related chiclet + LLBottomTray::getInstance()->getChicletPanel()->removeChiclet(object_id); + + // close floater + LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", object_id); + if(floater) + { + floater->closeFloater(); + } +} + +void LLScriptFloaterManager::toggleScriptFloater(const LLUUID& object_id) +{ + // hide "new message" icon from chiclet + LLIMChiclet* chiclet = LLBottomTray::getInstance()->getChicletPanel()->findChiclet(object_id); + if(chiclet) + { + chiclet->setShowNewMessagesIcon(false); + } + + // kill toast + using namespace LLNotificationsUI; + LLScreenChannel* channel = dynamic_cast(LLChannelManager::getInstance()->findChannelByID( + LLUUID(gSavedSettings.getString("NotificationChannelUUID")))); + if(channel) + { + channel->killToastByNotificationID(getToastNotificationId(object_id)); + } + + // toggle floater + LLScriptFloater::toggle(object_id); +} + +void LLScriptFloaterManager::closeScriptFloater(const LLUUID& object_id) +{ + LLNotificationPtr notification = LLNotifications::getInstance()->find( + getNotificationId(object_id)); + if(notification) + { + removeNotification(notification->getID()); + } +} + +void LLScriptFloaterManager::setToastNotificationId(const LLUUID& object_id, const LLUUID& notification_id) +{ + script_notification_map_t::iterator it = mNotifications.find(object_id); + if(mNotifications.end() != it) + { + it->second.toast_notification_id = notification_id; + } +} + +const LLUUID& LLScriptFloaterManager::getNotificationId(const LLUUID& object_id) +{ + script_notification_map_t::const_iterator it = mNotifications.find(object_id); + if(mNotifications.end() != it) + { + return it->second.notification_id; + } + return LLUUID::null; +} + +const LLUUID& LLScriptFloaterManager::getToastNotificationId(const LLUUID& object_id) +{ + script_notification_map_t::const_iterator it = mNotifications.find(object_id); + if(mNotifications.end() != it) + { + return it->second.toast_notification_id; + } + return LLUUID::null; +} + +//static +void LLScriptFloaterManager::onToastButtonClick(const LLSD¬ification, const LLSD&response) +{ + S32 option = LLNotification::getSelectedOption(notification, response); + LLUUID object_id = notification["payload"]["object_id"].asUUID(); + + switch(option) + { + case 0: // "Open" + LLScriptFloaterManager::getInstance()->toggleScriptFloater(object_id); + break; + case 1: // "Ignore" + LLScriptFloaterManager::getInstance()->closeScriptFloater(object_id); + break; + case 2: // "Mute" + LLMuteList::getInstance()->add(LLMute(object_id, notification["substitutions"]["TITLE"], LLMute::OBJECT)); + LLScriptFloaterManager::getInstance()->closeScriptFloater(object_id); + break; + default: + llwarns << "Unexpected value" << llendl; + break; + } +} + +// EOF diff --git a/indra/newview/llscriptfloater.h b/indra/newview/llscriptfloater.h new file mode 100644 index 0000000000..fc1d9a0186 --- /dev/null +++ b/indra/newview/llscriptfloater.h @@ -0,0 +1,114 @@ +/** + * @file llscriptfloater.h + * @brief LLScriptFloater class definition + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_SCRIPTFLOATER_H +#define LL_SCRIPTFLOATER_H + +#include "lltransientdockablefloater.h" + +/** + * This class manages Object script floaters. + */ +class LLScriptFloaterManager : public LLSingleton +{ +public: + + void onAddNotification(const LLUUID& notification_id); + + void onRemoveNotification(const LLUUID& notification_id); + + void toggleScriptFloater(const LLUUID& object_id); + + void closeScriptFloater(const LLUUID& object_id); + + const LLUUID& getNotificationId(const LLUUID& object_id); + + const LLUUID& getToastNotificationId(const LLUUID& object_id); + + void setToastNotificationId(const LLUUID& object_id, const LLUUID& notification_id); + + static void onToastButtonClick(const LLSD¬ification, const LLSD&response); + +private: + + struct LLNotificationData + { + LLUUID notification_id; + LLUUID toast_notification_id; + }; + + typedef std::map script_notification_map_t; + + script_notification_map_t mNotifications; +}; + +/** + * Floater for displaying script forms + */ +class LLScriptFloater : public LLTransientDockableFloater +{ +public: + + /** + * key - UUID of scripted Object + */ + LLScriptFloater(const LLSD& key); + + virtual ~LLScriptFloater(){}; + + static bool toggle(const LLUUID& object_id); + + static LLScriptFloater* show(const LLUUID& object_id); + + const LLUUID& getObjectId() { return mObjectId; } + + /*virtual*/ void onClose(bool app_quitting); + + /*virtual*/ void setDocked(bool docked, bool pop_on_undock = true); + + /*virtual*/ void setVisible(BOOL visible); + +protected: + + void createForm(const LLUUID& object_id); + + /*virtual*/ void getAllowedRect(LLRect& rect); + + static void updateToasts(); + + void setObjectId(const LLUUID& id) { mObjectId = id; } + +private: + LLUUID mObjectId; +}; + +#endif //LL_SCRIPTFLOATER_H diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 7772f613f0..812107dd72 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -124,6 +124,7 @@ #include "llpreviewsound.h" #include "llpreviewtexture.h" #include "llsyswellwindow.h" +#include "llscriptfloater.h" // *NOTE: Please add files in alphabetical order to keep merges easy. @@ -171,6 +172,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); + LLFloaterReg::add("script_floater", "floater_script.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8db6d5917a..ac1f366f9c 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -101,6 +101,7 @@ #include "llpanelgrouplandmoney.h" #include "llpanelplaces.h" #include "llrecentpeople.h" +#include "llscriptfloater.h" #include "llselectmgr.h" #include "llsidetray.h" #include "llstartup.h" @@ -5380,6 +5381,15 @@ void process_script_dialog(LLMessageSystem* msg, void**) notification = LLNotifications::instance().add( LLNotification::Params("ScriptDialogGroup").substitutions(args).payload(payload).form_elements(form.asLLSD())); } + + LLNotification::Params p("ScriptToast"); + p.substitutions(args).payload(payload).functor.function(boost::bind( + LLScriptFloaterManager::onToastButtonClick, _1, _2)); + + notification = LLNotifications::instance().add(p); + + LLScriptFloaterManager::getInstance()->setToastNotificationId( + object_id, notification->getID()); } //--------------------------------------------------------------------------- diff --git a/indra/newview/skins/default/xui/en/floater_script.xml b/indra/newview/skins/default/xui/en/floater_script.xml new file mode 100644 index 0000000000..f44ba6d873 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_script.xml @@ -0,0 +1,19 @@ + + + diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 4897a4c8ab..af71ae09d2 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -5298,6 +5298,27 @@ Grant this request? + + [FIRST] [LAST]'s '[TITLE]' is requesting user input. +
+
- + Date: Tue, 24 Nov 2009 19:35:24 +0200 Subject: Fixed a minor grammatical mistake. --HG-- branch : product-engine --- indra/newview/skins/default/xui/en/panel_picks.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml index 5cefe3e4ab..ece58180f7 100644 --- a/indra/newview/skins/default/xui/en/panel_picks.xml +++ b/indra/newview/skins/default/xui/en/panel_picks.xml @@ -24,7 +24,7 @@ top="10" visible="false" width="313"> - There are no any picks/classifieds here + There are no picks/classifieds here Date: Tue, 24 Nov 2009 12:49:36 -0500 Subject: For EXT-2571: Right click context menu for Outfits --HG-- branch : avatar-pipeline --- indra/newview/llinventorybridge.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index db079de593..628db46281 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -62,6 +62,7 @@ #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llwearablelist.h" +#include "llpaneloutfitsinventory.h" using namespace LLOldEvents; @@ -2340,6 +2341,15 @@ void LLFolderBridge::staticFolderOptionsMenu() sSelf->folderOptionsMenu(); } +bool isInOutfitsSidePanel(LLPanel *panel) +{ + LLInventoryPanel *my_panel = dynamic_cast(panel); + LLPanelOutfitsInventory *outfit_panel = + dynamic_cast(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); + LLInventoryPanel *outfit_inv_panel = outfit_panel ? outfit_panel->getActivePanel(): NULL; + return (my_panel && (my_panel == outfit_inv_panel)); +} + void LLFolderBridge::folderOptionsMenu() { std::vector disabled_items; @@ -2353,11 +2363,17 @@ void LLFolderBridge::folderOptionsMenu() // BAP change once we're no longer treating regular categories as ensembles. const bool is_ensemble = category && (type == LLFolderType::FT_NONE || LLFolderType::lookupIsEnsembleType(type)); + const bool is_sidepanel = isInOutfitsSidePanel(mInventoryPanel.get()); // calling card related functionality for folders. + if (is_sidepanel) + { + mItems.clear(); + } + // Only enable calling-card related options for non-default folders. - if (!is_default_folder) + if (!is_sidepanel && !is_default_folder) { LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard)) -- cgit v1.2.3 From c227f93b1a6f89847242261f634079d4d6bfbf08 Mon Sep 17 00:00:00 2001 From: Sergey Borushevsky Date: Tue, 24 Nov 2009 20:27:56 +0200 Subject: Fixed minor bug EXT-2745 (Contents of Groups field duplicates after IM session has been started) --HG-- branch : product-engine --- indra/newview/llpanelavatar.cpp | 30 ++++++++++++++++++------------ indra/newview/llpanelavatar.h | 4 +++- 2 files changed, 21 insertions(+), 13 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index 03401d934f..ed1d93db78 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -359,7 +359,7 @@ void LLPanelAvatarProfile::onOpen(const LLSD& key) { LLPanelProfileTab::onOpen(key); - mGroups.erase(); + mGroups.clear(); //Disable "Add Friend" button for friends. childSetEnabled("add_friend", !LLAvatarActions::isFriend(getAvatarId())); @@ -391,7 +391,7 @@ void LLPanelAvatarProfile::resetControls() void LLPanelAvatarProfile::resetData() { - mGroups.erase(); + mGroups.clear(); childSetValue("2nd_life_pic",LLUUID::null); childSetValue("real_world_pic",LLUUID::null); childSetValue("online_status",LLStringUtil::null); @@ -443,23 +443,29 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g // Group properties may arrive in two callbacks, we need to save them across // different calls. We can't do that in textbox as textbox may change the text. - std::string groups = mGroups; LLAvatarGroups::group_list_t::const_iterator it = avatar_groups->group_list.begin(); const LLAvatarGroups::group_list_t::const_iterator it_end = avatar_groups->group_list.end(); - if(groups.empty() && it_end != it) - { - groups = (*it).group_name; - ++it; - } for(; it_end != it; ++it) { LLAvatarGroups::LLGroupData group_data = *it; - groups += ", "; - groups += group_data.group_name; + + // Check if there is no duplicates for this group + if (std::find(mGroups.begin(), mGroups.end(), group_data.group_name) == mGroups.end()) + mGroups.push_back(group_data.group_name); + } + + // Creating string, containing group list + std::string groups = ""; + for (group_list_t::const_iterator it = mGroups.begin(); it != mGroups.end(); ++it) + { + if (it != mGroups.begin()) + groups += ", "; + + groups += *it; } - mGroups = groups; - childSetValue("sl_groups",mGroups); + + childSetValue("sl_groups", groups); } void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data) diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h index a0caf0c915..8e0965e0b7 100644 --- a/indra/newview/llpanelavatar.h +++ b/indra/newview/llpanelavatar.h @@ -183,7 +183,9 @@ protected: private: - std::string mGroups; + typedef std::list group_list_t; + group_list_t mGroups; + LLToggleableMenu* mProfileMenu; }; -- cgit v1.2.3 From 240c21cc2dd82dd41a664ec225fafb24bab44ca6 Mon Sep 17 00:00:00 2001 From: Sergey Borushevsky Date: Tue, 24 Nov 2009 20:34:05 +0200 Subject: Related to implementation of EXT-2517 (Add support for the viewer 1.23 chat history style (widget-less)) - reverted changes in session processing code in LLIMFloater::onClose in rev. bd3f78cc1c42. --HG-- branch : product-engine --- indra/newview/llimfloater.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp index 795770d3db..ee93a9349a 100644 --- a/indra/newview/llimfloater.cpp +++ b/indra/newview/llimfloater.cpp @@ -110,10 +110,10 @@ void LLIMFloater::onFocusReceived() // virtual void LLIMFloater::onClose(bool app_quitting) { - if (!gIMMgr->hasSession(mSessionID)) return; - setTyping(false); - gIMMgr->leaveSession(mSessionID); + // SJB: We want the close button to hide the session window, not end it + // *NOTE: Yhis is functional, but not ideal - it's still closing the floater; we really want to change the behavior of the X button instead. + //gIMMgr->leaveSession(mSessionID); } /* static */ -- cgit v1.2.3 From 3d2fbad4cafae520f790f97dad6b4eb6a0363751 Mon Sep 17 00:00:00 2001 From: Eugene Mutavchi Date: Tue, 24 Nov 2009 20:57:41 +0200 Subject: Fixed normal bug EXT-2570 (There is no connecting/leaving spatial voice chat notifications in the nearby chat) --HG-- branch : product-engine --- indra/newview/llimview.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'indra/newview') diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index c066f1f77a..ffa943092f 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -71,6 +71,7 @@ #include "llviewermessage.h" #include "llviewerwindow.h" #include "llnotify.h" +#include "llnearbychat.h" #include "llviewerregion.h" #include "llvoicechannel.h" #include "lltrans.h" @@ -1611,6 +1612,12 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; LLFloaterChat::addChatHistory(chat); + + LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance("nearby_chat", LLSD()); + if(nearby_chat) + { + nearby_chat->addMessage(chat); + } } else // going to IM session { -- cgit v1.2.3 From 87d7c6d6f962281f11b35e02a399e3d0e1dd9e12 Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Tue, 24 Nov 2009 21:18:09 +0200 Subject: Work on task EXT-2092 (Task Panel tabs should toggle visibility of the panel). Made the People and Me task panels support the desired tri-state behavior. Until all the other task panels support that behavior, it is disabled. --HG-- branch : product-engine --- indra/newview/llpanelme.cpp | 47 +++++++++++++++++++++++++++++++++--- indra/newview/llpanelme.h | 1 + indra/newview/llpanelpeople.cpp | 27 +++++++++++++++++++++ indra/newview/llpanelpeople.h | 4 +-- indra/newview/llpanelprofile.cpp | 18 ++------------ indra/newview/llpanelprofile.h | 2 +- indra/newview/llpanelprofileview.cpp | 4 ++- indra/newview/llpanelprofileview.h | 2 +- indra/newview/llsidetray.cpp | 39 ++++++++---------------------- 9 files changed, 90 insertions(+), 54 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llpanelme.cpp b/indra/newview/llpanelme.cpp index e12da97f3b..046118cf75 100644 --- a/indra/newview/llpanelme.cpp +++ b/indra/newview/llpanelme.cpp @@ -38,6 +38,7 @@ #include "llagent.h" #include "llagentwearables.h" #include "lliconctrl.h" +#include "llsidetray.h" #include "lltabcontainer.h" #include "lltexturectrl.h" @@ -70,6 +71,45 @@ void LLPanelMe::onOpen(const LLSD& key) LLPanelProfile::onOpen(key); } +void LLPanelMe::notifyChildren(const LLSD& info) +{ + if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state") + { + // Implement task panel tri-state behavior. + // + // When the button of an active open task panel is clicked, side tray + // calls notifyChildren() on the panel, passing task-panel-action=>handle-tri-state as an argument. + // The task panel is supposed to handle this by reverting to the default view, + // i.e. closing any dependent panels like "pick info" or "profile edit". + + bool on_default_view = true; + + const LLRect& task_panel_rect = getRect(); + for (LLView* child = getFirstChild(); child; child = findNextSibling(child)) + { + LLPanel* panel = dynamic_cast(child); + if (!panel) + continue; + + // *HACK: implement panel stack instead (e.g. me->pick_info->pick_edit). + if (panel->getRect().getWidth() == task_panel_rect.getWidth() && + panel->getRect().getHeight() == task_panel_rect.getHeight() && + panel->getVisible()) + { + panel->setVisible(FALSE); + on_default_view = false; + } + } + + if (on_default_view) + LLSideTray::getInstance()->collapseSideBar(); + + return; // this notification is only supposed to be handled by task panels + } + + LLPanel::notifyChildren(info); +} + void LLPanelMe::buildEditPanel() { if (NULL == mEditPanel) @@ -84,8 +124,7 @@ void LLPanelMe::buildEditPanel() void LLPanelMe::onEditProfileClicked() { buildEditPanel(); - togglePanel(mEditPanel); - mEditPanel->onOpen(getAvatarId()); + togglePanel(mEditPanel, getAvatarId()); // open } void LLPanelMe::onEditAppearanceClicked() @@ -108,13 +147,13 @@ void LLPanelMe::onSaveChangesClicked() data.allow_publish = mEditPanel->childGetValue("show_in_search_checkbox"); LLAvatarPropertiesProcessor::getInstance()->sendAvatarPropertiesUpdate(&data); - togglePanel(mEditPanel); + togglePanel(mEditPanel); // close onOpen(getAvatarId()); } void LLPanelMe::onCancelClicked() { - togglePanel(mEditPanel); + togglePanel(mEditPanel); // close } ////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llpanelme.h b/indra/newview/llpanelme.h index e16532a445..17d367132e 100644 --- a/indra/newview/llpanelme.h +++ b/indra/newview/llpanelme.h @@ -54,6 +54,7 @@ public: LLPanelMe(); /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void notifyChildren(const LLSD& info); /*virtual*/ BOOL postBuild(); diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 4dc8872557..2ccd10a065 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -56,6 +56,8 @@ #include "llgrouplist.h" #include "llinventoryobserver.h" #include "llpanelpeoplemenus.h" +#include "llsidetray.h" +#include "llsidetraypanelcontainer.h" #include "llrecentpeople.h" #include "llviewercontrol.h" // for gSavedSettings #include "llviewermenu.h" // for gMenuHolder @@ -1263,6 +1265,31 @@ void LLPanelPeople::onOpen(const LLSD& key) reSelectedCurrentTab(); } +void LLPanelPeople::notifyChildren(const LLSD& info) +{ + if (info.has("task-panel-action") && info["task-panel-action"].asString() == "handle-tri-state") + { + LLSideTrayPanelContainer* container = dynamic_cast(getParent()); + if (!container) + { + llwarns << "Cannot find People panel container" << llendl; + return; + } + + if (container->getCurrentPanelIndex() > 0) + { + // if not on the default panel, switch to it + container->onOpen(LLSD().insert(LLSideTrayPanelContainer::PARAM_SUB_PANEL_NAME, getName())); + } + else + LLSideTray::getInstance()->collapseSideBar(); + + return; // this notification is only supposed to be handled by task panels + } + + LLPanel::notifyChildren(info); +} + void LLPanelPeople::showAccordion(const std::string name, bool show) { if(name.empty()) diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index a369bcd3e2..d9dd76f3ac 100644 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -50,8 +50,8 @@ public: virtual ~LLPanelPeople(); /*virtual*/ BOOL postBuild(); - - virtual void onOpen(const LLSD& key); + /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void notifyChildren(const LLSD& info); // internals class Updater; diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 02f45c1b48..4d152a13f3 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -158,28 +158,14 @@ void LLPanelProfile::onOpen(const LLSD& key) } //*TODO redo panel toggling -void LLPanelProfile::togglePanel(LLPanel* panel) +void LLPanelProfile::togglePanel(LLPanel* panel, const LLSD& key) { // TRUE - we need to open/expand "panel" bool expand = getChildList()->front() != panel; // mTabCtrl->getVisible(); if (expand) { - if (panel->getParent() != this) - { - addChild(panel); - } - else - { - sendChildToFront(panel); - } - - panel->setVisible(TRUE); - - LLRect new_rect = getRect(); - panel->reshape(new_rect.getWidth(), new_rect.getHeight()); - new_rect.setLeftTopAndSize(0, new_rect.getHeight(), new_rect.getWidth(), new_rect.getHeight()); - panel->setRect(new_rect); + openPanel(panel, key); } else { diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index e216eb70f2..067beb248b 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -51,7 +51,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); - virtual void togglePanel(LLPanel*); + virtual void togglePanel(LLPanel*, const LLSD& key = LLSD()); virtual void openPanel(LLPanel* panel, const LLSD& params); diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp index d4ab5013f9..08aea8cfd8 100644 --- a/indra/newview/llpanelprofileview.cpp +++ b/indra/newview/llpanelprofileview.cpp @@ -193,8 +193,10 @@ void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& getChild("user_name", FALSE)->setValue(first_name + " " + last_name); } -void LLPanelProfileView::togglePanel(LLPanel* panel) +void LLPanelProfileView::togglePanel(LLPanel* panel, const LLSD& key) { + // *TODO: unused method? + LLPanelProfile::togglePanel(panel); if(FALSE == panel->getVisible()) { diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h index 45c2fc116e..5dc617d4a0 100644 --- a/indra/newview/llpanelprofileview.h +++ b/indra/newview/llpanelprofileview.h @@ -64,7 +64,7 @@ public: /*virtual*/ BOOL postBuild(); - /*virtual*/ void togglePanel(LLPanel* panel); + /*virtual*/ void togglePanel(LLPanel* panel, const LLSD& key = LLSD()); BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType cargo_type, diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp index 7711f3c733..0b832a8239 100644 --- a/indra/newview/llsidetray.cpp +++ b/indra/newview/llsidetray.cpp @@ -435,35 +435,16 @@ void LLSideTray::processTriState () expandSideBar(); else { - //!!!!!!!!!!!!!!!!! - //** HARDCODED!!!!! - //!!!!!!!!!!!!!!!!! - - //there is no common way to determine "default" panel for tab - //so default panels for now will be hardcoded - - //hardcoded for people tab and profile tab - - /*if(mActiveTab == getTab("sidebar_people")) - { - LLSideTrayPanelContainer* container = findChild("panel_container"); - if(container && container->getCurrentPanelIndex()>0) - { - container->onOpen(LLSD().insert("sub_panel_name","panel_people")); - } - else - collapseSideBar(); - } - else if(mActiveTab == getTab("sidebar_me")) - { - LLTabContainer* tab_container = findChild("tabs"); - if(tab_container && tab_container->getCurrentPanelIndex()>0) - tab_container->selectFirstTab(); - else - collapseSideBar(); - } - else*/ - collapseSideBar(); +#if 0 // *TODO: EXT-2092 + + // Tell the active task panel to switch to its default view + // or collapse side tray if already on the default view. + LLSD info; + info["task-panel-action"] = "handle-tri-state"; + mActiveTab->notifyChildren(info); +#else + collapseSideBar(); +#endif } } -- cgit v1.2.3 From fc6cfc27bec61ac1f66c1304cc7b54f19157584e Mon Sep 17 00:00:00 2001 From: "Brad Payne (Vir Linden)" Date: Tue, 24 Nov 2009 14:37:48 -0500 Subject: Fix for EXT-2571 to accommodate accordion panels --HG-- branch : avatar-pipeline --- indra/newview/llinventorybridge.cpp | 8 ++++++-- indra/newview/llpaneloutfitsinventory.cpp | 11 +++++++++++ indra/newview/llpaneloutfitsinventory.h | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 628db46281..3e847f11ce 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2346,8 +2346,12 @@ bool isInOutfitsSidePanel(LLPanel *panel) LLInventoryPanel *my_panel = dynamic_cast(panel); LLPanelOutfitsInventory *outfit_panel = dynamic_cast(LLSideTray::getInstance()->getPanel("panel_outfits_inventory")); - LLInventoryPanel *outfit_inv_panel = outfit_panel ? outfit_panel->getActivePanel(): NULL; - return (my_panel && (my_panel == outfit_inv_panel)); + if (!outfit_panel) + return false; + return outfit_panel->isAccordionPanel(my_panel); + + //LLInventoryPanel *outfit_inv_panel = outfit_panel ? outfit_panel->getActivePanel(): NULL; + //return (my_panel && (my_panel == outfit_inv_panel)); } void LLFolderBridge::folderOptionsMenu() diff --git a/indra/newview/llpaneloutfitsinventory.cpp b/indra/newview/llpaneloutfitsinventory.cpp index 2550962d76..e66a4440e9 100644 --- a/indra/newview/llpaneloutfitsinventory.cpp +++ b/indra/newview/llpaneloutfitsinventory.cpp @@ -398,3 +398,14 @@ LLInventoryPanel* LLPanelOutfitsInventory::getActivePanel() return mActivePanel; } +bool LLPanelOutfitsInventory::isAccordionPanel(LLInventoryPanel *panel) +{ + for(accordionpanels_vec_t::iterator it = mAccordionPanels.begin(); + it != mAccordionPanels.end(); + ++it) + { + if (*it == panel) + return true; + } + return false; +} diff --git a/indra/newview/llpaneloutfitsinventory.h b/indra/newview/llpaneloutfitsinventory.h index 902a5caab8..7769a7d172 100644 --- a/indra/newview/llpaneloutfitsinventory.h +++ b/indra/newview/llpaneloutfitsinventory.h @@ -78,6 +78,7 @@ public: ////////////////////////////////////////////////////////////////////////////////// // Accordion // LLInventoryPanel* getActivePanel(); + bool isAccordionPanel(LLInventoryPanel *panel); protected: void initAccordionPanels(); -- cgit v1.2.3 From 4821134aa7be2471aad461aa6a730a68a4c92560 Mon Sep 17 00:00:00 2001 From: "Nyx (Neal Orman)" Date: Tue, 24 Nov 2009 15:34:31 -0500 Subject: EXT-2671 avatar rebaking on every login We were querying agent wearables (baked texture) cache before setting mWearablesLoaded. First thing the function does is checks mWearablesLoaded. Moving the call down to later in the function allows us to request & use cached baked textures again. Code reviewed by Seraph --HG-- branch : avatar-pipeline --- indra/newview/llagentwearables.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/newview') diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 574b449d23..475f34dc2b 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -1547,7 +1547,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it gInventory.notifyObservers(); - queryWearableCache(); std::vector::iterator wearable_iter; @@ -1570,6 +1569,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it // Start rendering & update the server mWearablesLoaded = TRUE; checkWearablesLoaded(); + queryWearableCache(); updateServer(); lldebugs << "setWearableOutfit() end" << llendl; -- cgit v1.2.3 From 88a56949d5b121132e3a068c72ab370834d72ceb Mon Sep 17 00:00:00 2001 From: "Eric M. Tulla (BigPapi)" Date: Tue, 24 Nov 2009 15:43:29 -0500 Subject: made task inventory offers work the old way, and disabled inv slurls for them. --- indra/newview/llviewerinventory.cpp | 2 +- indra/newview/llviewermessage.cpp | 271 ++++++++++++++++----- indra/newview/llviewermessage.h | 1 + .../newview/skins/default/xui/en/notifications.xml | 8 - 4 files changed, 208 insertions(+), 74 deletions(-) (limited to 'indra/newview') diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index ad3828bba6..c6ec25c1cb 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -80,7 +80,7 @@ public: } const std::string verb = params[1].asString(); - //if (verb == "select") + if (verb == "select") { std::vector items_to_open; items_to_open.push_back(inventory_id); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 7eed40589b..eaffa75298 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1130,48 +1130,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& std::string from_string; // Used in the pop-up. std::string chatHistory_string; // Used in chat history. - if (mFromObject == TRUE) - { - if (mFromGroup) - { - std::string group_name; - if (gCacheName->getGroupName(mFromID, group_name)) - { - from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'" - + mFromName + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedByGroup") - + " "+ "'" + group_name + "'"; - - chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByGroup") - + " " + group_name + "'"; - } - else - { - from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'" - + mFromName +"'"+ " " + LLTrans::getString("InvOfferOwnedByUnknownGroup"); - chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownGroup"); - } - } - else - { - std::string first_name, last_name; - if (gCacheName->getName(mFromID, first_name, last_name)) - { - from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+ LLTrans::getString("'") + mFromName - + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name; - chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + first_name + " " + last_name; - } - else - { - from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+LLTrans::getString("'") - + mFromName + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedByUnknownUser"); - chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownUser"); - } - } - } - else - { - from_string = chatHistory_string = mFromName; - } + + // TODO: when task inventory offers can also be handled the new way, migrate the code that sets these strings here: + from_string = chatHistory_string = mFromName; bool busy=FALSE; @@ -1281,8 +1242,182 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& return false; } +bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const LLSD& response) +{ + LLChat chat; + std::string log_message; + S32 button = LLNotification::getSelectedOption(notification, response); + + // For muting, we need to add the mute, then decline the offer. + // This must be done here because: + // * callback may be called immediately, + // * adding the mute sends a message, + // * we can't build two messages at once. + if (2 == button) + { + gCacheName->get(mFromID, mFromGroup, &inventory_offer_mute_callback); + } + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_ImprovedInstantMessage); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + msg->nextBlockFast(_PREHASH_MessageBlock); + msg->addBOOLFast(_PREHASH_FromGroup, FALSE); + msg->addUUIDFast(_PREHASH_ToAgentID, mFromID); + msg->addU8Fast(_PREHASH_Offline, IM_ONLINE); + msg->addUUIDFast(_PREHASH_ID, mTransactionID); + msg->addU32Fast(_PREHASH_Timestamp, NO_TIMESTAMP); // no timestamp necessary + std::string name; + LLAgentUI::buildFullname(name); + msg->addStringFast(_PREHASH_FromAgentName, name); + msg->addStringFast(_PREHASH_Message, ""); + msg->addU32Fast(_PREHASH_ParentEstateID, 0); + msg->addUUIDFast(_PREHASH_RegionID, LLUUID::null); + msg->addVector3Fast(_PREHASH_Position, gAgent.getPositionAgent()); + LLInventoryObserver* opener = NULL; + LLViewerInventoryCategory* catp = NULL; + catp = (LLViewerInventoryCategory*)gInventory.getCategory(mObjectID); + LLViewerInventoryItem* itemp = NULL; + if(!catp) + { + itemp = (LLViewerInventoryItem*)gInventory.getItem(mObjectID); + } + + std::string from_string; // Used in the pop-up. + std::string chatHistory_string; // Used in chat history. + if (mFromObject == TRUE) + { + if (mFromGroup) + { + std::string group_name; + if (gCacheName->getGroupName(mFromID, group_name)) + { + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'" + + mFromName + LLTrans::getString("'") +" " + LLTrans::getString("InvOfferOwnedByGroup") + + " "+ "'" + group_name + "'"; + + chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByGroup") + + " " + group_name + "'"; + } + else + { + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+"'" + + mFromName +"'"+ " " + LLTrans::getString("InvOfferOwnedByUnknownGroup"); + chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownGroup"); + } + } + else + { + std::string first_name, last_name; + if (gCacheName->getName(mFromID, first_name, last_name)) + { + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+ LLTrans::getString("'") + mFromName + + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedBy") + first_name + " " + last_name; + chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedBy") + " " + first_name + " " + last_name; + } + else + { + from_string = LLTrans::getString("InvOfferAnObjectNamed") + " "+LLTrans::getString("'") + + mFromName + LLTrans::getString("'")+" " + LLTrans::getString("InvOfferOwnedByUnknownUser"); + chatHistory_string = mFromName + " " + LLTrans::getString("InvOfferOwnedByUnknownUser"); + } + } + } + else + { + from_string = chatHistory_string = mFromName; + } + + bool busy=FALSE; + + switch(button) + { + case IOR_ACCEPT: + // ACCEPT. The math for the dialog works, because the accept + // for inventory_offered, task_inventory_offer or + // group_notice_inventory is 1 greater than the offer integer value. + // Generates IM_INVENTORY_ACCEPTED, IM_TASK_INVENTORY_ACCEPTED, + // or IM_GROUP_NOTICE_INVENTORY_ACCEPTED + msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 1)); + msg->addBinaryDataFast(_PREHASH_BinaryBucket, &(mFolderID.mData), + sizeof(mFolderID.mData)); + // send the message + msg->sendReliable(mHost); + + //don't spam them if they are getting flooded + if (check_offer_throttle(mFromName, true)) + { + log_message = chatHistory_string + " " + LLTrans::getString("InvOfferGaveYou") + " " + mDesc + LLTrans::getString("."); + chat.mText = log_message; + LLFloaterChat::addChatHistory(chat); + } + + // we will want to open this item when it comes back. + LL_DEBUGS("Messaging") << "Initializing an opener for tid: " << mTransactionID + << LL_ENDL; + switch (mIM) + { + case IM_TASK_INVENTORY_OFFERED: + case IM_GROUP_NOTICE: + case IM_GROUP_NOTICE_REQUESTED: + { + // This is an offer from a task or group. + // We don't use a new instance of an opener + // We instead use the singular observer gOpenTaskOffer + // Since it already exists, we don't need to actually do anything + } + break; + default: + LL_WARNS("Messaging") << "inventory_offer_callback: unknown offer type" << LL_ENDL; + break; + } // end switch (mIM) + break; + + case IOR_BUSY: + //Busy falls through to decline. Says to make busy message. + busy=TRUE; + case IOR_MUTE: + // MUTE falls through to decline + case IOR_DECLINE: + // DECLINE. The math for the dialog works, because the decline + // for inventory_offered, task_inventory_offer or + // group_notice_inventory is 2 greater than the offer integer value. + // Generates IM_INVENTORY_DECLINED, IM_TASK_INVENTORY_DECLINED, + // or IM_GROUP_NOTICE_INVENTORY_DECLINED + default: + // close button probably (or any of the fall-throughs from above) + msg->addU8Fast(_PREHASH_Dialog, (U8)(mIM + 2)); + msg->addBinaryDataFast(_PREHASH_BinaryBucket, EMPTY_BINARY_BUCKET, EMPTY_BINARY_BUCKET_SIZE); + // send the message + msg->sendReliable(mHost); + + log_message = LLTrans::getString("InvOfferYouDecline") + " " + mDesc + " " + LLTrans::getString("InvOfferFrom") + " " + mFromName +"."; + chat.mText = log_message; + if( LLMuteList::getInstance()->isMuted(mFromID ) && ! LLMuteList::getInstance()->isLinden(mFromName) ) // muting for SL-42269 + { + chat.mMuted = TRUE; + } + LLFloaterChat::addChatHistory(chat); + + if (busy && (!mFromGroup && !mFromObject)) + { + busy_message(msg,mFromID); + } + break; + } + + if(opener) + { + gInventory.addObserver(opener); + } + + delete this; + return false; +} -void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) +void inventory_offer_handler(LLOfferInfo* info) { //Until throttling is implmented, busy mode should reject inventory instead of silently //accepting it. SEE SL-39554 @@ -1369,38 +1504,44 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) args["OBJECTFROMNAME"] = info->mFromName; args["NAME"] = info->mFromName; args["NAME_SLURL"] = LLSLURL::buildCommand("agent", info->mFromID, "about"); - std::string verb = "highlight?name=" + msg; + std::string verb = "select?name=" + msg; args["ITEM_SLURL"] = LLSLURL::buildCommand("inventory", info->mObjectID, verb.c_str()); LLNotification::Params p("ObjectGiveItem"); - p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2)); - if (from_task) + // Object -> Agent Inventory Offer + if (info->mFromObject) { + // Inventory Slurls don't currently work for non agent transfers, so only display the object name. + args["ITEM_SLURL"] = msg; + // Note: sets inventory_task_offer_callback as the callback + p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_task_offer_callback, info, _1, _2)); p.name = name_found ? "ObjectGiveItem" : "ObjectGiveItemUnknownUser"; } - else + else // Agent -> Agent Inventory Offer { + // Note: sets inventory_offer_callback as the callback + p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2)); p.name = "UserGiveItem"; + + // Prefetch the item into your local inventory. + LLInventoryFetchObserver::item_ref_t items; + items.push_back(info->mObjectID); + LLInventoryFetchObserver* fetch_item = new LLInventoryFetchObserver(); + fetch_item->fetchItems(items); + if(fetch_item->isEverythingComplete()) + { + fetch_item->done(); + } + else + { + gInventory.addObserver(fetch_item); + } + + // In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages). + info->send_auto_receive_response(); } - // Prefetch the item into your local inventory. - LLInventoryFetchObserver::item_ref_t items; - items.push_back(info->mObjectID); - LLInventoryFetchObserver* fetch_item = new LLInventoryFetchObserver(); - fetch_item->fetchItems(items); - if(fetch_item->isEverythingComplete()) - { - fetch_item->done(); - } - else - { - gInventory.addObserver(fetch_item); - } - - // In viewer 2 we're now auto receiving inventory offers and messaging as such (not sending reject messages). - info->send_auto_receive_response(); - // Pop up inv offer notification and let the user accept (keep), or reject (and silently delete) the inventory. LLNotifications::instance().add(p); } @@ -1897,7 +2038,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { - inventory_offer_handler(info, dialog == IM_TASK_INVENTORY_OFFERED); + inventory_offer_handler(info); } } break; diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index 2d8930d2fe..1a98828010 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -222,6 +222,7 @@ struct LLOfferInfo LLSD asLLSD(); void send_auto_receive_response(void); bool inventory_offer_callback(const LLSD& notification, const LLSD& response); + bool inventory_task_offer_callback(const LLSD& notification, const LLSD& response); }; diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index eb0db2683f..3e622d779c 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -4973,10 +4973,6 @@ An object named [OBJECTFROMNAME] owned by [NAME_SLURL] has given you [OBJECTTYPE index="0" name="Keep" text="Keep"/> -