Issue 1151: Add share to LLAvatarActions

Syncs LLGiveInventory and LLFloaterAvatarPicker with upstream.
Syncsyncsync~

Translators:
menu_inventory.xml menu_radar.xml and menu_avs_list.xml: Share
notifications.xml: ShareNotification, ShareItemsConfirmation, ShareFolderConfirmation, ItemsShared
strings.xml: share_alert
This commit is contained in:
Inusaito Sayori
2014-10-17 00:33:33 -04:00
parent 2d53641cd0
commit e98792209e
21 changed files with 937 additions and 136 deletions

View File

@@ -906,7 +906,6 @@ AIHTTPTimeoutPolicy const* AIHTTPTimeoutPolicy::getTimeoutPolicyByName(std::stri
// Policy name Policy // Policy name Policy
P(assetReportHandler); P(assetReportHandler);
P(avatarPickerResponder);
P(authHandler); P(authHandler);
P(avatarNameResponder); P(avatarNameResponder);
P2(baseCapabilitiesComplete, transfer_18s_connect_5s); P2(baseCapabilitiesComplete, transfer_18s_connect_5s);

View File

@@ -444,6 +444,7 @@ set(viewer_SOURCE_FILES
llscrollingpanelparam.cpp llscrollingpanelparam.cpp
llscrollingpanelparambase.cpp llscrollingpanelparambase.cpp
llselectmgr.cpp llselectmgr.cpp
llshareavatarhandler.cpp
llsky.cpp llsky.cpp
llslurl.cpp llslurl.cpp
llspatialpartition.cpp llspatialpartition.cpp

View File

@@ -5084,6 +5084,39 @@ This should be as low as possible, but too low may break functionality</string>
<key>Value</key> <key>Value</key>
<integer>0</integer> <integer>0</integer>
</map> </map>
<key>ContextConeInAlpha</key>
<map>
<key>Comment</key>
<string>Cone In Alpha</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>0.0</real>
</map>
<key>ContextConeOutAlpha</key>
<map>
<key>Comment</key>
<string>Cone Out Alpha</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>1.0</real>
</map>
<key>ContextConeFadeTime</key>
<map>
<key>Comment</key>
<string>Cone Fade Time</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
<string>F32</string>
<key>Value</key>
<real>.08</real>
</map>
<key>CookiesEnabled</key> <key>CookiesEnabled</key>
<map> <map>
<key>Comment</key> <key>Comment</key>

View File

@@ -37,20 +37,26 @@
#include "llagent.h" #include "llagent.h"
#include "llcallingcard.h" // for LLAvatarTracker #include "llcallingcard.h" // for LLAvatarTracker
#include "llfloateravatarinfo.h" #include "llfloateravatarinfo.h"
#include "llfloateravatarpicker.h" // for LLFloaterAvatarPicker
#include "llfloaterchatterbox.h"
#include "llfloatergroupbulkban.h" #include "llfloatergroupbulkban.h"
#include "llfloatergroupinvite.h" #include "llfloatergroupinvite.h"
#include "llfloatergroups.h" #include "llfloatergroups.h"
#include "llfloaterwebprofile.h" #include "llfloaterwebprofile.h"
#include "llfloaterworldmap.h" #include "llfloaterworldmap.h"
#include "llgiveinventory.h"
#include "llgivemoney.h" #include "llgivemoney.h"
#include "llinventorybridge.h"
#include "llinventoryfunctions.h"
#include "llinventorypanel.h"
#include "llimview.h" // for gIMMgr #include "llimview.h" // for gIMMgr
#include "llinventoryobserver.h"
#include "llmutelist.h" #include "llmutelist.h"
#include "llpanelprofile.h" #include "llpanelprofile.h"
#include "lltrans.h" #include "lltrans.h"
#include "llvoiceclient.h" #include "llvoiceclient.h"
#include "llweb.h" #include "llweb.h"
#include "llslurl.h" // IDEVO #include "llslurl.h" // IDEVO
#include "llpanelmaininventory.h"
#include "llavatarname.h" #include "llavatarname.h"
#include "llagentui.h" #include "llagentui.h"
// [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0) // [RLVa:KB] - Checked: 2011-04-11 (RLVa-1.3.0)
@@ -569,7 +575,262 @@ void LLAvatarActions::csr(const LLUUID& id)
LLWeb::loadURL(url); LLWeb::loadURL(url);
} }
// Singu TODO: Share inventory code block should live here //static
void LLAvatarActions::share(const LLUUID& id)
{
/*
LLSD key;
LLFloaterSidePanelContainer::showPanel("inventory", key);
LLFloaterReg::showInstance("im_container");
*/
LLInventoryView::getActiveInventory()->setVisible(true);
LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, id);
if (!gIMMgr->hasSession(session_id))
{
startIM(id);
}
if (gIMMgr->hasSession(session_id))
{
// we should always get here, but check to verify anyways
LLIMMgr::getInstance()->addMessage(session_id, LLUUID::null, SYSTEM_FROM, LLTrans::getString("share_alert"));
LLFloaterChatterBox::showInstance(session_id);
}
}
namespace action_give_inventory
{
/**
* Returns a pointer to 'Add More' inventory panel of Edit Outfit SP.
*
static LLInventoryPanel* get_outfit_editor_inventory_panel()
{
LLPanelOutfitEdit* panel_outfit_edit = dynamic_cast<LLPanelOutfitEdit*>(LLFloaterSidePanelContainer::getPanel("appearance", "panel_outfit_edit"));
if (NULL == panel_outfit_edit) return NULL;
LLInventoryPanel* inventory_panel = panel_outfit_edit->findChild<LLInventoryPanel>("folder_view");
return inventory_panel;
}*/
/**
* @return active inventory panel, or NULL if there's no such panel
*/
static LLInventoryPanel* get_active_inventory_panel()
{
LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
/*if (!active_panel)
{
active_panel = get_outfit_editor_inventory_panel();
}*/
return active_panel;
}
/**
* Checks My Inventory visibility.
*/
static bool is_give_inventory_acceptable()
{
// check selection in the panel
const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty()) return false; // nothing selected
bool acceptable = false;
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
// any category can be offered.
if (inv_cat)
{
acceptable = true;
continue;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
// check if inventory item can be given
if (LLGiveInventory::isInventoryGiveAcceptable(inv_item))
{
acceptable = true;
continue;
}
// there are neither item nor category in inventory
acceptable = false;
break;
}
return acceptable;
}
static void build_items_string(const std::set<LLUUID>& inventory_selected_uuids , std::string& items_string)
{
llassert(inventory_selected_uuids.size() > 0);
const std::string& separator = LLTrans::getString("words_separator");
for (std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin(); ; )
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (NULL != inv_cat)
{
items_string = inv_cat->getName();
break;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
if (NULL != inv_item)
{
items_string.append(inv_item->getName());
}
if(++it == inventory_selected_uuids.end())
{
break;
}
items_string.append(separator);
}
}
struct LLShareInfo : public LLSingleton<LLShareInfo>
{
std::vector<LLAvatarName> mAvatarNames;
uuid_vec_t mAvatarUuids;
};
static void give_inventory_cb(const LLSD& notification, const LLSD& response)
{
S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
// if Cancel pressed
if (option == 1)
{
return;
}
const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty())
{
return;
}
S32 count = LLShareInfo::instance().mAvatarNames.size();
bool shared = count && !inventory_selected_uuids.empty();
// iterate through avatars
for(S32 i = 0; i < count; ++i)
{
const LLUUID& avatar_uuid = LLShareInfo::instance().mAvatarUuids[i];
// We souldn't open IM session, just calculate session ID for logging purpose. See EXT-6710
const LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL, avatar_uuid);
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
const std::set<LLUUID>::const_iterator it_end = inventory_selected_uuids.end();
const std::string& separator = LLTrans::getString("words_separator");
std::string noncopy_item_names;
LLSD noncopy_items = LLSD::emptyArray();
// iterate through selected inventory objects
for (; it != it_end; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (inv_cat)
{
if (!LLGiveInventory::doGiveInventoryCategory(avatar_uuid, inv_cat, session_id, "ItemsShared"))
{
shared = false;
}
break;
}
LLViewerInventoryItem* inv_item = gInventory.getItem(*it);
if (!inv_item->getPermissions().allowCopyBy(gAgentID))
{
if (!noncopy_item_names.empty())
{
noncopy_item_names.append(separator);
}
noncopy_item_names.append(inv_item->getName());
noncopy_items.append(*it);
}
else
{
if (!LLGiveInventory::doGiveInventoryItem(avatar_uuid, inv_item, session_id))
{
shared = false;
}
}
}
if (noncopy_items.beginArray() != noncopy_items.endArray())
{
LLSD substitutions;
substitutions["ITEMS"] = noncopy_item_names;
LLSD payload;
payload["agent_id"] = avatar_uuid;
payload["items"] = noncopy_items;
payload["success_notification"] = "ItemsShared";
LLNotificationsUtil::add("CannotCopyWarning", substitutions, payload,
&LLGiveInventory::handleCopyProtectedItem);
shared = false;
break;
}
}
if (shared)
{
if (LLFloaterAvatarPicker::instanceExists()) LLFloaterAvatarPicker::instance().close();
LLNotificationsUtil::add("ItemsShared");
}
}
/**
* Performs "give inventory" operations for provided avatars.
*
* Sends one requests to give all selected inventory items for each passed avatar.
* Avatars are represent by two vectors: names and UUIDs which must be sychronized with each other.
*
* @param avatar_names - avatar names request to be sent.
* @param avatar_uuids - avatar names request to be sent.
*/
static void give_inventory(const uuid_vec_t& avatar_uuids, const std::vector<LLAvatarName> avatar_names)
{
llassert(avatar_names.size() == avatar_uuids.size());
const std::set<LLUUID> inventory_selected_uuids = LLAvatarActions::getInventorySelectedUUIDs();
if (inventory_selected_uuids.empty())
{
return;
}
std::string residents;
LLAvatarActions::buildResidentsString(avatar_names, residents);
std::string items;
build_items_string(inventory_selected_uuids, items);
int folders_count = 0;
std::set<LLUUID>::const_iterator it = inventory_selected_uuids.begin();
//traverse through selected inventory items and count folders among them
for ( ; it != inventory_selected_uuids.end() && folders_count <=1 ; ++it)
{
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(*it);
if (NULL != inv_cat)
{
folders_count++;
}
}
// EXP-1599
// In case of sharing multiple folders, make the confirmation
// dialog contain a warning that only one folder can be shared at a time.
std::string notification = (folders_count > 1) ? "ShareFolderConfirmation" : "ShareItemsConfirmation";
LLSD substitutions;
substitutions["RESIDENTS"] = residents;
substitutions["ITEMS"] = items;
LLShareInfo::instance().mAvatarNames = avatar_names;
LLShareInfo::instance().mAvatarUuids = avatar_uuids;
LLNotificationsUtil::add(notification, substitutions, LLSD(), &give_inventory_cb);
}
}
// static // static
void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string) void LLAvatarActions::buildResidentsString(std::vector<LLAvatarName> avatar_names, std::string& residents_string)
@@ -611,7 +872,118 @@ void LLAvatarActions::buildResidentsString(const uuid_vec_t& avatar_uuids, std::
} }
} }
// Singu TODO: Share inventory code block should live here, too //static
std::set<LLUUID> LLAvatarActions::getInventorySelectedUUIDs()
{
LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
return active_panel ? active_panel->getRootFolder()->getSelectionList() : std::set<LLUUID>();
/*std::set<LLFolderViewItem*> inventory_selected;
LLInventoryPanel* active_panel = action_give_inventory::get_active_inventory_panel();
if (active_panel)
{
inventory_selected= active_panel->getRootFolder()->getSelectionList();
}
if (inventory_selected.empty())
{
LLSidepanelInventory *sidepanel_inventory = LLFloaterSidePanelContainer::getPanel<LLSidepanelInventory>("inventory");
if (sidepanel_inventory)
{
inventory_selected= sidepanel_inventory->getInboxSelectionList();
}
}
std::set<LLUUID> inventory_selected_uuids;
for (std::set<LLFolderViewItem*>::iterator it = inventory_selected.begin(), end_it = inventory_selected.end();
it != end_it;
++it)
{
inventory_selected_uuids.insert(static_cast<LLFolderViewModelItemInventory*>((*it)->getViewModelItem())->getUUID());
}
return inventory_selected_uuids;*/
}
//static
void LLAvatarActions::shareWithAvatars(LLView * panel)
{
using namespace action_give_inventory;
LLFloater* root_floater = gFloaterView->getParentFloater(panel);
LLFloaterAvatarPicker* picker =
LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE, FALSE, root_floater->getName());
if (!picker)
{
return;
}
picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable));
picker->openFriendsTab();
if (root_floater)
{
root_floater->addDependentFloater(picker);
}
LLNotificationsUtil::add("ShareNotification");
}
// static
bool LLAvatarActions::canShareSelectedItems(LLInventoryPanel* inv_panel /* = NULL*/)
{
using namespace action_give_inventory;
if (!inv_panel)
{
LLInventoryPanel* active_panel = get_active_inventory_panel();
if (!active_panel) return false;
inv_panel = active_panel;
}
// check selection in the panel
LLFolderView* root_folder = inv_panel->getRootFolder();
if (!root_folder)
{
return false;
}
const std::set<LLUUID> inventory_selected = root_folder->getSelectionList();
if (inventory_selected.empty()) return false; // nothing selected
bool can_share = true;
const LLUUID& trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH); // <alchemy/>
std::set<LLUUID>::const_iterator it = inventory_selected.begin();
const std::set<LLUUID>::const_iterator it_end = inventory_selected.end();
for (; it != it_end; ++it)
{
const LLUUID id(*it);
LLViewerInventoryCategory* inv_cat = gInventory.getCategory(id);
// any category can be offered.
if (inv_cat && !gInventory.isObjectDescendentOf(inv_cat->getUUID(), trash_id)) // <alchemy/>
{
continue;
}
// check if inventory item can be given
else if (!inv_cat && gInventory.isObjectDescendentOf(id, gInventory.getRootFolderID())) // Singu Note: These three ifs comprise the item half of LLInvFVBridge::canShare, which LL calls here.
if (LLViewerInventoryItem* item = gInventory.getItem(id))
if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item) && LLGiveInventory::isInventoryGiveAcceptable(item))
/*
LLFolderViewItem* item = *it;
if (!item) return false;
LLInvFVBridge* bridge = dynamic_cast<LLInvFVBridge*>(item->getViewModelItem());
if (bridge && bridge->canShare())
*/
{
continue;
}
// there are neither item nor category in inventory
can_share = false;
break;
}
return can_share;
}
// static // static
void LLAvatarActions::toggleBlock(const LLUUID& id) void LLAvatarActions::toggleBlock(const LLUUID& id)
@@ -898,6 +1270,21 @@ bool LLAvatarActions::canBlock(const LLUUID& id)
return !is_self && !is_linden; return !is_self && !is_linden;
} }
//static
bool LLAvatarActions::isAgentMappable(const LLUUID& agent_id)
{
const LLRelationship* buddy_info = NULL;
bool is_friend = LLAvatarActions::isFriend(agent_id);
if (is_friend)
buddy_info = LLAvatarTracker::instance().getBuddyInfo(agent_id);
return (buddy_info &&
buddy_info->isOnline() &&
buddy_info->isRightGrantedFrom(LLRelationship::GRANT_MAP_LOCATION)
);
}
// static // static
void LLAvatarActions::copyUUIDs(const uuid_vec_t& ids) void LLAvatarActions::copyUUIDs(const uuid_vec_t& ids)
{ {

View File

@@ -28,7 +28,9 @@
#define LL_LLAVATARACTIONS_H #define LL_LLAVATARACTIONS_H
class LLAvatarName; class LLAvatarName;
class LLInventoryPanel;
class LLFloater; class LLFloater;
class LLView;
/** /**
* Friend-related actions (add, remove, offer teleport, etc) * Friend-related actions (add, remove, offer teleport, etc)
@@ -108,6 +110,16 @@ public:
static void teleportRequest(const LLUUID& id); static void teleportRequest(const LLUUID& id);
static void teleport_request_callback(const LLSD& notification, const LLSD& response); static void teleport_request_callback(const LLSD& notification, const LLSD& response);
/**
* Share items with the avatar.
*/
static void share(const LLUUID& id);
/**
* Share items with the picked avatars.
*/
static void shareWithAvatars(LLView * panel);
/** /**
* Block/unblock the avatar. * Block/unblock the avatar.
*/ */
@@ -190,6 +202,20 @@ public:
*/ */
static bool canOfferTeleport(const uuid_vec_t& ids); static bool canOfferTeleport(const uuid_vec_t& ids);
/**
* Checks whether all items selected in the given inventory panel can be shared
*
* @param inv_panel Inventory panel to get selection from. If NULL, the active inventory panel is used.
*
* @return false if the selected items cannot be shared or the active inventory panel cannot be obtained
*/
static bool canShareSelectedItems(LLInventoryPanel* inv_panel = NULL);
/**
* Checks whether agent is mappable
*/
static bool isAgentMappable(const LLUUID& agent_id);
/** /**
* Builds a string of residents' display names separated by "words_separator" string. * Builds a string of residents' display names separated by "words_separator" string.
* *
@@ -206,6 +232,8 @@ public:
*/ */
static void buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string); static void buildResidentsString(const uuid_vec_t& avatar_uuids, std::string& residents_string);
static std::set<LLUUID> getInventorySelectedUUIDs();
/** /**
* Copy the selected avatar's UUID to clipboard * Copy the selected avatar's UUID to clipboard
*/ */

View File

@@ -50,6 +50,7 @@
#include "llscrolllistitem.h" #include "llscrolllistitem.h"
#include "lltabcontainer.h" #include "lltabcontainer.h"
#include "lluictrlfactory.h" #include "lluictrlfactory.h"
#include "lldraghandle.h"
#include "message.h" #include "message.h"
@@ -58,17 +59,21 @@ static std::map<LLUUID, LLAvatarName> sAvatarNameMap;
LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback, LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
BOOL allow_multiple, BOOL allow_multiple,
BOOL closeOnSelect) BOOL closeOnSelect,
BOOL skip_agent,
const std::string& name,
LLView * frustumOrigin)
{ {
// *TODO: Use a key to allow this not to be an effective singleton // *TODO: Use a key to allow this not to be an effective singleton
LLFloaterAvatarPicker* floater =
LLFloaterAvatarPicker* floater = getInstance(); getInstance();
floater->open(); floater->open();
floater->mSelectionCallback = callback; floater->mSelectionCallback = callback;
floater->setAllowMultiple(allow_multiple); floater->setAllowMultiple(allow_multiple);
floater->mNearMeListComplete = FALSE; floater->mNearMeListComplete = FALSE;
floater->mCloseOnSelect = closeOnSelect; floater->mCloseOnSelect = closeOnSelect;
floater->mExcludeAgentFromSearchResults = skip_agent;
if (!closeOnSelect) if (!closeOnSelect)
{ {
@@ -79,6 +84,11 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,
floater->getChild<LLButton>("cancel_btn")->setLabel(close_string); floater->getChild<LLButton>("cancel_btn")->setLabel(close_string);
} }
if(frustumOrigin)
{
floater->mFrustumOrigin = frustumOrigin->getHandle();
}
return floater; return floater;
} }
@@ -87,10 +97,18 @@ LLFloaterAvatarPicker::LLFloaterAvatarPicker()
: LLFloater(), : LLFloater(),
mNumResultsReturned(0), mNumResultsReturned(0),
mNearMeListComplete(FALSE), mNearMeListComplete(FALSE),
mCloseOnSelect(FALSE) mCloseOnSelect(FALSE),
mContextConeOpacity (0.f),
mContextConeInAlpha(0.f),
mContextConeOutAlpha(0.f),
mContextConeFadeTime(0.f)
{ {
mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this)); mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml", NULL); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml", NULL);
mContextConeInAlpha = gSavedSettings.getF32("ContextConeInAlpha");
mContextConeOutAlpha = gSavedSettings.getF32("ContextConeOutAlpha");
mContextConeFadeTime = gSavedSettings.getF32("ContextConeFadeTime");
} }
BOOL LLFloaterAvatarPicker::postBuild() BOOL LLFloaterAvatarPicker::postBuild()
@@ -188,11 +206,10 @@ static void addAvatarUUID(const LLUUID av_id, uuid_vec_t& avatar_ids, std::vecto
static void getSelectedAvatarData(const LLUICtrl* from, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names) static void getSelectedAvatarData(const LLUICtrl* from, uuid_vec_t& avatar_ids, std::vector<LLAvatarName>& avatar_names)
{ {
const LLScrollListCtrl* list = dynamic_cast<const LLScrollListCtrl*>(from); if(const LLScrollListCtrl* list = dynamic_cast<const LLScrollListCtrl*>(from))
if(list)
{ {
std::vector<LLScrollListItem*> items = list->getAllSelected(); const std::vector<LLScrollListItem*> items = list->getAllSelected();
for (std::vector<LLScrollListItem*>::iterator iter = items.begin(); iter != items.end(); ++iter) for (std::vector<LLScrollListItem*>::const_iterator iter = items.begin(); iter != items.end(); ++iter)
{ {
addAvatarUUID((*iter)->getUUID(), avatar_ids, avatar_names); addAvatarUUID((*iter)->getUUID(), avatar_ids, avatar_names);
} }
@@ -366,8 +383,67 @@ void LLFloaterAvatarPicker::populateFriend()
friends_scroller->sortByColumnIndex(0, TRUE); friends_scroller->sortByColumnIndex(0, TRUE);
} }
void LLFloaterAvatarPicker::drawFrustum()
{
if (mFrustumOrigin.get())
{
LLView * frustumOrigin = mFrustumOrigin.get();
LLRect origin_rect;
frustumOrigin->localRectToOtherView(frustumOrigin->getLocalRect(), &origin_rect, this);
// draw context cone connecting color picker with color swatch in parent floater
LLRect local_rect = getLocalRect();
if (hasFocus() && frustumOrigin->isInVisibleChain() && mContextConeOpacity > 0.001f)
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
LLGLEnable(GL_CULL_FACE);
gGL.begin(LLRender::QUADS);
{
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
gGL.vertex2i(local_rect.mRight, local_rect.mTop);
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
gGL.vertex2i(local_rect.mLeft, local_rect.mTop);
gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
gGL.vertex2i(origin_rect.mLeft, origin_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
gGL.vertex2i(local_rect.mRight, local_rect.mTop);
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
gGL.vertex2i(origin_rect.mRight, origin_rect.mTop);
gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
gGL.color4f(0.f, 0.f, 0.f, mContextConeOutAlpha * mContextConeOpacity);
gGL.vertex2i(local_rect.mLeft, local_rect.mBottom);
gGL.vertex2i(local_rect.mRight, local_rect.mBottom);
gGL.color4f(0.f, 0.f, 0.f, mContextConeInAlpha * mContextConeOpacity);
gGL.vertex2i(origin_rect.mRight, origin_rect.mBottom);
gGL.vertex2i(origin_rect.mLeft, origin_rect.mBottom);
}
gGL.end();
}
if (gFocusMgr.childHasMouseCapture(getDragHandle()))
{
mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime));
}
else
{
mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime));
}
}
}
void LLFloaterAvatarPicker::draw() void LLFloaterAvatarPicker::draw()
{ {
drawFrustum();
// sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars). // sometimes it is hard to determine when Select/Ok button should be disabled (see LLAvatarActions::shareWithAvatars).
// lets check this via mOkButtonValidateSignal callback periodically. // lets check this via mOkButtonValidateSignal callback periodically.
static LLFrameTimer timer; static LLFrameTimer timer;
@@ -411,19 +487,20 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
return FALSE; return FALSE;
} }
extern AIHTTPTimeoutPolicy avatarPickerResponder_timeout;
class LLAvatarPickerResponder : public LLHTTPClient::ResponderWithCompleted class LLAvatarPickerResponder : public LLHTTPClient::ResponderWithCompleted
{ {
LOG_CLASS(LLAvatarPickerResponder);
public: public:
LLUUID mQueryID; LLUUID mQueryID;
LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { } LLAvatarPickerResponder(const LLUUID& id) : mQueryID(id) { }
/*virtual*/ void httpCompleted(void) protected:
/*virtual*/ void httpCompleted()
{ {
//std::ostringstream ss; //std::ostringstream ss;
//LLSDSerialize::toPrettyXML(mContent, ss); //LLSDSerialize::toPrettyXML(content, ss);
//llinfos << ss.str() << llendl; //LL_INFOS() << ss.str() << LL_ENDL;
// in case of invalid characters, the avatar picker returns a 400 // in case of invalid characters, the avatar picker returns a 400
// just set it to process so it displays 'not found' // just set it to process so it displays 'not found'
@@ -436,12 +513,11 @@ public:
} }
else else
{ {
llwarns << "avatar picker failed " << mStatus << " reason " << mReason << llendl; llwarns << "avatar picker failed " << dumpResponse() << LL_ENDL;
} }
} }
/*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return avatarPickerResponder_timeout; }
/*virtual*/ char const* getName(void) const { return "LLAvatarPickerResponder"; } /*virtual*/ char const* getName(void) const { return "LLAvatarPickerResponder"; }
}; };
@@ -460,9 +536,7 @@ void LLFloaterAvatarPicker::find()
LLViewerRegion* region = gAgent.getRegion(); LLViewerRegion* region = gAgent.getRegion();
url = region->getCapability("AvatarPickerSearch"); url = region->getCapability("AvatarPickerSearch");
// Prefer use of capabilities to search on both SLID and display name // Prefer use of capabilities to search on both SLID and display name
// but allow display name search to be manually turned off for test if (!url.empty())
if (!url.empty()
&& LLAvatarNameCache::useDisplayNames())
{ {
// capability urls don't end in '/', but we need one to parse // capability urls don't end in '/', but we need one to parse
// query parameters correctly // query parameters correctly
@@ -471,6 +545,7 @@ void LLFloaterAvatarPicker::find()
url += "/"; url += "/";
} }
url += "?page_size=100&names="; url += "?page_size=100&names=";
std::replace(text.begin(), text.end(), '.', ' ');
url += LLURI::escape(text); url += LLURI::escape(text);
llinfos << "avatar picker " << url << llendl; llinfos << "avatar picker " << url << llendl;
LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID)); LLHTTPClient::get(url, new LLAvatarPickerResponder(mQueryID));
@@ -595,8 +670,7 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
// Not for us // Not for us
if (agent_id != gAgent.getID()) return; if (agent_id != gAgent.getID()) return;
if(!instanceExists()) if (!instanceExists()) return;
return;
LLFloaterAvatarPicker* floater = getInstance(); LLFloaterAvatarPicker* floater = getInstance();
// floater is closed or these are not results from our last request // floater is closed or these are not results from our last request
@@ -620,35 +694,38 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
msg->getUUIDFast( _PREHASH_Data,_PREHASH_AvatarID, avatar_id, i); msg->getUUIDFast( _PREHASH_Data,_PREHASH_AvatarID, avatar_id, i);
msg->getStringFast(_PREHASH_Data,_PREHASH_FirstName, first_name, i); msg->getStringFast(_PREHASH_Data,_PREHASH_FirstName, first_name, i);
msg->getStringFast(_PREHASH_Data,_PREHASH_LastName, last_name, i); msg->getStringFast(_PREHASH_Data,_PREHASH_LastName, last_name, i);
std::string avatar_name;
if (avatar_id.isNull())
{
LLStringUtil::format_map_t map;
map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString();
avatar_name = floater->getString("not_found", map);
search_results->setEnabled(FALSE);
floater->getChildView("ok_btn")->setEnabled(FALSE);
}
else
{
avatar_name = LLCacheName::buildFullName(first_name, last_name);
search_results->setEnabled(TRUE);
found_one = TRUE;
LLAvatarName av_name; if (avatar_id != agent_id || !floater->isExcludeAgentFromSearchResults()) // exclude agent from search results?
av_name.mLegacyFirstName = first_name; {
av_name.mLegacyLastName = last_name; std::string avatar_name;
av_name.mDisplayName = avatar_name; if (avatar_id.isNull())
const LLUUID& agent_id = avatar_id; {
sAvatarNameMap[agent_id] = av_name; LLStringUtil::format_map_t map;
map["[TEXT]"] = floater->getChild<LLUICtrl>("Edit")->getValue().asString();
avatar_name = floater->getString("not_found", map);
search_results->setEnabled(FALSE);
floater->getChildView("ok_btn")->setEnabled(FALSE);
}
else
{
avatar_name = LLCacheName::buildFullName(first_name, last_name);
search_results->setEnabled(TRUE);
found_one = TRUE;
LLAvatarName av_name;
av_name.mLegacyFirstName = first_name;
av_name.mLegacyLastName = last_name;
av_name.mDisplayName = avatar_name;
const LLUUID& agent_id = avatar_id;
sAvatarNameMap[agent_id] = av_name;
}
LLSD element;
element["id"] = avatar_id; // value
element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = avatar_name;
search_results->addElement(element);
} }
LLSD element;
element["id"] = avatar_id; // value
element["columns"][0]["column"] = "name";
element["columns"][0]["value"] = avatar_name;
search_results->addElement(element);
} }
if (found_one) if (found_one)
@@ -690,18 +767,21 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD&
for ( ; it != agents.endArray(); ++it) for ( ; it != agents.endArray(); ++it)
{ {
const LLSD& row = *it; const LLSD& row = *it;
item["id"] = row["id"]; if (row["id"].asUUID() != gAgent.getID() || !mExcludeAgentFromSearchResults)
LLSD& columns = item["columns"]; {
columns[0]["column"] = "name"; item["id"] = row["id"];
columns[0]["value"] = row["display_name"]; LLSD& columns = item["columns"];
columns[1]["column"] = "username"; columns[0]["column"] = "name";
columns[1]["value"] = row["username"]; columns[0]["value"] = row["display_name"];
search_results->addElement(item); columns[1]["column"] = "username";
columns[1]["value"] = row["username"];
search_results->addElement(item);
// add the avatar name to our list // add the avatar name to our list
LLAvatarName avatar_name; LLAvatarName avatar_name;
avatar_name.fromLLSD(row); avatar_name.fromLLSD(row);
sAvatarNameMap[row["id"].asUUID()] = avatar_name; sAvatarNameMap[row["id"].asUUID()] = avatar_name;
}
} }
getChildView("ok_btn")->setEnabled(true); getChildView("ok_btn")->setEnabled(true);
@@ -713,10 +793,10 @@ void LLFloaterAvatarPicker::processResponse(const LLUUID& query_id, const LLSD&
void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller) void LLFloaterAvatarPicker::editKeystroke(LLLineEditor* caller)
{ {
if(caller->getName() == "Edit") if (caller->getName() == "Edit")
getChildView("Find")->setEnabled(caller->getText().size() >= 3); getChildView("Find")->setEnabled(caller->getText().size() >= 3);
else else
childSetEnabled("Select", caller->getValue().asUUID().notNull()); getChildView("Select")->setEnabled(caller->getValue().asUUID().notNull());
} }
// virtual // virtual

View File

@@ -45,11 +45,15 @@ public:
// Call this to select an avatar. // Call this to select an avatar.
static LLFloaterAvatarPicker* show(select_callback_t callback, static LLFloaterAvatarPicker* show(select_callback_t callback,
BOOL allow_multiple = FALSE, BOOL allow_multiple = FALSE,
BOOL closeOnSelect = FALSE); BOOL closeOnSelect = FALSE,
BOOL skip_agent = FALSE,
const std::string& name = "",
LLView * frustumOrigin = NULL);
// do not call these directly // do not call these directly
LLFloaterAvatarPicker(); LLFloaterAvatarPicker();
virtual ~LLFloaterAvatarPicker(); virtual ~LLFloaterAvatarPicker();
virtual BOOL postBuild(); virtual BOOL postBuild();
void setOkBtnEnableCb(validate_callback_t cb); void setOkBtnEnableCb(validate_callback_t cb);
@@ -63,6 +67,7 @@ public:
std::string& tooltip_msg); std::string& tooltip_msg);
void openFriendsTab(); void openFriendsTab();
BOOL isExcludeAgentFromSearchResults() { return mExcludeAgentFromSearchResults; }
private: private:
void editKeystroke(class LLLineEditor* caller); void editKeystroke(class LLLineEditor* caller);
@@ -84,6 +89,7 @@ private:
void setAllowMultiple(BOOL allow_multiple); void setAllowMultiple(BOOL allow_multiple);
LLScrollListCtrl* getActiveList(); LLScrollListCtrl* getActiveList();
void drawFrustum();
virtual void draw(); virtual void draw();
virtual BOOL handleKeyHere(KEY key, MASK mask); virtual BOOL handleKeyHere(KEY key, MASK mask);
@@ -91,6 +97,12 @@ private:
int mNumResultsReturned; int mNumResultsReturned;
BOOL mNearMeListComplete; BOOL mNearMeListComplete;
BOOL mCloseOnSelect; BOOL mCloseOnSelect;
BOOL mExcludeAgentFromSearchResults;
LLHandle <LLView> mFrustumOrigin;
F32 mContextConeOpacity;
F32 mContextConeInAlpha;
F32 mContextConeOutAlpha;
F32 mContextConeFadeTime;
validate_signal_t mOkButtonValidateSignal; validate_signal_t mOkButtonValidateSignal;
select_callback_t mSelectionCallback; select_callback_t mSelectionCallback;

View File

@@ -82,7 +82,7 @@ public:
virtual void pasteLinkFromClipboard() = 0; virtual void pasteLinkFromClipboard() = 0;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0; virtual void buildContextMenu(LLMenuGL& menu, U32 flags) = 0;
virtual BOOL isUpToDate() const = 0; virtual BOOL isUpToDate() const = 0;
virtual BOOL hasChildren() const = 0; virtual bool hasChildren() const = 0;
virtual LLInventoryType::EType getInventoryType() const = 0; virtual LLInventoryType::EType getInventoryType() const = 0;
virtual void performAction(LLInventoryModel* model, std::string action) = 0; virtual void performAction(LLInventoryModel* model, std::string action) = 0;
virtual LLWearableType::EType getWearableType() const = 0; virtual LLWearableType::EType getWearableType() const = 0;

View File

@@ -231,23 +231,25 @@ bool LLGiveInventory::doGiveInventoryItem(const LLUUID& to_agent,
return res; return res;
} }
void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent, bool LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat, const LLInventoryCategory* cat,
const LLUUID& im_session_id) const LLUUID& im_session_id,
const std::string& notification_name)
{ {
if (!cat) if (!cat)
{ {
return; return false;
} }
llinfos << "LLGiveInventory::giveInventoryCategory() - " llinfos << "LLGiveInventory::giveInventoryCategory() - "
<< cat->getUUID() << llendl; << cat->getUUID() << llendl;
if (!isAgentAvatarValid()) if (!isAgentAvatarValid())
{ {
return; return false;
} }
bool give_successful = true;
// Test out how many items are being given. // Test out how many items are being given.
LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items; LLViewerInventoryItem::item_array_t items;
@@ -270,24 +272,24 @@ void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
if(!complete) if(!complete)
{ {
LLNotificationsUtil::add("IncompleteInventory"); LLNotificationsUtil::add("IncompleteInventory");
return; give_successful = false;
} }
count = items.count() + cats.count(); count = items.count() + cats.count();
if(count > MAX_ITEMS) if(count > MAX_ITEMS)
{ {
LLNotificationsUtil::add("TooManyItems"); LLNotificationsUtil::add("TooManyItems");
return; give_successful = false;
} }
else if(count == 0) else if(count == 0)
{ {
LLNotificationsUtil::add("NoItems"); LLNotificationsUtil::add("NoItems");
return; give_successful = false;
} }
else else if (give_successful)
{ {
if(0 == giveable.countNoCopy()) if(0 == giveable.countNoCopy())
{ {
LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id); give_successful = LLGiveInventory::commitGiveInventoryCategory(to_agent, cat, im_session_id);
} }
else else
{ {
@@ -296,9 +298,16 @@ void LLGiveInventory::doGiveInventoryCategory(const LLUUID& to_agent,
LLSD payload; LLSD payload;
payload["agent_id"] = to_agent; payload["agent_id"] = to_agent;
payload["folder_id"] = cat->getUUID(); payload["folder_id"] = cat->getUUID();
if (!notification_name.empty())
{
payload["success_notification"] = notification_name;
}
LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLGiveInventory::handleCopyProtectedCategory); LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLGiveInventory::handleCopyProtectedCategory);
give_successful = false;
} }
} }
return give_successful;
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@@ -377,6 +386,10 @@ bool LLGiveInventory::handleCopyProtectedItem(const LLSD& notification, const LL
give_successful = false; give_successful = false;
} }
} }
if (give_successful && notification["payload"]["success_notification"].isDefined())
{
LLNotificationsUtil::add(notification["payload"]["success_notification"].asString());
}
break; break;
default: // no, cancel, whatever, who cares, not yes. default: // no, cancel, whatever, who cares, not yes.
@@ -445,13 +458,14 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons
{ {
S32 option = LLNotificationsUtil::getSelectedOption(notification, response); S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
LLInventoryCategory* cat = NULL; LLInventoryCategory* cat = NULL;
bool give_successful = true;
switch(option) switch(option)
{ {
case 0: // "Yes" case 0: // "Yes"
cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID()); cat = gInventory.getCategory(notification["payload"]["folder_id"].asUUID());
if(cat) if(cat)
{ {
LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(), give_successful = LLGiveInventory::commitGiveInventoryCategory(notification["payload"]["agent_id"].asUUID(),
cat); cat);
LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryCategory::cat_array_t cats;
LLViewerInventoryItem::item_array_t items; LLViewerInventoryItem::item_array_t items;
@@ -467,29 +481,36 @@ bool LLGiveInventory::handleCopyProtectedCategory(const LLSD& notification, cons
gInventory.deleteObject(items.get(i)->getUUID()); gInventory.deleteObject(items.get(i)->getUUID());
} }
gInventory.notifyObservers(); gInventory.notifyObservers();
if (give_successful && notification["payload"]["success_notification"].isDefined())
{
LLNotificationsUtil::add(notification["payload"]["success_notification"].asString());
}
} }
else else
{ {
LLNotificationsUtil::add("CannotGiveCategory"); LLNotificationsUtil::add("CannotGiveCategory");
give_successful = false;
} }
break; break;
default: // no, cancel, whatever, who cares, not yes. default: // no, cancel, whatever, who cares, not yes.
LLNotificationsUtil::add("TransactionCancelled"); LLNotificationsUtil::add("TransactionCancelled");
give_successful = false;
break; break;
} }
return false; return give_successful;
} }
// static // static
void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat, const LLInventoryCategory* cat,
const LLUUID& im_session_id) const LLUUID& im_session_id)
{ {
if(!cat) if (!cat)
{ {
return; return false;
} }
llinfos << "LLGiveInventory::commitGiveInventoryCategory() - " llinfos << "LLGiveInventory::commitGiveInventoryCategory() - "
<< cat->getUUID() << llendl; << cat->getUUID() << llendl;
@@ -504,6 +525,7 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
LLInventoryModel::EXCLUDE_TRASH, LLInventoryModel::EXCLUDE_TRASH,
giveable); giveable);
bool give_successful = true;
// MAX ITEMS is based on (sizeof(uuid)+2) * count must be < // MAX ITEMS is based on (sizeof(uuid)+2) * count must be <
// MTUBYTES or 18 * count < 1200 => count < 1200/18 => // MTUBYTES or 18 * count < 1200 => count < 1200/18 =>
// 66. I've cut it down a bit from there to give some pad. // 66. I've cut it down a bit from there to give some pad.
@@ -511,12 +533,12 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
if(count > MAX_ITEMS) if(count > MAX_ITEMS)
{ {
LLNotificationsUtil::add("TooManyItems"); LLNotificationsUtil::add("TooManyItems");
return; give_successful = false;
} }
else if(count == 0) else if(count == 0)
{ {
LLNotificationsUtil::add("NoItems"); LLNotificationsUtil::add("NoItems");
return; give_successful = false;
} }
else else
{ {
@@ -589,6 +611,8 @@ void LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent,
logInventoryOffer(to_agent, im_session_id); logInventoryOffer(to_agent, im_session_id);
} }
return give_successful;
} }
// EOF // EOF

View File

@@ -62,9 +62,11 @@ public:
/** /**
* Gives passed inventory category to specified avatar in specified session. * Gives passed inventory category to specified avatar in specified session.
*/ */
static void doGiveInventoryCategory(const LLUUID& to_agent, static bool doGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* item, const LLInventoryCategory* item,
const LLUUID &session_id = LLUUID::null); const LLUUID &session_id = LLUUID::null,
const std::string& notification = std::string());
// give inventory item functionality // give inventory item functionality
static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response); static bool handleCopyProtectedItem(const LLSD& notification, const LLSD& response);
@@ -84,7 +86,7 @@ private:
// give inventory category functionality // give inventory category functionality
static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response); static bool handleCopyProtectedCategory(const LLSD& notification, const LLSD& response);
static void commitGiveInventoryCategory(const LLUUID& to_agent, static bool commitGiveInventoryCategory(const LLUUID& to_agent,
const LLInventoryCategory* cat, const LLInventoryCategory* cat,
const LLUUID &im_session_id = LLUUID::null); const LLUUID &im_session_id = LLUUID::null);

View File

@@ -34,6 +34,7 @@
#include "llagentwearables.h" #include "llagentwearables.h"
#include "llappearancemgr.h" #include "llappearancemgr.h"
#include "llavataractions.h"
#include "llfloaterperms.h" #include "llfloaterperms.h"
#include "llfoldervieweventlistener.h" #include "llfoldervieweventlistener.h"
#include "llimview.h" #include "llimview.h"
@@ -627,6 +628,7 @@ void init_object_inventory_panel_actions(LLPanelObjectInventory *panel)
void init_inventory_actions(LLInventoryView *floater) void init_inventory_actions(LLInventoryView *floater)
{ {
(new LLDoToSelectedFloater())->registerListener(floater, "Inventory.DoToSelected");
(new LLDoToSelectedFloater())->registerListener(floater, "Inventory.DoToSelected"); (new LLDoToSelectedFloater())->registerListener(floater, "Inventory.DoToSelected");
(new LLCloseAllFoldersFloater())->registerListener(floater, "Inventory.CloseAllFolders"); (new LLCloseAllFoldersFloater())->registerListener(floater, "Inventory.CloseAllFolders");
(new LLEmptyTrashFloater())->registerListener(floater, "Inventory.EmptyTrash"); (new LLEmptyTrashFloater())->registerListener(floater, "Inventory.EmptyTrash");
@@ -640,6 +642,15 @@ void init_inventory_actions(LLInventoryView *floater)
(new LLSetSearchType())->registerListener(floater, "Inventory.SetSearchType"); (new LLSetSearchType())->registerListener(floater, "Inventory.SetSearchType");
} }
class LLShare : public inventory_panel_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
LLAvatarActions::shareWithAvatars(mPtr);
return true;
}
};
void init_inventory_panel_actions(LLInventoryPanel *panel) void init_inventory_panel_actions(LLInventoryPanel *panel)
{ {
(new LLDoToSelected())->registerListener(panel, "Inventory.DoToSelected"); (new LLDoToSelected())->registerListener(panel, "Inventory.DoToSelected");
@@ -649,4 +660,5 @@ void init_inventory_panel_actions(LLInventoryPanel *panel)
(new LLEmptyLostAndFound())->registerListener(panel, "Inventory.EmptyLostAndFound"); (new LLEmptyLostAndFound())->registerListener(panel, "Inventory.EmptyLostAndFound");
(new LLDoCreate())->registerListener(panel, "Inventory.DoCreate"); (new LLDoCreate())->registerListener(panel, "Inventory.DoCreate");
(new LLBeginIMSession())->registerListener(panel, "Inventory.BeginIMSession"); (new LLBeginIMSession())->registerListener(panel, "Inventory.BeginIMSession");
(new LLShare())->registerListener(panel, "Inventory.Share");
} }

View File

@@ -804,6 +804,12 @@ void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
} }
else else
{ {
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
addOpenRightClickMenuOption(items); addOpenRightClickMenuOption(items);
items.push_back(std::string("Properties")); items.push_back(std::string("Properties"));
@@ -1235,6 +1241,33 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
} }
} }
bool LLInvFVBridge::canShare() const
{
bool can_share = false;
if (!isItemInTrash() && isAgentInventory())
{
const LLInventoryModel* model = getInventoryModel();
if (model)
{
const LLViewerInventoryItem *item = model->getItem(mUUID);
if (item)
{
if (LLInventoryCollectFunctor::itemTransferCommonlyAllowed(item))
{
can_share = LLGiveInventory::isInventoryGiveAcceptable(item);
}
}
else
{
// Categories can be given.
can_share = (model->getCategory(mUUID) != NULL);
}
}
}
return can_share;
}
bool LLInvFVBridge::canListOnMarketplace() const bool LLInvFVBridge::canListOnMarketplace() const
{ {
@@ -2613,8 +2646,17 @@ void LLRightClickInventoryFetchDescendentsObserver::execute(bool clear_observer)
LLInventoryModel::item_array_t* item_array; LLInventoryModel::item_array_t* item_array;
gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array); gInventory.getDirectDescendentsOf(*current_folder, cat_array, item_array);
S32 item_count = item_array->count(); S32 item_count(0);
S32 cat_count = cat_array->count(); if (item_array)
{
item_count = item_array->count();
}
S32 cat_count(0);
if (cat_array)
{
cat_count = cat_array->count();
}
// Move to next if current folder empty // Move to next if current folder empty
if ((item_count == 0) && (cat_count == 0)) if ((item_count == 0) && (cat_count == 0))
@@ -3387,6 +3429,15 @@ void LLFolderBridge::buildContextMenuBaseOptions(U32 flags)
{ {
mDisabledItems.push_back(std::string("Delete System Folder")); mDisabledItems.push_back(std::string("Delete System Folder"));
} }
if (!isOutboxFolder() && !isItemInTrash()) // <alchemy/>
{
mItems.push_back(std::string("Share"));
if (!canShare())
{
mDisabledItems.push_back(std::string("Share"));
}
}
} }
void LLFolderBridge::buildContextMenuFolderOptions(U32 flags) void LLFolderBridge::buildContextMenuFolderOptions(U32 flags)
@@ -3528,7 +3579,7 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
menu.arrangeAndClear(); menu.arrangeAndClear();
} }
BOOL LLFolderBridge::hasChildren() const bool LLFolderBridge::hasChildren() const
{ {
LLInventoryModel* model = getInventoryModel(); LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE; if(!model) return FALSE;
@@ -4321,6 +4372,12 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
} }
else else
{ {
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
addOpenRightClickMenuOption(items); addOpenRightClickMenuOption(items);
items.push_back(std::string("Properties")); items.push_back(std::string("Properties"));
@@ -4412,6 +4469,11 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
} }
else else
{ {
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Sound Open")); items.push_back(std::string("Sound Open"));
items.push_back(std::string("Properties")); items.push_back(std::string("Properties"));
@@ -4465,6 +4527,11 @@ void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
} }
else else
{ {
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Landmark Open")); items.push_back(std::string("Landmark Open"));
items.push_back(std::string("Properties")); items.push_back(std::string("Properties"));
@@ -4734,6 +4801,11 @@ void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
} }
else else
{ {
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
/* Singu Note: Multiple profiles get opened in a multifloater /* Singu Note: Multiple profiles get opened in a multifloater
if ((flags & FIRST_SELECTED_ITEM) == 0) if ((flags & FIRST_SELECTED_ITEM) == 0)
{ {
@@ -5039,6 +5111,11 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
} }
else else
{ {
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
addOpenRightClickMenuOption(items); addOpenRightClickMenuOption(items);
items.push_back(std::string("Properties")); items.push_back(std::string("Properties"));
@@ -5094,6 +5171,11 @@ void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
} }
else else
{ {
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Animation Open")); items.push_back(std::string("Animation Open"));
items.push_back(std::string("Properties")); items.push_back(std::string("Properties"));
@@ -5411,6 +5493,12 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
} }
else else
{ {
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
items.push_back(std::string("Properties")); items.push_back(std::string("Properties"));
getClipboardEntries(true, items, disabled_items, flags); getClipboardEntries(true, items, disabled_items, flags);
@@ -5819,6 +5907,12 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{ {
can_open = FALSE; can_open = FALSE;
} }
items.push_back(std::string("Share"));
if (!canShare())
{
disabled_items.push_back(std::string("Share"));
}
if (can_open) if (can_open)
{ {
addOpenRightClickMenuOption(items); addOpenRightClickMenuOption(items);

View File

@@ -69,6 +69,7 @@ public:
U32 flags = 0x00); U32 flags = 0x00);
virtual ~LLInvFVBridge() {} virtual ~LLInvFVBridge() {}
bool canShare() const;
bool canListOnMarketplace() const; bool canListOnMarketplace() const;
bool canListOnMarketplaceNow() const; bool canListOnMarketplaceNow() const;
@@ -121,6 +122,8 @@ public:
void* cargo_data) { return FALSE; } void* cargo_data) { return FALSE; }
virtual LLInventoryType::EType getInventoryType() const { return mInvType; } virtual LLInventoryType::EType getInventoryType() const { return mInvType; }
virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; }
virtual LLInventoryObject* getInventoryObject() const;
//-------------------------------------------------------------------- //--------------------------------------------------------------------
// Convenience functions for adding various common menu options. // Convenience functions for adding various common menu options.
@@ -137,16 +140,15 @@ protected:
protected: protected:
LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid); LLInvFVBridge(LLInventoryPanel* inventory, LLFolderView* root, const LLUUID& uuid);
LLInventoryObject* getInventoryObject() const;
LLInventoryModel* getInventoryModel() const; LLInventoryModel* getInventoryModel() const;
BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash? BOOL isLinkedObjectInTrash() const; // Is this obj or its baseobj in the trash?
BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory? BOOL isLinkedObjectMissing() const; // Is this a linked obj whose baseobj is not in inventory?
BOOL isAgentInventory() const; // false if lost or in the inventory library BOOL isAgentInventory() const; // false if lost or in the inventory library
BOOL isCOFFolder() const; // true if COF or descendent of BOOL isCOFFolder() const; // true if COF or descendant of
BOOL isInboxFolder() const; // true if COF or descendent of marketplace inbox BOOL isInboxFolder() const; // true if COF or descendant of marketplace inbox
BOOL isOutboxFolder() const; // true if COF or descendent of marketplace outbox BOOL isOutboxFolder() const; // true if COF or descendant of marketplace outbox
BOOL isOutboxFolderDirectParent() const; BOOL isOutboxFolderDirectParent() const;
const LLUUID getOutboxFolder() const; const LLUUID getOutboxFolder() const;
@@ -165,7 +167,7 @@ protected:
LLFolderView* mRoot; LLFolderView* mRoot;
const LLUUID mUUID; // item id const LLUUID mUUID; // item id
LLInventoryType::EType mInvType; LLInventoryType::EType mInvType;
BOOL mIsLink; bool mIsLink;
void purgeItem(LLInventoryModel *model, const LLUUID &uuid); void purgeItem(LLInventoryModel *model, const LLUUID &uuid);
}; };
@@ -213,7 +215,7 @@ public:
virtual BOOL renameItem(const std::string& new_name); virtual BOOL renameItem(const std::string& new_name);
virtual BOOL removeItem(); virtual BOOL removeItem();
virtual BOOL isItemCopyable() const; virtual BOOL isItemCopyable() const;
virtual BOOL hasChildren() const { return FALSE; } virtual bool hasChildren() const { return FALSE; }
virtual BOOL isUpToDate() const { return TRUE; } virtual BOOL isUpToDate() const { return TRUE; }
static void showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker); static void showFloaterImagePreview(LLInventoryItem* item, AIFilePicker* filepicker);
@@ -235,8 +237,8 @@ class LLFolderBridge : public LLInvFVBridge
public: public:
LLFolderBridge(LLInventoryPanel* inventory, LLFolderBridge(LLInventoryPanel* inventory,
LLFolderView* root, LLFolderView* root,
const LLUUID& uuid) : const LLUUID& uuid)
LLInvFVBridge(inventory, root, uuid), : LLInvFVBridge(inventory, root, uuid),
mCallingCards(FALSE), mCallingCards(FALSE),
mWearables(FALSE) mWearables(FALSE)
{} {}
@@ -265,7 +267,7 @@ public:
virtual void pasteFromClipboard(bool only_copies = false); virtual void pasteFromClipboard(bool only_copies = false);
virtual void pasteLinkFromClipboard(); virtual void pasteLinkFromClipboard();
virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual BOOL hasChildren() const; virtual bool hasChildren() const;
virtual BOOL dragOrDrop(MASK mask, BOOL drop, virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type, EDragAndDropType cargo_type,
void* cargo_data); void* cargo_data);
@@ -326,8 +328,9 @@ public:
static void staticFolderOptionsMenu(); static void staticFolderOptionsMenu();
private: private:
BOOL mCallingCards;
BOOL mWearables; bool mCallingCards;
bool mWearables;
menuentry_vec_t mItems; menuentry_vec_t mItems;
menuentry_vec_t mDisabledItems; menuentry_vec_t mDisabledItems;
LLRootHandle<LLFolderBridge> mHandle; LLRootHandle<LLFolderBridge> mHandle;
@@ -405,7 +408,6 @@ protected:
LLCallingCardObserver* mObserver; LLCallingCardObserver* mObserver;
}; };
class LLNotecardBridge : public LLItemBridge class LLNotecardBridge : public LLItemBridge
{ {
public: public:
@@ -436,7 +438,6 @@ public:
static void playGesture(const LLUUID& item_id); static void playGesture(const LLUUID& item_id);
}; };
class LLAnimationBridge : public LLItemBridge class LLAnimationBridge : public LLItemBridge
{ {
public: public:
@@ -450,7 +451,6 @@ public:
virtual void openItem(); virtual void openItem();
}; };
class LLObjectBridge : public LLItemBridge class LLObjectBridge : public LLItemBridge
{ {
public: public:
@@ -515,8 +515,6 @@ public:
void editOnAvatar(); void editOnAvatar();
static BOOL canRemoveFromAvatar( void* userdata ); static BOOL canRemoveFromAvatar( void* userdata );
//static void onRemoveFromAvatar( void* userdata );
//static void onRemoveFromAvatarArrived( LLViewerWearable* wearable, void* userdata );
//static void removeAllClothesFromAvatar(); //static void removeAllClothesFromAvatar();
void removeFromAvatar(); void removeFromAvatar();
protected: protected:
@@ -629,7 +627,8 @@ public:
class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder class LLRecentInventoryBridgeBuilder : public LLInventoryFVBridgeBuilder
{ {
public: public:
LLRecentInventoryBridgeBuilder(): LLInventoryFVBridgeBuilder() {} LLRecentInventoryBridgeBuilder() {}
// Overrides FolderBridge for Recent Inventory Panel. // Overrides FolderBridge for Recent Inventory Panel.
// It use base functionality for bridges other than FolderBridge. // It use base functionality for bridges other than FolderBridge.
virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type, virtual LLInvFVBridge* createBridge(LLAssetType::EType asset_type,

View File

@@ -137,7 +137,7 @@ public:
virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual void performAction(LLInventoryModel* model, std::string action); virtual void performAction(LLInventoryModel* model, std::string action);
virtual BOOL isUpToDate() const { return TRUE; } virtual BOOL isUpToDate() const { return TRUE; }
virtual BOOL hasChildren() const { return FALSE; } virtual bool hasChildren() const { return FALSE; }
virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; } virtual LLInventoryType::EType getInventoryType() const { return LLInventoryType::IT_NONE; }
virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; } virtual LLWearableType::EType getWearableType() const { return LLWearableType::WT_NONE; }
@@ -872,7 +872,7 @@ public:
virtual BOOL renameItem(const std::string& new_name); virtual BOOL renameItem(const std::string& new_name);
virtual BOOL isItemRemovable() const; virtual BOOL isItemRemovable() const;
virtual void buildContextMenu(LLMenuGL& menu, U32 flags); virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual BOOL hasChildren() const; virtual bool hasChildren() const;
virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const; virtual BOOL startDrag(EDragAndDropType* type, LLUUID* id) const;
virtual BOOL dragOrDrop(MASK mask, BOOL drop, virtual BOOL dragOrDrop(MASK mask, BOOL drop,
EDragAndDropType cargo_type, EDragAndDropType cargo_type,
@@ -922,7 +922,7 @@ void LLTaskCategoryBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
hide_context_entries(menu, items, disabled_items); hide_context_entries(menu, items, disabled_items);
} }
BOOL LLTaskCategoryBridge::hasChildren() const bool LLTaskCategoryBridge::hasChildren() const
{ {
// return TRUE if we have or do know know if we have children. // return TRUE if we have or do know know if we have children.
// *FIX: For now, return FALSE - we will know for sure soon enough. // *FIX: For now, return FALSE - we will know for sure soon enough.

View File

@@ -0,0 +1,67 @@
/**
* @file llshareavatarhandler.cpp
* @brief slapp to handle sharing with an avatar
*
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2010, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llcommandhandler.h"
#include "llavataractions.h"
#include "llnotificationsutil.h"
#include "llui.h"
class LLShareWithAvatarHandler : public LLCommandHandler
{
public:
// requires trusted browser to trigger
LLShareWithAvatarHandler() : LLCommandHandler("sharewithavatar", UNTRUSTED_THROTTLE)
{
}
bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web)
{
/*if (!LLUI::sSettingGroups["config"]->getBOOL("EnableAvatarShare"))
{
LLNotificationsUtil::add("NoAvatarShare", LLSD(), LLSD(), std::string("SwitchToStandardSkinAndQuit"));
return true;
}*/
//Make sure we have some parameters
if (params.size() == 0)
{
return false;
}
//Get the ID
LLUUID id;
if (!id.set( params[0], FALSE))
{
return false;
}
//instigate share with this avatar
LLAvatarActions::share(id);
return true;
}
};
LLShareWithAvatarHandler gShareWithAvatar;

View File

@@ -2930,6 +2930,7 @@ class LLObjectImportUpload : public view_listener_t
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// Parcel freeze, eject, etc. // Parcel freeze, eject, etc.
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void send_freeze(const LLUUID& avatar_id, bool freeze);
bool callback_freeze(const LLSD& notification, const LLSD& response) bool callback_freeze(const LLSD& notification, const LLSD& response)
{ {
LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID(); LLUUID avatar_id = notification["payload"]["avatar_id"].asUUID();
@@ -2937,27 +2938,7 @@ bool callback_freeze(const LLSD& notification, const LLSD& response)
if (0 == option || 1 == option) if (0 == option || 1 == option)
{ {
U32 flags = KICK_FLAGS_FREEZE; send_freeze(avatar_id, !option);
if (1 == option)
{
// unfreeze
flags |= KICK_FLAGS_UNFREEZE;
}
LLMessageSystem* msg = gMessageSystem;
LLVOAvatar* avatarp = gObjectList.findAvatar(avatar_id);
if (avatarp && avatarp->getRegion())
{
msg->newMessage("FreezeUser");
msg->nextBlock("AgentData");
msg->addUUID("AgentID", gAgent.getID());
msg->addUUID("SessionID", gAgent.getSessionID());
msg->nextBlock("Data");
msg->addUUID("TargetID", avatar_id );
msg->addU32("Flags", flags );
msg->sendReliable( avatarp->getRegion()->getHost() );
}
} }
return false; return false;
} }
@@ -9105,6 +9086,15 @@ class ListRequestTeleport : public view_listener_t
} }
}; };
class ListShare : public view_listener_t
{
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
{
LLAvatarActions::share(get_focused_list_id_selected());
return true;
}
};
class ListShowProfile : public view_listener_t class ListShowProfile : public view_listener_t
{ {
bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata)
@@ -9559,6 +9549,7 @@ void initialize_menus()
addMenu(new ListRemoveFriend(), "List.RemoveFriend"); addMenu(new ListRemoveFriend(), "List.RemoveFriend");
addMenu(new ListRequestFriendship(), "List.RequestFriendship"); addMenu(new ListRequestFriendship(), "List.RequestFriendship");
addMenu(new ListRequestTeleport(), "List.RequestTeleport"); addMenu(new ListRequestTeleport(), "List.RequestTeleport");
addMenu(new ListShare(), "List.Share");
addMenu(new ListShowProfile(), "List.ShowProfile"); addMenu(new ListShowProfile(), "List.ShowProfile");
addMenu(new ListShowWebProfile(), "List.ShowWebProfile"); addMenu(new ListShowWebProfile(), "List.ShowWebProfile");
addMenu(new ListStartAdhocCall(), "List.StartAdhocCall"); addMenu(new ListStartAdhocCall(), "List.StartAdhocCall");

View File

@@ -56,6 +56,10 @@
<on_click function="List.RequestTeleport"/> <on_click function="List.RequestTeleport"/>
<on_visible function="List.EnableSingleSelected"/> <on_visible function="List.EnableSingleSelected"/>
</menu_item_call> </menu_item_call>
<menu_item_call label="Share" name="Share">
<on_click function="List.Share"/>
<on_visible function="List.EnableSingleSelected"/>
</menu_item_call>
<menu_item_separator/> <menu_item_separator/>
<menu_item_call label="Mute/Unmute" name="Mute/Unmute"> <menu_item_call label="Mute/Unmute" name="Mute/Unmute">
<on_click function="List.ToggleMute"/> <on_click function="List.ToggleMute"/>

View File

@@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?> <?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<menu bottom="100" color="MenuDefaultBgColor" drop_shadow="true" height="101" left="100" <menu bottom="100" color="MenuDefaultBgColor" drop_shadow="true" height="101" left="100"
mouse_opaque="false" name="Popup" opaque="true" width="128"> mouse_opaque="false" name="Popup" opaque="true" width="128">
<menu_item_call
label="Share"
layout="topleft"
name="Share"
visible="true">
<menu_item_call.on_click
function="Inventory.Share" />
</menu_item_call>
<menu_item_call bottom_delta="-18" height="18" label="Buy" left="0" mouse_opaque="true" <menu_item_call bottom_delta="-18" height="18" label="Buy" left="0" mouse_opaque="true"
name="Task Buy" width="128"> name="Task Buy" width="128">
<on_click filter="" function="Inventory.DoToSelected" userdata="task_buy" /> <on_click filter="" function="Inventory.DoToSelected" userdata="task_buy" />

View File

@@ -57,6 +57,10 @@
<on_click function="List.RequestTeleport"/> <on_click function="List.RequestTeleport"/>
<on_visible function="List.EnableSingleSelected"/> <on_visible function="List.EnableSingleSelected"/>
</menu_item_call> </menu_item_call>
<menu_item_call label="Share" name="Share">
<on_click function="List.Share"/>
<on_visible function="List.EnableSingleSelected"/>
</menu_item_call>
<menu_item_call label="Track/Untrack" name="Track/Untrack"> <menu_item_call label="Track/Untrack" name="Track/Untrack">
<on_click function="Radar.Track"/> <on_click function="Radar.Track"/>
<on_enable function="List.EnableSingleSelected"/> <on_enable function="List.EnableSingleSelected"/>

View File

@@ -2142,15 +2142,6 @@ Multiple parcels selected.
Try selecting a single parcel. Try selecting a single parcel.
</notification> </notification>
<notification
icon="notifytip.tga"
name="DeedToGroupFail"
type="notifytip">
Deed to group failed.
<tag>group</tag>
<tag>fail</tag>
</notification>
<notification <notification
icon="alertmodal.tga" icon="alertmodal.tga"
name="ParcelCanPlayMedia" name="ParcelCanPlayMedia"
@@ -7738,6 +7729,13 @@ Server Error: Media update or get failed.
yestext="OK"/> yestext="OK"/>
</notification> </notification>
<notification
icon="notifytip.tga"
name="ShareNotification"
type="notifytip">
Select residents to share with.
</notification>
<notification <notification
name="MeshUploadError" name="MeshUploadError"
icon="alert.tga" icon="alert.tga"
@@ -7761,6 +7759,61 @@ See the log file for details.
Could not get region capability &apos;[CAPABILITY]&apos;. Could not get region capability &apos;[CAPABILITY]&apos;.
</notification> </notification>
<notification
icon="notifytip.tga"
name="ShareItemsConfirmation"
type="alertmodal">
Are you sure you want to share the following items:
[ITEMS]
With the following Residents:
[RESIDENTS]
<tag>confirm</tag>
<usetemplate
name="okcancelbuttons"
notext="Cancel"
yestext="OK"/>
</notification>
<notification
icon="notifytip.tga"
name="ShareFolderConfirmation"
type="alertmodal">
Only one folder at a time can be shared.
Are you sure you want to share the following items:
[ITEMS]
With the following Residents:
[RESIDENTS]
<tag>confirm</tag>
<usetemplate
name="okcancelbuttons"
notext="Cancel"
yestext="Ok"/>
</notification>
<notification
icon="notifytip.tga"
name="ItemsShared"
type="notifytip">
Items successfully shared.
</notification>
<notification
icon="notifytip.tga"
name="DeedToGroupFail"
type="notifytip">
Deed to group failed.
<tag>group</tag>
<tag>fail</tag>
</notification>
<notification <notification
icon="notifytip.tga" icon="notifytip.tga"
name="AvatarRezNotification" name="AvatarRezNotification"

View File

@@ -4185,6 +4185,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="inventory_item_offered_rlv"> <string name="inventory_item_offered_rlv">
Inventory item offered to [NAME] Inventory item offered to [NAME]
</string> </string>
<string name="share_alert">
Drag items from inventory here
</string>
<string name="only_user_message"> <string name="only_user_message">