diff options
Diffstat (limited to 'indra/newview/llviewermessage.cpp')
-rw-r--r-- | indra/newview/llviewermessage.cpp | 533 |
1 files changed, 415 insertions, 118 deletions
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 9b39cbfdf1..3d107555bf 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -32,6 +32,7 @@ #include "llviewerprecompiledheaders.h" #include "llviewermessage.h" +#include "boost/lexical_cast.hpp" #include "llanimationstates.h" #include "llaudioengine.h" @@ -41,6 +42,7 @@ #include "lleventtimer.h" #include "llfloaterreg.h" #include "llfollowcamparams.h" +#include "llinventorydefines.h" #include "llregionhandle.h" #include "llsdserialize.h" #include "llteleportflags.h" @@ -53,8 +55,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llcallingcard.h" -//#include "llfirstuse.h" -#include "llfloaterbuycurrency.h" +#include "llbuycurrencyhtml.h" #include "llfloaterbuyland.h" #include "llfloaterland.h" #include "llfloaterregioninfo.h" @@ -70,7 +71,6 @@ #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpanelgrouplandmoney.h" -#include "llpanelplaces.h" #include "llrecentpeople.h" #include "llscriptfloater.h" #include "llselectmgr.h" @@ -109,12 +109,13 @@ #include <boost/algorithm/string/split.hpp> // #include <boost/regex.hpp> -#if LL_WINDOWS // For Windows specific error handler -#include "llwindebug.h" // For the invalid message handler -#endif - #include "llnotificationmanager.h" // +#if LL_MSVC +// disable boost::lexical_cast warning +#pragma warning (disable:4702) +#endif + // // Constants // @@ -277,7 +278,7 @@ void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_ { LLStringUtil::format_map_t args; args["AMOUNT"] = llformat("%d", amount); - LLFloaterBuyCurrency::buyCurrency(LLTrans::getString("giving", args), amount); + LLBuyCurrencyHTML::openCurrencyFloater( LLTrans::getString("giving", args), amount ); } } @@ -691,6 +692,52 @@ bool join_group_response(const LLSD& notification, const LLSD& response) return false; } + +static void highlight_inventory_items_in_panel(const std::vector<LLUUID>& items, LLInventoryPanel *inventory_panel) +{ + if (NULL == inventory_panel) return; + + for (std::vector<LLUUID>::const_iterator item_iter = items.begin(); + item_iter != items.end(); + ++item_iter) + { + const LLUUID& item_id = (*item_iter); + if(!highlight_offered_item(item_id)) + { + continue; + } + + LLInventoryItem* item = gInventory.getItem(item_id); + llassert(item); + if (!item) { + continue; + } + + LL_DEBUGS("Inventory_Move") << "Highlighting inventory item: " << item->getName() << ", " << item_id << LL_ENDL; + LLFolderView* fv = inventory_panel->getRootFolder(); + if (fv) + { + LLFolderViewItem* fv_item = fv->getItemByID(item_id); + if (fv_item) + { + LLFolderViewItem* fv_folder = fv_item->getParentFolder(); + if (fv_folder) + { + // Parent folders can be different in case of 2 consecutive drag and drop + // operations when the second one is started before the first one completes. + LL_DEBUGS("Inventory_Move") << "Open folder: " << fv_folder->getName() << LL_ENDL; + fv_folder->setOpen(TRUE); + if (fv_folder->isSelected()) + { + fv->changeSelection(fv_folder, FALSE); + } + } + fv->changeSelection(fv_item, TRUE); + } + } + } +} + static LLNotificationFunctorRegistration jgr_1("JoinGroup", join_group_response); static LLNotificationFunctorRegistration jgr_2("JoinedTooManyGroupsMember", join_group_response); static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_response); @@ -699,10 +746,13 @@ static LLNotificationFunctorRegistration jgr_3("JoinGroupCanAfford", join_group_ //----------------------------------------------------------------------------- // Instant Message //----------------------------------------------------------------------------- -class LLOpenAgentOffer : public LLInventoryFetchObserver +class LLOpenAgentOffer : public LLInventoryFetchItemsObserver { public: - LLOpenAgentOffer(const std::string& from_name) : mFromName(from_name) {} + LLOpenAgentOffer(const LLUUID& object_id, + const std::string& from_name) : + LLInventoryFetchItemsObserver(object_id), + mFromName(from_name) {} /*virtual*/ void done() { open_inventory_offer(mComplete, mFromName); @@ -713,6 +763,110 @@ private: std::string mFromName; }; +/** + * Class to observe adding of new items moved from the world to user's inventory to select them in inventory. + * + * We can't create it each time items are moved because "drop" event is sent separately for each + * element even while multi-dragging. We have to have the only instance of the observer. See EXT-4347. + */ +class LLViewerInventoryMoveFromWorldObserver : public LLInventoryAddItemByAssetObserver +{ +public: + LLViewerInventoryMoveFromWorldObserver() + : LLInventoryAddItemByAssetObserver() + , mActivePanel(NULL) + { + + } + + void setMoveIntoFolderID(const LLUUID& into_folder_uuid) {mMoveIntoFolderID = into_folder_uuid; } + +private: + /*virtual */void onAssetAdded(const LLUUID& asset_id) + { + // Store active Inventory panel. + mActivePanel = LLInventoryPanel::getActiveInventoryPanel(); + + // Store selected items (without destination folder) + mSelectedItems.clear(); + if (mActivePanel) + { + mSelectedItems = mActivePanel->getRootFolder()->getSelectionList(); + } + mSelectedItems.erase(mMoveIntoFolderID); + } + + /** + * Selects added inventory items watched by their Asset UUIDs if selection was not changed since + * all items were started to watch (dropped into a folder). + */ + void done() + { + // if selection is not changed since watch started lets hightlight new items. + if (mActivePanel && !isSelectionChanged()) + { + LL_DEBUGS("Inventory_Move") << "Selecting new items..." << LL_ENDL; + mActivePanel->clearSelection(); + highlight_inventory_items_in_panel(mAddedItems, mActivePanel); + } + } + + /** + * Returns true if selected inventory items were changed since moved inventory items were started to watch. + */ + bool isSelectionChanged() + { + const LLInventoryPanel * const current_active_panel = LLInventoryPanel::getActiveInventoryPanel(); + + if (NULL == mActivePanel || current_active_panel != mActivePanel) + { + return true; + } + + // get selected items (without destination folder) + selected_items_t selected_items = mActivePanel->getRootFolder()->getSelectionList(); + selected_items.erase(mMoveIntoFolderID); + + // compare stored & current sets of selected items + selected_items_t different_items; + std::set_symmetric_difference(mSelectedItems.begin(), mSelectedItems.end(), + selected_items.begin(), selected_items.end(), std::inserter(different_items, different_items.begin())); + + LL_DEBUGS("Inventory_Move") << "Selected firstly: " << mSelectedItems.size() + << ", now: " << selected_items.size() << ", difference: " << different_items.size() << LL_ENDL; + + return different_items.size() > 0; + } + + LLInventoryPanel *mActivePanel; + typedef std::set<LLUUID> selected_items_t; + selected_items_t mSelectedItems; + + /** + * UUID of FolderViewFolder into which watched items are moved. + * + * Destination FolderViewFolder becomes selected while mouse hovering (when dragged items are dropped). + * + * If mouse is moved out it set unselected and number of selected items is changed + * even if selected items in Inventory stay the same. + * So, it is used to update stored selection list. + * + * @see onAssetAdded() + * @see isSelectionChanged() + */ + LLUUID mMoveIntoFolderID; +}; + +LLViewerInventoryMoveFromWorldObserver* gInventoryMoveObserver = NULL; + +void set_dad_inventory_item(LLInventoryItem* inv_item, const LLUUID& into_folder_uuid) +{ + start_new_inventory_observer(); + + gInventoryMoveObserver->setMoveIntoFolderID(into_folder_uuid); + gInventoryMoveObserver->watchAsset(inv_item->getAssetUUID()); +} + //unlike the FetchObserver for AgentOffer, we only make one //instance of the AddedObserver for TaskOffers //and it never dies. We do this because we don't know the UUID of @@ -723,6 +877,33 @@ class LLOpenTaskOffer : public LLInventoryAddedObserver protected: /*virtual*/ void done() { + for (uuid_vec_t::iterator it = mAdded.begin(); it != mAdded.end();) + { + const LLUUID& item_uuid = *it; + bool was_moved = false; + LLInventoryObject* added_object = gInventory.getObject(item_uuid); + if (added_object) + { + // cast to item to get Asset UUID + LLInventoryItem* added_item = dynamic_cast<LLInventoryItem*>(added_object); + if (added_item) + { + const LLUUID& asset_uuid = added_item->getAssetUUID(); + if (gInventoryMoveObserver->isAssetWatched(asset_uuid)) + { + LL_DEBUGS("Inventory_Move") << "Found asset UUID: " << asset_uuid << LL_ENDL; + was_moved = true; + } + } + } + + if (was_moved) + { + it = mAdded.erase(it); + } + else ++it; + } + open_inventory_offer(mAdded, ""); mAdded.clear(); } @@ -751,13 +932,21 @@ void start_new_inventory_observer() gNewInventoryObserver = new LLOpenTaskOffer; gInventory.addObserver(gNewInventoryObserver); } + + if (!gInventoryMoveObserver) //inventory move from the world observer + { + // Observer is deleted by gInventory + gInventoryMoveObserver = new LLViewerInventoryMoveFromWorldObserver; + gInventory.addObserver(gInventoryMoveObserver); + } } -class LLDiscardAgentOffer : public LLInventoryFetchComboObserver +class LLDiscardAgentOffer : public LLInventoryFetchItemsObserver { LOG_CLASS(LLDiscardAgentOffer); public: LLDiscardAgentOffer(const LLUUID& folder_id, const LLUUID& object_id) : + LLInventoryFetchItemsObserver(object_id), mFolderID(folder_id), mObjectID(object_id) {} virtual ~LLDiscardAgentOffer() {} @@ -840,21 +1029,26 @@ bool check_offer_throttle(const std::string& from_name, bool check_only) { // Use the name of the last item giver, who is probably the person // spamming you. - std::ostringstream message; - message << LLAppViewer::instance()->getSecondLifeTitle(); + + LLStringUtil::format_map_t arg; + std::string log_msg; + std::ostringstream time ; + time<<OFFER_THROTTLE_TIME; + + arg["APP_NAME"] = LLAppViewer::instance()->getSecondLifeTitle(); + arg["TIME"] = time.str(); + if (!from_name.empty()) { - message << ": Items coming in too fast from " << from_name; + arg["FROM_NAME"] = from_name; + log_msg = LLTrans::getString("ItemsComingInTooFastFrom", arg); } else { - message << ": Items coming in too fast"; + log_msg = LLTrans::getString("ItemsComingInTooFast", arg); } - message << ", automatic preview disabled for " - << OFFER_THROTTLE_TIME << " seconds."; //this is kinda important, so actually put it on screen - std::string log_msg = message.str(); LLSD args; args["MESSAGE"] = log_msg; LLNotificationsUtil::add("SystemMessage", args); @@ -891,7 +1085,7 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name) //////////////////////////////////////////////////////////////////////////////// // Special handling for various types. - const LLAssetType::EType asset_type = item->getType(); + const LLAssetType::EType asset_type = item->getActualType(); if (check_offer_throttle(from_name, false)) // If we are throttled, don't display { LL_DEBUGS("Messaging") << "Highlighting inventory item: " << item->getUUID() << LL_ENDL; @@ -915,9 +1109,12 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name) } else if("group_offer" == from_name) { - // do not open inventory when we open group notice attachment because - // we already opened landmark info panel // "group_offer" is passed by LLOpenTaskGroupOffer + // Notification about added landmark will be generated under the "from_name.empty()" called from LLOpenTaskOffer::done(). + LLSD args; + args["type"] = "landmark"; + args["id"] = item_id; + LLSideTray::getInstance()->showPanel("panel_places", args); continue; } @@ -928,28 +1125,6 @@ void open_inventory_offer(const uuid_vec_t& items, const std::string& from_name) args["LANDMARK_NAME"] = item->getName(); args["FOLDER_NAME"] = std::string(parent_folder ? parent_folder->getName() : "unknown"); LLNotificationsUtil::add("LandmarkCreated", args); - // Created landmark is passed to Places panel to allow its editing. In fact panel should be already displayed. - // If the panel is closed we don't reopen it until created landmark is loaded. - //TODO*:: dserduk(7/12/09) remove LLPanelPlaces dependency from here - LLPanelPlaces *places_panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->getPanel("panel_places")); - if (places_panel) - { - // Landmark creation handling is moved to LLPanelPlaces::showAddedLandmarkInfo() - // TODO* LLPanelPlaces dependency is going to be removed. See EXT-4347. - //if("create_landmark" == places_panel->getPlaceInfoType() && !places_panel->getItem()) - //{ - // places_panel->setItem(item); - //} - //else - // we are opening a group notice attachment - if("create_landmark" != places_panel->getPlaceInfoType()) - { - LLSD args; - args["type"] = "landmark"; - args["id"] = item_id; - LLSideTray::getInstance()->showPanel("panel_places", args); - } - } } } break; @@ -1056,7 +1231,6 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, bool matches(const LLNotificationPtr notification) const { if(notification->getName() == "ObjectGiveItem" - || notification->getName() == "ObjectGiveItemUnknownUser" || notification->getName() == "UserGiveItem") { return (notification->getPayload()["from_id"].asUUID() == blocked_id); @@ -1071,6 +1245,16 @@ void inventory_offer_mute_callback(const LLUUID& blocked_id, gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(blocked_id)); } +LLOfferInfo::LLOfferInfo() + : LLNotificationResponderInterface() + , mFromGroup(FALSE) + , mFromObject(FALSE) + , mIM(IM_NOTHING_SPECIAL) + , mType(LLAssetType::AT_NONE) + , mPersist(false) +{ +} + LLOfferInfo::LLOfferInfo(const LLSD& sd) { mIM = (EInstantMessage)sd["im_type"].asInteger(); @@ -1084,6 +1268,7 @@ LLOfferInfo::LLOfferInfo(const LLSD& sd) mFromName = sd["from_name"].asString(); mDesc = sd["description"].asString(); mHost = LLHost(sd["sender"].asString()); + mPersist = sd["persist"].asBoolean(); } LLOfferInfo::LLOfferInfo(const LLOfferInfo& info) @@ -1099,6 +1284,7 @@ LLOfferInfo::LLOfferInfo(const LLOfferInfo& info) mFromName = info.mFromName; mDesc = info.mDesc; mHost = info.mHost; + mPersist = info.mPersist; } LLSD LLOfferInfo::asLLSD() @@ -1115,9 +1301,15 @@ LLSD LLOfferInfo::asLLSD() sd["from_name"] = mFromName; sd["description"] = mDesc; sd["sender"] = mHost.getIPandPort(); + sd["persist"] = mPersist; return sd; } +void LLOfferInfo::fromLLSD(const LLSD& params) +{ + *this = params; +} + void LLOfferInfo::send_auto_receive_response(void) { LLMessageSystem* msg = gMessageSystem; @@ -1157,6 +1349,21 @@ void LLOfferInfo::send_auto_receive_response(void) } } +void LLOfferInfo::handleRespond(const LLSD& notification, const LLSD& response) +{ + initRespondFunctionMap(); + + const std::string name = notification["name"].asString(); + if(mRespondFunctions.find(name) == mRespondFunctions.end()) + { + llwarns << "Unexpected notification name : " << name << llendl; + llassert(!"Unexpected notification name"); + return; + } + + mRespondFunctions[name](notification, response); +} + bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& response) { LLChat chat; @@ -1203,11 +1410,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // This is an offer from an agent. In this case, the back // end has already copied the items into your inventory, // so we can fetch it out of our inventory. - uuid_vec_t items; - items.push_back(mObjectID); - LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(from_string); - open_agent_offer->fetchItems(items); - if(catp || (itemp && itemp->isComplete())) + LLOpenAgentOffer* open_agent_offer = new LLOpenAgentOffer(mObjectID, from_string); + open_agent_offer->startFetch(); + if(catp || (itemp && itemp->isFinished())) { open_agent_offer->done(); } @@ -1264,13 +1469,9 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& // Disabled logging to old chat floater to fix crash in group notices - EXT-4149 // LLFloaterChat::addChatHistory(chat); - uuid_vec_t folders; - uuid_vec_t items; - items.push_back(mObjectID); - LLDiscardAgentOffer* discard_agent_offer; - discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID); - discard_agent_offer->fetch(folders, items); - if(catp || (itemp && itemp->isComplete())) + LLDiscardAgentOffer* discard_agent_offer = new LLDiscardAgentOffer(mFolderID, mObjectID); + discard_agent_offer->startFetch(); + if (catp || (itemp && itemp->isFinished())) { discard_agent_offer->done(); } @@ -1299,7 +1500,10 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& gInventory.addObserver(opener); } - delete this; + if(!mPersist) + { + delete this; + } return false; } @@ -1465,10 +1669,34 @@ bool LLOfferInfo::inventory_task_offer_callback(const LLSD& notification, const gInventory.addObserver(opener); } - delete this; + if(!mPersist) + { + delete this; + } return false; } +class LLPostponedOfferNotification: public LLPostponedNotification +{ +protected: + /* virtual */ + void modifyNotificationParams() + { + LLSD substitutions = mParams.substitutions; + substitutions["NAME"] = mName; + mParams.substitutions = substitutions; + } +}; + +void LLOfferInfo::initRespondFunctionMap() +{ + if(mRespondFunctions.empty()) + { + mRespondFunctions["ObjectGiveItem"] = boost::bind(&LLOfferInfo::inventory_task_offer_callback, this, _1, _2); + mRespondFunctions["UserGiveItem"] = boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2); + } +} + void inventory_offer_handler(LLOfferInfo* info) { //Until throttling is implmented, busy mode should reject inventory instead of silently @@ -1535,30 +1763,6 @@ void inventory_offer_handler(LLOfferInfo* info) return; } - // Name cache callbacks don't store userdata, so can't save - // off the LLOfferInfo. Argh. - BOOL name_found = FALSE; - if (info->mFromGroup) - { - std::string group_name; - if (gCacheName->getGroupName(info->mFromID, group_name)) - { - args["FIRST"] = group_name; - args["LAST"] = ""; - name_found = TRUE; - } - } - else - { - std::string first_name, last_name; - if (gCacheName->getName(info->mFromID, first_name, last_name)) - { - args["FIRST"] = first_name; - args["LAST"] = last_name; - name_found = TRUE; - } - } - // If mObjectID is null then generate the object_id based on msg to prevent // multiple creation of chiclets for same object. LLUUID object_id = info->mObjectID; @@ -1585,10 +1789,11 @@ void inventory_offer_handler(LLOfferInfo* info) // 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"; + p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info)); + info->mPersist = true; + p.name = "ObjectGiveItem"; // Pop up inv offer chiclet and let the user accept (keep), or reject (and silently delete) the inventory. - LLNotifications::instance().add(p); + LLPostponedNotification::add<LLPostponedOfferNotification>(p, info->mFromID, info->mFromGroup == TRUE); } else // Agent -> Agent Inventory Offer { @@ -1597,15 +1802,14 @@ void inventory_offer_handler(LLOfferInfo* info) // *TODO fix memory leak // inventory_offer_callback() is not invoked if user received notification and // closes viewer(without responding the notification) - p.substitutions(args).payload(payload).functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, info, _1, _2)); + p.substitutions(args).payload(payload).functor.responder(LLNotificationResponderPtr(info)); + info->mPersist = true; p.name = "UserGiveItem"; // Prefetch the item into your local inventory. - uuid_vec_t items; - items.push_back(info->mObjectID); - LLInventoryFetchObserver* fetch_item = new LLInventoryFetchObserver(); - fetch_item->fetchItems(items); - if(fetch_item->isEverythingComplete()) + LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID); + fetch_item->startFetch(); + if(fetch_item->isFinished()) { fetch_item->done(); } @@ -1620,7 +1824,8 @@ void inventory_offer_handler(LLOfferInfo* info) // Inform user that there is a script floater via toast system { payload["give_inventory_notification"] = TRUE; - LLNotificationPtr notification = LLNotifications::instance().add(p.payload(payload)); + p.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>(p, info->mFromID, false); } } } @@ -1697,6 +1902,64 @@ protected: } }; +static bool parse_lure_bucket(const std::string& bucket, + U64& region_handle, + LLVector3& pos, + LLVector3& look_at, + U8& region_access) +{ + // tokenize the bucket + typedef boost::tokenizer<boost::char_separator<char> > tokenizer; + boost::char_separator<char> sep("|", "", boost::keep_empty_tokens); + tokenizer tokens(bucket, sep); + tokenizer::iterator iter = tokens.begin(); + + S32 gx,gy,rx,ry,rz,lx,ly,lz; + try + { + gx = boost::lexical_cast<S32>((*(iter)).c_str()); + gy = boost::lexical_cast<S32>((*(++iter)).c_str()); + rx = boost::lexical_cast<S32>((*(++iter)).c_str()); + ry = boost::lexical_cast<S32>((*(++iter)).c_str()); + rz = boost::lexical_cast<S32>((*(++iter)).c_str()); + lx = boost::lexical_cast<S32>((*(++iter)).c_str()); + ly = boost::lexical_cast<S32>((*(++iter)).c_str()); + lz = boost::lexical_cast<S32>((*(++iter)).c_str()); + } + catch( boost::bad_lexical_cast& ) + { + LL_WARNS("parse_lure_bucket") + << "Couldn't parse lure bucket." + << LL_ENDL; + return false; + } + // Grab region access + region_access = SIM_ACCESS_MIN; + if (++iter != tokens.end()) + { + std::string access_str((*iter).c_str()); + LLStringUtil::trim(access_str); + if ( access_str == "A" ) + { + region_access = SIM_ACCESS_ADULT; + } + else if ( access_str == "M" ) + { + region_access = SIM_ACCESS_MATURE; + } + else if ( access_str == "PG" ) + { + region_access = SIM_ACCESS_PG; + } + } + + pos.setVec((F32)rx, (F32)ry, (F32)rz); + look_at.setVec((F32)lx, (F32)ly, (F32)lz); + + region_handle = to_region_handle(gx, gy); + return true; +} + void process_improved_im(LLMessageSystem *msg, void **user_data) { if (gNoRender) @@ -1796,7 +2059,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // initiated by the other party) then... std::string my_name; LLAgentUI::buildFullname(my_name); - std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2"); + std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); pack_instant_message( gMessageSystem, gAgent.getID(), @@ -2059,7 +2322,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLSD args; args["MESSAGE"] = message; - LLNotificationsUtil::add("JoinGroup", args, payload, join_group_response); + // we shouldn't pass callback functor since it is registered in LLFunctorRegistration + LLNotificationsUtil::add("JoinGroup", args, payload); } } break; @@ -2120,10 +2384,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) if (is_muted) { // Prefetch the offered item so that it can be discarded by the appropriate observer. (EXT-4331) - uuid_vec_t items; - items.push_back(info->mObjectID); - LLInventoryFetchObserver* fetch_item = new LLInventoryFetchObserver(); - fetch_item->fetchItems(items); + LLInventoryFetchItemsObserver* fetch_item = new LLInventoryFetchItemsObserver(info->mObjectID); + fetch_item->startFetch(); delete fetch_item; // Same as closing window @@ -2229,10 +2491,13 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) chat.mFromID = from_id ^ gAgent.getSessionID(); } + chat.mSourceType = CHAT_SOURCE_OBJECT; + if(SYSTEM_FROM == name) { // System's UUID is NULL (fixes EXT-4766) chat.mFromID = LLUUID::null; + chat.mSourceType = CHAT_SOURCE_SYSTEM; } LLSD query_string; @@ -2246,15 +2511,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) chat.mURL = LLSLURL("objectim", session_id, "").getSLURLString(); chat.mText = message; - chat.mSourceType = CHAT_SOURCE_OBJECT; // Note: lie to Nearby Chat, pretending that this is NOT an IM, because // IMs from obejcts don't open IM sessions. LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD()); - if(nearby_chat) + if(SYSTEM_FROM != name && nearby_chat) { + chat.mOwnerID = from_id; LLSD args; - args["owner_id"] = from_id; args["slurl"] = location; args["type"] = LLNotificationsUI::NT_NEARBYCHAT; LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); @@ -2325,15 +2589,34 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { + LLVector3 pos, look_at; + U64 region_handle; + U8 region_access; + std::string region_info = ll_safe_string((char*)binary_bucket, binary_bucket_size); + std::string region_access_str = LLStringUtil::null; + std::string region_access_icn = LLStringUtil::null; + + if (parse_lure_bucket(region_info, region_handle, pos, look_at, region_access)) + { + region_access_str = LLViewerRegion::accessToString(region_access); + region_access_icn = LLViewerRegion::getAccessIcon(region_access); + } + LLSD args; // *TODO: Translate -> [FIRST] [LAST] (maybe) args["NAME_SLURL"] = LLSLURL("agent", from_id, "about").getSLURLString(); args["MESSAGE"] = message; + args["MATURITY_STR"] = region_access_str; + args["MATURITY_ICON"] = region_access_icn; LLSD payload; payload["from_id"] = from_id; payload["lure_id"] = session_id; payload["godlike"] = FALSE; - LLNotificationsUtil::add("TeleportOffered", args, payload); + + LLNotification::Params params("TeleportOffered"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); } } break; @@ -2402,7 +2685,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) else { args["[MESSAGE]"] = message; - LLNotificationsUtil::add("OfferFriendship", args, payload); + LLNotification::Params params("OfferFriendship"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); } } } @@ -2446,7 +2732,7 @@ void busy_message (LLMessageSystem* msg, LLUUID from_id) { std::string my_name; LLAgentUI::buildFullname(my_name); - std::string response = gSavedPerAccountSettings.getString("BusyModeResponse2"); + std::string response = gSavedPerAccountSettings.getString("BusyModeResponse"); pack_instant_message( gMessageSystem, gAgent.getID(), @@ -2762,7 +3048,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // object inspect for an object that is chatting with you LLSD args; args["type"] = LLNotificationsUI::NT_NEARBYCHAT; - args["owner_id"] = owner_id; + chat.mOwnerID = owner_id; LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args); } @@ -2843,7 +3129,9 @@ void process_teleport_progress(LLMessageSystem* msg, void**) class LLFetchInWelcomeArea : public LLInventoryFetchDescendentsObserver { public: - LLFetchInWelcomeArea() {} + LLFetchInWelcomeArea(const uuid_vec_t &ids) : + LLInventoryFetchDescendentsObserver(ids) + {} virtual void done() { LLIsType is_landmark(LLAssetType::AT_LANDMARK); @@ -2854,8 +3142,8 @@ public: LLInventoryModel::cat_array_t land_cats; LLInventoryModel::item_array_t land_items; - uuid_vec_t::iterator it = mCompleteFolders.begin(); - uuid_vec_t::iterator end = mCompleteFolders.end(); + uuid_vec_t::iterator it = mComplete.begin(); + uuid_vec_t::iterator end = mComplete.end(); for(; it != end; ++it) { gInventory.collectDescendentsIf( @@ -2925,9 +3213,9 @@ BOOL LLPostTeleportNotifiers::tick() folders.push_back(folder_id); if(!folders.empty()) { - LLFetchInWelcomeArea* fetcher = new LLFetchInWelcomeArea; - fetcher->fetchDescendents(folders); - if(fetcher->isEverythingComplete()) + LLFetchInWelcomeArea* fetcher = new LLFetchInWelcomeArea(folders); + fetcher->startFetch(); + if(fetcher->isFinished()) { fetcher->done(); } @@ -4182,6 +4470,9 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) } gAgentCamera.setForceMouselook(force_mouselook); + // Forcing turning off flying here to prevent flying after pressing "Stand" + // to stand up from an object. See EXT-1655. + gAgent.setFlying(FALSE); LLViewerObject* object = gObjectList.findObject(sitObjectID); if (object) @@ -4550,11 +4841,12 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) if(boost::regex_match(desc, matches, expr)) { // Name of full localizable notification string - // there are three types of this string- with name of receiver and reason of payment, - // without name and without reason (but not simultaneously) + // there are four types of this string- with name of receiver and reason of payment, + // without name and without reason (both may also be absent simultaneously). // example of string without name - You paid L$100 to create a group. // example of string without reason - You paid Smdby Linden L$100. // example of string with reason and name - You paid Smbdy Linden L$100 for a land access pass. + // example of string with no info - You paid L$50. std::string line = "you_paid_ldollars_no_name"; // arguments of string which will be in notification @@ -4575,7 +4867,7 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) std::string reason = std::string(matches[3]); if (reason.empty()) { - line = "you_paid_ldollars_no_reason"; + line = name.empty() ? "you_paid_ldollars_no_info" : "you_paid_ldollars_no_reason"; } else { @@ -4619,6 +4911,10 @@ bool handle_special_notification_callback(const LLSD& notification, const LLSD& gSavedSettings.setU32("PreferredMaturity", preferredMaturity); gAgent.sendMaturityPreferenceToServer(preferredMaturity); + // notify user that the maturity preference has been changed + LLSD args; + args["RATING"] = LLViewerRegion::accessToString(preferredMaturity); + LLNotificationsUtil::add("PreferredMaturityChanged", args); } return false; @@ -5227,7 +5523,7 @@ void process_derez_container(LLMessageSystem *msg, void**) } void container_inventory_arrived(LLViewerObject* object, - InventoryObjectList* inventory, + LLInventoryObject::object_list_t* inventory, S32 serial_num, void* data) { @@ -5247,8 +5543,8 @@ void container_inventory_arrived(LLViewerObject* object, LLFolderType::FT_NONE, LLTrans::getString("AcquiredItems")); - InventoryObjectList::const_iterator it = inventory->begin(); - InventoryObjectList::const_iterator end = inventory->end(); + LLInventoryObject::object_list_t::const_iterator it = inventory->begin(); + LLInventoryObject::object_list_t::const_iterator end = inventory->end(); for ( ; it != end; ++it) { if ((*it)->getType() != LLAssetType::AT_CATEGORY) @@ -5284,7 +5580,7 @@ void container_inventory_arrived(LLViewerObject* object, { // we're going to get one fake root category as well as the // one actual object - InventoryObjectList::iterator it = inventory->begin(); + LLInventoryObject::object_list_t::iterator it = inventory->begin(); if ((*it)->getType() == LLAssetType::AT_CATEGORY) { @@ -6172,3 +6468,4 @@ void LLOfferInfo::forceResponse(InventoryOfferResponse response) params.functor.function(boost::bind(&LLOfferInfo::inventory_offer_callback, this, _1, _2)); LLNotifications::instance().forceResponse(params, response); } + |