summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--indra/llui/llfloater.cpp77
-rw-r--r--indra/newview/CMakeLists.txt2
-rw-r--r--indra/newview/app_settings/settings.xml26
-rw-r--r--indra/newview/llagentwearables.cpp7
-rw-r--r--indra/newview/llappearancemgr.cpp21
-rw-r--r--indra/newview/llappearancemgr.h1
-rw-r--r--indra/newview/llavataractions.cpp2
-rw-r--r--indra/newview/llbottomtray.cpp234
-rw-r--r--indra/newview/llbottomtray.h31
-rw-r--r--indra/newview/llchatbar.cpp5
-rw-r--r--indra/newview/llchathistory.cpp10
-rw-r--r--indra/newview/llchiclet.cpp11
-rw-r--r--indra/newview/llfloatergesture.cpp255
-rw-r--r--indra/newview/llfloatergesture.h12
-rw-r--r--indra/newview/llfriendcard.cpp265
-rw-r--r--indra/newview/llfriendcard.h47
-rw-r--r--indra/newview/llgesturemgr.cpp31
-rw-r--r--indra/newview/llgesturemgr.h30
-rw-r--r--indra/newview/llimfloater.cpp6
-rw-r--r--indra/newview/llimpanel.cpp7
-rw-r--r--indra/newview/llimview.cpp107
-rw-r--r--indra/newview/llimview.h22
-rw-r--r--indra/newview/llinventorymodel.cpp562
-rw-r--r--indra/newview/llinventorymodel.h259
-rw-r--r--indra/newview/llinventoryobserver.cpp564
-rw-r--r--indra/newview/llinventoryobserver.h249
-rw-r--r--indra/newview/llinventorypanel.cpp24
-rw-r--r--indra/newview/llinventorypanel.h2
-rw-r--r--indra/newview/lllogininstance.cpp3
-rw-r--r--indra/newview/llnearbychatbar.cpp35
-rw-r--r--indra/newview/llnearbychatbar.h10
-rw-r--r--indra/newview/llnearbychathandler.cpp3
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp13
-rw-r--r--indra/newview/llpanelmaininventory.cpp5
-rw-r--r--indra/newview/llpanelpeople.cpp4
-rw-r--r--indra/newview/llscreenchannel.cpp2
-rw-r--r--indra/newview/llspatialpartition.cpp2
-rw-r--r--indra/newview/llspeakbutton.cpp10
-rw-r--r--indra/newview/llspeakbutton.h5
-rw-r--r--indra/newview/llspeakers.cpp3
-rw-r--r--indra/newview/llstartup.cpp13
-rw-r--r--indra/newview/lltoastimpanel.cpp2
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp95
-rw-r--r--indra/newview/llviewermedia.h5
-rw-r--r--indra/newview/llviewermenu.cpp6
-rw-r--r--indra/newview/llviewertexture.cpp16
-rw-r--r--indra/newview/llviewertexture.h17
-rw-r--r--indra/newview/llviewertexturelist.cpp26
-rw-r--r--indra/newview/llviewertexturelist.h14
-rw-r--r--indra/newview/llvoicechannel.cpp15
-rw-r--r--indra/newview/llvoicechannel.h1
-rw-r--r--indra/newview/llvoiceclient.cpp4
-rw-r--r--indra/newview/llworldmipmap.cpp2
-rw-r--r--indra/newview/skins/default/xui/en/floater_gesture.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_incoming_call.xml40
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory.xml4
-rw-r--r--indra/newview/skins/default/xui/en/floater_outgoing_call.xml69
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml18
-rw-r--r--indra/newview/skins/default/xui/en/floater_tos.xml18
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml12
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml9
-rw-r--r--indra/newview/skins/default/xui/en/panel_activeim_row.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notify.xml194
-rw-r--r--indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification.xml24
-rw-r--r--indra/newview/skins/default/xui/en/panel_sys_well_item.xml5
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml2
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp1
-rw-r--r--indra/viewer_components/login/lllogin.cpp29
-rw-r--r--indra/viewer_components/login/tests/lllogin_test.cpp39
72 files changed, 2281 insertions, 1389 deletions
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index f2cdad8854..2a0dcaf333 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -1888,41 +1888,50 @@ void LLFloaterView::reshapeFloater(S32 width, S32 height, BOOL called_from_paren
// dependents use same follow flags as their "dependee"
continue;
}
- LLRect r = floaterp->getRect();
-
- // Compute absolute distance from each edge of screen
- S32 left_offset = llabs(r.mLeft - 0);
- S32 right_offset = llabs(old_width - r.mRight);
-
- S32 top_offset = llabs(old_height - r.mTop);
- S32 bottom_offset = llabs(r.mBottom - 0);
// Make if follow the edge it is closest to
U32 follow_flags = 0x0;
- if (left_offset < right_offset)
+ if (floaterp->isMinimized())
{
- follow_flags |= FOLLOWS_LEFT;
+ follow_flags |= (FOLLOWS_LEFT | FOLLOWS_TOP);
}
else
{
- follow_flags |= FOLLOWS_RIGHT;
- }
+ LLRect r = floaterp->getRect();
- // "No vertical adjustment" usually means that the bottom of the view
- // has been pushed up or down. Hence we want the floaters to follow
- // the top.
- if (!adjust_vertical)
- {
- follow_flags |= FOLLOWS_TOP;
- }
- else if (top_offset < bottom_offset)
- {
- follow_flags |= FOLLOWS_TOP;
- }
- else
- {
- follow_flags |= FOLLOWS_BOTTOM;
+ // Compute absolute distance from each edge of screen
+ S32 left_offset = llabs(r.mLeft - 0);
+ S32 right_offset = llabs(old_width - r.mRight);
+
+ S32 top_offset = llabs(old_height - r.mTop);
+ S32 bottom_offset = llabs(r.mBottom - 0);
+
+
+ if (left_offset < right_offset)
+ {
+ follow_flags |= FOLLOWS_LEFT;
+ }
+ else
+ {
+ follow_flags |= FOLLOWS_RIGHT;
+ }
+
+ // "No vertical adjustment" usually means that the bottom of the view
+ // has been pushed up or down. Hence we want the floaters to follow
+ // the top.
+ if (!adjust_vertical)
+ {
+ follow_flags |= FOLLOWS_TOP;
+ }
+ else if (top_offset < bottom_offset)
+ {
+ follow_flags |= FOLLOWS_TOP;
+ }
+ else
+ {
+ follow_flags |= FOLLOWS_BOTTOM;
+ }
}
floaterp->setFollows(follow_flags);
@@ -2172,16 +2181,16 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
const LLFloater::Params& default_params = LLFloater::getDefaultParams();
S32 floater_header_size = default_params.header_height;
static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0);
- S32 col = 0;
LLRect snap_rect_local = getLocalSnapRect();
- for(S32 row = snap_rect_local.mBottom;
- row < snap_rect_local.getHeight() - floater_header_size;
- row += floater_header_size ) //loop rows
- {
- for(col = snap_rect_local.mLeft;
- col < snap_rect_local.getWidth() - minimized_width;
- col += minimized_width)
+ for(S32 col = snap_rect_local.mLeft;
+ col < snap_rect_local.getWidth() - minimized_width;
+ col += minimized_width)
+ {
+ for(S32 row = snap_rect_local.mTop - floater_header_size;
+ row > floater_header_size;
+ row -= floater_header_size ) //loop rows
{
+
bool foundGap = TRUE;
for(child_list_const_iter_t child_it = getChildList()->begin();
child_it != getChildList()->end();
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b129bca1f3..9d44f34ea8 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -252,6 +252,7 @@ set(viewer_SOURCE_FILES
llinventoryfilter.cpp
llinventoryfunctions.cpp
llinventorymodel.cpp
+ llinventoryobserver.cpp
llinventorypanel.cpp
llinventorysubtreepanel.cpp
lljoystickbutton.cpp
@@ -748,6 +749,7 @@ set(viewer_HEADER_FILES
llinventoryfilter.h
llinventoryfunctions.h
llinventorymodel.h
+ llinventoryobserver.h
llinventorypanel.h
llinventorysubtreepanel.h
lljoystickbutton.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 38f14793d9..8ad52784d3 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4259,7 +4259,29 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>LogMessages</key>
+ <key>LoginSRVTimeout</key>
+ <map>
+ <key>Comment</key>
+ <string>Duration in seconds of the login SRV request timeout</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>10.0</real>
+ </map>
+ <key>LoginSRVPump</key>
+ <map>
+ <key>Comment</key>
+ <string>Name of the message pump that handles SRV request</string>
+ <key>Persist</key>
+ <integer>0</integer>
+ <key>Type</key>
+ <string>String</string>
+ <key>Value</key>
+ <string>LLAres</string>
+ </map>
+ <key>LogMessages</key>
<map>
<key>Comment</key>
<string>Log network traffic</string>
@@ -5501,7 +5523,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>QAMode</key>
<map>
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 9938c3db2b..9b4986247f 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -887,9 +887,8 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
lldebugs << " " << LLWearableDictionary::getTypeLabel(type) << llendl;
}
- // What we do here is get the complete information on the items in
- // the inventory, and set up an observer that will wait for that to
- // happen.
+ // Get the complete information on the items in the inventory and set up an observer
+ // that will trigger when the complete information is fetched.
LLInventoryFetchDescendentsObserver::folder_ref_t folders;
folders.push_back(current_outfit_id);
outfit->fetchDescendents(folders);
@@ -2023,6 +2022,8 @@ void LLInitialWearablesFetch::done()
else
{
processWearablesMessage();
+ // Create links for attachments that may have arrived before the COF existed.
+ LLAppearanceManager::linkRegisteredAttachments();
}
delete this;
}
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index d14de1c301..0901289dac 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -1123,6 +1123,7 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
{
if (do_update)
LLAppearanceManager::updateAppearanceFromCOF();
+ return;
}
else
{
@@ -1134,6 +1135,7 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
LLAssetType::AT_LINK,
cb);
}
+ return;
}
/* static */
@@ -1281,3 +1283,22 @@ void LLAppearanceManager::unregisterAttachment(const LLUUID& item_id)
//llinfos << "no link changes, inv link not enabled" << llendl;
}
}
+
+/* static */
+void LLAppearanceManager::linkRegisteredAttachments()
+{
+ for (std::set<LLUUID>::iterator it = sRegisteredAttachments.begin();
+ it != sRegisteredAttachments.end();
+ ++it)
+ {
+ LLUUID item_id = *it;
+ LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ if (item)
+ {
+ wearItem(item, false);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ gInventory.notifyObservers();
+ }
+ }
+ sRegisteredAttachments.clear();
+}
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index 56f54dfc23..7dea16b6cf 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -71,6 +71,7 @@ public:
static void unregisterAttachment(const LLUUID& item_id);
static void registerAttachment(const LLUUID& item_id);
static void setAttachmentInvLinkEnable(bool val);
+ static void linkRegisteredAttachments();
private:
static void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type);
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index f631978565..ee4a9df15f 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -192,7 +192,7 @@ void LLAvatarActions::startIM(const LLUUID& id)
// static
void LLAvatarActions::startCall(const LLUUID& id)
{
- if (id.isNull() || isCalling(id))
+ if (id.isNull())
{
return;
}
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 291f645ea2..dd06959472 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -40,6 +40,7 @@
#include "llimfloater.h" // for LLIMFloater
#include "lllayoutstack.h"
#include "llnearbychatbar.h"
+#include "llspeakbutton.h"
#include "llsplitbutton.h"
#include "llsyswellwindow.h"
#include "llfloatercamera.h"
@@ -51,6 +52,7 @@ LLBottomTray::LLBottomTray(const LLSD&)
mNearbyChatBar(NULL),
mToolbarStack(NULL)
, mMovementButton(NULL)
+, mResizeState(RS_NORESIZE)
// Add more members
{
mFactoryMap["chat_bar"] = LLCallbackMap(LLBottomTray::createNearbyChatBar, NULL);
@@ -185,6 +187,28 @@ void LLBottomTray::sessionIDUpdated(const LLUUID& old_session_id, const LLUUID&
}
}
+// virtual
+void LLBottomTray::onChange(EStatusType status, const std::string &channelURI, bool proximal)
+{
+ // Time it takes to connect to voice channel might be pretty long,
+ // so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED.
+ BOOL enable = FALSE;
+
+ switch (status)
+ {
+ // Do not add STATUS_VOICE_ENABLED because voice chat is
+ // inactive until STATUS_JOINED
+ case STATUS_JOINED:
+ enable = TRUE;
+ break;
+ default:
+ enable = FALSE;
+ break;
+ }
+
+ mSpeakBtn->setEnabled(enable);
+}
+
//virtual
void LLBottomTray::onFocusLost()
{
@@ -238,22 +262,22 @@ void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask)
void LLBottomTray::showGestureButton(BOOL visible)
{
- showTrayButton(RS_BUTTON_GESTURES, visible);
+ setTrayButtonVisibleIfPossible(RS_BUTTON_GESTURES, visible);
}
void LLBottomTray::showMoveButton(BOOL visible)
{
- showTrayButton(RS_BUTTON_MOVEMENT, visible);
+ setTrayButtonVisibleIfPossible(RS_BUTTON_MOVEMENT, visible);
}
void LLBottomTray::showCameraButton(BOOL visible)
{
- showTrayButton(RS_BUTTON_CAMERA, visible);
+ setTrayButtonVisibleIfPossible(RS_BUTTON_CAMERA, visible);
}
void LLBottomTray::showSnapshotButton(BOOL visible)
{
- showTrayButton(RS_BUTTON_SNAPSHOT, visible);
+ setTrayButtonVisibleIfPossible(RS_BUTTON_SNAPSHOT, visible);
}
namespace
@@ -280,6 +304,19 @@ BOOL LLBottomTray::postBuild()
mSnapshotPanel = getChild<LLPanel>("snapshot_panel");
setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
+ mSpeakBtn = getChild<LLSpeakButton>("talk");
+
+ // Speak button should be initially disabled because
+ // it takes some time between logging in to world and connecting to voice channel.
+ mSpeakBtn->setEnabled(FALSE);
+
+ // Localization tool doesn't understand custom buttons like <talk_button>
+ mSpeakBtn->setSpeakToolTip( getString("SpeakBtnToolTip") );
+ mSpeakBtn->setShowToolTip( getString("VoiceControlBtnToolTip") );
+
+ // Registering Chat Bar to receive Voice client status change notifications.
+ gVoiceClient->addObserver(this);
+
if (mChicletPanel && mToolbarStack && mNearbyChatBar)
{
verifyChildControlsSizes();
@@ -331,74 +368,87 @@ void LLBottomTray::verifyChildControlsSizes()
mNearbyChatBar->setRect(rect);
}
}
-#define __FEATURE_EXT_991
+
void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent)
{
- lldebugs << "****************************************" << llendl;
+ static S32 debug_calling_number = 0;
+ lldebugs << "**************************************** " << ++debug_calling_number << llendl;
S32 current_width = getRect().getWidth();
+ S32 delta_width = width - current_width;
lldebugs << "Reshaping: "
<< ", width: " << width
- << ", height: " << height
- << ", called_from_parent: " << called_from_parent
<< ", cur width: " << current_width
- << ", cur height: " << getRect().getHeight()
+ << ", delta_width: " << delta_width
+ << ", called_from_parent: " << called_from_parent
<< llendl;
if (mNearbyChatBar) log(mNearbyChatBar, "before");
if (mChicletPanel) log(mChicletPanel, "before");
+ // stores width size on which bottom tray is less than width required by its children. EXT-991
+ static S32 extra_shrink_width = 0;
+ bool should_be_reshaped = true;
+
if (mChicletPanel && mToolbarStack && mNearbyChatBar)
{
mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE);
verifyChildControlsSizes();
- updateResizeState(width, current_width);
- }
-
- LLPanel::reshape(width, height, called_from_parent);
-
-
- if (mNearbyChatBar) log(mNearbyChatBar, "after");
- if (mChicletPanel) log(mChicletPanel, "after");
-}
-
-void LLBottomTray::updateResizeState(S32 new_width, S32 cur_width)
-{
- mResizeState = RS_NORESIZE;
-
- S32 delta_width = new_width - cur_width;
-// if (delta_width == 0) return;
- bool shrink = new_width < cur_width;
-
- const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
- const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
-
- const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
- const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
- const S32 chatbar_panel_max_width = mNearbyChatBar->getMaxWidth();
- lldebugs << "chatbar_panel_width: " << chatbar_panel_width
- << ", chatbar_panel_min_width: " << chatbar_panel_min_width
- << ", chatbar_panel_max_width: " << chatbar_panel_max_width
- << ", chiclet_panel_width: " << chiclet_panel_width
- << ", chiclet_panel_min_width: " << chiclet_panel_min_width
- << llendl;
+ // bottom tray is narrowed
+ if (delta_width < 0)
+ {
+ if (extra_shrink_width > 0)
+ {
+ // is world rect was extra shrunk and decreasing again only update this value
+ // to delta_width negative
+ extra_shrink_width -= delta_width; // use "-=" because delta_width is negative
+ should_be_reshaped = false;
+ }
+ else
+ {
+ extra_shrink_width = processWidthDecreased(delta_width);
- // bottom tray is narrowed
- if (shrink)
- {
- processWidthDecreased(delta_width);
+ // increase new width to extra_shrink_width value to not reshape less than bottom tray minimum
+ width += extra_shrink_width;
+ }
+ }
+ // bottom tray is widen
+ else
+ {
+ if (extra_shrink_width > delta_width)
+ {
+ // Less than minimum width is more than increasing (delta_width)
+ // only reduce it value and make no reshape
+ extra_shrink_width -= delta_width;
+ should_be_reshaped = false;
+ }
+ else
+ {
+ if (extra_shrink_width > 0)
+ {
+ // If we have some extra shrink width let's reduce delta_width & width
+ delta_width -= extra_shrink_width;
+ width -= extra_shrink_width;
+ extra_shrink_width = 0;
+ }
+ processWidthIncreased(delta_width);
+ }
+ }
}
- // bottom tray is widen
- else
+
+ lldebugs << "There is no enough width to reshape all children: " << extra_shrink_width << llendl;
+ if (should_be_reshaped)
{
- processWidthIncreased(delta_width);
+ lldebugs << "Reshape all children with width: " << width << llendl;
+ LLPanel::reshape(width, height, called_from_parent);
}
- lldebugs << "New resize state: " << mResizeState << llendl;
+ if (mNearbyChatBar) log(mNearbyChatBar, "after");
+ if (mChicletPanel) log(mChicletPanel, "after");
}
-void LLBottomTray::processWidthDecreased(S32 delta_width)
+S32 LLBottomTray::processWidthDecreased(S32 delta_width)
{
bool still_should_be_processed = true;
@@ -409,7 +459,6 @@ void LLBottomTray::processWidthDecreased(S32 delta_width)
{
// we have some space to decrease chiclet panel
S32 panel_delta_min = chiclet_panel_width - chiclet_panel_min_width;
- mResizeState |= RS_CHICLET_PANEL;
S32 delta_panel = llmin(-delta_width, panel_delta_min);
@@ -437,27 +486,25 @@ void LLBottomTray::processWidthDecreased(S32 delta_width)
{
// we have some space to decrease chatbar panel
S32 panel_delta_min = chatbar_panel_width - chatbar_panel_min_width;
- mResizeState |= RS_CHATBAR_INPUT;
S32 delta_panel = llmin(-delta_width, panel_delta_min);
- // is chatbar panel width enough to process resizing?
+ // whether chatbar panel width is enough to process resizing?
delta_width += panel_delta_min;
-
still_should_be_processed = delta_width < 0;
mNearbyChatBar->reshape(mNearbyChatBar->getRect().getWidth() - delta_panel, mNearbyChatBar->getRect().getHeight());
+ log(mChicletPanel, "after processing panel decreasing via nearby chatbar panel");
+
lldebugs << "RS_CHATBAR_INPUT"
<< ", delta_panel: " << delta_panel
<< ", delta_width: " << delta_width
<< llendl;
-
- log(mChicletPanel, "after nearby was processed");
-
}
+ S32 extra_shrink_width = 0;
S32 buttons_freed_width = 0;
if (still_should_be_processed)
{
@@ -480,7 +527,9 @@ void LLBottomTray::processWidthDecreased(S32 delta_width)
if (delta_width < 0)
{
- llwarns << "WARNING: there is no enough room for bottom tray, resizing still should be processed" << llendl;
+ extra_shrink_width = -delta_width;
+ lldebugs << "There is no enough room for bottom tray, resizing still should be processed: "
+ << extra_shrink_width << llendl;
}
if (buttons_freed_width > 0)
@@ -491,10 +540,14 @@ void LLBottomTray::processWidthDecreased(S32 delta_width)
lldebugs << buttons_freed_width << llendl;
}
}
+
+ return extra_shrink_width;
}
void LLBottomTray::processWidthIncreased(S32 delta_width)
{
+ if (delta_width <= 0) return;
+
const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
@@ -573,7 +626,6 @@ void LLBottomTray::processWidthIncreased(S32 delta_width)
S32 chatbar_panel_width_ = mNearbyChatBar->getRect().getWidth();
if (delta_width > 0 && chatbar_panel_width_ < chatbar_panel_max_width)
{
- mResizeState |= RS_CHATBAR_INPUT;
S32 delta_panel_max = chatbar_panel_max_width - chatbar_panel_width_;
S32 delta_panel = llmin(delta_width, delta_panel_max);
delta_width -= delta_panel_max;
@@ -589,7 +641,7 @@ bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* availa
lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
return false;
}
- bool can_be_shown = canButtonBeShown(panel);
+ bool can_be_shown = canButtonBeShown(shown_object_type);
if (can_be_shown)
{
//validate if we have enough room to show this button
@@ -600,22 +652,23 @@ bool LLBottomTray::processShowButton(EResizeState shown_object_type, S32* availa
*available_width -= required_width;
*buttons_required_width += required_width;
- showTrayButton(shown_object_type, true);
+ setTrayButtonVisible(shown_object_type, true);
lldebugs << "processing object type: " << shown_object_type
<< ", buttons_required_width: " << *buttons_required_width
<< llendl;
+ mResizeState &= ~shown_object_type;
}
}
return can_be_shown;
}
-void LLBottomTray::processHideButton(EResizeState shown_object_type, S32* required_width, S32* buttons_freed_width)
+void LLBottomTray::processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width)
{
- LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
+ LLPanel* panel = mStateProcessedObjectMap[processed_object_type];
if (NULL == panel)
{
- lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
+ lldebugs << "There is no object to process for state: " << processed_object_type << llendl;
return;
}
@@ -628,17 +681,19 @@ void LLBottomTray::processHideButton(EResizeState shown_object_type, S32* requir
*buttons_freed_width += *required_width;
}
- showTrayButton(shown_object_type, false);
+ setTrayButtonVisible(processed_object_type, false);
- lldebugs << "processing object type: " << shown_object_type
+ mResizeState |= processed_object_type;
+
+ lldebugs << "processing object type: " << processed_object_type
<< ", buttons_freed_width: " << *buttons_freed_width
<< llendl;
}
}
-bool LLBottomTray::canButtonBeShown(LLPanel* panel) const
+bool LLBottomTray::canButtonBeShown(EResizeState processed_object_type) const
{
- bool can_be_shown = !panel->getVisible();
+ bool can_be_shown = mResizeState & processed_object_type;
if (can_be_shown)
{
// *TODO: mantipov: synchronize with situation when button was hidden via context menu;
@@ -654,7 +709,7 @@ void LLBottomTray::initStateProcessedObjectMap()
mStateProcessedObjectMap.insert(std::make_pair(RS_BUTTON_SNAPSHOT, mSnapshotPanel));
}
-void LLBottomTray::showTrayButton(EResizeState shown_object_type, bool visible)
+void LLBottomTray::setTrayButtonVisible(EResizeState shown_object_type, bool visible)
{
LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
if (NULL == panel)
@@ -665,4 +720,49 @@ void LLBottomTray::showTrayButton(EResizeState shown_object_type, bool visible)
panel->setVisible(visible);
}
+
+void LLBottomTray::setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible)
+{
+ bool can_be_set = true;
+
+ if (visible)
+ {
+ LLPanel* panel = mStateProcessedObjectMap[shown_object_type];
+ if (NULL == panel)
+ {
+ lldebugs << "There is no object to process for state: " << shown_object_type << llendl;
+ return;
+ }
+
+ const S32 chatbar_panel_width = mNearbyChatBar->getRect().getWidth();
+ const S32 chatbar_panel_min_width = mNearbyChatBar->getMinWidth();
+
+ const S32 chiclet_panel_width = mChicletPanel->getParent()->getRect().getWidth();
+ const S32 chiclet_panel_min_width = mChicletPanel->getMinWidth();
+
+ const S32 available_width = (chatbar_panel_width - chatbar_panel_min_width)
+ + (chiclet_panel_width - chiclet_panel_min_width);
+
+ const S32 required_width = panel->getRect().getWidth();
+ can_be_set = available_width >= required_width;
+ }
+
+ if (can_be_set)
+ {
+ setTrayButtonVisible(shown_object_type, visible);
+
+ // if we hide the button mark it NOT to show while future bottom tray extending
+ if (!visible)
+ {
+ mResizeState &= ~shown_object_type;
+ }
+ }
+ else
+ {
+ // mark this button to show it while future bottom tray extending
+ mResizeState |= shown_object_type;
+ LLNotifications::instance().add("BottomTrayButtonCanNotBeShown");
+ }
+}
+
//EOF
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index 2972a2b1ac..86d341f233 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -33,7 +33,7 @@
#ifndef LL_LLBOTTOMPANEL_H
#define LL_LLBOTTOMPANEL_H
-#include <llmenugl.h>
+#include "llmenugl.h"
#include "llpanel.h"
#include "llimview.h"
@@ -51,6 +51,7 @@ class LLBottomTray
: public LLSingleton<LLBottomTray>
, public LLPanel
, public LLIMSessionObserver
+ , public LLVoiceClientStatusObserver
{
LOG_CLASS(LLBottomTray);
friend class LLSingleton<LLBottomTray>;
@@ -75,6 +76,10 @@ public:
virtual void onFocusLost();
virtual void setVisible(BOOL visible);
+ // Implements LLVoiceClientStatusObserver::onChange() to enable the speak
+ // button when voice is available
+ /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
+
void showBottomTrayContextMenu(S32 x, S32 y, MASK mask);
void showGestureButton(BOOL visible);
@@ -98,14 +103,30 @@ private:
void updateResizeState(S32 new_width, S32 cur_width);
void verifyChildControlsSizes();
- void processWidthDecreased(S32 delta_width);
+ S32 processWidthDecreased(S32 delta_width);
void processWidthIncreased(S32 delta_width);
void log(LLView* panel, const std::string& descr);
bool processShowButton(EResizeState shown_object_type, S32* available_width, S32* buttons_required_width);
- void processHideButton(EResizeState shown_object_type, S32* required_width, S32* buttons_freed_width);
- bool canButtonBeShown(LLPanel* panel) const;
+ void processHideButton(EResizeState processed_object_type, S32* required_width, S32* buttons_freed_width);
+ bool canButtonBeShown(EResizeState processed_object_type) const;
void initStateProcessedObjectMap();
- void showTrayButton(EResizeState shown_object_type, bool visible);
+
+ /**
+ * Sets passed visibility to object specified by resize type.
+ */
+ void setTrayButtonVisible(EResizeState shown_object_type, bool visible);
+
+ /**
+ * Sets passed visibility to object specified by resize type if it is possible.
+ *
+ * If it is impossible to show required button due to there is no enough room in bottom tray
+ * it will no be shown. Is called via context menu commands.
+ * Method also stores resize state to be processed while future bottom tray extending:
+ * - if hidden while resizing button should be hidden it will not be shown while extending;
+ * - if hidden via context menu button should be shown but there is no enough room for now
+ * it will be shown while extending.
+ */
+ void setTrayButtonVisibleIfPossible(EResizeState shown_object_type, bool visible);
MASK mResizeState;
diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp
index 4523267edd..442dc660cd 100644
--- a/indra/newview/llchatbar.cpp
+++ b/indra/newview/llchatbar.cpp
@@ -210,8 +210,9 @@ void LLChatBar::refreshGestures()
// collect list of unique gestures
std::map <std::string, BOOL> unique;
- LLGestureManager::item_map_t::iterator it;
- for (it = LLGestureManager::instance().mActive.begin(); it != LLGestureManager::instance().mActive.end(); ++it)
+ LLGestureManager::item_map_t::const_iterator it;
+ const LLGestureManager::item_map_t& active_gestures = LLGestureManager::instance().getActiveGestures();
+ for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
{
LLMultiGesture* gesture = (*it).second;
if (gesture)
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
index 046e1d92dc..f228373063 100644
--- a/indra/newview/llchathistory.cpp
+++ b/indra/newview/llchathistory.cpp
@@ -53,7 +53,7 @@ std::string formatCurrentTime()
time_t utc_time;
utc_time = time_corrected();
std::string timeStr ="["+ LLTrans::getString("TimeHour")+"]:["
- +LLTrans::getString("TimeMin")+"] ";
+ +LLTrans::getString("TimeMin")+"]";
LLSD substitution;
@@ -84,6 +84,10 @@ public:
if (level == "profile")
{
+ LLSD params;
+ params["object_id"] = getAvatarId();
+
+ LLFloaterReg::showInstance("inspect_object", params);
}
else if (level == "block")
{
@@ -344,7 +348,9 @@ LLView* LLChatHistory::getHeader(const LLChat& chat,const LLStyle::Params& style
void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params)
{
LLView* view = NULL;
- std::string view_text = "\n[" + formatCurrentTime() + "] " + chat.mFromName + ": ";
+ std::string view_text = "\n[" + formatCurrentTime() + "] ";
+ if (utf8str_trim(chat.mFromName).size() != 0 && chat.mFromName != SYSTEM_FROM)
+ view_text += chat.mFromName + ": ";
LLInlineViewSegment::Params p;
p.force_newline = true;
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index fd86192650..9e290c8c04 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -838,11 +838,15 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
LLUUID session_id = data["session_id"].asUUID();
LLUUID from_id = data["from_id"].asUUID();
const std::string from = data["from"].asString();
+ S32 unread = data["num_unread"].asInteger();
- //we do not show balloon (indicator of new messages) for system messages and our own messages
- if (from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from) return;
+ // if new message came
+ if(unread != 0)
+ {
+ //we do not show balloon (indicator of new messages) for system messages and our own messages
+ if (from_id.isNull() || from_id == gAgentID || SYSTEM_FROM == from) return;
+ }
- S32 unread = data["num_unread"].asInteger();
LLIMFloater* im_floater = LLIMFloater::findInstance(session_id);
if (im_floater && im_floater->getVisible())
{
@@ -862,7 +866,6 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
llwarns << "Unable to set counter for chiclet " << session_id << llendl;
}
}
-
}
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index c114eed4a2..ca0ba96a08 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -89,6 +89,52 @@ LLFloaterGesture::LLFloaterGesture(const LLSD& key)
//LLUICtrlFactory::getInstance()->buildFloater(this, "floater_gesture.xml");
}
+void LLFloaterGesture::done()
+{
+ //this method can be called twice: for GestureFolder and once after loading all sudir of GestureFolder
+ if (gInventory.isCategoryComplete(mGestureFolderID))
+ {
+ LL_DEBUGS("Gesture")<< "mGestureFolderID loaded" << LL_ENDL;
+ // we load only gesture folder without childred.
+ LLInventoryModel::cat_array_t* categories;
+ LLInventoryModel::item_array_t* items;
+ folder_ref_t unloaded_folders;
+ LL_DEBUGS("Gesture")<< "Get subdirs of Gesture Folder...." << LL_ENDL;
+ gInventory.getDirectDescendentsOf(mGestureFolderID, categories, items);
+ if (categories->empty())
+ {
+ gInventory.removeObserver(this);
+ LL_INFOS("Gesture")<< "Gesture dos NOT contains sub-directories."<< LL_ENDL;
+ return;
+ }
+ LL_DEBUGS("Gesture")<< "There are " << categories->size() << " Folders "<< LL_ENDL;
+ for (LLInventoryModel::cat_array_t::iterator it = categories->begin(); it != categories->end(); it++)
+ {
+ if (!gInventory.isCategoryComplete(it->get()->getUUID()))
+ {
+ unloaded_folders.push_back(it->get()->getUUID());
+ LL_DEBUGS("Gesture")<< it->get()->getName()<< " Folder added to fetchlist"<< LL_ENDL;
+ }
+
+ }
+ if (!unloaded_folders.empty())
+ {
+ LL_DEBUGS("Gesture")<< "Fetching subdirectories....." << LL_ENDL;
+ fetchDescendents(unloaded_folders);
+ }
+ else
+ {
+ LL_DEBUGS("Gesture")<< "All Gesture subdirectories have been loaded."<< LL_ENDL;
+ gInventory.removeObserver(this);
+ buildGestureList();
+ }
+ }
+ else
+ {
+ LL_WARNS("Gesture")<< "Gesture list was NOT loaded"<< LL_ENDL;
+ }
+}
+
// virtual
LLFloaterGesture::~LLFloaterGesture()
{
@@ -121,7 +167,14 @@ BOOL LLFloaterGesture::postBuild()
childSetVisible("play_btn", true);
childSetVisible("stop_btn", false);
setDefaultBtn("play_btn");
-
+ mGestureFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE, false);
+
+ folder_ref_t folders;
+ folders.push_back(mGestureFolderID);
+ //perform loading Gesture directory anyway to make sure that all subdirectory are loaded too. See method done() for details.
+ gInventory.addObserver(this);
+ fetchDescendents(folders);
+
buildGestureList();
childSetFocus("gesture_list");
@@ -171,101 +224,125 @@ void LLFloaterGesture::buildGestureList()
if (! (list && scroll)) return;
- // attempt to preserve scroll position through re-builds
- // since we do re-build any time anything dirties
- S32 current_scroll_pos = scroll->getScrollPos();
-
+ LLUUID selected_item = list->getCurrentID();
+ LL_DEBUGS("Gesture")<< "Rebuilding gesture list "<< LL_ENDL;
list->operateOnAll(LLCtrlListInterface::OP_DELETE);
- LLGestureManager::item_map_t::iterator it;
- for (it = LLGestureManager::instance().mActive.begin(); it != LLGestureManager::instance().mActive.end(); ++it)
+ LLGestureManager::item_map_t::const_iterator it;
+ const LLGestureManager::item_map_t& active_gestures = LLGestureManager::instance().getActiveGestures();
+ for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
{
- const LLUUID& item_id = (*it).first;
- LLMultiGesture* gesture = (*it).second;
+ addGesture(it->first,it->second, list);
+ }
+ if (gInventory.isCategoryComplete(mGestureFolderID))
+ {
+ LLIsType is_gesture(LLAssetType::AT_GESTURE);
+ LLInventoryModel::cat_array_t categories;
+ LLInventoryModel::item_array_t items;
+ gInventory.collectDescendentsIf(mGestureFolderID, categories, items,
+ LLInventoryModel::EXCLUDE_TRASH, is_gesture);
- // Note: Can have NULL item if inventory hasn't arrived yet.
- std::string item_name = getString("loading");
- LLInventoryItem* item = gInventory.getItem(item_id);
- if (item)
+ for (LLInventoryModel::item_array_t::iterator it = items.begin(); it!= items.end(); ++it)
{
- item_name = item->getName();
+ LLInventoryItem* item = it->get();
+ if (active_gestures.find(item->getUUID()) == active_gestures.end())
+ {
+ // if gesture wasn't loaded yet, we can display only name
+ addGesture(item->getUUID(), NULL, list);
+ }
}
+ }
+ // attempt to preserve scroll position through re-builds
+ // since we do re-build any time anything dirties
+ if(list->selectByValue(LLSD(selected_item)))
+ {
+ scroll->scrollToShowSelected();
+ }
+}
- std::string font_style = "NORMAL";
- // If gesture is playing, bold it
+void LLFloaterGesture::addGesture(const LLUUID& item_id , LLMultiGesture* gesture,LLCtrlListInterface * list )
+{
+ // Note: Can have NULL item if inventory hasn't arrived yet.
+ static std::string item_name = getString("loading");
+ LLInventoryItem* item = gInventory.getItem(item_id);
+ if (item)
+ {
+ item_name = item->getName();
+ }
+
+ static std::string font_style = "NORMAL";
+ // If gesture is playing, bold it
- LLSD element;
- element["id"] = item_id;
+ LLSD element;
+ element["id"] = item_id;
- if (gesture)
+ if (gesture)
+ {
+ if (gesture->mPlaying)
{
- if (gesture->mPlaying)
- {
- font_style = "BOLD";
- }
+ font_style = "BOLD";
+ }
- element["columns"][0]["column"] = "trigger";
- element["columns"][0]["value"] = gesture->mTrigger;
- element["columns"][0]["font"]["name"] = "SANSSERIF";
- element["columns"][0]["font"]["style"] = font_style;
+ element["columns"][0]["column"] = "trigger";
+ element["columns"][0]["value"] = gesture->mTrigger;
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = font_style;
- std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
- std::string buffer;
+ std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
+ std::string buffer;
- if (gesture->mKey == KEY_NONE)
- {
- buffer = "---";
- key_string = "~~~"; // alphabetize to end
- }
- else
- {
- buffer = LLKeyboard::stringFromAccelerator( gesture->mMask, gesture->mKey );
- }
+ if (gesture->mKey == KEY_NONE)
+ {
+ buffer = "---";
+ key_string = "~~~"; // alphabetize to end
+ }
+ else
+ {
+ buffer = LLKeyboard::stringFromAccelerator(gesture->mMask,
+ gesture->mKey);
+ }
- element["columns"][1]["column"] = "shortcut";
- element["columns"][1]["value"] = buffer;
- element["columns"][1]["font"]["name"] = "SANSSERIF";
- element["columns"][1]["font"]["style"] = font_style;
+ element["columns"][1]["column"] = "shortcut";
+ element["columns"][1]["value"] = buffer;
+ element["columns"][1]["font"]["name"] = "SANSSERIF";
+ element["columns"][1]["font"]["style"] = font_style;
- // hidden column for sorting
- element["columns"][2]["column"] = "key";
- element["columns"][2]["value"] = key_string;
- element["columns"][2]["font"]["name"] = "SANSSERIF";
- element["columns"][2]["font"]["style"] = font_style;
+ // hidden column for sorting
+ element["columns"][2]["column"] = "key";
+ element["columns"][2]["value"] = key_string;
+ element["columns"][2]["font"]["name"] = "SANSSERIF";
+ element["columns"][2]["font"]["style"] = font_style;
- // Only add "playing" if we've got the name, less confusing. JC
- if (item && gesture->mPlaying)
- {
- item_name += " " + getString("playing");
- }
- element["columns"][3]["column"] = "name";
- element["columns"][3]["value"] = item_name;
- element["columns"][3]["font"]["name"] = "SANSSERIF";
- element["columns"][3]["font"]["style"] = font_style;
- }
- else
+ // Only add "playing" if we've got the name, less confusing. JC
+ if (item && gesture->mPlaying)
{
- element["columns"][0]["column"] = "trigger";
- element["columns"][0]["value"] = "";
- element["columns"][0]["font"]["name"] = "SANSSERIF";
- element["columns"][0]["font"]["style"] = font_style;
- element["columns"][0]["column"] = "trigger";
- element["columns"][0]["value"] = "---";
- element["columns"][0]["font"]["name"] = "SANSSERIF";
- element["columns"][0]["font"]["style"] = font_style;
- element["columns"][2]["column"] = "key";
- element["columns"][2]["value"] = "~~~";
- element["columns"][2]["font"]["name"] = "SANSSERIF";
- element["columns"][2]["font"]["style"] = font_style;
- element["columns"][3]["column"] = "name";
- element["columns"][3]["value"] = item_name;
- element["columns"][3]["font"]["name"] = "SANSSERIF";
- element["columns"][3]["font"]["style"] = font_style;
+ item_name += " " + getString("playing");
}
- list->addElement(element, ADD_BOTTOM);
+ element["columns"][3]["column"] = "name";
+ element["columns"][3]["value"] = item_name;
+ element["columns"][3]["font"]["name"] = "SANSSERIF";
+ element["columns"][3]["font"]["style"] = font_style;
}
-
- scroll->setScrollPos(current_scroll_pos);
+ else
+ {
+ element["columns"][0]["column"] = "trigger";
+ element["columns"][0]["value"] = "";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = font_style;
+ element["columns"][0]["column"] = "trigger";
+ element["columns"][0]["value"] = "---";
+ element["columns"][0]["font"]["name"] = "SANSSERIF";
+ element["columns"][0]["font"]["style"] = font_style;
+ element["columns"][2]["column"] = "key";
+ element["columns"][2]["value"] = "~~~";
+ element["columns"][2]["font"]["name"] = "SANSSERIF";
+ element["columns"][2]["font"]["style"] = font_style;
+ element["columns"][3]["column"] = "name";
+ element["columns"][3]["value"] = item_name;
+ element["columns"][3]["font"]["name"] = "SANSSERIF";
+ element["columns"][3]["font"]["style"] = font_style;
+ }
+ list->addElement(element, ADD_BOTTOM);
}
void LLFloaterGesture::onClickInventory()
@@ -284,14 +361,21 @@ void LLFloaterGesture::onClickPlay()
LLCtrlListInterface *list = childGetListInterface("gesture_list");
if (!list) return;
const LLUUID& item_id = list->getCurrentID();
+ if(item_id.isNull()) return;
- if (LLGestureManager::instance().isGesturePlaying(item_id))
+ LL_DEBUGS("Gesture")<<" Trying to play gesture id: "<< item_id <<LL_ENDL;
+ if(!LLGestureManager::instance().isGestureActive(item_id))
{
- LLGestureManager::instance().stopGesture(item_id);
+ // we need to inform server about gesture activating to be consistent with LLPreviewGesture.
+ BOOL inform_server = TRUE;
+ BOOL deactivate_similar = FALSE;
+ LLGestureManager::instance().activateGestureWithAsset(item_id, gInventory.getItem(item_id)->getAssetUUID(), inform_server, deactivate_similar);
+ LL_DEBUGS("Gesture")<< "Activating gesture with inventory ID: " << item_id <<LL_ENDL;
+ LLGestureManager::instance().setGestureLoadedCallback(item_id, boost::bind(&LLFloaterGesture::playGesture, this, item_id));
}
else
{
- LLGestureManager::instance().playGesture(item_id);
+ playGesture(item_id);
}
}
@@ -345,3 +429,14 @@ void LLFloaterGesture::onCommitList()
childSetVisible("stop_btn", false);
}
}
+void LLFloaterGesture::playGesture(LLUUID item_id)
+{
+ if (LLGestureManager::instance().isGesturePlaying(item_id))
+ {
+ LLGestureManager::instance().stopGesture(item_id);
+ }
+ else
+ {
+ LLGestureManager::instance().playGesture(item_id);
+ }
+}
diff --git a/indra/newview/llfloatergesture.h b/indra/newview/llfloatergesture.h
index 9c1ab27cb0..9d047bf1cf 100644
--- a/indra/newview/llfloatergesture.h
+++ b/indra/newview/llfloatergesture.h
@@ -38,7 +38,7 @@
#define LL_LLFLOATERGESTURE_H
#include "llfloater.h"
-
+#include "llinventorymodel.h"
#include "lldarray.h"
class LLScrollContainer;
@@ -51,31 +51,35 @@ class LLGestureOptions;
class LLScrollListCtrl;
class LLFloaterGestureObserver;
class LLFloaterGestureInventoryObserver;
+class LLMultiGesture;
class LLFloaterGesture
-: public LLFloater
+: public LLFloater, LLInventoryFetchDescendentsObserver
{
+ LOG_CLASS(LLFloaterGesture);
public:
LLFloaterGesture(const LLSD& key);
virtual ~LLFloaterGesture();
virtual BOOL postBuild();
-
+ virtual void done ();
void refreshAll();
protected:
// Reads from the gesture manager's list of active gestures
// and puts them in this list.
void buildGestureList();
-
+ void addGesture(const LLUUID& item_id, LLMultiGesture* gesture, LLCtrlListInterface * list);
void onClickInventory();
void onClickEdit();
void onClickPlay();
void onClickNew();
void onCommitList();
+ void playGesture(LLUUID item_id);
protected:
LLUUID mSelectedID;
+ LLUUID mGestureFolderID;
LLFloaterGestureObserver* mObserver;
};
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 1ff2566dca..481b75cf73 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -91,44 +91,39 @@ const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollect
return LLUUID::null;
}
-
-// LLViewerInventoryCategory::fetchDescendents has it own period of fetching.
-// for now it is FETCH_TIMER_EXPIRY = 10.0f; So made our period a bit more.
-const F32 FETCH_FRIENDS_DESCENDENTS_PERIOD = 11.0f;
-
-
/**
- * Intended to call passed callback after the specified period of time.
+ * Class for fetching initial friend cards data
*
- * Implemented to fix an issue when Inventory folders are in incomplete state. See EXT-2061, EXT-1935, EXT-813.
- * For now it uses to periodically sync Inventory Friends/All folder with a Agent's Friends List
- * until it is complete.
- */
-class FriendListUpdater : public LLEventTimer
+ * Implemented to fix an issue when Inventory folders are in incomplete state.
+ * See EXT-2320, EXT-2061, EXT-1935, EXT-813.
+ * Uses a callback to sync Inventory Friends/All folder with agent's Friends List.
+ */
+class LLInitialFriendCardsFetch : public LLInventoryFetchDescendentsObserver
{
public:
- typedef boost::function<bool()> callback_t;
+ typedef boost::function<void()> callback_t;
- FriendListUpdater(callback_t cb, F32 period)
- : LLEventTimer(period)
- , mCallback(cb)
- {
- mEventTimer.start();
- }
+ LLInitialFriendCardsFetch(callback_t cb)
+ : mCheckFolderCallback(cb) {}
- virtual BOOL tick() // from LLEventTimer
- {
- return mCallback();
- }
+ /* virtual */ void done();
private:
- callback_t mCallback;
+ callback_t mCheckFolderCallback;
};
+void LLInitialFriendCardsFetch::done()
+{
+ // This observer is no longer needed.
+ gInventory.removeObserver(this);
+
+ mCheckFolderCallback();
+
+ delete this;
+}
// LLFriendCardsManager Constructor / Destructor
LLFriendCardsManager::LLFriendCardsManager()
-: mFriendsAllFolderCompleted(true)
{
LLAvatarTracker::instance().addObserver(this);
}
@@ -167,30 +162,6 @@ const LLUUID LLFriendCardsManager::extractAvatarID(const LLUUID& avatarID)
return rv;
}
-// be sure LLInventoryModel::buildParentChildMap() has been called before it.
-// and this method must be called before any actions with friend list
-void LLFriendCardsManager::ensureFriendFoldersExist()
-{
- const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
-
- LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
-
- if (friendFolderUUID.isNull())
- {
- friendFolderUUID = gInventory.createNewCategory(callingCardsFolderID,
- LLFolderType::FT_CALLINGCARD, get_friend_folder_name());
- }
-
- LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl();
-
- if (friendAllSubfolderUUID.isNull())
- {
- friendAllSubfolderUUID = gInventory.createNewCategory(friendFolderUUID,
- LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name());
- }
-}
-
-
bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* item)
{
if (item->getType() != LLAssetType::AT_CALLINGCARD)
@@ -305,63 +276,12 @@ bool LLFriendCardsManager::isAnyFriendCategory(const LLUUID& catID) const
return TRUE == gInventory.isObjectDescendentOf(catID, friendFolderID);
}
-bool LLFriendCardsManager::syncFriendsFolder()
+void LLFriendCardsManager::syncFriendCardsFolders()
{
- //lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent
- LLFriendCardsManager::instance().ensureFriendFoldersExist();
-
- LLAvatarTracker::buddy_map_t all_buddies;
- LLAvatarTracker::instance().copyBuddyList(all_buddies);
-
- // 1. Remove Friend Cards for non-friends
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
-
- gInventory.collectDescendents(findFriendAllSubfolderUUIDImpl(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
-
- LLInventoryModel::item_array_t::const_iterator it;
- for (it = items.begin(); it != items.end(); ++it)
- {
- lldebugs << "Check if buddy is in list: " << (*it)->getName() << " " << (*it)->getCreatorUUID() << llendl;
- if (NULL == get_ptr_in_map(all_buddies, (*it)->getCreatorUUID()))
- {
- lldebugs << "NONEXISTS, so remove it" << llendl;
- removeFriendCardFromInventory((*it)->getCreatorUUID());
- }
- }
-
- // 2. Add missing Friend Cards for friends
- LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
- llinfos << "try to build friends, count: " << all_buddies.size() << llendl;
- mFriendsAllFolderCompleted = true;
- for(; buddy_it != all_buddies.end(); ++buddy_it)
- {
- const LLUUID& buddy_id = (*buddy_it).first;
- addFriendCardToInventory(buddy_id);
- }
-
- if (!mFriendsAllFolderCompleted)
- {
- forceFriendListIsLoaded(findFriendAllSubfolderUUIDImpl());
-
- static bool timer_started = false;
- if (!timer_started)
- {
- lldebugs << "Create and start timer to sync Inventory Friends All folder with Friends list" << llendl;
-
- // do not worry about destruction of the FriendListUpdater.
- // It will be deleted by LLEventTimer::updateClass when FriendListUpdater::tick() returns true.
- new FriendListUpdater(boost::bind(&LLFriendCardsManager::syncFriendsFolder, this),
- FETCH_FRIENDS_DESCENDENTS_PERIOD);
- }
- timer_started = true;
- }
- else
- {
- lldebugs << "Friends/All Inventory folder is synchronized with the Agent's Friends List" << llendl;
- }
+ const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
- return mFriendsAllFolderCompleted;
+ fetchAndCheckFolderDescendents(callingCardsFolderID,
+ boost::bind(&LLFriendCardsManager::ensureFriendsFolderExists, this));
}
void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const
@@ -482,6 +402,122 @@ void LLFriendCardsManager::findMatchedFriendCards(const LLUUID& avatarID, LLInve
}
}
+void LLFriendCardsManager::fetchAndCheckFolderDescendents(const LLUUID& folder_id, callback_t cb)
+{
+ // This instance will be deleted in LLInitialFriendCardsFetch::done().
+ LLInitialFriendCardsFetch* fetch = new LLInitialFriendCardsFetch(cb);
+
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ folders.push_back(folder_id);
+
+ fetch->fetchDescendents(folders);
+ if(fetch->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ fetch->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(fetch);
+ }
+}
+
+// Make sure LLInventoryModel::buildParentChildMap() has been called before it.
+// This method must be called before any actions with friends list.
+void LLFriendCardsManager::ensureFriendsFolderExists()
+{
+ const LLUUID calling_cards_folder_ID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
+
+ // If "Friends" folder exists in "Calling Cards" we should check if "All" sub-folder
+ // exists in "Friends", otherwise we create it.
+ LLUUID friends_folder_ID = findFriendFolderUUIDImpl();
+ if (friends_folder_ID.notNull())
+ {
+ fetchAndCheckFolderDescendents(friends_folder_ID,
+ boost::bind(&LLFriendCardsManager::ensureFriendsAllFolderExists, this));
+ }
+ else
+ {
+ if (!gInventory.isCategoryComplete(calling_cards_folder_ID))
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(calling_cards_folder_ID);
+ std::string cat_name = cat ? cat->getName() : "unknown";
+ llwarns << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << llendl;
+ }
+
+ friends_folder_ID = gInventory.createNewCategory(calling_cards_folder_ID,
+ LLFolderType::FT_CALLINGCARD, get_friend_folder_name());
+
+ gInventory.createNewCategory(friends_folder_ID,
+ LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name());
+
+ // Now when we have all needed folders we can sync their contents with buddies list.
+ syncFriendsFolder();
+ }
+}
+
+// Make sure LLFriendCardsManager::ensureFriendsFolderExists() has been called before it.
+void LLFriendCardsManager::ensureFriendsAllFolderExists()
+{
+ LLUUID friends_all_folder_ID = findFriendAllSubfolderUUIDImpl();
+ if (friends_all_folder_ID.notNull())
+ {
+ fetchAndCheckFolderDescendents(friends_all_folder_ID,
+ boost::bind(&LLFriendCardsManager::syncFriendsFolder, this));
+ }
+ else
+ {
+ LLUUID friends_folder_ID = findFriendFolderUUIDImpl();
+
+ if (!gInventory.isCategoryComplete(friends_folder_ID))
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(friends_folder_ID);
+ std::string cat_name = cat ? cat->getName() : "unknown";
+ llwarns << "Failed to find \"" << cat_name << "\" category descendents in Category Tree." << llendl;
+ }
+
+ friends_all_folder_ID = gInventory.createNewCategory(friends_folder_ID,
+ LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name());
+
+ // Now when we have all needed folders we can sync their contents with buddies list.
+ syncFriendsFolder();
+ }
+}
+
+void LLFriendCardsManager::syncFriendsFolder()
+{
+ LLAvatarTracker::buddy_map_t all_buddies;
+ LLAvatarTracker::instance().copyBuddyList(all_buddies);
+
+ // 1. Remove Friend Cards for non-friends
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+
+ gInventory.collectDescendents(findFriendAllSubfolderUUIDImpl(), cats, items, LLInventoryModel::EXCLUDE_TRASH);
+
+ LLInventoryModel::item_array_t::const_iterator it;
+ for (it = items.begin(); it != items.end(); ++it)
+ {
+ lldebugs << "Check if buddy is in list: " << (*it)->getName() << " " << (*it)->getCreatorUUID() << llendl;
+ if (NULL == get_ptr_in_map(all_buddies, (*it)->getCreatorUUID()))
+ {
+ lldebugs << "NONEXISTS, so remove it" << llendl;
+ removeFriendCardFromInventory((*it)->getCreatorUUID());
+ }
+ }
+
+ // 2. Add missing Friend Cards for friends
+ LLAvatarTracker::buddy_map_t::const_iterator buddy_it = all_buddies.begin();
+ llinfos << "try to build friends, count: " << all_buddies.size() << llendl;
+ for(; buddy_it != all_buddies.end(); ++buddy_it)
+ {
+ const LLUUID& buddy_id = (*buddy_it).first;
+ addFriendCardToInventory(buddy_id);
+ }
+}
+
class CreateFriendCardCallback : public LLInventoryCallback
{
public:
@@ -494,9 +530,8 @@ public:
}
};
-bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
+void LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
{
- LLInventoryModel* invModel = &gInventory;
bool shouldBeAdded = true;
std::string name;
@@ -518,13 +553,6 @@ bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
lldebugs << "is found in sentRequests: " << name << llendl;
}
- LLUUID friendListFolderID = findFriendAllSubfolderUUIDImpl();
- if (friendListFolderID.notNull() && shouldBeAdded && !invModel->isCategoryComplete(friendListFolderID))
- {
- mFriendsAllFolderCompleted = false;
- shouldBeAdded = false;
- lldebugs << "Friends/All category is not completed" << llendl;
- }
if (shouldBeAdded)
{
putAvatarData(avatarID);
@@ -533,10 +561,8 @@ bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
// TODO: mantipov: Is CreateFriendCardCallback really needed? Probably not
LLPointer<LLInventoryCallback> cb = new CreateFriendCardCallback();
- create_inventory_callingcard(avatarID, friendListFolderID, cb);
+ create_inventory_callingcard(avatarID, findFriendAllSubfolderUUIDImpl(), cb);
}
-
- return shouldBeAdded;
}
void LLFriendCardsManager::removeFriendCardFromInventory(const LLUUID& avatarID)
@@ -582,11 +608,4 @@ void LLFriendCardsManager::onFriendListUpdate(U32 changed_mask)
}
}
-void LLFriendCardsManager::forceFriendListIsLoaded(const LLUUID& folder_id) const
-{
- bool fetching_inventory = gInventory.fetchDescendentsOf(folder_id);
- lldebugs << "Trying to fetch descendants of Friends/All Inventory folder, fetched: "
- << fetching_inventory << llendl;
-}
-
// EOF
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
index feea05bc1d..98dc3153d0 100644
--- a/indra/newview/llfriendcard.h
+++ b/indra/newview/llfriendcard.h
@@ -58,14 +58,6 @@ public:
}
/**
- * Ensures that all necessary folders are created in Inventory.
- *
- * For now it processes Calling Card, Calling Card/Friends & Calling Card/Friends/All folders
- */
- void ensureFriendFoldersExist();
-
-
- /**
* Determines if specified Inventory Calling Card exists in any of lists
* in the Calling Card/Friends/ folder (Default, or Custom)
*/
@@ -88,11 +80,10 @@ public:
bool isAnyFriendCategory(const LLUUID& catID) const;
/**
- * Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List
- *
- * @return true - if folder is already synchronized, false otherwise.
+ * Checks whether "Friends" and "Friends/All" folders exist in "Calling Cards" category
+ * (creates them otherwise) and fetches their contents to synchronize with Agent's Friends List.
*/
- bool syncFriendsFolder();
+ void syncFriendCardsFolders();
/*!
* \brief
@@ -108,6 +99,8 @@ public:
void collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const;
private:
+ typedef boost::function<void()> callback_t;
+
LLFriendCardsManager();
~LLFriendCardsManager();
@@ -133,10 +126,29 @@ private:
const LLUUID& findFriendCardInventoryUUIDImpl(const LLUUID& avatarID);
void findMatchedFriendCards(const LLUUID& avatarID, LLInventoryModel::item_array_t& items) const;
+ void fetchAndCheckFolderDescendents(const LLUUID& folder_id, callback_t cb);
+
+ /**
+ * Checks whether "Calling Cards/Friends" folder exists. If not, creates it with "All"
+ * sub-folder and synchronizes its contents with buddies list.
+ */
+ void ensureFriendsFolderExists();
+
+ /**
+ * Checks whether "Calling Cards/Friends/All" folder exists. If not, creates it and
+ * synchronizes its contents with buddies list.
+ */
+ void ensureFriendsAllFolderExists();
+
+ /**
+ * Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List
+ */
+ void syncFriendsFolder();
+
/**
* Adds avatar specified by its UUID into the Calling Card/Friends/All Global Inventory folder
*/
- bool addFriendCardToInventory(const LLUUID& avatarID);
+ void addFriendCardToInventory(const LLUUID& avatarID);
/**
* Removes an avatar specified by its UUID from the Calling Card/Friends/All Global Inventory folder
@@ -146,20 +158,11 @@ private:
void onFriendListUpdate(U32 changed_mask);
- /**
- * Force fetching of the Inventory folder specified by passed folder's LLUUID.
- *
- * It only sends request to server, server reply should be processed in other place.
- * Because request can be sent via UDP we need to periodically check if request was completed with success.
- */
- void forceFriendListIsLoaded(const LLUUID& folder_id) const;
-
private:
typedef std::set<LLUUID> avatar_uuid_set_t;
avatar_uuid_set_t mBuddyIDSet;
- bool mFriendsAllFolderCompleted;
};
#endif // LL_LLFRIENDCARD_H
diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp
index 59274c8638..8e774dc199 100644
--- a/indra/newview/llgesturemgr.cpp
+++ b/indra/newview/llgesturemgr.cpp
@@ -37,7 +37,6 @@
// system
#include <functional>
#include <algorithm>
-#include <boost/tokenizer.hpp>
// library
#include "lldatapacker.h"
@@ -206,6 +205,9 @@ struct LLLoadInfo
// If inform_server is true, will send a message upstream to update
// the user_gesture_active table.
+/**
+ * It will load a gesture from remote storage
+ */
void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id,
const LLUUID& asset_id,
BOOL inform_server,
@@ -921,8 +923,8 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
delete info;
info = NULL;
-
- LLGestureManager::instance().mLoadingCount--;
+ LLGestureManager& self = LLGestureManager::instance();
+ self.mLoadingCount--;
if (0 == status)
{
@@ -944,15 +946,15 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
{
if (deactivate_similar)
{
- LLGestureManager::instance().deactivateSimilarGestures(gesture, item_id);
+ self.deactivateSimilarGestures(gesture, item_id);
// Display deactivation message if this was the last of the bunch.
- if (LLGestureManager::instance().mLoadingCount == 0
- && LLGestureManager::instance().mDeactivateSimilarNames.length() > 0)
+ if (self.mLoadingCount == 0
+ && self.mDeactivateSimilarNames.length() > 0)
{
// we're done with this set of deactivations
LLSD args;
- args["NAMES"] = LLGestureManager::instance().mDeactivateSimilarNames;
+ args["NAMES"] = self.mDeactivateSimilarNames;
LLNotifications::instance().add("DeactivatedGesturesTrigger", args);
}
}
@@ -965,9 +967,9 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
else
{
// Watch this item and set gesture name when item exists in inventory
- LLGestureManager::instance().watchItem(item_id);
+ self.watchItem(item_id);
}
- LLGestureManager::instance().mActive[item_id] = gesture;
+ self.mActive[item_id] = gesture;
// Everything has been successful. Add to the active list.
gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
@@ -989,14 +991,21 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs,
gAgent.sendReliableMessage();
}
+ callback_map_t::iterator i_cb = self.mCallbackMap.find(item_id);
+
+ if(i_cb != self.mCallbackMap.end())
+ {
+ i_cb->second(gesture);
+ self.mCallbackMap.erase(i_cb);
+ }
- LLGestureManager::instance().notifyObservers();
+ self.notifyObservers();
}
else
{
llwarns << "Unable to load gesture" << llendl;
- LLGestureManager::instance().mActive.erase(item_id);
+ self.mActive.erase(item_id);
delete gesture;
gesture = NULL;
diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h
index 947773d66d..7c3b742780 100644
--- a/indra/newview/llgesturemgr.h
+++ b/indra/newview/llgesturemgr.h
@@ -57,6 +57,12 @@ public:
class LLGestureManager : public LLSingleton<LLGestureManager>, public LLInventoryCompletionObserver
{
public:
+
+ typedef boost::function<void (LLMultiGesture* loaded_gesture)> gesture_loaded_callback_t;
+ // Maps inventory item_id to gesture
+ typedef std::map<LLUUID, LLMultiGesture*> item_map_t;
+ typedef std::map<LLUUID, gesture_loaded_callback_t> callback_map_t;
+
LLGestureManager();
~LLGestureManager();
@@ -97,6 +103,7 @@ public:
BOOL isGesturePlaying(const LLUUID& item_id);
+ const item_map_t& getActiveGestures() const { return mActive; }
// Force a gesture to be played, for example, if it is being
// previewed.
void playGesture(LLMultiGesture* gesture);
@@ -106,7 +113,15 @@ public:
// Also remove from playing list
void stopGesture(LLMultiGesture* gesture);
void stopGesture(const LLUUID& item_id);
-
+ /**
+ * Add cb into callbackMap.
+ * Note:
+ * Manager will call cb after gesture will be loaded and will remove cb automatically.
+ */
+ void setGestureLoadedCallback(LLUUID inv_item_id, gesture_loaded_callback_t cb)
+ {
+ mCallbackMap[inv_item_id] = cb;
+ }
// Trigger the first gesture that matches this key.
// Returns TRUE if it finds a gesture bound to that key.
BOOL triggerGesture(KEY key, MASK mask);
@@ -144,13 +159,7 @@ protected:
LLAssetType::EType type,
void* user_data, S32 status, LLExtStat ext_status);
-public:
- BOOL mValid;
- std::vector<LLMultiGesture*> mPlaying;
-
- // Maps inventory item_id to gesture
- typedef std::map<LLUUID, LLMultiGesture*> item_map_t;
-
+private:
// Active gestures.
// NOTE: The gesture pointer CAN BE NULL. This means that
// there is a gesture with that item_id, but the asset data
@@ -159,8 +168,11 @@ public:
S32 mLoadingCount;
std::string mDeactivateSimilarNames;
-
+
std::vector<LLGestureManagerObserver*> mObservers;
+ callback_map_t mCallbackMap;
+ std::vector<LLMultiGesture*> mPlaying;
+ BOOL mValid;
};
#endif
diff --git a/indra/newview/llimfloater.cpp b/indra/newview/llimfloater.cpp
index 5ea900e46d..059912d5d4 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -120,11 +120,7 @@ void LLIMFloater::newIMCallback(const LLSD& data){
LLUUID session_id = data["session_id"].asUUID();
LLIMFloater* floater = LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
- if (floater == NULL)
- {
- llwarns << "new_im_callback for non-existent session_id " << session_id << llendl;
- return;
- }
+ if (floater == NULL) return;
// update if visible, otherwise will be updated when opened
if (floater->getVisible())
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 0b8b5935f8..87b801d73b 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -848,8 +848,11 @@ void LLFloaterIMPanel::processSessionUpdate(const LLSD& session_update)
}
- //update the speakers dropdown too
- mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+ //update the speakers dropdown too, if it's available
+ if (mSpeakerPanel)
+ {
+ mSpeakerPanel->setVoiceModerationCtrlMode(voice_moderated);
+ }
}
}
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 9c38d9c5fc..ee785e7ecb 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -46,6 +46,7 @@
#include "llagent.h"
#include "llavatariconctrl.h"
+#include "llbottomtray.h"
#include "llcallingcard.h"
#include "llchat.h"
#include "llresmgr.h"
@@ -73,6 +74,7 @@
#include "llvoicechannel.h"
#include "lltrans.h"
#include "llrecentpeople.h"
+#include "llsyswellwindow.h"
#include "llfirstuse.h"
#include "llagentui.h"
@@ -1087,16 +1089,90 @@ LLIMMgr::onConfirmForceCloseError(
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLOutgoingCallDialog
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+LLOutgoingCallDialog::LLOutgoingCallDialog(const LLSD& payload) :
+ LLDockableFloater(NULL, false, payload),
+ mPayload(payload)
+{
+}
+
+void LLOutgoingCallDialog::getAllowedRect(LLRect& rect)
+{
+ rect = gViewerWindow->getWorldViewRectRaw();
+}
+
+void LLOutgoingCallDialog::onOpen(const LLSD& key)
+{
+ // tell the user which voice channel they are leaving
+ if (!mPayload["old_channel_name"].asString().empty())
+ {
+ childSetTextArg("leaving", "[CURRENT_CHAT]", mPayload["old_channel_name"].asString());
+ }
+ else
+ {
+ childSetTextArg("leaving", "[CURRENT_CHAT]", getString("localchat"));
+ }
+
+ std::string callee_name = mPayload["session_name"].asString();
+ if (callee_name == "anonymous")
+ {
+ callee_name = getString("anonymous");
+ }
+
+ setTitle(callee_name);
+
+ LLSD callee_id = mPayload["other_user_id"];
+ childSetTextArg("calling", "[CALLEE_NAME]", callee_name);
+ LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+ icon->setValue(callee_id);
+
+ // dock the dialog to the sys well, where other sys messages appear
+ setDockControl(new LLDockControl(LLBottomTray::getInstance()->getSysWell(),
+ this, getDockTongue(), LLDockControl::TOP,
+ boost::bind(&LLOutgoingCallDialog::getAllowedRect, this, _1)));
+}
+
+
+//static
+void LLOutgoingCallDialog::onCancel(void* user_data)
+{
+ LLOutgoingCallDialog* self = (LLOutgoingCallDialog*)user_data;
+
+ if (!gIMMgr)
+ return;
+
+ LLUUID session_id = self->mPayload["session_id"].asUUID();
+ gIMMgr->endCall(session_id);
+
+ self->closeFloater();
+}
+
+
+BOOL LLOutgoingCallDialog::postBuild()
+{
+ BOOL success = LLDockableFloater::postBuild();
+
+ childSetAction("Cancel", onCancel, this);
+
+ return success;
+}
+
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLIncomingCallDialog
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LLIncomingCallDialog::LLIncomingCallDialog(const LLSD& payload) :
- LLModalDialog(payload),
+ LLDockableFloater(NULL, false, payload),
mPayload(payload)
{
}
BOOL LLIncomingCallDialog::postBuild()
{
+ LLDockableFloater::postBuild();
+
LLSD caller_id = mPayload["caller_id"];
EInstantMessage type = (EInstantMessage)mPayload["type"].asInteger();
@@ -1115,6 +1191,11 @@ BOOL LLIncomingCallDialog::postBuild()
call_type = getString("VoiceInviteAdHoc");
}
+ // check to see if this is an Avaline call
+ LLUUID session_id = mPayload["session_id"].asUUID();
+ bool is_avatar = LLVoiceClient::getInstance()->isParticipantAvatar(session_id);
+ childSetVisible("Start IM", is_avatar); // no IM for avaline
+
LLUICtrl* caller_name_widget = getChild<LLUICtrl>("caller name");
caller_name_widget->setValue(caller_name + " " + call_type);
LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
@@ -1128,6 +1209,30 @@ BOOL LLIncomingCallDialog::postBuild()
return TRUE;
}
+void LLIncomingCallDialog::getAllowedRect(LLRect& rect)
+{
+ rect = gViewerWindow->getWorldViewRectRaw();
+}
+
+void LLIncomingCallDialog::onOpen(const LLSD& key)
+{
+ // tell the user which voice channel they would be leaving
+ LLVoiceChannel *voice = LLVoiceChannel::getCurrentVoiceChannel();
+ if (voice && !voice->getSessionName().empty())
+ {
+ childSetTextArg("question", "[CURRENT_CHAT]", voice->getSessionName());
+ }
+ else
+ {
+ childSetTextArg("question", "[CURRENT_CHAT]", getString("localchat"));
+ }
+
+ // dock the dialog to the sys well, where other sys messages appear
+ setDockControl(new LLDockControl(LLBottomTray::getInstance()->getSysWell(),
+ this, getDockTongue(), LLDockControl::TOP,
+ boost::bind(&LLIncomingCallDialog::getAllowedRect, this, _1)));
+}
+
//static
void LLIncomingCallDialog::onAccept(void* user_data)
{
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index c566b111ca..62a54bc081 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -34,9 +34,11 @@
#define LL_LLIMVIEW_H
#include "lldarray.h"
+#include "lldockablefloater.h"
#include "llspeakers.h" //for LLIMSpeakerMgr
#include "llimpanel.h" //for voice channels
#include "llmodaldialog.h"
+#include "lldockablefloater.h"
#include "llinstantmessage.h"
#include "lluuid.h"
#include "llmultifloater.h"
@@ -401,12 +403,13 @@ private:
LLSD mPendingAgentListUpdates;
};
-class LLIncomingCallDialog : public LLModalDialog
+class LLIncomingCallDialog : public LLDockableFloater
{
public:
LLIncomingCallDialog(const LLSD& payload);
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
static void onAccept(void* user_data);
static void onReject(void* user_data);
@@ -414,6 +417,23 @@ public:
private:
void processCallResponse(S32 response);
+ void getAllowedRect(LLRect& rect);
+
+ LLSD mPayload;
+};
+
+class LLOutgoingCallDialog : public LLDockableFloater
+{
+public:
+ LLOutgoingCallDialog(const LLSD& payload);
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+ static void onCancel(void* user_data);
+
+private:
+ void getAllowedRect(LLRect& rect);
LLSD mPayload;
};
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index e7d7eb19d0..4b0d524906 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -176,6 +176,7 @@ LLInventoryModel::LLInventoryModel()
mRootFolderID(),
mLibraryRootFolderID(),
mLibraryOwnerID(),
+ mIsNotifyObservers(FALSE),
mIsAgentInvUsable(false)
{
}
@@ -537,7 +538,10 @@ void LLInventoryModel::updateLinkedItems(const LLUUID& object_id)
item_array,
LLInventoryModel::INCLUDE_TRASH,
is_linked_item_match);
-
+ if (cat_array.empty() && item_array.empty())
+ {
+ return;
+ }
for (LLInventoryModel::cat_array_t::iterator cat_iter = cat_array.begin();
cat_iter != cat_array.end();
cat_iter++)
@@ -639,6 +643,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* item)
new_item = old_item;
LLUUID old_parent_id = old_item->getParentUUID();
LLUUID new_parent_id = item->getParentUUID();
+
if(old_parent_id != new_parent_id)
{
// need to update the parent-child tree
@@ -1133,6 +1138,15 @@ BOOL LLInventoryModel::containsObserver(LLInventoryObserver* observer) const
// The optional argument 'service_name' is used by Agent Inventory Service [DEV-20328]
void LLInventoryModel::notifyObservers(const std::string service_name)
{
+ if (mIsNotifyObservers)
+ {
+ // Within notifyObservers, something called notifyObservers
+ // again. This type of recursion is unsafe because it causes items to be
+ // processed twice, and this can easily lead to infinite loops.
+ llwarns << "Call was made to notifyObservers within notifyObservers!" << llendl;
+ return;
+ }
+ mIsNotifyObservers = TRUE;
for (observer_list_t::iterator iter = mObservers.begin();
iter != mObservers.end(); )
{
@@ -1154,12 +1168,21 @@ void LLInventoryModel::notifyObservers(const std::string service_name)
mModifyMask = LLInventoryObserver::NONE;
mChangedItemIDs.clear();
+ mIsNotifyObservers = FALSE;
}
// store flag for change
// and id of object change applies to
void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
{
+ if (mIsNotifyObservers)
+ {
+ // Something marked an item for change within a call to notifyObservers
+ // (which is in the process of processing the list of items marked for change).
+ // This means the change may fail to be processed.
+ llwarns << "Adding changed mask within notify observers! Change will likely be lost." << llendl;
+ }
+
mModifyMask |= mask;
if (referent.notNull())
{
@@ -1833,13 +1856,13 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
{
//llinfos << "LLInventoryModel::addItem()" << llendl;
-
- // This can happen if assettype enums change. This can be a backwards compatibility issue
- // in some viewer prototypes prior to when the AT_LINK enum changed from 23 to 24.
+ // This can happen if assettype enums from llassettype.h ever change.
+ // For example, there is a known backwards compatibility issue in some viewer prototypes prior to when
+ // the AT_LINK enum changed from 23 to 24.
if ((item->getType() == LLAssetType::AT_NONE)
|| LLAssetType::lookup(item->getType()) == LLAssetType::badLookup())
{
- llwarns << "Got bad asset type for item ( name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ), ignoring." << llendl;
+ llwarns << "Got bad asset type for item [ name: " << item->getName() << " type: " << item->getType() << " inv-type: " << item->getInventoryType() << " ], ignoring." << llendl;
return;
}
if(item)
@@ -1848,7 +1871,7 @@ void LLInventoryModel::addItem(LLViewerInventoryItem* item)
// The item will show up as a broken link.
if (item->getIsBrokenLink())
{
- llinfos << "Adding broken link ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl;
+ llinfos << "Adding broken link [ name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ) parent: " << item->getParentUUID() << llendl;
}
mItemMap[item->getUUID()] = item;
}
@@ -2176,7 +2199,7 @@ bool LLInventoryModel::loadSkeleton(
// Add all the items loaded which are parented to a
// category with a correctly cached parent
- count = items.count();
+ S32 bad_link_count = 0;
cat_map_t::iterator unparented = mCategoryMap.end();
for(item_array_t::const_iterator item_iter = items.begin();
item_iter != items.end();
@@ -2193,7 +2216,11 @@ bool LLInventoryModel::loadSkeleton(
// This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
if (item->getIsBrokenLink())
{
- llinfos << "Attempted to add cached link item without baseobj present ( name: " << item->getName() << " itemID: " << item->getUUID() << " assetID: " << item->getAssetUUID() << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
+ bad_link_count++;
+ lldebugs << "Attempted to add cached link item without baseobj present ( name: "
+ << item->getName() << " itemID: " << item->getUUID()
+ << " assetID: " << item->getAssetUUID()
+ << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
invalid_categories.insert(cit->second);
continue;
}
@@ -2203,6 +2230,12 @@ bool LLInventoryModel::loadSkeleton(
}
}
}
+ if (bad_link_count > 0)
+ {
+ llinfos << "Attempted to add " << bad_link_count
+ << " cached link items without baseobj present. "
+ << "The corresponding categories were invalidated." << llendl;
+ }
}
else
{
@@ -3307,6 +3340,12 @@ void LLInventoryModel::processInventoryDescendents(LLMessageSystem* msg,void**)
for(i = 0; i < count; ++i)
{
titem->unpackMessage(msg, _PREHASH_ItemData, i);
+ // If the item has already been added (e.g. from link prefetch), then it doesn't need to be re-added.
+ if (gInventory.getItem(titem->getUUID()))
+ {
+ llinfos << "Skipping prefetched item [ Name: " << titem->getName() << " | Type: " << titem->getActualType() << " | ItemUUID: " << titem->getUUID() << " ] " << llendl;
+ continue;
+ }
gInventory.updateItem(titem);
}
@@ -3682,513 +3721,6 @@ bool LLNameCategoryCollector::operator()(
return false;
}
-
-
-///----------------------------------------------------------------------------
-/// Observers
-///----------------------------------------------------------------------------
-
-void LLInventoryCompletionObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mIncomplete.empty())
- {
- for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- it = mIncomplete.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mComplete.push_back(*it);
- it = mIncomplete.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncomplete.empty())
- {
- done();
- }
- }
-}
-
-void LLInventoryCompletionObserver::watchItem(const LLUUID& id)
-{
- if(id.notNull())
- {
- mIncomplete.push_back(id);
- }
-}
-
-
-void LLInventoryFetchObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mIncomplete.empty())
- {
- for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- // BUG: This can cause done() to get called prematurely below.
- // This happens with the LLGestureInventoryFetchObserver that
- // loads gestures at startup. JC
- it = mIncomplete.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mComplete.push_back(*it);
- it = mIncomplete.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncomplete.empty())
- {
- done();
- }
- }
- //llinfos << "LLInventoryFetchObserver::changed() mComplete size " << mComplete.size() << llendl;
- //llinfos << "LLInventoryFetchObserver::changed() mIncomplete size " << mIncomplete.size() << llendl;
-}
-
-bool LLInventoryFetchObserver::isEverythingComplete() const
-{
- return mIncomplete.empty();
-}
-
-void fetch_items_from_llsd(const LLSD& items_llsd)
-{
- if (!items_llsd.size()) return;
- LLSD body;
- body[0]["cap_name"] = "FetchInventory";
- body[1]["cap_name"] = "FetchLib";
- for (S32 i=0; i<items_llsd.size();i++)
- {
- if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
- {
- body[0]["items"].append(items_llsd[i]);
- continue;
- }
- if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString())
- {
- body[1]["items"].append(items_llsd[i]);
- continue;
- }
- }
-
- for (S32 i=0; i<body.size(); i++)
- {
- if (0 >= body[i].size()) continue;
- std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString());
-
- if (!url.empty())
- {
- body[i]["agent_id"] = gAgent.getID();
- LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
- break;
- }
-
- LLMessageSystem* msg = gMessageSystem;
- BOOL start_new_message = TRUE;
- for (S32 j=0; j<body[i]["items"].size(); j++)
- {
- LLSD item_entry = body[i]["items"][j];
- if(start_new_message)
- {
- start_new_message = FALSE;
- msg->newMessageFast(_PREHASH_FetchInventory);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
- msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
- if(msg->isSendFull(NULL))
- {
- start_new_message = TRUE;
- gAgent.sendReliableMessage();
- }
- }
- if(!start_new_message)
- {
- gAgent.sendReliableMessage();
- }
- }
-}
-
-void LLInventoryFetchObserver::fetchItems(
- const LLInventoryFetchObserver::item_ref_t& ids)
-{
- LLUUID owner_id;
- LLSD items_llsd;
- for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(item)
- {
- if(item->isComplete())
- {
- // It's complete, so put it on the complete container.
- mComplete.push_back(*it);
- continue;
- }
- else
- {
- owner_id = item->getPermissions().getOwner();
- }
- }
- else
- {
- // assume it's agent inventory.
- owner_id = gAgent.getID();
- }
-
- // It's incomplete, so put it on the incomplete container, and
- // pack this on the message.
- mIncomplete.push_back(*it);
-
- // Prepare the data to fetch
- LLSD item_entry;
- item_entry["owner_id"] = owner_id;
- item_entry["item_id"] = (*it);
- items_llsd.append(item_entry);
- }
- fetch_items_from_llsd(items_llsd);
-}
-
-// virtual
-void LLInventoryFetchDescendentsObserver::changed(U32 mask)
-{
- for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat)
- {
- it = mIncompleteFolders.erase(it);
- continue;
- }
- if(isComplete(cat))
- {
- mCompleteFolders.push_back(*it);
- it = mIncompleteFolders.erase(it);
- continue;
- }
- ++it;
- }
- if(mIncompleteFolders.empty())
- {
- done();
- }
-}
-
-void LLInventoryFetchDescendentsObserver::fetchDescendents(
- const folder_ref_t& ids)
-{
- for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat) continue;
- if(!isComplete(cat))
- {
- cat->fetchDescendents(); //blindly fetch it without seeing if anything else is fetching it.
- mIncompleteFolders.push_back(*it); //Add to list of things being downloaded for this observer.
- }
- else
- {
- mCompleteFolders.push_back(*it);
- }
- }
-}
-
-bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const
-{
- return mIncompleteFolders.empty();
-}
-
-bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat)
-{
- S32 version = cat->getVersion();
- S32 descendents = cat->getDescendentCount();
- if((LLViewerInventoryCategory::VERSION_UNKNOWN == version)
- || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents))
- {
- return false;
- }
- // it might be complete - check known descendents against
- // currently available.
- LLInventoryModel::cat_array_t* cats;
- LLInventoryModel::item_array_t* items;
- gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items);
- if(!cats || !items)
- {
- // bit of a hack - pretend we're done if they are gone or
- // incomplete. should never know, but it would suck if this
- // kept tight looping because of a corrupt memory state.
- return true;
- }
- S32 known = cats->count() + items->count();
- if(descendents == known)
- {
- // hey - we're done.
- return true;
- }
- return false;
-}
-
-void LLInventoryFetchComboObserver::changed(U32 mask)
-{
- if(!mIncompleteItems.empty())
- {
- for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- it = mIncompleteItems.erase(it);
- continue;
- }
- if(item->isComplete())
- {
- mCompleteItems.push_back(*it);
- it = mIncompleteItems.erase(it);
- continue;
- }
- ++it;
- }
- }
- if(!mIncompleteFolders.empty())
- {
- for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
- if(!cat)
- {
- it = mIncompleteFolders.erase(it);
- continue;
- }
- if(gInventory.isCategoryComplete(*it))
- {
- mCompleteFolders.push_back(*it);
- it = mIncompleteFolders.erase(it);
- continue;
- }
- ++it;
- }
- }
- if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty())
- {
- mDone = true;
- done();
- }
-}
-
-void LLInventoryFetchComboObserver::fetch(
- const folder_ref_t& folder_ids,
- const item_ref_t& item_ids)
-{
- lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl;
- for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit)
- {
- LLViewerInventoryCategory* cat = gInventory.getCategory(*fit);
- if(!cat) continue;
- if(!gInventory.isCategoryComplete(*fit))
- {
- cat->fetchDescendents();
- lldebugs << "fetching folder " << *fit <<llendl;
- mIncompleteFolders.push_back(*fit);
- }
- else
- {
- mCompleteFolders.push_back(*fit);
- lldebugs << "completing folder " << *fit <<llendl;
- }
- }
-
- // Now for the items - we fetch everything which is not a direct
- // descendent of an incomplete folder because the item will show
- // up in an inventory descendents message soon enough so we do not
- // have to fetch it individually.
- LLSD items_llsd;
- LLUUID owner_id;
- for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
- {
- LLViewerInventoryItem* item = gInventory.getItem(*iit);
- if(!item)
- {
- lldebugs << "uanble to find item " << *iit << llendl;
- continue;
- }
- if(item->isComplete())
- {
- // It's complete, so put it on the complete container.
- mCompleteItems.push_back(*iit);
- lldebugs << "completing item " << *iit << llendl;
- continue;
- }
- else
- {
- mIncompleteItems.push_back(*iit);
- owner_id = item->getPermissions().getOwner();
- }
- if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
- {
- LLSD item_entry;
- item_entry["owner_id"] = owner_id;
- item_entry["item_id"] = (*iit);
- items_llsd.append(item_entry);
- }
- else
- {
- lldebugs << "not worrying about " << *iit << llendl;
- }
- }
- fetch_items_from_llsd(items_llsd);
-}
-
-void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
-{
- if(id.notNull())
- {
- mMIA.push_back(id);
- }
-}
-
-void LLInventoryExistenceObserver::changed(U32 mask)
-{
- // scan through the incomplete items and move or erase them as
- // appropriate.
- if(!mMIA.empty())
- {
- for(item_ref_t::iterator it = mMIA.begin(); it < mMIA.end(); )
- {
- LLViewerInventoryItem* item = gInventory.getItem(*it);
- if(!item)
- {
- ++it;
- continue;
- }
- mExist.push_back(*it);
- it = mMIA.erase(it);
- }
- if(mMIA.empty())
- {
- done();
- }
- }
-}
-
-void LLInventoryAddedObserver::changed(U32 mask)
-{
- if(!(mask & LLInventoryObserver::ADD))
- {
- return;
- }
-
- // *HACK: If this was in response to a packet off
- // the network, figure out which item was updated.
- LLMessageSystem* msg = gMessageSystem;
-
- std::string msg_name;
- if (mMessageName.empty())
- {
- msg_name = msg->getMessageName();
- }
- else
- {
- msg_name = mMessageName;
- }
-
- if (msg_name.empty())
- {
- return;
- }
-
- // We only want newly created inventory items. JC
- if ( msg_name != "UpdateCreateInventoryItem")
- {
- return;
- }
-
- LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
- S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
- for(S32 i = 0; i < num_blocks; ++i)
- {
- titem->unpackMessage(msg, _PREHASH_InventoryData, i);
- if (!(titem->getUUID().isNull()))
- {
- //we don't do anything with null keys
- mAdded.push_back(titem->getUUID());
- }
- }
- if (!mAdded.empty())
- {
- done();
- }
-}
-
-LLInventoryTransactionObserver::LLInventoryTransactionObserver(
- const LLTransactionID& transaction_id) :
- mTransactionID(transaction_id)
-{
-}
-
-void LLInventoryTransactionObserver::changed(U32 mask)
-{
- if(mask & LLInventoryObserver::ADD)
- {
- // This could be it - see if we are processing a bulk update
- LLMessageSystem* msg = gMessageSystem;
- if(msg->getMessageName()
- && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
- {
- // we have a match for the message - now check the
- // transaction id.
- LLUUID id;
- msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
- if(id == mTransactionID)
- {
- // woo hoo, we found it
- folder_ref_t folders;
- item_ref_t items;
- S32 count;
- count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
- S32 i;
- for(i = 0; i < count; ++i)
- {
- msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
- if(id.notNull())
- {
- folders.push_back(id);
- }
- }
- count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
- for(i = 0; i < count; ++i)
- {
- msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
- if(id.notNull())
- {
- items.push_back(id);
- }
- }
-
- // call the derived class the implements this method.
- done(folders, items);
- }
- }
- }
-}
-
-
///----------------------------------------------------------------------------
/// LLAssetIDMatches
///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index faf026887a..bd64591194 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -41,40 +41,27 @@
#include "lluuid.h"
#include "llpermissionsflags.h"
#include "llstring.h"
-
#include <map>
#include <set>
#include <string>
#include <vector>
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryObserver
-//
-// This class is designed to be a simple abstract base class which can
-// relay messages when the inventory changes.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// ! REFACTOR ! Remove llinventoryobservers.h and have other files that need it explicitly
+// include llinventoryobservers.h instead of llinventorymodel.h . This will reduce dependency on
+// llinventorymodel.h.
+#include "llinventoryobserver.h"
+
+class LLInventoryObserver;
+class LLInventoryObject;
+class LLInventoryItem;
+class LLInventoryCategory;
+class LLViewerInventoryItem;
+class LLViewerInventoryCategory;
+class LLViewerInventoryItem;
+class LLViewerInventoryCategory;
+class LLMessageSystem;
+class LLInventoryCollectFunctor;
-class LLInventoryObserver
-{
-public:
- // This enumeration is a way to refer to what changed in a more
- // human readable format. You can mask the value provided by
- // chaged() to see if the observer is interested in the change.
- enum
- {
- NONE = 0,
- LABEL = 1, // name changed
- INTERNAL = 2, // internal change, eg, asset uuid different
- ADD = 4, // something added
- REMOVE = 8, // something deleted
- STRUCTURE = 16, // structural change, eg, item or folder moved
- CALLING_CARD = 32, // online, grant status, cancel, etc change
- ALL = 0xffffffff
- };
- virtual ~LLInventoryObserver() {};
- virtual void changed(U32 mask) = 0;
- std::string mMessageName; // used by Agent Inventory Service only. [DEV-20328]
-};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInventoryModel
@@ -87,16 +74,6 @@ public:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryObject;
-class LLInventoryItem;
-class LLInventoryCategory;
-class LLViewerInventoryItem;
-class LLViewerInventoryCategory;
-class LLViewerInventoryItem;
-class LLViewerInventoryCategory;
-class LLMessageSystem;
-class LLInventoryCollectFunctor;
-
class LLInventoryModel
{
public:
@@ -473,23 +450,12 @@ protected:
cat_array_t* getUnlockedCatArray(const LLUUID& id);
item_array_t* getUnlockedItemArray(const LLUUID& id);
-protected:
+private:
// Variables used to track what has changed since the last notify.
U32 mModifyMask;
typedef std::set<LLUUID> changed_items_t;
changed_items_t mChangedItemIDs;
- // Information for tracking the actual inventory. We index this
- // information in a lot of different ways so we can access
- // the inventory using several different identifiers.
- // mInventory member data is the 'master' list of inventory, and
- // mCategoryMap and mItemMap store uuid->object mappings.
- typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
- typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
- //inv_map_t mInventory;
- cat_map_t mCategoryMap;
- item_map_t mItemMap;
-
std::map<LLUUID, bool> mCategoryLock;
std::map<LLUUID, bool> mItemLock;
@@ -525,6 +491,21 @@ protected:
// This flag is used to handle an invalid inventory state.
bool mIsAgentInvUsable;
+private:
+ // Information for tracking the actual inventory. We index this
+ // information in a lot of different ways so we can access
+ // the inventory using several different identifiers.
+ // mInventory member data is the 'master' list of inventory, and
+ // mCategoryMap and mItemMap store uuid->object mappings.
+ typedef std::map<LLUUID, LLPointer<LLViewerInventoryCategory> > cat_map_t;
+ typedef std::map<LLUUID, LLPointer<LLViewerInventoryItem> > item_map_t;
+ //inv_map_t mInventory;
+ cat_map_t mCategoryMap;
+ item_map_t mItemMap;
+
+ // Flag set when notifyObservers is being called, to look for bugs
+ // where it's called recursively.
+ BOOL mIsNotifyObservers;
public:
// *NOTE: DEBUG functionality
void dumpInventory() const;
@@ -767,183 +748,5 @@ public:
LLInventoryItem* item);
};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryCompletionObserver
-//
-// Class which can be used as a base class for doing something when
-// when all observed items are locally complete. This class implements
-// the changed() method of LLInventoryObserver and declares a new
-// method named done() which is called when all watched items have
-// complete information in the inventory model.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryCompletionObserver : public LLInventoryObserver
-{
-public:
- LLInventoryCompletionObserver() {}
- virtual void changed(U32 mask);
-
- void watchItem(const LLUUID& id);
-
-protected:
- virtual void done() = 0;
-
- typedef std::vector<LLUUID> item_ref_t;
- item_ref_t mComplete;
- item_ref_t mIncomplete;
-};
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryFetchObserver
-//
-// This class is much like the LLInventoryCompletionObserver, except
-// that it handles all the the fetching necessary. Override the done()
-// method to do the thing you want.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryFetchObserver : public LLInventoryObserver
-{
-public:
- LLInventoryFetchObserver() {}
- virtual void changed(U32 mask);
-
- typedef std::vector<LLUUID> item_ref_t;
-
- bool isEverythingComplete() const;
- void fetchItems(const item_ref_t& ids);
- virtual void done() = 0;
-
-protected:
- item_ref_t mComplete;
- item_ref_t mIncomplete;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryFetchDescendentsObserver
-//
-// This class is much like the LLInventoryCompletionObserver, except
-// that it handles fetching based on category. Override the done()
-// method to do the thing you want.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryFetchDescendentsObserver : public LLInventoryObserver
-{
-public:
- LLInventoryFetchDescendentsObserver() {}
- virtual void changed(U32 mask);
-
- typedef std::vector<LLUUID> folder_ref_t;
- void fetchDescendents(const folder_ref_t& ids);
- bool isEverythingComplete() const;
- virtual void done() = 0;
-
-protected:
- bool isComplete(LLViewerInventoryCategory* cat);
- folder_ref_t mIncompleteFolders;
- folder_ref_t mCompleteFolders;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryFetchComboObserver
-//
-// This class does an appropriate combination of fetch descendents and
-// item fetches based on completion of categories and items. Much like
-// the fetch and fetch descendents, this will call done() when everything
-// has arrived.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryFetchComboObserver : public LLInventoryObserver
-{
-public:
- LLInventoryFetchComboObserver() : mDone(false) {}
- virtual void changed(U32 mask);
-
- typedef std::vector<LLUUID> folder_ref_t;
- typedef std::vector<LLUUID> item_ref_t;
- void fetch(const folder_ref_t& folder_ids, const item_ref_t& item_ids);
-
- virtual void done() = 0;
-
-protected:
- bool mDone;
- folder_ref_t mCompleteFolders;
- folder_ref_t mIncompleteFolders;
- item_ref_t mCompleteItems;
- item_ref_t mIncompleteItems;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryExistenceObserver
-//
-// This class is used as a base class for doing somethign when all the
-// observed item ids exist in the inventory somewhere. You can derive
-// a class from this class and implement the done() method to do
-// something useful.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryExistenceObserver : public LLInventoryObserver
-{
-public:
- LLInventoryExistenceObserver() {}
- virtual void changed(U32 mask);
-
- void watchItem(const LLUUID& id);
-
-protected:
- virtual void done() = 0;
-
- typedef std::vector<LLUUID> item_ref_t;
- item_ref_t mExist;
- item_ref_t mMIA;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryAddedObserver
-//
-// This class is used as a base class for doing something when
-// a new item arrives in inventory.
-// It does not watch for a certain UUID, rather it acts when anything is added
-// Derive a class from this class and implement the done() method to do
-// something useful.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryAddedObserver : public LLInventoryObserver
-{
-public:
- LLInventoryAddedObserver() : mAdded() {}
- virtual void changed(U32 mask);
-
-protected:
- virtual void done() = 0;
-
- typedef std::vector<LLUUID> item_ref_t;
- item_ref_t mAdded;
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryTransactionObserver
-//
-// Class which can be used as a base class for doing something when an
-// inventory transaction completes.
-//
-// *NOTE: This class is not quite complete. Avoid using unless you fix up it's
-// functionality gaps.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLInventoryTransactionObserver : public LLInventoryObserver
-{
-public:
- LLInventoryTransactionObserver(const LLTransactionID& transaction_id);
- virtual void changed(U32 mask);
-
-protected:
- typedef std::vector<LLUUID> folder_ref_t;
- typedef std::vector<LLUUID> item_ref_t;
- virtual void done(const folder_ref_t& folders, const item_ref_t& items) = 0;
-
- LLTransactionID mTransactionID;
-};
-
-
#endif // LL_LLINVENTORYMODEL_H
diff --git a/indra/newview/llinventoryobserver.cpp b/indra/newview/llinventoryobserver.cpp
new file mode 100644
index 0000000000..3ccf593d27
--- /dev/null
+++ b/indra/newview/llinventoryobserver.cpp
@@ -0,0 +1,564 @@
+/**
+ * @file llinventoryobserver.cpp
+ * @brief Implementation of the inventory observers used to track agent inventory.
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llinventoryobserver.h"
+
+#include "llassetstorage.h"
+#include "llcrc.h"
+#include "lldir.h"
+#include "llsys.h"
+#include "llxfermanager.h"
+#include "message.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llfloater.h"
+#include "llfocusmgr.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llviewermessage.h"
+#include "llviewerwindow.h"
+#include "llviewerregion.h"
+#include "llappviewer.h"
+#include "lldbstrings.h"
+#include "llviewerstats.h"
+#include "llmutelist.h"
+#include "llnotifications.h"
+#include "llcallbacklist.h"
+#include "llpreview.h"
+#include "llviewercontrol.h"
+#include "llvoavatarself.h"
+#include "llsdutil.h"
+#include <deque>
+
+void LLInventoryCompletionObserver::changed(U32 mask)
+{
+ // scan through the incomplete items and move or erase them as
+ // appropriate.
+ if(!mIncomplete.empty())
+ {
+ for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(!item)
+ {
+ it = mIncomplete.erase(it);
+ continue;
+ }
+ if(item->isComplete())
+ {
+ mComplete.push_back(*it);
+ it = mIncomplete.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if(mIncomplete.empty())
+ {
+ done();
+ }
+ }
+}
+
+void LLInventoryCompletionObserver::watchItem(const LLUUID& id)
+{
+ if(id.notNull())
+ {
+ mIncomplete.push_back(id);
+ }
+}
+
+
+void LLInventoryFetchObserver::changed(U32 mask)
+{
+ // scan through the incomplete items and move or erase them as
+ // appropriate.
+ if(!mIncomplete.empty())
+ {
+ for(item_ref_t::iterator it = mIncomplete.begin(); it < mIncomplete.end(); )
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(!item)
+ {
+ // BUG: This can cause done() to get called prematurely below.
+ // This happens with the LLGestureInventoryFetchObserver that
+ // loads gestures at startup. JC
+ it = mIncomplete.erase(it);
+ continue;
+ }
+ if(item->isComplete())
+ {
+ mComplete.push_back(*it);
+ it = mIncomplete.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if(mIncomplete.empty())
+ {
+ done();
+ }
+ }
+ //llinfos << "LLInventoryFetchObserver::changed() mComplete size " << mComplete.size() << llendl;
+ //llinfos << "LLInventoryFetchObserver::changed() mIncomplete size " << mIncomplete.size() << llendl;
+}
+
+bool LLInventoryFetchObserver::isEverythingComplete() const
+{
+ return mIncomplete.empty();
+}
+
+void fetch_items_from_llsd(const LLSD& items_llsd)
+{
+ if (!items_llsd.size()) return;
+ LLSD body;
+ body[0]["cap_name"] = "FetchInventory";
+ body[1]["cap_name"] = "FetchLib";
+ for (S32 i=0; i<items_llsd.size();i++)
+ {
+ if (items_llsd[i]["owner_id"].asString() == gAgent.getID().asString())
+ {
+ body[0]["items"].append(items_llsd[i]);
+ continue;
+ }
+ if (items_llsd[i]["owner_id"].asString() == ALEXANDRIA_LINDEN_ID.asString())
+ {
+ body[1]["items"].append(items_llsd[i]);
+ continue;
+ }
+ }
+
+ for (S32 i=0; i<body.size(); i++)
+ {
+ if (0 >= body[i].size()) continue;
+ std::string url = gAgent.getRegion()->getCapability(body[i]["cap_name"].asString());
+
+ if (!url.empty())
+ {
+ body[i]["agent_id"] = gAgent.getID();
+ LLHTTPClient::post(url, body[i], new LLInventoryModel::fetchInventoryResponder(body[i]));
+ break;
+ }
+
+ LLMessageSystem* msg = gMessageSystem;
+ BOOL start_new_message = TRUE;
+ for (S32 j=0; j<body[i]["items"].size(); j++)
+ {
+ LLSD item_entry = body[i]["items"][j];
+ if(start_new_message)
+ {
+ start_new_message = FALSE;
+ msg->newMessageFast(_PREHASH_FetchInventory);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_OwnerID, item_entry["owner_id"].asUUID());
+ msg->addUUIDFast(_PREHASH_ItemID, item_entry["item_id"].asUUID());
+ if(msg->isSendFull(NULL))
+ {
+ start_new_message = TRUE;
+ gAgent.sendReliableMessage();
+ }
+ }
+ if(!start_new_message)
+ {
+ gAgent.sendReliableMessage();
+ }
+ }
+}
+
+void LLInventoryFetchObserver::fetchItems(
+ const LLInventoryFetchObserver::item_ref_t& ids)
+{
+ LLUUID owner_id;
+ LLSD items_llsd;
+ for(item_ref_t::const_iterator it = ids.begin(); it < ids.end(); ++it)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(item)
+ {
+ if(item->isComplete())
+ {
+ // It's complete, so put it on the complete container.
+ mComplete.push_back(*it);
+ continue;
+ }
+ else
+ {
+ owner_id = item->getPermissions().getOwner();
+ }
+ }
+ else
+ {
+ // assume it's agent inventory.
+ owner_id = gAgent.getID();
+ }
+
+ // It's incomplete, so put it on the incomplete container, and
+ // pack this on the message.
+ mIncomplete.push_back(*it);
+
+ // Prepare the data to fetch
+ LLSD item_entry;
+ item_entry["owner_id"] = owner_id;
+ item_entry["item_id"] = (*it);
+ items_llsd.append(item_entry);
+ }
+ fetch_items_from_llsd(items_llsd);
+}
+
+// virtual
+void LLInventoryFetchDescendentsObserver::changed(U32 mask)
+{
+ for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
+ if(!cat)
+ {
+ it = mIncompleteFolders.erase(it);
+ continue;
+ }
+ if(isComplete(cat))
+ {
+ mCompleteFolders.push_back(*it);
+ it = mIncompleteFolders.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ if(mIncompleteFolders.empty())
+ {
+ done();
+ }
+}
+
+void LLInventoryFetchDescendentsObserver::fetchDescendents(
+ const folder_ref_t& ids)
+{
+ for(folder_ref_t::const_iterator it = ids.begin(); it != ids.end(); ++it)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
+ if(!cat) continue;
+ if(!isComplete(cat))
+ {
+ cat->fetchDescendents(); //blindly fetch it without seeing if anything else is fetching it.
+ mIncompleteFolders.push_back(*it); //Add to list of things being downloaded for this observer.
+ }
+ else
+ {
+ mCompleteFolders.push_back(*it);
+ }
+ }
+}
+
+bool LLInventoryFetchDescendentsObserver::isEverythingComplete() const
+{
+ return mIncompleteFolders.empty();
+}
+
+bool LLInventoryFetchDescendentsObserver::isComplete(LLViewerInventoryCategory* cat)
+{
+ S32 version = cat->getVersion();
+ S32 descendents = cat->getDescendentCount();
+ if((LLViewerInventoryCategory::VERSION_UNKNOWN == version)
+ || (LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN == descendents))
+ {
+ return false;
+ }
+ // it might be complete - check known descendents against
+ // currently available.
+ LLInventoryModel::cat_array_t* cats;
+ LLInventoryModel::item_array_t* items;
+ gInventory.getDirectDescendentsOf(cat->getUUID(), cats, items);
+ if(!cats || !items)
+ {
+ // bit of a hack - pretend we're done if they are gone or
+ // incomplete. should never know, but it would suck if this
+ // kept tight looping because of a corrupt memory state.
+ return true;
+ }
+ S32 known = cats->count() + items->count();
+ if(descendents == known)
+ {
+ // hey - we're done.
+ return true;
+ }
+ return false;
+}
+
+void LLInventoryFetchComboObserver::changed(U32 mask)
+{
+ if(!mIncompleteItems.empty())
+ {
+ for(item_ref_t::iterator it = mIncompleteItems.begin(); it < mIncompleteItems.end(); )
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(!item)
+ {
+ it = mIncompleteItems.erase(it);
+ continue;
+ }
+ if(item->isComplete())
+ {
+ mCompleteItems.push_back(*it);
+ it = mIncompleteItems.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ }
+ if(!mIncompleteFolders.empty())
+ {
+ for(folder_ref_t::iterator it = mIncompleteFolders.begin(); it < mIncompleteFolders.end();)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*it);
+ if(!cat)
+ {
+ it = mIncompleteFolders.erase(it);
+ continue;
+ }
+ if(gInventory.isCategoryComplete(*it))
+ {
+ mCompleteFolders.push_back(*it);
+ it = mIncompleteFolders.erase(it);
+ continue;
+ }
+ ++it;
+ }
+ }
+ if(!mDone && mIncompleteItems.empty() && mIncompleteFolders.empty())
+ {
+ mDone = true;
+ done();
+ }
+}
+
+void LLInventoryFetchComboObserver::fetch(
+ const folder_ref_t& folder_ids,
+ const item_ref_t& item_ids)
+{
+ lldebugs << "LLInventoryFetchComboObserver::fetch()" << llendl;
+ for(folder_ref_t::const_iterator fit = folder_ids.begin(); fit != folder_ids.end(); ++fit)
+ {
+ LLViewerInventoryCategory* cat = gInventory.getCategory(*fit);
+ if(!cat) continue;
+ if(!gInventory.isCategoryComplete(*fit))
+ {
+ cat->fetchDescendents();
+ lldebugs << "fetching folder " << *fit <<llendl;
+ mIncompleteFolders.push_back(*fit);
+ }
+ else
+ {
+ mCompleteFolders.push_back(*fit);
+ lldebugs << "completing folder " << *fit <<llendl;
+ }
+ }
+
+ // Now for the items - we fetch everything which is not a direct
+ // descendent of an incomplete folder because the item will show
+ // up in an inventory descendents message soon enough so we do not
+ // have to fetch it individually.
+ LLSD items_llsd;
+ LLUUID owner_id;
+ for(item_ref_t::const_iterator iit = item_ids.begin(); iit != item_ids.end(); ++iit)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*iit);
+ if(!item)
+ {
+ lldebugs << "uanble to find item " << *iit << llendl;
+ continue;
+ }
+ if(item->isComplete())
+ {
+ // It's complete, so put it on the complete container.
+ mCompleteItems.push_back(*iit);
+ lldebugs << "completing item " << *iit << llendl;
+ continue;
+ }
+ else
+ {
+ mIncompleteItems.push_back(*iit);
+ owner_id = item->getPermissions().getOwner();
+ }
+ if(std::find(mIncompleteFolders.begin(), mIncompleteFolders.end(), item->getParentUUID()) == mIncompleteFolders.end())
+ {
+ LLSD item_entry;
+ item_entry["owner_id"] = owner_id;
+ item_entry["item_id"] = (*iit);
+ items_llsd.append(item_entry);
+ }
+ else
+ {
+ lldebugs << "not worrying about " << *iit << llendl;
+ }
+ }
+ fetch_items_from_llsd(items_llsd);
+}
+
+void LLInventoryExistenceObserver::watchItem(const LLUUID& id)
+{
+ if(id.notNull())
+ {
+ mMIA.push_back(id);
+ }
+}
+
+void LLInventoryExistenceObserver::changed(U32 mask)
+{
+ // scan through the incomplete items and move or erase them as
+ // appropriate.
+ if(!mMIA.empty())
+ {
+ for(item_ref_t::iterator it = mMIA.begin(); it < mMIA.end(); )
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(*it);
+ if(!item)
+ {
+ ++it;
+ continue;
+ }
+ mExist.push_back(*it);
+ it = mMIA.erase(it);
+ }
+ if(mMIA.empty())
+ {
+ done();
+ }
+ }
+}
+
+void LLInventoryAddedObserver::changed(U32 mask)
+{
+ if(!(mask & LLInventoryObserver::ADD))
+ {
+ return;
+ }
+
+ // *HACK: If this was in response to a packet off
+ // the network, figure out which item was updated.
+ LLMessageSystem* msg = gMessageSystem;
+
+ std::string msg_name;
+ if (mMessageName.empty())
+ {
+ msg_name = msg->getMessageName();
+ }
+ else
+ {
+ msg_name = mMessageName;
+ }
+
+ if (msg_name.empty())
+ {
+ return;
+ }
+
+ // We only want newly created inventory items. JC
+ if ( msg_name != "UpdateCreateInventoryItem")
+ {
+ return;
+ }
+
+ LLPointer<LLViewerInventoryItem> titem = new LLViewerInventoryItem;
+ S32 num_blocks = msg->getNumberOfBlocksFast(_PREHASH_InventoryData);
+ for(S32 i = 0; i < num_blocks; ++i)
+ {
+ titem->unpackMessage(msg, _PREHASH_InventoryData, i);
+ if (!(titem->getUUID().isNull()))
+ {
+ //we don't do anything with null keys
+ mAdded.push_back(titem->getUUID());
+ }
+ }
+ if (!mAdded.empty())
+ {
+ done();
+ }
+}
+
+LLInventoryTransactionObserver::LLInventoryTransactionObserver(
+ const LLTransactionID& transaction_id) :
+ mTransactionID(transaction_id)
+{
+}
+
+void LLInventoryTransactionObserver::changed(U32 mask)
+{
+ if(mask & LLInventoryObserver::ADD)
+ {
+ // This could be it - see if we are processing a bulk update
+ LLMessageSystem* msg = gMessageSystem;
+ if(msg->getMessageName()
+ && (0 == strcmp(msg->getMessageName(), "BulkUpdateInventory")))
+ {
+ // we have a match for the message - now check the
+ // transaction id.
+ LLUUID id;
+ msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_TransactionID, id);
+ if(id == mTransactionID)
+ {
+ // woo hoo, we found it
+ folder_ref_t folders;
+ item_ref_t items;
+ S32 count;
+ count = msg->getNumberOfBlocksFast(_PREHASH_FolderData);
+ S32 i;
+ for(i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(_PREHASH_FolderData, _PREHASH_FolderID, id, i);
+ if(id.notNull())
+ {
+ folders.push_back(id);
+ }
+ }
+ count = msg->getNumberOfBlocksFast(_PREHASH_ItemData);
+ for(i = 0; i < count; ++i)
+ {
+ msg->getUUIDFast(_PREHASH_ItemData, _PREHASH_ItemID, id, i);
+ if(id.notNull())
+ {
+ items.push_back(id);
+ }
+ }
+
+ // call the derived class the implements this method.
+ done(folders, items);
+ }
+ }
+ }
+}
diff --git a/indra/newview/llinventoryobserver.h b/indra/newview/llinventoryobserver.h
new file mode 100644
index 0000000000..384e6292e8
--- /dev/null
+++ b/indra/newview/llinventoryobserver.h
@@ -0,0 +1,249 @@
+/**
+ * @file llinventoryobserver.h
+ * @brief LLInventoryObserver class header file
+ *
+ * $LicenseInfo:firstyear=2002&license=viewergpl$
+ *
+ * Copyright (c) 2002-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLINVENTORYOBSERVERS_H
+#define LL_LLINVENTORYOBSERVERS_H
+
+#include "lluuid.h"
+#include <string>
+#include <vector>
+
+class LLViewerInventoryCategory;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryObserver
+//
+// This class is designed to be a simple abstract base class which can
+// relay messages when the inventory changes.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryObserver
+{
+public:
+ // This enumeration is a way to refer to what changed in a more
+ // human readable format. You can mask the value provided by
+ // chaged() to see if the observer is interested in the change.
+ enum
+ {
+ NONE = 0,
+ LABEL = 1, // name changed
+ INTERNAL = 2, // internal change, eg, asset uuid different
+ ADD = 4, // something added
+ REMOVE = 8, // something deleted
+ STRUCTURE = 16, // structural change, eg, item or folder moved
+ CALLING_CARD = 32, // online, grant status, cancel, etc change
+ ALL = 0xffffffff
+ };
+ virtual ~LLInventoryObserver() {};
+ virtual void changed(U32 mask) = 0;
+ std::string mMessageName; // used by Agent Inventory Service only. [DEV-20328]
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryCompletionObserver
+//
+// Class which can be used as a base class for doing something when
+// when all observed items are locally complete. This class implements
+// the changed() method of LLInventoryObserver and declares a new
+// method named done() which is called when all watched items have
+// complete information in the inventory model.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryCompletionObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryCompletionObserver() {}
+ virtual void changed(U32 mask);
+
+ void watchItem(const LLUUID& id);
+
+protected:
+ virtual void done() = 0;
+
+ typedef std::vector<LLUUID> item_ref_t;
+ item_ref_t mComplete;
+ item_ref_t mIncomplete;
+};
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryFetchObserver
+//
+// This class is much like the LLInventoryCompletionObserver, except
+// that it handles all the the fetching necessary. Override the done()
+// method to do the thing you want.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryFetchObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryFetchObserver() {}
+ virtual void changed(U32 mask);
+
+ typedef std::vector<LLUUID> item_ref_t;
+
+ bool isEverythingComplete() const;
+ void fetchItems(const item_ref_t& ids);
+ virtual void done() = 0;
+
+protected:
+ item_ref_t mComplete;
+ item_ref_t mIncomplete;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryFetchDescendentsObserver
+//
+// This class is much like the LLInventoryCompletionObserver, except
+// that it handles fetching based on category. Override the done()
+// method to do the thing you want.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryFetchDescendentsObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryFetchDescendentsObserver() {}
+ virtual void changed(U32 mask);
+
+ typedef std::vector<LLUUID> folder_ref_t;
+ void fetchDescendents(const folder_ref_t& ids);
+ bool isEverythingComplete() const;
+ virtual void done() = 0;
+
+protected:
+ bool isComplete(LLViewerInventoryCategory* cat);
+ folder_ref_t mIncompleteFolders;
+ folder_ref_t mCompleteFolders;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryFetchComboObserver
+//
+// This class does an appropriate combination of fetch descendents and
+// item fetches based on completion of categories and items. Much like
+// the fetch and fetch descendents, this will call done() when everything
+// has arrived.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryFetchComboObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryFetchComboObserver() : mDone(false) {}
+ virtual void changed(U32 mask);
+
+ typedef std::vector<LLUUID> folder_ref_t;
+ typedef std::vector<LLUUID> item_ref_t;
+ void fetch(const folder_ref_t& folder_ids, const item_ref_t& item_ids);
+
+ virtual void done() = 0;
+
+protected:
+ bool mDone;
+ folder_ref_t mCompleteFolders;
+ folder_ref_t mIncompleteFolders;
+ item_ref_t mCompleteItems;
+ item_ref_t mIncompleteItems;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryExistenceObserver
+//
+// This class is used as a base class for doing somethign when all the
+// observed item ids exist in the inventory somewhere. You can derive
+// a class from this class and implement the done() method to do
+// something useful.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryExistenceObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryExistenceObserver() {}
+ virtual void changed(U32 mask);
+
+ void watchItem(const LLUUID& id);
+
+protected:
+ virtual void done() = 0;
+
+ typedef std::vector<LLUUID> item_ref_t;
+ item_ref_t mExist;
+ item_ref_t mMIA;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryAddedObserver
+//
+// This class is used as a base class for doing something when
+// a new item arrives in inventory.
+// It does not watch for a certain UUID, rather it acts when anything is added
+// Derive a class from this class and implement the done() method to do
+// something useful.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryAddedObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryAddedObserver() : mAdded() {}
+ virtual void changed(U32 mask);
+
+protected:
+ virtual void done() = 0;
+
+ typedef std::vector<LLUUID> item_ref_t;
+ item_ref_t mAdded;
+};
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryTransactionObserver
+//
+// Class which can be used as a base class for doing something when an
+// inventory transaction completes.
+//
+// *NOTE: This class is not quite complete. Avoid using unless you fix up it's
+// functionality gaps.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+class LLInventoryTransactionObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryTransactionObserver(const LLTransactionID& transaction_id);
+ virtual void changed(U32 mask);
+
+protected:
+ typedef std::vector<LLUUID> folder_ref_t;
+ typedef std::vector<LLUUID> item_ref_t;
+ virtual void done(const folder_ref_t& folders, const item_ref_t& items) = 0;
+
+ LLTransactionID mTransactionID;
+};
+
+
+#endif // LL_LLINVENTORYOBSERVERS_H
+
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 9a71e53441..dfd4af5c28 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -191,11 +191,9 @@ BOOL LLInventoryPanel::postBuild()
{
rebuildViewsFor(mStartFolderID);
mHasInventoryConnection = true;
+ defaultOpenInventory();
}
- // bit of a hack to make sure the inventory is open.
- mFolders->openFolder(preferred_type != LLFolderType::FT_NONE ? LLViewerFolderType::lookupNewCategoryName(preferred_type) : "My Inventory");
-
if (mSortOrderSetting != INHERIT_SORT_ORDER)
{
setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
@@ -300,6 +298,7 @@ void LLInventoryPanel::modelChanged(U32 mask)
{
rebuildViewsFor(mStartFolderID);
mHasInventoryConnection = true;
+ defaultOpenInventory();
return;
}
@@ -561,6 +560,25 @@ void LLInventoryPanel::buildNewViews(const LLUUID& id)
}
}
+// bit of a hack to make sure the inventory is open.
+void LLInventoryPanel::defaultOpenInventory()
+{
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
+ if (preferred_type != LLFolderType::FT_NONE)
+ {
+ const std::string& top_level_folder_name = LLViewerFolderType::lookupNewCategoryName(preferred_type);
+ mFolders->openFolder(top_level_folder_name);
+ }
+ else
+ {
+ // Get the first child (it should be "My Inventory") and
+ // open it up by name (just to make sure the first child is actually a folder).
+ LLView* first_child = mFolders->getFirstChild();
+ const std::string& first_child_name = first_child->getName();
+ mFolders->openFolder(first_child_name);
+ }
+}
+
struct LLConfirmPurgeData
{
LLUUID mID;
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
index 9f74fad5c1..e398c44105 100644
--- a/indra/newview/llinventorypanel.h
+++ b/indra/newview/llinventorypanel.h
@@ -165,7 +165,7 @@ protected:
// Given the id and the parent, build all of the folder views.
void rebuildViewsFor(const LLUUID& id);
virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719
-
+ void defaultOpenInventory(); // open the first level of inventory
protected:
LLInventoryModel* mInventory;
LLInventoryObserver* mInventoryObserver;
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 945294f3f2..a01426ea87 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -182,6 +182,9 @@ void LLLoginInstance::constructAuthParams(const LLSD& credentials)
mRequestData["method"] = "login_to_simulator";
mRequestData["params"] = request_params;
mRequestData["options"] = requested_options;
+
+ mRequestData["cfg_srv_timeout"] = gSavedSettings.getF32("LoginSRVTimeout");
+ mRequestData["cfg_srv_pump"] = gSavedSettings.getString("LoginSRVPump");
}
bool LLLoginInstance::handleLoginEvent(const LLSD& event)
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index 3993431311..333646d2c5 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -36,7 +36,6 @@
#include "lltrans.h"
#include "llnearbychatbar.h"
-#include "llspeakbutton.h"
#include "llbottomtray.h"
#include "llagent.h"
#include "llgesturemgr.h"
@@ -98,9 +97,10 @@ void LLGestureComboBox::refreshGestures()
clearRows();
mGestures.clear();
- LLGestureManager::item_map_t::iterator it;
+ LLGestureManager::item_map_t::const_iterator it;
+ const LLGestureManager::item_map_t& active_gestures = LLGestureManager::instance().getActiveGestures();
LLSD::Integer idx(0);
- for (it = LLGestureManager::instance().mActive.begin(); it != LLGestureManager::instance().mActive.end(); ++it)
+ for (it = active_gestures.begin(); it != active_gestures.end(); ++it)
{
LLMultiGesture* gesture = (*it).second;
if (gesture)
@@ -234,14 +234,6 @@ BOOL LLNearbyChatBar::postBuild()
mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator");
mOutputMonitor->setVisible(FALSE);
- mSpeakBtn = getParent()->getChild<LLSpeakButton>("talk");
-
- // Speak button should be initially disabled because
- // it takes some time between logging in to world and connecting to voice channel.
- mSpeakBtn->setEnabled(FALSE);
-
- // Registering Chat Bar to receive Voice client status change notifications.
- gVoiceClient->addObserver(this);
return TRUE;
}
@@ -733,27 +725,6 @@ public:
}
};
-void LLNearbyChatBar::onChange(EStatusType status, const std::string &channelURI, bool proximal)
-{
- // Time it takes to connect to voice channel might be pretty long,
- // so don't expect user login or STATUS_VOICE_ENABLED to be followed by STATUS_JOINED.
- BOOL enable = FALSE;
-
- switch (status)
- {
- // Do not add STATUS_VOICE_ENABLED because voice chat is
- // inactive until STATUS_JOINED
- case STATUS_JOINED:
- enable = TRUE;
- break;
- default:
- enable = FALSE;
- break;
- }
-
- mSpeakBtn->setEnabled(enable);
-}
-
// Creating the object registers with the dispatcher.
LLChatHandler gChatHandler;
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index 56ee706a97..224118e088 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -42,9 +42,6 @@
#include "llspeakers.h"
-class LLSpeakButton;
-
-
class LLGestureComboBox
: public LLComboBox
, public LLGestureManagerObserver
@@ -76,7 +73,6 @@ protected:
class LLNearbyChatBar
: public LLPanel
-, public LLVoiceClientStatusObserver
{
public:
// constructor for inline chat-bars (e.g. hosted in chat history window)
@@ -105,11 +101,6 @@ public:
S32 getMinWidth() const;
S32 getMaxWidth() const;
- /**
- * Implements LLVoiceClientStatusObserver::onChange()
- */
- /*virtual*/ void onChange(EStatusType status, const std::string &channelURI, bool proximal);
-
protected:
static BOOL matchChatTypeTrigger(const std::string& in_str, std::string* out_str);
static void onChatBoxKeystroke(LLLineEditor* caller, void* userdata);
@@ -127,7 +118,6 @@ protected:
static S32 sLastSpecialChatChannel;
LLLineEditor* mChatBox;
- LLSpeakButton* mSpeakBtn;
LLOutputMonitorCtrl* mOutputMonitor;
LLLocalSpeakerMgr* mSpeakerMgr;
};
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index b4e0ab198a..f3b63c8616 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -332,7 +332,8 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg)
//only messages from AGENTS
if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType)
{
- return;//dn't show toast for messages from objects
+ if(chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG)
+ return;//ok for now we don't skip messeges from object, so skip only debug messages
}
LLUUID id;
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index 1770138b3e..9cd949c9cc 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -174,10 +174,8 @@ void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID);
- // Fetch the currect name
- gCacheName->get(mAvatarID, FALSE, boost::bind(&LLPanelIMControlPanel::nameUpdatedCallback, this, _1, _2, _3, _4));
-
- // Disable profile button if participant is not realy SL avatar
+ // Disable most profile buttons if the participant is
+ // not really an SL avatar (e.g., an Avaline caller).
LLIMModel::LLIMSession* im_session =
im_model.findIMSession(session_id);
if( im_session && !im_session->mOtherParticipantIsAvatar )
@@ -188,6 +186,13 @@ void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
childSetEnabled("share_btn", FALSE);
childSetEnabled("teleport_btn", FALSE);
childSetEnabled("pay_btn", FALSE);
+
+ getChild<LLTextBox>("avatar_name")->setValue(im_session->mName);
+ }
+ else
+ {
+ // If the participant is an avatar, fetch the currect name
+ gCacheName->get(mAvatarID, FALSE, boost::bind(&LLPanelIMControlPanel::nameUpdatedCallback, this, _1, _2, _3, _4));
}
}
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index 15a75cb930..e3b2ab77aa 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -204,11 +204,6 @@ void LLPanelMainInventory::initListCommandsHandlers()
mListCommands->childSetAction("options_gear_btn", boost::bind(&LLPanelMainInventory::onGearButtonClick, this));
mListCommands->childSetAction("trash_btn", boost::bind(&LLPanelMainInventory::onTrashButtonClick, this));
mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddButtonClick, this));
- /*
- mListCommands->getChild<LLButton>("add_btn")->setHeldDownCallback(boost::bind(&LLPanelMainInventory::onAddButtonHeldDown, this));
- static const LLSD add_landmark_command("add_landmark");
- mListCommands->childSetAction("add_btn", boost::bind(&LLPanelMainInventory::onAddAction, this, add_landmark_command));
- */
LLDragAndDropButton* trash_btn = mListCommands->getChild<LLDragAndDropButton>("trash_btn");
trash_btn->setDragAndDropHandler(boost::bind(&LLPanelMainInventory::handleDragAndDropToTrash, this
diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index 9ba94c8ca9..ca87ebf5a2 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -519,7 +519,6 @@ BOOL LLPanelPeople::postBuild()
LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME);
groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this));
groups_panel->childSetAction("plus_btn", boost::bind(&LLPanelPeople::onGroupPlusButtonClicked, this));
- groups_panel->childSetAction("minus_btn", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this));
LLPanel* friends_panel = getChild<LLPanel>(FRIENDS_TAB_NAME);
friends_panel->childSetAction("add_btn", boost::bind(&LLPanelPeople::onAddFriendWizButtonClicked, this));
@@ -568,6 +567,7 @@ BOOL LLPanelPeople::postBuild()
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
registrar.add("People.Group.Plus.Action", boost::bind(&LLPanelPeople::onGroupPlusMenuItemClicked, this, _2));
+ registrar.add("People.Group.Minus.Action", boost::bind(&LLPanelPeople::onGroupMinusButtonClicked, this));
registrar.add("People.Friends.ViewSort.Action", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemClicked, this, _2));
registrar.add("People.Nearby.ViewSort.Action", boost::bind(&LLPanelPeople::onNearbyViewSortMenuItemClicked, this, _2));
registrar.add("People.Groups.ViewSort.Action", boost::bind(&LLPanelPeople::onGroupsViewSortMenuItemClicked, this, _2));
@@ -1193,7 +1193,7 @@ void LLPanelPeople::onCallButtonClicked()
if (selected_uuids.size() == 1)
{
// initiate a P2P voice chat with the selected user
- LLAvatarActions::startCall(selected_uuids[0]);
+ LLAvatarActions::startCall(getCurrentItemID());
}
else if (selected_uuids.size() > 1)
{
diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index ed606d5457..81eb133b07 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -455,7 +455,7 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)
if(!mOverflowToastPanel)
return;
- mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::closeOverflowToastPanel, this));
+ mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onOverflowToastHide, this));
LLTextBox* text_box = mOverflowToastPanel->getChild<LLTextBox>("toast_text");
std::string text = llformat(mOverflowFormatString.c_str(),mHiddenToastsNum);
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 8c5439d47e..6ca6734598 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -435,7 +435,7 @@ void LLSpatialGroup::clearDrawMap()
BOOL LLSpatialGroup::isRecentlyVisible() const
{
- return (LLDrawable::getCurrentFrame() - (S32)mVisible) < LLDrawable::getMinVisFrameRange() ;
+ return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ;
}
BOOL LLSpatialGroup::isVisible() const
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
index 57ea018f25..51d53b2674 100644
--- a/indra/newview/llspeakbutton.cpp
+++ b/indra/newview/llspeakbutton.cpp
@@ -133,6 +133,16 @@ LLSpeakButton::~LLSpeakButton()
LLTransientFloaterMgr::getInstance()->removeControlView(mShowBtn);
}
+void LLSpeakButton::setSpeakToolTip(const std::string& msg)
+{
+ mSpeakBtn->setToolTip(msg);
+}
+
+void LLSpeakButton::setShowToolTip(const std::string& msg)
+{
+ mShowBtn->setToolTip(msg);
+}
+
void LLSpeakButton::onMouseDown_SpeakBtn()
{
bool down = true;
diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h
index e213c562dd..02c8ab3890 100644
--- a/indra/newview/llspeakbutton.h
+++ b/indra/newview/llspeakbutton.h
@@ -62,6 +62,11 @@ public:
/*virtual*/ ~LLSpeakButton();
/*virtual*/ void draw();
+ // *HACK: Need to put tooltips in a translatable location,
+ // the panel that contains this button.
+ void setSpeakToolTip(const std::string& msg);
+ void setShowToolTip(const std::string& msg);
+
protected:
friend class LLUICtrlFactory;
LLSpeakButton(const Params& p);
diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp
index 2ed82b7d62..261bdbcfc0 100644
--- a/indra/newview/llspeakers.cpp
+++ b/indra/newview/llspeakers.cpp
@@ -359,6 +359,9 @@ void LLSpeakerMgr::updateSpeakerList()
LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
{
+ //In some conditions map causes crash if it is empty(Windows only), adding check (EK)
+ if (mSpeakers.size() == 0)
+ return NULL;
speaker_map_t::iterator found_it = mSpeakers.find(speaker_id);
if (found_it == mSpeakers.end())
{
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 64dcd7b97f..696b0d9af1 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -873,6 +873,9 @@ bool idle_startup()
gViewerWindow->getWindow()->show();
display_startup();
+ //DEV-10530. do cleanup. remove at some later date. jan-2009
+ LLFloaterPreference::cleanupBadSetting();
+
// DEV-16927. The following code removes errant keystrokes that happen while the window is being
// first made visible.
#ifdef _WIN32
@@ -1688,8 +1691,11 @@ bool idle_startup()
//all categories loaded. lets create "My Favorites" category
gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
- // lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" and fill it with buddies
- LLFriendCardsManager::instance().syncFriendsFolder();
+ // Checks whether "Friends" and "Friends/All" folders exist in "Calling Cards" folder,
+ // fetches their contents if needed and synchronizes it with buddies list.
+ // If the folders are not found they are created.
+ LLFriendCardsManager::instance().syncFriendCardsFolders();
+
// set up callbacks
llinfos << "Registering Callbacks" << llendl;
@@ -1900,9 +1906,6 @@ bool idle_startup()
//DEV-17797. get null folder. Any items found here moved to Lost and Found
LLInventoryModel::findLostItems();
- //DEV-10530. do cleanup. remove at some later date. jan-2009
- LLFloaterPreference::cleanupBadSetting();
-
LLStartUp::setStartupState( STATE_PRECACHE );
timeout.reset();
return FALSE;
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index 9370e318cf..1ea5f515b7 100644
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -69,7 +69,7 @@ LLToastIMPanel::LLToastIMPanel(LLToastIMPanel::Params &p) : LLToastPanel(p.notif
mNotification = p.notification;
// if message comes from the system - there shouldn't be a reply btn
- if(p.from == "Second Life")
+ if(p.from == SYSTEM_FROM)
{
mAvatar->setVisible(FALSE);
sys_msg_icon->setVisible(TRUE);
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 964d3bc2fa..7772f613f0 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -197,7 +197,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("notifications_console", "floater_notifications_console.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotificationConsole>);
LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
-
+ LLFloaterReg::add("outgoing_call", "floater_outgoing_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLOutgoingCallDialog>);
LLFloaterReg::add("parcel_info", "floater_preview_url.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterParcelInfo>);
LLFloaterPayUtil::registerFloater();
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 493457704b..69d4da373e 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -135,9 +135,19 @@ public:
LLMimeDiscoveryResponder( viewer_media_t media_impl)
: mMediaImpl(media_impl),
mInitialized(false)
- {}
-
+ {
+ if(mMediaImpl->mMimeTypeProbe != NULL)
+ {
+ llerrs << "impl already has an outstanding responder" << llendl;
+ }
+
+ mMediaImpl->mMimeTypeProbe = this;
+ }
+ ~LLMimeDiscoveryResponder()
+ {
+ disconnectOwner();
+ }
virtual void completedHeader(U32 status, const std::string& reason, const LLSD& content)
{
@@ -149,23 +159,54 @@ public:
virtual void error( U32 status, const std::string& reason )
{
+ llwarns << "responder failed with status " << status << ", reason " << reason << llendl;
+ if(mMediaImpl)
+ {
+ mMediaImpl->mMediaSourceFailed = true;
+ }
// completeAny(status, "none/none");
}
void completeAny(U32 status, const std::string& mime_type)
{
- if(!mInitialized && ! mime_type.empty())
+ // the call to initializeMedia may disconnect the responder, which will clear mMediaImpl.
+ // Make a local copy so we can call loadURI() afterwards.
+ LLViewerMediaImpl *impl = mMediaImpl;
+
+ if(impl && !mInitialized && ! mime_type.empty())
{
- if(mMediaImpl->initializeMedia(mime_type))
+ if(impl->initializeMedia(mime_type))
{
mInitialized = true;
- mMediaImpl->loadURI();
+ impl->loadURI();
+ disconnectOwner();
}
}
}
+
+ void cancelRequest()
+ {
+ disconnectOwner();
+ }
+
+private:
+ void disconnectOwner()
+ {
+ if(mMediaImpl)
+ {
+ if(mMediaImpl->mMimeTypeProbe != this)
+ {
+ llerrs << "internal error: mMediaImpl->mMimeTypeProbe != this" << llendl;
+ }
- public:
- viewer_media_t mMediaImpl;
+ mMediaImpl->mMimeTypeProbe = NULL;
+ }
+ mMediaImpl = NULL;
+ }
+
+
+public:
+ LLViewerMediaImpl *mMediaImpl;
bool mInitialized;
};
static LLViewerMedia::impl_list sViewerMediaImplList;
@@ -708,6 +749,7 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
mIsDisabled(false),
mIsParcelMedia(false),
mProximity(-1),
+ mMimeTypeProbe(NULL),
mIsUpdated(false)
{
@@ -811,7 +853,9 @@ void LLViewerMediaImpl::destroyMediaSource()
{
oldImage->setPlaying(FALSE) ;
}
-
+
+ cancelMimeTypeProbe();
+
if(mMediaSource)
{
delete mMediaSource;
@@ -1316,6 +1360,8 @@ void LLViewerMediaImpl::unload()
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
{
+ cancelMimeTypeProbe();
+
if(mMediaURL != url)
{
// Don't carry media play state across distinct URLs.
@@ -1358,6 +1404,12 @@ void LLViewerMediaImpl::navigateInternal()
// Helpful to have media urls in log file. Shouldn't be spammy.
llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
+ if(mMimeTypeProbe != NULL)
+ {
+ llwarns << "MIME type probe already in progress -- bailing out." << llendl;
+ return;
+ }
+
if(mNavigateServerRequest)
{
setNavState(MEDIANAVSTATE_SERVER_SENT);
@@ -1390,7 +1442,7 @@ void LLViewerMediaImpl::navigateInternal()
if(scheme.empty() || "http" == scheme || "https" == scheme)
{
- LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this));
+ LLHTTPClient::getHeaderOnly( mMediaURL, new LLMimeDiscoveryResponder(this), 10.0f);
}
else if("data" == scheme || "file" == scheme || "about" == scheme)
{
@@ -1521,7 +1573,15 @@ void LLViewerMediaImpl::update()
{
if(mMediaSource == NULL)
{
- if(mPriority != LLPluginClassMedia::PRIORITY_UNLOADED)
+ if(mPriority == LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ // This media source should not be loaded.
+ }
+ else if(mMimeTypeProbe != NULL)
+ {
+ // this media source is doing a MIME type probe -- don't try loading it again.
+ }
+ else
{
// This media may need to be loaded.
if(sMediaCreateTimer.hasExpired())
@@ -2120,6 +2180,21 @@ void LLViewerMediaImpl::setNavState(EMediaNavState state)
}
}
+void LLViewerMediaImpl::cancelMimeTypeProbe()
+{
+ if(mMimeTypeProbe != NULL)
+ {
+ // There doesn't seem to be a way to actually cancel an outstanding request.
+ // Simulate it by telling the LLMimeDiscoveryResponder not to write back any results.
+ mMimeTypeProbe->cancelRequest();
+
+ // The above should already have set mMimeTypeProbe to NULL.
+ if(mMimeTypeProbe != NULL)
+ {
+ llerrs << "internal error: mMimeTypeProbe is not NULL after cancelling request." << llendl;
+ }
+ }
+}
void LLViewerMediaImpl::addObject(LLVOVolume* obj)
{
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index 3f5f3ca746..719deb28bf 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -48,6 +48,7 @@ class LLUUID;
class LLViewerMediaTexture;
class LLMediaEntry;
class LLVOVolume ;
+class LLMimeDiscoveryResponder;
typedef LLPointer<LLViewerMediaImpl> viewer_media_t;
///////////////////////////////////////////////////////////////////////////////
@@ -294,6 +295,7 @@ public:
EMediaNavState getNavState() { return mMediaNavState; }
void setNavState(EMediaNavState state);
+ void cancelMimeTypeProbe();
public:
// a single media url with some data and an impl.
LLPluginClassMedia* mMediaSource;
@@ -331,7 +333,8 @@ public:
bool mIsDisabled;
bool mIsParcelMedia;
S32 mProximity;
-
+ LLMimeDiscoveryResponder *mMimeTypeProbe;
+
private:
BOOL mIsUpdated ;
std::list< LLVOVolume* > mObjectList ;
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 976d89a5b7..728fb7c616 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -1879,7 +1879,9 @@ class LLAdvancedDebugAvatarTextures : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
handle_debug_avatar_textures(NULL);
+#endif
return true;
}
};
@@ -1893,7 +1895,9 @@ class LLAdvancedDumpAvatarLocalTextures : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
+#ifndef LL_RELEASE_FOR_DOWNLOAD
handle_dump_avatar_local_textures(NULL);
+#endif
return true;
}
};
@@ -7860,10 +7864,8 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedCheckDebugCharacterVis(), "Advanced.CheckDebugCharacterVis");
view_listener_t::addMenu(new LLAdvancedDumpAttachments(), "Advanced.DumpAttachments");
view_listener_t::addMenu(new LLAdvancedRebakeTextures(), "Advanced.RebakeTextures");
- #ifndef LL_RELEASE_FOR_DOWNLOAD
view_listener_t::addMenu(new LLAdvancedDebugAvatarTextures(), "Advanced.DebugAvatarTextures");
view_listener_t::addMenu(new LLAdvancedDumpAvatarLocalTextures(), "Advanced.DumpAvatarLocalTextures");
- #endif
// Advanced > Network
view_listener_t::addMenu(new LLAdvancedEnableMessageLog(), "Advanced.EnableMessageLog");
view_listener_t::addMenu(new LLAdvancedDisableMessageLog(), "Advanced.DisableMessageLog");
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 9923c9ac74..85bc26c9c0 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -206,33 +206,31 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(
const LLUUID &image_id,
BOOL usemipmaps,
- S32 boost_priority,
+ LLViewerTexture::EBoostLevel boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
LLHost request_from_host)
{
- llassert_always(boost_priority >= LLViewerTexture::BOOST_NONE) ;
return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ;
}
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile(
const std::string& filename,
BOOL usemipmaps,
- S32 boost_priority,
+ LLViewerTexture::EBoostLevel boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
const LLUUID& force_id)
{
- llassert_always(boost_priority >= LLViewerTexture::BOOST_NONE) ;
return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
}
//static
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url,
BOOL usemipmaps,
- S32 boost_priority,
+ LLViewerTexture::EBoostLevel boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
@@ -1485,9 +1483,8 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
if ( mBoostLevel > BOOST_HIGH)
{
priority += 10000000.f;
- }
-
- if(mAdditionalDecodePriority > 0.0f)
+ }
+ else if(mAdditionalDecodePriority > 0.0f)
{
// 1-9
S32 additional_priority = (S32)(1.0f + mAdditionalDecodePriority*8.0f + .5f); // round
@@ -3147,8 +3144,7 @@ F32 LLViewerMediaTexture::getMaxVirtualSize()
if(mNeedsResetMaxVirtualSize)
{
- mMaxVirtualSize = 0.f ;//reset
- mNeedsResetMaxVirtualSize = FALSE ;
+ addTextureStats(0.f, FALSE) ;//reset
}
if(mIsPlaying) //media is playing
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index bde87d1dd5..141979052d 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -107,12 +107,11 @@ public:
enum EBoostLevel
{
- //skip 0 and 1 to avoid mistakenly mixing boost level with boolean numbers.
- BOOST_NONE = 2,
- BOOST_AVATAR_BAKED = 3,
- BOOST_AVATAR = 4,
- BOOST_CLOUDS = 5,
- BOOST_SCULPTED = 6,
+ BOOST_NONE = 0,
+ BOOST_AVATAR_BAKED = 1,
+ BOOST_AVATAR = 2,
+ BOOST_CLOUDS = 3,
+ BOOST_SCULPTED = 4,
BOOST_HIGH = 10,
BOOST_TERRAIN = 11, // has to be high priority for minimap / low detail
@@ -668,7 +667,7 @@ public:
static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id,
BOOL usemipmap = TRUE,
- S32 boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
@@ -677,7 +676,7 @@ public:
static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename,
BOOL usemipmap = TRUE,
- S32 boost_priority = LLViewerTexture::BOOST_NONE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE,
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
@@ -686,7 +685,7 @@ public:
static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url,
BOOL usemipmap = TRUE,
- S32 boost_priority = LLViewerTexture::BOOST_NONE,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE,
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index 081b7cc483..703a13976c 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -325,7 +325,7 @@ void LLViewerTextureList::restoreGL()
LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename,
BOOL usemipmaps,
- S32 boost_priority,
+ LLViewerTexture::EBoostLevel boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
@@ -345,7 +345,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url,
BOOL usemipmaps,
- S32 boost_priority,
+ LLViewerTexture::EBoostLevel boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
@@ -411,7 +411,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string&
LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
BOOL usemipmaps,
- S32 boost_priority,
+ LLViewerTexture::EBoostLevel boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
@@ -441,7 +441,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
//when this function is called, there is no such texture in the gTextureList with image_id.
LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
BOOL usemipmaps,
- S32 boost_priority,
+ LLViewerTexture::EBoostLevel boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
@@ -1346,7 +1346,7 @@ LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id, S32 priority)
const BOOL use_mips = FALSE;
const LLRect scale_rect = LLRect::null;
- return loadUIImageByID(image_id, use_mips, scale_rect, priority);
+ return loadUIImageByID(image_id, use_mips, scale_rect, (LLViewerTexture::EBoostLevel)priority);
}
LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priority)
@@ -1360,21 +1360,27 @@ LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priori
const BOOL use_mips = FALSE;
const LLRect scale_rect = LLRect::null;
- return loadUIImageByName(image_name, image_name, use_mips, scale_rect, priority);
+ return loadUIImageByName(image_name, image_name, use_mips, scale_rect, (LLViewerTexture::EBoostLevel)priority);
}
LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename,
- BOOL use_mips, const LLRect& scale_rect, S32 boost_priority )
+ BOOL use_mips, const LLRect& scale_rect, LLViewerTexture::EBoostLevel boost_priority )
{
- if (boost_priority == 0) boost_priority = LLViewerFetchedTexture::BOOST_UI;
+ if (boost_priority == LLViewerTexture::BOOST_NONE)
+ {
+ boost_priority = LLViewerTexture::BOOST_UI;
+ }
LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, boost_priority);
return loadUIImage(imagep, name, use_mips, scale_rect);
}
LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id,
- BOOL use_mips, const LLRect& scale_rect, S32 boost_priority)
+ BOOL use_mips, const LLRect& scale_rect, LLViewerTexture::EBoostLevel boost_priority)
{
- if (boost_priority == 0) boost_priority = LLViewerFetchedTexture::BOOST_UI;
+ if (boost_priority == LLViewerTexture::BOOST_NONE)
+ {
+ boost_priority = LLViewerTexture::BOOST_UI;
+ }
LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority);
return loadUIImage(imagep, id.asString(), use_mips, scale_rect);
}
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 3c9c81a689..028f8441ab 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -130,7 +130,7 @@ private:
LLViewerFetchedTexture * getImage(const LLUUID &image_id,
BOOL usemipmap = TRUE,
- S32 boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
@@ -139,7 +139,7 @@ private:
LLViewerFetchedTexture * getImageFromFile(const std::string& filename,
BOOL usemipmap = TRUE,
- S32 boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
@@ -148,7 +148,7 @@ private:
LLViewerFetchedTexture* getImageFromUrl(const std::string& url,
BOOL usemipmap = TRUE,
- BOOL level_immediate = FALSE, // Get the requested level immediately upon creation.
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
@@ -157,7 +157,7 @@ private:
LLViewerFetchedTexture* createImage(const LLUUID &image_id,
BOOL usemipmap = TRUE,
- S32 boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_NONE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
LLGLenum primary_format = 0,
@@ -228,9 +228,11 @@ public:
static void onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata );
private:
LLUIImagePtr loadUIImageByName(const std::string& name, const std::string& filename,
- BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, S32 boost_priority = 0);
+ BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI);
LLUIImagePtr loadUIImageByID(const LLUUID& id,
- BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, S32 boost_priority = 0);
+ BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null,
+ LLViewerTexture::EBoostLevel boost_priority = LLViewerTexture::BOOST_UI);
LLUIImagePtr loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index 89649407ff..d93913b944 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -306,8 +306,10 @@ void LLVoiceChannel::activate()
// activating the proximal channel between IM calls
LLVoiceChannel* old_channel = sCurrentVoiceChannel;
sCurrentVoiceChannel = this;
+ mCallDialogPayload["old_channel_name"] = "";
if (old_channel)
{
+ mCallDialogPayload["old_channel_name"] = old_channel->getSessionName();
old_channel->deactivate();
}
}
@@ -870,6 +872,19 @@ void LLVoiceChannelP2P::setState(EState state)
{
// HACK: Open/close the call window if needed.
toggleCallWindowIfNeeded(state);
+
+ // *HACK: open outgoing call floater if needed, might be better done elsewhere.
+ mCallDialogPayload["session_id"] = mSessionID;
+ mCallDialogPayload["session_name"] = mSessionName;
+ mCallDialogPayload["other_user_id"] = mOtherUserID;
+ if (!mReceivedCall && state == STATE_RINGING)
+ {
+ llinfos << "RINGINGGGGGGGG " << mSessionName << llendl;
+ if (!mSessionName.empty())
+ {
+ LLFloaterReg::showInstance("outgoing_call", mCallDialogPayload, TRUE);
+ }
+ }
// you only "answer" voice invites in p2p mode
// so provide a special purpose message here
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
index 20b6157b48..639585de55 100644
--- a/indra/newview/llvoicechannel.h
+++ b/indra/newview/llvoicechannel.h
@@ -109,6 +109,7 @@ protected:
EState mState;
std::string mSessionName;
LLSD mNotifyArgs;
+ LLSD mCallDialogPayload;
BOOL mIgnoreNextSessionLeave;
LLHandle<LLPanel> mLoginNotificationHandle;
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 39d4bb0c02..5fedfc943b 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -1598,7 +1598,7 @@ void LLVoiceClient::stateMachine()
}
else
{
- LL_WARNS("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL;
+ LL_WARNS_ONCE("Voice") << "region doesn't have ParcelVoiceInfoRequest capability. This is normal for a short time after teleporting, but bad if it persists for very long." << LL_ENDL;
}
}
}
@@ -4273,7 +4273,7 @@ void LLVoiceClient::mediaStreamUpdatedEvent(
if(incoming)
{
// Send the voice chat invite to the GUI layer
- // TODO: Question: Should we correlate with the mute list here?
+ // *TODO: Question: Should we correlate with the mute list here?
session->mIMSessionID = LLIMMgr::computeSessionID(IM_SESSION_P2P_INVITE, session->mCallerID);
session->mVoiceInvitePending = true;
if(session->mName.empty())
diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp
index 8d3165b98c..9897f40c4e 100644
--- a/indra/newview/llworldmipmap.cpp
+++ b/indra/newview/llworldmipmap.cpp
@@ -196,7 +196,7 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32
// END DEBUG
//LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL;
- LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ LLPointer<LLViewerFetchedTexture> img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
img->setBoostLevel(LLViewerTexture::BOOST_MAP);
// Return the smart pointer
diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml
index b23482655c..a3ac878202 100644
--- a/indra/newview/skins/default/xui/en/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/en/floater_gesture.xml
@@ -84,21 +84,21 @@
top_delta="0"
width="18" />
<button
- follows="bottom|left"
+ follows="bottom|right"
font="SansSerifBigBold"
height="18"
image_selected="TrashItem_Press"
image_unselected="TrashItem_Off"
image_disabled="TrashItem_Disabled"
layout="topleft"
- left_pad="230"
name="del_btn"
+ right="-5"
tool_tip="Delete this gesture"
top_delta="0"
width="18" />
</panel>
<button
- follows="bottom|right"
+ follows="left|bottom"
height="23"
label="Edit"
layout="topleft"
@@ -107,7 +107,7 @@
top_pad="5"
width="83" />
<button
- follows="bottom|right"
+ follows="left|bottom"
height="23"
label="Play"
layout="topleft"
@@ -116,7 +116,7 @@
top_delta="0"
width="83" />
<button
- follows="bottom|right"
+ follows="left|bottom"
height="23"
label="Stop"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
index 16873df310..9c2898945b 100644
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -4,13 +4,17 @@
can_close="false"
can_minimize="false"
can_tear_off="false"
- height="200"
+ height="125"
layout="topleft"
name="incoming call"
help_topic="incoming_call"
title="UNKNOWN PERSON IS CALLING"
- width="240">
- <floater.string
+ width="410">
+ <floater.string
+ name="localchat">
+ Local Voice Chat
+ </floater.string>
+ <floater.string
name="anonymous">
anonymous
</floater.string>
@@ -31,18 +35,26 @@
left_delta="19"
top="35"
width="36" />
- <text_editor
- font="SansSerif"
- height="64"
- border_visible="false"
+ <text
+ font="SansSerifLarge"
+ height="20"
layout="topleft"
left="77"
- max_length="2147483647"
name="caller name"
- read_only="true"
- top="21"
- width="163"
+ top="27"
+ width="315"
word_wrap="true" />
+ <text
+ font="SansSerif"
+ height="50"
+ layout="topleft"
+ left="77"
+ name="question"
+ top="52"
+ width="315"
+ word_wrap="true">
+ Do you want to leave [CURRENT_CHAT] and join this voice chat?
+ </text>
<button
height="24"
label="Accept"
@@ -57,16 +69,14 @@
label="Reject"
label_selected="Reject"
layout="topleft"
- left_delta="0"
name="Reject"
- top_pad="12"
+ left_pad="10"
width="100" />
<button
height="24"
label="Start IM"
layout="topleft"
- left_delta="0"
name="Start IM"
- top_pad="12"
+ left_pad="10"
width="100" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml
index 30639f955f..b48c962413 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory.xml
@@ -36,10 +36,10 @@
filename="panel_main_inventory.xml"
follows="all"
layout="topleft"
+ hide_top_panel="true"
left="0"
label="Inventory Panel"
name="Inventory Panel"
top="15"
- width="467">
-</panel>
+ width="467" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_outgoing_call.xml b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
new file mode 100644
index 0000000000..44956f7e52
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_outgoing_call.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_close="false"
+ can_minimize="false"
+ can_tear_off="false"
+ height="125"
+ layout="topleft"
+ name="outgoing call"
+ help_topic="outgoing_call"
+ title="CALLING"
+ width="410">
+ <floater.string
+ name="localchat">
+ Local Voice Chat
+ </floater.string>
+ <floater.string
+ name="anonymous">
+ anonymous
+ </floater.string>
+ <floater.string
+ name="VoiceInviteP2P">
+ is calling.
+ </floater.string>
+ <floater.string
+ name="VoiceInviteAdHoc">
+ has joined a Voice Chat call with a conference chat.
+ </floater.string>
+ <avatar_icon
+ enabled="false"
+ follows="left|top"
+ height="36"
+ image_name="icon_avatar_online.tga"
+ layout="topleft"
+ left_delta="19"
+ top="35"
+ width="36" />
+ <text
+ font="SansSerifLarge"
+ height="20"
+ layout="topleft"
+ left="77"
+ name="calling"
+ top="27"
+ width="315"
+ word_wrap="true">
+Calling [CALLEE_NAME]
+ </text>
+ <text
+ font="SansSerif"
+ height="50"
+ layout="topleft"
+ left="77"
+ name="leaving"
+ top="52"
+ width="315"
+ word_wrap="true">
+Leaving [CURRENT_CHAT].
+ </text>
+ <button
+ height="24"
+ label="Cancel"
+ label_selected="Cancel"
+ left="70"
+ layout="topleft"
+ name="Cancel"
+ left_pad="10"
+ width="100" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index c33d7cf31d..b2f46bc433 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -262,6 +262,18 @@
<check_box.commit_callback
function="BuildTool.selectComponent"/>
</check_box>
+
+ <text
+ text_color="LtGray_50"
+ follows="top|left"
+ halign="left"
+ left="13"
+ name="RenderingCost"
+ top_pad="9"
+ type="string"
+ width="100">
+ รพ: [COUNT]
+ </text>
<check_box
control_name="ScaleUniform"
height="19"
@@ -325,7 +337,7 @@
<button.commit_callback
function="BuildTool.gridOptions"/>
</button>
- <button
+ <button
follows="left|top"
height="20"
image_disabled="Object_Cube"
@@ -701,6 +713,7 @@
function="BuildTool.applyToSelection"/>
</button>
<text
+ text_color="LtGray_50"
type="string"
length="1"
height="12"
@@ -714,6 +727,7 @@
Objects: [COUNT]
</text>
<text
+ text_color="LtGray_50"
type="string"
length="1"
follows="left|top"
@@ -730,7 +744,7 @@
halign="center"
left="0"
name="Object Info Tabs"
- tab_max_width="55"
+ tab_max_width="54"
tab_min_width="40"
tab_position="top"
tab_height="25"
diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml
index 4e2cce1428..1adb824e2a 100644
--- a/indra/newview/skins/default/xui/en/floater_tos.xml
+++ b/indra/newview/skins/default/xui/en/floater_tos.xml
@@ -53,22 +53,6 @@
Please read the following Terms of Service carefully. To continue logging in to [SECOND_LIFE],
you must accept the agreement.
</text>
- <text_editor
- type="string"
- length="1"
- follows="left|top"
- font="SansSerif"
- height="283"
- layout="topleft"
- left_delta="0"
- max_length="65536"
- name="tos_text"
- top_pad="43"
- width="568"
- handle_edit_keys_directly="true"
- word_wrap="true">
- TOS_TEXT
- </text_editor>
<web_browser
follows="left|top"
height="340"
@@ -76,6 +60,6 @@ you must accept the agreement.
left_delta="0"
name="tos_html"
start_url="data:text/html,%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody text=%22000000%22%3E%3Ch2%3E Loading %3Ca%20target%3D%22_external%22%20href%3D%22http%3A//secondlife.com/app/tos/%22%3ETerms%20of%20Service%3C/a%3E...%3C/h2%3E %3C/body%3E %3C/html%3E"
- top_delta="-27"
+ top_delta="0"
width="568" />
</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml
index 6dd44255bf..304492bedb 100644
--- a/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml
+++ b/indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml
@@ -13,15 +13,11 @@
function="CheckControl"
parameter="GroupListShowIcons" />
</menu_item_check>
- <menu_item_check
+ <menu_item_call
label="Leave Selected Group"
layout="topleft"
name="Leave Selected Group">
- <menu_item_check.on_click
- function="People.Groups.ViewSort.Action"
- parameter="show_icons" />
- <menu_item_check.on_check
- function="CheckControl"
- parameter="GroupListShowIcons" />
- </menu_item_check>
+ <menu_item_call.on_click
+ function="People.Group.Minus.Action"/>
+ </menu_item_call>
</menu>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 9c4e394f0d..70b21d14be 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5741,6 +5741,15 @@ Are you sure you want to delete your teleport history?
yestext="OK"/>
</notification>
+ <notification
+ icon="alert.tga"
+ name="BottomTrayButtonCanNotBeShown"
+ type="alert">
+Selected button can not be shown right now.
+The button will be shown when there is enough space for it.
+ </notification>
+
+
<global name="UnsupportedCPU">
- Your CPU speed does not meet the minimum requirements.
</global>
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
index 5562ec8406..38294c907a 100644
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -7,7 +7,9 @@
left="0"
height="35"
width="318"
- background_visible="false">
+ background_opaque="false"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 0.0" >
<chiclet_im_p2p
name="p2p_chiclet"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index 8188016455..a902f50582 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -13,6 +13,8 @@
chrome="true"
border_visible="false"
width="1000">
+ <string name="SpeakBtnToolTip">Turns microphone on/off</string>
+ <string name="VoiceControlBtnToolTip">Shows/hides voice control panel</string>
<layout_stack
mouse_opaque="false"
border_size="0"
@@ -70,9 +72,7 @@
left="0"
name="talk"
top="3"
- width="100"
- speak_button.tool_tip="Turns microphone on/off"
- show_button.tool_tip="Shows/hides voice control panel" />
+ width="100" />
</layout_panel>
<icon
auto_resize="false"
@@ -333,6 +333,6 @@ as for parent layout_panel (chiclet_list_panel) to resize bottom tray properly.
min_width="4"
right="-1"
top="0"
- width="26"/>
+ width="4"/>
</layout_stack>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_group_notify.xml b/indra/newview/skins/default/xui/en/panel_group_notify.xml
index ef3120174e..984a799b41 100644
--- a/indra/newview/skins/default/xui/en/panel_group_notify.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_notify.xml
@@ -1,77 +1,117 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel background_visible="true" bevel_style="in" bg_alpha_color="0 0 0 0"
- height="155" label="instant_message" layout="topleft" left="0"
- name="panel_group_notify" top="0" width="350">
- <string
- name="message_max_lines_count">
- 4
- </string>
- <panel follows="top" background_visible="true" bevel_style="in" bg_alpha_color="black"
- height="30" label="header" layout="topleft" left="0" name="header"
- top="0" width="350">
- <icon follows="left|top|right|bottom" height="20" width="20" layout="topleft"
- top="5" left="5" mouse_opaque="true" name="group_icon"/>
- <text type="string" length="1" follows="left|top|right|bottom"
- font="SansSerifBigBold" height="20" layout="topleft" left_pad="10" name="title"
- text_color="GroupNotifyTextColor" top="5" width="275" use_ellipses="true">
- Sender Name / Group Name
- </text>
- </panel>
- <text
- follows="top"
- height="20"
- layout="topleft"
- left="25"
- name="subject"
- text_color="GroupNotifyTextColor"
- font="SansSerifBig"
- top="40"
- use_ellipses="true"
- value="subject"
- width="300"
- word_wrap="true">
- subject
- </text>
- <text
- follows="top"
- height="20"
- layout="topleft"
- left="25"
- name="datetime"
- text_color="GroupNotifyTextColor"
- font="SansSerif"
- top="80"
- use_ellipses="true"
- value="datetime"
- width="300"
- word_wrap="true">
- datetime
- </text>
- <text
- follows="left|top|bottom|right"
- height="0"
- layout="topleft"
- left="25"
- name="message"
- text_color="GroupNotifyTextColor"
- top="100"
- use_ellipses="true"
- value="message"
- width="300"
- word_wrap="true"
- visible="true" >
- </text>
- <icon
- follows="left|bottom|right" height="15" width="15"
- layout="topleft" bottom="122" left="25" mouse_opaque="true" name="attachment_icon" visible="true"
- />
- <text font="SansSerif" font.style="UNDERLINE" font_shadow="none"
- type="string" length="1" follows="left|bottom|right" layout="topleft"
- left="45" bottom="122" height="15" width="280" name="attachment"
- text_color="GroupNotifyTextColor" visible="true">
- Attachment
- </text>
-
- <button label="OK" layout="topleft" bottom="145" left="140" height="20"
- width="70" name="btn_ok" follows="bottom" />
-</panel> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bevel_style="in"
+ bg_alpha_color="0 0 0 0"
+ height="135"
+ label="instant_message"
+ layout="topleft"
+ left="0"
+ name="panel_group_notify"
+ top="0"
+ width="305">
+ <string
+ name="message_max_lines_count"
+ value="4" />
+ <panel
+ background_visible="true"
+ bevel_style="in"
+ bg_alpha_color="black"
+ follows="top"
+ height="30"
+ label="header"
+ layout="topleft"
+ left="0"
+ name="header"
+ top="0"
+ width="305">
+ <icon
+ follows="left|top|right|bottom"
+ height="20"
+ layout="topleft"
+ left="5"
+ mouse_opaque="true"
+ name="group_icon"
+ top="5"
+ width="20" />
+ <text
+ follows="left|top|right|bottom"
+ font="SansSerifBigBold"
+ height="20"
+ layout="topleft"
+ left_pad="10"
+ name="title"
+ text_color="GroupNotifyTextColor"
+ top="5"
+ use_ellipses="true"
+ value="Sender Name / Group Name"
+ width="230" />
+ </panel>
+ <text
+ follows="top"
+ font="SansSerifBig"
+ height="20"
+ layout="topleft"
+ left="25"
+ name="subject"
+ text_color="GroupNotifyTextColor"
+ top="40"
+ use_ellipses="true"
+ value="subject"
+ width="270"
+ wrap="true" />
+ <text
+ follows="top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left="25"
+ name="datetime"
+ text_color="GroupNotifyTextColor"
+ top="80"
+ use_ellipses="true"
+ value="datetime"
+ width="270"
+ wrap="true" />
+ <text
+ follows="left|top|bottom|right"
+ height="0"
+ layout="topleft"
+ left="25"
+ name="message"
+ text_color="GroupNotifyTextColor"
+ top="100"
+ use_ellipses="true"
+ value="message"
+ width="270"
+ wrap="true" />
+ <icon
+ bottom="122"
+ follows="left|bottom|right"
+ height="15"
+ layout="topleft"
+ left="25"
+ mouse_opaque="true"
+ name="attachment_icon"
+ width="15" />
+ <text
+ bottom="122"
+ follows="left|bottom|right"
+ font="SansSerif"
+ height="15"
+ layout="topleft"
+ left="45"
+ name="attachment"
+ text_color="GroupNotifyTextColor"
+ value="Attachment"
+ width="280" />
+ <button
+ bottom="130"
+ follows="bottom"
+ height="20"
+ label="OK"
+ layout="topleft"
+ left="25"
+ name="btn_ok"
+ width="70" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
index a77094e942..ecf35523cd 100644
--- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
@@ -23,7 +23,7 @@
layout="topleft"
left_delta="7"
left="0"
- max_length="254"
+ max_length="512"
name="chat_box"
tool_tip="Press Enter to say, Ctrl+Enter to shout"
top="0"
diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml
index 40f8da0c2c..462188ee24 100644
--- a/indra/newview/skins/default/xui/en/panel_notification.xml
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -10,7 +10,7 @@
left="0"
name="notification_panel"
top="0"
- height="10"
+ height="140"
width="305">
<!-- THIS PANEL CONTROLS TOAST HEIGHT? -->
<panel
@@ -20,18 +20,18 @@
bg_alpha_color="0.3 0.3 0.3 0"
bg_opaque_color="0.3 0.3 0.3 0"
follows="left|right|top"
- height="10"
+ height="100"
label="info_panel"
layout="topleft"
left="0"
name="info_panel"
top="0"
width="305">
- <!-- <text
+ <text
border_visible="false"
follows="left|right|top|bottom"
font="SansSerif"
- height="90"
+ height="85"
layout="topleft"
left="10"
name="text_box"
@@ -39,21 +39,21 @@
text_color="white"
top="10"
visible="false"
- width="300"
+ width="285"
wrap="true"/>
<text
border_visible="false"
follows="left|right|top|bottom"
font="SansSerifBold"
- height="90"
+ height="85"
layout="topleft"
- left="45"
+ left="10"
name="caution_text_box"
text_color="1 0.82 0.46 1"
- top="5"
+ top="10"
visible="false"
- width="300"
- wrap="true"/> -->
+ width="285"
+ wrap="true"/>
<text_editor
h_pad="0"
v_pad="0"
@@ -63,6 +63,7 @@
enabled="false"
follows="left|right|top|bottom"
font="SansSerif"
+ height="85"
layout="topleft"
left="10"
mouse_opaque="false"
@@ -81,12 +82,13 @@
<panel
background_visible="false"
follows="left|right|bottom"
+ height="40"
label="control_panel"
layout="topleft"
left="0"
left_delta="-38"
name="control_panel"
- top="20">
+ top_pad="0">
</panel>
<!--
<icon
diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
index 7722583ce2..63e60aab78 100644
--- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
@@ -9,7 +9,10 @@
width="300"
height="35"
layout="topleft"
- follows="left|right">
+ follows="left|right"
+ background_opaque="false"
+ background_visible="true"
+ bg_alpha_color="0.0 0.0 0.0 0.0" >
<text
top="2"
left="10"
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index ea66bfa197..761c17cfd2 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2863,7 +2863,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
Connecting...
</string>
<string name="conference-title">
- Friends Conference
+ Ad-hoc Conference
</string>
<string name="inventory_item_offered-im">
Inventory item offered
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index d31a81e128..7b28a3b72c 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -76,6 +76,7 @@ LLControlGroup::LLControlGroup(const std::string& name) :
LLControlGroup::~LLControlGroup() {}
void LLControlGroup::setBOOL(const std::string& name, BOOL val) {}
BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; }
+F32 LLControlGroup::getF32(const std::string& name) { return 0.0f; }
U32 LLControlGroup::saveToFile(const std::string& filename, BOOL nondefault_only) { return 1; }
void LLControlGroup::setString(const std::string& name, const std::string& val) {}
std::string LLControlGroup::getString(const std::string& name) { return "test_string"; }
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index 7a30315b9a..b14c59ab9a 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -70,7 +70,7 @@ public:
LLEventPump& getEventPump() { return mPump; }
private:
- void sendProgressEvent(const std::string& state, const std::string& change,
+ LLSD getProgressEventLLSD(const std::string& state, const std::string& change,
const LLSD& data = LLSD())
{
LLSD status_data;
@@ -87,7 +87,13 @@ private:
{
status_data["data"] = data;
}
+ return status_data;
+ }
+ void sendProgressEvent(const std::string& state, const std::string& change,
+ const LLSD& data = LLSD())
+ {
+ LLSD status_data = getProgressEventLLSD(state, change, data);
mPump.post(status_data);
}
@@ -140,15 +146,28 @@ void LLLogin::Impl::login_(LLCoros::self& self, std::string uri, LLSD credential
// Request SRV record.
LL_INFOS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL;
- // *NOTE:Mani - Completely arbitrary timeout value for SRV request.
- filter.errorAfter(5, "SRV Request timed out!");
+ // *NOTE:Mani - Completely arbitrary default timeout value for SRV request.
+ F32 seconds_to_timeout = 5.0f;
+ if(credentials.has("cfg_srv_timeout"))
+ {
+ seconds_to_timeout = credentials["cfg_srv_timeout"].asReal();
+ }
+
+ filter.eventAfter(seconds_to_timeout,
+ getProgressEventLLSD("offline", "fail.login"));
+
+ std::string srv_pump_name = "LLAres";
+ if(credentials.has("cfg_srv_pump"))
+ {
+ srv_pump_name = credentials["cfg_srv_pump"].asString();
+ }
- // Make request
+ // Make request
LLSD request;
request["op"] = "rewriteURI";
request["uri"] = uri;
request["reply"] = replyPump.getName();
- rewrittenURIs = postAndWait(self, request, "LLAres", filter);
+ rewrittenURIs = postAndWait(self, request, srv_pump_name, filter);
} // we no longer need the filter
LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
diff --git a/indra/viewer_components/login/tests/lllogin_test.cpp b/indra/viewer_components/login/tests/lllogin_test.cpp
index a8ae2883d5..99ea796ad0 100644
--- a/indra/viewer_components/login/tests/lllogin_test.cpp
+++ b/indra/viewer_components/login/tests/lllogin_test.cpp
@@ -47,6 +47,7 @@ public:
bool call(const LLSD& event)
{
mDebug(STRINGIZE("LoginListener called!: " << event));
+
mLastEvent = event;
return false;
}
@@ -414,4 +415,42 @@ namespace tut
ensure_equals("Failed to offline", listener.lastEvent()["state"].asString(), "offline");
}
+
+/*
+ template<> template<>
+ void llviewerlogin_object::test<5>()
+ {
+ DEBUG;
+ // Test SRV request timeout.
+ set_test_name("LLLogin SRV timeout testing");
+
+ // Testing normal login procedure.
+ LLEventStream llaresPump("LLAres"); // Dummy LLAres pump.
+
+ // LLAresListener dummyLLAres("dummy_llares");
+ // dummyLLAres.listenTo(llaresPump);
+
+ LLLogin login;
+ LoginListener listener("test_ear");
+ listener.listenTo(login.getEventPump());
+
+ LLSD credentials;
+ credentials["first"] = "these";
+ credentials["last"] = "don't";
+ credentials["passwd"] = "matter";
+ credentials["cfg_srv_timeout"] = 0.0f;
+
+ login.connect("login.bar.com", credentials);
+
+ ensure_equals("SRV State", listener.lastEvent()["change"].asString(), "srvrequest");
+
+ // Get the mainloop eventpump, which needs a pinging in order to drive the
+ // SRV timeout.
+ LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
+ LLSD frame_event;
+ mainloop.post(frame_event);
+
+ ensure_equals("SRV Failure", listener.lastEvent()["change"].asString(), "fail.login");
+ }
+*/
}